summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.appveyor.yml24
-rw-r--r--.gitignore2
-rw-r--r--.travis.yml18
-rw-r--r--COPYRIGHT.txt8
-rw-r--r--README.md3
-rw-r--r--SConstruct127
-rw-r--r--core/SCsub21
-rw-r--r--core/array.cpp4
-rw-r--r--core/bind/core_bind.cpp116
-rw-r--r--core/bind/core_bind.h61
-rw-r--r--core/color.cpp127
-rw-r--r--core/color.h17
-rw-r--r--core/core_string_names.cpp23
-rw-r--r--core/core_string_names.h27
-rw-r--r--core/engine.cpp4
-rw-r--r--core/engine.h8
-rw-r--r--core/error_list.h2
-rw-r--r--core/error_macros.cpp3
-rw-r--r--core/error_macros.h21
-rw-r--r--core/global_constants.cpp2
-rw-r--r--core/hash_map.h33
-rw-r--r--core/hashfuncs.h34
-rw-r--r--core/image.cpp10
-rw-r--r--core/io/compression.cpp2
-rw-r--r--core/io/file_access_buffered.cpp2
-rw-r--r--core/io/file_access_buffered.h2
-rw-r--r--core/io/file_access_buffered_fa.h5
-rw-r--r--core/io/file_access_compressed.cpp11
-rw-r--r--core/io/file_access_compressed.h3
-rw-r--r--core/io/file_access_encrypted.cpp10
-rw-r--r--core/io/file_access_encrypted.h3
-rw-r--r--core/io/file_access_memory.cpp6
-rw-r--r--core/io/file_access_memory.h3
-rw-r--r--core/io/file_access_network.cpp6
-rw-r--r--core/io/file_access_network.h3
-rw-r--r--core/io/file_access_pack.cpp13
-rw-r--r--core/io/file_access_pack.h3
-rw-r--r--core/io/file_access_zip.cpp11
-rw-r--r--core/io/file_access_zip.h3
-rw-r--r--core/io/logger.cpp252
-rw-r--r--core/io/logger.h107
-rw-r--r--core/io/pck_packer.cpp8
-rw-r--r--core/io/resource_format_binary.cpp8
-rw-r--r--core/io/resource_import.cpp29
-rw-r--r--core/io/resource_import.h7
-rw-r--r--core/io/resource_loader.cpp25
-rw-r--r--core/io/resource_loader.h2
-rw-r--r--core/io/stream_peer.cpp6
-rw-r--r--core/io/stream_peer.h2
-rw-r--r--core/io/xml_parser.cpp2
-rw-r--r--core/io/zip_io.h4
-rw-r--r--core/map.h319
-rw-r--r--core/math/a_star.cpp12
-rw-r--r--core/math/a_star.h4
-rw-r--r--core/math/camera_matrix.cpp2
-rw-r--r--core/math/math_funcs.h40
-rw-r--r--core/oa_hash_map.h593
-rw-r--r--core/object.cpp14
-rw-r--r--core/object.h11
-rw-r--r--core/os/dir_access.cpp9
-rw-r--r--core/os/dir_access.h2
-rw-r--r--core/os/file_access.cpp2
-rw-r--r--core/os/file_access.h5
-rw-r--r--core/os/input.cpp2
-rw-r--r--core/os/input.h2
-rw-r--r--core/os/input_event.cpp2
-rw-r--r--core/os/os.cpp34
-rw-r--r--core/os/os.h25
-rw-r--r--core/project_settings.cpp6
-rw-r--r--core/register_core_types.cpp6
-rw-r--r--core/safe_refcount.cpp148
-rw-r--r--core/safe_refcount.h135
-rw-r--r--core/script_debugger_local.cpp10
-rw-r--r--core/script_debugger_local.h4
-rw-r--r--core/script_debugger_remote.cpp14
-rw-r--r--core/script_debugger_remote.h4
-rw-r--r--core/script_language.h2
-rw-r--r--core/set.h311
-rw-r--r--core/typedefs.h8
-rw-r--r--core/undo_redo.cpp4
-rw-r--r--core/ustring.cpp12
-rw-r--r--core/variant.cpp161
-rw-r--r--core/variant.h7
-rw-r--r--core/variant_call.cpp84
-rw-r--r--core/variant_op.cpp2271
-rw-r--r--doc/Makefile2
-rw-r--r--doc/classes/@GDScript.xml379
-rw-r--r--doc/classes/@Global Scope.xml4
-rw-r--r--doc/classes/AStar.xml16
-rw-r--r--doc/classes/AcceptDialog.xml12
-rw-r--r--doc/classes/AnimatedSprite.xml14
-rw-r--r--doc/classes/Animation.xml10
-rw-r--r--doc/classes/AnimationPlayer.xml6
-rw-r--r--doc/classes/AnimationTreePlayer.xml8
-rw-r--r--doc/classes/Area.xml47
-rw-r--r--doc/classes/Area2D.xml75
-rw-r--r--doc/classes/Array.xml6
-rw-r--r--doc/classes/AudioEffectAmplify.xml9
-rw-r--r--doc/classes/AudioEffectCompressor.xml15
-rw-r--r--doc/classes/AudioEffectDelay.xml16
-rw-r--r--doc/classes/AudioEffectDistortion.xml13
-rw-r--r--doc/classes/AudioEffectEQ.xml6
-rw-r--r--doc/classes/AudioEffectEQ10.xml15
-rw-r--r--doc/classes/AudioEffectEQ21.xml26
-rw-r--r--doc/classes/AudioEffectEQ6.xml11
-rw-r--r--doc/classes/AudioEffectLimiter.xml6
-rw-r--r--doc/classes/AudioEffectPanner.xml3
-rw-r--r--doc/classes/AudioEffectPhaser.xml8
-rw-r--r--doc/classes/AudioEffectPitchShift.xml4
-rw-r--r--doc/classes/AudioEffectReverb.xml11
-rw-r--r--doc/classes/AudioServer.xml4
-rw-r--r--doc/classes/AudioStreamOGGVorbis.xml3
-rw-r--r--doc/classes/AudioStreamPlayer.xml17
-rw-r--r--doc/classes/AudioStreamPlayer2D.xml21
-rw-r--r--doc/classes/AudioStreamPlayer3D.xml38
-rw-r--r--doc/classes/AudioStreamRandomPitch.xml4
-rw-r--r--doc/classes/AudioStreamSample.xml15
-rw-r--r--doc/classes/BitMap.xml4
-rw-r--r--doc/classes/BoxContainer.xml14
-rw-r--r--doc/classes/BoxShape.xml3
-rw-r--r--doc/classes/Camera2D.xml2
-rw-r--r--doc/classes/CanvasItem.xml16
-rw-r--r--doc/classes/CanvasLayer.xml8
-rw-r--r--doc/classes/CapsuleShape.xml6
-rw-r--r--doc/classes/CapsuleShape2D.xml6
-rw-r--r--doc/classes/CircleShape2D.xml5
-rw-r--r--doc/classes/CollisionObject.xml30
-rw-r--r--doc/classes/CollisionObject2D.xml33
-rw-r--r--doc/classes/CollisionPolygon.xml5
-rw-r--r--doc/classes/CollisionPolygon2D.xml10
-rw-r--r--doc/classes/Control.xml157
-rw-r--r--doc/classes/Curve.xml4
-rw-r--r--doc/classes/Curve2D.xml18
-rw-r--r--doc/classes/Curve3D.xml18
-rw-r--r--doc/classes/EditorImportPlugin.xml54
-rw-r--r--doc/classes/EditorResourceConversionPlugin.xml29
-rw-r--r--doc/classes/EditorResourcePreview.xml4
-rw-r--r--doc/classes/EditorSpatialGizmo.xml2
-rw-r--r--doc/classes/Environment.xml86
-rw-r--r--doc/classes/File.xml6
-rw-r--r--doc/classes/Font.xml8
-rw-r--r--doc/classes/Geometry.xml6
-rw-r--r--doc/classes/GraphEdit.xml6
-rw-r--r--doc/classes/GraphNode.xml4
-rw-r--r--doc/classes/ImageTexture.xml2
-rw-r--r--doc/classes/ImmediateGeometry.xml2
-rw-r--r--doc/classes/Input.xml2
-rw-r--r--doc/classes/InputEventScreenTouch.xml2
-rw-r--r--doc/classes/ItemList.xml6
-rw-r--r--doc/classes/JSON.xml35
-rw-r--r--doc/classes/JSONParseResult.xml95
-rw-r--r--doc/classes/KinematicBody2D.xml3
-rw-r--r--doc/classes/KinematicCollision.xml14
-rw-r--r--doc/classes/KinematicCollision2D.xml14
-rw-r--r--doc/classes/Label.xml21
-rw-r--r--doc/classes/Light2D.xml21
-rw-r--r--doc/classes/Line2D.xml8
-rw-r--r--doc/classes/LineEdit.xml6
-rw-r--r--doc/classes/LineShape2D.xml6
-rw-r--r--doc/classes/NinePatchRect.xml15
-rw-r--r--doc/classes/Node.xml2
-rw-r--r--doc/classes/Node2D.xml4
-rw-r--r--doc/classes/OS.xml16
-rw-r--r--doc/classes/Physics2DDirectBodyState.xml6
-rw-r--r--doc/classes/Physics2DServer.xml2
-rw-r--r--doc/classes/PhysicsBody.xml12
-rw-r--r--doc/classes/PhysicsBody2D.xml9
-rw-r--r--doc/classes/PhysicsDirectBodyState.xml10
-rw-r--r--doc/classes/PhysicsServer.xml2
-rw-r--r--doc/classes/Polygon2D.xml16
-rw-r--r--doc/classes/ProjectSettings.xml2
-rw-r--r--doc/classes/Range.xml9
-rw-r--r--doc/classes/RayShape.xml3
-rw-r--r--doc/classes/RayShape2D.xml5
-rw-r--r--doc/classes/Rect2.xml2
-rw-r--r--doc/classes/Rect3.xml2
-rw-r--r--doc/classes/RectangleShape2D.xml5
-rw-r--r--doc/classes/RichTextLabel.xml12
-rw-r--r--doc/classes/RigidBody.xml37
-rw-r--r--doc/classes/RigidBody2D.xml27
-rw-r--r--doc/classes/SegmentShape2D.xml6
-rw-r--r--doc/classes/Shape.xml2
-rw-r--r--doc/classes/Spatial.xml76
-rw-r--r--doc/classes/SpatialMaterial.xml80
-rw-r--r--doc/classes/SphereShape.xml3
-rw-r--r--doc/classes/Sprite.xml14
-rw-r--r--doc/classes/SpriteFrames.xml20
-rw-r--r--doc/classes/StaticBody2D.xml9
-rw-r--r--doc/classes/StreamPeerBuffer.xml4
-rw-r--r--doc/classes/String.xml10
-rw-r--r--doc/classes/Texture.xml2
-rw-r--r--doc/classes/TextureProgress.xml16
-rw-r--r--doc/classes/TextureRect.xml18
-rw-r--r--doc/classes/TileMap.xml8
-rw-r--r--doc/classes/Transform.xml22
-rw-r--r--doc/classes/Transform2D.xml22
-rw-r--r--doc/classes/Tree.xml16
-rw-r--r--doc/classes/Tween.xml2
-rw-r--r--doc/classes/UndoRedo.xml26
-rw-r--r--doc/classes/VideoPlayer.xml2
-rw-r--r--doc/classes/Viewport.xml2
-rw-r--r--doc/classes/VisibilityNotifier.xml9
-rw-r--r--doc/classes/VisibilityNotifier2D.xml9
-rw-r--r--doc/classes/VisualScript.xml8
-rw-r--r--doc/classes/XMLParser.xml2
-rw-r--r--doc/tools/doc_status.py40
-rw-r--r--doc/tools/makerst.py54
-rw-r--r--drivers/SCsub9
-rw-r--r--drivers/coreaudio/SCsub8
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.cpp (renamed from platform/osx/audio_driver_osx.cpp)56
-rw-r--r--drivers/coreaudio/audio_driver_coreaudio.h (renamed from platform/osx/audio_driver_osx.h)20
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp52
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h11
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp2
-rw-r--r--drivers/gles3/shader_compiler_gles3.cpp14
-rw-r--r--drivers/gles3/shaders/canvas.glsl12
-rw-r--r--drivers/gles3/shaders/scene.glsl74
-rw-r--r--drivers/png/SCsub2
-rw-r--r--drivers/rtaudio/audio_driver_rtaudio.cpp2
-rw-r--r--drivers/unix/dir_access_unix.cpp9
-rw-r--r--drivers/unix/file_access_unix.cpp17
-rw-r--r--drivers/unix/file_access_unix.h5
-rw-r--r--drivers/unix/os_unix.cpp93
-rw-r--r--drivers/unix/os_unix.h12
-rw-r--r--drivers/unix/syslog_logger.cpp71
-rw-r--r--drivers/unix/syslog_logger.h48
-rw-r--r--drivers/windows/dir_access_windows.cpp2
-rw-r--r--drivers/windows/file_access_windows.cpp12
-rw-r--r--drivers/windows/file_access_windows.h3
-rw-r--r--editor/SCsub40
-rw-r--r--editor/animation_editor.cpp64
-rw-r--r--editor/animation_editor.h2
-rw-r--r--editor/code_editor.cpp46
-rw-r--r--editor/collada/collada.cpp2
-rw-r--r--editor/create_dialog.cpp71
-rw-r--r--editor/create_dialog.h7
-rw-r--r--editor/dependency_editor.cpp13
-rw-r--r--editor/doc/doc_data.cpp4
-rw-r--r--editor/editor_asset_installer.cpp2
-rw-r--r--editor/editor_audio_buses.cpp59
-rw-r--r--editor/editor_audio_buses.h4
-rw-r--r--editor/editor_autoload_settings.cpp10
-rw-r--r--editor/editor_dir_dialog.cpp4
-rw-r--r--editor/editor_export.cpp24
-rw-r--r--editor/editor_export.h4
-rw-r--r--editor/editor_file_dialog.cpp22
-rw-r--r--editor/editor_file_dialog.h3
-rw-r--r--editor/editor_file_system.cpp16
-rw-r--r--editor/editor_file_system.h8
-rw-r--r--editor/editor_fonts.cpp34
-rw-r--r--editor/editor_help.cpp32
-rw-r--r--editor/editor_log.cpp12
-rw-r--r--editor/editor_node.cpp149
-rw-r--r--editor/editor_node.h8
-rw-r--r--editor/editor_plugin.cpp4
-rw-r--r--editor/editor_plugin_settings.cpp8
-rw-r--r--editor/editor_profiler.cpp19
-rw-r--r--editor/editor_profiler.h6
-rw-r--r--editor/editor_settings.cpp448
-rw-r--r--editor/editor_settings.h13
-rw-r--r--editor/editor_themes.cpp526
-rw-r--r--editor/export_template_manager.cpp8
-rw-r--r--editor/filesystem_dock.cpp42
-rw-r--r--editor/icons/icon_2_d.svg4
-rw-r--r--editor/icons/icon_3_d.svg4
-rw-r--r--editor/icons/icon_GUI_checked.svg4
-rw-r--r--editor/icons/icon_GUI_dropdown.svg6
-rw-r--r--editor/icons/icon_GUI_h_tick.svg3
-rw-r--r--editor/icons/icon_GUI_mini_checkerboard.svg (renamed from editor/icons/icon_mini_checkerboard.svg)0
-rw-r--r--editor/icons/icon_GUI_mini_tab_menu.svg6
-rw-r--r--editor/icons/icon_GUI_play_button_group.svg5
-rw-r--r--editor/icons/icon_GUI_scroll_arrow_left.svg3
-rw-r--r--editor/icons/icon_GUI_scroll_arrow_right.svg3
-rw-r--r--editor/icons/icon_GUI_tab.svg5
-rw-r--r--editor/icons/icon_GUI_tab_menu.svg6
-rw-r--r--editor/icons/icon_GUI_tree_option.svg5
-rw-r--r--editor/icons/icon_GUI_v_tick.svg5
-rw-r--r--editor/icons/icon_a_r_v_r_camera.svg3
-rw-r--r--editor/icons/icon_accept_dialog.svg4
-rw-r--r--editor/icons/icon_add.svg4
-rw-r--r--editor/icons/icon_area.svg2
-rw-r--r--editor/icons/icon_audio_bus_bypass.svg2
-rw-r--r--editor/icons/icon_audio_bus_mute.svg2
-rw-r--r--editor/icons/icon_audio_bus_solo.svg2
-rw-r--r--editor/icons/icon_audio_effect_amplify.svg12
-rw-r--r--editor/icons/icon_audio_stream_gibberish.svg5
-rw-r--r--editor/icons/icon_bool.svg5
-rw-r--r--editor/icons/icon_collapse.svg2
-rw-r--r--editor/icons/icon_color.svg24
-rw-r--r--editor/icons/icon_connect.svg4
-rw-r--r--editor/icons/icon_create_new_scene_from.svg3
-rw-r--r--editor/icons/icon_cube_map.svg9
-rw-r--r--editor/icons/icon_curve_close.svg10
-rw-r--r--editor/icons/icon_curve_create.svg9
-rw-r--r--editor/icons/icon_curve_curve.svg8
-rw-r--r--editor/icons/icon_curve_delete.svg8
-rw-r--r--editor/icons/icon_curve_edit.svg8
-rw-r--r--editor/icons/icon_debug.svg11
-rw-r--r--editor/icons/icon_debug_continue.svg5
-rw-r--r--editor/icons/icon_debug_next.svg10
-rw-r--r--editor/icons/icon_debug_step.svg11
-rw-r--r--editor/icons/icon_dependency_changed.svg6
-rw-r--r--editor/icons/icon_dependency_changed_hl.svg5
-rw-r--r--editor/icons/icon_dependency_local_changed.svg6
-rw-r--r--editor/icons/icon_dependency_local_changed_hl.svg5
-rw-r--r--editor/icons/icon_dependency_ok.svg6
-rw-r--r--editor/icons/icon_dependency_ok_hl.svg5
-rw-r--r--editor/icons/icon_distraction_free.svg8
-rw-r--r--editor/icons/icon_editor_3d_handle.svg1
-rw-r--r--editor/icons/icon_editor_control_anchor.svg4
-rw-r--r--editor/icons/icon_editor_handle.svg9
-rw-r--r--editor/icons/icon_editor_pivot.svg2
-rw-r--r--editor/icons/icon_error.svg2
-rw-r--r--editor/icons/icon_error_sign.svg5
-rw-r--r--editor/icons/icon_event_player.svg8
-rw-r--r--editor/icons/icon_file_broken.svg2
-rw-r--r--editor/icons/icon_file_broken_big_thumb.svg2
-rw-r--r--editor/icons/icon_file_dead.svg2
-rw-r--r--editor/icons/icon_file_dead_big_thumb.svg2
-rw-r--r--editor/icons/icon_file_dead_medium_thumb.svg2
-rw-r--r--editor/icons/icon_file_server.svg7
-rw-r--r--editor/icons/icon_file_server_active.svg7
-rw-r--r--editor/icons/icon_gizmo_camera.svg1
-rw-r--r--editor/icons/icon_gizmo_directional_light.svg1
-rw-r--r--editor/icons/icon_gizmo_g_i_probe.svg3
-rw-r--r--editor/icons/icon_gizmo_light.svg1
-rw-r--r--editor/icons/icon_gizmo_listener.svg1
-rw-r--r--editor/icons/icon_gizmo_particles.svg1
-rw-r--r--editor/icons/icon_gizmo_reflection_probe.svg5
-rw-r--r--editor/icons/icon_gizmo_spatial_sample_player.svg5
-rw-r--r--editor/icons/icon_gizmo_spatial_stream_player.svg5
-rw-r--r--editor/icons/icon_gizmo_spot_light.svg1
-rw-r--r--editor/icons/icon_graph_comment.svg5
-rw-r--r--editor/icons/icon_graph_cube_uniform.svg5
-rw-r--r--editor/icons/icon_graph_curve_map.svg6
-rw-r--r--editor/icons/icon_graph_default_texture.svg5
-rw-r--r--editor/icons/icon_graph_input.svg5
-rw-r--r--editor/icons/icon_graph_rgb.svg12
-rw-r--r--editor/icons/icon_graph_rgb_op.svg11
-rw-r--r--editor/icons/icon_graph_rgb_uniform.svg12
-rw-r--r--editor/icons/icon_graph_scalar.svg5
-rw-r--r--editor/icons/icon_graph_scalar_interp.svg5
-rw-r--r--editor/icons/icon_graph_scalar_op.svg8
-rw-r--r--editor/icons/icon_graph_scalar_uniform.svg5
-rw-r--r--editor/icons/icon_graph_scalars_to_vec.svg11
-rw-r--r--editor/icons/icon_graph_texscreen.svg6
-rw-r--r--editor/icons/icon_graph_texture_uniform.svg5
-rw-r--r--editor/icons/icon_graph_time.svg7
-rw-r--r--editor/icons/icon_graph_vec_dp.svg7
-rw-r--r--editor/icons/icon_graph_vec_interp.svg5
-rw-r--r--editor/icons/icon_graph_vec_length.svg7
-rw-r--r--editor/icons/icon_graph_vec_op.svg5
-rw-r--r--editor/icons/icon_graph_vec_scalar_op.svg6
-rw-r--r--editor/icons/icon_graph_vec_to_scalars.svg11
-rw-r--r--editor/icons/icon_graph_vecs_to_xform.svg11
-rw-r--r--editor/icons/icon_graph_vector.svg5
-rw-r--r--editor/icons/icon_graph_vector_uniform.svg6
-rw-r--r--editor/icons/icon_graph_xform.svg11
-rw-r--r--editor/icons/icon_graph_xform_mult.svg7
-rw-r--r--editor/icons/icon_graph_xform_scalar_func.svg10
-rw-r--r--editor/icons/icon_graph_xform_to_vecs.svg11
-rw-r--r--editor/icons/icon_graph_xform_uniform.svg5
-rw-r--r--editor/icons/icon_graph_xform_vec_func.svg10
-rw-r--r--editor/icons/icon_graph_xform_vec_imult.svg7
-rw-r--r--editor/icons/icon_graph_xform_vec_mult.svg7
-rw-r--r--editor/icons/icon_group_viewport.svg7
-rw-r--r--editor/icons/icon_gui_close_customizable.svg5
-rw-r--r--editor/icons/icon_gui_graph_node_port.svg5
-rw-r--r--editor/icons/icon_gui_resizer.svg3
-rw-r--r--editor/icons/icon_h_box_container.svg6
-rw-r--r--editor/icons/icon_h_separator.svg6
-rw-r--r--editor/icons/icon_h_split_container.svg7
-rw-r--r--editor/icons/icon_h_t_t_p_request.svg5
-rw-r--r--editor/icons/icon_headphones.svg10
-rw-r--r--editor/icons/icon_import_check.svg2
-rw-r--r--editor/icons/icon_import_fail.svg2
-rw-r--r--editor/icons/icon_instance.svg3
-rw-r--r--editor/icons/icon_integer.svg7
-rw-r--r--editor/icons/icon_interp_wrap_clamp.svg6
-rw-r--r--editor/icons/icon_interp_wrap_loop.svg7
-rw-r--r--editor/icons/icon_invalid_key.svg5
-rw-r--r--editor/icons/icon_inverse_kinematics.svg9
-rw-r--r--editor/icons/icon_item_list.svg13
-rw-r--r--editor/icons/icon_key.svg6
-rw-r--r--editor/icons/icon_key_invalid.svg2
-rw-r--r--editor/icons/icon_key_move_enabled.svg5
-rw-r--r--editor/icons/icon_key_rotate_enabled.svg5
-rw-r--r--editor/icons/icon_key_scale_enabled.svg5
-rw-r--r--editor/icons/icon_keyboard.svg3
-rw-r--r--editor/icons/icon_light_occluder_2d.svg10
-rw-r--r--editor/icons/icon_line_edit.svg5
-rw-r--r--editor/icons/icon_link_button.svg5
-rw-r--r--editor/icons/icon_list_select.svg5
-rw-r--r--editor/icons/icon_listener.svg5
-rw-r--r--editor/icons/icon_lock.svg7
-rw-r--r--editor/icons/icon_lock_viewport.svg6
-rw-r--r--editor/icons/icon_loop_interpolation.svg9
-rw-r--r--editor/icons/icon_matrix.svg19
-rw-r--r--editor/icons/icon_menu_button.svg5
-rw-r--r--editor/icons/icon_mesh_instance.svg10
-rw-r--r--editor/icons/icon_mini_aabb.svg8
-rw-r--r--editor/icons/icon_mini_array.svg12
-rw-r--r--editor/icons/icon_mini_basis.svg17
-rw-r--r--editor/icons/icon_mini_boolean.svg12
-rw-r--r--editor/icons/icon_mini_dictionary.svg15
-rw-r--r--editor/icons/icon_mini_float.svg14
-rw-r--r--editor/icons/icon_mini_float_array.svg12
-rw-r--r--editor/icons/icon_mini_image.svg16
-rw-r--r--editor/icons/icon_mini_input.svg14
-rw-r--r--editor/icons/icon_mini_int_array.svg5
-rw-r--r--editor/icons/icon_mini_integer.svg13
-rw-r--r--editor/icons/icon_mini_matrix3.svg19
-rw-r--r--editor/icons/icon_mini_object.svg10
-rw-r--r--editor/icons/icon_mini_path.svg13
-rw-r--r--editor/icons/icon_mini_plane.svg11
-rw-r--r--editor/icons/icon_mini_quat.svg11
-rw-r--r--editor/icons/icon_mini_raw_array.svg6
-rw-r--r--editor/icons/icon_mini_rect2.svg18
-rw-r--r--editor/icons/icon_mini_rid.svg13
-rw-r--r--editor/icons/icon_mini_string.svg11
-rw-r--r--editor/icons/icon_mini_string_array.svg7
-rw-r--r--editor/icons/icon_mini_transform.svg5
-rw-r--r--editor/icons/icon_mini_transform2D.svg8
-rw-r--r--editor/icons/icon_mini_variant.svg13
-rw-r--r--editor/icons/icon_mini_vector2.svg13
-rw-r--r--editor/icons/icon_mini_vector2_array.svg11
-rw-r--r--editor/icons/icon_mini_vector3.svg13
-rw-r--r--editor/icons/icon_mini_vector3_array.svg11
-rw-r--r--editor/icons/icon_multi_edit.svg7
-rw-r--r--editor/icons/icon_multi_line.svg9
-rw-r--r--editor/icons/icon_multi_script.svg6
-rw-r--r--editor/icons/icon_node_warning.svg6
-rw-r--r--editor/icons/icon_object.svg5
-rw-r--r--editor/icons/icon_override.svg3
-rw-r--r--editor/icons/icon_packed_scene.svg7
-rw-r--r--editor/icons/icon_panels_2.svg5
-rw-r--r--editor/icons/icon_panels_2_alt.svg5
-rw-r--r--editor/icons/icon_panels_3.svg6
-rw-r--r--editor/icons/icon_panels_3_alt.svg6
-rw-r--r--editor/icons/icon_panels_4.svg7
-rw-r--r--editor/icons/icon_panorama_sky.svg4
-rw-r--r--editor/icons/icon_parallax_background.svg11
-rw-r--r--editor/icons/icon_parallax_layer.svg4
-rw-r--r--editor/icons/icon_path.svg4
-rw-r--r--editor/icons/icon_path_2d.svg6
-rw-r--r--editor/icons/icon_path_follow.svg6
-rw-r--r--editor/icons/icon_path_follow_2d.svg6
-rw-r--r--editor/icons/icon_pin.svg7
-rw-r--r--editor/icons/icon_pin_joint.svg7
-rw-r--r--editor/icons/icon_pin_pressed.svg7
-rw-r--r--editor/icons/icon_play.svg4
-rw-r--r--editor/icons/icon_play_backwards.svg4
-rw-r--r--editor/icons/icon_play_custom.svg5
-rw-r--r--editor/icons/icon_play_scene.svg7
-rw-r--r--editor/icons/icon_play_start.svg7
-rw-r--r--editor/icons/icon_play_start_backwards.svg7
-rw-r--r--editor/icons/icon_popup_menu.svg5
-rw-r--r--editor/icons/icon_popup_panel.svg5
-rw-r--r--editor/icons/icon_procedural_sky.svg4
-rw-r--r--editor/icons/icon_progress_1.svg8
-rw-r--r--editor/icons/icon_progress_2.svg8
-rw-r--r--editor/icons/icon_progress_3.svg8
-rw-r--r--editor/icons/icon_progress_4.svg8
-rw-r--r--editor/icons/icon_progress_5.svg8
-rw-r--r--editor/icons/icon_progress_6.svg8
-rw-r--r--editor/icons/icon_progress_7.svg8
-rw-r--r--editor/icons/icon_progress_8.svg8
-rw-r--r--editor/icons/icon_progress_bar.svg7
-rw-r--r--editor/icons/icon_proximity_group.svg10
-rw-r--r--editor/icons/icon_quat.svg5
-rw-r--r--editor/icons/icon_range.svg8
-rw-r--r--editor/icons/icon_rating_no_star.svg7
-rw-r--r--editor/icons/icon_rating_star.svg5
-rw-r--r--editor/icons/icon_ray_cast.svg5
-rw-r--r--editor/icons/icon_ray_shape.svg7
-rw-r--r--editor/icons/icon_ray_shape_2d.svg5
-rw-r--r--editor/icons/icon_real.svg11
-rw-r--r--editor/icons/icon_reference_rect.svg11
-rw-r--r--editor/icons/icon_region_edit.svg9
-rw-r--r--editor/icons/icon_remote.svg7
-rw-r--r--editor/icons/icon_remote_transform.svg7
-rw-r--r--editor/icons/icon_remote_transform_2d.svg5
-rw-r--r--editor/icons/icon_remove.svg6
-rw-r--r--editor/icons/icon_resource_preloader.svg5
-rw-r--r--editor/icons/icon_rich_text_label.svg10
-rw-r--r--editor/icons/icon_rigid_body.svg5
-rw-r--r--editor/icons/icon_rigid_body_2d.svg10
-rw-r--r--editor/icons/icon_room_bounds.svg2
-rw-r--r--editor/icons/icon_rotate_0.svg5
-rw-r--r--editor/icons/icon_rotate_180.svg8
-rw-r--r--editor/icons/icon_rotate_270.svg9
-rw-r--r--editor/icons/icon_rotate_90.svg7
-rw-r--r--editor/icons/icon_sample_library.svg5
-rw-r--r--editor/icons/icon_save.svg6
-rw-r--r--editor/icons/icon_scroll_bar.svg4
-rw-r--r--editor/icons/icon_scroll_container.svg8
-rw-r--r--editor/icons/icon_search.svg5
-rw-r--r--editor/icons/icon_shader.svg11
-rw-r--r--editor/icons/icon_signal.svg8
-rw-r--r--editor/icons/icon_skeleton.svg7
-rw-r--r--editor/icons/icon_slider_joint.svg7
-rw-r--r--editor/icons/icon_slot.svg6
-rw-r--r--editor/icons/icon_snap.svg8
-rw-r--r--editor/icons/icon_snap_grid.svg6
-rw-r--r--editor/icons/icon_sound_room_params.svg9
-rw-r--r--editor/icons/icon_spatial_sample_player.svg5
-rw-r--r--editor/icons/icon_spatial_stream_player.svg5
-rw-r--r--editor/icons/icon_spin_box.svg7
-rw-r--r--editor/icons/icon_status_error.svg3
-rw-r--r--editor/icons/icon_status_success.svg3
-rw-r--r--editor/icons/icon_status_warning.svg3
-rw-r--r--editor/icons/icon_stream_player.svg5
-rw-r--r--editor/icons/icon_string.svg5
-rw-r--r--editor/icons/icon_tool_pan.svg12
-rw-r--r--editor/icons/icon_track_discrete.svg6
-rw-r--r--editor/icons/icon_track_trigger.svg8
-rw-r--r--editor/icons/icon_unlock.svg6
-rw-r--r--editor/icons/icon_v_slider.svg2
-rw-r--r--editor/icons/icon_vector.svg6
-rw-r--r--editor/icons/icon_vector2.svg5
-rw-r--r--editor/icons/icon_vehicle_wheel.svg5
-rw-r--r--editor/icons/icon_video_player.svg4
-rw-r--r--editor/icons/icon_visual_shader_port.svg4
-rw-r--r--editor/icons/icon_vu_empty.svg13
-rw-r--r--editor/icons/icon_vu_full.svg12
-rw-r--r--editor/icons/icon_warning.svg2
-rw-r--r--editor/icons/icon_world.svg5
-rw-r--r--editor/icons/icon_zoom_less.svg5
-rw-r--r--editor/icons/icon_zoom_more.svg12
-rw-r--r--editor/icons/icon_zoom_reset.svg10
-rw-r--r--editor/import/editor_import_collada.cpp15
-rw-r--r--editor/import/resource_importer_obj.cpp172
-rw-r--r--editor/import/resource_importer_obj.h22
-rw-r--r--editor/import/resource_importer_scene.cpp18
-rw-r--r--editor/import/resource_importer_scene.h10
-rw-r--r--editor/import/resource_importer_wav.cpp2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp16
-rw-r--r--editor/plugins/animation_tree_editor_plugin.cpp26
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp4
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp1502
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h120
-rw-r--r--editor/plugins/collision_polygon_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/cube_grid_theme_editor_plugin.cpp4
-rw-r--r--editor/plugins/curve_editor_plugin.cpp56
-rw-r--r--editor/plugins/light_occluder_2d_editor_plugin.cpp2
-rw-r--r--editor/plugins/line_2d_editor_plugin.cpp16
-rw-r--r--editor/plugins/material_editor_plugin.cpp46
-rw-r--r--editor/plugins/material_editor_plugin.h10
-rw-r--r--editor/plugins/mesh_editor_plugin.cpp4
-rw-r--r--editor/plugins/navigation_mesh_editor_plugin.h6
-rw-r--r--editor/plugins/navigation_mesh_generator.h2
-rw-r--r--editor/plugins/navigation_polygon_editor_plugin.cpp2
-rw-r--r--editor/plugins/path_2d_editor_plugin.cpp30
-rw-r--r--editor/plugins/path_editor_plugin.cpp40
-rw-r--r--editor/plugins/polygon_2d_editor_plugin.cpp4
-rw-r--r--editor/plugins/resource_preloader_editor_plugin.cpp6
-rw-r--r--editor/plugins/script_editor_plugin.cpp3
-rw-r--r--editor/plugins/script_text_editor.cpp142
-rw-r--r--editor/plugins/shader_editor_plugin.cpp115
-rw-r--r--editor/plugins/shader_graph_editor_plugin.cpp18
-rw-r--r--editor/plugins/spatial_editor_plugin.cpp522
-rw-r--r--editor/plugins/spatial_editor_plugin.h8
-rw-r--r--editor/plugins/sprite_frames_editor_plugin.cpp10
-rw-r--r--editor/plugins/style_box_editor_plugin.cpp2
-rw-r--r--editor/plugins/texture_editor_plugin.cpp2
-rw-r--r--editor/plugins/texture_region_editor_plugin.cpp17
-rw-r--r--editor/plugins/theme_editor_plugin.cpp6
-rw-r--r--editor/plugins/tile_map_editor_plugin.cpp82
-rw-r--r--editor/plugins/tile_map_editor_plugin.h4
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp4
-rw-r--r--editor/progress_dialog.cpp4
-rw-r--r--editor/project_export.cpp20
-rw-r--r--editor/project_manager.cpp361
-rw-r--r--editor/project_manager.h6
-rw-r--r--editor/project_settings_editor.cpp3
-rw-r--r--editor/property_editor.cpp120
-rw-r--r--editor/property_editor.h16
-rw-r--r--editor/quick_open.cpp2
-rw-r--r--editor/scene_tree_dock.cpp13
-rw-r--r--editor/scene_tree_editor.cpp14
-rw-r--r--editor/script_editor_debugger.cpp22
-rw-r--r--editor/script_editor_debugger.h2
-rw-r--r--editor/settings_config_dialog.cpp5
-rw-r--r--editor/spatial_editor_gizmos.cpp38
-rw-r--r--editor/spatial_editor_gizmos.h3
-rw-r--r--editor/translations/ar.po6
-rw-r--r--editor/translations/bg.po6
-rw-r--r--editor/translations/bn.po6
-rw-r--r--editor/translations/ca.po6
-rw-r--r--editor/translations/cs.po6
-rw-r--r--editor/translations/da.po6
-rw-r--r--editor/translations/de.po6
-rw-r--r--editor/translations/de_CH.po6
-rw-r--r--editor/translations/editor.pot6
-rw-r--r--editor/translations/el.po6
-rw-r--r--editor/translations/es.po6
-rw-r--r--editor/translations/es_AR.po6
-rw-r--r--editor/translations/fa.po6
-rw-r--r--editor/translations/fi.po6
-rw-r--r--editor/translations/fr.po6
-rw-r--r--editor/translations/hu.po6
-rw-r--r--editor/translations/id.po6
-rw-r--r--editor/translations/it.po6
-rw-r--r--editor/translations/ja.po6
-rw-r--r--editor/translations/ko.po6
-rw-r--r--editor/translations/nb.po6
-rw-r--r--editor/translations/nl.po6
-rw-r--r--editor/translations/pl.po6
-rw-r--r--editor/translations/pr.po6
-rw-r--r--editor/translations/pt_BR.po6
-rw-r--r--editor/translations/pt_PT.po6
-rw-r--r--editor/translations/ru.po6
-rw-r--r--editor/translations/sk.po6
-rw-r--r--editor/translations/sl.po6
-rw-r--r--editor/translations/th.po6
-rw-r--r--editor/translations/tr.po6
-rw-r--r--editor/translations/ur_PK.po6
-rw-r--r--editor/translations/zh_CN.po6
-rw-r--r--editor/translations/zh_HK.po6
-rw-r--r--editor/translations/zh_TW.po6
-rw-r--r--main/input_default.cpp31
-rw-r--r--main/input_default.h4
-rw-r--r--main/main.cpp59
-rw-r--r--main/performance.cpp14
-rw-r--r--main/performance.h6
-rw-r--r--main/tests/test_main.cpp7
-rw-r--r--main/tests/test_oa_hash_map.cpp97
-rw-r--r--main/tests/test_oa_hash_map.h39
-rw-r--r--methods.py6
-rw-r--r--misc/dist/ios_xcode/export_options.plist10
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.debug.arm (renamed from misc/dist/ios_xcode/godot_debug.iphone)0
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.debug.arm64 (renamed from misc/dist/ios_xcode/godot_opt.iphone)0
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.debug.fat0
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.arm0
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.arm640
-rwxr-xr-xmisc/dist/ios_xcode/godot.iphone.release.fat0
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj198
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata2
-rw-r--r--misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme93
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-568h@2x.png (renamed from misc/dist/ios_xcode/godot_ios/Default-568h@2x~iphone.png)bin564 -> 564 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-667h.pngbin683 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-736h@3x.pngbin2582 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Landscape-1366h@2x.pngbin0 -> 32836 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Landscape-736h@3x.png (renamed from misc/dist/ios_xcode/godot_ios/Default-Landscape-736h.png)bin2582 -> 2582 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Landscape@2x.png (renamed from misc/dist/ios_xcode/godot_ios/Default-Landscape@2x~ipad.png)bin3131 -> 3131 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Landscape~ipad.pngbin634 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Portrait-1366h@2x.pngbin0 -> 33309 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Portrait-736h@3x.png (renamed from misc/dist/ios_xcode/godot_ios/Default-736h.png)bin1676 -> 1676 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Portrait@2x.pngbin0 -> 33309 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Portrait@2x~ipad.pngbin3070 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default-Portrait~ipad.pngbin589 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default@2x~iphone.pngbin515 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Default~iphone.pngbin309 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json128
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.pngbin250 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.pngbin253 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.pngbin253 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.pngbin259 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.pngbin260 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.pngbin265 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.pngbin242 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.pngbin240 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.pngbin243 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.pngbin243 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.pngbin243 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.pngbin244 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.pngbin244 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.pngbin246 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.pngbin245 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.pngbin262 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.pngbin247 -> 0 bytes
-rw-r--r--misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes17
-rw-r--r--misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist15
-rw-r--r--misc/dist/ios_xcode/godot_ios/godot_ios.entitlements8
-rw-r--r--misc/dist/linux/godot.6165
-rw-r--r--misc/dist/linux/godot.appdata.xml34
-rw-r--r--misc/dist/linux/godot.desktop9
-rwxr-xr-xmisc/dist/osx_tools.app/Contents/Info.plist4
-rw-r--r--modules/dds/texture_loader_dds.cpp2
-rw-r--r--modules/enet/SCsub2
-rw-r--r--modules/etc/config.py4
-rw-r--r--modules/freetype/SCsub4
-rw-r--r--modules/gdnative/SCsub2
-rw-r--r--modules/gdnative/gd_native_library_editor.cpp94
-rw-r--r--modules/gdnative/gd_native_library_editor.h39
-rw-r--r--modules/gdnative/gdnative.cpp20
-rw-r--r--modules/gdnative/gdnative.h3
-rw-r--r--modules/gdnative/gdnative/variant.cpp5
-rw-r--r--modules/gdnative/include/gdnative/gdnative.h10
-rw-r--r--modules/gdnative/include/gdnative/variant.h2
-rw-r--r--modules/gdnative/include/gdnative_api_struct.h723
-rw-r--r--modules/gdnative/include/nativescript/godot_nativescript.h4
-rw-r--r--modules/gdnative/nativescript/SCsub3
-rw-r--r--modules/gdnative/register_types.cpp4
-rw-r--r--modules/gdscript/gd_compiler.cpp4
-rw-r--r--modules/gdscript/gd_editor.cpp5
-rw-r--r--modules/gdscript/gd_function.cpp421
-rw-r--r--modules/gdscript/gd_parser.cpp2
-rw-r--r--modules/mobile_vr/SCsub13
-rw-r--r--modules/mobile_vr/config.py6
-rw-r--r--modules/mobile_vr/mobile_interface.cpp511
-rw-r--r--modules/mobile_vr/mobile_interface.h155
-rw-r--r--modules/mobile_vr/register_types.cpp43
-rw-r--r--modules/mobile_vr/register_types.h31
-rw-r--r--modules/mobile_vr/shaders/SCsub7
-rw-r--r--modules/mobile_vr/shaders/lens_distorted.glsl59
-rw-r--r--modules/mono/SCsub120
-rw-r--r--modules/mono/config.py143
-rw-r--r--modules/mono/csharp_script.cpp1853
-rw-r--r--modules/mono/csharp_script.h338
-rw-r--r--modules/mono/doc_classes/@C#.xml15
-rw-r--r--modules/mono/doc_classes/CSharpScript.xml21
-rw-r--r--modules/mono/doc_classes/GodotSharp.xml43
-rw-r--r--modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs335
-rw-r--r--modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs58
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj45
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.sln17
-rw-r--r--modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs14
-rw-r--r--modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs49
-rw-r--r--modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs216
-rw-r--r--modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs17
-rw-r--r--modules/mono/editor/GodotSharpTools/Properties/AssemblyInfo.cs27
-rw-r--r--modules/mono/editor/GodotSharpTools/StringExtensions.cs52
-rw-r--r--modules/mono/editor/bindings_generator.cpp2151
-rw-r--r--modules/mono/editor/bindings_generator.h429
-rw-r--r--modules/mono/editor/csharp_project.cpp120
-rw-r--r--modules/mono/editor/csharp_project.h44
-rw-r--r--modules/mono/editor/godotsharp_builds.cpp440
-rw-r--r--modules/mono/editor/godotsharp_builds.h96
-rw-r--r--modules/mono/editor/godotsharp_editor.cpp256
-rw-r--r--modules/mono/editor/godotsharp_editor.h87
-rw-r--r--modules/mono/editor/mono_bottom_panel.cpp441
-rw-r--r--modules/mono/editor/mono_bottom_panel.h145
-rw-r--r--modules/mono/editor/mono_build_info.h64
-rw-r--r--modules/mono/editor/monodevelop_instance.cpp81
-rw-r--r--modules/mono/editor/monodevelop_instance.h50
-rw-r--r--modules/mono/editor/net_solution.cpp130
-rw-r--r--modules/mono/editor/net_solution.h57
-rw-r--r--modules/mono/glue/cs_files/Basis.cs475
-rw-r--r--modules/mono/glue/cs_files/Color.cs590
-rw-r--r--modules/mono/glue/cs_files/Error.cs48
-rw-r--r--modules/mono/glue/cs_files/ExportAttribute.cs19
-rw-r--r--modules/mono/glue/cs_files/GD.cs191
-rw-r--r--modules/mono/glue/cs_files/GodotMethodAttribute.cs17
-rw-r--r--modules/mono/glue/cs_files/GodotSynchronizationContext.cs26
-rw-r--r--modules/mono/glue/cs_files/GodotTaskScheduler.cs94
-rw-r--r--modules/mono/glue/cs_files/IAwaitable.cs12
-rw-r--r--modules/mono/glue/cs_files/IAwaiter.cs19
-rw-r--r--modules/mono/glue/cs_files/MarshalUtils.cs36
-rw-r--r--modules/mono/glue/cs_files/Mathf.cs234
-rw-r--r--modules/mono/glue/cs_files/Plane.cs209
-rw-r--r--modules/mono/glue/cs_files/Quat.cs328
-rw-r--r--modules/mono/glue/cs_files/RPCAttributes.cs16
-rw-r--r--modules/mono/glue/cs_files/Rect2.cs233
-rw-r--r--modules/mono/glue/cs_files/Rect3.cs477
-rw-r--r--modules/mono/glue/cs_files/SignalAwaiter.cs59
-rw-r--r--modules/mono/glue/cs_files/StringExtensions.cs962
-rw-r--r--modules/mono/glue/cs_files/ToolAttribute.cs7
-rw-r--r--modules/mono/glue/cs_files/Transform.cs168
-rw-r--r--modules/mono/glue/cs_files/Transform2D.cs356
-rw-r--r--modules/mono/glue/cs_files/Vector2.cs362
-rw-r--r--modules/mono/glue/cs_files/Vector3.cs420
-rw-r--r--modules/mono/glue/glue_header.h302
-rw-r--r--modules/mono/godotsharp_defs.h41
-rw-r--r--modules/mono/godotsharp_dirs.cpp185
-rw-r--r--modules/mono/godotsharp_dirs.h58
-rw-r--r--modules/mono/mono_gc_handle.cpp77
-rw-r--r--modules/mono/mono_gc_handle.h63
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp771
-rw-r--r--modules/mono/mono_gd/gd_mono.h224
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.cpp327
-rw-r--r--modules/mono/mono_gd/gd_mono_assembly.h113
-rw-r--r--modules/mono/mono_gd/gd_mono_class.cpp381
-rw-r--r--modules/mono/mono_gd/gd_mono_class.h124
-rw-r--r--modules/mono/mono_gd/gd_mono_field.cpp362
-rw-r--r--modules/mono/mono_gd/gd_mono_field.h74
-rw-r--r--modules/mono/mono_gd/gd_mono_header.h59
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.cpp66
-rw-r--r--modules/mono/mono_gd/gd_mono_internals.h42
-rw-r--r--modules/mono/mono_gd/gd_mono_log.cpp175
-rw-r--r--modules/mono/mono_gd/gd_mono_log.h (renamed from platform/iphone/audio_driver_iphone.h)49
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.cpp856
-rw-r--r--modules/mono/mono_gd/gd_mono_marshal.h229
-rw-r--r--modules/mono/mono_gd/gd_mono_method.cpp192
-rw-r--r--modules/mono/mono_gd/gd_mono_method.h81
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.cpp367
-rw-r--r--modules/mono/mono_gd/gd_mono_utils.h182
-rw-r--r--modules/mono/mono_reg_utils.py54
-rw-r--r--modules/mono/register_types.cpp71
-rw-r--r--modules/mono/register_types.h31
-rw-r--r--modules/mono/signal_awaiter_utils.cpp77
-rw-r--r--modules/mono/signal_awaiter_utils.h53
-rw-r--r--modules/mono/utils/mono_reg_utils.cpp228
-rw-r--r--modules/mono/utils/mono_reg_utils.h54
-rw-r--r--modules/mono/utils/path_utils.cpp111
-rw-r--r--modules/mono/utils/path_utils.h53
-rw-r--r--modules/mono/utils/string_utils.cpp128
-rw-r--r--modules/mono/utils/string_utils.h38
-rw-r--r--modules/ogg/SCsub2
-rw-r--r--modules/openssl/SCsub2
-rw-r--r--modules/openssl/stream_peer_openssl.cpp60
-rw-r--r--modules/openssl/stream_peer_openssl.h5
-rw-r--r--modules/opus/SCsub4
-rw-r--r--modules/opus/audio_stream_opus.cpp10
-rw-r--r--modules/opus/audio_stream_opus.h4
-rw-r--r--modules/pvr/texture_loader_pvr.cpp2
-rw-r--r--modules/recast/SCsub6
-rw-r--r--modules/recast/config.py2
-rw-r--r--modules/regex/SCsub2
-rw-r--r--modules/regex/regex.h4
-rw-r--r--modules/squish/SCsub2
-rw-r--r--modules/squish/config.py4
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.cpp8
-rw-r--r--modules/stb_vorbis/audio_stream_ogg_vorbis.h4
-rw-r--r--modules/svg/image_loader_svg.cpp10
-rw-r--r--modules/svg/image_loader_svg.h2
-rw-r--r--modules/tga/image_loader_tga.cpp4
-rw-r--r--modules/theora/SCsub6
-rw-r--r--modules/theora/video_stream_theora.cpp4
-rw-r--r--modules/theora/video_stream_theora.h4
-rw-r--r--modules/tinyexr/config.py4
-rw-r--r--modules/visual_script/visual_script.cpp14
-rw-r--r--modules/visual_script/visual_script.h4
-rw-r--r--modules/visual_script/visual_script_editor.cpp60
-rw-r--r--modules/visual_script/visual_script_expression.cpp4
-rw-r--r--modules/visual_script/visual_script_func_nodes.cpp16
-rw-r--r--modules/visual_script/visual_script_nodes.cpp2
-rw-r--r--modules/visual_script/visual_script_yield_nodes.cpp8
-rw-r--r--modules/visual_script/visual_script_yield_nodes.h2
-rw-r--r--modules/vorbis/SCsub4
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.cpp10
-rw-r--r--modules/vorbis/audio_stream_ogg_vorbis.h4
-rw-r--r--modules/webm/SCsub8
-rw-r--r--modules/webm/libvpx/SCsub2
-rw-r--r--modules/webm/video_stream_webm.cpp6
-rw-r--r--modules/webm/video_stream_webm.h4
-rw-r--r--modules/webp/SCsub2
-rw-r--r--platform/android/AndroidManifest.xml.template10
-rw-r--r--platform/android/SCsub8
-rw-r--r--platform/android/detect.py19
-rw-r--r--platform/android/file_access_android.cpp7
-rw-r--r--platform/android/file_access_android.h3
-rw-r--r--platform/android/file_access_jandroid.cpp5
-rw-r--r--platform/android/file_access_jandroid.h3
-rw-r--r--platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java20
-rw-r--r--platform/android/os_android.cpp39
-rw-r--r--platform/android/os_android.h3
-rw-r--r--platform/haiku/detect.py16
-rw-r--r--platform/haiku/haiku_direct_window.cpp8
-rw-r--r--platform/haiku/os_haiku.cpp6
-rw-r--r--platform/iphone/SCsub1
-rw-r--r--platform/iphone/app_delegate.mm6
-rw-r--r--platform/iphone/audio_driver_iphone.cpp187
-rw-r--r--platform/iphone/detect.py28
-rw-r--r--platform/iphone/export/export.cpp361
-rw-r--r--platform/iphone/game_center.mm1
-rw-r--r--platform/iphone/os_iphone.cpp16
-rw-r--r--platform/iphone/os_iphone.h6
-rw-r--r--platform/javascript/SCsub2
-rw-r--r--platform/javascript/detect.py16
-rw-r--r--platform/javascript/engine.js6
-rw-r--r--platform/javascript/os_javascript.cpp26
-rw-r--r--platform/javascript/os_javascript.h6
-rw-r--r--platform/osx/SCsub14
-rw-r--r--platform/osx/crash_handler_osx.mm3
-rw-r--r--platform/osx/detect.py16
-rw-r--r--platform/osx/os_osx.h14
-rw-r--r--platform/osx/os_osx.mm125
-rw-r--r--platform/server/detect.py58
-rw-r--r--platform/server/os_server.cpp8
-rw-r--r--platform/server/os_server.h2
-rw-r--r--platform/uwp/detect.py4
-rw-r--r--platform/uwp/export/export.cpp6
-rw-r--r--platform/uwp/gl_context_egl.cpp36
-rw-r--r--platform/uwp/os_uwp.cpp67
-rw-r--r--platform/uwp/os_uwp.h4
-rw-r--r--platform/windows/SCsub14
-rw-r--r--platform/windows/crash_handler_win.cpp4
-rw-r--r--platform/windows/detect.py25
-rw-r--r--platform/windows/godot_win.cpp38
-rw-r--r--platform/windows/os_windows.cpp179
-rw-r--r--platform/windows/os_windows.h8
-rw-r--r--platform/windows/windows_terminal_logger.cpp157
-rw-r--r--platform/windows/windows_terminal_logger.h47
-rw-r--r--platform/x11/SCsub9
-rw-r--r--platform/x11/crash_handler_x11.cpp3
-rw-r--r--platform/x11/detect.py114
-rw-r--r--platform/x11/export/export.cpp1
-rw-r--r--platform/x11/os_x11.cpp117
-rw-r--r--platform/x11/os_x11.h11
-rw-r--r--scene/2d/animated_sprite.cpp2
-rw-r--r--scene/2d/area_2d.cpp10
-rw-r--r--scene/2d/area_2d.h4
-rw-r--r--scene/2d/audio_stream_player_2d.cpp20
-rw-r--r--scene/2d/audio_stream_player_2d.h2
-rw-r--r--scene/2d/camera_2d.cpp16
-rw-r--r--scene/2d/camera_2d.h2
-rw-r--r--scene/2d/canvas_item.cpp20
-rw-r--r--scene/2d/canvas_item.h4
-rw-r--r--scene/2d/collision_object_2d.cpp2
-rw-r--r--scene/2d/line_2d.cpp10
-rw-r--r--scene/2d/line_2d.h4
-rw-r--r--scene/2d/node_2d.cpp4
-rw-r--r--scene/2d/path_2d.cpp2
-rw-r--r--scene/2d/physics_body_2d.cpp2
-rw-r--r--scene/2d/ray_cast_2d.cpp10
-rw-r--r--scene/2d/tile_map.cpp8
-rw-r--r--scene/2d/visibility_notifier_2d.cpp18
-rw-r--r--scene/2d/visibility_notifier_2d.h2
-rw-r--r--scene/3d/SCsub2
-rw-r--r--scene/3d/audio_stream_player_3d.cpp22
-rw-r--r--scene/3d/audio_stream_player_3d.h4
-rw-r--r--scene/3d/camera.cpp4
-rw-r--r--scene/3d/camera.h2
-rw-r--r--scene/3d/collision_object.cpp6
-rw-r--r--scene/3d/immediate_geometry.cpp2
-rw-r--r--scene/3d/immediate_geometry.h2
-rw-r--r--scene/3d/interpolated_camera.cpp2
-rw-r--r--scene/3d/light.cpp6
-rw-r--r--scene/3d/light.h2
-rw-r--r--scene/3d/physics_body.cpp4
-rw-r--r--scene/3d/ray_cast.cpp10
-rw-r--r--scene/3d/spatial.cpp4
-rw-r--r--scene/3d/spatial.h2
-rw-r--r--scene/3d/spatial_velocity_tracker.cpp28
-rw-r--r--scene/3d/spatial_velocity_tracker.h6
-rw-r--r--scene/3d/vehicle_body.cpp7
-rw-r--r--scene/3d/vehicle_body.h2
-rw-r--r--scene/animation/animation_player.cpp20
-rw-r--r--scene/animation/animation_player.h4
-rw-r--r--scene/animation/animation_tree_player.cpp28
-rw-r--r--scene/animation/animation_tree_player.h6
-rw-r--r--scene/animation/tween.cpp12
-rw-r--r--scene/animation/tween.h2
-rw-r--r--scene/audio/audio_player.cpp19
-rw-r--r--scene/audio/audio_player.h2
-rw-r--r--scene/gui/base_button.cpp4
-rw-r--r--scene/gui/color_picker.cpp45
-rw-r--r--scene/gui/control.cpp194
-rw-r--r--scene/gui/control.h36
-rw-r--r--scene/gui/graph_edit.cpp52
-rw-r--r--scene/gui/graph_node.cpp17
-rw-r--r--scene/gui/graph_node.h4
-rw-r--r--scene/gui/item_list.cpp45
-rw-r--r--scene/gui/item_list.h2
-rw-r--r--scene/gui/line_edit.cpp60
-rw-r--r--scene/gui/line_edit.h4
-rw-r--r--scene/gui/popup.cpp2
-rw-r--r--scene/gui/range.cpp10
-rw-r--r--scene/gui/rich_text_label.cpp74
-rw-r--r--scene/gui/rich_text_label.h4
-rw-r--r--scene/gui/scroll_bar.cpp38
-rw-r--r--scene/gui/scroll_container.cpp28
-rw-r--r--scene/gui/scroll_container.h2
-rw-r--r--scene/gui/slider.cpp4
-rw-r--r--scene/gui/spin_box.cpp4
-rw-r--r--scene/gui/tab_container.cpp14
-rw-r--r--scene/gui/text_edit.cpp50
-rw-r--r--scene/gui/text_edit.h2
-rw-r--r--scene/gui/tree.cpp160
-rw-r--r--scene/gui/tree.h7
-rw-r--r--scene/gui/video_player.cpp6
-rw-r--r--scene/gui/video_player.h2
-rwxr-xr-xscene/main/node.cpp98
-rw-r--r--scene/main/node.h18
-rw-r--r--scene/main/scene_tree.cpp15
-rw-r--r--scene/main/scene_tree.h4
-rwxr-xr-xscene/main/timer.cpp20
-rwxr-xr-xscene/main/timer.h2
-rw-r--r--scene/main/viewport.cpp10
-rw-r--r--scene/resources/animation.cpp28
-rw-r--r--scene/resources/animation.h2
-rw-r--r--scene/resources/audio_stream_sample.cpp6
-rw-r--r--scene/resources/audio_stream_sample.h4
-rw-r--r--scene/resources/bit_mask.cpp4
-rw-r--r--scene/resources/curve.cpp51
-rw-r--r--scene/resources/curve.h10
-rw-r--r--scene/resources/default_theme/default_theme.cpp5
-rw-r--r--scene/resources/default_theme/icon_snap_grid.png (renamed from scene/resources/default_theme/icon_snap.png)bin269 -> 325 bytes
-rw-r--r--scene/resources/default_theme/mini_checkerboard.pngbin0 -> 166 bytes
-rw-r--r--scene/resources/default_theme/source/arrow_down.svg80
-rw-r--r--scene/resources/default_theme/source/arrow_right.svg80
-rw-r--r--scene/resources/default_theme/source/graph_node_close.svg94
-rw-r--r--scene/resources/default_theme/source/graph_port.svg80
-rw-r--r--scene/resources/default_theme/source/icon_close.svg94
-rw-r--r--scene/resources/default_theme/source/option_arrow.svg86
-rw-r--r--scene/resources/default_theme/source/popup_checked.svg81
-rw-r--r--scene/resources/default_theme/source/spinbox_updown.svg86
-rw-r--r--scene/resources/default_theme/source/submenu.svg80
-rw-r--r--scene/resources/default_theme/source/tab_close.svg93
-rw-r--r--scene/resources/default_theme/source/tab_menu.svg80
-rw-r--r--scene/resources/default_theme/source/updown.svg86
-rw-r--r--scene/resources/default_theme/theme_data.h8
-rw-r--r--scene/resources/dynamic_font.cpp21
-rw-r--r--scene/resources/environment.cpp21
-rw-r--r--scene/resources/environment.h6
-rw-r--r--scene/resources/font.cpp4
-rw-r--r--scene/resources/material.cpp155
-rw-r--r--scene/resources/material.h38
-rw-r--r--scene/resources/scene_format_text.cpp4
-rw-r--r--scene/resources/shader_graph.cpp14
-rw-r--r--scene/resources/shader_graph.h4
-rw-r--r--scene/resources/sky_box.cpp6
-rw-r--r--scene/resources/style_box.h4
-rw-r--r--scene/resources/texture.cpp6
-rw-r--r--scene/resources/video_stream.h4
-rw-r--r--scene/scene_string_names.cpp2
-rw-r--r--scene/scene_string_names.h2
-rw-r--r--servers/audio/audio_stream.cpp8
-rw-r--r--servers/audio/audio_stream.h8
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp3
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp2
-rw-r--r--servers/audio_server.cpp43
-rw-r--r--servers/audio_server.h5
-rw-r--r--servers/physics/body_sw.h6
-rw-r--r--servers/physics/broad_phase_basic.h2
-rw-r--r--servers/physics/joints/pin_joint_sw.h4
-rw-r--r--servers/physics/physics_server_sw.cpp6
-rw-r--r--servers/physics/physics_server_sw.h2
-rw-r--r--servers/physics_2d/body_2d_sw.h6
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp2
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h2
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.cpp3
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h2
-rw-r--r--servers/physics_2d/space_2d_sw.cpp12
-rw-r--r--servers/physics_2d/space_2d_sw.h6
-rw-r--r--servers/physics_2d_server.cpp8
-rw-r--r--servers/physics_2d_server.h8
-rw-r--r--servers/physics_server.cpp12
-rw-r--r--servers/physics_server.h8
-rw-r--r--servers/visual/rasterizer.h2
-rw-r--r--servers/visual/shader_language.cpp11
-rw-r--r--servers/visual/shader_types.cpp38
-rw-r--r--servers/visual/visual_server_raster.h22
-rw-r--r--servers/visual/visual_server_wrap_mt.h2
-rw-r--r--servers/visual_server.h4
-rw-r--r--thirdparty/README.md8
-rw-r--r--thirdparty/fonts/Hack_Regular.ttfbin0 -> 399724 bytes
-rw-r--r--thirdparty/fonts/LICENSE_Hack.md64
-rw-r--r--thirdparty/fonts/LICENSE_Mononoki94
-rw-r--r--thirdparty/fonts/mononoki_Regular.ttfbin90216 -> 0 bytes
-rw-r--r--thirdparty/zstd/SCsub23
1042 files changed, 34883 insertions, 9037 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
new file mode 100644
index 0000000000..dbd56ab7e0
--- /dev/null
+++ b/.appveyor.yml
@@ -0,0 +1,24 @@
+os: Visual Studio 2015
+
+environment:
+ PYTHON: C:\Python27
+ matrix:
+ - VS: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat
+ GD_PLATFORM: windows
+ TOOLS: yes
+ TARGET: release_debug
+ ARCH: amd64
+
+install:
+ - SET "PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
+ - pip install --egg scons # it will fail on AppVeyor without --egg flag
+ - if defined VS call "%VS%" %ARCH% # if defined - so we can also use mingw
+
+before_build:
+ - echo %GD_PLATFORM%
+ - python --version
+ - scons --version
+ - cl.exe
+
+build_script:
+- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% progress=no
diff --git a/.gitignore b/.gitignore
index 315dc7950f..d27b8b2b4b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,6 +80,8 @@ build/
bld/
[Bb]in/
[Oo]bj/
+*.debug
+*.dSYM
# MSTest test Results
[Tt]est[Rr]esult*/
diff --git a/.travis.yml b/.travis.yml
index 602152374a..a2c3417412 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,7 +19,7 @@ env:
- GODOT_TARGET=osx
- GODOT_TARGET=x11
#- GODOT_TARGET=android
- - GODOT_TARGET=windows
+ #- GODOT_TARGET=windows
matrix:
include:
@@ -66,13 +66,13 @@ addons:
- libxrandr-dev
# For cross-compiling to Windows.
- - binutils-mingw-w64-i686
- - binutils-mingw-w64-x86-64
- - gcc-mingw-w64-i686
- - gcc-mingw-w64-x86-64
- - g++-mingw-w64-i686
- - g++-mingw-w64-x86-64
- - mingw-w64
+ #- binutils-mingw-w64-i686
+ #- binutils-mingw-w64-x86-64
+ #- gcc-mingw-w64-i686
+ #- gcc-mingw-w64-x86-64
+ #- g++-mingw-w64-i686
+ #- g++-mingw-w64-x86-64
+ #- mingw-w64
# For style checks.
- clang-format-3.9
@@ -92,5 +92,5 @@ script:
- if [ "$STATIC_CHECKS" = "yes" ]; then
sh ./misc/travis/clang-format.sh;
else
- scons -j 2 platform=$GODOT_TARGET progress=no verbose=yes CXX=$CXX builtin_openssl=yes;
+ scons -j 2 platform=$GODOT_TARGET progress=no verbose=yes CXX=$CXX;
fi
diff --git a/COPYRIGHT.txt b/COPYRIGHT.txt
index 16ef854f1f..21cbdd9860 100644
--- a/COPYRIGHT.txt
+++ b/COPYRIGHT.txt
@@ -150,10 +150,10 @@ Comment: Noto Sans font
Copyright: 2012, Google Inc.
License: OFL-1.1
-Files: ./thirdparty/fonts/mononoki_Regular.ttf
-Comment: Mononoki font
-Copyright: 2013, Matthias Tellen
-License: OFL-1.1
+Files: ./thirdparty/fonts/Hack_Regular.ttf
+Comment: Hack font
+Copyright: 2015-2017, Christopher Simpkins (with Reserved Font Name Hack).
+License: Hack Open Font License v2.0
Files: ./thirdparty/freetype/
Comment: The FreeType Project
diff --git a/README.md b/README.md
index dc0dad6b90..675e666ce6 100644
--- a/README.md
+++ b/README.md
@@ -62,5 +62,6 @@ There are also a number of other learning resources provided by the community,
such as text and video tutorials, demos, etc. Consult the [community channels](https://godotengine.org/community)
for more info.
-[![Build Status](https://travis-ci.org/godotengine/godot.svg?branch=master)](https://travis-ci.org/godotengine/godot)
+[![Travis Build Status](https://travis-ci.org/godotengine/godot.svg?branch=master)](https://travis-ci.org/godotengine/godot)
+[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/bfiihqq6byxsjxxh/branch/master?svg=true)](https://ci.appveyor.com/project/akien-mga/godot)
[![Code Triagers Badge](https://www.codetriage.com/godotengine/godot/badges/users.svg)](https://www.codetriage.com/godotengine/godot)
diff --git a/SConstruct b/SConstruct
index bc89aa7540..6045be54c7 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,7 +1,7 @@
#!/usr/bin/env python
-EnsureSConsVersion(0, 14)
+EnsureSConsVersion(0, 98, 1)
import string
@@ -132,45 +132,46 @@ opts = Variables(customs, ARGUMENTS)
# Target build options
opts.Add('arch', "Platform-dependent architecture (arm/arm64/x86/x64/mips/etc)", '')
-opts.Add('bits', "Target platform bits (default/32/64/fat)", 'default')
+opts.Add(EnumVariable('bits', "Target platform bits", 'default', ('default', '32', '64', 'fat')))
opts.Add('p', "Platform (alias for 'platform')", '')
-opts.Add('platform', "Target platform: any in " + str(platform_list), '')
-opts.Add('target', "Compilation target (debug/release_debug/release)", 'debug')
-opts.Add('tools', "Build the tools a.k.a. the Godot editor (yes/no)", 'yes')
+opts.Add('platform', "Target platform (%s)" % ('|'.join(platform_list), ), '')
+opts.Add(EnumVariable('target', "Compilation target", 'debug', ('debug', 'release_debug', 'release')))
+opts.Add(BoolVariable('tools', "Build the tools a.k.a. the Godot editor", True))
# Components
-opts.Add('deprecated', "Enable deprecated features (yes/no)", 'yes')
-opts.Add('gdscript', "Build GDSCript support (yes/no)", 'yes')
-opts.Add('minizip', "Build minizip archive support (yes/no)", 'yes')
-opts.Add('xaudio2', "XAudio2 audio driver (yes/no)", 'no')
-opts.Add('xml', "XML format support for resources (yes/no)", 'yes')
+opts.Add(BoolVariable('deprecated', "Enable deprecated features", True))
+opts.Add(BoolVariable('gdscript', "Build GDSCript support", True))
+opts.Add(BoolVariable('minizip', "Build minizip archive support", True))
+opts.Add(BoolVariable('xaudio2', "XAudio2 audio driver", False))
+opts.Add(BoolVariable('xml', "XML format support for resources", True))
# Advanced options
-opts.Add('disable_3d', "Disable 3D nodes for smaller executable (yes/no)", 'no')
-opts.Add('disable_advanced_gui', "Disable advance 3D gui nodes and behaviors (yes/no)", 'no')
+opts.Add(BoolVariable('disable_3d', "Disable 3D nodes for smaller executable", False))
+opts.Add(BoolVariable('disable_advanced_gui', "Disable advance 3D gui nodes and behaviors", False))
opts.Add('extra_suffix', "Custom extra suffix added to the base filename of all generated binary files", '')
opts.Add('unix_global_settings_path', "UNIX-specific path to system-wide settings. Currently only used for templates", '')
-opts.Add('verbose', "Enable verbose output for the compilation (yes/no)", 'no')
-opts.Add('vsproj', "Generate Visual Studio Project. (yes/no)", 'no')
-opts.Add('warnings', "Set the level of warnings emitted during compilation (extra/all/moderate/no)", 'no')
-opts.Add('progress', "Show a progress indicator during build (yes/no)", 'yes')
-opts.Add('dev', "If yes, alias for verbose=yes warnings=all (yes/no)", 'no')
+opts.Add(BoolVariable('verbose', "Enable verbose output for the compilation", False))
+opts.Add(BoolVariable('vsproj', "Generate Visual Studio Project.", False))
+opts.Add(EnumVariable('warnings', "Set the level of warnings emitted during compilation", 'no', ('extra', 'all', 'moderate', 'no')))
+opts.Add(BoolVariable('progress', "Show a progress indicator during build", True))
+opts.Add(BoolVariable('dev', "If yes, alias for verbose=yes warnings=all", False))
# Thirdparty libraries
-opts.Add('builtin_enet', "Use the builtin enet library (yes/no)", 'yes')
-opts.Add('builtin_freetype', "Use the builtin freetype library (yes/no)", 'yes')
-opts.Add('builtin_libogg', "Use the builtin libogg library (yes/no)", 'yes')
-opts.Add('builtin_libpng', "Use the builtin libpng library (yes/no)", 'yes')
-opts.Add('builtin_libtheora', "Use the builtin libtheora library (yes/no)", 'yes')
-opts.Add('builtin_libvorbis', "Use the builtin libvorbis library (yes/no)", 'yes')
-opts.Add('builtin_libvpx', "Use the builtin libvpx library (yes/no)", 'yes')
-opts.Add('builtin_libwebp', "Use the builtin libwebp library (yes/no)", 'yes')
-opts.Add('builtin_openssl', "Use the builtin openssl library (yes/no)", 'yes')
-opts.Add('builtin_opus', "Use the builtin opus library (yes/no)", 'yes')
-opts.Add('builtin_pcre2', "Use the builtin pcre2 library (yes/no)", 'yes')
-opts.Add('builtin_recast', "Use the builtin recast library (yes/no)", 'yes')
-opts.Add('builtin_squish', "Use the builtin squish library (yes/no)", 'yes')
-opts.Add('builtin_zlib', "Use the builtin zlib library (yes/no)", 'yes')
+opts.Add(BoolVariable('builtin_enet', "Use the builtin enet library", True))
+opts.Add(BoolVariable('builtin_freetype', "Use the builtin freetype library", True))
+opts.Add(BoolVariable('builtin_libogg', "Use the builtin libogg library", True))
+opts.Add(BoolVariable('builtin_libpng', "Use the builtin libpng library", True))
+opts.Add(BoolVariable('builtin_libtheora', "Use the builtin libtheora library", True))
+opts.Add(BoolVariable('builtin_libvorbis', "Use the builtin libvorbis library", True))
+opts.Add(BoolVariable('builtin_libvpx', "Use the builtin libvpx library", True))
+opts.Add(BoolVariable('builtin_libwebp', "Use the builtin libwebp library", True))
+opts.Add(BoolVariable('builtin_openssl', "Use the builtin openssl library", True))
+opts.Add(BoolVariable('builtin_opus', "Use the builtin opus library", True))
+opts.Add(BoolVariable('builtin_pcre2', "Use the builtin pcre2 library)", True))
+opts.Add(BoolVariable('builtin_recast', "Use the builtin recast library", True))
+opts.Add(BoolVariable('builtin_squish', "Use the builtin squish library", True))
+opts.Add(BoolVariable('builtin_zlib', "Use the builtin zlib library", True))
+opts.Add(BoolVariable('builtin_zstd', "Use the builtin zstd library", True))
# Environment setup
opts.Add("CXX", "C++ compiler")
@@ -185,10 +186,19 @@ opts.Add("LINKFLAGS", "Custom flags for the linker")
for k in platform_opts.keys():
opt_list = platform_opts[k]
for o in opt_list:
- opts.Add(o[0], o[1], o[2])
+ opts.Add(o)
for x in module_list:
- opts.Add('module_' + x + '_enabled', "Enable module '" + x + "' (yes/no)", "yes")
+ module_enabled = True
+ tmppath = "./modules/" + x
+ sys.path.append(tmppath)
+ import config
+ enabled_attr = getattr(config, "is_enabled", None)
+ if (callable(enabled_attr) and not config.is_enabled()):
+ module_enabled = False
+ sys.path.remove(tmppath)
+ sys.modules.pop('config')
+ opts.Add(BoolVariable('module_' + x + '_enabled', "Enable module '%s'" % (x, ), module_enabled))
opts.Update(env_base) # update environment
Help(opts.GenerateHelpText(env_base)) # generate help
@@ -212,7 +222,7 @@ if (env_base['target'] == 'debug'):
env_base.Append(CPPFLAGS=['-DDEBUG_MEMORY_ALLOC'])
env_base.Append(CPPFLAGS=['-DSCI_NAMESPACE'])
-if (env_base['deprecated'] == 'no'):
+if not env_base['deprecated']:
env_base.Append(CPPFLAGS=['-DDISABLE_DEPRECATED'])
env_base.platforms = {}
@@ -235,12 +245,12 @@ if selected_platform in platform_list:
env = detect.create(env_base)
else:
env = env_base.Clone()
-
- if (env["dev"] == "yes"):
+
+ if env['dev']:
env["warnings"] = "all"
- env["verbose"] = "yes"
+ env['verbose'] = True
- if env['vsproj'] == "yes":
+ if env['vsproj']:
env.vs_incs = []
env.vs_srcs = []
@@ -318,19 +328,19 @@ if selected_platform in platform_list:
suffix = "." + selected_platform
if (env["target"] == "release"):
- if (env["tools"] == "yes"):
+ if env["tools"]:
print("Tools can only be built with targets 'debug' and 'release_debug'.")
sys.exit(255)
suffix += ".opt"
env.Append(CCFLAGS=['-DNDEBUG'])
elif (env["target"] == "release_debug"):
- if (env["tools"] == "yes"):
+ if env["tools"]:
suffix += ".opt.tools"
else:
suffix += ".opt.debug"
else:
- if (env["tools"] == "yes"):
+ if env["tools"]:
suffix += ".tools"
else:
suffix += ".debug"
@@ -358,7 +368,7 @@ if selected_platform in platform_list:
env.doc_class_path={}
for x in module_list:
- if env['module_' + x + '_enabled'] != "yes":
+ if not env['module_' + x + '_enabled']:
continue
tmppath = "./modules/" + x
sys.path.append(tmppath)
@@ -367,13 +377,13 @@ if selected_platform in platform_list:
if (config.can_build(selected_platform)):
config.configure(env)
env.module_list.append(x)
- try:
- doc_classes = config.get_doc_classes()
- doc_path = config.get_doc_path()
- for c in doc_classes:
- env.doc_class_path[c]="modules/"+x+"/"+doc_path
- except:
- pass
+ try:
+ doc_classes = config.get_doc_classes()
+ doc_path = config.get_doc_path()
+ for c in doc_classes:
+ env.doc_class_path[c]="modules/"+x+"/"+doc_path
+ except:
+ pass
sys.path.remove(tmppath)
@@ -385,22 +395,22 @@ if selected_platform in platform_list:
# to test 64 bits compiltion
# env.Append(CPPFLAGS=['-m64'])
- if (env['tools'] == 'yes'):
+ if env['tools']:
env.Append(CPPFLAGS=['-DTOOLS_ENABLED'])
- if (env['disable_3d'] == 'yes'):
+ if env['disable_3d']:
env.Append(CPPFLAGS=['-D_3D_DISABLED'])
- if (env['gdscript'] == 'yes'):
+ if env['gdscript']:
env.Append(CPPFLAGS=['-DGDSCRIPT_ENABLED'])
- if (env['disable_advanced_gui'] == 'yes'):
+ if env['disable_advanced_gui']:
env.Append(CPPFLAGS=['-DADVANCED_GUI_DISABLED'])
- if (env['minizip'] == 'yes'):
+ if env['minizip']:
env.Append(CPPFLAGS=['-DMINIZIP_ENABLED'])
- if (env['xml'] == 'yes'):
+ if env['xml']:
env.Append(CPPFLAGS=['-DXML_ENABLED'])
- if (env['verbose'] == 'no'):
+ if not env['verbose']:
methods.no_verbose(sys, env)
if (True): # FIXME: detect GLES3
@@ -422,7 +432,8 @@ if selected_platform in platform_list:
SConscript("platform/" + selected_platform + "/SCsub") # build selected platform
# Microsoft Visual Studio Project Generation
- if (env['vsproj']) == "yes":
+ if env['vsproj']:
+ env['CPPPATH'] = [Dir(path) for path in env['CPPPATH']]
methods.generate_vs_project(env, GetOption("num_jobs"))
# Check for the existence of headers
@@ -469,7 +480,7 @@ def progress_finish(target, source, env):
with open(node_count_fname, 'w') as f:
f.write('%d\n' % node_count)
-if ('env' in locals() and env["progress"] == "yes"):
+if 'env' in locals() and env['progress']:
try:
with open(node_count_fname) as f:
node_count_max = int(f.readline())
diff --git a/core/SCsub b/core/SCsub
index c1e57f6840..e9b21bc71b 100644
--- a/core/SCsub
+++ b/core/SCsub
@@ -83,24 +83,8 @@ thirdparty_minizip_sources = [
thirdparty_minizip_sources = [thirdparty_minizip_dir + file for file in thirdparty_minizip_sources]
env.add_source_files(env.core_sources, thirdparty_minizip_sources)
-thirdparty_zstd_dir = "#thirdparty/zstd/"
-thirdparty_zstd_sources = [
- "common/entropy_common.c",
- "common/error_private.c",
- "common/fse_decompress.c",
- "common/pool.c",
- "common/threading.c",
- "common/xxhash.c",
- "common/zstd_common.c",
- "compress/fse_compress.c",
- "compress/huf_compress.c",
- "compress/zstd_compress.c",
- "compress/zstdmt_compress.c",
- "decompress/huf_decompress.c",
- "decompress/zstd_decompress.c",
-]
-thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
-env.add_source_files(env.core_sources, thirdparty_zstd_sources)
+if 'builtin_zstd' in env and env['builtin_zstd']:
+ SConscript("#thirdparty/zstd/SCsub")
# Godot's own sources
@@ -123,5 +107,4 @@ SConscript('helper/SCsub')
# Build it all as a library
lib = env.Library("core", env.core_sources)
env.Prepend(LIBS=[lib])
-env.Append(CPPPATH=["#thirdparty/zstd", "#thirdparty/zstd/common"])
Export('env')
diff --git a/core/array.cpp b/core/array.cpp
index 2e3fbf858d..30184a002e 100644
--- a/core/array.cpp
+++ b/core/array.cpp
@@ -47,11 +47,11 @@ void Array::_ref(const Array &p_from) const {
ERR_FAIL_COND(!_fp); // should NOT happen.
if (_fp == _p)
- return; //wathever it is, nothing to do here move along
+ return; // whatever it is, nothing to do here move along
bool success = _fp->refcount.ref();
- ERR_FAIL_COND(!success); //should really not happen either
+ ERR_FAIL_COND(!success); // should really not happen either
_unref();
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index d0acd04497..f47d540351 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -33,6 +33,7 @@
#include "geometry.h"
#include "io/file_access_compressed.h"
#include "io/file_access_encrypted.h"
+#include "io/json.h"
#include "io/marshalls.h"
#include "os/keyboard.h"
#include "os/os.h"
@@ -440,8 +441,8 @@ bool _OS::is_vsync_enabled() const {
return OS::get_singleton()->is_vsync_enabled();
}
-OS::PowerState _OS::get_power_state() {
- return OS::get_singleton()->get_power_state();
+_OS::PowerState _OS::get_power_state() {
+ return _OS::PowerState(OS::get_singleton()->get_power_state());
}
int _OS::get_power_seconds_left() {
@@ -1032,10 +1033,8 @@ void _OS::_bind_methods() {
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(D_METHOD("get_unix_time_from_datetime", "datetime"),
- &_OS::get_unix_time_from_datetime);
+ ClassDB::bind_method(D_METHOD("get_datetime_from_unix_time", "unix_time_val"), &_OS::get_datetime_from_unix_time);
+ ClassDB::bind_method(D_METHOD("get_unix_time_from_datetime", "datetime"), &_OS::get_unix_time_from_datetime);
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);
@@ -1142,11 +1141,11 @@ void _OS::_bind_methods() {
BIND_ENUM_CONSTANT(SYSTEM_DIR_PICTURES);
BIND_ENUM_CONSTANT(SYSTEM_DIR_RINGTONES);
- BIND_ENUM_CONSTANT(OS::POWERSTATE_UNKNOWN);
- BIND_ENUM_CONSTANT(OS::POWERSTATE_ON_BATTERY);
- BIND_ENUM_CONSTANT(OS::POWERSTATE_NO_BATTERY);
- BIND_ENUM_CONSTANT(OS::POWERSTATE_CHARGING);
- BIND_ENUM_CONSTANT(OS::POWERSTATE_CHARGED);
+ BIND_ENUM_CONSTANT(POWERSTATE_UNKNOWN);
+ BIND_ENUM_CONSTANT(POWERSTATE_ON_BATTERY);
+ BIND_ENUM_CONSTANT(POWERSTATE_NO_BATTERY);
+ BIND_ENUM_CONSTANT(POWERSTATE_CHARGING);
+ BIND_ENUM_CONSTANT(POWERSTATE_CHARGED);
}
_OS::_OS() {
@@ -1336,7 +1335,7 @@ void _Geometry::_bind_methods() {
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_circle", "segment_from", "segment_to", "circle_position", "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);
@@ -1352,7 +1351,7 @@ void _Geometry::_bind_methods() {
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_sphere", "from", "to", "sphere_position", "sphere_radius"), &_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);
@@ -1451,10 +1450,10 @@ void _File::seek_end(int64_t p_position) {
ERR_FAIL_COND(!f);
f->seek_end(p_position);
}
-int64_t _File::get_pos() const {
+int64_t _File::get_position() const {
ERR_FAIL_COND_V(!f, 0);
- return f->get_pos();
+ return f->get_position();
}
int64_t _File::get_len() const {
@@ -1533,7 +1532,7 @@ String _File::get_as_text() const {
ERR_FAIL_COND_V(!f, String());
String text;
- size_t original_pos = f->get_pos();
+ size_t original_pos = f->get_position();
f->seek(0);
String l = get_line();
@@ -1730,9 +1729,9 @@ void _File::_bind_methods() {
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("seek", "position"), &_File::seek);
+ ClassDB::bind_method(D_METHOD("seek_end", "position"), &_File::seek_end, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("get_position"), &_File::get_position);
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);
@@ -2558,8 +2557,8 @@ Dictionary _Engine::get_version_info() const {
return Engine::get_singleton()->get_version_info();
}
-bool _Engine::is_in_fixed_frame() const {
- return Engine::get_singleton()->is_in_fixed_frame();
+bool _Engine::is_in_physics_frame() const {
+ return Engine::get_singleton()->is_in_physics_frame();
}
void _Engine::set_editor_hint(bool p_enabled) {
@@ -2589,7 +2588,7 @@ void _Engine::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_version_info"), &_Engine::get_version_info);
- ClassDB::bind_method(D_METHOD("is_in_fixed_frame"), &_Engine::is_in_fixed_frame);
+ ClassDB::bind_method(D_METHOD("is_in_physics_frame"), &_Engine::is_in_physics_frame);
ClassDB::bind_method(D_METHOD("set_editor_hint", "enabled"), &_Engine::set_editor_hint);
ClassDB::bind_method(D_METHOD("is_editor_hint"), &_Engine::is_editor_hint);
@@ -2600,3 +2599,76 @@ _Engine *_Engine::singleton = NULL;
_Engine::_Engine() {
singleton = this;
}
+
+void JSONParseResult::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_error"), &JSONParseResult::get_error);
+ ClassDB::bind_method(D_METHOD("get_error_string"), &JSONParseResult::get_error_string);
+ ClassDB::bind_method(D_METHOD("get_error_line"), &JSONParseResult::get_error_line);
+ ClassDB::bind_method(D_METHOD("get_result"), &JSONParseResult::get_result);
+
+ ClassDB::bind_method(D_METHOD("set_error", "error"), &JSONParseResult::set_error);
+ ClassDB::bind_method(D_METHOD("set_error_string", "error_string"), &JSONParseResult::set_error_string);
+ ClassDB::bind_method(D_METHOD("set_error_line", "error_line"), &JSONParseResult::set_error_line);
+ ClassDB::bind_method(D_METHOD("set_result", "result"), &JSONParseResult::set_result);
+
+ ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "error", PROPERTY_HINT_NONE, "Error", PROPERTY_USAGE_CLASS_IS_ENUM), "set_error", "get_error");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::STRING, "error_string"), "set_error_string", "get_error_string");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "error_line"), "set_error_line", "get_error_line");
+ ADD_PROPERTYNZ(PropertyInfo(Variant::NIL, "result", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NIL_IS_VARIANT), "set_result", "get_result");
+}
+
+void JSONParseResult::set_error(Error p_error) {
+ error = p_error;
+}
+
+Error JSONParseResult::get_error() const {
+ return error;
+}
+
+void JSONParseResult::set_error_string(const String &p_error_string) {
+ error_string = p_error_string;
+}
+
+String JSONParseResult::get_error_string() const {
+ return error_string;
+}
+
+void JSONParseResult::set_error_line(int p_error_line) {
+ error_line = p_error_line;
+}
+
+int JSONParseResult::get_error_line() const {
+ return error_line;
+}
+
+void JSONParseResult::set_result(const Variant &p_result) {
+ result = p_result;
+}
+
+Variant JSONParseResult::get_result() const {
+ return result;
+}
+
+void _JSON::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("print", "value"), &_JSON::print);
+ ClassDB::bind_method(D_METHOD("parse", "json"), &_JSON::parse);
+}
+
+String _JSON::print(const Variant &p_value) {
+ return JSON::print(p_value);
+}
+
+Ref<JSONParseResult> _JSON::parse(const String &p_json) {
+ Ref<JSONParseResult> result;
+ result.instance();
+
+ result->error = JSON::parse(p_json, result->result, result->error_string, result->error_line);
+
+ return result;
+}
+
+_JSON *_JSON::singleton = NULL;
+
+_JSON::_JSON() {
+ singleton = this;
+}
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 0578c2b80f..f12ab9f000 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -97,6 +97,14 @@ protected:
static _OS *singleton;
public:
+ enum PowerState {
+ 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 */
+ };
+
enum Weekday {
DAY_SUNDAY,
DAY_MONDAY,
@@ -303,7 +311,7 @@ public:
void set_use_vsync(bool p_enable);
bool is_vsync_enabled() const;
- OS::PowerState get_power_state();
+ PowerState get_power_state();
int get_power_seconds_left();
int get_power_percent_left();
@@ -312,6 +320,7 @@ public:
_OS();
};
+VARIANT_ENUM_CAST(_OS::PowerState);
VARIANT_ENUM_CAST(_OS::Weekday);
VARIANT_ENUM_CAST(_OS::Month);
VARIANT_ENUM_CAST(_OS::SystemDir);
@@ -390,7 +399,7 @@ public:
void seek(int64_t p_position); ///< seek to a given position
void seek_end(int64_t p_position = 0); ///< seek from the end of file
- int64_t get_pos() const; ///< get position in the file
+ int64_t get_position() const; ///< get position in the file
int64_t get_len() const; ///< get size of the file
bool eof_reached() const; ///< reading passed EOF
@@ -652,7 +661,7 @@ public:
Dictionary get_version_info() const;
- bool is_in_fixed_frame() const;
+ bool is_in_physics_frame() const;
void set_editor_hint(bool p_enabled);
bool is_editor_hint() const;
@@ -660,4 +669,50 @@ public:
_Engine();
};
+class _JSON;
+
+class JSONParseResult : public Reference {
+ GDCLASS(JSONParseResult, Reference)
+
+ friend class _JSON;
+
+ Error error;
+ String error_string;
+ int error_line;
+
+ Variant result;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_error(Error p_error);
+ Error get_error() const;
+
+ void set_error_string(const String &p_error_string);
+ String get_error_string() const;
+
+ void set_error_line(int p_error_line);
+ int get_error_line() const;
+
+ void set_result(const Variant &p_result);
+ Variant get_result() const;
+};
+
+class _JSON : public Object {
+ GDCLASS(_JSON, Object)
+
+protected:
+ static void _bind_methods();
+ static _JSON *singleton;
+
+public:
+ static _JSON *get_singleton() { return singleton; }
+
+ String print(const Variant &p_value);
+ Ref<JSONParseResult> parse(const String &p_json);
+
+ _JSON();
+};
+
#endif // CORE_BIND_H
diff --git a/core/color.cpp b/core/color.cpp
index 259a4988b1..78b11a84df 100644
--- a/core/color.cpp
+++ b/core/color.cpp
@@ -250,6 +250,14 @@ Color Color::html(const String &p_color) {
return Color();
if (color[0] == '#')
color = color.substr(1, color.length() - 1);
+ if (color.length() == 3 || color.length() == 4) {
+ String exp_color;
+ for (int i = 0; i < color.length(); i++) {
+ exp_color += color[i];
+ exp_color += color[i];
+ }
+ color = exp_color;
+ }
bool alpha = false;
@@ -400,3 +408,122 @@ Color::operator String() const {
return rtos(r) + ", " + rtos(g) + ", " + rtos(b) + ", " + rtos(a);
}
+
+Color Color::operator+(const Color &p_color) const {
+
+ return Color(
+ CLAMP(r + p_color.r, 0.0, 1.0),
+ CLAMP(g + p_color.g, 0.0, 1.0),
+ CLAMP(b + p_color.b, 0.0, 1.0),
+ CLAMP(a + p_color.a, 0.0, 1.0));
+}
+
+void Color::operator+=(const Color &p_color) {
+
+ r = CLAMP(r + p_color.r, 0.0, 1.0);
+ g = CLAMP(g + p_color.g, 0.0, 1.0);
+ b = CLAMP(b + p_color.b, 0.0, 1.0);
+ a = CLAMP(a + p_color.a, 0.0, 1.0);
+}
+
+Color Color::operator-(const Color &p_color) const {
+
+ return Color(
+ CLAMP(r - p_color.r, 0.0, 1.0),
+ CLAMP(g - p_color.g, 0.0, 1.0),
+ CLAMP(b - p_color.b, 0.0, 1.0),
+ CLAMP(a - p_color.a, 0.0, 1.0));
+}
+
+void Color::operator-=(const Color &p_color) {
+
+ r = CLAMP(r - p_color.r, 0.0, 1.0);
+ g = CLAMP(g - p_color.g, 0.0, 1.0);
+ b = CLAMP(b - p_color.b, 0.0, 1.0);
+ a = CLAMP(a - p_color.a, 0.0, 1.0);
+}
+
+Color Color::operator*(const Color &p_color) const {
+
+ return Color(
+ CLAMP(r * p_color.r, 0.0, 1.0),
+ CLAMP(g * p_color.g, 0.0, 1.0),
+ CLAMP(b * p_color.b, 0.0, 1.0),
+ CLAMP(a * p_color.a, 0.0, 1.0));
+}
+
+Color Color::operator*(const real_t &rvalue) const {
+
+ return Color(
+ CLAMP(r * rvalue, 0.0, 1.0),
+ CLAMP(g * rvalue, 0.0, 1.0),
+ CLAMP(b * rvalue, 0.0, 1.0),
+ CLAMP(a * rvalue, 0.0, 1.0));
+}
+
+void Color::operator*=(const Color &p_color) {
+
+ r = CLAMP(r * p_color.r, 0.0, 1.0);
+ g = CLAMP(g * p_color.g, 0.0, 1.0);
+ b = CLAMP(b * p_color.b, 0.0, 1.0);
+ a = CLAMP(a * p_color.a, 0.0, 1.0);
+}
+
+void Color::operator*=(const real_t &rvalue) {
+
+ r = CLAMP(r * rvalue, 0.0, 1.0);
+ g = CLAMP(g * rvalue, 0.0, 1.0);
+ b = CLAMP(b * rvalue, 0.0, 1.0);
+ a = CLAMP(a * rvalue, 0.0, 1.0);
+};
+
+Color Color::operator/(const Color &p_color) const {
+
+ return Color(
+ p_color.r == 0 ? 1 : CLAMP(r / p_color.r, 0.0, 1.0),
+ p_color.g == 0 ? 1 : CLAMP(g / p_color.g, 0.0, 1.0),
+ p_color.b == 0 ? 1 : CLAMP(b / p_color.b, 0.0, 1.0),
+ p_color.a == 0 ? 1 : CLAMP(a / p_color.a, 0.0, 1.0));
+}
+
+Color Color::operator/(const real_t &rvalue) const {
+
+ if (rvalue == 0) return Color(1.0, 1.0, 1.0, 1.0);
+ return Color(
+ CLAMP(r / rvalue, 0.0, 1.0),
+ CLAMP(g / rvalue, 0.0, 1.0),
+ CLAMP(b / rvalue, 0.0, 1.0),
+ CLAMP(a / rvalue, 0.0, 1.0));
+}
+
+void Color::operator/=(const Color &p_color) {
+
+ r = p_color.r == 0 ? 1 : CLAMP(r / p_color.r, 0.0, 1.0);
+ g = p_color.g == 0 ? 1 : CLAMP(g / p_color.g, 0.0, 1.0);
+ b = p_color.b == 0 ? 1 : CLAMP(b / p_color.b, 0.0, 1.0);
+ a = p_color.a == 0 ? 1 : CLAMP(a / p_color.a, 0.0, 1.0);
+}
+
+void Color::operator/=(const real_t &rvalue) {
+
+ if (rvalue == 0) {
+ r = 1.0;
+ g = 1.0;
+ b = 1.0;
+ a = 1.0;
+ } else {
+ r = CLAMP(r / rvalue, 0.0, 1.0);
+ g = CLAMP(g / rvalue, 0.0, 1.0);
+ b = CLAMP(b / rvalue, 0.0, 1.0);
+ a = CLAMP(a / rvalue, 0.0, 1.0);
+ }
+};
+
+Color Color::operator-() const {
+
+ return Color(
+ CLAMP(1.0 - r, 0.0, 1.0),
+ CLAMP(1.0 - g, 0.0, 1.0),
+ CLAMP(1.0 - b, 0.0, 1.0),
+ CLAMP(1.0 - a, 0.0, 1.0));
+}
diff --git a/core/color.h b/core/color.h
index d3d5db09f9..972b6a1b33 100644
--- a/core/color.h
+++ b/core/color.h
@@ -67,6 +67,23 @@ struct Color {
return components[idx];
}
+ Color operator+(const Color &p_color) const;
+ void operator+=(const Color &p_color);
+
+ Color operator-() const;
+ Color operator-(const Color &p_color) const;
+ void operator-=(const Color &p_color);
+
+ Color operator*(const Color &p_color) const;
+ Color operator*(const real_t &rvalue) const;
+ void operator*=(const Color &p_color);
+ void operator*=(const real_t &rvalue);
+
+ Color operator/(const Color &p_color) const;
+ Color operator/(const real_t &rvalue) const;
+ void operator/=(const Color &p_color);
+ void operator/=(const real_t &rvalue);
+
void invert();
void contrast();
Color inverted() const;
diff --git a/core/core_string_names.cpp b/core/core_string_names.cpp
index ef9346253f..feee39225f 100644
--- a/core/core_string_names.cpp
+++ b/core/core_string_names.cpp
@@ -47,4 +47,27 @@ CoreStringNames::CoreStringNames()
_sections_unfolded(StaticCString::create("_sections_unfolded")),
#endif
_custom_features(StaticCString::create("_custom_features")) {
+
+ x = StaticCString::create("x");
+ y = StaticCString::create("y");
+ z = StaticCString::create("z");
+ w = StaticCString::create("w");
+ r = StaticCString::create("r");
+ g = StaticCString::create("g");
+ b = StaticCString::create("b");
+ a = StaticCString::create("a");
+ position = StaticCString::create("position");
+ size = StaticCString::create("size");
+ end = StaticCString::create("end");
+ basis = StaticCString::create("basis");
+ origin = StaticCString::create("origin");
+ normal = StaticCString::create("normal");
+ d = StaticCString::create("d");
+ h = StaticCString::create("h");
+ s = StaticCString::create("s");
+ v = StaticCString::create("v");
+ r8 = StaticCString::create("r8");
+ g8 = StaticCString::create("g8");
+ b8 = StaticCString::create("b8");
+ a8 = StaticCString::create("a8");
}
diff --git a/core/core_string_names.h b/core/core_string_names.h
index 2eb2b703ae..6fcc773169 100644
--- a/core/core_string_names.h
+++ b/core/core_string_names.h
@@ -37,8 +37,6 @@ class CoreStringNames {
friend void register_core_types();
friend void unregister_core_types();
- static CoreStringNames *singleton;
-
static void create() { singleton = memnew(CoreStringNames); }
static void free() {
memdelete(singleton);
@@ -50,6 +48,8 @@ class CoreStringNames {
public:
_FORCE_INLINE_ static CoreStringNames *get_singleton() { return singleton; }
+ static CoreStringNames *singleton;
+
StringName _free;
StringName changed;
StringName _meta;
@@ -65,6 +65,29 @@ public:
StringName _sections_unfolded;
#endif
StringName _custom_features;
+
+ StringName x;
+ StringName y;
+ StringName z;
+ StringName w;
+ StringName r;
+ StringName g;
+ StringName b;
+ StringName a;
+ StringName position;
+ StringName size;
+ StringName end;
+ StringName basis;
+ StringName origin;
+ StringName normal;
+ StringName d;
+ StringName h;
+ StringName s;
+ StringName v;
+ StringName r8;
+ StringName g8;
+ StringName b8;
+ StringName a8;
};
#endif // SCENE_STRING_NAMES_H
diff --git a/core/engine.cpp b/core/engine.cpp
index d73693dc12..c609ae9520 100644
--- a/core/engine.cpp
+++ b/core/engine.cpp
@@ -116,9 +116,9 @@ Engine::Engine() {
_target_fps = 0;
_time_scale = 1.0;
_pixel_snap = false;
- _fixed_frames = 0;
+ _physics_frames = 0;
_idle_frames = 0;
- _in_fixed = false;
+ _in_physics = false;
_frame_ticks = 0;
_frame_step = 0;
editor_hint = false;
diff --git a/core/engine.h b/core/engine.h
index 6f46ec8923..3b4979582f 100644
--- a/core/engine.h
+++ b/core/engine.h
@@ -49,10 +49,10 @@ class Engine {
int _target_fps;
float _time_scale;
bool _pixel_snap;
- uint64_t _fixed_frames;
+ uint64_t _physics_frames;
uint64_t _idle_frames;
- bool _in_fixed;
+ bool _in_physics;
bool editor_hint;
@@ -71,9 +71,9 @@ public:
uint64_t get_frames_drawn();
- uint64_t get_fixed_frames() const { return _fixed_frames; }
+ uint64_t get_physics_frames() const { return _physics_frames; }
uint64_t get_idle_frames() const { return _idle_frames; }
- bool is_in_fixed_frame() const { return _in_fixed; }
+ bool is_in_physics_frame() const { return _in_physics; }
uint64_t get_idle_frame_ticks() const { return _frame_ticks; }
float get_idle_frame_step() const { return _frame_step; }
diff --git a/core/error_list.h b/core/error_list.h
index bc65ad0ee4..50d248b3d0 100644
--- a/core/error_list.h
+++ b/core/error_list.h
@@ -66,7 +66,7 @@ enum Error {
ERR_CANT_CONNECT, // (25)
ERR_CANT_RESOLVE,
ERR_CONNECTION_ERROR,
- ERR_CANT_AQUIRE_RESOURCE,
+ ERR_CANT_ACQUIRE_RESOURCE,
ERR_CANT_FORK,
ERR_INVALID_DATA, ///< Data passed is invalid (30)
ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
diff --git a/core/error_macros.cpp b/core/error_macros.cpp
index 5919d38375..170a22e8dd 100644
--- a/core/error_macros.cpp
+++ b/core/error_macros.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "error_macros.h"
+#include "io/logger.h"
#include "os/os.h"
bool _err_error_exists = false;
@@ -79,7 +80,7 @@ void remove_error_handler(ErrorHandlerList *p_handler) {
void _err_print_error(const char *p_function, const char *p_file, int p_line, const char *p_error, ErrorHandlerType p_type) {
- OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (OS::ErrorType)p_type);
+ OS::get_singleton()->print_error(p_function, p_file, p_line, p_error, _err_error_exists ? OS::get_singleton()->get_last_error() : "", (Logger::ErrorType)p_type);
_global_lock();
ErrorHandlerList *l = error_handler_list;
diff --git a/core/error_macros.h b/core/error_macros.h
index 005b0e32a3..1fa7f2c134 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -30,6 +30,7 @@
#ifndef ERROR_MACROS_H
#define ERROR_MACROS_H
+#include "typedefs.h"
/**
* Error macros. Unlike exceptions and asserts, these macros try to mantain consistency and stability
* inside the code. It is recommended to always return processable data, so in case of an error, the
@@ -130,7 +131,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_INDEX(m_index, m_size) \
do { \
- if ((m_index) < 0 || (m_index) >= (m_size)) { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
return; \
} else \
@@ -144,7 +145,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
do { \
- if ((m_index) < 0 || (m_index) >= (m_size)) { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
return m_retval; \
} else \
@@ -156,7 +157,7 @@ extern bool _err_error_exists;
*/
#define CRASH_BAD_INDEX(m_index, m_size) \
do { \
- if ((m_index) < 0 || (m_index) >= (m_size)) { \
+ if (unlikely((m_index) < 0 || (m_index) >= (m_size))) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Index " _STR(m_index) " out of size (" _STR(m_size) ")."); \
GENERATE_TRAP \
} \
@@ -168,7 +169,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_NULL(m_param) \
{ \
- if (!m_param) { \
+ if (unlikely(!m_param)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
return; \
} else \
@@ -177,7 +178,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_NULL_V(m_param, m_retval) \
{ \
- if (!m_param) { \
+ if (unlikely(!m_param)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Parameter ' " _STR(m_param) " ' is null."); \
return m_retval; \
} else \
@@ -190,7 +191,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_COND(m_cond) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true."); \
return; \
} else \
@@ -202,7 +203,7 @@ extern bool _err_error_exists;
#define CRASH_COND(m_cond) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "FATAL: Condition ' " _STR(m_cond) " ' is true."); \
GENERATE_TRAP \
} \
@@ -216,7 +217,7 @@ extern bool _err_error_exists;
#define ERR_FAIL_COND_V(m_cond, m_retval) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. returned: " _STR(m_retval)); \
return m_retval; \
} else \
@@ -229,7 +230,7 @@ extern bool _err_error_exists;
#define ERR_CONTINUE(m_cond) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Continuing..:"); \
continue; \
} else \
@@ -242,7 +243,7 @@ extern bool _err_error_exists;
#define ERR_BREAK(m_cond) \
{ \
- if (m_cond) { \
+ if (unlikely(m_cond)) { \
_err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
break; \
} else \
diff --git a/core/global_constants.cpp b/core/global_constants.cpp
index 224ee0e0aa..6f58af2ccf 100644
--- a/core/global_constants.cpp
+++ b/core/global_constants.cpp
@@ -472,7 +472,7 @@ void register_global_constants() {
BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_IN_USE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_LOCKED); ///< resource is locked
BIND_GLOBAL_ENUM_CONSTANT(ERR_TIMEOUT);
- BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_AQUIRE_RESOURCE);
+ BIND_GLOBAL_ENUM_CONSTANT(ERR_CANT_ACQUIRE_RESOURCE);
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_DATA); ///< Data passed is invalid
BIND_GLOBAL_ENUM_CONSTANT(ERR_INVALID_PARAMETER); ///< Parameter passed is invalid
BIND_GLOBAL_ENUM_CONSTANT(ERR_ALREADY_EXISTS); ///< When adding ), item already exists
diff --git a/core/hash_map.h b/core/hash_map.h
index 37391a4c83..e100d7a904 100644
--- a/core/hash_map.h
+++ b/core/hash_map.h
@@ -37,39 +37,6 @@
#include "os/memory.h"
#include "ustring.h"
-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) { return hash_one_uint64(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 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 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>
diff --git a/core/hashfuncs.h b/core/hashfuncs.h
index 56d40f1dd7..2880cc451e 100644
--- a/core/hashfuncs.h
+++ b/core/hashfuncs.h
@@ -33,6 +33,7 @@
#include "math_defs.h"
#include "math_funcs.h"
#include "typedefs.h"
+#include "ustring.h"
/**
* Hashing functions
@@ -128,4 +129,37 @@ static inline uint64_t make_uint64_t(T p_in) {
return _u._u64;
}
+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) { return hash_one_uint64(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 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 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));
+ }
+};
+
#endif
diff --git a/core/image.cpp b/core/image.cpp
index 4d1f32c360..c7f21d5599 100644
--- a/core/image.cpp
+++ b/core/image.cpp
@@ -530,7 +530,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
int height = p_src_height;
double xfac = (double)width / p_dst_width;
double yfac = (double)height / p_dst_height;
- // coordinates of source points and cooefficiens
+ // coordinates of source points and coefficients
double ox, oy, dx, dy, k1, k2;
int ox1, oy1, ox2, oy2;
// destination pixel values
@@ -561,7 +561,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
}
for (int n = -1; n < 3; n++) {
- // get Y cooefficient
+ // get Y coefficient
k1 = _bicubic_interp_kernel(dy - (double)n);
oy2 = oy1 + n;
@@ -571,7 +571,7 @@ static void _scale_cubic(const uint8_t *p_src, uint8_t *p_dst, uint32_t p_src_wi
oy2 = ymax;
for (int m = -1; m < 3; m++) {
- // get X cooefficient
+ // get X coefficient
k2 = k1 * _bicubic_interp_kernel((double)m - dx);
ox2 = ox1 + m;
@@ -1013,8 +1013,8 @@ void Image::shrink_x2() {
copymem(w.ptr(), &r[ofs], new_size);
}
- width /= 2;
- height /= 2;
+ width = MAX(width / 2, 1);
+ height = MAX(height / 2, 1);
data = new_img;
} else {
diff --git a/core/io/compression.cpp b/core/io/compression.cpp
index 44fa65e11d..fbe97e54c7 100644
--- a/core/io/compression.cpp
+++ b/core/io/compression.cpp
@@ -33,9 +33,9 @@
#include "zip_io.h"
#include "thirdparty/misc/fastlz.h"
-#include "thirdparty/zstd/zstd.h"
#include <zlib.h>
+#include <zstd.h>
int Compression::compress(uint8_t *p_dst, const uint8_t *p_src, int p_src_size, Mode p_mode) {
diff --git a/core/io/file_access_buffered.cpp b/core/io/file_access_buffered.cpp
index 859f2e3f8c..9ec03bf32b 100644
--- a/core/io/file_access_buffered.cpp
+++ b/core/io/file_access_buffered.cpp
@@ -76,7 +76,7 @@ void FileAccessBuffered::seek_end(int64_t p_position) {
file.offset = file.size + p_position;
};
-size_t FileAccessBuffered::get_pos() const {
+size_t FileAccessBuffered::get_position() const {
return file.offset;
};
diff --git a/core/io/file_access_buffered.h b/core/io/file_access_buffered.h
index d3137058fb..70aaeb8ae0 100644
--- a/core/io/file_access_buffered.h
+++ b/core/io/file_access_buffered.h
@@ -72,7 +72,7 @@ protected:
int get_cache_size();
public:
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual void seek(size_t p_position); ///< seek to a given position
diff --git a/core/io/file_access_buffered_fa.h b/core/io/file_access_buffered_fa.h
index 9e41834561..309fc16d09 100644
--- a/core/io/file_access_buffered_fa.h
+++ b/core/io/file_access_buffered_fa.h
@@ -76,6 +76,11 @@ protected:
};
public:
+ void flush() {
+
+ f.flush();
+ };
+
void store_8(uint8_t p_dest) {
f.store_8(p_dest);
diff --git a/core/io/file_access_compressed.cpp b/core/io/file_access_compressed.cpp
index 70430ca5d3..514e3c65f0 100644
--- a/core/io/file_access_compressed.cpp
+++ b/core/io/file_access_compressed.cpp
@@ -62,7 +62,7 @@ Error FileAccessCompressed::open_after_magic(FileAccess *p_base) {
block_size = f->get_32();
read_total = f->get_32();
int bc = (read_total / block_size) + 1;
- int acc_ofs = f->get_pos() + bc * 4;
+ int acc_ofs = f->get_position() + bc * 4;
int max_bs = 0;
for (int i = 0; i < bc; i++) {
@@ -232,7 +232,7 @@ void FileAccessCompressed::seek_end(int64_t p_position) {
seek(read_total + p_position);
}
}
-size_t FileAccessCompressed::get_pos() const {
+size_t FileAccessCompressed::get_position() const {
ERR_FAIL_COND_V(!f, 0);
if (writing) {
@@ -338,6 +338,13 @@ Error FileAccessCompressed::get_error() const {
return read_eof ? ERR_FILE_EOF : OK;
}
+void FileAccessCompressed::flush() {
+ ERR_FAIL_COND(!f);
+ ERR_FAIL_COND(!writing);
+
+ // compressed files keep data in memory till close()
+}
+
void FileAccessCompressed::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);
diff --git a/core/io/file_access_compressed.h b/core/io/file_access_compressed.h
index ba84c9767c..1d99e5bfd4 100644
--- a/core/io/file_access_compressed.h
+++ b/core/io/file_access_compressed.h
@@ -74,7 +74,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -84,6 +84,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp
index 12503f3be4..c93e12f7da 100644
--- a/core/io/file_access_encrypted.cpp
+++ b/core/io/file_access_encrypted.cpp
@@ -71,7 +71,7 @@ Error FileAccessEncrypted::open_and_parse(FileAccess *p_base, const Vector<uint8
unsigned char md5d[16];
p_base->get_buffer(md5d, 16);
length = p_base->get_64();
- base = p_base->get_pos();
+ base = p_base->get_position();
ERR_FAIL_COND_V(p_base->get_len() < base + length, ERR_FILE_CORRUPT);
uint32_t ds = length;
if (ds % 16) {
@@ -199,7 +199,7 @@ void FileAccessEncrypted::seek_end(int64_t p_position) {
seek(data.size() + p_position);
}
-size_t FileAccessEncrypted::get_pos() const {
+size_t FileAccessEncrypted::get_position() const {
return pos;
}
@@ -268,6 +268,12 @@ void FileAccessEncrypted::store_buffer(const uint8_t *p_src, int p_length) {
}
}
+void FileAccessEncrypted::flush() {
+ ERR_FAIL_COND(!writing);
+
+ // encrypted files keep data in memory till close()
+}
+
void FileAccessEncrypted::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!writing);
diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h
index 74d00a5a8f..d83fed3e0e 100644
--- a/core/io/file_access_encrypted.h
+++ b/core/io/file_access_encrypted.h
@@ -61,7 +61,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -71,6 +71,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
diff --git a/core/io/file_access_memory.cpp b/core/io/file_access_memory.cpp
index 5b186b7798..0a5815fca8 100644
--- a/core/io/file_access_memory.cpp
+++ b/core/io/file_access_memory.cpp
@@ -120,7 +120,7 @@ void FileAccessMemory::seek_end(int64_t p_position) {
pos = length + p_position;
}
-size_t FileAccessMemory::get_pos() const {
+size_t FileAccessMemory::get_position() const {
ERR_FAIL_COND_V(!data, 0);
return pos;
@@ -170,6 +170,10 @@ Error FileAccessMemory::get_error() const {
return pos >= length ? ERR_FILE_EOF : OK;
}
+void FileAccessMemory::flush() {
+ ERR_FAIL_COND(!data);
+}
+
void FileAccessMemory::store_8(uint8_t p_byte) {
ERR_FAIL_COND(!data);
diff --git a/core/io/file_access_memory.h b/core/io/file_access_memory.h
index 7feb16461b..23392719b4 100644
--- a/core/io/file_access_memory.h
+++ b/core/io/file_access_memory.h
@@ -51,7 +51,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -62,6 +62,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_byte); ///< store a byte
virtual void store_buffer(const uint8_t *p_src, int p_length); ///< store an array of bytes
diff --git a/core/io/file_access_network.cpp b/core/io/file_access_network.cpp
index 58ca2d4c58..a224abd9e7 100644
--- a/core/io/file_access_network.cpp
+++ b/core/io/file_access_network.cpp
@@ -350,7 +350,7 @@ void FileAccessNetwork::seek_end(int64_t p_position) {
seek(total_size + p_position);
}
-size_t FileAccessNetwork::get_pos() const {
+size_t FileAccessNetwork::get_position() const {
ERR_FAIL_COND_V(!opened, 0);
return pos;
@@ -456,6 +456,10 @@ Error FileAccessNetwork::get_error() const {
return pos == total_size ? ERR_FILE_EOF : OK;
}
+void FileAccessNetwork::flush() {
+ ERR_FAIL();
+}
+
void FileAccessNetwork::store_8(uint8_t p_dest) {
ERR_FAIL();
diff --git a/core/io/file_access_network.h b/core/io/file_access_network.h
index cd5046f007..20614476d0 100644
--- a/core/io/file_access_network.h
+++ b/core/io/file_access_network.h
@@ -145,7 +145,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -155,6 +155,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists
diff --git a/core/io/file_access_pack.cpp b/core/io/file_access_pack.cpp
index e511085ac5..a7eb8ce6a9 100644
--- a/core/io/file_access_pack.cpp
+++ b/core/io/file_access_pack.cpp
@@ -140,17 +140,17 @@ bool PackedSourcePCK::try_open_pack(const String &p_path) {
if (magic != 0x43504447) {
//maybe at he end.... self contained exe
f->seek_end();
- f->seek(f->get_pos() - 4);
+ f->seek(f->get_position() - 4);
magic = f->get_32();
if (magic != 0x43504447) {
memdelete(f);
return false;
}
- f->seek(f->get_pos() - 12);
+ f->seek(f->get_position() - 12);
uint64_t ds = f->get_64();
- f->seek(f->get_pos() - ds - 8);
+ f->seek(f->get_position() - ds - 8);
magic = f->get_32();
if (magic != 0x43504447) {
@@ -236,7 +236,7 @@ void FileAccessPack::seek_end(int64_t p_position) {
seek(pf.size + p_position);
}
-size_t FileAccessPack::get_pos() const {
+size_t FileAccessPack::get_position() const {
return pos;
}
@@ -293,6 +293,11 @@ Error FileAccessPack::get_error() const {
return OK;
}
+void FileAccessPack::flush() {
+
+ ERR_FAIL();
+}
+
void FileAccessPack::store_8(uint8_t p_dest) {
ERR_FAIL();
diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h
index 758e9afa8e..12187a353a 100644
--- a/core/io/file_access_pack.h
+++ b/core/io/file_access_pack.h
@@ -148,7 +148,7 @@ public:
virtual void seek(size_t p_position);
virtual void seek_end(int64_t p_position = 0);
- virtual size_t get_pos() const;
+ virtual size_t get_position() const;
virtual size_t get_len() const;
virtual bool eof_reached() const;
@@ -161,6 +161,7 @@ public:
virtual Error get_error() const;
+ virtual void flush();
virtual void store_8(uint8_t p_dest);
virtual void store_buffer(const uint8_t *p_src, int p_length);
diff --git a/core/io/file_access_zip.cpp b/core/io/file_access_zip.cpp
index 8c99ef2983..ec809011a9 100644
--- a/core/io/file_access_zip.cpp
+++ b/core/io/file_access_zip.cpp
@@ -65,7 +65,7 @@ static uLong godot_write(voidpf opaque, voidpf stream, const void *buf, uLong si
static long godot_tell(voidpf opaque, voidpf stream) {
FileAccess *f = (FileAccess *)opaque;
- return f->get_pos();
+ return f->get_position();
};
static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
@@ -76,7 +76,7 @@ static long godot_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
- pos = f->get_pos() + offset;
+ pos = f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
@@ -301,7 +301,7 @@ void FileAccessZip::seek_end(int64_t p_position) {
unzSeekCurrentFile(zfile, get_len() + p_position);
};
-size_t FileAccessZip::get_pos() const {
+size_t FileAccessZip::get_position() const {
ERR_FAIL_COND_V(!zfile, 0);
return unztell(zfile);
@@ -353,6 +353,11 @@ Error FileAccessZip::get_error() const {
return OK;
};
+void FileAccessZip::flush() {
+
+ ERR_FAIL();
+}
+
void FileAccessZip::store_8(uint8_t p_dest) {
ERR_FAIL();
diff --git a/core/io/file_access_zip.h b/core/io/file_access_zip.h
index 2a8ec3fca5..0977b241ee 100644
--- a/core/io/file_access_zip.h
+++ b/core/io/file_access_zip.h
@@ -98,7 +98,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -108,6 +108,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/core/io/logger.cpp b/core/io/logger.cpp
new file mode 100644
index 0000000000..7ea5f06d7e
--- /dev/null
+++ b/core/io/logger.cpp
@@ -0,0 +1,252 @@
+/*************************************************************************/
+/* logger.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "logger.h"
+#include "os/dir_access.h"
+#include "os/os.h"
+#include "print_string.h"
+
+bool Logger::should_log(bool p_err) {
+ return (!p_err || _print_error_enabled) && (p_err || _print_line_enabled);
+}
+
+void Logger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+ if (!should_log(true)) {
+ return;
+ }
+
+ const char *err_type = "**ERROR**";
+ switch (p_type) {
+ case ERR_ERROR: err_type = "**ERROR**"; break;
+ case ERR_WARNING: err_type = "**WARNING**"; break;
+ case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
+ case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
+ default: ERR_PRINT("Unknown error type"); break;
+ }
+
+ const char *err_details;
+ if (p_rationale && *p_rationale)
+ err_details = p_rationale;
+ else
+ err_details = p_code;
+
+ logf_error("%s: %s\n", err_type, err_details);
+ logf_error(" At: %s:%i:%s() - %s\n", p_file, p_line, p_function, p_code);
+}
+
+void Logger::logf(const char *p_format, ...) {
+ if (!should_log(false)) {
+ return;
+ }
+
+ va_list argp;
+ va_start(argp, p_format);
+
+ logv(p_format, argp, false);
+
+ va_end(argp);
+}
+
+void Logger::logf_error(const char *p_format, ...) {
+ if (!should_log(true)) {
+ return;
+ }
+
+ va_list argp;
+ va_start(argp, p_format);
+
+ logv(p_format, argp, true);
+
+ va_end(argp);
+}
+
+Logger::~Logger() {}
+
+void RotatedFileLogger::close_file() {
+ if (file) {
+ memdelete(file);
+ file = NULL;
+ }
+}
+
+void RotatedFileLogger::clear_old_backups() {
+ int max_backups = max_files - 1; // -1 for the current file
+
+ String basename = base_path.get_basename();
+ String extension = "." + base_path.get_extension();
+
+ DirAccess *da = DirAccess::open(base_path.get_base_dir());
+ if (!da) {
+ return;
+ }
+
+ da->list_dir_begin();
+ String f = da->get_next();
+ Set<String> backups;
+ while (f != String()) {
+ if (!da->current_is_dir() && f.begins_with(basename) && f.ends_with(extension) && f != base_path) {
+ backups.insert(f);
+ }
+ f = da->get_next();
+ }
+ da->list_dir_end();
+
+ if (backups.size() > max_backups) {
+ // since backups are appended with timestamp and Set iterates them in sorted order,
+ // first backups are the oldest
+ int to_delete = backups.size() - max_backups;
+ for (Set<String>::Element *E = backups.front(); E && to_delete > 0; E = E->next(), --to_delete) {
+ da->remove(E->get());
+ }
+ }
+
+ memdelete(da);
+}
+
+void RotatedFileLogger::rotate_file() {
+ close_file();
+
+ if (FileAccess::exists(base_path)) {
+ if (max_files > 1) {
+ char timestamp[21];
+ OS::Date date = OS::get_singleton()->get_date();
+ OS::Time time = OS::get_singleton()->get_time();
+ sprintf(timestamp, "-%04d-%02d-%02d-%02d-%02d-%02d", date.year, date.month, date.day + 1, time.hour, time.min, time.sec);
+
+ String backup_name = base_path.get_basename() + timestamp + "." + base_path.get_extension();
+
+ DirAccess *da = DirAccess::open(base_path.get_base_dir());
+ if (da) {
+ da->copy(base_path, backup_name);
+ memdelete(da);
+ }
+ clear_old_backups();
+ }
+ } else {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_USERDATA);
+ if (da) {
+ da->make_dir_recursive(base_path.get_base_dir());
+ memdelete(da);
+ }
+ }
+
+ file = FileAccess::open(base_path, FileAccess::WRITE);
+}
+
+RotatedFileLogger::RotatedFileLogger(const String &p_base_path, int p_max_files) {
+ file = NULL;
+ base_path = p_base_path.simplify_path();
+ max_files = p_max_files > 0 ? p_max_files : 1;
+
+ rotate_file();
+}
+
+void RotatedFileLogger::logv(const char *p_format, va_list p_list, bool p_err) {
+ if (!should_log(p_err)) {
+ return;
+ }
+
+ if (file) {
+ const int static_buf_size = 512;
+ char static_buf[static_buf_size];
+ char *buf = static_buf;
+ int len = vsnprintf(buf, static_buf_size, p_format, p_list);
+ if (len >= static_buf_size) {
+ buf = (char *)Memory::alloc_static(len + 1);
+ vsnprintf(buf, len + 1, p_format, p_list);
+ }
+ file->store_buffer((uint8_t *)buf, len);
+ if (len >= static_buf_size) {
+ Memory::free_static(buf);
+ }
+#ifdef DEBUG_ENABLED
+ const bool need_flush = true;
+#else
+ bool need_flush = p_err;
+#endif
+ if (need_flush) {
+ file->flush();
+ }
+ }
+}
+
+RotatedFileLogger::~RotatedFileLogger() {
+ close_file();
+}
+
+void StdLogger::logv(const char *p_format, va_list p_list, bool p_err) {
+ if (!should_log(p_err)) {
+ return;
+ }
+
+ if (p_err) {
+ vfprintf(stderr, p_format, p_list);
+ } else {
+ vprintf(p_format, p_list);
+#ifdef DEBUG_ENABLED
+ fflush(stdout);
+#endif
+ }
+}
+
+StdLogger::~StdLogger() {}
+
+CompositeLogger::CompositeLogger(Vector<Logger *> p_loggers) {
+ loggers = p_loggers;
+}
+
+void CompositeLogger::logv(const char *p_format, va_list p_list, bool p_err) {
+ if (!should_log(p_err)) {
+ return;
+ }
+
+ for (int i = 0; i < loggers.size(); ++i) {
+ va_list list_copy;
+ va_copy(list_copy, p_list);
+ loggers[i]->logv(p_format, list_copy, p_err);
+ va_end(list_copy);
+ }
+}
+
+void CompositeLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+ if (!should_log(true)) {
+ return;
+ }
+
+ for (int i = 0; i < loggers.size(); ++i) {
+ loggers[i]->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
+ }
+}
+
+CompositeLogger::~CompositeLogger() {
+ for (int i = 0; i < loggers.size(); ++i) {
+ memdelete(loggers[i]);
+ }
+}
diff --git a/core/io/logger.h b/core/io/logger.h
new file mode 100644
index 0000000000..cf0cc7699f
--- /dev/null
+++ b/core/io/logger.h
@@ -0,0 +1,107 @@
+/*************************************************************************/
+/* logger.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 LOGGER_H
+#define LOGGER_H
+
+#include "os/file_access.h"
+#include "ustring.h"
+#include "vector.h"
+#include <stdarg.h>
+
+class Logger {
+protected:
+ bool should_log(bool p_err);
+
+public:
+ enum ErrorType {
+ ERR_ERROR,
+ ERR_WARNING,
+ ERR_SCRIPT,
+ ERR_SHADER
+ };
+
+ virtual void logv(const char *p_format, va_list p_list, bool p_err) = 0;
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+
+ void logf(const char *p_format, ...);
+ void logf_error(const char *p_format, ...);
+
+ virtual ~Logger();
+};
+
+/**
+ * Writes messages to stdout/stderr.
+ */
+class StdLogger : public Logger {
+
+public:
+ virtual void logv(const char *p_format, va_list p_list, bool p_err);
+ virtual ~StdLogger();
+};
+
+/**
+ * Writes messages to the specified file. If the file already exists, creates a copy (backup)
+ * of it with timestamp appended to the file name. Maximum number of backups is configurable.
+ * When maximum is reached, the oldest backups are erased. With the maximum being equal to 1,
+ * it acts as a simple file logger.
+ */
+class RotatedFileLogger : public Logger {
+ String base_path;
+ int max_files;
+
+ FileAccess *file;
+
+ void rotate_file_without_closing();
+ void close_file();
+ void clear_old_backups();
+ void rotate_file();
+
+public:
+ RotatedFileLogger(const String &p_base_path, int p_max_files = 10);
+
+ virtual void logv(const char *p_format, va_list p_list, bool p_err);
+
+ virtual ~RotatedFileLogger();
+};
+
+class CompositeLogger : public Logger {
+ Vector<Logger *> loggers;
+
+public:
+ CompositeLogger(Vector<Logger *> p_loggers);
+
+ virtual void logv(const char *p_format, va_list p_list, bool p_err);
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+
+ virtual ~CompositeLogger();
+};
+
+#endif \ No newline at end of file
diff --git a/core/io/pck_packer.cpp b/core/io/pck_packer.cpp
index f1f5b6f538..23e86580d1 100644
--- a/core/io/pck_packer.cpp
+++ b/core/io/pck_packer.cpp
@@ -119,7 +119,7 @@ Error PCKPacker::flush(bool p_verbose) {
for (int i = 0; i < files.size(); i++) {
file->store_pascal_string(files[i].path);
- files[i].offset_offset = file->get_pos();
+ files[i].offset_offset = file->get_position();
file->store_64(0); // offset
file->store_64(files[i].size); // size
@@ -130,10 +130,10 @@ Error PCKPacker::flush(bool p_verbose) {
file->store_32(0);
};
- uint64_t ofs = file->get_pos();
+ uint64_t ofs = file->get_position();
ofs = _align(ofs, alignment);
- _pad(file, ofs - file->get_pos());
+ _pad(file, ofs - file->get_position());
const uint32_t buf_max = 65536;
uint8_t *buf = memnew_arr(uint8_t, buf_max);
@@ -150,7 +150,7 @@ Error PCKPacker::flush(bool p_verbose) {
to_write -= read;
};
- uint64_t pos = file->get_pos();
+ uint64_t pos = file->get_position();
file->seek(files[i].offset_offset); // go back to store the file's offset
file->store_64(ofs);
file->seek(pos);
diff --git a/core/io/resource_format_binary.cpp b/core/io/resource_format_binary.cpp
index 16ec6cd3c5..900db7c2dc 100644
--- a/core/io/resource_format_binary.cpp
+++ b/core/io/resource_format_binary.cpp
@@ -1179,7 +1179,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
save_ustring(fw, get_ustring(f)); //type
- size_t md_ofs = f->get_pos();
+ size_t md_ofs = f->get_position();
size_t importmd_ofs = f->get_64();
fw->store_64(0); //metadata offset
@@ -1227,7 +1227,7 @@ Error ResourceFormatLoaderBinary::rename_dependencies(const String &p_path, cons
save_ustring(fw, path);
}
- int64_t size_diff = (int64_t)fw->get_pos() - (int64_t)f->get_pos();
+ int64_t size_diff = (int64_t)fw->get_position() - (int64_t)f->get_position();
//internal resources
uint32_t int_resources_size = f->get_32();
@@ -1880,7 +1880,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
} else {
save_unicode_string(r->get_path()); //actual external
}
- ofs_pos.push_back(f->get_pos());
+ ofs_pos.push_back(f->get_position());
f->store_64(0); //offset in 64 bits
}
@@ -1891,7 +1891,7 @@ Error ResourceFormatSaverBinaryInstance::save(const String &p_path, const RES &p
ResourceData &rd = E->get();
- ofs_table.push_back(f->get_pos());
+ ofs_table.push_back(f->get_position());
save_unicode_string(rd.type);
f->store_32(rd.properties.size());
diff --git a/core/io/resource_import.cpp b/core/io/resource_import.cpp
index be486a86a3..bc7ea47762 100644
--- a/core/io/resource_import.cpp
+++ b/core/io/resource_import.cpp
@@ -87,6 +87,8 @@ Error ResourceFormatImporter::_get_path_and_type(const String &p_path, PathAndTy
path_found = true; //first match must have priority
} else if (assign == "type") {
r_path_and_type.type = value;
+ } else if (assign == "importer") {
+ r_path_and_type.importer = value;
} else if (assign == "valid") {
if (r_valid) {
*r_valid = value;
@@ -184,6 +186,29 @@ bool ResourceFormatImporter::can_be_imported(const String &p_path) const {
return ResourceFormatLoader::recognize_path(p_path);
}
+int ResourceFormatImporter::get_import_order(const String &p_path) const {
+
+ Ref<ResourceImporter> importer;
+
+ if (FileAccess::exists(p_path + ".import")) {
+
+ PathAndType pat;
+ Error err = _get_path_and_type(p_path, pat);
+
+ if (err == OK) {
+ importer = get_importer_by_name(pat.importer);
+ }
+ } else {
+
+ importer = get_importer_by_extension(p_path.get_extension().to_lower());
+ }
+
+ if (importer.is_valid())
+ return importer->get_import_order();
+
+ return 0;
+}
+
bool ResourceFormatImporter::handles_type(const String &p_type) const {
for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
@@ -291,7 +316,7 @@ void ResourceFormatImporter::get_dependencies(const String &p_path, List<String>
return ResourceLoader::get_dependencies(pat.path, p_dependencies, p_add_types);
}
-Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String &p_name) {
+Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_name(const String &p_name) const {
for (Set<Ref<ResourceImporter> >::Element *E = importers.front(); E; E = E->next()) {
if (E->get()->get_importer_name() == p_name) {
@@ -315,7 +340,7 @@ void ResourceFormatImporter::get_importers_for_extension(const String &p_extensi
}
}
-Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String &p_extension) {
+Ref<ResourceImporter> ResourceFormatImporter::get_importer_by_extension(const String &p_extension) const {
Ref<ResourceImporter> importer;
float priority = 0;
diff --git a/core/io/resource_import.h b/core/io/resource_import.h
index b10255fbab..28489b5d34 100644
--- a/core/io/resource_import.h
+++ b/core/io/resource_import.h
@@ -38,6 +38,7 @@ class ResourceFormatImporter : public ResourceFormatLoader {
struct PathAndType {
String path;
String type;
+ String importer;
};
Error _get_path_and_type(const String &p_path, PathAndType &r_path_and_type, bool *r_valid = NULL) const;
@@ -58,14 +59,15 @@ public:
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual bool can_be_imported(const String &p_path) const;
+ virtual int get_import_order(const String &p_path) const;
String get_internal_resource_path(const String &p_path) const;
void get_internal_resource_path_list(const String &p_path, List<String> *r_paths);
void add_importer(const Ref<ResourceImporter> &p_importer) { importers.insert(p_importer); }
void remove_importer(const Ref<ResourceImporter> &p_importer) { importers.erase(p_importer); }
- Ref<ResourceImporter> get_importer_by_name(const String &p_name);
- Ref<ResourceImporter> get_importer_by_extension(const String &p_extension);
+ Ref<ResourceImporter> get_importer_by_name(const String &p_name) const;
+ Ref<ResourceImporter> get_importer_by_extension(const String &p_extension) const;
void get_importers_for_extension(const String &p_extension, List<Ref<ResourceImporter> > *r_importers);
String get_import_base_path(const String &p_for_file) const;
@@ -82,6 +84,7 @@ public:
virtual String get_save_extension() const = 0;
virtual String get_resource_type() const = 0;
virtual float get_priority() const { return 1.0; }
+ virtual int get_import_order() const { return 0; }
struct ImportOption {
PropertyInfo option;
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp
index 4f266df43e..89cb4a22c2 100644
--- a/core/io/resource_loader.cpp
+++ b/core/io/resource_loader.cpp
@@ -308,6 +308,31 @@ void ResourceLoader::add_resource_format_loader(ResourceFormatLoader *p_format_l
}
}
+int ResourceLoader::get_import_order(const String &p_path) {
+
+ String path = _path_remap(p_path);
+
+ String local_path;
+ if (path.is_rel_path())
+ local_path = "res://" + path;
+ else
+ local_path = ProjectSettings::get_singleton()->localize_path(path);
+
+ for (int i = 0; i < loader_count; i++) {
+
+ if (!loader[i]->recognize_path(local_path))
+ continue;
+ /*
+ if (p_type_hint!="" && !loader[i]->handles_type(p_type_hint))
+ continue;
+ */
+
+ return loader[i]->get_import_order(p_path);
+ }
+
+ return 0;
+}
+
bool ResourceLoader::is_import_valid(const String &p_path) {
String path = _path_remap(p_path);
diff --git a/core/io/resource_loader.h b/core/io/resource_loader.h
index a71a568569..5deffbca1a 100644
--- a/core/io/resource_loader.h
+++ b/core/io/resource_loader.h
@@ -67,6 +67,7 @@ public:
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
virtual Error rename_dependencies(const String &p_path, const Map<String, String> &p_map) { return OK; }
virtual bool is_import_valid(const String &p_path) const { return true; }
+ virtual int get_import_order(const String &p_path) const { return 0; }
virtual ~ResourceFormatLoader() {}
};
@@ -110,6 +111,7 @@ public:
static void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
static Error rename_dependencies(const String &p_path, const Map<String, String> &p_map);
static bool is_import_valid(const String &p_path);
+ static int get_import_order(const String &p_path);
static void set_timestamp_on_load(bool p_timestamp) { timestamp_on_load = p_timestamp; }
diff --git a/core/io/stream_peer.cpp b/core/io/stream_peer.cpp
index f4f81f0807..2583eb369d 100644
--- a/core/io/stream_peer.cpp
+++ b/core/io/stream_peer.cpp
@@ -405,9 +405,9 @@ void StreamPeer::_bind_methods() {
void StreamPeerBuffer::_bind_methods() {
- ClassDB::bind_method(D_METHOD("seek", "pos"), &StreamPeerBuffer::seek);
+ ClassDB::bind_method(D_METHOD("seek", "position"), &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("get_position"), &StreamPeerBuffer::get_position);
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);
@@ -484,7 +484,7 @@ int StreamPeerBuffer::get_size() const {
return data.size();
}
-int StreamPeerBuffer::get_pos() const {
+int StreamPeerBuffer::get_position() const {
return pointer;
}
diff --git a/core/io/stream_peer.h b/core/io/stream_peer.h
index 1ee997c123..b120d18501 100644
--- a/core/io/stream_peer.h
+++ b/core/io/stream_peer.h
@@ -111,7 +111,7 @@ public:
void seek(int p_pos);
int get_size() const;
- int get_pos() const;
+ int get_position() const;
void resize(int p_size);
void set_data_array(const PoolVector<uint8_t> &p_data);
diff --git a/core/io/xml_parser.cpp b/core/io/xml_parser.cpp
index 3a4be7cd13..8ae68183d7 100644
--- a/core/io/xml_parser.cpp
+++ b/core/io/xml_parser.cpp
@@ -369,7 +369,7 @@ void XMLParser::_bind_methods() {
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("seek", "position"), &XMLParser::seek);
ClassDB::bind_method(D_METHOD("open", "file"), &XMLParser::open);
ClassDB::bind_method(D_METHOD("open_buffer", "buffer"), &XMLParser::open_buffer);
diff --git a/core/io/zip_io.h b/core/io/zip_io.h
index 8cf971ee08..ce3c919b77 100644
--- a/core/io/zip_io.h
+++ b/core/io/zip_io.h
@@ -72,7 +72,7 @@ static uLong zipio_write(voidpf opaque, voidpf stream, const void *buf, uLong si
static long zipio_tell(voidpf opaque, voidpf stream) {
FileAccess *f = *(FileAccess **)opaque;
- return f->get_pos();
+ return f->get_position();
};
static long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
@@ -83,7 +83,7 @@ static long zipio_seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
switch (origin) {
case ZLIB_FILEFUNC_SEEK_CUR:
- pos = f->get_pos() + offset;
+ pos = f->get_position() + offset;
break;
case ZLIB_FILEFUNC_SEEK_END:
pos = f->get_len() + offset;
diff --git a/core/map.h b/core/map.h
index a37d898a9c..f01062ebed 100644
--- a/core/map.h
+++ b/core/map.h
@@ -31,6 +31,7 @@
#define MAP_H
#include "set.h"
+
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -52,7 +53,6 @@ public:
private:
friend class Map<K, V, C, A>;
- //Color color;
int color;
Element *right;
Element *left;
@@ -61,7 +61,6 @@ public:
Element *_prev;
K _key;
V _value;
-
//_Data *data;
public:
@@ -147,7 +146,6 @@ private:
#ifdef GLOBALNIL_DISABLED
memdelete_allocator<Element, A>(_nil);
#endif
- //memdelete_allocator<Element,A>(_root);
}
};
@@ -158,6 +156,7 @@ private:
ERR_FAIL_COND(p_node == _data._nil && p_color == RED);
p_node->color = p_color;
}
+
inline void _rotate_left(Element *p_node) {
Element *r = p_node->right;
@@ -206,8 +205,9 @@ private:
while (node == node->parent->right) {
node = node->parent;
}
+
if (node->parent == _data._root)
- return NULL;
+ return NULL; // No successor, as p_node = last node
return node->parent;
}
}
@@ -225,10 +225,11 @@ private:
} else {
while (node == node->parent->left) {
- if (node->parent == _data._root)
- return NULL;
node = node->parent;
}
+
+ if (node == _data._root)
+ return NULL; // No predecessor, as p_node = first node
return node->parent;
}
}
@@ -239,16 +240,15 @@ private:
C less;
while (node != _data._nil) {
-
if (less(p_key, node->_key))
node = node->left;
else if (less(node->_key, p_key))
node = node->right;
else
- break; // found
+ return node; // found
}
- return (node != _data._nil) ? node : NULL;
+ return NULL;
}
Element *_find_closest(const K &p_key) const {
@@ -265,24 +265,68 @@ private:
else if (less(node->_key, p_key))
node = node->right;
else
- break; // found
+ return node; // found
}
- if (node == _data._nil) {
- if (prev == NULL)
- return NULL;
- if (less(p_key, prev->_key)) {
+ if (prev == NULL)
+ return NULL; // tree empty
- prev = prev->_prev;
- }
+ if (less(p_key, prev->_key))
+ prev = prev->_prev;
- return prev;
+ return prev;
+ }
- } else
- return node;
+ void _insert_rb_fix(Element *p_new_node) {
+
+ Element *node = p_new_node;
+ Element *nparent = node->parent;
+ Element *ngrand_parent;
+
+ while (nparent->color == RED) {
+ ngrand_parent = nparent->parent;
+
+ if (nparent == ngrand_parent->left) {
+ if (ngrand_parent->right->color == RED) {
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent->right, BLACK);
+ _set_color(ngrand_parent, RED);
+ node = ngrand_parent;
+ nparent = node->parent;
+ } else {
+ if (node == nparent->right) {
+ _rotate_left(nparent);
+ node = nparent;
+ nparent = node->parent;
+ }
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent, RED);
+ _rotate_right(ngrand_parent);
+ }
+ } else {
+ if (ngrand_parent->left->color == RED) {
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent->left, BLACK);
+ _set_color(ngrand_parent, RED);
+ node = ngrand_parent;
+ nparent = node->parent;
+ } else {
+ if (node == nparent->left) {
+ _rotate_right(nparent);
+ node = nparent;
+ nparent = node->parent;
+ }
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent, RED);
+ _rotate_left(ngrand_parent);
+ }
+ }
+ }
+
+ _set_color(_data._root->left, BLACK);
}
- Element *_insert(const K &p_key, bool &r_exists) {
+ Element *_insert(const K &p_key, const V &p_value) {
Element *new_parent = _data._root;
Element *node = _data._root->left;
@@ -297,27 +341,25 @@ private:
else if (less(node->_key, p_key))
node = node->right;
else {
- r_exists = true;
- return node;
+ node->_value = p_value;
+ return node; // Return existing node with new value
}
}
Element *new_node = memnew_allocator(Element, A);
-
new_node->parent = new_parent;
new_node->right = _data._nil;
new_node->left = _data._nil;
new_node->_key = p_key;
+ new_node->_value = p_value;
//new_node->data=_data;
- if (new_parent == _data._root || less(p_key, new_parent->_key)) {
+ if (new_parent == _data._root || less(p_key, new_parent->_key)) {
new_parent->left = new_node;
} else {
new_parent->right = new_node;
}
- r_exists = false;
-
new_node->_next = _successor(new_node);
new_node->_prev = _predecessor(new_node);
if (new_node->_next)
@@ -325,168 +367,113 @@ private:
if (new_node->_prev)
new_node->_prev->_next = new_node;
- return new_node;
- }
-
- Element *_insert_rb(const K &p_key, const V &p_value) {
-
- bool exists = false;
- Element *new_node = _insert(p_key, exists);
-
- if (new_node) {
- new_node->_value = p_value;
- }
- if (exists)
- return new_node;
-
- Element *node = new_node;
_data.size_cache++;
-
- while (node->parent->color == RED) {
-
- if (node->parent == node->parent->parent->left) {
-
- Element *aux = node->parent->parent->right;
-
- if (aux->color == RED) {
- _set_color(node->parent, BLACK);
- _set_color(aux, BLACK);
- _set_color(node->parent->parent, RED);
- node = node->parent->parent;
- } else {
- if (node == node->parent->right) {
- node = node->parent;
- _rotate_left(node);
- }
- _set_color(node->parent, BLACK);
- _set_color(node->parent->parent, RED);
- _rotate_right(node->parent->parent);
- }
- } else {
- Element *aux = node->parent->parent->left;
-
- if (aux->color == RED) {
- _set_color(node->parent, BLACK);
- _set_color(aux, BLACK);
- _set_color(node->parent->parent, RED);
- node = node->parent->parent;
- } else {
- if (node == node->parent->left) {
- node = node->parent;
- _rotate_right(node);
- }
- _set_color(node->parent, BLACK);
- _set_color(node->parent->parent, RED);
- _rotate_left(node->parent->parent);
- }
- }
- }
- _set_color(_data._root->left, BLACK);
+ _insert_rb_fix(new_node);
return new_node;
}
- void _erase_fix(Element *p_node) {
+ void _erase_fix_rb(Element *p_node) {
Element *root = _data._root->left;
- Element *node = p_node;
-
- while ((node->color == BLACK) && (root != node)) {
- if (node == node->parent->left) {
- Element *aux = node->parent->right;
- if (aux->color == RED) {
- _set_color(aux, BLACK);
- _set_color(node->parent, RED);
- _rotate_left(node->parent);
- aux = node->parent->right;
- }
- if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) {
- _set_color(aux, RED);
- node = node->parent;
+ Element *node = _data._nil;
+ Element *sibling = p_node;
+ Element *parent = sibling->parent;
+
+ while (node != root) { // If red node found, will exit at a break
+ if (sibling->color == RED) {
+ _set_color(sibling, BLACK);
+ _set_color(parent, RED);
+ if (sibling == parent->right) {
+ sibling = sibling->left;
+ _rotate_left(parent);
} else {
- if (aux->right->color == BLACK) {
- _set_color(aux->left, BLACK);
- _set_color(aux, RED);
- _rotate_right(aux);
- aux = node->parent->right;
- }
- _set_color(aux, node->parent->color);
- _set_color(node->parent, BLACK);
- _set_color(aux->right, BLACK);
- _rotate_left(node->parent);
- node = root; /* this is to exit while loop */
+ sibling = sibling->right;
+ _rotate_right(parent);
}
- } else { /* the code below is has left and right switched from above */
- Element *aux = node->parent->left;
- if (aux->color == RED) {
- _set_color(aux, BLACK);
- _set_color(node->parent, RED);
- _rotate_right(node->parent);
- aux = node->parent->left;
+ }
+ if ((sibling->left->color == BLACK) && (sibling->right->color == BLACK)) {
+ _set_color(sibling, RED);
+ if (parent->color == RED) {
+ _set_color(parent, BLACK);
+ break;
+ } else { // loop: haven't found any red nodes yet
+ node = parent;
+ parent = node->parent;
+ sibling = (node == parent->left) ? parent->right : parent->left;
}
- if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) {
- _set_color(aux, RED);
- node = node->parent;
+ } else {
+ if (sibling == parent->right) {
+ if (sibling->right->color == BLACK) {
+ _set_color(sibling->left, BLACK);
+ _set_color(sibling, RED);
+ _rotate_right(sibling);
+ sibling = sibling->parent;
+ }
+ _set_color(sibling, parent->color);
+ _set_color(parent, BLACK);
+ _set_color(sibling->right, BLACK);
+ _rotate_left(parent);
+ break;
} else {
- if (aux->left->color == BLACK) {
- _set_color(aux->right, BLACK);
- _set_color(aux, RED);
- _rotate_left(aux);
- aux = node->parent->left;
+ if (sibling->left->color == BLACK) {
+ _set_color(sibling->right, BLACK);
+ _set_color(sibling, RED);
+ _rotate_left(sibling);
+ sibling = sibling->parent;
}
- _set_color(aux, node->parent->color);
- _set_color(node->parent, BLACK);
- _set_color(aux->left, BLACK);
- _rotate_right(node->parent);
- node = root;
+
+ _set_color(sibling, parent->color);
+ _set_color(parent, BLACK);
+ _set_color(sibling->left, BLACK);
+ _rotate_right(parent);
+ break;
}
}
}
- _set_color(node, BLACK);
-
ERR_FAIL_COND(_data._nil->color != BLACK);
}
void _erase(Element *p_node) {
- Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : _successor(p_node);
- if (!rp)
- rp = _data._nil;
+ Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
node->parent = rp->parent;
- if (_data._root == node->parent) {
- _data._root->left = node;
+ Element *sibling;
+ if (rp == rp->parent->left) {
+ rp->parent->left = node;
+ sibling = rp->parent->right;
} else {
- if (rp == rp->parent->left) {
- rp->parent->left = node;
- } else {
- rp->parent->right = node;
- }
+ rp->parent->right = node;
+ sibling = rp->parent->left;
+ }
+
+ if (node->color == RED) {
+ node->parent = rp->parent;
+ _set_color(node, BLACK);
+ } else if (rp->color == BLACK && rp->parent != _data._root) {
+ _erase_fix_rb(sibling);
}
if (rp != p_node) {
ERR_FAIL_COND(rp == _data._nil);
- if (rp->color == BLACK)
- _erase_fix(node);
-
rp->left = p_node->left;
rp->right = p_node->right;
rp->parent = p_node->parent;
rp->color = p_node->color;
- p_node->left->parent = rp;
- p_node->right->parent = rp;
+ if (p_node->left != _data._nil)
+ p_node->left->parent = rp;
+ if (p_node->right != _data._nil)
+ p_node->right->parent = rp;
if (p_node == p_node->parent->left) {
p_node->parent->left = rp;
} else {
p_node->parent->right = rp;
}
- } else {
- if (p_node->color == BLACK)
- _erase_fix(node);
}
if (p_node->_next)
@@ -501,11 +488,12 @@ private:
void _calculate_depth(Element *p_element, int &max_d, int d) const {
- if (p_element == _data._nil) {
+ if (p_element == _data._nil)
return;
- }
+
_calculate_depth(p_element->left, max_d, d + 1);
_calculate_depth(p_element->right, max_d, d + 1);
+
if (d > max_d)
max_d = d;
}
@@ -544,6 +532,7 @@ public:
if (!_data._root)
return NULL;
+
Element *res = _find(p_key);
return res;
}
@@ -552,6 +541,7 @@ public:
if (!_data._root)
return NULL;
+
const Element *res = _find_closest(p_key);
return res;
}
@@ -560,21 +550,28 @@ public:
if (!_data._root)
return NULL;
+
Element *res = _find_closest(p_key);
return res;
}
+ bool has(const K &p_key) const {
+
+ return find(p_key) != NULL;
+ }
+
Element *insert(const K &p_key, const V &p_value) {
if (!_data._root)
_data._create_root();
- return _insert_rb(p_key, p_value);
+ return _insert(p_key, p_value);
}
void erase(Element *p_element) {
- if (!_data._root)
+ if (!_data._root || !p_element)
return;
+
_erase(p_element);
if (_data.size_cache == 0 && _data._root)
_data._free_root();
@@ -584,20 +581,17 @@ public:
if (!_data._root)
return false;
+
Element *e = find(p_key);
if (!e)
return false;
+
_erase(e);
+ if (_data.size_cache == 0 && _data._root)
+ _data._free_root();
return true;
}
- bool has(const K &p_key) const {
-
- if (!_data._root)
- return false;
- return find(p_key) != NULL;
- }
-
const V &operator[](const K &p_key) const {
CRASH_COND(!_data._root);
@@ -605,6 +599,7 @@ public:
CRASH_COND(!e);
return e->_value;
}
+
V &operator[](const K &p_key) {
if (!_data._root)
@@ -614,7 +609,6 @@ public:
if (!e)
e = insert(p_key, V());
- CRASH_COND(!e);
return e->_value;
}
@@ -637,6 +631,7 @@ public:
if (!_data._root)
return NULL;
+
Element *e = _data._root->left;
if (e == _data._nil)
return NULL;
@@ -649,10 +644,12 @@ public:
inline bool empty() const { return _data.size_cache == 0; }
inline int size() const { return _data.size_cache; }
+
int calculate_depth() const {
// used for debug mostly
if (!_data._root)
return 0;
+
int max_d = 0;
_calculate_depth(_data._root->left, max_d, 0);
return max_d;
@@ -662,10 +659,10 @@ public:
if (!_data._root)
return;
+
_cleanup_tree(_data._root->left);
_data._root->left = _data._nil;
_data.size_cache = 0;
- _data._nil->parent = _data._nil;
_data._free_root();
}
diff --git a/core/math/a_star.cpp b/core/math/a_star.cpp
index d1afcec18f..4f80fb2491 100644
--- a/core/math/a_star.cpp
+++ b/core/math/a_star.cpp
@@ -58,7 +58,7 @@ void AStar::add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale) {
}
}
-Vector3 AStar::get_point_pos(int p_id) const {
+Vector3 AStar::get_point_position(int p_id) const {
ERR_FAIL_COND_V(!points.has(p_id), Vector3());
@@ -171,7 +171,7 @@ int AStar::get_closest_point(const Vector3 &p_point) const {
return closest_id;
}
-Vector3 AStar::get_closest_pos_in_segment(const Vector3 &p_point) const {
+Vector3 AStar::get_closest_position_in_segment(const Vector3 &p_point) const {
real_t closest_dist = 1e20;
bool found = false;
@@ -412,8 +412,8 @@ PoolVector<int> AStar::get_id_path(int p_from_id, int p_to_id) {
void AStar::_bind_methods() {
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("add_point", "id", "position", "weight_scale"), &AStar::add_point, DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("get_point_position", "id"), &AStar::get_point_position);
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(D_METHOD("has_point", "id"), &AStar::has_point);
@@ -425,8 +425,8 @@ void AStar::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &AStar::clear);
- 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(D_METHOD("get_closest_point", "to_position"), &AStar::get_closest_point);
+ ClassDB::bind_method(D_METHOD("get_closest_position_in_segment", "to_position"), &AStar::get_closest_position_in_segment);
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/a_star.h b/core/math/a_star.h
index 38d13d510b..2c1e2e2cf7 100644
--- a/core/math/a_star.h
+++ b/core/math/a_star.h
@@ -101,7 +101,7 @@ public:
int get_available_point_id() const;
void add_point(int p_id, const Vector3 &p_pos, real_t p_weight_scale = 1);
- Vector3 get_point_pos(int p_id) const;
+ Vector3 get_point_position(int p_id) const;
real_t get_point_weight_scale(int p_id) const;
void remove_point(int p_id);
bool has_point(int p_id) const;
@@ -114,7 +114,7 @@ public:
void clear();
int get_closest_point(const Vector3 &p_point) const;
- Vector3 get_closest_pos_in_segment(const Vector3 &p_point) const;
+ Vector3 get_closest_position_in_segment(const Vector3 &p_point) const;
PoolVector<Vector3> get_point_path(int p_from_id, int p_to_id);
PoolVector<int> get_id_path(int p_from_id, int p_to_id);
diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp
index 7132b6573e..2c587762e8 100644
--- a/core/math/camera_matrix.cpp
+++ b/core/math/camera_matrix.cpp
@@ -577,7 +577,7 @@ real_t CameraMatrix::get_fov() const {
if ((matrix[8] == 0) && (matrix[9] == 0)) {
return Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0;
} else {
- // our frustum is asymetrical need to calculate the left planes angle seperately..
+ // our frustum is asymmetrical need to calculate the left planes angle separately..
Plane left_plane = Plane(matrix[3] + matrix[0],
matrix[7] + matrix[4],
matrix[11] + matrix[8],
diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h
index 9651e37f3e..d63da322a5 100644
--- a/core/math/math_funcs.h
+++ b/core/math/math_funcs.h
@@ -104,8 +104,44 @@ public:
static _ALWAYS_INLINE_ double exp(double p_x) { return ::exp(p_x); }
static _ALWAYS_INLINE_ float exp(float p_x) { return ::expf(p_x); }
- static _ALWAYS_INLINE_ bool is_nan(double p_val) { return (p_val != p_val); }
- static _ALWAYS_INLINE_ bool is_nan(float p_val) { return (p_val != p_val); }
+ static _ALWAYS_INLINE_ bool is_nan(double p_val) {
+#ifdef _MSC_VER
+ return _isnan(p_val);
+#elif defined(__GNUC__) && __GNUC__ < 6
+ union {
+ uint64_t u;
+ double f;
+ } ieee754;
+ ieee754.f = p_val;
+ // (unsigned)(0x7ff0000000000001 >> 32) : 0x7ff00000
+ return ((((unsigned)(ieee754.u >> 32) & 0x7fffffff) + ((unsigned)ieee754.u != 0)) > 0x7ff00000);
+#else
+ return isnan(p_val);
+#endif
+ }
+
+ static _ALWAYS_INLINE_ bool is_nan(float p_val) {
+#ifdef _MSC_VER
+ return _isnan(p_val);
+#elif defined(__GNUC__) && __GNUC__ < 6
+ union {
+ uint32_t u;
+ float f;
+ } ieee754;
+ ieee754.f = p_val;
+ // -----------------------------------
+ // (single-precision floating-point)
+ // NaN : s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
+ // : (> 0x7f800000)
+ // where,
+ // s : sign
+ // x : non-zero number
+ // -----------------------------------
+ return ((ieee754.u & 0x7fffffff) > 0x7f800000);
+#else
+ return isnan(p_val);
+#endif
+ }
static _ALWAYS_INLINE_ bool is_inf(double p_val) {
#ifdef _MSC_VER
diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h
new file mode 100644
index 0000000000..66a1e348a1
--- /dev/null
+++ b/core/oa_hash_map.h
@@ -0,0 +1,593 @@
+/*************************************************************************/
+/* oa_hash_map.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 OA_HASH_MAP_H
+#define OA_HASH_MAP_H
+
+#include "hashfuncs.h"
+#include "math_funcs.h"
+#include "os/copymem.h"
+#include "os/memory.h"
+
+// uncomment this to disable intial local storage.
+#define OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+
+/**
+ * This class implements a hash map datastructure that uses open addressing with
+ * local probing.
+ *
+ * It can give huge performance improvements over a chained HashMap because of
+ * the increased data locality.
+ *
+ * Because of that locality property it's important to not use "large" value
+ * types as the "TData" type. If TData values are too big it can cause more
+ * cache misses then chaining. If larger values are needed then storing those
+ * in a separate array and using pointers or indices to reference them is the
+ * better solution.
+ *
+ * This hash map also implements real-time incremental rehashing.
+ *
+ */
+template <class TKey, class TData,
+ uint16_t INITIAL_NUM_ELEMENTS = 64,
+ class Hasher = HashMapHasherDefault,
+ class Comparator = HashMapComparatorDefault<TKey> >
+class OAHashMap {
+
+private:
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+ TData local_data[INITIAL_NUM_ELEMENTS];
+ TKey local_keys[INITIAL_NUM_ELEMENTS];
+ uint32_t local_hashes[INITIAL_NUM_ELEMENTS];
+ uint8_t local_flags[INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0)];
+#endif
+
+ struct {
+ TData *data;
+ TKey *keys;
+ uint32_t *hashes;
+
+ // This is actually an array of bits, 4 bit pairs per octet.
+ // | ba ba ba ba | ba ba ba ba | ....
+ //
+ // if a is set it means that there is an element present.
+ // if b is set it means that an element was deleted. This is needed for
+ // the local probing to work without relocating any succeeding and
+ // colliding entries.
+ uint8_t *flags;
+
+ uint32_t capacity;
+ } table, old_table;
+
+ bool is_rehashing;
+ uint32_t rehash_position;
+ uint32_t rehash_amount;
+
+ uint32_t elements;
+
+ /* Methods */
+
+ // returns true if the value already existed, false if it's a new entry
+ bool _raw_set_with_hash(uint32_t p_hash, const TKey &p_key, const TData &p_data) {
+ for (int i = 0; i < table.capacity; i++) {
+
+ int pos = (p_hash + i) % table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset));
+ bool is_deleted_flag = table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1));
+
+ if (is_filled_flag) {
+ if (table.hashes[pos] == p_hash && Comparator::compare(table.keys[pos], p_key)) {
+ table.data[pos] = p_data;
+ return true;
+ }
+ continue;
+ }
+
+ table.keys[pos] = p_key;
+ table.data[pos] = p_data;
+ table.hashes[pos] = p_hash;
+
+ table.flags[flags_pos] |= (1 << (2 * flags_pos_offset));
+ table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset + 1));
+
+ return false;
+ }
+ return false;
+ }
+
+public:
+ _FORCE_INLINE_ uint32_t get_capacity() const { return table.capacity; }
+ _FORCE_INLINE_ uint32_t get_num_elements() const { return elements; }
+
+ void set(const TKey &p_key, const TData &p_data) {
+
+ uint32_t hash = Hasher::hash(p_key);
+
+ // We don't progress the rehashing if the table just got resized
+ // to keep the cost of this function low.
+ if (is_rehashing) {
+
+ // rehash progress
+
+ for (int i = 0; i <= rehash_amount && rehash_position < old_table.capacity; rehash_position++) {
+
+ int flags_pos = rehash_position / 4;
+ int flags_pos_offset = rehash_position % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ _raw_set_with_hash(old_table.hashes[rehash_position], old_table.keys[rehash_position], old_table.data[rehash_position]);
+
+ old_table.keys[rehash_position].~TKey();
+ old_table.data[rehash_position].~TData();
+
+ memnew_placement(&old_table.keys[rehash_position], TKey);
+ memnew_placement(&old_table.data[rehash_position], TData);
+
+ old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset));
+ old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1));
+ }
+ }
+
+ if (rehash_position >= old_table.capacity) {
+
+ // wohooo, we can get rid of the old table.
+ is_rehashing = false;
+
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+ if (old_table.data == local_data) {
+ // Everything is local, so no cleanup :P
+ } else
+#endif
+ {
+ memdelete_arr(old_table.data);
+ memdelete_arr(old_table.keys);
+ memdelete_arr(old_table.hashes);
+ memdelete_arr(old_table.flags);
+ }
+ }
+ }
+
+ // Table is almost full, resize and start rehashing process.
+ if (elements >= table.capacity * 0.7) {
+
+ old_table.capacity = table.capacity;
+ old_table.data = table.data;
+ old_table.flags = table.flags;
+ old_table.hashes = table.hashes;
+ old_table.keys = table.keys;
+
+ table.capacity = old_table.capacity * 2;
+
+ table.data = memnew_arr(TData, table.capacity);
+ table.flags = memnew_arr(uint8_t, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0));
+ table.hashes = memnew_arr(uint32_t, table.capacity);
+ table.keys = memnew_arr(TKey, table.capacity);
+
+ zeromem(table.flags, table.capacity / 4 + (table.capacity % 4 != 0 ? 1 : 0));
+
+ is_rehashing = true;
+ rehash_position = 0;
+ rehash_amount = (elements * 2) / (table.capacity * 0.7 - old_table.capacity);
+ }
+
+ if (!_raw_set_with_hash(hash, p_key, p_data))
+ elements++;
+ }
+
+ /**
+ * returns true if the value was found, false otherwise.
+ *
+ * if r_data is not NULL then the value will be written to the object
+ * it points to.
+ */
+ bool lookup(const TKey &p_key, TData *r_data) {
+
+ uint32_t hash = Hasher::hash(p_key);
+
+ bool check_old_table = is_rehashing;
+ bool check_new_table = true;
+
+ // search for the key and return the value associated with it
+ //
+ // if we're rehashing we need to check both the old and the
+ // current table. If we find a value in the old table we still
+ // need to continue searching in the new table as it might have
+ // been added after
+
+ TData *value = NULL;
+
+ for (int i = 0; i < table.capacity; i++) {
+
+ if (!check_new_table && !check_old_table) {
+
+ break;
+ }
+
+ // if we're rehashing check the old table
+ if (check_old_table && i < old_table.capacity) {
+
+ int pos = (hash + i) % old_table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ // found our entry?
+ if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) {
+ value = &old_table.data[pos];
+ check_old_table = false;
+ }
+ } else if (!is_deleted_flag) {
+
+ // we hit an empty field here, we don't
+ // need to further check this old table
+ // because we know it's not in here.
+
+ check_old_table = false;
+ }
+ }
+
+ if (check_new_table) {
+
+ int pos = (hash + i) % table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ // found our entry?
+ if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) {
+ if (r_data != NULL)
+ *r_data = table.data[pos];
+ return true;
+ }
+ continue;
+ } else if (is_deleted_flag) {
+ continue;
+ } else if (value != NULL) {
+
+ // We found a value in the old table
+ if (r_data != NULL)
+ *r_data = *value;
+ return true;
+ } else {
+ check_new_table = false;
+ }
+ }
+ }
+
+ if (value != NULL) {
+ if (r_data != NULL)
+ *r_data = *value;
+ return true;
+ }
+ return false;
+ }
+
+ _FORCE_INLINE_ bool has(const TKey &p_key) {
+ return lookup(p_key, NULL);
+ }
+
+ void remove(const TKey &p_key) {
+ uint32_t hash = Hasher::hash(p_key);
+
+ bool check_old_table = is_rehashing;
+ bool check_new_table = true;
+
+ for (int i = 0; i < table.capacity; i++) {
+
+ if (!check_new_table && !check_old_table) {
+ return;
+ }
+
+ // if we're rehashing check the old table
+ if (check_old_table && i < old_table.capacity) {
+
+ int pos = (hash + i) % old_table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ // found our entry?
+ if (old_table.hashes[pos] == hash && Comparator::compare(old_table.keys[pos], p_key)) {
+ old_table.keys[pos].~TKey();
+ old_table.data[pos].~TData();
+
+ memnew_placement(&old_table.keys[pos], TKey);
+ memnew_placement(&old_table.data[pos], TData);
+
+ old_table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset));
+ old_table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1));
+
+ elements--;
+ return;
+ }
+ } else if (!is_deleted_flag) {
+
+ // we hit an empty field here, we don't
+ // need to further check this old table
+ // because we know it's not in here.
+
+ check_old_table = false;
+ }
+ }
+
+ if (check_new_table) {
+
+ int pos = (hash + i) % table.capacity;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+ bool is_deleted_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset + 1))) > 0;
+
+ if (is_filled_flag) {
+ // found our entry?
+ if (table.hashes[pos] == hash && Comparator::compare(table.keys[pos], p_key)) {
+ table.keys[pos].~TKey();
+ table.data[pos].~TData();
+
+ memnew_placement(&table.keys[pos], TKey);
+ memnew_placement(&table.data[pos], TData);
+
+ table.flags[flags_pos] &= ~(1 << (2 * flags_pos_offset));
+ table.flags[flags_pos] |= (1 << (2 * flags_pos_offset + 1));
+
+ // don't return here, this value might still be in the old table
+ // if it was already relocated.
+
+ elements--;
+ return;
+ }
+ continue;
+ } else if (is_deleted_flag) {
+ continue;
+ } else {
+ check_new_table = false;
+ }
+ }
+ }
+ }
+
+ struct Iterator {
+ bool valid;
+
+ uint32_t hash;
+
+ const TKey *key;
+ const TData *data;
+
+ private:
+ friend class OAHashMap;
+ bool was_from_old_table;
+ };
+
+ Iterator iter() const {
+ Iterator it;
+
+ it.valid = false;
+ it.was_from_old_table = false;
+
+ bool check_old_table = is_rehashing;
+
+ for (int i = 0; i < table.capacity; i++) {
+
+ // if we're rehashing check the old table first
+ if (check_old_table && i < old_table.capacity) {
+
+ int pos = i;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+
+ if (is_filled_flag) {
+ it.valid = true;
+ it.hash = old_table.hashes[pos];
+ it.data = &old_table.data[pos];
+ it.key = &old_table.keys[pos];
+
+ it.was_from_old_table = true;
+
+ return it;
+ }
+ }
+
+ {
+
+ int pos = i;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+
+ if (is_filled_flag) {
+ it.valid = true;
+ it.hash = table.hashes[pos];
+ it.data = &table.data[pos];
+ it.key = &table.keys[pos];
+
+ return it;
+ }
+ }
+ }
+
+ return it;
+ }
+
+ Iterator next_iter(const Iterator &p_iter) const {
+ if (!p_iter.valid) {
+ return p_iter;
+ }
+
+ Iterator it;
+
+ it.valid = false;
+ it.was_from_old_table = false;
+
+ bool check_old_table = is_rehashing;
+
+ // we use this to skip the first check or not
+ bool was_from_old_table = p_iter.was_from_old_table;
+
+ int prev_index = (p_iter.data - (p_iter.was_from_old_table ? old_table.data : table.data));
+
+ if (!was_from_old_table) {
+ prev_index++;
+ }
+
+ for (int i = prev_index; i < table.capacity; i++) {
+
+ // if we're rehashing check the old table first
+ if (check_old_table && i < old_table.capacity && !was_from_old_table) {
+
+ int pos = i;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (old_table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+
+ if (is_filled_flag) {
+ it.valid = true;
+ it.hash = old_table.hashes[pos];
+ it.data = &old_table.data[pos];
+ it.key = &old_table.keys[pos];
+
+ it.was_from_old_table = true;
+
+ return it;
+ }
+ }
+
+ was_from_old_table = false;
+
+ {
+ int pos = i;
+
+ int flags_pos = pos / 4;
+ int flags_pos_offset = pos % 4;
+
+ bool is_filled_flag = (table.flags[flags_pos] & (1 << (2 * flags_pos_offset))) > 0;
+
+ if (is_filled_flag) {
+ it.valid = true;
+ it.hash = table.hashes[pos];
+ it.data = &table.data[pos];
+ it.key = &table.keys[pos];
+
+ return it;
+ }
+ }
+ }
+
+ return it;
+ }
+
+ OAHashMap(uint32_t p_initial_capacity = INITIAL_NUM_ELEMENTS) {
+
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+
+ if (p_initial_capacity <= INITIAL_NUM_ELEMENTS) {
+ table.data = local_data;
+ table.keys = local_keys;
+ table.hashes = local_hashes;
+ table.flags = local_flags;
+
+ zeromem(table.flags, INITIAL_NUM_ELEMENTS / 4 + (INITIAL_NUM_ELEMENTS % 4 != 0 ? 1 : 0));
+
+ table.capacity = INITIAL_NUM_ELEMENTS;
+ elements = 0;
+ } else
+#endif
+ {
+ table.data = memnew_arr(TData, p_initial_capacity);
+ table.keys = memnew_arr(TKey, p_initial_capacity);
+ table.hashes = memnew_arr(uint32_t, p_initial_capacity);
+ table.flags = memnew_arr(uint8_t, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0));
+
+ zeromem(table.flags, p_initial_capacity / 4 + (p_initial_capacity % 4 != 0 ? 1 : 0));
+
+ table.capacity = p_initial_capacity;
+ elements = 0;
+ }
+
+ is_rehashing = false;
+ rehash_position = 0;
+ }
+
+ ~OAHashMap() {
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+ if (table.capacity <= INITIAL_NUM_ELEMENTS) {
+ return; // Everything is local, so no cleanup :P
+ }
+#endif
+ if (is_rehashing) {
+
+#ifdef OA_HASH_MAP_INITIAL_LOCAL_STORAGE
+ if (old_table.data == local_data) {
+ // Everything is local, so no cleanup :P
+ } else
+#endif
+ {
+ memdelete_arr(old_table.data);
+ memdelete_arr(old_table.keys);
+ memdelete_arr(old_table.hashes);
+ memdelete_arr(old_table.flags);
+ }
+ }
+
+ memdelete_arr(table.data);
+ memdelete_arr(table.keys);
+ memdelete_arr(table.hashes);
+ memdelete_arr(table.flags);
+ }
+};
+
+#endif
diff --git a/core/object.cpp b/core/object.cpp
index 23e32a214a..823cbe14d4 100644
--- a/core/object.cpp
+++ b/core/object.cpp
@@ -277,32 +277,32 @@ MethodInfo::MethodInfo(Variant::Type ret, const String &p_name, const PropertyIn
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name)
: name(p_name),
flags(METHOD_FLAG_NORMAL),
+ return_val(p_ret),
id(0) {
- return_val = p_ret;
}
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
}
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
arguments.push_back(p_param2);
}
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
arguments.push_back(p_param2);
arguments.push_back(p_param3);
@@ -310,9 +310,9 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
arguments.push_back(p_param2);
arguments.push_back(p_param3);
@@ -321,9 +321,9 @@ MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const Pr
MethodInfo::MethodInfo(const PropertyInfo &p_ret, const String &p_name, const PropertyInfo &p_param1, const PropertyInfo &p_param2, const PropertyInfo &p_param3, const PropertyInfo &p_param4, const PropertyInfo &p_param5)
: name(p_name),
+ return_val(p_ret),
flags(METHOD_FLAG_NORMAL),
id(0) {
- return_val = p_ret;
arguments.push_back(p_param1);
arguments.push_back(p_param2);
arguments.push_back(p_param3);
@@ -1052,7 +1052,7 @@ Variant Object::_emit_signal(const Variant **p_args, int p_argcount, Variant::Ca
Error Object::emit_signal(const StringName &p_name, const Variant **p_args, int p_argcount) {
if (_block_signals)
- return ERR_CANT_AQUIRE_RESOURCE; //no emit, signals blocked
+ return ERR_CANT_ACQUIRE_RESOURCE; //no emit, signals blocked
Signal *s = signal_map.getptr(p_name);
if (!s) {
diff --git a/core/object.h b/core/object.h
index 644e2b8270..7af2c78fc3 100644
--- a/core/object.h
+++ b/core/object.h
@@ -64,9 +64,9 @@ enum PropertyHint {
PROPERTY_HINT_LAYERS_3D_RENDER,
PROPERTY_HINT_LAYERS_3D_PHYSICS,
PROPERTY_HINT_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
- PROPERTY_HINT_DIR, ///< a directort path must be passed
+ PROPERTY_HINT_DIR, ///< a directory path must be passed
PROPERTY_HINT_GLOBAL_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,"
- PROPERTY_HINT_GLOBAL_DIR, ///< a directort path must be passed
+ PROPERTY_HINT_GLOBAL_DIR, ///< a directory path must be passed
PROPERTY_HINT_RESOURCE_TYPE, ///< a resource object type
PROPERTY_HINT_MULTILINE_TEXT, ///< used for string properties that can contain multiple lines
PROPERTY_HINT_COLOR_NO_ALPHA, ///< used for ignoring alpha component when editing a color
@@ -148,6 +148,7 @@ struct PropertyInfo {
hint(PROPERTY_HINT_NONE),
usage(PROPERTY_USAGE_DEFAULT) {
}
+
PropertyInfo(Variant::Type p_type, const String p_name, PropertyHint p_hint = PROPERTY_HINT_NONE, const String &p_hint_string = "", uint32_t p_usage = PROPERTY_USAGE_DEFAULT, const StringName &p_class_name = StringName())
: type(p_type),
name(p_name),
@@ -161,12 +162,12 @@ struct PropertyInfo {
class_name = p_class_name;
}
}
+
PropertyInfo(const StringName &p_class_name)
: type(Variant::OBJECT),
+ class_name(p_class_name),
hint(PROPERTY_HINT_NONE),
usage(PROPERTY_USAGE_DEFAULT) {
-
- class_name = p_class_name;
}
bool operator<(const PropertyInfo &p_info) const {
@@ -220,7 +221,7 @@ struct MethodInfo {
//return NULL;
/*
- the following is an uncomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
+ the following is an incomprehensible blob of hacks and workarounds to compensate for many of the fallencies in C++. As a plus, this macro pretty much alone defines the object model.
*/
#define REVERSE_GET_PROPERTY_LIST \
diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp
index f24d6d16ca..0875f78478 100644
--- a/core/os/dir_access.cpp
+++ b/core/os/dir_access.cpp
@@ -292,7 +292,7 @@ String DirAccess::get_full_path(const String &p_path, AccessType p_access) {
return full;
}
-Error DirAccess::copy(String p_from, String p_to) {
+Error DirAccess::copy(String p_from, String p_to, int chmod_flags) {
//printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data());
Error err;
@@ -312,7 +312,7 @@ Error DirAccess::copy(String p_from, String p_to) {
}
fsrc->seek_end(0);
- int size = fsrc->get_pos();
+ int size = fsrc->get_position();
fsrc->seek(0);
err = OK;
while (size--) {
@@ -329,6 +329,11 @@ Error DirAccess::copy(String p_from, String p_to) {
fdst->store_8(fsrc->get_8());
}
+ if (err == OK && chmod_flags != -1) {
+ fdst->close();
+ err = fdst->_chmod(p_to, chmod_flags);
+ }
+
memdelete(fsrc);
memdelete(fdst);
diff --git a/core/os/dir_access.h b/core/os/dir_access.h
index 6ad8b4c49b..7fa3ce5cf1 100644
--- a/core/os/dir_access.h
+++ b/core/os/dir_access.h
@@ -89,7 +89,7 @@ public:
static bool exists(String p_dir);
virtual size_t get_space_left() = 0;
- virtual Error copy(String p_from, String p_to);
+ virtual Error copy(String p_from, String p_to, int chmod_flags = -1);
virtual Error rename(String p_from, String p_to) = 0;
virtual Error remove(String p_name) = 0;
diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp
index b969b58bfb..fcb3b58fed 100644
--- a/core/os/file_access.cpp
+++ b/core/os/file_access.cpp
@@ -55,7 +55,7 @@ FileAccess *FileAccess::create(AccessType p_access) {
bool FileAccess::exists(const String &p_name) {
- if (PackedData::get_singleton()->has_path(p_name))
+ if (PackedData::get_singleton() && PackedData::get_singleton()->has_path(p_name))
return true;
FileAccess *f = open(p_name, READ);
diff --git a/core/os/file_access.h b/core/os/file_access.h
index 8e5728f525..455dd1ea99 100644
--- a/core/os/file_access.h
+++ b/core/os/file_access.h
@@ -90,7 +90,7 @@ public:
virtual void seek(size_t p_position) = 0; ///< seek to a given position
virtual void seek_end(int64_t p_position = 0) = 0; ///< seek from the end of file
- virtual size_t get_pos() const = 0; ///< get position in the file
+ virtual size_t get_position() const = 0; ///< get position in the file
virtual size_t get_len() const = 0; ///< get size of the file
virtual bool eof_reached() const = 0; ///< reading passed EOF
@@ -119,6 +119,7 @@ public:
virtual Error get_error() const = 0; ///< get last error
+ virtual void flush() = 0;
virtual void store_8(uint8_t p_dest) = 0; ///< store a byte
virtual void store_16(uint16_t p_dest); ///< store 16 bits uint
virtual void store_32(uint32_t p_dest); ///< store 32 bits uint
@@ -140,6 +141,8 @@ public:
virtual Error reopen(const String &p_path, int p_mode_flags); ///< does not change the AccessType
+ virtual Error _chmod(const String &p_path, int p_mod) { return FAILED; }
+
static FileAccess *create(AccessType p_access); /// Create a file access (for the current platform) this is the only portable way of accessing files.
static FileAccess *create_for_path(const String &p_path);
static FileAccess *open(const String &p_path, int p_mode_flags, Error *r_error = NULL); /// Create a file access (for the current platform) this is the only portable way of accessing files.
diff --git a/core/os/input.cpp b/core/os/input.cpp
index 65752662d7..a4b82299a7 100644
--- a/core/os/input.cpp
+++ b/core/os/input.cpp
@@ -80,7 +80,7 @@ void Input::_bind_methods() {
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("warp_mouse_position", "to"), &Input::warp_mouse_position);
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", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(Vector2()));
diff --git a/core/os/input.h b/core/os/input.h
index f98b97e647..97d3bef4f9 100644
--- a/core/os/input.h
+++ b/core/os/input.h
@@ -81,7 +81,7 @@ public:
virtual Point2 get_last_mouse_speed() const = 0;
virtual int get_mouse_button_mask() const = 0;
- virtual void warp_mouse_pos(const Vector2 &p_to) = 0;
+ virtual void warp_mouse_position(const Vector2 &p_to) = 0;
virtual Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) = 0;
virtual Vector3 get_gravity() const = 0;
diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp
index 88037859aa..bef98ac3f2 100644
--- a/core/os/input_event.cpp
+++ b/core/os/input_event.cpp
@@ -781,7 +781,7 @@ void InputEventScreenTouch::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_index", "index"), &InputEventScreenTouch::set_index);
ClassDB::bind_method(D_METHOD("get_index"), &InputEventScreenTouch::get_index);
- ClassDB::bind_method(D_METHOD("set_position", "pos"), &InputEventScreenTouch::set_position);
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &InputEventScreenTouch::set_position);
ClassDB::bind_method(D_METHOD("get_position"), &InputEventScreenTouch::get_position);
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &InputEventScreenTouch::set_pressed);
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 437ce01a5e..ff17cdb508 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -62,20 +62,20 @@ void OS::debug_break(){
// something
};
-void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
-
- const char *err_type = "**ERROR**";
- switch (p_type) {
- case ERR_ERROR: err_type = "**ERROR**"; break;
- case ERR_WARNING: err_type = "**WARNING**"; break;
- case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
- case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
- default: ERR_PRINT("Unknown error type"); break;
+void OS::_set_logger(Logger *p_logger) {
+ if (_logger) {
+ memdelete(_logger);
}
+ _logger = p_logger;
+}
+
+void OS::initialize_logger() {
+ _set_logger(memnew(StdLogger));
+}
+
+void OS::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type) {
- if (p_rationale && *p_rationale)
- print("%s: %s\n ", err_type, p_rationale);
- print("%s: At: %s:%i:%s() - %s\n", err_type, p_file, p_line, p_function, p_code);
+ _logger->log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
}
void OS::print(const char *p_format, ...) {
@@ -83,17 +83,16 @@ void OS::print(const char *p_format, ...) {
va_list argp;
va_start(argp, p_format);
- vprint(p_format, argp);
+ _logger->logv(p_format, argp, false);
va_end(argp);
};
void OS::printerr(const char *p_format, ...) {
-
va_list argp;
va_start(argp, p_format);
- vprint(p_format, argp, true);
+ _logger->logv(p_format, argp, true);
va_end(argp);
};
@@ -533,9 +532,12 @@ OS::OS() {
_allow_hidpi = true;
_stack_bottom = (void *)(&stack_bottom);
+
+ _logger = NULL;
+ _set_logger(memnew(StdLogger));
}
OS::~OS() {
-
+ memdelete(_logger);
singleton = NULL;
}
diff --git a/core/os/os.h b/core/os/os.h
index 2fc87e44a0..c9d25792b9 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -32,6 +32,7 @@
#include "engine.h"
#include "image.h"
+#include "io/logger.h"
#include "list.h"
#include "os/main_loop.h"
#include "ustring.h"
@@ -61,6 +62,11 @@ class OS {
void *_stack_bottom;
+ Logger *_logger;
+
+protected:
+ void _set_logger(Logger *p_logger);
+
public:
typedef void (*ImeCallback)(void *p_inp, String p_text, Point2 p_selection);
@@ -108,6 +114,7 @@ protected:
virtual int get_audio_driver_count() const = 0;
virtual const char *get_audio_driver_name(int p_driver) const = 0;
+ virtual void initialize_logger();
virtual void initialize_core() = 0;
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0;
@@ -127,18 +134,10 @@ public:
static OS *get_singleton();
- enum ErrorType {
- ERR_ERROR,
- ERR_WARNING,
- ERR_SCRIPT,
- ERR_SHADER
- };
-
- virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, Logger::ErrorType p_type = Logger::ERR_ERROR);
+ void print(const char *p_format, ...);
+ void printerr(const char *p_format, ...);
- virtual void print(const char *p_format, ...);
- virtual void printerr(const char *p_format, ...);
- virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false) = 0;
virtual void alert(const String &p_alert, const String &p_title = "ALERT!") = 0;
virtual String get_stdin_string(bool p_block = true) = 0;
@@ -156,7 +155,7 @@ public:
virtual void set_mouse_mode(MouseMode p_mode);
virtual MouseMode get_mouse_mode() const;
- virtual void warp_mouse_pos(const Point2 &p_to) {}
+ virtual void warp_mouse_position(const Point2 &p_to) {}
virtual Point2 get_mouse_position() const = 0;
virtual int get_mouse_button_state() const = 0;
virtual void set_window_title(const String &p_title) = 0;
@@ -335,6 +334,8 @@ public:
virtual String get_data_dir() const;
virtual String get_resource_dir() const;
+ virtual Error move_to_trash(const String &p_path) { return FAILED; }
+
enum SystemDir {
SYSTEM_DIR_DESKTOP,
SYSTEM_DIR_DCIM,
diff --git a/core/project_settings.cpp b/core/project_settings.cpp
index 72d40b42c3..14ebe87dc5 100644
--- a/core/project_settings.cpp
+++ b/core/project_settings.cpp
@@ -307,8 +307,8 @@ Error ProjectSettings::setup(const String &p_path, const String &p_main_pack) {
if (exec_path != "") {
bool found = false;
- // get our filename without our path (note, not using exec_path.get_basename anymore because not all file systems have dots in their file names!)
- String filebase_name = exec_path.get_file();
+ // get our filename without our path (note, using exec_path.get_file before get_basename anymore because not all file systems have dots in their file names!)
+ String filebase_name = exec_path.get_file().get_basename();
// try to open at the location of executable
String datapack_name = exec_path.get_base_dir().plus_file(filebase_name) + ".pck";
@@ -910,7 +910,7 @@ Variant ProjectSettings::property_get_revert(const String &p_name) {
void ProjectSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("has", "name"), &ProjectSettings::has);
- ClassDB::bind_method(D_METHOD("set_order", "name", "pos"), &ProjectSettings::set_order);
+ ClassDB::bind_method(D_METHOD("set_order", "name", "position"), &ProjectSettings::set_order);
ClassDB::bind_method(D_METHOD("get_order", "name"), &ProjectSettings::get_order);
ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &ProjectSettings::set_initial_value);
ClassDB::bind_method(D_METHOD("add_property_info", "hint"), &ProjectSettings::_add_property_info_bind);
diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp
index 27c31127a4..0e34a3eea5 100644
--- a/core/register_core_types.cpp
+++ b/core/register_core_types.cpp
@@ -68,6 +68,7 @@ static _Engine *_engine = NULL;
static _ClassDB *_classdb = NULL;
static _Marshalls *_marshalls = NULL;
static TranslationLoaderPO *resource_format_po = NULL;
+static _JSON *_json = NULL;
static IP *ip = NULL;
@@ -162,6 +163,8 @@ void register_core_types() {
ClassDB::register_class<AStar>();
ClassDB::register_class<EncodedObjectAsID>();
+ ClassDB::register_class<JSONParseResult>();
+
ip = IP::create();
_geometry = memnew(_Geometry);
@@ -172,6 +175,7 @@ void register_core_types() {
_engine = memnew(_Engine);
_classdb = memnew(_ClassDB);
_marshalls = memnew(_Marshalls);
+ _json = memnew(_JSON);
}
void register_core_settings() {
@@ -193,6 +197,7 @@ void register_core_singletons() {
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("TranslationServer", TranslationServer::get_singleton()));
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("Input", Input::get_singleton()));
ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("InputMap", InputMap::get_singleton()));
+ ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("JSON", _JSON::get_singleton()));
}
void unregister_core_types() {
@@ -203,6 +208,7 @@ void unregister_core_types() {
memdelete(_engine);
memdelete(_classdb);
memdelete(_marshalls);
+ memdelete(_json);
memdelete(_geometry);
diff --git a/core/safe_refcount.cpp b/core/safe_refcount.cpp
index c330a983a7..c9acdb7970 100644
--- a/core/safe_refcount.cpp
+++ b/core/safe_refcount.cpp
@@ -27,122 +27,10 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "safe_refcount.h"
-
-// Atomic functions, these are used for multithread safe reference counters!
-
-#ifdef NO_THREADS
-
-/* Bogus implementation unaware of multiprocessing */
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_conditional_increment_impl(register T *pw) {
-
- if (*pw == 0)
- return 0;
-
- (*pw)++;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_decrement_impl(register T *pw) {
-
- (*pw)--;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_increment_impl(register T *pw) {
-
- (*pw)++;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_sub_impl(register T *pw, register T val) {
-
- (*pw) -= val;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) {
-
- (*pw) += val;
-
- return *pw;
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, register T val) {
-
- if (val > *pw)
- *pw = val;
-
- return *pw;
-}
-#elif defined(__GNUC__)
-
-/* Implementation for GCC & Clang */
-
-// GCC guarantees atomic intrinsics for sizes of 1, 2, 4 and 8 bytes.
-// Clang states it supports GCC atomic builtins.
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_conditional_increment_impl(register T *pw) {
-
- while (true) {
- T tmp = static_cast<T const volatile &>(*pw);
- if (tmp == 0)
- return 0; // if zero, can't add to it anymore
- if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp)
- return tmp + 1;
- }
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_decrement_impl(register T *pw) {
-
- return __sync_sub_and_fetch(pw, 1);
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_increment_impl(register T *pw) {
-
- return __sync_add_and_fetch(pw, 1);
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_sub_impl(register T *pw, register T val) {
-
- return __sync_sub_and_fetch(pw, val);
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_add_impl(register T *pw, register T val) {
-
- return __sync_add_and_fetch(pw, val);
-}
-
-template <class T>
-static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, register T val) {
-
- while (true) {
- T tmp = static_cast<T const volatile &>(*pw);
- if (tmp >= val)
- return tmp; // already greater, or equal
- if (__sync_val_compare_and_swap(pw, tmp, val) == tmp)
- return val;
- }
-}
+#include "safe_refcount.h"
-#elif defined(_MSC_VER)
+#if defined(_MSC_VER)
/* Implementation for MSVC-Windows */
@@ -169,73 +57,66 @@ static _ALWAYS_INLINE_ T _atomic_exchange_if_greater_impl(register T *pw, regist
return m_val; \
}
-static _ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_conditional_increment_impl(register uint32_t *pw) {
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONG, InterlockedCompareExchange, uint32_t)
}
-static _ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_decrement_impl(register uint32_t *pw) {
return InterlockedDecrement((LONG volatile *)pw);
}
-static _ALWAYS_INLINE_ uint32_t _atomic_increment_impl(register uint32_t *pw) {
+_ALWAYS_INLINE_ uint32_t _atomic_increment_impl(register uint32_t *pw) {
return InterlockedIncrement((LONG volatile *)pw);
}
-static _ALWAYS_INLINE_ uint32_t _atomic_sub_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_sub_impl(register uint32_t *pw, register uint32_t val) {
return InterlockedExchangeAdd((LONG volatile *)pw, -(int32_t)val) - val;
}
-static _ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_add_impl(register uint32_t *pw, register uint32_t val) {
return InterlockedAdd((LONG volatile *)pw, val);
}
-static _ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(register uint32_t *pw, register uint32_t val) {
+_ALWAYS_INLINE_ uint32_t _atomic_exchange_if_greater_impl(register uint32_t *pw, register uint32_t val) {
ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONG, InterlockedCompareExchange, uint32_t)
}
-static _ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_conditional_increment_impl(register uint64_t *pw) {
ATOMIC_CONDITIONAL_INCREMENT_BODY(pw, LONGLONG, InterlockedCompareExchange64, uint64_t)
}
-static _ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_decrement_impl(register uint64_t *pw) {
return InterlockedDecrement64((LONGLONG volatile *)pw);
}
-static _ALWAYS_INLINE_ uint64_t _atomic_increment_impl(register uint64_t *pw) {
+_ALWAYS_INLINE_ uint64_t _atomic_increment_impl(register uint64_t *pw) {
return InterlockedIncrement64((LONGLONG volatile *)pw);
}
-static _ALWAYS_INLINE_ uint64_t _atomic_sub_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_sub_impl(register uint64_t *pw, register uint64_t val) {
return InterlockedExchangeAdd64((LONGLONG volatile *)pw, -(int64_t)val) - val;
}
-static _ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_add_impl(register uint64_t *pw, register uint64_t val) {
return InterlockedAdd64((LONGLONG volatile *)pw, val);
}
-static _ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(register uint64_t *pw, register uint64_t val) {
+_ALWAYS_INLINE_ uint64_t _atomic_exchange_if_greater_impl(register uint64_t *pw, register uint64_t val) {
ATOMIC_EXCHANGE_IF_GREATER_BODY(pw, val, LONGLONG, InterlockedCompareExchange64, uint64_t)
}
-#else
-
-//no threads supported?
-#error Must provide atomic functions for this platform or compiler!
-
-#endif
-
// The actual advertised functions; they'll call the right implementation
uint32_t atomic_conditional_increment(register uint32_t *counter) {
@@ -285,3 +166,4 @@ uint64_t atomic_add(register uint64_t *pw, register uint64_t val) {
uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val) {
return _atomic_exchange_if_greater_impl(pw, val);
}
+#endif
diff --git a/core/safe_refcount.h b/core/safe_refcount.h
index 802d84cccc..39967d5ac4 100644
--- a/core/safe_refcount.h
+++ b/core/safe_refcount.h
@@ -36,20 +36,141 @@
#include "platform_config.h"
#include "typedefs.h"
-uint32_t atomic_conditional_increment(register uint32_t *counter);
+// Atomic functions, these are used for multithread safe reference counters!
+
+#ifdef NO_THREADS
+
+/* Bogus implementation unaware of multiprocessing */
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
+
+ if (*pw == 0)
+ return 0;
+
+ (*pw)++;
+
+ return *pw;
+}
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
+
+ (*pw)--;
+
+ return *pw;
+}
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
+
+ (*pw)++;
+
+ return *pw;
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
+
+ (*pw) -= val;
+
+ return *pw;
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
+
+ (*pw) += val;
+
+ return *pw;
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V val) {
+
+ if (val > *pw)
+ *pw = val;
+
+ return *pw;
+}
+
+#elif defined(__GNUC__)
+
+/* Implementation for GCC & Clang */
+
+// GCC guarantees atomic intrinsics for sizes of 1, 2, 4 and 8 bytes.
+// Clang states it supports GCC atomic builtins.
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_conditional_increment(register T *pw) {
+
+ while (true) {
+ T tmp = static_cast<T const volatile &>(*pw);
+ if (tmp == 0)
+ return 0; // if zero, can't add to it anymore
+ if (__sync_val_compare_and_swap(pw, tmp, tmp + 1) == tmp)
+ return tmp + 1;
+ }
+}
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_decrement(register T *pw) {
+
+ return __sync_sub_and_fetch(pw, 1);
+}
+
+template <class T>
+static _ALWAYS_INLINE_ T atomic_increment(register T *pw) {
+
+ return __sync_add_and_fetch(pw, 1);
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_sub(register T *pw, register V val) {
+
+ return __sync_sub_and_fetch(pw, val);
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_add(register T *pw, register V val) {
+
+ return __sync_add_and_fetch(pw, val);
+}
+
+template <class T, class V>
+static _ALWAYS_INLINE_ T atomic_exchange_if_greater(register T *pw, register V val) {
+
+ while (true) {
+ T tmp = static_cast<T const volatile &>(*pw);
+ if (tmp >= val)
+ return tmp; // already greater, or equal
+ if (__sync_val_compare_and_swap(pw, tmp, val) == tmp)
+ return val;
+ }
+}
+
+#elif defined(_MSC_VER)
+// For MSVC use a separate compilation unit to prevent windows.h from polluting
+// the global namespace.
+uint32_t atomic_conditional_increment(register uint32_t *pw);
uint32_t atomic_decrement(register uint32_t *pw);
uint32_t atomic_increment(register uint32_t *pw);
uint32_t atomic_sub(register uint32_t *pw, register uint32_t val);
uint32_t atomic_add(register uint32_t *pw, register uint32_t val);
uint32_t atomic_exchange_if_greater(register uint32_t *pw, register uint32_t val);
-uint64_t atomic_conditional_increment(register uint64_t *counter);
+uint64_t atomic_conditional_increment(register uint64_t *pw);
uint64_t atomic_decrement(register uint64_t *pw);
uint64_t atomic_increment(register uint64_t *pw);
uint64_t atomic_sub(register uint64_t *pw, register uint64_t val);
uint64_t atomic_add(register uint64_t *pw, register uint64_t val);
uint64_t atomic_exchange_if_greater(register uint64_t *pw, register uint64_t val);
+#else
+//no threads supported?
+#error Must provide atomic functions for this platform or compiler!
+#endif
+
struct SafeRefCount {
uint32_t count;
@@ -57,17 +178,17 @@ struct SafeRefCount {
public:
// destroy() is called when weak_count_ drops to zero.
- bool ref() { //true on success
+ _ALWAYS_INLINE_ bool ref() { //true on success
return atomic_conditional_increment(&count) != 0;
}
- uint32_t refval() { //true on success
+ _ALWAYS_INLINE_ uint32_t refval() { //true on success
return atomic_conditional_increment(&count);
}
- bool unref() { // true if must be disposed of
+ _ALWAYS_INLINE_ bool unref() { // true if must be disposed of
if (atomic_decrement(&count) == 0) {
return true;
@@ -76,12 +197,12 @@ public:
return false;
}
- uint32_t get() const { // nothrow
+ _ALWAYS_INLINE_ uint32_t get() const { // nothrow
return count;
}
- void init(uint32_t p_value = 1) {
+ _ALWAYS_INLINE_ void init(uint32_t p_value = 1) {
count = p_value;
}
diff --git a/core/script_debugger_local.cpp b/core/script_debugger_local.cpp
index c2632da38b..8d2600e52d 100644
--- a/core/script_debugger_local.cpp
+++ b/core/script_debugger_local.cpp
@@ -186,12 +186,12 @@ struct _ScriptDebuggerLocalProfileInfoSort {
}
};
-void ScriptDebuggerLocal::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) {
+void ScriptDebuggerLocal::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
frame_time = p_frame_time;
idle_time = p_idle_time;
- fixed_time = p_fixed_time;
- fixed_frame_time = p_fixed_frame_time;
+ physics_time = p_physics_time;
+ physics_frame_time = p_physics_frame_time;
}
void ScriptDebuggerLocal::idle_poll() {
@@ -250,9 +250,9 @@ void ScriptDebuggerLocal::profiling_start() {
profiling = true;
pinfo.resize(32768);
frame_time = 0;
- fixed_time = 0;
+ physics_time = 0;
idle_time = 0;
- fixed_frame_time = 0;
+ physics_frame_time = 0;
}
void ScriptDebuggerLocal::profiling_end() {
diff --git a/core/script_debugger_local.h b/core/script_debugger_local.h
index 097c7c41f3..91f787052c 100644
--- a/core/script_debugger_local.h
+++ b/core/script_debugger_local.h
@@ -35,7 +35,7 @@
class ScriptDebuggerLocal : public ScriptDebugger {
bool profiling;
- float frame_time, idle_time, fixed_time, fixed_frame_time;
+ float frame_time, idle_time, physics_time, physics_frame_time;
uint64_t idle_accum;
Vector<ScriptLanguage::ProfilingInfo> pinfo;
@@ -51,7 +51,7 @@ public:
virtual void profiling_start();
virtual void profiling_end();
- virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time);
+ virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time);
ScriptDebuggerLocal();
};
diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp
index f0097054b1..4653ade294 100644
--- a/core/script_debugger_remote.cpp
+++ b/core/script_debugger_remote.cpp
@@ -647,8 +647,8 @@ void ScriptDebuggerRemote::_poll_events() {
profiling = true;
frame_time = 0;
idle_time = 0;
- fixed_time = 0;
- fixed_frame_time = 0;
+ physics_time = 0;
+ physics_frame_time = 0;
print_line("PROFILING ALRIGHT!");
@@ -727,8 +727,8 @@ void ScriptDebuggerRemote::_send_profiling_data(bool p_for_frame) {
packet_peer_stream->put_var(Engine::get_singleton()->get_frames_drawn()); //total frame time
packet_peer_stream->put_var(frame_time); //total frame time
packet_peer_stream->put_var(idle_time); //idle frame time
- packet_peer_stream->put_var(fixed_time); //fixed frame time
- packet_peer_stream->put_var(fixed_frame_time); //fixed frame time
+ packet_peer_stream->put_var(physics_time); //fixed frame time
+ packet_peer_stream->put_var(physics_frame_time); //fixed frame time
packet_peer_stream->put_var(USEC_TO_SEC(total_script_time)); //total script execution time
@@ -917,12 +917,12 @@ void ScriptDebuggerRemote::profiling_end() {
//ignores this, uses it via connnection
}
-void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) {
+void ScriptDebuggerRemote::profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) {
frame_time = p_frame_time;
idle_time = p_idle_time;
- fixed_time = p_fixed_time;
- fixed_frame_time = p_fixed_frame_time;
+ physics_time = p_physics_time;
+ physics_frame_time = p_physics_frame_time;
}
ScriptDebuggerRemote::ResourceUsageFunc ScriptDebuggerRemote::resource_usage_func = NULL;
diff --git a/core/script_debugger_remote.h b/core/script_debugger_remote.h
index b1ef88b812..22137d1350 100644
--- a/core/script_debugger_remote.h
+++ b/core/script_debugger_remote.h
@@ -54,7 +54,7 @@ class ScriptDebuggerRemote : public ScriptDebugger {
Vector<ScriptLanguage::ProfilingInfo *> profile_info_ptrs;
Map<StringName, int> profiler_function_signature_map;
- float frame_time, idle_time, fixed_time, fixed_frame_time;
+ float frame_time, idle_time, physics_time, physics_frame_time;
bool profiling;
int max_frame_functions;
@@ -161,7 +161,7 @@ public:
virtual void profiling_start();
virtual void profiling_end();
- virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time);
+ virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time);
ScriptDebuggerRemote();
~ScriptDebuggerRemote();
diff --git a/core/script_language.h b/core/script_language.h
index 2261737f9a..25767a2f7a 100644
--- a/core/script_language.h
+++ b/core/script_language.h
@@ -397,7 +397,7 @@ public:
virtual void add_profiling_frame_data(const StringName &p_name, const Array &p_data) = 0;
virtual void profiling_start() = 0;
virtual void profiling_end() = 0;
- virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_fixed_time, float p_fixed_frame_time) = 0;
+ virtual void profiling_set_frame_times(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) = 0;
ScriptDebugger();
virtual ~ScriptDebugger() { singleton = NULL; }
diff --git a/core/set.h b/core/set.h
index f68d78cea1..0f48e07520 100644
--- a/core/set.h
+++ b/core/set.h
@@ -100,17 +100,15 @@ private:
Element *_nil;
int size_cache;
- _Data() {
+ _FORCE_INLINE_ _Data() {
#ifdef GLOBALNIL_DISABLED
_nil = memnew_allocator(Element, A);
_nil->parent = _nil->left = _nil->right = _nil;
_nil->color = BLACK;
#else
-
_nil = (Element *)&_GlobalNilClass::_nil;
#endif
_root = NULL;
-
size_cache = 0;
}
@@ -132,10 +130,10 @@ private:
~_Data() {
_free_root();
+
#ifdef GLOBALNIL_DISABLED
memdelete_allocator<Element, A>(_nil);
#endif
- //memdelete_allocator<Element,A>(_root);
}
};
@@ -146,6 +144,7 @@ private:
ERR_FAIL_COND(p_node == _data._nil && p_color == RED);
p_node->color = p_color;
}
+
inline void _rotate_left(Element *p_node) {
Element *r = p_node->right;
@@ -194,8 +193,9 @@ private:
while (node == node->parent->right) {
node = node->parent;
}
+
if (node->parent == _data._root)
- return NULL;
+ return NULL; // No successor, as p_node = last node
return node->parent;
}
}
@@ -213,11 +213,11 @@ private:
} else {
while (node == node->parent->left) {
- if (node->parent == _data._root)
- return NULL;
-
node = node->parent;
}
+
+ if (node == _data._root)
+ return NULL; // No predecessor, as p_node = first node.
return node->parent;
}
}
@@ -228,16 +228,15 @@ private:
C less;
while (node != _data._nil) {
-
if (less(p_value, node->value))
node = node->left;
else if (less(node->value, p_value))
node = node->right;
else
- break; // found
+ return node; // found
}
- return (node != _data._nil) ? node : NULL;
+ return NULL;
}
Element *_lower_bound(const T &p_value) const {
@@ -254,24 +253,68 @@ private:
else if (less(node->value, p_value))
node = node->right;
else
- break; // found
+ return node; // found
}
- if (node == _data._nil) {
- if (prev == NULL)
- return NULL;
- if (less(prev->value, p_value)) {
+ if (prev == NULL)
+ return NULL; // tree empty
- prev = prev->_next;
- }
+ if (less(prev->value, p_value))
+ prev = prev->_next;
- return prev;
+ return prev;
+ }
- } else
- return node;
+ void _insert_rb_fix(Element *p_new_node) {
+
+ Element *node = p_new_node;
+ Element *nparent = node->parent;
+ Element *ngrand_parent;
+
+ while (nparent->color == RED) {
+ ngrand_parent = nparent->parent;
+
+ if (nparent == ngrand_parent->left) {
+ if (ngrand_parent->right->color == RED) {
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent->right, BLACK);
+ _set_color(ngrand_parent, RED);
+ node = ngrand_parent;
+ nparent = node->parent;
+ } else {
+ if (node == nparent->right) {
+ _rotate_left(nparent);
+ node = nparent;
+ nparent = node->parent;
+ }
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent, RED);
+ _rotate_right(ngrand_parent);
+ }
+ } else {
+ if (ngrand_parent->left->color == RED) {
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent->left, BLACK);
+ _set_color(ngrand_parent, RED);
+ node = ngrand_parent;
+ nparent = node->parent;
+ } else {
+ if (node == nparent->left) {
+ _rotate_right(nparent);
+ node = nparent;
+ nparent = node->parent;
+ }
+ _set_color(nparent, BLACK);
+ _set_color(ngrand_parent, RED);
+ _rotate_left(ngrand_parent);
+ }
+ }
+ }
+
+ _set_color(_data._root->left, BLACK);
}
- Element *_insert(const T &p_value, bool &r_exists) {
+ Element *_insert(const T &p_value) {
Element *new_parent = _data._root;
Element *node = _data._root->left;
@@ -286,27 +329,23 @@ private:
else if (less(node->value, p_value))
node = node->right;
else {
- r_exists = true;
- return node;
+ return node; // Return existing node
}
}
Element *new_node = memnew_allocator(Element, A);
-
new_node->parent = new_parent;
new_node->right = _data._nil;
new_node->left = _data._nil;
new_node->value = p_value;
//new_node->data=_data;
- if (new_parent == _data._root || less(p_value, new_parent->value)) {
+ if (new_parent == _data._root || less(p_value, new_parent->value)) {
new_parent->left = new_node;
} else {
new_parent->right = new_node;
}
- r_exists = false;
-
new_node->_next = _successor(new_node);
new_node->_prev = _predecessor(new_node);
if (new_node->_next)
@@ -314,164 +353,113 @@ private:
if (new_node->_prev)
new_node->_prev->_next = new_node;
- return new_node;
- }
-
- Element *_insert_rb(const T &p_value) {
-
- bool exists = false;
- Element *new_node = _insert(p_value, exists);
- if (exists)
- return new_node;
-
- Element *node = new_node;
_data.size_cache++;
-
- while (node->parent->color == RED) {
-
- if (node->parent == node->parent->parent->left) {
-
- Element *aux = node->parent->parent->right;
-
- if (aux->color == RED) {
- _set_color(node->parent, BLACK);
- _set_color(aux, BLACK);
- _set_color(node->parent->parent, RED);
- node = node->parent->parent;
- } else {
- if (node == node->parent->right) {
- node = node->parent;
- _rotate_left(node);
- }
- _set_color(node->parent, BLACK);
- _set_color(node->parent->parent, RED);
- _rotate_right(node->parent->parent);
- }
- } else {
- Element *aux = node->parent->parent->left;
-
- if (aux->color == RED) {
- _set_color(node->parent, BLACK);
- _set_color(aux, BLACK);
- _set_color(node->parent->parent, RED);
- node = node->parent->parent;
- } else {
- if (node == node->parent->left) {
- node = node->parent;
- _rotate_right(node);
- }
- _set_color(node->parent, BLACK);
- _set_color(node->parent->parent, RED);
- _rotate_left(node->parent->parent);
- }
- }
- }
- _set_color(_data._root->left, BLACK);
+ _insert_rb_fix(new_node);
return new_node;
}
- void _erase_fix(Element *p_node) {
+ void _erase_fix_rb(Element *p_node) {
Element *root = _data._root->left;
- Element *node = p_node;
-
- while ((node->color == BLACK) && (root != node)) {
- if (node == node->parent->left) {
- Element *aux = node->parent->right;
- if (aux->color == RED) {
- _set_color(aux, BLACK);
- _set_color(node->parent, RED);
- _rotate_left(node->parent);
- aux = node->parent->right;
- }
- if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) {
- _set_color(aux, RED);
- node = node->parent;
+ Element *node = _data._nil;
+ Element *sibling = p_node;
+ Element *parent = sibling->parent;
+
+ while (node != root) { // If red node found, will exit at a break
+ if (sibling->color == RED) {
+ _set_color(sibling, BLACK);
+ _set_color(parent, RED);
+ if (sibling == parent->right) {
+ sibling = sibling->left;
+ _rotate_left(parent);
} else {
- if (aux->right->color == BLACK) {
- _set_color(aux->left, BLACK);
- _set_color(aux, RED);
- _rotate_right(aux);
- aux = node->parent->right;
- }
- _set_color(aux, node->parent->color);
- _set_color(node->parent, BLACK);
- _set_color(aux->right, BLACK);
- _rotate_left(node->parent);
- node = root; /* this is to exit while loop */
+ sibling = sibling->right;
+ _rotate_right(parent);
}
- } else { /* the code below is has left and right switched from above */
- Element *aux = node->parent->left;
- if (aux->color == RED) {
- _set_color(aux, BLACK);
- _set_color(node->parent, RED);
- _rotate_right(node->parent);
- aux = node->parent->left;
+ }
+ if ((sibling->left->color == BLACK) && (sibling->right->color == BLACK)) {
+ _set_color(sibling, RED);
+ if (parent->color == RED) {
+ _set_color(parent, BLACK);
+ break;
+ } else { // loop: haven't found any red nodes yet
+ node = parent;
+ parent = node->parent;
+ sibling = (node == parent->left) ? parent->right : parent->left;
}
- if ((aux->right->color == BLACK) && (aux->left->color == BLACK)) {
- _set_color(aux, RED);
- node = node->parent;
+ } else {
+ if (sibling == parent->right) {
+ if (sibling->right->color == BLACK) {
+ _set_color(sibling->left, BLACK);
+ _set_color(sibling, RED);
+ _rotate_right(sibling);
+ sibling = sibling->parent;
+ }
+ _set_color(sibling, parent->color);
+ _set_color(parent, BLACK);
+ _set_color(sibling->right, BLACK);
+ _rotate_left(parent);
+ break;
} else {
- if (aux->left->color == BLACK) {
- _set_color(aux->right, BLACK);
- _set_color(aux, RED);
- _rotate_left(aux);
- aux = node->parent->left;
+ if (sibling->left->color == BLACK) {
+ _set_color(sibling->right, BLACK);
+ _set_color(sibling, RED);
+ _rotate_left(sibling);
+ sibling = sibling->parent;
}
- _set_color(aux, node->parent->color);
- _set_color(node->parent, BLACK);
- _set_color(aux->left, BLACK);
- _rotate_right(node->parent);
- node = root;
+
+ _set_color(sibling, parent->color);
+ _set_color(parent, BLACK);
+ _set_color(sibling->left, BLACK);
+ _rotate_right(parent);
+ break;
}
}
}
- _set_color(node, BLACK);
-
ERR_FAIL_COND(_data._nil->color != BLACK);
}
void _erase(Element *p_node) {
- Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : _successor(p_node);
- if (!rp)
- rp = _data._nil;
+ Element *rp = ((p_node->left == _data._nil) || (p_node->right == _data._nil)) ? p_node : p_node->_next;
Element *node = (rp->left == _data._nil) ? rp->right : rp->left;
node->parent = rp->parent;
- if (_data._root == node->parent) {
- _data._root->left = node;
+ Element *sibling;
+ if (rp == rp->parent->left) {
+ rp->parent->left = node;
+ sibling = rp->parent->right;
} else {
- if (rp == rp->parent->left) {
- rp->parent->left = node;
- } else {
- rp->parent->right = node;
- }
+ rp->parent->right = node;
+ sibling = rp->parent->left;
+ }
+
+ if (node->color == RED) {
+ node->parent = rp->parent;
+ _set_color(node, BLACK);
+ } else if (rp->color == BLACK && rp->parent != _data._root) {
+ _erase_fix_rb(sibling);
}
if (rp != p_node) {
ERR_FAIL_COND(rp == _data._nil);
- if (rp->color == BLACK)
- _erase_fix(node);
-
rp->left = p_node->left;
rp->right = p_node->right;
rp->parent = p_node->parent;
rp->color = p_node->color;
- p_node->left->parent = rp;
- p_node->right->parent = rp;
+ if (p_node->left != _data._nil)
+ p_node->left->parent = rp;
+ if (p_node->right != _data._nil)
+ p_node->right->parent = rp;
if (p_node == p_node->parent->left) {
p_node->parent->left = rp;
} else {
p_node->parent->right = rp;
}
- } else {
- if (p_node->color == BLACK)
- _erase_fix(node);
}
if (p_node->_next)
@@ -486,11 +474,12 @@ private:
void _calculate_depth(Element *p_element, int &max_d, int d) const {
- if (p_element == _data._nil) {
+ if (p_element == _data._nil)
return;
- }
+
_calculate_depth(p_element->left, max_d, d + 1);
_calculate_depth(p_element->right, max_d, d + 1);
+
if (d > max_d)
max_d = d;
}
@@ -529,14 +518,18 @@ public:
if (!_data._root)
return NULL;
+
Element *res = _find(p_value);
return res;
}
+ Element *lower_bound(const T &p_value) const {
+
+ return _lower_bound(p_value);
+ }
+
bool has(const T &p_value) const {
- if (!_data._root)
- return false;
return find(p_value) != NULL;
}
@@ -544,13 +537,14 @@ public:
if (!_data._root)
_data._create_root();
- return _insert_rb(p_value);
+ return _insert(p_value);
}
void erase(Element *p_element) {
- if (!_data._root)
+ if (!_data._root || !p_element)
return;
+
_erase(p_element);
if (_data.size_cache == 0 && _data._root)
_data._free_root();
@@ -560,9 +554,11 @@ public:
if (!_data._root)
return false;
+
Element *e = find(p_value);
if (!e)
return false;
+
_erase(e);
if (_data.size_cache == 0 && _data._root)
_data._free_root();
@@ -573,6 +569,7 @@ public:
if (!_data._root)
return NULL;
+
Element *e = _data._root->left;
if (e == _data._nil)
return NULL;
@@ -587,6 +584,7 @@ public:
if (!_data._root)
return NULL;
+
Element *e = _data._root->left;
if (e == _data._nil)
return NULL;
@@ -597,16 +595,13 @@ public:
return e;
}
- Element *lower_bound(const T &p_value) const {
-
- return _lower_bound(p_value);
- }
-
inline int size() const { return _data.size_cache; }
+
int calculate_depth() const {
// used for debug mostly
if (!_data._root)
return 0;
+
int max_d = 0;
_calculate_depth(_data._root->left, max_d, 0);
return max_d;
@@ -620,7 +615,6 @@ public:
_cleanup_tree(_data._root->left);
_data._root->left = _data._nil;
_data.size_cache = 0;
- _data._nil->parent = _data._nil;
_data._free_root();
}
@@ -633,6 +627,7 @@ public:
_copy_from(p_set);
}
+
_FORCE_INLINE_ Set() {
}
diff --git a/core/typedefs.h b/core/typedefs.h
index 565e28020b..bf5c8b0f75 100644
--- a/core/typedefs.h
+++ b/core/typedefs.h
@@ -290,4 +290,12 @@ struct _GlobalLock {
#define __STRX(m_index) #m_index
#define __STR(m_index) __STRX(m_index)
+#ifdef __GNUC__
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+#define likely(x) x
+#define unlikely(x) x
+#endif
+
#endif /* typedefs.h */
diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp
index 4760047959..27fc73ec63 100644
--- a/core/undo_redo.cpp
+++ b/core/undo_redo.cpp
@@ -503,6 +503,10 @@ void UndoRedo::_bind_methods() {
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);
+ ClassDB::bind_method(D_METHOD("set_max_steps", "max_steps"), &UndoRedo::set_max_steps);
+ ClassDB::bind_method(D_METHOD("get_max_steps"), &UndoRedo::get_max_steps);
+ ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo);
+ ClassDB::bind_method(D_METHOD("undo"), &UndoRedo::undo);
BIND_ENUM_CONSTANT(MERGE_DISABLE);
BIND_ENUM_CONSTANT(MERGE_ENDS);
diff --git a/core/ustring.cpp b/core/ustring.cpp
index 8273ed144b..b85996e3d1 100644
--- a/core/ustring.cpp
+++ b/core/ustring.cpp
@@ -1755,7 +1755,7 @@ static double built_in_strtod(const C *string, /* A decimal ASCII floating-point
register int c;
int exp = 0; /* Exponent read from "EX" field. */
int fracExp = 0; /* Exponent that derives from the fractional
- * part. Under normal circumstatnces, it is
+ * part. Under normal circumstances, it is
* the negative of the number of digits in F.
* However, if I is very long, the last digits
* of I get dropped (otherwise a long I with a
@@ -2332,12 +2332,12 @@ int String::findn(String p_str, int p_from) const {
int String::rfind(String p_str, int p_from) const {
- //stabilish a limit
+ // establish a limit
int limit = length() - p_str.length();
if (limit < 0)
return -1;
- //stabilish a starting point
+ // establish a starting point
if (p_from < 0)
p_from = limit;
else if (p_from > limit)
@@ -2347,7 +2347,7 @@ int String::rfind(String p_str, int p_from) const {
int len = length();
if (src_len == 0 || len == 0)
- return -1; //wont find anything!
+ return -1; // won't find anything!
const CharType *src = c_str();
@@ -2378,12 +2378,12 @@ int String::rfind(String p_str, int p_from) const {
}
int String::rfindn(String p_str, int p_from) const {
- //stabilish a limit
+ // establish a limit
int limit = length() - p_str.length();
if (limit < 0)
return -1;
- //stabilish a starting point
+ // establish a starting point
if (p_from < 0)
p_from = limit;
else if (p_from > limit)
diff --git a/core/variant.cpp b/core/variant.cpp
index 10d86152ee..f70e4a5218 100644
--- a/core/variant.cpp
+++ b/core/variant.cpp
@@ -903,9 +903,6 @@ bool Variant::is_one() const {
void Variant::reference(const Variant &p_variant) {
- if (this == &p_variant)
- return;
-
clear();
type = p_variant.type;
@@ -924,17 +921,14 @@ void Variant::reference(const Variant &p_variant) {
case INT: {
_data._int = p_variant._data._int;
-
} break;
case REAL: {
_data._real = p_variant._data._real;
-
} break;
case STRING: {
memnew_placement(_data._mem, String(*reinterpret_cast<const String *>(p_variant._data._mem)));
-
} break;
// math types
@@ -942,33 +936,24 @@ void Variant::reference(const Variant &p_variant) {
case VECTOR2: {
memnew_placement(_data._mem, Vector2(*reinterpret_cast<const Vector2 *>(p_variant._data._mem)));
-
} break;
case RECT2: {
memnew_placement(_data._mem, Rect2(*reinterpret_cast<const Rect2 *>(p_variant._data._mem)));
-
} break;
case TRANSFORM2D: {
_data._transform2d = memnew(Transform2D(*p_variant._data._transform2d));
-
} break;
case VECTOR3: {
memnew_placement(_data._mem, Vector3(*reinterpret_cast<const Vector3 *>(p_variant._data._mem)));
-
} break;
case PLANE: {
memnew_placement(_data._mem, Plane(*reinterpret_cast<const Plane *>(p_variant._data._mem)));
-
} break;
- /*
- case QUAT: {
-
- } break;*/
case RECT3: {
_data._rect3 = memnew(Rect3(*p_variant._data._rect3));
@@ -986,7 +971,6 @@ void Variant::reference(const Variant &p_variant) {
case TRANSFORM: {
_data._transform = memnew(Transform(*p_variant._data._transform));
-
} break;
// misc types
@@ -1058,6 +1042,7 @@ void Variant::reference(const Variant &p_variant) {
default: {}
}
}
+
void Variant::zero() {
switch (type) {
case NIL: break;
@@ -1073,6 +1058,7 @@ void Variant::zero() {
default: this->clear(); break;
}
}
+
void Variant::clear() {
switch (type) {
@@ -1092,12 +1078,10 @@ void Variant::clear() {
case TRANSFORM2D: {
memdelete(_data._transform2d);
-
} break;
case RECT3: {
memdelete(_data._rect3);
-
} break;
case BASIS: {
@@ -1106,14 +1090,12 @@ void Variant::clear() {
case TRANSFORM: {
memdelete(_data._transform);
-
} break;
// misc types
case NODE_PATH: {
reinterpret_cast<NodePath *>(_data._mem)->~NodePath();
-
} break;
case OBJECT: {
@@ -1127,48 +1109,39 @@ void Variant::clear() {
case DICTIONARY: {
reinterpret_cast<Dictionary *>(_data._mem)->~Dictionary();
-
} break;
case ARRAY: {
reinterpret_cast<Array *>(_data._mem)->~Array();
-
} break;
// arrays
case POOL_BYTE_ARRAY: {
reinterpret_cast<PoolVector<uint8_t> *>(_data._mem)->~PoolVector<uint8_t>();
-
} break;
case POOL_INT_ARRAY: {
reinterpret_cast<PoolVector<int> *>(_data._mem)->~PoolVector<int>();
-
} break;
case POOL_REAL_ARRAY: {
reinterpret_cast<PoolVector<real_t> *>(_data._mem)->~PoolVector<real_t>();
-
} break;
case POOL_STRING_ARRAY: {
reinterpret_cast<PoolVector<String> *>(_data._mem)->~PoolVector<String>();
-
} break;
case POOL_VECTOR2_ARRAY: {
reinterpret_cast<PoolVector<Vector2> *>(_data._mem)->~PoolVector<Vector2>();
-
} break;
case POOL_VECTOR3_ARRAY: {
reinterpret_cast<PoolVector<Vector3> *>(_data._mem)->~PoolVector<Vector3>();
-
} break;
case POOL_COLOR_ARRAY: {
reinterpret_cast<PoolVector<Color> *>(_data._mem)->~PoolVector<Color>();
-
} break;
default: {} /* not needed */
}
@@ -2496,7 +2469,135 @@ Variant::Variant(const Vector<Color> &p_array) {
void Variant::operator=(const Variant &p_variant) {
- reference(p_variant);
+ if (unlikely(this == &p_variant))
+ return;
+
+ if (unlikely(type != p_variant.type)) {
+ reference(p_variant);
+ return;
+ }
+
+ switch (p_variant.type) {
+ case NIL: {
+
+ // none
+ } break;
+
+ // atomic types
+ case BOOL: {
+
+ _data._bool = p_variant._data._bool;
+ } break;
+ case INT: {
+
+ _data._int = p_variant._data._int;
+ } break;
+ case REAL: {
+
+ _data._real = p_variant._data._real;
+ } break;
+ case STRING: {
+
+ *reinterpret_cast<String *>(_data._mem) = *reinterpret_cast<const String *>(p_variant._data._mem);
+ } break;
+
+ // math types
+
+ case VECTOR2: {
+
+ *reinterpret_cast<Vector2 *>(_data._mem) = *reinterpret_cast<const Vector2 *>(p_variant._data._mem);
+ } break;
+ case RECT2: {
+
+ *reinterpret_cast<Rect2 *>(_data._mem) = *reinterpret_cast<const Rect2 *>(p_variant._data._mem);
+ } break;
+ case TRANSFORM2D: {
+
+ *_data._transform2d = *(p_variant._data._transform2d);
+ } break;
+ case VECTOR3: {
+
+ *reinterpret_cast<Vector3 *>(_data._mem) = *reinterpret_cast<const Vector3 *>(p_variant._data._mem);
+ } break;
+ case PLANE: {
+
+ *reinterpret_cast<Plane *>(_data._mem) = *reinterpret_cast<const Plane *>(p_variant._data._mem);
+ } break;
+
+ case RECT3: {
+
+ *_data._rect3 = *(p_variant._data._rect3);
+ } break;
+ case QUAT: {
+
+ *reinterpret_cast<Quat *>(_data._mem) = *reinterpret_cast<const Quat *>(p_variant._data._mem);
+ } break;
+ case BASIS: {
+
+ *_data._basis = *(p_variant._data._basis);
+ } break;
+ case TRANSFORM: {
+
+ *_data._transform = *(p_variant._data._transform);
+ } break;
+
+ // misc types
+ case COLOR: {
+
+ *reinterpret_cast<Color *>(_data._mem) = *reinterpret_cast<const Color *>(p_variant._data._mem);
+ } break;
+ case _RID: {
+
+ *reinterpret_cast<RID *>(_data._mem) = *reinterpret_cast<const RID *>(p_variant._data._mem);
+ } break;
+ case OBJECT: {
+
+ *reinterpret_cast<ObjData *>(_data._mem) = p_variant._get_obj();
+ } break;
+ case NODE_PATH: {
+
+ *reinterpret_cast<NodePath *>(_data._mem) = *reinterpret_cast<const NodePath *>(p_variant._data._mem);
+ } break;
+ case DICTIONARY: {
+
+ *reinterpret_cast<Dictionary *>(_data._mem) = *reinterpret_cast<const Dictionary *>(p_variant._data._mem);
+ } break;
+ case ARRAY: {
+
+ *reinterpret_cast<Array *>(_data._mem) = *reinterpret_cast<const Array *>(p_variant._data._mem);
+ } break;
+
+ // arrays
+ case POOL_BYTE_ARRAY: {
+
+ *reinterpret_cast<PoolVector<uint8_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<uint8_t> *>(p_variant._data._mem);
+ } break;
+ case POOL_INT_ARRAY: {
+
+ *reinterpret_cast<PoolVector<int> *>(_data._mem) = *reinterpret_cast<const PoolVector<int> *>(p_variant._data._mem);
+ } break;
+ case POOL_REAL_ARRAY: {
+
+ *reinterpret_cast<PoolVector<real_t> *>(_data._mem) = *reinterpret_cast<const PoolVector<real_t> *>(p_variant._data._mem);
+ } break;
+ case POOL_STRING_ARRAY: {
+
+ *reinterpret_cast<PoolVector<String> *>(_data._mem) = *reinterpret_cast<const PoolVector<String> *>(p_variant._data._mem);
+ } break;
+ case POOL_VECTOR2_ARRAY: {
+
+ *reinterpret_cast<PoolVector<Vector2> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector2> *>(p_variant._data._mem);
+ } break;
+ case POOL_VECTOR3_ARRAY: {
+
+ *reinterpret_cast<PoolVector<Vector3> *>(_data._mem) = *reinterpret_cast<const PoolVector<Vector3> *>(p_variant._data._mem);
+ } break;
+ case POOL_COLOR_ARRAY: {
+
+ *reinterpret_cast<PoolVector<Color> *>(_data._mem) = *reinterpret_cast<const PoolVector<Color> *>(p_variant._data._mem);
+ } break;
+ default: {}
+ }
}
Variant::Variant(const IP_Address &p_address) {
diff --git a/core/variant.h b/core/variant.h
index e77e2e93c4..e0d0bf05c8 100644
--- a/core/variant.h
+++ b/core/variant.h
@@ -70,6 +70,7 @@ typedef PoolVector<Color> PoolColorArray;
class Variant {
public:
+ // If this changes the table in variant_op must be updated
enum Type {
NIL,
@@ -288,6 +289,7 @@ public:
Variant(const IP_Address &p_address);
+ // If this changes the table in variant_op must be updated
enum Operator {
//comparation
@@ -299,7 +301,7 @@ public:
OP_GREATER_EQUAL,
//mathematic
OP_ADD,
- OP_SUBSTRACT,
+ OP_SUBTRACT,
OP_MULTIPLY,
OP_DIVIDE,
OP_NEGATE,
@@ -366,6 +368,7 @@ public:
static Vector<Variant> get_method_default_arguments(Variant::Type p_type, const StringName &p_method);
static Variant::Type get_method_return_type(Variant::Type p_type, const StringName &p_method, bool *r_has_return = NULL);
static Vector<StringName> get_method_argument_names(Variant::Type p_type, const StringName &p_method);
+ static bool is_method_const(Variant::Type p_type, const StringName &p_method);
void set_named(const StringName &p_index, const Variant &p_value, bool *r_valid = NULL);
Variant get_named(const StringName &p_index, bool *r_valid = NULL) const;
@@ -388,7 +391,7 @@ public:
uint32_t hash() const;
bool hash_compare(const Variant &p_variant) const;
- bool booleanize(bool &valid) const;
+ bool booleanize() const;
void static_assign(const Variant &p_variant);
static void get_constructor_list(Variant::Type p_type, List<MethodInfo> *p_list);
diff --git a/core/variant_call.cpp b/core/variant_call.cpp
index 19d9b0297f..d141621fbb 100644
--- a/core/variant_call.cpp
+++ b/core/variant_call.cpp
@@ -53,6 +53,7 @@ struct _VariantCall {
Vector<StringName> arg_names;
Variant::Type return_type;
+ bool _const;
#ifdef DEBUG_ENABLED
bool returns;
#endif
@@ -145,11 +146,12 @@ struct _VariantCall {
#endif
}
- static void addfunc(Variant::Type p_type, Variant::Type p_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) {
+ static void addfunc(bool p_const, Variant::Type p_type, Variant::Type p_return, const StringName &p_name, VariantFunc p_func, const Vector<Variant> &p_defaultarg, const Arg &p_argtype1 = Arg(), const Arg &p_argtype2 = Arg(), const Arg &p_argtype3 = Arg(), const Arg &p_argtype4 = Arg(), const Arg &p_argtype5 = Arg()) {
FuncData funcdata;
funcdata.func = p_func;
funcdata.default_args = p_defaultarg;
+ funcdata._const = p_const;
#ifdef DEBUG_ENABLED
funcdata.return_type = p_return;
funcdata.returns = p_return != Variant::NIL;
@@ -1201,6 +1203,17 @@ Vector<Variant::Type> Variant::get_method_argument_types(Variant::Type p_type, c
return E->get().arg_types;
}
+bool Variant::is_method_const(Variant::Type p_type, const StringName &p_method) {
+
+ const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type];
+
+ const Map<StringName, _VariantCall::FuncData>::Element *E = fd.functions.find(p_method);
+ if (!E)
+ return false;
+
+ return E->get()._const;
+}
+
Vector<StringName> Variant::get_method_argument_names(Variant::Type p_type, const StringName &p_method) {
const _VariantCall::TypeFunc &fd = _VariantCall::type_funcs[p_type];
@@ -1248,6 +1261,10 @@ void Variant::get_method_list(List<MethodInfo> *p_list) const {
MethodInfo mi;
mi.name = E->key();
+ if (fd._const) {
+ mi.flags |= METHOD_FLAG_CONST;
+ }
+
for (int i = 0; i < fd.arg_types.size(); i++) {
PropertyInfo pi;
@@ -1360,15 +1377,26 @@ 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_create(#m_method), VCALL(m_class, m_method), m_defarg);
+ _VariantCall::addfunc(true, 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_create(#m_method), VCALL(m_class, m_method), m_defarg, _VariantCall::Arg(Variant::m_arg1, _scs_create(m_argname1)));
+ _VariantCall::addfunc(true, 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_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::addfunc(true, 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_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::addfunc(true, 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_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)));
+ _VariantCall::addfunc(true, 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)));
+
+#define ADDFUNC0NC(m_vtype, m_ret, m_class, m_method, m_defarg) \
+ _VariantCall::addfunc(false, Variant::m_vtype, Variant::m_ret, _scs_create(#m_method), VCALL(m_class, m_method), m_defarg);
+#define ADDFUNC1NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_defarg) \
+ _VariantCall::addfunc(false, 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 ADDFUNC2NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_defarg) \
+ _VariantCall::addfunc(false, 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 ADDFUNC3NC(m_vtype, m_ret, m_class, m_method, m_arg1, m_argname1, m_arg2, m_argname2, m_arg3, m_argname3, m_defarg) \
+ _VariantCall::addfunc(false, 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 ADDFUNC4NC(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(false, 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 */
ADDFUNC1(STRING, INT, String, casecmp_to, STRING, "to", varray());
@@ -1394,7 +1422,7 @@ void register_variant_methods() {
ADDFUNC2(STRING, STRING, String, format, NIL, "values", STRING, "placeholder", varray("{_}"));
ADDFUNC2(STRING, STRING, String, replace, STRING, "what", STRING, "forwhat", varray());
ADDFUNC2(STRING, STRING, String, replacen, STRING, "what", STRING, "forwhat", varray());
- ADDFUNC2(STRING, STRING, String, insert, INT, "pos", STRING, "what", varray());
+ ADDFUNC2(STRING, STRING, String, insert, INT, "position", STRING, "what", varray());
ADDFUNC0(STRING, STRING, String, capitalize, varray());
ADDFUNC2(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", varray(true));
ADDFUNC2(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true));
@@ -1402,14 +1430,14 @@ void register_variant_methods() {
ADDFUNC0(STRING, STRING, String, to_upper, varray());
ADDFUNC0(STRING, STRING, String, to_lower, varray());
- ADDFUNC1(STRING, STRING, String, left, INT, "pos", varray());
- ADDFUNC1(STRING, STRING, String, right, INT, "pos", varray());
+ ADDFUNC1(STRING, STRING, String, left, INT, "position", varray());
+ ADDFUNC1(STRING, STRING, String, right, INT, "position", varray());
ADDFUNC2(STRING, STRING, String, strip_edges, BOOL, "left", BOOL, "right", varray(true, true));
ADDFUNC0(STRING, STRING, String, get_extension, varray());
ADDFUNC0(STRING, STRING, String, get_basename, varray());
ADDFUNC1(STRING, STRING, String, plus_file, STRING, "file", varray());
ADDFUNC1(STRING, INT, String, ord_at, INT, "at", varray());
- ADDFUNC2(STRING, NIL, String, erase, INT, "pos", INT, "chars", varray());
+ ADDFUNC2(STRING, NIL, String, erase, INT, "position", INT, "chars", varray());
ADDFUNC0(STRING, INT, String, hash, varray());
ADDFUNC0(STRING, STRING, String, md5_text, varray());
ADDFUNC0(STRING, STRING, String, sha256_text, varray());
@@ -1545,7 +1573,7 @@ void register_variant_methods() {
ADDFUNC0(DICTIONARY, INT, Dictionary, size, varray());
ADDFUNC0(DICTIONARY, BOOL, Dictionary, empty, varray());
- ADDFUNC0(DICTIONARY, NIL, Dictionary, clear, varray());
+ ADDFUNC0NC(DICTIONARY, NIL, Dictionary, clear, varray());
ADDFUNC1(DICTIONARY, BOOL, Dictionary, has, NIL, "key", varray());
ADDFUNC1(DICTIONARY, BOOL, Dictionary, has_all, ARRAY, "keys", varray());
ADDFUNC1(DICTIONARY, NIL, Dictionary, erase, NIL, "key", varray());
@@ -1555,15 +1583,15 @@ void register_variant_methods() {
ADDFUNC0(ARRAY, INT, Array, size, varray());
ADDFUNC0(ARRAY, BOOL, Array, empty, varray());
- ADDFUNC0(ARRAY, NIL, Array, clear, varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, clear, varray());
ADDFUNC0(ARRAY, INT, Array, hash, varray());
- ADDFUNC1(ARRAY, NIL, Array, push_back, NIL, "value", varray());
- ADDFUNC1(ARRAY, NIL, Array, push_front, NIL, "value", varray());
- ADDFUNC1(ARRAY, NIL, Array, append, NIL, "value", varray());
- ADDFUNC1(ARRAY, NIL, Array, resize, INT, "pos", varray());
- ADDFUNC2(ARRAY, NIL, Array, insert, INT, "pos", NIL, "value", varray());
- ADDFUNC1(ARRAY, NIL, Array, remove, INT, "pos", varray());
- ADDFUNC1(ARRAY, NIL, Array, erase, NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, push_back, NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, push_front, NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, append, NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, resize, INT, "size", varray());
+ ADDFUNC2NC(ARRAY, NIL, Array, insert, INT, "position", NIL, "value", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, remove, INT, "position", varray());
+ ADDFUNC1NC(ARRAY, NIL, Array, erase, NIL, "value", varray());
ADDFUNC0(ARRAY, NIL, Array, front, varray());
ADDFUNC0(ARRAY, NIL, Array, back, varray());
ADDFUNC2(ARRAY, INT, Array, find, NIL, "what", INT, "from", varray(0));
@@ -1571,12 +1599,12 @@ void register_variant_methods() {
ADDFUNC1(ARRAY, INT, Array, find_last, NIL, "value", varray());
ADDFUNC1(ARRAY, INT, Array, count, NIL, "value", varray());
ADDFUNC1(ARRAY, BOOL, Array, has, NIL, "value", varray());
- ADDFUNC0(ARRAY, NIL, Array, pop_back, varray());
- ADDFUNC0(ARRAY, NIL, Array, pop_front, varray());
- ADDFUNC0(ARRAY, NIL, Array, sort, varray());
- ADDFUNC2(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray());
- ADDFUNC0(ARRAY, NIL, Array, invert, varray());
- ADDFUNC0(ARRAY, ARRAY, Array, duplicate, varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, pop_back, varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, pop_front, varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, sort, varray());
+ ADDFUNC2NC(ARRAY, NIL, Array, sort_custom, OBJECT, "obj", STRING, "func", varray());
+ ADDFUNC0NC(ARRAY, NIL, Array, invert, varray());
+ ADDFUNC0NC(ARRAY, ARRAY, Array, duplicate, varray());
ADDFUNC0(POOL_BYTE_ARRAY, INT, PoolByteArray, size, varray());
ADDFUNC2(POOL_BYTE_ARRAY, NIL, PoolByteArray, set, INT, "idx", INT, "byte", varray());
@@ -1728,10 +1756,10 @@ void register_variant_methods() {
_VariantCall::add_constructor(_VariantCall::Vector2_init1, Variant::VECTOR2, "x", Variant::REAL, "y", Variant::REAL);
- _VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "pos", Variant::VECTOR2, "size", Variant::VECTOR2);
+ _VariantCall::add_constructor(_VariantCall::Rect2_init1, Variant::RECT2, "position", Variant::VECTOR2, "size", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Rect2_init2, Variant::RECT2, "x", Variant::REAL, "y", Variant::REAL, "width", Variant::REAL, "height", Variant::REAL);
- _VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rot", Variant::REAL, "pos", Variant::VECTOR2);
+ _VariantCall::add_constructor(_VariantCall::Transform2D_init2, Variant::TRANSFORM2D, "rotation", Variant::REAL, "position", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Transform2D_init3, Variant::TRANSFORM2D, "x_axis", Variant::VECTOR2, "y_axis", Variant::VECTOR2, "origin", Variant::VECTOR2);
_VariantCall::add_constructor(_VariantCall::Vector3_init1, Variant::VECTOR3, "x", Variant::REAL, "y", Variant::REAL, "z", Variant::REAL);
@@ -1746,7 +1774,7 @@ void register_variant_methods() {
_VariantCall::add_constructor(_VariantCall::Color_init1, Variant::COLOR, "r", Variant::REAL, "g", Variant::REAL, "b", Variant::REAL, "a", Variant::REAL);
_VariantCall::add_constructor(_VariantCall::Color_init2, Variant::COLOR, "r", Variant::REAL, "g", Variant::REAL, "b", Variant::REAL);
- _VariantCall::add_constructor(_VariantCall::Rect3_init1, Variant::RECT3, "pos", Variant::VECTOR3, "size", Variant::VECTOR3);
+ _VariantCall::add_constructor(_VariantCall::Rect3_init1, Variant::RECT3, "position", Variant::VECTOR3, "size", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Basis_init1, Variant::BASIS, "x_axis", Variant::VECTOR3, "y_axis", Variant::VECTOR3, "z_axis", Variant::VECTOR3);
_VariantCall::add_constructor(_VariantCall::Basis_init2, Variant::BASIS, "axis", Variant::VECTOR3, "phi", Variant::REAL);
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index b6e114b853..03ec336291 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -33,49 +33,123 @@
#include "object.h"
#include "script_language.h"
-Variant::operator bool() const {
-
- bool b;
- return booleanize(b);
+#define CASE_TYPE_ALL(PREFIX, OP) \
+ CASE_TYPE(PREFIX, OP, INT) \
+ CASE_TYPE_ALL_BUT_INT(PREFIX, OP)
+
+#define CASE_TYPE_ALL_BUT_INT(PREFIX, OP) \
+ CASE_TYPE(PREFIX, OP, NIL) \
+ CASE_TYPE(PREFIX, OP, BOOL) \
+ CASE_TYPE(PREFIX, OP, REAL) \
+ CASE_TYPE(PREFIX, OP, STRING) \
+ CASE_TYPE(PREFIX, OP, VECTOR2) \
+ CASE_TYPE(PREFIX, OP, RECT2) \
+ CASE_TYPE(PREFIX, OP, VECTOR3) \
+ CASE_TYPE(PREFIX, OP, TRANSFORM2D) \
+ CASE_TYPE(PREFIX, OP, PLANE) \
+ CASE_TYPE(PREFIX, OP, QUAT) \
+ CASE_TYPE(PREFIX, OP, RECT3) \
+ CASE_TYPE(PREFIX, OP, BASIS) \
+ CASE_TYPE(PREFIX, OP, TRANSFORM) \
+ CASE_TYPE(PREFIX, OP, COLOR) \
+ CASE_TYPE(PREFIX, OP, NODE_PATH) \
+ CASE_TYPE(PREFIX, OP, _RID) \
+ CASE_TYPE(PREFIX, OP, OBJECT) \
+ CASE_TYPE(PREFIX, OP, DICTIONARY) \
+ CASE_TYPE(PREFIX, OP, ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_BYTE_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_INT_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_REAL_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_STRING_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY) \
+ CASE_TYPE(PREFIX, OP, POOL_COLOR_ARRAY)
+
+#ifdef __GNUC__
+#define TYPE(PREFIX, OP, TYPE) &&PREFIX##_##OP##_##TYPE
+
+/* clang-format off */
+#define TYPES(PREFIX, OP) { \
+ TYPE(PREFIX, OP, NIL), \
+ TYPE(PREFIX, OP, BOOL), \
+ TYPE(PREFIX, OP, INT), \
+ TYPE(PREFIX, OP, REAL), \
+ TYPE(PREFIX, OP, STRING), \
+ TYPE(PREFIX, OP, VECTOR2), \
+ TYPE(PREFIX, OP, RECT2), \
+ TYPE(PREFIX, OP, VECTOR3), \
+ TYPE(PREFIX, OP, TRANSFORM2D), \
+ TYPE(PREFIX, OP, PLANE), \
+ TYPE(PREFIX, OP, QUAT), \
+ TYPE(PREFIX, OP, RECT3), \
+ TYPE(PREFIX, OP, BASIS), \
+ TYPE(PREFIX, OP, TRANSFORM), \
+ TYPE(PREFIX, OP, COLOR), \
+ TYPE(PREFIX, OP, NODE_PATH), \
+ TYPE(PREFIX, OP, _RID), \
+ TYPE(PREFIX, OP, OBJECT), \
+ TYPE(PREFIX, OP, DICTIONARY), \
+ TYPE(PREFIX, OP, ARRAY), \
+ TYPE(PREFIX, OP, POOL_BYTE_ARRAY), \
+ TYPE(PREFIX, OP, POOL_INT_ARRAY), \
+ TYPE(PREFIX, OP, POOL_REAL_ARRAY), \
+ TYPE(PREFIX, OP, POOL_STRING_ARRAY), \
+ TYPE(PREFIX, OP, POOL_VECTOR2_ARRAY), \
+ TYPE(PREFIX, OP, POOL_VECTOR3_ARRAY), \
+ TYPE(PREFIX, OP, POOL_COLOR_ARRAY), \
+}
+/* clang-format on */
+
+#define CASES(PREFIX) static const void *switch_table_##PREFIX[25][27] = { \
+ TYPES(PREFIX, OP_EQUAL), \
+ TYPES(PREFIX, OP_NOT_EQUAL), \
+ TYPES(PREFIX, OP_LESS), \
+ TYPES(PREFIX, OP_LESS_EQUAL), \
+ TYPES(PREFIX, OP_GREATER), \
+ TYPES(PREFIX, OP_GREATER_EQUAL), \
+ TYPES(PREFIX, OP_ADD), \
+ TYPES(PREFIX, OP_SUBTRACT), \
+ TYPES(PREFIX, OP_MULTIPLY), \
+ TYPES(PREFIX, OP_DIVIDE), \
+ TYPES(PREFIX, OP_NEGATE), \
+ TYPES(PREFIX, OP_POSITIVE), \
+ TYPES(PREFIX, OP_MODULE), \
+ TYPES(PREFIX, OP_STRING_CONCAT), \
+ TYPES(PREFIX, OP_SHIFT_LEFT), \
+ TYPES(PREFIX, OP_SHIFT_RIGHT), \
+ TYPES(PREFIX, OP_BIT_AND), \
+ TYPES(PREFIX, OP_BIT_OR), \
+ TYPES(PREFIX, OP_BIT_XOR), \
+ TYPES(PREFIX, OP_BIT_NEGATE), \
+ TYPES(PREFIX, OP_AND), \
+ TYPES(PREFIX, OP_OR), \
+ TYPES(PREFIX, OP_XOR), \
+ TYPES(PREFIX, OP_NOT), \
+ TYPES(PREFIX, OP_IN), \
}
-bool Variant::booleanize(bool &r_valid) const {
+#define SWITCH(PREFIX, op, val) goto *switch_table_##PREFIX[op][val];
+#define SWITCH_OP(PREFIX, OP, val)
+#define CASE_TYPE(PREFIX, OP, TYPE) PREFIX##_##OP##_##TYPE:
+
+#else
+#define CASES(PREFIX)
+#define SWITCH(PREFIX, op, val) switch (op)
+#define SWITCH_OP(PREFIX, OP, val) \
+ case OP: \
+ switch (val)
+#define CASE_TYPE(PREFIX, OP, TYPE) case TYPE:
+#endif
- r_valid = true;
- switch (type) {
- case NIL: return false;
- case BOOL: return _data._bool;
- case INT: return _data._int;
- case REAL: return _data._real;
- case STRING: return (*reinterpret_cast<const String *>(_data._mem)) != "";
- case VECTOR2:
- case RECT2:
- case TRANSFORM2D:
- case VECTOR3:
- case PLANE:
- case RECT3:
- case QUAT:
- case BASIS:
- case TRANSFORM:
- case COLOR:
- case _RID: return (*reinterpret_cast<const RID *>(_data._mem)).is_valid();
- case OBJECT: return _get_obj().obj;
- case NODE_PATH: return (*reinterpret_cast<const NodePath *>(_data._mem)) != NodePath();
- case DICTIONARY:
- case ARRAY:
- case POOL_BYTE_ARRAY:
- case POOL_INT_ARRAY:
- case POOL_REAL_ARRAY:
- case POOL_STRING_ARRAY:
- case POOL_VECTOR2_ARRAY:
- case POOL_VECTOR3_ARRAY:
- case POOL_COLOR_ARRAY:
- r_valid = false;
- return false;
- default: {}
- }
+Variant::operator bool() const {
- return false;
+ return booleanize();
+}
+
+// We consider all unitialized or empty types to be false based on the type's
+// zeroiness.
+bool Variant::booleanize() const {
+ return !is_zero();
}
#define _RETURN(m_what) \
@@ -84,146 +158,228 @@ bool Variant::booleanize(bool &r_valid) const {
return; \
}
-#define DEFAULT_OP_NUM(m_op, m_name, m_type) \
- case m_name: { \
- switch (p_b.type) { \
- case BOOL: _RETURN(p_a._data.m_type m_op p_b._data._bool); \
- case INT: _RETURN(p_a._data.m_type m_op p_b._data._int); \
- case REAL: _RETURN(p_a._data.m_type m_op p_b._data._real); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#define _RETURN_FAIL \
+ { \
+ r_valid = false; \
+ return; \
+ }
+
+#define DEFAULT_OP_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
+ \
+ _RETURN_FAIL \
};
-#define DEFAULT_OP_NUM_NEG(m_name, m_type) \
- case m_name: { \
- \
- _RETURN(-p_a._data.m_type); \
+#define DEFAULT_OP_NUM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
+ if (p_b.type == NIL) _RETURN(!p_b.type m_op NIL); \
+ \
+ _RETURN_FAIL \
};
-#define DEFAULT_OP_NUM_POS(m_name, m_type) \
- case m_name: { \
- \
- _RETURN(p_a._data.m_type); \
+#ifdef DEBUG_ENABLED
+#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) { \
+ if (p_b._data._int == 0) { \
+ r_valid = false; \
+ _RETURN("Division By Zero"); \
+ } \
+ _RETURN(p_a._data.m_type / p_b._data._int); \
+ } \
+ if (p_b.type == REAL) { \
+ if (p_b._data._real == 0) { \
+ r_valid = false; \
+ _RETURN("Division By Zero"); \
+ } \
+ _RETURN(p_a._data.m_type / p_b._data._real); \
+ } \
+ \
+ _RETURN_FAIL \
+ };
+#else
+#define DEFAULT_OP_NUM_DIV(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type / p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type / p_b._data._real); \
+ \
+ _RETURN_FAIL \
};
+#endif
-#define DEFAULT_OP_NUM_VEC(m_op, m_name, m_type) \
- case m_name: { \
- switch (p_b.type) { \
- case BOOL: _RETURN(p_a._data.m_type m_op p_b._data._bool); \
- case INT: _RETURN(p_a._data.m_type m_op p_b._data._int); \
- case REAL: _RETURN(p_a._data.m_type m_op p_b._data._real); \
- case VECTOR2: _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
- case VECTOR3: _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#define DEFAULT_OP_NUM_NEG(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ _RETURN(-p_a._data.m_type); \
};
-#define DEFAULT_OP_STR(m_op, m_name, m_type) \
- case m_name: { \
- switch (p_b.type) { \
- case STRING: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
- case NODE_PATH: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#define DEFAULT_OP_NUM_POS(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ _RETURN(p_a._data.m_type); \
};
-#define DEFAULT_OP_LOCALMEM(m_op, m_name, m_type) \
- case m_name: { \
- switch (p_b.type) { \
- case m_name: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
- default: {} \
- } \
- r_valid = false; \
- return; \
- }
+#define DEFAULT_OP_NUM_VEC(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == INT) _RETURN(p_a._data.m_type m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(p_a._data.m_type m_op p_b._data._real); \
+ if (p_b.type == VECTOR2) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector2 *>(p_b._data._mem)); \
+ if (p_b.type == VECTOR3) _RETURN(p_a._data.m_type m_op *reinterpret_cast<const Vector3 *>(p_b._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_STR_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const String *>(p_a._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const NodePath *>(p_a._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_STR(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_STR_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == STRING) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const String *>(p_b._data._mem)); \
+ if (p_b.type == NODE_PATH) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const NodePath *>(p_b._data._mem)); \
+ if (p_b.type == NIL) _RETURN(!p_b.type m_op NIL); \
+ \
+ _RETURN_FAIL \
+ };
-#define DEFAULT_OP_LOCALMEM_NEG(m_name, m_type) \
- case m_name: { \
+#define DEFAULT_OP_LOCALMEM_REV(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(*reinterpret_cast<const m_type *>(p_b._data._mem) m_op *reinterpret_cast<const m_type *>(p_a._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_LOCALMEM(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_LOCALMEM_NULL(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
+ if (p_b.type == NIL) \
+ _RETURN(!p_b.type m_op NIL); \
+ \
+ _RETURN_FAIL \
+ };
+
+#define DEFAULT_OP_LOCALMEM_NEG(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
_RETURN(-*reinterpret_cast<const m_type *>(p_a._data._mem)); \
}
-#define DEFAULT_OP_LOCALMEM_POS(m_name, m_type) \
- case m_name: { \
- _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \
+#define DEFAULT_OP_LOCALMEM_POS(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem)); \
}
-#define DEFAULT_OP_LOCALMEM_NUM(m_op, m_name, m_type) \
- case m_name: { \
- switch (p_b.type) { \
- case m_name: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
- case BOOL: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._bool); \
- case INT: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \
- case REAL: _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._real); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#define DEFAULT_OP_LOCALMEM_NUM(m_prefix, m_op_name, m_name, m_op, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op *reinterpret_cast<const m_type *>(p_b._data._mem)); \
+ if (p_b.type == INT) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._int); \
+ if (p_b.type == REAL) _RETURN(*reinterpret_cast<const m_type *>(p_a._data._mem) m_op p_b._data._real); \
+ \
+ _RETURN_FAIL \
}
-#define DEFAULT_OP_PTR(m_op, m_name, m_sub) \
- case m_name: { \
- switch (p_b.type) { \
- case m_name: _RETURN(p_a._data.m_sub m_op p_b._data.m_sub); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#define DEFAULT_OP_PTR(m_op, m_name, m_sub) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(p_a._data.m_sub m_op p_b._data.m_sub); \
+ \
+ _RETURN_FAIL \
}
-#define DEFAULT_OP_PTRREF(m_op, m_name, m_sub) \
- case m_name: { \
- switch (p_b.type) { \
- case m_name: _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \
- default: {} \
- } \
- r_valid = false; \
- return; \
+#define DEFAULT_OP_PTRREF(m_prefix, m_op_name, m_name, m_op, m_sub) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \
+ \
+ _RETURN_FAIL \
}
-#define DEFAULT_OP_ARRAY_EQ(m_name, m_type) \
- DEFAULT_OP_ARRAY_OP(m_name, m_type, !=, !=, true, false, false)
+#define DEFAULT_OP_PTRREF_NULL(m_prefix, m_op_name, m_name, m_op, m_sub) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == m_name) \
+ _RETURN(*p_a._data.m_sub m_op *p_b._data.m_sub); \
+ if (p_b.type == NIL) \
+ _RETURN(!p_b.type m_op NIL); \
+ \
+ _RETURN_FAIL \
+ }
-#define DEFAULT_OP_ARRAY_LT(m_name, m_type) \
- DEFAULT_OP_ARRAY_OP(m_name, m_type, <, !=, false, a_len < array_b.size(), true)
+#define DEFAULT_OP_ARRAY_EQ(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == NIL) \
+ _RETURN(false) \
+ DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, !=, !=, true, false, false) \
+ }
-#define DEFAULT_OP_ARRAY_OP(m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \
- case m_name: { \
- if (p_a.type != p_b.type) { \
- r_valid = false; \
- return; \
- } \
- const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \
- const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \
- \
- int a_len = array_a.size(); \
- if (a_len m_opa array_b.size()) { \
- _RETURN(m_ret_s); \
- } else { \
- \
- PoolVector<m_type>::Read ra = array_a.read(); \
- PoolVector<m_type>::Read rb = array_b.read(); \
- \
- for (int i = 0; i < a_len; i++) { \
- if (ra[i] m_opb rb[i]) \
- _RETURN(m_ret_f); \
- } \
- \
- _RETURN(m_ret_def); \
- } \
+#define DEFAULT_OP_ARRAY_NEQ(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_b.type == NIL) \
+ _RETURN(true) \
+ DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, !=, ==, true, true, false) \
+ }
+
+#define DEFAULT_OP_ARRAY_LT(m_prefix, m_op_name, m_name, m_type) \
+ DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, <, !=, false, a_len < array_b.size(), true)
+
+#define DEFAULT_OP_ARRAY_GT(m_prefix, m_op_name, m_name, m_type) \
+ DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, >, !=, false, a_len < array_b.size(), true)
+
+#define DEFAULT_OP_ARRAY_OP(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \
+ }
+
+#define DEFAULT_OP_ARRAY_OP_BODY(m_prefix, m_op_name, m_name, m_type, m_opa, m_opb, m_ret_def, m_ret_s, m_ret_f) \
+ if (p_a.type != p_b.type) \
+ _RETURN_FAIL \
+ \
+ const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \
+ const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \
+ \
+ int a_len = array_a.size(); \
+ if (a_len m_opa array_b.size()) { \
+ _RETURN(m_ret_s); \
+ } else { \
+ \
+ PoolVector<m_type>::Read ra = array_a.read(); \
+ PoolVector<m_type>::Read rb = array_b.read(); \
+ \
+ for (int i = 0; i < a_len; i++) { \
+ if (ra[i] m_opb rb[i]) \
+ _RETURN(m_ret_f); \
+ } \
+ \
+ _RETURN(m_ret_def); \
}
-#define DEFAULT_OP_ARRAY_ADD(m_name, m_type) \
- case m_name: { \
- if (p_a.type != p_b.type) { \
- r_valid = false; \
- _RETURN(NIL); \
- } \
+#define DEFAULT_OP_ARRAY_ADD(m_prefix, m_op_name, m_name, m_type) \
+ CASE_TYPE(m_prefix, m_op_name, m_name) { \
+ if (p_a.type != p_b.type) \
+ _RETURN_FAIL; \
+ \
const PoolVector<m_type> &array_a = *reinterpret_cast<const PoolVector<m_type> *>(p_a._data._mem); \
const PoolVector<m_type> &array_b = *reinterpret_cast<const PoolVector<m_type> *>(p_b._data._mem); \
PoolVector<m_type> sum = array_a; \
@@ -231,595 +387,670 @@ bool Variant::booleanize(bool &r_valid) const {
_RETURN(sum); \
}
-#define DEFAULT_OP_FAIL(m_name) \
- case m_name: { \
- r_valid = false; \
- return; \
- }
-
-void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &p_b, Variant &r_ret, bool &r_valid) {
+void Variant::evaluate(const Operator &p_op, const Variant &p_a,
+ const Variant &p_b, Variant &r_ret, bool &r_valid) {
+ CASES(math);
r_valid = true;
- switch (p_op) {
+ SWITCH(math, p_op, p_a.type) {
+ SWITCH_OP(math, OP_EQUAL, p_a.type) {
+ CASE_TYPE(math, OP_EQUAL, NIL) {
+ if (p_b.type == NIL) _RETURN(true);
+ if (p_b.type == OBJECT)
+ _RETURN(p_b._get_obj().obj == NULL);
- case OP_EQUAL: {
+ _RETURN(false);
+ }
- if ((int(p_a.type) * int(p_b.type)) == 0) {
- //null case is an exception, one of both is null
- if (p_a.type == p_b.type) //null against null is true
- _RETURN(true);
- //only against object is allowed
- if (p_a.type == Variant::OBJECT) {
- _RETURN(p_a._get_obj().obj == NULL);
- } else if (p_b.type == Variant::OBJECT) {
- _RETURN(p_b._get_obj().obj == NULL);
+ CASE_TYPE(math, OP_EQUAL, BOOL) {
+ if (p_b.type != BOOL) {
+ if (p_b.type == NIL)
+ _RETURN(false);
+ _RETURN_FAIL;
}
- //otherwise, always false
- _RETURN(false);
+
+ _RETURN(p_a._data._bool == p_b._data._bool);
}
- switch (p_a.type) {
+ CASE_TYPE(math, OP_EQUAL, OBJECT) {
+ if (p_b.type == OBJECT)
+ _RETURN((p_a._get_obj().obj == p_b._get_obj().obj));
+ if (p_b.type == NIL)
+ _RETURN(p_a._get_obj().obj == NULL);
- case NIL: {
+ _RETURN_FAIL;
+ }
- _RETURN(p_b.type == NIL || (p_b.type == Variant::OBJECT && !p_b._get_obj().obj));
- } break;
+ CASE_TYPE(math, OP_EQUAL, DICTIONARY) {
+ if (p_b.type != DICTIONARY) {
+ if (p_b.type == NIL)
+ _RETURN(false);
+ _RETURN_FAIL;
+ }
- DEFAULT_OP_NUM(==, BOOL, _bool);
- DEFAULT_OP_NUM(==, INT, _int);
- DEFAULT_OP_NUM(==, REAL, _real);
- DEFAULT_OP_STR(==, STRING, String);
- DEFAULT_OP_LOCALMEM(==, VECTOR2, Vector2);
- DEFAULT_OP_LOCALMEM(==, RECT2, Rect2);
- DEFAULT_OP_PTRREF(==, TRANSFORM2D, _transform2d);
- DEFAULT_OP_LOCALMEM(==, VECTOR3, Vector3);
- DEFAULT_OP_LOCALMEM(==, PLANE, Plane);
- DEFAULT_OP_LOCALMEM(==, QUAT, Quat);
- DEFAULT_OP_PTRREF(==, RECT3, _rect3);
- DEFAULT_OP_PTRREF(==, BASIS, _basis);
- DEFAULT_OP_PTRREF(==, TRANSFORM, _transform);
+ const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
+ const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
- DEFAULT_OP_LOCALMEM(==, COLOR, Color);
- DEFAULT_OP_STR(==, NODE_PATH, NodePath);
- DEFAULT_OP_LOCALMEM(==, _RID, RID);
- case OBJECT: {
+ _RETURN(*arr_a == *arr_b);
+ }
- if (p_b.type == OBJECT)
- _RETURN((p_a._get_obj().obj == p_b._get_obj().obj));
+ CASE_TYPE(math, OP_EQUAL, ARRAY) {
+ if (p_b.type != ARRAY) {
if (p_b.type == NIL)
- _RETURN(!p_a._get_obj().obj);
- } break;
-
- case DICTIONARY: {
+ _RETURN(false);
+ _RETURN_FAIL;
+ }
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
- if (p_b.type != DICTIONARY)
+ int l = arr_a->size();
+ if (arr_b->size() != l)
+ _RETURN(false);
+ for (int i = 0; i < l; i++) {
+ if (!((*arr_a)[i] == (*arr_b)[i])) {
_RETURN(false);
+ }
+ }
- const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
- const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
+ _RETURN(true);
+ }
+
+ DEFAULT_OP_NUM_NULL(math, OP_EQUAL, INT, ==, _int);
+ DEFAULT_OP_NUM_NULL(math, OP_EQUAL, REAL, ==, _real);
+ DEFAULT_OP_STR_NULL(math, OP_EQUAL, STRING, ==, String);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR2, ==, Vector2);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, RECT2, ==, Rect2);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM2D, ==, _transform2d);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, VECTOR3, ==, Vector3);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, PLANE, ==, Plane);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, QUAT, ==, Quat);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, RECT3, ==, _rect3);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, BASIS, ==, _basis);
+ DEFAULT_OP_PTRREF_NULL(math, OP_EQUAL, TRANSFORM, ==, _transform);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, COLOR, ==, Color);
+ DEFAULT_OP_STR_NULL(math, OP_EQUAL, NODE_PATH, ==, NodePath);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_EQUAL, _RID, ==, RID);
+
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR2_ARRAY, Vector2);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_EQ(math, OP_EQUAL, POOL_COLOR_ARRAY, Color);
+ }
- _RETURN(*arr_a == *arr_b);
+ SWITCH_OP(math, OP_NOT_EQUAL, p_a.type) {
+ CASE_TYPE(math, OP_NOT_EQUAL, NIL) {
+ if (p_b.type == NIL) _RETURN(false);
+ if (p_b.type == OBJECT)
+ _RETURN(p_b._get_obj().obj != NULL);
- } break;
- case ARRAY: {
+ _RETURN(true);
+ }
- if (p_b.type != ARRAY)
- _RETURN(false);
+ CASE_TYPE(math, OP_NOT_EQUAL, BOOL) {
+ if (p_b.type != BOOL) {
+ if (p_b.type == NIL)
+ _RETURN(true);
- const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
- const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
+ _RETURN_FAIL;
+ }
- int l = arr_a->size();
- if (arr_b->size() != l)
- _RETURN(false);
- for (int i = 0; i < l; i++) {
- if (!((*arr_a)[i] == (*arr_b)[i])) {
- _RETURN(false);
- }
- }
+ _RETURN(p_a._data._bool != p_b._data._bool);
+ }
- _RETURN(true);
+ CASE_TYPE(math, OP_NOT_EQUAL, OBJECT) {
+ if (p_b.type == OBJECT)
+ _RETURN((p_a._get_obj().obj != p_b._get_obj().obj));
+ if (p_b.type == NIL)
+ _RETURN(p_a._get_obj().obj != NULL);
- } break;
+ _RETURN_FAIL;
+ }
- DEFAULT_OP_ARRAY_EQ(POOL_BYTE_ARRAY, uint8_t);
- DEFAULT_OP_ARRAY_EQ(POOL_INT_ARRAY, int);
- DEFAULT_OP_ARRAY_EQ(POOL_REAL_ARRAY, real_t);
- DEFAULT_OP_ARRAY_EQ(POOL_STRING_ARRAY, String);
- DEFAULT_OP_ARRAY_EQ(POOL_VECTOR2_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_EQ(POOL_VECTOR3_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_EQ(POOL_COLOR_ARRAY, Color);
+ CASE_TYPE(math, OP_NOT_EQUAL, DICTIONARY) {
+ if (p_b.type != DICTIONARY) {
+ if (p_b.type == NIL)
+ _RETURN(true);
+ _RETURN_FAIL;
+ }
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ const Dictionary *arr_a = reinterpret_cast<const Dictionary *>(p_a._data._mem);
+ const Dictionary *arr_b = reinterpret_cast<const Dictionary *>(p_b._data._mem);
- } break;
+ _RETURN((*arr_a == *arr_b) == false);
}
- } break;
- case OP_NOT_EQUAL: {
- Variant res;
- evaluate(OP_EQUAL, p_a, p_b, res, r_valid);
- if (!r_valid)
- return;
- if (res.type == BOOL)
- res._data._bool = !res._data._bool;
- _RETURN(res);
-
- } break;
- case OP_LESS: {
-
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(<, BOOL, _bool);
- DEFAULT_OP_NUM(<, INT, _int);
- DEFAULT_OP_NUM(<, REAL, _real);
- DEFAULT_OP_STR(<, STRING, String);
- DEFAULT_OP_LOCALMEM(<, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM(<, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_FAIL(QUAT);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_LOCALMEM(<, _RID, RID);
- case OBJECT: {
-
- if (p_b.type == OBJECT)
- _RETURN((p_a._get_obj().obj < p_b._get_obj().obj));
- } break;
- DEFAULT_OP_FAIL(DICTIONARY);
- case ARRAY: {
-
- if (p_b.type != ARRAY)
- _RETURN(false);
- const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
- const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
+ CASE_TYPE(math, OP_NOT_EQUAL, ARRAY) {
+ if (p_b.type != ARRAY) {
+ if (p_b.type == NIL)
+ _RETURN(true);
+
+ _RETURN_FAIL;
+ }
- int l = arr_a->size();
- if (arr_b->size() < l)
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
+
+ int l = arr_a->size();
+ if (arr_b->size() != l)
+ _RETURN(true);
+ for (int i = 0; i < l; i++) {
+ if (((*arr_a)[i] == (*arr_b)[i])) {
_RETURN(false);
- for (int i = 0; i < l; i++) {
- if (!((*arr_a)[i] < (*arr_b)[i])) {
- _RETURN(true);
- }
}
+ }
- _RETURN(false);
+ _RETURN(true);
+ }
+
+ DEFAULT_OP_NUM_NULL(math, OP_NOT_EQUAL, INT, !=, _int);
+ DEFAULT_OP_NUM_NULL(math, OP_NOT_EQUAL, REAL, !=, _real);
+ DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, STRING, !=, String);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR2, !=, Vector2);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, RECT2, !=, Rect2);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM2D, !=, _transform2d);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, VECTOR3, !=, Vector3);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, PLANE, !=, Plane);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, QUAT, !=, Quat);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, RECT3, !=, _rect3);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, BASIS, !=, _basis);
+ DEFAULT_OP_PTRREF_NULL(math, OP_NOT_EQUAL, TRANSFORM, !=, _transform);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, COLOR, !=, Color);
+ DEFAULT_OP_STR_NULL(math, OP_NOT_EQUAL, NODE_PATH, !=, NodePath);
+ DEFAULT_OP_LOCALMEM_NULL(math, OP_NOT_EQUAL, _RID, !=, RID);
+
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_VECTOR2_ARRAY, Vector2);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_NEQ(math, OP_NOT_EQUAL, POOL_COLOR_ARRAY, Color);
+ }
- } break;
- DEFAULT_OP_ARRAY_LT(POOL_BYTE_ARRAY, uint8_t);
- DEFAULT_OP_ARRAY_LT(POOL_INT_ARRAY, int);
- DEFAULT_OP_ARRAY_LT(POOL_REAL_ARRAY, real_t);
- DEFAULT_OP_ARRAY_LT(POOL_STRING_ARRAY, String);
- DEFAULT_OP_ARRAY_LT(POOL_VECTOR2_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_LT(POOL_VECTOR3_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_LT(POOL_COLOR_ARRAY, Color);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ SWITCH_OP(math, OP_LESS, p_a.type) {
+ CASE_TYPE(math, OP_LESS, BOOL) {
+ if (p_b.type != BOOL)
+ _RETURN_FAIL;
- } break;
- }
-
- } break;
- case OP_LESS_EQUAL: {
-
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(<=, BOOL, _bool);
- DEFAULT_OP_NUM(<=, INT, _int);
- DEFAULT_OP_NUM(<=, REAL, _real);
- DEFAULT_OP_STR(<=, STRING, String);
- DEFAULT_OP_LOCALMEM(<=, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM(<=, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_FAIL(QUAT);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_LOCALMEM(<=, _RID, RID);
- case OBJECT: {
-
- if (p_b.type == OBJECT)
- _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj));
- } break;
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ if (p_a._data._bool == p_b._data._bool)
+ _RETURN(false);
+
+ if (p_a._data._bool && !p_b._data._bool)
+ _RETURN(false);
- } break;
+ _RETURN(true);
}
- } break;
- case OP_GREATER: {
+ CASE_TYPE(math, OP_LESS, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj < p_b._get_obj().obj));
+ }
- Variant res;
- evaluate(OP_LESS, p_b, p_a, res, r_valid);
- if (!r_valid)
- return;
- _RETURN(res);
+ CASE_TYPE(math, OP_LESS, ARRAY) {
+ if (p_b.type != ARRAY)
+ _RETURN_FAIL;
- } break;
- case OP_GREATER_EQUAL: {
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
- Variant res;
- evaluate(OP_LESS_EQUAL, p_b, p_a, res, r_valid);
- if (!r_valid)
- return;
- _RETURN(res);
- } break;
- //mathematic
- case OP_ADD: {
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(+, BOOL, _bool);
- DEFAULT_OP_NUM(+, INT, _int);
- DEFAULT_OP_NUM(+, REAL, _real);
- DEFAULT_OP_STR(+, STRING, String);
- DEFAULT_OP_LOCALMEM(+, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM(+, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_LOCALMEM(+, QUAT, Quat);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
-
- case ARRAY: {
- if (p_a.type != p_b.type) {
- r_valid = false;
- return;
+ int l = arr_a->size();
+ if (arr_b->size() < l)
+ _RETURN(false);
+ for (int i = 0; i < l; i++) {
+ if (!((*arr_a)[i] < (*arr_b)[i])) {
+ _RETURN(true);
}
- const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem);
- const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem);
- Array sum;
- int asize = array_a.size();
- int bsize = array_b.size();
- sum.resize(asize + bsize);
- for (int i = 0; i < asize; i++)
- sum[i] = array_a[i];
- for (int i = 0; i < bsize; i++)
- sum[i + asize] = array_b[i];
- _RETURN(sum);
- }
- DEFAULT_OP_ARRAY_ADD(POOL_BYTE_ARRAY, uint8_t);
- DEFAULT_OP_ARRAY_ADD(POOL_INT_ARRAY, int);
- DEFAULT_OP_ARRAY_ADD(POOL_REAL_ARRAY, real_t);
- DEFAULT_OP_ARRAY_ADD(POOL_STRING_ARRAY, String);
- DEFAULT_OP_ARRAY_ADD(POOL_VECTOR2_ARRAY, Vector2);
- DEFAULT_OP_ARRAY_ADD(POOL_VECTOR3_ARRAY, Vector3);
- DEFAULT_OP_ARRAY_ADD(POOL_COLOR_ARRAY, Color);
- case VARIANT_MAX: {
- r_valid = false;
- return;
-
- } break;
- }
- } break;
- case OP_SUBSTRACT: {
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(-, BOOL, _bool);
- DEFAULT_OP_NUM(-, INT, _int);
- DEFAULT_OP_NUM(-, REAL, _real);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_LOCALMEM(-, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM(-, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- DEFAULT_OP_LOCALMEM(-, QUAT, Quat);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ }
- } break;
+ _RETURN(false);
}
- } break;
- case OP_MULTIPLY: {
- switch (p_a.type) {
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(*, BOOL, _bool);
- DEFAULT_OP_NUM_VEC(*, INT, _int);
- DEFAULT_OP_NUM_VEC(*, REAL, _real);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_LOCALMEM_NUM(*, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- case TRANSFORM2D: {
+ DEFAULT_OP_NUM(math, OP_LESS, INT, <, _int);
+ DEFAULT_OP_NUM(math, OP_LESS, REAL, <, _real);
+ DEFAULT_OP_STR(math, OP_LESS, STRING, <, String);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR2, <, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS, VECTOR3, <, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS, _RID, <, RID);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR2_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_LT(math, OP_LESS, POOL_COLOR_ARRAY, Color);
+
+ CASE_TYPE(math, OP_LESS, NIL)
+ CASE_TYPE(math, OP_LESS, RECT2)
+ CASE_TYPE(math, OP_LESS, TRANSFORM2D)
+ CASE_TYPE(math, OP_LESS, PLANE)
+ CASE_TYPE(math, OP_LESS, QUAT)
+ CASE_TYPE(math, OP_LESS, RECT3)
+ CASE_TYPE(math, OP_LESS, BASIS)
+ CASE_TYPE(math, OP_LESS, TRANSFORM)
+ CASE_TYPE(math, OP_LESS, COLOR)
+ CASE_TYPE(math, OP_LESS, NODE_PATH)
+ CASE_TYPE(math, OP_LESS, DICTIONARY)
+ _RETURN_FAIL;
+ }
- if (p_b.type == TRANSFORM2D) {
- _RETURN(*p_a._data._transform2d * *p_b._data._transform2d);
- };
- if (p_b.type == VECTOR2) {
- _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem));
- };
- r_valid = false;
- return;
- } break;
- DEFAULT_OP_LOCALMEM_NUM(*, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- case QUAT: {
-
- switch (p_b.type) {
- case VECTOR3: {
-
- _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem));
- } break;
- case QUAT: {
-
- _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem));
- } break;
- case REAL: {
- _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real);
- } break;
- default: {}
- };
- r_valid = false;
- return;
- } break;
- DEFAULT_OP_FAIL(RECT3);
- case BASIS: {
+ SWITCH_OP(math, OP_LESS_EQUAL, p_a.type) {
+ CASE_TYPE(math, OP_LESS_EQUAL, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj <= p_b._get_obj().obj));
+ }
+
+ DEFAULT_OP_NUM(math, OP_LESS_EQUAL, INT, <=, _int);
+ DEFAULT_OP_NUM(math, OP_LESS_EQUAL, REAL, <=, _real);
+ DEFAULT_OP_STR(math, OP_LESS_EQUAL, STRING, <=, String);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR2, <=, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, VECTOR3, <=, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_LESS_EQUAL, _RID, <=, RID);
+
+ CASE_TYPE(math, OP_LESS_EQUAL, NIL)
+ CASE_TYPE(math, OP_LESS_EQUAL, BOOL)
+ CASE_TYPE(math, OP_LESS_EQUAL, RECT2)
+ CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM2D)
+ CASE_TYPE(math, OP_LESS_EQUAL, PLANE)
+ CASE_TYPE(math, OP_LESS_EQUAL, QUAT)
+ CASE_TYPE(math, OP_LESS_EQUAL, RECT3)
+ CASE_TYPE(math, OP_LESS_EQUAL, BASIS)
+ CASE_TYPE(math, OP_LESS_EQUAL, TRANSFORM)
+ CASE_TYPE(math, OP_LESS_EQUAL, COLOR)
+ CASE_TYPE(math, OP_LESS_EQUAL, NODE_PATH)
+ CASE_TYPE(math, OP_LESS_EQUAL, DICTIONARY)
+ CASE_TYPE(math, OP_LESS_EQUAL, ARRAY)
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_LESS_EQUAL, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- switch (p_b.type) {
- case VECTOR3: {
+ SWITCH_OP(math, OP_GREATER, p_a.type) {
+ CASE_TYPE(math, OP_GREATER, BOOL) {
+ if (p_b.type != BOOL)
+ _RETURN_FAIL;
- _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem));
- };
- case BASIS: {
+ if (p_a._data._bool == p_b._data._bool)
+ _RETURN(false);
- _RETURN(*p_a._data._basis * *p_b._data._basis);
- };
- default: {}
- };
- r_valid = false;
- return;
- } break;
- case TRANSFORM: {
+ if (!p_a._data._bool && p_b._data._bool)
+ _RETURN(false);
- switch (p_b.type) {
- case VECTOR3: {
+ _RETURN(true);
+ }
- _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem));
- };
- case TRANSFORM: {
+ CASE_TYPE(math, OP_GREATER, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj > p_b._get_obj().obj));
+ }
- _RETURN(*p_a._data._transform * *p_b._data._transform);
- };
- default: {}
- };
- r_valid = false;
- return;
- } break;
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ CASE_TYPE(math, OP_GREATER, ARRAY) {
+ if (p_b.type != ARRAY)
+ _RETURN_FAIL;
- } break;
- }
- } break;
- case OP_DIVIDE: {
- switch (p_a.type) {
+ const Array *arr_a = reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array *arr_b = reinterpret_cast<const Array *>(p_b._data._mem);
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM(/, BOOL, _bool);
- case INT: {
- switch (p_b.type) {
- case BOOL: {
- int64_t b = p_b._data._bool;
- if (b == 0) {
+ int l = arr_a->size();
+ if (arr_b->size() > l)
+ _RETURN(false);
+ for (int i = 0; i < l; i++) {
+ if (((*arr_a)[i] < (*arr_b)[i])) {
+ _RETURN(false);
+ }
+ }
+
+ _RETURN(true);
+ }
+
+ DEFAULT_OP_NUM(math, OP_GREATER, INT, >, _int);
+ DEFAULT_OP_NUM(math, OP_GREATER, REAL, >, _real);
+ DEFAULT_OP_STR_REV(math, OP_GREATER, STRING, <, String);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR2, <, Vector2);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, VECTOR3, <, Vector3);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER, _RID, <, RID);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR2_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_GT(math, OP_GREATER, POOL_COLOR_ARRAY, Color);
+
+ CASE_TYPE(math, OP_GREATER, NIL)
+ CASE_TYPE(math, OP_GREATER, RECT2)
+ CASE_TYPE(math, OP_GREATER, TRANSFORM2D)
+ CASE_TYPE(math, OP_GREATER, PLANE)
+ CASE_TYPE(math, OP_GREATER, QUAT)
+ CASE_TYPE(math, OP_GREATER, RECT3)
+ CASE_TYPE(math, OP_GREATER, BASIS)
+ CASE_TYPE(math, OP_GREATER, TRANSFORM)
+ CASE_TYPE(math, OP_GREATER, COLOR)
+ CASE_TYPE(math, OP_GREATER, NODE_PATH)
+ CASE_TYPE(math, OP_GREATER, DICTIONARY)
+ _RETURN_FAIL;
+ }
- r_valid = false;
- _RETURN("Division By False");
- }
- _RETURN(p_a._data._int / b);
+ SWITCH_OP(math, OP_GREATER_EQUAL, p_a.type) {
+ CASE_TYPE(math, OP_GREATER_EQUAL, OBJECT) {
+ if (p_b.type != OBJECT)
+ _RETURN_FAIL;
+ _RETURN((p_a._get_obj().obj >= p_b._get_obj().obj));
+ }
+
+ DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, INT, >=, _int);
+ DEFAULT_OP_NUM(math, OP_GREATER_EQUAL, REAL, >=, _real);
+ DEFAULT_OP_STR_REV(math, OP_GREATER_EQUAL, STRING, <=, String);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR2, <=, Vector2);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, VECTOR3, <=, Vector3);
+ DEFAULT_OP_LOCALMEM_REV(math, OP_GREATER_EQUAL, _RID, <=, RID);
+
+ CASE_TYPE(math, OP_GREATER_EQUAL, NIL)
+ CASE_TYPE(math, OP_GREATER_EQUAL, BOOL)
+ CASE_TYPE(math, OP_GREATER_EQUAL, RECT2)
+ CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM2D)
+ CASE_TYPE(math, OP_GREATER_EQUAL, PLANE)
+ CASE_TYPE(math, OP_GREATER_EQUAL, QUAT)
+ CASE_TYPE(math, OP_GREATER_EQUAL, RECT3)
+ CASE_TYPE(math, OP_GREATER_EQUAL, BASIS)
+ CASE_TYPE(math, OP_GREATER_EQUAL, TRANSFORM)
+ CASE_TYPE(math, OP_GREATER_EQUAL, COLOR)
+ CASE_TYPE(math, OP_GREATER_EQUAL, NODE_PATH)
+ CASE_TYPE(math, OP_GREATER_EQUAL, DICTIONARY)
+ CASE_TYPE(math, OP_GREATER_EQUAL, ARRAY)
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_GREATER_EQUAL, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- } break;
- case INT: {
- int64_t b = p_b._data._int;
- if (b == 0) {
+ SWITCH_OP(math, OP_ADD, p_a.type) {
+ CASE_TYPE(math, OP_ADD, ARRAY) {
+ if (p_a.type != p_b.type)
+ _RETURN_FAIL;
+
+ const Array &array_a = *reinterpret_cast<const Array *>(p_a._data._mem);
+ const Array &array_b = *reinterpret_cast<const Array *>(p_b._data._mem);
+ Array sum;
+ int asize = array_a.size();
+ int bsize = array_b.size();
+ sum.resize(asize + bsize);
+ for (int i = 0; i < asize; i++)
+ sum[i] = array_a[i];
+ for (int i = 0; i < bsize; i++)
+ sum[i + asize] = array_b[i];
+ _RETURN(sum);
+ }
+
+ DEFAULT_OP_NUM(math, OP_ADD, INT, +, _int);
+ DEFAULT_OP_NUM(math, OP_ADD, REAL, +, _real);
+ DEFAULT_OP_STR(math, OP_ADD, STRING, +, String);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR2, +, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, VECTOR3, +, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, QUAT, +, Quat);
+ DEFAULT_OP_LOCALMEM(math, OP_ADD, COLOR, +, Color);
+
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_BYTE_ARRAY, uint8_t);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_INT_ARRAY, int);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_REAL_ARRAY, real_t);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_STRING_ARRAY, String);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR2_ARRAY, Vector2);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_VECTOR3_ARRAY, Vector3);
+ DEFAULT_OP_ARRAY_ADD(math, OP_ADD, POOL_COLOR_ARRAY, Color);
+
+ CASE_TYPE(math, OP_ADD, NIL)
+ CASE_TYPE(math, OP_ADD, BOOL)
+ CASE_TYPE(math, OP_ADD, RECT2)
+ CASE_TYPE(math, OP_ADD, TRANSFORM2D)
+ CASE_TYPE(math, OP_ADD, PLANE)
+ CASE_TYPE(math, OP_ADD, RECT3)
+ CASE_TYPE(math, OP_ADD, BASIS)
+ CASE_TYPE(math, OP_ADD, TRANSFORM)
+ CASE_TYPE(math, OP_ADD, NODE_PATH)
+ CASE_TYPE(math, OP_ADD, _RID)
+ CASE_TYPE(math, OP_ADD, OBJECT)
+ CASE_TYPE(math, OP_ADD, DICTIONARY)
+ _RETURN_FAIL;
+ }
- r_valid = false;
- _RETURN("Division By Zero");
- }
- _RETURN(p_a._data._int / b);
+ SWITCH_OP(math, OP_SUBTRACT, p_a.type) {
+ DEFAULT_OP_NUM(math, OP_SUBTRACT, INT, -, _int);
+ DEFAULT_OP_NUM(math, OP_SUBTRACT, REAL, -, _real);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR2, -, Vector2);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, VECTOR3, -, Vector3);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, QUAT, -, Quat);
+ DEFAULT_OP_LOCALMEM(math, OP_SUBTRACT, COLOR, -, Color);
+
+ CASE_TYPE(math, OP_SUBTRACT, NIL)
+ CASE_TYPE(math, OP_SUBTRACT, BOOL)
+ CASE_TYPE(math, OP_SUBTRACT, STRING)
+ CASE_TYPE(math, OP_SUBTRACT, RECT2)
+ CASE_TYPE(math, OP_SUBTRACT, TRANSFORM2D)
+ CASE_TYPE(math, OP_SUBTRACT, PLANE)
+ CASE_TYPE(math, OP_SUBTRACT, RECT3)
+ CASE_TYPE(math, OP_SUBTRACT, BASIS)
+ CASE_TYPE(math, OP_SUBTRACT, TRANSFORM)
+ CASE_TYPE(math, OP_SUBTRACT, NODE_PATH)
+ CASE_TYPE(math, OP_SUBTRACT, _RID)
+ CASE_TYPE(math, OP_SUBTRACT, OBJECT)
+ CASE_TYPE(math, OP_SUBTRACT, DICTIONARY)
+ CASE_TYPE(math, OP_SUBTRACT, ARRAY)
+ CASE_TYPE(math, OP_SUBTRACT, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_SUBTRACT, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
- } break;
- case REAL: _RETURN(p_a._data._int / p_b._data._real);
- default: {}
+ SWITCH_OP(math, OP_MULTIPLY, p_a.type) {
+ CASE_TYPE(math, OP_MULTIPLY, TRANSFORM2D) {
+ switch (p_b.type) {
+ case TRANSFORM2D: {
+ _RETURN(*p_a._data._transform2d * *p_b._data._transform2d);
}
- r_valid = false;
- return;
- };
- DEFAULT_OP_NUM(/, REAL, _real);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_LOCALMEM_NUM(/, VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM_NUM(/, VECTOR3, Vector3);
- DEFAULT_OP_FAIL(PLANE);
- case QUAT: {
- if (p_b.type != REAL) {
- r_valid = false;
- return;
+ case VECTOR2: {
+ _RETURN(p_a._data._transform2d->xform(*(const Vector2 *)p_b._data._mem));
}
- _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real);
- } break;
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ default: _RETURN_FAIL;
+ }
+ }
- } break;
- }
-
- } break;
- case OP_POSITIVE: {
- // Simple case when user defines variable as +value.
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
- DEFAULT_OP_NUM_POS(BOOL, _bool);
- DEFAULT_OP_NUM_POS(INT, _int);
- DEFAULT_OP_NUM_POS(REAL, _real);
- DEFAULT_OP_LOCALMEM_POS(VECTOR3, Vector3);
- DEFAULT_OP_LOCALMEM_POS(PLANE, Plane);
- DEFAULT_OP_LOCALMEM_POS(QUAT, Quat);
- DEFAULT_OP_LOCALMEM_POS(VECTOR2, Vector2);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ CASE_TYPE(math, OP_MULTIPLY, QUAT) {
+ switch (p_b.type) {
+ case VECTOR3: {
+ _RETURN(reinterpret_cast<const Quat *>(p_a._data._mem)->xform(*(const Vector3 *)p_b._data._mem));
+ }
+ case QUAT: {
+ _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * *reinterpret_cast<const Quat *>(p_b._data._mem));
+ }
+ case REAL: {
+ _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) * p_b._data._real);
+ }
+ default: _RETURN_FAIL;
+ }
+ }
- } break;
- }
- } break;
- case OP_NEGATE: {
- switch (p_a.type) {
-
- DEFAULT_OP_FAIL(NIL);
- DEFAULT_OP_NUM_NEG(BOOL, _bool);
- DEFAULT_OP_NUM_NEG(INT, _int);
- DEFAULT_OP_NUM_NEG(REAL, _real);
- DEFAULT_OP_FAIL(STRING);
- DEFAULT_OP_LOCALMEM_NEG(VECTOR2, Vector2);
- DEFAULT_OP_FAIL(RECT2);
- DEFAULT_OP_FAIL(TRANSFORM2D);
- DEFAULT_OP_LOCALMEM_NEG(VECTOR3, Vector3);
- DEFAULT_OP_LOCALMEM_NEG(PLANE, Plane);
- DEFAULT_OP_LOCALMEM_NEG(QUAT, Quat);
- DEFAULT_OP_FAIL(RECT3);
- DEFAULT_OP_FAIL(BASIS);
- DEFAULT_OP_FAIL(TRANSFORM);
-
- DEFAULT_OP_FAIL(COLOR);
-
- DEFAULT_OP_FAIL(NODE_PATH);
- DEFAULT_OP_FAIL(_RID);
- DEFAULT_OP_FAIL(OBJECT);
- DEFAULT_OP_FAIL(DICTIONARY);
- DEFAULT_OP_FAIL(ARRAY);
- DEFAULT_OP_FAIL(POOL_BYTE_ARRAY);
- DEFAULT_OP_FAIL(POOL_INT_ARRAY);
- DEFAULT_OP_FAIL(POOL_REAL_ARRAY);
- DEFAULT_OP_FAIL(POOL_STRING_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR2_ARRAY);
- DEFAULT_OP_FAIL(POOL_VECTOR3_ARRAY);
- DEFAULT_OP_FAIL(POOL_COLOR_ARRAY);
- case VARIANT_MAX: {
- r_valid = false;
- return;
+ CASE_TYPE(math, OP_MULTIPLY, BASIS) {
+ switch (p_b.type) {
+ case VECTOR3: {
+ _RETURN(p_a._data._basis->xform(*(const Vector3 *)p_b._data._mem));
+ }
+ case BASIS: {
+ _RETURN(*p_a._data._basis * *p_b._data._basis);
+ }
+ default: _RETURN_FAIL;
+ }
+ }
- } break;
+ CASE_TYPE(math, OP_MULTIPLY, TRANSFORM) {
+ switch (p_b.type) {
+ case VECTOR3: {
+ _RETURN(p_a._data._transform->xform(*(const Vector3 *)p_b._data._mem));
+ }
+ case TRANSFORM: {
+ _RETURN(*p_a._data._transform * *p_b._data._transform);
+ }
+ default: _RETURN_FAIL;
+ }
}
- } break;
- case OP_MODULE: {
- if (p_a.type == INT && p_b.type == INT) {
+
+ DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, INT, *, _int);
+ DEFAULT_OP_NUM_VEC(math, OP_MULTIPLY, REAL, *, _real);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR2, *, Vector2);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, VECTOR3, *, Vector3);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_MULTIPLY, COLOR, *, Color);
+
+ CASE_TYPE(math, OP_MULTIPLY, NIL)
+ CASE_TYPE(math, OP_MULTIPLY, BOOL)
+ CASE_TYPE(math, OP_MULTIPLY, STRING)
+ CASE_TYPE(math, OP_MULTIPLY, RECT2)
+ CASE_TYPE(math, OP_MULTIPLY, PLANE)
+ CASE_TYPE(math, OP_MULTIPLY, RECT3)
+ CASE_TYPE(math, OP_MULTIPLY, NODE_PATH)
+ CASE_TYPE(math, OP_MULTIPLY, _RID)
+ CASE_TYPE(math, OP_MULTIPLY, OBJECT)
+ CASE_TYPE(math, OP_MULTIPLY, DICTIONARY)
+ CASE_TYPE(math, OP_MULTIPLY, ARRAY)
+ CASE_TYPE(math, OP_MULTIPLY, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_MULTIPLY, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
+
+ SWITCH_OP(math, OP_DIVIDE, p_a.type) {
+ CASE_TYPE(math, OP_DIVIDE, QUAT) {
+ if (p_b.type != REAL)
+ _RETURN_FAIL;
+#ifdef DEBUG_ENABLED
+ if (p_b._data._real == 0) {
+ r_valid = false;
+ _RETURN("Division By Zero");
+ }
+#endif
+ _RETURN(*reinterpret_cast<const Quat *>(p_a._data._mem) / p_b._data._real);
+ }
+
+ DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, INT, _int);
+ DEFAULT_OP_NUM_DIV(math, OP_DIVIDE, REAL, _real);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR2, /, Vector2);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, VECTOR3, /, Vector3);
+ DEFAULT_OP_LOCALMEM_NUM(math, OP_DIVIDE, COLOR, /, Color);
+
+ CASE_TYPE(math, OP_DIVIDE, NIL)
+ CASE_TYPE(math, OP_DIVIDE, BOOL)
+ CASE_TYPE(math, OP_DIVIDE, STRING)
+ CASE_TYPE(math, OP_DIVIDE, RECT2)
+ CASE_TYPE(math, OP_DIVIDE, TRANSFORM2D)
+ CASE_TYPE(math, OP_DIVIDE, PLANE)
+ CASE_TYPE(math, OP_DIVIDE, RECT3)
+ CASE_TYPE(math, OP_DIVIDE, BASIS)
+ CASE_TYPE(math, OP_DIVIDE, TRANSFORM)
+ CASE_TYPE(math, OP_DIVIDE, NODE_PATH)
+ CASE_TYPE(math, OP_DIVIDE, _RID)
+ CASE_TYPE(math, OP_DIVIDE, OBJECT)
+ CASE_TYPE(math, OP_DIVIDE, DICTIONARY)
+ CASE_TYPE(math, OP_DIVIDE, ARRAY)
+ CASE_TYPE(math, OP_DIVIDE, POOL_BYTE_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_INT_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_REAL_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_STRING_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR2_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_VECTOR3_ARRAY);
+ CASE_TYPE(math, OP_DIVIDE, POOL_COLOR_ARRAY);
+ _RETURN_FAIL;
+ }
+
+ SWITCH_OP(math, OP_POSITIVE, p_a.type) {
+ DEFAULT_OP_NUM_POS(math, OP_POSITIVE, INT, _int);
+ DEFAULT_OP_NUM_POS(math, OP_POSITIVE, REAL, _real);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR3, Vector3);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, PLANE, Plane);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, QUAT, Quat);
+ DEFAULT_OP_LOCALMEM_POS(math, OP_POSITIVE, VECTOR2, Vector2);
+
+ CASE_TYPE(math, OP_POSITIVE, NIL)
+ CASE_TYPE(math, OP_POSITIVE, BOOL)
+ CASE_TYPE(math, OP_POSITIVE, STRING)
+ CASE_TYPE(math, OP_POSITIVE, RECT2)
+ CASE_TYPE(math, OP_POSITIVE, TRANSFORM2D)
+ CASE_TYPE(math, OP_POSITIVE, RECT3)
+ CASE_TYPE(math, OP_POSITIVE, BASIS)
+ CASE_TYPE(math, OP_POSITIVE, TRANSFORM)
+ CASE_TYPE(math, OP_POSITIVE, COLOR)
+ CASE_TYPE(math, OP_POSITIVE, NODE_PATH)
+ CASE_TYPE(math, OP_POSITIVE, _RID)
+ CASE_TYPE(math, OP_POSITIVE, OBJECT)
+ CASE_TYPE(math, OP_POSITIVE, DICTIONARY)
+ CASE_TYPE(math, OP_POSITIVE, ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_BYTE_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_INT_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_REAL_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_STRING_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR2_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_VECTOR3_ARRAY)
+ CASE_TYPE(math, OP_POSITIVE, POOL_COLOR_ARRAY)
+ _RETURN_FAIL;
+ }
+
+ SWITCH_OP(math, OP_NEGATE, p_a.type) {
+ DEFAULT_OP_NUM_NEG(math, OP_NEGATE, INT, _int);
+ DEFAULT_OP_NUM_NEG(math, OP_NEGATE, REAL, _real);
+
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR2, Vector2);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, VECTOR3, Vector3);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, PLANE, Plane);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, QUAT, Quat);
+ DEFAULT_OP_LOCALMEM_NEG(math, OP_NEGATE, COLOR, Color);
+
+ CASE_TYPE(math, OP_NEGATE, NIL)
+ CASE_TYPE(math, OP_NEGATE, BOOL)
+ CASE_TYPE(math, OP_NEGATE, STRING)
+ CASE_TYPE(math, OP_NEGATE, RECT2)
+ CASE_TYPE(math, OP_NEGATE, TRANSFORM2D)
+ CASE_TYPE(math, OP_NEGATE, RECT3)
+ CASE_TYPE(math, OP_NEGATE, BASIS)
+ CASE_TYPE(math, OP_NEGATE, TRANSFORM)
+ CASE_TYPE(math, OP_NEGATE, NODE_PATH)
+ CASE_TYPE(math, OP_NEGATE, _RID)
+ CASE_TYPE(math, OP_NEGATE, OBJECT)
+ CASE_TYPE(math, OP_NEGATE, DICTIONARY)
+ CASE_TYPE(math, OP_NEGATE, ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_BYTE_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_INT_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_REAL_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_STRING_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_VECTOR2_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_VECTOR3_ARRAY)
+ CASE_TYPE(math, OP_NEGATE, POOL_COLOR_ARRAY)
+ _RETURN_FAIL;
+ }
+
+ SWITCH_OP(math, OP_MODULE, p_a.type) {
+ CASE_TYPE(math, OP_MODULE, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
#ifdef DEBUG_ENABLED
if (p_b._data._int == 0) {
r_valid = false;
@@ -827,8 +1058,9 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
}
#endif
_RETURN(p_a._data._int % p_b._data._int);
+ }
- } else if (p_a.type == STRING) {
+ CASE_TYPE(math, OP_MODULE, STRING) {
const String *format = reinterpret_cast<const String *>(p_a._data._mem);
String result;
@@ -847,171 +1079,627 @@ void Variant::evaluate(const Operator &p_op, const Variant &p_a, const Variant &
_RETURN(result);
}
- r_valid = false;
- return;
+ CASE_TYPE(math, OP_MODULE, NIL)
+ CASE_TYPE(math, OP_MODULE, BOOL)
+ CASE_TYPE(math, OP_MODULE, REAL)
+ CASE_TYPE(math, OP_MODULE, VECTOR2)
+ CASE_TYPE(math, OP_MODULE, RECT2)
+ CASE_TYPE(math, OP_MODULE, VECTOR3)
+ CASE_TYPE(math, OP_MODULE, TRANSFORM2D)
+ CASE_TYPE(math, OP_MODULE, PLANE)
+ CASE_TYPE(math, OP_MODULE, QUAT)
+ CASE_TYPE(math, OP_MODULE, RECT3)
+ CASE_TYPE(math, OP_MODULE, BASIS)
+ CASE_TYPE(math, OP_MODULE, TRANSFORM)
+ CASE_TYPE(math, OP_MODULE, COLOR)
+ CASE_TYPE(math, OP_MODULE, NODE_PATH)
+ CASE_TYPE(math, OP_MODULE, _RID)
+ CASE_TYPE(math, OP_MODULE, OBJECT)
+ CASE_TYPE(math, OP_MODULE, DICTIONARY)
+ CASE_TYPE(math, OP_MODULE, ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_BYTE_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_INT_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_REAL_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_STRING_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_VECTOR2_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_VECTOR3_ARRAY)
+ CASE_TYPE(math, OP_MODULE, POOL_COLOR_ARRAY)
+ _RETURN_FAIL;
+ }
- } break;
- case OP_STRING_CONCAT: {
+ SWITCH_OP(math, OP_STRING_CONCAT, p_a.type) {
+ CASE_TYPE_ALL(math, OP_STRING_CONCAT)
_RETURN(p_a.operator String() + p_b.operator String());
- } break;
- //bitwise
- case OP_SHIFT_LEFT: {
- if (p_a.type == INT && p_b.type == INT)
+ }
+
+ SWITCH_OP(math, OP_SHIFT_LEFT, p_a.type) {
+ CASE_TYPE(math, OP_SHIFT_LEFT, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int << p_b._data._int);
+ }
- r_valid = false;
- return;
+ CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_LEFT)
+ _RETURN_FAIL;
+ }
- } break;
- case OP_SHIFT_RIGHT: {
- if (p_a.type == INT && p_b.type == INT)
+ SWITCH_OP(math, OP_SHIFT_RIGHT, p_a.type) {
+ CASE_TYPE(math, OP_SHIFT_RIGHT, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int >> p_b._data._int);
+ }
- r_valid = false;
- return;
+ CASE_TYPE_ALL_BUT_INT(math, OP_SHIFT_RIGHT)
+ _RETURN_FAIL;
+ }
- } break;
- case OP_BIT_AND: {
- if (p_a.type == INT && p_b.type == INT)
+ SWITCH_OP(math, OP_BIT_AND, p_a.type) {
+ CASE_TYPE(math, OP_BIT_AND, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int & p_b._data._int);
+ }
- r_valid = false;
- return;
-
- } break;
- case OP_BIT_OR: {
+ CASE_TYPE_ALL_BUT_INT(math, OP_BIT_AND)
+ _RETURN_FAIL;
+ }
- if (p_a.type == INT && p_b.type == INT)
+ SWITCH_OP(math, OP_BIT_OR, p_a.type) {
+ CASE_TYPE(math, OP_BIT_OR, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int | p_b._data._int);
+ }
- r_valid = false;
- return;
-
- } break;
- case OP_BIT_XOR: {
+ CASE_TYPE_ALL_BUT_INT(math, OP_BIT_OR)
+ _RETURN_FAIL;
+ }
- if (p_a.type == INT && p_b.type == INT)
+ SWITCH_OP(math, OP_BIT_XOR, p_a.type) {
+ CASE_TYPE(math, OP_BIT_XOR, INT) {
+ if (p_b.type != INT)
+ _RETURN_FAIL;
_RETURN(p_a._data._int ^ p_b._data._int);
+ }
- r_valid = false;
- return;
-
- } break;
- case OP_BIT_NEGATE: {
+ CASE_TYPE_ALL_BUT_INT(math, OP_BIT_XOR)
+ _RETURN_FAIL;
+ }
- if (p_a.type == INT)
+ SWITCH_OP(math, OP_BIT_NEGATE, p_a.type) {
+ CASE_TYPE(math, OP_BIT_NEGATE, INT) {
_RETURN(~p_a._data._int);
+ }
- r_valid = false;
- return;
+ CASE_TYPE_ALL_BUT_INT(math, OP_BIT_NEGATE)
+ _RETURN_FAIL;
+ }
+
+ SWITCH_OP(math, OP_AND, p_a.type) {
+ CASE_TYPE_ALL(math, OP_AND) {
+ bool l = p_a.booleanize();
+ bool r = p_b.booleanize();
+
+ _RETURN(l && r);
+ }
+ }
+
+ SWITCH_OP(math, OP_OR, p_a.type) {
+ CASE_TYPE_ALL(math, OP_OR) {
+ bool l = p_a.booleanize();
+ bool r = p_b.booleanize();
+
+ _RETURN(l || r);
+ }
+ }
+
+ SWITCH_OP(math, OP_XOR, p_a.type) {
+ CASE_TYPE_ALL(math, OP_XOR) {
+ bool l = p_a.booleanize();
+ bool r = p_b.booleanize();
+
+ _RETURN((l || r) && !(l && r));
+ }
+ }
+
+ SWITCH_OP(math, OP_NOT, p_a.type) {
+ CASE_TYPE_ALL(math, OP_NOT) {
+ bool l = p_a.booleanize();
+ _RETURN(!l);
+ }
+ }
+
+ SWITCH_OP(math, OP_IN, p_a.type) {
+ CASE_TYPE_ALL(math, OP_IN)
+ _RETURN(p_b.in(p_a, &r_valid));
+ }
+ }
+}
+
+void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) {
+
+ bool valid = false;
+ switch (type) {
+ case VECTOR2: {
+ if (p_value.type == Variant::INT) {
+ Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Vector2 *v = reinterpret_cast<Vector2 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._real;
+ valid = true;
+ }
+ }
} break;
- //logic
- case OP_AND: {
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- bool r = p_b.booleanize(r_valid);
- if (!r_valid)
- return;
+ case RECT2: {
- _RETURN(l && r);
+ if (p_value.type == Variant::VECTOR2) {
+ Rect2 *v = reinterpret_cast<Rect2 *>(_data._mem);
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ v->position = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ v->size = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ v->size = *reinterpret_cast<const Vector2 *>(p_value._data._mem) - v->position;
+ valid = true;
+ }
+ }
} break;
- case OP_OR: {
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- bool r = p_b.booleanize(r_valid);
- if (!r_valid)
- return;
+ case TRANSFORM2D: {
- _RETURN(l || r);
+ if (p_value.type == Variant::VECTOR2) {
+ Transform2D *v = _data._transform2d;
+ if (p_index == CoreStringNames::singleton->x) {
+ v->elements[0] = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->elements[1] = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->origin) {
+ v->elements[2] = *reinterpret_cast<const Vector2 *>(p_value._data._mem);
+ valid = true;
+ }
+ }
} break;
- case OP_XOR: {
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- bool r = p_b.booleanize(r_valid);
- if (!r_valid)
- return;
+ case VECTOR3: {
+
+ if (p_value.type == Variant::INT) {
+ Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Vector3 *v = reinterpret_cast<Vector3 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._real;
+ valid = true;
+ }
+ }
- _RETURN((l || r) && !(l && r));
} break;
- case OP_NOT: {
+ case PLANE: {
- bool l = p_a.booleanize(r_valid);
- if (!r_valid)
- return;
- _RETURN(!l);
+ if (p_value.type == Variant::INT) {
+ Plane *v = reinterpret_cast<Plane *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->normal.x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->normal.y = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->normal.z = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->d) {
+ v->d = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Plane *v = reinterpret_cast<Plane *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->normal.x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->normal.y = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->normal.z = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->d) {
+ v->d = p_value._data._real;
+ valid = true;
+ }
+
+ } else if (p_value.type == Variant::VECTOR3) {
+ Plane *v = reinterpret_cast<Plane *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->normal) {
+ v->normal = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
+ valid = true;
+ }
+ }
} break;
- case OP_IN: {
+ case QUAT: {
- _RETURN(p_b.in(p_a, &r_valid));
+ if (p_value.type == Variant::INT) {
+ Quat *v = reinterpret_cast<Quat *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->w) {
+ v->w = p_value._data._int;
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Quat *v = reinterpret_cast<Quat *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ v->x = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->y = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->z = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->w) {
+ v->w = p_value._data._real;
+ valid = true;
+ }
+ }
+
+ } break; // 10
+ case RECT3: {
+ if (p_value.type == Variant::VECTOR3) {
+ Rect3 *v = _data._rect3;
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ v->position = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ v->size = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ v->size = *reinterpret_cast<const Vector3 *>(p_value._data._mem) - v->position;
+ valid = true;
+ }
+ }
} break;
- case OP_MAX: {
+ case BASIS: {
- r_valid = false;
- ERR_FAIL();
- }
- }
+ if (p_value.type == Variant::VECTOR3) {
+ Basis *v = _data._basis;
+ //scalar name
+ if (p_index == CoreStringNames::singleton->x) {
+ v->set_axis(0, *reinterpret_cast<const Vector3 *>(p_value._data._mem));
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ v->set_axis(1, *reinterpret_cast<const Vector3 *>(p_value._data._mem));
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ v->set_axis(2, *reinterpret_cast<const Vector3 *>(p_value._data._mem));
+ valid = true;
+ }
+ }
+ } break;
+ case TRANSFORM: {
- r_valid = false;
-}
+ if (p_value.type == Variant::BASIS && p_index == CoreStringNames::singleton->basis) {
+ _data._transform->basis = *p_value._data._basis;
+ valid = true;
+ } else if (p_value.type == Variant::VECTOR3 && p_index == CoreStringNames::singleton->origin) {
+ _data._transform->origin = *reinterpret_cast<const Vector3 *>(p_value._data._mem);
+ valid = true;
+ }
-void Variant::set_named(const StringName &p_index, const Variant &p_value, bool *r_valid) {
+ } break;
+ case COLOR: {
- if (type == OBJECT) {
+ if (p_value.type == Variant::INT) {
+ Color *v = reinterpret_cast<Color *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->r) {
+ v->r = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->g) {
+ v->g = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->b) {
+ v->b = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->a) {
+ v->a = p_value._data._int;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->r8) {
+ v->r = p_value._data._int / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->g8) {
+ v->g = p_value._data._int / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->b8) {
+ v->b = p_value._data._int / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->a8) {
+ v->a = p_value._data._int / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->h) {
+ v->set_hsv(p_value._data._int, v->get_s(), v->get_v());
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->s) {
+ v->set_hsv(v->get_h(), p_value._data._int, v->get_v());
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->v) {
+ v->set_hsv(v->get_h(), v->get_v(), p_value._data._int);
+ valid = true;
+ }
+ } else if (p_value.type == Variant::REAL) {
+ Color *v = reinterpret_cast<Color *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->r) {
+ v->r = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->g) {
+ v->g = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->b) {
+ v->b = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->a) {
+ v->a = p_value._data._real;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->r8) {
+ v->r = p_value._data._real / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->g8) {
+ v->g = p_value._data._real / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->b8) {
+ v->b = p_value._data._real / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->a8) {
+ v->a = p_value._data._real / 255.0;
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->h) {
+ v->set_hsv(p_value._data._real, v->get_s(), v->get_v());
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->s) {
+ v->set_hsv(v->get_h(), p_value._data._real, v->get_v());
+ valid = true;
+ } else if (p_index == CoreStringNames::singleton->v) {
+ v->set_hsv(v->get_h(), v->get_v(), p_value._data._real);
+ valid = true;
+ }
+ }
+ } break;
+ case OBJECT: {
#ifdef DEBUG_ENABLED
- if (!_get_obj().obj) {
- if (r_valid)
- *r_valid = false;
- return;
- } else {
-
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
- if (r_valid)
- *r_valid = false;
- return;
+ if (!_get_obj().obj) {
+ break;
+ } else if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+ break;
}
- }
#endif
- _get_obj().obj->set(p_index, p_value, r_valid);
- return;
+ _get_obj().obj->set(p_index, p_value, &valid);
+
+ } break;
+ default: {
+ set(p_index.operator String(), p_value, &valid);
+ } break;
}
- set(p_index.operator String(), p_value, r_valid);
+ if (r_valid) {
+ *r_valid = valid;
+ }
}
Variant Variant::get_named(const StringName &p_index, bool *r_valid) const {
- if (type == OBJECT) {
+ if (r_valid) {
+ *r_valid = true;
+ }
+ switch (type) {
+ case VECTOR2: {
+ const Vector2 *v = reinterpret_cast<const Vector2 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->y;
+ }
-#ifdef DEBUG_ENABLED
- if (!_get_obj().obj) {
- if (r_valid)
- *r_valid = false;
- return "Instance base is null.";
- } else {
+ } break;
+ case RECT2: {
- if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+ const Rect2 *v = reinterpret_cast<const Rect2 *>(_data._mem);
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ return v->position;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ return v->size;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ return v->size + v->position;
+ }
+ } break;
+ case TRANSFORM2D: {
+
+ const Transform2D *v = _data._transform2d;
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->elements[0];
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->elements[1];
+ } else if (p_index == CoreStringNames::singleton->origin) {
+ return v->elements[2];
+ }
+
+ } break;
+ case VECTOR3: {
+
+ const Vector3 *v = reinterpret_cast<const Vector3 *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->y;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->z;
+ }
+
+ } break;
+ case PLANE: {
+
+ const Plane *v = reinterpret_cast<const Plane *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->normal.x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->normal.y;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->normal.z;
+ } else if (p_index == CoreStringNames::singleton->d) {
+ return v->d;
+ } else if (p_index == CoreStringNames::singleton->normal) {
+ return v->normal;
+ }
+
+ } break;
+ case QUAT: {
+
+ const Quat *v = reinterpret_cast<const Quat *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->x;
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->y;
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->z;
+ } else if (p_index == CoreStringNames::singleton->w) {
+ return v->w;
+ }
+
+ } break; // 10
+ case RECT3: {
+
+ const Rect3 *v = _data._rect3;
+ //scalar name
+ if (p_index == CoreStringNames::singleton->position) {
+ return v->position;
+ } else if (p_index == CoreStringNames::singleton->size) {
+ return v->size;
+ } else if (p_index == CoreStringNames::singleton->end) {
+ return v->size + v->position;
+ }
+ } break;
+ case BASIS: {
+
+ const Basis *v = _data._basis;
+ //scalar name
+ if (p_index == CoreStringNames::singleton->x) {
+ return v->get_axis(0);
+ } else if (p_index == CoreStringNames::singleton->y) {
+ return v->get_axis(1);
+ } else if (p_index == CoreStringNames::singleton->z) {
+ return v->get_axis(2);
+ }
+
+ } break;
+ case TRANSFORM: {
+
+ if (p_index == CoreStringNames::singleton->basis) {
+ return _data._transform->basis;
+ } else if (p_index == CoreStringNames::singleton->origin) {
+ return _data._transform->origin;
+ }
+
+ } break;
+ case COLOR: {
+
+ const Color *v = reinterpret_cast<const Color *>(_data._mem);
+ if (p_index == CoreStringNames::singleton->r) {
+ return v->r;
+ } else if (p_index == CoreStringNames::singleton->g) {
+ return v->g;
+ } else if (p_index == CoreStringNames::singleton->b) {
+ return v->b;
+ } else if (p_index == CoreStringNames::singleton->a) {
+ return v->a;
+ } else if (p_index == CoreStringNames::singleton->r8) {
+ return v->r * 255.0;
+ } else if (p_index == CoreStringNames::singleton->g8) {
+ return v->g * 255.0;
+ } else if (p_index == CoreStringNames::singleton->b8) {
+ return v->b * 255.0;
+ } else if (p_index == CoreStringNames::singleton->a8) {
+ return v->a * 255.0;
+ } else if (p_index == CoreStringNames::singleton->h) {
+ return v->get_h();
+ } else if (p_index == CoreStringNames::singleton->s) {
+ return v->get_s();
+ } else if (p_index == CoreStringNames::singleton->v) {
+ return v->get_v();
+ }
+ } break;
+ case OBJECT: {
+
+#ifdef DEBUG_ENABLED
+ if (!_get_obj().obj) {
if (r_valid)
*r_valid = false;
- return "Attempted use of stray pointer object.";
+ return "Instance base is null.";
+ } else {
+
+ if (ScriptDebugger::get_singleton() && _get_obj().ref.is_null() && !ObjectDB::instance_validate(_get_obj().obj)) {
+ if (r_valid)
+ *r_valid = false;
+ return "Attempted use of stray pointer object.";
+ }
}
- }
#endif
- return _get_obj().obj->get(p_index, r_valid);
+ return _get_obj().obj->get(p_index, r_valid);
+
+ } break;
+ default: {
+ return get(p_index.operator String(), r_valid);
+ }
}
- return get(p_index.operator String(), r_valid);
+ if (r_valid) {
+ *r_valid = false;
+ }
+ return Variant();
}
#define DEFAULT_OP_ARRAY_CMD(m_name, m_type, skip_test, cmd) \
@@ -1512,7 +2200,8 @@ void Variant::set(const Variant &p_index, const Variant &p_value, bool *r_valid)
DEFAULT_OP_DVECTOR_SET(POOL_VECTOR2_ARRAY, Vector2, p_value.type != Variant::VECTOR2) // 25
DEFAULT_OP_DVECTOR_SET(POOL_VECTOR3_ARRAY, Vector3, p_value.type != Variant::VECTOR3)
DEFAULT_OP_DVECTOR_SET(POOL_COLOR_ARRAY, Color, p_value.type != Variant::COLOR)
- default: return;
+ default:
+ return;
}
}
@@ -1885,7 +2574,8 @@ Variant Variant::get(const Variant &p_index, bool *r_valid) const {
DEFAULT_OP_DVECTOR_GET(POOL_VECTOR2_ARRAY, Vector2) // 25
DEFAULT_OP_DVECTOR_GET(POOL_VECTOR3_ARRAY, Vector3)
DEFAULT_OP_DVECTOR_GET(POOL_COLOR_ARRAY, Color)
- default: return Variant();
+ default:
+ return Variant();
}
return Variant();
@@ -2374,7 +3064,8 @@ bool Variant::iter_init(Variant &r_iter, bool &valid) const {
return true;
} break;
- default: {}
+ default: {
+ }
}
valid = false;
@@ -2401,7 +3092,7 @@ bool Variant::iter_next(Variant &r_iter, bool &valid) const {
return true;
} break;
case VECTOR2: {
- int64_t to = reinterpret_cast<const Vector3 *>(_data._mem)->y;
+ int64_t to = reinterpret_cast<const Vector2 *>(_data._mem)->y;
int64_t idx = r_iter;
idx++;
@@ -2793,7 +3484,9 @@ void Variant::blend(const Variant &a, const Variant &b, float c, Variant &r_dst)
r_dst = Color(r, g, b, a);
}
return;
- default: { r_dst = c < 0.5 ? a : b; }
+ default: {
+ r_dst = c < 0.5 ? a : b;
+ }
return;
}
}
diff --git a/doc/Makefile b/doc/Makefile
index 4914c657d2..d68c66f8eb 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -1,5 +1,5 @@
BASEDIR = $(CURDIR)
-CLASSES = $(BASEDIR)/base/classes.xml
+CLASSES = $(BASEDIR)/classes/ $(BASEDIR)/../modules/
OUTPUTDIR = $(BASEDIR)/_build
TOOLSDIR = $(BASEDIR)/tools
diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml
index 52df939fc5..b61cf93ef7 100644
--- a/doc/classes/@GDScript.xml
+++ b/doc/classes/@GDScript.xml
@@ -23,11 +23,11 @@
<argument index="3" name="a8" type="int">
</argument>
<description>
- Returns a 32 bit color with red, green, blue and alpha channels. Each channel has 8bits of information ranging from 0 to 255.
- 'r8' red channel
- 'g8' green channel
- 'b8' blue channel
- 'a8' alpha channel
+ Returns a 32 bit color with red, green, blue and alpha channels. Each channel has 8 bits of information ranging from 0 to 255.
+ [code]r8[/code] red channel
+ [code]g8[/code] green channel
+ [code]b8[/code] blue channel
+ [code]a8[/code] alpha channel
[codeblock]
red = Color8(255, 0, 0)
[/codeblock]
@@ -41,7 +41,7 @@
<argument index="1" name="alpha" type="float">
</argument>
<description>
- Returns color 'name' with alpha ranging from 0 to 1. Note: 'name' is defined in color_names.inc.
+ Returns color [code]name[/code] with [code]alpha[/code] ranging from 0 to 1. Note: [code]name[/code] is defined in color_names.inc.
[codeblock]
red = ColorN('red')
[/codeblock]
@@ -53,7 +53,7 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the absolute value of parameter 's' (i.e. unsigned value, works for integer and float).
+ Returns the absolute value of parameter [code]s[/code] (i.e. unsigned value, works for integer and float).
[codeblock]
# a is 1
a = abs(-1)
@@ -66,7 +66,7 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the arc cosine of 's' in radians. Use to get the angle of cosine 's'.
+ Returns the arc cosine of [code]s[/code] in radians. Use to get the angle of cosine [code]s[/code].
[codeblock]
# c is 0.523599 or 30 degrees if converted with rad2deg(s)
c = acos(0.866025)
@@ -79,10 +79,10 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the arc sine of 's' in radians. Use to get the angle of sine 's'.
+ Returns the arc sine of [code]s[/code] in radians. Use to get the angle of sine [code]s[/code].
[codeblock]
# s is 0.523599 or 30 degrees if converted with rad2deg(s)
- s = asin(0.5)
+ s = asin(0.5)
[/codeblock]
</description>
</method>
@@ -92,6 +92,14 @@
<argument index="0" name="condition" type="bool">
</argument>
<description>
+ Assert that the [code]condition[/code] is true. If the [code]condition[/code] is false a fatal error is generated and the program is halted. Useful for debugging to make sure a value is always true.
+ [codeblock]
+ # Speed should always be between 0 and 20
+ speed = -10
+ assert(speed &lt; 20) # Is true and program continues
+ assert(speed &gt;= 0) # Is false and program stops
+ assert(speed &gt;= 0 &amp;&amp; speed &lt; 20) # Or combined
+ [/codeblock]
</description>
</method>
<method name="atan">
@@ -100,6 +108,11 @@
<argument index="0" name="s" type="float">
</argument>
<description>
+ Returns the arc tangent of [code]s[/code] in radians. Use it to get the angle from an angle's tangent in trigonometry: [code]atan(tan(angle)) == angle[/code].
+ The method cannot know in which quadrant the angle should fall. See [method atan2] if you always want an exact angle.
+ [codeblock]
+ a = atan(0.5) # a is 0.463648
+ [/codeblock]
</description>
</method>
<method name="atan2">
@@ -110,10 +123,9 @@
<argument index="1" name="y" type="float">
</argument>
<description>
- Returns the arc tangent of y/x in radians. Use to get the angle of tangent y/x. To compute the value, the function takes into account the sign of both arguments in order to determine the quadrant.
+ Returns the arc tangent of [code]y/x[/code] in radians. Use to get the angle of tangent [code]y/x[/code]. To compute the value, the method takes into account the sign of both arguments in order to determine the quadrant.
[codeblock]
- # a is 3.141593
- a = atan(0,-1)
+ a = atan(0,-1) # a is 3.141593
[/codeblock]
</description>
</method>
@@ -123,7 +135,7 @@
<argument index="0" name="bytes" type="PoolByteArray">
</argument>
<description>
- Decode a byte array back to a value.
+ Decodes a byte array back to a value.
</description>
</method>
<method name="ceil">
@@ -132,12 +144,10 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Rounds 's' upward, returning the smallest integral value that is not less than 's'.
+ Rounds [code]s[/code] upward, returning the smallest integral value that is not less than [code]s[/code].
[codeblock]
- # i is 2
- i = ceil(1.45)
- # i is 2
- i = ceil(1.001)
+ i = ceil(1.45) # i is 2
+ i = ceil(1.001) # i is 2
[/codeblock]
</description>
</method>
@@ -147,7 +157,7 @@
<argument index="0" name="ascii" type="int">
</argument>
<description>
- Returns a character as String of the given ASCII code.
+ Returns a character as a String of the given ASCII code.
[codeblock]
# a is 'A'
a = char(65)
@@ -166,7 +176,7 @@
<argument index="2" name="max" type="float">
</argument>
<description>
- Clamp 'val' and return a value not less than 'min' and not more than 'max'.
+ Clamps [code]val[/code] and returns a value not less than [code]min[/code] and not more than [code]max[/code].
[codeblock]
speed = 1000
# a is 20
@@ -186,7 +196,7 @@
<argument index="1" name="type" type="int">
</argument>
<description>
- Convert from a type to another in the best way possible. The "type" parameter uses the enum TYPE_* in [@Global Scope].
+ Converts from a type to another in the best way possible. The [code]type[/code] parameter uses the enum TYPE_* in [@Global Scope].
[codeblock]
a = Vector2(1, 0)
# prints 1
@@ -204,7 +214,7 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the cosine of angle 's' in radians.
+ Returns the cosine of angle [code]s[/code] in radians.
[codeblock]
# prints 1 and -1
print(cos(PI*2))
@@ -218,7 +228,7 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the hyperbolic cosine of 's' in radians.
+ Returns the hyperbolic cosine of [code]s[/code] in radians.
[codeblock]
# prints 1.543081
print(cosh(1))
@@ -231,7 +241,7 @@
<argument index="0" name="db" type="float">
</argument>
<description>
- Convert from decibels to linear energy (audio).
+ Converts from decibels to linear energy (audio).
</description>
</method>
<method name="decimals">
@@ -240,7 +250,7 @@
<argument index="0" name="step" type="float">
</argument>
<description>
- Returns the number of digit places after the decimal that the first non-zero digit occurs.
+ Returns the position of the first non-zero digit, after the decimal point.
[codeblock]
# n is 2
n = decimals(0.035)
@@ -257,7 +267,7 @@
<argument index="2" name="step" type="float">
</argument>
<description>
- Returns the result of 'value' decreased by 'step' * 'amount'.
+ Returns the result of [code]value[/code] decreased by [code]step[/code] * [code]amount[/code].
[codeblock]
# a = 59
a = dectime(60, 10, 0.1))
@@ -283,7 +293,7 @@
<argument index="0" name="dict" type="Dictionary">
</argument>
<description>
- Convert a previously converted instance to dictionary back into an instance. Useful for deserializing.
+ Converts a previously converted instance to a dictionary, back into an instance. Useful for deserializing.
</description>
</method>
<method name="ease">
@@ -303,7 +313,10 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns [b]e[/b] raised to the power of 's'. [b]e[/b] sometimes called "Euler's number" is a mathematical constant whose value is approximately 2.71828.
+ Raises the Euler's constant [b]e[/b] to the power of [code]s[/code] and returns it. [b]e[/b] has an approximate value of 2.71828.
+ [codeblock]
+ a = exp(2) # approximately 7.39
+ [/codeblock]
</description>
</method>
<method name="floor">
@@ -312,7 +325,13 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the largest integer value (rounded down) that is less than or equal to 's'.
+ Rounds [code]s[/code] to the closest smaller integer and returns it.
+ [codeblock]
+ # a is 2
+ a = floor(2.99)
+ # a is -3
+ a = floor(-2.99)
+ [/codeblock]
</description>
</method>
<method name="fmod">
@@ -323,11 +342,11 @@
<argument index="1" name="y" type="float">
</argument>
<description>
- Returns the floating-point remainder of x/y (rounded towards zero):
+ Returns the floating-point remainder of [code]x/y[/code].
[codeblock]
- fmod = x - tquot * y
+ # remainder is 1.5
+ var remainder = fmod(7, 5.5)
[/codeblock]
- Where tquot is the truncated (i.e., rounded towards zero) result of: x/y.
</description>
</method>
<method name="fposmod">
@@ -338,6 +357,26 @@
<argument index="1" name="y" type="float">
</argument>
<description>
+ Returns the floating-point remainder of [code]x/y[/code] that wraps equally in positive and negative.
+ [codeblock]
+ var i = -10;
+ while i &lt; 0:
+ prints(i, fposmod(i, 10))
+ i += 1
+ [/codeblock]
+ Produces:
+ [codeblock]
+ -10 10
+ -9 1
+ -8 2
+ -7 3
+ -6 4
+ -5 5
+ -4 6
+ -3 7
+ -2 8
+ -1 9
+ [/codeblock]
</description>
</method>
<method name="funcref">
@@ -348,6 +387,14 @@
<argument index="1" name="funcname" type="String">
</argument>
<description>
+ Returns a reference to the specified function [code]funcname[/code] in the [code]instance[/code] node. As functions aren't first-class objects in GDscript, use [code]funcref[/code] to store a [FuncRef] in a variable and call it later.
+ [codeblock]
+ func foo():
+ return("bar")
+
+ a = funcref(self, "foo")
+ print(a.call_func()) # prints bar
+ [/codeblock]
</description>
</method>
<method name="hash">
@@ -358,8 +405,7 @@
<description>
Returns the integer hash of the variable passed.
[codeblock]
- # print 177670
- print(hash("a"))
+ print(hash("a")) # prints 177670
[/codeblock]
</description>
</method>
@@ -369,7 +415,7 @@
<argument index="0" name="inst" type="Object">
</argument>
<description>
- Returns the passed instance converted a dictionary (useful for serializing).
+ Returns the passed instance converted to a dictionary (useful for serializing).
[codeblock]
var foo = "bar"
func _ready():
@@ -390,15 +436,14 @@
<argument index="0" name="instance_id" type="int">
</argument>
<description>
- Returns the Object that corresponds to 'instance_id'. All Objects have a unique instance ID.
+ Returns the Object that corresponds to [code]instance_id[/code]. All Objects have a unique instance ID.
[codeblock]
var foo = "bar"
func _ready():
var id = get_instance_id()
var inst = instance_from_id(id)
- print(inst.foo)
+ print(inst.foo) # prints bar
[/codeblock]
- Prints "bar"
</description>
</method>
<method name="inverse_lerp">
@@ -413,7 +458,7 @@
<description>
Returns a normalized value considering the given range.
[codeblock]
- inverse_lerp(3, 5, 4) # return 0.5
+ inverse_lerp(3, 5, 4) # returns 0.5
[/codeblock]
</description>
</method>
@@ -423,7 +468,7 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns True/False whether 's' is an infinity value (either positive infinity or negative infinity).
+ Returns True/False whether [code]s[/code] is an infinity value (either positive infinity or negative infinity).
</description>
</method>
<method name="is_nan">
@@ -432,7 +477,7 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns True/False whether 's' is a NaN (Not-A-Number) value.
+ Returns True/False whether [code]s[/code] is a NaN (Not-A-Number) value.
</description>
</method>
<method name="len">
@@ -441,12 +486,11 @@
<argument index="0" name="var" type="Variant">
</argument>
<description>
- Returns length of Variant 'var'. Length is the character count of String, element count of Array, size of Dictionary, etc. Note: Generates a fatal error if Variant can not provide a length.
+ Returns length of Variant [code]var[/code]. Length is the character count of String, element count of Array, size of Dictionary, etc. Note: Generates a fatal error if Variant can not provide a length.
[codeblock]
a = [1, 2, 3, 4]
- print(len(a))
+ len(a) # returns 4
[/codeblock]
- Prints 4
</description>
</method>
<method name="lerp">
@@ -459,7 +503,10 @@
<argument index="2" name="weight" type="float">
</argument>
<description>
- Linear interpolates between two values by a normalized value.
+ Linearly interpolates between two values by a normalized value.
+ [codeblock]
+ lerp(1, 3, 0.5) # returns 2
+ [/codeblock]
</description>
</method>
<method name="linear2db">
@@ -468,7 +515,7 @@
<argument index="0" name="nrg" type="float">
</argument>
<description>
- Convert from linear energy to decibels (audio).
+ Converts from linear energy to decibels (audio).
</description>
</method>
<method name="load">
@@ -477,7 +524,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Load a resource from the filesystem located at 'path'. Note: resource paths can be obtained by right clicking on a resource in the Assets Pannel and choosing "Copy Path".
+ Loads a resource from the filesystem located at 'path'. Note: resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path".
[codeblock]
# load a scene called main located in the root of the project directory
var main = load("res://main.tscn")
@@ -490,10 +537,9 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Natural logarithm. The amount of time needed to reach a certain level of continuous growth. Note: This is not the same as the log funcation on your calculator which is a base 10 logarithm.
+ Natural logarithm. The amount of time needed to reach a certain level of continuous growth. Note: This is not the same as the log function on your calculator which is a base 10 logarithm.
[codeblock]
- # a is 2.302585
- a = log(10)
+ log(10) # returns 2.302585
[/codeblock]
</description>
</method>
@@ -507,10 +553,8 @@
<description>
Returns the maximum of two values.
[codeblock]
- # a is 2
- a = max(1,2)
- # a is -3.99
- a = max(-3.99, -4)
+ max(1,2) # returns 2
+ max(-3.99, -4) # returns -3.99
[/codeblock]
</description>
</method>
@@ -524,10 +568,8 @@
<description>
Returns the minimum of two values.
[codeblock]
- # a is 1
- a = min(1,2)
- # a is -4
- a = min(-3.99, -4)
+ min(1,2) # returns 1
+ min(-3.99, -4) # returns -4
[/codeblock]
</description>
</method>
@@ -537,14 +579,11 @@
<argument index="0" name="val" type="int">
</argument>
<description>
- Returns the nearest larger power of 2 for an integer.
+ Returns the nearest larger power of 2 for integer [code]val[/code].
[codeblock]
- # a is 4
- a = nearest_po2(3)
- # a is 4
- a = nearest_po2(4)
- # a is 8
- a = nearest_po2(5)
+ nearest_po2(3) # returns 4
+ nearest_po2(4) # returns 4
+ nearest_po2(5) # returns 8
[/codeblock]
</description>
</method>
@@ -555,11 +594,11 @@
</argument>
<description>
Parse JSON text to a Variant (use [method typeof] to check if it is what you expect).
- Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert every numerical values to [float] types.
+ Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert all numerical values to [float] types.
[codeblock]
p = parse_json('["a", "b", "c"]')
if typeof(p) == TYPE_ARRAY:
- print(p[0])
+ print(p[0]) # prints a
else:
print("unexpected results")
[/codeblock]
@@ -573,10 +612,9 @@
<argument index="1" name="y" type="float">
</argument>
<description>
- Returns the result of 'x' raised to the power of 'y'.
+ Returns the result of [code]x[/code] raised to the power of [code]y[/code].
[codeblock]
- # a is 32
- a = pow(2,5)
+ pow(2,5) # returns 32
[/codeblock]
</description>
</method>
@@ -586,10 +624,11 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Returns a resource from the filesystem that is loaded during script parsing. Note: resource paths can be obtained by right clicking on a resource in the Assets Pannel and choosing "Copy Path".
+ Returns a resource from the filesystem that is loaded during script parsing. Note: resource paths can be obtained by right clicking on a resource in the Assets Panel and choosing "Copy Path".
[codeblock]
# load a scene called main located in the root of the project directory
var main = preload("res://main.tscn")
+ [/codeblock]
</description>
</method>
<method name="print" qualifiers="vararg">
@@ -599,44 +638,61 @@
Converts one or more arguments to strings in the best way possible and prints them to the console.
[codeblock]
a = [1,2,3]
- print("a","b",a)
+ print("a","b",a) # prints ab[1, 2, 3]
[/codeblock]
- Prints ab[1, 2, 3]
</description>
</method>
<method name="print_stack">
<return type="void">
</return>
<description>
- Print a stack track at code location, only works when running with debugger turned on.
+ Prints a stack track at code location, only works when running with debugger turned on.
+ Output in the console would look something like this:
+ [codeblock]
+ Frame 0 - res://test.gd:16 in function '_process'
+ [/codeblock]
</description>
</method>
<method name="printerr" qualifiers="vararg">
<return type="void">
</return>
<description>
- Print one or more arguments to strings in the best way possible to standard error line.
+ Prints one or more arguments to strings in the best way possible to standard error line.
+ [codeblock]
+ printerr("prints to stderr")
+ [/codeblock]
</description>
</method>
<method name="printraw" qualifiers="vararg">
<return type="void">
</return>
<description>
- Print one or more arguments to strings in the best way possible to console. No newline is added at the end.
+ Prints one or more arguments to strings in the best way possible to console. No newline is added at the end.
+ [codeblock]
+ printraw("A")
+ printraw("B")
+ # prints AB
+ [/codeblock]
</description>
</method>
<method name="prints" qualifiers="vararg">
<return type="void">
</return>
<description>
- Print one or more arguments to the console with a space between each argument.
+ Prints one or more arguments to the console with a space between each argument.
+ [codeblock]
+ prints("A", "B", "C") # prints A B C
+ [/codeblock]
</description>
</method>
<method name="printt" qualifiers="vararg">
<return type="void">
</return>
<description>
- Print one or more arguments to the console with a tab between each argument.
+ Prints one or more arguments to the console with a tab between each argument.
+ [codeblock]
+ printt("A", "B", "C") # prints A B C
+ [/codeblock]
</description>
</method>
<method name="rad2deg">
@@ -645,7 +701,10 @@
<argument index="0" name="rad" type="float">
</argument>
<description>
- Convert from radians to degrees.
+ Converts from radians to degrees.
+ [codeblock]
+ rad2deg(0.523599) # returns 30
+ [/codeblock]
</description>
</method>
<method name="rand_range">
@@ -656,7 +715,10 @@
<argument index="1" name="to" type="float">
</argument>
<description>
- Random range, any floating point value between 'from' and 'to'.
+ Random range, any floating point value between [code]from[/code] and [code]to[/code].
+ [codeblock]
+ prints(rand_range(0, 1), rand_range(0, 1)) # prints 0.135591 0.405263
+ [/codeblock]
</description>
</method>
<method name="rand_seed">
@@ -665,35 +727,70 @@
<argument index="0" name="seed" type="int">
</argument>
<description>
- Random from seed: pass a seed, and an array with both number and new seed is returned. "Seed" here refers to the internal state of the pseudo random number generator. The internal state of the current implementation is 64 bits.
+ Random from seed: pass a [code]seed[/code], and an array with both number and new seed is returned. "Seed" here refers to the internal state of the pseudo random number generator. The internal state of the current implementation is 64 bits.
</description>
</method>
<method name="randf">
<return type="float">
</return>
<description>
- Return a random floating point value between 0 and 1.
+ Returns a random floating point value between 0 and 1.
+ [codeblock]
+ randf() # returns 0.375671
+ [/codeblock]
</description>
</method>
<method name="randi">
<return type="int">
</return>
<description>
- Return a random 32 bits integer value. To obtain a random value between 0 to N (where N is smaller than 2^32 - 1), you can use remainder. For example, to get a random integer between 0 and 19 inclusive, you can use randi() % 20.
+ Returns a random 32 bit integer. Use remainder to obtain a random value between 0 and N (where N is smaller than 2^32 -1).
+ [codeblock]
+ randi() % 20 # returns random number between 0 and 19
+ randi() % 100 # returns random number between 0 and 99
+ randi() % 100 + 1 # returns random number between 1 and 100
+ [/codeblock]
</description>
</method>
<method name="randomize">
<return type="void">
</return>
<description>
- Randomize the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time.
+ Randomizes the seed (or the internal state) of the random number generator. Current implementation reseeds using a number based on time.
+ [codeblock]
+ func _ready():
+ randomize()
+ [/codeblock]
</description>
</method>
<method name="range" qualifiers="vararg">
<return type="Array">
</return>
<description>
- Return an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial, final-1, increment).
+ Returns an array with the given range. Range can be 1 argument N (0 to N-1), two arguments (initial, final-1) or three arguments (initial, final-1, increment).
+ [codeblock]
+ for i in range(4):
+ print(i)
+ for i in range(2, 5):
+ print(i)
+ for i in range(0, 6, 2):
+ print(i)
+ [/codeblock]
+ Output:
+ [codeblock]
+ 0
+ 1
+ 2
+ 3
+
+ 2
+ 3
+ 4
+
+ 0
+ 2
+ 4
+ [/codeblock]
</description>
</method>
<method name="range_lerp">
@@ -710,7 +807,7 @@
<argument index="4" name="ostop" type="float">
</argument>
<description>
- Maps a value from range [istart, istop] to [ostart, ostop].
+ Maps a [code]value[/code] from range [code][istart, istop][/code] to [code][ostart, ostop][/code].
[codeblock]
range_lerp(75, 0, 100, -1, 1) # returns 0.5
[/codeblock]
@@ -722,7 +819,10 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the integral value that is nearest to s, with halfway cases rounded away from zero.
+ Returns the integral value that is nearest to [code]s[/code], with halfway cases rounded away from zero.
+ [codeblock]
+ round(2.6) # returns 3
+ [/codeblock]
</description>
</method>
<method name="seed">
@@ -731,7 +831,11 @@
<argument index="0" name="seed" type="int">
</argument>
<description>
- Set seed for the random number generator.
+ Sets seed for the random number generator.
+ [codeblock]
+ my_seed = "Godot Rocks"
+ seed(my_seed.hash())
+ [/codeblock]
</description>
</method>
<method name="sign">
@@ -740,7 +844,11 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Return sign (-1 or +1).
+ Returns sign of [code]s[/code] -1 or 1.
+ [codeblock]
+ sign(-6) # returns -1
+ sign(6) # returns 1
+ [/codeblock]
</description>
</method>
<method name="sin">
@@ -749,7 +857,10 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the sine of an angle of s radians.
+ Returns the sine of angle [code]s[/code] in radians.
+ [codeblock]
+ sin(0.523599) # returns 0.5
+ [/codeblock]
</description>
</method>
<method name="sinh">
@@ -758,7 +869,11 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the hyperbolic sine of s.
+ Returns the hyperbolic sine of [code]s[/code].
+ [codeblock]
+ a = log(2.0) # returns 0.693147
+ sinh(a) # returns 0.75
+ [/codeblock]
</description>
</method>
<method name="sqrt">
@@ -767,7 +882,10 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the square root of s.
+ Returns the square root of [code]s[/code].
+ [codeblock]
+ sqrt(9) # returns 3
+ [/codeblock]
</description>
</method>
<method name="stepify">
@@ -778,14 +896,20 @@
<argument index="1" name="step" type="float">
</argument>
<description>
- Snap float value to a given step.
+ Snaps float value [code]s[/code] to a given [code]step[/code].
</description>
</method>
<method name="str" qualifiers="vararg">
<return type="String">
</return>
<description>
- Convert one or more arguments to string in the best way possible.
+ Converts one or more arguments to string in the best way possible.
+ [codeblock]
+ var a = [10, 20, 30]
+ var b = str(a);
+ len(a) # returns 3
+ len(b) # returns 12
+ [/codeblock]
</description>
</method>
<method name="str2var">
@@ -794,7 +918,12 @@
<argument index="0" name="string" type="String">
</argument>
<description>
- Convert a formatted string that was returned by [method var2str] to the original value.
+ Converts a formatted string that was returned by [method var2str] to the original value.
+ [codeblock]
+ a = '{ "a": 1, "b": 2 }'
+ b = str2var(a)
+ print(b['a']) # prints 1
+ [/codeblock]
</description>
</method>
<method name="tan">
@@ -803,7 +932,10 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the tangent of an angle of s radians.
+ Returns the tangent of angle [code]s[/code] in radians.
+ [codeblock]
+ tan( deg2rad(45) ) # returns 1
+ [/codeblock]
</description>
</method>
<method name="tanh">
@@ -812,7 +944,11 @@
<argument index="0" name="s" type="float">
</argument>
<description>
- Returns the hyperbolic tangent of s.
+ Returns the hyperbolic tangent of [code]s[/code].
+ [codeblock]
+ a = log(2.0) # returns 0.693147
+ tanh(a) # returns 0.6
+ [/codeblock]
</description>
</method>
<method name="to_json">
@@ -821,7 +957,12 @@
<argument index="0" name="var" type="Variant">
</argument>
<description>
- Convert a Variant to json text.
+ Converts a Variant [code]var[/code] to JSON text and return the result. Useful for serializing data to store or send over the network.
+ [codeblock]
+ a = { 'a': 1, 'b': 2 }
+ b = to_json(a)
+ print(b) # {"a":1, "b":2}
+ [/codeblock]
</description>
</method>
<method name="type_exists">
@@ -830,7 +971,7 @@
<argument index="0" name="type" type="String">
</argument>
<description>
- Returns whether the given class is exist in [ClassDB].
+ Returns whether the given class exists in [ClassDB].
[codeblock]
type_exists("Sprite") # returns true
type_exists("Variant") # returns false
@@ -843,7 +984,14 @@
<argument index="0" name="what" type="Variant">
</argument>
<description>
- Return the internal type of the given Variant object, using the TYPE_* enum in [@Global Scope].
+ Returns the internal type of the given Variant object, using the TYPE_* enum in [@Global Scope].
+ [codeblock]
+ p = parse_json('["a", "b", "c"]')
+ if typeof(p) == TYPE_ARRAY:
+ print(p[0]) # prints a
+ else:
+ print("unexpected results")
+ [/codeblock]
</description>
</method>
<method name="validate_json">
@@ -852,7 +1000,15 @@
<argument index="0" name="json" type="String">
</argument>
<description>
- This method is used to validate the structure and data types of a piece of JSON, similar to XML Schema for XML.
+ Checks that [code]json[/code] is valid JSON data. Returns empty string if valid. Returns error message if not valid.
+ [codeblock]
+ j = to_json([1, 2, 3])
+ v = validate_json(j)
+ if not v:
+ print("valid")
+ else:
+ prints("invalid", v)
+ [/codeblock]
</description>
</method>
<method name="var2bytes">
@@ -861,7 +1017,7 @@
<argument index="0" name="var" type="Variant">
</argument>
<description>
- Encode a variable value to a byte array.
+ Encodes a variable value to a byte array.
</description>
</method>
<method name="var2str">
@@ -870,7 +1026,18 @@
<argument index="0" name="var" type="Variant">
</argument>
<description>
- Convert a value to a formatted string that can later be parsed using [method str2var].
+ Converts a Variant [code]var[/code] to a formatted string that can later be parsed using [method str2var].
+ [codeblock]
+ a = { 'a': 1, 'b': 2 }
+ print(var2str(a))
+ [/codeblock]
+ prints
+ [codeblock]
+ {
+ "a": 1,
+ "b": 2
+ }
+ [/codeblock]
</description>
</method>
<method name="weakref">
@@ -879,7 +1046,7 @@
<argument index="0" name="obj" type="Object">
</argument>
<description>
- Return a weak reference to an object.
+ Returns a weak reference to an object.
A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it.
</description>
</method>
@@ -891,7 +1058,7 @@
<argument index="1" name="signal" type="String">
</argument>
<description>
- Stop the function execution and return the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state.
+ Stops the function execution and returns the current state. Call [method GDFunctionState.resume] on the state to resume execution. This invalidates the state.
Returns anything that was passed to the resume function call. If passed an object and a signal, the execution is resumed when the object's signal is emitted.
</description>
</method>
diff --git a/doc/classes/@Global Scope.xml b/doc/classes/@Global Scope.xml
index 4044c4ed1f..d8c9a57a88 100644
--- a/doc/classes/@Global Scope.xml
+++ b/doc/classes/@Global Scope.xml
@@ -38,6 +38,8 @@
<member name="InputMap" type="InputMap" setter="" getter="">
[InputMap] singleton
</member>
+ <member name="JSON" type="JSON" setter="" getter="">
+ </member>
<member name="Marshalls" type="Reference" setter="" getter="">
[Marshalls] singleton
</member>
@@ -1011,7 +1013,7 @@
</constant>
<constant name="ERR_TIMEOUT" value="24">
</constant>
- <constant name="ERR_CANT_AQUIRE_RESOURCE" value="28">
+ <constant name="ERR_CANT_ACQUIRE_RESOURCE" value="28">
</constant>
<constant name="ERR_INVALID_DATA" value="30">
</constant>
diff --git a/doc/classes/AStar.xml b/doc/classes/AStar.xml
index d94b8355ba..9b15afbbd4 100644
--- a/doc/classes/AStar.xml
+++ b/doc/classes/AStar.xml
@@ -39,7 +39,7 @@
</return>
<argument index="0" name="id" type="int">
</argument>
- <argument index="1" name="pos" type="Vector3">
+ <argument index="1" name="position" type="Vector3">
</argument>
<argument index="2" name="weight_scale" type="float" default="1.0">
</argument>
@@ -113,19 +113,19 @@
<method name="get_closest_point" qualifiers="const">
<return type="int">
</return>
- <argument index="0" name="to_pos" type="Vector3">
+ <argument index="0" name="to_position" type="Vector3">
</argument>
<description>
- Returns the id of the closest point to [code]to_pos[/code]. Returns -1 if there are no points in the points pool.
+ Returns the id of the closest point to [code]to_position[/code]. Returns -1 if there are no points in the points pool.
</description>
</method>
- <method name="get_closest_pos_in_segment" qualifiers="const">
+ <method name="get_closest_position_in_segment" qualifiers="const">
<return type="Vector3">
</return>
- <argument index="0" name="to_pos" type="Vector3">
+ <argument index="0" name="to_position" type="Vector3">
</argument>
<description>
- Returns the closest position to [code]to_pos[/code] that resides inside a segment between two connected points.
+ Returns the closest position to [code]to_position[/code] that resides inside a segment between two connected points.
[codeblock]
var as = AStar.new()
@@ -134,7 +134,7 @@
as.connect_points(1, 2)
- var res = as.get_closest_pos_in_segment(Vector3(3,3,0)) # returns (0, 3, 0)
+ var res = as.get_closest_position_in_segment(Vector3(3,3,0)) # returns (0, 3, 0)
[/codeblock]
The result is in the segment that goes from [code]y=0[/code] to [code]y=5[/code]. It's the closest position in the segment to the given point.
</description>
@@ -178,7 +178,7 @@
Returns an array with the points that are in the path found by AStar between the given points. The array is ordered from the starting point to the ending point of the path.
</description>
</method>
- <method name="get_point_pos" qualifiers="const">
+ <method name="get_point_position" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="id" type="int">
diff --git a/doc/classes/AcceptDialog.xml b/doc/classes/AcceptDialog.xml
index 8821a450e5..4244e66a35 100644
--- a/doc/classes/AcceptDialog.xml
+++ b/doc/classes/AcceptDialog.xml
@@ -21,8 +21,8 @@
<argument index="2" name="action" type="String" default="&quot;&quot;">
</argument>
<description>
- Add custom button to the dialog and return the created button.
- The button titled with [i]text[/i] and the [i]action[/i] will be passed to [custom_action] signal when it is pressed.
+ Adds a button with label [i]text[/i] and a custom [i]action[/i] to the dialog and returns the created button. [i]action[/i] will be passed to the [custom_action] signal when pressed.
+ If [code]true[/code], [i]right[/i] will place the button to the right of any sibling buttons. Default value: [code]false[/code].
</description>
</method>
<method name="add_cancel">
@@ -31,7 +31,7 @@
<argument index="0" name="name" type="String">
</argument>
<description>
- Add custom cancel button to the dialog and return the created button.
+ Adds a button with label [i]name[/i] and a cancel action to the dialog and returns the created button.
</description>
</method>
<method name="get_hide_on_ok" qualifiers="const">
@@ -68,7 +68,7 @@
<argument index="0" name="line_edit" type="Node">
</argument>
<description>
- Register a [LineEdit] in the dialog. When the enter key is pressed, the dialog will be accepted.
+ Registers a [LineEdit] in the dialog. When the enter key is pressed, the dialog will be accepted.
</description>
</method>
<method name="set_hide_on_ok">
@@ -99,14 +99,14 @@
<signals>
<signal name="confirmed">
<description>
- Emitted when accepted.
+ Emitted when the dialog is accepted.
</description>
</signal>
<signal name="custom_action">
<argument index="0" name="action" type="String">
</argument>
<description>
- Emitted with a custom button is added.
+ Emitted when a custom button is pressed. See [method add_button].
</description>
</signal>
</signals>
diff --git a/doc/classes/AnimatedSprite.xml b/doc/classes/AnimatedSprite.xml
index f8663e90e0..809890bea1 100644
--- a/doc/classes/AnimatedSprite.xml
+++ b/doc/classes/AnimatedSprite.xml
@@ -4,7 +4,7 @@
Sprite node that can use multiple textures for animation.
</brief_description>
<description>
- Sprite node that can use multiple textures for animation.
+ Sprite node that can use multiple textures for animation. Animations are created using a [SpriteFrames] resource, which can be configured in the editor via the SpriteFrames panel.
</description>
<tutorials>
</tutorials>
@@ -149,31 +149,39 @@
</methods>
<members>
<member name="animation" type="String" setter="set_animation" getter="get_animation">
+ The current animation from the [code]frames[/code] resource. If this value is changed, the [code]frame[/code] counter is reset.
</member>
<member name="centered" type="bool" setter="set_centered" getter="is_centered">
+ If [code]true[/code] texture will be centered. Default value: [code]true[/code].
</member>
<member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h">
+ If [code]true[/code] texture is flipped horizontally. Default value: [code]false[/code].
</member>
<member name="flip_v" type="bool" setter="set_flip_v" getter="is_flipped_v">
+ If [code]true[/code] texture is flipped vertically. Default value: [code]false[/code].
</member>
<member name="frame" type="int" setter="set_frame" getter="get_frame">
+ The current frame index.
</member>
<member name="frames" type="SpriteFrames" setter="set_sprite_frames" getter="get_sprite_frames">
+ The [SpriteFrames] resource containing the animation(s).
</member>
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset">
+ The texture's drawing offset.
</member>
<member name="playing" type="bool" setter="_set_playing" getter="_is_playing">
+ If [code]true[/code] the [code]animation[/code] is currently playing.
</member>
</members>
<signals>
<signal name="animation_finished">
<description>
- Emitted when the animation is finished (when it plays the last frame). If the animation is looping, this signal is emitted every time the last frame is drawn, before looping.
+ Emitted when the animation is finished (when it plays the last frame). If the animation is looping, this signal is emitted every time the last frame is drawn.
</description>
</signal>
<signal name="frame_changed">
<description>
- Emitted when frame is changed.
+ Emitted when [code]frame[/code] changes.
</description>
</signal>
</signals>
diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml
index b80edb24da..d853345268 100644
--- a/doc/classes/Animation.xml
+++ b/doc/classes/Animation.xml
@@ -17,7 +17,7 @@
</return>
<argument index="0" name="type" type="int" enum="Animation.TrackType">
</argument>
- <argument index="1" name="at_pos" type="int" default="-1">
+ <argument index="1" name="at_position" type="int" default="-1">
</argument>
<description>
Add a track to the Animation. The track type must be specified as any of the values in the TYPE_* enumeration.
@@ -281,12 +281,12 @@
Remove a key by index in a given track.
</description>
</method>
- <method name="track_remove_key_at_pos">
+ <method name="track_remove_key_at_position">
<return type="void">
</return>
<argument index="0" name="idx" type="int">
</argument>
- <argument index="1" name="pos" type="float">
+ <argument index="1" name="position" type="float">
</argument>
<description>
Remove a key by position (seconds) in a given track.
@@ -368,9 +368,9 @@
</argument>
<argument index="1" name="time" type="float">
</argument>
- <argument index="2" name="loc" type="Vector3">
+ <argument index="2" name="location" type="Vector3">
</argument>
- <argument index="3" name="rot" type="Quat">
+ <argument index="3" name="rotation" type="Quat">
</argument>
<argument index="4" name="scale" type="Vector3">
</argument>
diff --git a/doc/classes/AnimationPlayer.xml b/doc/classes/AnimationPlayer.xml
index 746462380b..74a7f6c8a4 100644
--- a/doc/classes/AnimationPlayer.xml
+++ b/doc/classes/AnimationPlayer.xml
@@ -129,7 +129,7 @@
Get the length (in seconds) of the currently being played animation.
</description>
</method>
- <method name="get_current_animation_pos" qualifiers="const">
+ <method name="get_current_animation_position" qualifiers="const">
<return type="float">
</return>
<description>
@@ -143,7 +143,7 @@
Return the default blend time between animations.
</description>
</method>
- <method name="get_pos" qualifiers="const">
+ <method name="get_position" qualifiers="const">
<return type="float">
</return>
<description>
@@ -245,7 +245,7 @@
<method name="seek">
<return type="void">
</return>
- <argument index="0" name="pos_sec" type="float">
+ <argument index="0" name="seconds" type="float">
</argument>
<argument index="1" name="update" type="bool" default="false">
</argument>
diff --git a/doc/classes/AnimationTreePlayer.xml b/doc/classes/AnimationTreePlayer.xml
index e128b4d865..f088d21e41 100644
--- a/doc/classes/AnimationTreePlayer.xml
+++ b/doc/classes/AnimationTreePlayer.xml
@@ -271,7 +271,7 @@
Return the input source for a given node input.
</description>
</method>
- <method name="node_get_pos" qualifiers="const">
+ <method name="node_get_position" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="id" type="String">
@@ -300,12 +300,12 @@
Rename a node in the graph.
</description>
</method>
- <method name="node_set_pos">
+ <method name="node_set_position">
<return type="void">
</return>
<argument index="0" name="id" type="String">
</argument>
- <argument index="1" name="screen_pos" type="Vector2">
+ <argument index="1" name="screen_position" type="Vector2">
</argument>
<description>
Sets position of a node in the graph given its name and position.
@@ -531,7 +531,7 @@
</return>
<argument index="0" name="id" type="String">
</argument>
- <argument index="1" name="pos_sec" type="float">
+ <argument index="1" name="seconds" type="float">
</argument>
<description>
Sets time seek value of a TimeSeek node given its name and value.
diff --git a/doc/classes/Area.xml b/doc/classes/Area.xml
index c59bbee084..8797575038 100644
--- a/doc/classes/Area.xml
+++ b/doc/classes/Area.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Area" inherits="CollisionObject" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- General purpose area detection and influence for 3D physics.
+ General purpose area node for detection and 3D physics influence.
</brief_description>
<description>
- General purpose area detection for 3D physics. Areas can be used for detection of objects that enter/exit them, as well as overriding space parameters (changing gravity, damping, etc). For this, use any space override different from AREA_SPACE_OVERRIDE_DISABLE and point gravity at the center of mass.
+ 3D area that detects [CollisionObject] nodes overlapping, entering, or exiting. Can also alter or override local physics parameters (gravity, damping).
</description>
<tutorials>
</tutorials>
@@ -88,14 +88,14 @@
<return type="Array">
</return>
<description>
- Return a list of the areas that are totally or partially inside this area.
+ Returns a list of intersecting [Area]\ s.
</description>
</method>
<method name="get_overlapping_bodies" qualifiers="const">
<return type="Array">
</return>
<description>
- Return a list of the bodies ([PhysicsBody]) that are totally or partially inside this area.
+ Returns a list of intersecting [PhysicsBody]\ s.
</description>
</method>
<method name="get_priority" qualifiers="const">
@@ -169,7 +169,7 @@
<argument index="0" name="area" type="Node">
</argument>
<description>
- Return whether the area passed is totally or partially inside this area.
+ If [code]true[/code] the given area overlaps the Area.
</description>
</method>
<method name="overlaps_body" qualifiers="const">
@@ -178,7 +178,7 @@
<argument index="0" name="body" type="Node">
</argument>
<description>
- Return whether the body passed is totally or partially inside this area.
+ If [code]true[/code] the given body overlaps the Area.
</description>
</method>
<method name="set_angular_damp">
@@ -374,30 +374,43 @@
</methods>
<members>
<member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp">
+ The rate at which objects stop spinning in this area. Represents the angular velocity lost per second. Values range from [code]0[/code] (no damping) to [code]1[/code] (full damping).
</member>
<member name="audio_bus_name" type="String" setter="set_audio_bus" getter="get_audio_bus">
+ The name of the area's audio bus.
</member>
<member name="audio_bus_override" type="bool" setter="set_audio_bus_override" getter="is_overriding_audio_bus">
+ If [code]true[/code] the area's audio bus overrides the default audio bus. Default value: [code]false[/code].
</member>
<member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer">
+ The area's physics layer(s). Collidable objects can exist in any of 32 different layers. A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See also [code]collision_mask[/code].
</member>
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask">
+ The physics layers this area scans to determine collision detection.
</member>
<member name="gravity" type="float" setter="set_gravity" getter="get_gravity">
+ The area's gravity intensity (ranges from -1024 to 1024). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction.
</member>
<member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale">
+ The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance.
</member>
<member name="gravity_point" type="bool" setter="set_gravity_is_point" getter="is_gravity_a_point">
+ If [code]true[/code] gravity is calculated from a point (set via [code]gravity_vec[/code]). Also see [code]space_override[/code]. Default value: [code]false[/code].
</member>
<member name="gravity_vec" type="Vector3" setter="set_gravity_vector" getter="get_gravity_vector">
+ The area's gravity vector (not normalized). If gravity is a point (see [method is_gravity_a_point]), this will be the point of attraction.
</member>
<member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp">
+ The rate at which objects stop moving in this area. Represents the linear velocity lost per second. Values range from [code]0[/code] (no damping) to [code]1[/code] (full damping).
</member>
<member name="monitorable" type="bool" setter="set_monitorable" getter="is_monitorable">
+ If [code]true[/code] other monitoring areas can detect this area. Default value: [code]true[/code].
</member>
<member name="monitoring" type="bool" setter="set_monitoring" getter="is_monitoring">
+ If [code]true[/code] the area detects bodies or areas entering and exiting it. Default value: [code]true[/code].
</member>
<member name="priority" type="float" setter="set_priority" getter="get_priority">
+ The area's priority. Higher priority areas are processed first. Default value: 0.
</member>
<member name="reverb_bus_amount" type="float" setter="set_reverb_amount" getter="get_reverb_amount">
</member>
@@ -408,6 +421,7 @@
<member name="reverb_bus_uniformity" type="float" setter="set_reverb_uniformity" getter="get_reverb_uniformity">
</member>
<member name="space_override" type="int" setter="set_space_override_mode" getter="get_space_override_mode" enum="Area.SpaceOverride">
+ Override mode for gravity and damping calculations within this area. See the SPACE_OVERRIDE_* constants for values.
</member>
</members>
<signals>
@@ -415,14 +429,14 @@
<argument index="0" name="area" type="Object">
</argument>
<description>
- This signal is triggered only once when an area enters this area. The only parameter passed is the area that entered this area.
+ Emitted when another area enters.
</description>
</signal>
<signal name="area_exited">
<argument index="0" name="area" type="Object">
</argument>
<description>
- This signal is triggered only once when an area exits this area. The only parameter passed is the area that exited this area.
+ Emitted when another area exits.
</description>
</signal>
<signal name="area_shape_entered">
@@ -435,7 +449,7 @@
<argument index="3" name="self_shape" type="int">
</argument>
<description>
- This signal triggers only once when an area enters this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering.
+ Emitted when another area enters, reporting which areas overlapped.
</description>
</signal>
<signal name="area_shape_exited">
@@ -448,21 +462,21 @@
<argument index="3" name="self_shape" type="int">
</argument>
<description>
- This signal triggers only once when an area exits this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering.
+ Emitted when another area exits, reporting which areas were overlapping.
</description>
</signal>
<signal name="body_entered">
<argument index="0" name="body" type="Object">
</argument>
<description>
- This signal is triggered only once when a body enters this area. The only parameter passed is the body that entered this area.
+ Emitted when a [PhysicsBody] object enters.
</description>
</signal>
<signal name="body_exited">
<argument index="0" name="body" type="Object">
</argument>
<description>
- This signal is triggered only once when a body exits this area. The only parameter passed is the body that exited this area.
+ Emitted when a [PhysicsBody2D] object exits.
</description>
</signal>
<signal name="body_shape_entered">
@@ -475,7 +489,7 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
- This signal triggers only once when a body enters this area. The first parameter is the body's [RID]. The second one is the body as an object. The third one is the index of the shape of the body that entered this area, and the fourth one is the index of the shape in this area that reported the entering.
+ Emitted when a [PhysicsBody2D] object enters, reporting which shapes overlapped.
</description>
</signal>
<signal name="body_shape_exited">
@@ -488,20 +502,25 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
- This signal triggers only once when a body exits this area. The first parameter is the body's [RID]. The second one is the body as an object. The third one is the index of the shape exiting this area, and the fourth one is the index of the shape in this area that reported the exit.
+ Emitted when a [PhysicsBody2D] object exits, reporting which shapes were overlapping.
</description>
</signal>
</signals>
<constants>
<constant name="SPACE_OVERRIDE_DISABLED" value="0">
+ This area does not affect gravity/damping.
</constant>
<constant name="SPACE_OVERRIDE_COMBINE" value="1">
+ This area adds its gravity/damping values to whatever has been calculated so far (in [code]priority[/code] order).
</constant>
<constant name="SPACE_OVERRIDE_COMBINE_REPLACE" value="2">
+ This area adds its gravity/damping values to whatever has been calculated so far (in [code]priority[/code] order), ignoring any lower priority areas.
</constant>
<constant name="SPACE_OVERRIDE_REPLACE" value="3">
+ This area replaces any gravity/damping, even the defaults, ignoring any lower priority areas.
</constant>
<constant name="SPACE_OVERRIDE_REPLACE_COMBINE" value="4">
+ This area replaces any gravity/damping calculated so far (in [code]priority[/code] order), but keeps calculating the rest of the areas.
</constant>
</constants>
</class>
diff --git a/doc/classes/Area2D.xml b/doc/classes/Area2D.xml
index e093b5cb49..0cbc079962 100644
--- a/doc/classes/Area2D.xml
+++ b/doc/classes/Area2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Area2D" inherits="CollisionObject2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- 2D area that detects nodes that enter or exit it. Can override 2D physics properties within range.
+ 2D area for detection and 2D physics influence.
</brief_description>
<description>
- 2D area that detects nodes that enter or exit it. Change the 'space_override' property SPACE_OVERRIDE_* to override physics parameters for nodes like [Rigidbody2D]. E.g. gravity, damping... See [CollisionObject2D] for usage.
+ 2D area that detects [CollisionObject2D] nodes overlapping, entering, or exiting. Can also alter or override local physics parameters (gravity, damping).
</description>
<tutorials>
</tutorials>
@@ -18,7 +18,7 @@
Return the angular damp rate.
</description>
</method>
- <method name="get_audio_bus" qualifiers="const">
+ <method name="get_audio_bus_name" qualifiers="const">
<return type="String">
</return>
<description>
@@ -88,14 +88,14 @@
<return type="Array">
</return>
<description>
- Returns a list of the [Area2D]s that intersect with this area.
+ Returns a list of intersecting [Area2D]\ s.
</description>
</method>
<method name="get_overlapping_bodies" qualifiers="const">
<return type="Array">
</return>
<description>
- Return a list of the [PhysicsBody2D]s that intersect with this area.
+ Returns a list of intersecting [PhysicsBody2D]\ s.
</description>
</method>
<method name="get_priority" qualifiers="const">
@@ -145,7 +145,7 @@
<argument index="0" name="area" type="Node">
</argument>
<description>
- Return whether the area passed is totally or partially inside this area.
+ If [code]true[/code] the given area overlaps the Area2D.
</description>
</method>
<method name="overlaps_body" qualifiers="const">
@@ -154,7 +154,7 @@
<argument index="0" name="body" type="Node">
</argument>
<description>
- Return whether the body passed is totally or partially inside this area.
+ If [code]true[/code] the given body overlaps the Area2D.
</description>
</method>
<method name="set_angular_damp">
@@ -167,7 +167,7 @@
In practice, as the fraction of speed lost gets smaller with each frame, a value of 1.0 does not mean the object will stop in exactly one second. Only when the physics calculations are done at 1 frame per second, it does stop in a second.
</description>
</method>
- <method name="set_audio_bus">
+ <method name="set_audio_bus_name">
<return type="void">
</return>
<argument index="0" name="name" type="String">
@@ -318,49 +318,46 @@
</methods>
<members>
<member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp">
- The rate at which objects stop spinning in this area. Represents the amount of speed lost per second. If 1.0, physics bodies in the area stop rotating immediately. If 0.0, they never slow down. Does not incorporate external forces. The physics-update's rate affects 'angular_damp'.
+ The rate at which objects stop spinning in this area. Represents the angular velocity lost per second. Values range from [code]0[/code] (no damping) to [code]1[/code] (full damping).
</member>
- <member name="audio_bus_name" type="String" setter="set_audio_bus" getter="get_audio_bus">
- The name of the Area2D's audio bus.
+ <member name="audio_bus_name" type="String" setter="set_audio_bus_name" getter="get_audio_bus_name">
+ The name of the area's audio bus.
</member>
<member name="audio_bus_override" type="bool" setter="set_audio_bus_override" getter="is_overriding_audio_bus">
- If [code]true[/code], overrides the default audio bus with the Area2D's. Defaults to [code]false[/code].
+ If [code]true[/code] the area's audio bus overrides the default audio bus. Default value: [code]false[/code].
</member>
<member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer">
- The physics layer this Area2D is in.
- Collidable objects can exist in any of 32 different layers. These layers are not visual, but more of a tagging system instead. A collidable can use these layers/tags to select with which objects it can collide, using [method set_collision_mask].
- A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans.
+ The area's physics layer(s). Collidable objects can exist in any of 32 different layers. A contact is detected if object A is in any of the layers that object B scans, or object B is in any layers that object A scans. See also [code]collision_mask[/code].
</member>
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask">
- The physics layers this Area2D scans to determine collision detections.
+ The physics layers this area scans to determine collision detection.
</member>
<member name="gravity" type="float" setter="set_gravity" getter="get_gravity">
- The gravity intensity within the Area2D (ranges -1024 to 1024). This is useful to alter the force of gravity without altering its direction.
- This value multiplies the gravity vector, whether it is the given vector ([method set_gravity_vector]), or a calculated one (when using a center of gravity).
+ The area's gravity intensity (ranges from -1024 to 1024). This value multiplies the gravity vector. This is useful to alter the force of gravity without altering its direction.
</member>
<member name="gravity_distance_scale" type="float" setter="set_gravity_distance_scale" getter="get_gravity_distance_scale">
- The falloff factor for point gravity. The greater this value is, the faster the strength of gravity decreases with the square of distance.
+ The falloff factor for point gravity. The greater the value, the faster gravity decreases with distance.
</member>
<member name="gravity_point" type="bool" setter="set_gravity_is_point" getter="is_gravity_a_point">
- If [code]true[/code], calculates gravity from a particular point during a space override (see [method set_space_override_mode]). If a point, [Vector2] position is set with [method set_gravity_vector]. Defaults to [code]false[/code].
+ If [code]true[/code] gravity is calculated from a point (set via [code]gravity_vec[/code]). Also see [code]space_override[/code]. Default value: [code]false[/code].
</member>
<member name="gravity_vec" type="Vector2" setter="set_gravity_vector" getter="get_gravity_vector">
- The gravitational direction/strength as a vector (not normalized). If gravity is a point (see [method is_gravity_a_point]), this will be the attraction center.
+ The area's gravity vector (not normalized). If gravity is a point (see [method is_gravity_a_point]), this will be the point of attraction.
</member>
<member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp">
- The rate at which objects stop spinning in this area. Represents the amount of speed lost per second. If 1.0, physics bodies in the area stop rotating immediately. If 0.0, they never slow down. Does not incorporate external forces. The physics-update's rate affects 'angular_damp'.
+ The rate at which objects stop moving in this area. Represents the linear velocity lost per second. Values range from [code]0[/code] (no damping) to [code]1[/code] (full damping).
</member>
<member name="monitorable" type="bool" setter="set_monitorable" getter="is_monitorable">
- If [code]true[/code], other monitoring areas can detect this Area2D (is it undetectable at the moment?). Defaults to [code]true[/code].
+ If [code]true[/code] other monitoring areas can detect this area. Default value: [code]true[/code].
</member>
<member name="monitoring" type="bool" setter="set_monitoring" getter="is_monitoring">
- If [code]true[/code], this detects bodies/areas entering/exiting it (can it detect others at the moment?). Defaults to [code]true[/code].
+ If [code]true[/code] the area detects bodies or areas entering and exiting it. Default value: [code]true[/code].
</member>
<member name="priority" type="float" setter="set_priority" getter="get_priority">
- The processing order for this priority. Ranges from 0 to 128. Defaults to 0. Higher priorities are processed first.
+ The area's priority. Higher priority areas are processed first. Default value: 0.
</member>
<member name="space_override" type="int" setter="set_space_override_mode" getter="get_space_override_mode" enum="Area2D.SpaceOverride">
- How to override gravity and damping calculations within this Area2D, if at all. Consult the SPACE_OVERRIDE_* constants for available options.
+ Override mode for gravity and damping calculations within this area. See the SPACE_OVERRIDE_* constants for values.
</member>
</members>
<signals>
@@ -368,14 +365,14 @@
<argument index="0" name="area" type="Object">
</argument>
<description>
- This signal is triggered only once when an area enters this area. The only parameter passed is the area that entered this area.
+ Emitted when another area enters.
</description>
</signal>
<signal name="area_exited">
<argument index="0" name="area" type="Object">
</argument>
<description>
- This signal is triggered only once when an area exits this area. The only parameter passed is the area that exited this area.
+ Emitted when another area exits.
</description>
</signal>
<signal name="area_shape_entered">
@@ -388,7 +385,7 @@
<argument index="3" name="self_shape" type="int">
</argument>
<description>
- This signal triggers only once when an area enters this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering.
+ Emitted when another area enters, reporting which shapes overlapped.
</description>
</signal>
<signal name="area_shape_exited">
@@ -401,21 +398,21 @@
<argument index="3" name="self_shape" type="int">
</argument>
<description>
- This signal triggers only once when an area exits this area. The first parameter is the area's [RID]. The second one is the area as an object. The third one is the index of the shape entering this area, and the fourth one is the index of the shape in this area that reported the entering.
+ Emitted when another area exits, reporting which shapes were overlapping.
</description>
</signal>
<signal name="body_entered">
<argument index="0" name="body" type="Object">
</argument>
<description>
- This signal is triggered only once when a body enters this area. The only parameter passed is the body that entered this area.
+ Emitted when a [PhysicsBody2D] object enters.
</description>
</signal>
<signal name="body_exited">
<argument index="0" name="body" type="Object">
</argument>
<description>
- This signal is triggered only once when a body exits this area. The only parameter passed is the body that exited this area.
+ Emitted when a [PhysicsBody2D] object exits.
</description>
</signal>
<signal name="body_shape_entered">
@@ -428,7 +425,7 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
- This signal triggers only once when a body enters this area. The first parameter is the body's [RID]. The second one is the body as an object. The third one is the index of the shape of the body that entered this area, and the fourth one is the index of the shape in this area that reported the entering.
+ Emitted when a [PhysicsBody2D] object enters, reporting which shapes overlapped.
</description>
</signal>
<signal name="body_shape_exited">
@@ -441,25 +438,25 @@
<argument index="3" name="area_shape" type="int">
</argument>
<description>
- This signal triggers only once when a body exits this area. The first parameter is the body's [RID]. The second one is the body as an object. The third one is the index of the shape exiting this area, and the fourth one is the index of the shape in this area that reported the exit.
+ Emitted when a [PhysicsBody2D] object exits, reporting which shapes were overlapping.
</description>
</signal>
</signals>
<constants>
<constant name="SPACE_OVERRIDE_DISABLED" value="0">
- This area does not affect gravity/damp. These are areas that exist only to detect collisions and objects entering or exiting them.
+ This area does not affect gravity/damping.
</constant>
<constant name="SPACE_OVERRIDE_COMBINE" value="1">
- This area adds its gravity/damp values to whatever has been calculated so far. This way, many overlapping areas can combine their physics to make interesting effects.
+ This area adds its gravity/damping values to whatever has been calculated so far (in [code]priority[/code] order).
</constant>
<constant name="SPACE_OVERRIDE_COMBINE_REPLACE" value="2">
- This area adds its gravity/damp values to whatever has been calculated so far. Then stops taking into account the rest of the areas, even the default one.
+ This area adds its gravity/damping values to whatever has been calculated so far (in [code]priority[/code] order), ignoring any lower priority areas.
</constant>
<constant name="SPACE_OVERRIDE_REPLACE" value="3">
- This area replaces any gravity/damp, even the default one, and stops taking into account the rest of the areas.
+ This area replaces any gravity/damping, even the defaults, ignoring any lower priority areas.
</constant>
<constant name="SPACE_OVERRIDE_REPLACE_COMBINE" value="4">
- This area replaces any gravity/damp calculated so far, but keeps calculating the rest of the areas, down to the default one.
+ This area replaces any gravity/damping calculated so far (in [code]priority[/code] order), but keeps calculating the rest of the areas.
</constant>
</constants>
</class>
diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml
index 042dfb3e12..9542c83eaf 100644
--- a/doc/classes/Array.xml
+++ b/doc/classes/Array.xml
@@ -168,7 +168,7 @@
</description>
</method>
<method name="insert">
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<argument index="1" name="value" type="var">
</argument>
@@ -206,14 +206,14 @@
</description>
</method>
<method name="remove">
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<description>
Remove an element from the array by index.
</description>
</method>
<method name="resize">
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="size" type="int">
</argument>
<description>
Resize the array to contain a different number of elements. If the array size is smaller, elements are cleared, if bigger, new elements are Null.
diff --git a/doc/classes/AudioEffectAmplify.xml b/doc/classes/AudioEffectAmplify.xml
index 8497042b53..35d7991833 100644
--- a/doc/classes/AudioEffectAmplify.xml
+++ b/doc/classes/AudioEffectAmplify.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectAmplify" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Amplifies the volume of an audio source.
+ Adds a Amplify audio effect to an Audio bus.
+ Increases or decreases the volume of the selected audio bus.
</brief_description>
<description>
- Amplifies the volume of an audio source. Increase gain of the audio being routed through the bus.
+ Increases or decreases the volume being routed through the audio bus.
</description>
<tutorials>
</tutorials>
@@ -15,7 +16,6 @@
<return type="float">
</return>
<description>
- Returns the set maximum volume.
</description>
</method>
<method name="set_volume_db">
@@ -24,13 +24,12 @@
<argument index="0" name="volume" type="float">
</argument>
<description>
- Sets the maximum volume.
</description>
</method>
</methods>
<members>
<member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db">
- The effect's volume limit.
+ Amount of amplification. Positive values make the sound louder, negative values make it quieter. Value can range from -80 to 24. Default value: [code]0[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/AudioEffectCompressor.xml b/doc/classes/AudioEffectCompressor.xml
index 5a7a91ede0..9d7e25dbf2 100644
--- a/doc/classes/AudioEffectCompressor.xml
+++ b/doc/classes/AudioEffectCompressor.xml
@@ -1,8 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectCompressor" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a Compressor audio effect to an Audio bus.
+ Reduces sounds that exceed a certain threshold level, smooths out the dynamics and increases the overall volume.
</brief_description>
<description>
+ Dynamic range compressor reduces the level of the sound when the amplitude goes over a certain threshold in Decibels. One of the main uses of a compressor is to increase the dynamic range by clipping as little as possible (when sound goes over 0dB).
+ Compressor has many uses in the mix:
+ - In the Master bus to compress the whole output (Although a [AudioEffectLimiter] is probably better)
+ - In voice channels to ensure they sound as balanced as possible.
+ - Sidechained. Sidechained, which can reduce the sound level sidechained with another audio bus for threshold detection.. This technique is very common in video game mixing to download the level of Music/SFX while voices are being heard.
+ - Accentuates transients by using a wider attack, making effects sound more punchy.
</description>
<tutorials>
</tutorials>
@@ -110,18 +118,25 @@
</methods>
<members>
<member name="attack_us" type="float" setter="set_attack_us" getter="get_attack_us">
+ Compressor's reaction time when the signal exceeds the threshold. Value can range from 20 to 2000. Default value: [code]20ms[/code].
</member>
<member name="gain" type="float" setter="set_gain" getter="get_gain">
+ Gain applied to the output signal.
</member>
<member name="mix" type="float" setter="set_mix" getter="get_mix">
+ Balance between original signal and effect signal. Value can range from 0 (totally dry) to 1 (totally wet). Default value: [code]1[/code].
</member>
<member name="ratio" type="float" setter="set_ratio" getter="get_ratio">
+ Amount of compression applied to the audio once it passes the threshold level. The higher the ratio the more the loud parts of the audio will be compressed. Value can range from 1 to 48. Default value: [code]4[/code].
</member>
<member name="release_ms" type="float" setter="set_release_ms" getter="get_release_ms">
+ Compressor's delay time to stop reducing the signal after the signal level falls below the threshold. Value can range from 20 to 2000. Default value: [code]250ms[/code].
</member>
<member name="sidechain" type="String" setter="set_sidechain" getter="get_sidechain">
+ Reduce the sound level using another audio bus for threshold detection.
</member>
<member name="threshold" type="float" setter="set_threshold" getter="get_threshold">
+ The level above which compression is applied to the audio. Value can range from -60 to 0. Default value: [code]0[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/AudioEffectDelay.xml b/doc/classes/AudioEffectDelay.xml
index 8d317b3c46..9dc61883ab 100644
--- a/doc/classes/AudioEffectDelay.xml
+++ b/doc/classes/AudioEffectDelay.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectDelay" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a Delay audio effect to an Audio bus. Plays input signal back after a period of time.
+ Two tap delay and feedback options.
</brief_description>
<description>
+ Plays input signal back after a period of time. The delayed signal may be played back multiple times to create the sound of a repeating, decaying echo. Delay effects range from a subtle echo effect to a pronounced blending of previous sounds with new sounds.
</description>
<tutorials>
</tutorials>
@@ -194,30 +197,43 @@
</methods>
<members>
<member name="dry" type="float" setter="set_dry" getter="get_dry">
+ Output percent of original sound. At 0, only delayed sounds are output. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="feedback/active" type="bool" setter="set_feedback_active" getter="is_feedback_active">
+ If [code]true[/code] feedback is enabled. Default value: [code]false[/code].
</member>
<member name="feedback/delay_ms" type="float" setter="set_feedback_delay_ms" getter="get_feedback_delay_ms">
+ Feedback delay time in milliseconds. Default value: [code]340[/code].
</member>
<member name="feedback/level_db" type="float" setter="set_feedback_level_db" getter="get_feedback_level_db">
+ Sound level for [code]tap1[/code]. Default value: [code]-6 dB[/code].
</member>
<member name="feedback/lowpass" type="float" setter="set_feedback_lowpass" getter="get_feedback_lowpass">
+ Low-pass filter for feedback. Frequencies below the Low Cut value are filtered out of the source signal. Default value: [code]16000[/code].
</member>
<member name="tap1/active" type="bool" setter="set_tap1_active" getter="is_tap1_active">
+ If [code]true[/code], [code]tap1[/code] will be enabled. Default value: [code]true[/code].
</member>
<member name="tap1/delay_ms" type="float" setter="set_tap1_delay_ms" getter="get_tap1_delay_ms">
+ [b]Tap1[/b] delay time in milliseconds. Default value: [code]250ms[/code].
</member>
<member name="tap1/level_db" type="float" setter="set_tap1_level_db" getter="get_tap1_level_db">
+ Sound level for [code]tap1[/code]. Default value: [code]-6 dB[/code].
</member>
<member name="tap1/pan" type="float" setter="set_tap1_pan" getter="get_tap1_pan">
+ Pan position for [code]tap1[/code]. Value can range from -1 (fully left) to 1 (fully right). Default value: [code]0.2[/code].
</member>
<member name="tap2/active" type="bool" setter="set_tap2_active" getter="is_tap2_active">
+ If [code]true[/code], [code]tap2[/code] will be enabled. Default value: [code]true[/code].
</member>
<member name="tap2/delay_ms" type="float" setter="set_tap2_delay_ms" getter="get_tap2_delay_ms">
+ [b]Tap2[/b] delay time in milliseconds. Default value: [code]500ms[/code].
</member>
<member name="tap2/level_db" type="float" setter="set_tap2_level_db" getter="get_tap2_level_db">
+ Sound level for [code]tap2[/code]. Default value: [code]-12 dB[/code].
</member>
<member name="tap2/pan" type="float" setter="set_tap2_pan" getter="get_tap2_pan">
+ Pan position for [code]tap2[/code]. Value can range from -1 (fully left) to 1 (fully right). Default value: [code]-0.4[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/AudioEffectDistortion.xml b/doc/classes/AudioEffectDistortion.xml
index e5c5a3b50e..1a6aa1d2b6 100644
--- a/doc/classes/AudioEffectDistortion.xml
+++ b/doc/classes/AudioEffectDistortion.xml
@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectDistortion" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a Distortion audio effect to an Audio bus.
+ Modify the sound to make it dirty.
</brief_description>
<description>
+ Modify the sound and make it dirty. Differents types available : clip, tan, lofi (bit crushing), overdrive, or waveshape.
+ By distorting the waveform the frequency content change, which will often make the sound "crunchy" or "abrasive". For games, it can simulate sound coming from some saturated device or speaker very efficiently.
</description>
<tutorials>
</tutorials>
@@ -82,26 +86,35 @@
</methods>
<members>
<member name="drive" type="float" setter="set_drive" getter="get_drive">
+ Distortion power. Value can range from 0 to 1. Default value: [code]0[/code].
</member>
<member name="keep_hf_hz" type="float" setter="set_keep_hf_hz" getter="get_keep_hf_hz">
+ High-pass filter. Frequencies higher than this value will not be affected by the distortion. Value can range from 1 to 20000. Default value: [code]16000[/code].
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="AudioEffectDistortion.Mode">
+ Distortion type. Default value: [code]MODE_CLIP[/code].
</member>
<member name="post_gain" type="float" setter="set_post_gain" getter="get_post_gain">
+ Increases or decreases the volume after the effect. Value can range from -80 to 24. Default value: [code]0[/code].
</member>
<member name="pre_gain" type="float" setter="set_pre_gain" getter="get_pre_gain">
+ Increases or decreases the volume before the effect. Value can range from -60 to 60. Default value: [code]0[/code].
</member>
</members>
<constants>
<constant name="MODE_CLIP" value="0">
+ Digital distortion effect which cuts off peaks at the top and bottom of the waveform.
</constant>
<constant name="MODE_ATAN" value="1">
</constant>
<constant name="MODE_LOFI" value="2">
+ Low-resolution digital distortion effect. You can use it to emulate the sound of early digital audio devices.
</constant>
<constant name="MODE_OVERDRIVE" value="3">
+ Emulates the warm distortion produced by a field effect transistor, which is commonly used in solid-state musical instrument amplifiers.
</constant>
<constant name="MODE_WAVESHAPE" value="4">
+ Waveshaper distortions are used mainly by electronic musicians to achieve an extra-abrasive sound.
</constant>
</constants>
</class>
diff --git a/doc/classes/AudioEffectEQ.xml b/doc/classes/AudioEffectEQ.xml
index 94d5c696c3..246f6b882e 100644
--- a/doc/classes/AudioEffectEQ.xml
+++ b/doc/classes/AudioEffectEQ.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectEQ" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Base class for audio equalizers. Gives you control over frequencies.
+ Use it to create a custom equalizer if [AudioEffectEQ6], [AudioEffectEQ10] or [AudioEffectEQ21] don't fit your needs.
</brief_description>
<description>
+ AudioEffectEQ gives you control over frequencies. Use it to compensate for existing deficiencies in audio. AudioEffectEQ are very useful on the Master Bus to completely master a mix and give it character. They are also very useful when a game is run on a mobile device, to adjust the mix to that kind of speakers (it can be added but disabled when headphones are plugged).
</description>
<tutorials>
</tutorials>
@@ -13,6 +16,7 @@
<return type="int">
</return>
<description>
+ Returns the number of bands of the equalizer.
</description>
</method>
<method name="get_band_gain_db" qualifiers="const">
@@ -21,6 +25,7 @@
<argument index="0" name="band_idx" type="int">
</argument>
<description>
+ Returns the band's gain at the specified index, in dB.
</description>
</method>
<method name="set_band_gain_db">
@@ -31,6 +36,7 @@
<argument index="1" name="volume_db" type="float">
</argument>
<description>
+ Sets band's gain at the specified index, in dB.
</description>
</method>
</methods>
diff --git a/doc/classes/AudioEffectEQ10.xml b/doc/classes/AudioEffectEQ10.xml
index 004236dfde..7a29f4cc0b 100644
--- a/doc/classes/AudioEffectEQ10.xml
+++ b/doc/classes/AudioEffectEQ10.xml
@@ -1,8 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectEQ10" inherits="AudioEffectEQ" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a 10-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 31 Hz to 16000 Hz.
+ Each frequency can be modulated between -60/+24 dB.
</brief_description>
<description>
+ Frequency bands :
+ Band 1 : 31 Hz
+ Band 2 : 62 Hz
+ Band 3 : 125 Hz
+ Band 4 : 250 Hz
+ Band 5 : 500 Hz
+ Band 6 : 1000 Hz
+ Band 7 : 2000 Hz
+ Band 8 : 4000 Hz
+ Band 9 : 8000 Hz
+ Band 10 : 16000 Hz
+
+ See also [AudioEffectEQ], [AudioEffectEQ6], [AudioEffectEQ21].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectEQ21.xml b/doc/classes/AudioEffectEQ21.xml
index e4faa9bb0c..327f5a291a 100644
--- a/doc/classes/AudioEffectEQ21.xml
+++ b/doc/classes/AudioEffectEQ21.xml
@@ -1,8 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectEQ21" inherits="AudioEffectEQ" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a 21-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 22 Hz to 22000 Hz.
+ Each frequency can be modulated between -60/+24 dB.
</brief_description>
<description>
+ Frequency bands :
+ Band 1 : 22 Hz
+ Band 2 : 32 Hz
+ Band 3 : 44 Hz
+ Band 4 : 63 Hz
+ Band 5 : 90 Hz
+ Band 6 : 125 Hz
+ Band 7 : 175 Hz
+ Band 8 : 250 Hz
+ Band 9 : 350 Hz
+ Band 10 : 500 Hz
+ Band 11 : 700 Hz
+ Band 12 : 1000 Hz
+ Band 13 : 1400 Hz
+ Band 14 : 2000 Hz
+ Band 15 : 2800 Hz
+ Band 16 : 4000 Hz
+ Band 17 : 5600 Hz
+ Band 18 : 8000 Hz
+ Band 19 : 11000 Hz
+ Band 20 : 16000 Hz
+ Band 21 : 22000 Hz
+
+ See also [AudioEffectEQ], [AudioEffectEQ6], [AudioEffectEQ10].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectEQ6.xml b/doc/classes/AudioEffectEQ6.xml
index b74cc5d285..bc05535041 100644
--- a/doc/classes/AudioEffectEQ6.xml
+++ b/doc/classes/AudioEffectEQ6.xml
@@ -1,8 +1,19 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectEQ6" inherits="AudioEffectEQ" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a 6-band equalizer audio effect to an Audio bus. Gives you control over frequencies from 32 Hz to 10000 Hz.
+ Each frequency can be modulated between -60/+24 dB.
</brief_description>
<description>
+ Frequency bands :
+ Band 1 : 32 Hz
+ Band 2 : 100 Hz
+ Band 3 : 320 Hz
+ Band 4 : 1000 Hz
+ Band 5 : 3200 Hz
+ Band 6 : 10000 Hz
+
+ See also [AudioEffectEQ], [AudioEffectEQ10], [AudioEffectEQ21].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/AudioEffectLimiter.xml b/doc/classes/AudioEffectLimiter.xml
index e52fb57c70..5209f290b1 100644
--- a/doc/classes/AudioEffectLimiter.xml
+++ b/doc/classes/AudioEffectLimiter.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectLimiter" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a soft clip Limiter audio effect to an Audio bus.
</brief_description>
<description>
+ A limiter is similar to a compressor, but it’s less flexible and designed to disallow sound going over a given dB threshold. Adding one in the Master Bus is always recommended to reduce the effects of clipping.
+ Soft clipping starts to reduce the peaks a little below the threshold level and progressively increases its effect as the input level increases such that the threshold is never exceeded.
</description>
<tutorials>
</tutorials>
@@ -68,12 +71,15 @@
</methods>
<members>
<member name="ceiling_db" type="float" setter="set_ceiling_db" getter="get_ceiling_db">
+ The waveform's maximum allowed value. Value can range from -20 to -0.1. Default value: [code]-0.1dB[/code].
</member>
<member name="soft_clip_db" type="float" setter="set_soft_clip_db" getter="get_soft_clip_db">
+ Applies a gain to the limited waves. Value can range from 0 to 6. Default value: [code]2dB[/code].
</member>
<member name="soft_clip_ratio" type="float" setter="set_soft_clip_ratio" getter="get_soft_clip_ratio">
</member>
<member name="threshold_db" type="float" setter="set_threshold_db" getter="get_threshold_db">
+ Threshold from which the limiter begins to be active. Value can range from -30 to 0. Default value: [code]0dB[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/AudioEffectPanner.xml b/doc/classes/AudioEffectPanner.xml
index b55d7f91c1..56b39a36c6 100644
--- a/doc/classes/AudioEffectPanner.xml
+++ b/doc/classes/AudioEffectPanner.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectPanner" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a Panner audio effect to an Audio bus. Pans sound left or right.
</brief_description>
<description>
+ Determines how much of an audio signal is sent to the left and right buses.
</description>
<tutorials>
</tutorials>
@@ -26,6 +28,7 @@
</methods>
<members>
<member name="pan" type="float" setter="set_pan" getter="get_pan">
+ Pan position. Value can range from -1 (fully left) to 1 (fully right).
</member>
</members>
<constants>
diff --git a/doc/classes/AudioEffectPhaser.xml b/doc/classes/AudioEffectPhaser.xml
index 7e9cd27a47..bd9067471b 100644
--- a/doc/classes/AudioEffectPhaser.xml
+++ b/doc/classes/AudioEffectPhaser.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectPhaser" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a Phaser audio effect to an Audio bus.
+ Combines the original signal with a copy that is slightly out of phase with the original.
</brief_description>
<description>
+ Combines phase-shifted signals with the original signal. The movement of the phase-shifted signals is controlled using a Low Frequency Oscillator.
</description>
<tutorials>
</tutorials>
@@ -82,14 +85,19 @@
</methods>
<members>
<member name="depth" type="float" setter="set_depth" getter="get_depth">
+ Governs how high the filter frequencies sweep. Low value will primarily affect bass frequencies. High value can sweep high into the treble. Value can range from 0.1 to 4. Default value: [code]1[/code].
</member>
<member name="feedback" type="float" setter="set_feedback" getter="get_feedback">
+ Output percent of modified sound. Value can range from 0.1 to 0.9. Default value: [code]0.7[/code].
</member>
<member name="range_max_hz" type="float" setter="set_range_max_hz" getter="get_range_max_hz">
+ Determines the maximum frequency affected by the LFO modulations. Value can range from 10 to 10000. Default value: [code]1600hz[/code].
</member>
<member name="range_min_hz" type="float" setter="set_range_min_hz" getter="get_range_min_hz">
+ Determines the minimum frequency affected by the LFO modulations. Value can range from 10 to 10000. Default value: [code]440hz[/code].
</member>
<member name="rate_hz" type="float" setter="set_rate_hz" getter="get_rate_hz">
+ Adjusts the rate at which the effect sweeps up and down across the frequency range.
</member>
</members>
<constants>
diff --git a/doc/classes/AudioEffectPitchShift.xml b/doc/classes/AudioEffectPitchShift.xml
index 6fc3acdc20..edcb54e09e 100644
--- a/doc/classes/AudioEffectPitchShift.xml
+++ b/doc/classes/AudioEffectPitchShift.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectPitchShift" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a Pitch shift audio effect to an Audio bus.
+ Raises or lowers the pitch of original sound.
</brief_description>
<description>
+ Allows modulation of pitch independently of tempo. All frequencies can be increased/decreased with minimal effect on transients.
</description>
<tutorials>
</tutorials>
@@ -26,6 +29,7 @@
</methods>
<members>
<member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale">
+ Pitch value. Can range from 0 (-1 octave) to 16 (+16 octaves).
</member>
</members>
<constants>
diff --git a/doc/classes/AudioEffectReverb.xml b/doc/classes/AudioEffectReverb.xml
index b390fa239c..4cda24530b 100644
--- a/doc/classes/AudioEffectReverb.xml
+++ b/doc/classes/AudioEffectReverb.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectReverb" inherits="AudioEffect" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Adds a Reverb audio effect to an Audio bus.
+ Simulates the sound of acoustic environments such as rooms, concert halls, caverns, or an open spaces.
</brief_description>
<description>
+ Simulates rooms of different sizes. Its parameters can be adjusted to simulate the sound of a specific room.
</description>
<tutorials>
</tutorials>
@@ -124,20 +127,28 @@
</methods>
<members>
<member name="damping" type="float" setter="set_damping" getter="get_damping">
+ Widens or narrows the stereo image of the reverb tail. 1 means fully widens. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="dry" type="float" setter="set_dry" getter="get_dry">
+ Output percent of original sound. At 0, only modified sound is outputted. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="hipass" type="float" setter="set_hpf" getter="get_hpf">
+ High-pass filter passes signals with a frequency higher than a certain cutoff frequency and attenuates signals with frequencies lower than the cutoff frequency. Value can range from 0 to 1. Default value: [code]0[/code].
</member>
<member name="predelay_feedback" type="float" setter="set_predelay_msec" getter="get_predelay_msec">
+ Output percent of predelay. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="predelay_msec" type="float" setter="set_predelay_msec" getter="get_predelay_msec">
+ Time between the original signal and the early reflections of the reverb signal. Default value: [code]150ms[/code].
</member>
<member name="room_size" type="float" setter="set_room_size" getter="get_room_size">
+ Dimensions of simulated room. Bigger means more echoes. Value can range from 0 to 1. Default value: [code]0.8[/code].
</member>
<member name="spread" type="float" setter="set_spread" getter="get_spread">
+ Defines how reflective the imaginary room's walls are. Value can range from 0 to 1. Default value: [code]1[/code].
</member>
<member name="wet" type="float" setter="set_wet" getter="get_wet">
+ Output percent of modified sound. At 0, only original sound is outputted. Value can range from 0 to 1. Default value: [code]0.5[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/AudioServer.xml b/doc/classes/AudioServer.xml
index dc30c0c5f9..768987fd0b 100644
--- a/doc/classes/AudioServer.xml
+++ b/doc/classes/AudioServer.xml
@@ -14,7 +14,7 @@
<method name="add_bus">
<return type="void">
</return>
- <argument index="0" name="at_pos" type="int" default="-1">
+ <argument index="0" name="at_position" type="int" default="-1">
</argument>
<description>
</description>
@@ -26,7 +26,7 @@
</argument>
<argument index="1" name="effect" type="AudioEffect">
</argument>
- <argument index="2" name="at_pos" type="int" default="-1">
+ <argument index="2" name="at_position" type="int" default="-1">
</argument>
<description>
</description>
diff --git a/doc/classes/AudioStreamOGGVorbis.xml b/doc/classes/AudioStreamOGGVorbis.xml
index fd9018764d..679438b66b 100644
--- a/doc/classes/AudioStreamOGGVorbis.xml
+++ b/doc/classes/AudioStreamOGGVorbis.xml
@@ -56,10 +56,13 @@
</methods>
<members>
<member name="data" type="PoolByteArray" setter="set_data" getter="get_data">
+ Raw audio data.
</member>
<member name="loop" type="bool" setter="set_loop" getter="has_loop">
+ If [code]true[/code], audio will loop continuously. Default value: [code]false[/code].
</member>
<member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset">
+ If loop is [code]true[/code], loop starts from this position, in seconds.
</member>
</members>
<constants>
diff --git a/doc/classes/AudioStreamPlayer.xml b/doc/classes/AudioStreamPlayer.xml
index 6ee0ba09a1..9b104fe757 100644
--- a/doc/classes/AudioStreamPlayer.xml
+++ b/doc/classes/AudioStreamPlayer.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamPlayer" inherits="Node" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Plays back audio.
</brief_description>
<description>
+ Plays background audio.
</description>
<tutorials>
</tutorials>
@@ -21,7 +23,7 @@
<description>
</description>
</method>
- <method name="get_pos">
+ <method name="get_playback_position">
<return type="float">
</return>
<description>
@@ -54,17 +56,19 @@
<method name="play">
<return type="void">
</return>
- <argument index="0" name="from_pos" type="float" default="0.0">
+ <argument index="0" name="from_position" type="float" default="0.0">
</argument>
<description>
+ Plays the audio from the given position 'from_position', in seconds.
</description>
</method>
<method name="seek">
<return type="void">
</return>
- <argument index="0" name="to_pos" type="float">
+ <argument index="0" name="to_position" type="float">
</argument>
<description>
+ Sets the position from which audio will be played, in seconds.
</description>
</method>
<method name="set_autoplay">
@@ -111,26 +115,33 @@
<return type="void">
</return>
<description>
+ Stops the audio.
</description>
</method>
</methods>
<members>
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled">
+ If [code]true[/code], audio plays when added to scene tree. Default value: [code]false[/code].
</member>
<member name="bus" type="String" setter="set_bus" getter="get_bus">
+ Bus on which this audio is playing.
</member>
<member name="mix_target" type="int" setter="set_mix_target" getter="get_mix_target" enum="AudioStreamPlayer.MixTarget">
</member>
<member name="playing" type="bool" setter="_set_playing" getter="is_playing">
+ If [code]true[/code], audio is playing.
</member>
<member name="stream" type="AudioStream" setter="set_stream" getter="get_stream">
+ The [AudioStream] object to be played.
</member>
<member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db">
+ Volume of sound, in dB.
</member>
</members>
<signals>
<signal name="finished">
<description>
+ Emitted when the audio stops playing.
</description>
</signal>
</signals>
diff --git a/doc/classes/AudioStreamPlayer2D.xml b/doc/classes/AudioStreamPlayer2D.xml
index f2464ddac4..600e0858dd 100644
--- a/doc/classes/AudioStreamPlayer2D.xml
+++ b/doc/classes/AudioStreamPlayer2D.xml
@@ -1,10 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamPlayer2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Plays audio in 2D.
</brief_description>
<description>
+ Plays audio that dampens with distance from screen center.
</description>
<tutorials>
+ http://docs.godotengine.org/en/latest/learning/features/audio/index.html
</tutorials>
<demos>
</demos>
@@ -33,7 +36,7 @@
<description>
</description>
</method>
- <method name="get_pos">
+ <method name="get_playback_position">
<return type="float">
</return>
<description>
@@ -66,17 +69,19 @@
<method name="play">
<return type="void">
</return>
- <argument index="0" name="from_pos" type="float" default="0.0">
+ <argument index="0" name="from_position" type="float" default="0.0">
</argument>
<description>
+ Plays the audio from the given position 'from_position', in seconds.
</description>
</method>
<method name="seek">
<return type="void">
</return>
- <argument index="0" name="to_pos" type="float">
+ <argument index="0" name="to_position" type="float">
</argument>
<description>
+ Sets the position from which audio will be played, in seconds.
</description>
</method>
<method name="set_area_mask">
@@ -139,30 +144,40 @@
<return type="void">
</return>
<description>
+ Stops the audio.
</description>
</method>
</methods>
<members>
<member name="area_mask" type="int" setter="set_area_mask" getter="get_area_mask">
+ Areas in which this sound plays.
</member>
<member name="attenuation" type="float" setter="set_attenuation" getter="get_attenuation">
+ Dampens audio over distance with this as an exponent.
</member>
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled">
+ If [code]true[/code], audio plays when added to scene tree. Default value: [code]false[/code].
</member>
<member name="bus" type="String" setter="set_bus" getter="get_bus">
+ Bus on which this audio is playing.
</member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance">
+ Maximum distance from which audio is still hearable.
</member>
<member name="playing" type="bool" setter="_set_playing" getter="is_playing">
+ If [code]true[/code], audio is playing.
</member>
<member name="stream" type="AudioStream" setter="set_stream" getter="get_stream">
+ The [AudioStream] object to be played.
</member>
<member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db">
+ Base volume without dampening.
</member>
</members>
<signals>
<signal name="finished">
<description>
+ Emitted when the audio stops playing.
</description>
</signal>
</signals>
diff --git a/doc/classes/AudioStreamPlayer3D.xml b/doc/classes/AudioStreamPlayer3D.xml
index 668e0cc0d2..886b2b975a 100644
--- a/doc/classes/AudioStreamPlayer3D.xml
+++ b/doc/classes/AudioStreamPlayer3D.xml
@@ -1,10 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamPlayer3D" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Plays 3D sound in 3D space
</brief_description>
<description>
+ Plays a sound effect with directed sound effects, dampens with distance if needed, generates effect of hearable position in space.
</description>
<tutorials>
+ http://docs.godotengine.org/en/latest/learning/features/audio/index.html
</tutorials>
<demos>
</demos>
@@ -75,7 +78,7 @@
<description>
</description>
</method>
- <method name="get_pos">
+ <method name="get_playback_position">
<return type="float">
</return>
<description>
@@ -120,17 +123,19 @@
<method name="play">
<return type="void">
</return>
- <argument index="0" name="from_pos" type="float" default="0.0">
+ <argument index="0" name="from_position" type="float" default="0.0">
</argument>
<description>
+ Plays the audio from the given position 'from_position', in seconds.
</description>
</method>
<method name="seek">
<return type="void">
</return>
- <argument index="0" name="to_pos" type="float">
+ <argument index="0" name="to_position" type="float">
</argument>
<description>
+ Sets the position from which audio will be played, in seconds.
</description>
</method>
<method name="set_area_mask">
@@ -265,67 +270,94 @@
<return type="void">
</return>
<description>
+ Stops the audio.
</description>
</method>
</methods>
<members>
<member name="area_mask" type="int" setter="set_area_mask" getter="get_area_mask">
+ Areas in which this sound plays.
</member>
<member name="attenuation_filter_cutoff_hz" type="float" setter="set_attenuation_filter_cutoff_hz" getter="get_attenuation_filter_cutoff_hz">
+ Dampens audio above this frequency, in Hz.
</member>
<member name="attenuation_filter_db" type="float" setter="set_attenuation_filter_db" getter="get_attenuation_filter_db">
+ Amount how much the filter affects the loudness, in dB.
</member>
<member name="attenuation_model" type="int" setter="set_attenuation_model" getter="get_attenuation_model" enum="AudioStreamPlayer3D.AttenuationModel">
+ Decides if audio should get quieter with distance linearly, quadratically or logarithmically.
</member>
<member name="autoplay" type="bool" setter="set_autoplay" getter="is_autoplay_enabled">
+ If [code]true[/code], audio plays audio plays when added to scene tree. Default value: [code]false[/code].
</member>
<member name="bus" type="String" setter="set_bus" getter="get_bus">
+ Bus on which this audio is playing.
</member>
<member name="doppler_tracking" type="int" setter="set_doppler_tracking" getter="get_doppler_tracking" enum="AudioStreamPlayer3D.DopplerTracking">
+ Decides in which step the Doppler effect should be calculated.
</member>
<member name="emission_angle_degrees" type="float" setter="set_emission_angle" getter="get_emission_angle">
+ The angle in which the audio reaches cameras undampened.
</member>
<member name="emission_angle_enabled" type="bool" setter="set_emission_angle_enabled" getter="is_emission_angle_enabled">
+ If [code]true[/code], the audio should be dampened according to the direction of the sound.
</member>
<member name="emission_angle_filter_attenuation_db" type="float" setter="set_emission_angle_filter_attenuation_db" getter="get_emission_angle_filter_attenuation_db">
+ dampens audio if camera is outside of 'emission_angle_degrees' and 'emission_angle_enabled' is set by this factor, in dB.
</member>
<member name="max_db" type="float" setter="set_max_db" getter="get_max_db">
+ Sets the absolute maximum of the soundlevel, in dB.
</member>
<member name="max_distance" type="float" setter="set_max_distance" getter="get_max_distance">
+ Sets the distance from wich the 'out_of_range_mode' takes effect. Has no effect if set to 0.
</member>
<member name="out_of_range_mode" type="int" setter="set_out_of_range_mode" getter="get_out_of_range_mode" enum="AudioStreamPlayer3D.OutOfRangeMode">
+ Decides if audio should pause when source is outside of 'max_distance' range.
</member>
<member name="playing" type="bool" setter="_set_playing" getter="is_playing">
+ If [code]true[/code], audio is playing.
</member>
<member name="stream" type="AudioStream" setter="set_stream" getter="get_stream">
+ The [AudioStream] object to be played.
</member>
<member name="unit_db" type="float" setter="set_unit_db" getter="get_unit_db">
+ Base sound level unaffected by dampening, in dB.
</member>
<member name="unit_size" type="float" setter="set_unit_size" getter="get_unit_size">
+ Factor for the attenuation effect.
</member>
</members>
<signals>
<signal name="finished">
<description>
+ Fires when the audio stops playing.
</description>
</signal>
</signals>
<constants>
<constant name="ATTENUATION_INVERSE_DISTANCE" value="0">
+ Linear dampening of loudness according to distance.
</constant>
<constant name="ATTENUATION_INVERSE_SQUARE_DISTANCE" value="1">
+ Squared dampening of loudness according to distance.
</constant>
<constant name="ATTENUATION_LOGARITHMIC" value="2">
+ Logarithmic dampening of loudness according to distance.
</constant>
<constant name="OUT_OF_RANGE_MIX" value="0">
+ Mix this audio in, even when it's out of range.
</constant>
<constant name="OUT_OF_RANGE_PAUSE" value="1">
+ Pause this audio when it gets out of range.
</constant>
<constant name="DOPPLER_TRACKING_DISABLED" value="0">
+ Disables doppler tracking.
</constant>
<constant name="DOPPLER_TRACKING_IDLE_STEP" value="1">
+ Executes doppler trackin in idle step.
</constant>
<constant name="DOPPLER_TRACKING_FIXED_STEP" value="2">
+ Executes doppler tracking in fixed step.
</constant>
</constants>
</class>
diff --git a/doc/classes/AudioStreamRandomPitch.xml b/doc/classes/AudioStreamRandomPitch.xml
index 91856682e6..1573a78d1f 100644
--- a/doc/classes/AudioStreamRandomPitch.xml
+++ b/doc/classes/AudioStreamRandomPitch.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamRandomPitch" inherits="AudioStream" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Plays audio with random pitch tweaking.
</brief_description>
<description>
+ Randomly varies pitch on each start.
</description>
<tutorials>
</tutorials>
@@ -40,8 +42,10 @@
</methods>
<members>
<member name="audio_stream" type="AudioStream" setter="set_audio_stream" getter="get_audio_stream">
+ The current [AudioStream].
</member>
<member name="random_pitch" type="float" setter="set_random_pitch" getter="get_random_pitch">
+ The intensity of random pitch variation.
</member>
</members>
<constants>
diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamSample.xml
index 22b820aa7d..7f7414e4d3 100644
--- a/doc/classes/AudioStreamSample.xml
+++ b/doc/classes/AudioStreamSample.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamSample" inherits="AudioStream" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Plays audio.
</brief_description>
<description>
+ Plays audio, can loop.
</description>
<tutorials>
</tutorials>
@@ -110,32 +112,45 @@
</methods>
<members>
<member name="data" type="PoolByteArray" setter="set_data" getter="get_data">
+ Raw audio data.
</member>
<member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format">
+ Audio format. See FORMAT_* constants for values.
</member>
<member name="loop_begin" type="int" setter="set_loop_begin" getter="get_loop_begin">
+ Loop start in bytes.
</member>
<member name="loop_end" type="int" setter="set_loop_end" getter="get_loop_end">
+ Loop end in bytes.
</member>
<member name="loop_mode" type="int" setter="set_loop_mode" getter="get_loop_mode" enum="AudioStreamSample.LoopMode">
+ Loop mode. See LOOP_* constants for values.
</member>
<member name="mix_rate" type="int" setter="set_mix_rate" getter="get_mix_rate">
+ The sample rate for mixing this audio.
</member>
<member name="stereo" type="bool" setter="set_stereo" getter="is_stereo">
+ If [code]true[/code], audio is stereo. Default value: [code]false[/code].
</member>
</members>
<constants>
<constant name="FORMAT_8_BITS" value="0">
+ Audio codec 8 bit.
</constant>
<constant name="FORMAT_16_BITS" value="1">
+ Audio codec 16 bit.
</constant>
<constant name="FORMAT_IMA_ADPCM" value="2">
+ Audio codec IMA ADPCM.
</constant>
<constant name="LOOP_DISABLED" value="0">
+ Audio does not loop.
</constant>
<constant name="LOOP_FORWARD" value="1">
+ Audio loops the data between loop_begin and loop_end playing forward only.
</constant>
<constant name="LOOP_PING_PONG" value="2">
+ Audio loops the data between loop_begin and loop_end playing back and forth.
</constant>
</constants>
</class>
diff --git a/doc/classes/BitMap.xml b/doc/classes/BitMap.xml
index 62b1c9ff4f..d872d0892d 100644
--- a/doc/classes/BitMap.xml
+++ b/doc/classes/BitMap.xml
@@ -32,7 +32,7 @@
<method name="get_bit" qualifiers="const">
<return type="bool">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Returns bitmap's value at the specified position.
@@ -55,7 +55,7 @@
<method name="set_bit">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="bit" type="bool">
</argument>
diff --git a/doc/classes/BoxContainer.xml b/doc/classes/BoxContainer.xml
index f7e50f02d8..0c70d919f3 100644
--- a/doc/classes/BoxContainer.xml
+++ b/doc/classes/BoxContainer.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="BoxContainer" inherits="Container" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Base class for Box containers.
+ Base class for box containers.
</brief_description>
<description>
- Base class for Box containers. It arranges children controls vertically or horizontally, and rearranges them automatically when their minimum size changes.
+ Arranges child controls vertically or horizontally, and rearranges the controls automatically when their minimum size changes.
</description>
<tutorials>
</tutorials>
@@ -17,8 +17,7 @@
<argument index="0" name="begin" type="bool">
</argument>
<description>
- Add a control to the box as a spacer.
- If [i]begin[/i] is true the spacer control will be inserted in front of other children.
+ Adds a control to the box as a spacer. If [code]true[/code], [i]begin[/i] will insert the spacer control in front of other children.
</description>
</method>
<method name="get_alignment" qualifiers="const">
@@ -40,17 +39,18 @@
</methods>
<members>
<member name="alignment" type="int" setter="set_alignment" getter="get_alignment" enum="BoxContainer.AlignMode">
+ The alignment of the container's children (must be one of ALIGN_BEGIN, ALIGN_CENTER, or ALIGN_END).
</member>
</members>
<constants>
<constant name="ALIGN_BEGIN" value="0">
- Align children with beginning of the container.
+ Aligns children with the beginning of the container.
</constant>
<constant name="ALIGN_CENTER" value="1">
- Align children with center of the container.
+ Aligns children with the center of the container.
</constant>
<constant name="ALIGN_END" value="2">
- Align children with end of the container.
+ Aligns children with the end of the container.
</constant>
</constants>
</class>
diff --git a/doc/classes/BoxShape.xml b/doc/classes/BoxShape.xml
index 8c98c93b57..4e8eb0ba6f 100644
--- a/doc/classes/BoxShape.xml
+++ b/doc/classes/BoxShape.xml
@@ -4,7 +4,7 @@
Box shape resource.
</brief_description>
<description>
- Box shape resource, which can be set into a [PhysicsBody] or area.
+ 3D box shape that can be a child of a [PhysicsBody] or [Area].
</description>
<tutorials>
</tutorials>
@@ -30,6 +30,7 @@
</methods>
<members>
<member name="extents" type="Vector3" setter="set_extents" getter="get_extents">
+ The shape's half extents.
</member>
</members>
<constants>
diff --git a/doc/classes/Camera2D.xml b/doc/classes/Camera2D.xml
index 659efa860d..b6b699612e 100644
--- a/doc/classes/Camera2D.xml
+++ b/doc/classes/Camera2D.xml
@@ -38,7 +38,7 @@
<description>
</description>
</method>
- <method name="get_camera_pos" qualifiers="const">
+ <method name="get_camera_position" qualifiers="const">
<return type="Vector2">
</return>
<description>
diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml
index 26a9e1519b..4a9890ea18 100644
--- a/doc/classes/CanvasItem.xml
+++ b/doc/classes/CanvasItem.xml
@@ -27,7 +27,7 @@
</return>
<argument index="0" name="font" type="Font">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="char" type="String">
</argument>
@@ -42,7 +42,7 @@
<method name="draw_circle">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="radius" type="float">
</argument>
@@ -170,9 +170,9 @@
<method name="draw_set_transform">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
- <argument index="1" name="rot" type="float">
+ <argument index="1" name="rotation" type="float">
</argument>
<argument index="2" name="scale" type="Vector2">
</argument>
@@ -193,7 +193,7 @@
</return>
<argument index="0" name="font" type="Font">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="text" type="String">
</argument>
@@ -221,7 +221,7 @@
</return>
<argument index="0" name="texture" type="Texture">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
@@ -367,7 +367,7 @@
Get this item's light mask number.
</description>
</method>
- <method name="get_local_mouse_pos" qualifiers="const">
+ <method name="get_local_mouse_position" qualifiers="const">
<return type="Vector2">
</return>
<description>
@@ -476,7 +476,7 @@
<description>
</description>
</method>
- <method name="make_canvas_pos_local" qualifiers="const">
+ <method name="make_canvas_position_local" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="screen_point" type="Vector2">
diff --git a/doc/classes/CanvasLayer.xml b/doc/classes/CanvasLayer.xml
index f19e7ef041..3ee1f10536 100644
--- a/doc/classes/CanvasLayer.xml
+++ b/doc/classes/CanvasLayer.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CanvasLayer" inherits="Node" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Canvas Item layer.
+ Canvas drawing layer.
</brief_description>
<description>
- Canvas Item layer. [CanvasItem] nodes that are direct or indirect children of a [CanvasLayer] will be drawn in that layer. The layer is a numeric index that defines the draw order. The default 2D scene renders with index 0, so a [CanvasLayer] with index -1 will be drawn below, and one with index 1 will be drawn above. This is very useful for HUDs (in layer 1+ or above), or backgrounds (in layer -1 or below).
+ Canvas drawing layer. [CanvasItem] nodes that are direct or indirect children of a [CanvasLayer] will be drawn in that layer. The layer is a numeric index that defines the draw order. The default 2D scene renders with index 0, so a [CanvasLayer] with index -1 will be drawn below, and one with index 1 will be drawn above. This is very useful for HUDs (in layer 1+ or above), or backgrounds (in layer -1 or below).
</description>
<tutorials>
</tutorials>
@@ -131,12 +131,16 @@
</methods>
<members>
<member name="layer" type="int" setter="set_layer" getter="get_layer">
+ Layer index for draw order. Lower values are drawn first. Default value: [code]1[/code].
</member>
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset">
+ The layer's base offset.
</member>
<member name="rotation" type="float" setter="set_rotationd" getter="get_rotationd">
+ The layer's rotation in degrees.
</member>
<member name="scale" type="Vector2" setter="set_scale" getter="get_scale">
+ The layer's scale.
</member>
</members>
<constants>
diff --git a/doc/classes/CapsuleShape.xml b/doc/classes/CapsuleShape.xml
index 29072203ea..db075a504c 100644
--- a/doc/classes/CapsuleShape.xml
+++ b/doc/classes/CapsuleShape.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CapsuleShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Capsule shape resource.
+ Capsule shape for collisions.
</brief_description>
<description>
- Capsule shape resource, which can be set into a [PhysicsBody] or area.
+ Capsule shape for collisions.
</description>
<tutorials>
</tutorials>
@@ -46,8 +46,10 @@
</methods>
<members>
<member name="height" type="float" setter="set_height" getter="get_height">
+ The capsule's height.
</member>
<member name="radius" type="float" setter="set_radius" getter="get_radius">
+ The capsule's radius.
</member>
</members>
<constants>
diff --git a/doc/classes/CapsuleShape2D.xml b/doc/classes/CapsuleShape2D.xml
index 9c2b1c4a3d..df833e0582 100644
--- a/doc/classes/CapsuleShape2D.xml
+++ b/doc/classes/CapsuleShape2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CapsuleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Capsule 2D shape resource for physics.
+ Capsule shape for 2D collisions.
</brief_description>
<description>
- Capsule 2D shape resource for physics. A capsule (or sometimes called "pill") is like a line grown in all directions. It has a radius and a height, and is often useful for modeling biped characters.
+ Capsule shape for 2D collisions.
</description>
<tutorials>
</tutorials>
@@ -46,8 +46,10 @@
</methods>
<members>
<member name="height" type="float" setter="set_height" getter="get_height">
+ The capsule's height.
</member>
<member name="radius" type="float" setter="set_radius" getter="get_radius">
+ The capsules's radius.
</member>
</members>
<constants>
diff --git a/doc/classes/CircleShape2D.xml b/doc/classes/CircleShape2D.xml
index c3d4bdae03..1ed54f0705 100644
--- a/doc/classes/CircleShape2D.xml
+++ b/doc/classes/CircleShape2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CircleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Circular Shape for 2D Physics.
+ Circular shape for 2D collisions.
</brief_description>
<description>
- Circular Shape for 2D Physics. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast.
+ Circular shape for 2D collisions. This shape is useful for modeling balls or small characters and its collision detection with everything else is very fast.
</description>
<tutorials>
</tutorials>
@@ -30,6 +30,7 @@
</methods>
<members>
<member name="radius" type="float" setter="set_radius" getter="get_radius">
+ The circle's radius.
</member>
</members>
<constants>
diff --git a/doc/classes/CollisionObject.xml b/doc/classes/CollisionObject.xml
index 791978993c..64e9e07925 100644
--- a/doc/classes/CollisionObject.xml
+++ b/doc/classes/CollisionObject.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CollisionObject" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Base node for collision objects.
</brief_description>
<description>
+ CollisionObject is the base class for physics objects. It can hold any number of collision [Shape]\ s. Each shape must be assigned to a [i]shape owner[/i]. The CollisionObject can have any number of shape owners. Shape owners are not nodes and do not appear in the editor, but are accessible through code using the [code]shape_owner_*[/code] methods.
</description>
<tutorials>
</tutorials>
@@ -16,7 +18,7 @@
</argument>
<argument index="1" name="event" type="InputEvent">
</argument>
- <argument index="2" name="click_pos" type="Vector3">
+ <argument index="2" name="click_position" type="Vector3">
</argument>
<argument index="3" name="click_normal" type="Vector3">
</argument>
@@ -31,7 +33,7 @@
<argument index="0" name="owner" type="Object">
</argument>
<description>
- Creates new holder for the shapes. Argument is a [CollisionShape] node. It will return owner_id which usually you will want to save for later use.
+ Creates a new shape owner for the given object. Returns [code]owner_id[/code] of the new owner for future reference.
</description>
</method>
<method name="get_capture_input_on_drag" qualifiers="const">
@@ -44,13 +46,14 @@
<return type="RID">
</return>
<description>
+ Returns the object's [RID].
</description>
</method>
<method name="get_shape_owners">
<return type="Array">
</return>
<description>
- Shape owner is a node which is holding concrete shape resources. This method will return an array which is holding an integer numbers that are representing unique ID of each owner. You can use those ids when you are using others shape_owner methods.
+ Returns an [Array] of [code]owner_id[/code] identifiers. You can use these ids in other methods that take [code]owner_id[/code] as an argument.
</description>
</method>
<method name="is_ray_pickable" qualifiers="const">
@@ -65,6 +68,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
+ If [code]true[/code] the shape owner and its shapes are disabled.
</description>
</method>
<method name="remove_shape_owner">
@@ -73,6 +77,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
+ Removes the given shape owner.
</description>
</method>
<method name="set_capture_input_on_drag">
@@ -97,6 +102,7 @@
<argument index="0" name="shape_index" type="int">
</argument>
<description>
+ Returns the [code]owner_id[/code] of the given shape.
</description>
</method>
<method name="shape_owner_add_shape">
@@ -107,6 +113,7 @@
<argument index="1" name="shape" type="Shape">
</argument>
<description>
+ Adds a [Shape] to the shape owner.
</description>
</method>
<method name="shape_owner_clear_shapes">
@@ -115,7 +122,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
- Will remove all the shapes associated with given owner.
+ Removes all shapes from the shape owner.
</description>
</method>
<method name="shape_owner_get_owner" qualifiers="const">
@@ -124,6 +131,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
+ Returns the parent object of the given shape owner.
</description>
</method>
<method name="shape_owner_get_shape" qualifiers="const">
@@ -134,7 +142,7 @@
<argument index="1" name="shape_id" type="int">
</argument>
<description>
- Will return a [Shape]. First argument owner_id is an integer that can be obtained from [method get_shape_owners]. Shape_id is a position of the shape inside owner; it's a value in range from 0 to [method shape_owner_get_shape_count].
+ Returns the [Shape] with the given id from the given shape owner.
</description>
</method>
<method name="shape_owner_get_shape_count" qualifiers="const">
@@ -143,7 +151,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
- Returns number of shapes to which given owner is associated to.
+ Returns the number of shapes the given shape owner contains.
</description>
</method>
<method name="shape_owner_get_shape_index" qualifiers="const">
@@ -162,7 +170,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
- Will return [Transform] of an owner node.
+ Returns the shape owner's [Transform].
</description>
</method>
<method name="shape_owner_remove_shape">
@@ -173,7 +181,7 @@
<argument index="1" name="shape_id" type="int">
</argument>
<description>
- Removes related shape from the owner.
+ Removes a shape from the given shape owner.
</description>
</method>
<method name="shape_owner_set_disabled">
@@ -184,6 +192,7 @@
<argument index="1" name="disabled" type="bool">
</argument>
<description>
+ If [code]true[/code] disables the given shape owner.
</description>
</method>
<method name="shape_owner_set_transform">
@@ -194,6 +203,7 @@
<argument index="1" name="transform" type="Transform">
</argument>
<description>
+ Sets the [Transform] of the given shape owner.
</description>
</method>
</methods>
@@ -209,7 +219,7 @@
</argument>
<argument index="1" name="event" type="Object">
</argument>
- <argument index="2" name="click_pos" type="Vector3">
+ <argument index="2" name="click_position" type="Vector3">
</argument>
<argument index="3" name="click_normal" type="Vector3">
</argument>
@@ -220,10 +230,12 @@
</signal>
<signal name="mouse_entered">
<description>
+ Emitted when the mouse pointer enters any of this object's shapes.
</description>
</signal>
<signal name="mouse_exited">
<description>
+ Emitted when the mouse pointer exits all this object's shapes.
</description>
</signal>
</signals>
diff --git a/doc/classes/CollisionObject2D.xml b/doc/classes/CollisionObject2D.xml
index db1412805f..52743bd37d 100644
--- a/doc/classes/CollisionObject2D.xml
+++ b/doc/classes/CollisionObject2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CollisionObject2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Base node for 2D collisionables.
+ Base node for 2D collision objects.
</brief_description>
<description>
- CollisionObject2D is the base class for 2D physics collisionables. They can hold any number of 2D collision shapes. Usually, they are edited by placing [CollisionShape2D] and/or [CollisionPolygon2D] nodes as children. Such nodes are for reference and not present outside the editor, so code should use the regular shape API.
+ CollisionObject2D is the base class for 2D physics objects. It can hold any number of 2D collision [Shape2D]\ s. Each shape must be assigned to a [i]shape owner[/i]. The CollisionObject2D can have any number of shape owners. Shape owners are not nodes and do not appear in the editor, but are accessible through code using the [code]shape_owner_*[/code] methods.
</description>
<tutorials>
</tutorials>
@@ -29,21 +29,21 @@
<argument index="0" name="owner" type="Object">
</argument>
<description>
- Creates new holder for the shapes. Argument is a [CollisionShape2D] node. It will return owner_id which usually you will want to save for later use.
+ Creates a new shape owner for the given object. Returns [code]owner_id[/code] of the new owner for future reference.
</description>
</method>
<method name="get_rid" qualifiers="const">
<return type="RID">
</return>
<description>
- Return the RID of this object.
+ Returns the object's [RID].
</description>
</method>
<method name="get_shape_owners">
<return type="Array">
</return>
<description>
- Shape owner is a node which is holding concrete shape resources. This method will return an array which is holding an integer numbers that are representing unique ID of each owner. You can use those ids when you are using others shape_owner methods.
+ Returns an [Array] of [code]owner_id[/code] identifiers. You can use these ids in other methods that take [code]owner_id[/code] as an argument.
</description>
</method>
<method name="is_pickable" qualifiers="const">
@@ -59,6 +59,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
+ If [code]true[/code] the shape owner and its shapes are disabled.
</description>
</method>
<method name="is_shape_owner_one_way_collision_enabled" qualifiers="const">
@@ -75,6 +76,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
+ Removes the given shape owner.
</description>
</method>
<method name="set_pickable">
@@ -92,6 +94,7 @@
<argument index="0" name="shape_index" type="int">
</argument>
<description>
+ Returns the [code]owner_id[/code] of the given shape.
</description>
</method>
<method name="shape_owner_add_shape">
@@ -102,6 +105,7 @@
<argument index="1" name="shape" type="Shape2D">
</argument>
<description>
+ Adds a [Shape2D] to the shape owner.
</description>
</method>
<method name="shape_owner_clear_shapes">
@@ -110,7 +114,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
- Will remove all the shapes associated with given owner.
+ Removes all shapes from the shape owner.
</description>
</method>
<method name="shape_owner_get_owner" qualifiers="const">
@@ -119,6 +123,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
+ Returns the parent object of the given shape owner.
</description>
</method>
<method name="shape_owner_get_shape" qualifiers="const">
@@ -129,7 +134,7 @@
<argument index="1" name="shape_id" type="int">
</argument>
<description>
- Will return a [Shape2D]. First argument owner_id is an integer that can be obtained from [method get_shape_owners]. Shape_id is a position of the shape inside owner; it's a value in range from 0 to [method shape_owner_get_shape_count].
+ Returns the [Shape2D] with the given id from the given shape owner.
</description>
</method>
<method name="shape_owner_get_shape_count" qualifiers="const">
@@ -138,7 +143,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
- Returns number of shapes to which given owner is associated to.
+ Returns the number of shapes the given shape owner contains.
</description>
</method>
<method name="shape_owner_get_shape_index" qualifiers="const">
@@ -157,7 +162,7 @@
<argument index="0" name="owner_id" type="int">
</argument>
<description>
- Will return [Transform2D] of an owner node.
+ Returns the shape owner's [Transform2D].
</description>
</method>
<method name="shape_owner_remove_shape">
@@ -168,7 +173,7 @@
<argument index="1" name="shape_id" type="int">
</argument>
<description>
- Removes related shape from the owner.
+ Removes a shape from the given shape owner.
</description>
</method>
<method name="shape_owner_set_disabled">
@@ -179,6 +184,7 @@
<argument index="1" name="disabled" type="bool">
</argument>
<description>
+ If [code]true[/code] disables the given shape owner.
</description>
</method>
<method name="shape_owner_set_one_way_collision">
@@ -199,11 +205,13 @@
<argument index="1" name="transform" type="Transform2D">
</argument>
<description>
+ Sets the [Transform2D] of the given shape owner.
</description>
</method>
</methods>
<members>
<member name="input_pickable" type="bool" setter="set_pickable" getter="is_pickable">
+ If [code]true[/code] this object is pickable. A pickable object can detect the mouse pointer entering/leaving, and if the mouse is inside it, report input events.
</member>
</members>
<signals>
@@ -215,16 +223,17 @@
<argument index="2" name="shape_idx" type="int">
</argument>
<description>
+ Emitted when an input event occurs and [code]input_pickable[/code] is [code]true[/code].
</description>
</signal>
<signal name="mouse_entered">
<description>
- This event fires only once when the mouse pointer enters any shape of this object.
+ Emitted when the mouse pointer enters any of this object's shapes.
</description>
</signal>
<signal name="mouse_exited">
<description>
- This event fires only once when the mouse pointer exits all shapes of this object.
+ Emitted when the mouse pointer exits all this object's shapes.
</description>
</signal>
</signals>
diff --git a/doc/classes/CollisionPolygon.xml b/doc/classes/CollisionPolygon.xml
index cf425e3d60..c2496424d6 100644
--- a/doc/classes/CollisionPolygon.xml
+++ b/doc/classes/CollisionPolygon.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CollisionPolygon" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Editor-only class for defining a collision polygon in 3D space.
</brief_description>
<description>
+ Allows editing a collision polygon's vertices on a selected plane. Can also set a depth perpendicular to that plane. This class is only available in the editor. It will not appear in the scene tree at runtime. Creates a [Shape] for gameplay. Properties modified during gameplay will have no effect.
</description>
<tutorials>
</tutorials>
@@ -54,10 +56,13 @@
</methods>
<members>
<member name="depth" type="float" setter="set_depth" getter="get_depth">
+ Length that the resulting collision extends in either direction perpendicular to its polygon.
</member>
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled">
+ If true, no collision will be produced.
</member>
<member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon">
+ Array of vertices which define the polygon.
</member>
</members>
<constants>
diff --git a/doc/classes/CollisionPolygon2D.xml b/doc/classes/CollisionPolygon2D.xml
index b602610167..7f30e8e83e 100644
--- a/doc/classes/CollisionPolygon2D.xml
+++ b/doc/classes/CollisionPolygon2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="CollisionPolygon2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Editor-only class for easy editing of collision polygons.
+ Defines a 2D collision polygon.
</brief_description>
<description>
- Editor-only class. This is not present when running the game. It's used in the editor to properly edit and position collision shapes in [CollisionObject2D]. This is not accessible from regular code. This class is for editing custom shape polygons.
+ Provides a 2D collision polygon to a [CollisionObject2D] parent. Polygon can be drawn in the editor or specified by a list of vertices.
</description>
<tutorials>
</tutorials>
@@ -75,18 +75,24 @@
</methods>
<members>
<member name="build_mode" type="int" setter="set_build_mode" getter="get_build_mode" enum="CollisionPolygon2D.BuildMode">
+ Collision build mode. Use one of the [code]BUILD_*[/code] constants. Default value: [code]BUILD_SOLIDS[/code].
</member>
<member name="disabled" type="bool" setter="set_disabled" getter="is_disabled">
+ If [code]true[/code] no collisions will be detected.
</member>
<member name="one_way_collision" type="bool" setter="set_one_way_collision" getter="is_one_way_collision_enabled">
+ If [code]true[/code] only edges that face up, relative to CollisionPolygon2D's rotation, will collide with other objects.
</member>
<member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon">
+ The polygon's list of vertices. The final point will be connected to the first.
</member>
</members>
<constants>
<constant name="BUILD_SOLIDS" value="0">
+ Collisions will include the polygon and its contained area.
</constant>
<constant name="BUILD_SEGMENTS" value="1">
+ Collisions will only include the polygon edges.
</constant>
</constants>
</class>
diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml
index 5d77f3a450..b3bdd1d6c2 100644
--- a/doc/classes/Control.xml
+++ b/doc/classes/Control.xml
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Control" inherits="CanvasItem" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Base node for all User Interface components.
+ All User Interface nodes inherit from Control. Features anchors and margins to adapt its position and size to its parent.
</brief_description>
<description>
- The base class Node for all User Interface components. Every UI node inherits from it. Any scene or portion of a scene tree composed of Control nodes is a User Interface.
- Controls use anchors and margins to place themselves relative to their parent. They adapt automatically when their parent or the screen size changes. To build flexible UIs, use built-in [Container] nodes or create your own.
- Anchors work by defining which margin do they follow, and a value relative to it. Allowed anchoring modes are ANCHOR_BEGIN, where the margin is relative to the top or left margins of the parent (in pixels), ANCHOR_END for the right and bottom margins of the parent and ANCHOR_RATIO, which is a ratio from 0 to 1 in the parent range.
- Godot sends Input events to the root node first, via [method Node._input]. The method distributes it through the node tree and delivers the input events to the node under the mouse cursor or on focus with the keyboard. To do so, it calls [method MainLoop._input_event]. No need to enable [method Node.set_process_input] on Controls to receive input events. Call [method accept_event] to ensure no other node receives the event, not even [method Node._unhandled_input].
- Only the one Control node in focus receives keyboard events. To do so, the Control must get the focus mode with [method set_focus_mode]. It loses focus when another Control gets it, or if the current Control in focus is hidden.
- You'll sometimes want Controls to ignore mouse or touch events. For example, if you place an icon on top of a button. Call [method set_ignore_mouse] for that.
- [Theme] resources change the Control's appearance. If you change the [Theme] on a parent Control node, it will propagate to all of its children. You can override parts of the theme on each Control with the add_*_override methods, like [method add_font_override]. You can also override the theme from the editor.
+ Base class for all User Interface or [i]UI[/i] related nodes. [code]Control[/code] features a bounding rectangle that defines its extents, an anchor position relative to its parent and margins that represent an offset to the anchor. The margins update automatically when the node, any of its parents, or the screen size change.
+ For more information on Godot's UI system, anchors, margins, and containers, see the related tutorials in the manual. To build flexible UIs, you'll need a mix of UI elements that inherit from [code]Control[/code] and [Container] nodes.
+ [b]User Interface nodes and input[/b]
+ Godot sends input events to the scene's root node first, by calling [method Node._input]. [method Node._input] forwards the event down the node tree to the nodes under the mouse cursor, or on keyboard focus. To do so, it calls [method MainLoop._input_event]. Call [method accept_event] so no other node receives the event. Once you accepted an input, it becomes handled so [method Node._unhandled_input] will not process it.
+ Only one [code]Control[/code] node can be in keyboard focus. Only the node in focus will receive keyboard events. To get the foucs, call [method set_focus_mode]. [code]Control[/code] nodes lose focus when another node grabs it, or if you hide the node in focus.
+ Call [method set_ignore_mouse] to tell a [code]Control[/code] node to ignore mouse or touch events. You'll need it if you place an icon on top of a button.
+ [Theme] resources change the Control's appearance. If you change the [Theme] on a [code]Control[/code] node, it affects all of its children. To override some of the theme's parameters, call one of the [code]add_*_override[/code] methods, like [method add_font_override]. You can override the theme with the inspector.
</description>
<tutorials>
</tutorials>
@@ -21,7 +21,7 @@
<return type="Vector2">
</return>
<description>
- Returns the minimum size this Control can shrink to. A control will never be displayed or resized smaller than its minimum size.
+ Returns the minimum size this Control can shrink to. The node can never be smaller than this minimum size.
</description>
</method>
<method name="_gui_input" qualifiers="virtual">
@@ -30,13 +30,15 @@
<argument index="0" name="event" type="InputEvent">
</argument>
<description>
+ The node's parent forwards input events to this method. Use it to process and accept inputs on UI elements. See [method accept_event].
+ Replaces Godot 2's [code]_input_event[/code].
</description>
</method>
<method name="accept_event">
<return type="void">
</return>
<description>
- Marks the input event as handled. No other Control will receive it, and the input event will not propagate. Not even to nodes listening to [method Node._unhandled_input] or [method Node._unhandled_key_input].
+ Marks an input event as handled. Once you accept an input event, it stops propagating, even to nodes listening to [method Node._unhandled_input] or [method Node._unhandled_key_input].
</description>
</method>
<method name="add_color_override">
@@ -47,6 +49,7 @@
<argument index="1" name="color" type="Color">
</argument>
<description>
+ Overrides the color in the [theme] resource the node uses.
</description>
</method>
<method name="add_constant_override">
@@ -57,7 +60,7 @@
<argument index="1" name="constant" type="int">
</argument>
<description>
- Override a single constant (integer) in the theme of this Control. If constant equals Theme.INVALID_CONSTANT, override is cleared.
+ Overrides an integer constant in the [theme] resource the node uses. If the [code]constant[code] is invalid, Godot clears the override. See [member Theme.INVALID_CONSTANT] for more information.
</description>
</method>
<method name="add_font_override">
@@ -68,7 +71,7 @@
<argument index="1" name="font" type="Font">
</argument>
<description>
- Override a single font (font) in the theme of this Control. If font is empty, override is cleared.
+ Overrides the [code]name[/code] font in the [theme] resource the node uses. If [code]font[/code] is empty, Godot clears the override.
</description>
</method>
<method name="add_icon_override">
@@ -79,7 +82,7 @@
<argument index="1" name="texture" type="Texture">
</argument>
<description>
- Override a single icon ([Texture]) in the theme of this Control. If texture is empty, override is cleared.
+ Overrides the [code]name[/code] icon in the [theme] resource the node uses. If [code]icon[/code] is empty, Godot clears the override.
</description>
</method>
<method name="add_shader_override">
@@ -90,6 +93,7 @@
<argument index="1" name="shader" type="Shader">
</argument>
<description>
+ Overrides the [code]name[/code] shader in the [theme] resource the node uses. If [code]shader[/code] is empty, Godot clears the override.
</description>
</method>
<method name="add_style_override">
@@ -100,13 +104,13 @@
<argument index="1" name="stylebox" type="StyleBox">
</argument>
<description>
- Override a single stylebox ([Stylebox]) in the theme of this Control. If stylebox is empty, override is cleared.
+ Overrides the [code]name[/code] [Stylebox] in the [theme] resource the node uses. If [code]stylebox[/code] is empty, Godot clears the override.
</description>
</method>
<method name="can_drop_data" qualifiers="virtual">
<return type="bool">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="data" type="Variant">
</argument>
@@ -116,7 +120,7 @@
<method name="drop_data" qualifiers="virtual">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="data" type="Variant">
</argument>
@@ -177,10 +181,10 @@
<method name="get_cursor_shape" qualifiers="const">
<return type="int" enum="Control.CursorShape">
</return>
- <argument index="0" name="pos" type="Vector2" default="Vector2( 0, 0 )">
+ <argument index="0" name="position" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<description>
- Return the cursor shape at a certain position in the control.
+ Returns the mouse cursor shape the control displays on mouse hover, one of the [code]CURSOR_*[/code] constants.
</description>
</method>
<method name="get_custom_minimum_size" qualifiers="const">
@@ -193,13 +197,13 @@
<return type="int" enum="Control.CursorShape">
</return>
<description>
- Return the default cursor shape for this control. See enum CURSOR_* for the list of shapes.
+ Returns the default cursor shape for this control. See enum [code]CURSOR_*[/code] for the list of shapes.
</description>
</method>
<method name="get_drag_data" qualifiers="virtual">
<return type="Object">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
</description>
@@ -390,7 +394,7 @@
<method name="get_tooltip" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="atpos" type="Vector2" default="Vector2( 0, 0 )">
+ <argument index="0" name="at_position" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<description>
Return the tooltip, which will appear when the cursor is resting over this control.
@@ -596,7 +600,7 @@
<method name="set_begin">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Sets MARGIN_LEFT and MARGIN_TOP at the same time. This is a helper (see [method set_margin]).
@@ -624,7 +628,7 @@
<argument index="0" name="shape" type="int" enum="Control.CursorShape">
</argument>
<description>
- Set the default cursor shape for this control. See enum CURSOR_* for the list of shapes.
+ Sets the default cursor shape for this control. See [code]CURSOR_*[/code] for the list of available cursor shapes. Useful for Godot plugins and applications or games that use the system's mouse cursors.
</description>
</method>
<method name="set_drag_forwarding">
@@ -646,7 +650,7 @@
<method name="set_end">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Sets MARGIN_RIGHT and MARGIN_BOTTOM at the same time. This is a helper (see [method set_margin]).
@@ -675,7 +679,7 @@
<method name="set_global_position">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Move the Control to a new position, relative to the top-left corner of the [i]window[/i] Control, and without changing current anchor mode. (see [method set_margin]).
@@ -729,7 +733,7 @@
<method name="set_position">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Move the Control to a new position, relative to the top-left corner of the parent Control, changing all margins if needed and without changing current anchor mode. This is a helper (see [method set_margin]).
@@ -785,7 +789,7 @@
<argument index="0" name="theme" type="Theme">
</argument>
<description>
- Override whole the [Theme] for this Control and all its children controls.
+ Overrides the whole [Theme] for this node and all its [code]Control[/code] children.
</description>
</method>
<method name="set_tooltip">
@@ -794,7 +798,7 @@
<argument index="0" name="tooltip" type="String">
</argument>
<description>
- Set a tooltip, which will appear when the cursor is resting over this control.
+ Changes the tooltip text. The tooltip appears when the user's mouse cursor stays idle over this control for a few moments.
</description>
</method>
<method name="set_v_grow_direction">
@@ -826,7 +830,7 @@
<method name="warp_mouse">
<return type="void">
</return>
- <argument index="0" name="to_pos" type="Vector2">
+ <argument index="0" name="to_position" type="Vector2">
</argument>
<description>
</description>
@@ -834,58 +838,83 @@
</methods>
<members>
<member name="anchor_bottom" type="float" setter="_set_anchor" getter="get_anchor">
+ Anchors the bottom edge of the node to the origin, the center, or the end of its parent container. It changes how the bottom margin updates when the node moves or changes size. Use one of the [code]ANCHOR_*[/code] constants. Default value: [code]ANCHOR_BEGIN[/code].
</member>
<member name="anchor_left" type="float" setter="_set_anchor" getter="get_anchor">
+ Anchors the left edge of the node to the origin, the center or the end of its parent container. It changes how the left margin updates when the node moves or changes size. Use one of the [code]ANCHOR_*[/code] constants. Default value: [code]ANCHOR_BEGIN[/code].
</member>
<member name="anchor_right" type="float" setter="_set_anchor" getter="get_anchor">
+ Anchors the right edge of the node to the origin, the center or the end of its parent container. It changes how the right margin updates when the node moves or changes size. Use one of the [code]ANCHOR_*[/code] constants. Default value: [code]ANCHOR_BEGIN[/code].
</member>
<member name="anchor_top" type="float" setter="_set_anchor" getter="get_anchor">
+ Anchors the top edge of the node to the origin, the center or the end of its parent container. It changes how the top margin updates when the node moves or changes size. Use one of the [code]ANCHOR_*[/code] constants. Default value: [code]ANCHOR_BEGIN[/code].
</member>
<member name="focus_neighbour_bottom" type="NodePath" setter="set_focus_neighbour" getter="get_focus_neighbour">
+ Tells Godot which node it should give keyboard focus to if the user presses Tab, the down arrow on the keyboard, or down on a gamepad. The node must be a [code]Control[/code]. If this property is not set, Godot will give focus to the closest [code]Control[/code] to the bottom of this one.
+ If the user presses Tab, Godot will give focus to the closest node to the right first, then to the bottom. If the user presses Shift+Tab, Godot will look to the left of the node, then above it.
</member>
<member name="focus_neighbour_left" type="NodePath" setter="set_focus_neighbour" getter="get_focus_neighbour">
+ Tells Godot which node it should give keyboard focus to if the user presses Shift+Tab, the left arrow on the keyboard or left on a gamepad. The node must be a [code]Control[/code]. If this property is not set, Godot will give focus to the closest [code]Control[/code] to the left of this one.
</member>
<member name="focus_neighbour_right" type="NodePath" setter="set_focus_neighbour" getter="get_focus_neighbour">
+ Tells Godot which node it should give keyboard focus to if the user presses Tab, the right arrow on the keyboard or right on a gamepad. The node must be a [code]Control[/code]. If this property is not set, Godot will give focus to the closest [code]Control[/code] to the bottom of this one.
</member>
<member name="focus_neighbour_top" type="NodePath" setter="set_focus_neighbour" getter="get_focus_neighbour">
+ Tells Godot which node it should give keyboard focus to if the user presses Shift+Tab, the top arrow on the keyboard or top on a gamepad. The node must be a [code]Control[/code]. If this property is not set, Godot will give focus to the closest [code]Control[/code] to the bottom of this one.
</member>
<member name="grow_horizontal" type="int" setter="set_h_grow_direction" getter="get_h_grow_direction" enum="Control.GrowDirection">
</member>
<member name="grow_vertical" type="int" setter="set_v_grow_direction" getter="get_v_grow_direction" enum="Control.GrowDirection">
</member>
<member name="hint_tooltip" type="String" setter="set_tooltip" getter="_get_tooltip">
+ Changes the tooltip text. The tooltip appears when the user's mouse cursor stays idle over this control for a few moments.
</member>
<member name="margin_bottom" type="float" setter="set_margin" getter="get_margin">
+ Distance between the node's bottom edge and its parent container, based on [member anchor_bottom].
+ Margins are often controlled by one or multiple parent [Container] nodes. Margins update automatically when you move or resize the node.
</member>
<member name="margin_left" type="float" setter="set_margin" getter="get_margin">
+ Distance between the node's left edge and its parent container, based on [member anchor_left].
</member>
<member name="margin_right" type="float" setter="set_margin" getter="get_margin">
+ Distance between the node's right edge and its parent container, based on [member anchor_right].
</member>
<member name="margin_top" type="float" setter="set_margin" getter="get_margin">
+ Distance between the node's top edge and its parent container, based on [member anchor_top].
</member>
<member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" enum="Control.MouseFilter">
</member>
<member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents">
</member>
<member name="rect_min_size" type="Vector2" setter="set_custom_minimum_size" getter="get_custom_minimum_size">
+ The minimum size of the node's bounding rectangle. If you set it to a value greater than (0, 0), the node's bounding rectangle will always have at least this size, even if its content is smaller. If it's set to (0, 0), the node sizes automatically to fit its content, be it a texture or child nodes.
</member>
<member name="rect_pivot_offset" type="Vector2" setter="set_pivot_offset" getter="get_pivot_offset">
+ By default, the node's pivot is its top-left corner. When you change its [member rect_scale], it will scale around this pivot. Set this property to [member rect_size] / 2 to center the pivot in the node's rectangle.
</member>
<member name="rect_position" type="Vector2" setter="set_position" getter="get_position">
+ The node's position, relative to its parent. It corresponds to the rectangle's top-left corner. The property is not affected by [member rect_pivot_offset].
</member>
<member name="rect_rotation" type="float" setter="set_rotation_deg" getter="get_rotation_deg">
+ The node's rotation around its pivot, in degrees. See [member rect_pivot_offset] to change the pivot's position.
</member>
<member name="rect_scale" type="Vector2" setter="set_scale" getter="get_scale">
+ The node's scale, relative to its [member rect_size]. Change this property to scale the node around its [member rect_pivot_offset].
</member>
<member name="rect_size" type="Vector2" setter="set_size" getter="get_size">
+ The size of the node's bounding rectangle, in pixels. [Container] nodes update this property automatically.
</member>
<member name="size_flags_horizontal" type="int" setter="set_h_size_flags" getter="get_h_size_flags">
+ Tells the parent [Container] nodes how they should resize and place the node on the X axis. Use one of the [code]SIZE_*[/code] constants to change the flags. See the constants to learn what each does.
</member>
<member name="size_flags_stretch_ratio" type="float" setter="set_stretch_ratio" getter="get_stretch_ratio">
+ If the node and at least one of its neighbours uses the [code]SIZE_EXPAND[/code] size flag, the parent [Container] will let it take more or less space depending on this property. If this node has a stretch ratio of 2 and its neighbour a ratio of 1, this node will take two thirds of the available space.
</member>
<member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags">
+ Tells the parent [Container] nodes how they should resize and place the node on the Y axis. Use one of the [code]SIZE_*[/code] constants to change the flags. See the constants to learn what each does.
</member>
<member name="theme" type="Theme" setter="set_theme" getter="get_theme">
+ Changing this property replaces the current [Theme] resource this node and all its [code]Control[/code] children use.
</member>
</members>
<signals>
@@ -903,6 +932,7 @@
<argument index="0" name="ev" type="Object">
</argument>
<description>
+ Emitted when the node receives an [InputEvent].
</description>
</signal>
<signal name="minimum_size_changed">
@@ -912,16 +942,17 @@
</signal>
<signal name="modal_closed">
<description>
+ Emitted when a modal [code]Control[/code] is closed. See [method show_modal].
</description>
</signal>
<signal name="mouse_entered">
<description>
- Emitted when the mouse enters the control's area.
+ Emitted when the mouse enters the control's [code]Rect[/code] area.
</description>
</signal>
<signal name="mouse_exited">
<description>
- Emitted when the mouse leaves the control's area.
+ Emitted when the mouse leaves the control's [code]Rect[/code] area.
</description>
</signal>
<signal name="resized">
@@ -931,116 +962,154 @@
</signal>
<signal name="size_flags_changed">
<description>
- Emitted when the size flags change.
+ Emitted when one of the size flags changes. See [member size_flags_horizontal] and [member size_flags_vertical].
</description>
</signal>
</signals>
<constants>
<constant name="FOCUS_NONE" value="0">
- Control can't acquire focus.
+ The node cannot grab focus. Use with [member set_focus_mode].
</constant>
<constant name="FOCUS_CLICK" value="1">
- Control can acquire focus only if clicked.
+ The node can only grab focus on mouse clicks. Use with [member set_focus_mode].
</constant>
<constant name="FOCUS_ALL" value="2">
- Control can acquire focus if clicked, or by pressing TAB/Directionals in the keyboard from another Control.
+ The node can grab focus on mouse click or using the arrows and the Tab keys on the keyboard. Use with [member set_focus_mode].
</constant>
<constant name="NOTIFICATION_RESIZED" value="40" enum="">
- Control changed size (get_size() reports the new size).
+ Sent when the node changes size. Use [member rect_size] to get the new size.
</constant>
<constant name="NOTIFICATION_MOUSE_ENTER" value="41" enum="">
- Mouse pointer entered the area of the Control.
+ Sent when the mouse pointer enters the node's [code]Rect[/code] area.
</constant>
<constant name="NOTIFICATION_MOUSE_EXIT" value="42" enum="">
- Mouse pointer exited the area of the Control.
+ Sent when the mouse pointer exits the node's [code]Rect[/code] area.
</constant>
<constant name="NOTIFICATION_FOCUS_ENTER" value="43" enum="">
- Control gained focus.
+ Sent when the node grabs focus.
</constant>
<constant name="NOTIFICATION_FOCUS_EXIT" value="44" enum="">
- Control lost focus.
+ Sent when the node loses focus.
</constant>
<constant name="NOTIFICATION_THEME_CHANGED" value="45" enum="">
- Theme changed. Redrawing is desired.
+ Sent when the node's [member theme] changes, right before Godot redraws the [code]Control[/code]. Happens when you call one of the [code]add_*_override[/code]
</constant>
<constant name="NOTIFICATION_MODAL_CLOSE" value="46" enum="">
- Modal control was closed.
+ Sent when an open modal dialog closes. See [member show_modal].
</constant>
<constant name="CURSOR_ARROW" value="0">
+ Show the system's arrow mouse cursor when the user hovers the node. Use with [method set_default_cursor_shape].
</constant>
<constant name="CURSOR_IBEAM" value="1">
+ Show the system's I-beam mouse cursor when the user hovers the node. The I-beam pointer has a shape similar to "I". It tells the user they can highlight or insert text.
</constant>
<constant name="CURSOR_POINTING_HAND" value="2">
+ Show the system's pointing hand mouse cursor when the user hovers the node.
</constant>
<constant name="CURSOR_CROSS" value="3">
+ Show the system's cross mouse cursor when the user hovers the node.
</constant>
<constant name="CURSOR_WAIT" value="4">
+ Show the system's wait mouse cursor, often an hourglass, when the user hovers the node.
</constant>
<constant name="CURSOR_BUSY" value="5">
+ Show the system's busy mouse cursor when the user hovers the node. Often an hourglass.
</constant>
<constant name="CURSOR_DRAG" value="6">
+ Show the system's drag mouse cursor, often a closed fist or a cross symbol, when the user hovers the node. It tells the user they're currently dragging an item, like a node in the Scene dock.
</constant>
<constant name="CURSOR_CAN_DROP" value="7">
+ Show the system's drop mouse cursor when the user hovers the node. It can be an open hand. It tells the user they can drop an item they're currently grabbing, like a node in the Scene dock.
</constant>
<constant name="CURSOR_FORBIDDEN" value="8">
+ Show the system's forbidden mouse cursor when the user hovers the node. Often a crossed circle.
</constant>
<constant name="CURSOR_VSIZE" value="9">
+ Show the system's vertical resize mouse cursor when the user hovers the node. A double headed vertical arrow. It tells the user they can resize the window or the panel vertically.
</constant>
<constant name="CURSOR_HSIZE" value="10">
+ Show the system's horizontal resize mouse cursor when the user hovers the node. A double headed horizontal arrow. It tells the user they can resize the window or the panel horizontally.
</constant>
<constant name="CURSOR_BDIAGSIZE" value="11">
+ Show the system's window resize mouse cursor when the user hovers the node. The cursor is a double headed arrow that goes from the bottom left to the top right. It tells the user they can resize the window or the panel both horizontally and vertically.
</constant>
<constant name="CURSOR_FDIAGSIZE" value="12">
+ Show the system's window resize mouse cursor when the user hovers the node. The cursor is a double headed arrow that goes from the top left to the bottom right, the opposite of [code]CURSOR_BDIAGSIZE[/code]. It tells the user they can resize the window or the panel both horizontally and vertically.
</constant>
<constant name="CURSOR_MOVE" value="13">
+ Show the system's move mouse cursor when the user hovers the node. It shows 2 double-headed arrows at a 90 degree angle. It tells the user they can move a UI element freely.
</constant>
<constant name="CURSOR_VSPLIT" value="14">
+ Show the system's vertical split mouse cursor when the user hovers the node. On Windows, it's the same as [code]CURSOR_VSIZE[/code].
</constant>
<constant name="CURSOR_HSPLIT" value="15">
+ Show the system's horizontal split mouse cursor when the user hovers the node. On Windows, it's the same as [code]CURSOR_HSIZE[/code].
</constant>
<constant name="CURSOR_HELP" value="16">
+ Show the system's help mouse cursor when the user hovers the node, a question mark.
</constant>
<constant name="PRESET_TOP_LEFT" value="0">
+ Snap all 4 anchors to the top-left of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_TOP_RIGHT" value="1">
+ Snap all 4 anchors to the top-right of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_BOTTOM_LEFT" value="2">
+ Snap all 4 anchors to the bottom-left of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_BOTTOM_RIGHT" value="3">
+ Snap all 4 anchors to the bottom-right of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_CENTER_LEFT" value="4">
+ Snap all 4 anchors to the center of the left edge of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_CENTER_TOP" value="5">
+ Snap all 4 anchors to the center of the top edge of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_CENTER_RIGHT" value="6">
+ Snap all 4 anchors to the center of the right edge of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_CENTER_BOTTOM" value="7">
+ Snap all 4 anchors to the center of the bottom edge of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_CENTER" value="8">
+ Snap all 4 anchors to the center of the parent container's bounds. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_LEFT_WIDE" value="9">
+ Snap all 4 anchors to the left edge of the parent container. The left margin becomes relative to the left edge and the top margin relative to the top left corner of the node's parent. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_TOP_WIDE" value="10">
+ Snap all 4 anchors to the top edge of the parent container. The left margin becomes relative to the top left corner, the top margin relative to the top edge, and the right margin relative to the top right corner of the node's parent. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_RIGHT_WIDE" value="11">
+ Snap all 4 anchors to the right edge of the parent container. The right margin becomes relative to the right edge and the top margin relative to the top right corner of the node's parent. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_BOTTOM_WIDE" value="12">
+ Snap all 4 anchors to the bottom edge of the parent container. The left margin becomes relative to the bottom left corner, the bottom margin relative to the bottom edge, and the right margin relative to the bottom right corner of the node's parent. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_VCENTER_WIDE" value="13">
+ Snap all 4 anchors to a vertical line that cuts the parent container in half. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_HCENTER_WIDE" value="14">
+ Snap all 4 anchors to a horizontal line that cuts the parent container in half. Use with [method set_anchors_preset].
</constant>
<constant name="PRESET_WIDE" value="15">
+ Snap all 4 anchors to the respective corners of the parent container. Set all 4 margins to 0 after you applied this preset and the [code]Control[/code] will fit its parent container. Use with [method set_anchors_preset].
</constant>
<constant name="SIZE_EXPAND" value="2">
+ Tells the parent [Container] to let this node take all the available space on the axis you flag. If multiple neighboring nodes are set to expand, they'll share the space based on their stretch ratio. See [member size_flags_stretch_ratio]. Use with [member size_flags_horizontal] and [member size_flags_vertical].
</constant>
<constant name="SIZE_FILL" value="1">
+ Tells the parent [Container] to expand the bounds of this node to fill all the available space without pushing any other node. Use with [member size_flags_horizontal] and [member size_flags_vertical].
</constant>
<constant name="SIZE_EXPAND_FILL" value="3">
+ Sets the node's size flags to both fill and expand. See the 2 constants above for more information.
</constant>
<constant name="SIZE_SHRINK_CENTER" value="4">
+ Tells the parent [Container] to center the node in itself. It centers the [code]Control[/code] based on its bounding box, so it doesn't work with the fill or expand size flags. Use with [member size_flags_horizontal] and [member size_flags_vertical].
</constant>
<constant name="SIZE_SHRINK_END" value="8">
+ Tells the parent [Container] to align the node with its end, either the bottom or the right edge. It doesn't work with the fill or expand size flags. Use with [member size_flags_horizontal] and [member size_flags_vertical].
</constant>
<constant name="MOUSE_FILTER_STOP" value="0">
</constant>
@@ -1053,10 +1122,10 @@
<constant name="GROW_DIRECTION_END" value="1">
</constant>
<constant name="ANCHOR_BEGIN" value="0">
- X is relative to MARGIN_LEFT, Y is relative to MARGIN_TOP.
+ Snaps one of the 4 anchor's sides to the origin of the node's [code]Rect[/code], in the top left. Use it with one of the [code]anchor_*[/code] member variables, like [member anchor_left]. To change all 4 anchors at once, use [method set_anchors_preset].
</constant>
<constant name="ANCHOR_END" value="1">
- X is relative to -MARGIN_RIGHT, Y is relative to -MARGIN_BOTTOM.
+ Snaps one of the 4 anchor's sides to the end of the node's [code]Rect[/code], in the bottom right. Use it with one of the [code]anchor_*[/code] member variables, like [member anchor_left]. To change all 4 anchors at once, use [method set_anchors_preset].
</constant>
</constants>
</class>
diff --git a/doc/classes/Curve.xml b/doc/classes/Curve.xml
index d676f635c9..ef43d9024c 100644
--- a/doc/classes/Curve.xml
+++ b/doc/classes/Curve.xml
@@ -12,7 +12,7 @@
<method name="add_point">
<return type="int">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="left_tangent" type="float" default="0">
</argument>
@@ -77,7 +77,7 @@
<description>
</description>
</method>
- <method name="get_point_pos" qualifiers="const">
+ <method name="get_point_position" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="index" type="int">
diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml
index ccf6101829..4362887be3 100644
--- a/doc/classes/Curve2D.xml
+++ b/doc/classes/Curve2D.xml
@@ -15,17 +15,17 @@
<method name="add_point">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="in" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<argument index="2" name="out" type="Vector2" default="Vector2( 0, 0 )">
</argument>
- <argument index="3" name="atpos" type="int" default="-1">
+ <argument index="3" name="at_position" type="int" default="-1">
</argument>
<description>
- Adds a point to a curve, at position "pos", with control points "in" and "out".
- If "atpos" is given, the point is inserted before the point number "atpos", moving that point (and every point after) after the inserted point. If "atpos" is not given, or is an illegal value (atpos &lt;0 or atpos &gt;= [method get_point_count]), the point will be appended at the end of the point list.
+ Adds a point to a curve, at "position", with control points "in" and "out".
+ If "at_position" is given, the point is inserted before the point number "at_position", moving that point (and every point after) after the inserted point. If "at_position" is not given, or is an illegal value (at_position &lt;0 or at_position &gt;= [method get_point_count]), the point will be appended at the end of the point list.
</description>
</method>
<method name="clear_points">
@@ -80,7 +80,7 @@
Returns the position of the control point leading out of the vertex "idx". If the index is out of bounds, the function sends an error to the console, and returns (0, 0).
</description>
</method>
- <method name="get_point_pos" qualifiers="const">
+ <method name="get_point_position" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="idx" type="int">
@@ -146,7 +146,7 @@
</return>
<argument index="0" name="idx" type="int">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<description>
Sets the position of the control point leading to the vertex "idx". If the index is out of bounds, the function sends an error to the console.
@@ -157,18 +157,18 @@
</return>
<argument index="0" name="idx" type="int">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<description>
Sets the position of the control point leading out of the vertex "idx". If the index is out of bounds, the function sends an error to the console.
</description>
</method>
- <method name="set_point_pos">
+ <method name="set_point_position">
<return type="void">
</return>
<argument index="0" name="idx" type="int">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<description>
Sets the position for the vertex "idx". If the index is out of bounds, the function sends an error to the console.
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index 8ea0e04b14..02299753cf 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -15,17 +15,17 @@
<method name="add_point">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector3">
+ <argument index="0" name="position" type="Vector3">
</argument>
<argument index="1" name="in" type="Vector3" default="Vector3( 0, 0, 0 )">
</argument>
<argument index="2" name="out" type="Vector3" default="Vector3( 0, 0, 0 )">
</argument>
- <argument index="3" name="atpos" type="int" default="-1">
+ <argument index="3" name="at_position" type="int" default="-1">
</argument>
<description>
- Adds a point to a curve, at position "pos", with control points "in" and "out".
- If "atpos" is given, the point is inserted before the point number "atpos", moving that point (and every point after) after the inserted point. If "atpos" is not given, or is an illegal value (atpos &lt;0 or atpos &gt;= [method get_point_count]), the point will be appended at the end of the point list.
+ Adds a point to a curve, at "position", with control points "in" and "out".
+ If "at_position" is given, the point is inserted before the point number "at_position", moving that point (and every point after) after the inserted point. If "at_position" is not given, or is an illegal value (at_position &lt;0 or at_position &gt;= [method get_point_count]), the point will be appended at the end of the point list.
</description>
</method>
<method name="clear_points">
@@ -87,7 +87,7 @@
Returns the position of the control point leading out of the vertex "idx". If the index is out of bounds, the function sends an error to the console, and returns (0, 0, 0).
</description>
</method>
- <method name="get_point_pos" qualifiers="const">
+ <method name="get_point_position" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="idx" type="int">
@@ -162,7 +162,7 @@
</return>
<argument index="0" name="idx" type="int">
</argument>
- <argument index="1" name="pos" type="Vector3">
+ <argument index="1" name="position" type="Vector3">
</argument>
<description>
Sets the position of the control point leading to the vertex "idx". If the index is out of bounds, the function sends an error to the console.
@@ -173,18 +173,18 @@
</return>
<argument index="0" name="idx" type="int">
</argument>
- <argument index="1" name="pos" type="Vector3">
+ <argument index="1" name="position" type="Vector3">
</argument>
<description>
Sets the position of the control point leading out of the vertex "idx". If the index is out of bounds, the function sends an error to the console.
</description>
</method>
- <method name="set_point_pos">
+ <method name="set_point_position">
<return type="void">
</return>
<argument index="0" name="idx" type="int">
</argument>
- <argument index="1" name="pos" type="Vector3">
+ <argument index="1" name="position" type="Vector3">
</argument>
<description>
Sets the position for the vertex "idx". If the index is out of bounds, the function sends an error to the console.
diff --git a/doc/classes/EditorImportPlugin.xml b/doc/classes/EditorImportPlugin.xml
index 0ced30bda6..05319e926c 100644
--- a/doc/classes/EditorImportPlugin.xml
+++ b/doc/classes/EditorImportPlugin.xml
@@ -1,8 +1,54 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="EditorImportPlugin" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Registers a custom resource importer in the editor. Use the class to parse any file and import it as a new resource type.
</brief_description>
<description>
+ EditorImportPlugins provide a way to extend the editor's resource import functionality. Use them to import resources from custom files or to provide alternatives to the editor's existing importers. Register your [EditorPlugin] with [method EditorPlugin.add_import_plugin].
+
+ EditorImportPlugins work by associating with specific file extensions and a resource type. See [method get_recognized_extension] and [method get_resource_type]). They may optionally specify some import presets that affect the import process. EditorImportPlugins are responsible for creating the resources and saving them in the [code].import[/code] directory.
+
+
+ Below is an example EditorImportPlugin that imports a [Mesh] from a file with the extension ".special" or ".spec":
+ [codeblock]
+ tool
+ extends EditorImportPlugin
+
+ func get_importer_name():
+ return "my.special.plugin"
+
+ func get_visible_name():
+ return "Special Mesh Importer"
+
+ func get_recognized_extensions():
+ return ["special", "spec"]
+
+ func get_save_extension():
+ return "mesh"
+
+ func get_resource_type():
+ return "Mesh"
+
+ func get_preset_count():
+ return 1
+
+ func get_preset_name(i):
+ return "Default"
+
+ func get_import_optons(i):
+ return [{"name": "my_option", "default_value": false}]
+
+ func load(src, dst, opts, r_platform_variants, r_gen_files):
+ var f = File.new()
+ if f.open(src, File.READ) != OK:
+ return FAILED
+
+ var mesh = Mesh.new()
+
+ var save = dst + "." + get_save_extension()
+ ResourceSaver.save(file, mesh)
+ return OK
+ [/codeblock]
</description>
<tutorials>
</tutorials>
@@ -15,12 +61,14 @@
<argument index="0" name="preset" type="int">
</argument>
<description>
+ Get the options and default values for the preset at this index. Returns an Array of Dictionaries with the following keys: "name", "default_value", "property_hint" (optional), "hint_string" (optional), "usage" (optional).
</description>
</method>
<method name="get_importer_name" qualifiers="virtual">
<return type="String">
</return>
<description>
+ Get the unique name of the importer.
</description>
</method>
<method name="get_option_visibility" qualifiers="virtual">
@@ -37,6 +85,7 @@
<return type="int">
</return>
<description>
+ Get the number of initial presets defined by the plugin. Use [method get_import_options] to get the default options for the preset and [method get_preset_name] to get the name of the preset.
</description>
</method>
<method name="get_preset_name" qualifiers="virtual">
@@ -45,30 +94,35 @@
<argument index="0" name="preset" type="int">
</argument>
<description>
+ Get the name of the options preset at this index.
</description>
</method>
<method name="get_recognized_extensions" qualifiers="virtual">
<return type="Array">
</return>
<description>
+ Get the list of file extensions to associate with this loader (case insensitive). e.g. ["obj"].
</description>
</method>
<method name="get_resource_type" qualifiers="virtual">
<return type="String">
</return>
<description>
+ Get the godot resource type associated with this loader. e.g. "Mesh" or "Animation".
</description>
</method>
<method name="get_save_extension" qualifiers="virtual">
<return type="String">
</return>
<description>
+ Get the extension used to save this resource in the [code].import[/code] directory.
</description>
</method>
<method name="get_visible_name" qualifiers="virtual">
<return type="String">
</return>
<description>
+ Get the name to display in the import window.
</description>
</method>
<method name="import" qualifiers="virtual">
diff --git a/doc/classes/EditorResourceConversionPlugin.xml b/doc/classes/EditorResourceConversionPlugin.xml
new file mode 100644
index 0000000000..e165ae376b
--- /dev/null
+++ b/doc/classes/EditorResourceConversionPlugin.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="EditorResourceConversionPlugin" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="_convert" qualifiers="virtual">
+ <return type="Resource">
+ </return>
+ <argument index="0" name="resource" type="Resource">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="_converts_to" qualifiers="virtual">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/EditorResourcePreview.xml b/doc/classes/EditorResourcePreview.xml
index e530557a23..acf36b6a08 100644
--- a/doc/classes/EditorResourcePreview.xml
+++ b/doc/classes/EditorResourcePreview.xml
@@ -41,7 +41,7 @@
<argument index="3" name="userdata" type="Variant">
</argument>
<description>
- Queue a resource being edited for preview (using an instance). Once the preview is ready, your receiver.receiver_func will be called either containing the preview texture or an empty texure (if no preview was possible). Callback must have the format: (path,texture,userdata). Userdata can be anything.
+ Queue a resource being edited for preview (using an instance). Once the preview is ready, your receiver.receiver_func will be called either containing the preview texture or an empty texture (if no preview was possible). Callback must have the format: (path,texture,userdata). Userdata can be anything.
</description>
</method>
<method name="queue_resource_preview">
@@ -56,7 +56,7 @@
<argument index="3" name="userdata" type="Variant">
</argument>
<description>
- Queue a resource file for preview (using a path). Once the preview is ready, your receiver.receiver_func will be called either containing the preview texture or an empty texure (if no preview was possible). Callback must have the format: (path,texture,userdata). Userdata can be anything.
+ Queue a resource file for preview (using a path). Once the preview is ready, your receiver.receiver_func will be called either containing the preview texture or an empty texture (if no preview was possible). Callback must have the format: (path,texture,userdata). Userdata can be anything.
</description>
</method>
<method name="remove_preview_generator">
diff --git a/doc/classes/EditorSpatialGizmo.xml b/doc/classes/EditorSpatialGizmo.xml
index de9ea5282a..baab995fab 100644
--- a/doc/classes/EditorSpatialGizmo.xml
+++ b/doc/classes/EditorSpatialGizmo.xml
@@ -24,6 +24,8 @@
</return>
<argument index="0" name="triangles" type="TriangleMesh">
</argument>
+ <argument index="1" name="bounds" type="Rect3">
+ </argument>
<description>
Add collision triangles to the gizmo for picking. A [TriangleMesh] can be generated from a regular [Mesh] too. Call this function during [method redraw].
</description>
diff --git a/doc/classes/Environment.xml b/doc/classes/Environment.xml
index 4338b188a6..3880c45a86 100644
--- a/doc/classes/Environment.xml
+++ b/doc/classes/Environment.xml
@@ -1,8 +1,15 @@
<?xml version="1.0" encoding="UTF-8" ?>
-<class name="Environment" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
+<class name="Environment" inherits="Resource" category="Core" version="3.0">
<brief_description>
+ Resource for environment nodes (like [WorldEnvironment]) that define multiple rendering options.
</brief_description>
<description>
+ Resource for environment nodes (like [WorldEnvironment]) that define multiple environment operations (such as background [Sky] or [Color], ambient light, fog, depth-of-field...). These parameters affect the final render of the scene. The order of these operations is:
+ - DOF Blur
+ - Motion Blur
+ - Bloom
+ - Tonemap (auto exposure)
+ - Adjustments
</description>
<tutorials>
</tutorials>
@@ -982,118 +989,174 @@
</methods>
<members>
<member name="adjustment_brightness" type="float" setter="set_adjustment_brightness" getter="get_adjustment_brightness">
+ Global brightness value of the rendered scene (default value is 1).
</member>
<member name="adjustment_color_correction" type="Texture" setter="set_adjustment_color_correction" getter="get_adjustment_color_correction">
+ Applies the provided [Texture] resource to affect the global color aspect of the rendered scene.
</member>
<member name="adjustment_contrast" type="float" setter="set_adjustment_contrast" getter="get_adjustment_contrast">
+ Global contrast value of the rendered scene (default value is 1).
</member>
<member name="adjustment_enabled" type="bool" setter="set_adjustment_enable" getter="is_adjustment_enabled">
+ Enables the adjustment_* options provided by this resource. If false, adjustments modifications will have no effect on the rendered scene.
</member>
<member name="adjustment_saturation" type="float" setter="set_adjustment_saturation" getter="get_adjustment_saturation">
+ Global color saturation value of the rendered scene (default value is 1).
</member>
<member name="ambient_light_color" type="Color" setter="set_ambient_light_color" getter="get_ambient_light_color">
+ [Color] of the ambient light.
</member>
<member name="ambient_light_energy" type="float" setter="set_ambient_light_energy" getter="get_ambient_light_energy">
+ Energy of the ambient light. The higher the value, the stronger the light.
</member>
<member name="ambient_light_sky_contribution" type="float" setter="set_ambient_light_sky_contribution" getter="get_ambient_light_sky_contribution">
+ Defines the amount of light that the sky brings on the scene. A value of 0 means that the sky's light emission has no effect on the scene illumination, thus all ambient illumination is provided by the ambient light. On the contrary, a value of 1 means that all the light that affects the scene is provided by the sky, thus the ambient light parameter has no effect on the scene.
</member>
<member name="auto_exposure_enabled" type="bool" setter="set_tonemap_auto_exposure" getter="get_tonemap_auto_exposure">
+ Enables the tonemapping auto exposure mode of the scene renderer. If activated, the renderer will automatically determine the exposure setting to adapt to the illumination of the scene and the observed light.
</member>
<member name="auto_exposure_max_luma" type="float" setter="set_tonemap_auto_exposure_max" getter="get_tonemap_auto_exposure_max">
+ Maximum luminance value for the auto exposure.
</member>
<member name="auto_exposure_min_luma" type="float" setter="set_tonemap_auto_exposure_min" getter="get_tonemap_auto_exposure_min">
+ Minimum luminance value for the auto exposure.
</member>
<member name="auto_exposure_scale" type="float" setter="set_tonemap_auto_exposure_grey" getter="get_tonemap_auto_exposure_grey">
+ Scale of the auto exposure effect. Affects the intensity of auto exposure.
</member>
<member name="auto_exposure_speed" type="float" setter="set_tonemap_auto_exposure_speed" getter="get_tonemap_auto_exposure_speed">
+ Speed of the auto exposure effect. Affects the time needed for the camera to perform auto exposure.
</member>
<member name="background_canvas_max_layer" type="int" setter="set_canvas_max_layer" getter="get_canvas_max_layer">
+ Maximum layer id (if using Layer background mode).
</member>
<member name="background_color" type="Color" setter="set_bg_color" getter="get_bg_color">
+ Color displayed for clear areas of the scene (if using Custom color or Color+Sky background modes).
</member>
<member name="background_energy" type="float" setter="set_bg_energy" getter="get_bg_energy">
+ Power of light emitted by the background.
</member>
<member name="background_mode" type="int" setter="set_background" getter="get_background" enum="Environment.BGMode">
+ Defines the mode of background.
</member>
<member name="background_sky" type="Sky" setter="set_sky" getter="get_sky">
+ [Sky] resource defined as background.
</member>
<member name="background_sky_scale" type="float" setter="set_sky_scale" getter="get_sky_scale">
+ [Sky] resource's scale.
</member>
<member name="dof_blur_far_amount" type="float" setter="set_dof_blur_far_amount" getter="get_dof_blur_far_amount">
+ Amount of far blur.
</member>
<member name="dof_blur_far_distance" type="float" setter="set_dof_blur_far_distance" getter="get_dof_blur_far_distance">
+ Distance from the camera where the far blur effect affects the rendering.
</member>
<member name="dof_blur_far_enabled" type="bool" setter="set_dof_blur_far_enabled" getter="is_dof_blur_far_enabled">
+ Enables the far blur effect.
</member>
<member name="dof_blur_far_quality" type="int" setter="set_dof_blur_far_quality" getter="get_dof_blur_far_quality" enum="Environment.DOFBlurQuality">
+ Quality of the far blur quality.
</member>
<member name="dof_blur_far_transition" type="float" setter="set_dof_blur_far_transition" getter="get_dof_blur_far_transition">
+ Transition between no-blur area and far blur.
</member>
<member name="dof_blur_near_amount" type="float" setter="set_dof_blur_near_amount" getter="get_dof_blur_near_amount">
+ Amount of near blur.
</member>
<member name="dof_blur_near_distance" type="float" setter="set_dof_blur_near_distance" getter="get_dof_blur_near_distance">
+ Distance from the camera where the near blur effect affects the rendering.
</member>
<member name="dof_blur_near_enabled" type="bool" setter="set_dof_blur_near_enabled" getter="is_dof_blur_near_enabled">
+ Enables the near blur effect.
</member>
<member name="dof_blur_near_quality" type="int" setter="set_dof_blur_near_quality" getter="get_dof_blur_near_quality" enum="Environment.DOFBlurQuality">
+ Quality of the near blur quality.
</member>
<member name="dof_blur_near_transition" type="float" setter="set_dof_blur_near_transition" getter="get_dof_blur_near_transition">
+ Transition between near blur and no-blur area.
</member>
<member name="fog_color" type="Color" setter="set_fog_color" getter="get_fog_color">
+ Fog's [Color].
</member>
<member name="fog_depth_begin" type="float" setter="set_fog_depth_begin" getter="get_fog_depth_begin">
+ Fog's depth starting distance from the camera.
</member>
<member name="fog_depth_curve" type="float" setter="set_fog_depth_curve" getter="get_fog_depth_curve">
+ Value defining the fog depth intensity.
</member>
<member name="fog_depth_enabled" type="bool" setter="set_fog_depth_enabled" getter="is_fog_depth_enabled">
+ Enables the fog depth.
</member>
<member name="fog_enabled" type="bool" setter="set_fog_enabled" getter="is_fog_enabled">
+ Enables the fog. Needs fog_height_enabled and/or for_depth_enabled to actually display fog.
</member>
<member name="fog_height_curve" type="float" setter="set_fog_height_curve" getter="get_fog_height_curve">
+ Value defining the fog height intensity.
</member>
<member name="fog_height_enabled" type="bool" setter="set_fog_height_enabled" getter="is_fog_height_enabled">
+ Enables the fog height.
</member>
<member name="fog_height_max" type="float" setter="set_fog_height_max" getter="get_fog_height_max">
+ Maximum height of fog.
</member>
<member name="fog_height_min" type="float" setter="set_fog_height_min" getter="get_fog_height_min">
+ Minimum height of fog.
</member>
<member name="fog_sun_amount" type="float" setter="set_fog_sun_amount" getter="get_fog_sun_amount">
+ Amount of sun that affects the fog rendering.
</member>
<member name="fog_sun_color" type="Color" setter="set_fog_sun_color" getter="get_fog_sun_color">
+ Sun [Color].
</member>
<member name="fog_transmit_curve" type="float" setter="set_fog_transmit_curve" getter="get_fog_transmit_curve">
+ Amount of light that the fog transmits.
</member>
<member name="fog_transmit_enabled" type="bool" setter="set_fog_transmit_enabled" getter="is_fog_transmit_enabled">
+ Enables fog's light transmission. If enabled, lets reflections light to be transmitted by the fog.
</member>
<member name="glow_bicubic_upscale" type="bool" setter="set_glow_bicubic_upscale" getter="is_glow_bicubic_upscale_enabled">
</member>
<member name="glow_blend_mode" type="int" setter="set_glow_blend_mode" getter="get_glow_blend_mode" enum="Environment.GlowBlendMode">
+ Glow blending mode.
</member>
<member name="glow_bloom" type="float" setter="set_glow_bloom" getter="get_glow_bloom">
+ Bloom value (global glow).
</member>
<member name="glow_enabled" type="bool" setter="set_glow_enabled" getter="is_glow_enabled">
+ Enables glow rendering.
</member>
<member name="glow_hdr_scale" type="float" setter="set_glow_hdr_bleed_scale" getter="get_glow_hdr_bleed_scale">
+ Bleed scale of the HDR glow.
</member>
<member name="glow_hdr_threshold" type="float" setter="set_glow_hdr_bleed_threshold" getter="get_glow_hdr_bleed_threshold">
+ Bleed threshold of the HDR glow.
</member>
<member name="glow_intensity" type="float" setter="set_glow_intensity" getter="get_glow_intensity">
+ Glow intensity.
</member>
<member name="glow_levels/1" type="bool" setter="set_glow_level" getter="is_glow_level_enabled">
+ First level of glow (most local).
</member>
<member name="glow_levels/2" type="bool" setter="set_glow_level" getter="is_glow_level_enabled">
+ Second level of glow.
</member>
<member name="glow_levels/3" type="bool" setter="set_glow_level" getter="is_glow_level_enabled">
+ Third level of glow.
</member>
<member name="glow_levels/4" type="bool" setter="set_glow_level" getter="is_glow_level_enabled">
+ Fourth level of glow.
</member>
<member name="glow_levels/5" type="bool" setter="set_glow_level" getter="is_glow_level_enabled">
+ Fifth level of glow.
</member>
<member name="glow_levels/6" type="bool" setter="set_glow_level" getter="is_glow_level_enabled">
+ Sixth level of glow.
</member>
<member name="glow_levels/7" type="bool" setter="set_glow_level" getter="is_glow_level_enabled">
+ Seventh level of glow (most global).
</member>
<member name="glow_strength" type="float" setter="set_glow_strength" getter="get_glow_strength">
+ Glow strength.
</member>
<member name="ss_reflections_depth_tolerance" type="float" setter="set_ssr_depth_tolerance" getter="get_ssr_depth_tolerance">
</member>
@@ -1126,48 +1189,69 @@
<member name="ssao_radius2" type="float" setter="set_ssao_radius2" getter="get_ssao_radius2">
</member>
<member name="tonemap_exposure" type="float" setter="set_tonemap_exposure" getter="get_tonemap_exposure">
+ Default exposure for tonemap.
</member>
<member name="tonemap_mode" type="int" setter="set_tonemapper" getter="get_tonemapper" enum="Environment.ToneMapper">
+ Tonemapping mode.
</member>
<member name="tonemap_white" type="float" setter="set_tonemap_white" getter="get_tonemap_white">
+ White reference value for tonemap.
</member>
</members>
<constants>
<constant name="BG_KEEP" value="5">
+ Keep on screen every pixel drawn in the background.
</constant>
<constant name="BG_CLEAR_COLOR" value="0">
+ Clear the background using the project's clear color.
</constant>
<constant name="BG_COLOR" value="1">
+ Clear the background using a custom clear color.
</constant>
<constant name="BG_SKY" value="2">
+ Display a user-defined sky in the background.
</constant>
<constant name="BG_COLOR_SKY" value="3">
+ Clear the background using a custom clear color and allows defining a sky for shading and reflection.
</constant>
<constant name="BG_CANVAS" value="4">
+ Display a [CanvasLayer] in the background.
</constant>
<constant name="BG_MAX" value="6">
+ Helper constant keeping track of the enum's size, has no direct usage in API calls.
</constant>
<constant name="GLOW_BLEND_MODE_ADDITIVE" value="0">
+ Additive glow blending mode. Mostly used for particles, glows (bloom), lens flare, bright sources.
</constant>
<constant name="GLOW_BLEND_MODE_SCREEN" value="1">
+ Screen glow blending mode. Increases brightness, used frequently with bloom.
</constant>
<constant name="GLOW_BLEND_MODE_SOFTLIGHT" value="2">
+ Softlight glow blending mode. Modifies contrast, exposes shadows and highlights, vivid bloom.
</constant>
<constant name="GLOW_BLEND_MODE_REPLACE" value="3">
+ Replace glow blending mode. Replaces all pixels' color by the glow value.
</constant>
<constant name="TONE_MAPPER_LINEAR" value="0">
+ Linear tonemapper operator. Reads the linear data and performs an exposure adjustment.
</constant>
<constant name="TONE_MAPPER_REINHARDT" value="1">
+ Reinhardt tonemapper operator. Performs a variation on rendered pixels' colors by this formula: color = color / (1 + color).
</constant>
<constant name="TONE_MAPPER_FILMIC" value="2">
+ Filmic tonemapper operator.
</constant>
<constant name="TONE_MAPPER_ACES" value="3">
+ Academy Color Encoding System tonemapper operator.
</constant>
<constant name="DOF_BLUR_QUALITY_LOW" value="0">
+ Low depth-of-field blur quality.
</constant>
<constant name="DOF_BLUR_QUALITY_MEDIUM" value="1">
+ Medium depth-of-field blur quality.
</constant>
<constant name="DOF_BLUR_QUALITY_HIGH" value="2">
+ High depth-of-field blur quality.
</constant>
</constants>
</class>
diff --git a/doc/classes/File.xml b/doc/classes/File.xml
index 4e73cd8ae2..e1a024270e 100644
--- a/doc/classes/File.xml
+++ b/doc/classes/File.xml
@@ -168,7 +168,7 @@
Get a [String] saved in Pascal format from the file.
</description>
</method>
- <method name="get_pos" qualifiers="const">
+ <method name="get_position" qualifiers="const">
<return type="int">
</return>
<description>
@@ -258,7 +258,7 @@
<method name="seek">
<return type="void">
</return>
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<description>
Change the file reading/writing cursor to the specified position (in bytes from the beginning of the file).
@@ -267,7 +267,7 @@
<method name="seek_end">
<return type="void">
</return>
- <argument index="0" name="pos" type="int" default="0">
+ <argument index="0" name="position" type="int" default="0">
</argument>
<description>
Change the file reading/writing cursor to the specified position (in bytes from the end of the file). Note that this is an offset, so you should use negative numbers or the cursor will be at the end of the file.
diff --git a/doc/classes/Font.xml b/doc/classes/Font.xml
index 420756975f..2e2124cbd6 100644
--- a/doc/classes/Font.xml
+++ b/doc/classes/Font.xml
@@ -16,7 +16,7 @@
</return>
<argument index="0" name="canvas_item" type="RID">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="string" type="String">
</argument>
@@ -25,7 +25,7 @@
<argument index="4" name="clip_w" type="int" default="-1">
</argument>
<description>
- Draw "string" into a canvas item using the font at a given "pos" position, with "modulate" color, and optionally clipping the width. "pos" specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
+ Draw "string" into a canvas item using the font at a given position, with "modulate" color, and optionally clipping the width. "position" specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis.
</description>
</method>
<method name="draw_char" qualifiers="const">
@@ -33,7 +33,7 @@
</return>
<argument index="0" name="canvas_item" type="RID">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="char" type="int">
</argument>
@@ -42,7 +42,7 @@
<argument index="4" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
<description>
- Draw character "char" into a canvas item using the font at a given "pos" position, with "modulate" color, and optionally kerning if "next" is passed. clipping the width. "pos" specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. The width used by the character is returned, making this function useful for drawing strings character by character.
+ Draw character "char" into a canvas item using the font at a given position, with "modulate" color, and optionally kerning if "next" is passed. clipping the width. "position" specifies the baseline, not the top. To draw from the top, [i]ascent[/i] must be added to the Y axis. The width used by the character is returned, making this function useful for drawing strings character by character.
</description>
</method>
<method name="get_ascent" qualifiers="const">
diff --git a/doc/classes/Geometry.xml b/doc/classes/Geometry.xml
index 6c301cb928..49f32bc68f 100644
--- a/doc/classes/Geometry.xml
+++ b/doc/classes/Geometry.xml
@@ -176,7 +176,7 @@
</argument>
<argument index="1" name="segment_to" type="Vector2">
</argument>
- <argument index="2" name="circle_pos" type="Vector2">
+ <argument index="2" name="circle_position" type="Vector2">
</argument>
<argument index="3" name="circle_radius" type="float">
</argument>
@@ -230,9 +230,9 @@
</argument>
<argument index="1" name="to" type="Vector3">
</argument>
- <argument index="2" name="spos" type="Vector3">
+ <argument index="2" name="sphere_position" type="Vector3">
</argument>
- <argument index="3" name="sradius" type="float">
+ <argument index="3" name="sphere_radius" type="float">
</argument>
<description>
</description>
diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml
index bd594033ee..f064029a01 100644
--- a/doc/classes/GraphEdit.xml
+++ b/doc/classes/GraphEdit.xml
@@ -177,7 +177,7 @@
</argument>
<argument index="1" name="from_slot" type="int">
</argument>
- <argument index="2" name="release_pos" type="Vector2">
+ <argument index="2" name="release_position" type="Vector2">
</argument>
<description>
</description>
@@ -228,6 +228,8 @@
<constants>
</constants>
<theme_items>
+ <theme_item name="SnapGrid" type="Texture">
+ </theme_item>
<theme_item name="bezier_len_neg" type="int">
</theme_item>
<theme_item name="bezier_len_pos" type="int">
@@ -244,7 +246,5 @@
</theme_item>
<theme_item name="reset" type="Texture">
</theme_item>
- <theme_item name="snap" type="Texture">
- </theme_item>
</theme_items>
</class>
diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml
index de1d9c1194..e230390882 100644
--- a/doc/classes/GraphNode.xml
+++ b/doc/classes/GraphNode.xml
@@ -43,7 +43,7 @@
Return the number of enabled input slots (connections) to the GraphNode.
</description>
</method>
- <method name="get_connection_input_pos">
+ <method name="get_connection_input_position">
<return type="Vector2">
</return>
<argument index="0" name="idx" type="int">
@@ -77,7 +77,7 @@
Return the number of enabled output slots (connections) of the GraphNode.
</description>
</method>
- <method name="get_connection_output_pos">
+ <method name="get_connection_output_position">
<return type="Vector2">
</return>
<argument index="0" name="idx" type="int">
diff --git a/doc/classes/ImageTexture.xml b/doc/classes/ImageTexture.xml
index 2b74a15fd5..4fcdf684c0 100644
--- a/doc/classes/ImageTexture.xml
+++ b/doc/classes/ImageTexture.xml
@@ -66,7 +66,7 @@
<argument index="0" name="path" type="String">
</argument>
<description>
- Load an [ImageTexure].
+ Load an [ImageTexture].
</description>
</method>
<method name="set_data">
diff --git a/doc/classes/ImmediateGeometry.xml b/doc/classes/ImmediateGeometry.xml
index 7b45c0c678..b12f9c99a9 100644
--- a/doc/classes/ImmediateGeometry.xml
+++ b/doc/classes/ImmediateGeometry.xml
@@ -28,7 +28,7 @@
<method name="add_vertex">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector3">
+ <argument index="0" name="position" type="Vector3">
</argument>
<description>
Add a vertex with the currently set color/uv/etc.
diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml
index f636000242..3d8b4154f8 100644
--- a/doc/classes/Input.xml
+++ b/doc/classes/Input.xml
@@ -298,7 +298,7 @@
Stops the vibration of the joypad.
</description>
</method>
- <method name="warp_mouse_pos">
+ <method name="warp_mouse_position">
<return type="void">
</return>
<argument index="0" name="to" type="Vector2">
diff --git a/doc/classes/InputEventScreenTouch.xml b/doc/classes/InputEventScreenTouch.xml
index 97c3537364..48c5626f14 100644
--- a/doc/classes/InputEventScreenTouch.xml
+++ b/doc/classes/InputEventScreenTouch.xml
@@ -33,7 +33,7 @@
<method name="set_position">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
</description>
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index 3423b8fb9c..a8d879888f 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -85,10 +85,10 @@
<description>
</description>
</method>
- <method name="get_item_at_pos" qualifiers="const">
+ <method name="get_item_at_position" qualifiers="const">
<return type="int">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="exact" type="bool" default="false">
</argument>
@@ -490,7 +490,7 @@
<signal name="item_rmb_selected">
<argument index="0" name="index" type="int">
</argument>
- <argument index="1" name="atpos" type="Vector2">
+ <argument index="1" name="at_position" type="Vector2">
</argument>
<description>
Fired when specified list item has been selected via right mouse clicking.
diff --git a/doc/classes/JSON.xml b/doc/classes/JSON.xml
new file mode 100644
index 0000000000..8bff140bb4
--- /dev/null
+++ b/doc/classes/JSON.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="JSON" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+ <brief_description>
+ Helper class for parsing JSON data.
+ </brief_description>
+ <description>
+ Helper class for parsing JSON data.
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="parse">
+ <return type="JSONParseResult">
+ </return>
+ <argument index="0" name="json" type="String">
+ </argument>
+ <description>
+ Parses a JSON encoded string and returns a [JSONParseResult] containing the result.
+ </description>
+ </method>
+ <method name="print">
+ <return type="String">
+ </return>
+ <argument index="0" name="value" type="Variant">
+ </argument>
+ <description>
+ Converts a Variant var to JSON text and returns the result. Useful for serializing data to store or send over the network.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/JSONParseResult.xml b/doc/classes/JSONParseResult.xml
new file mode 100644
index 0000000000..86edaaf1e6
--- /dev/null
+++ b/doc/classes/JSONParseResult.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="JSONParseResult" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
+ <brief_description>
+ Data class wrapper for decoded JSON.
+ </brief_description>
+ <description>
+ Returned by [method JSON.parse], [JSONParseResult] contains decoded JSON or error information if JSON source not successfully parsed. You can check if JSON source was successfully parsed with [code]if json_result.error == 0[/code].
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="get_error" qualifiers="const">
+ <return type="int" enum="Error">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_error_line" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_error_string" qualifiers="const">
+ <return type="String">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_result" qualifiers="const">
+ <return type="Variant">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_error">
+ <return type="void">
+ </return>
+ <argument index="0" name="error" type="int" enum="Error">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_error_line">
+ <return type="void">
+ </return>
+ <argument index="0" name="error_line" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_error_string">
+ <return type="void">
+ </return>
+ <argument index="0" name="error_string" type="String">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_result">
+ <return type="void">
+ </return>
+ <argument index="0" name="result" type="Variant">
+ </argument>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <members>
+ <member name="error" type="int" setter="set_error" getter="get_error" enum="Error">
+ The error type if JSON source was not successfully parsed. See [@Global Scope]ERR_* constants.
+ </member>
+ <member name="error_line" type="int" setter="set_error_line" getter="get_error_line">
+ The line number where the error occurred if JSON source was not successfully parsed.
+ </member>
+ <member name="error_string" type="String" setter="set_error_string" getter="get_error_string">
+ The error message if JSON source was not successfully parsed. See [@Global Scope]ERR_* constants.
+ </member>
+ <member name="result" type="Variant" setter="set_result" getter="get_result">
+ A [Variant] containing the parsed JSON. Use typeof() to check if it is what you expect. For exemple, if JSON source starts with braces [code]{}[/code] a [Dictionary] will be returned, if JSON source starts with array braces [code][][/code] an [Array] will be returned.
+ [i]Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert all numerical values to float types.[/i]
+ [codeblock]
+ p = JSON.parse('["hello", "world", "!"]')
+ if typeof(p) == TYPE_ARRAY:
+ print(p[0]) # prints 'hello'
+ else:
+ print("unexpected results")
+ [/codeblock]
+ </member>
+ </members>
+ <constants>
+ </constants>
+</class>
diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml
index 26c7c6125d..dddae2c0fc 100644
--- a/doc/classes/KinematicBody2D.xml
+++ b/doc/classes/KinematicBody2D.xml
@@ -63,6 +63,7 @@
<argument index="0" name="rel_vec" type="Vector2">
</argument>
<description>
+ Moves the body along the given vector. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the colliding body.
</description>
</method>
<method name="move_and_slide">
@@ -97,7 +98,7 @@
<argument index="1" name="rel_vec" type="Vector2">
</argument>
<description>
- Return true if there would be a collision if the body moved from the given point in the given direction.
+ Returns true if there would be a collision if the body moved from the given point in the given direction.
</description>
</method>
</methods>
diff --git a/doc/classes/KinematicCollision.xml b/doc/classes/KinematicCollision.xml
index 5e5b125654..b7269a646e 100644
--- a/doc/classes/KinematicCollision.xml
+++ b/doc/classes/KinematicCollision.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="KinematicCollision" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Collision data for KinematicBody2D collisions.
</brief_description>
<description>
+ Contains collision data for KinematicBody collisions. When a [KinematicBody] is moved using [method KinematicBody.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a KinematicCollision object is returned.
+ This object contains information about the collision, including the colliding object, the remaining motion, and the collision position. This information can be used to calculate a collision response.
</description>
<tutorials>
</tutorials>
@@ -78,26 +81,37 @@
</methods>
<members>
<member name="collider" type="Object" setter="" getter="get_collider">
+ The colliding body.
</member>
<member name="collider_id" type="int" setter="" getter="get_collider_id">
+ The colliding body's unique [RID].
</member>
<member name="collider_metadata" type="Variant" setter="" getter="get_collider_metadata">
+ The colliding body's metadata. See [Object].
</member>
<member name="collider_shape" type="Object" setter="" getter="get_collider_shape">
+ The colliding body's shape.
</member>
<member name="collider_shape_index" type="int" setter="" getter="get_collider_shape_index">
+ The colliding shape's index. See [CollisionObject].
</member>
<member name="collider_velocity" type="Vector3" setter="" getter="get_collider_velocity">
+ The colliding object's velocity.
</member>
<member name="local_shape" type="Object" setter="" getter="get_local_shape">
+ The moving object's colliding shape.
</member>
<member name="normal" type="Vector3" setter="" getter="get_normal">
+ The colliding body's shape's normal at the point of collision.
</member>
<member name="position" type="Vector3" setter="" getter="get_position">
+ The point of collision.
</member>
<member name="remainder" type="Vector3" setter="" getter="get_remainder">
+ The moving object's remaining movement vector.
</member>
<member name="travel" type="Vector3" setter="" getter="get_travel">
+ The distance the moving object traveled before collision.
</member>
</members>
<constants>
diff --git a/doc/classes/KinematicCollision2D.xml b/doc/classes/KinematicCollision2D.xml
index 4ef35066d0..7a40a39292 100644
--- a/doc/classes/KinematicCollision2D.xml
+++ b/doc/classes/KinematicCollision2D.xml
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="KinematicCollision2D" inherits="Reference" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Collision data for KinematicBody2D collisions.
</brief_description>
<description>
+ Contains collision data for KinematicBody2D collisions. When a [KinematicBody2D] is moved using [method KinematicBody2D.move_and_collide], it stops if it detects a collision with another body. If a collision is detected, a KinematicCollision2D object is returned.
+ This object contains information about the collision, including the colliding object, the remaining motion, and the collision position. This information can be used to calculate a collision response.
</description>
<tutorials>
</tutorials>
@@ -78,26 +81,37 @@
</methods>
<members>
<member name="collider" type="Object" setter="" getter="get_collider">
+ The colliding body.
</member>
<member name="collider_id" type="int" setter="" getter="get_collider_id">
+ The colliding body's unique [RID].
</member>
<member name="collider_metadata" type="Variant" setter="" getter="get_collider_metadata">
+ The colliding body's metadata. See [Object].
</member>
<member name="collider_shape" type="Object" setter="" getter="get_collider_shape">
+ The colliding body's shape.
</member>
<member name="collider_shape_index" type="int" setter="" getter="get_collider_shape_index">
+ The colliding shape's index. See [CollisionObject2D].
</member>
<member name="collider_velocity" type="Vector2" setter="" getter="get_collider_velocity">
+ The colliding object's velocity.
</member>
<member name="local_shape" type="Object" setter="" getter="get_local_shape">
+ The moving object's colliding shape.
</member>
<member name="normal" type="Vector2" setter="" getter="get_normal">
+ The colliding body's shape's normal at the point of collision.
</member>
<member name="position" type="Vector2" setter="" getter="get_position">
+ The point of collision.
</member>
<member name="remainder" type="Vector2" setter="" getter="get_remainder">
+ The moving object's remaining movement vector.
</member>
<member name="travel" type="Vector2" setter="" getter="get_travel">
+ The distance the moving object traveled before collision.
</member>
</members>
<constants>
diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml
index 2e860aac0c..8c5e69b407 100644
--- a/doc/classes/Label.xml
+++ b/doc/classes/Label.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Label" inherits="Control" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Control that displays formatted text.
+ Displays plain text in a line or wrapped inside a rectangle. For formatted text, use [RichTextLabel].
</brief_description>
<description>
- Label is a control that displays formatted text, optionally autowrapping it to the [Control] area. It inherits from range to be able to scroll wrapped text vertically.
+ Label displays plain text on the screen. It gives you control over the horizontal and vertical alignment, and can wrap the text inside the node's bounding rectangle. It doesn't support bold, italics or other formatting. For that, use [RichTextLabel] instead.
</description>
<tutorials>
</tutorials>
@@ -22,14 +22,14 @@
<return type="int">
</return>
<description>
- Return the amount of lines.
+ Returns the amount of lines of text the Label has.
</description>
</method>
<method name="get_line_height" qualifiers="const">
<return type="int">
</return>
<description>
- Return the height of a line.
+ Returns the font size in pixels.
</description>
</method>
<method name="get_lines_skipped" qualifiers="const">
@@ -98,14 +98,14 @@
<return type="bool">
</return>
<description>
- Return true if text would be cut off if it is too wide.
+ Return [code]true[/code] if text would be cut off if it is too wide.
</description>
</method>
<method name="is_uppercase" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if text is displayed in all capitals.
+ Return [code]true[/code] if text is displayed in all capitals.
</description>
</method>
<method name="set_align">
@@ -201,22 +201,31 @@
</methods>
<members>
<member name="align" type="int" setter="set_align" getter="get_align" enum="Label.Align">
+ Controls the text's horizontal align. Supports left, center, right, and fill, or justify. Set it to one of the [code]ALIGN_*[/code] constants.
</member>
<member name="autowrap" type="bool" setter="set_autowrap" getter="has_autowrap">
+ If [code]true[/code], wraps the text inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. Default: false.
</member>
<member name="clip_text" type="bool" setter="set_clip_text" getter="is_clipping_text">
+ If [code]true[/code], the Label only shows the text that fits inside its bounding rectangle. It also lets you scale the node down freely.
</member>
<member name="lines_skipped" type="int" setter="set_lines_skipped" getter="get_lines_skipped">
+ The node ignores the first [code]lines_skipped[/code] lines before it starts to display text.
</member>
<member name="max_lines_visible" type="int" setter="set_max_lines_visible" getter="get_max_lines_visible">
+ Limits the lines of text the node shows on screen.
</member>
<member name="percent_visible" type="float" setter="set_percent_visible" getter="get_percent_visible">
+ Limits the count of visible characters. If you set [code]percent_visible[/code] to 50, only up to half of the text's characters will display on screen. Useful to animate the text in a dialog box.
</member>
<member name="text" type="String" setter="set_text" getter="get_text">
+ The text to display on screen.
</member>
<member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase">
+ If [code]true[/code], all the text displays as UPPERCASE.
</member>
<member name="valign" type="int" setter="set_valign" getter="get_valign" enum="Label.VAlign">
+ Controls the text's vertical align. Supports top, center, bottom, and fill. Set it to one of the [code]VALIGN_*[/code] constants.
</member>
</members>
<constants>
diff --git a/doc/classes/Light2D.xml b/doc/classes/Light2D.xml
index 1386fc53d9..7ce7cef7c1 100644
--- a/doc/classes/Light2D.xml
+++ b/doc/classes/Light2D.xml
@@ -340,46 +340,67 @@
</methods>
<members>
<member name="color" type="Color" setter="set_color" getter="get_color">
+ The Light2D's [Color].
</member>
<member name="editor_only" type="bool" setter="set_editor_only" getter="is_editor_only">
+ If [code]true[/code] Light2D will only appear when editing the scene. Default value: [code]false[/code].
</member>
<member name="enabled" type="bool" setter="set_enabled" getter="is_enabled">
+ If [code]true[/code] Light2D will emit light. Default value: [code]true[/code].
</member>
<member name="energy" type="float" setter="set_energy" getter="get_energy">
+ The Light2D's energy value. The larger the value, the stronger the light.
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="Light2D.Mode">
+ The Light2D's mode. See MODE_* constants for values.
</member>
<member name="offset" type="Vector2" setter="set_texture_offset" getter="get_texture_offset">
+ The offset of the Light2D's [code]texture[/code].
</member>
<member name="range_height" type="float" setter="set_height" getter="get_height">
+ The height of the Light2D. Used with 2D normal mapping.
</member>
<member name="range_item_cull_mask" type="int" setter="set_item_cull_mask" getter="get_item_cull_mask">
+ The layer mask. Only objects with a matching mask will be affected by the Light2D.
</member>
<member name="range_layer_max" type="int" setter="set_layer_range_max" getter="get_layer_range_max">
+ Maximum layer value of objects that are affected by the Light2D. Default value: [code]0[/code].
</member>
<member name="range_layer_min" type="int" setter="set_layer_range_min" getter="get_layer_range_min">
+ Minimum layer value of objects that are affected by the Light2D. Default value: [code]0[/code].
</member>
<member name="range_z_max" type="int" setter="set_z_range_max" getter="get_z_range_max">
+ Maximum [code]Z[/code] value of objects that are affected by the Light2D. Default value: [code]1024[/code].
</member>
<member name="range_z_min" type="int" setter="set_z_range_min" getter="get_z_range_min">
+ Minimum [code]z[/code] value of objects that are affected by the Light2D. Default value: [code]-1024[/code].
</member>
<member name="shadow_buffer_size" type="int" setter="set_shadow_buffer_size" getter="get_shadow_buffer_size">
+ Shadow buffer size. Default value: [code]2048[/code].
</member>
<member name="shadow_color" type="Color" setter="set_shadow_color" getter="get_shadow_color">
+ [Color] of shadows cast by the Light2D.
</member>
<member name="shadow_enabled" type="bool" setter="set_shadow_enabled" getter="is_shadow_enabled">
+ If [code]true[/code] the Light2D will cast shadows. Default value: [code]false[/code].
</member>
<member name="shadow_filter" type="int" setter="set_shadow_filter" getter="get_shadow_filter" enum="Light2D.ShadowFilter">
+ Shadow filter type. May be one of [code][None, PCF5, PCF9, PCF13][/code]. Default value: [code]None[/code].
</member>
<member name="shadow_filter_smooth" type="float" setter="set_shadow_smooth" getter="get_shadow_smooth">
+ Smoothing value for shadows.
</member>
<member name="shadow_gradient_length" type="float" setter="set_shadow_gradient_length" getter="get_shadow_gradient_length">
+ Smooth shadow gradient length.
</member>
<member name="shadow_item_cull_mask" type="int" setter="set_item_shadow_cull_mask" getter="get_item_shadow_cull_mask">
+ The shadow mask. Used with [LightOccluder2D] to cast shadows. Only occluders with a matching shadow mask will cast shadows.
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
+ [Texture] used for the Light2D's appearance.
</member>
<member name="texture_scale" type="float" setter="set_texture_scale" getter="get_texture_scale">
+ The [code]texture[/code]'s scale factor.
</member>
</members>
<constants>
diff --git a/doc/classes/Line2D.xml b/doc/classes/Line2D.xml
index 81fd255781..e6e615ccf1 100644
--- a/doc/classes/Line2D.xml
+++ b/doc/classes/Line2D.xml
@@ -14,7 +14,7 @@
<method name="add_point">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Add a point at the x/y position in the supplied [Vector2]
@@ -56,7 +56,7 @@
<description>
</description>
</method>
- <method name="get_point_pos" qualifiers="const">
+ <method name="get_point_position" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="i" type="int">
@@ -149,12 +149,12 @@
<description>
</description>
</method>
- <method name="set_point_pos">
+ <method name="set_point_position">
<return type="void">
</return>
<argument index="0" name="i" type="int">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<description>
</description>
diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml
index 0577e1ba37..e6c26e3248 100644
--- a/doc/classes/LineEdit.xml
+++ b/doc/classes/LineEdit.xml
@@ -66,7 +66,7 @@
Return the align mode of the [LineEdit].
</description>
</method>
- <method name="get_cursor_pos" qualifiers="const">
+ <method name="get_cursor_position" qualifiers="const">
<return type="int">
</return>
<description>
@@ -169,10 +169,10 @@
Set text alignment of the [LineEdit].
</description>
</method>
- <method name="set_cursor_pos">
+ <method name="set_cursor_position">
<return type="void">
</return>
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<description>
Set the cursor position inside the [LineEdit], causing it to scroll if needed.
diff --git a/doc/classes/LineShape2D.xml b/doc/classes/LineShape2D.xml
index 3346c46a19..5596c48162 100644
--- a/doc/classes/LineShape2D.xml
+++ b/doc/classes/LineShape2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="LineShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Line shape for 2D collision objects.
+ Line shape for 2D collisions.
</brief_description>
<description>
- Line shape for 2D collision objects. It works like a 2D plane and will not allow any body to go to the negative side. Not recommended for rigid bodies, and usually not recommended for static bodies either because it forces checks against it on every frame.
+ Line shape for 2D collisions. It works like a 2D plane and will not allow any body to go to the negative side. Not recommended for rigid bodies, and usually not recommended for static bodies either because it forces checks against it on every frame.
</description>
<tutorials>
</tutorials>
@@ -46,8 +46,10 @@
</methods>
<members>
<member name="d" type="float" setter="set_d" getter="get_d">
+ The line's distance from the origin.
</member>
<member name="normal" type="Vector2" setter="set_normal" getter="get_normal">
+ The line's normal.
</member>
</members>
<constants>
diff --git a/doc/classes/NinePatchRect.xml b/doc/classes/NinePatchRect.xml
index 092e928ef9..6829b36e14 100644
--- a/doc/classes/NinePatchRect.xml
+++ b/doc/classes/NinePatchRect.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="NinePatchRect" inherits="Control" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Scalable texture-based frame that tiles the texture's centers and sides, but keeps the corners' original size. Perfect for panels and dialog boxes.
</brief_description>
<description>
+ Better known as 9-slice panels, NinePatchRect produces clean panels of any size, based on a small texture. To do so, it splits the texture in a 3 by 3 grid. When you scale the node, it tiles the texture's sides horizontally or vertically, the center on both axes but it doesn't scale or tile the corners.
</description>
<tutorials>
</tutorials>
@@ -100,36 +102,49 @@
</methods>
<members>
<member name="axis_stretch_horizontal" type="int" setter="set_h_axis_stretch_mode" getter="get_h_axis_stretch_mode" enum="NinePatchRect.AxisStretchMode">
+ Doesn't do anything at the time of writing.
</member>
<member name="axis_stretch_vertical" type="int" setter="set_v_axis_stretch_mode" getter="get_v_axis_stretch_mode" enum="NinePatchRect.AxisStretchMode">
+ Doesn't do anything at the time of writing.
</member>
<member name="draw_center" type="bool" setter="set_draw_center" getter="is_draw_center_enabled">
+ If [code]true[/code], draw the panel's center. Else, only draw the 9-slice's borders. Default value: [code]true[/code]
</member>
<member name="patch_margin_bottom" type="int" setter="set_patch_margin" getter="get_patch_margin">
+ The height of the 9-slice's bottom row. A margin of 16 means the 9-slice's bottom corners and side will have a height of 16 pixels. You can set all 4 margin values indivually to create panels with non-uniform borders.
</member>
<member name="patch_margin_left" type="int" setter="set_patch_margin" getter="get_patch_margin">
+ The height of the 9-slice's left column.
</member>
<member name="patch_margin_right" type="int" setter="set_patch_margin" getter="get_patch_margin">
+ The height of the 9-slice's right column.
</member>
<member name="patch_margin_top" type="int" setter="set_patch_margin" getter="get_patch_margin">
+ The height of the 9-slice's top row.
</member>
<member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect">
+ Rectangular region of the texture to sample from. If you're working with an atlas, use this property to define the area the 9-slice should use. All other properties are relative to this one.
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
+ The node's texture resource.
</member>
</members>
<signals>
<signal name="texture_changed">
<description>
+ Fired when the node's texture changes.
</description>
</signal>
</signals>
<constants>
<constant name="AXIS_STRETCH_MODE_STRETCH" value="0">
+ Doesn't do anything at the time of writing. Default value for [code]axis_stretch_horizontal[/code] and [code]axis_stretch_vertical[/code].
</constant>
<constant name="AXIS_STRETCH_MODE_TILE" value="1">
+ Doesn't do anything at the time of writing.
</constant>
<constant name="AXIS_STRETCH_MODE_TILE_FIT" value="2">
+ Doesn't do anything at the time of writing.
</constant>
</constants>
</class>
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index 5a99263f1e..e35f64a9c0 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -441,7 +441,7 @@
</return>
<argument index="0" name="child_node" type="Node">
</argument>
- <argument index="1" name="to_pos" type="int">
+ <argument index="1" name="to_position" type="int">
</argument>
<description>
Move a child node to a different position (order) amongst the other children. Since calls, signals, etc are performed by tree order, changing the order of children nodes may be useful.
diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml
index 2ba312b301..084bee92df 100644
--- a/doc/classes/Node2D.xml
+++ b/doc/classes/Node2D.xml
@@ -169,7 +169,7 @@
<method name="set_global_position">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Set the node's global position.
@@ -214,7 +214,7 @@
<method name="set_position">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Set the node's position.
diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 5b14d5a746..65200c4769 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -286,7 +286,7 @@
</description>
</method>
<method name="get_screen_orientation" qualifiers="const">
- <return type="int" enum="_OS.ScreenOrientation">
+ <return type="int" enum="OS.ScreenOrientation">
</return>
<description>
Returns the current screen orientation, the return value will be one of the SCREEN_ORIENTATION constants in this class.
@@ -331,7 +331,7 @@
<method name="get_system_dir" qualifiers="const">
<return type="String">
</return>
- <argument index="0" name="dir" type="int" enum="_OS.SystemDir">
+ <argument index="0" name="dir" type="int" enum="OS.SystemDir">
</argument>
<description>
</description>
@@ -660,7 +660,7 @@
<method name="set_screen_orientation">
<return type="void">
</return>
- <argument index="0" name="orientation" type="int" enum="_OS.ScreenOrientation">
+ <argument index="0" name="orientation" type="int" enum="OS.ScreenOrientation">
</argument>
<description>
Sets the current screen orientation, the argument value must be one of the SCREEN_ORIENTATION constants in this class.
@@ -840,15 +840,15 @@
</constant>
<constant name="SYSTEM_DIR_RINGTONES" value="7">
</constant>
- <constant name="OS::POWERSTATE_UNKNOWN" value="0">
+ <constant name="POWERSTATE_UNKNOWN" value="0">
</constant>
- <constant name="OS::POWERSTATE_ON_BATTERY" value="1">
+ <constant name="POWERSTATE_ON_BATTERY" value="1">
</constant>
- <constant name="OS::POWERSTATE_NO_BATTERY" value="2">
+ <constant name="POWERSTATE_NO_BATTERY" value="2">
</constant>
- <constant name="OS::POWERSTATE_CHARGING" value="3">
+ <constant name="POWERSTATE_CHARGING" value="3">
</constant>
- <constant name="OS::POWERSTATE_CHARGED" value="4">
+ <constant name="POWERSTATE_CHARGED" value="4">
</constant>
</constants>
</class>
diff --git a/doc/classes/Physics2DDirectBodyState.xml b/doc/classes/Physics2DDirectBodyState.xml
index 9b6fe69b4a..cc68aaab1f 100644
--- a/doc/classes/Physics2DDirectBodyState.xml
+++ b/doc/classes/Physics2DDirectBodyState.xml
@@ -45,7 +45,7 @@
Return the collider object, this depends on how it was created (will return a scene node if such was used to create it).
</description>
</method>
- <method name="get_contact_collider_pos" qualifiers="const">
+ <method name="get_contact_collider_position" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="contact_idx" type="int">
@@ -72,7 +72,7 @@
Return the metadata of the collided shape. This metadata is different from [method Object.get_meta], and is set with [method Physics2DServer.shape_set_data].
</description>
</method>
- <method name="get_contact_collider_velocity_at_pos" qualifiers="const">
+ <method name="get_contact_collider_velocity_at_position" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="contact_idx" type="int">
@@ -97,7 +97,7 @@
Return the local normal (of this body) of the contact point.
</description>
</method>
- <method name="get_contact_local_pos" qualifiers="const">
+ <method name="get_contact_local_position" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="contact_idx" type="int">
diff --git a/doc/classes/Physics2DServer.xml b/doc/classes/Physics2DServer.xml
index ab63089691..fd093edc84 100644
--- a/doc/classes/Physics2DServer.xml
+++ b/doc/classes/Physics2DServer.xml
@@ -306,7 +306,7 @@
</return>
<argument index="0" name="body" type="RID">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="impulse" type="Vector2">
</argument>
diff --git a/doc/classes/PhysicsBody.xml b/doc/classes/PhysicsBody.xml
index e8ae986346..e75fbb8e2d 100644
--- a/doc/classes/PhysicsBody.xml
+++ b/doc/classes/PhysicsBody.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PhysicsBody" inherits="CollisionObject" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Base class for different types of Physics bodies.
+ Base class for all objects affected by physics in 3D space.
</brief_description>
<description>
- PhysicsBody is an abstract base class for implementing a physics body. All PhysicsBody types inherit from it.
+ PhysicsBody is an abstract base class for implementing a physics body. All *Body types inherit from it.
</description>
<tutorials>
</tutorials>
@@ -17,7 +17,7 @@
<argument index="0" name="body" type="Node">
</argument>
<description>
- Adds a body to the collision exception list. This list contains bodies that this body will not collide with.
+ Adds a body to the list of bodies that this body can't collide with.
</description>
</method>
<method name="get_collision_layer" qualifiers="const">
@@ -54,7 +54,7 @@
<argument index="0" name="body" type="Node">
</argument>
<description>
- Removes a body from the collision exception list.
+ Removes a body from the list of bodies that this body can't collide with.
</description>
</method>
<method name="set_collision_layer">
@@ -96,8 +96,12 @@
</methods>
<members>
<member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer">
+ The physics layers this area is in.
+ Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property.
+ A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A.
</member>
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask">
+ The physics layers this area can scan for collisions.
</member>
</members>
<constants>
diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml
index e160311090..748506baa9 100644
--- a/doc/classes/PhysicsBody2D.xml
+++ b/doc/classes/PhysicsBody2D.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="PhysicsBody2D" inherits="CollisionObject2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Base class for all objects affected by physics.
+ Base class for all objects affected by physics in 2D space.
</brief_description>
<description>
PhysicsBody2D is an abstract base class for implementing a physics body. All *Body2D types inherit from it.
@@ -17,6 +17,7 @@
<argument index="0" name="body" type="Node">
</argument>
<description>
+ Adds a body to the list of bodies that this body can't collide with.
</description>
</method>
<method name="get_collision_layer" qualifiers="const">
@@ -57,6 +58,7 @@
<argument index="0" name="body" type="Node">
</argument>
<description>
+ Removes a body from the list of bodies that this body can't collide with.
</description>
</method>
<method name="set_collision_layer">
@@ -104,10 +106,15 @@
</methods>
<members>
<member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer">
+ The physics layers this area is in.
+ Collidable objects can exist in any of 32 different layers. These layers work like a tagging system, and are not visual. A collidable can use these layers to select with which objects it can collide, using the collision_mask property.
+ A contact is detected if object A is in any of the layers that object B scans, or object B is in any layer scanned by object A.
</member>
<member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask">
+ The physics layers this area can scan for collisions.
</member>
<member name="layers" type="int" setter="_set_layers" getter="_get_layers">
+ Both collision_layer and collision_mask. Returns collision_layer when accessed. Updates collision_layers and collision_mask when modified.
</member>
</members>
<constants>
diff --git a/doc/classes/PhysicsDirectBodyState.xml b/doc/classes/PhysicsDirectBodyState.xml
index de51d0e958..349b7e7c3f 100644
--- a/doc/classes/PhysicsDirectBodyState.xml
+++ b/doc/classes/PhysicsDirectBodyState.xml
@@ -14,7 +14,7 @@
</return>
<argument index="0" name="force" type="Vector3">
</argument>
- <argument index="1" name="pos" type="Vector3">
+ <argument index="1" name="position" type="Vector3">
</argument>
<description>
</description>
@@ -22,7 +22,7 @@
<method name="apply_impulse">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector3">
+ <argument index="0" name="position" type="Vector3">
</argument>
<argument index="1" name="j" type="Vector3">
</argument>
@@ -73,7 +73,7 @@
<description>
</description>
</method>
- <method name="get_contact_collider_pos" qualifiers="const">
+ <method name="get_contact_collider_position" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="contact_idx" type="int">
@@ -89,7 +89,7 @@
<description>
</description>
</method>
- <method name="get_contact_collider_velocity_at_pos" qualifiers="const">
+ <method name="get_contact_collider_velocity_at_position" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="contact_idx" type="int">
@@ -111,7 +111,7 @@
<description>
</description>
</method>
- <method name="get_contact_local_pos" qualifiers="const">
+ <method name="get_contact_local_position" qualifiers="const">
<return type="Vector3">
</return>
<argument index="0" name="contact_idx" type="int">
diff --git a/doc/classes/PhysicsServer.xml b/doc/classes/PhysicsServer.xml
index 0076625ebd..145f5a0163 100644
--- a/doc/classes/PhysicsServer.xml
+++ b/doc/classes/PhysicsServer.xml
@@ -268,7 +268,7 @@
</return>
<argument index="0" name="body" type="RID">
</argument>
- <argument index="1" name="pos" type="Vector3">
+ <argument index="1" name="position" type="Vector3">
</argument>
<argument index="2" name="impulse" type="Vector3">
</argument>
diff --git a/doc/classes/Polygon2D.xml b/doc/classes/Polygon2D.xml
index 05869c514e..23cb9bd91b 100644
--- a/doc/classes/Polygon2D.xml
+++ b/doc/classes/Polygon2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Polygon2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- 2D polygon representation
+ A 2D polygon.
</brief_description>
<description>
- A Polygon2D is defined by a set of n vertices connected together by line segments, meaning that the vertex 1 will be connected with vertex 2, vertex 2 with vertex 3 ..., vertex n-1 with vertex n and vertex n with vertex 1 in order to close the loop and define a polygon.
+ A Polygon2D is defined by a set of points. Each point is connected to the next, with the final point being connected to the first, resulting in a closed polygon. Polygon2Ds can be filled with color (solid or gradient) or filled with a given texture.
</description>
<tutorials>
</tutorials>
@@ -204,28 +204,40 @@
</methods>
<members>
<member name="antialiased" type="bool" setter="set_antialiased" getter="get_antialiased">
+ If [code]true[/code] polygon edges will be anti-aliased. Default value: [code]false[/code].
</member>
<member name="color" type="Color" setter="set_color" getter="get_color">
+ The polygon's fill color. If [code]texture[/code] is defined, it will be multiplied by this color. It will also be the default color for vertices not set in [code]vertex_colors[/code].
</member>
<member name="invert_border" type="float" setter="set_invert_border" getter="get_invert_border">
+ Added padding applied to the bounding box when using [code]invert[/code]. Setting this value too small may result in a "Bad Polygon" error. Default value: [code]100[/code].
</member>
<member name="invert_enable" type="bool" setter="set_invert" getter="get_invert">
+ If [code]true[/code] polygon will be inverted, containing the area outside the defined points and extending to the [code]invert_border[/code]. Default value: [code]false[/code].
</member>
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset">
+ The offset applied to each vertex.
</member>
<member name="polygon" type="PoolVector2Array" setter="set_polygon" getter="get_polygon">
+ The polygon's list of vertices. The final point will be connected to the first.
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
+ The polygon's fill texture. Use [code]uv[/code] to set texture coordinates.
</member>
<member name="texture_offset" type="Vector2" setter="set_texture_offset" getter="get_texture_offset">
+ Amount to offset the polygon's [code]texture[/code]. If [code](0, 0)[/code] the texture's origin (its top-left corner) will be placed at the polygon's [code]position[/code].
</member>
<member name="texture_rotation" type="float" setter="_set_texture_rotationd" getter="_get_texture_rotationd">
+ The texture's rotation in degrees.
</member>
<member name="texture_scale" type="Vector2" setter="set_texture_scale" getter="get_texture_scale">
+ Amount to multiply the [code]uv[/code] coordinates when using a [code]texture[/code]. Larger values make the texture smaller, and vice versa.
</member>
<member name="uv" type="PoolVector2Array" setter="set_uv" getter="get_uv">
+ Texture coordinates for each vertex of the polygon. There should be one [code]uv[/code] per polygon vertex. If there are fewer, undefined vertices will use [code](0, 0)[/code].
</member>
<member name="vertex_colors" type="PoolColorArray" setter="set_vertex_colors" getter="get_vertex_colors">
+ Color for each vertex. Colors are interpolated between vertices, resulting in smooth gradients. There should be one per polygon vertex. If there are fewer, undefined vertices will use [code]color[/code].
</member>
</members>
<constants>
diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml
index bec9525a45..1a3ea5c5c7 100644
--- a/doc/classes/ProjectSettings.xml
+++ b/doc/classes/ProjectSettings.xml
@@ -147,7 +147,7 @@
</return>
<argument index="0" name="name" type="String">
</argument>
- <argument index="1" name="pos" type="int">
+ <argument index="1" name="position" type="int">
</argument>
<description>
Set the order of a configuration value (influences when saved to the config file).
diff --git a/doc/classes/Range.xml b/doc/classes/Range.xml
index 9af6abf7b8..cd75c2b658 100644
--- a/doc/classes/Range.xml
+++ b/doc/classes/Range.xml
@@ -138,29 +138,38 @@
<argument index="0" name="with" type="Node">
</argument>
<description>
+ Binds two Ranges together along with any Ranges previously grouped with either of them. When any of Range's member variables change, it will share the new value with all other Ranges in its group.
</description>
</method>
<method name="unshare">
<return type="void">
</return>
<description>
+ Stop Range from sharing its member variables with any other Range.
</description>
</method>
</methods>
<members>
<member name="exp_edit" type="bool" setter="set_exp_ratio" getter="is_ratio_exp">
+ If [code]true[/code] and [code]min_value[/code] is greater than 0, [code]value[/code] will be represented exponentially rather than linearly.
</member>
<member name="max_value" type="float" setter="set_max" getter="get_max">
+ Maximum value. Range is clamped if [code]value[/code] is greater than [code]max_value[/code]. Default value: 100.
</member>
<member name="min_value" type="float" setter="set_min" getter="get_min">
+ Minimum value. Range is clamped if [code]value[/code] is less than [code]min_value[/code]. Default value: 0.
</member>
<member name="page" type="float" setter="set_page" getter="get_page">
+ Page size. Used mainly for [ScrollBar]. ScrollBar's length is its size multiplied by [code]page[/code] over the difference between [code]min_value[/code] and [code]max_value[/code].
</member>
<member name="rounded" type="bool" setter="set_use_rounded_values" getter="is_using_rounded_values">
+ If [code]true[/code], [code]value[/code] will always be rounded to the nearest integer.
</member>
<member name="step" type="float" setter="set_step" getter="get_step">
+ If greater than 0, [code]value[/code] will always be rounded to a multiple of [code]step[/code]. If [code]rounded[/code] is also [code]true[/code], [code]value[/code] will first be rounded to a multiple of [code]step[/code] then rounded to the nearest integer.
</member>
<member name="value" type="float" setter="set_value" getter="get_value">
+ Range's current value.
</member>
</members>
<signals>
diff --git a/doc/classes/RayShape.xml b/doc/classes/RayShape.xml
index 7fab9c3949..d5d367a335 100644
--- a/doc/classes/RayShape.xml
+++ b/doc/classes/RayShape.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RayShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Ray shape for 3D collisions.
</brief_description>
<description>
+ Ray shape for 3D collisions, which can be set into a [PhysicsBody] or [Area]. A ray is not really a collision body, instead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters.
</description>
<tutorials>
</tutorials>
@@ -26,6 +28,7 @@
</methods>
<members>
<member name="length" type="float" setter="set_length" getter="get_length">
+ The ray's length.
</member>
</members>
<constants>
diff --git a/doc/classes/RayShape2D.xml b/doc/classes/RayShape2D.xml
index 8414ee2348..4f6313a1d2 100644
--- a/doc/classes/RayShape2D.xml
+++ b/doc/classes/RayShape2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RayShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Ray 2D shape resource for physics.
+ Ray shape for 2D collisions.
</brief_description>
<description>
- Ray 2D shape resource for physics. A ray is not really a collision body, instead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters.
+ Ray shape for 2D collisions. A ray is not really a collision body, instead it tries to separate itself from whatever is touching its far endpoint. It's often useful for characters.
</description>
<tutorials>
</tutorials>
@@ -30,6 +30,7 @@
</methods>
<members>
<member name="length" type="float" setter="set_length" getter="get_length">
+ The ray's length.
</member>
</members>
<constants>
diff --git a/doc/classes/Rect2.xml b/doc/classes/Rect2.xml
index 1a467861b3..80f7830a16 100644
--- a/doc/classes/Rect2.xml
+++ b/doc/classes/Rect2.xml
@@ -14,7 +14,7 @@
<method name="Rect2">
<return type="Rect2">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="size" type="Vector2">
</argument>
diff --git a/doc/classes/Rect3.xml b/doc/classes/Rect3.xml
index 8837b8f812..f41665db34 100644
--- a/doc/classes/Rect3.xml
+++ b/doc/classes/Rect3.xml
@@ -14,7 +14,7 @@
<method name="Rect3">
<return type="Rect3">
</return>
- <argument index="0" name="pos" type="Vector3">
+ <argument index="0" name="position" type="Vector3">
</argument>
<argument index="1" name="size" type="Vector3">
</argument>
diff --git a/doc/classes/RectangleShape2D.xml b/doc/classes/RectangleShape2D.xml
index 9c18df970b..7a1aec2021 100644
--- a/doc/classes/RectangleShape2D.xml
+++ b/doc/classes/RectangleShape2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RectangleShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Rectangle Shape for 2D Physics.
+ Rectangle shape for 2D collisions.
</brief_description>
<description>
- Rectangle Shape for 2D Physics. This shape is useful for modeling box-like 2D objects.
+ Rectangle shape for 2D collisions. This shape is useful for modeling box-like 2D objects.
</description>
<tutorials>
</tutorials>
@@ -30,6 +30,7 @@
</methods>
<members>
<member name="extents" type="Vector2" setter="set_extents" getter="get_extents">
+ The rectangle's half extents. The width and height of this shape is twice the half extents.
</member>
</members>
<constants>
diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml
index 90ee76cb98..9f8cdcce6d 100644
--- a/doc/classes/RichTextLabel.xml
+++ b/doc/classes/RichTextLabel.xml
@@ -47,6 +47,12 @@
<description>
</description>
</method>
+ <method name="get_line_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_percent_visible" qualifiers="const">
<return type="float">
</return>
@@ -84,6 +90,12 @@
<description>
</description>
</method>
+ <method name="get_visible_line_count" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="is_meta_underlined" qualifiers="const">
<return type="bool">
</return>
diff --git a/doc/classes/RigidBody.xml b/doc/classes/RigidBody.xml
index fc9d241e35..76a93248fb 100644
--- a/doc/classes/RigidBody.xml
+++ b/doc/classes/RigidBody.xml
@@ -1,10 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RigidBody" inherits="PhysicsBody" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Rigid body node.
+ Physics Body whose position is determined through physics simulation in 3D space.
</brief_description>
<description>
- Rigid body node. This node is used for placing rigid bodies in the scene. It can contain a number of shapes, and also shift mode between regular Rigid body, Kinematic, Character or Static.
+ This is the node that implements full 3D physics. This means that you do not control a RigidBody directly. Instead you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc.
+ This node can use custom force integration, for writing complex physics motion behavior per node.
+ This node can shift state between regular Rigid body, Kinematic, Character or Static.
+ Character mode forbids this node from being rotated.
+ As a warning, don't change RigidBody's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior.
</description>
<tutorials>
</tutorials>
@@ -23,7 +27,7 @@
<method name="apply_impulse">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector3">
+ <argument index="0" name="position" type="Vector3">
</argument>
<argument index="1" name="impulse" type="Vector3">
</argument>
@@ -324,55 +328,56 @@
</methods>
<members>
<member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp">
- Dampens rotational forces of the Rigid body by the 'angular_damp' rate.
+ Damps RigidBody's rotational forces.
</member>
<member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity">
- The current rotational velocity of the Rigid body
+ RigidBody's rotational velocity.
</member>
<member name="axis_lock" type="int" setter="set_axis_lock" getter="get_axis_lock" enum="RigidBody.AxisLock">
Locks the rotational forces to a particular axis, preventing rotations on other axes.
</member>
<member name="bounce" type="float" setter="set_bounce" getter="get_bounce">
- Bounciness of the Rigid body.
+ RigidBody's bounciness.
</member>
<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep">
- If true, the Rigid body will no longer calculate forces when there is no movement and will act as a static body. It will wake up when other forces are applied through other collisions or when the 'apply_impulse' method is used.
+ If [code]true[/code] the RigidBody will not calculate forces and will act as a static body while there is no movement. It will wake up when forces are applied through other collisions or when the [code]apply_impulse[/code] method is used.
</member>
<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled">
- If true, the Rigid body will emit signals when it collides with another Rigid body.
+ If true, the RigidBody will emit signals when it collides with another RigidBody.
</member>
<member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported">
The maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0.
</member>
<member name="continuous_cd" type="bool" setter="set_use_continuous_collision_detection" getter="is_using_continuous_collision_detection">
- Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. The first is more precise, and misses less impacts by small, fast-moving objects. The second is faster to compute, but can miss small, fast-moving objects.
+ If [code]true[/code] continuous collision detection is used.
+ Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. Continuous collision detection is more precise, and misses less impacts by small, fast-moving objects. Not using continuous collision detection is faster to compute, but can miss small, fast-moving objects.
</member>
<member name="custom_integrator" type="bool" setter="set_use_custom_integrator" getter="is_using_custom_integrator">
- If true, internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined.
+ If [code]true[/code] internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined.
</member>
<member name="friction" type="float" setter="set_friction" getter="get_friction">
The body friction, from 0 (frictionless) to 1 (max friction).
</member>
<member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale">
- The 'gravity_scale' for this Rigid body will be multiplied by the global 3d gravity setting found in "Project &gt; Project Settings &gt; Physics &gt; 3d". A value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object.
+ This is multiplied by the global 3D gravity setting found in "Project &gt; Project Settings &gt; Physics &gt; 3d" to produce RigidBody's gravity. E.g. a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object.
</member>
<member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp">
- The linear damp for this body. Default of -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden.
+ RigidBody's linear damp. Default value: -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden.
</member>
<member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity">
- The body linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state.
+ RigidBody's linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state.
</member>
<member name="mass" type="float" setter="set_mass" getter="get_mass">
- The body mass.
+ RigidBody's mass.
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody.Mode">
The body mode from the MODE_* enum. Modes include: MODE_STATIC, MODE_KINEMATIC, MODE_RIGID, and MODE_CHARACTER.
</member>
<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping">
- The current 'sleeping' state of the Rigid body.
+ If [code]true[/code] RigidBody is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method.
</member>
<member name="weight" type="float" setter="set_weight" getter="get_weight">
- The body weight given standard earth-weight (gravity 9.8).
+ RigidBody's weight based on its mass and the global 3D gravity. Global values are set in "Project &gt; Project Settings &gt; Physics &gt; 3d".
</member>
</members>
<signals>
diff --git a/doc/classes/RigidBody2D.xml b/doc/classes/RigidBody2D.xml
index e92c417323..a4faa697de 100644
--- a/doc/classes/RigidBody2D.xml
+++ b/doc/classes/RigidBody2D.xml
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="RigidBody2D" inherits="PhysicsBody2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Rigid body 2D node.
+ Physics Body whose position is determined through physics simulation in 2D space.
</brief_description>
<description>
- Rigid body 2D node. This node is used for placing rigid bodies in the scene. It can contain a number of shapes, and also shift state between regular Rigid body, Kinematic, Character or Static.
- Character mode forbids the node from being rotated. This node can have a custom force integrator function, for writing complex physics motion behavior per node.
- As a warning, don't change this node position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior.
+ This is the node that implements full 2D physics. This means that you do not control a RigidBody2D directly. Instead you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc.
+ This node can use custom force integration, for writing complex physics motion behavior per node.
+ This node can shift state between regular Rigid body, Kinematic, Character or Static.
+ Character mode forbids this node from being rotated.
+ As a warning, don't change RigidBody2D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop will yield strange behavior.
</description>
<tutorials>
</tutorials>
@@ -382,36 +384,53 @@
</methods>
<members>
<member name="angular_damp" type="float" setter="set_angular_damp" getter="get_angular_damp">
+ Damps RigidBody2D's rotational forces.
</member>
<member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity">
+ RigidBody2D's rotational velocity.
</member>
<member name="bounce" type="float" setter="set_bounce" getter="get_bounce">
+ RigidBody2D's bounciness.
</member>
<member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep">
+ If [code]true[/code] RigidBody2D will not calculate forces and will act as a static body while there is no movement. It will wake up when other forces are applied through other collisions or when the [code]apply_impulse[/code] method is used. Default value: [code]true[/code]
</member>
<member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled">
+ If [code]true[/code] RigidBody2D will emit signals when it collides with another RigidBody2D.
</member>
<member name="contacts_reported" type="int" setter="set_max_contacts_reported" getter="get_max_contacts_reported">
+ The maximum contacts to report. Bodies can keep a log of the contacts with other bodies, this is enabled by setting the maximum amount of contacts reported to a number greater than 0.
</member>
<member name="continuous_cd" type="int" setter="set_continuous_collision_detection_mode" getter="get_continuous_collision_detection_mode" enum="RigidBody2D.CCDMode">
+ If [code]true[/code] continuous collision detection is used. Default value: [code]false[/code]
+ Continuous collision detection tries to predict where a moving body will collide, instead of moving it and correcting its movement if it collided. Continuous collision detection is more precise, and misses less impacts by small, fast-moving objects. Not using continuous collision detection is faster to compute, but can miss small, fast-moving objects.
</member>
<member name="custom_integrator" type="bool" setter="set_use_custom_integrator" getter="is_using_custom_integrator">
+ If [code]true[/code] internal force integration will be disabled (like gravity or air friction) for this body. Other than collision response, the body will only move as determined by the [method _integrate_forces] function, if defined.
</member>
<member name="friction" type="float" setter="set_friction" getter="get_friction">
+ The body friction, from 0 (frictionless) to 1 (max friction).
</member>
<member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale">
+ This is multiplied by the global 2D gravity setting found in "Project &gt; Project Settings &gt; Physics &gt; 2d" to produce RigidBody2D's gravity. E.g. a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object.
</member>
<member name="linear_damp" type="float" setter="set_linear_damp" getter="get_linear_damp">
+ RigidBody2D's linear damp. Default of -1, cannot be less than -1. If this value is different from -1, any linear damp derived from the world or areas will be overridden.
</member>
<member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity">
+ RigidBody2D's linear velocity. Can be used sporadically, but [b]DON'T SET THIS IN EVERY FRAME[/b], because physics may run in another thread and runs at a different granularity. Use [method _integrate_forces] as your process loop for precise control of the body state.
</member>
<member name="mass" type="float" setter="set_mass" getter="get_mass">
+ RigidBody2D's mass.
</member>
<member name="mode" type="int" setter="set_mode" getter="get_mode" enum="RigidBody2D.Mode">
+ The body mode from the MODE_* enum. Modes include: MODE_STATIC, MODE_KINEMATIC, MODE_RIGID, and MODE_CHARACTER.
</member>
<member name="sleeping" type="bool" setter="set_sleeping" getter="is_sleeping">
+ If [code]true[/code] RigidBody2D is sleeping and will not calculate forces until woken up by a collision or the [code]apply_impulse[/code] method.
</member>
<member name="weight" type="float" setter="set_weight" getter="get_weight">
+ RigidBody2D's weight based on its mass and the global 2D gravity. Global values are set in "Project &gt; Project Settings &gt; Physics &gt; 2d".
</member>
</members>
<signals>
diff --git a/doc/classes/SegmentShape2D.xml b/doc/classes/SegmentShape2D.xml
index 0e2c5c86f3..3b7a747bcb 100644
--- a/doc/classes/SegmentShape2D.xml
+++ b/doc/classes/SegmentShape2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="SegmentShape2D" inherits="Shape2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Segment Shape for 2D Collision Detection.
+ Segment shape for 2D collisions.
</brief_description>
<description>
- Segment Shape for 2D Collision Detection, consists of two points, 'a' and 'b'.
+ Segment shape for 2D collisions. Consists of two points, [code]a[/code] and [code]b[/code].
</description>
<tutorials>
</tutorials>
@@ -46,8 +46,10 @@
</methods>
<members>
<member name="a" type="Vector2" setter="set_a" getter="get_a">
+ The segment's first point position.
</member>
<member name="b" type="Vector2" setter="set_b" getter="get_b">
+ The segment's second point position.
</member>
</members>
<constants>
diff --git a/doc/classes/Shape.xml b/doc/classes/Shape.xml
index 8e6e12a736..4d822a1705 100644
--- a/doc/classes/Shape.xml
+++ b/doc/classes/Shape.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="Shape" inherits="Resource" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Base class for all 3D shape resources.
</brief_description>
<description>
+ Base class for all 3D shape resources. All 3D shapes that inherit from this can be set into a [PhysicsBody] or [Area].
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/Spatial.xml b/doc/classes/Spatial.xml
index 076d0b9bc3..54eb82fbff 100644
--- a/doc/classes/Spatial.xml
+++ b/doc/classes/Spatial.xml
@@ -4,7 +4,7 @@
Most basic 3D game object, parent of all 3D related nodes.
</brief_description>
<description>
- Most basic 3D game object, with a 3D [Transform] and visibility settings. All 3D physics nodes and sprites inherit from Spatial. Use Spatial as a parent node to move, scale, rotate and show/hide children in a 3D project.
+ Most basic 3D game object, with a 3D [Transform] and visibility settings. All other 3D game objects inherit from Spatial. Use Spatial as a parent node to move, scale, rotate and show/hide children in a 3D project.
</description>
<tutorials>
</tutorials>
@@ -15,35 +15,35 @@
<return type="SpatialGizmo">
</return>
<description>
- Return the SpatialGizmo for this node. Used for example in [EditorSpatialGizmo] as custom visualization and editing handles in Editor.
+ Returns the SpatialGizmo for this node. Used for example in [EditorSpatialGizmo] as custom visualization and editing handles in Editor.
</description>
</method>
<method name="get_global_transform" qualifiers="const">
<return type="Transform">
</return>
<description>
- Return the global transform, relative to worldspace.
+ Returns the global transform, relative to worldspace.
</description>
</method>
<method name="get_parent_spatial" qualifiers="const">
<return type="Spatial">
</return>
<description>
- Return the parent [Spatial], or an empty [Object] if no parent exists or parent is not of type [Spatial].
+ Returns the parent [Spatial], or an empty [Object] if no parent exists or parent is not of type [Spatial].
</description>
</method>
<method name="get_rotation" qualifiers="const">
<return type="Vector3">
</return>
<description>
- Return the rotation (in radians).
+ Returns the rotation (in radians).
</description>
</method>
<method name="get_rotation_deg" qualifiers="const">
<return type="Vector3">
</return>
<description>
- Return the rotation (in degrees).
+ Returns the rotation (in degrees).
</description>
</method>
<method name="get_scale" qualifiers="const">
@@ -56,7 +56,7 @@
<return type="Transform">
</return>
<description>
- Return the local transform, relative to the bone parent.
+ Returns the local transform, relative to the bone parent.
</description>
</method>
<method name="get_translation" qualifiers="const">
@@ -69,7 +69,7 @@
<return type="World">
</return>
<description>
- Return current [World] resource this Spatial node is registered to.
+ Returns the current [World] resource this Spatial node is registered to.
</description>
</method>
<method name="global_rotate">
@@ -80,7 +80,7 @@
<argument index="1" name="radians" type="float">
</argument>
<description>
- Rotate current node along normal [Vector3] by angle in radians in Global space.
+ Rotates the current node along normal [Vector3] by angle in radians in Global space.
</description>
</method>
<method name="global_translate">
@@ -89,49 +89,49 @@
<argument index="0" name="offset" type="Vector3">
</argument>
<description>
- Move current node by [Vector3] offset in Global space.
+ Moves the node by [Vector3] offset in Global space.
</description>
</method>
<method name="hide">
<return type="void">
</return>
<description>
- Disable rendering of this node. Change Spatial Visible property to false.
+ Disables rendering of this node. Change Spatial Visible property to false.
</description>
</method>
<method name="is_local_transform_notification_enabled" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns whether node sends notification that its local transformation changed. Spatial will not propagate this by default.
+ Returns whether node notifies about its local transformation changes. Spatial will not propagate this by default.
</description>
</method>
<method name="is_set_as_toplevel" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns whether this node is set as Toplevel, ignoring its parent node transformations.
+ Returns whether this node is set as Toplevel, that is whether it ignores its parent nodes transformations.
</description>
</method>
<method name="is_transform_notification_enabled" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns whether node sends notification that its transformation changed. Spatial will not propagate this by default.
+ Returns whether the node notifies about its global and local transformation changes. Spatial will not propagate this by default.
</description>
</method>
<method name="is_visible" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns whether this node is set to be visible.
+ Returns whether the node is set to be visible.
</description>
</method>
<method name="is_visible_in_tree" qualifiers="const">
<return type="bool">
</return>
<description>
- Returns whether this node is visible, taking into consideration that its parents visibility.
+ Returns whether the node is visible, taking into consideration that its parents visibility.
</description>
</method>
<method name="look_at">
@@ -145,24 +145,24 @@
Rotates itself to point into direction of target position. Operations take place in global space.
</description>
</method>
- <method name="look_at_from_pos">
+ <method name="look_at_from_position">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector3">
+ <argument index="0" name="position" type="Vector3">
</argument>
<argument index="1" name="target" type="Vector3">
</argument>
<argument index="2" name="up" type="Vector3">
</argument>
<description>
- Moves itself to specified position and then rotates itself to point into direction of target position. Operations take place in global space.
+ Moves the node to specified position and then rotates itself to point into direction of target position. Operations take place in global space.
</description>
</method>
<method name="orthonormalize">
<return type="void">
</return>
<description>
- Reset this node transformations (like scale, skew and taper) preserving its rotation and translation. Performs orthonormalization on this node [Transform3D].
+ Resets this node's transformations (like scale, skew and taper) preserving its rotation and translation. Performs orthonormalization on this node [Transform3D].
</description>
</method>
<method name="rotate">
@@ -173,7 +173,7 @@
<argument index="1" name="radians" type="float">
</argument>
<description>
- Rotates node in local space on given normal [Vector3] by angle in radians.
+ Rotates the node in local space on given normal [Vector3] by angle in radians.
</description>
</method>
<method name="rotate_x">
@@ -182,7 +182,7 @@
<argument index="0" name="radians" type="float">
</argument>
<description>
- Rotates node in local space on X axis by angle in radians.
+ Rotates the node in local space on X axis by angle in radians.
</description>
</method>
<method name="rotate_y">
@@ -191,7 +191,7 @@
<argument index="0" name="radians" type="float">
</argument>
<description>
- Rotates node in local space on Y axis by angle in radians.
+ Rotates the node in local space on Y axis by angle in radians.
</description>
</method>
<method name="rotate_z">
@@ -200,7 +200,7 @@
<argument index="0" name="radians" type="float">
</argument>
<description>
- Rotates node in local space on Z axis by angle in radians.
+ Rotates the node in local space on Z axis by angle in radians.
</description>
</method>
<method name="set_as_toplevel">
@@ -209,7 +209,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Makes this node ignore its parents tranformations. Node tranformations are only in global space.
+ Makes the node ignore its parents tranformations. Node tranformations are only in global space.
</description>
</method>
<method name="set_gizmo">
@@ -243,7 +243,7 @@
<argument index="0" name="enabled" type="bool">
</argument>
<description>
- Set whether this node ignores notification that its transformation changed.
+ Set whether the node ignores notification that its transformation (global or local) changed.
</description>
</method>
<method name="set_notify_local_transform">
@@ -252,7 +252,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set whether this node sends notification that its local transformation changed. Spatial will not propagate this by default.
+ Set whether the node notifies about its local transformation changes. Spatial will not propagate this by default.
</description>
</method>
<method name="set_notify_transform">
@@ -261,7 +261,7 @@
<argument index="0" name="enable" type="bool">
</argument>
<description>
- Set whether this node sends notification that its transformation changed. Spatial will not propagate this by default.
+ Set whether the node notifies about its global and local transformation changes. Spatial will not propagate this by default.
</description>
</method>
<method name="set_rotation">
@@ -320,7 +320,7 @@
<return type="void">
</return>
<description>
- Enable rendering of this node. Change Spatial Visible property to false.
+ Enables rendering of this node. Change Spatial Visible property to "True".
</description>
</method>
<method name="to_global" qualifiers="const">
@@ -329,7 +329,7 @@
<argument index="0" name="local_point" type="Vector3">
</argument>
<description>
- Tranform [Vector3] from this node local space to world space.
+ Tranforms [Vector3] "local_point" from this node's local space to world space.
</description>
</method>
<method name="to_local" qualifiers="const">
@@ -338,7 +338,7 @@
<argument index="0" name="global_point" type="Vector3">
</argument>
<description>
- Tranform [Vector3] from world space to this node local space.
+ Tranforms [Vector3] "global_point" from world space to this node's local space.
</description>
</method>
<method name="translate">
@@ -347,14 +347,14 @@
<argument index="0" name="offset" type="Vector3">
</argument>
<description>
- Change node position by given offset [Vector3].
+ Changes the node's position by given offset [Vector3].
</description>
</method>
<method name="update_gizmo">
<return type="void">
</return>
<description>
- Update [SpatialGizmo] of this node.
+ Updates the [SpatialGizmo] of this node.
</description>
</method>
</methods>
@@ -384,23 +384,23 @@
<signals>
<signal name="visibility_changed">
<description>
- Emitted when node visibility changed.
+ Emitted when node visibility changes.
</description>
</signal>
</signals>
<constants>
<constant name="NOTIFICATION_TRANSFORM_CHANGED" value="29" enum="">
- Spatial nodes receive this notification when their global transform changes. This means that either the current or a parent node changed its transform.
+ Spatial nodes receives this notification when their global transform changes. This means that either the current or a parent node changed its transform.
In order for NOTIFICATION_TRANSFORM_CHANGED to work user first needs to ask for it, with set_notify_transform(true).
</constant>
<constant name="NOTIFICATION_ENTER_WORLD" value="41" enum="">
- Spatial nodes receive this notification when they are registered to new [World] resource.
+ Spatial nodes receives this notification when they are registered to new [World] resource.
</constant>
<constant name="NOTIFICATION_EXIT_WORLD" value="42" enum="">
- Spatial nodes receive this notification when they are unregistered from current [World] resource.
+ Spatial nodes receives this notification when they are unregistered from current [World] resource.
</constant>
<constant name="NOTIFICATION_VISIBILITY_CHANGED" value="43" enum="">
- Spatial nodes receive this notification when their visibility changes.
+ Spatial nodes receives this notification when their visibility changes.
</constant>
</constants>
</class>
diff --git a/doc/classes/SpatialMaterial.xml b/doc/classes/SpatialMaterial.xml
index 0f1c57e85b..344a42b7c0 100644
--- a/doc/classes/SpatialMaterial.xml
+++ b/doc/classes/SpatialMaterial.xml
@@ -105,6 +105,18 @@
<description>
</description>
</method>
+ <method name="get_distance_fade_max_distance" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="get_distance_fade_min_distance" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_emission" qualifiers="const">
<return type="Color">
</return>
@@ -187,6 +199,12 @@
<description>
</description>
</method>
+ <method name="get_proximity_fade_distance" qualifiers="const">
+ <return type="float">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_refraction" qualifiers="const">
<return type="float">
</return>
@@ -297,12 +315,24 @@
<description>
</description>
</method>
+ <method name="is_distance_fade_enabled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="is_grow_enabled" qualifiers="const">
<return type="bool">
</return>
<description>
</description>
</method>
+ <method name="is_proximity_fade_enabled" qualifiers="const">
+ <return type="bool">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="set_albedo">
<return type="void">
</return>
@@ -439,6 +469,30 @@
<description>
</description>
</method>
+ <method name="set_distance_fade">
+ <return type="void">
+ </return>
+ <argument index="0" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_distance_fade_max_distance">
+ <return type="void">
+ </return>
+ <argument index="0" name="distance" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_distance_fade_min_distance">
+ <return type="void">
+ </return>
+ <argument index="0" name="distance" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_emission">
<return type="void">
</return>
@@ -555,6 +609,22 @@
<description>
</description>
</method>
+ <method name="set_proximity_fade">
+ <return type="void">
+ </return>
+ <argument index="0" name="enabled" type="bool">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="set_proximity_fade_distance">
+ <return type="void">
+ </return>
+ <argument index="0" name="distance" type="float">
+ </argument>
+ <description>
+ </description>
+ </method>
<method name="set_refraction">
<return type="void">
</return>
@@ -745,6 +815,12 @@
</member>
<member name="detail_uv_layer" type="int" setter="set_detail_uv" getter="get_detail_uv" enum="SpatialMaterial.DetailUV">
</member>
+ <member name="distance_fade_enable" type="bool" setter="set_distance_fade" getter="is_distance_fade_enabled">
+ </member>
+ <member name="distance_fade_max_distance" type="float" setter="set_distance_fade_max_distance" getter="get_distance_fade_max_distance">
+ </member>
+ <member name="distance_fade_min_distance" type="float" setter="set_distance_fade_min_distance" getter="get_distance_fade_min_distance">
+ </member>
<member name="emission" type="Color" setter="set_emission" getter="get_emission">
</member>
<member name="emission_enabled" type="bool" setter="set_feature" getter="get_feature">
@@ -811,6 +887,10 @@
</member>
<member name="particles_anim_v_frames" type="int" setter="set_particles_anim_v_frames" getter="get_particles_anim_v_frames">
</member>
+ <member name="proximity_fade_distance" type="float" setter="set_proximity_fade_distance" getter="get_proximity_fade_distance">
+ </member>
+ <member name="proximity_fade_enable" type="bool" setter="set_proximity_fade" getter="is_proximity_fade_enabled">
+ </member>
<member name="refraction_enabled" type="bool" setter="set_feature" getter="get_feature">
</member>
<member name="refraction_scale" type="float" setter="set_refraction" getter="get_refraction">
diff --git a/doc/classes/SphereShape.xml b/doc/classes/SphereShape.xml
index 120c7fcc25..7c6174f4e4 100644
--- a/doc/classes/SphereShape.xml
+++ b/doc/classes/SphereShape.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="SphereShape" inherits="Shape" category="Core" version="3.0.alpha.custom_build">
<brief_description>
+ Sphere shape for 3D collisions.
</brief_description>
<description>
+ Sphere shape for 3D collisions, which can be set into a [PhysicsBody] or [Area]. This shape is useful for modeling sphere-like 3D objects.
</description>
<tutorials>
</tutorials>
@@ -26,6 +28,7 @@
</methods>
<members>
<member name="radius" type="float" setter="set_radius" getter="get_radius">
+ The sphere's radius. The shape's diameter is double the radius.
</member>
</members>
<constants>
diff --git a/doc/classes/Sprite.xml b/doc/classes/Sprite.xml
index 90ebe79666..c0c491140f 100644
--- a/doc/classes/Sprite.xml
+++ b/doc/classes/Sprite.xml
@@ -4,7 +4,7 @@
General purpose Sprite node.
</brief_description>
<description>
- General purpose Sprite node. This Sprite node can show any texture as a sprite. The texture can be used as a spritesheet for animation, or only a region from a bigger texture can referenced, like an atlas.
+ A node that displays a 2D texture. The texture displayed can be a region from a larger atlas texture, or a frame from a sprite sheet animation.
</description>
<tutorials>
</tutorials>
@@ -202,37 +202,49 @@
</methods>
<members>
<member name="centered" type="bool" setter="set_centered" getter="is_centered">
+ If [code]true[/code] texture will be centered. Default value: [code]true[/code].
</member>
<member name="flip_h" type="bool" setter="set_flip_h" getter="is_flipped_h">
+ If [code]true[/code] texture is flipped horizontally. Default value: [code]false[/code].
</member>
<member name="flip_v" type="bool" setter="set_flip_v" getter="is_flipped_v">
+ If [code]true[/code] texture is flipped vertically. Default value: [code]false[/code].
</member>
<member name="frame" type="int" setter="set_frame" getter="get_frame">
+ Current frame to display from sprite sheet. [code]vframes[/code] or [code]hframes[/code] must be greater than 1.
</member>
<member name="hframes" type="int" setter="set_hframes" getter="get_hframes">
+ The number of horizontal frames in the sprite sheet.
</member>
<member name="normal_map" type="Texture" setter="set_normal_map" getter="get_normal_map">
</member>
<member name="offset" type="Vector2" setter="set_offset" getter="get_offset">
+ The texture's drawing offset.
</member>
<member name="region_enabled" type="bool" setter="set_region" getter="is_region">
+ If [code]true[/code] texture will be cut from a larger atlas texture. See [code]region_rect[/code]. Default value: [code]false[/code].
</member>
<member name="region_filter_clip" type="bool" setter="set_region_filter_clip" getter="is_region_filter_clip_enabled">
</member>
<member name="region_rect" type="Rect2" setter="set_region_rect" getter="get_region_rect">
+ The region of the atlas texture to display. [code]region_enabled[/code] must be [code]true[/code].
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
+ [Texture] object to draw.
</member>
<member name="vframes" type="int" setter="set_vframes" getter="get_vframes">
+ The number of vertical frames in the sprite sheet.
</member>
</members>
<signals>
<signal name="frame_changed">
<description>
+ Emitted when the [code]frame[/code] changes.
</description>
</signal>
<signal name="texture_changed">
<description>
+ Emitted when the [code]texture[/code] changes.
</description>
</signal>
</signals>
diff --git a/doc/classes/SpriteFrames.xml b/doc/classes/SpriteFrames.xml
index 1c5669b898..e46fdc80e0 100644
--- a/doc/classes/SpriteFrames.xml
+++ b/doc/classes/SpriteFrames.xml
@@ -4,7 +4,7 @@
Sprite frame library for AnimatedSprite.
</brief_description>
<description>
- Sprite frame library for [AnimatedSprite].
+ Sprite frame library for [AnimatedSprite]. Contains frames and animation data for playback.
</description>
<tutorials>
</tutorials>
@@ -17,6 +17,7 @@
<argument index="0" name="anim" type="String">
</argument>
<description>
+ Adds a new animation to the the library.
</description>
</method>
<method name="add_frame">
@@ -26,9 +27,10 @@
</argument>
<argument index="1" name="frame" type="Texture">
</argument>
- <argument index="2" name="atpos" type="int" default="-1">
+ <argument index="2" name="at_position" type="int" default="-1">
</argument>
<description>
+ Adds a frame to the given animation.
</description>
</method>
<method name="clear">
@@ -37,12 +39,14 @@
<argument index="0" name="anim" type="String">
</argument>
<description>
+ Removes all frames from the given animation.
</description>
</method>
<method name="clear_all">
<return type="void">
</return>
<description>
+ Removes all animations. A "default" animation will be created.
</description>
</method>
<method name="get_animation_loop" qualifiers="const">
@@ -51,6 +55,7 @@
<argument index="0" name="anim" type="String">
</argument>
<description>
+ If [code]true[/code] the given animation will loop.
</description>
</method>
<method name="get_animation_speed" qualifiers="const">
@@ -59,6 +64,7 @@
<argument index="0" name="anim" type="String">
</argument>
<description>
+ The animation's speed in frames per second.
</description>
</method>
<method name="get_frame" qualifiers="const">
@@ -69,6 +75,7 @@
<argument index="1" name="idx" type="int">
</argument>
<description>
+ Returns the animation's selected frame.
</description>
</method>
<method name="get_frame_count" qualifiers="const">
@@ -77,6 +84,7 @@
<argument index="0" name="anim" type="String">
</argument>
<description>
+ Returns the number of frames in the animation.
</description>
</method>
<method name="has_animation" qualifiers="const">
@@ -85,6 +93,7 @@
<argument index="0" name="anim" type="String">
</argument>
<description>
+ If [code]true[/code] the named animation exists.
</description>
</method>
<method name="remove_animation">
@@ -93,6 +102,7 @@
<argument index="0" name="anim" type="String">
</argument>
<description>
+ Removes the given animation.
</description>
</method>
<method name="remove_frame">
@@ -103,6 +113,7 @@
<argument index="1" name="idx" type="int">
</argument>
<description>
+ Removes the animation's selected frame.
</description>
</method>
<method name="rename_animation">
@@ -113,6 +124,7 @@
<argument index="1" name="newname" type="String">
</argument>
<description>
+ Changes the animation's name to [code]newname[/code].
</description>
</method>
<method name="set_animation_loop">
@@ -123,6 +135,7 @@
<argument index="1" name="loop" type="bool">
</argument>
<description>
+ If [code]true[/code] the animation will loop.
</description>
</method>
<method name="set_animation_speed">
@@ -133,6 +146,7 @@
<argument index="1" name="speed" type="float">
</argument>
<description>
+ The animation's speed in frames per second.
</description>
</method>
<method name="set_frame">
@@ -145,11 +159,13 @@
<argument index="2" name="txt" type="Texture">
</argument>
<description>
+ Sets the texture of the given frame.
</description>
</method>
</methods>
<members>
<member name="animations" type="Array" setter="_set_animations" getter="_get_animations">
+ An [Array] containing the [code]name[/code], [code]speed[/code], [code]loop[/code], and [code]frames[/code] of each animation.
</member>
<member name="frames" type="Array" setter="_set_frames" getter="_get_frames">
</member>
diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml
index 2f23ac588b..cff41074b8 100644
--- a/doc/classes/StaticBody2D.xml
+++ b/doc/classes/StaticBody2D.xml
@@ -4,9 +4,8 @@
Static body for 2D Physics.
</brief_description>
<description>
- Static body for 2D Physics. A static body is a simple body that is not intended to move. They don't consume any CPU resources in contrast to a [RigidBody2D] so they are great for scenario collision.
- A static body can also be animated by using simulated motion mode. This is useful for implementing functionalities such as moving platforms. When this mode is active the body can be animated and automatically computes linear and angular velocity to apply in that frame and to influence other bodies.
- Alternatively, a constant linear or angular velocity can be set for the static body, so even if it doesn't move, it affects other bodies as if it was moving (this is useful for simulating conveyor belts or conveyor wheels).
+ Static body for 2D Physics. A StaticBody2D is a body that is not intended to move. It is ideal for implementing objects in the environment, such as walls or platforms.
+ Additionally, a constant linear or angular velocity can be set for the static body, which will affect colliding bodies as if it were moving (for example, a conveyor belt).
</description>
<tutorials>
</tutorials>
@@ -80,12 +79,16 @@
</methods>
<members>
<member name="bounce" type="float" setter="set_bounce" getter="get_bounce">
+ The body's bounciness. Values range from [code]0[/code] (no bounce) to [code]1[/code] (full bounciness).
</member>
<member name="constant_angular_velocity" type="float" setter="set_constant_angular_velocity" getter="get_constant_angular_velocity">
+ Constant angular velocity for the body. This does not rotate the body, but affects colliding bodies, as if it were rotating.
</member>
<member name="constant_linear_velocity" type="Vector2" setter="set_constant_linear_velocity" getter="get_constant_linear_velocity">
+ Constant linear velocity for the body. This does not move the body, but affects colliding bodies, as if it were moving.
</member>
<member name="friction" type="float" setter="set_friction" getter="get_friction">
+ The body's friction. Values range from [code]0[/code] (no friction) to [code]1[/code] (full friction).
</member>
</members>
<constants>
diff --git a/doc/classes/StreamPeerBuffer.xml b/doc/classes/StreamPeerBuffer.xml
index 70a4c781c9..141d46564c 100644
--- a/doc/classes/StreamPeerBuffer.xml
+++ b/doc/classes/StreamPeerBuffer.xml
@@ -27,7 +27,7 @@
<description>
</description>
</method>
- <method name="get_pos" qualifiers="const">
+ <method name="get_position" qualifiers="const">
<return type="int">
</return>
<description>
@@ -50,7 +50,7 @@
<method name="seek">
<return type="void">
</return>
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<description>
</description>
diff --git a/doc/classes/String.xml b/doc/classes/String.xml
index ce3dc1db2f..c7c19997b9 100644
--- a/doc/classes/String.xml
+++ b/doc/classes/String.xml
@@ -266,12 +266,12 @@
</description>
</method>
<method name="erase">
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<argument index="1" name="chars" type="int">
</argument>
<description>
- Erase [code]chars[/code] characters from the string starting from [code]pos[/code].
+ Erase [code]chars[/code] characters from the string starting from [code]position[/code].
</description>
</method>
<method name="find">
@@ -360,7 +360,7 @@
<method name="insert">
<return type="String">
</return>
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<argument index="1" name="what" type="String">
</argument>
@@ -445,7 +445,7 @@
<method name="left">
<return type="String">
</return>
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<description>
Return an amount of characters from the left of the string.
@@ -596,7 +596,7 @@
<method name="right">
<return type="String">
</return>
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<description>
Return the right side of the string from a given position.
diff --git a/doc/classes/Texture.xml b/doc/classes/Texture.xml
index d09236bbc9..cbf72eb991 100644
--- a/doc/classes/Texture.xml
+++ b/doc/classes/Texture.xml
@@ -16,7 +16,7 @@
</return>
<argument index="0" name="canvas_item" type="RID">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<argument index="2" name="modulate" type="Color" default="Color( 1, 1, 1, 1 )">
</argument>
diff --git a/doc/classes/TextureProgress.xml b/doc/classes/TextureProgress.xml
index 1ac031c411..0a6ffcdeb8 100644
--- a/doc/classes/TextureProgress.xml
+++ b/doc/classes/TextureProgress.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextureProgress" inherits="Range" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Textured progress bar implementation.
+ Textured progress bar.
</brief_description>
<description>
- [ProgressBar] implementation that is easier to theme (by just passing a few textures).
+ A [ProgressBar] that uses textures to display fill percentage. Can be set to linear or radial mode.
</description>
<tutorials>
</tutorials>
@@ -148,28 +148,40 @@
</methods>
<members>
<member name="fill_mode" type="int" setter="set_fill_mode" getter="get_fill_mode">
+ The fill direction. Uses FILL_* constants.
</member>
<member name="nine_patch_stretch" type="bool" setter="set_nine_patch_stretch" getter="get_nine_patch_stretch">
+ If [code]true[/code] textures will be stretched as [NinePatchRect]. Uses [code]stretch_margin[/code] properties (see below). Default value: [code]false[/code]
</member>
<member name="radial_center_offset" type="Vector2" setter="set_radial_center_offset" getter="get_radial_center_offset">
+ The offset amount for radial mode.
</member>
<member name="radial_fill_degrees" type="float" setter="set_fill_degrees" getter="get_fill_degrees">
+ The amount of the texture to use for radial mode.
</member>
<member name="radial_initial_angle" type="float" setter="set_radial_initial_angle" getter="get_radial_initial_angle">
+ Start angle for radial mode.
</member>
<member name="stretch_margin_bottom" type="int" setter="set_stretch_margin" getter="get_stretch_margin">
+ Nine-patch texture offset for bottom margin.
</member>
<member name="stretch_margin_left" type="int" setter="set_stretch_margin" getter="get_stretch_margin">
+ Nine-patch texture offset for left margin.
</member>
<member name="stretch_margin_right" type="int" setter="set_stretch_margin" getter="get_stretch_margin">
+ Nine-patch texture offset for right margin.
</member>
<member name="stretch_margin_top" type="int" setter="set_stretch_margin" getter="get_stretch_margin">
+ Nine-patch texture offset for top margin.
</member>
<member name="texture_over" type="Texture" setter="set_over_texture" getter="get_over_texture">
+ The [Texture] that will be drawn over the progress bar.
</member>
<member name="texture_progress" type="Texture" setter="set_progress_texture" getter="get_progress_texture">
+ The [Texture] used to display [code]value[/code].
</member>
<member name="texture_under" type="Texture" setter="set_under_texture" getter="get_under_texture">
+ The [Texture] that will be drawn under the progress bar.
</member>
</members>
<constants>
diff --git a/doc/classes/TextureRect.xml b/doc/classes/TextureRect.xml
index 6d137cb14c..af5626ae84 100644
--- a/doc/classes/TextureRect.xml
+++ b/doc/classes/TextureRect.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="TextureRect" inherits="Control" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Control that draws a texture.
+ Draws a sprite or a texture inside a User Interface. The texture can tile or not.
</brief_description>
<description>
- Control that draws a texture.
+ Use TextureRect to draw icons and sprites in your User Interfaces. To create panels and menu boxes, take a look at [NinePatchFrame]. Its Stretch Mode property controls the texture's scale and placement. It can scale, tile and stay centered inside its bounding rectangle. TextureRect is one of the 5 most common nodes to create game UI.
</description>
<tutorials>
</tutorials>
@@ -56,31 +56,39 @@
</methods>
<members>
<member name="expand" type="bool" setter="set_expand" getter="has_expand">
- If [code]true[/code] texture will expand to fit. Default value: [code]false[/code].
+ If [code]true[/code], the texture scales to fit its bounding rectangle. Default value: [code]false[/code].
</member>
<member name="stretch_mode" type="int" setter="set_stretch_mode" getter="get_stretch_mode" enum="TextureRect.StretchMode">
- Stretch mode of the texture. Use STRETCH_* constants as value.
+ Controls the texture's behavior when you resize the node's bounding rectangle. Set it to one of the [code]STRETCH_*[/code] constants. See the constants to learn more.
</member>
<member name="texture" type="Texture" setter="set_texture" getter="get_texture">
- The [Texture] resource for the node.
+ The node's [Texture] resource.
</member>
</members>
<constants>
<constant name="STRETCH_SCALE_ON_EXPAND" value="0">
+ Scale to fit the node's bounding rectangle, only if [code]expand[/code] is [code]true[/code]. Default [code]stretch_mode[/code], for backwards compatibility. Until you set [code]expand[/code] to [code]true[/code], the texture will behave like [code]STRETCH_KEEP[/code].
</constant>
<constant name="STRETCH_SCALE" value="1">
+ Scale to fit the node's bounding rectangle.
</constant>
<constant name="STRETCH_TILE" value="2">
+ Tile inside the node's bounding rectangle.
</constant>
<constant name="STRETCH_KEEP" value="3">
+ The texture keeps its original size and stays in the bounding rectangle's top-left corner.
</constant>
<constant name="STRETCH_KEEP_CENTERED" value="4">
+ The texture keeps its original size and stays centered in the node's bounding rectangle.
</constant>
<constant name="STRETCH_KEEP_ASPECT" value="5">
+ Scale the texture to fit the node's bounding rectangle, but maintain the texture's aspect ratio.
</constant>
<constant name="STRETCH_KEEP_ASPECT_CENTERED" value="6">
+ Scale the texture to fit the node's bounding rectangle, center it and maintain its aspect ratio.
</constant>
<constant name="STRETCH_KEEP_ASPECT_COVERED" value="7">
+ Scale the texture so that the shorter side fits the bounding rectangle. The other side clips to the node's limits.
</constant>
</constants>
</class>
diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml
index e1a6c0b523..c44fa500cd 100644
--- a/doc/classes/TileMap.xml
+++ b/doc/classes/TileMap.xml
@@ -39,7 +39,7 @@
<method name="get_cellv" qualifiers="const">
<return type="int">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Return the tile index of the cell referenced by a Vector2.
@@ -222,7 +222,7 @@
<method name="map_to_world" qualifiers="const">
<return type="Vector2">
</return>
- <argument index="0" name="mappos" type="Vector2">
+ <argument index="0" name="map_position" type="Vector2">
</argument>
<argument index="1" name="ignore_half_ofs" type="bool" default="false">
</argument>
@@ -264,7 +264,7 @@
<method name="set_cellv">
<return type="void">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<argument index="1" name="tile" type="int">
</argument>
@@ -442,7 +442,7 @@
<method name="world_to_map" qualifiers="const">
<return type="Vector2">
</return>
- <argument index="0" name="worldpos" type="Vector2">
+ <argument index="0" name="world_position" type="Vector2">
</argument>
<description>
Return the tilemap (grid-based) coordinates corresponding to the absolute world position given as an argument.
diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml
index d632eee70a..6780de1943 100644
--- a/doc/classes/Transform.xml
+++ b/doc/classes/Transform.xml
@@ -23,7 +23,7 @@
<argument index="3" name="origin" type="Vector3">
</argument>
<description>
- Construct the Transform from four [Vector3]. Each axis corresponds to local basis vectors (some of which may be scaled).
+ Constructs the Transform from four [Vector3]. Each axis corresponds to local basis vectors (some of which may be scaled).
</description>
</method>
<method name="Transform">
@@ -34,7 +34,7 @@
<argument index="1" name="origin" type="Vector3">
</argument>
<description>
- Construct the Transform from a [Basis] and [Vector3].
+ Constructs the Transform from a [Basis] and [Vector3].
</description>
</method>
<method name="Transform">
@@ -43,7 +43,7 @@
<argument index="0" name="from" type="Transform2D">
</argument>
<description>
- Construct the Transform from a [Transform2D].
+ Constructs the Transform from a [Transform2D].
</description>
</method>
<method name="Transform">
@@ -52,7 +52,7 @@
<argument index="0" name="from" type="Quat">
</argument>
<description>
- Construct the Transform from a [Quat]. The origin will be Vector3(0, 0, 0).
+ Constructs the Transform from a [Quat]. The origin will be Vector3(0, 0, 0).
</description>
</method>
<method name="Transform">
@@ -61,7 +61,7 @@
<argument index="0" name="from" type="Basis">
</argument>
<description>
- Construct the Transform from a [Basis]. The origin will be Vector3(0, 0, 0).
+ Constructs the Transform from a [Basis]. The origin will be Vector3(0, 0, 0).
</description>
</method>
<method name="affine_inverse">
@@ -79,7 +79,7 @@
<argument index="1" name="weight" type="float">
</argument>
<description>
- Interpolate to other Transform by weight amount (0-1).
+ Interpolates the transform to other Transform by weight amount (0-1).
</description>
</method>
<method name="inverse">
@@ -104,7 +104,7 @@
<return type="Transform">
</return>
<description>
- Returns a transfrom with the basis orthogonal (90 degrees), and normalized axis vectors.
+ Returns the transfrom with the basis orthogonal (90 degrees), and normalized axis vectors.
</description>
</method>
<method name="rotated">
@@ -115,7 +115,7 @@
<argument index="1" name="phi" type="float">
</argument>
<description>
- Rotate the transform around given axis by phi. The axis must be a normalized vector.
+ Rotates the transform around given axis by phi. The axis must be a normalized vector.
</description>
</method>
<method name="scaled">
@@ -124,7 +124,7 @@
<argument index="0" name="scale" type="Vector3">
</argument>
<description>
- Scale the transform by the specified 3D scaling factors.
+ Scales the transform by the specified 3D scaling factors.
</description>
</method>
<method name="translated">
@@ -133,7 +133,7 @@
<argument index="0" name="ofs" type="Vector3">
</argument>
<description>
- Translate the transform by the specified offset.
+ Translates the transform by the specified offset.
</description>
</method>
<method name="xform">
@@ -151,7 +151,7 @@
<argument index="0" name="v" type="var">
</argument>
<description>
- Inverse-transforms vector "v" by this transform.
+ Inverse-transforms the given vector "v" by this transform.
</description>
</method>
</methods>
diff --git a/doc/classes/Transform2D.xml b/doc/classes/Transform2D.xml
index b3b752c1da..0e39505ac3 100644
--- a/doc/classes/Transform2D.xml
+++ b/doc/classes/Transform2D.xml
@@ -36,9 +36,9 @@
<method name="Transform2D">
<return type="Transform2D">
</return>
- <argument index="0" name="rot" type="float">
+ <argument index="0" name="rotation" type="float">
</argument>
- <argument index="1" name="pos" type="Vector2">
+ <argument index="1" name="position" type="Vector2">
</argument>
<description>
Constructs the [Transform2D] from rotation angle in radians and position [Vector2].
@@ -66,28 +66,28 @@
<argument index="0" name="v" type="var">
</argument>
<description>
- Inverse-transforms vector "v" by this transform basis (no translation).
+ Inverse-transforms the given vector "v" by this transform basis (no translation).
</description>
</method>
<method name="get_origin">
<return type="Vector2">
</return>
<description>
- Return the origin [Vector2] (translation).
+ Returns the origin [Vector2] (translation).
</description>
</method>
<method name="get_rotation">
<return type="float">
</return>
<description>
- Return the rotation (in radians).
+ Returns the rotation (in radians).
</description>
</method>
<method name="get_scale">
<return type="Vector2">
</return>
<description>
- Return the scale.
+ Returns the scale.
</description>
</method>
<method name="interpolate_with">
@@ -98,7 +98,7 @@
<argument index="1" name="weight" type="float">
</argument>
<description>
- Interpolate to other Transform2D by weight amount (0-1).
+ Interpolates the transform to other Transform2D by weight amount (0-1).
</description>
</method>
<method name="inverse">
@@ -112,7 +112,7 @@
<return type="Transform2D">
</return>
<description>
- Returns a transfrom with the basis orthogonal (90 degrees), and normalized axis vectors.
+ Returns the transfrom with the basis orthogonal (90 degrees), and normalized axis vectors.
</description>
</method>
<method name="rotated">
@@ -121,7 +121,7 @@
<argument index="0" name="phi" type="float">
</argument>
<description>
- Rotate the transform by phi.
+ Rotates the transform by phi.
</description>
</method>
<method name="scaled">
@@ -130,7 +130,7 @@
<argument index="0" name="scale" type="Vector2">
</argument>
<description>
- Scale the transform by the specified 2D scaling factors.
+ Scales the transform by the specified 2D scaling factors.
</description>
</method>
<method name="translated">
@@ -139,7 +139,7 @@
<argument index="0" name="offset" type="Vector2">
</argument>
<description>
- Translate the transform by the specified offset.
+ Translates the transform by the specified offset.
</description>
</method>
<method name="xform">
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index a92a51049b..82e85126cc 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -65,10 +65,10 @@
Get whether a right click can select items.
</description>
</method>
- <method name="get_column_at_pos" qualifiers="const">
+ <method name="get_column_at_position" qualifiers="const">
<return type="int">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Get the column index under the given point.
@@ -113,10 +113,10 @@
Get the flags of the current drop mode.
</description>
</method>
- <method name="get_drop_section_at_pos" qualifiers="const">
+ <method name="get_drop_section_at_position" qualifiers="const">
<return type="int">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
</description>
@@ -146,10 +146,10 @@
Get the rectangle area of the the specified item. If column is specified, only get the position and size of that column, otherwise get the rectangle containing all columns.
</description>
</method>
- <method name="get_item_at_pos" qualifiers="const">
+ <method name="get_item_at_position" qualifiers="const">
<return type="TreeItem">
</return>
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Get the tree item at the specified position (relative to the tree origin position).
@@ -342,7 +342,7 @@
</description>
</signal>
<signal name="empty_tree_rmb_selected">
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Emitted when the right mouse button is pressed if RMB selection is active and the tree is empty.
@@ -378,7 +378,7 @@
</description>
</signal>
<signal name="item_rmb_selected">
- <argument index="0" name="pos" type="Vector2">
+ <argument index="0" name="position" type="Vector2">
</argument>
<description>
Emitted when an item is selected with right mouse button.
diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index 790a82a60a..d291f44de3 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -8,7 +8,7 @@
Because it is easy to get it wrong, here is a quick usage example:
[codeblock]
var tween = get_node("Tween")
- tween.interpolate_property(get_node("Node2D_to_move"), "transform/pos", Vector2(0,0), Vector2(100,100), 1, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
+ tween.interpolate_property(get_node("Node2D_to_move"), "transform/origin", Vector2(0,0), Vector2(100,100), 1, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.start()
[/codeblock]
Some of the methods of this class require a property name. You can get the property name by hovering over the property in the inspector of the editor.
diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml
index 43e0ad7873..d450a8812e 100644
--- a/doc/classes/UndoRedo.xml
+++ b/doc/classes/UndoRedo.xml
@@ -108,6 +108,12 @@
Get the name of the current action.
</description>
</method>
+ <method name="get_max_steps" qualifiers="const">
+ <return type="int">
+ </return>
+ <description>
+ </description>
+ </method>
<method name="get_version" qualifiers="const">
<return type="int">
</return>
@@ -116,6 +122,26 @@
This is useful mostly to check if something changed from a saved version.
</description>
</method>
+ <method name="redo">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
+ <method name="set_max_steps">
+ <return type="void">
+ </return>
+ <argument index="0" name="max_steps" type="int">
+ </argument>
+ <description>
+ </description>
+ </method>
+ <method name="undo">
+ <return type="void">
+ </return>
+ <description>
+ </description>
+ </method>
</methods>
<constants>
<constant name="MERGE_DISABLE" value="0">
diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml
index 7994c1b65a..57e417974e 100644
--- a/doc/classes/VideoPlayer.xml
+++ b/doc/classes/VideoPlayer.xml
@@ -39,7 +39,7 @@
Get the name of the video stream.
</description>
</method>
- <method name="get_stream_pos" qualifiers="const">
+ <method name="get_stream_position" qualifiers="const">
<return type="float">
</return>
<description>
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index a5170b8d03..2cf36ba69b 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -528,7 +528,7 @@
<method name="warp_mouse">
<return type="void">
</return>
- <argument index="0" name="to_pos" type="Vector2">
+ <argument index="0" name="to_position" type="Vector2">
</argument>
<description>
Warp the mouse to a position, relative to the viewport.
diff --git a/doc/classes/VisibilityNotifier.xml b/doc/classes/VisibilityNotifier.xml
index 4d76c7c927..816523fc27 100644
--- a/doc/classes/VisibilityNotifier.xml
+++ b/doc/classes/VisibilityNotifier.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisibilityNotifier" inherits="Spatial" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Detect when the node is visible on screen.
+ Detects when the node is visible on screen.
</brief_description>
<description>
- The VisibilityNotifier is used to notify when its bounding box enters the screen, is visible on the screen, or when it exits the screen.
+ The VisibilityNotifier detects when it is visible on the screen. It also notifies when its bounding rectangle enters or exits the screen or a [Camera]'s view.
</description>
<tutorials>
</tutorials>
@@ -15,14 +15,14 @@
<return type="Rect3">
</return>
<description>
- Return the visibility bounding box of the VisibilityNotifier.
+ Returns the bounding box of the VisibilityNotifier.
</description>
</method>
<method name="is_on_screen" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if any part of the bounding box is on the screen.
+ If [code]true[/code] the bounding box is on the screen.
</description>
</method>
<method name="set_aabb">
@@ -37,6 +37,7 @@
</methods>
<members>
<member name="aabb" type="Rect3" setter="set_aabb" getter="get_aabb">
+ The VisibilityNotifier's bounding box.
</member>
</members>
<signals>
diff --git a/doc/classes/VisibilityNotifier2D.xml b/doc/classes/VisibilityNotifier2D.xml
index 1058e3d6d4..86227a0277 100644
--- a/doc/classes/VisibilityNotifier2D.xml
+++ b/doc/classes/VisibilityNotifier2D.xml
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="VisibilityNotifier2D" inherits="Node2D" category="Core" version="3.0.alpha.custom_build">
<brief_description>
- Detect when the node is visible on screen.
+ Detects when the node is visible on screen.
</brief_description>
<description>
- The VisibilityNotifier2D is used to notify when its bounding rectangle enters the screen, is visible on the screen, or when it exits the screen.
+ The VisibilityNotifier2D detects when it is visible on the screen. It also notifies when its bounding rectangle enters or exits the screen or a viewport.
</description>
<tutorials>
</tutorials>
@@ -15,14 +15,14 @@
<return type="Rect2">
</return>
<description>
- Return the visibility bounding rectangle of the VisibilityNotifier2D.
+ Returns the bounding rectangle of the VisibilityNotifier2D.
</description>
</method>
<method name="is_on_screen" qualifiers="const">
<return type="bool">
</return>
<description>
- Return true if any part of the bounding rectangle is on the screen.
+ If [code]true[/code] the bounding rectangle is on the screen.
</description>
</method>
<method name="set_rect">
@@ -37,6 +37,7 @@
</methods>
<members>
<member name="rect" type="Rect2" setter="set_rect" getter="get_rect">
+ The VisibilityNotifier2D's bounding rectangle.
</member>
</members>
<signals>
diff --git a/doc/classes/VisualScript.xml b/doc/classes/VisualScript.xml
index db516c229e..e44547cd8f 100644
--- a/doc/classes/VisualScript.xml
+++ b/doc/classes/VisualScript.xml
@@ -40,7 +40,7 @@
</argument>
<argument index="2" name="node" type="VisualScriptNode">
</argument>
- <argument index="3" name="pos" type="Vector2" default="Vector2( 0, 0 )">
+ <argument index="3" name="position" type="Vector2" default="Vector2( 0, 0 )">
</argument>
<description>
Add a node to a function of the VisualScript.
@@ -218,7 +218,7 @@
Returns a node given its id and its function.
</description>
</method>
- <method name="get_node_pos" qualifiers="const">
+ <method name="get_node_position" qualifiers="const">
<return type="Vector2">
</return>
<argument index="0" name="func" type="String">
@@ -448,14 +448,14 @@
Set the base type of the script.
</description>
</method>
- <method name="set_node_pos">
+ <method name="set_node_position">
<return type="void">
</return>
<argument index="0" name="func" type="String">
</argument>
<argument index="1" name="id" type="int">
</argument>
- <argument index="2" name="pos" type="Vector2">
+ <argument index="2" name="position" type="Vector2">
</argument>
<description>
Position a node on the screen.
diff --git a/doc/classes/XMLParser.xml b/doc/classes/XMLParser.xml
index 6ab84ef345..bb9599e273 100644
--- a/doc/classes/XMLParser.xml
+++ b/doc/classes/XMLParser.xml
@@ -133,7 +133,7 @@
<method name="seek">
<return type="int" enum="Error">
</return>
- <argument index="0" name="pos" type="int">
+ <argument index="0" name="position" type="int">
</argument>
<description>
Move the buffer cursor to a certain offset (since the beginning) and read the next node there. This returns an error code.
diff --git a/doc/tools/doc_status.py b/doc/tools/doc_status.py
index b0fa36230c..75e18bbe81 100644
--- a/doc/tools/doc_status.py
+++ b/doc/tools/doc_status.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
+import fnmatch
import os
import sys
import re
@@ -91,7 +92,7 @@ def validate_tag(elem, tag):
def color(color, string):
- if flags['c']:
+ if flags['c'] and terminal_supports_color():
color_format = ''
for code in colors[color]:
color_format += '\033[' + str(code) + 'm'
@@ -105,6 +106,15 @@ ansi_escape = re.compile(r'\x1b[^m]*m')
def nonescape_len(s):
return len(ansi_escape.sub('', s))
+def terminal_supports_color():
+ p = sys.platform
+ supported_platform = p != 'Pocket PC' and (p != 'win32' or
+ 'ANSICON' in os.environ)
+
+ is_a_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
+ if not supported_platform or not is_a_tty:
+ return False
+ return True
################################################################################
# Classes #
@@ -134,8 +144,8 @@ class ClassStatusProgress:
return self.to_colored_string()
def to_colored_string(self, format='{has}/{total}', pad_format='{pad_described}{s}{pad_total}'):
- ratio = self.described / self.total if self.total != 0 else 1
- percent = round(100 * ratio)
+ ratio = float(self.described) / float(self.total) if self.total != 0 else 1
+ percent = int(round(100 * ratio))
s = format.format(has=str(self.described), total=str(self.total), percent=str(percent))
if self.described >= self.total:
s = color('part_good', s)
@@ -218,6 +228,7 @@ class ClassStatus:
return output
+ @staticmethod
def generate_for_class(c):
status = ClassStatus()
status.name = c.attrib['name']
@@ -253,6 +264,9 @@ class ClassStatus:
for sub_tag in list(tag):
status.progresses[tag.tag].increment(len(sub_tag.text.strip()) > 0)
+ elif tag.tag in ['tutorials', 'demos']:
+ pass # Ignore those tags for now
+
elif tag.tag in ['theme_items']:
pass # Ignore those tags, since they seem to lack description at all
@@ -353,23 +367,25 @@ for file in input_file_list:
class_names.sort()
if len(input_class_list) < 1:
- input_class_list = class_names
+ input_class_list = ['*']
+filtered_classes = set()
+for pattern in input_class_list:
+ filtered_classes |= set(fnmatch.filter(class_names, pattern))
+filtered_classes = list(filtered_classes)
+filtered_classes.sort()
################################################################################
# Make output table #
################################################################################
table = [table_column_names]
-table_row_chars = '+- '
+table_row_chars = '| - '
table_column_chars = '|'
total_status = ClassStatus('Total')
-for cn in input_class_list:
- if not cn in classes:
- print('Cannot find class ' + cn + '!')
- sys.exit(255)
+for cn in filtered_classes:
c = classes[cn]
validate_tag(c, 'class')
@@ -423,7 +439,7 @@ for row in table:
divider_string = table_row_chars[0]
for cell_i in range(len(table[0])):
- divider_string += table_row_chars[1] * (table_column_sizes[cell_i] + 2) + table_row_chars[0]
+ divider_string += table_row_chars[1] + table_row_chars[2] * (table_column_sizes[cell_i]) + table_row_chars[1] + table_row_chars[0]
print(divider_string)
for row_i, row in enumerate(table):
@@ -431,9 +447,9 @@ for row_i, row in enumerate(table):
for cell_i, cell in enumerate(row):
padding_needed = table_column_sizes[cell_i] - nonescape_len(cell) + 2
if cell_i == 0:
- row_string += table_row_chars[2] + cell + table_row_chars[2] * (padding_needed - 1)
+ row_string += table_row_chars[3] + cell + table_row_chars[3] * (padding_needed - 1)
else:
- row_string += table_row_chars[2] * math.floor(padding_needed / 2) + cell + table_row_chars[2] * math.ceil((padding_needed / 2))
+ row_string += table_row_chars[3] * int(math.floor(float(padding_needed) / 2)) + cell + table_row_chars[3] * int(math.ceil(float(padding_needed) / 2))
row_string += table_column_chars
print(row_string)
diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py
index 696e3c9c78..c4dff588b0 100644
--- a/doc/tools/makerst.py
+++ b/doc/tools/makerst.py
@@ -3,15 +3,19 @@
import codecs
import sys
+import os
import xml.etree.ElementTree as ET
input_list = []
for arg in sys.argv[1:]:
+ if arg.endswith(os.sep):
+ arg = arg[:-1]
input_list.append(arg)
if len(input_list) < 1:
- print 'usage: makerst.py <classes.xml>'
+ print 'usage: makerst.py <path to folders> and/or <path to .xml files> (order of arguments irrelevant)'
+ print 'example: makerst.py "../../modules/" "../classes" path_to/some_class.xml'
sys.exit(0)
@@ -34,7 +38,6 @@ def ul_string(str, ul):
def make_class_list(class_list, columns):
-
f = codecs.open('class_list.rst', 'wb', 'utf-8')
prev = 0
col_max = len(class_list) / columns + 1
@@ -102,7 +105,6 @@ def make_class_list(class_list, columns):
def rstize_text(text, cclass):
-
# Linebreak + tabs in the XML should become two line breaks unless in a "codeblock"
pos = 0
while True:
@@ -250,9 +252,6 @@ def rstize_text(text, cclass):
text = pre_text + tag_text + post_text
pos = len(pre_text) + len(tag_text)
- # tnode = ET.SubElement(parent,"div")
- # tnode.text=text
-
return text
@@ -272,7 +271,6 @@ def make_method(
event=False,
pp=None
):
-
if (declare or pp == None):
t = '- '
else:
@@ -340,7 +338,6 @@ def make_method(
if 'qualifiers' in m.attrib:
s += ' ' + m.attrib['qualifiers']
-# f.write(s)
if (not declare):
if (pp != None):
pp.append((t, s))
@@ -355,24 +352,23 @@ def make_heading(title, underline):
def make_rst_class(node):
-
name = node.attrib['name']
f = codecs.open("class_" + name.lower() + '.rst', 'wb', 'utf-8')
# Warn contributors not to edit this file directly
f.write(".. Generated automatically by doc/tools/makerst.py in Godot's source tree.\n")
- f.write(".. DO NOT EDIT THIS FILE, but the doc/base/classes.xml source instead.\n\n")
+ f.write(".. DO NOT EDIT THIS FILE, but the " + name + ".xml source instead.\n")
+ f.write(".. The source is found in doc/classes or modules/<name>/doc_classes.\n\n")
f.write(".. _class_" + name + ":\n\n")
f.write(make_heading(name, '='))
if 'inherits' in node.attrib:
inh = node.attrib['inherits'].strip()
-# whle inh in classes[cn]
f.write('**Inherits:** ')
first = True
- while(inh in classes):
+ while (inh in classes):
if (not first):
f.write(" **<** ")
else:
@@ -436,10 +432,10 @@ def make_rst_class(node):
f.write(sep)
for s in ml:
rt = s[0]
- while(len(rt) < longest_s):
+ while (len(rt) < longest_s):
rt += " "
st = s[1]
- while(len(st) < longest_t):
+ while (len(st) < longest_t):
st += " "
f.write("| " + rt + " | " + st + " |\n")
f.write(sep)
@@ -494,8 +490,6 @@ def make_rst_class(node):
f.write(make_heading('Member Function Description', '-'))
for m in list(methods):
f.write(".. _class_" + name + "_" + m.attrib['name'] + ":\n\n")
-# f.write(ul_string(m.attrib['name'],"^"))
- #f.write('\n<a name="'+m.attrib['name']+'">' + m.attrib['name'] + '</a>\n------\n')
make_method(f, node.attrib['name'], m, True, name)
f.write('\n')
d = m.find('description')
@@ -506,7 +500,21 @@ def make_rst_class(node):
f.write('\n')
-for file in input_list:
+file_list = []
+
+for path in input_list:
+ if os.path.basename(path) == 'modules':
+ for subdir, dirs, _ in os.walk(path):
+ if 'doc_classes' in dirs:
+ doc_dir = os.path.join(subdir, 'doc_classes')
+ class_file_name = [f for f in os.listdir(doc_dir) if f.endswith('.xml')][0]
+ file_list.append(os.path.join(doc_dir, class_file_name))
+ elif not os.path.isfile(path):
+ file_list += [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.xml')]
+ elif os.path.isfile(path) and path.endswith('.xml'):
+ file_list.append(path)
+
+for file in file_list:
tree = ET.parse(file)
doc = tree.getroot()
@@ -515,17 +523,15 @@ for file in input_list:
sys.exit(255)
version = doc.attrib['version']
-
- for c in list(doc):
- if c.attrib['name'] in class_names:
- continue
- class_names.append(c.attrib['name'])
- classes[c.attrib['name']] = c
+ if doc.attrib['name'] in class_names:
+ continue
+ class_names.append(doc.attrib['name'])
+ classes[doc.attrib['name']] = doc
class_names.sort()
# Don't make class list for Sphinx, :toctree: handles it
-#make_class_list(class_names, 2)
+# make_class_list(class_names, 2)
for cn in class_names:
c = classes[cn]
diff --git a/drivers/SCsub b/drivers/SCsub
index b8bba91378..34d6254578 100644
--- a/drivers/SCsub
+++ b/drivers/SCsub
@@ -4,7 +4,7 @@ Import('env')
env.drivers_sources = []
-if ("builtin_zlib" in env and env["builtin_zlib"] == "yes"):
+if 'builtin_zlib' in env and env['builtin_zlib']:
SConscript("zlib/SCsub")
# OS drivers
@@ -13,11 +13,12 @@ SConscript('windows/SCsub')
# Sounds drivers
SConscript('alsa/SCsub')
+SConscript('coreaudio/SCsub')
SConscript('pulseaudio/SCsub')
if (env["platform"] == "windows"):
SConscript("rtaudio/SCsub")
SConscript("wasapi/SCsub")
-if (env["xaudio2"] == "yes"):
+if env['xaudio2']:
SConscript("xaudio2/SCsub")
# Graphics drivers
@@ -29,10 +30,10 @@ SConscript("png/SCsub")
# Tools override
# FIXME: Should likely be integrated in the tools/ codebase
-if (env["tools"] == "yes"):
+if env['tools']:
SConscript("convex_decomp/SCsub")
-if env['vsproj'] == "yes":
+if env['vsproj']:
env.AddToVSProject(env.drivers_sources)
if env.split_drivers:
diff --git a/drivers/coreaudio/SCsub b/drivers/coreaudio/SCsub
new file mode 100644
index 0000000000..233593b0f9
--- /dev/null
+++ b/drivers/coreaudio/SCsub
@@ -0,0 +1,8 @@
+#!/usr/bin/env python
+
+Import('env')
+
+# Driver source files
+env.add_source_files(env.drivers_sources, "*.cpp")
+
+Export('env')
diff --git a/platform/osx/audio_driver_osx.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp
index 3b3ba60507..c531d6af9d 100644
--- a/platform/osx/audio_driver_osx.cpp
+++ b/drivers/coreaudio/audio_driver_coreaudio.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_driver_osx.cpp */
+/* audio_driver_coreaudio.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,27 +27,33 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef OSX_ENABLED
+#ifdef COREAUDIO_ENABLED
-#include "audio_driver_osx.h"
+#include "audio_driver_coreaudio.h"
#include "core/project_settings.h"
#include "os/os.h"
#define kOutputBus 0
+#ifdef OSX_ENABLED
static OSStatus outputDeviceAddressCB(AudioObjectID inObjectID, UInt32 inNumberAddresses, const AudioObjectPropertyAddress *inAddresses, void *__nullable inClientData) {
- AudioDriverOSX *driver = (AudioDriverOSX *)inClientData;
+ AudioDriverCoreAudio *driver = (AudioDriverCoreAudio *)inClientData;
driver->reopen();
return noErr;
}
+#endif
-Error AudioDriverOSX::initDevice() {
+Error AudioDriverCoreAudio::initDevice() {
AudioComponentDescription desc;
zeromem(&desc, sizeof(desc));
desc.componentType = kAudioUnitType_Output;
+#ifdef OSX_ENABLED
desc.componentSubType = kAudioUnitSubType_HALOutput;
+#else
+ desc.componentSubType = kAudioUnitSubType_RemoteIO;
+#endif
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
AudioComponent comp = AudioComponentFindNext(NULL, &desc);
@@ -96,8 +102,10 @@ Error AudioDriverOSX::initDevice() {
// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
+#ifdef OSX_ENABLED
result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global, kOutputBus, &buffer_frames, sizeof(UInt32));
ERR_FAIL_COND_V(result != noErr, FAILED);
+#endif
buffer_size = buffer_frames * channels;
samples_in.resize(buffer_size);
@@ -109,7 +117,7 @@ Error AudioDriverOSX::initDevice() {
AURenderCallbackStruct callback;
zeromem(&callback, sizeof(AURenderCallbackStruct));
- callback.inputProc = &AudioDriverOSX::output_callback;
+ callback.inputProc = &AudioDriverCoreAudio::output_callback;
callback.inputProcRefCon = this;
result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback));
ERR_FAIL_COND_V(result != noErr, FAILED);
@@ -120,7 +128,7 @@ Error AudioDriverOSX::initDevice() {
return OK;
}
-Error AudioDriverOSX::finishDevice() {
+Error AudioDriverCoreAudio::finishDevice() {
OSStatus result;
if (active) {
@@ -136,24 +144,26 @@ Error AudioDriverOSX::finishDevice() {
return OK;
}
-Error AudioDriverOSX::init() {
+Error AudioDriverCoreAudio::init() {
OSStatus result;
mutex = Mutex::create();
active = false;
channels = 2;
+#ifdef OSX_ENABLED
outputDeviceAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
outputDeviceAddress.mScope = kAudioObjectPropertyScopeGlobal;
outputDeviceAddress.mElement = kAudioObjectPropertyElementMaster;
result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this);
ERR_FAIL_COND_V(result != noErr, FAILED);
+#endif
return initDevice();
};
-Error AudioDriverOSX::reopen() {
+Error AudioDriverCoreAudio::reopen() {
bool restart = false;
lock();
@@ -185,13 +195,13 @@ Error AudioDriverOSX::reopen() {
return OK;
}
-OSStatus AudioDriverOSX::output_callback(void *inRefCon,
+OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber, UInt32 inNumberFrames,
AudioBufferList *ioData) {
- AudioDriverOSX *ad = (AudioDriverOSX *)inRefCon;
+ AudioDriverCoreAudio *ad = (AudioDriverCoreAudio *)inRefCon;
if (!ad->active || !ad->try_lock()) {
for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
@@ -227,7 +237,7 @@ OSStatus AudioDriverOSX::output_callback(void *inRefCon,
return 0;
};
-void AudioDriverOSX::start() {
+void AudioDriverCoreAudio::start() {
if (!active) {
OSStatus result = AudioOutputUnitStart(audio_unit);
if (result != noErr) {
@@ -238,37 +248,41 @@ void AudioDriverOSX::start() {
}
};
-int AudioDriverOSX::get_mix_rate() const {
+int AudioDriverCoreAudio::get_mix_rate() const {
return mix_rate;
};
-AudioDriver::SpeakerMode AudioDriverOSX::get_speaker_mode() const {
+AudioDriver::SpeakerMode AudioDriverCoreAudio::get_speaker_mode() const {
return get_speaker_mode_by_total_channels(channels);
};
-void AudioDriverOSX::lock() {
+void AudioDriverCoreAudio::lock() {
if (mutex)
mutex->lock();
};
-void AudioDriverOSX::unlock() {
+void AudioDriverCoreAudio::unlock() {
if (mutex)
mutex->unlock();
};
-bool AudioDriverOSX::try_lock() {
+bool AudioDriverCoreAudio::try_lock() {
if (mutex)
return mutex->try_lock() == OK;
return true;
}
-void AudioDriverOSX::finish() {
+void AudioDriverCoreAudio::finish() {
+ OSStatus result;
+
finishDevice();
- OSStatus result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this);
+#ifdef OSX_ENABLED
+ result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &outputDeviceAddress, &outputDeviceAddressCB, this);
if (result != noErr) {
ERR_PRINT("AudioObjectRemovePropertyListener failed");
}
+#endif
AURenderCallbackStruct callback;
zeromem(&callback, sizeof(AURenderCallbackStruct));
@@ -283,7 +297,7 @@ void AudioDriverOSX::finish() {
}
};
-AudioDriverOSX::AudioDriverOSX() {
+AudioDriverCoreAudio::AudioDriverCoreAudio() {
active = false;
mutex = NULL;
@@ -296,6 +310,6 @@ AudioDriverOSX::AudioDriverOSX() {
samples_in.clear();
};
-AudioDriverOSX::~AudioDriverOSX(){};
+AudioDriverCoreAudio::~AudioDriverCoreAudio(){};
#endif
diff --git a/platform/osx/audio_driver_osx.h b/drivers/coreaudio/audio_driver_coreaudio.h
index a7e68c8141..33b3ba93ec 100644
--- a/platform/osx/audio_driver_osx.h
+++ b/drivers/coreaudio/audio_driver_coreaudio.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_driver_osx.h */
+/* audio_driver_coreaudio.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,20 +27,24 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifdef OSX_ENABLED
+#ifdef COREAUDIO_ENABLED
-#ifndef AUDIO_DRIVER_OSX_H
-#define AUDIO_DRIVER_OSX_H
+#ifndef AUDIO_DRIVER_COREAUDIO_H
+#define AUDIO_DRIVER_COREAUDIO_H
#include "servers/audio_server.h"
#include <AudioUnit/AudioUnit.h>
+#ifdef OSX_ENABLED
#include <CoreAudio/AudioHardware.h>
+#endif
-class AudioDriverOSX : public AudioDriver {
+class AudioDriverCoreAudio : public AudioDriver {
AudioComponentInstance audio_unit;
+#ifdef OSX_ENABLED
AudioObjectPropertyAddress outputDeviceAddress;
+#endif
bool active;
Mutex *mutex;
@@ -62,7 +66,7 @@ class AudioDriverOSX : public AudioDriver {
public:
const char *get_name() const {
- return "AudioUnit";
+ return "CoreAudio";
};
virtual Error init();
@@ -76,8 +80,8 @@ public:
bool try_lock();
Error reopen();
- AudioDriverOSX();
- ~AudioDriverOSX();
+ AudioDriverCoreAudio();
+ ~AudioDriverCoreAudio();
};
#endif
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 146a2359b6..eaf0b06664 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "rasterizer_scene_gles3.h"
-
+#include "math_funcs.h"
#include "os/os.h"
#include "project_settings.h"
#include "rasterizer_canvas_gles3.h"
@@ -799,12 +799,12 @@ void RasterizerSceneGLES3::environment_set_sky(RID p_env, RID p_sky) {
env->sky = p_sky;
}
-void RasterizerSceneGLES3::environment_set_sky_scale(RID p_env, float p_scale) {
+void RasterizerSceneGLES3::environment_set_sky_custom_fov(RID p_env, float p_scale) {
Environment *env = environment_owner.getornull(p_env);
ERR_FAIL_COND(!env);
- env->sky_scale = p_scale;
+ env->sky_custom_fov = p_scale;
}
void RasterizerSceneGLES3::environment_set_bg_color(RID p_env, const Color &p_color) {
@@ -2319,7 +2319,7 @@ void RasterizerSceneGLES3::_add_geometry_with_material(RasterizerStorageGLES3::G
}
}
-void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy) {
+void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy) {
if (!p_sky)
return;
@@ -2365,16 +2365,28 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C
//sky uv vectors
float vw, vh, zn;
- p_projection.get_viewport_size(vw, vh);
- zn = p_projection.get_z_near();
+ CameraMatrix camera;
+
+ if (p_custom_fov) {
+
+ float near_plane = p_projection.get_z_near();
+ float far_plane = p_projection.get_z_far();
+ float aspect = p_projection.get_aspect();
+
+ camera.set_perspective(p_custom_fov, aspect, near_plane, far_plane);
- float scale = p_scale;
+ } else {
+ camera = p_projection;
+ }
+
+ camera.get_viewport_size(vw, vh);
+ zn = p_projection.get_z_near();
for (int i = 0; i < 4; i++) {
Vector3 uv = vertices[i * 2 + 1];
- uv.x = (uv.x * 2.0 - 1.0) * vw * scale;
- uv.y = -(uv.y * 2.0 - 1.0) * vh * scale;
+ uv.x = (uv.x * 2.0 - 1.0) * vw;
+ uv.y = -(uv.y * 2.0 - 1.0) * vh;
uv.z = -zn;
vertices[i * 2 + 1] = p_transform.basis.xform(uv).normalized();
vertices[i * 2 + 1].z = -vertices[i * 2 + 1].z;
@@ -2404,6 +2416,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr
//store camera into ubo
store_camera(p_cam_projection, state.ubo_data.projection_matrix);
+ store_camera(p_cam_projection.inverse(), state.ubo_data.inv_projection_matrix);
store_transform(p_cam_transform, state.ubo_data.camera_matrix);
store_transform(p_cam_transform.affine_inverse(), state.ubo_data.camera_inverse_matrix);
@@ -2521,9 +2534,10 @@ void RasterizerSceneGLES3::_setup_directional_light(int p_index, const Transform
float sign = li->light_ptr->negative ? -1 : 1;
Color linear_col = li->light_ptr->color.to_linear();
- ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
- ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
- ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
+ //compensate normalized diffuse range by multiplying by PI
+ ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
+ ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
+ ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
ubo_data.light_color_energy[3] = 0;
//omni, keep at 0
@@ -2661,9 +2675,9 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c
float sign = li->light_ptr->negative ? -1 : 1;
Color linear_col = li->light_ptr->color.to_linear();
- ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
- ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
- ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
+ ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
+ ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
+ ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
ubo_data.light_color_energy[3] = 0;
Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin);
@@ -2747,9 +2761,9 @@ void RasterizerSceneGLES3::_setup_lights(RID *p_light_cull_result, int p_light_c
float sign = li->light_ptr->negative ? -1 : 1;
Color linear_col = li->light_ptr->color.to_linear();
- ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
- ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
- ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY];
+ ubo_data.light_color_energy[0] = linear_col.r * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
+ ubo_data.light_color_energy[1] = linear_col.g * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
+ ubo_data.light_color_energy[2] = linear_col.b * sign * li->light_ptr->param[VS::LIGHT_PARAM_ENERGY] * Math_PI;
ubo_data.light_color_energy[3] = 0;
Vector3 pos = p_camera_inverse_transform.xform(li->transform.origin);
@@ -4257,7 +4271,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const
glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo); //switch to alpha fbo for sky, only diffuse/ambient matters
*/
- _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_scale, env->bg_energy);
+ _draw_sky(sky, p_cam_projection, p_cam_transform, false, env->sky_custom_fov, env->bg_energy);
}
//_render_list_forward(&alpha_render_list,camera_transform,camera_transform_inverse,camera_projection,false,fragment_lighting,true);
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index b3fd6fa2a0..28a5cef0ee 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/drivers/gles3/rasterizer_scene_gles3.h
@@ -110,6 +110,7 @@ public:
struct SceneDataUBO {
//this is a std140 compatible struct. Please read the OpenGL 3.3 Specificaiton spec before doing any changes
float projection_matrix[16];
+ float inv_projection_matrix[16];
float camera_inverse_matrix[16];
float camera_matrix[16];
float ambient_light_color[4];
@@ -351,7 +352,7 @@ public:
VS::EnvironmentBG bg_mode;
RID sky;
- float sky_scale;
+ float sky_custom_fov;
Color bg_color;
float bg_energy;
@@ -434,7 +435,7 @@ public:
Environment() {
bg_mode = VS::ENV_BG_CLEAR_COLOR;
- sky_scale = 1.0;
+ sky_custom_fov = 0.0;
bg_energy = 1.0;
sky_ambient = 0;
ambient_energy = 1.0;
@@ -519,7 +520,7 @@ public:
virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg);
virtual void environment_set_sky(RID p_env, RID p_sky);
- virtual void environment_set_sky_scale(RID p_env, float p_scale);
+ virtual void environment_set_sky_custom_fov(RID p_env, float p_scale);
virtual void environment_set_bg_color(RID p_env, const Color &p_color);
virtual void environment_set_bg_energy(RID p_env, float p_energy);
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
@@ -806,11 +807,11 @@ public:
void _render_list(RenderList::Element **p_elements, int p_element_count, const Transform &p_view_transform, const CameraMatrix &p_projection, GLuint p_base_env, bool p_reverse_cull, bool p_alpha_pass, bool p_shadow, bool p_directional_add, bool p_directional_shadows);
- _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_passs);
+ _FORCE_INLINE_ void _add_geometry(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, int p_material, bool p_depth_pass);
_FORCE_INLINE_ void _add_geometry_with_material(RasterizerStorageGLES3::Geometry *p_geometry, InstanceBase *p_instance, RasterizerStorageGLES3::GeometryOwner *p_owner, RasterizerStorageGLES3::Material *p_material, bool p_depth_pass);
- void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_scale, float p_energy);
+ void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy);
void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform);
void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index b99817fb12..ae41a936c6 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -1564,6 +1564,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX;
p_shader->canvas_item.uses_screen_texture = false;
p_shader->canvas_item.uses_screen_uv = false;
+ p_shader->canvas_item.uses_time = false;
shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD);
shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX);
@@ -1595,6 +1596,7 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const {
p_shader->spatial.unshaded = false;
p_shader->spatial.no_depth_test = false;
p_shader->spatial.uses_sss = false;
+ p_shader->spatial.uses_time = false;
p_shader->spatial.uses_vertex_lighting = false;
p_shader->spatial.uses_screen_texture = false;
p_shader->spatial.uses_vertex = false;
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index 5401c8266a..91159e3381 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -700,9 +700,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
/** CANVAS ITEM SHADER **/
- actions[VS::SHADER_CANVAS_ITEM].renames["SRC_VERTEX"] = "vertex";
actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy";
- actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX_COLOR"] = "vertex_color";
actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv_interp";
actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "gl_PointSize";
@@ -711,6 +709,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] == "extra_matrix";
actions[VS::SHADER_CANVAS_ITEM].renames["TIME"] = "time";
actions[VS::SHADER_CANVAS_ITEM].renames["AT_LIGHT_PASS"] = "at_light_pass";
+ actions[VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom";
actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color";
actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal";
@@ -720,6 +719,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture";
actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size";
+ actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture";
actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv";
actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture";
actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size";
@@ -750,6 +750,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix";
actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix";
actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix";
+ actions[VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
actions[VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview";
actions[VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz";
@@ -786,6 +787,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength";
actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission";
actions[VS::SHADER_SPATIAL].renames["AO"] = "ao";
+ actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect";
actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission";
//actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord";
@@ -796,6 +798,13 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].renames["SIDE"] = "side";
actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor";
+ //for light
+ actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view";
+ actions[VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color";
+ actions[VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation";
+ actions[VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light";
+ actions[VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light";
+
actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n";
actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT";
actions[VS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n";
@@ -805,6 +814,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n";
actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY";
actions[VS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n";
+ actions[VS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n";
actions[VS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n";
actions[VS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n";
actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n";
diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl
index bf8eaf601d..731d6968ce 100644
--- a/drivers/gles3/shaders/canvas.glsl
+++ b/drivers/gles3/shaders/canvas.glsl
@@ -105,13 +105,16 @@ VERTEX_SHADER_GLOBALS
void main() {
- vec4 vertex_color = color_attrib;
+ vec4 color = color_attrib;
#ifdef USE_INSTANCING
mat4 extra_matrix2 = extra_matrix * transpose(mat4(instance_xform0,instance_xform1,instance_xform2,vec4(0.0,0.0,0.0,1.0)));
- vertex_color*=instance_color;
+ color*=instance_color;
+ vec4 instance_custom = instance_custom_data;
+
#else
mat4 extra_matrix2 = extra_matrix;
+ vec4 instance_custom = vec4(0.0);
#endif
#ifdef USE_TEXTURE_RECT
@@ -135,7 +138,7 @@ void main() {
//compute h and v frames and adjust UV interp for animation
int total_frames = h_frames * v_frames;
- int frame = min(int(float(total_frames) *instance_custom_data.z),total_frames-1);
+ int frame = min(int(float(total_frames) *instance_custom.z),total_frames-1);
float frame_w = 1.0/float(h_frames);
float frame_h = 1.0/float(v_frames);
uv_interp.x = uv_interp.x * frame_w + frame_w * float(frame % h_frames);
@@ -146,7 +149,6 @@ void main() {
#define extra_matrix extra_matrix2
{
- vec2 src_vtx=outvec.xy;
VERTEX_SHADER_CODE
@@ -165,7 +167,7 @@ VERTEX_SHADER_CODE
#undef extra_matrix
- color_interp = vertex_color;
+ color_interp = color;
#ifdef USE_PIXEL_SNAP
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 5f83033293..dee5994124 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1,5 +1,6 @@
[vertex]
+#define M_PI 3.14159265359
/*
from VisualServer:
@@ -61,6 +62,7 @@ layout(location=12) in highp vec4 instance_custom_data;
layout(std140) uniform SceneData { //ubo:0
highp mat4 projection_matrix;
+ highp mat4 inv_projection_matrix;
highp mat4 camera_inverse_matrix;
highp mat4 camera_matrix;
@@ -165,7 +167,7 @@ out vec4 specular_light_interp;
void light_compute(vec3 N, vec3 L,vec3 V, vec3 light_color,float roughness,inout vec3 diffuse, inout vec3 specular) {
float dotNL = max(dot(N,L), 0.0 );
- diffuse += dotNL * light_color;
+ diffuse += dotNL * light_color / M_PI;
if (roughness > 0.0) {
@@ -588,7 +590,7 @@ vec3 textureDualParaboloid(sampler2DArray p_tex, vec3 p_vec,float p_roughness) {
norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25);
// we need to lie the derivatives (normg) and assume that DP side is always the same
- // to get proper texure filtering
+ // to get proper texture filtering
vec2 normg=norm.xy;
if (norm.z>0.0) {
norm.y=0.5-norm.y+0.5;
@@ -643,6 +645,7 @@ FRAGMENT_SHADER_GLOBALS
layout(std140) uniform SceneData {
highp mat4 projection_matrix;
+ highp mat4 inv_projection_matrix;
highp mat4 camera_inverse_matrix;
highp mat4 camera_matrix;
@@ -887,11 +890,15 @@ float GTR1(float NdotH, float a)
-void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) {
+void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 attenuation,vec3 diffuse_color, vec3 transmission, float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) {
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
+ vec3 normal = N;
+ vec3 albedo = diffuse_color;
+ vec3 light = L;
+ vec3 view = V;
LIGHT_SHADER_CODE
@@ -914,6 +921,7 @@ LIGHT_SHADER_CODE
#elif defined(DIFFUSE_OREN_NAYAR)
{
+ // see http://mimosa-pudica.net/improved-oren-nayar.html
float LdotV = dot(L, V);
float NdotL = dot(L, N);
float NdotV = dot(N, V);
@@ -922,10 +930,10 @@ LIGHT_SHADER_CODE
float t = mix(1.0, max(NdotL, NdotV), step(0.0, s));
float sigma2 = roughness * roughness;
- vec3 A = 1.0 + sigma2 * (diffuse_color / (sigma2 + 0.13) + 0.5 / (sigma2 + 0.33));
+ vec3 A = 1.0 + sigma2 * (- 0.5 / (sigma2 + 0.33) + 0.17*diffuse_color / (sigma2 + 0.13) );
float B = 0.45 * sigma2 / (sigma2 + 0.09);
- light_amount = max(0.0, NdotL) * (A + vec3(B) * s / t) / M_PI;
+ light_amount = dotNL * (A + vec3(B) * s / t) / M_PI;
}
#elif defined(DIFFUSE_TOON)
@@ -939,13 +947,13 @@ LIGHT_SHADER_CODE
vec3 H = normalize(V + L);
float NoL = max(0.0,dot(N, L));
- float VoH = max(0.0,dot(L, H));
+ float LoH = max(0.0,dot(L, H));
float NoV = max(0.0,dot(N, V));
- float FD90 = 0.5 + 2.0 * VoH * VoH * roughness;
- float FdV = 1.0 + (FD90 - 1.0) * pow( 1.0 - NoV, 5.0 );
- float FdL = 1.0 + (FD90 - 1.0) * pow( 1.0 - NoL, 5.0 );
- light_amount = ( (1.0 / M_PI) * FdV * FdL );
+ float FD90 = 0.5 + 2.0 * LoH * LoH * roughness;
+ float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(NoV);
+ float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(NoL);
+ light_amount = ( (1.0 / M_PI) * FdV * FdL ) * NoL;
/*
float energyBias = mix(roughness, 0.0, 0.5);
float energyFactor = mix(roughness, 1.0, 1.0 / 1.51);
@@ -958,13 +966,13 @@ LIGHT_SHADER_CODE
}
#else
//lambert
- light_amount = dotNL;
+ light_amount = dotNL / M_PI;
#endif
#if defined(TRANSMISSION_USED)
- diffuse += light_color * diffuse_color * mix(vec3(light_amount),vec3(1.0),transmission);
+ diffuse += light_color * diffuse_color * mix(vec3(light_amount),vec3(M_PI),transmission) * attenuation;
#else
- diffuse += light_color * diffuse_color * light_amount;
+ diffuse += light_color * diffuse_color * light_amount * attenuation;
#endif
@@ -985,14 +993,14 @@ LIGHT_SHADER_CODE
vec3 H = normalize(V + L);
float dotNH = max(dot(N,H), 0.0 );
float intensity = pow( dotNH, (1.0-roughness) * 256.0);
- specular += light_color * intensity * specular_blob_intensity;
+ specular += light_color * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_PHONG)
vec3 R = normalize(-reflect(L,N));
float dotNV = max(0.0,dot(R,V));
float intensity = pow( dotNV, (1.0-roughness) * 256.0);
- specular += light_color * intensity * specular_blob_intensity;
+ specular += light_color * intensity * specular_blob_intensity * attenuation;
#elif defined(SPECULAR_TOON)
@@ -1001,12 +1009,12 @@ LIGHT_SHADER_CODE
float mid = 1.0-roughness;
mid*=mid;
float intensity = smoothstep(mid-roughness*0.5,mid+roughness*0.5,dotNV) * mid;
- diffuse += light_color * intensity * specular_blob_intensity; //write to diffuse, as in toon shading you generally want no reflection
+ diffuse += light_color * intensity * specular_blob_intensity * attenuation; //write to diffuse, as in toon shading you generally want no reflection
#elif defined(SPECULAR_DISABLED)
//none..
-#else
+#elif defined(SPECULAR_SCHLICK_GGX)
// shlick+ggx as default
float alpha = roughness * roughness;
@@ -1045,10 +1053,16 @@ LIGHT_SHADER_CODE
float speci = dotNL * D * F * vis;
- specular += speci * light_color * specular_blob_intensity;
+ specular += speci * light_color * specular_blob_intensity * attenuation;
#endif
#if defined(LIGHT_USE_CLEARCOAT)
+# if !defined(SPECULAR_SCHLICK_GGX)
+ vec3 H = normalize(V + L);
+ float dotLH5 = SchlickFresnel( dotLH );
+ float dotNH = max(dot(N,H), 0.0 );
+# endif
+
float Dr = GTR1(dotNH, mix(.1,.001,clearcoat_gloss));
float Fr = mix(.04, 1.0, dotLH5);
float Gr = G1V(dotNL, .25) * G1V(dotNV, .25);
@@ -1191,7 +1205,7 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 bino
light_attenuation*=mix(omni_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
}
- light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,transmission,omni_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+ light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,omni_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
}
@@ -1225,7 +1239,7 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 bi
light_attenuation*=mix(spot_lights[idx].shadow_color_contact.rgb,vec3(1.0),shadow);
}
- light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,transmission,spot_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+ light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb,light_attenuation,albedo,transmission,spot_lights[idx].light_params.z*p_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
}
@@ -1534,6 +1548,7 @@ void main() {
#if defined(ENABLE_AO)
float ao=1.0;
+ float ao_light_affect=0.0;
#endif
float alpha = 1.0;
@@ -1857,7 +1872,7 @@ FRAGMENT_SHADER_CODE
specular_light*=mix(vec3(1.0),light_attenuation,specular_light_interp.a);
#else
- light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb*light_attenuation,albedo,transmission,light_params.z*specular_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
+ light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb,light_attenuation,albedo,transmission,light_params.z*specular_blob_intensity,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
#endif
@@ -1918,9 +1933,13 @@ FRAGMENT_SHADER_CODE
#if defined(ENABLE_AO)
ambient_light*=ao;
+ ao_light_affect = mix(1.0,ao,ao_light_affect);
+ specular_light*=ao_light_affect;
+ diffuse_light*=ao_light_affect;
#endif
+
//energu conservation
diffuse_light=mix(diffuse_light,vec3(0.0),metallic);
ambient_light=mix(ambient_light,vec3(0.0),metallic);
@@ -1932,18 +1951,19 @@ FRAGMENT_SHADER_CODE
//simplify for toon, as
specular_light *= specular * metallic * albedo * 2.0;
#else
- //brdf approximation (Lazarov 2013)
- float ndotv = clamp(dot(normal,eye_vec),0.0,1.0);
- vec3 dielectric = vec3(0.034) * specular * 2.0;
//energy conservation
- vec3 f0 = mix(dielectric, albedo, metallic);
+ vec3 dielectric = vec3(0.034) * specular * 2.0;
+ vec3 specular_color = mix(dielectric, albedo, metallic);
+ // Environment brdf approximation (Lazarov 2013)
+ // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
const vec4 c1 = vec4( 1.0, 0.0425, 1.04, -0.04);
vec4 r = roughness * c0 + c1;
+ float ndotv = clamp(dot(normal,eye_vec),0.0,1.0);
float a004 = min( r.x * r.x, exp2( -9.28 * ndotv ) ) * r.x + r.y;
- vec2 brdf = vec2( -1.04, 1.04 ) * a004 + r.zw;
+ vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;
- specular_light *= min(1.0,50.0 * f0.g) * brdf.y + brdf.x * f0;
+ specular_light *= AB.x * specular_color + AB.y;
#endif
}
diff --git a/drivers/png/SCsub b/drivers/png/SCsub
index 6684e36b20..39480351a6 100644
--- a/drivers/png/SCsub
+++ b/drivers/png/SCsub
@@ -5,7 +5,7 @@ Import('env')
env_png = env.Clone()
# Thirdparty source files
-if (env['builtin_libpng'] != 'no'):
+if env['builtin_libpng']:
thirdparty_dir = "#thirdparty/libpng/"
thirdparty_sources = [
"png.c",
diff --git a/drivers/rtaudio/audio_driver_rtaudio.cpp b/drivers/rtaudio/audio_driver_rtaudio.cpp
index ae5fdd28b6..a184c9e9cf 100644
--- a/drivers/rtaudio/audio_driver_rtaudio.cpp
+++ b/drivers/rtaudio/audio_driver_rtaudio.cpp
@@ -143,7 +143,7 @@ Error AudioDriverRtAudio::init() {
}
}
- return OK;
+ return active ? OK : ERR_UNAVAILABLE;
}
int AudioDriverRtAudio::get_mix_rate() const {
diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp
index 45ea654bad..e7054e11a3 100644
--- a/drivers/unix/dir_access_unix.cpp
+++ b/drivers/unix/dir_access_unix.cpp
@@ -183,17 +183,18 @@ void DirAccessUnix::list_dir_end() {
_cisdir = false;
}
-#ifdef HAVE_MNTENT
+#if defined(HAVE_MNTENT) && defined(X11_ENABLED)
static bool _filter_drive(struct mntent *mnt) {
// Ignore devices that don't point to /dev
if (strncmp(mnt->mnt_fsname, "/dev", 4) != 0) {
return false;
}
- // Accept devices mounted at /media, /mnt or /home
+ // Accept devices mounted at common locations
if (strncmp(mnt->mnt_dir, "/media", 6) == 0 ||
strncmp(mnt->mnt_dir, "/mnt", 4) == 0 ||
- strncmp(mnt->mnt_dir, "/home", 5) == 0) {
+ strncmp(mnt->mnt_dir, "/home", 5) == 0 ||
+ strncmp(mnt->mnt_dir, "/run/media", 10) == 0) {
return true;
}
@@ -204,7 +205,7 @@ static bool _filter_drive(struct mntent *mnt) {
static void _get_drives(List<String> *list) {
-#ifdef HAVE_MNTENT
+#if defined(HAVE_MNTENT) && defined(X11_ENABLED)
// Check /etc/mtab for the list of mounted partitions
FILE *mtab = setmntent("/etc/mtab", "r");
if (mtab) {
diff --git a/drivers/unix/file_access_unix.cpp b/drivers/unix/file_access_unix.cpp
index 80565c5b02..206f57d4a2 100644
--- a/drivers/unix/file_access_unix.cpp
+++ b/drivers/unix/file_access_unix.cpp
@@ -168,7 +168,7 @@ void FileAccessUnix::seek_end(int64_t p_position) {
check_errors();
}
-size_t FileAccessUnix::get_pos() const {
+size_t FileAccessUnix::get_position() const {
ERR_FAIL_COND_V(!f, 0);
@@ -223,6 +223,12 @@ Error FileAccessUnix::get_error() const {
return last_error;
}
+void FileAccessUnix::flush() {
+
+ ERR_FAIL_COND(!f);
+ fflush(f);
+}
+
void FileAccessUnix::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);
@@ -274,6 +280,15 @@ uint64_t FileAccessUnix::_get_modified_time(const String &p_file) {
};
}
+Error FileAccessUnix::_chmod(const String &p_path, int p_mod) {
+ int err = chmod(p_path.utf8().get_data(), p_mod);
+ if (!err) {
+ return OK;
+ }
+
+ return FAILED;
+}
+
FileAccess *FileAccessUnix::create_libc() {
return memnew(FileAccessUnix);
diff --git a/drivers/unix/file_access_unix.h b/drivers/unix/file_access_unix.h
index 6e5110431f..96f2ff8e26 100644
--- a/drivers/unix/file_access_unix.h
+++ b/drivers/unix/file_access_unix.h
@@ -62,7 +62,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -72,12 +72,15 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists
virtual uint64_t _get_modified_time(const String &p_file);
+ virtual Error _chmod(const String &p_path, int p_mod);
+
FileAccessUnix();
virtual ~FileAccessUnix();
};
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp
index 75c8a153f6..29fe73f170 100644
--- a/drivers/unix/os_unix.cpp
+++ b/drivers/unix/os_unix.cpp
@@ -64,39 +64,7 @@
#include <string.h>
#include <sys/time.h>
#include <sys/wait.h>
-
-extern bool _print_error_enabled;
-
-void OS_Unix::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
-
- if (!_print_error_enabled)
- return;
-
- const char *err_details;
- if (p_rationale && p_rationale[0])
- err_details = p_rationale;
- else
- err_details = p_code;
-
- switch (p_type) {
- case ERR_ERROR:
- print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- print("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
- break;
- case ERR_WARNING:
- print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
- print("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
- break;
- case ERR_SCRIPT:
- print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- print("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
- break;
- case ERR_SHADER:
- print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- print("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
- break;
- }
-}
+#include <unistd.h>
void OS_Unix::debug_break() {
@@ -165,29 +133,16 @@ void OS_Unix::initialize_core() {
}
}
-void OS_Unix::finalize_core() {
+void OS_Unix::initialize_logger() {
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(UnixTerminalLogger));
+ loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
+ _set_logger(memnew(CompositeLogger(loggers)));
}
-void OS_Unix::vprint(const char *p_format, va_list p_list, bool p_stder) {
-
- if (p_stder) {
-
- vfprintf(stderr, p_format, p_list);
- fflush(stderr);
- } else {
-
- vprintf(p_format, p_list);
- fflush(stdout);
- }
+void OS_Unix::finalize_core() {
}
-void OS_Unix::print(const char *p_format, ...) {
-
- va_list argp;
- va_start(argp, p_format);
- vprintf(p_format, argp);
- va_end(argp);
-}
void OS_Unix::alert(const String &p_alert, const String &p_title) {
fprintf(stderr, "ERROR: %s\n", p_alert.utf8().get_data());
@@ -559,4 +514,38 @@ String OS_Unix::get_executable_path() const {
#endif
}
+void UnixTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+ if (!should_log(true)) {
+ return;
+ }
+
+ const char *err_details;
+ if (p_rationale && p_rationale[0])
+ err_details = p_rationale;
+ else
+ err_details = p_code;
+
+ switch (p_type) {
+ case ERR_WARNING:
+ logf_error("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
+ logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
+ break;
+ case ERR_SCRIPT:
+ logf_error("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
+ logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
+ break;
+ case ERR_SHADER:
+ logf_error("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
+ logf_error("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
+ break;
+ case ERR_ERROR:
+ default:
+ logf_error("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
+ logf_error("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
+ break;
+ }
+}
+
+UnixTerminalLogger::~UnixTerminalLogger() {}
+
#endif
diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h
index 19e79728fb..1cc44c0ffd 100644
--- a/drivers/unix/os_unix.h
+++ b/drivers/unix/os_unix.h
@@ -54,11 +54,11 @@ protected:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
+ virtual void initialize_logger();
virtual void initialize_core();
virtual int unix_initialize_audio(int p_audio_driver);
//virtual void initialize(int p_video_driver,int p_audio_driver);
- //virtual void finalize();
virtual void finalize_core();
String stdin_buf;
@@ -66,10 +66,6 @@ protected:
String get_global_settings_path() const;
public:
- virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
-
- virtual void print(const char *p_format, ...);
- virtual void vprint(const char *p_format, va_list p_list, bool p_stder = false);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual String get_stdin_string(bool p_block);
@@ -120,6 +116,12 @@ public:
//virtual void run( MainLoop * p_main_loop );
};
+class UnixTerminalLogger : public StdLogger {
+public:
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ virtual ~UnixTerminalLogger();
+};
+
#endif
#endif
diff --git a/drivers/unix/syslog_logger.cpp b/drivers/unix/syslog_logger.cpp
new file mode 100644
index 0000000000..d57f391325
--- /dev/null
+++ b/drivers/unix/syslog_logger.cpp
@@ -0,0 +1,71 @@
+/*************************************************************************/
+/* syslog_logger.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 UNIX_ENABLED
+
+#include "syslog_logger.h"
+#include "print_string.h"
+#include <syslog.h>
+
+void SyslogLogger::logv(const char *p_format, va_list p_list, bool p_err) {
+ if (!should_log(p_err)) {
+ return;
+ }
+
+ vsyslog(p_err ? LOG_ERR : LOG_INFO, p_format, p_list);
+}
+
+void SyslogLogger::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+ if (!should_log(true)) {
+ return;
+ }
+
+ const char *err_type = "**ERROR**";
+ switch (p_type) {
+ case ERR_ERROR: err_type = "**ERROR**"; break;
+ case ERR_WARNING: err_type = "**WARNING**"; break;
+ case ERR_SCRIPT: err_type = "**SCRIPT ERROR**"; break;
+ case ERR_SHADER: err_type = "**SHADER ERROR**"; break;
+ default: ERR_PRINT("Unknown error type"); break;
+ }
+
+ const char *err_details;
+ if (p_rationale && *p_rationale)
+ err_details = p_rationale;
+ else
+ err_details = p_code;
+
+ syslog(p_type == ERR_WARNING ? LOG_WARNING : LOG_ERR, "%s: %s\n At: %s:%i:%s() - %s", err_type, err_details, p_file, p_line, p_function, p_code);
+}
+
+SyslogLogger::~SyslogLogger() {
+}
+
+#endif \ No newline at end of file
diff --git a/drivers/unix/syslog_logger.h b/drivers/unix/syslog_logger.h
new file mode 100644
index 0000000000..b3cf2f9e3a
--- /dev/null
+++ b/drivers/unix/syslog_logger.h
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* syslog_logger.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 SYSLOG_LOGGER_H
+#define SYSLOG_LOGGER_H
+
+#ifdef UNIX_ENABLED
+
+#include "io/logger.h"
+
+class SyslogLogger : public Logger {
+public:
+ virtual void logv(const char *p_format, va_list p_list, bool p_err);
+ virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
+
+ virtual ~SyslogLogger();
+};
+
+#endif
+
+#endif \ No newline at end of file
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 6d6a6027d9..8d6e78dbee 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -162,10 +162,10 @@ Error DirAccessWindows::make_dir(String p_dir) {
GLOBAL_LOCK_FUNCTION
+ p_dir = fix_path(p_dir);
if (p_dir.is_rel_path())
p_dir = get_current_dir().plus_file(p_dir);
- p_dir = fix_path(p_dir);
p_dir = p_dir.replace("/", "\\");
bool success;
diff --git a/drivers/windows/file_access_windows.cpp b/drivers/windows/file_access_windows.cpp
index fe2069089c..3b6e469c9c 100644
--- a/drivers/windows/file_access_windows.cpp
+++ b/drivers/windows/file_access_windows.cpp
@@ -156,7 +156,7 @@ void FileAccessWindows::seek_end(int64_t p_position) {
if (fseek(f, p_position, SEEK_END))
check_errors();
}
-size_t FileAccessWindows::get_pos() const {
+size_t FileAccessWindows::get_position() const {
size_t aux_position = 0;
aux_position = ftell(f);
@@ -169,9 +169,9 @@ size_t FileAccessWindows::get_len() const {
ERR_FAIL_COND_V(!f, 0);
- size_t pos = get_pos();
+ size_t pos = get_position();
fseek(f, 0, SEEK_END);
- int size = get_pos();
+ int size = get_position();
fseek(f, pos, SEEK_SET);
return size;
@@ -207,6 +207,12 @@ Error FileAccessWindows::get_error() const {
return last_error;
}
+void FileAccessWindows::flush() {
+
+ ERR_FAIL_COND(!f);
+ fflush(f);
+}
+
void FileAccessWindows::store_8(uint8_t p_dest) {
ERR_FAIL_COND(!f);
diff --git a/drivers/windows/file_access_windows.h b/drivers/windows/file_access_windows.h
index 6956e7855a..e5e7fd4a13 100644
--- a/drivers/windows/file_access_windows.h
+++ b/drivers/windows/file_access_windows.h
@@ -54,7 +54,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -64,6 +64,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_name); ///< return true if a file exists
diff --git a/editor/SCsub b/editor/SCsub
index 839d8e74c1..11cdb471a8 100644
--- a/editor/SCsub
+++ b/editor/SCsub
@@ -6,6 +6,16 @@ env.editor_sources = []
import os
from compat import encode_utf8, byte_to_str, open_utf8
+def escape_string(s, encoding='ascii'):
+ if isinstance(s, unicode):
+ s = s.encode(encoding)
+ result = ''
+ for c in s:
+ if not (32 <= ord(c) < 127) or c in ('\\', '"'):
+ result += '\\%03o' % ord(c)
+ else:
+ result += c
+ return result
def make_certs_header(target, source, env):
@@ -41,7 +51,7 @@ def make_doc_header(target, source, env):
src = s.srcnode().abspath
f = open_utf8(src, "r")
content = f.read()
- buf+=content
+ buf+=content
buf = encode_utf8(docbegin + buf + docend)
decomp_size = len(buf)
@@ -162,7 +172,7 @@ def make_authors_header(target, source, env):
for line in f:
if reading:
if line.startswith(" "):
- g.write("\t\"" + line.strip() + "\",\n")
+ g.write("\t\"" + escape_string(line.strip()) + "\",\n")
continue
if line.startswith("## "):
if reading:
@@ -170,7 +180,7 @@ def make_authors_header(target, source, env):
reading = False
for i in range(len(sections)):
if line.strip().endswith(sections[i]):
- current_section = sections_id[i]
+ current_section = escape_string(sections_id[i])
reading = True
g.write("static const char *" + current_section + "[] = {\n")
break
@@ -204,7 +214,7 @@ def make_donors_header(target, source, env):
for line in f:
if reading >= 0:
if line.startswith(" "):
- g.write("\t\"" + line.strip() + "\",\n")
+ g.write("\t\"" + escape_string(line.strip()) + "\",\n")
continue
if line.startswith("## "):
if reading:
@@ -212,7 +222,7 @@ def make_donors_header(target, source, env):
reading = False
for i in range(len(sections)):
if line.strip().endswith(sections[i]):
- current_section = sections_id[i]
+ current_section = escape_string(sections_id[i])
reading = True
g.write("static const char *" + current_section + "[] = {\n")
break
@@ -237,7 +247,8 @@ def make_license_header(target, source, env):
g.write("static const char *about_license =")
for line in f:
- g.write("\n\t\"" + line.strip().replace("\"", "\\\"") + "\\n\"")
+ escaped_string = escape_string(line.strip().replace("\"", "\\\""))
+ g.write("\n\t\"" + escaped_string + "\\n\"")
g.write(";\n")
@@ -322,11 +333,13 @@ def make_license_header(target, source, env):
for k in j[0].split("\n"):
if file_body != "":
file_body += "\\n\"\n"
- file_body += "\t\"" + k.strip().replace("\"", "\\\"")
+ escaped_string = escape_string(k.strip().replace("\"", "\\\""))
+ file_body += "\t\"" + escaped_string
for k in j[1].split("\n"):
if copyright_body != "":
copyright_body += "\\n\"\n"
- copyright_body += "\t\"" + k.strip().replace("\"", "\\\"")
+ escaped_string = escape_string(k.strip().replace("\"", "\\\""))
+ copyright_body += "\t\"" + escaped_string
about_tp_file += "\t" + file_body + "\",\n"
about_tp_copyright += "\t" + copyright_body + "\",\n"
@@ -340,7 +353,8 @@ def make_license_header(target, source, env):
for j in i[1].split("\n"):
if body != "":
body += "\\n\"\n"
- body += "\t\"" + j.strip().replace("\"", "\\\"")
+ escaped_string = escape_string(j.strip().replace("\"", "\\\""))
+ body += "\t\"" + escaped_string
about_license_name += "\t\"" + i[0] + "\",\n"
about_license_body += "\t" + body + "\",\n"
@@ -385,18 +399,18 @@ def make_license_header(target, source, env):
def _make_doc_data_class_path(to_path):
- g = open_utf8(os.path.join(to_path,"doc_data_class_path.gen.h"), "wb")
+ g = open_utf8(os.path.join(to_path,"doc_data_class_path.gen.h"), "w")
g.write("static const int _doc_data_class_path_count="+str(len(env.doc_class_path))+";\n")
g.write("struct _DocDataClassPath { const char* name; const char* path; };\n")
g.write("static const _DocDataClassPath _doc_data_class_paths["+str(len(env.doc_class_path)+1)+"]={\n");
for c in env.doc_class_path:
- g.write("{\""+c+"\",\""+env.doc_class_path[c]+"\"},\n")
+ g.write("{\""+c+"\",\""+env.doc_class_path[c]+"\"},\n")
g.write("{NULL,NULL}\n")
g.write("};\n")
-if (env["tools"] == "yes"):
+if env['tools']:
# Register exporters
reg_exporters_inc = '#include "register_exporters.h"\n'
reg_exporters = 'void register_exporters() {\n'
@@ -414,7 +428,7 @@ if (env["tools"] == "yes"):
docs=[]
print("cdir is: "+env.Dir('#').abspath)
for f in os.listdir(os.path.join(env.Dir('#').abspath,"doc/classes")):
- docs.append("#doc/classes/"+f)
+ docs.append("#doc/classes/"+f)
_make_doc_data_class_path(os.path.join(env.Dir('#').abspath,"editor/doc"))
diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp
index 47360ff7fb..b832b993bb 100644
--- a/editor/animation_editor.cpp
+++ b/editor/animation_editor.cpp
@@ -322,7 +322,7 @@ public:
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_remove_key_at_position", 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);
@@ -563,8 +563,8 @@ public:
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, "location"));
+ p_list->push_back(PropertyInfo(Variant::QUAT, "rotation"));
p_list->push_back(PropertyInfo(Variant::VECTOR3, "scale"));
} break;
@@ -719,7 +719,7 @@ void AnimationKeyEditor::_anim_duplicate_keys(bool transpose) {
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);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", dst_track, dst_time);
Pair<int, float> p;
p.first = dst_track;
@@ -1016,7 +1016,7 @@ float AnimationKeyEditor::_get_zoom_scale() const {
}
}
-void AnimationKeyEditor::_track_pos_draw() {
+void AnimationKeyEditor::_track_position_draw() {
if (!animation.is_valid()) {
return;
@@ -2301,8 +2301,8 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
if (tt == Animation::TYPE_TRANSFORM) {
Dictionary d;
- d["loc"] = Vector3();
- d["rot"] = Quat();
+ d["location"] = Vector3();
+ d["rotation"] = Quat();
d["scale"] = Vector3();
newval = d;
@@ -2337,7 +2337,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
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);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", idx, pos);
if (existing != -1) {
Variant v = animation->track_get_key_value(idx, existing);
@@ -2506,7 +2506,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
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);
+ undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_position", E->key().track, newtime);
_AnimMoveRestore amr;
amr.key = animation->track_get_key_value(E->key().track, idx);
@@ -2536,7 +2536,7 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
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);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", E->key().track, newpos);
}
// 5-(undo) reinsert keys
@@ -2753,10 +2753,10 @@ void AnimationKeyEditor::_track_editor_gui_input(const Ref<InputEvent> &p_input)
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("location"))
+ text += "location: " + String(d["location"]) + "\n";
+ if (d.has("rotation"))
+ text += "rot: " + String(d["rotation"]) + "\n";
if (d.has("scale"))
text += "scale: " + String(d["scale"]) + "\n";
} break;
@@ -2898,10 +2898,6 @@ void AnimationKeyEditor::_notification(int p_what) {
zoomicon->set_custom_minimum_size(Size2(24 * EDSCALE, 0));
zoomicon->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED);
- 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);
@@ -3363,9 +3359,9 @@ int AnimationKeyEditor::_confirm_insert(InsertData p_id, int p_last_track) {
Transform tr = p_id.value;
Dictionary d;
- d["loc"] = tr.origin;
+ d["location"] = tr.origin;
d["scale"] = tr.basis.get_scale();
- d["rot"] = Quat(tr.basis); //.orthonormalized();
+ d["rotation"] = Quat(tr.basis); //.orthonormalized();
value = d;
} break;
default: {}
@@ -3380,7 +3376,7 @@ int AnimationKeyEditor::_confirm_insert(InsertData p_id, int p_last_track) {
p_last_track++;
} else {
- undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_pos", p_id.track_idx, time);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", 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);
@@ -3455,7 +3451,7 @@ void AnimationKeyEditor::_create_value_item(int p_type) {
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);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", cvi_track, cvi_pos);
int existing = animation->track_find_key(cvi_track, cvi_pos, true);
@@ -3590,7 +3586,7 @@ void AnimationKeyEditor::_scale() {
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);
+ undo_redo->add_do_method(animation.ptr(), "track_remove_key_at_position", E->key().track, newtime);
_AnimMoveRestore amr;
amr.key = animation->track_get_key_value(E->key().track, idx);
@@ -3613,7 +3609,7 @@ void AnimationKeyEditor::_scale() {
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);
+ undo_redo->add_undo_method(animation.ptr(), "track_remove_key_at_position", E->key().track, newpos);
}
// 5-(undo) reinsert keys
@@ -3700,7 +3696,7 @@ void AnimationKeyEditor::_bind_methods() {
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("_track_position_draw"), &AnimationKeyEditor::_track_position_draw);
ClassDB::bind_method(D_METHOD("_insert_delay"), &AnimationKeyEditor::_insert_delay);
ClassDB::bind_method(D_METHOD("_step_changed"), &AnimationKeyEditor::_step_changed);
@@ -3719,7 +3715,7 @@ void AnimationKeyEditor::_bind_methods() {
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("timeline_changed", PropertyInfo(Variant::REAL, "position"), 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")));
@@ -3817,6 +3813,9 @@ AnimationKeyEditor::AnimationKeyEditor() {
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."));
+ 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);
move_up_button = memnew(ToolButton);
hb->add_child(move_up_button);
@@ -3901,7 +3900,7 @@ AnimationKeyEditor::AnimationKeyEditor() {
//menu->get_popup()->connect("id_pressed",this,"_menu_callback");
hb = memnew(HBoxContainer);
- hb->set_area_as_parent_rect();
+ hb->set_anchors_and_margins_preset(Control::PRESET_WIDE);
ec->add_child(hb);
hb->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -3913,14 +3912,14 @@ AnimationKeyEditor::AnimationKeyEditor() {
track_editor->set_h_size_flags(SIZE_EXPAND_FILL);
track_pos = memnew(Control);
- track_pos->set_area_as_parent_rect();
+ track_pos->set_anchors_and_margins_preset(Control::PRESET_WIDE);
track_pos->set_mouse_filter(MOUSE_FILTER_IGNORE);
track_editor->add_child(track_pos);
- track_pos->connect("draw", this, "_track_pos_draw");
+ track_pos->connect("draw", this, "_track_position_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_anchors_and_margins_preset(Control::PRESET_WIDE);
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);
@@ -3934,10 +3933,9 @@ AnimationKeyEditor::AnimationKeyEditor() {
key_editor_tab = memnew(TabContainer);
key_editor_tab->set_tab_align(TabContainer::ALIGN_LEFT);
hb->add_child(key_editor_tab);
- key_editor_tab->set_custom_minimum_size(Size2(200, 0));
+ key_editor_tab->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
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);
@@ -4052,8 +4050,6 @@ AnimationKeyEditor::AnimationKeyEditor() {
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);
}
diff --git a/editor/animation_editor.h b/editor/animation_editor.h
index c16072502b..8a89dc1a1c 100644
--- a/editor/animation_editor.h
+++ b/editor/animation_editor.h
@@ -273,7 +273,7 @@ class AnimationKeyEditor : public VBoxContainer {
void _track_editor_draw();
void _track_editor_gui_input(const Ref<InputEvent> &p_input);
- void _track_pos_draw();
+ void _track_position_draw();
void _track_name_changed(const String &p_name);
void _track_menu_selected(int p_idx);
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp
index 8c153d2745..ee1faf5a55 100644
--- a/editor/code_editor.cpp
+++ b/editor/code_editor.cpp
@@ -86,7 +86,7 @@ void FindReplaceBar::_notification(int p_what) {
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_hover_texture(get_icon("Close", "EditorIcons"));
hide_button->set_pressed_texture(get_icon("Close", "EditorIcons"));
} else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
@@ -97,7 +97,7 @@ void FindReplaceBar::_notification(int p_what) {
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_hover_texture(get_icon("Close", "EditorIcons"));
hide_button->set_pressed_texture(get_icon("Close", "EditorIcons"));
}
}
@@ -367,7 +367,7 @@ void FindReplaceBar::_show_search() {
if (!get_search_text().empty()) {
search_text->select_all();
- search_text->set_cursor_pos(search_text->get_text().length());
+ search_text->set_cursor_position(search_text->get_text().length());
search_current();
}
}
@@ -993,14 +993,14 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
}
void CodeTextEditor::_zoom_in() {
- font_resize_val += 1;
+ font_resize_val += EDSCALE;
if (font_resize_timer->get_time_left() == 0)
font_resize_timer->start();
}
void CodeTextEditor::_zoom_out() {
- font_resize_val -= 1;
+ font_resize_val -= EDSCALE;
if (font_resize_timer->get_time_left() == 0)
font_resize_timer->start();
@@ -1010,7 +1010,7 @@ 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);
+ EditorSettings::get_singleton()->set("interface/editor/source_font_size", 14);
font->set_size(14);
}
}
@@ -1023,7 +1023,10 @@ void CodeTextEditor::_line_col_changed() {
void CodeTextEditor::_text_changed() {
- code_complete_timer->start();
+ if (text_editor->is_insert_text_operation()) {
+ code_complete_timer->start();
+ }
+
idle->start();
}
@@ -1062,11 +1065,10 @@ 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);
+ int new_size = CLAMP(font->get_size() + font_resize_val, 8 * EDSCALE, 96 * EDSCALE);
+ if (new_size != font->get_size()) {
+ EditorSettings::get_singleton()->set("interface/editor/source_font_size", new_size / EDSCALE);
+ font->set_size(new_size);
}
font_resize_val = 0;
@@ -1196,17 +1198,9 @@ CodeTextEditor::CodeTextEditor() {
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);
+ 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);
@@ -1225,14 +1219,18 @@ CodeTextEditor::CodeTextEditor() {
error->set_clip_text(true); //do not change, or else very long errors can push the whole container to the right
error->set_valign(Label::VALIGN_CENTER);
error->add_color_override("font_color", EditorNode::get_singleton()->get_gui_base()->get_color("error_color", "Editor"));
+ error->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
error->set_h_size_flags(SIZE_EXPAND_FILL); //required for it to display, given now it's clipping contents, do not touch
+ status_bar->add_child(memnew(Label)); //to keep the height if the other labels are not visible
+
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_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
line_nb = memnew(Label);
status_bar->add_child(line_nb);
@@ -1241,6 +1239,8 @@ CodeTextEditor::CodeTextEditor() {
line_nb->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch
line_nb->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch
line_nb->set_custom_minimum_size(Size2(40, 1) * EDSCALE);
+ line_nb->set_align(Label::ALIGN_RIGHT);
+ line_nb->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
Label *col_txt = memnew(Label);
status_bar->add_child(col_txt);
@@ -1248,6 +1248,7 @@ CodeTextEditor::CodeTextEditor() {
col_txt->set_valign(Label::VALIGN_CENTER);
col_txt->set_v_size_flags(SIZE_FILL);
col_txt->set_text(TTR("Col:"));
+ col_txt->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
col_nb = memnew(Label);
status_bar->add_child(col_nb);
@@ -1256,6 +1257,9 @@ CodeTextEditor::CodeTextEditor() {
col_nb->set_autowrap(true); // workaround to prevent resizing the label on each change, do not touch
col_nb->set_clip_text(true); // workaround to prevent resizing the label on each change, do not touch
col_nb->set_custom_minimum_size(Size2(40, 1) * EDSCALE);
+ col_nb->set_align(Label::ALIGN_RIGHT);
+ col_nb->set("custom_constants/margin_right", 0);
+ col_nb->add_font_override("font", EditorNode::get_singleton()->get_gui_base()->get_font("status_source", "EditorFonts"));
text_editor->connect("gui_input", this, "_text_editor_gui_input");
text_editor->connect("cursor_changed", this, "_line_col_changed");
diff --git a/editor/collada/collada.cpp b/editor/collada/collada.cpp
index 4986d97e8f..2d49840683 100644
--- a/editor/collada/collada.cpp
+++ b/editor/collada/collada.cpp
@@ -1918,7 +1918,7 @@ void Collada::_parse_animation(XMLParser &parser) {
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
+ track.keys[j].data[k] = output[l + j * stride + k]; //super weird but should work:
}
if (sampler.has("INTERPOLATION")) {
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp
index 344cb87aa6..ca68d84abd 100644
--- a/editor/create_dialog.cpp
+++ b/editor/create_dialog.cpp
@@ -54,12 +54,7 @@ void CreateDialog::popup_create(bool p_dontclear) {
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"));
- }
+ ti->set_icon(0, _get_editor_icon(l));
}
}
@@ -122,6 +117,29 @@ void CreateDialog::_sbox_input(const Ref<InputEvent> &p_ie) {
}
}
+Ref<Texture> CreateDialog::_get_editor_icon(const String &p_type) const {
+
+ if (has_icon(p_type, "EditorIcons")) {
+ return get_icon(p_type, "EditorIcons");
+ }
+
+ const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types();
+ for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) {
+ const Vector<EditorData::CustomType> &ct = E->value();
+ for (int i = 0; i < ct.size(); ++i) {
+ if (ct[i].name == p_type) {
+ if (ct[i].icon.is_valid()) {
+ return ct[i].icon;
+ } else {
+ return get_icon("Object", "EditorIcons");
+ }
+ }
+ }
+ }
+
+ return get_icon("Object", "EditorIcons");
+}
+
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))
@@ -147,11 +165,14 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p
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_custom_color(0, get_color("disabled_font_color", "Editor"));
item->set_selectable(0, false);
} else {
+ bool is_search_subsequence = search_box->get_text().is_subsequence_ofi(p_type);
+ String to_select_type = *to_select ? (*to_select)->get_text(0) : "";
+ bool current_item_is_preffered = ClassDB::is_parent_class(p_type, preferred_search_result_type) && !ClassDB::is_parent_class(to_select_type, preferred_search_result_type);
- if ((!*to_select && (search_box->get_text().is_subsequence_ofi(p_type))) || search_box->get_text() == p_type) {
+ if (((!*to_select || current_item_is_preffered) && is_search_subsequence) || search_box->get_text() == p_type) {
*to_select = item;
}
}
@@ -343,6 +364,19 @@ void CreateDialog::set_base_type(const String &p_base) {
_update_search();
}
+String CreateDialog::get_base_type() const {
+
+ return base_type;
+}
+
+void CreateDialog::set_preferred_search_result_type(const String &p_preferred_type) {
+ preferred_search_result_type = p_preferred_type;
+}
+
+String CreateDialog::get_preferred_search_result_type() {
+
+ return preferred_search_result_type;
+}
String CreateDialog::get_selected_type() {
TreeItem *selected = search_options->get_selected();
@@ -393,11 +427,6 @@ Object *CreateDialog::instance_selected() {
return NULL;
}
-String CreateDialog::get_base_type() const {
-
- return base_type;
-}
-
void CreateDialog::_item_selected() {
TreeItem *item = search_options->get_selected();
@@ -457,13 +486,7 @@ void CreateDialog::_update_favorite_list() {
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"));
- }
+ ti->set_icon(0, _get_editor_icon(l));
}
}
@@ -501,7 +524,7 @@ void CreateDialog::_favorite_activated() {
Variant CreateDialog::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
- TreeItem *ti = favorites->get_item_at_pos(p_point);
+ TreeItem *ti = favorites->get_item_at_position(p_point);
if (ti) {
Dictionary d;
d["type"] = "create_favorite_drag";
@@ -532,12 +555,12 @@ void CreateDialog::drop_data_fw(const Point2 &p_point, const Variant &p_data, Co
Dictionary d = p_data;
- TreeItem *ti = favorites->get_item_at_pos(p_point);
+ TreeItem *ti = favorites->get_item_at_position(p_point);
if (!ti)
return;
String drop_at = ti->get_text(0);
- int ds = favorites->get_drop_section_at_pos(p_point);
+ int ds = favorites->get_drop_section_at_position(p_point);
int drop_idx = favorite_list.find(drop_at);
if (drop_idx < 0)
@@ -625,6 +648,7 @@ CreateDialog::CreateDialog() {
search_box->set_h_size_flags(SIZE_EXPAND_FILL);
search_hb->add_child(search_box);
favorite = memnew(Button);
+ favorite->set_flat(true);
favorite->set_toggle_mode(true);
search_hb->add_child(favorite);
favorite->connect("pressed", this, "_favorite_toggled");
@@ -641,6 +665,7 @@ CreateDialog::CreateDialog() {
search_options->connect("cell_selected", this, "_item_selected");
//search_options->set_hide_root(true);
base_type = "Object";
+ preferred_search_result_type = "";
help_bit = memnew(EditorHelpBit);
vbc->add_margin_child(TTR("Description:"), help_bit);
diff --git a/editor/create_dialog.h b/editor/create_dialog.h
index 31f106ea22..2e4ce9b277 100644
--- a/editor/create_dialog.h
+++ b/editor/create_dialog.h
@@ -53,7 +53,7 @@ class CreateDialog : public ConfirmationDialog {
LineEdit *search_box;
Tree *search_options;
String base_type;
-
+ String preferred_search_result_type;
EditorHelpBit *help_bit;
void _item_selected();
@@ -74,6 +74,8 @@ class CreateDialog : public ConfirmationDialog {
void _confirmed();
void _text_changed(const String &p_newtext);
+ Ref<Texture> _get_editor_icon(const String &p_type) const;
+
void add_type(const String &p_type, HashMap<String, TreeItem *> &p_types, TreeItem *p_root, TreeItem **to_select);
Variant get_drag_data_fw(const Point2 &p_point, Control *p_from);
@@ -91,6 +93,9 @@ public:
void set_base_type(const String &p_base);
String get_base_type() const;
+ void set_preferred_search_result_type(const String &p_preferred_type);
+ String get_preferred_search_result_type();
+
void popup_create(bool p_dontclear);
CreateDialog();
diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp
index 54bf31cd62..5305c4f256 100644
--- a/editor/dependency_editor.cpp
+++ b/editor/dependency_editor.cpp
@@ -409,17 +409,22 @@ void DependencyRemoveDialog::show(const Vector<String> &to_erase) {
void DependencyRemoveDialog::ok_pressed() {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
+ bool changed = false;
+
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());
+ String fpath = OS::get_singleton()->get_resource_dir() + E->key().replace_first("res://", "/");
+ OS::get_singleton()->move_to_trash(fpath);
+ changed = true;
+ }
+
+ if (changed) {
+ EditorFileSystem::get_singleton()->scan_changes();
}
- memdelete(da);
}
DependencyRemoveDialog::DependencyRemoveDialog() {
diff --git a/editor/doc/doc_data.cpp b/editor/doc/doc_data.cpp
index 272a5af59b..d35dc53ae1 100644
--- a/editor/doc/doc_data.cpp
+++ b/editor/doc/doc_data.cpp
@@ -170,6 +170,8 @@ static void return_doc_from_retinfo(DocData::MethodDoc &p_method, const Property
if (p_retinfo.type == Variant::INT && p_retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
p_method.return_enum = p_retinfo.class_name;
+ if (p_method.return_enum.begins_with("_")) //proxy class
+ p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length());
p_method.return_type = "int";
} else if (p_retinfo.class_name != StringName()) {
p_method.return_type = p_retinfo.class_name;
@@ -190,6 +192,8 @@ static void argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const Pr
if (p_arginfo.type == Variant::INT && p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
p_argument.enumeration = p_arginfo.class_name;
+ if (p_argument.enumeration.begins_with("_")) //proxy class
+ p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length());
p_argument.type = "int";
} else if (p_arginfo.class_name != StringName()) {
p_argument.type = p_arginfo.class_name;
diff --git a/editor/editor_asset_installer.cpp b/editor/editor_asset_installer.cpp
index a8eee24fe2..1aac697ffd 100644
--- a/editor/editor_asset_installer.cpp
+++ b/editor/editor_asset_installer.cpp
@@ -197,7 +197,7 @@ void EditorAssetInstaller::open(const String &p_path, int p_depth) {
String res_path = "res://" + path;
if (FileAccess::exists(res_path)) {
- ti->set_custom_color(0, Color(1, 0.3, 0.2));
+ ti->set_custom_color(0, get_color("error_color", "Editor"));
ti->set_tooltip(0, res_path + " (Already Exists)");
ti->set_checked(0, false);
} else {
diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp
index a36faeb0de..de64c11308 100644
--- a/editor/editor_audio_buses.cpp
+++ b/editor/editor_audio_buses.cpp
@@ -64,6 +64,8 @@ void EditorAudioBus::_notification(int p_what) {
if (has_focus()) {
draw_style_box(get_stylebox("focus", "Button"), Rect2(Vector2(), get_size()));
+ } else if (is_master) {
+ draw_style_box(get_stylebox("disabled", "Button"), Rect2(Vector2(), get_size()));
}
}
@@ -123,7 +125,7 @@ void EditorAudioBus::_notification(int p_what) {
void EditorAudioBus::update_send() {
send->clear();
- if (get_index() == 0) {
+ if (is_master) {
send->set_disabled(true);
send->set_text(TTR("Speakers"));
} else {
@@ -154,7 +156,7 @@ void EditorAudioBus::update_bus() {
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)
+ if (is_master)
track_name->set_editable(false);
solo->set_pressed(AudioServer::get_singleton()->is_bus_solo(index));
@@ -237,6 +239,8 @@ void EditorAudioBus::_name_changed(const String &p_new_name) {
ur->commit_action();
updating_bus = false;
+
+ track_name->release_focus();
}
void EditorAudioBus::_volume_db_changed(float p_db) {
@@ -401,7 +405,6 @@ void EditorAudioBus::_gui_input(const Ref<InputEvent> &p_event) {
Vector2 pos = Vector2(mb->get_position().x, mb->get_position().y);
bus_popup->set_position(get_global_position() + pos);
- bus_popup->set_item_disabled(1, get_index() == 0);
bus_popup->popup();
}
}
@@ -459,7 +462,7 @@ void EditorAudioBus::drop_data(const Point2 &p_point, const Variant &p_data) {
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);
+ TreeItem *item = effects->get_item_at_position(p_point);
if (!item) {
print_line("no item");
return Variant();
@@ -489,7 +492,7 @@ bool EditorAudioBus::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
if (!d.has("type") || String(d["type"]) != "audio_bus_effect")
return false;
- TreeItem *item = effects->get_item_at_pos(p_point);
+ TreeItem *item = effects->get_item_at_position(p_point);
if (!item)
return false;
@@ -502,10 +505,10 @@ void EditorAudioBus::drop_data_fw(const Point2 &p_point, const Variant &p_data,
Dictionary d = p_data;
- TreeItem *item = effects->get_item_at_pos(p_point);
+ TreeItem *item = effects->get_item_at_position(p_point);
if (!item)
return;
- int pos = effects->get_drop_section_at_pos(p_point);
+ int pos = effects->get_drop_section_at_position(p_point);
Variant md = item->get_metadata(0);
int paste_at;
@@ -619,10 +622,11 @@ void EditorAudioBus::_bind_methods() {
ADD_SIGNAL(MethodInfo("dropped"));
}
-EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses) {
+EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) {
buses = p_buses;
updating_bus = false;
+ is_master = p_is_master;
set_tooltip(TTR("Audio Bus, Drag and Drop to rearrange."));
@@ -630,24 +634,15 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses) {
add_child(vb);
set_v_size_flags(SIZE_EXPAND_FILL);
+ set_custom_minimum_size(Size2(100, 0) * EDSCALE);
- HBoxContainer *head = memnew(HBoxContainer);
track_name = memnew(LineEdit);
- head->add_child(track_name);
track_name->connect("text_entered", this, "_name_changed");
track_name->connect("focus_exited", this, "_name_focus_exit");
- track_name->set_h_size_flags(SIZE_EXPAND_FILL);
-
- bus_options = memnew(MenuButton);
- bus_options->set_h_size_flags(SIZE_SHRINK_END);
- bus_options->set_tooltip(TTR("Bus options"));
- head->add_child(bus_options);
-
- vb->add_child(head);
+ vb->add_child(track_name);
HBoxContainer *hbc = memnew(HBoxContainer);
vb->add_child(hbc);
- hbc->add_spacer();
solo = memnew(ToolButton);
solo->set_toggle_mode(true);
solo->set_tooltip(TTR("Solo"));
@@ -668,6 +663,23 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses) {
hbc->add_child(bypass);
hbc->add_spacer();
+ bus_options = memnew(MenuButton);
+ bus_options->set_h_size_flags(SIZE_SHRINK_END);
+ bus_options->set_anchor(MARGIN_RIGHT, 0.0);
+ bus_options->set_tooltip(TTR("Bus options"));
+ hbc->add_child(bus_options);
+
+ Ref<StyleBoxEmpty> sbempty = memnew(StyleBoxEmpty);
+ for (int i = 0; i < hbc->get_child_count(); i++) {
+ Control *child = Object::cast_to<Control>(hbc->get_child(i));
+ child->add_style_override("normal", sbempty);
+ child->add_style_override("hover", sbempty);
+ child->add_style_override("focus", sbempty);
+ child->add_style_override("pressed", sbempty);
+ }
+
+ vb->add_child(memnew(HSeparator));
+
HBoxContainer *hb = memnew(HBoxContainer);
vb->add_child(hb);
slider = memnew(VSlider);
@@ -699,8 +711,6 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses) {
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, 100) * EDSCALE);
@@ -745,6 +755,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses) {
bus_popup = bus_options->get_popup();
bus_popup->add_item(TTR("Duplicate"));
bus_popup->add_item(TTR("Delete"));
+ bus_popup->set_item_disabled(1, is_master);
bus_popup->add_item(TTR("Reset Volume"));
bus_popup->connect("index_pressed", this, "_bus_popup_pressed");
@@ -787,10 +798,8 @@ void EditorAudioBuses::_update_buses() {
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));
- }
+ bool is_master = i == 0 ? true : false;
+ EditorAudioBus *audio_bus = memnew(EditorAudioBus(this, is_master));
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);
diff --git a/editor/editor_audio_buses.h b/editor/editor_audio_buses.h
index dba1b73295..995def468c 100644
--- a/editor/editor_audio_buses.h
+++ b/editor/editor_audio_buses.h
@@ -84,6 +84,8 @@ class EditorAudioBus : public PanelContainer {
bool updating_bus;
+ bool is_master;
+
void _gui_input(const Ref<InputEvent> &p_event);
void _bus_popup_pressed(int p_option);
@@ -120,7 +122,7 @@ public:
void update_bus();
void update_send();
- EditorAudioBus(EditorAudioBuses *p_buses = NULL);
+ EditorAudioBus(EditorAudioBuses *p_buses = NULL, bool p_is_master = false);
};
class EditorAudioBusDrop : public Panel {
diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp
index 82a7fa734a..efa9572bf5 100644
--- a/editor/editor_autoload_settings.cpp
+++ b/editor/editor_autoload_settings.cpp
@@ -364,7 +364,7 @@ void EditorAutoloadSettings::update_autoload() {
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->add_button(3, get_icon("Remove", "EditorIcons"), BUTTON_DELETE);
item->set_selectable(3, false);
}
@@ -419,12 +419,12 @@ bool EditorAutoloadSettings::can_drop_data_fw(const Point2 &p_point, const Varia
return false;
if (drop_data.has("type")) {
- TreeItem *ti = tree->get_item_at_pos(p_point);
+ TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return false;
- int section = tree->get_drop_section_at_pos(p_point);
+ int section = tree->get_drop_section_at_position(p_point);
if (section < -1)
return false;
@@ -437,12 +437,12 @@ bool EditorAutoloadSettings::can_drop_data_fw(const Point2 &p_point, const Varia
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);
+ TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return;
- int section = tree->get_drop_section_at_pos(p_point);
+ int section = tree->get_drop_section_at_position(p_point);
if (section < -1)
return;
diff --git a/editor/editor_dir_dialog.cpp b/editor/editor_dir_dialog.cpp
index cfb3abfd1d..658c12d4d0 100644
--- a/editor/editor_dir_dialog.cpp
+++ b/editor/editor_dir_dialog.cpp
@@ -64,7 +64,7 @@ void EditorDirDialog::_update_dir(TreeItem *p_item, EditorFileSystemDirectory *p
}
}
-void EditorDirDialog::reload(const String &p_with_path) {
+void EditorDirDialog::reload(const String &p_path) {
if (!is_visible_in_tree()) {
must_reload = true;
@@ -73,7 +73,7 @@ void EditorDirDialog::reload(const String &p_with_path) {
tree->clear();
TreeItem *root = tree->create_item();
- _update_dir(root, EditorFileSystem::get_singleton()->get_filesystem(), p_with_path);
+ _update_dir(root, EditorFileSystem::get_singleton()->get_filesystem(), p_path);
_item_collapsed(root);
must_reload = false;
}
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp
index d08a595fd2..db12998dd2 100644
--- a/editor/editor_export.cpp
+++ b/editor/editor_export.cpp
@@ -273,12 +273,14 @@ void EditorExportPlatform::gen_debug_flags(Vector<String> &r_flags, int p_flags)
}
Error EditorExportPlatform::_save_pack_file(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) {
+ if (p_path.ends_with(".so") || p_path.ends_with(".dylib") || p_path.ends_with(".dll"))
+ return OK;
PackData *pd = (PackData *)p_userdata;
SavedData sd;
sd.path_utf8 = p_path.utf8();
- sd.ofs = pd->f->get_pos();
+ sd.ofs = pd->f->get_position();
sd.size = p_data.size();
pd->f->store_buffer(p_data.ptr(), p_data.size());
@@ -736,7 +738,7 @@ Error EditorExportPlatform::save_pack(const Ref<EditorExportPreset> &p_preset, c
f->store_32(pd.file_ofs.size()); //amount of files
- size_t header_size = f->get_pos();
+ size_t header_size = f->get_position();
//precalculate header size
@@ -1246,9 +1248,13 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr
}
DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- da->copy(template_path, p_path);
+ Error err = da->copy(template_path, p_path, get_chmod_flags());
memdelete(da);
+ if (err != OK) {
+ return err;
+ }
+
String pck_path = p_path.get_basename() + ".pck";
return save_pack(p_preset, pck_path);
@@ -1302,5 +1308,17 @@ void EditorExportPlatformPC::get_platform_features(List<String> *r_features) {
}
}
+int EditorExportPlatformPC::get_chmod_flags() const {
+
+ return chmod_flags;
+}
+
+void EditorExportPlatformPC::set_chmod_flags(int p_flags) {
+
+ chmod_flags = p_flags;
+}
+
EditorExportPlatformPC::EditorExportPlatformPC() {
+
+ chmod_flags = -1;
}
diff --git a/editor/editor_export.h b/editor/editor_export.h
index b6ea4fd889..50379b9683 100644
--- a/editor/editor_export.h
+++ b/editor/editor_export.h
@@ -319,6 +319,7 @@ class EditorExportPlatformPC : public EditorExportPlatform {
Set<String> extra_features;
bool use64;
+ int chmod_flags;
public:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
@@ -347,6 +348,9 @@ public:
void add_platform_feature(const String &p_feature);
virtual void get_platform_features(List<String> *r_features);
+ int get_chmod_flags() const;
+ void set_chmod_flags(int p_flags);
+
EditorExportPlatformPC();
};
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 9d1756a7ec..b980c4f0ec 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -56,15 +56,15 @@ void EditorFileDialog::_notification(int p_what) {
//_update_icons
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_prev->set_icon(get_icon("Back", "EditorIcons"));
+ dir_next->set_icon(get_icon("Forward", "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"));
+ fav_rm->set_icon(get_icon("Remove", "EditorIcons"));
} else if (p_what == NOTIFICATION_PROCESS) {
@@ -97,18 +97,16 @@ void EditorFileDialog::_notification(int p_what) {
//_update_icons
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_prev->set_icon(get_icon("Back", "EditorIcons"));
+ dir_next->set_icon(get_icon("Forward", "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"));
+ fav_rm->set_icon(get_icon("Remove", "EditorIcons"));
- Theme::get_default()->clear_icon("ResizedFile", "EditorIcons");
- Theme::get_default()->clear_icon("ResizedFolder", "EditorIcons");
update_file_list();
}
}
@@ -1283,6 +1281,7 @@ EditorFileDialog::EditorFileDialog() {
dir_prev = memnew(ToolButton);
dir_next = memnew(ToolButton);
dir_up = memnew(ToolButton);
+ dir_up->set_tooltip(TTR("Go to parent folder"));
pathhb->add_child(dir_prev);
pathhb->add_child(dir_next);
@@ -1292,6 +1291,8 @@ EditorFileDialog::EditorFileDialog() {
dir_next->connect("pressed", this, "_go_forward");
dir_up->connect("pressed", this, "_go_up");
+ pathhb->add_child(memnew(Label(TTR("Path:"))));
+
dir = memnew(LineEdit);
pathhb->add_child(dir);
dir->set_h_size_flags(SIZE_EXPAND_FILL);
@@ -1301,6 +1302,7 @@ EditorFileDialog::EditorFileDialog() {
pathhb->add_child(refresh);
favorite = memnew(ToolButton);
+ favorite->set_flat(true);
favorite->set_toggle_mode(true);
favorite->connect("toggled", this, "_favorite_toggled");
pathhb->add_child(favorite);
@@ -1331,9 +1333,9 @@ EditorFileDialog::EditorFileDialog() {
makedir->connect("pressed", this, "_make_dir");
pathhb->add_child(makedir);
- list_hb = memnew(HBoxContainer);
+ list_hb = memnew(HSplitContainer);
- vbc->add_margin_child(TTR("Path:"), pathhb);
+ vbc->add_child(pathhb);
vbc->add_child(list_hb);
list_hb->set_v_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 3b22189014..4dc2947292 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -36,6 +36,7 @@
#include "scene/gui/item_list.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/option_button.h"
+#include "scene/gui/split_container.h"
#include "scene/gui/texture_rect.h"
#include "scene/gui/tool_button.h"
/**
@@ -92,7 +93,7 @@ private:
ItemList *item_list;
TextureRect *preview;
VBoxContainer *preview_vb;
- HBoxContainer *list_hb;
+ HSplitContainer *list_hb;
LineEdit *file;
AcceptDialog *mkdirerr;
AcceptDialog *exterr;
diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp
index 6e12a8fd02..481f2a8179 100644
--- a/editor/editor_file_system.cpp
+++ b/editor/editor_file_system.cpp
@@ -1498,10 +1498,22 @@ void EditorFileSystem::reimport_files(const Vector<String> &p_files) {
importing = true;
EditorProgress pr("reimport", TTR("(Re)Importing Assets"), p_files.size());
+
+ Vector<ImportFile> files;
+
for (int i = 0; i < p_files.size(); i++) {
- pr.step(p_files[i].get_file(), i);
+ ImportFile ifile;
+ ifile.path = p_files[i];
+ ifile.order = ResourceFormatImporter::get_singleton()->get_import_order(p_files[i]);
+ files.push_back(ifile);
+ }
+
+ files.sort();
+
+ for (int i = 0; i < files.size(); i++) {
+ pr.step(files[i].path.get_file(), i);
- _reimport_file(p_files[i]);
+ _reimport_file(files[i].path);
}
_save_filesystem_cache();
diff --git a/editor/editor_file_system.h b/editor/editor_file_system.h
index cee3219b43..ebcc091b0a 100644
--- a/editor/editor_file_system.h
+++ b/editor/editor_file_system.h
@@ -206,6 +206,14 @@ class EditorFileSystem : public Node {
Vector<String> _get_dependencies(const String &p_path);
+ struct ImportFile {
+ String path;
+ int order;
+ bool operator<(const ImportFile &p_if) const {
+ return order < p_if.order;
+ }
+ };
+
protected:
void _notification(int p_what);
static void _bind_methods();
diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp
index d806b825ba..05f9da03e1 100644
--- a/editor/editor_fonts.cpp
+++ b/editor/editor_fonts.cpp
@@ -119,10 +119,10 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DynamicFontData> dfmono;
dfmono.instance();
- dfmono->set_font_ptr(_font_mononoki_Regular, _font_mononoki_Regular_size);
+ dfmono->set_font_ptr(_font_Hack_Regular, _font_Hack_Regular_size);
//dfd->set_force_autohinter(true); //just looks better..i think?
- MAKE_DEFAULT_FONT(df, int(EditorSettings::get_singleton()->get("interface/font_size")) * EDSCALE);
+ MAKE_DEFAULT_FONT(df, int(EditorSettings::get_singleton()->get("interface/editor/font_size")) * EDSCALE);
p_theme->set_default_theme_font(df);
@@ -130,16 +130,19 @@ void editor_register_fonts(Ref<Theme> p_theme) {
//Ref<BitmapFont> doc_title_font = make_font(_bi_font_doc_title_font_height,_bi_font_doc_title_font_ascent,0,_bi_font_doc_title_font_charcount,_bi_font_doc_title_font_characters,p_theme->get_icon("DocTitleFont","EditorIcons"));
//Ref<BitmapFont> doc_code_font = make_font(_bi_font_doc_code_font_height,_bi_font_doc_code_font_ascent,0,_bi_font_doc_code_font_charcount,_bi_font_doc_code_font_characters,p_theme->get_icon("DocCodeFont","EditorIcons"));
- MAKE_DEFAULT_FONT(df_title, int(EDITOR_DEF("text_editor/help/help_title_font_size", 18)) * EDSCALE);
+ MAKE_DEFAULT_FONT(df_title, int(EDITOR_DEF("text_editor/help/help_title_font_size", 16)) * EDSCALE);
- MAKE_DEFAULT_FONT(df_doc, int(EDITOR_DEF("text_editor/help/help_font_size", 16)) * EDSCALE);
+ MAKE_DEFAULT_FONT(df_doc, int(EDITOR_DEF("text_editor/help/help_font_size", 14)) * EDSCALE);
p_theme->set_font("doc", "EditorFonts", df_doc);
p_theme->set_font("doc_title", "EditorFonts", df_title);
+ MAKE_DEFAULT_FONT(df_rulers, int(EDITOR_DEF("canvas_item_editor/rulers", 8)) * EDSCALE);
+ p_theme->set_font("rulers", "EditorFonts", df_rulers);
+
Ref<DynamicFont> df_code;
df_code.instance();
- df_code->set_size(int(EditorSettings::get_singleton()->get("interface/source_font_size")) * EDSCALE);
+ df_code->set_size(int(EditorSettings::get_singleton()->get("interface/editor/source_font_size")) * EDSCALE);
df_code->set_font_data(dfmono);
MAKE_FALLBACKS(df_code);
@@ -147,7 +150,7 @@ void editor_register_fonts(Ref<Theme> p_theme) {
Ref<DynamicFont> df_doc_code;
df_doc_code.instance();
- df_doc_code->set_size(int(EDITOR_DEF("text_editor/help/help_source_font_size", 18)) * EDSCALE);
+ df_doc_code->set_size(int(EDITOR_DEF("text_editor/help/help_source_font_size", 16)) * EDSCALE);
df_doc_code->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE);
df_doc_code->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE);
df_doc_code->set_font_data(dfmono);
@@ -155,6 +158,25 @@ void editor_register_fonts(Ref<Theme> p_theme) {
p_theme->set_font("doc_source", "EditorFonts", df_doc_code);
+ Ref<DynamicFont> df_output_code;
+ df_output_code.instance();
+ df_output_code->set_size(int(EDITOR_DEF("run/output/font_size", 13)) * EDSCALE);
+ df_output_code->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE);
+ df_output_code->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE);
+ df_output_code->set_font_data(dfmono);
+ MAKE_FALLBACKS(df_output_code);
+
+ p_theme->set_font("output_source", "EditorFonts", df_output_code);
+
+ Ref<DynamicFont> df_text_editor_status_code;
+ df_output_code.instance();
+ df_output_code->set_size(14 * EDSCALE);
+ df_output_code->set_spacing(DynamicFont::SPACING_TOP, -EDSCALE);
+ df_output_code->set_spacing(DynamicFont::SPACING_BOTTOM, -EDSCALE);
+ df_output_code->set_font_data(dfmono);
+ MAKE_FALLBACKS(df_output_code);
+ p_theme->set_font("status_source", "EditorFonts", df_output_code);
+
//replace default theme
Ref<Texture> di;
Ref<StyleBox> ds;
diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp
index 6c8bd0f14b..cb94ea72d1 100644
--- a/editor/editor_help.cpp
+++ b/editor/editor_help.cpp
@@ -650,8 +650,8 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
// Colors
const Color title_color = get_color("accent_color", "Editor");
- const Color text_color = get_color("font_color", "RichTextLabel");
- const Color highlight_color = get_color("highlight_color", "RichTextLabel");
+ const Color text_color = get_color("default_color", "RichTextLabel");
+ const Color headline_color = get_color("headline_color", "EditorHelp");
const Color base_type_color = title_color.linear_interpolate(text_color, 0.5);
const Color comment_color = Color(text_color.r, text_color.g, text_color.b, 0.6);
const Color symbol_color = comment_color;
@@ -669,7 +669,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->push_font(doc_title_font);
class_desc->push_color(title_color);
class_desc->add_text(TTR("Class:") + " ");
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(p_class);
class_desc->pop();
class_desc->pop();
@@ -812,7 +812,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
}
class_desc->push_font(doc_code_font);
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(cd.properties[i].name);
if (describe) {
@@ -883,7 +883,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
method_descr = true;
class_desc->push_meta("@" + methods[i].name);
}
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(methods[i].name);
class_desc->pop();
if (methods[i].description != "")
@@ -969,7 +969,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->push_cell();
class_desc->push_font(doc_code_font);
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(cd.theme_properties[i].name);
class_desc->pop();
class_desc->pop();
@@ -1015,7 +1015,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
class_desc->push_font(doc_code_font); // monofont
//_add_type("void");
//class_desc->add_text(" ");
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(cd.signals[i].name);
class_desc->pop();
class_desc->push_color(symbol_color);
@@ -1102,7 +1102,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
e = e.get_slice(".", 1);
}
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
class_desc->add_text(e);
class_desc->pop();
class_desc->pop();
@@ -1117,7 +1117,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
for (int i = 0; i < enum_list.size(); i++) {
class_desc->push_font(doc_code_font);
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(enum_list[i].name);
class_desc->pop();
class_desc->push_color(symbol_color);
@@ -1165,7 +1165,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
constant_line[constants[i].name] = class_desc->get_line_count() - 2;
class_desc->push_font(doc_code_font);
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(constants[i].name);
class_desc->pop();
class_desc->push_color(symbol_color);
@@ -1235,7 +1235,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
_add_type(cd.properties[i].type, cd.properties[i].enumeration);
class_desc->add_text(" ");
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(cd.properties[i].name);
class_desc->pop(); //color
@@ -1324,7 +1324,7 @@ Error EditorHelp::_goto_desc(const String &p_class, int p_vscr) {
_add_type(methods[i].return_type, methods[i].return_enum);
class_desc->add_text(" ");
- class_desc->push_color(highlight_color);
+ class_desc->push_color(headline_color);
_add_text(methods[i].name);
class_desc->pop();
class_desc->push_color(symbol_color);
@@ -1456,7 +1456,7 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) {
Ref<Font> doc_font = p_rt->get_font("doc", "EditorFonts");
Ref<Font> doc_code_font = p_rt->get_font("doc_source", "EditorFonts");
- Color font_color_hl = p_rt->get_color("highlight_color", "RichTextLabel");
+ Color font_color_hl = p_rt->get_color("headline_color", "EditorHelp");
Color link_color = p_rt->get_color("accent_color", "Editor").linear_interpolate(font_color_hl, 0.8);
String bbcode = p_bbcode.replace("\t", " ").replace("\r", " ").strip_edges();
@@ -1695,9 +1695,6 @@ void EditorHelp::_notification(int p_what) {
//back->set_icon(get_icon("Back","EditorIcons"));
_update_doc();
- class_desc->add_style_override("normal", class_desc->get_stylebox("code_normal", "RichTextLabel"));
- class_desc->add_style_override("focus", class_desc->get_stylebox("code_focus", "RichTextLabel"));
-
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
@@ -1790,7 +1787,6 @@ EditorHelp::EditorHelp() {
{
class_desc = memnew(RichTextLabel);
vbc->add_child(class_desc);
- class_desc->set_area_as_parent_rect();
class_desc->set_v_size_flags(SIZE_EXPAND_FILL);
class_desc->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
class_desc->connect("meta_clicked", this, "_class_desc_select");
@@ -1900,7 +1896,7 @@ EditorHelpBit::EditorHelpBit() {
rich_text = memnew(RichTextLabel);
add_child(rich_text);
- rich_text->set_area_as_parent_rect();
+ rich_text->set_anchors_and_margins_preset(Control::PRESET_WIDE);
rich_text->connect("meta_clicked", this, "_meta_clicked");
rich_text->add_color_override("selection_color", EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1)));
set_custom_minimum_size(Size2(0, 70 * EDSCALE));
diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp
index 035819f503..407420d3d0 100644
--- a/editor/editor_log.cpp
+++ b/editor/editor_log.cpp
@@ -31,6 +31,7 @@
#include "editor_node.h"
#include "scene/gui/center_container.h"
+#include "scene/resources/dynamic_font.h"
#include "version.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) {
@@ -51,7 +52,6 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f
self->emit_signal("show_request");
*/
- err_str = " " + err_str;
self->add_message(err_str, true);
}
@@ -60,6 +60,13 @@ void EditorLog::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
//button->set_icon(get_icon("Console","EditorIcons"));
+ log->add_font_override("normal_font", get_font("output_source", "EditorFonts"));
+ } else if (p_what == NOTIFICATION_THEME_CHANGED) {
+ Ref<DynamicFont> df_output_code = get_font("output_source", "EditorFonts");
+ if (df_output_code.is_valid()) {
+ df_output_code->set_size(int(EDITOR_DEF("run/output/font_size", 13)) * EDSCALE);
+ log->add_font_override("normal_font", get_font("output_source", "EditorFonts"));
+ }
}
/*if (p_what==NOTIFICATION_DRAW) {
@@ -86,10 +93,12 @@ void EditorLog::clear() {
void EditorLog::add_message(const String &p_msg, bool p_error) {
log->add_newline();
+
if (p_error) {
log->push_color(get_color("error_color", "Editor"));
Ref<Texture> icon = get_icon("Error", "EditorIcons");
log->add_image(icon);
+ log->add_text(" ");
//button->set_icon(icon);
} else {
//button->set_icon(Ref<Texture>());
@@ -152,7 +161,6 @@ EditorLog::EditorLog() {
log->set_selection_enabled(true);
log->set_focus_mode(FOCUS_CLICK);
log->set_custom_minimum_size(Size2(0, 180) * EDSCALE);
- log->set_area_as_parent_rect();
log->set_v_size_flags(SIZE_EXPAND_FILL);
log->set_h_size_flags(SIZE_EXPAND_FILL);
vb->add_child(log);
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 3f0520379a..a04ded7b5b 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -114,7 +114,7 @@ EditorNode *EditorNode::singleton = NULL;
void EditorNode::_update_scene_tabs() {
- bool show_rb = EditorSettings::get_singleton()->get("interface/show_script_in_scene_tabs");
+ bool show_rb = EditorSettings::get_singleton()->get("interface/editor/show_script_in_scene_tabs");
scene_tabs->clear_tabs();
Ref<Texture> script_icon = gui_base->get_icon("Script", "EditorIcons");
@@ -282,8 +282,8 @@ void EditorNode::_notification(int p_what) {
}
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));
- property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/capitalize_properties", true)));
+ scene_tabs->set_tab_close_display_policy((bool(EDITOR_DEF("interface/editor/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
+ property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
Ref<Theme> theme = create_editor_theme(theme_base->get_theme());
theme_base->set_theme(theme);
@@ -308,6 +308,10 @@ void EditorNode::_notification(int p_what) {
}
_update_scene_tabs();
+ // debugger area
+ if (ScriptEditor::get_singleton()->get_debugger()->is_visible())
+ bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles"));
+
//_update_icons
for (int i = 0; i < singleton->main_editor_buttons.size(); i++) {
main_editor_buttons[i]->set_icon(gui_base->get_icon(singleton->main_editor_buttons[i]->get_name(), "EditorIcons"));
@@ -2240,10 +2244,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case RUN_PROJECT_MANAGER: {
if (!p_confirmed) {
- bool save_each = EDITOR_DEF("interface/save_each_scene_on_quit", true);
+ bool save_each = EDITOR_DEF("interface/editor/save_each_scene_on_quit", true);
if (_next_unsaved_scene(!save_each) == -1) {
- bool confirm = EDITOR_DEF("interface/quit_confirmation", true);
+ bool confirm = EDITOR_DEF("interface/editor/quit_confirmation", true);
if (confirm) {
confirmation->get_ok()->set_text(p_option == FILE_QUIT ? TTR("Quit") : TTR("Yes"));
@@ -2568,7 +2572,7 @@ void EditorNode::_editor_select(int p_which) {
editor_data.get_editor_plugin(i)->notify_main_screen_changed(editor_plugin_screen->get_name());
}
- if (EditorSettings::get_singleton()->get("interface/separate_distraction_mode")) {
+ if (EditorSettings::get_singleton()->get("interface/editor/separate_distraction_mode")) {
if (p_which == EDITOR_SCRIPT) {
set_distraction_free_mode(script_distraction);
} else {
@@ -2780,14 +2784,6 @@ Dictionary EditorNode::_get_main_scene_state() {
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();
- int current = -1;
- for (int i = 0; i < editor_table.size(); i++) {
- if (editor_plugin_screen == editor_table[i]) {
- current = i;
- break;
- }
- }
- state["editor_index"] = current;
return state;
}
@@ -2798,29 +2794,32 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
changing_scene = false;
- if (p_state.has("editor_index")) {
-
- int index = p_state["editor_index"];
- int current = -1;
- for (int i = 0; i < editor_table.size(); i++) {
- if (editor_plugin_screen == editor_table[i]) {
- current = i;
- break;
- }
+ int current = -1;
+ for (int i = 0; i < editor_table.size(); i++) {
+ if (editor_plugin_screen == editor_table[i]) {
+ current = i;
+ break;
}
+ }
+ if (p_state.has("editor_index")) {
+ int index = p_state["editor_index"];
if (current < 2) { //if currently in spatial/2d, only switch to spatial/2d. if curently in script, stay there
if (index < 2 || !get_edited_scene()) {
_editor_select(index);
- } else {
- //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);
- }
+ }
+ }
+ }
+
+ if (get_edited_scene()) {
+ 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);
}
}
}
@@ -3252,6 +3251,7 @@ void EditorNode::register_editor_types() {
ClassDB::register_virtual_class<ScriptEditor>();
ClassDB::register_virtual_class<EditorInterface>();
ClassDB::register_class<EditorExportPlugin>();
+ ClassDB::register_class<EditorResourceConversionPlugin>();
// FIXME: Is this stuff obsolete, or should it be ported to new APIs?
//ClassDB::register_class<EditorScenePostImport>();
@@ -3343,9 +3343,9 @@ void EditorNode::_editor_file_dialog_unregister(EditorFileDialog *p_dialog) {
Vector<EditorNodeInitCallback> EditorNode::_init_callbacks;
-Error EditorNode::export_preset(const String &preset, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after) {
+Error EditorNode::export_preset(const String &p_preset, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after) {
- export_defer.preset = preset;
+ export_defer.preset = p_preset;
export_defer.path = p_path;
export_defer.debug = p_debug;
export_defer.password = p_password;
@@ -3472,7 +3472,7 @@ void EditorNode::_dock_select_draw() {
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 tab_selected = theme_base->get_color("mono_color", "Editor");
Color unused = used;
unused.a = 0.4;
Color unusable = unused;
@@ -4071,9 +4071,15 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
bottom_panel_items[i].button->set_pressed(i == p_idx);
bottom_panel_items[i].control->set_visible(i == p_idx);
}
+ if (ScriptEditor::get_singleton()->get_debugger() == bottom_panel_items[p_idx].control) { // this is the debug panel wich uses tabs, so the top section should be smaller
+ bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles"));
+ } else {
+ bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
+ }
center_split->set_dragger_visibility(SplitContainer::DRAGGER_VISIBLE);
center_split->set_collapsed(false);
} else {
+ bottom_panel->add_style_override("panel", gui_base->get_stylebox("panel", "TabContainer"));
for (int i = 0; i < bottom_panel_items.size(); i++) {
bottom_panel_items[i].button->set_pressed(false);
@@ -4095,7 +4101,7 @@ bool EditorNode::get_docks_visible() const {
void EditorNode::_toggle_distraction_free_mode() {
- if (EditorSettings::get_singleton()->get("interface/separate_distraction_mode")) {
+ if (EditorSettings::get_singleton()->get("interface/editor/separate_distraction_mode")) {
int screen = -1;
for (int i = 0; i < editor_table.size(); i++) {
if (editor_plugin_screen == editor_table[i]) {
@@ -4379,7 +4385,7 @@ void EditorNode::_open_imported() {
void EditorNode::dim_editor(bool p_dimming) {
static int dim_count = 0;
- bool dim_ui = EditorSettings::get_singleton()->get("interface/dim_editor_on_dialog_popup");
+ bool dim_ui = EditorSettings::get_singleton()->get("interface/editor/dim_editor_on_dialog_popup");
if (p_dimming) {
if (dim_ui) {
if (dim_count == 0) {
@@ -4406,9 +4412,9 @@ void EditorNode::_start_dimming(bool p_dimming) {
void EditorNode::_dim_timeout() {
_dim_time += _dim_timer->get_wait_time();
- float wait_time = EditorSettings::get_singleton()->get("interface/dim_transition_time");
+ float wait_time = EditorSettings::get_singleton()->get("interface/editor/dim_transition_time");
- float c = 1.0f - (float)EditorSettings::get_singleton()->get("interface/dim_amount");
+ float c = 1.0f - (float)EditorSettings::get_singleton()->get("interface/editor/dim_amount");
Color base = _dimming ? Color(1, 1, 1) : Color(c, c, c);
Color final = _dimming ? Color(c, c, c) : Color(1, 1, 1);
@@ -4421,27 +4427,32 @@ void EditorNode::_dim_timeout() {
}
}
-void EditorNode::_check_gui_base_size() {
- if (gui_base->get_size().width > 1200 * EDSCALE) {
- for (int i = 0; i < singleton->main_editor_button_vb->get_child_count(); i++) {
- ToolButton *btn = Object::cast_to<ToolButton>(singleton->main_editor_button_vb->get_child(i));
- if (btn == singleton->distraction_free) continue;
- btn->set_text(btn->get_name());
- }
- } else {
- for (int i = 0; i < singleton->main_editor_button_vb->get_child_count(); i++) {
- ToolButton *btn = Object::cast_to<ToolButton>(singleton->main_editor_button_vb->get_child(i));
- if (btn == singleton->distraction_free) continue;
- btn->set_text("");
- }
- }
-}
-
void EditorNode::open_export_template_manager() {
export_template_manager->popup_manager();
}
+void EditorNode::add_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin) {
+ resource_conversion_plugins.push_back(p_plugin);
+}
+
+void EditorNode::remove_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin) {
+ resource_conversion_plugins.erase(p_plugin);
+}
+
+Vector<Ref<EditorResourceConversionPlugin> > EditorNode::find_resource_conversion_plugin(const Ref<Resource> &p_for_resource) {
+
+ Vector<Ref<EditorResourceConversionPlugin> > ret;
+
+ for (int i = 0; i < resource_conversion_plugins.size(); i++) {
+ if (resource_conversion_plugins[i].is_valid() && resource_conversion_plugins[i]->handles(p_for_resource)) {
+ ret.push_back(resource_conversion_plugins[i]);
+ }
+ }
+
+ return ret;
+}
+
void EditorNode::_bind_methods() {
ClassDB::bind_method("_menu_option", &EditorNode::_menu_option);
@@ -4516,7 +4527,6 @@ void EditorNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("_open_imported"), &EditorNode::_open_imported);
ClassDB::bind_method(D_METHOD("_inherit_imported"), &EditorNode::_inherit_imported);
ClassDB::bind_method(D_METHOD("_dim_timeout"), &EditorNode::_dim_timeout);
- ClassDB::bind_method(D_METHOD("_check_gui_base_size"), &EditorNode::_check_gui_base_size);
ClassDB::bind_method(D_METHOD("_resources_reimported"), &EditorNode::_resources_reimported);
@@ -4576,7 +4586,7 @@ EditorNode::EditorNode() {
EditorSettings::create();
{
- int dpi_mode = EditorSettings::get_singleton()->get("interface/hidpi_mode");
+ int dpi_mode = EditorSettings::get_singleton()->get("interface/editor/hidpi_mode");
if (dpi_mode == 0) {
editor_set_scale(OS::get_singleton()->get_screen_dpi(0) >= 192 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x > 2000 ? 2.0 : 1.0);
} else if (dpi_mode == 1) {
@@ -4613,6 +4623,10 @@ EditorNode::EditorNode() {
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);
@@ -4661,12 +4675,11 @@ EditorNode::EditorNode() {
theme_base = memnew(Control);
add_child(theme_base);
- theme_base->set_area_as_parent_rect();
+ theme_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
gui_base = memnew(Panel);
theme_base->add_child(gui_base);
- gui_base->set_area_as_parent_rect();
- gui_base->connect("item_rect_changed", this, "_check_gui_base_size");
+ gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
Ref<Theme> theme = create_editor_theme();
theme_base->set_theme(theme);
@@ -4685,7 +4698,7 @@ EditorNode::EditorNode() {
main_vbox = memnew(VBoxContainer);
gui_base->add_child(main_vbox);
- main_vbox->set_area_as_parent_rect(8);
+ main_vbox->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 8);
main_vbox->set_margin(MARGIN_TOP, 5 * EDSCALE);
menu_hb = memnew(HBoxContainer);
@@ -4828,7 +4841,7 @@ EditorNode::EditorNode() {
scene_tabs->add_style_override("tab_bg", gui_base->get_stylebox("SceneTabBG", "EditorStyles"));
scene_tabs->add_tab("unsaved");
scene_tabs->set_tab_align(Tabs::ALIGN_LEFT);
- 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->set_tab_close_display_policy((bool(EDITOR_DEF("interface/editor/always_show_close_button_in_scene_tabs", false)) ? Tabs::CLOSE_BUTTON_SHOW_ALWAYS : Tabs::CLOSE_BUTTON_SHOW_ACTIVE_ONLY));
scene_tabs->set_min_width(int(EDITOR_DEF("interface/scene_tabs/minimum_width", 50)) * EDSCALE);
scene_tabs->connect("tab_changed", this, "_scene_tab_changed");
scene_tabs->connect("right_button_pressed", this, "_scene_tab_script_edited");
@@ -4854,7 +4867,7 @@ EditorNode::EditorNode() {
scene_root_parent = memnew(PanelContainer);
scene_root_parent->set_custom_minimum_size(Size2(0, 80) * EDSCALE);
scene_root_parent->add_style_override("panel", gui_base->get_stylebox("Content", "EditorStyles"));
-
+ scene_root_parent->set_draw_behind_parent(true);
srt->add_child(scene_root_parent);
scene_root_parent->set_v_size_flags(Control::SIZE_EXPAND_FILL);
@@ -5074,9 +5087,6 @@ EditorNode::EditorNode() {
play_cc = memnew(CenterContainer);
play_cc->set_mouse_filter(Control::MOUSE_FILTER_IGNORE);
menu_hb->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);
play_button_panel = memnew(PanelContainer);
// play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles"));
@@ -5285,7 +5295,7 @@ EditorNode::EditorNode() {
property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
property_editor->set_use_doc_hints(true);
property_editor->set_hide_script(false);
- property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/capitalize_properties", true)));
+ property_editor->set_enable_capitalize_paths(bool(EDITOR_DEF("interface/editor/capitalize_properties", true)));
property_editor->hide_top_label();
property_editor->register_text_enter(search_box);
@@ -5510,6 +5520,11 @@ EditorNode::EditorNode() {
resource_preview->add_preview_generator(Ref<EditorMeshPreviewPlugin>(memnew(EditorMeshPreviewPlugin)));
resource_preview->add_preview_generator(Ref<EditorBitmapPreviewPlugin>(memnew(EditorBitmapPreviewPlugin)));
+ {
+ Ref<SpatialMaterialConversionPlugin> spatial_mat_convert;
+ spatial_mat_convert.instance();
+ resource_conversion_plugins.push_back(spatial_mat_convert);
+ }
circle_step_msec = OS::get_singleton()->get_ticks_msec();
circle_step_frame = Engine::get_singleton()->get_frames_drawn();
circle_step = 0;
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 5c6c5be4c8..0d1c6787cd 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -605,10 +605,10 @@ private:
void _start_dimming(bool p_dimming);
void _dim_timeout();
- void _check_gui_base_size();
void _license_tree_selected();
+ Vector<Ref<EditorResourceConversionPlugin> > resource_conversion_plugins;
protected:
void _notification(int p_what);
@@ -716,7 +716,7 @@ public:
void show_warning(const String &p_text, const String &p_title = "Warning!");
- Error export_preset(const String &p_platform, const String &p_path, bool p_debug, const String &p_password, bool p_quit_after = false);
+ Error export_preset(const String &p_preset, 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();
@@ -778,6 +778,10 @@ public:
~EditorNode();
void get_singleton(const char *arg1, bool arg2);
+ void add_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin);
+ void remove_resource_conversion_plugin(const Ref<EditorResourceConversionPlugin> &p_plugin);
+ Vector<Ref<EditorResourceConversionPlugin> > find_resource_conversion_plugin(const Ref<Resource> &p_for_resource);
+
static void add_init_callback(EditorNodeInitCallback p_callback) { _init_callbacks.push_back(p_callback); }
static void add_build_callback(EditorBuildCallback p_callback);
};
diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp
index 246599be11..b4460c5619 100644
--- a/editor/editor_plugin.cpp
+++ b/editor/editor_plugin.cpp
@@ -112,8 +112,10 @@ Vector<Ref<Texture> > EditorInterface::make_mesh_previews(const Vector<Ref<Mesh>
Rect3 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)
+ if (m == 0) {
+ textures.push_back(Ref<Texture>());
continue;
+ }
m = 1.0 / m;
m *= 0.5;
print_line("scale: " + rtos(m));
diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp
index 6732d7048f..8baa56b9b4 100644
--- a/editor/editor_plugin_settings.cpp
+++ b/editor/editor_plugin_settings.cpp
@@ -127,10 +127,10 @@ void EditorPluginSettings::update_plugins() {
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_custom_color(3, get_color("success_color", "Editor"));
item->set_range(3, 1);
} else {
- item->set_custom_color(3, Color(1, 0.2, 0.2));
+ item->set_custom_color(3, get_color("disabled_font_color", "Editor"));
item->set_range(3, 0);
}
}
@@ -160,9 +160,9 @@ void EditorPluginSettings::_plugin_activity_changed() {
}
if (is_active)
- ti->set_custom_color(3, Color(0.2, 1, 0.2));
+ ti->set_custom_color(3, get_color("success_color", "Editor"));
else
- ti->set_custom_color(3, Color(1, 0.2, 0.2));
+ ti->set_custom_color(3, get_color("disabled_font_color", "Editor"));
}
void EditorPluginSettings::_bind_methods() {
diff --git a/editor/editor_profiler.cpp b/editor/editor_profiler.cpp
index 6b972262b9..968d8b831e 100644
--- a/editor/editor_profiler.cpp
+++ b/editor/editor_profiler.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "editor_profiler.h"
+#include "editor_scale.h"
#include "editor_settings.h"
#include "os/os.h"
@@ -88,7 +89,7 @@ void EditorProfiler::clear() {
variables->clear();
//activate->set_pressed(false);
plot_sigs.clear();
- plot_sigs.insert("fixed_frame_time");
+ plot_sigs.insert("physics_frame_time");
plot_sigs.insert("category_frame_time");
updating_frame = true;
@@ -119,9 +120,9 @@ String EditorProfiler::_get_time_as_text(Metric &m, float p_time, int p_calls) {
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) {
+ } else if (dmode == DISPLAY_PHYSICS_FRAME_PERCENT) {
- return _get_percent_txt(p_time, m.fixed_frame_time);
+ return _get_percent_txt(p_time, m.physics_frame_time);
}
return "err";
@@ -656,14 +657,14 @@ EditorProfiler::EditorProfiler() {
hb->add_child(cursor_metric_edit);
cursor_metric_edit->connect("value_changed", this, "_cursor_metric_changed");
- hb->add_constant_override("separation", 8);
+ hb->add_constant_override("separation", 8 * EDSCALE);
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_custom_minimum_size(Size2(300, 0) * EDSCALE);
variables->set_hide_folding(true);
h_split->add_child(variables);
variables->set_hide_root(true);
@@ -674,10 +675,10 @@ EditorProfiler::EditorProfiler() {
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_min_width(1, 60 * EDSCALE);
variables->set_column_title(2, "Calls");
variables->set_column_expand(2, false);
- variables->set_column_min_width(2, 60);
+ variables->set_column_min_width(2, 60 * EDSCALE);
variables->connect("item_edited", this, "_item_edited");
graph = memnew(TextureRect);
@@ -691,8 +692,6 @@ EditorProfiler::EditorProfiler() {
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;
@@ -715,7 +714,7 @@ EditorProfiler::EditorProfiler() {
add_child(plot_delay);
plot_delay->connect("timeout", this, "_update_plot");
- plot_sigs.insert("fixed_frame_time");
+ plot_sigs.insert("physics_frame_time");
plot_sigs.insert("category_frame_time");
seeking = false;
diff --git a/editor/editor_profiler.h b/editor/editor_profiler.h
index e2d781f125..e9e88ed7f2 100644
--- a/editor/editor_profiler.h
+++ b/editor/editor_profiler.h
@@ -51,8 +51,8 @@ public:
int frame_number;
float frame_time;
float idle_time;
- float fixed_time;
- float fixed_frame_time;
+ float physics_time;
+ float physics_frame_time;
struct Category {
@@ -89,7 +89,7 @@ public:
DISPLAY_FRAME_TIME,
DISPLAY_AVERAGE_TIME,
DISPLAY_FRAME_PERCENT,
- DISPLAY_FIXED_FRAME_PERCENT,
+ DISPLAY_PHYSICS_FRAME_PERCENT,
};
enum DisplayTime {
diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp
index d7266df67c..1b6b66c198 100644
--- a/editor/editor_settings.cpp
+++ b/editor/editor_settings.cpp
@@ -54,7 +54,7 @@ EditorSettings *EditorSettings::get_singleton() {
return singleton.ptr();
}
-bool EditorSettings::_set(const StringName &p_name, const Variant &p_value) {
+bool EditorSettings::_set(const StringName &p_name, const Variant &p_value, bool p_emit_signal) {
_THREAD_SAFE_METHOD_
@@ -90,7 +90,9 @@ bool EditorSettings::_set(const StringName &p_name, const Variant &p_value) {
}
}
- emit_signal("settings_changed");
+ if (p_emit_signal) {
+ emit_signal("settings_changed");
+ }
return true;
}
@@ -131,6 +133,11 @@ bool EditorSettings::_get(const StringName &p_name, Variant &r_ret) const {
return true;
}
+void EditorSettings::_initial_set(const StringName &p_name, const Variant &p_value) {
+ set(p_name, p_value);
+ props[p_name].initial = p_value;
+}
+
struct _EVCSort {
String name;
@@ -214,6 +221,8 @@ 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);
+ EditorSettings::get_singleton()->set_initial_value(p_var, p_default);
+
return p_default;
}
@@ -444,7 +453,7 @@ String EditorSettings::get_settings_path() const {
void EditorSettings::setup_language() {
- String lang = get("interface/editor_language");
+ String lang = get("interface/editor/editor_language");
if (lang == "en")
return; //none to do
@@ -460,7 +469,7 @@ void EditorSettings::setup_network() {
List<IP_Address> local_ip;
IP::get_singleton()->get_local_addresses(&local_ip);
- String lip;
+ String lip = "127.0.0.1";
String hint;
String current = has("network/debug/remote_host") ? get("network/debug/remote_host") : "";
int port = has("network/debug/remote_port") ? (int)get("network/debug/remote_port") : 6007;
@@ -469,8 +478,9 @@ void EditorSettings::setup_network() {
String ip = E->get();
- if (lip == "")
- lip = ip;
+ // link-local IPv6 addresses don't work, skipping them
+ if (ip.begins_with("fe80:0:0:0:")) // fe80::/64
+ continue;
if (ip == current)
lip = current; //so it saves
if (hint != "")
@@ -545,220 +555,235 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
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);
+ _initial_set("interface/editor/editor_language", best);
+ hints["interface/editor/editor_language"] = PropertyInfo(Variant::STRING, "interface/editor/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, "*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/dim_editor_on_dialog_popup", true);
- set("interface/dim_amount", 0.6f);
- hints["interface/dim_amount"] = PropertyInfo(Variant::REAL, "interface/dim_amount", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT);
- set("interface/dim_transition_time", 0.08f);
- hints["interface/dim_transition_time"] = PropertyInfo(Variant::REAL, "interface/dim_transition_time", PROPERTY_HINT_RANGE, "0,1,0.001", PROPERTY_USAGE_DEFAULT);
-
- set("interface/separate_distraction_mode", false);
-
- set("interface/save_each_scene_on_quit", true); // Regression
- set("interface/quit_confirmation", true);
-
- set("interface/theme/preset", 0);
- hints["interface/theme/preset"] = PropertyInfo(Variant::INT, "interface/theme/preset", PROPERTY_HINT_ENUM, "Default,Grey,Godot 2,Arc,Light,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/theme/icon_and_font_color", 0);
+ _initial_set("interface/editor/hidpi_mode", 0);
+ hints["interface/editor/hidpi_mode"] = PropertyInfo(Variant::INT, "interface/editor/hidpi_mode", PROPERTY_HINT_ENUM, "Auto,VeryLoDPI,LoDPI,MidDPI,HiDPI", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/editor/show_script_in_scene_tabs", false);
+ _initial_set("interface/editor/font_size", 14);
+ hints["interface/editor/font_size"] = PropertyInfo(Variant::INT, "interface/editor/font_size", PROPERTY_HINT_RANGE, "10,40,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/editor/source_font_size", 14);
+ hints["interface/editor/source_font_size"] = PropertyInfo(Variant::INT, "interface/editor/source_font_size", PROPERTY_HINT_RANGE, "8,96,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/editor/custom_font", "");
+ hints["interface/editor/custom_font"] = PropertyInfo(Variant::STRING, "interface/editor/custom_font", PROPERTY_HINT_GLOBAL_FILE, "*.font,*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/editor/dim_editor_on_dialog_popup", true);
+ _initial_set("interface/editor/dim_amount", 0.6f);
+ hints["interface/editor/dim_amount"] = PropertyInfo(Variant::REAL, "interface/editor/dim_amount", PROPERTY_HINT_RANGE, "0,1,0.01", PROPERTY_USAGE_DEFAULT);
+ _initial_set("interface/editor/dim_transition_time", 0.08f);
+ hints["interface/editor/dim_transition_time"] = PropertyInfo(Variant::REAL, "interface/editor/dim_transition_time", PROPERTY_HINT_RANGE, "0,1,0.001", PROPERTY_USAGE_DEFAULT);
+
+ _initial_set("interface/editor/separate_distraction_mode", false);
+
+ _initial_set("interface/editor/save_each_scene_on_quit", true); // Regression
+ _initial_set("interface/editor/quit_confirmation", true);
+
+ _initial_set("interface/theme/preset", 0);
+ hints["interface/theme/preset"] = PropertyInfo(Variant::INT, "interface/theme/preset", PROPERTY_HINT_ENUM, "Default,Grey,Godot 2,Arc,Light,Alien,Custom", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/theme/icon_and_font_color", 0);
hints["interface/theme/icon_and_font_color"] = PropertyInfo(Variant::INT, "interface/theme/icon_and_font_color", PROPERTY_HINT_ENUM, "Auto,Dark,Light", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/theme/base_color", Color::html("#323b4f"));
+ _initial_set("interface/theme/base_color", Color::html("#323b4f"));
hints["interface/theme/accent_color"] = PropertyInfo(Variant::COLOR, "interface/theme/accent_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/theme/accent_color", Color::html("#699ce8"));
+ _initial_set("interface/theme/accent_color", Color::html("#699ce8"));
hints["interface/theme/base_color"] = PropertyInfo(Variant::COLOR, "interface/theme/base_color", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/theme/contrast", 0.25);
+ _initial_set("interface/theme/contrast", 0.25);
hints["interface/theme/contrast"] = PropertyInfo(Variant::REAL, "interface/theme/contrast", PROPERTY_HINT_RANGE, "0.01, 1, 0.01");
- set("interface/theme/highlight_tabs", false);
- set("interface/theme/border_size", 1);
+ _initial_set("interface/theme/highlight_tabs", false);
+ _initial_set("interface/theme/border_size", 1);
+ _initial_set("interface/theme/use_graph_node_headers", false);
hints["interface/theme/border_size"] = PropertyInfo(Variant::INT, "interface/theme/border_size", PROPERTY_HINT_RANGE, "0,2,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/theme/custom_theme", "");
+ _initial_set("interface/theme/additional_spacing", 0);
+ hints["interface/theme/additional_spacing"] = PropertyInfo(Variant::REAL, "interface/theme/additional_spacing", PROPERTY_HINT_RANGE, "0,5,0.1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+ _initial_set("interface/theme/custom_theme", "");
hints["interface/theme/custom_theme"] = PropertyInfo(Variant::STRING, "interface/theme/custom_theme", PROPERTY_HINT_GLOBAL_FILE, "*.res,*.tres,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("interface/scene_tabs/show_extension", false);
- set("interface/scene_tabs/show_thumbnail_on_hover", true);
- set("interface/scene_tabs/resize_if_many_tabs", true);
- set("interface/scene_tabs/minimum_width", 50);
+ _initial_set("interface/scene_tabs/show_extension", false);
+ _initial_set("interface/scene_tabs/show_thumbnail_on_hover", true);
+ _initial_set("interface/scene_tabs/resize_if_many_tabs", true);
+ _initial_set("interface/scene_tabs/minimum_width", 50);
hints["interface/scene_tabs/minimum_width"] = PropertyInfo(Variant::INT, "interface/scene_tabs/minimum_width", PROPERTY_HINT_RANGE, "50,500,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
- set("filesystem/directories/autoscan_project_path", "");
+ _initial_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", OS::get_singleton()->has_environment("HOME") ? OS::get_singleton()->get_environment("HOME") : OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS));
+ _initial_set("filesystem/directories/default_project_path", OS::get_singleton()->has_environment("HOME") ? OS::get_singleton()->get_environment("HOME") : OS::get_singleton()->get_system_dir(OS::SYSTEM_DIR_DOCUMENTS));
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", "");
+ _initial_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);
+ _initial_set("interface/editor/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");
+ _initial_set("text_editor/theme/color_theme", "Adaptive");
+ hints["text_editor/theme/color_theme"] = PropertyInfo(Variant::STRING, "text_editor/theme/color_theme", PROPERTY_HINT_ENUM, "Adaptive,Default");
- set("text_editor/theme/line_spacing", 4);
+ _initial_set("text_editor/theme/line_spacing", 4);
_load_default_text_editor_theme();
- set("text_editor/highlighting/syntax_highlighting", true);
+ _initial_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);
+ _initial_set("text_editor/highlighting/highlight_all_occurrences", true);
+ _initial_set("text_editor/cursor/scroll_past_end_of_file", false);
- set("text_editor/indent/type", 0);
+ _initial_set("text_editor/indent/type", 0);
hints["text_editor/indent/type"] = PropertyInfo(Variant::INT, "text_editor/indent/type", PROPERTY_HINT_ENUM, "Tabs,Spaces");
- set("text_editor/indent/size", 4);
+ _initial_set("text_editor/indent/size", 4);
hints["text_editor/indent/size"] = PropertyInfo(Variant::INT, "text_editor/indent/size", PROPERTY_HINT_RANGE, "1, 64, 1"); // size of 0 crashes.
- set("text_editor/indent/auto_indent", true);
- set("text_editor/indent/convert_indent_on_save", false);
- 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);
+ _initial_set("text_editor/indent/auto_indent", true);
+ _initial_set("text_editor/indent/convert_indent_on_save", false);
+ _initial_set("text_editor/indent/draw_tabs", true);
+
+ _initial_set("text_editor/line_numbers/show_line_numbers", true);
+ _initial_set("text_editor/line_numbers/line_numbers_zero_padded", false);
+ _initial_set("text_editor/line_numbers/show_breakpoint_gutter", true);
+ _initial_set("text_editor/line_numbers/show_line_length_guideline", false);
+ _initial_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/open_scripts/smooth_scrolling", true);
- set("text_editor/open_scripts/v_scroll_speed", 80);
- set("text_editor/open_scripts/show_members_overview", true);
+ _initial_set("text_editor/open_scripts/smooth_scrolling", true);
+ _initial_set("text_editor/open_scripts/v_scroll_speed", 80);
+ _initial_set("text_editor/open_scripts/show_members_overview", true);
- 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);
+ _initial_set("text_editor/files/trim_trailing_whitespace_on_save", false);
+ _initial_set("text_editor/completion/idle_parse_delay", 2);
+ _initial_set("text_editor/tools/create_signal_callbacks", true);
+ _initial_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);
+ _initial_set("text_editor/cursor/block_caret", false);
+ _initial_set("text_editor/cursor/caret_blink", false);
+ _initial_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, "*.font");
- set("text_editor/completion/auto_brace_complete", false);
- set("text_editor/files/restore_scripts_on_load", true);
- set("text_editor/completion/complete_file_paths", true);
- set("text_editor/files/maximum_recent_files", 20);
+ _initial_set("text_editor/theme/font", "");
+ hints["text_editor/theme/font"] = PropertyInfo(Variant::STRING, "text_editor/theme/font", PROPERTY_HINT_GLOBAL_FILE, "*.font,*.tres,*.res");
+ _initial_set("text_editor/completion/auto_brace_complete", false);
+ _initial_set("text_editor/files/restore_scripts_on_load", true);
+ _initial_set("text_editor/completion/complete_file_paths", true);
+ _initial_set("text_editor/files/maximum_recent_files", 20);
hints["text_editor/files/maximum_recent_files"] = PropertyInfo(Variant::INT, "text_editor/files/maximum_recent_files", PROPERTY_HINT_RANGE, "1, 200, 0");
- 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(1, 1, 1, 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", 55.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/3d/warped_mouse_panning", true);
-
- set("editors/3d/orbit_sensitivity", 0.4);
-
- set("editors/3d/orbit_inertia", 0.2);
- hints["editors/3d/orbit_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/orbit_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
-
- set("editors/3d/freelook_inertia", 0.2);
- hints["editors/3d/freelook_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/freelook_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
-
- set("editors/3d/freelook_base_speed", 0.5);
- hints["editors/3d/freelook_base_speed"] = PropertyInfo(Variant::REAL, "editors/3d/freelook_base_speed", PROPERTY_HINT_RANGE, "0.0, 10, 0.1");
-
- set("editors/3d/freelook_activation_modifier", 0);
- hints["editors/3d/freelook_activation_modifier"] = PropertyInfo(Variant::INT, "editors/3d/freelook_activation_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
-
- set("editors/3d/freelook_modifier_speed_factor", 5.0);
-
- 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("editors/2d/warped_mouse_panning", true);
- set("editors/2d/scroll_to_pan", false);
- set("editors/2d/pan_speed", 20);
-
- set("editors/poly_editor/point_grab_radius", 8);
- set("editors/poly_editor/show_previous_outline", true);
-
- set("run/window_placement/rect", 1);
+ _initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false);
+ _initial_set("docks/scene_tree/draw_relationship_lines", false);
+ _initial_set("docks/scene_tree/relationship_line_color", Color::html("464646"));
+
+ _initial_set("editors/grid_map/pick_distance", 5000.0);
+
+ _initial_set("editors/3d/grid_color", Color::html("808080"));
+ hints["editors/3d/grid_color"] = PropertyInfo(Variant::COLOR, "editors/3d/grid_color", PROPERTY_HINT_COLOR_NO_ALPHA, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
+
+ _initial_set("editors/3d/default_fov", 55.0);
+ _initial_set("editors/3d/default_z_near", 0.1);
+ _initial_set("editors/3d/default_z_far", 500.0);
+
+ // navigation
+ _initial_set("editors/3d/navigation/navigation_scheme", 0);
+ hints["editors/3d/navigation/navigation_scheme"] = PropertyInfo(Variant::INT, "editors/3d/navigation/navigation_scheme", PROPERTY_HINT_ENUM, "Godot,Maya,Modo");
+ _initial_set("editors/3d/navigation/zoom_style", 0);
+ hints["editors/3d/navigation/zoom_style"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_style", PROPERTY_HINT_ENUM, "Vertical, Horizontal");
+
+ _initial_set("editors/3d/navigation/emulate_3_button_mouse", false);
+ _initial_set("editors/3d/navigation/orbit_modifier", 0);
+ hints["editors/3d/navigation/orbit_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/orbit_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
+ _initial_set("editors/3d/navigation/pan_modifier", 1);
+ hints["editors/3d/navigation/pan_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/pan_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
+ _initial_set("editors/3d/navigation/zoom_modifier", 4);
+ hints["editors/3d/navigation/zoom_modifier"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
+
+ // _initial_set("editors/3d/navigation/emulate_numpad", false); not used at the moment
+ _initial_set("editors/3d/navigation/warped_mouse_panning", true);
+
+ // navigation feel
+ _initial_set("editors/3d/navigation_feel/orbit_sensitivity", 0.4);
+ hints["editors/3d/navigation_feel/orbit_sensitivity"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/orbit_sensitivity", PROPERTY_HINT_RANGE, "0.0, 2, 0.01");
+
+ _initial_set("editors/3d/navigation_feel/orbit_inertia", 0.15);
+ hints["editors/3d/navigation_feel/orbit_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/orbit_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
+ _initial_set("editors/3d/navigation_feel/translation_inertia", 0.15);
+ hints["editors/3d/navigation_feel/translation_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/translation_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
+ _initial_set("editors/3d/navigation_feel/zoom_inertia", 0.075);
+ hints["editors/3d/navigation_feel/zoom_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/zoom_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
+ _initial_set("editors/3d/navigation_feel/manipulation_orbit_inertia", 0.075);
+ hints["editors/3d/navigation_feel/manipulation_orbit_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/manipulation_orbit_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
+ _initial_set("editors/3d/navigation_feel/manipulation_translation_inertia", 0.075);
+ hints["editors/3d/navigation_feel/manipulation_translation_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/navigation_feel/manipulation_translation_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
+
+ // freelook
+ _initial_set("editors/3d/freelook/freelook_inertia", 0.1);
+ hints["editors/3d/freelook/freelook_inertia"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_inertia", PROPERTY_HINT_RANGE, "0.0, 1, 0.01");
+ _initial_set("editors/3d/freelook/freelook_base_speed", 0.1);
+ hints["editors/3d/freelook/freelook_base_speed"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_base_speed", PROPERTY_HINT_RANGE, "0.0, 10, 0.01");
+ _initial_set("editors/3d/freelook/freelook_activation_modifier", 0);
+ hints["editors/3d/freelook/freelook_activation_modifier"] = PropertyInfo(Variant::INT, "editors/3d/freelook/freelook_activation_modifier", PROPERTY_HINT_ENUM, "None,Shift,Alt,Meta,Ctrl");
+ _initial_set("editors/3d/freelook/freelook_modifier_speed_factor", 3.0);
+ hints["editors/3d/freelook/freelook_modifier_speed_factor"] = PropertyInfo(Variant::REAL, "editors/3d/freelook/freelook_modifier_speed_factor", PROPERTY_HINT_RANGE, "0.0, 10.0, 0.1");
+
+ _initial_set("editors/2d/bone_width", 5);
+ _initial_set("editors/2d/bone_color1", Color(1.0, 1.0, 1.0, 0.9));
+ _initial_set("editors/2d/bone_color2", Color(0.75, 0.75, 0.75, 0.9));
+ _initial_set("editors/2d/bone_selected_color", Color(0.9, 0.45, 0.45, 0.9));
+ _initial_set("editors/2d/bone_ik_color", Color(0.9, 0.9, 0.45, 0.9));
+ _initial_set("editors/2d/keep_margins_when_changing_anchors", false);
+ _initial_set("editors/2d/warped_mouse_panning", true);
+ _initial_set("editors/2d/scroll_to_pan", false);
+ _initial_set("editors/2d/pan_speed", 20);
+
+ _initial_set("editors/poly_editor/point_grab_radius", 8);
+ _initial_set("editors/poly_editor/show_previous_outline", true);
+
+ _initial_set("run/window_placement/rect", 1);
hints["run/window_placement/rect"] = PropertyInfo(Variant::INT, "run/window_placement/rect", PROPERTY_HINT_ENUM, "Top Left,Centered,Custom Position,Force Maximized,Force Fullscreen");
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);
+ _initial_set("run/window_placement/rect_custom_position", Vector2());
+ _initial_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);
+ _initial_set("filesystem/on_save/compress_binary_resources", true);
+ _initial_set("filesystem/on_save/save_modified_external_resources", true);
- set("text_editor/tools/create_signal_callbacks", true);
+ _initial_set("text_editor/tools/create_signal_callbacks", true);
- set("filesystem/file_dialog/show_hidden_files", false);
- set("filesystem/file_dialog/display_mode", 0);
+ _initial_set("filesystem/file_dialog/show_hidden_files", false);
+ _initial_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);
+ _initial_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);
+ _initial_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);
+ _initial_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("docks/filesystem/display_mode", 0);
+ _initial_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/always_show_folders", true);
+ _initial_set("docks/filesystem/always_show_folders", true);
- set("editors/animation/autorename_animation_tracks", true);
- set("editors/animation/confirm_insert_track", true);
+ _initial_set("editors/animation/autorename_animation_tracks", true);
+ _initial_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("text_editor/help/show_help_index", true);
+ _initial_set("docks/property_editor/texture_preview_width", 48);
+ _initial_set("docks/property_editor/auto_refresh_interval", 0.3);
+ _initial_set("text_editor/help/doc_path", "");
+ _initial_set("text_editor/help/show_help_index", true);
- set("filesystem/import/ask_save_before_reimport", false);
+ _initial_set("filesystem/import/ask_save_before_reimport", false);
- set("filesystem/import/pvrtc_texture_tool", "");
+ _initial_set("filesystem/import/pvrtc_texture_tool", "");
#ifdef WINDOWS_ENABLED
hints["filesystem/import/pvrtc_texture_tool"] = PropertyInfo(Variant::STRING, "filesystem/import/pvrtc_texture_tool", PROPERTY_HINT_GLOBAL_FILE, "*.exe");
#else
hints["filesystem/import/pvrtc_texture_tool"] = PropertyInfo(Variant::STRING, "filesystem/import/pvrtc_texture_tool", PROPERTY_HINT_GLOBAL_FILE, "");
#endif
- set("filesystem/import/pvrtc_fast_conversion", false);
+ _initial_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);
+ _initial_set("run/auto_save/save_before_running", true);
+ _initial_set("run/output/always_clear_output_on_play", true);
+ _initial_set("run/output/always_open_output_on_play", true);
+ _initial_set("run/output/always_close_output_on_stop", false);
+ _initial_set("filesystem/resources/save_compressed_resources", true);
+ _initial_set("filesystem/resources/auto_reload_modified_images", true);
- set("filesystem/import/automatic_reimport_on_sources_changed", true);
+ _initial_set("filesystem/import/automatic_reimport_on_sources_changed", true);
if (p_extra_config.is_valid()) {
@@ -788,35 +813,35 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
}
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("6ca9c2"));
- 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));
+ _initial_set("text_editor/highlighting/background_color", Color::html("3b000000"));
+ _initial_set("text_editor/highlighting/completion_background_color", Color::html("2C2A32"));
+ _initial_set("text_editor/highlighting/completion_selected_color", Color::html("434244"));
+ _initial_set("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"));
+ _initial_set("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"));
+ _initial_set("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"));
+ _initial_set("text_editor/highlighting/caret_color", Color::html("aaaaaa"));
+ _initial_set("text_editor/highlighting/caret_background_color", Color::html("000000"));
+ _initial_set("text_editor/highlighting/line_number_color", Color::html("66aaaaaa"));
+ _initial_set("text_editor/highlighting/text_color", Color::html("aaaaaa"));
+ _initial_set("text_editor/highlighting/text_selected_color", Color::html("000000"));
+ _initial_set("text_editor/highlighting/keyword_color", Color::html("ffffb3"));
+ _initial_set("text_editor/highlighting/base_type_color", Color::html("a4ffd4"));
+ _initial_set("text_editor/highlighting/engine_type_color", Color::html("83d3ff"));
+ _initial_set("text_editor/highlighting/function_color", Color::html("66a2ce"));
+ _initial_set("text_editor/highlighting/member_variable_color", Color::html("e64e59"));
+ _initial_set("text_editor/highlighting/comment_color", Color::html("676767"));
+ _initial_set("text_editor/highlighting/string_color", Color::html("ef6ebe"));
+ _initial_set("text_editor/highlighting/number_color", Color::html("EB9532"));
+ _initial_set("text_editor/highlighting/symbol_color", Color::html("badfff"));
+ _initial_set("text_editor/highlighting/selection_color", Color::html("6ca9c2"));
+ _initial_set("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2));
+ _initial_set("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15));
+ _initial_set("text_editor/highlighting/line_length_guideline_color", Color(0.3, 0.5, 0.8, 0.1));
+ _initial_set("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4));
+ _initial_set("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2));
+ _initial_set("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15));
+ _initial_set("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1));
+ _initial_set("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1));
}
void EditorSettings::notify_changes() {
@@ -924,13 +949,13 @@ void EditorSettings::load_favorites() {
}
void EditorSettings::list_text_editor_themes() {
- String themes = "Default";
+ String themes = "Adaptive,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") {
+ if (file.get_extension() == "tet" && file.get_basename().to_lower() != "default" && file.get_basename().to_lower() != "adaptive") {
themes += "," + file.get_basename();
}
file = d->get_next();
@@ -942,7 +967,7 @@ void EditorSettings::list_text_editor_themes() {
}
void EditorSettings::load_text_editor_theme() {
- if (get("text_editor/theme/color_theme") == "Default") {
+ if (get("text_editor/theme/color_theme") == "Default" || get("text_editor/theme/color_theme") == "Adaptive") {
_load_default_text_editor_theme(); // sorry for "Settings changed" console spam
return;
}
@@ -999,7 +1024,7 @@ bool EditorSettings::save_text_editor_theme() {
String p_file = get("text_editor/theme/color_theme");
- if (p_file.get_file().to_lower() == "default") {
+ if (p_file.get_file().to_lower() == "default" || p_file.get_file().to_lower() == "adaptive") {
return false;
}
String theme_path = get_settings_path() + "/text_editor_themes/" + p_file + ".tet";
@@ -1011,7 +1036,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) {
p_file += ".tet";
}
- if (p_file.get_file().to_lower() == "default.tet") {
+ if (p_file.get_file().to_lower() == "default.tet" || p_file.get_file().to_lower() == "adaptive.tet") {
return false;
}
if (_save_text_editor_theme(p_file)) {
@@ -1021,7 +1046,7 @@ bool EditorSettings::save_text_editor_theme_as(String p_file) {
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);
+ _initial_set("text_editor/theme/color_theme", theme_name);
load_text_editor_theme();
}
return true;
@@ -1145,6 +1170,28 @@ void EditorSettings::set_project_metadata(const String &p_section, const String
cf->save(path);
}
+bool EditorSettings::property_can_revert(const String &p_name) {
+
+ if (!props.has(p_name))
+ return false;
+
+ return props[p_name].initial != props[p_name].variant;
+}
+
+Variant EditorSettings::property_get_revert(const String &p_name) {
+
+ if (!props.has(p_name))
+ return Variant();
+
+ return props[p_name].initial;
+}
+
+void EditorSettings::set_initial_value(const StringName &p_name, const Variant &p_value) {
+
+ ERR_FAIL_COND(!props.has(p_name));
+ props[p_name].initial = p_value;
+}
+
void EditorSettings::_bind_methods() {
ClassDB::bind_method(D_METHOD("erase", "property"), &EditorSettings::erase);
@@ -1159,6 +1206,11 @@ void EditorSettings::_bind_methods() {
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);
+ ClassDB::bind_method(D_METHOD("property_can_revert", "name"), &EditorSettings::property_can_revert);
+ ClassDB::bind_method(D_METHOD("property_get_revert", "name"), &EditorSettings::property_get_revert);
+
+ ClassDB::bind_method(D_METHOD("set_initial_value", "name", "value"), &EditorSettings::set_initial_value);
+
ADD_SIGNAL(MethodInfo("settings_changed"));
}
diff --git a/editor/editor_settings.h b/editor/editor_settings.h
index 177ec4760d..19cf367d57 100644
--- a/editor/editor_settings.h
+++ b/editor/editor_settings.h
@@ -65,6 +65,7 @@ private:
struct VariantContainer {
int order;
Variant variant;
+ Variant initial;
bool hide_from_editor;
bool save;
VariantContainer() {
@@ -84,10 +85,12 @@ private:
HashMap<String, VariantContainer> props;
String resource_path;
- bool _set(const StringName &p_name, const Variant &p_value);
+ bool _set(const StringName &p_name, const Variant &p_value, bool p_emit_signal = true);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ void _initial_set(const StringName &p_name, const Variant &p_value);
+
static Ref<EditorSettings> singleton;
String config_file_path;
@@ -123,6 +126,9 @@ public:
NOTIFICATION_EDITOR_SETTINGS_CHANGED = 10000
};
+ void set_manually(const StringName &p_name, const Variant &p_value, bool p_emit_signal = false) {
+ _set(p_name, p_value, p_emit_signal);
+ }
bool has(String p_var) const;
static EditorSettings *get_singleton();
void erase(String p_var);
@@ -171,6 +177,11 @@ public:
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);
+ bool property_can_revert(const String &p_name);
+ Variant property_get_revert(const String &p_name);
+
+ void set_initial_value(const StringName &p_name, const Variant &p_value);
+
EditorSettings();
~EditorSettings();
};
diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp
index 304d6acd62..a2e6df4e41 100644
--- a/editor/editor_themes.cpp
+++ b/editor/editor_themes.cpp
@@ -37,9 +37,9 @@
#include "modules/svg/image_loader_svg.h"
#include "time.h"
-static Ref<StyleBoxTexture> make_stylebox(Ref<Texture> texture, float p_left, float p_top, float p_right, float p_botton, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1, bool p_draw_center = true) {
+static Ref<StyleBoxTexture> make_stylebox(Ref<Texture> p_texture, float p_left, float p_top, float p_right, float p_botton, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_botton = -1, bool p_draw_center = true) {
Ref<StyleBoxTexture> style(memnew(StyleBoxTexture));
- style->set_texture(texture);
+ style->set_texture(p_texture);
style->set_margin_size(MARGIN_LEFT, p_left * EDSCALE);
style->set_margin_size(MARGIN_RIGHT, p_right * EDSCALE);
style->set_margin_size(MARGIN_BOTTOM, p_botton * EDSCALE);
@@ -61,9 +61,9 @@ static Ref<StyleBoxEmpty> make_empty_stylebox(float p_margin_left = -1, float p_
return style;
}
-static Ref<StyleBoxFlat> make_flat_stylebox(Color color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
+static Ref<StyleBoxFlat> make_flat_stylebox(Color p_color, float p_margin_left = -1, float p_margin_top = -1, float p_margin_right = -1, float p_margin_bottom = -1) {
Ref<StyleBoxFlat> style(memnew(StyleBoxFlat));
- style->set_bg_color(color);
+ style->set_bg_color(p_color);
style->set_default_margin(MARGIN_LEFT, p_margin_left * EDSCALE);
style->set_default_margin(MARGIN_RIGHT, p_margin_right * EDSCALE);
style->set_default_margin(MARGIN_BOTTOM, p_margin_bottom * EDSCALE);
@@ -71,12 +71,12 @@ static Ref<StyleBoxFlat> make_flat_stylebox(Color color, float p_margin_left = -
return style;
}
-static Ref<StyleBoxLine> make_line_stylebox(Color color, int thickness = 1, float grow = 1, bool vertical = false) {
+static Ref<StyleBoxLine> make_line_stylebox(Color p_color, int p_thickness = 1, float p_grow = 1, bool p_vertical = false) {
Ref<StyleBoxLine> style(memnew(StyleBoxLine));
- style->set_color(color);
- style->set_grow(grow);
- style->set_thickness(thickness);
- style->set_vertical(vertical);
+ style->set_color(p_color);
+ style->set_grow(p_grow);
+ style->set_thickness(p_thickness);
+ style->set_vertical(p_vertical);
return style;
}
@@ -86,7 +86,7 @@ static Ref<StyleBoxFlat> change_border_color(Ref<StyleBoxFlat> p_style, Color p_
return style;
}
-Ref<ImageTexture> editor_generate_icon(int p_index, bool convert_color, float p_scale = EDSCALE, bool force_filter = false) {
+Ref<ImageTexture> editor_generate_icon(int p_index, bool p_convert_color, float p_scale = EDSCALE, bool p_force_filter = false) {
Ref<ImageTexture> icon = memnew(ImageTexture);
Ref<Image> img = memnew(Image);
@@ -94,9 +94,9 @@ Ref<ImageTexture> editor_generate_icon(int p_index, bool convert_color, float p_
// dumb gizmo check
bool is_gizmo = String(editor_icons_names[p_index]).begins_with("Gizmo");
- ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, true, convert_color);
+ ImageLoaderSVG::create_image_from_string(img, editor_icons_sources[p_index], p_scale, true, p_convert_color);
- if ((p_scale - (float)((int)p_scale)) > 0.0 || is_gizmo || force_filter)
+ if ((p_scale - (float)((int)p_scale)) > 0.0 || is_gizmo || p_force_filter)
icon->create_from_image(img); // in this case filter really helps
else
icon->create_from_image(img, 0);
@@ -108,45 +108,53 @@ Ref<ImageTexture> editor_generate_icon(int p_index, bool convert_color, float p_
#define ADD_CONVERT_COLOR(dictionary, old_color, new_color) dictionary[Color::html(old_color)] = Color::html(new_color)
#endif
-void editor_register_and_generate_icons(Ref<Theme> p_theme, bool dark_theme = true, int p_thumb_size = 32, bool only_thumbs = false) {
+void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = true, int p_thumb_size = 32, bool p_only_thumbs = false) {
#ifdef SVG_ENABLED
Dictionary dark_icon_color_dictionary;
- //convert color: FROM TO
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#4f4f4f"); // common icon color
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#000000"); // white
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#000000"); // script darker color
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#cea4f1", "#bb6dff"); // animation
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc9c9c", "#ff5f5f"); // spatial
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5b7f3", "#6d90ff"); // 2d
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#708cea", "#0843ff"); // 2d dark
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#29d739"); // control
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff3333"); // error
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00db50"); // success
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#ffad07"); // warning
-
- // rainbow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff7070", "#ff2929"); // red
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffeb70", "#ffe337"); // yellow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9dff70", "#74ff34"); // green
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70ffb9", "#2cff98"); // aqua
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70deff", "#22ccff"); // blue
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9f70ff", "#702aff"); // purple
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff70ac", "#ff2781"); // pink
-
- // audio gradient
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff4040"); // red
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1dc7a", "#d6cf4b"); // yellow
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00f010"); // green
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#fea900"); // mesh (orange)
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#40a2ff", "#68b6ff"); // shape (blue)
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84c2ff", "#5caeff"); // selection (blue)
-
- ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea686c", "#e3383d"); // key xform (red)
+ if (!p_dark_theme) {
+ //convert color: FROM TO
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#4f4f4f"); // common icon color
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#000000"); // white
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#000000"); // script darker color
+
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#cea4f1", "#bb6dff"); // animation
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc9c9c", "#ff5f5f"); // spatial
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5b7f3", "#6d90ff"); // 2d
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#708cea", "#0843ff"); // 2d dark
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#29d739"); // control
+
+ // rainbow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff7070", "#ff2929"); // red
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffeb70", "#ffe337"); // yellow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9dff70", "#74ff34"); // green
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70ffb9", "#2cff98"); // aqua
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#70deff", "#22ccff"); // blue
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#9f70ff", "#702aff"); // purple
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff70ac", "#ff2781"); // pink
+
+ // audio gradient
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff4040"); // red
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e1dc7a", "#d6cf4b"); // yellow
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00f010"); // green
+
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffd684", "#fea900"); // mesh (orange)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#40a2ff", "#68b6ff"); // shape (blue)
+
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff8484", "#ff3333"); // remove (red)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84ffb1", "#00db50"); // add (green)
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#84c2ff", "#5caeff"); // selection (blue)
+
+ ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea686c", "#e3383d"); // key xform (red)
+ }
+
+ // these ones should be converted even if we are using a dark theme
+ const Color error_color = p_theme->get_color("error_color", "Editor");
+ const Color success_color = p_theme->get_color("success_color", "Editor");
+ const Color warning_color = p_theme->get_color("warning_color", "Editor");
+ dark_icon_color_dictionary[Color::html("#ff5d5d")] = error_color;
+ dark_icon_color_dictionary[Color::html("#45ff8b")] = success_color;
+ dark_icon_color_dictionary[Color::html("#ffdd65")] = warning_color;
List<String> exceptions;
exceptions.push_back("EditorPivot");
@@ -157,17 +165,25 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool dark_theme = tr
exceptions.push_back("ProceduralSky");
exceptions.push_back("EditorControlAnchor");
exceptions.push_back("DefaultProjectIcon");
+ exceptions.push_back("GuiCloseCustomizable");
+ exceptions.push_back("GuiGraphNodePort");
+ exceptions.push_back("GuiResizer");
+ exceptions.push_back("ZoomMore");
+ exceptions.push_back("ZoomLess");
+ exceptions.push_back("ZoomReset");
+ exceptions.push_back("LockViewport");
+ exceptions.push_back("GroupViewport");
clock_t begin_time = clock();
- ImageLoaderSVG::set_convert_colors(dark_theme ? NULL : &dark_icon_color_dictionary);
+ ImageLoaderSVG::set_convert_colors(&dark_icon_color_dictionary);
// generate icons
- if (!only_thumbs)
+ if (!p_only_thumbs)
for (int i = 0; i < editor_icons_count; i++) {
List<String>::Element *is_exception = exceptions.find(editor_icons_names[i]);
if (is_exception) exceptions.erase(is_exception);
- Ref<ImageTexture> icon = editor_generate_icon(i, !dark_theme && !is_exception);
+ Ref<ImageTexture> icon = editor_generate_icon(i, !is_exception);
p_theme->set_icon(editor_icons_names[i], "EditorIcons", icon);
}
@@ -179,7 +195,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool dark_theme = tr
int index = editor_bg_thumbs_indices[i];
List<String>::Element *is_exception = exceptions.find(editor_icons_names[index]);
if (is_exception) exceptions.erase(is_exception);
- Ref<ImageTexture> icon = editor_generate_icon(index, !dark_theme && !is_exception, scale, force_filter);
+ Ref<ImageTexture> icon = editor_generate_icon(index, !p_dark_theme && !is_exception, scale, force_filter);
p_theme->set_icon(editor_icons_names[index], "EditorIcons", icon);
}
} else {
@@ -188,7 +204,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool dark_theme = tr
int index = editor_md_thumbs_indices[i];
List<String>::Element *is_exception = exceptions.find(editor_icons_names[index]);
if (is_exception) exceptions.erase(is_exception);
- Ref<ImageTexture> icon = editor_generate_icon(index, !dark_theme && !is_exception, scale, force_filter);
+ Ref<ImageTexture> icon = editor_generate_icon(index, !p_dark_theme && !is_exception, scale, force_filter);
p_theme->set_icon(editor_icons_names[index], "EditorIcons", icon);
}
}
@@ -211,8 +227,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const float default_contrast = 0.25;
//Theme settings
- Color accent_color = EDITOR_DEF("interface/theme/accent_color", Color::html("#000000"));
- Color base_color = EDITOR_DEF("interface/theme/base_color", Color::html("#000000"));
+ Color accent_color = EDITOR_DEF("interface/theme/accent_color", Color::html("#699ce8"));
+ Color base_color = EDITOR_DEF("interface/theme/base_color", Color::html("#323b4f"));
float contrast = EDITOR_DEF("interface/theme/contrast", default_contrast);
int preset = EDITOR_DEF("interface/theme/preset", 0);
@@ -220,36 +236,64 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
bool highlight_tabs = EDITOR_DEF("interface/theme/highlight_tabs", false);
int border_size = EDITOR_DEF("interface/theme/border_size", 1);
+ bool use_gn_headers = EDITOR_DEF("interface/theme/use_graph_node_headers", false);
+
Color script_bg_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0));
+ Color preset_accent_color;
+ Color preset_base_color;
+ float preset_contrast;
switch (preset) {
case 0: { // Default
- accent_color = Color::html("#699ce8");
- base_color = Color::html("#323b4f");
- contrast = default_contrast;
+ preset_accent_color = Color::html("#699ce8");
+ preset_base_color = Color::html("#323b4f");
+ preset_contrast = default_contrast;
} break;
case 1: { // Grey
- accent_color = Color::html("#3e3e3e");
- base_color = Color::html("#3d3d3d");
- contrast = 0.2;
+ preset_accent_color = Color::html("#b8e4ff");
+ preset_base_color = Color::html("#3d3d3d");
+ preset_contrast = 0.2;
} break;
case 2: { // Godot 2
- accent_color = Color::html("#86ace2");
- base_color = Color::html("#3C3A44");
- contrast = 0.25;
+ preset_accent_color = Color::html("#86ace2");
+ preset_base_color = Color::html("#3C3A44");
+ preset_contrast = 0.25;
} break;
case 3: { // Arc
- accent_color = Color::html("#5294e2");
- base_color = Color::html("#383c4a");
- contrast = 0.25;
+ preset_accent_color = Color::html("#5294e2");
+ preset_base_color = Color::html("#383c4a");
+ preset_contrast = 0.25;
} break;
case 4: { // Light
- accent_color = Color::html("#2070ff");
- base_color = Color::html("#ffffff");
- contrast = 0.08;
+ preset_accent_color = Color::html("#2070ff");
+ preset_base_color = Color::html("#ffffff");
+ preset_contrast = 0.08;
} break;
+ case 5: { // Alien
+ preset_accent_color = Color::html("#1bfe99");
+ preset_base_color = Color::html("#2f373f");
+ preset_contrast = 0.25;
+ }
+ default: { // Custom
+ accent_color = EDITOR_DEF("interface/theme/accent_color", Color::html("#699ce8"));
+ base_color = EDITOR_DEF("interface/theme/base_color", Color::html("#323b4f"));
+ contrast = EDITOR_DEF("interface/theme/contrast", default_contrast);
+ }
}
+ if (preset != 6) {
+ accent_color = preset_accent_color;
+ base_color = preset_base_color;
+ contrast = preset_contrast;
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/accent_color", accent_color);
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/base_color", base_color);
+ EditorSettings::get_singleton()->set_initial_value("interface/theme/contrast", contrast);
+ }
+ EditorSettings::get_singleton()->set_manually("interface/theme/preset", preset);
+ EditorSettings::get_singleton()->set_manually("interface/theme/accent_color", accent_color);
+ EditorSettings::get_singleton()->set_manually("interface/theme/base_color", base_color);
+ EditorSettings::get_singleton()->set_manually("interface/theme/contrast", contrast);
+
//Colors
int AUTO_COLOR = 0;
int LIGHT_COLOR = 2;
@@ -278,6 +322,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const Color highlight_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.2);
theme->set_color("accent_color", "Editor", accent_color);
+ theme->set_color("highlight_color", "Editor", highlight_color);
theme->set_color("base_color", "Editor", base_color);
theme->set_color("dark_color_1", "Editor", dark_color_1);
theme->set_color("dark_color_2", "Editor", dark_color_2);
@@ -286,14 +331,30 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_color("contrast_color_2", "Editor", contrast_color_2);
theme->set_color("font_color", "Editor", font_color);
-
- Color success_color = accent_color.linear_interpolate(Color(.6, 1, .6), 0.8);
- Color warning_color = accent_color.linear_interpolate(Color(1, 1, .2), 0.8);
- Color error_color = accent_color.linear_interpolate(Color(1, .2, .2), 0.8);
+ theme->set_color("disabled_font_color", "Editor", font_color_disabled);
+
+ theme->set_color("mono_color", "Editor", mono_color);
+
+ Color success_color = accent_color.linear_interpolate(Color(0.2, 1, 0.2), 0.6) * 1.2;
+ Color warning_color = accent_color.linear_interpolate(Color(1, 1, 0), 0.7) * 1.2;
+ Color error_color = accent_color.linear_interpolate(Color(1, 0, 0), 0.8) * 1.7;
+ if (!dark_theme) {
+ // yellow on white themes is a P.I.T.A.
+ warning_color = accent_color.linear_interpolate(Color(1, 0.8, 0), 0.9);
+ warning_color = warning_color.linear_interpolate(mono_color, 0.2);
+ success_color = success_color.linear_interpolate(mono_color, 0.2);
+ error_color = error_color.linear_interpolate(mono_color, 0.2);
+ }
theme->set_color("success_color", "Editor", success_color);
theme->set_color("warning_color", "Editor", warning_color);
theme->set_color("error_color", "Editor", error_color);
+ // 2d grid color
+ const Color grid_minor_color = mono_color * Color(1.0, 1.0, 1.0, 0.07);
+ const Color grid_major_color = Color(font_color_disabled.r, font_color_disabled.g, font_color_disabled.b, 0.15);
+ theme->set_color("grid_major_color", "Editor", grid_major_color);
+ theme->set_color("grid_minor_color", "Editor", grid_minor_color);
+
const int thumb_size = EDITOR_DEF("filesystem/file_dialog/thumbnail_size", 64);
theme->set_constant("scale", "Editor", EDSCALE);
theme->set_constant("thumb_size", "Editor", thumb_size);
@@ -322,6 +383,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
const int border_width = CLAMP(border_size, 0, 3) * EDSCALE;
const int default_margin_size = 4;
+ const int margin_size_extra = default_margin_size + CLAMP(border_size, 0, 3);
// styleboxes
// this is the most commonly used stylebox, variations should be made as duplicate of this
@@ -331,13 +393,14 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_default->set_draw_center(true);
// Button and widgets
- Ref<StyleBoxFlat> style_widget = style_default->duplicate();
+ const float extra_spacing = EDITOR_GET("interface/theme/additional_spacing");
- // style_widget->set_bg_color(dark_color_1.linear_interpolate(base_color, 0.4));
+ Ref<StyleBoxFlat> style_widget = style_default->duplicate();
+ style_widget->set_default_margin(MARGIN_LEFT, (extra_spacing + 6) * EDSCALE);
+ style_widget->set_default_margin(MARGIN_TOP, (extra_spacing + default_margin_size) * EDSCALE);
+ style_widget->set_default_margin(MARGIN_RIGHT, (extra_spacing + 6) * EDSCALE);
+ style_widget->set_default_margin(MARGIN_BOTTOM, (extra_spacing + default_margin_size) * EDSCALE);
style_widget->set_bg_color(dark_color_1);
- style_widget->set_default_margin(MARGIN_LEFT, 6 * EDSCALE);
- style_widget->set_default_margin(MARGIN_RIGHT, 6 * EDSCALE);
- // style_widget->set_border_color_all(contrast_color_1);
style_widget->set_border_color_all(dark_color_2);
Ref<StyleBoxFlat> style_widget_disabled = style_widget->duplicate();
@@ -355,27 +418,44 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// style for windows, popups, etc..
Ref<StyleBoxFlat> style_popup = style_default->duplicate();
- style_popup->set_default_margin(MARGIN_LEFT, default_margin_size * EDSCALE * 2);
- style_popup->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE * 2);
- style_popup->set_default_margin(MARGIN_RIGHT, default_margin_size * EDSCALE * 2);
- style_popup->set_default_margin(MARGIN_BOTTOM, default_margin_size * EDSCALE * 2);
+ const int popup_margin_size = default_margin_size * EDSCALE * 2;
+ style_popup->set_default_margin(MARGIN_LEFT, popup_margin_size);
+ style_popup->set_default_margin(MARGIN_TOP, popup_margin_size);
+ style_popup->set_default_margin(MARGIN_RIGHT, popup_margin_size);
+ style_popup->set_default_margin(MARGIN_BOTTOM, popup_margin_size);
style_popup->set_border_color_all(contrast_color_1);
style_popup->set_border_width_all(MAX(EDSCALE, border_width));
const Color shadow_color = Color(0, 0, 0, dark_theme ? 0.3 : 0.1);
style_popup->set_shadow_color(shadow_color);
style_popup->set_shadow_size(4 * EDSCALE);
+ Ref<StyleBoxLine> style_popup_separator(memnew(StyleBoxLine));
+ style_popup_separator->set_color(separator_color);
+ style_popup_separator->set_grow(popup_margin_size - MAX(EDSCALE, border_width));
+ style_popup_separator->set_thickness(MAX(EDSCALE, border_width));
+
Ref<StyleBoxEmpty> style_empty = make_empty_stylebox(default_margin_size, default_margin_size, default_margin_size, default_margin_size);
// Tabs
- Ref<StyleBoxFlat> style_tab_selected = style_default->duplicate();
- style_tab_selected->set_default_margin(MARGIN_LEFT, 10 * EDSCALE);
- style_tab_selected->set_default_margin(MARGIN_RIGHT, 10 * EDSCALE);
+
+ const int tab_default_margin_side = 10 * EDSCALE + extra_spacing * EDSCALE;
+ const int tab_default_margin_vertical = 5 * EDSCALE + extra_spacing * EDSCALE;
+
+ Ref<StyleBoxFlat> style_tab_selected = style_widget->duplicate();
+
+ style_tab_selected->set_border_width_all(border_width);
+ style_tab_selected->set_border_width(MARGIN_BOTTOM, 0);
+ style_tab_selected->set_border_color_all(dark_color_3);
+ style_tab_selected->set_expand_margin_size(MARGIN_BOTTOM, border_width);
+ style_tab_selected->set_default_margin(MARGIN_LEFT, tab_default_margin_side);
+ style_tab_selected->set_default_margin(MARGIN_RIGHT, tab_default_margin_side);
+ style_tab_selected->set_default_margin(MARGIN_BOTTOM, tab_default_margin_vertical);
+ style_tab_selected->set_default_margin(MARGIN_TOP, tab_default_margin_vertical);
style_tab_selected->set_bg_color(tab_color);
- Ref<StyleBoxEmpty> style_tab_unselected = style_empty->duplicate();
- style_tab_unselected->set_default_margin(MARGIN_LEFT, 10 * EDSCALE);
- style_tab_unselected->set_default_margin(MARGIN_RIGHT, 10 * EDSCALE);
+ Ref<StyleBoxFlat> style_tab_unselected = style_tab_selected->duplicate();
+ style_tab_unselected->set_draw_center(false);
+ style_tab_unselected->set_border_width_all(0);
// Editor background
theme->set_stylebox("Background", "EditorStyles", make_flat_stylebox(background_color, default_margin_size, default_margin_size, default_margin_size, default_margin_size));
@@ -387,7 +467,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("Focus", "EditorStyles", style_focus);
// Menu
- Ref<StyleBoxEmpty> style_menu = style_empty;
+ Ref<StyleBoxFlat> style_menu = style_widget->duplicate();
+ style_menu->set_draw_center(false);
+ style_menu->set_border_width_all(0);
theme->set_stylebox("panel", "PanelContainer", style_menu);
theme->set_stylebox("MenuPanel", "EditorStyles", style_menu);
@@ -396,16 +478,16 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("ScriptEditor", "EditorStyles", make_empty_stylebox(0, 0, 0, 0));
// Play button group
- theme->set_stylebox("PlayButtonPanel", "EditorStyles", style_empty); //make_stylebox(theme->get_icon("GuiPlayButtonGroup", "EditorIcons"), 16, 16, 16, 16, 8, 4, 8, 4));
+ theme->set_stylebox("PlayButtonPanel", "EditorStyles", style_empty);
//MenuButton
- Ref<StyleBoxFlat> style_menu_hover_border = style_default->duplicate();
+ Ref<StyleBoxFlat> style_menu_hover_border = style_widget->duplicate();
style_menu_hover_border->set_draw_center(false);
style_menu_hover_border->set_border_width_all(0);
style_menu_hover_border->set_border_width(MARGIN_BOTTOM, border_width);
style_menu_hover_border->set_border_color_all(accent_color);
- Ref<StyleBoxFlat> style_menu_hover_bg = style_default->duplicate();
+ Ref<StyleBoxFlat> style_menu_hover_bg = style_widget->duplicate();
style_menu_hover_bg->set_border_width_all(0);
style_menu_hover_bg->set_bg_color(dark_color_1);
@@ -435,19 +517,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("MenuHover", "EditorStyles", style_menu_hover_border);
- // Content of each tab
- Ref<StyleBoxFlat> style_content_panel = style_default->duplicate();
- style_content_panel->set_border_color_all(base_color);
-
- // this is the stylebox used in 3d and 2d viewports (no borders)
- Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
- style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width);
- style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size);
- style_content_panel_vp->set_default_margin(MARGIN_RIGHT, border_width);
- style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width);
- theme->set_stylebox("panel", "TabContainer", style_content_panel);
- theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp);
-
// Buttons
theme->set_stylebox("normal", "Button", style_widget);
theme->set_stylebox("hover", "Button", style_widget_hover);
@@ -504,7 +573,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// PopupMenu
Ref<StyleBoxFlat> style_popup_menu = style_popup;
theme->set_stylebox("panel", "PopupMenu", style_popup_menu);
- theme->set_stylebox("separator", "PopupMenu", make_line_stylebox(separator_color, MAX(EDSCALE, border_width), 8 - MAX(EDSCALE, border_width)));
+ theme->set_stylebox("separator", "PopupMenu", style_popup_separator);
theme->set_color("font_color", "PopupMenu", font_color);
theme->set_color("font_color_hover", "PopupMenu", font_color_hl);
theme->set_color("font_color_accel", "PopupMenu", font_color_disabled);
@@ -513,6 +582,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("unchecked", "PopupMenu", theme->get_icon("GuiUnchecked", "EditorIcons"));
theme->set_icon("radio_checked", "PopupMenu", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("radio_unchecked", "PopupMenu", theme->get_icon("GuiUnchecked", "EditorIcons"));
+ theme->set_icon("submenu", "PopupMenu", theme->get_icon("ArrowRight", "EditorIcons"));
+ theme->set_constant("vseparation", "PopupMenu", (extra_spacing + default_margin_size) * EDSCALE);
// Tree & ItemList background
Ref<StyleBoxFlat> style_tree_bg = style_default->duplicate();
@@ -520,19 +591,32 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
style_tree_bg->set_border_color_all(dark_color_3);
theme->set_stylebox("bg", "Tree", style_tree_bg);
+ const Color guide_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.05);
// Tree
theme->set_icon("checked", "Tree", theme->get_icon("GuiChecked", "EditorIcons"));
theme->set_icon("unchecked", "Tree", theme->get_icon("GuiUnchecked", "EditorIcons"));
theme->set_icon("arrow", "Tree", theme->get_icon("GuiTreeArrowDown", "EditorIcons"));
theme->set_icon("arrow_collapsed", "Tree", theme->get_icon("GuiTreeArrowRight", "EditorIcons"));
theme->set_icon("select_arrow", "Tree", theme->get_icon("GuiDropdown", "EditorIcons"));
+ theme->set_icon("select_option", "Tree", theme->get_icon("GuiTreeOption", "EditorIcons"));
theme->set_stylebox("bg_focus", "Tree", style_focus);
theme->set_stylebox("custom_button", "Tree", make_empty_stylebox());
theme->set_stylebox("custom_button_pressed", "Tree", make_empty_stylebox());
theme->set_stylebox("custom_button_hover", "Tree", style_widget);
theme->set_color("custom_button_font_highlight", "Tree", font_color_hl);
theme->set_color("font_color", "Tree", font_color);
- theme->set_color("font_color_selected", "Tree", font_color);
+ theme->set_color("font_color_selected", "Tree", mono_color);
+ theme->set_color("title_button_color", "Tree", font_color);
+ theme->set_color("guide_color", "Tree", guide_color);
+ theme->set_color("drop_position_color", "Tree", accent_color);
+ theme->set_constant("vseparation", "Tree", (extra_spacing + default_margin_size) * EDSCALE);
+ theme->set_constant("hseparation", "Tree", (extra_spacing + default_margin_size) * EDSCALE);
+ theme->set_constant("guide_width", "Tree", border_width);
+ theme->set_constant("item_margin", "Tree", 3 * default_margin_size * EDSCALE);
+ theme->set_constant("button_margin", "Tree", default_margin_size * EDSCALE);
+ theme->set_constant("draw_relationship_lines", "Tree", 0);
+ theme->set_constant("scroll_border", "Tree", default_margin_size * EDSCALE);
+ theme->set_constant("scroll_speed", "Tree", 12);
Ref<StyleBoxFlat> style_tree_btn = style_default->duplicate();
style_tree_btn->set_bg_color(contrast_color_1);
@@ -561,9 +645,6 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("title_button_hover", "Tree", style_tree_title);
theme->set_stylebox("title_button_pressed", "Tree", style_tree_title);
- // Color prop_category_color = dark_color_1.linear_interpolate(mono_color, 0.12) : dark_color_1.linear_interpolate(Color(0, 0, 0, 1), 0.2);
- // Color prop_section_color = dark_color_1.linear_interpolate(mono_color, 0.09) : dark_color_1.linear_interpolate(Color(0, 1, 0, 1), 0.1);
- // Color prop_subsection_color = dark_color_1.linear_interpolate(mono_color, 0.06) : dark_color_1.linear_interpolate(Color(0, 0, 0, 1), 0.1);
Color prop_category_color = dark_color_1.linear_interpolate(mono_color, 0.12);
Color prop_section_color = dark_color_1.linear_interpolate(mono_color, 0.09);
Color prop_subsection_color = dark_color_1.linear_interpolate(mono_color, 0.06);
@@ -588,8 +669,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("selected", "ItemList", style_tree_selected);
theme->set_stylebox("bg_focus", "ItemList", style_focus);
theme->set_stylebox("bg", "ItemList", style_itemlist_bg);
- theme->set_constant("vseparation", "ItemList", 5 * EDSCALE);
theme->set_color("font_color", "ItemList", font_color);
+ theme->set_color("font_color_selected", "ItemList", mono_color);
+ theme->set_color("guide_color", "ItemList", guide_color);
+ theme->set_constant("vseparation", "ItemList", 2);
+ theme->set_constant("hseparation", "ItemList", 2);
+ theme->set_constant("icon_margin", "ItemList", default_margin_size * EDSCALE);
+ theme->set_constant("line_separation", "ItemList", 2 * EDSCALE);
// Tabs & TabContainer
theme->set_stylebox("tab_fg", "TabContainer", style_tab_selected);
@@ -607,21 +693,45 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_icon("close", "Tabs", theme->get_icon("GuiClose", "EditorIcons"));
theme->set_stylebox("button_pressed", "Tabs", style_menu);
theme->set_stylebox("button", "Tabs", style_menu);
+ theme->set_icon("increment", "TabContainer", theme->get_icon("GuiScrollArrowRight", "EditorIcons"));
+ theme->set_icon("decrement", "TabContainer", theme->get_icon("GuiScrollArrowLeft", "EditorIcons"));
+
+ // Content of each tab
+ Ref<StyleBoxFlat> style_content_panel = style_default->duplicate();
+ style_content_panel->set_border_color_all(dark_color_3);
+ style_content_panel->set_border_width_all(border_width);
+ // compensate the border
+ style_content_panel->set_default_margin(MARGIN_TOP, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(MARGIN_RIGHT, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(MARGIN_BOTTOM, margin_size_extra * EDSCALE);
+ style_content_panel->set_default_margin(MARGIN_LEFT, margin_size_extra * EDSCALE);
+
+ // this is the stylebox used in 3d and 2d viewports (no borders)
+ Ref<StyleBoxFlat> style_content_panel_vp = style_content_panel->duplicate();
+ style_content_panel_vp->set_default_margin(MARGIN_LEFT, border_width * 2);
+ style_content_panel_vp->set_default_margin(MARGIN_TOP, default_margin_size * EDSCALE);
+ style_content_panel_vp->set_default_margin(MARGIN_RIGHT, border_width * 2);
+ style_content_panel_vp->set_default_margin(MARGIN_BOTTOM, border_width * 2);
+ theme->set_stylebox("panel", "TabContainer", style_content_panel);
+ theme->set_stylebox("Content", "EditorStyles", style_content_panel_vp);
- // Separators (no separators)
+ // Separators
theme->set_stylebox("separator", "HSeparator", make_line_stylebox(separator_color, border_width));
theme->set_stylebox("separator", "VSeparator", make_line_stylebox(separator_color, border_width, 0, true));
// Debugger
- Ref<StyleBoxFlat> style_panel_debugger = style_default->duplicate();
- theme->set_stylebox("DebuggerPanel", "EditorStyles", style_panel_debugger);
- Ref<StyleBoxFlat> style_tab_fg_debugger = style_tab_selected->duplicate();
- style_tab_fg_debugger->set_border_width_all(0);
-
- theme->set_stylebox("DebuggerTabFG", "EditorStyles", style_tab_fg_debugger);
+ Ref<StyleBoxFlat> style_panel_debugger = style_content_panel->duplicate();
+ style_panel_debugger->set_border_width(MARGIN_BOTTOM, 0);
+ theme->set_stylebox("DebuggerPanel", "EditorStyles", style_panel_debugger);
+ theme->set_stylebox("DebuggerTabFG", "EditorStyles", style_tab_selected);
theme->set_stylebox("DebuggerTabBG", "EditorStyles", style_tab_unselected);
+ Ref<StyleBoxFlat> style_panel_invisible_top = style_content_panel->duplicate();
+ int stylebox_offset = theme->get_font("tab_fg", "TabContainer")->get_height() + theme->get_stylebox("tab_fg", "TabContainer")->get_minimum_size().height + theme->get_stylebox("panel", "TabContainer")->get_default_margin(MARGIN_TOP);
+ style_panel_invisible_top->set_expand_margin_size(MARGIN_TOP, -stylebox_offset);
+ theme->set_stylebox("BottomPanelDebuggerOverride", "EditorStyles", style_panel_invisible_top);
+
// LineEdit
theme->set_stylebox("normal", "LineEdit", style_widget);
theme->set_stylebox("focus", "LineEdit", style_widget_focus);
@@ -634,6 +744,9 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("normal", "TextEdit", style_widget);
theme->set_stylebox("focus", "TextEdit", style_widget_hover);
theme->set_constant("side_margin", "TabContainer", 0);
+ theme->set_icon("tab", "TextEdit", theme->get_icon("GuiTab", "EditorIcons"));
+ theme->set_color("font_color", "TextEdit", font_color);
+ theme->set_color("caret_color", "TextEdit", highlight_color);
// H/VSplitContainer
theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1));
@@ -645,6 +758,17 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_constant("separation", "HSplitContainer", default_margin_size * 2 * EDSCALE);
theme->set_constant("separation", "VSplitContainer", default_margin_size * 2 * EDSCALE);
+ // Containers
+ theme->set_constant("separation", "BoxContainer", default_margin_size * EDSCALE);
+ theme->set_constant("separation", "HBoxContainer", default_margin_size * EDSCALE);
+ theme->set_constant("separation", "VBoxContainer", default_margin_size * EDSCALE);
+ theme->set_constant("margin_left", "MarginContainer", 0);
+ theme->set_constant("margin_top", "MarginContainer", 0);
+ theme->set_constant("margin_right", "MarginContainer", 0);
+ theme->set_constant("margin_bottom", "MarginContainer", 0);
+ theme->set_constant("hseparation", "GridContainer", default_margin_size * EDSCALE);
+ theme->set_constant("vseparation", "GridContainer", default_margin_size * EDSCALE);
+
// WindowDialog
Ref<StyleBoxFlat> style_window = style_popup->duplicate();
style_window->set_border_color_all(tab_color);
@@ -705,34 +829,31 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
theme->set_stylebox("grabber_area", "VSlider", make_flat_stylebox(contrast_color_1, default_margin_size / 2, 0, default_margin_size / 2, 0));
//RichTextLabel
- Color rtl_combined_bg_color = dark_color_1.linear_interpolate(script_bg_color, script_bg_color.a);
- Color rtl_mono_color = (rtl_combined_bg_color.r + rtl_combined_bg_color.g + rtl_combined_bg_color.b > 1.5) ? Color(0, 0, 0) : Color(1, 1, 1);
- Color rtl_font_color = rtl_mono_color.linear_interpolate(rtl_combined_bg_color, 0.25);
- theme->set_color("default_color", "RichTextLabel", rtl_font_color);
+ theme->set_color("default_color", "RichTextLabel", font_color);
theme->set_stylebox("focus", "RichTextLabel", make_empty_stylebox());
theme->set_stylebox("normal", "RichTextLabel", style_tree_bg);
- Ref<StyleBoxFlat> style_code = style_tree_bg->duplicate();
- style_code->set_bg_color(rtl_combined_bg_color);
- theme->set_stylebox("code_normal", "RichTextLabel", style_code);
- Ref<StyleBoxFlat> style_code_focus = style_tree_focus->duplicate();
- style_code_focus->set_bg_color(rtl_combined_bg_color);
- theme->set_stylebox("code_focus", "RichTextLabel", style_code_focus);
- theme->set_color("font_color", "RichTextLabel", rtl_font_color);
- theme->set_color("highlight_color", "RichTextLabel", rtl_mono_color);
+ theme->set_color("headline_color", "EditorHelp", mono_color);
// Panel
theme->set_stylebox("panel", "Panel", make_flat_stylebox(dark_color_1, 6, 4, 6, 4));
// Label
+ theme->set_stylebox("normal", "Label", style_empty);
theme->set_color("font_color", "Label", font_color);
+ theme->set_color("font_color_shadow", "Label", Color(0, 0, 0, 0));
+ theme->set_constant("shadow_offset_x", "Label", 1 * EDSCALE);
+ theme->set_constant("shadow_offset_y", "Label", 1 * EDSCALE);
+ theme->set_constant("shadow_as_outline", "Label", 0 * EDSCALE);
+ theme->set_constant("line_spacing", "Label", 3 * EDSCALE);
// TooltipPanel
Ref<StyleBoxFlat> style_tooltip = style_popup->duplicate();
style_tooltip->set_bg_color(Color(mono_color.r, mono_color.g, mono_color.b, 0.9));
style_tooltip->set_border_width_all(border_width);
style_tooltip->set_border_color_all(mono_color);
- theme->set_color("font_color", "TooltipPanel", font_color);
+ theme->set_color("font_color", "TooltipLabel", font_color.inverted());
+ theme->set_color("font_color_shadow", "TooltipLabel", mono_color.inverted() * Color(1, 1, 1, 0.1));
theme->set_stylebox("panel", "TooltipPanel", style_tooltip);
// PopupPanel
@@ -748,40 +869,155 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
// GraphEdit
theme->set_stylebox("bg", "GraphEdit", style_tree_bg);
- theme->set_color("grid_major", "GraphEdit", Color(font_color.r, font_color.g, font_color.b, 0.1));
- theme->set_color("grid_minor", "GraphEdit", Color(font_color_disabled.r, font_color_disabled.g, font_color_disabled.b, 0.05));
+ theme->set_color("grid_major", "GraphEdit", grid_major_color);
+ theme->set_color("grid_minor", "GraphEdit", grid_minor_color);
theme->set_icon("minus", "GraphEdit", theme->get_icon("ZoomLess", "EditorIcons"));
theme->set_icon("more", "GraphEdit", theme->get_icon("ZoomMore", "EditorIcons"));
theme->set_icon("reset", "GraphEdit", theme->get_icon("ZoomReset", "EditorIcons"));
+ theme->set_icon("snap", "GraphEdit", theme->get_icon("SnapGrid", "EditorIcons"));
+ theme->set_constant("bezier_len_pos", "GraphEdit", 80 * EDSCALE);
+ theme->set_constant("bezier_len_neg", "GraphEdit", 160 * EDSCALE);
// GraphNode
- Ref<StyleBoxFlat> graphsb = make_flat_stylebox(Color(0, 0, 0, 0.3), 16, 24, 16, 5);
+ const int gn_margin_side = 28;
+ Ref<StyleBoxFlat> graphsb = make_flat_stylebox(Color(0, 0, 0, 0.3), gn_margin_side, 24, gn_margin_side, 5);
graphsb->set_border_width_all(border_width);
- graphsb->set_border_color_all(Color(1, 1, 1, 0.6));
- graphsb->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width);
- Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(Color(0, 0, 0, 0.4), 16, 24, 16, 5);
+ graphsb->set_border_color_all(Color(1, 1, 1, 0.9));
+ Ref<StyleBoxFlat> graphsbselected = make_flat_stylebox(Color(0, 0, 0, 0.6), gn_margin_side, 24, gn_margin_side, 5);
graphsbselected->set_border_width_all(border_width);
graphsbselected->set_border_color_all(Color(accent_color.r, accent_color.g, accent_color.b, 0.9));
graphsbselected->set_shadow_size(8 * EDSCALE);
graphsbselected->set_shadow_color(shadow_color);
- graphsbselected->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width);
- Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(Color(0, 0, 0, 0.3), 16, 24, 16, 5);
+ Ref<StyleBoxFlat> graphsbcomment = make_flat_stylebox(Color(0, 0, 0, 0.3), gn_margin_side, 24, gn_margin_side, 5);
graphsbcomment->set_border_width_all(border_width);
- graphsbcomment->set_border_color_all(Color(1, 1, 1, 0.6));
- graphsbcomment->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width);
- Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(Color(0, 0, 0, 0.4), 16, 24, 16, 5);
+ graphsbcomment->set_border_color_all(Color(1, 1, 1, 0.9));
+ Ref<StyleBoxFlat> graphsbcommentselected = make_flat_stylebox(Color(0, 0, 0, 0.4), gn_margin_side, 24, gn_margin_side, 5);
graphsbcommentselected->set_border_width_all(border_width);
graphsbcommentselected->set_border_color_all(Color(1, 1, 1, 0.9));
- graphsbcommentselected->set_border_width(MARGIN_TOP, 22 * EDSCALE + border_width);
+ Ref<StyleBoxFlat> graphsbbreakpoint = graphsbselected->duplicate();
+ graphsbbreakpoint->set_draw_center(false);
+ graphsbbreakpoint->set_border_color_all(warning_color);
+ graphsbbreakpoint->set_shadow_color(warning_color * Color(1.0, 1.0, 1.0, 0.1));
+ Ref<StyleBoxFlat> graphsbposition = graphsbselected->duplicate();
+ graphsbposition->set_draw_center(false);
+ graphsbposition->set_border_color_all(error_color);
+ graphsbposition->set_shadow_color(error_color * Color(1.0, 1.0, 1.0, 0.2));
+
+ if (use_gn_headers) {
+ graphsb->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ graphsbselected->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ graphsbcomment->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ graphsbcommentselected->set_border_width(MARGIN_TOP, 24 * EDSCALE);
+ }
+
theme->set_stylebox("frame", "GraphNode", graphsb);
theme->set_stylebox("selectedframe", "GraphNode", graphsbselected);
theme->set_stylebox("comment", "GraphNode", graphsbcomment);
theme->set_stylebox("commentfocus", "GraphNode", graphsbcommentselected);
+ theme->set_stylebox("breakpoint", "GraphNode", graphsbbreakpoint);
+ theme->set_stylebox("position", "GraphNode", graphsbposition);
+ theme->set_constant("port_offset", "GraphNode", 14 * EDSCALE);
+ theme->set_constant("title_h_offset", "GraphNode", -16 * EDSCALE);
+ theme->set_constant("close_h_offset", "GraphNode", 20 * EDSCALE);
+ theme->set_constant("close_offset", "GraphNode", 20 * EDSCALE);
+ theme->set_icon("close", "GraphNode", theme->get_icon("GuiCloseCustomizable", "EditorIcons"));
+ theme->set_icon("resizer", "GraphNode", theme->get_icon("GuiResizer", "EditorIcons"));
+ theme->set_icon("port", "GraphNode", theme->get_icon("GuiGraphNodePort", "EditorIcons"));
+
+ // GridContainer
+ theme->set_constant("vseperation", "GridContainer", (extra_spacing + default_margin_size) * EDSCALE);
// FileDialog
+ theme->set_icon("folder", "FileDialog", theme->get_icon("Folder", "EditorIcons"));
theme->set_color("files_disabled", "FileDialog", font_color_disabled);
+ // color picker
+ theme->set_constant("margin", "ColorPicker", popup_margin_size);
+ theme->set_constant("sv_width", "ColorPicker", 256 * EDSCALE);
+ theme->set_constant("sv_height", "ColorPicker", 256 * EDSCALE);
+ theme->set_constant("h_width", "ColorPicker", 30 * EDSCALE);
+ theme->set_constant("label_width", "ColorPicker", 10 * EDSCALE);
+ theme->set_icon("screen_picker", "ColorPicker", theme->get_icon("ColorPick", "EditorIcons"));
+ theme->set_icon("add_preset", "ColorPicker", theme->get_icon("Add", "EditorIcons"));
+ theme->set_icon("preset_bg", "ColorPicker", theme->get_icon("GuiMiniCheckerboard", "EditorIcons"));
+
+ theme->set_icon("bg", "ColorPickerButton", theme->get_icon("GuiMiniCheckerboard", "EditorIcons"));
+
+ // adaptive script theme constants
+ // for comments and elements with lower relevance
+ const Color dim_color = Color(font_color.r, font_color.g, font_color.b, 0.5);
+
+ const float mono_value = mono_color.r;
+ const Color alpha1 = Color(mono_value, mono_value, mono_value, 0.1);
+ const Color alpha2 = Color(mono_value, mono_value, mono_value, 0.3);
+ const Color alpha3 = Color(mono_value, mono_value, mono_value, 0.5);
+ const Color alpha4 = Color(mono_value, mono_value, mono_value, 0.7);
+
+ // editor main color
+ const Color main_color = Color::html(dark_theme ? "#57b3ff" : "#0480ff");
+
+ const Color symbol_color = Color::html("#5792ff").linear_interpolate(mono_color, dark_theme ? 0.5 : 0.3);
+ const Color keyword_color = Color::html("#ff7185");
+ const Color basetype_color = Color::html(dark_theme ? "#42ffc2" : "#00c161");
+ const Color type_color = basetype_color.linear_interpolate(mono_color, dark_theme ? 0.7 : 0.5);
+ const Color comment_color = dim_color;
+ const Color string_color = Color::html(dark_theme ? "#ffd942" : "#ffd118").linear_interpolate(mono_color, dark_theme ? 0.5 : 0.3);
+
+ const Color te_background_color = Color(0, 0, 0, 0);
+ const Color completion_background_color = base_color;
+ const Color completion_selected_color = alpha1;
+ const Color completion_existing_color = alpha2;
+ const Color completion_scroll_color = alpha1;
+ const Color completion_font_color = font_color;
+ const Color text_color = font_color;
+ const Color line_number_color = dim_color;
+ const Color caret_color = mono_color;
+ const Color caret_background_color = mono_color.inverted();
+ const Color text_selected_color = dark_color_3;
+ const Color selection_color = alpha3;
+ const Color brace_mismatch_color = error_color;
+ const Color current_line_color = alpha1;
+ const Color line_length_guideline_color = warning_color;
+ const Color word_highlighted_color = alpha1;
+ const Color number_color = basetype_color.linear_interpolate(mono_color, dark_theme ? 0.5 : 0.3);
+ const Color function_color = main_color;
+ const Color member_variable_color = mono_color;
+ const Color mark_color = Color(error_color.r, error_color.g, error_color.b, 0.3);
+ const Color breakpoint_color = error_color;
+ const Color search_result_color = alpha1;
+ const Color search_result_border_color = alpha4;
+
+ theme->set_color("text_editor/theme/symbol_color", "Editor", symbol_color);
+ theme->set_color("text_editor/theme/keyword_color", "Editor", keyword_color);
+ theme->set_color("text_editor/theme/basetype_color", "Editor", basetype_color);
+ theme->set_color("text_editor/theme/type_color", "Editor", type_color);
+ theme->set_color("text_editor/theme/comment_color", "Editor", comment_color);
+ theme->set_color("text_editor/theme/string_color", "Editor", string_color);
+ theme->set_color("text_editor/theme/background_color", "Editor", te_background_color);
+ theme->set_color("text_editor/theme/completion_background_color", "Editor", completion_background_color);
+ theme->set_color("text_editor/theme/completion_selected_color", "Editor", completion_selected_color);
+ theme->set_color("text_editor/theme/completion_existing_color", "Editor", completion_existing_color);
+ theme->set_color("text_editor/theme/completion_scroll_color", "Editor", completion_scroll_color);
+ theme->set_color("text_editor/theme/completion_font_color", "Editor", completion_font_color);
+ theme->set_color("text_editor/theme/text_color", "Editor", text_color);
+ theme->set_color("text_editor/theme/line_number_color", "Editor", line_number_color);
+ theme->set_color("text_editor/theme/caret_color", "Editor", caret_color);
+ theme->set_color("text_editor/theme/caret_background_color", "Editor", caret_background_color);
+ theme->set_color("text_editor/theme/text_selected_color", "Editor", text_selected_color);
+ theme->set_color("text_editor/theme/selection_color", "Editor", selection_color);
+ theme->set_color("text_editor/theme/brace_mismatch_color", "Editor", brace_mismatch_color);
+ theme->set_color("text_editor/theme/current_line_color", "Editor", current_line_color);
+ theme->set_color("text_editor/theme/line_length_guideline_color", "Editor", line_length_guideline_color);
+ theme->set_color("text_editor/theme/word_highlighted_color", "Editor", word_highlighted_color);
+ theme->set_color("text_editor/theme/number_color", "Editor", number_color);
+ theme->set_color("text_editor/theme/function_color", "Editor", function_color);
+ theme->set_color("text_editor/theme/member_variable_color", "Editor", member_variable_color);
+ theme->set_color("text_editor/theme/mark_color", "Editor", mark_color);
+ theme->set_color("text_editor/theme/breakpoint_color", "Editor", breakpoint_color);
+ theme->set_color("text_editor/theme/search_result_color", "Editor", search_result_color);
+ theme->set_color("text_editor/theme/search_result_border_color", "Editor", search_result_border_color);
+
return theme;
}
@@ -793,7 +1029,7 @@ Ref<Theme> create_custom_theme() {
theme = ResourceLoader::load(custom_theme);
}
- String global_font = EditorSettings::get_singleton()->get("interface/custom_font");
+ String global_font = EditorSettings::get_singleton()->get("interface/editor/custom_font");
if (global_font != "") {
Ref<Font> fnt = ResourceLoader::load(global_font);
if (fnt.is_valid()) {
diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp
index 147d5f90c6..d867404f3d 100644
--- a/editor/export_template_manager.cpp
+++ b/editor/export_template_manager.cpp
@@ -73,7 +73,7 @@ void ExportTemplateManager::_update_template_list() {
current_hb->add_child(current);
if (templates.has(current_version)) {
- current->add_color_override("font_color", Color(0.5, 1, 0.5));
+ current->add_color_override("font_color", get_color("success_color", "Editor"));
Button *redownload = memnew(Button);
redownload->set_text(TTR("Re-Download"));
current_hb->add_child(redownload);
@@ -86,7 +86,7 @@ void ExportTemplateManager::_update_template_list() {
uninstall->connect("pressed", this, "_uninstall_template", varray(current_version));
} else {
- current->add_color_override("font_color", Color(1.0, 0.5, 0.5));
+ current->add_color_override("font_color", get_color("error_color", "Editor"));
Button *redownload = memnew(Button);
redownload->set_text(TTR("Download"));
redownload->connect("pressed", this, "_download_template", varray(current_version));
@@ -98,7 +98,7 @@ void ExportTemplateManager::_update_template_list() {
HBoxContainer *hbc = memnew(HBoxContainer);
Label *version = memnew(Label);
- version->set_modulate(Color(1, 1, 1, 0.7));
+ version->set_modulate(get_color("disabled_font_color", "Editor"));
String text = E->get();
if (text == current_version) {
text += " " + TTR("(Current)");
@@ -299,7 +299,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file) {
void ExportTemplateManager::popup_manager() {
_update_template_list();
- popup_centered_minsize(Size2(400, 600) * EDSCALE);
+ popup_centered_minsize(Size2(400, 400) * EDSCALE);
}
void ExportTemplateManager::ok_pressed() {
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index f0ace864e4..a9d72607b4 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1002,7 +1002,7 @@ void FileSystemDock::_file_option(int p_option) {
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))
+ if (!files->is_selected(i))
continue;
torem.push_back(path);
}
@@ -1258,11 +1258,11 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
if (drag_data.has("type") && String(drag_data["type"]) == "favorite") {
//moving favorite around
- TreeItem *ti = tree->get_item_at_pos(p_point);
+ TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return false;
- int what = tree->get_drop_section_at_pos(p_point);
+ int what = tree->get_drop_section_at_position(p_point);
if (ti == tree->get_root()->get_children()) {
return (what == 1); //the parent, first fav
@@ -1288,7 +1288,7 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
if (p_from == files) {
- int at_pos = files->get_item_at_pos(p_point);
+ int at_pos = files->get_item_at_position(p_point);
if (at_pos != -1) {
String dir = files->get_item_metadata(at_pos);
@@ -1299,7 +1299,7 @@ bool FileSystemDock::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
if (p_from == tree) {
- TreeItem *ti = tree->get_item_at_pos(p_point);
+ TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return false;
String path = ti->get_metadata(0);
@@ -1323,7 +1323,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
if (drag_data.has("type") && String(drag_data["type"]) == "favorite") {
//moving favorite around
- TreeItem *ti = tree->get_item_at_pos(p_point);
+ TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return;
@@ -1336,7 +1336,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
swap = swap.substr(0, swap.length() - 1);
}
- int what = tree->get_drop_section_at_pos(p_point);
+ int what = tree->get_drop_section_at_position(p_point);
TreeItem *swap_item = NULL;
@@ -1391,7 +1391,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
if (p_from == tree) {
- TreeItem *ti = tree->get_item_at_pos(p_point);
+ TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return;
String path = ti->get_metadata(0);
@@ -1406,7 +1406,7 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
if (p_from == files) {
String save_path = path;
- int at_pos = files->get_item_at_pos(p_point);
+ int at_pos = files->get_item_at_position(p_point);
if (at_pos != -1) {
String to_dir = files->get_item_metadata(at_pos);
if (to_dir.ends_with("/")) {
@@ -1429,11 +1429,11 @@ void FileSystemDock::drop_data_fw(const Point2 &p_point, const Variant &p_data,
if (p_from == files) {
- int at_pos = files->get_item_at_pos(p_point);
+ int at_pos = files->get_item_at_position(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);
+ TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return;
to_dir = ti->get_metadata(0);
@@ -1466,6 +1466,7 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
bool all_scenes = true;
bool all_can_reimport = true;
+ bool is_dir = false;
Set<String> types;
for (int i = 0; i < files->get_item_count(); i++) {
@@ -1481,8 +1482,7 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
}
if (path.ends_with("/")) {
- //no operate on dirs
- return;
+ is_dir = true;
}
int pos;
@@ -1513,17 +1513,19 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
file_options->add_separator();
- if (filenames.size() == 1) {
+ if (filenames.size() == 1 && !is_dir) {
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);
+ if (!is_dir) {
+ 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);
@@ -1812,8 +1814,6 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
display_mode = DISPLAY_THUMBNAILS;
path = "res://";
-
- add_constant_override("separation", 4);
}
FileSystemDock::~FileSystemDock() {
diff --git a/editor/icons/icon_2_d.svg b/editor/icons/icon_2_d.svg
index b77c330bff..dcc22a579e 100644
--- a/editor/icons/icon_2_d.svg
+++ b/editor/icons/icon_2_d.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m3.9844 1.002a1.0001 1.0001 0 0 0 -0.69141 0.29102l-2 2a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l0.29297-0.29297v8.5859h8.5859l-0.29297 0.29297a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 0 -1.4141l-2-2a1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l0.29297 0.29297h-6.5859v-6.5859l0.29297 0.29297a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-2-2a1.0001 1.0001 0 0 0 -0.72266 -0.29102z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-</g>
+<path d="m3.9844 1.002a1.0001 1.0001 0 0 0 -0.69141 0.29102l-2 2a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l0.29297-0.29297v8.5859h8.5859l-0.29297 0.29297a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 0 -1.4141l-2-2a1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l0.29297 0.29297h-6.5859v-6.5859l0.29297 0.29297a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-2-2a1.0001 1.0001 0 0 0 -0.72266 -0.29102z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</svg>
diff --git a/editor/icons/icon_3_d.svg b/editor/icons/icon_3_d.svg
index 91d3abf60d..2b89b0fbbe 100644
--- a/editor/icons/icon_3_d.svg
+++ b/editor/icons/icon_3_d.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m3.9902 1.002a1.0001 1.0001 0 0 0 -0.69141 0.29102l-2 2a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l0.29297-0.29297v8.5859h8.5859l-0.29297 0.29297a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 0 -1.4141l-2-2a1 1 0 0 0 -0.72266 -0.29102 1 1 0 0 0 -0.69141 0.29102 1 1 0 0 0 0 1.4141l0.29297 0.29297h-5.1719l5.5859-5.5859v0.41602a1 1 0 0 0 1 1 1 1 0 0 0 1 -1v-2.8301a1.0001 1.0001 0 0 0 -1 -1h-2.8301a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h0.41602l-5.5859 5.5859v-5.1719l0.29297 0.29297a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-2-2a1.0001 1.0001 0 0 0 -0.72266 -0.29102z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-</g>
+<path d="m3.9902 1.002a1.0001 1.0001 0 0 0 -0.69141 0.29102l-2 2a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l0.29297-0.29297v8.5859h8.5859l-0.29297 0.29297a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 0 -1.4141l-2-2a1 1 0 0 0 -0.72266 -0.29102 1 1 0 0 0 -0.69141 0.29102 1 1 0 0 0 0 1.4141l0.29297 0.29297h-5.1719l5.5859-5.5859v0.41602a1 1 0 0 0 1 1 1 1 0 0 0 1 -1v-2.8301a1.0001 1.0001 0 0 0 -1 -1h-2.8301a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h0.41602l-5.5859 5.5859v-5.1719l0.29297 0.29297a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-2-2a1.0001 1.0001 0 0 0 -0.72266 -0.29102z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</svg>
diff --git a/editor/icons/icon_GUI_checked.svg b/editor/icons/icon_GUI_checked.svg
index 7ba83d48d5..e5fa67ebf5 100644
--- a/editor/icons/icon_GUI_checked.svg
+++ b/editor/icons/icon_GUI_checked.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m4 2c-1.1046 0-2 0.89543-2 2v8c0 1.1046 0.89543 2 2 2h8c1.1046 0 2-0.89543 2-2v-8c0-1.1046-0.89543-2-2-2h-8zm7.293 2.293l1.4141 1.4141-6.707 6.707-2.707-2.707 1.4141-1.4141 1.293 1.293 5.293-5.293z" fill="#e0e0e0" fill-opacity=".78431"/>
-</g>
+<path d="m4 2c-1.1046 0-2 0.89543-2 2v8c0 1.1046 0.89543 2 2 2h8c1.1046 0 2-0.89543 2-2v-8c0-1.1046-0.89543-2-2-2h-8zm7.293 2.293l1.4141 1.4141-6.707 6.707-2.707-2.707 1.4141-1.4141 1.293 1.293 5.293-5.293z" fill="#e0e0e0" fill-opacity=".78431"/>
</svg>
diff --git a/editor/icons/icon_GUI_dropdown.svg b/editor/icons/icon_GUI_dropdown.svg
index 22db0fa1a7..4aa800b470 100644
--- a/editor/icons/icon_GUI_dropdown.svg
+++ b/editor/icons/icon_GUI_dropdown.svg
@@ -1,7 +1,5 @@
<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill="#fff" fill-opacity=".58824" stroke-linejoin="round" stroke-opacity=".39216" stroke-width="2">
-<circle cx="7.5" cy="1040.9" r="1.5"/>
-<circle cx="7.5" cy="1045.9" r="1.5"/>
-<circle cx="7.5" cy="1050.9" r="1.5"/>
+<g transform="translate(0 -1038.4)">
+<path d="m4 1045.4 3 3 3-3" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".58824" stroke-width="2"/>
</g>
</svg>
diff --git a/editor/icons/icon_GUI_h_tick.svg b/editor/icons/icon_GUI_h_tick.svg
new file mode 100644
index 0000000000..5aa799deb0
--- /dev/null
+++ b/editor/icons/icon_GUI_h_tick.svg
@@ -0,0 +1,3 @@
+<svg width="4" height="16" version="1.1" viewBox="0 0 4 15.999999" xmlns="http://www.w3.org/2000/svg">
+<circle cx="2" cy="2" r="1" fill="#fff" fill-opacity=".39216"/>
+</svg>
diff --git a/editor/icons/icon_mini_checkerboard.svg b/editor/icons/icon_GUI_mini_checkerboard.svg
index e740113b2d..e740113b2d 100644
--- a/editor/icons/icon_mini_checkerboard.svg
+++ b/editor/icons/icon_GUI_mini_checkerboard.svg
diff --git a/editor/icons/icon_GUI_mini_tab_menu.svg b/editor/icons/icon_GUI_mini_tab_menu.svg
index c54eb26115..8aeb85277c 100644
--- a/editor/icons/icon_GUI_mini_tab_menu.svg
+++ b/editor/icons/icon_GUI_mini_tab_menu.svg
@@ -1,7 +1,5 @@
<svg width="6" height="16" version="1.1" viewBox="0 0 6 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fff" fill-opacity=".39216">
-<circle cx="3" cy="1038.4" r="2"/>
-<circle cx="3" cy="1044.4" r="2"/>
-<circle cx="3" cy="1050.4" r="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm0 6a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm0 6a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_GUI_play_button_group.svg b/editor/icons/icon_GUI_play_button_group.svg
deleted file mode 100644
index 1d67816b3a..0000000000
--- a/editor/icons/icon_GUI_play_button_group.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="32" height="32" version="1.1" viewBox="0 0 32 31.999998" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1020.4)">
-<circle cx="16" cy="1036.4" r="14" fill-opacity=".19608"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_GUI_scroll_arrow_left.svg b/editor/icons/icon_GUI_scroll_arrow_left.svg
new file mode 100644
index 0000000000..364d15ea26
--- /dev/null
+++ b/editor/icons/icon_GUI_scroll_arrow_left.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg">
+<path d="m8 2a6 6 0 0 1 6 6 6 6 0 0 1 -6 6 6 6 0 0 1 -6 -6 6 6 0 0 1 6 -6zm1.0137 2a1 1 0 0 0 -0.7207 0.29297l-3 3a1.0001 1.0001 0 0 0 0 1.4141l3 3a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-2.293-2.293 2.293-2.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.69336 -0.29297z" fill="#e0e0e0" fill-opacity=".78431" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+</svg>
diff --git a/editor/icons/icon_GUI_scroll_arrow_right.svg b/editor/icons/icon_GUI_scroll_arrow_right.svg
new file mode 100644
index 0000000000..5788aa1b0b
--- /dev/null
+++ b/editor/icons/icon_GUI_scroll_arrow_right.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 15.999999" xmlns="http://www.w3.org/2000/svg">
+<path d="m8 2a6 6 0 0 0 -6 6 6 6 0 0 0 6 6 6 6 0 0 0 6 -6 6 6 0 0 0 -6 -6zm-1.0137 2a1 1 0 0 1 0.7207 0.29297l3 3a1.0001 1.0001 0 0 1 0 1.4141l-3 3a1 1 0 0 1 -1.4141 0 1 1 0 0 1 0 -1.4141l2.293-2.293-2.293-2.293a1 1 0 0 1 0 -1.4141 1 1 0 0 1 0.69336 -0.29297z" fill="#e0e0e0" fill-opacity=".78431" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+</svg>
diff --git a/editor/icons/icon_GUI_tab.svg b/editor/icons/icon_GUI_tab.svg
new file mode 100644
index 0000000000..3eed0680c0
--- /dev/null
+++ b/editor/icons/icon_GUI_tab.svg
@@ -0,0 +1,5 @@
+<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1044.4)">
+<path transform="translate(0 1044.4)" d="m6 0v8h2v-8h-2zm-5.0137 0.0019531a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l2.293 2.293-2.293 2.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l3-3a1.0001 1.0001 0 0 0 0 -1.4141l-3-3a1 1 0 0 0 -0.7207 -0.29102z" fill="#fff" fill-opacity=".19608"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_GUI_tab_menu.svg b/editor/icons/icon_GUI_tab_menu.svg
index 3324adf98b..9284e7488b 100644
--- a/editor/icons/icon_GUI_tab_menu.svg
+++ b/editor/icons/icon_GUI_tab_menu.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fff" fill-opacity=".39216">
-<circle cx="8" cy="1038.4" r="2"/>
-<circle cx="8" cy="1044.4" r="2"/>
-<circle cx="8" cy="1050.4" r="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm0 6a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm0 6a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_GUI_tree_option.svg b/editor/icons/icon_GUI_tree_option.svg
new file mode 100644
index 0000000000..4200745a78
--- /dev/null
+++ b/editor/icons/icon_GUI_tree_option.svg
@@ -0,0 +1,5 @@
+<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1038.4)">
+<path transform="translate(0 1038.4)" d="m7.5 1a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5 -1.5 1.5 1.5 0 0 0 -1.5 -1.5zm0 5a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5 -1.5 1.5 1.5 0 0 0 -1.5 -1.5zm0 5a1.5 1.5 0 0 0 -1.5 1.5 1.5 1.5 0 0 0 1.5 1.5 1.5 1.5 0 0 0 1.5 -1.5 1.5 1.5 0 0 0 -1.5 -1.5z" fill="#fff" fill-opacity=".58824" stroke-linejoin="round" stroke-opacity=".39216" stroke-width="2"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_GUI_v_tick.svg b/editor/icons/icon_GUI_v_tick.svg
new file mode 100644
index 0000000000..87b5656927
--- /dev/null
+++ b/editor/icons/icon_GUI_v_tick.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="4" version="1.1" viewBox="0 0 16 3.9999998" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0,-12)">
+<circle cx="2" cy="14" r="1" fill="#fff" fill-opacity=".39216"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_a_r_v_r_camera.svg b/editor/icons/icon_a_r_v_r_camera.svg
new file mode 100644
index 0000000000..a02b4d983c
--- /dev/null
+++ b/editor/icons/icon_a_r_v_r_camera.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m2 1c-0.55401 0-1 0.446-1 1v7c0 0.554 0.44599 1 1 1h4l1-2c0.24699-0.494 0.44772-1 1-1s0.75301 0.506 1 1l1 2h4c0.55401 0 1-0.446 1-1v-7c0-0.554-0.44599-1-1-1h-12zm2 3a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm8 0a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2zm-8 7v4h2c0.502 4e-4 0.9265-0.37144 0.99219-0.86914 0.0059-0.047 0.0085325-0.094025 0.0078125-0.14062v-2.9902h-1v3h-1v-3h-1zm5 0v4h1v-1h1v1h1v-1c-7.73e-4 -0.1811-0.05073-0.35867-0.14453-0.51367 0.08369-0.1462 0.14453-0.30573 0.14453-0.48633v-1c0-0.5523-0.4485-1.0293-1-1h-2zm1 1h1v1h-1v-1z" fill="#fc9c9c"/>
+</svg>
diff --git a/editor/icons/icon_accept_dialog.svg b/editor/icons/icon_accept_dialog.svg
index 331b88dd74..b65f58b35e 100644
--- a/editor/icons/icon_accept_dialog.svg
+++ b/editor/icons/icon_accept_dialog.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.8954-2 2v1h14v-1c0-1.1046-0.89543-2-2-2zm9 1h1v1h-1zm-11 3v8c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.8954 2-2v-8zm9.4746 1.6367 1.4141 1.4141-4.9492 4.9492-2.8281-2.8281 1.4141-1.4141 1.4141 1.4141z" fill="#a5efac"/>
-</g>
+<path d="m3 1c-1.1046 0-2 0.8954-2 2v1h14v-1c0-1.1046-0.89543-2-2-2zm9 1h1v1h-1zm-11 3v8c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.8954 2-2v-8zm9.4746 1.6367 1.4141 1.4141-4.9492 4.9492-2.8281-2.8281 1.4141-1.4141 1.4141 1.4141z" fill="#a5efac"/>
</svg>
diff --git a/editor/icons/icon_add.svg b/editor/icons/icon_add.svg
index 685e6e82e8..3b7e9b8fc1 100644
--- a/editor/icons/icon_add.svg
+++ b/editor/icons/icon_add.svg
@@ -1,5 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m7 1v6h-6v2h6v6h2v-6h6v-2h-6v-6h-2z" fill="#e0e0e0"/>
-</g>
+<path d="m7 1v6h-6v2h6v6h2v-6h6v-2h-6v-6h-2z" fill="#e0e0e0"/>
</svg>
diff --git a/editor/icons/icon_area.svg b/editor/icons/icon_area.svg
index 22348d50c1..ac673d10fc 100644
--- a/editor/icons/icon_area.svg
+++ b/editor/icons/icon_area.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#fc9c9c" fill-opacity=".99608"/>
+<path transform="translate(0 1036.4)" d="m1 1v2 2h2v-2h2v-2h-4zm10 0v2h2v2h2v-4h-4zm-7 3v2 4 2h8v-2-6h-8zm2 2h4v4h-4v-4zm-5 5v2 2h2 2v-2h-2v-2h-2zm12 0v2h-2v2h4v-2-2h-2z" fill="#fc9c9c"/>
</g>
</svg>
diff --git a/editor/icons/icon_audio_bus_bypass.svg b/editor/icons/icon_audio_bus_bypass.svg
index 75c1caf7f1..f85c9d17b5 100644
--- a/editor/icons/icon_audio_bus_bypass.svg
+++ b/editor/icons/icon_audio_bus_bypass.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m6.9707 2c-0.25474 0.01-0.49715 0.11122-0.67773 0.29102l-2.707 2.707h-1.5859c-0.55226 1e-4 -0.99994 0.4477-1 1v4c5.52e-5 0.5523 0.44774 0.9999 1 1h1.5859l2.707 2.707c0.63002 0.6296 1.7067 0.18367 1.707-0.70703v-10c-9.424e-4 -0.5631-0.46642-1.0144-1.0293-0.99805zm3.0293 5v1 1h4v-1-1h-4z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1036.4)" d="m5 3c-0.55226 5.52e-5 -0.99994 0.44774-1 1v8c5.52e-5 0.55226 0.44774 0.99994 1 1h4c1.0702 0 2.0645-0.5732 2.5996-1.5 0.5351-0.9268 0.5351-2.0732 0-3-0.40058-0.69381-1.058-1.1892-1.8125-1.3945 0.33452-0.84425 0.27204-1.8062-0.18945-2.6055-0.5351-0.9268-1.5275-1.5-2.5977-1.5zm1 2h1c0.35887 0 0.6858 0.1892 0.86523 0.5s0.17943 0.6892 0 1-0.50637 0.5-0.86523 0.5h-1zm0 4h1 2c0.35887 0 0.68775 0.1892 0.86719 0.5 0.17943 0.3108 0.17943 0.6892 0 1-0.17944 0.3108-0.50832 0.5-0.86719 0.5h-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_audio_bus_mute.svg b/editor/icons/icon_audio_bus_mute.svg
index a7d085d535..cacca295eb 100644
--- a/editor/icons/icon_audio_bus_mute.svg
+++ b/editor/icons/icon_audio_bus_mute.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m6.9707 2c-0.25474 0.01-0.49715 0.11122-0.67773 0.29102l-2.707 2.707h-1.5859c-0.55226 1e-4 -0.99994 0.4477-1 1v4c5.52e-5 0.5523 0.44774 0.9999 1 1h1.5859l2.707 2.707c0.63002 0.6296 1.7067 0.18367 1.707-0.70703v-10c-9.424e-4 -0.5631-0.46642-1.0144-1.0293-0.99805zm4.0195 2.9902a1.0001 1.0001 0 0 0 -0.69726 1.7168l1.293 1.293-1.293 1.293a1.0001 1.0001 0 1 0 1.4141 1.4141l1.293-1.293 1.293 1.293a1.0001 1.0001 0 1 0 1.4141 -1.4141l-1.293-1.293 1.293-1.293a1.0001 1.0001 0 0 0 -0.72656 -1.7148 1.0001 1.0001 0 0 0 -0.6875 0.30078l-1.293 1.293-1.293-1.293a1.0001 1.0001 0 0 0 -0.7168 -0.30273z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path d="m4 1048.4v-8l4 5 4-5v8" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</svg>
diff --git a/editor/icons/icon_audio_bus_solo.svg b/editor/icons/icon_audio_bus_solo.svg
index e84c1cca25..25e26d6038 100644
--- a/editor/icons/icon_audio_bus_solo.svg
+++ b/editor/icons/icon_audio_bus_solo.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m6.9707 2c-0.25474 0.01-0.49715 0.11122-0.67773 0.29102l-2.707 2.707h-1.5859c-0.55226 1e-4 -0.99994 0.4477-1 1v4c5.52e-5 0.5523 0.44774 0.9999 1 1h1.5859l2.707 2.707c0.63002 0.6296 1.7067 0.18367 1.707-0.70703v-10c-9.424e-4 -0.5631-0.46642-1.0144-1.0293-0.99805zm8.0293 2a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3 -3v-2a1 1 0 0 1 1 -1h1v-2h-1z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1036.4)" d="m7 3a1 1 0 0 0 -0.12695 0.0078125c-1.0208 0.043703-1.957 0.60248-2.4707 1.4922-0.5351 0.9268-0.5351 2.0732 0 3 0.5351 0.9268 1.5275 1.5 2.5977 1.5h2c0.35887 0 0.6858 0.1892 0.86523 0.5 0.17943 0.3108 0.17943 0.6892 0 1-0.17943 0.3108-0.50637 0.5-0.86523 0.5h-3a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h3c1.0702 0 2.0626-0.5732 2.5977-1.5s0.5351-2.0732 0-3-1.5275-1.5-2.5977-1.5h-2c-0.35887 0-0.6858-0.1892-0.86523-0.5s-0.17943-0.6892 0-1 0.50637-0.5 0.86523-0.5h3a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_audio_effect_amplify.svg b/editor/icons/icon_audio_effect_amplify.svg
deleted file mode 100644
index 20612bbaf3..0000000000
--- a/editor/icons/icon_audio_effect_amplify.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<linearGradient id="a" x1="9" x2="9" y1="1037.4" y2="1051.4" gradientTransform="translate(0 -1036.4)" gradientUnits="userSpaceOnUse">
-<stop stop-color="#ff8484" offset="0"/>
-<stop stop-color="#e1dc7a" offset=".5"/>
-<stop stop-color="#84ffb1" offset="1"/>
-</linearGradient>
-</defs>
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m2 1v8h2v-2h2v-2h-2v-2h3v-2zm6 0 2 4-2 4h2l1-2 1 2h2l-2-4 2-4h-2l-1 2-1-2zm-6 9v1h2v-1zm2 1v1h-2v-1h-1v4h1v-2h2v2h1v-4zm2-1v5h1v-4h1v4h1v-4h1v-1zm4 1v4h1v-4zm2-1v5h1v-2h2v-3zm1 1h1v1h-1z" fill="url(#a)"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_audio_stream_gibberish.svg b/editor/icons/icon_audio_stream_gibberish.svg
deleted file mode 100644
index 4b503a211a..0000000000
--- a/editor/icons/icon_audio_stream_gibberish.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m3 2a2 2 0 0 0 -2 2v5a2 2 0 0 0 2 2h3v3l3-3h4a2 2 0 0 0 2 -2v-5a2 2 0 0 0 -2 -2h-10zm0 4h2v1h-2v-1zm5 0a1 1 0 0 1 1 1v1a1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1v-1a1 1 0 0 1 1 -1zm3 0h2v1h-2v-1z" fill="#e0e0e0" fill-opacity=".99216"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_bool.svg b/editor/icons/icon_bool.svg
deleted file mode 100644
index 56fcba5833..0000000000
--- a/editor/icons/icon_bool.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m0 4v4 4h2a3 3 0 0 0 2.5 -1.3457 3 3 0 0 0 2.5 1.3457 3 3 0 0 0 2 -0.76758 3 3 0 0 0 2 0.76758 3 3 0 0 0 2.5 -1.3457 3 3 0 0 0 2.5 1.3457v-2a1 1 0 0 1 -1 -1v-5h-2v2.7695a3 3 0 0 0 -2 -0.76953 3 3 0 0 0 -2 0.76758 3 3 0 0 0 -2 -0.76758 3 3 0 0 0 -2.5 1.3457 3 3 0 0 0 -2.5 -1.3457v-2h-2zm2 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#cf68ea"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_collapse.svg b/editor/icons/icon_collapse.svg
index ace258a38a..8d50772b9b 100644
--- a/editor/icons/icon_collapse.svg
+++ b/editor/icons/icon_collapse.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m2 1040.4v3.9375l6 5.0625 6-5.0625v-3.9375h-12z" fill="#e0e0e0"/>
+<path d="m3 1044.4 5 4 5-4" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</svg>
diff --git a/editor/icons/icon_color.svg b/editor/icons/icon_color.svg
deleted file mode 100644
index 7e2d9216f3..0000000000
--- a/editor/icons/icon_color.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<defs>
-<clipPath id="a">
-<path d="m8 1037.4a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 3a4 4 0 0 1 4 4 4 4 0 0 1 -4 4 4 4 0 0 1 -4 -4 4 4 0 0 1 4 -4z" fill="#fff"/>
-</clipPath>
-</defs>
-<g transform="translate(0 -1036.4)">
-<circle cx="8" cy="1044.4" r="8" fill="#fff"/>
-<g clip-path="url(#a)">
-<path d="m6.1883 1037.6a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#f00"/>
-<path transform="matrix(.86603 .5 -.5 .86603 0 0)" d="m527.3 893.68a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#ff4d00"/>
-<path transform="matrix(.5 .86603 -.86603 .5 0 0)" d="m906.63 508.49a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#f90"/>
-<path transform="rotate(90)" d="m1042.6-14.761a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#ffca00"/>
-<path transform="matrix(-.5 .86603 -.86603 -.5 0 0)" d="m898.63-535.87a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#ff0"/>
-<path transform="matrix(-.86603 .5 -.5 -.86603 0 0)" d="m513.44-915.21a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#9fff00"/>
-<path transform="scale(-1)" d="m-9.8118-1051.1a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#0f0"/>
-<path transform="matrix(-.86603 -.5 .5 -.86603 0 0)" d="m-530.92-907.21a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#0fa"/>
-<path transform="matrix(-.5 -.86603 .86603 -.5 0 0)" d="m-910.26-522.01a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#00f"/>
-<path transform="rotate(-90)" d="m-1046.2 1.2385a7 7 0 0 1 3.6235 1e-7l-1.8118 6.7615z" fill="#9000ff"/>
-<path transform="matrix(.5 -.86603 .86603 .5 0 0)" d="m-902.26 522.35a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#f0e"/>
-<path transform="matrix(.86603 -.5 .5 .86603 0 0)" d="m-517.06 901.68a7 7 0 0 1 3.6235 0l-1.8117 6.7615z" fill="#ff009a"/>
-</g>
-</g>
-</svg>
diff --git a/editor/icons/icon_connect.svg b/editor/icons/icon_connect.svg
index 43ec84646c..97859370b7 100644
--- a/editor/icons/icon_connect.svg
+++ b/editor/icons/icon_connect.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<circle cx="4" cy="1048.4" r="2" fill="#e0e0e0"/>
-<path d="m4 1043.4a5 5 0 0 1 5 5" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
-<path d="m4 1039.4a9 9 0 0 1 9 9" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m4 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1c4.4301 0 8 3.5699 8 8a1 1 0 0 0 1 1 1 1 0 0 0 1 -1c0-5.511-4.489-10-10-10zm0 4a1 1 0 0 0 -1 1 1 1 0 0 0 1 1c2.221 0 4 1.779 4 4a1 1 0 0 0 1 1 1 1 0 0 0 1 -1c0-3.3018-2.6981-6-6-6zm0 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_create_new_scene_from.svg b/editor/icons/icon_create_new_scene_from.svg
index b41fd38e70..1b1771dae0 100644
--- a/editor/icons/icon_create_new_scene_from.svg
+++ b/editor/icons/icon_create_new_scene_from.svg
@@ -1,7 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m1 7v6c0 1.1046 0.89543 2 2 2h7v-1h-2v-4h2v-2h4v2h1v-3z" fill="#e0e0e0"/>
-<path d="m0.71129 1040.4 0.28871 1.9791l2.2438-0.3273-0.81826-1.9018-1.7143 0.25zm3.6933-0.5387 0.81826 1.9018 1.9791-0.2887-0.81826-1.9018-1.9791 0.2887zm3.9581-0.5775 0.81826 1.9018 1.9791-0.2887-0.81826-1.9018-1.9791 0.2887zm3.9581-0.5774 0.81826 1.9018 1.7143-0.25-0.28871-1.9791-2.2438 0.3273z" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m14.564 2l-2.2441 0.32812 0.81836 1.9004 1.7148-0.25-0.28906-1.9785zm-4.2227 0.61523l-1.9785 0.28906 0.81836 1.9023 1.9785-0.28906-0.81836-1.9023zm-3.959 0.57812l-1.9785 0.28906 0.81836 1.9023 1.9785-0.28906-0.81836-1.9023zm-3.957 0.57812l-1.7148 0.25 0.28906 1.9785 2.2441-0.32812-0.81836-1.9004zm-1.4258 3.2285v6c0 1.1046 0.89543 2 2 2h7v-1h-2v-4h2v-2h4v2h1v-3h-14z" fill="#e0e0e0"/>
<circle cx="-14" cy="1047.4" r="0" fill="#e0e0e0"/>
<path d="m13 1049.4h2v-2h-2v-2h-2v2h-2v2h2v2h2z" fill="#84ffb1" fill-rule="evenodd"/>
</g>
diff --git a/editor/icons/icon_cube_map.svg b/editor/icons/icon_cube_map.svg
index 8afc2e42e9..d814998500 100644
--- a/editor/icons/icon_cube_map.svg
+++ b/editor/icons/icon_cube_map.svg
@@ -1,10 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<rect y="1042.4" width="4" height="4" fill="#84ffb1"/>
-<rect x="4" y="1042.4" width="4" height="4" fill="#ff8484"/>
-<rect x="8" y="1042.4" width="4" height="4" fill="#84ffb1"/>
-<rect x="12" y="1042.4" width="4" height="4" fill="#ff8484"/>
-<rect x="4" y="1038.4" width="4" height="4" fill="#84c2ff"/>
-<rect x="4" y="1046.4" width="4" height="4" fill="#84c2ff"/>
+<path transform="translate(0 1036.4)" d="m0 6v4h4v-4h-4zm8 0v4h4v-4h-4z" fill="#84ffb1"/>
+<path transform="translate(0 1036.4)" d="m4 6v4h4v-4h-4zm8 0v4h4v-4h-4z" fill="#ff8484"/>
+<path transform="translate(0 1036.4)" d="m4 2v4h4v-4h-4zm0 8v4h4v-4h-4z" fill="#84c2ff"/>
</g>
</svg>
diff --git a/editor/icons/icon_curve_close.svg b/editor/icons/icon_curve_close.svg
index 415c046fd3..561ef33cb2 100644
--- a/editor/icons/icon_curve_close.svg
+++ b/editor/icons/icon_curve_close.svg
@@ -1,11 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#e0e0e0"/>
-<circle cx="5" cy="1041.4" r="2" fill="#f5f5f5"/>
-<rect x="8" y="1044.4" width="2" height="2" fill="#84c2ff"/>
-<circle cx="5" cy="1049.4" r="2" fill="#f5f5f5"/>
-<circle cx="13" cy="1041.4" r="2" fill="#f5f5f5"/>
-<rect x="6" y="1046.4" width="2" height="2" fill="#84c2ff"/>
-<rect x="10" y="1042.4" width="2" height="2" fill="#84c2ff"/>
+<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm8 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#f5f5f5"/>
+<path transform="translate(0 1036.4)" d="m10 6v2h2v-2h-2zm0 2h-2v2h2v-2zm-2 2h-2v2h2v-2z" fill="#84c2ff"/>
</g>
</svg>
diff --git a/editor/icons/icon_curve_create.svg b/editor/icons/icon_curve_create.svg
index c26361bc9f..1181111a0c 100644
--- a/editor/icons/icon_curve_create.svg
+++ b/editor/icons/icon_curve_create.svg
@@ -1,10 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#e0e0e0"/>
-<circle cx="5" cy="1041.4" r="2" fill="#84ffb1"/>
-<circle cx="5" cy="1049.4" r="2" fill="#f5f5f5"/>
-<circle cx="13" cy="1041.4" r="2" fill="#f5f5f5"/>
-<rect x="8" y="1047.4" width="8" height="2" fill="#84ffb1"/>
-<rect transform="rotate(90)" x="1044.4" y="-13" width="8" height="2" fill="#84ffb1"/>
+<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm6 5v3h-3v2h3v3h2v-3h3v-2h-3v-3h-2z" fill="#84ffb1"/>
+<path transform="translate(0 1036.4)" d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#f5f5f5"/>
</g>
</svg>
diff --git a/editor/icons/icon_curve_curve.svg b/editor/icons/icon_curve_curve.svg
index 81c14ec063..51597d613a 100644
--- a/editor/icons/icon_curve_curve.svg
+++ b/editor/icons/icon_curve_curve.svg
@@ -1,9 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#e0e0e0"/>
-<circle cx="5" cy="1041.4" r="2" fill="#84c2ff"/>
-<circle cx="5" cy="1049.4" r="2" fill="#f5f5f5"/>
-<circle cx="13" cy="1041.4" r="2" fill="#f5f5f5"/>
-<path d="m1 1045.4 8-8" fill="#84c2ff" fill-rule="evenodd" stroke="#84c2ff" stroke-width="1px"/>
+<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m8.4688 0.4707l-2.6875 2.6875h-0.0019531a2 2 0 0 0 -0.7793 -0.1582 2 2 0 0 0 -2 2 2 2 0 0 0 0.16016 0.7793l-2.6914 2.6914 1.0625 1.0605 2.6895-2.6895a2 2 0 0 0 0.7793 0.1582 2 2 0 0 0 2 -2 2 2 0 0 0 -0.16016 -0.77734l2.6914-2.6914-1.0625-1.0605z" fill="#84c2ff"/>
+<path transform="translate(0 1036.4)" d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#f5f5f5"/>
</g>
</svg>
diff --git a/editor/icons/icon_curve_delete.svg b/editor/icons/icon_curve_delete.svg
index b24993839b..901a08e984 100644
--- a/editor/icons/icon_curve_delete.svg
+++ b/editor/icons/icon_curve_delete.svg
@@ -1,9 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#e0e0e0"/>
-<circle cx="5" cy="1041.4" r="2" fill="#ff8484"/>
-<circle cx="5" cy="1049.4" r="2" fill="#f5f5f5"/>
-<circle cx="13" cy="1041.4" r="2" fill="#f5f5f5"/>
-<path d="m8.4645 1046.2 2.1213 2.1213-2.1213 2.1213 1.4142 1.4142l2.1213-2.1213 2.1213 2.1213 1.4142-1.4142-2.1213-2.1213 2.1213-2.1213-1.4142-1.4142-2.1213 2.1213-2.1213-2.1213-1.4142 1.4142z" fill="#ff8484"/>
+<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/>
+<path d="m5 1039.4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm4.8789 5.4648-1.4141 1.4141 2.1211 2.1211-2.1211 2.1211 1.4141 1.4141l2.1211-2.1211 2.1211 2.1211 1.4141-1.4141-2.1211-2.1211 2.1211-2.1211-1.4141-1.4141-2.1211 2.1211z" fill="#ff8484"/>
+<path d="m13 1039.4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#f5f5f5"/>
</g>
</svg>
diff --git a/editor/icons/icon_curve_edit.svg b/editor/icons/icon_curve_edit.svg
index d9f89bf15d..8f09ca6793 100644
--- a/editor/icons/icon_curve_edit.svg
+++ b/editor/icons/icon_curve_edit.svg
@@ -1,9 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#e0e0e0"/>
-<circle cx="5" cy="1041.4" r="2" fill="#84c2ff"/>
-<circle cx="5" cy="1049.4" r="2" fill="#f5f5f5"/>
-<circle cx="13" cy="1041.4" r="2" fill="#f5f5f5"/>
-<path d="m16 1047.7-8-3.291 3.291 8 0.9471-2.8201 1.8836 1.8835 0.9418-0.9418-1.8836-1.8835z" fill="#84c2ff"/>
+<path d="m5 1049.4c-2-9-1-10 8-8" fill="none" stroke="#f5f5f5" stroke-opacity=".39216" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m5 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm3 5l3.291 8 0.94726-2.8203 1.8828 1.8828 0.94336-0.94141-1.8848-1.8828 2.8203-0.94726-8-3.291z" fill="#84c2ff"/>
+<path transform="translate(0 1036.4)" d="m13 3a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-8 8a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#f5f5f5"/>
</g>
</svg>
diff --git a/editor/icons/icon_debug.svg b/editor/icons/icon_debug.svg
index bf6e37f4b4..dfab5eb28b 100644
--- a/editor/icons/icon_debug.svg
+++ b/editor/icons/icon_debug.svg
@@ -1,14 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="scale(1,-1)" d="m10.828-1039.5a4 4 0 0 1 -2.8284 1.1716 4 4 0 0 1 -2.8284 -1.1716" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
-<ellipse cx="8" cy="1047.4" rx="3.6445" ry="1.6348" fill="none" stroke-width="0"/>
-<circle cx="8" cy="1047.4" r="4" fill="#e0e0e0" stroke-width="0"/>
-<path d="m5 1047.4h-3" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-width="2"/>
-<path d="m10 1047.4h4" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-width="2"/>
-<path d="m6 1045.4c-2 0-3-2-3-3" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-width="2"/>
-<path d="m10 1045.4c2 0 3-2 3-3" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-width="2"/>
-<path d="m6 1049.4c-1 0-2 1-3 2" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-width="2"/>
-<path d="m10 1049.4c1 0 2 1 3 2" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-width="2"/>
-<circle cx="8" cy="1043.4" r="2" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m8 1c-1.3257 0-2.5977 0.52744-3.5352 1.4648a1 1 0 0 0 0 1.4141 1 1 0 0 0 0.69141 0.29297 1 1 0 0 0 0.72266 -0.29297c0.56288-0.5628 1.3251-0.87891 2.1211-0.87891s1.5582 0.31611 2.1211 0.87891a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141c-0.93741-0.9374-2.2095-1.4648-3.5352-1.4648zm-5 3.9961a1 1 0 0 0 -1 1c0 0.8334 0.32654 1.6973 0.96875 2.5 0.33016 0.41272 0.7705 0.79575 1.3008 1.0723a4 4 0 0 0 -0.13672 0.43164h-2.1328a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h2.1309a4 4 0 0 0 0.17969 0.53711c-0.14177 0.089422-0.27868 0.1846-0.41016 0.2832-0.58533 0.439-1.1074 0.96875-1.6074 1.4688a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0c0.5-0.5 0.97791-0.9722 1.3926-1.2832 0.1693-0.12693 0.3098-0.20282 0.44336-0.26953a4 4 0 0 0 2.457 0.84961 4 4 0 0 0 2.459 -0.84766c0.13307 0.066645 0.27298 0.14126 0.44141 0.26758 0.41467 0.311 0.89258 0.7832 1.3926 1.2832a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141c-0.5-0.5-1.0221-1.0297-1.6074-1.4688-0.13076-0.098068-0.26727-0.19224-0.4082-0.28125a4 4 0 0 0 0.17578 -0.53906h2.1328a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-2.1309a4 4 0 0 0 -0.13477 -0.43359c0.52857-0.27637 0.96751-0.65858 1.2969-1.0703 0.64221-0.8027 0.96875-1.6666 0.96875-2.5a1 1 0 0 0 -1 -1 1 1 0 0 0 -1 1c0 0.1667-0.17346 0.8028-0.53125 1.25-0.25089 0.31365-0.54884 0.54907-0.93164 0.66602a4 4 0 0 0 -0.60352 -0.41211 2 2 0 0 0 0.066406 -0.5 2 2 0 0 0 -2 -2 2 2 0 0 0 -2 2 2 2 0 0 0 0.066406 0.50391 4 4 0 0 0 -0.60352 0.4082c-0.3828-0.11694-0.68075-0.35236-0.93164-0.66602-0.35779-0.4472-0.53125-1.0833-0.53125-1.25a1 1 0 0 0 -1 -1z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_debug_continue.svg b/editor/icons/icon_debug_continue.svg
index 49289d1b28..d38bde9ea6 100644
--- a/editor/icons/icon_debug_continue.svg
+++ b/editor/icons/icon_debug_continue.svg
@@ -1,9 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<rect x="5" y="1043.4" width="6" height="2" fill="#ff8484"/>
-<g transform="matrix(-.71429 0 0 .88889 2.4999 121.82)" fill="#ff8484">
-<path transform="matrix(0 1.4412 1.2943 0 1331.1 1030.7)" d="m8.1225-1036.6h-3.1225-3.1225l1.5612-2.7042 1.5612-2.7041 1.5612 2.7041z" fill="#ff8484"/>
-</g>
+<path transform="translate(0 1036.4)" d="m10 4v3h-5v2h5v3l2.5-2 2.5-2-2.5-2-2.5-2z" fill="#ff8484"/>
<circle cx="4" cy="1044.4" r="3" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_debug_next.svg b/editor/icons/icon_debug_next.svg
index 6251e174e7..e641fb9dbe 100644
--- a/editor/icons/icon_debug_next.svg
+++ b/editor/icons/icon_debug_next.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<rect transform="rotate(90)" x="1037.4" y="-5" width="10" height="2" fill="#ff8484"/>
-<g transform="matrix(0 -.57144 -.66666 0 695.91 1041.4)" fill="#ff8484">
-<path transform="matrix(0 1.4412 1.2943 0 1331.1 1030.7)" d="m8.1225-1036.6h-3.1225-3.1225l1.5612-2.7042 1.5612-2.7041 1.5612 2.7041z" fill="#ff8484"/>
-</g>
-<rect x="7" y="1037.4" width="8" height="2" fill="#e0e0e0"/>
-<rect x="9" y="1041.4" width="6" height="2" fill="#e0e0e0"/>
-<rect x="9" y="1045.4" width="6" height="2" fill="#e0e0e0"/>
-<rect x="7" y="1049.4" width="8" height="2" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m3 1v10h-2l1.5 2 1.5 2 1.5-2 1.5-2h-2v-10h-2z" fill="#ff8484"/>
+<path transform="translate(0 1036.4)" d="m7 1v2h8v-2h-8zm2 4v2h6v-2h-6zm0 4v2h6v-2h-6zm-2 4v2h8v-2h-8z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_debug_step.svg b/editor/icons/icon_debug_step.svg
index 3a98803fc3..0a1f878a78 100644
--- a/editor/icons/icon_debug_step.svg
+++ b/editor/icons/icon_debug_step.svg
@@ -1,13 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<rect transform="rotate(90)" x="1037.4" y="-3" width="10" height="2" fill="#ff8484"/>
-<g transform="matrix(-.57144 0 0 .66666 -2.0001 354.46)" fill="#ff8484">
-<path transform="matrix(0 1.4412 1.2943 0 1331.1 1030.7)" d="m8.1225-1036.6h-3.1225-3.1225l1.5612-2.7042 1.5612-2.7041 1.5612 2.7041z" fill="#ff8484"/>
-</g>
-<rect x="7" y="1037.4" width="8" height="2" fill="#e0e0e0"/>
-<rect x="9" y="1041.4" width="6" height="2" fill="#e0e0e0"/>
-<rect x="9" y="1045.4" width="6" height="2" fill="#e0e0e0"/>
-<rect x="7" y="1049.4" width="8" height="2" fill="#e0e0e0"/>
-<rect transform="rotate(90)" x="1045.4" y="-4" width="2" height="3" fill="#ff8484"/>
+<path transform="translate(0 1036.4)" d="m1 1v8 2h2 1v2l2-1.5 2-1.5-2-1.5-2-1.5v2h-1v-8h-2z" fill="#ff8484"/>
+<path transform="translate(0 1036.4)" d="m7 1v2h8v-2h-8zm2 4v2h6v-2h-6zm0 4v2h6v-2h-6zm-2 4v2h8v-2h-8z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_dependency_changed.svg b/editor/icons/icon_dependency_changed.svg
deleted file mode 100644
index 6d7787e769..0000000000
--- a/editor/icons/icon_dependency_changed.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-1 2h2v7h-2v-7zm0 8h2v2h-2v-2z" fill="#ff8484"/>
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-1 2h2v7h-2v-7zm0 8h2v2h-2v-2z" fill-opacity=".23529"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_dependency_changed_hl.svg b/editor/icons/icon_dependency_changed_hl.svg
deleted file mode 100644
index fa0f3919ea..0000000000
--- a/editor/icons/icon_dependency_changed_hl.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-1 2h2v7h-2v-7zm0 8h2v2h-2v-2z" fill="#ff8484"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_dependency_local_changed.svg b/editor/icons/icon_dependency_local_changed.svg
deleted file mode 100644
index 5fef88844a..0000000000
--- a/editor/icons/icon_dependency_local_changed.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -3 3.8672v0.13281h-2v-2h1a2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2 2 2 0 0 0 -2 2h-2a4 4 0 0 1 4 -4zm-1 9h2v2h-2v-2z" fill="#ffd684"/>
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -3 3.8672v0.13281h-2v-2h1a2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2 2 2 0 0 0 -2 2h-2a4 4 0 0 1 4 -4zm-1 9h2v2h-2v-2z" fill-opacity=".23529"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_dependency_local_changed_hl.svg b/editor/icons/icon_dependency_local_changed_hl.svg
deleted file mode 100644
index b9ab80fecb..0000000000
--- a/editor/icons/icon_dependency_local_changed_hl.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a4 4 0 0 1 4 4 4 4 0 0 1 -3 3.8672v0.13281h-2v-2h1a2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2 2 2 0 0 0 -2 2h-2a4 4 0 0 1 4 -4zm-1 9h2v2h-2v-2z" fill="#ffd684"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_dependency_ok.svg b/editor/icons/icon_dependency_ok.svg
deleted file mode 100644
index 91cc398029..0000000000
--- a/editor/icons/icon_dependency_ok.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm3.1816 3.9297l1.4141 1.4141-4.2422 4.2422-0.70703 0.70703-0.70703 0.70703-3.5352-3.5352 1.4141-1.4141 2.1211 2.1211 4.2422-4.2422z" fill="#84ffb1"/>
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm3.1816 3.9297l1.4141 1.4141-4.2422 4.2422-0.70703 0.70703-0.70703 0.70703-3.5352-3.5352 1.4141-1.4141 2.1211 2.1211 4.2422-4.2422z" fill-opacity=".23529"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_dependency_ok_hl.svg b/editor/icons/icon_dependency_ok_hl.svg
deleted file mode 100644
index 7c3f058dc4..0000000000
--- a/editor/icons/icon_dependency_ok_hl.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm3.1816 3.9297l1.4141 1.4141-4.2422 4.2422-0.70703 0.70703-0.70703 0.70703-3.5352-3.5352 1.4141-1.4141 2.1211 2.1211 4.2422-4.2422z" fill="#84ffb1"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_distraction_free.svg b/editor/icons/icon_distraction_free.svg
index eaf8061f0a..3b59dd1650 100644
--- a/editor/icons/icon_distraction_free.svg
+++ b/editor/icons/icon_distraction_free.svg
@@ -1,9 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m3.7578 2.3438l-1.4141 1.4141 2.9492 2.9492 1.4141-1.4141-2.9492-2.9492zm8.4844 0l-2.9492 2.9492 1.4141 1.4141 2.9492-2.9492-1.4141-1.4141zm-6.9492 6.9492l-2.9492 2.9492 1.4141 1.4141 2.9492-2.9492-1.4141-1.4141zm5.4141 0l-1.4141 1.4141 2.9492 2.9492 1.4141-1.4141-2.9492-2.9492z"/>
-<path d="m1 1051.4v-5l5 5z" fill-rule="evenodd"/>
-<path d="m15 1051.4v-5l-5 5z" fill-rule="evenodd"/>
-<path d="m15 1037.4v5l-5-5z" fill-rule="evenodd"/>
-<path d="m1 1037.4v5l5-5z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v5l1.793-1.793 2.5 2.5 1.4141-1.4141-2.5-2.5 1.793-1.793h-5zm9 0l1.793 1.793-2.5 2.5 1.4141 1.4141 2.5-2.5 1.793 1.793v-5h-5zm-4.707 8.293l-2.5 2.5-1.793-1.793v5h5l-1.793-1.793 2.5-2.5-1.4141-1.4141zm5.4141 0l-1.4141 1.4141 2.5 2.5-1.793 1.793h5v-5l-1.793 1.793-2.5-2.5z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_editor_3d_handle.svg b/editor/icons/icon_editor_3d_handle.svg
index 189baf3dad..cd28f8d22e 100644
--- a/editor/icons/icon_editor_3d_handle.svg
+++ b/editor/icons/icon_editor_3d_handle.svg
@@ -1,5 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
+<circle cx="8" cy="1044.4" r="8" fill-opacity=".29412"/>
<circle cx="8" cy="1044.4" r="7" fill="#fff"/>
<circle cx="8" cy="1044.4" r="5" fill="#ff8484"/>
</g>
diff --git a/editor/icons/icon_editor_control_anchor.svg b/editor/icons/icon_editor_control_anchor.svg
index eeee2c182f..5e75f9bdf5 100644
--- a/editor/icons/icon_editor_control_anchor.svg
+++ b/editor/icons/icon_editor_control_anchor.svg
@@ -1,8 +1,8 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8.832 6.1445a4 4 0 0 1 -2.6914 2.6855l9.8594 7.1699-7.168-9.8555z" fill="#a5efac" fill-rule="evenodd"/>
+<path transform="translate(0 1036.4)" d="m5 0a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 1.0566 -0.11914l9.9434 6.1191-6.1172-9.9395a5 5 0 0 0 0.11719 -1.0605 5 5 0 0 0 -5 -5z" fill-opacity=".39216" style="paint-order:fill markers stroke"/>
+<path transform="translate(0 1036.4)" d="m5 1a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 1.1406 -0.16992l9.8594 7.1699-7.168-9.8555a4 4 0 0 0 0.16797 -1.1445 4 4 0 0 0 -4 -4z" fill="#a5efac" fill-rule="evenodd"/>
<ellipse cx="3" cy="1039.4" r="2" fill="#6e6e6e"/>
-<ellipse cx="4" cy="1040.4" rx="4" ry="4" fill="#a5efac" style="paint-order:fill markers stroke"/>
<circle cx="5" cy="1041.4" r="0" fill="#a5efac" style="paint-order:fill markers stroke"/>
</g>
</svg>
diff --git a/editor/icons/icon_editor_handle.svg b/editor/icons/icon_editor_handle.svg
index 7e58aaa803..05f3e2f2cc 100644
--- a/editor/icons/icon_editor_handle.svg
+++ b/editor/icons/icon_editor_handle.svg
@@ -1,6 +1,7 @@
-<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1044.4)">
-<ellipse cx="4" cy="1048.4" rx="4" ry="4" fill="#fff"/>
-<ellipse cx="4" cy="1048.4" rx="2.8572" ry="2.8571" fill="#ff8484"/>
+<svg width="10" height="10" version="1.1" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1042.4)">
+<ellipse cx="5" cy="1047.4" rx="5" ry="5" fill-opacity=".29412"/>
+<ellipse cx="5" cy="1047.4" rx="4" ry="4" fill="#fff"/>
+<ellipse cx="5" cy="1047.4" rx="3" ry="3" fill="#ff8484"/>
</g>
</svg>
diff --git a/editor/icons/icon_editor_pivot.svg b/editor/icons/icon_editor_pivot.svg
index d59d2d804d..8b8d07c7de 100644
--- a/editor/icons/icon_editor_pivot.svg
+++ b/editor/icons/icon_editor_pivot.svg
@@ -1,6 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
<path transform="translate(0 1036.4)" d="m6 0v6h-6v4h6v6h4v-6h6v-4h-6v-6h-4zm1 7h2v2h-2v-2z" fill="#fff" fill-opacity=".70588"/>
-<path transform="translate(0 1036.4)" d="m7 1v5h2v-5h-2zm-6 6v2h5v-2h-5zm9 0v2h5v-2h-5zm-3 3v5h2v-5h-2z" fill="#ff8484" fill-opacity=".58824"/>
+<path transform="translate(0 1036.4)" d="m7 1v5h2v-5h-2zm-6 6v2h5v-2h-5zm9 0v2h5v-2h-5zm-3 3v5h2v-5h-2z" fill="#ff8484"/>
</g>
</svg>
diff --git a/editor/icons/icon_error.svg b/editor/icons/icon_error.svg
index 771a418cfa..846bd88cb1 100644
--- a/editor/icons/icon_error.svg
+++ b/editor/icons/icon_error.svg
@@ -1,5 +1,5 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)">
-<rect x="2.2204e-16" y="1044.4" width="8" height="8" ry="4" fill="#ff8484"/>
+<rect x="2.2204e-16" y="1044.4" width="8" height="8" ry="4" fill="#ff5d5d"/>
</g>
</svg>
diff --git a/editor/icons/icon_error_sign.svg b/editor/icons/icon_error_sign.svg
index a2d714c31a..bde0494a93 100644
--- a/editor/icons/icon_error_sign.svg
+++ b/editor/icons/icon_error_sign.svg
@@ -1,7 +1,6 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1020.4)">
-<path d="m10 1048.4h12l6-6v-12l-6-6h-12l-6 6v12z" fill="#ff8484" fill-rule="evenodd"/>
-<rect x="14" y="1028.4" width="4" height="9" fill="#fff"/>
-<rect x="14" y="1040.4" width="4" height="4" fill="#fff"/>
+<path d="m10 1048.4h12l6-6v-12l-6-6h-12l-6 6v12z" fill="#ff5d5d" fill-rule="evenodd"/>
+<path transform="translate(0 1020.4)" d="m14 8l1 10h2l1-10h-4zm2 12a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#fff"/>
</g>
</svg>
diff --git a/editor/icons/icon_event_player.svg b/editor/icons/icon_event_player.svg
deleted file mode 100644
index 06630c349a..0000000000
--- a/editor/icons/icon_event_player.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m1 1v14h14v-14h-14zm2 2h10v10h-10v-10z"/>
-<path transform="translate(0 1036.4)" d="m5 3v6h2v-6h-2zm4 0v6h2v-6h-2z"/>
-<rect x="5" y="1039.4" width="1" height="10"/>
-<rect x="9" y="1039.4" width="1" height="10"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_file_broken.svg b/editor/icons/icon_file_broken.svg
index f352eeb001..7b05ab625e 100644
--- a/editor/icons/icon_file_broken.svg
+++ b/editor/icons/icon_file_broken.svg
@@ -1,7 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 1036.4)" d="m2 1v8.5859l1.293-1.293a1.0001 1.0001 0 0 1 0.69141 -0.29102 1.0001 1.0001 0 0 1 0.72266 0.29102l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 1.4141 0l2.293 2.293 1-1v-3.5859h-5v-5h-7zm8 0v4h4l-4-4zm-6 9.4141l-2 2v2.5859h12v-2.5859l-0.29297 0.29297a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293-2.293 2.293a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293z" fill="#ff8484"/>
+<path transform="translate(0 1036.4)" d="m2 1v8.5859l1.293-1.293a1.0001 1.0001 0 0 1 0.69141 -0.29102 1.0001 1.0001 0 0 1 0.72266 0.29102l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 1.4141 0l2.293 2.293 1-1v-3.5859h-5v-5h-7zm8 0v4h4l-4-4zm-6 9.4141l-2 2v2.5859h12v-2.5859l-0.29297 0.29297a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293-2.293 2.293a1.0001 1.0001 0 0 1 -1.4141 0l-2.293-2.293z" fill="#ff5d5d"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_broken_big_thumb.svg b/editor/icons/icon_file_broken_big_thumb.svg
index 167bb1bb5f..5e8fa607c1 100644
--- a/editor/icons/icon_file_broken_big_thumb.svg
+++ b/editor/icons/icon_file_broken_big_thumb.svg
@@ -1,7 +1,7 @@
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -988.36)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 988.36)" d="m14 5c-2.1987 0-4 1.8013-4 4v26.172a1.0001 1.0001 0 0 0 1.707 0.70703l3.293-3.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l8-8a1.0001 1.0001 0 0 0 0.29297 -0.70703v-11.172a1.0001 1.0001 0 0 0 -0.29297 -0.70703l-16-16a1.0001 1.0001 0 0 0 -0.70703 -0.29297h-23zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v9.7578l-7 7-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-2.293 2.293v-23.758c0-1.1253 0.87473-2 2-2zm0.98438 28.83a1.0001 1.0001 0 0 0 -0.69141 0.29297l-4 4a1.0001 1.0001 0 0 0 -0.29297 0.70703v14.17c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-16.17a1.0001 1.0001 0 0 0 -1.707 -0.70703l-7.293 7.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -0.72266 -0.29297zm0.015625 2.4141l9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l6.293-6.293v13.756c0 1.1253-0.87473 2-2 2h-36c-1.1253 0-2-0.87473-2-2v-13.756l3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 988.36)" d="m14 5c-2.1987 0-4 1.8013-4 4v26.172a1.0001 1.0001 0 0 0 1.707 0.70703l3.293-3.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l8-8a1.0001 1.0001 0 0 0 0.29297 -0.70703v-11.172a1.0001 1.0001 0 0 0 -0.29297 -0.70703l-16-16a1.0001 1.0001 0 0 0 -0.70703 -0.29297h-23zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v9.7578l-7 7-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-2.293 2.293v-23.758c0-1.1253 0.87473-2 2-2zm0.98438 28.83a1.0001 1.0001 0 0 0 -0.69141 0.29297l-4 4a1.0001 1.0001 0 0 0 -0.29297 0.70703v14.17c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-16.17a1.0001 1.0001 0 0 0 -1.707 -0.70703l-7.293 7.293-9.293-9.293a1.0001 1.0001 0 0 0 -1.4141 0l-9.293 9.293-9.293-9.293a1.0001 1.0001 0 0 0 -0.72266 -0.29297zm0.015625 2.4141l9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l9.293-9.293 9.293 9.293a1.0001 1.0001 0 0 0 1.4141 0l6.293-6.293v13.756c0 1.1253-0.87473 2-2 2h-36c-1.1253 0-2-0.87473-2-2v-13.756l3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_dead.svg b/editor/icons/icon_file_dead.svg
index e0aee6fd90..ec13e7087f 100644
--- a/editor/icons/icon_file_dead.svg
+++ b/editor/icons/icon_file_dead.svg
@@ -1,7 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 1036.4)" d="m2 1v14h12v-9h-5v-5zm8 0v4h4zm-6.0078 6c0.1353-0.0020779 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091882 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm6 0c0.1353-0.00208 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091883 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm-6.4922 4h9c0.277 0 0.5 0.223 0.5 0.5s-0.223 0.5-0.5 0.5h-4.5c0 1.1046-0.89543 2-2 2s-2-0.8954-2-2h-0.5c-0.277 0-0.5-0.223-0.5-0.5s0.223-0.5 0.5-0.5zm1.5 1c-1.9e-5 0.5523 0.44771 1 1 1s1-0.4477 1-1z" fill="#ff8484"/>
+<path transform="translate(0 1036.4)" d="m2 1v14h12v-9h-5v-5zm8 0v4h4zm-6.0078 6c0.1353-0.0020779 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091882 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm6 0c0.1353-0.00208 0.26567 0.050774 0.36133 0.14648l0.64648 0.64648 0.64648-0.64648c0.09183-0.091883 0.21582-0.14442 0.3457-0.14648 0.1353-0.00208 0.26567 0.050774 0.36133 0.14648 0.19521 0.19525 0.19521 0.51178 0 0.70703l-0.64648 0.64648 0.64648 0.64648c0.19521 0.19525 0.19521 0.51178 0 0.70703-0.19525 0.19521-0.51178 0.19521-0.70703 0l-0.64648-0.64648-0.64648 0.64648c-0.19525 0.19521-0.51178 0.19521-0.70703 0-0.19521-0.19525-0.19521-0.51178 0-0.70703l0.64648-0.64648-0.64648-0.64648c-0.19521-0.19525-0.19521-0.51178 0-0.70703 0.09183-0.091882 0.21582-0.14442 0.3457-0.14648zm-6.4922 4h9c0.277 0 0.5 0.223 0.5 0.5s-0.223 0.5-0.5 0.5h-4.5c0 1.1046-0.89543 2-2 2s-2-0.8954-2-2h-0.5c-0.277 0-0.5-0.223-0.5-0.5s0.223-0.5 0.5-0.5zm1.5 1c-1.9e-5 0.5523 0.44771 1 1 1s1-0.4477 1-1z" fill="#ff5d5d"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_dead_big_thumb.svg b/editor/icons/icon_file_dead_big_thumb.svg
index c8aab912f1..2ac8d1e9df 100644
--- a/editor/icons/icon_file_dead_big_thumb.svg
+++ b/editor/icons/icon_file_dead_big_thumb.svg
@@ -1,7 +1,7 @@
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -988.36)">
<g transform="translate(0 -1.6949e-5)">
-<path d="m14 993.36c-2.1987 0-4 1.8013-4 4v46c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-33h-0.0078c2e-3 -0.2483-0.0793-0.501-0.28516-0.707l-16-16c-0.18788-0.18693-0.44247-0.28939-0.70704-0.28907v-4e-3zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v32c0 1.1253-0.87472 2-2 2h-36c-1.1253 0-2-0.8747-2-2v-46c0-1.1253 0.87472-2 2-2zm2.9512 22.002a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm23 0a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm-18.951 13.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h3v3c0 2.7527 2.2473 5 5 5s5-2.2473 5-5v-3h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm5 2h6v3c0 1.6793-1.3207 3-3 3s-3-1.3207-3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path d="m14 993.36c-2.1987 0-4 1.8013-4 4v46c0 2.1987 1.8013 4 4 4h36c2.1987 0 4-1.8013 4-4v-33h-0.0078c2e-3 -0.2483-0.0793-0.501-0.28516-0.707l-16-16c-0.18788-0.18693-0.44247-0.28939-0.70704-0.28907v-4e-3zm0 2h22v12c0 2.1987 1.8013 4 4 4h12v32c0 1.1253-0.87472 2-2 2h-36c-1.1253 0-2-0.8747-2-2v-46c0-1.1253 0.87472-2 2-2zm2.9512 22.002a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm23 0a1 1 0 0 0 -0.60938 0.2461 1 1 0 0 0 -0.09375 1.4121l2.9238 3.3398-2.9238 3.3418a1 1 0 0 0 0.09375 1.4121 1 1 0 0 0 1.4102 -0.094l2.748-3.1407 2.748 3.1407a1 1 0 0 0 1.4102 0.094 1 1 0 0 0 0.09375 -1.4121l-2.9238-3.3418 2.9238-3.3398a1 1 0 0 0 -0.09375 -1.4121 1 1 0 0 0 -0.63867 -0.2461 1 1 0 0 0 -0.77148 0.3398l-2.748 3.1406-2.748-3.1406a1 1 0 0 0 -0.80078 -0.3398zm-18.951 13.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h3v3c0 2.7527 2.2473 5 5 5s5-2.2473 5-5v-3h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm5 2h6v3c0 1.6793-1.3207 3-3 3s-3-1.3207-3-3z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_dead_medium_thumb.svg b/editor/icons/icon_file_dead_medium_thumb.svg
index 60a456a600..010019ae03 100644
--- a/editor/icons/icon_file_dead_medium_thumb.svg
+++ b/editor/icons/icon_file_dead_medium_thumb.svg
@@ -1,7 +1,7 @@
<svg width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1020.4)">
<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 1020.4)" d="m5 1c-1.6447 0-3 1.3553-3 3v24c0 1.6447 1.3553 3 3 3h22c1.6447 0 3-1.3553 3-3v-16.809c-5.1e-5 -0.2652-0.10543-0.51952-0.29297-0.70703l-9.1816-9.1895c-0.18719-0.18825-0.44155-0.29435-0.70703-0.29492h-14.818zm0 2h14v6c0 1.6447 1.3553 3 3 3h6v16c0 0.5713-0.42868 1-1 1h-22c-0.57133 0-1-0.4287-1-1v-24c0-0.5713 0.42867-1 1-1zm1.9863 11.002a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm14 0a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm-13.986 7.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h1a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2 -3.4648h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-18zm3 2h4a2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff8484" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1020.4)" d="m5 1c-1.6447 0-3 1.3553-3 3v24c0 1.6447 1.3553 3 3 3h22c1.6447 0 3-1.3553 3-3v-16.809c-5.1e-5 -0.2652-0.10543-0.51952-0.29297-0.70703l-9.1816-9.1895c-0.18719-0.18825-0.44155-0.29435-0.70703-0.29492h-14.818zm0 2h14v6c0 1.6447 1.3553 3 3 3h6v16c0 0.5713-0.42868 1-1 1h-22c-0.57133 0-1-0.4287-1-1v-24c0-0.5713 0.42867-1 1-1zm1.9863 11.002a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm14 0a1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l1.293 1.293-1.293 1.293a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l1.293-1.293 1.293 1.293a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-1.293-1.293 1.293-1.293a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-1.293 1.293-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102zm-13.986 7.998a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h1a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2 -3.4648h9a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-18zm3 2h4a2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#ff5d5d" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</g>
</svg>
diff --git a/editor/icons/icon_file_server.svg b/editor/icons/icon_file_server.svg
deleted file mode 100644
index 02bc363c19..0000000000
--- a/editor/icons/icon_file_server.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#c5c5c5">
-<path transform="translate(0 1036.4)" d="m1 8v3h14v-3h-14zm1 1h1v1h-1v-1zm2 0h1v1h-1v-1zm-3 3v3h14v-3h-14zm1 1h1v1h-1v-1zm2 0h1v1h-1v-1z"/>
-<rect x="5" y="1038.4" width="6" height="4"/>
-<rect x="5" y="1037.4" width="3" height="1"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_file_server_active.svg b/editor/icons/icon_file_server_active.svg
deleted file mode 100644
index d491df2009..0000000000
--- a/editor/icons/icon_file_server_active.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#84ffb1">
-<path transform="translate(0 1036.4)" d="m1 8v3h14v-3h-14zm1 1h1v1h-1v-1zm2 0h1v1h-1v-1zm-3 3v3h14v-3h-14zm1 1h1v1h-1v-1zm2 0h1v1h-1v-1z"/>
-<rect x="5" y="1038.4" width="6" height="4"/>
-<rect x="5" y="1037.4" width="3" height="1"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_gizmo_camera.svg b/editor/icons/icon_gizmo_camera.svg
index f6e5f885e7..cb80c16598 100644
--- a/editor/icons/icon_gizmo_camera.svg
+++ b/editor/icons/icon_gizmo_camera.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -924.36)">
+<path transform="translate(0 924.36)" d="m76 16a28 28 0 0 0 -26.631 19.4 28 28 0 0 0 -13.369 -3.4004 28 28 0 0 0 -28 28 28 28 0 0 0 16 25.26v14.74c0 6.648 5.352 12 12 12h48c6.648 0 12-5.352 12-12l24 16v-64l-24 16v-4.4434a28 28 0 0 0 8 -19.557 28 28 0 0 0 -28 -28z" fill-opacity=".29412" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2"/>
<path d="m76 944.36a24 24 0 0 0 -23.906 22.219 24 24 0 0 0 -16.094 -6.2192 24 24 0 0 0 -24 24 24 24 0 0 0 16 22.594v17.406c0 4.432 3.5679 8 8 8h48c4.4321 0 8-3.568 8-8v-8l24 16v-48l-24 16v-14.156a24 24 0 0 0 8 -17.844 24 24 0 0 0 -24 -24z" fill="#f7f5cf"/>
</g>
</svg>
diff --git a/editor/icons/icon_gizmo_directional_light.svg b/editor/icons/icon_gizmo_directional_light.svg
index f7fa732501..1b125b44de 100644
--- a/editor/icons/icon_gizmo_directional_light.svg
+++ b/editor/icons/icon_gizmo_directional_light.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -924.36)">
+<path transform="translate(0 924.36)" d="m64 4c-4.432 0-8 3.568-8 8v16c0 4.432 3.568 8 8 8s8-3.568 8-8v-16c0-4.432-3.568-8-8-8zm-36.77 15.223c-2.045 0-4.0893 0.78461-5.6562 2.3516-3.1339 3.1339-3.1339 8.1786 0 11.312l11.312 11.314c3.1339 3.1339 8.1806 3.1339 11.314 0s3.1339-8.1806 0-11.314l-11.314-11.312c-1.5669-1.5669-3.6113-2.3516-5.6562-2.3516zm73.539 0c-2.045 0-4.0893 0.78461-5.6562 2.3516l-11.314 11.312c-3.1339 3.1339-3.1339 8.1806 0 11.314s8.1806 3.1339 11.314 0l11.312-11.314c3.1339-3.1339 3.1339-8.1786 0-11.312-1.567-1.5669-3.6113-2.3516-5.6562-2.3516zm-36.77 20.777a24 24 0 0 0 -24 24 24 24 0 0 0 24 24 24 24 0 0 0 24 -24 24 24 0 0 0 -24 -24zm-52 16c-4.432 0-8 3.568-8 8s3.568 8 8 8h16c4.432 0 8-3.568 8-8s-3.568-8-8-8h-16zm88 0c-4.432 0-8 3.568-8 8s3.568 8 8 8h16c4.432 0 8-3.568 8-8s-3.568-8-8-8h-16zm-61.455 25.449c-2.045 0-4.0913 0.78266-5.6582 2.3496l-11.312 11.314c-3.1339 3.1339-3.1339 8.1786 0 11.312 3.1339 3.1339 8.1786 3.1339 11.312 0l11.314-11.312c3.1339-3.1339 3.1339-8.1806 0-11.314-1.5669-1.5669-3.6113-2.3496-5.6562-2.3496zm50.91 0c-2.045 0-4.0893 0.78266-5.6562 2.3496-3.1339 3.1339-3.1339 8.1806 0 11.314l11.314 11.312c3.1339 3.1339 8.1786 3.1339 11.312 0s3.1339-8.1786 0-11.312l-11.312-11.314c-1.5669-1.5669-3.6132-2.3496-5.6582-2.3496zm-25.455 10.551c-4.432 0-8 3.568-8 8v16c0 4.432 3.568 8 8 8s8-3.568 8-8v-16c0-4.432-3.568-8-8-8z" fill-opacity=".29412" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2"/>
<path transform="translate(0 924.36)" d="m64 8c-2.216 0-4 1.784-4 4v16c0 2.216 1.784 4 4 4s4-1.784 4-4v-16c0-2.216-1.784-4-4-4zm-36.77 15.227c-1.0225 0-2.0447 0.39231-2.8281 1.1758-1.5669 1.5669-1.5669 4.0893 0 5.6562l11.312 11.314c1.5669 1.5669 4.0913 1.5669 5.6582 0s1.5669-4.0913 0-5.6582l-11.314-11.312c-0.78348-0.78348-1.8056-1.1758-2.8281-1.1758zm73.539 0c-1.0225 0-2.0446 0.39231-2.8281 1.1758l-11.314 11.312c-1.5669 1.5669-1.5669 4.0913 0 5.6582s4.0913 1.5669 5.6582 0l11.313-11.314c1.5669-1.5669 1.5669-4.0893 0-5.6562-0.78348-0.78348-1.8056-1.1758-2.8281-1.1758zm-36.77 20.773c-11.046 1e-5 -20 8.9543-20 20 7e-6 11.046 8.9543 20 20 20s20-8.9543 20-20c-8e-6 -11.046-8.9543-20-20-20zm-52 16c-2.216 0-4 1.784-4 4s1.784 4 4 4h16c2.216 0 4-1.784 4-4s-1.784-4-4-4h-16zm88 0c-2.216 0-4 1.784-4 4s1.784 4 4 4h16c2.216 0 4-1.784 4-4s-1.784-4-4-4h-16zm-61.455 25.453c-1.0225 0-2.0466 0.39035-2.8301 1.1738l-11.312 11.314c-1.5669 1.5669-1.5669 4.0893 0 5.6563 1.5669 1.5669 4.0893 1.5669 5.6562 0l11.314-11.313c1.5669-1.5669 1.5669-4.0913 0-5.6582-0.78347-0.78347-1.8056-1.1738-2.8281-1.1738zm50.91 0c-1.0225 0-2.0447 0.39035-2.8281 1.1738-1.5669 1.5669-1.5669 4.0913 0 5.6582l11.314 11.313c1.5669 1.5669 4.0893 1.5669 5.6563 0 1.5669-1.567 1.5669-4.0893 0-5.6563l-11.313-11.314c-0.78347-0.78347-1.8076-1.1738-2.8301-1.1738zm-25.455 10.547c-2.216 0-4 1.784-4 4v16c0 2.216 1.784 4 4 4s4-1.784 4-4v-16c0-2.216-1.784-4-4-4z" fill="#f7f5cf"/>
</g>
</svg>
diff --git a/editor/icons/icon_gizmo_g_i_probe.svg b/editor/icons/icon_gizmo_g_i_probe.svg
index 7d3adf4196..815da4d5c3 100644
--- a/editor/icons/icon_gizmo_g_i_probe.svg
+++ b/editor/icons/icon_gizmo_g_i_probe.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -924.36)">
-<path transform="translate(0 924.36)" d="m12 8a4.0004 4.0004 0 0 0 -4 4v104a4.0004 4.0004 0 0 0 4 4h60v-8h-56v-96h96v8h8v-12a4.0004 4.0004 0 0 0 -4 -4h-104zm27.715 17.951c-1.2324 0.086154-2.3996 0.76492-3.0664 1.9199l-0.14844 0.25781c-1.0669 1.848-0.43784 4.1948 1.4102 5.2617l10.648 6.1484c1.848 1.0669 4.1948 0.43784 5.2617-1.4102l0.14844-0.25781c1.0669-1.848 0.43784-4.1948-1.4102-5.2617l-10.648-6.1484c-0.693-0.4001-1.4558-0.56146-2.1953-0.50977zm52.285 2.0488a32 32 0 0 0 -32 32 32 32 0 0 0 16 27.668v8.332c0 4.432 3.568 8 8 8h16c4.432 0 8-3.568 8-8v-8.3223a32 32 0 0 0 16 -27.678 32 32 0 0 0 -32 -32zm0 12a20 20 0 0 1 20 20 20 20 0 0 1 -20 20 20 20 0 0 1 -20 -20 20 20 0 0 1 20 -20zm-60.148 16c-2.1339 0-3.8516 1.7177-3.8516 3.8516v0.29688c0 2.1339 1.7177 3.8516 3.8516 3.8516h12.297c2.1339 0 3.8516-1.7177 3.8516-3.8516v-0.29688c0-2.1339-1.7177-3.8516-3.8516-3.8516h-12.297zm18.902 23.951c-0.73947-0.051693-1.5023 0.10966-2.1953 0.50977l-10.648 6.1484c-1.848 1.0669-2.4771 3.4137-1.4102 5.2617l0.14844 0.25781c1.0669 1.848 3.4137 2.4771 5.2617 1.4102l10.648-6.1484c1.848-1.0669 2.4771-3.4137 1.4102-5.2617l-0.14844-0.25781c-0.66684-1.155-1.834-1.8338-3.0664-1.9199zm33.246 32.049v8h16v-8h-16z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#f7f5cf" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 924.36)" d="m12 4c-4.4183 9.5e-6 -8 3.5817-8 8v104c9.5e-6 4.4183 3.5817 8 8 8h64v-16h-56v-88h88v7.7676a36 36 0 0 0 -16 -3.7676 36 36 0 0 0 -36 36 36 36 0 0 0 16 29.9v8.0996c0 4.8544 3.4253 8.8788 8 9.8008v16.199h24v-16.199c4.5747-0.92197 8-4.9464 8-9.8008v-8.0879a36 36 0 0 0 16 -29.912 36 36 0 0 0 -19.523 -32h15.523v-16c-1e-5 -4.4183-3.5817-8-8-8h-104zm28.25 17.996c-2.8358-0.076599-5.6171 1.3651-7.1406 4.0039-2.216 3.8382-0.90854 8.7117 2.9297 10.928l10.393 6c3.8382 2.216 8.7117 0.91049 10.928-2.9277s0.91049-8.7117-2.9277-10.928l-10.393-6c-1.1994-0.6925-2.5-1.0414-3.7891-1.0762zm51.75 22.004a16 16 0 0 1 16 16 16 16 0 0 1 -16 16 16 16 0 0 1 -16 -16 16 16 0 0 1 16 -16zm-60 8c-4.432 0-8 3.568-8 8s3.568 8 8 8h12c4.432 0 8-3.568 8-8s-3.568-8-8-8h-12zm18.221 23.996c-1.289 0.034818-2.5896 0.38367-3.7891 1.0762l-10.393 6c-3.8382 2.216-5.1457 7.0895-2.9297 10.928s7.0915 5.1437 10.93 2.9277l10.393-6c3.8382-2.216 5.1437-7.0895 2.9277-10.928-1.5235-2.6388-4.3028-4.0805-7.1387-4.0039z" fill-opacity=".29412"/>
+<path transform="translate(0 924.36)" d="m12 8a4.0004 4.0004 0 0 0 -4 4v104a4.0004 4.0004 0 0 0 4 4h60v-8h-56v-96h96v8h8v-12a4.0004 4.0004 0 0 0 -4 -4zm27.715 17.951c-1.2324 0.08615-2.3996 0.76492-3.0664 1.9199l-0.14844 0.25781c-1.0669 1.848-0.43784 4.1948 1.4102 5.2617l10.648 6.1484c1.848 1.0669 4.1948 0.43784 5.2617-1.4102l0.14844-0.25781c1.0669-1.848 0.43784-4.1948-1.4102-5.2617l-10.648-6.1484c-0.693-0.4001-1.4558-0.56146-2.1953-0.50977zm52.285 2.0488a32 32 0 0 0 -32 32 32 32 0 0 0 16 27.668v8.332c0 4.432 3.568 8 8 8h16c4.432 0 8-3.568 8-8v-8.3223a32 32 0 0 0 16 -27.678 32 32 0 0 0 -32 -32zm0 12a20 20 0 0 1 20 20 20 20 0 0 1 -20 20 20 20 0 0 1 -20 -20 20 20 0 0 1 20 -20zm-60.148 16c-2.1339 0-3.8516 1.7177-3.8516 3.8516v0.29688c0 2.1339 1.7177 3.8516 3.8516 3.8516h12.297c2.1339 0 3.8516-1.7177 3.8516-3.8516v-0.29688c0-2.1339-1.7177-3.8516-3.8516-3.8516zm18.902 23.951c-0.73947-0.05169-1.5023 0.10966-2.1953 0.50977l-10.648 6.1484c-1.848 1.0669-2.4771 3.4137-1.4102 5.2617l0.14844 0.25781c1.0669 1.848 3.4137 2.4771 5.2617 1.4102l10.648-6.1484c1.848-1.0669 2.4771-3.4137 1.4102-5.2617l-0.14844-0.25781c-0.66684-1.155-1.834-1.8338-3.0664-1.9199zm33.246 32.049v8h16v-8z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#f7f5cf" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_gizmo_light.svg b/editor/icons/icon_gizmo_light.svg
index c411d13dc7..0db2749e91 100644
--- a/editor/icons/icon_gizmo_light.svg
+++ b/editor/icons/icon_gizmo_light.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -924.36)">
+<path transform="translate(0 924.36)" d="m64 2a44 44 0 0 0 -44 44 44 44 0 0 0 24 39.189v5.8105 5 3c0 5.0515 3.3756 9.2769 8 10.578v16.422h24v-16.422c4.6244-1.3012 8-5.5266 8-10.578v-3-5-5.8574a44 44 0 0 0 24 -39.143 44 44 0 0 0 -44 -44zm0 20a24 24 0 0 1 24 24 24 24 0 0 1 -24 24 24 24 0 0 1 -24 -24 24 24 0 0 1 24 -24z" fill-opacity=".29412" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="2.2"/>
<path transform="translate(0 924.36)" d="m64 6a40 40 0 0 0 -40 40 40 40 0 0 0 24 36.607v15.393a8 8 0 0 0 8 8h16a8 8 0 0 0 8 -8v-15.363a40 40 0 0 0 24 -36.637 40 40 0 0 0 -40 -40zm0 12a28 28 0 0 1 28 28 28 28 0 0 1 -28 28 28 28 0 0 1 -28 -28 28 28 0 0 1 28 -28zm-8 96v8h16v-8h-16z" fill="#f7f5cf"/>
</g>
</svg>
diff --git a/editor/icons/icon_gizmo_listener.svg b/editor/icons/icon_gizmo_listener.svg
index adb6aebaec..9b74469b67 100644
--- a/editor/icons/icon_gizmo_listener.svg
+++ b/editor/icons/icon_gizmo_listener.svg
@@ -1,6 +1,7 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -924.36)">
<g transform="matrix(2 0 0 2 -16 -1040.4)">
+<path d="m32 984.36c-12.126 2e-5 -22 9.8729-22 21.999 1.1e-4 1.1045 0.89548 1.9999 2 2h8c1.1045-1e-4 1.9999-0.8955 2-2 2.23e-4 -5.546 4.4536-9.999 10-9.999 5.5464 1e-5 9.9998 4.453 10 9.999 0 6.5873-1.6032 8.0251-3.8408 9.8897-1.0295 0.8579-2.3133 1.6111-3.7969 2.6826-0.72285 0.522-1.6649 1.2341-2.5488 2.3496-0.98288 1.2402-1.8135 2.99-1.8135 5.0781 0 2.3898-0.31658 3.686-0.61035 4.3194-0.29378 0.6333-0.4706 0.73-0.97754 1.0341-0.54947 0.3297-2.5162 0.6446-4.4121 0.6446-0.0065 3e-4 -0.01302 6e-4 -0.01953 1e-3h-3.9805c-1.1045 1e-4 -1.9999 0.8954-2 2v8c1.1e-4 1.1045 0.89548 1.9999 2 2h4c0.0072-3e-4 0.01432-5e-4 0.02148-1e-3 1.9052 1e-3 6.3098 0.1982 10.566-2.3555 4.0103-2.4061 6.6628-7.2724 7.1738-13.592 0.81224-0.548 2.3445-1.497 4.0791-2.9424 4.0025-3.3353 8.1592-9.5405 8.1592-19.108-9.5e-5 -12.126-9.8735-21.999-22-21.999zm31.807 4.002c-0.38259-0.0177-0.76221 0.0749-1.0938 0.2666l-6.9531 4.0156c-0.95754 0.55332-1.2843 1.7787-0.72949 2.7354 1.9364 3.3365 2.9609 7.1229 2.9717 10.98-0.0072 3.8597-1.0296 7.6487-2.9648 10.988-0.55452 0.9572-0.22681 2.1827 0.73144 2.7353l6.9453 4.0069c0.95656 0.5517 2.1792 0.2238 2.7314-0.7325 6.0717-10.516 6.0717-23.482 0-33.998-0.3406-0.59005-0.95812-0.96615-1.6387-0.99805z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill-opacity=".29412" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
<path transform="matrix(.5 0 0 .5 8 982.36)" d="m48 8a40 39.998 0 0 0 -40 39.998h16a24 23.999 0 0 1 24 -23.998 24 23.999 0 0 1 24 23.998c0 13.999-4.33 18.859-9.1211 22.852-2.3955 1.9962-5.0363 3.5302-7.8125 5.5352-1.3881 1.0024-2.8661 2.126-4.3047 3.9414-1.4385 1.8152-2.7617 4.6719-2.7617 7.6719 0 10.221-2.5383 12.59-5.1172 14.137-2.5789 1.5472-6.8828 1.8594-10.883 1.8594v0.00195h-8v16h8v-0.00195c4 0 11.696 0.31158 19.117-4.1406 7.0602-4.236 12.198-13.279 12.695-26 0.1835-0.1636 0.14883-0.15489 0.62109-0.49609 1.7238-1.245 5.083-3.2112 8.6875-6.2148 7.209-6.0072 14.879-17.145 14.879-35.145a40 39.998 0 0 0 -40 -39.998zm63.426 8l-13.906 8.0312a48 47.998 0 0 1 6.4844 23.967 48 47.998 0 0 1 -6.4688 23.984l13.891 8.0137a64 63.997 0 0 0 0 -63.996z" fill="#f7f5cf"/>
</g>
</g>
diff --git a/editor/icons/icon_gizmo_particles.svg b/editor/icons/icon_gizmo_particles.svg
index 05fc84619e..0989c1acad 100644
--- a/editor/icons/icon_gizmo_particles.svg
+++ b/editor/icons/icon_gizmo_particles.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -924.36)">
+<path d="m63.998 928.36c-18.429 5e-3 -34.029 13.88-38.557 32.926-12.4 3.0077-21.427 14.08-21.441 27.07v4e-3c0 15.417 12.583 28 28 28h64c15.417 0 28-12.583 28-28v-4e-3c-0.0152-13-9.0549-24.076-21.467-27.074-4.5265-19.033-20.112-32.903-38.529-32.922zm32.002 88c-6.58 0-12 5.42-12 12s5.42 12 12 12c6.58 0 12-5.42 12-12s-5.42-12-12-12zm-64 0c-6.58 0-12 5.42-12 12s5.42 12 12 12 12-5.42 12-12-5.42-12-12-12zm32 8c-6.58 0-12 5.42-12 12s5.42 12 12 12 12-5.42 12-12-5.42-12-12-12z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill-opacity=".29412" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
<path transform="translate(0 924.36)" d="m64 8a36 40 0 0 0 -35.311 32.256 24 24 0 0 0 -20.689 23.744 24 24 0 0 0 24 24h64a24 24 0 0 0 24 -24 24 24 0 0 0 -20.715 -23.746 36 40 0 0 0 -35.285 -32.254zm-32 88a8 8 0 0 0 -8 8 8 8 0 0 0 8 8 8 8 0 0 0 8 -8 8 8 0 0 0 -8 -8zm64 0a8 8 0 0 0 -8 8 8 8 0 0 0 8 8 8 8 0 0 0 8 -8 8 8 0 0 0 -8 -8zm-32 8a8 8 0 0 0 -8 8 8 8 0 0 0 8 8 8 8 0 0 0 8 -8 8 8 0 0 0 -8 -8z" fill="#f7f5cf"/>
</g>
</svg>
diff --git a/editor/icons/icon_gizmo_reflection_probe.svg b/editor/icons/icon_gizmo_reflection_probe.svg
index 6d80e73b8c..bcfd6e53f9 100644
--- a/editor/icons/icon_gizmo_reflection_probe.svg
+++ b/editor/icons/icon_gizmo_reflection_probe.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -924.36)">
-<path transform="translate(0 924.36)" d="m12 8a4.0004 4.0004 0 0 0 -4 4v24h8v-20h96v8h8v-12a4.0004 4.0004 0 0 0 -4 -4h-104zm76 28a4 4 0 0 0 -4 4 4 4 0 0 0 4 4h18.732l-42.957 50.119-44.947-44.947-5.6562 5.6582 48 48a4.0004 4.0004 0 0 0 5.8652 -0.22656l44.963-52.457v17.854a4 4 0 0 0 4 4 4 4 0 0 0 4 -4v-28a4.0004 4.0004 0 0 0 -4 -4h-28zm-80 52v28a4.0004 4.0004 0 0 0 4 4h104a4.0004 4.0004 0 0 0 4 -4v-28h-8v24h-96v-24h-8z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#f7f5cf" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<g transform="translate(0 -924.36)" shape-rendering="auto">
+<path d="m12 928.36c-4.3705 4.4e-4 -7.9996 3.6295-8 8v28h16v-20h88v8h16v-16c-4.4e-4 -4.3705-3.6295-7.9996-8-8zm76 28c-4.3709 0-8 3.6291-8 8s3.6291 8 8 8h10.035l-34.486 40.236-44.721-44.723-11.312 11.316 50.828 50.828c3.2536 3.2513 8.7374 3.0394 11.73-0.4531l37.926-44.244v7.0391c0 4.3709 3.6291 8 8 8s8-3.6291 8-8v-28c-4.4e-4 -4.3705-3.6295-7.9996-8-8zm-84 52v32c4.37e-4 4.3705 3.6295 7.9996 8 8h104c4.3705-4e-4 7.9996-3.6295 8-8v-32h-16v24h-88v-24z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill-opacity=".29412" image-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path d="m12 932.36c-2.209 2.2e-4 -3.9998 1.791-4 4v24h8v-20h96v8h8v-12c-2.2e-4 -2.209-1.791-3.9998-4-4zm76 28c-2.2091 0-4 1.7909-4 4s1.7909 4 4 4h18.732l-42.957 50.119-44.947-44.947-5.6562 5.6582 48 48c1.648 1.6468 4.3491 1.5425 5.8652-0.2266l44.963-52.457v17.854c0 2.2091 1.7909 4 4 4s4-1.7909 4-4v-28c-2.2e-4 -2.209-1.791-3.9998-4-4zm-80 52v28c2.209e-4 2.2091 1.791 3.9998 4 4h104c2.209-2e-4 3.9998-1.7909 4-4v-28h-8v24h-96v-24z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#f7f5cf" image-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_gizmo_spatial_sample_player.svg b/editor/icons/icon_gizmo_spatial_sample_player.svg
index 7dbb4744be..aa69248503 100644
--- a/editor/icons/icon_gizmo_spatial_sample_player.svg
+++ b/editor/icons/icon_gizmo_spatial_sample_player.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -924.36)">
-<path transform="translate(0 924.36)" d="m63.883 12.004c-1.0195 0.0295-1.9892 0.4473-2.7109 1.168l-30.828 30.83h-14.344c-2.209 2.21e-4 -3.9998 1.791-4 4v32c2.21e-4 2.209 1.791 3.9998 4 4h14.344l30.828 30.828c2.52 2.5182 6.8267 0.73442 6.8281-2.8281v-96.002c-0.0015-2.2541-1.8641-4.0619-4.1172-3.9961zm48.117 3.9961a4 4 0 0 0 -4 4v88a4 4 0 0 0 4 4 4 4 0 0 0 4 -4v-88a4 4 0 0 0 -4 -4zm-24 24a4 4 0 0 0 -4 4v40a4 4 0 0 0 4 4 4 4 0 0 0 4 -4v-40a4 4 0 0 0 -4 -4z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#f7f5cf" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<g transform="translate(0 -924.36)" fill-rule="evenodd" shape-rendering="auto">
+<path d="m63.766 932.37c-2.0369 0.0594-3.9779 0.89602-5.4199 2.3359l-2e-3 2e-3 -29.656 29.658h-12.688c-4.3705 4.4e-4 -7.9996 3.6295-8 8v32c4.372e-4 4.3705 3.6295 7.9995 8 8h12.688l29.656 29.656c2.4 2.3983 5.9795 2.8662 8.7168 1.7324 2.7373-1.1337 4.9381-3.9958 4.9395-7.3886v-96.004c-3e-3 -4.4555-3.779-8.1211-8.2324-7.9922zm48.234 3.9941c-4.3709 0-8 3.6291-8 8v88c0 4.3709 3.6291 8 8 8s8-3.6291 8-8v-88c0-4.3709-3.6291-8-8-8zm-24 24c-4.3709 0-8 3.6291-8 8v40c0 4.3709 3.6291 8 8 8s8-3.6291 8-8v-40c0-4.3709-3.6291-8-8-8z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill-opacity=".29412" image-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 924.36)" d="m63.883 12.004c-1.0195 0.0295-1.9892 0.4473-2.7109 1.168l-30.828 30.83h-14.344c-2.209 2.21e-4 -3.9998 1.791-4 4v32c2.21e-4 2.209 1.791 3.9998 4 4h14.344l30.828 30.828c2.52 2.5182 6.8267 0.73442 6.8281-2.8281v-96.002c-0.0015-2.2541-1.8641-4.0619-4.1172-3.9961zm48.117 3.9961a4 4 0 0 0 -4 4v88a4 4 0 0 0 4 4 4 4 0 0 0 4 -4v-88a4 4 0 0 0 -4 -4zm-24 24a4 4 0 0 0 -4 4v40a4 4 0 0 0 4 4 4 4 0 0 0 4 -4v-40a4 4 0 0 0 -4 -4z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#f7f5cf" image-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_gizmo_spatial_stream_player.svg b/editor/icons/icon_gizmo_spatial_stream_player.svg
index 2cf3966364..1470d3bfba 100644
--- a/editor/icons/icon_gizmo_spatial_stream_player.svg
+++ b/editor/icons/icon_gizmo_spatial_stream_player.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -924.36)">
-<path d="m99.766 934.36a8.0008 8.0011 0 0 0 -1.9609 0.296l-56 16a8.0008 8.0011 0 0 0 -5.8047 7.6964v48.119a18 18.001 0 0 0 -2 -0.116 18 18.001 0 0 0 -18 18.001 18 18.001 0 0 0 18 18.001 18 18.001 0 0 0 17.875 -16.001h0.125v-2-59.963l40-11.43v37.517a18 18.001 0 0 0 -2 -0.124 18 18.001 0 0 0 -18 18.001 18 18.001 0 0 0 18 18 18 18.001 0 0 0 17.875 -16h0.125v-2-66.003a8.0008 8.0011 0 0 0 -8.2344 -7.9924z" color="#000000" color-rendering="auto" fill="#f7f5cf" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<g transform="translate(0 -924.36)" shape-rendering="auto">
+<path transform="translate(0 924.36)" d="m99.645 6.0059c-0.9956 0.029687-1.9837 0.18322-2.9414 0.45703l-56 16c-5.1336 1.4668-8.7021 6.198-8.7031 11.537v44.203c-11.16 1.0331-20 10.379-20 21.797 1.1e-5 12.103 9.8971 22 22 22 12.103-1e-5 22-9.8971 22-22v-56.947l32-9.1426v28.293c-11.16 1.0331-20 10.379-20 21.797 1.1e-5 12.103 9.8971 22 22 22 12.103-1e-5 22-9.8971 22-22v-66c-0.00104-6.7137-5.6428-12.192-12.354-11.994z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill-opacity=".29412" image-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 924.36)" d="m99.764 10.004a8.0008 8.0008 0 0 0 -1.9609 0.30469l-56 16a8.0008 8.0008 0 0 0 -5.8027 7.6914v48.121a18 18 0 0 0 -2 -0.12109 18 18 0 0 0 -18 18 18 18 0 0 0 18 18 18 18 0 0 0 18 -18v-59.965l40-11.428v37.514a18 18 0 0 0 -2 -0.12109 18 18 0 0 0 -18 18 18 18 0 0 0 18 18 18 18 0 0 0 18 -18v-66a8.0008 8.0008 0 0 0 -8.2363 -7.9961z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#f7f5cf" image-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_gizmo_spot_light.svg b/editor/icons/icon_gizmo_spot_light.svg
index 9b4ddadd17..1881b6b60a 100644
--- a/editor/icons/icon_gizmo_spot_light.svg
+++ b/editor/icons/icon_gizmo_spot_light.svg
@@ -1,5 +1,6 @@
<svg width="128" height="128" version="1.1" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -924.36)">
+<path transform="translate(0 924.36)" d="m52 4c-6.5788 0-12 5.4212-12 12v26.625c-12.263 7.2822-19.978 19.75-20 33.369l-0.005859 4.0059h28.578c1.7994 6.8632 8.0265 12 15.428 12s13.628-5.1368 15.428-12h28.576l-0.00391-4.0039c-0.01526-13.625-7.7323-26.099-20-33.385v-26.611c0-6.5788-5.4212-12-12-12zm-11.689 78.016c-1.536-0.10738-3.1419 0.23676-4.5586 1.0547l-10.393 6c-3.7786 2.1816-5.1117 7.1503-2.9297 10.93 2.1816 3.7786 7.1503 5.1117 10.93 2.9297l10.393-6c3.7796-2.1822 5.1087-7.1521 2.9277-10.93-1.3629-2.3605-3.8057-3.8052-6.3691-3.9844zm47.379 0c-2.5634 0.1792-5.0063 1.6238-6.3691 3.9844-2.181 3.7776-0.85187 8.7475 2.9277 10.93l10.393 6c3.7794 2.182 8.7481 0.8489 10.93-2.9297 2.182-3.7794 0.84891-8.7481-2.9297-10.93l-10.393-6c-1.4167-0.81792-3.0225-1.1621-4.5586-1.0547zm-23.689 13.984c-4.3628 0-8 3.6372-8 8v12c0 4.3628 3.6372 8 8 8s8-3.6372 8-8v-12c0-4.3628-3.6372-8-8-8z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill-opacity=".29412" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
<path transform="translate(0 924.36)" d="m52 8c-4.432 0-8 3.568-8 8v12 16.875a40 36 0 0 0 -20 31.125h28a12 12 0 0 0 12 12 12 12 0 0 0 12 -12h28a40 36 0 0 0 -20 -31.141v-20.859-8c0-4.432-3.568-8-8-8h-24zm-11.969 78.006c-0.76793-0.053681-1.5596 0.1138-2.2793 0.5293l-10.393 6c-1.9191 1.108-2.5728 3.5457-1.4648 5.4648s3.5457 2.5728 5.4648 1.4648l10.393-6c1.9191-1.108 2.5709-3.5457 1.4629-5.4648-0.6925-1.1994-1.9037-1.9047-3.1836-1.9941zm47.938 0c-1.2799 0.08947-2.4911 0.7947-3.1836 1.9941-1.108 1.9191-0.45622 4.3568 1.4629 5.4648l10.393 6c1.9191 1.108 4.3568 0.45427 5.4648-1.4648s0.45427-4.3568-1.4648-5.4648l-10.393-6c-0.71967-0.4155-1.5114-0.58298-2.2793-0.5293zm-23.969 13.994c-2.216 0-4 1.784-4 4v12c0 2.216 1.784 4 4 4s4-1.784 4-4v-12c0-2.216-1.784-4-4-4z" fill="#f7f5cf" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.1082"/>
</g>
</svg>
diff --git a/editor/icons/icon_graph_comment.svg b/editor/icons/icon_graph_comment.svg
deleted file mode 100644
index d83bd62058..0000000000
--- a/editor/icons/icon_graph_comment.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m3 1v2h-2v2h2v4h-2v2h2v2h2v-2h4v2h2v-2h2v-2h-2v-4h2v-2h-2v-2h-2v2h-4v-2h-2zm2 4h4v4h-4v-4z" fill="#e0e0e0"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_cube_uniform.svg b/editor/icons/icon_graph_cube_uniform.svg
deleted file mode 100644
index a7ef1499b5..0000000000
--- a/editor/icons/icon_graph_cube_uniform.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m2 0c-1.1046 0-2 0.8954-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.8954 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm4.9727 2a0.71438 0.71438 0 0 1 0.34766 0.074219l4.2852 2.1426a0.71438 0.71438 0 0 1 0.39453 0.64062v4.2852a0.71438 0.71438 0 0 1 -0.39453 0.63867l-4.2852 2.1426a0.71438 0.71438 0 0 1 -0.64062 0l-4.2852-2.1426a0.71438 0.71438 0 0 1 -0.39453 -0.63867v-4.2852a0.71438 0.71438 0 0 1 0.39453 -0.64062l4.2852-2.1426a0.71438 0.71438 0 0 1 0.29297 -0.074219zm0.027344 1.5137l-2.6895 1.3438 2.6895 1.3438 2.6895-1.3438-2.6895-1.3438zm-3.5723 2.498v2.6895l2.8574 1.4277v-2.6875l-2.8574-1.4297zm7.1445 0l-2.8574 1.4297v2.6875l2.8574-1.4277v-2.6895z" fill="#eac968"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_curve_map.svg b/editor/icons/icon_graph_curve_map.svg
deleted file mode 100644
index a5a3184926..0000000000
--- a/editor/icons/icon_graph_curve_map.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m2 1049.4c8 0 9 0 9-9" fill="none" stroke="#f6f6f6" stroke-linecap="round" stroke-width="2"/>
-<path transform="translate(0 1038.4)" d="m11 4a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm-5 5a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2z" fill="#68d0ea"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_default_texture.svg b/editor/icons/icon_graph_default_texture.svg
deleted file mode 100644
index 0a1a0e9673..0000000000
--- a/editor/icons/icon_graph_default_texture.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m2 2v10h10v-10h-10zm9 2v5h-8l2-3 2 2 4-4z" fill="#eae068"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_input.svg b/editor/icons/icon_graph_input.svg
deleted file mode 100644
index c5034ecd2c..0000000000
--- a/editor/icons/icon_graph_input.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<circle cx="7" cy="1045.4" r="6" fill="#f6f6f6"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_rgb.svg b/editor/icons/icon_graph_rgb.svg
deleted file mode 100644
index 403572a82e..0000000000
--- a/editor/icons/icon_graph_rgb.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill-opacity=".39216">
-<path d="m7 1039.4a4 4 0 0 0 -4 4 4 4 0 0 0 0.03906 0.5195 4 4 0 0 0 -2.0391 3.4805 4 4 0 0 0 4 4 4 4 0 0 0 1.998 -0.541 4 4 0 0 0 2.002 0.541 4 4 0 0 0 4 -4 4 4 0 0 0 -2.0371 -3.4824 4 4 0 0 0 0.03711 -0.5176 4 4 0 0 0 -4 -4z" fill="#fff"/>
-<path d="m7 1040.4a3 3 0 0 0 -3 3 3 3 0 0 0 0.21094 1.1055 3 3 0 0 0 -2.2109 2.8945 3 3 0 0 0 3 3 3 3 0 0 0 2 -0.7676 3 3 0 0 0 2 0.7676 3 3 0 0 0 3 -3 3 3 0 0 0 -2.2148 -2.8906 3 3 0 0 0 0.21484 -1.1094 3 3 0 0 0 -3 -3z" fill="#fff"/>
-<circle cx="7" cy="1043.4" r="3" fill="#f00"/>
-<circle cx="5" cy="1047.4" r="3" fill="#00f"/>
-<circle cx="9" cy="1047.4" r="3" fill="#0f0"/>
-<circle cx="7" cy="1043.4" r="3" fill="#f00"/>
-<circle cx="5" cy="1047.4" r="3" fill="#00f"/>
-<circle cx="9" cy="1047.4" r="3" fill="#0f0"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_rgb_op.svg b/editor/icons/icon_graph_rgb_op.svg
deleted file mode 100644
index 6dbcd6ee44..0000000000
--- a/editor/icons/icon_graph_rgb_op.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m4 1050.4h6v-10h-6z" fill="#fff" fill-rule="evenodd" stroke="#fff" stroke-linejoin="round" stroke-width="2"/>
-<rect x="1" y="1041.4" width="2" height="2" fill="#fff"/>
-<rect x="1" y="1047.4" width="2" height="2" fill="#fff"/>
-<rect x="11" y="1044.4" width="2" height="2" fill="#fff"/>
-<rect x="5" y="1041.4" width="4" height="2" fill="#ff4646" fill-opacity=".86275"/>
-<rect x="5" y="1044.4" width="4" height="2" fill="#46ff46" fill-opacity=".86275"/>
-<rect x="5" y="1047.4" width="4" height="2" fill="#4646ff" fill-opacity=".86275"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_rgb_uniform.svg b/editor/icons/icon_graph_rgb_uniform.svg
deleted file mode 100644
index 4244bd408a..0000000000
--- a/editor/icons/icon_graph_rgb_uniform.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m2 1038.4c-1.1046 0-2 0.8954-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.8954 2-2v-10c0-1.1046-0.89543-2-2-2z" fill="#fff"/>
-<path transform="translate(0 1038.4)" d="m7 2a3 3 0 0 0 -3 3 3 3 0 0 0 0.21094 1.1055 3 3 0 0 0 -2.2109 2.8945 3 3 0 0 0 3 3 3 3 0 0 0 2 -0.76758 3 3 0 0 0 2 0.76758 3 3 0 0 0 3 -3 3 3 0 0 0 -2.2148 -2.8906 3 3 0 0 0 0.21484 -1.1094 3 3 0 0 0 -3 -3z" fill="#fff" fill-opacity=".39216"/>
-<circle cx="7" cy="1043.4" r="3" fill="#f00" fill-opacity=".39216"/>
-<circle cx="5" cy="1047.4" r="3" fill="#00f" fill-opacity=".39216"/>
-<circle cx="9" cy="1047.4" r="3" fill="#0f0" fill-opacity=".39216"/>
-<circle cx="7" cy="1043.4" r="3" fill="#f00" fill-opacity=".39216"/>
-<circle cx="5" cy="1047.4" r="3" fill="#00f" fill-opacity=".39216"/>
-<circle cx="9" cy="1047.4" r="3" fill="#0f0" fill-opacity=".39216"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_scalar.svg b/editor/icons/icon_graph_scalar.svg
deleted file mode 100644
index ba921a961c..0000000000
--- a/editor/icons/icon_graph_scalar.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m6 2c-1.6569 0-3 1.3431-3 3s1.3431 3 3 3h2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-5v2h5c1.6569 0 3-1.3431 3-3s-1.3431-3-3-3h-2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1h5v-2h-5z" fill="#cf68ea"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_scalar_interp.svg b/editor/icons/icon_graph_scalar_interp.svg
deleted file mode 100644
index edfbe36066..0000000000
--- a/editor/icons/icon_graph_scalar_interp.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m2 1050.4 10-10" fill="none" stroke="#cf68ea" stroke-linecap="round" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_scalar_op.svg b/editor/icons/icon_graph_scalar_op.svg
deleted file mode 100644
index 34f7d9b2b1..0000000000
--- a/editor/icons/icon_graph_scalar_op.svg
+++ /dev/null
@@ -1,8 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill="#cf68ea">
-<path transform="translate(0 1038.4)" d="m4 1c-0.55226 1e-4 -0.99994 0.4477-1 1v10c5.52e-5 0.5523 0.44774 0.9999 1 1h6c0.55226-1e-4 0.99994-0.4477 1-1v-10c-5.5e-5 -0.5523-0.44774-0.9999-1-1zm1 3 4 3-4 3z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<rect x="1" y="1041.4" width="2" height="2"/>
-<rect x="1" y="1047.4" width="2" height="2"/>
-<rect x="11" y="1044.4" width="2" height="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_scalar_uniform.svg b/editor/icons/icon_graph_scalar_uniform.svg
deleted file mode 100644
index d2ee2ec827..0000000000
--- a/editor/icons/icon_graph_scalar_uniform.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m2 0a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-10a2 2 0 0 0 -2 -2h-10zm4 2h5v2h-5a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h2c1.6569 0 3 1.3431 3 3s-1.3431 3-3 3h-5v-2h5a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-2c-1.6569 0-3-1.3431-3-3s1.3431-3 3-3z" fill="#cf68ea"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_scalars_to_vec.svg b/editor/icons/icon_graph_scalars_to_vec.svg
deleted file mode 100644
index bd3bc0424a..0000000000
--- a/editor/icons/icon_graph_scalars_to_vec.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<linearGradient id="a" x1="1" x2="13.014" y1="7" y2="7" gradientUnits="userSpaceOnUse">
-<stop stop-color="#cf68ea" offset="0"/>
-<stop stop-color="#b8ea68" offset="1"/>
-</linearGradient>
-</defs>
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m1.9902 0.99023a1.0001 1.0001 0 0 0 -0.69727 1.7168l3.293 3.293h-2.5859a1.0001 1.0001 0 1 0 0 2h2.5859l-3.293 3.293a1.0001 1.0001 0 1 0 1.4141 1.4141l4.707-4.707h4.5859a1.0001 1.0001 0 1 0 0 -2h-4.5859l-4.707-4.707a1.0001 1.0001 0 0 0 -0.7168 -0.30273z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="url(#a)" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_texscreen.svg b/editor/icons/icon_graph_texscreen.svg
deleted file mode 100644
index 6c26332203..0000000000
--- a/editor/icons/icon_graph_texscreen.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m2 1041.4h10v8h-10z" fill="none" stroke="#f6f6f6" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
-<rect x="3" y="1042.4" width="8" height="1" fill="#f6f6f6"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_texture_uniform.svg b/editor/icons/icon_graph_texture_uniform.svg
deleted file mode 100644
index 9e72743432..0000000000
--- a/editor/icons/icon_graph_texture_uniform.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m2 0c-1.1046 0-2 0.8954-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.8954 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm0 2h10v10h-10v-10zm9 2l-4 4-2-2-2 3h8v-5z" fill="#eae068"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_time.svg b/editor/icons/icon_graph_time.svg
deleted file mode 100644
index 6227b53c62..0000000000
--- a/editor/icons/icon_graph_time.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill="#f6f6f6">
-<rect x="6" y="1042.4" width="2" height="4"/>
-<rect x="6" y="1044.4" width="4" height="2"/>
-<path transform="translate(0 1038.4)" d="m7 0a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5 -5 5 5 0 0 1 5 -5z"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vec_dp.svg b/editor/icons/icon_graph_vec_dp.svg
deleted file mode 100644
index 0b24b47895..0000000000
--- a/editor/icons/icon_graph_vec_dp.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m1 1042.4 2 6 2-6" fill="none" stroke="#b8ea68" stroke-linejoin="round" stroke-width="2"/>
-<circle cx="7" cy="1046.4" r="1" fill="#b8ea68"/>
-<path d="m9 1042.4 2 6 2-6" fill="none" stroke="#b8ea68" stroke-linejoin="round" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vec_interp.svg b/editor/icons/icon_graph_vec_interp.svg
deleted file mode 100644
index a3df7ff93d..0000000000
--- a/editor/icons/icon_graph_vec_interp.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m2 1050.4 10-10" fill="none" stroke="#b8ea68" stroke-linecap="round" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vec_length.svg b/editor/icons/icon_graph_vec_length.svg
deleted file mode 100644
index cd2a39312a..0000000000
--- a/editor/icons/icon_graph_vec_length.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<rect y="1039.4" width="2" height="12" fill="#b8ea68"/>
-<rect x="12" y="1039.4" width="2" height="12" fill="#b8ea68"/>
-<path d="m5 1043.4 2 5 2-5" fill="none" stroke="#b8ea68" stroke-linecap="square" stroke-linejoin="round" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vec_op.svg b/editor/icons/icon_graph_vec_op.svg
deleted file mode 100644
index 2792d63378..0000000000
--- a/editor/icons/icon_graph_vec_op.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m4 1c-0.55226 1e-4 -0.99994 0.4477-1 1v1h-2v2h2v4h-2v2h2v1c5.52e-5 0.5523 0.44774 0.9999 1 1h6c0.55226-1e-4 0.99994-0.4477 1-1v-4h2v-2h-2v-4c-5.5e-5 -0.5523-0.44774-0.9999-1-1h-6zm1 3l4 3-4 3v-6z" color="#000000" color-rendering="auto" fill="#b8ea68" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vec_scalar_op.svg b/editor/icons/icon_graph_vec_scalar_op.svg
deleted file mode 100644
index effcb596a1..0000000000
--- a/editor/icons/icon_graph_vec_scalar_op.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill-rule="evenodd" shape-rendering="auto">
-<path transform="translate(0 1038.4)" d="m3 7v2h-2v2h2v1c5.52e-5 0.5523 0.44774 0.9999 1 1h6c0.55226-1e-4 0.99994-0.4477 1-1v-4h2v-1h-4l-4 3v-3h-2z" color="#000000" color-rendering="auto" fill="#cf68ea" image-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<path d="m3 1045.4v-2h-2v-2h2v-1c5.52e-5 -0.5523 0.44774-0.9999 1-1h6c0.55226 1e-4 0.99994 0.4477 1 1v4h2v1h-4l-4-3v3h-2z" color="#000000" color-rendering="auto" fill="#b8ea68" image-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vec_to_scalars.svg b/editor/icons/icon_graph_vec_to_scalars.svg
deleted file mode 100644
index 2ecacb8434..0000000000
--- a/editor/icons/icon_graph_vec_to_scalars.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<linearGradient id="a" x1="1" x2="13.014" y1="7" y2="7" gradientTransform="matrix(-1 0 0 1 14 1038.4)" gradientUnits="userSpaceOnUse">
-<stop stop-color="#cf68ea" offset="0"/>
-<stop stop-color="#b8ea68" offset="1"/>
-</linearGradient>
-</defs>
-<g transform="translate(0 -1038.4)">
-<path d="m12.01 1039.4a1.0001 1.0001 0 0 1 0.69726 1.7168l-3.293 3.293h2.5859a1.0001 1.0001 0 1 1 0 2h-2.5859l3.293 3.293a1.0001 1.0001 0 1 1 -1.4141 1.414l-4.707-4.707h-4.5859a1.0001 1.0001 0 1 1 0 -2h4.5859l4.707-4.707a1.0001 1.0001 0 0 1 0.7168 -0.3028z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="url(#a)" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vecs_to_xform.svg b/editor/icons/icon_graph_vecs_to_xform.svg
deleted file mode 100644
index ba9526231a..0000000000
--- a/editor/icons/icon_graph_vecs_to_xform.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<linearGradient id="a" x1="1" x2="13.014" y1="7" y2="7" gradientTransform="translate(.00074682 1038.4)" gradientUnits="userSpaceOnUse">
-<stop stop-color="#b8ea68" offset="0"/>
-<stop stop-color="#ea686c" offset="1"/>
-</linearGradient>
-</defs>
-<g transform="translate(0 -1038.4)">
-<path d="m1.991 1039.4a1.0001 1.0001 0 0 0 -0.69726 1.7168l3.293 3.293h-2.5859a1.0001 1.0001 0 1 0 0 2h2.5859l-3.293 3.293a1.0001 1.0001 0 1 0 1.4141 1.414l4.707-4.707h4.5859a1.0001 1.0001 0 1 0 0 -2h-4.5859l-4.707-4.707a1.0001 1.0001 0 0 0 -0.7168 -0.3028z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="url(#a)" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vector.svg b/editor/icons/icon_graph_vector.svg
deleted file mode 100644
index 81772fa4f5..0000000000
--- a/editor/icons/icon_graph_vector.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m8 1038.4v2h-5v2h5v2l3-3zm-3.6562 5.6289-1.7148 1.0293 0.51367 0.8574 3 5c0.3885 0.647 1.3263 0.647 1.7148 0l3-5 0.51367-0.8574-1.7148-1.0293-0.51367 0.8574-2.1426 3.5703-2.1426-3.5703z" color="#000000" color-rendering="auto" fill="#b8ea68" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_vector_uniform.svg b/editor/icons/icon_graph_vector_uniform.svg
deleted file mode 100644
index 66f31bf5dd..0000000000
--- a/editor/icons/icon_graph_vector_uniform.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m2 0c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2zm6 0 3 3-3 3v-2h-5v-2h5zm-3.6562 5.6289 0.51367 0.85742 2.1426 3.5703 2.1426-3.5703 0.51367-0.85742l1.7148 1.0293-0.51367 0.85742-3 5c-0.3885 0.64706-1.3263 0.64706-1.7148 0l-3-5-0.51367-0.85742z" fill="#b8ea68"/>
-<path transform="translate(0 1038.4)" d="m23 0v2h-5v2h5v2l3-3zm-3.6562 5.6289-1.7148 1.0293 0.51367 0.85742 3 5c0.3885 0.64706 1.3263 0.64706 1.7148 0l3-5 0.51367-0.85742-1.7148-1.0293-0.51367 0.85742-2.1426 3.5703-2.1426-3.5703z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_xform.svg b/editor/icons/icon_graph_xform.svg
deleted file mode 100644
index 95b0a2eff8..0000000000
--- a/editor/icons/icon_graph_xform.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<rect x="1" y="1039.4" width="1" height="12" fill="#ea686c"/>
-<rect x="1" y="1039.4" width="3" height="1" fill="#ea686c"/>
-<rect x="1" y="1050.4" width="3" height="1" fill="#ea686c"/>
-<rect x="10" y="1050.4" width="3" height="1" fill="#ea686c"/>
-<rect x="10" y="1039.4" width="3" height="1" fill="#ea686c"/>
-<rect x="12" y="1039.4" width="1" height="12" fill="#ea686c"/>
-<path d="m4 1049.4v-7l3 3 3-3v7" fill="none" stroke="#ea686c" stroke-linejoin="round" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_xform_mult.svg b/editor/icons/icon_graph_xform_mult.svg
deleted file mode 100644
index 4d5593084e..0000000000
--- a/editor/icons/icon_graph_xform_mult.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m1 1049.4v-7l2 3 2-3v7" fill="none" stroke="#ea686c" stroke-linejoin="round" stroke-width="2"/>
-<path d="m9 1049.4v-7l2 3 2-3v7" fill="none" stroke="#ea686c" stroke-linejoin="round" stroke-width="2"/>
-<circle cx="7" cy="1045.4" r="1" fill="#ea686c"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_xform_scalar_func.svg b/editor/icons/icon_graph_xform_scalar_func.svg
deleted file mode 100644
index 350d9e98d7..0000000000
--- a/editor/icons/icon_graph_xform_scalar_func.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill="#cf68ea">
-<rect x="6" y="1042.4" width="2" height="5"/>
-<path transform="translate(0 1038.4)" d="m9.0703 1a3 3 0 0 0 -1.5703 0.40234 3 3 0 0 0 -1.5 2.5977h2a1 1 0 0 1 1 -1 1 1 0 0 1 1 1h2a3 3 0 0 0 -1.5 -2.5977 3 3 0 0 0 -1.4297 -0.40234z"/>
-<rect x="10" y="1042.4" width="2" height="1"/>
-<path transform="translate(0 1038.4)" d="m2 10a3 3 0 0 0 1.5 2.5977 3 3 0 0 0 3 0 3 3 0 0 0 1.5 -2.5977h-2a1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1h-2z"/>
-<rect transform="scale(1,-1)" x="6" y="-1048.4" width="2" height="1"/>
-<rect x="4" y="1044.4" width="6" height="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_xform_to_vecs.svg b/editor/icons/icon_graph_xform_to_vecs.svg
deleted file mode 100644
index 7da2834f43..0000000000
--- a/editor/icons/icon_graph_xform_to_vecs.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<linearGradient id="a" x1="1" x2="13.014" y1="7" y2="7" gradientTransform="matrix(-1 0 0 1 14 1038.4)" gradientUnits="userSpaceOnUse">
-<stop stop-color="#b8ea68" offset="0"/>
-<stop stop-color="#ea686c" offset="1"/>
-</linearGradient>
-</defs>
-<g transform="translate(0 -1038.4)">
-<path d="m12.01 1039.4a1.0001 1.0001 0 0 1 0.69726 1.7168l-3.293 3.293h2.5859a1.0001 1.0001 0 1 1 0 2h-2.5859l3.293 3.293a1.0001 1.0001 0 1 1 -1.4141 1.414l-4.707-4.707h-4.5859a1.0001 1.0001 0 1 1 0 -2h4.5859l4.707-4.707a1.0001 1.0001 0 0 1 0.7168 -0.3028z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="url(#a)" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_xform_uniform.svg b/editor/icons/icon_graph_xform_uniform.svg
deleted file mode 100644
index 08bd345bc4..0000000000
--- a/editor/icons/icon_graph_xform_uniform.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path transform="translate(0 1038.4)" d="m2 0c-1.1046 0-2 0.8954-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.8954 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm-1 1h1 2v1h-2v10h2v1h-2-1v-1-10-1zm9 0h3v11 1h-3v-1h2v-10h-2v-1zm-0.029297 2a1.0001 1.0001 0 0 1 1.0293 1v7h-2v-4.5859l-1.293 1.293a1.0001 1.0001 0 0 1 -1.4141 0l-1.293-1.293v4.5859h-2v-7a1.0001 1.0001 0 0 1 0.98438 -0.99805 1.0001 1.0001 0 0 1 0.72266 0.29102l2.293 2.293 2.293-2.293a1.0001 1.0001 0 0 1 0.67773 -0.29297z" fill="#ea686c"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_xform_vec_func.svg b/editor/icons/icon_graph_xform_vec_func.svg
deleted file mode 100644
index 29bff80cd5..0000000000
--- a/editor/icons/icon_graph_xform_vec_func.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill="#b8ea68">
-<rect x="6" y="1042.4" width="2" height="5"/>
-<path transform="translate(0 1038.4)" d="m9.0703 1a3 3 0 0 0 -1.5703 0.40234 3 3 0 0 0 -1.5 2.5977h2a1 1 0 0 1 1 -1 1 1 0 0 1 1 1h2a3 3 0 0 0 -1.5 -2.5977 3 3 0 0 0 -1.4297 -0.40234z"/>
-<rect x="10" y="1042.4" width="2" height="1"/>
-<path transform="translate(0 1038.4)" d="m2 10a3 3 0 0 0 1.5 2.5977 3 3 0 0 0 3 0 3 3 0 0 0 1.5 -2.5977h-2a1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1h-2z"/>
-<rect transform="scale(1,-1)" x="6" y="-1048.4" width="2" height="1"/>
-<rect x="4" y="1044.4" width="6" height="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_xform_vec_imult.svg b/editor/icons/icon_graph_xform_vec_imult.svg
deleted file mode 100644
index edb68ffc4a..0000000000
--- a/editor/icons/icon_graph_xform_vec_imult.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m1 1042.4 2 6 2-6" fill="none" stroke="#b8ea68" stroke-linejoin="round" stroke-width="2"/>
-<circle cx="7" cy="1046.4" r="1" fill="#b8ea68"/>
-<path d="m9 1049.4v-7l2 3 2-3v7" fill="none" stroke="#ea686c" stroke-linejoin="round" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_graph_xform_vec_mult.svg b/editor/icons/icon_graph_xform_vec_mult.svg
deleted file mode 100644
index 1e5cbafdb2..0000000000
--- a/editor/icons/icon_graph_xform_vec_mult.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)">
-<path d="m9 1042.4 2 6 2-6" fill="none" stroke="#b8ea68" stroke-linejoin="round" stroke-width="2"/>
-<circle cx="7" cy="1046.4" r="1" fill="#b8ea68"/>
-<path d="m1 1049.4v-7l2 3 2-3v7" fill="none" stroke="#ea686c" stroke-linejoin="round" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_group_viewport.svg b/editor/icons/icon_group_viewport.svg
new file mode 100644
index 0000000000..350fb4103f
--- /dev/null
+++ b/editor/icons/icon_group_viewport.svg
@@ -0,0 +1,7 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m0 0v4h4v-4h-4zm6 0v6h-6v10h10v-6h6v-10h-10zm4 4h2v2h-2v-2zm2 8v4h4v-4h-4z" fill-opacity=".39216" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width=".5"/>
+<path transform="translate(0 1036.4)" d="m7 1v6h-6v8h8v-6h6v-8zm2 2h4v4h-4z" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m1 1v2c0 2.34e-5 0.446 0 1 0s1 2.34e-5 1 0v-2c0-2.341e-5 -0.446 0-1 0s-1-2.341e-5 -1 0zm12 0v2c0 2.34e-5 0.446 0 1 0s1 2.34e-5 1 0v-2c0-2.341e-5 -0.446 0-1 0s-1-2.341e-5 -1 0zm-12 12v2c0 2.3e-5 0.446 0 1 0s1 2.3e-5 1 0v-2c0-2.3e-5 -0.446 0-1 0s-1-2.3e-5 -1 0zm12 0v2c0 2.3e-5 0.446 0 1 0s1 2.3e-5 1 0v-2c0-2.3e-5 -0.446 0-1 0s-1-2.3e-5 -1 0z" fill="#fff"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_gui_close_customizable.svg b/editor/icons/icon_gui_close_customizable.svg
new file mode 100644
index 0000000000..ac023b7030
--- /dev/null
+++ b/editor/icons/icon_gui_close_customizable.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3.7578 2.3438l-1.4141 1.4141 4.2422 4.2422-4.2422 4.2422 1.4141 1.4141 4.2422-4.2422 4.2422 4.2422 1.4141-1.4141-4.2422-4.2422 4.2422-4.2422-1.4141-1.4141-4.2422 4.2422-4.2422-4.2422z" fill="#fff" fill-opacity=".89804"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_gui_graph_node_port.svg b/editor/icons/icon_gui_graph_node_port.svg
new file mode 100644
index 0000000000..1120218844
--- /dev/null
+++ b/editor/icons/icon_gui_graph_node_port.svg
@@ -0,0 +1,5 @@
+<svg width="10" height="10" version="1.1" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1042.4)">
+<circle cx="5" cy="1047.4" r="5" fill="#fff" fill-rule="evenodd"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_gui_resizer.svg b/editor/icons/icon_gui_resizer.svg
new file mode 100644
index 0000000000..d9af047213
--- /dev/null
+++ b/editor/icons/icon_gui_resizer.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m11 3c-0.55228 0-1 0.44772-1 1v6h-6c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1h7c0.55226-5.5e-5 0.99994-0.44774 1-1v-7c0-0.55228-0.44772-1-1-1z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fff" fill-opacity=".58824" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+</svg>
diff --git a/editor/icons/icon_h_box_container.svg b/editor/icons/icon_h_box_container.svg
index 48a1fc7d64..1428af8542 100644
--- a/editor/icons/icon_h_box_container.svg
+++ b/editor/icons/icon_h_box_container.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2zm0 2h10v10h-10z"/>
-<rect x="5" y="1039.4" width="2" height="10"/>
-<rect x="9" y="1039.4" width="2" height="10"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm0 2h2v10h-2v-10zm4 0h2v10h-2v-10zm4 0h2v10h-2v-10z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_h_separator.svg b/editor/icons/icon_h_separator.svg
index 34689555b3..60a665c730 100644
--- a/editor/icons/icon_h_separator.svg
+++ b/editor/icons/icon_h_separator.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<rect x="5" y="1038.4" width="6" height="3"/>
-<rect transform="matrix(0,-1,-1,0,0,0)" x="-1045.4" y="-15" width="2" height="14"/>
-<rect x="5" y="1047.4" width="6" height="3"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m5 2v3h6v-3h-6zm-4 5v2h14v-2h-14zm4 4v3h6v-3h-6z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_h_split_container.svg b/editor/icons/icon_h_split_container.svg
index 9985fcccfe..1f84ef4353 100644
--- a/editor/icons/icon_h_split_container.svg
+++ b/editor/icons/icon_h_split_container.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2zm0 2h10v10h-10z"/>
-<rect x="7" y="1039.4" width="2" height="10"/>
-<path d="m9 1042.4v4l2-2z"/>
-<path d="m7 1042.4-2 2 2 2z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm0 2h4v3l-2 2 2 2v3h-4v-10zm6 0h4v10h-4v-3l2-2-2-2v-3z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_h_t_t_p_request.svg b/editor/icons/icon_h_t_t_p_request.svg
index 27812cdd68..6568825af4 100644
--- a/editor/icons/icon_h_t_t_p_request.svg
+++ b/editor/icons/icon_h_t_t_p_request.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0" fill-opacity=".99608">
-<path transform="translate(0 1036.4)" d="m1 10v2 1 2h1v-2h1v2h1v-5h-1v2h-1v-2h-1zm4 0v1h1v4h1v-4h1v-1h-3zm4 0v1h1v4h1v-4h1v-1h-3zm4 0v2 1 2h1v-2h1 1v-1-2h-2-1zm1 1h1v1h-1v-1z"/>
-<path transform="translate(0 1036.4)" d="m4 1l-3 4h2v3h2v-3h2l-3-4zm7 0v3h-2l3 4 3-4h-2v-3h-2z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m4 1l-3 4h2v3h2v-3h2l-3-4zm7 0v3h-2l3 4 3-4h-2v-3h-2zm-10 9v2 1 2h1v-2h1v2h1v-5h-1v2h-1v-2h-1zm4 0v1h1v4h1v-4h1v-1h-3zm4 0v1h1v4h1v-4h1v-1h-3zm4 0v2 1 2h1v-2h1 1v-1-2h-2-1zm1 1h1v1h-1v-1z" fill="#e0e0e0" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_headphones.svg b/editor/icons/icon_headphones.svg
index e23a6c54f0..0df3f6f85c 100644
--- a/editor/icons/icon_headphones.svg
+++ b/editor/icons/icon_headphones.svg
@@ -1,11 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m1 1046.4v3h2v2h2v-5h-4z"/>
-<path d="m11 1046.4v5h2v-2h2v-3h-4z"/>
-<path d="m8 1037.4a7 7 0 0 0 -7 7h2a5 5 0 0 1 5 -5 5 5 0 0 1 5 5h2a7 7 0 0 0 -7 -7z"/>
-<rect x="1" y="1044.4" width="2" height="2"/>
-<rect x="13" y="1044.4" width="2" height="2"/>
-<circle cx="3" cy="1049.4" r="2"/>
-<circle transform="scale(-1,1)" cx="-13" cy="1049.4" r="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7v2 3a2 2 0 0 0 2 2h2v-5h-2v-2a5 5 0 0 1 5 -5 5 5 0 0 1 5 5v2h-2v3 2h2a2 2 0 0 0 2 -2v-3-2a7 7 0 0 0 -7 -7z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_import_check.svg b/editor/icons/icon_import_check.svg
index e3ad9ec37e..c9f51bb6e0 100644
--- a/editor/icons/icon_import_check.svg
+++ b/editor/icons/icon_import_check.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m2 1044.4 4 4 8-8" fill="none" stroke="#84ffb1" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+<path d="m2 1044.4 4 4 8-8" fill="none" stroke="#45ff8b" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
</g>
</svg>
diff --git a/editor/icons/icon_import_fail.svg b/editor/icons/icon_import_fail.svg
index e088126043..f4aa212c20 100644
--- a/editor/icons/icon_import_fail.svg
+++ b/editor/icons/icon_import_fail.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m2.9902 1.9902a1.0001 1.0001 0 0 0 -0.69727 1.7168l4.293 4.293-4.293 4.293a1.0001 1.0001 0 1 0 1.4141 1.4141l4.293-4.293 4.293 4.293a1.0001 1.0001 0 1 0 1.4141 -1.4141l-4.293-4.293 4.293-4.293a1.0001 1.0001 0 0 0 -0.72656 -1.7148 1.0001 1.0001 0 0 0 -0.6875 0.30078l-4.293 4.293-4.293-4.293a1.0001 1.0001 0 0 0 -0.7168 -0.30273z" color="#000000" color-rendering="auto" fill="#ff8484" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1036.4)" d="m2.9902 1.9902a1.0001 1.0001 0 0 0 -0.69727 1.7168l4.293 4.293-4.293 4.293a1.0001 1.0001 0 1 0 1.4141 1.4141l4.293-4.293 4.293 4.293a1.0001 1.0001 0 1 0 1.4141 -1.4141l-4.293-4.293 4.293-4.293a1.0001 1.0001 0 0 0 -0.72656 -1.7148 1.0001 1.0001 0 0 0 -0.6875 0.30078l-4.293 4.293-4.293-4.293a1.0001 1.0001 0 0 0 -0.7168 -0.30273z" color="#000000" color-rendering="auto" fill="#ff5d5d" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_instance.svg b/editor/icons/icon_instance.svg
index 8fecb9696a..5ef7be9331 100644
--- a/editor/icons/icon_instance.svg
+++ b/editor/icons/icon_instance.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m5 1047.4 6-6" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-width="2"/>
-<path transform="translate(0 1036.4)" d="m11 1c-2.1973 0-4 1.8027-4 4 0 0.35477 0.062329 0.69321 0.15039 1.0215l2.3945-2.3945c0.36302-0.38506 0.87563-0.62695 1.4551-0.62695 1.1164 0 2 0.8836 2 2 0 0.57388-0.23667 1.0829-0.61523 1.4453l-2.4043 2.4043c0.32773 0.087749 0.66541 0.15039 1.0195 0.15039 2.1973 0 4-1.8027 4-4s-1.8027-4-4-4zm-6 6c-2.1973 0-4 1.8027-4 4s1.8027 4 4 4 4-1.8027 4-4c0-0.35412-0.062641-0.6918-0.15039-1.0195l-2.4043 2.4043c-0.36245 0.37857-0.87143 0.61523-1.4453 0.61523-1.1164 0-2-0.8836-2-2 0-0.57944 0.24189-1.0921 0.62695-1.4551l2.3945-2.3945c-0.32827-0.088062-0.66671-0.15039-1.0215-0.15039z" color="#000000" color-rendering="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1036.4)" d="m11 1c-2.1973 0-4 1.8027-4 4 0 0.35477 0.062329 0.69321 0.15039 1.0215l2.3945-2.3945c0.36302-0.38506 0.87563-0.62695 1.4551-0.62695 1.1164 0 2 0.8836 2 2 0 0.57388-0.23667 1.0829-0.61523 1.4453l-2.4043 2.4043c0.32773 0.087749 0.66541 0.15039 1.0195 0.15039 2.1973 0 4-1.8027 4-4s-1.8027-4-4-4zm-0.013672 3.002a1 1 0 0 0 -0.69336 0.29102l-6 6a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l6-6a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102zm-5.9863 2.998c-2.1973 0-4 1.8027-4 4s1.8027 4 4 4 4-1.8027 4-4c0-0.35412-0.062641-0.6918-0.15039-1.0195l-2.4043 2.4043c-0.36245 0.37857-0.87143 0.61523-1.4453 0.61523-1.1164 0-2-0.8836-2-2 0-0.57944 0.24189-1.0921 0.62695-1.4551l2.3945-2.3945c-0.32827-0.088062-0.66671-0.15039-1.0215-0.15039z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_integer.svg b/editor/icons/icon_integer.svg
deleted file mode 100644
index bcd952f635..0000000000
--- a/editor/icons/icon_integer.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill="#cf68ea">
-<rect x="6" y="1040.4" width="2" height="10"/>
-<rect x="4" y="1039.4" width="6" height="2"/>
-<rect x="4" y="1049.4" width="6" height="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_interp_wrap_clamp.svg b/editor/icons/icon_interp_wrap_clamp.svg
index d49a450d2e..8ed349c185 100644
--- a/editor/icons/icon_interp_wrap_clamp.svg
+++ b/editor/icons/icon_interp_wrap_clamp.svg
@@ -1,9 +1,5 @@
<svg width="16" height="8" version="1.1" viewBox="0 0 16 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)">
-<rect x="1" y="1045.4" width="2" height="6" rx="1.7383e-5" ry="1.7383e-5" fill="#e0e0e0"/>
-<rect x="13" y="1045.4" width="2" height="6" rx="1.7383e-5" ry="1.7383e-5" fill="#e0e0e0"/>
-<path d="m5 1048.4h6" fill="none" stroke="#e0e0e0" stroke-width="2"/>
-<path d="m6 1046.4-2 2 2 2" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
-<path d="m10 1046.4 2 2-2 2" fill="none" stroke="#e0e0e0" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+<path transform="translate(0 1044.4)" d="m1 1v6h2v-2.9863-3.0137h-2zm2 3.0137a1.0001 1.0001 0 0 0 0.29297 0.69336l2 2a1 1 0 0 0 1.4141 0 1 1 0 0 0 0 -1.4141l-0.29297-0.29297h3.1719l-0.29297 0.29297a1 1 0 0 0 0 1.4141 1 1 0 0 0 1.4141 0l2-2a1.0001 1.0001 0 0 0 0.29297 -0.72266 1.0001 1.0001 0 0 0 -0.29297 -0.69141l-2-2a1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l0.29297 0.29297h-3.1719l0.29297-0.29297a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102l-2 2a1.0001 1.0001 0 0 0 -0.29297 0.7207zm10-0.029297v3.0156h2v-6h-2v2.9844z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_interp_wrap_loop.svg b/editor/icons/icon_interp_wrap_loop.svg
index 85d17cb50d..69c4d31d79 100644
--- a/editor/icons/icon_interp_wrap_loop.svg
+++ b/editor/icons/icon_interp_wrap_loop.svg
@@ -1,10 +1,5 @@
<svg width="16" height="8" version="1.1" viewBox="0 0 16 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)" fill="#e0e0e0">
-<path transform="translate(0 1044.4)" d="m12 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3z"/>
-<path transform="translate(0 1044.4)" d="m4 1a3 3 0 0 0 -3 3 3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1v-2z"/>
-<rect x="9" y="1045.4" width="3" height="2" rx="6.5185e-6" ry="1.7383e-5"/>
-<rect x="4" y="1049.4" width="3" height="2" rx="6.5185e-6" ry="1.7383e-5"/>
-<path d="m7 1048.4v4l3-2z" fill-rule="evenodd"/>
-<path d="m9 1044.4v4l-3-2z" fill-rule="evenodd"/>
+<path transform="translate(0 1044.4)" d="m9 0l-3 2 3 2v-1h3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3h-3v-1zm-5 1a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h3v1l3-2-3-2v1h-3a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1v-2z"/>
</g>
</svg>
diff --git a/editor/icons/icon_invalid_key.svg b/editor/icons/icon_invalid_key.svg
deleted file mode 100644
index f1df51f7c3..0000000000
--- a/editor/icons/icon_invalid_key.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1044.4)">
-<path d="m0.46447 1046.2 2.1213 2.1213-2.1213 2.1213 1.4142 1.4142l2.1213-2.1213 2.1213 2.1213 1.4142-1.4142-2.1213-2.1213 2.1213-2.1213-1.4142-1.4142-2.1213 2.1213-2.1213-2.1213-1.4142 1.4142z" fill="#ff8484"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_inverse_kinematics.svg b/editor/icons/icon_inverse_kinematics.svg
index fa99b6c7cc..aac40f6015 100644
--- a/editor/icons/icon_inverse_kinematics.svg
+++ b/editor/icons/icon_inverse_kinematics.svg
@@ -1,12 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m3 1039.4v12" fill="none" stroke="#fc9c9c" stroke-width="2"/>
-<circle cx="3" cy="1039.4" r="2" fill="#fc9c9c"/>
-<path d="m10 1039.4h-7" fill="#fc9c9c" fill-rule="evenodd" stroke="#fc9c9c" stroke-width="2"/>
-<circle cx="11" cy="1039.4" r="2" fill="#fc9c9c"/>
-<rect x="8" y="1044.4" width="6" height="2" fill="#fc9c9c"/>
-<path d="m11 1039.4v6" fill="none" stroke="#fc9c9c" stroke-width="2"/>
-<path d="m10 1046.4v4l-3-2 1-2z" fill="#fc9c9c" fill-rule="evenodd"/>
-<path d="m12 1046.4v4l3-2-1-2z" fill="#fc9c9c" fill-rule="evenodd"/>
+<path transform="translate(0 1036.4)" d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v10.27h2v-10.271a2 2 0 0 0 0.73047 -0.72852h4.541a2 2 0 0 0 0.72852 0.73047v3.2695h-2v2l-1 2 3 2v-4h2v4l3-2-1-2v-2h-2v-3.2715a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-4.541a2 2 0 0 0 -1.7285 -1z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fc9c9c" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_item_list.svg b/editor/icons/icon_item_list.svg
index e01c4cd098..8b2221ade6 100644
--- a/editor/icons/icon_item_list.svg
+++ b/editor/icons/icon_item_list.svg
@@ -1,14 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2zm0 2h10v10h-10z"/>
-<rect x="4" y="1040.4" width="2" height="2"/>
-<rect x="7" y="1040.4" width="2" height="2"/>
-<rect x="10" y="1040.4" width="2" height="2"/>
-<rect x="4" y="1043.4" width="2" height="2"/>
-<rect x="7" y="1043.4" width="2" height="2"/>
-<rect x="10" y="1043.4" width="2" height="2"/>
-<rect x="4" y="1046.4" width="2" height="2"/>
-<rect x="7" y="1046.4" width="2" height="2"/>
-<rect x="10" y="1046.4" width="2" height="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm0 2h10v10h-10v-10zm1 1v2h2v-2h-2zm3 0v2h2v-2h-2zm3 0v2h2v-2h-2zm-6 3v2h2v-2h-2zm3 0v2h2v-2h-2zm3 0v2h2v-2h-2zm-6 3v2h2v-2h-2zm3 0v2h2v-2h-2zm3 0v2h2v-2h-2z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_key.svg b/editor/icons/icon_key.svg
index 041b820e00..cc152b58a5 100644
--- a/editor/icons/icon_key.svg
+++ b/editor/icons/icon_key.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0" fill-opacity=".99608">
-<path transform="translate(0 1036.4)" d="m11 4a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 4 -4 4 4 0 0 0 -4 -4zm0 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2z"/>
-<rect x="1" y="1043.4" width="8" height="2"/>
-<rect x="2" y="1045.4" width="3" height="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m11 4a4 4 0 0 0 -3.8691 3h-6.1309v2h1v2h3v-2h2.1328a4 4 0 0 0 3.8672 3 4 4 0 0 0 4 -4 4 4 0 0 0 -4 -4zm0 2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2 2 2 0 0 1 -2 -2 2 2 0 0 1 2 -2z" fill="#e0e0e0" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_key_invalid.svg b/editor/icons/icon_key_invalid.svg
index f1df51f7c3..742859bac5 100644
--- a/editor/icons/icon_key_invalid.svg
+++ b/editor/icons/icon_key_invalid.svg
@@ -1,5 +1,5 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)">
-<path d="m0.46447 1046.2 2.1213 2.1213-2.1213 2.1213 1.4142 1.4142l2.1213-2.1213 2.1213 2.1213 1.4142-1.4142-2.1213-2.1213 2.1213-2.1213-1.4142-1.4142-2.1213 2.1213-2.1213-2.1213-1.4142 1.4142z" fill="#ff8484"/>
+<path d="m0.46447 1046.2 2.1213 2.1213-2.1213 2.1213 1.4142 1.4142l2.1213-2.1213 2.1213 2.1213 1.4142-1.4142-2.1213-2.1213 2.1213-2.1213-1.4142-1.4142-2.1213 2.1213-2.1213-2.1213-1.4142 1.4142z" fill="#ff5d5d"/>
</g>
</svg>
diff --git a/editor/icons/icon_key_move_enabled.svg b/editor/icons/icon_key_move_enabled.svg
new file mode 100644
index 0000000000..203b697ad2
--- /dev/null
+++ b/editor/icons/icon_key_move_enabled.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1c-0.195 0-0.38964 0.07519-0.53906 0.22461l-3.2363 3.2363c-0.29884 0.29884-0.29884 0.77929 0 1.0781l3.2363 3.2363c0.29884 0.29884 0.77929 0.29884 1.0781 0l3.2363-3.2363c0.29884-0.29884 0.29884-0.77929 0-1.0781l-3.2363-3.2363c-0.14942-0.14942-0.34406-0.22461-0.53906-0.22461zm-7 7v5c0 1.6569 1.3471 3.114 3 3h1v-2h-1c-0.55228-1e-5 -0.99999-0.44772-1-1v-5h-2zm7 2c-1.645 0-3 1.355-3 3s1.355 3 3 3 3-1.355 3-3-1.355-3-3-3zm3 3c0 1.6569 1.3431 3 3 3h1v-2h-1c-0.55228-1e-5 -0.99999-0.44772-1-1 1e-5 -0.55228 0.44772-0.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3zm-3-1c0.56413 0 1 0.4359 1 1 0 0.5642-0.43587 1-1 1s-1-0.4358-1-1c0-0.5641 0.43587-1 1-1z" fill="#e0e0e0" fill-opacity=".99608"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_key_rotate_enabled.svg b/editor/icons/icon_key_rotate_enabled.svg
new file mode 100644
index 0000000000..0f975631b2
--- /dev/null
+++ b/editor/icons/icon_key_rotate_enabled.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1c-0.195 0-0.38964 0.07519-0.53906 0.22461l-3.2363 3.2363c-0.29884 0.29884-0.29884 0.77929 0 1.0781l3.2363 3.2363c0.29884 0.29884 0.77929 0.29884 1.0781 0l3.2363-3.2363c0.29884-0.29884 0.29884-0.77929 0-1.0781l-3.2363-3.2363c-0.14942-0.14942-0.34406-0.22461-0.53906-0.22461zm3 7v5c0 1.6569 1.3431 3 3 3h1v-2h-1c-0.55228 0-0.99999-0.4477-1-1v-1h2v-2h-2v-2h-2zm0 5c0-1.645-1.355-3-3-3s-3 1.355-3 3 1.355 3 3 3 3-1.355 3-3zm-7-3c-1.6569 0-3 1.3431-3 3v3h2v-3c9.6e-6 -0.5523 0.44772-1 1-1h1v-2h-1zm4 2c0.56413 0 1 0.4359 1 1 0 0.5642-0.43587 1-1 1s-1-0.4358-1-1c0-0.5641 0.43587-1 1-1z" fill="#e0e0e0" fill-opacity=".99608"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_key_scale_enabled.svg b/editor/icons/icon_key_scale_enabled.svg
new file mode 100644
index 0000000000..eaa12fdf0e
--- /dev/null
+++ b/editor/icons/icon_key_scale_enabled.svg
@@ -0,0 +1,5 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1c-0.195 0-0.38964 0.07519-0.53906 0.22461l-3.2363 3.2363c-0.29884 0.29884-0.29884 0.77929 0 1.0781l3.2363 3.2363c0.29884 0.29884 0.77929 0.29884 1.0781 0l3.2363-3.2363c0.29884-0.29884 0.29884-0.77929 0-1.0781l-3.2363-3.2363c-0.14942-0.14942-0.34406-0.22461-0.53906-0.22461zm3 7v5c0 1.6569 1.3431 3 3 3h1v-2h-1c-0.55228-1e-5 -0.99999-0.44772-1-1v-5h-2zm-8 2c-0.71466-1e-4 -1.3751 0.3811-1.7324 1-0.35727 0.6188-0.35727 1.3812 0 2 0.35733 0.6189 1.0178 1.0001 1.7324 1h-2v2h2c0.71466 1e-4 1.3751-0.3811 1.7324-1 0.35727-0.6188 0.35727-1.3812 0-2-0.35733-0.6189-1.0178-1.0001-1.7324-1h2v-2h-2zm6 0c-1.6569 0-3 1.3431-3 3s1.3431 3 3 3h1v-2h-1c-0.55228-1e-5 -0.99999-0.44772-1-1 9.6e-6 -0.55228 0.44772-0.99999 1-1h1v-2h-1z" fill="#e0e0e0" fill-opacity=".99608"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_keyboard.svg b/editor/icons/icon_keyboard.svg
index ce98e47ab4..ca58ec6cb2 100644
--- a/editor/icons/icon_keyboard.svg
+++ b/editor/icons/icon_keyboard.svg
@@ -1,7 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill-opacity=".99608">
-<path transform="translate(0 1036.4)" d="m1 4v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-9h-1v9a0.99998 0.99998 0 0 1 -1 1h-10a1 1 0 0 1 -1 -1v-9h-1z" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m4 2a1 1 0 0 0 -1 1v9.084a1 0.91667 0 0 0 1 0.91602h8a1 0.91667 0 0 0 1 -0.91602v-9.084a1 1 0 0 0 -1 -1h-8zm-3 2v9a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-9h-1v9a0.99998 0.99998 0 0 1 -1 1h-10a1 1 0 0 1 -1 -1v-9h-1zm4 0h2v3l2-3h2l-2 3 2 4h-2l-2-4v4h-2v-7z" fill="#e0e0e0"/>
<rect x="27" y="1038.4" width="7" height="14" fill="#fff"/>
-<path transform="translate(0 1036.4)" d="m4 2a1 1 0 0 0 -1 1v9.084a1 0.91667 0 0 0 1 0.91602h8a1 0.91667 0 0 0 1 -0.91602v-9.084a1 1 0 0 0 -1 -1h-8zm1 2h2v3l2-3h2l-2 3 2 4h-2l-2-4v4h-2v-7z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_light_occluder_2d.svg b/editor/icons/icon_light_occluder_2d.svg
index f7eb588e74..153de7eede 100644
--- a/editor/icons/icon_light_occluder_2d.svg
+++ b/editor/icons/icon_light_occluder_2d.svg
@@ -1,11 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5b7f3" fill-opacity=".98824">
-<rect x="1" y="1039.4" width="14" height="2"/>
-<rect x="1" y="1042.4" width="14" height="2"/>
-<rect x="1" y="1045.4" width="14" height="2"/>
-<rect x="1" y="1048.4" width="14" height="2"/>
-<rect x="2" y="1037.4" width="1" height="14"/>
-<rect x="13" y="1037.4" width="1" height="14"/>
-<rect x="1" y="1037.4" width="14" height=".99998"/>
+<g transform="translate(0 -1036.4)">
+<path d="m8 1037.4c-2.7614 0-5 2.2386-5 5 0.00253 1.9858 1.18 3.7819 3 4.5762v2.4238h4v-2.4199c1.8213-0.7949 2.999-2.5929 3-4.5801 0-2.7614-2.2386-5-5-5zm0 2v6c-1.6569 0-3-1.3431-3-3s1.3431-3 3-3zm-1 11v1h2v-1z" fill="#a5b7f3" fill-opacity=".98824"/>
</g>
</svg>
diff --git a/editor/icons/icon_line_edit.svg b/editor/icons/icon_line_edit.svg
index 209f0e1940..13a4f3c2c2 100644
--- a/editor/icons/icon_line_edit.svg
+++ b/editor/icons/icon_line_edit.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m1 11c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2h-2-10-2z"/>
-<rect x="2" y="1040.4" width="2" height="5"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m2 4v5h2v-5h-2zm-1 7c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2h-2-10-2z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_link_button.svg b/editor/icons/icon_link_button.svg
index f2fad1f259..0e13db7477 100644
--- a/editor/icons/icon_link_button.svg
+++ b/editor/icons/icon_link_button.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m6 7a0.99998 0.99998 0 0 0 -1 1 0.99998 0.99998 0 0 0 1 1h4a0.99998 0.99998 0 0 0 1 -1 0.99998 0.99998 0 0 0 -1 -1h-4z"/>
-<path transform="translate(0 1036.4)" d="m6 3a5 5 0 0 0 -4.3301 2.5 5 5 0 0 0 0 5 5 5 0 0 0 4.3301 2.5h1v-2h-1a3 3 0 0 1 -3 -3 3 3 0 0 1 3 -3h1v-2h-1zm3 0v2h1a3 3 0 0 1 3 3 3 3 0 0 1 -3 3h-1v2h1a5 5 0 0 0 4.3301 -2.5 5 5 0 0 0 0 -5 5 5 0 0 0 -4.3301 -2.5h-1z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m6 3a5 5 0 0 0 -4.3301 2.5 5 5 0 0 0 0 5 5 5 0 0 0 4.3301 2.5h1v-2h-1a3 3 0 0 1 -3 -3 3 3 0 0 1 3 -3h1v-2h-1zm3 0v2h1a3 3 0 0 1 3 3 3 3 0 0 1 -3 3h-1v2h1a5 5 0 0 0 4.3301 -2.5 5 5 0 0 0 0 -5 5 5 0 0 0 -4.3301 -2.5h-1zm-3 4a0.99998 0.99998 0 0 0 -1 1 0.99998 0.99998 0 0 0 1 1h4a0.99998 0.99998 0 0 0 1 -1 0.99998 0.99998 0 0 0 -1 -1h-4z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_list_select.svg b/editor/icons/icon_list_select.svg
index a37a4830f3..d619d84fd9 100644
--- a/editor/icons/icon_list_select.svg
+++ b/editor/icons/icon_list_select.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m1 1v14h8.2578l-0.82227-2h-5.4355v-2h4.6113l-0.82227-2h-3.7891v-2h3.8867a1.5002 1.5002 0 0 1 1.0977 -0.49805v-0.0019531a1.5002 1.5002 0 0 1 0.58594 0.11133l0.94531 0.38867h0.48438v0.19922l2 0.82227v-7.0215h-11zm2 2h7v2h-7v-2zm7.7559 7.7559l0.52344 1.2734a1.5002 1.5002 0 0 1 0.48047 -0.26953 1.5002 1.5002 0 0 1 0.24023 -0.43945v-0.050781l-1.2441-0.51367z" fill-opacity=".99608"/>
-<path d="m16 1047.7-8-3.291 3.291 8 0.9471-2.8201 1.8836 1.8835 0.9418-0.9418-1.8836-1.8835z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v14h8.2578l-0.82227-2h-5.4355v-2h4.6113l-0.82227-2h-3.7891v-2h3.8867a1.5002 1.5002 0 0 1 1.0977 -0.49805v-0.0019531a1.5002 1.5002 0 0 1 0.58594 0.11133l0.94531 0.38867h0.48438v0.19922l2 0.82227v-7.0215h-11zm2 2h7v2h-7v-2zm5 5l3.291 8 0.94726-2.8203 1.8828 1.8828 0.94336-0.94141-1.8848-1.8828 2.8203-0.94726-8-3.291z" fill="#e0e0e0" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_listener.svg b/editor/icons/icon_listener.svg
index 2b4b87e6d0..3624e5a085 100644
--- a/editor/icons/icon_listener.svg
+++ b/editor/icons/icon_listener.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m13.928 1038.4-1.7383 1.0039a6 6 0 0 1 0.81055 2.9961 6 6 0 0 1 -0.80859 2.998l1.7363 1.002a8 8 0 0 0 0 -8z" fill="#fc9c9c"/>
-<rect x="3" y="1049.4" width="1" height="2" fill="#fc9c9c"/>
-<path transform="translate(0 1036.4)" d="m6 1a5 5 0 0 0 -5 5h2a3 3 0 0 1 3 -3 3 3 0 0 1 3 3h2a5 5 0 0 0 -5 -5z" fill="#fc9c9c"/>
-<path d="m10 1042.4c0 4-3 4-3 5 0 3-2 3-3 3" fill="none" stroke="#fc9c9c" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m6 1a5 5 0 0 0 -5 5h2a3 3 0 0 1 3 -3 3 3 0 0 1 3 3c0 1.75-0.54175 2.3583-1.1406 2.8574-0.29944 0.2495-0.62954 0.44071-0.97656 0.69141-0.17351 0.1253-0.35729 0.26529-0.53711 0.49219-0.17982 0.227-0.3457 0.58398-0.3457 0.95898 0 1.2778-0.31632 1.5742-0.63867 1.7676-0.32236 0.1934-0.86133 0.23242-1.3613 0.23242h-1v2h1c0.5 0 1.461 0.038922 2.3887-0.51758 0.87316-0.5239 1.4826-1.6633 1.5566-3.2266 0.011365-0.0098 0.027247-0.024684 0.10938-0.083984 0.21547-0.1556 0.63537-0.40194 1.0859-0.77734 0.90112-0.751 1.8594-2.1445 1.8594-4.3945a5 5 0 0 0 -5 -5zm7.9277 1l-1.7383 1.0039a6 6 0 0 1 0.81055 2.9961 6 6 0 0 1 -0.80859 2.998l1.7363 1.002a8 8 0 0 0 0 -8z" fill="#fc9c9c"/>
</g>
</svg>
diff --git a/editor/icons/icon_lock.svg b/editor/icons/icon_lock.svg
index b0b0125648..1202f1d86f 100644
--- a/editor/icons/icon_lock.svg
+++ b/editor/icons/icon_lock.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m2 8v7h12v-7h-12zm5 2h2v3h-2v-3z"/>
-<path transform="translate(0 1036.4)" d="m8 1a5 5 0 0 0 -5 5h2a3 3 0 0 1 3 -3 3 3 0 0 1 3 3h2a5 5 0 0 0 -5 -5z"/>
-<rect x="3" y="1042.4" width="2" height="2"/>
-<rect x="11" y="1042.4" width="2" height="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1a5 5 0 0 0 -5 5v2h-1v7h12v-7h-1v-2a5 5 0 0 0 -5 -5zm0 2a3 3 0 0 1 3 3v2h-6v-2a3 3 0 0 1 3 -3zm-1 7h2v3h-2v-3z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_lock_viewport.svg b/editor/icons/icon_lock_viewport.svg
new file mode 100644
index 0000000000..54dc9f6b82
--- /dev/null
+++ b/editor/icons/icon_lock_viewport.svg
@@ -0,0 +1,6 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 0a6 6 0 0 0 -6 6v1h-1v9h14v-9h-1v-1a6 6 0 0 0 -6 -6zm0 4c1.1046 0 2 0.89543 2 2v1h-4v-1c0-1.1046 0.89543-2 2-2z" fill-opacity=".39216" stroke-linecap="round" stroke-linejoin="round" stroke-opacity=".98824" stroke-width="4"/>
+<path transform="translate(0 1036.4)" d="m8 1a5 5 0 0 0 -5 5v2h-1v7h12v-7h-1v-2a5 5 0 0 0 -5 -5zm0 2a3 3 0 0 1 3 3v2h-6v-2a3 3 0 0 1 3 -3zm-1 7h2v3h-2v-3z" fill="#e0e0e0"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_loop_interpolation.svg b/editor/icons/icon_loop_interpolation.svg
index ab2e564f78..247d01b113 100644
--- a/editor/icons/icon_loop_interpolation.svg
+++ b/editor/icons/icon_loop_interpolation.svg
@@ -1,10 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0" fill-opacity=".99608">
-<circle cx="3" cy="1048.4" r="2"/>
-<path transform="translate(0 1036.4)" d="m4 3a2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.0019531v0.046875 6.9531h2v-5-2h2v-2h-2z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<path d="m6 1037.4v6l4-3z" fill-rule="evenodd"/>
-<circle cx="13" cy="1040.4" r="2"/>
-<path transform="translate(0 1036.4)" d="m12 4v5 2h-2v2h2a2 2 0 0 0 1.7324 -1 2 2 0 0 0 0.26562 -1h0.001953v-7h-2z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<path d="m10 1045.4v6l-4-3z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m6 1v2h-2a2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.0019531v0.046875 5.2246a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -1 -1.7305v-3.2695-2h2v2l4-3-4-3zm7 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v3.2695 2h-2v-2l-4 3 4 3v-2h2a2 2 0 0 0 1.7324 -1 2 2 0 0 0 0.26562 -1h0.001953v-5.2715a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2z" fill="#e0e0e0" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_matrix.svg b/editor/icons/icon_matrix.svg
deleted file mode 100644
index e14566f816..0000000000
--- a/editor/icons/icon_matrix.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill="#ea686c">
-<rect x="1" y="1039.4" width="1" height="12"/>
-<rect x="1" y="1039.4" width="3" height="1"/>
-<rect x="1" y="1050.4" width="3" height="1"/>
-<rect x="10" y="1050.4" width="3" height="1"/>
-<rect x="10" y="1039.4" width="3" height="1"/>
-<rect x="12" y="1039.4" width="1" height="12"/>
-<rect x="3" y="1041.4" width="2" height="2"/>
-<rect x="6" y="1041.4" width="2" height="2"/>
-<rect x="9" y="1041.4" width="2" height="2"/>
-<rect x="3" y="1044.4" width="2" height="2"/>
-<rect x="6" y="1044.4" width="2" height="2"/>
-<rect x="9" y="1044.4" width="2" height="2"/>
-<rect x="3" y="1047.4" width="2" height="2"/>
-<rect x="6" y="1047.4" width="2" height="2"/>
-<rect x="9" y="1047.4" width="2" height="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_menu_button.svg b/editor/icons/icon_menu_button.svg
index 28fafcc465..fa24532f24 100644
--- a/editor/icons/icon_menu_button.svg
+++ b/editor/icons/icon_menu_button.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m1 1v4h14v-4h-14zm5 1h4l-2 2-2-2z"/>
-<path transform="translate(0 1036.4)" d="m2 6a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h12a1 1 0 0 0 1 -1v-7a1 1 0 0 0 -1 -1h-12zm1 2h10v2h-10v-2zm0 3h10v2h-10v-2z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v4h14v-4h-14zm5 1h4l-2 2-2-2zm-4 4a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h12a1 1 0 0 0 1 -1v-7a1 1 0 0 0 -1 -1h-12zm1 2h10v2h-10v-2zm0 3h10v2h-10v-2z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_mesh_instance.svg b/editor/icons/icon_mesh_instance.svg
index 12599bd78b..3342a3e06d 100644
--- a/editor/icons/icon_mesh_instance.svg
+++ b/editor/icons/icon_mesh_instance.svg
@@ -1,13 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<circle cx="3" cy="1049.4" r="2" fill="#fc9c9c" fill-opacity=".99608"/>
-<rect x="2" y="1039.4" width="2" height="8.5" fill="#fc9c9c" fill-opacity=".99608"/>
-<circle cx="3" cy="1039.4" r="2" fill="#fc9c9c" fill-opacity=".99608"/>
-<rect transform="rotate(90)" x="1038.4" y="-11.5" width="2" height="8.5" fill="#fc9c9c" fill-opacity=".99608"/>
-<circle cx="13" cy="1039.4" r="2" fill="#fc9c9c" fill-opacity=".99608"/>
-<rect x="12" y="1039.1" width="2" height="8.5" fill="#fc9c9c" fill-opacity=".99608"/>
-<circle cx="13" cy="1049.4" r="2" fill="#fc9c9c" fill-opacity=".99608"/>
-<rect transform="rotate(90)" x="1048.4" y="-12.25" width="2" height="8.5" fill="#fc9c9c" fill-opacity=".99608"/>
-<path d="m3 1039.4 10 10" fill="none" stroke="#fc9c9c" stroke-opacity=".99608" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m3 1a2 2 0 0 0 -2 2 2 2 0 0 0 1 1.7305v6.541a2 2 0 0 0 -1 1.7285 2 2 0 0 0 2 2 2 2 0 0 0 1.7305 -1h6.541a2 2 0 0 0 1.7285 1 2 2 0 0 0 2 -2 2 2 0 0 0 -1.0312 -1.75h0.03125v-6.5215a2 2 0 0 0 1 -1.7285 2 2 0 0 0 -2 -2 2 2 0 0 0 -1.7305 1h-6.541a2 2 0 0 0 -1.7285 -1zm2.4141 3h5.8574a2 2 0 0 0 0.72852 0.73047v5.8555l-6.5859-6.5859zm-1.4141 1.4141l6.5859 6.5859h-5.8574a2 2 0 0 0 -0.72852 -0.73047v-5.8555z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_aabb.svg b/editor/icons/icon_mini_aabb.svg
index d9c710ee1c..1af05f9b68 100644
--- a/editor/icons/icon_mini_aabb.svg
+++ b/editor/icons/icon_mini_aabb.svg
@@ -1,10 +1,6 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<path d="m5 1041.4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6h-2zm0 2v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#ee7991"/>
-<path d="m3 1046.4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6h-2zm0 2v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#f39bad"/>
-<path d="m13 1043.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z" fill="#ee7991"/>
-<path d="m13 1049.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z" fill="#ee7991"/>
-<rect transform="matrix(0,1,1,0,0,0)" x="1041.4" y="11" width="8" height="2" fill="#ee7991"/>
-<path d="m8 1044.4v8h2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3v-2h-2zm2 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2z" fill="#f39bad"/>
+<path transform="translate(0 1040.4)" d="m5 1a3 3 0 0 0 -3 3 3 3 0 0 0 0.77734 2.0117 3 3 0 0 0 -2.7773 2.9883 3 3 0 0 0 3 3h2v-5h2v-6h-2zm6 0v5.1738a3 3 0 0 0 -1 -0.17383v-2h-2v8h2a3 3 0 0 0 3 -3 3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3v-2h-2zm-6 2v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm8 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2zm-10 3v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm7 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2z" fill="#ee7991"/>
+<path transform="translate(0 1040.4)" d="m8 4v8h2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3v-2h-2zm-5 2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6h-2zm0 2v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm7 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2z" fill="#fff" fill-opacity=".23529"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_array.svg b/editor/icons/icon_mini_array.svg
index a1ec948063..4a279bf87b 100644
--- a/editor/icons/icon_mini_array.svg
+++ b/editor/icons/icon_mini_array.svg
@@ -1,13 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#e0e0e0">
-<rect x="11" y="1047.4" width="2" height="3"/>
-<path d="m14 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<rect x="7" y="1047.4" width="2" height="3"/>
-<path d="m10 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<path d="m4 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path d="m4 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="4" y="-1050.4" width="2" height="6"/>
-<rect x="10" y="1044.4" width="1" height="2"/>
-<rect x="14" y="1044.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m4 4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6h-2zm6 0a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1 -1h1v-2h-1zm4 0a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1 -1h1v-2h-1zm-10 2v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_basis.svg b/editor/icons/icon_mini_basis.svg
index e0dc132d12..21b4f29aa4 100644
--- a/editor/icons/icon_mini_basis.svg
+++ b/editor/icons/icon_mini_basis.svg
@@ -1,19 +1,6 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<rect transform="scale(-1,1)" x="-2" y="1044.4" width="2" height="6" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-2" y="1044.4" width="1" height="2" fill="#e3ec69"/>
-<path d="m2 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1z" fill="#e3ec69"/>
-<path d="m2 1050.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1z" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-2" y="1042.4" width="2" height="3.9999" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-9" y="1044.4" width="2" height="2" fill="#e3ec69"/>
-<path d="m7 1048.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#e3ec69"/>
-<path transform="scale(-1,1)" d="m-7 1050.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-7" y="1048.4" width="2" height="2" fill="#e3ec69"/>
-<rect x="10" y="1046.4" width="2" height="3.9999" fill="#eef39f"/>
-<rect x="10" y="1042.4" width="2" height="2" fill="#eef39f"/>
-<rect transform="scale(-1,1)" x="-16" y="1044.4" width="2" height="2" fill="#e3ec69"/>
-<path d="m14 1048.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#e3ec69"/>
-<path transform="scale(-1,1)" d="m-14 1050.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-14" y="1048.4" width="2" height="2" fill="#e3ec69"/>
+<path transform="translate(0 1040.4)" d="m0 2v4 4h2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3v-2h-2zm10 0v2h2v-2h-2zm-3 2a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v2h2a2 2 0 0 0 1.7324 -1 2 2 0 0 0 0 -2 2 2 0 0 0 -1.7324 -1h2v-2h-2zm7 0a2 2 0 0 0 -1.7324 1 2 2 0 0 0 0 2 2 2 0 0 0 1.7324 1h-2v-2h-2v4h2 2a2 2 0 0 0 1.7324 -1 2 2 0 0 0 0 -2 2 2 0 0 0 -1.7324 -1h2v-2h-2zm-12 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2z" fill="#e3ec69"/>
+<path d="m10 1042.4v2h2v-2zm0 4v4h2v-4z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_boolean.svg b/editor/icons/icon_mini_boolean.svg
index b8861c9f17..b1e169d73c 100644
--- a/editor/icons/icon_mini_boolean.svg
+++ b/editor/icons/icon_mini_boolean.svg
@@ -1,13 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#8da6f0">
-<rect transform="scale(-1,1)" x="-2" y="1044.4" width="2" height="6"/>
-<rect transform="scale(-1,1)" x="-2" y="1044.4" width="1" height="2"/>
-<path d="m2 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="13" y="-1047.4" width="2" height="5"/>
-<path d="m2 1050.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z"/>
-<rect transform="scale(-1,1)" x="-2" y="1042.4" width="2" height="3.9999"/>
-<path d="m16 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path d="m7 1044.4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3zm0 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z"/>
-<path d="m11 1044.4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3zm0 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m0 2v4 4h2a3 3 0 0 0 2.5 -1.3457 3 3 0 0 0 2.5 1.3457 3 3 0 0 0 2 -0.76758 3 3 0 0 0 2 0.76758 3 3 0 0 0 2.5 -1.3457 3 3 0 0 0 2.5 1.3457v-2a1 1 0 0 1 -1 -1v-5h-2v2.7695a3 3 0 0 0 -2 -0.76953 3 3 0 0 0 -2 0.76758 3 3 0 0 0 -2 -0.76758 3 3 0 0 0 -2.5 1.3457 3 3 0 0 0 -2.5 -1.3457v-2h-2zm2 4a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#8da6f0"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_dictionary.svg b/editor/icons/icon_mini_dictionary.svg
index eb68709c4f..814f27e2f9 100644
--- a/editor/icons/icon_mini_dictionary.svg
+++ b/editor/icons/icon_mini_dictionary.svg
@@ -1,16 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#77edb1">
-<rect transform="scale(1,-1)" x="13" y="-1047.4" width="2" height="5"/>
-<rect transform="scale(1,-1)" x="15" y="-1046.4" width="1" height="2"/>
-<path d="m16 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path d="m11 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<path d="m11 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect x="6" y="1046.4" width="2" height="3.9999"/>
-<rect x="6" y="1042.4" width="2" height="2"/>
-<path d="m3 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<path d="m3 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect x="3" y="1042.4" width="2" height="8"/>
-<rect x="11" y="1044.4" width="1" height="2"/>
-<rect x="11" y="1048.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m3 2v2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-8h-2zm3 0v2h2v-2h-2zm7 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2zm-2 2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1h1v-2h-1zm-3 3v-1h-2v4h2v-3zm-5-1v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#77edb1"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_float.svg b/editor/icons/icon_mini_float.svg
index 2eb71fd85e..68f09ef07a 100644
--- a/editor/icons/icon_mini_float.svg
+++ b/editor/icons/icon_mini_float.svg
@@ -1,15 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#61daf4">
-<rect y="1045.4" width="2" height="5"/>
-<rect x="2" y="1046.4" width="2" height="2"/>
-<path d="m3 1042.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="6" y="-1047.4" width="2" height="5"/>
-<path d="m9 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect transform="scale(1,-1)" x="12" y="-1047.4" width="2" height="5"/>
-<path d="m15 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect x="9" y="1048.4" width="1" height="2"/>
-<rect x="14" y="1044.4" width="2" height="2"/>
-<rect x="15" y="1048.4" width="1" height="2"/>
-<rect x="3" y="1042.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m3 2a3 3 0 0 0 -3 3v5h2v-2h2v-2h-2v-1a1 1 0 0 1 1 -1h1v-2h-1zm3 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1v-5h-2zm6 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1v-1h2v-2h-2v-2h-2z" fill="#61daf4"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_float_array.svg b/editor/icons/icon_mini_float_array.svg
index 284b5911b7..3e3c88cc99 100644
--- a/editor/icons/icon_mini_float_array.svg
+++ b/editor/icons/icon_mini_float_array.svg
@@ -1,13 +1,7 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<rect y="1050.4" width="4" height="2" fill="#e0e0e0"/>
-<rect y="1040.4" width="2" height="12" fill="#e0e0e0"/>
-<rect y="1040.4" width="4" height="2" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1050.4" width="4" height="2" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1040.4" width="2" height="12" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1040.4" width="4" height="2" fill="#e0e0e0"/>
-<path d="m6 1042.4a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1 -1v-2z" fill="#61daf4"/>
-<path d="m10 1042.4v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2z" fill="#61daf4"/>
-<path d="m7 1042.4v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-5h-2z" fill="#c6f2fb"/>
+<path transform="translate(0 1040.4)" d="m0 0v2 8 2h4v-2h-2v-8h2v-2h-2-2zm12 0v2h2v8h-2v2h4v-2-10h-4z" fill="#e0e0e0"/>
+<path transform="translate(0 1040.4)" d="m6 2a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1 -1v-2zm1 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-5h-2zm3 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2z" fill="#61daf4"/>
+<path d="m7 1042.4v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-5h-2z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_image.svg b/editor/icons/icon_mini_image.svg
index a3f273078c..735cb563cb 100644
--- a/editor/icons/icon_mini_image.svg
+++ b/editor/icons/icon_mini_image.svg
@@ -1,17 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#93f1b9">
-<rect y="1045.4" width="2" height="3.9999"/>
-<rect x="3" y="1043.4" width="2" height="6"/>
-<path d="m5 1043.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect x="6" y="1046.4" width="2" height="3"/>
-<rect y="1041.4" width="2" height="2"/>
-<rect x="6" y="1043.4" width="2" height="6"/>
-<path d="m8 1043.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect x="9" y="1046.4" width="2" height="3"/>
-<path d="m14 1049.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path d="m14 1043.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="14" y="-1049.4" width="2" height="6"/>
-<path d="m13 1052.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z"/>
-<rect x="12" y="1050.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m0 1v2h2v-2h-2zm3 2v6h2v-4a1 1 0 0 1 1 1v3h2v-3-1a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3h-2v0.17578a3 3 0 0 0 -1 -0.17578h-2zm8 3a3 3 0 0 0 3 3 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3 -3v-6h-2a3 3 0 0 0 -3 3zm-11-1v4h2v-4h-2zm14 0v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#93f1b9"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_input.svg b/editor/icons/icon_mini_input.svg
index c64db97127..92cf763cf8 100644
--- a/editor/icons/icon_mini_input.svg
+++ b/editor/icons/icon_mini_input.svg
@@ -1,15 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#adf18f">
-<path d="m10 1050.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z"/>
-<path d="m10 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect transform="scale(-1)" x="-10" y="-1052.4" width="2" height="8"/>
-<rect y="1046.4" width="2" height="3.9999"/>
-<rect x="3" y="1044.4" width="2" height="6"/>
-<path d="m5 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect x="6" y="1047.4" width="2" height="3"/>
-<rect y="1042.4" width="2" height="2"/>
-<rect transform="scale(1,-1)" x="13" y="-1047.4" width="2" height="5"/>
-<rect transform="scale(1,-1)" x="15" y="-1046.4" width="1" height="2"/>
-<path d="m16 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m0 2v2h2v-2h-2zm13 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2zm0 5a3 3 0 0 0 -3 -3h-2v3a3 3 0 0 0 -3 -3h-2v6h2v-4a1 1 0 0 1 1 1v3h2v2h2v-2a3 3 0 0 0 3 -3zm-13-1v4h2v-4h-2zm10 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2z" fill="#adf18f"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_int_array.svg b/editor/icons/icon_mini_int_array.svg
index e5d4d97a90..04957c8d4b 100644
--- a/editor/icons/icon_mini_int_array.svg
+++ b/editor/icons/icon_mini_int_array.svg
@@ -1,8 +1,7 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
<path transform="translate(0 1040.4)" d="m0 0v2 8 2h2 2v-2h-2v-8h2v-2h-4zm12 0v2h2v8h-2v2h4v-2-8-2h-2-2z" fill="#e0e0e0"/>
-<path transform="translate(0 1040.4)" d="m3 2v2h2v-2h-2zm0 4v4h2v-4h-2z" fill="#7dc6ef"/>
-<path transform="translate(0 1040.4)" d="m5 4v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3h-2z" fill="#c8e7f9"/>
-<path transform="translate(0 1040.4)" d="m10 2v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2z" fill="#7dc6ef"/>
+<path transform="translate(0 1040.4)" d="m3 2v2h2v-2h-2zm2 2v2h-2v4h2 2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3h-2zm5 3a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2v5z" fill="#7dc6ef"/>
+<path transform="translate(0 1040.4)" d="m5 4v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3h-2z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_integer.svg b/editor/icons/icon_mini_integer.svg
index 05d09d9823..3bfe95980d 100644
--- a/editor/icons/icon_mini_integer.svg
+++ b/editor/icons/icon_mini_integer.svg
@@ -1,14 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#7dc6ef">
-<rect x="1" y="1046.4" width="2" height="3.9999"/>
-<rect x="4" y="1044.4" width="2" height="6"/>
-<path d="m7 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect x="8" y="1047.4" width="2" height="3"/>
-<rect x="1" y="1042.4" width="2" height="2"/>
-<rect transform="scale(1,-1)" x="12" y="-1047.4" width="2" height="5"/>
-<rect transform="scale(1,-1)" x="14" y="-1046.4" width="2" height="2"/>
-<path d="m15 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect x="5" y="1044.4" width="2" height="2"/>
-<rect transform="scale(1,-1)" x="15" y="-1050.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m1 2v2h2v-2h-2zm11 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1v-1h2v-2h-2v-2h-2zm-8 2v6h2v-4h1a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3h-1-2zm-3 2v4h2v-4h-2z" fill="#7dc6ef"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_matrix3.svg b/editor/icons/icon_mini_matrix3.svg
deleted file mode 100644
index e0dc132d12..0000000000
--- a/editor/icons/icon_mini_matrix3.svg
+++ /dev/null
@@ -1,19 +0,0 @@
-<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)">
-<rect transform="scale(-1,1)" x="-2" y="1044.4" width="2" height="6" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-2" y="1044.4" width="1" height="2" fill="#e3ec69"/>
-<path d="m2 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1z" fill="#e3ec69"/>
-<path d="m2 1050.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1z" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-2" y="1042.4" width="2" height="3.9999" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-9" y="1044.4" width="2" height="2" fill="#e3ec69"/>
-<path d="m7 1048.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#e3ec69"/>
-<path transform="scale(-1,1)" d="m-7 1050.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-7" y="1048.4" width="2" height="2" fill="#e3ec69"/>
-<rect x="10" y="1046.4" width="2" height="3.9999" fill="#eef39f"/>
-<rect x="10" y="1042.4" width="2" height="2" fill="#eef39f"/>
-<rect transform="scale(-1,1)" x="-16" y="1044.4" width="2" height="2" fill="#e3ec69"/>
-<path d="m14 1048.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#e3ec69"/>
-<path transform="scale(-1,1)" d="m-14 1050.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#e3ec69"/>
-<rect transform="scale(-1,1)" x="-14" y="1048.4" width="2" height="2" fill="#e3ec69"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_mini_object.svg b/editor/icons/icon_mini_object.svg
index 8cbbfa2808..a59808b970 100644
--- a/editor/icons/icon_mini_object.svg
+++ b/editor/icons/icon_mini_object.svg
@@ -1,11 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#79f3e8">
-<path d="m8 1050.4a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3v-2h-2v8h2zm0-2v-2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1z"/>
-<path d="m3 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path d="m3 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<path d="m15 1044.4v5a3 3 0 0 1 -3 3v-2a1 1 0 0 0 1 -1v-5h2z"/>
-<path d="m3 1050.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z"/>
-<path d="m3 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect x="11" y="1050.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m6 2v5 3h2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3v-2h-2zm0 5a3 3 0 0 0 -3 -3 3 3 0 0 0 -3 3 3 3 0 0 0 3 3 3 3 0 0 0 3 -3zm7-3v5a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3 -3v-5h-2zm-10 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm5 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2z" fill="#79f3e8"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_path.svg b/editor/icons/icon_mini_path.svg
index d09f56e753..4c99ad8cc0 100644
--- a/editor/icons/icon_mini_path.svg
+++ b/editor/icons/icon_mini_path.svg
@@ -1,14 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#6993ec">
-<rect transform="scale(1,-1)" x="6" y="-1047.4" width="2" height="5"/>
-<rect transform="scale(1,-1)" x="8" y="-1046.4" width="2" height="2"/>
-<path d="m9 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect transform="scale(1,-1)" x="11" y="-1050.4" width="2" height="8"/>
-<path d="m13 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="14" y="-1050.4" width="2" height="3"/>
-<path d="m2 1048.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z"/>
-<path d="m2 1042.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect transform="scale(-1)" x="-2" y="-1050.4" width="2" height="8"/>
-<rect transform="scale(1,-1)" x="9" y="-1050.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m0 2v8h2v-2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3h-2zm6 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1v-1h2v-2h-2v-2h-2zm5 0v8h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3v-2h-2zm-9 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2z" fill="#6993ec"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_plane.svg b/editor/icons/icon_mini_plane.svg
index 5d2ee937c0..e02fded99f 100644
--- a/editor/icons/icon_mini_plane.svg
+++ b/editor/icons/icon_mini_plane.svg
@@ -1,12 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#f77070">
-<path d="m3 1048.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z"/>
-<path d="m3 1042.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect transform="scale(-1)" x="-3" y="-1050.4" width="2" height="8"/>
-<rect transform="scale(1,-1)" x="7" y="-1047.4" width="2" height="5"/>
-<path d="m10 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect x="11" y="1044.4" width="2" height="6"/>
-<path d="m13 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect x="14" y="1047.4" width="2" height="3"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m1 2v8h2v-2a3 3 0 0 0 3 -3 3 3 0 0 0 -3 -3h-2zm6 0v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-5h-2zm-4 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v-2zm8 0v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3h-2z" fill="#f77070"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_quat.svg b/editor/icons/icon_mini_quat.svg
index 7baaf44089..c705fae2b6 100644
--- a/editor/icons/icon_mini_quat.svg
+++ b/editor/icons/icon_mini_quat.svg
@@ -1,12 +1,7 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<path d="m3 1049.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z" fill="#ec69a3"/>
-<path d="m3 1043.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z" fill="#ec69a3"/>
-<rect transform="scale(1,-1)" x="3" y="-1051.4" width="2" height="8" fill="#ec69a3"/>
-<rect transform="scale(1,-1)" x="13" y="-1046.4" width="2" height="5" fill="#ec69a3"/>
-<rect transform="scale(1,-1)" x="15" y="-1045.4" width="1" height="2" fill="#ec69a3"/>
-<path d="m16 1049.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z" fill="#ec69a3"/>
-<path d="m4 1043.4v3a3 3 0 0 0 3 3h2v-6h-2v4a1 1 0 0 1 -1 -1v-3h-2z" fill="#f298c0"/>
-<path transform="translate(0 1040.4)" d="m11 3a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6h-2zm0 2v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#ec69a3"/>
+<path transform="translate(0 1040.4)" d="m3 3a3 3 0 0 0 -3 3 3 3 0 0 0 3 3v2h2v-2.7695a3 3 0 0 0 2 0.76953h2v-6h-2v4a1 1 0 0 1 -1 -1v-3h-1-1-1zm0 2v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#ec69a3"/>
+<path d="m4 1043.4v3a3 3 0 0 0 3 3h2v-6h-2v4a1 1 0 0 1 -1 -1v-3z" fill="#fff" fill-opacity=".39216"/>
+<path transform="translate(0 1040.4)" d="m13 1v2h-2a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-3a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2zm-2 4v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#ec69a3"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_raw_array.svg b/editor/icons/icon_mini_raw_array.svg
index 827e60d0e3..ebd6c9a225 100644
--- a/editor/icons/icon_mini_raw_array.svg
+++ b/editor/icons/icon_mini_raw_array.svg
@@ -1,9 +1,7 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
<path transform="translate(0 1040.4)" d="m0 0v2 8 2h4v-2h-2v-8h2v-2h-2-2zm12 0v2h2v8h-2v2h4v-2-8-2h-2-2z" fill="#e0e0e0"/>
-<rect x="2" y="1046.4" width="2" height="3" fill="#69ec9e"/>
-<rect x="5" y="1043.4" width="1" height="2" fill="#69ec9e"/>
-<path d="m5 1043.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z" fill="#69ec9e"/>
-<path d="m6 1049.4v-6h2v4a1 1 0 0 0 1 -1v-3h2v3 1a1 1 0 0 0 1 -1v-3h2v3a3 3 0 0 1 -3 3h-2v-0.1758a3 3 0 0 1 -1 0.1758h-2z" fill="#aaf4c8"/>
+<path transform="translate(0 1040.4)" d="m5 3a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1 -1h1v4h2a3 3 0 0 0 1 -0.17578v0.17578h2a3 3 0 0 0 3 -3v-3h-2v3a1 1 0 0 1 -1 1v-1-3h-2v3a1 1 0 0 1 -1 1v-4h-2-1z" fill="#69ec9e"/>
+<path d="m6 1049.4v-6h2v4a1 1 0 0 0 1 -1v-3h2v3 1a1 1 0 0 0 1 -1v-3h2v3a3 3 0 0 1 -3 3h-2v-0.1758a3 3 0 0 1 -1 0.1758h-2z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_rect2.svg b/editor/icons/icon_mini_rect2.svg
index d9e9413185..9dec66dfa1 100644
--- a/editor/icons/icon_mini_rect2.svg
+++ b/editor/icons/icon_mini_rect2.svg
@@ -1,19 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#f191a5">
-<rect y="1047.4" width="2" height="3"/>
-<path d="m3 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="13" y="-1047.4" width="2" height="5"/>
-<rect transform="scale(1,-1)" x="15" y="-1046.4" width="1" height="2"/>
-<path d="m16 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path d="m7 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="7" y="-1050.4" width="1" height="2"/>
-<path d="m7 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect x="12" y="1044.4" width="1" height="2"/>
-<path d="m12 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="12" y="-1050.4" width="1" height="2"/>
-<path d="m12 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path d="m7 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect x="6" y="1046.4" width="2" height="1"/>
-<rect transform="scale(1,-1)" x="3" y="-1046.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m13 2v2h-1a3 3 0 0 0 -2.5 1.3457 3 3 0 0 0 -2.5 -1.3457 3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1h2 1a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1h1v1a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2zm-10 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1 -1h1v-2h-1z" fill="#f191a5"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_rid.svg b/editor/icons/icon_mini_rid.svg
index 3fe12d0819..f1709a5acc 100644
--- a/editor/icons/icon_mini_rid.svg
+++ b/editor/icons/icon_mini_rid.svg
@@ -1,14 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#69ec9a">
-<rect x="1" y="1047.4" width="2" height="3"/>
-<rect x="7" y="1042.4" width="2" height="1.9999"/>
-<rect x="7" y="1046.4" width="2" height="4"/>
-<rect x="4" y="1044.4" width="1" height="2"/>
-<path d="m4 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<path d="m13 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<path d="m13 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect x="14" y="1042.4" width="2" height="8"/>
-<rect x="13" y="1044.4" width="1" height="2"/>
-<rect x="13" y="1048.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m7 2v2h2v-2h-2zm7 0v2h-1a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h1 2v-8h-2zm-10 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1 -1h1v-2h-1zm3 2v4h2v-4h-2zm6 0h1v2h-1a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#69ec9a"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_string.svg b/editor/icons/icon_mini_string.svg
index 7212058fe6..17e565cd75 100644
--- a/editor/icons/icon_mini_string.svg
+++ b/editor/icons/icon_mini_string.svg
@@ -1,12 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#6ba7ec">
-<path d="m5 1042.4a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1v2a3 3 0 0 0 3 -3v-2a1 1 0 0 1 1 -1v-2z"/>
-<rect transform="scale(1,-1)" x="7" y="-1047.4" width="2" height="5"/>
-<rect transform="scale(1,-1)" x="9" y="-1046.4" width="2" height="2"/>
-<path d="m10 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path transform="translate(0 1040.4)" d="m15 4a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1 -1h1v-2h-1z"/>
-<rect y="1048.4" width="1" height="2"/>
-<rect x="5" y="1042.4" width="1" height="2"/>
-<rect transform="scale(1,-1)" x="10" y="-1050.4" width="1" height="2"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m5 2a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3 -3v-2a1 1 0 0 1 1 -1h1v-2h-1zm2 0v5a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1v-1h2v-2h-2v-2h-2zm8 2a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1 -1h1v-2h-1z" fill="#6ba7ec"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_string_array.svg b/editor/icons/icon_mini_string_array.svg
index e0b927d3a9..af81cabce4 100644
--- a/editor/icons/icon_mini_string_array.svg
+++ b/editor/icons/icon_mini_string_array.svg
@@ -1,10 +1,7 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
<path transform="translate(0 1040.4)" d="m0 0v2 8 2h2 2v-2h-2v-8h2v-2h-2-2zm12 0v2h2v8h-2v2h4v-2-10h-4z" fill="#e0e0e0"/>
-<path d="m7 1042.4a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1v2a3 3 0 0 0 3 -3v-2a1 1 0 0 1 1 -1v-2z" fill="#6ba7ec"/>
-<path d="m14 1044.4a3 3 0 0 0 -3 3v3h2v-3a1 1 0 0 1 1 -1v-2z" fill="#6ba7ec"/>
-<path d="m8 1042.4v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2z" fill="#b5d3f6"/>
-<rect x="7" y="1042.4" width="1" height="2" fill="#6ba7ec"/>
-<rect x="2" y="1048.4" width="1" height="2" fill="#6ba7ec"/>
+<path transform="translate(0 1040.4)" d="m7 2a3 3 0 0 0 -3 3v2a1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 3 -3v-2a1 1 0 0 1 1 -1h1v3a3 3 0 0 0 3 3h2v-3a1 1 0 0 1 1 -1v-2a3 3 0 0 0 -3 3v1a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2-1z" fill="#6ba7ec"/>
+<path d="m8 1042.4v5a3 3 0 0 0 3 3v-2a1 1 0 0 1 -1 -1v-1h1v-2h-1v-2h-2z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_transform.svg b/editor/icons/icon_mini_transform.svg
index 43c4bb4a8f..53bad91efc 100644
--- a/editor/icons/icon_mini_transform.svg
+++ b/editor/icons/icon_mini_transform.svg
@@ -1,7 +1,6 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<path d="m4 1042.4-0.9082 2.1816-1.0918-2.1816h-2l2 4-2 4h2l0.9082-2.1816 1.0918 2.1816h2l-2-4 2-4z" fill="#f6a86e"/>
-<path d="m9 1042.4a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1 -1h1v-2h-1z" fill="#f8bf95"/>
-<path transform="translate(0 1040.4)" d="m10 4v2 2 2h2v-2l1 1 1-1v2h2v-2-2-2h-2l-1 2-1-2h-2z" fill="#f6a86e"/>
+<path transform="translate(0 1040.4)" d="m0 2l2 4-2 4h2l0.9082-2.1816 1.0918 2.1816h2l-2-4 2-4h-2l-0.9082 2.1816-1.0918-2.1816h-2zm6 8h2v-2h1v-2h-1v-1a1 1 0 0 1 1 -1h1v-2h-1a3 3 0 0 0 -3 3v5zm4-6v2 2 2h2v-2l1 1 1-1v2h2v-2-2-2h-2l-1 2-1-2h-2z" fill="#f6a86e"/>
+<path d="m9 1042.4a3 3 0 0 0 -3 3v5h2v-2h1v-2h-1v-1a1 1 0 0 1 1 -1h1v-2h-1z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_transform2D.svg b/editor/icons/icon_mini_transform2D.svg
index 38921ea85a..b4723d37c4 100644
--- a/editor/icons/icon_mini_transform2D.svg
+++ b/editor/icons/icon_mini_transform2D.svg
@@ -1,10 +1,6 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<rect x="5" y="1048.4" width="5" height="2" fill="#ddf4aa"/>
-<path d="m7 1050.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#ddf4aa"/>
-<path d="m7 1042.4v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v2a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5z" fill="#ddf4aa"/>
-<rect y="1042.4" width="6" height="2" fill="#c4ec69"/>
-<rect x="2" y="1043.4" width="2" height="7" fill="#c4ec69"/>
-<path transform="translate(0 1040.4)" d="m10 2v8h2a4 4 0 0 0 3.4648 -2 4 4 0 0 0 0 -4 4 4 0 0 0 -3.4648 -2h-2zm2 2a2 2 0 0 1 1.7324 1 2 2 0 0 1 0 2 2 2 0 0 1 -1.7324 1v-4z" fill="#c4ec69"/>
+<path transform="translate(0 1040.4)" d="m0 2v2h2v6h2v-6h2v-2h-6zm7 0v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.0019531v0.046875 1.9531h2 3 2a4 4 0 0 0 3.4648 -2 4 4 0 0 0 0 -4 4 4 0 0 0 -3.4648 -2h-2v6h-3a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5zm5 2a2 2 0 0 1 1.7324 1 2 2 0 0 1 0 2 2 2 0 0 1 -1.7324 1v-4z" fill="#c4ec69"/>
+<path transform="translate(0 1040.4)" d="m7 2v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.0019531v0.046875 1.9531h2 3v-2h-3a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_variant.svg b/editor/icons/icon_mini_variant.svg
index aeb23ed2bc..4b9a2a5f18 100644
--- a/editor/icons/icon_mini_variant.svg
+++ b/editor/icons/icon_mini_variant.svg
@@ -1,14 +1,5 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="#69ecbd">
-<rect x="3" y="1044.4" width="2" height="6"/>
-<rect x="6" y="1044.4" width="2" height="6"/>
-<rect x="3" y="1044.4" width="1" height="2"/>
-<path d="m3 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z"/>
-<path d="m14 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<rect transform="scale(1,-1)" x="14" y="-1052.4" width="2" height="8"/>
-<rect transform="scale(1,-1)" x="11" y="-1047.4" width="2" height="3"/>
-<path d="m3 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z"/>
-<path d="m8 1044.4a3 3 0 0 1 3 3h-2a1 1 0 0 0 -1 -1v-2z"/>
-<rect x="9" y="1047.4" width="2" height="3"/>
+<g transform="translate(0 -1040.4)">
+<path transform="translate(0 1040.4)" d="m3 4a3 3 0 0 0 -3 3 3 3 0 0 0 3 3h2v-6h-2zm3 0v6h2v-4a1 1 0 0 1 1 1v3h2v-3a3 3 0 0 0 -3 -3h-2zm5 3a3 3 0 0 0 3 3v2h2v-8h-2v4a1 1 0 0 1 -1 -1v-3h-2v3zm-8-1v2a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#69ecbd"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_vector2.svg b/editor/icons/icon_mini_vector2.svg
index 7abc73c41f..907e6ba84d 100644
--- a/editor/icons/icon_mini_vector2.svg
+++ b/editor/icons/icon_mini_vector2.svg
@@ -1,15 +1,6 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<path d="m3 1050.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z" fill="#bd91f1"/>
-<rect x="4" y="1044.4" width="2" height="3" fill="#bd91f1"/>
-<rect x="11" y="1048.4" width="5" height="2" fill="#dcc5f8"/>
-<rect x="1" y="1044.4" width="2" height="6" fill="#bd91f1"/>
-<rect x="9" y="1044.4" width="1" height="2" fill="#bd91f1"/>
-<path d="m9 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z" fill="#bd91f1"/>
-<rect transform="scale(1,-1)" x="9" y="-1050.4" width="1" height="2" fill="#bd91f1"/>
-<path d="m9 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z" fill="#bd91f1"/>
-<path d="m13 1050.4a2 2 0 0 1 -1.7321 -1 2 2 0 0 1 0 -2 2 2 0 0 1 1.7321 -1" fill="#dcc5f8"/>
-<path d="m13 1042.4v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v2a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5z" fill="#dcc5f8"/>
-<rect x="12" y="1042.4" width="1" height="2" fill="#dcc5f8"/>
+<path transform="translate(0 1040.4)" d="m12 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.001953v2h5v-2h-3a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5h-1zm-11 2v6h2a3 3 0 0 0 3 -3v-3h-2v3a1 1 0 0 1 -1 1v-4h-2zm5 3a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1h1v-2h-1a3 3 0 0 0 -3 3z" fill="#bd91f1"/>
+<path transform="translate(0 1040.4)" d="m12 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.001953v2h5v-2h-3a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5h-1z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_vector2_array.svg b/editor/icons/icon_mini_vector2_array.svg
index 0070144ca5..e05eefc46a 100644
--- a/editor/icons/icon_mini_vector2_array.svg
+++ b/editor/icons/icon_mini_vector2_array.svg
@@ -1,12 +1,7 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<rect y="1050.4" width="4" height="2" fill="#e0e0e0"/>
-<rect y="1040.4" width="2" height="12" fill="#e0e0e0"/>
-<rect y="1040.4" width="4" height="2" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1050.4" width="4" height="2" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1040.4" width="2" height="12" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1040.4" width="4" height="2" fill="#e0e0e0"/>
-<path transform="translate(0 1040.4)" d="m3 3v6h2a3 3 0 0 0 3 -3v-3h-2v3a1 1 0 0 1 -1 1v-4h-2z" fill="#bd91f1"/>
-<path d="m9 1042.4v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.00195v0.047 1.9531h2 3v-2h-3a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5001h-1z" fill="#dcc5f8"/>
+<path transform="translate(0 1040.4)" d="m0 0v2 10h2 2v-2h-2v-8h2v-2h-2-2zm12 0v2h2v8h-2v2h4v-2-10h-4z" fill="#e0e0e0"/>
+<path transform="translate(0 1040.4)" d="m9 2v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.0019531v0.046875 1.9531h2 3v-2h-3a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5h-1zm-6 1v6h2a3 3 0 0 0 3 -3v-3h-2v3a1 1 0 0 1 -1 1v-4h-2z" fill="#bd91f1"/>
+<path d="m9 1042.4v2h1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 2 2 0 0 0 -1.7324 1 2 2 0 0 0 -0.26562 1h-0.00195v0.047 1.9531h2 3v-2h-3a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5001h-1z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_vector3.svg b/editor/icons/icon_mini_vector3.svg
index 88b6f1f53c..be1f8ec360 100644
--- a/editor/icons/icon_mini_vector3.svg
+++ b/editor/icons/icon_mini_vector3.svg
@@ -1,15 +1,6 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<path d="m3.0004 1050.4a3 3 0 0 0 3 -3h-2a1 1 0 0 1 -1 1v2z" fill="#e286f0"/>
-<rect x="4.0004" y="1044.4" width="2" height="3" fill="#e286f0"/>
-<rect x="1.0004" y="1044.4" width="2" height="6" fill="#e286f0"/>
-<rect x="9.0004" y="1044.4" width="1" height="2" fill="#e286f0"/>
-<path d="m9.0004 1044.4a3 3 0 0 0 -3 3h2a1 1 0 0 1 1 -1v-2z" fill="#e286f0"/>
-<rect transform="scale(1,-1)" x="9.0004" y="-1050.4" width="1" height="2" fill="#e286f0"/>
-<path d="m9.0004 1050.4a3 3 0 0 1 -3 -3h2a1 1 0 0 0 1 1v2z" fill="#e286f0"/>
-<path transform="translate(0 1040.4)" d="m13 2v1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v2a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -0.36328 -0.5h-2.2344z" fill="#eeb9f6"/>
-<rect x="12" y="1042.4" width="3.9996" height="2" fill="#eeb9f6"/>
-<path d="m13 1045.4v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1v2a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -2.5977 -1.5z" fill="#eeb9f6"/>
-<rect x="12" y="1049.4" width="1" height="2" fill="#eeb9f6"/>
+<path transform="translate(0 1040.4)" d="m12 2v2h2a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -0.36523 -0.50195 3 3 0 0 0 0.36523 -0.49805 3 3 0 0 0 0.39844 -1.5h0.003906v-2h-4zm-11 2v6h2a3 3 0 0 0 3 -3v-3h-2v3a1 1 0 0 1 -1 1v-4h-2zm5 3a3 3 0 0 0 3 3h1v-2h-1a1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1h1v-2h-1a3 3 0 0 0 -3 3z" fill="#e286f0"/>
+<path transform="translate(0 1040.4)" d="m12 2v2h2a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -0.36523 -0.50195 3 3 0 0 0 0.36523 -0.49805 3 3 0 0 0 0.39844 -1.5h0.003906v-2h-4z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_mini_vector3_array.svg b/editor/icons/icon_mini_vector3_array.svg
index a1b880bdf0..e2843d2e68 100644
--- a/editor/icons/icon_mini_vector3_array.svg
+++ b/editor/icons/icon_mini_vector3_array.svg
@@ -1,12 +1,7 @@
<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1040.4)">
-<rect y="1050.4" width="4" height="2" fill="#e0e0e0"/>
-<rect y="1040.4" width="2" height="12" fill="#e0e0e0"/>
-<rect y="1040.4" width="4" height="2" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1050.4" width="4" height="2" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1040.4" width="2" height="12" fill="#e0e0e0"/>
-<rect transform="scale(-1,1)" x="-16" y="1040.4" width="4" height="2" fill="#e0e0e0"/>
-<path transform="translate(0 1040.4)" d="m3 3v6h2a3 3 0 0 0 3 -3v-3h-2v3a1 1 0 0 1 -1 1v-4h-2z" fill="#e286f0"/>
-<path transform="translate(0 1040.4)" d="m8 1v2h1 1a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -0.36523 -0.50195 3 3 0 0 0 0.36523 -0.49805 3 3 0 0 0 0.39844 -1.5h0.003906v-2h-0.76562-2.2344-1z" fill="#eeb9f6"/>
+<path transform="translate(0 1040.4)" d="m0 0v2 8 2h4v-2h-2v-8h2v-2h-2-2zm12 0v2h2v8h-2v2h4v-2-10h-4z" fill="#e0e0e0"/>
+<path transform="translate(0 1040.4)" d="m8 1v2h1 1a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -0.36523 -0.50195 3 3 0 0 0 0.36523 -0.49805 3 3 0 0 0 0.39844 -1.5h0.003906v-2h-0.76562-2.2344-1zm0 2h-2v3a1 1 0 0 1 -1 1v-4h-2v6h2a3 3 0 0 0 3 -3v-3z" fill="#e286f0"/>
+<path transform="translate(0 1040.4)" d="m8 1v2h1 1a1 1 0 0 1 -1 1v2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1h-1v2h1a3 3 0 0 0 2.5977 -1.5 3 3 0 0 0 0 -3 3 3 0 0 0 -0.36523 -0.50195 3 3 0 0 0 0.36523 -0.49805 3 3 0 0 0 0.39844 -1.5h0.003906v-2h-0.76562-2.2344-1z" fill="#fff" fill-opacity=".39216"/>
</g>
</svg>
diff --git a/editor/icons/icon_multi_edit.svg b/editor/icons/icon_multi_edit.svg
index b0de08316a..36f62006e0 100644
--- a/editor/icons/icon_multi_edit.svg
+++ b/editor/icons/icon_multi_edit.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m1.7071 1047.8-0.70711 3.5356l3.5355-0.7071 7.7782-7.7782-2.8284-2.8284zm9.1924-9.1924 2.8284 2.8285 1.4142-1.4142-2.8284-2.8285z"/>
-<rect x="1" y="1037.4" width="2" height="2"/>
-<rect x="1" y="1041.4" width="2" height="2"/>
-<rect x="5" y="1037.4" width="2" height="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m12.314 0.85742l-1.4141 1.4141 2.8281 2.8281 1.4141-1.4141-2.8281-2.8281zm-11.314 0.14258v2h2v-2h-2zm4 0v2h2v-2h-2zm4.4844 2.6855l-7.7773 7.7793-0.70703 3.5352 3.5352-0.70703 7.7793-7.7773-2.8301-2.8301zm-8.4844 1.3145v2h2v-2h-2z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_multi_line.svg b/editor/icons/icon_multi_line.svg
index 0cd8be93f6..d2e6d3818a 100644
--- a/editor/icons/icon_multi_line.svg
+++ b/editor/icons/icon_multi_line.svg
@@ -1,10 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<rect x="10" y="1037.4" width="5" height="1.9999"/>
-<rect transform="rotate(90)" x="1037.4" y="-8" width="2" height="7"/>
-<rect x="1" y="1041.4" width="11" height="1.9999"/>
-<rect x="1" y="1045.4" width="4" height="1.9999"/>
-<rect x="7" y="1045.4" width="8" height="1.9999"/>
-<rect x="1" y="1049.4" width="13" height="1.9999"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v2h7v-2h-7zm9 0v2h5v-2h-5zm-9 4v2h11v-2h-11zm0 4v2h4v-2h-4zm6 0v2h8v-2h-8zm-6 4v2h13v-2h-13z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_multi_script.svg b/editor/icons/icon_multi_script.svg
deleted file mode 100644
index b377f04da2..0000000000
--- a/editor/icons/icon_multi_script.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m7 1l-0.56445 2.2578a5 5 0 0 0 -0.68945 0.2793l-1.9883-1.1934-1.4141 1.4141 1.1953 1.9941a5 5 0 0 0 -0.28516 0.68555l-2.2539 0.5625v2l2.2578 0.56445a5 5 0 0 0 0.2793 0.6875l-1.1934 1.9902 1.4141 1.4141 1.2422-0.74414v-4.9121h1a2 2 0 0 1 2 -2v-1h4.9121l0.74414-1.2422-1.4141-1.4141-1.9941 1.1953a5 5 0 0 0 -0.68555 -0.28516l-0.5625-2.2539h-2z"/>
-<path d="m10 1043.4v3h-3v2h3v3h2v-3h3v-2h-3v-3z"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_node_warning.svg b/editor/icons/icon_node_warning.svg
index 5c03bad343..8a1a3bd2ea 100644
--- a/editor/icons/icon_node_warning.svg
+++ b/editor/icons/icon_node_warning.svg
@@ -1,7 +1,3 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<g transform="translate(0 -1.6949e-5)">
-<path transform="translate(0 1036.4)" d="m8.0293 2.002a1.0001 1.0001 0 0 0 -0.88672 0.48438l-6 10a1.0001 1.0001 0 0 0 0.85742 1.5137h12a1.0001 1.0001 0 0 0 0.85742 -1.5137l-6-10a1.0001 1.0001 0 0 0 -0.82812 -0.48438zm-1.0293 2.998h2v5h-2v-5zm0 6h2v2h-2v-2z" color="#000000" color-rendering="auto" fill="#ffd684" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-</g>
-</g>
+<path d="m8.0293 2.002a1.0001 1.0001 0 0 0 -0.88672 0.48438l-6 10a1.0001 1.0001 0 0 0 0.85742 1.5137h12a1.0001 1.0001 0 0 0 0.85742 -1.5137l-6-10a1.0001 1.0001 0 0 0 -0.82812 -0.48438zm-1.0293 2.998h2v5h-2v-5zm0 6h2v2h-2v-2z" color="#000000" color-rendering="auto" fill="#ffdd65" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
</svg>
diff --git a/editor/icons/icon_object.svg b/editor/icons/icon_object.svg
index 223761d0d8..fe8cbc6f92 100644
--- a/editor/icons/icon_object.svg
+++ b/editor/icons/icon_object.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0" fill-rule="evenodd">
-<path d="m8 1043.9v6l6-3v-6z"/>
-<path transform="translate(0 1036.4)" d="m7.9629 1.002a1.0001 1.0001 0 0 0 -0.41016 0.10352l-6 3a1.0001 1.0001 0 0 0 -0.55273 0.89453v6a1.0001 1.0001 0 0 0 0.55273 0.89453l6 3a1.0001 1.0001 0 0 0 0.89453 0l6-3a1.0001 1.0001 0 0 0 0.55273 -0.89453v-6a1.0001 1.0001 0 0 0 -0.55273 -0.89453l-6-3a1.0001 1.0001 0 0 0 -0.48438 -0.10352zm0.037109 2.1172l3.7637 1.8809-3.7637 1.8828-3.7637-1.8828 3.7637-1.8809zm-5 3.498l4 2v3.7656l-4-2v-3.7656zm10 0v3.7656l-4 2v-3.7656l4-2z" color="#000000" color-rendering="auto" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m7.9629 1.002a1.0001 1.0001 0 0 0 -0.41016 0.10352l-6 3a1.0001 1.0001 0 0 0 -0.55273 0.89453v6a1.0001 1.0001 0 0 0 0.55273 0.89453l6 3a1.0001 1.0001 0 0 0 0.89453 0l6-3a1.0001 1.0001 0 0 0 0.55273 -0.89453v-6a1.0001 1.0001 0 0 0 -0.55273 -0.89453l-6-3a1.0001 1.0001 0 0 0 -0.48438 -0.10352zm0.037109 2.1172l3.7637 1.8809-3.7637 1.8828-3.7637-1.8828 3.7637-1.8809zm-5 3.498l4 2v3.7656l-4-2v-3.7656z" fill="#e0e0e0" fill-rule="evenodd"/>
</g>
</svg>
diff --git a/editor/icons/icon_override.svg b/editor/icons/icon_override.svg
index 9c6fd9e177..4a797af6d8 100644
--- a/editor/icons/icon_override.svg
+++ b/editor/icons/icon_override.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m5 1c-1.108 0-2 0.89199-2 2v1h4v-1h2v1h4v-1c0-1.108-0.89199-2-2-2h-6z" fill="#e0e0e0"/>
-<path transform="translate(0 1036.4)" d="m3 6c-1.108 0-2 0.89199-2 2v5c0 1.108 0.89199 2 2 2h10c1.108 0 2-0.89199 2-2v-5c0-1.108-0.89199-2-2-2h-4v3h2l-3 4-3-4h2v-3h-4z" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m5 1c-1.108 0-2 0.89199-2 2v1h4v-1h2v1h4v-1c0-1.108-0.89199-2-2-2h-6zm-2 5c-1.108 0-2 0.89199-2 2v5c0 1.108 0.89199 2 2 2h10c1.108 0 2-0.89199 2-2v-5c0-1.108-0.89199-2-2-2h-4v3h2l-3 4-3-4h2v-3h-4z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_packed_scene.svg b/editor/icons/icon_packed_scene.svg
index 349ecd0a03..a853322537 100644
--- a/editor/icons/icon_packed_scene.svg
+++ b/editor/icons/icon_packed_scene.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m1 7v6h2v2h12v-8h-14z"/>
-<path d="m0.71129 1040.4 0.28871 1.9791l2.2438-0.3273-0.81826-1.9018-1.7143 0.25zm3.6933-0.5387 0.81826 1.9018 1.9791-0.2887-0.81826-1.9018-1.9791 0.2887zm3.9581-0.5775 0.81826 1.9018 1.9791-0.2887-0.81826-1.9018-1.9791 0.2887zm3.9581-0.5774 0.81826 1.9018 1.7143-0.25-0.28871-1.9791-2.2438 0.3273z"/>
-<circle cx="3" cy="1049.4" r="2"/>
-<circle cx="13" cy="1049.4" r="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m14.564 2-2.2441 0.32812 0.81836 1.9004 1.7148-0.25zm-4.2227 0.61523-1.9785 0.28906 0.81836 1.9023 1.9785-0.28906zm-3.959 0.57812-1.9785 0.28906 0.81836 1.9023 1.9785-0.28906zm-3.957 0.57812-1.7148 0.25l0.28906 1.9785 2.2441-0.32812zm-1.4258 3.2285v6c0 1.1046 0.89543 2 2 2h12v-8z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_panels_2.svg b/editor/icons/icon_panels_2.svg
index 7a2c18ecc9..1f0fe8bc6b 100644
--- a/editor/icons/icon_panels_2.svg
+++ b/editor/icons/icon_panels_2.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<rect y="1036.4" width="16" height="7"/>
-<rect y="1045.4" width="16" height="7"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m0 0v7h16v-7h-16zm0 9v7h16v-7h-16z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_panels_2_alt.svg b/editor/icons/icon_panels_2_alt.svg
index c411650136..78c2839f36 100644
--- a/editor/icons/icon_panels_2_alt.svg
+++ b/editor/icons/icon_panels_2_alt.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<rect x="9" y="1036.4" width="7" height="16"/>
-<rect y="1036.4" width="7" height="16"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m0 0v16h7v-16h-7zm9 0v16h7v-16h-7z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_panels_3.svg b/editor/icons/icon_panels_3.svg
index ec5aa86540..37e1601f29 100644
--- a/editor/icons/icon_panels_3.svg
+++ b/editor/icons/icon_panels_3.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<rect y="1036.4" width="16" height="7"/>
-<rect x="9" y="1045.4" width="7" height="7"/>
-<rect y="1045.4" width="7" height="7"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m0 0v7h16v-7h-16zm0 9v7h7v-7h-7zm9 0v7h7v-7h-7z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_panels_3_alt.svg b/editor/icons/icon_panels_3_alt.svg
index 5f8c78d471..11ca8e2814 100644
--- a/editor/icons/icon_panels_3_alt.svg
+++ b/editor/icons/icon_panels_3_alt.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<rect y="1045.4" width="7" height="7"/>
-<rect x="9" y="1036.4" width="7" height="16"/>
-<rect y="1036.4" width="7" height="7"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m0 0v7h7v-7h-7zm9 0v16h7v-16h-7zm-9 9v7h7v-7h-7z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_panels_4.svg b/editor/icons/icon_panels_4.svg
index 093b40b603..8315c2a789 100644
--- a/editor/icons/icon_panels_4.svg
+++ b/editor/icons/icon_panels_4.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<rect x="9" y="1045.4" width="7" height="7"/>
-<rect y="1045.4" width="7" height="7"/>
-<rect x="9" y="1036.4" width="7" height="7"/>
-<rect y="1036.4" width="7" height="7"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m0 0v7h7v-7h-7zm9 0v7h7v-7h-7zm-9 9v7h7v-7h-7zm9 0v7h7v-7h-7z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_panorama_sky.svg b/editor/icons/icon_panorama_sky.svg
index f3da955dbd..86c5af576f 100644
--- a/editor/icons/icon_panorama_sky.svg
+++ b/editor/icons/icon_panorama_sky.svg
@@ -7,8 +7,6 @@
</defs>
<g transform="translate(0 -1037.4)">
<path d="m1 1039.4c4.2749 2.6091 10.765 2.7449 14 0v12c-3.5849-2.6849-9.7929-2.6544-14 0z" fill="url(#a)" stroke-width="15.242"/>
-<rect x="2" y="1046.4" width="3" height="2" ry="1" fill="#fff"/>
-<rect x="8" y="1044.4" width="4" height="2" ry="1" fill="#fff"/>
-<rect x="10" y="1043.4" width="4" height="2" ry="1" fill="#fff"/>
+<path transform="translate(0 1037.4)" d="m11 6c-0.554 0-1 0.446-1 1h-1c-0.554 0-1 0.446-1 1s0.446 1 1 1h2c0.554 0 1-0.446 1-1h1c0.554 0 1-0.446 1-1s-0.446-1-1-1h-2zm-8 3c-0.554 0-1 0.446-1 1s0.446 1 1 1h1c0.554 0 1-0.446 1-1s-0.446-1-1-1h-1z" fill="#fff"/>
</g>
</svg>
diff --git a/editor/icons/icon_parallax_background.svg b/editor/icons/icon_parallax_background.svg
index dc0a7ba216..822e7149a9 100644
--- a/editor/icons/icon_parallax_background.svg
+++ b/editor/icons/icon_parallax_background.svg
@@ -1,15 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
<ellipse cx="3" cy="1039.4" r="2" fill="#6e6e6e"/>
-<path d="m1 1039.4a1 1 0 0 1 1 -1v1z" fill="#e0e0e0" fill-opacity=".99608"/>
-<path transform="scale(-1,1)" d="m-15 1039.4a1 1 0 0 1 1 -1v1z" fill="#e0e0e0" fill-opacity=".99608"/>
-<rect x="2" y="1038.4" width="12" height="1" fill="#e0e0e0" fill-opacity=".99608"/>
-<rect x="2" y="1049.4" width="12" height="1" fill="#e0e0e0" fill-opacity=".99608"/>
-<path transform="scale(1,-1)" d="m1-1049.4a1 1 0 0 1 1 -1v1z" fill="#e0e0e0" fill-opacity=".99608"/>
-<path transform="scale(-1)" d="m-15-1049.4a1 1 0 0 1 1 -1v1z" fill="#e0e0e0" fill-opacity=".99608"/>
-<rect x="1" y="1039.4" width="1" height="10" fill="#e0e0e0" fill-opacity=".99608"/>
-<rect x="14" y="1039.4" width="1" height="10" fill="#e0e0e0" fill-opacity=".99608"/>
-<path d="m7 1041.4-3 3 3 3z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/>
-<path d="m9 1041.4 3 3-3 3z" fill="#e0e0e0" fill-opacity=".99608" fill-rule="evenodd"/>
+<path transform="translate(0 1036.4)" d="m2 2a1 1 0 0 0 -1 1v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1 -1v-10a1 1 0 0 0 -1 -1h-12zm0 1h12v10h-12v-10zm5 2l-3 3 3 3v-6zm2 0v6l3-3-3-3z" fill="#e0e0e0" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_parallax_layer.svg b/editor/icons/icon_parallax_layer.svg
index 776f7d6a6c..fbdf7f0d1f 100644
--- a/editor/icons/icon_parallax_layer.svg
+++ b/editor/icons/icon_parallax_layer.svg
@@ -1,8 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
<ellipse cx="3" cy="1039.4" r="2" fill="#6e6e6e"/>
-<path d="m7 1041.4-3 3 3 3z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd"/>
-<path d="m9 1041.4 3 3-3 3z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd"/>
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2zm0 1h10c0.55228 9.6e-6 0.99999 0.44772 1 1v10c-1e-5 0.55228-0.44772 0.99999-1 1h-10c-0.55228-1e-5 -0.99999-0.44772-1-1v-10c9.6e-6 -0.55228 0.44772-0.99999 1-1z" fill="#a5b7f3" fill-opacity=".98824"/>
+<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm0 1h10c0.55228 9.6e-6 0.99999 0.44772 1 1v10c-1e-5 0.55228-0.44772 0.99999-1 1h-10c-0.55228-1e-5 -0.99999-0.44772-1-1v-10c9.6e-6 -0.55228 0.44772-0.99999 1-1zm4 3l-3 3 3 3v-6zm2 0v6l3-3-3-3z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd"/>
</g>
</svg>
diff --git a/editor/icons/icon_path.svg b/editor/icons/icon_path.svg
index 998fabb888..254aa4b324 100644
--- a/editor/icons/icon_path.svg
+++ b/editor/icons/icon_path.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<circle cx="3" cy="1049.4" r="2" fill="#fc9c9c" fill-opacity=".99608"/>
-<circle cx="13" cy="1039.4" r="2" fill="#fc9c9c" fill-opacity=".99608"/>
-<path d="m3 1049.4c0-9 10-1 10-10" fill="none" stroke="#fc9c9c" stroke-opacity=".99608" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 0.84961 1.6328c-0.19239 0.88508-0.55317 1.3394-0.98633 1.6426-0.64426 0.451-1.7129 0.60547-2.9629 0.73047s-2.6814 0.22053-3.9121 1.082c-0.89278 0.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -0.84961 -1.6328c0.19235-0.88496 0.55306-1.3373 0.98633-1.6406 0.64426-0.451 1.7129-0.60547 2.9629-0.73047s2.6814-0.22053 3.9121-1.082c0.8927-0.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699 -1.8164 2 2 0 0 0 -2 -2z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_path_2d.svg b/editor/icons/icon_path_2d.svg
index 8d329b3f1f..0195bfe1d7 100644
--- a/editor/icons/icon_path_2d.svg
+++ b/editor/icons/icon_path_2d.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5b7f3" fill-opacity=".98824">
-<circle cx="3" cy="1049.4" r="2"/>
-<circle cx="13" cy="1039.4" r="2"/>
-<path d="m12 1039.4c0 2.0648-0.49246 2.8244-1.1367 3.2754-0.64426 0.451-1.7129 0.6055-2.9629 0.7305s-2.6814 0.2205-3.9121 1.082c-1.2307 0.8615-1.9883 2.4769-1.9883 4.9121h2c0-2.0648 0.49246-2.8224 1.1367-3.2734 0.64426-0.451 1.7129-0.6055 2.9629-0.7305s2.6814-0.2205 3.9121-1.082c1.2307-0.8615 1.9883-2.4789 1.9883-4.9141h-2z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m13 1a2 2 0 0 0 -2 2 2 2 0 0 0 0.84961 1.6328c-0.19239 0.88508-0.55317 1.3394-0.98633 1.6426-0.64426 0.451-1.7129 0.60547-2.9629 0.73047s-2.6814 0.22053-3.9121 1.082c-0.89278 0.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -0.84961 -1.6328c0.19235-0.88496 0.55306-1.3373 0.98633-1.6406 0.64426-0.451 1.7129-0.60547 2.9629-0.73047s2.6814-0.22053 3.9121-1.082c0.8927-0.62488 1.5321-1.6538 1.8184-3.0977a2 2 0 0 0 1.1699 -1.8164 2 2 0 0 0 -2 -2z" fill="#a5b7f3" fill-opacity=".98824"/>
</g>
</svg>
diff --git a/editor/icons/icon_path_follow.svg b/editor/icons/icon_path_follow.svg
index a614e2c861..bd3f585e54 100644
--- a/editor/icons/icon_path_follow.svg
+++ b/editor/icons/icon_path_follow.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fc9c9c" fill-opacity=".99608">
-<circle cx="3" cy="1049.4" r="2"/>
-<path d="m12 1039.4c0 2.0648-0.49246 2.8244-1.1367 3.2754-0.64426 0.451-1.7129 0.6055-2.9629 0.7305s-2.6814 0.2205-3.9121 1.082c-1.2307 0.8615-1.9883 2.4769-1.9883 4.9121h2c0-2.0648 0.49246-2.8224 1.1367-3.2734 0.64426-0.451 1.7129-0.6055 2.9629-0.7305s2.6814-0.2205 3.9121-1.082c1.2307-0.8615 1.9883-2.4789 1.9883-4.9141h-2z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<path d="m10 1040.4h6l-3-4z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m13 0l-3 4h1.9473c-0.1385 1.3203-0.5583 1.9074-1.084 2.2754-0.64426 0.451-1.7129 0.60547-2.9629 0.73047s-2.6814 0.22053-3.9121 1.082c-0.89278 0.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -0.84961 -1.6328c0.19235-0.88496 0.55306-1.3373 0.98633-1.6406 0.64426-0.451 1.7129-0.60547 2.9629-0.73047s2.6814-0.22053 3.9121-1.082c1.0528-0.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_path_follow_2d.svg b/editor/icons/icon_path_follow_2d.svg
index 97e21396af..7dc3015105 100644
--- a/editor/icons/icon_path_follow_2d.svg
+++ b/editor/icons/icon_path_follow_2d.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5b7f3" fill-opacity=".98824">
-<circle cx="3" cy="1049.4" r="2"/>
-<path d="m12 1039.4c0 2.0648-0.49246 2.8244-1.1367 3.2754-0.64426 0.451-1.7129 0.6055-2.9629 0.7305s-2.6814 0.2205-3.9121 1.082c-1.2307 0.8615-1.9883 2.4769-1.9883 4.9121h2c0-2.0648 0.49246-2.8224 1.1367-3.2734 0.64426-0.451 1.7129-0.6055 2.9629-0.7305s2.6814-0.2205 3.9121-1.082c1.2307-0.8615 1.9883-2.4789 1.9883-4.9141h-2z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<path d="m10 1040.4h6l-3-4z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m13 0l-3 4h1.9473c-0.1385 1.3203-0.5583 1.9074-1.084 2.2754-0.64426 0.451-1.7129 0.60547-2.9629 0.73047s-2.6814 0.22053-3.9121 1.082c-0.89278 0.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -0.84961 -1.6328c0.19235-0.88496 0.55306-1.3373 0.98633-1.6406 0.64426-0.451 1.7129-0.60547 2.9629-0.73047s2.6814-0.22053 3.9121-1.082c1.0528-0.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#a5b7f3" fill-opacity=".98824"/>
</g>
</svg>
diff --git a/editor/icons/icon_pin.svg b/editor/icons/icon_pin.svg
index b0f4ae4e99..332692fdd5 100644
--- a/editor/icons/icon_pin.svg
+++ b/editor/icons/icon_pin.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m3 1046.4h10l-2-3h-6z" fill-rule="evenodd"/>
-<path transform="translate(0 1036.4)" d="m4 1v1l1 1v3h6v-3l1-1v-1h-8z" fill-rule="evenodd"/>
-<rect x="7" y="1047.4" width="2" height="2"/>
-<path d="m7 1049.4 1 2 1-2h-2z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m4 1v1l1 1v3h6v-3l1-1v-1h-8zm1 6l-2 3h10l-2-3h-6zm2 4v2l1 2 1-2v-2h-2z" fill="#e0e0e0" fill-rule="evenodd"/>
</g>
</svg>
diff --git a/editor/icons/icon_pin_joint.svg b/editor/icons/icon_pin_joint.svg
index 028981a95a..cfbb8cbbcd 100644
--- a/editor/icons/icon_pin_joint.svg
+++ b/editor/icons/icon_pin_joint.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fc9c9c">
-<path d="m1.9289 1043.3 7.0711 7.071l0.70711-3.5355-4.2426-4.2426z" fill-rule="evenodd"/>
-<path d="m9 1037.6-0.70711 0.7071v1.4142l-2.1213 2.1214 4.2426 4.2426 2.1213-2.1213h1.4142l0.70711-0.7071-5.6569-5.6569z" fill-rule="evenodd"/>
-<rect transform="matrix(.70711 .70711 -.70711 .70711 0 0)" x="743.08" y="737.35" width="2" height="2"/>
-<path d="m2.636 1048.2-0.70711 2.1213 2.1213-0.7071-1.4142-1.4142z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m9 1.2715l-0.70703 0.70703v1.4141l-2.1211 2.123 4.2422 4.2422 2.1211-2.1211h1.4141l0.70703-0.70703-5.6562-5.6582zm-3.5352 4.9512l-3.5352 0.70703 7.0703 7.0703 0.70703-3.5352-4.2422-4.2422zm-1.4141 4.2422l-1.4141 1.4141-0.70703 2.1211 2.1211-0.70703 1.4141-1.4141-1.4141-1.4141z" fill="#fc9c9c" fill-rule="evenodd"/>
</g>
</svg>
diff --git a/editor/icons/icon_pin_pressed.svg b/editor/icons/icon_pin_pressed.svg
index b0f4ae4e99..332692fdd5 100644
--- a/editor/icons/icon_pin_pressed.svg
+++ b/editor/icons/icon_pin_pressed.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m3 1046.4h10l-2-3h-6z" fill-rule="evenodd"/>
-<path transform="translate(0 1036.4)" d="m4 1v1l1 1v3h6v-3l1-1v-1h-8z" fill-rule="evenodd"/>
-<rect x="7" y="1047.4" width="2" height="2"/>
-<path d="m7 1049.4 1 2 1-2h-2z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m4 1v1l1 1v3h6v-3l1-1v-1h-8zm1 6l-2 3h10l-2-3h-6zm2 4v2l1 2 1-2v-2h-2z" fill="#e0e0e0" fill-rule="evenodd"/>
</g>
</svg>
diff --git a/editor/icons/icon_play.svg b/editor/icons/icon_play.svg
index 7b96840a44..47a2ca12cc 100644
--- a/editor/icons/icon_play.svg
+++ b/editor/icons/icon_play.svg
@@ -1,5 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m4 1048.4v-8l7 4z" fill="#e0e0e0" fill-rule="evenodd" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2"/>
+<g>
+<path d="m4.9883 1039.4c-0.5469 0.01-0.98717 0.4511-0.98828 0.998v8c1.163e-4 0.7986 0.89011 1.275 1.5547 0.8321l6-4c0.59362-0.3959 0.59362-1.2682 0-1.6641l-6-4c-0.1678-0.1111-0.3652-0.1689-0.56641-0.166z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+</g>
</g>
</svg>
diff --git a/editor/icons/icon_play_backwards.svg b/editor/icons/icon_play_backwards.svg
index bb6ae76e0d..c6de746f05 100644
--- a/editor/icons/icon_play_backwards.svg
+++ b/editor/icons/icon_play_backwards.svg
@@ -1,5 +1,7 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m12 1048.4v-8l-7 4z" fill="#e0e0e0" fill-rule="evenodd" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2"/>
+<g transform="matrix(-1 0 0 1 16 0)">
+<path d="m4.9883 1039.4c-0.5469 0.01-0.98717 0.4511-0.98828 0.998v8c1.163e-4 0.7986 0.89011 1.275 1.5547 0.8321l6-4c0.59362-0.3959 0.59362-1.2682 0-1.6641l-6-4c-0.1678-0.1111-0.3652-0.1689-0.56641-0.166z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+</g>
</g>
</svg>
diff --git a/editor/icons/icon_play_custom.svg b/editor/icons/icon_play_custom.svg
index 9da56dc19e..ddd2ee56d8 100644
--- a/editor/icons/icon_play_custom.svg
+++ b/editor/icons/icon_play_custom.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m1 7v6a2 2 0 0 0 2 2h12v-8h-14zm3 1h4v1h4v5h-4-4v-5-1z"/>
-<path d="m0.71129 1040.4 0.28871 1.9791l2.2438-0.3273-0.81826-1.9018-1.7143 0.25zm3.6933-0.5387 0.81826 1.9018 1.9791-0.2887-0.81826-1.9018-1.9791 0.2887zm3.9581-0.5775 0.81826 1.9018 1.9791-0.2887-0.81826-1.9018-1.9791 0.2887zm3.9581-0.5774 0.81826 1.9018 1.7143-0.25-0.28871-1.9791-2.2438 0.3273z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m14.564 2l-2.2441 0.32812 0.81836 1.9004 1.7148-0.25-0.28906-1.9785zm-4.2227 0.61523l-1.9785 0.28906 0.81836 1.9023 1.9785-0.28906-0.81836-1.9023zm-3.959 0.57812l-1.9785 0.28906 0.81836 1.9023 1.9785-0.28906-0.81836-1.9023zm-3.957 0.57812l-1.7148 0.25 0.28906 1.9785 2.2441-0.32812-0.81836-1.9004zm-1.4258 3.2285v6a2 2 0 0 0 2 2h12v-8h-14zm3 1h4v1h4v5h-4-4v-5-1z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_play_scene.svg b/editor/icons/icon_play_scene.svg
index aef7b9e803..4ba0f88bcf 100644
--- a/editor/icons/icon_play_scene.svg
+++ b/editor/icons/icon_play_scene.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m1 7v6h2v2h12v-8h-14zm5 1l5 3-5 3v-6z"/>
-<path d="m0.71129 1040.4 0.28871 1.9791l2.2438-0.3273-0.81826-1.9018-1.7143 0.25zm3.6933-0.5387 0.81826 1.9018 1.9791-0.2887-0.81826-1.9018-1.9791 0.2887zm3.9581-0.5775 0.81826 1.9018 1.9791-0.2887-0.81826-1.9018-1.9791 0.2887zm3.9581-0.5774 0.81826 1.9018 1.7143-0.25-0.28871-1.9791-2.2438 0.3273z"/>
-<circle cx="3" cy="1049.4" r="2"/>
-<circle cx="13" cy="1049.4" r="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m14.564 2-2.2441 0.32812 0.81836 1.9004 1.7148-0.25zm-4.2227 0.61523-1.9785 0.28906 0.81836 1.9023 1.9785-0.28906zm-3.959 0.57812-1.9785 0.28906 0.81836 1.9023 1.9785-0.28906zm-3.957 0.57812-1.7148 0.25l0.28906 1.9785 2.2441-0.32812zm-1.4258 3.2285v6c0 1.1046 0.89543 2 2 2h12v-8zm5 1 5 3-5 3z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_play_start.svg b/editor/icons/icon_play_start.svg
index 9c75dca2a1..541a18e3d9 100644
--- a/editor/icons/icon_play_start.svg
+++ b/editor/icons/icon_play_start.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m7.0001 1048.4v-8l7 4z" fill-rule="evenodd" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2"/>
-<path d="m3 1039.4c0.55226 1e-4 0.99994 0.4477 1 1v8c-5.5e-5 0.5523-0.44774 0.9999-1 1h-1v-1h-1v-8h1v-1z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<circle transform="scale(-1,1)" cx="-2" cy="1040.4" r="1"/>
-<circle transform="scale(-1,1)" cx="-2" cy="1048.4" r="1"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 3a1 1 0 0 0 -1 1v8a1 1 0 0 0 1 1h1c0.55226-1e-4 0.99994-0.4477 1-1v-8c-5.5e-5 -0.5523-0.44774-0.9999-1-1h-1zm4.9746 0c-0.54154 0.014-0.97365 0.45635-0.97461 0.99805v8c-3.92e-4 0.8389 0.97003 1.3054 1.625 0.78125l5-4c0.49938-0.4004 0.49938-1.1601 0-1.5605l-5-4c-0.18422-0.1473-0.41459-0.22485-0.65039-0.21875z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_play_start_backwards.svg b/editor/icons/icon_play_start_backwards.svg
index eede120ae7..b1acc749e0 100644
--- a/editor/icons/icon_play_start_backwards.svg
+++ b/editor/icons/icon_play_start_backwards.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m8.9999 1048.4v-8l-7 4z" fill-rule="evenodd" stroke="#e0e0e0" stroke-linejoin="round" stroke-width="2"/>
-<path d="m13 1039.4c-0.55226 1e-4 -0.99994 0.4477-1 1v8c5.5e-5 0.5523 0.44774 0.9999 1 1h1v-1h1v-8h-1v-1z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<circle cx="14" cy="1040.4" r="1"/>
-<circle cx="14" cy="1048.4" r="1"/>
+<g transform="translate(0 -1036.4)">
+<path d="m13 1039.4a1 1 0 0 1 1 1v8a1 1 0 0 1 -1 1h-1c-0.55226-1e-4 -0.99994-0.4477-1-1v-8c5.5e-5 -0.5523 0.44774-0.9999 1-1zm-4.9746 0c0.54154 0.014 0.97365 0.4563 0.97461 0.998v8c3.92e-4 0.8389-0.97003 1.3055-1.625 0.7813l-5-4c-0.49938-0.4004-0.49938-1.1601 0-1.5605l5-4c0.18422-0.1473 0.41459-0.2249 0.65039-0.2188z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_popup_menu.svg b/editor/icons/icon_popup_menu.svg
index 05e60d7d41..9181cb42a3 100644
--- a/editor/icons/icon_popup_menu.svg
+++ b/editor/icons/icon_popup_menu.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m2 6a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h12a1 1 0 0 0 1 -1v-7a1 1 0 0 0 -1 -1h-12zm1 2h10v2h-10v-2zm0 3h10v2h-10v-2z"/>
-<path transform="translate(0 1036.4)" d="m1 1v4h6v-4h-6zm1 1h4l-2 2-2-2z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v4h6v-4h-6zm1 1h4l-2 2-2-2zm0 4a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h12a1 1 0 0 0 1 -1v-7a1 1 0 0 0 -1 -1h-12zm1 2h10v2h-10v-2zm0 3h10v2h-10v-2z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_popup_panel.svg b/editor/icons/icon_popup_panel.svg
index ce4e7c283c..302b12670c 100644
--- a/editor/icons/icon_popup_panel.svg
+++ b/editor/icons/icon_popup_panel.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m2 6c-0.55228 0-1 0.44772-1 1v7c0 0.55228 0.44772 1 1 1h12c0.55228 0 1-0.44772 1-1v-7c0-0.55228-0.44772-1-1-1z"/>
-<path transform="translate(0 1036.4)" d="m1 1v4h6v-4h-6zm1 1h4l-2 2-2-2z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v4h6v-4h-6zm1 1h4l-2 2-2-2zm0 4c-0.55228 0-1 0.44772-1 1v7c0 0.55228 0.44772 1 1 1h12c0.55228 0 1-0.44772 1-1v-7c0-0.55228-0.44772-1-1-1h-12z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_procedural_sky.svg b/editor/icons/icon_procedural_sky.svg
index b3bc927409..47c933c202 100644
--- a/editor/icons/icon_procedural_sky.svg
+++ b/editor/icons/icon_procedural_sky.svg
@@ -7,8 +7,6 @@
</defs>
<g transform="translate(0 -1037.4)">
<path d="m8 1040.4a7 7 0 0 0 -7 7 7 7 0 0 0 0.68555 3h12.631a7 7 0 0 0 0.68359 -3 7 7 0 0 0 -7 -7z" fill="url(#a)"/>
-<rect x="2" y="1047.4" width="3" height="2" ry="1" fill="#fff"/>
-<rect x="7" y="1045.4" width="4" height="2" ry="1" fill="#fff"/>
-<rect x="9" y="1044.4" width="4" height="2" ry="1" fill="#fff"/>
+<path transform="translate(0 1037.4)" d="m10 7c-0.554 0-1 0.446-1 1h-1c-0.554 0-1 0.446-1 1s0.446 1 1 1h2c0.554 0 1-0.446 1-1h1c0.554 0 1-0.446 1-1s-0.446-1-1-1h-2zm-7 3c-0.554 0-1 0.446-1 1s0.446 1 1 1h1c0.554 0 1-0.446 1-1s-0.446-1-1-1h-1z" fill="#fff"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_1.svg b/editor/icons/icon_progress_1.svg
index 2df93a13f7..b793b88b45 100644
--- a/editor/icons/icon_progress_1.svg
+++ b/editor/icons/icon_progress_1.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
<path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273 0.4258l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223z" fill-opacity=".99608"/>
-<path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.4277v-3.0508z" fill-opacity=".19608"/>
-<path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582z" fill-opacity=".19608"/>
-<path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855z" fill-opacity=".19608"/>
-<path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508z" fill-opacity=".19608"/>
-<path d="m11.867 1045.4a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547z" fill-opacity=".19608"/>
-<path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.4258z" fill-opacity=".19608"/>
-<path d="m10.027 1047.8a4 4 0 0 1 -1.0273 0.4277v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
+<path transform="translate(0 1036.4)" d="m7 1.0801a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582zm11.199 0l-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508zm10.787 0a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547zm-5.8945 2.4414l-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.42578zm4.0547 0a4 4 0 0 1 -1.0273 0.42774v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_2.svg b/editor/icons/icon_progress_2.svg
index 9af1ff7c3d..26595912e1 100644
--- a/editor/icons/icon_progress_2.svg
+++ b/editor/icons/icon_progress_2.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273 0.4258l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223z" fill-opacity=".19608"/>
-<path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.4277v-3.0508z" fill-opacity=".19608"/>
-<path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582z" fill-opacity=".19608"/>
+<path transform="translate(0 1036.4)" d="m9 1.0781v3.0547a4 4 0 0 1 1.0273 0.42578l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223zm-2 0.0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582zm-1.3203 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508zm10.787 0a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547zm-5.8945 2.4414l-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.42578zm4.0547 0a4 4 0 0 1 -1.0273 0.42774v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
<path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855z" fill-opacity=".99608"/>
-<path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508z" fill-opacity=".19608"/>
-<path d="m11.867 1045.4a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547z" fill-opacity=".19608"/>
-<path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.4258z" fill-opacity=".19608"/>
-<path d="m10.027 1047.8a4 4 0 0 1 -1.0273 0.4277v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_3.svg b/editor/icons/icon_progress_3.svg
index 92489f013c..c618848106 100644
--- a/editor/icons/icon_progress_3.svg
+++ b/editor/icons/icon_progress_3.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273 0.4258l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223z" fill-opacity=".19608"/>
-<path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.4277v-3.0508z" fill-opacity=".19608"/>
-<path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582z" fill-opacity=".19608"/>
-<path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855z" fill-opacity=".19608"/>
-<path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508z" fill-opacity=".19608"/>
+<path transform="translate(0 1036.4)" d="m9 1.0781v3.0547a4 4 0 0 1 1.0273 0.42578l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223zm-2 0.0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582zm11.199 0l-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508zm4.8926 2.4414l-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.42578zm4.0547 0a4 4 0 0 1 -1.0273 0.42774v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
<path d="m11.867 1045.4a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547z" fill-opacity=".99608"/>
-<path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.4258z" fill-opacity=".19608"/>
-<path d="m10.027 1047.8a4 4 0 0 1 -1.0273 0.4277v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_4.svg b/editor/icons/icon_progress_4.svg
index 5acd6c3936..fa71f5e484 100644
--- a/editor/icons/icon_progress_4.svg
+++ b/editor/icons/icon_progress_4.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273 0.4258l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223z" fill-opacity=".19608"/>
-<path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.4277v-3.0508z" fill-opacity=".19608"/>
-<path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582z" fill-opacity=".19608"/>
-<path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855z" fill-opacity=".19608"/>
-<path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508z" fill-opacity=".19608"/>
-<path d="m11.867 1045.4a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547z" fill-opacity=".19608"/>
-<path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.4258z" fill-opacity=".19608"/>
+<path transform="translate(0 1036.4)" d="m9 1.0781v3.0547a4 4 0 0 1 1.0273 0.42578l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223zm-2 0.0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582zm11.199 0l-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508zm10.787 0a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547zm-5.8945 2.4414l-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.42578z" fill-opacity=".19608"/>
<path d="m10.027 1047.8a4 4 0 0 1 -1.0273 0.4277v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_5.svg b/editor/icons/icon_progress_5.svg
index 8c4d1abcc3..90151fb9c9 100644
--- a/editor/icons/icon_progress_5.svg
+++ b/editor/icons/icon_progress_5.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273 0.4258l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223z" fill-opacity=".19608"/>
-<path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.4277v-3.0508z" fill-opacity=".19608"/>
-<path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582z" fill-opacity=".19608"/>
-<path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855z" fill-opacity=".19608"/>
-<path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508z" fill-opacity=".19608"/>
-<path d="m11.867 1045.4a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547z" fill-opacity=".19608"/>
+<path transform="translate(0 1036.4)" d="m9 1.0781v3.0547a4 4 0 0 1 1.0273 0.42578l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223zm-2 0.0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582zm11.199 0l-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508zm10.787 0a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547zm-1.8398 2.4414a4 4 0 0 1 -1.0273 0.42774v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
<path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.4258z" fill-opacity=".99608"/>
-<path d="m10.027 1047.8a4 4 0 0 1 -1.0273 0.4277v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_6.svg b/editor/icons/icon_progress_6.svg
index c91a5d7e9e..c1c43929ef 100644
--- a/editor/icons/icon_progress_6.svg
+++ b/editor/icons/icon_progress_6.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273 0.4258l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223z" fill-opacity=".19608"/>
-<path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.4277v-3.0508z" fill-opacity=".19608"/>
-<path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582z" fill-opacity=".19608"/>
-<path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855z" fill-opacity=".19608"/>
+<path transform="translate(0 1036.4)" d="m9 1.0781v3.0547a4 4 0 0 1 1.0273 0.42578l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223zm-2 0.0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.42773v-3.0508zm-4.5996 2.7344a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582zm11.199 0l-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855zm-1.7324 5.1855a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547zm-5.8945 2.4414l-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.42578zm4.0547 0a4 4 0 0 1 -1.0273 0.42774v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
<path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508z" fill-opacity=".99608"/>
-<path d="m11.867 1045.4a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547z" fill-opacity=".19608"/>
-<path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.4258z" fill-opacity=".19608"/>
-<path d="m10.027 1047.8a4 4 0 0 1 -1.0273 0.4277v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_7.svg b/editor/icons/icon_progress_7.svg
index b28175215d..718cb799f8 100644
--- a/editor/icons/icon_progress_7.svg
+++ b/editor/icons/icon_progress_7.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273 0.4258l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223z" fill-opacity=".19608"/>
-<path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.4277v-3.0508z" fill-opacity=".19608"/>
+<path transform="translate(0 1036.4)" d="m9 1.0781v3.0547a4 4 0 0 1 1.0273 0.42578l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223zm-2 0.0019531a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.42773v-3.0508zm6.5996 2.7344l-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508zm10.787 0a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547zm-5.8945 2.4414l-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.42578zm4.0547 0a4 4 0 0 1 -1.0273 0.42774v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
<path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582z" fill-opacity=".99608"/>
-<path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855z" fill-opacity=".19608"/>
-<path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508z" fill-opacity=".19608"/>
-<path d="m11.867 1045.4a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547z" fill-opacity=".19608"/>
-<path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.4258z" fill-opacity=".19608"/>
-<path d="m10.027 1047.8a4 4 0 0 1 -1.0273 0.4277v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_8.svg b/editor/icons/icon_progress_8.svg
index f88fbe308d..b6033cc527 100644
--- a/editor/icons/icon_progress_8.svg
+++ b/editor/icons/icon_progress_8.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m9 1037.4v3.0547a4 4 0 0 1 1.0273 0.4258l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223z" fill-opacity=".19608"/>
+<path transform="translate(0 1036.4)" d="m9 1.0781v3.0547a4 4 0 0 1 1.0273 0.42578l2.1582-2.1582a7 7 0 0 0 -3.1855 -1.3223zm-6.5996 2.7363a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582zm11.199 0l-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855zm-12.52 5.1855a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508zm10.787 0a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547zm-5.8945 2.4414l-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.42578zm4.0547 0a4 4 0 0 1 -1.0273 0.42774v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
<path d="m7 1037.4a7 7 0 0 0 -3.1855 1.3203l2.1582 2.1582a4 4 0 0 1 1.0273 -0.4277v-3.0508z" fill-opacity=".99608"/>
-<path d="m2.4004 1040.2a7 7 0 0 0 -1.3223 3.1855h3.0547a4 4 0 0 1 0.42578 -1.0273l-2.1582-2.1582z" fill-opacity=".19608"/>
-<path d="m13.6 1040.2-2.1582 2.1582a4 4 0 0 1 0.42774 1.0273h3.0508a7 7 0 0 0 -1.3203 -3.1855z" fill-opacity=".19608"/>
-<path d="m1.0801 1045.4a7 7 0 0 0 1.3203 3.1855l2.1582-2.1582a4 4 0 0 1 -0.42773 -1.0273h-3.0508z" fill-opacity=".19608"/>
-<path d="m11.867 1045.4a4 4 0 0 1 -0.42578 1.0273l2.1582 2.1582a7 7 0 0 0 1.3223 -3.1855h-3.0547z" fill-opacity=".19608"/>
-<path d="m5.9727 1047.8-2.1582 2.1582a7 7 0 0 0 3.1855 1.3223v-3.0547a4 4 0 0 1 -1.0273 -0.4258z" fill-opacity=".19608"/>
-<path d="m10.027 1047.8a4 4 0 0 1 -1.0273 0.4277v3.0508a7 7 0 0 0 3.1855 -1.3203l-2.1582-2.1582z" fill-opacity=".19608"/>
</g>
</svg>
diff --git a/editor/icons/icon_progress_bar.svg b/editor/icons/icon_progress_bar.svg
index f068d3e810..e8fe90bca2 100644
--- a/editor/icons/icon_progress_bar.svg
+++ b/editor/icons/icon_progress_bar.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m3 3c-1.1046 0-2 0.89543-2 2v6c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-6c0-1.1046-0.89543-2-2-2zm0 2h10v6h-10z"/>
-<rect x="4" y="1042.4" width="1" height="4"/>
-<rect x="6" y="1042.4" width="1" height="4"/>
-<rect x="8" y="1042.4" width="1" height="4"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 3c-1.1046 0-2 0.89543-2 2v6c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-6c0-1.1046-0.89543-2-2-2h-10zm0 2h10v6h-10v-6zm1 1v4h1v-4h-1zm2 0v4h1v-4h-1zm2 0v4h1v-4h-1z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_proximity_group.svg b/editor/icons/icon_proximity_group.svg
index 536060dc7e..4f977ca548 100644
--- a/editor/icons/icon_proximity_group.svg
+++ b/editor/icons/icon_proximity_group.svg
@@ -1,11 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fc9c9c" fill-opacity=".99608">
-<rect x="1" y="1037.4" width="2" height="14"/>
-<rect x="1" y="1037.4" width="14" height="2"/>
-<rect transform="scale(-1)" x="-15" y="-1051.4" width="2" height="14"/>
-<rect transform="scale(-1)" x="-15" y="-1051.4" width="14" height="2"/>
-<circle cx="10.5" cy="1041.9" r="1.5"/>
-<circle cx="5.5" cy="1046.9" r="1.5"/>
-<circle cx="10.5" cy="1046.9" r="1.5"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v14h14v-14zm2 2h10v10h-10zm7.5 1c-0.82843 4.8e-6 -1.5 0.67157-1.5 1.5 4.8e-6 0.82843 0.67157 1.5 1.5 1.5 0.82842-4.8e-6 1.5-0.67157 1.5-1.5-5e-6 -0.82843-0.67158-1.5-1.5-1.5zm-5 5c-0.82843-4.8e-6 -1.5 0.67157-1.5 1.5-4.8e-6 0.82843 0.67157 1.5 1.5 1.5 0.82843 5e-6 1.5-0.67157 1.5-1.5 4.8e-6 -0.82843-0.67157-1.5-1.5-1.5zm5 0c-0.82843 4.8e-6 -1.5 0.67157-1.5 1.5 4.8e-6 0.82842 0.67157 1.5 1.5 1.5 0.82842-5e-6 1.5-0.67158 1.5-1.5-5e-6 -0.82843-0.67158-1.5-1.5-1.5z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_quat.svg b/editor/icons/icon_quat.svg
index 076770360c..fc99c33aeb 100644
--- a/editor/icons/icon_quat.svg
+++ b/editor/icons/icon_quat.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m7 1v6h2v-6h-2zm0 12v2h2v-2h-2z"/>
-<path d="m11 1039.8v2.0137a5 2 0 0 1 2 1.5957 5 2 0 0 1 -5 2 5 2 0 0 1 -5 -2 5 2 0 0 1 2 -1.5977v-2.0097a7 4 0 0 0 -4 3.6074 7 4 0 0 0 7 4 7 4 0 0 0 7 -4 7 4 0 0 0 -4 -3.6094z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m7 1v6h2v-6h-2zm4 2.3906v2.0137a5 2 0 0 1 2 1.5957 5 2 0 0 1 -5 2 5 2 0 0 1 -5 -2 5 2 0 0 1 2 -1.5977v-2.0098a7 4 0 0 0 -4 3.6074 7 4 0 0 0 7 4 7 4 0 0 0 7 -4 7 4 0 0 0 -4 -3.6094zm-4 9.6094v2h2v-2h-2z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_range.svg b/editor/icons/icon_range.svg
index e8b62cd723..4bf0170e55 100644
--- a/editor/icons/icon_range.svg
+++ b/editor/icons/icon_range.svg
@@ -1,9 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<rect x="1" y="1039.4" width="2" height="10"/>
-<rect x="1" y="1043.4" width="13" height="2"/>
-<rect x="13" y="1039.4" width="2" height="10"/>
-<rect x="5" y="1041.4" width="2" height="6"/>
-<rect x="9" y="1041.4" width="2" height="6"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 3v10h2v-4h2v2h2v-2h2v2h2v-2h2v4h2v-10h-2v4h-2v-2h-2v2h-2v-2h-2v2h-2v-4z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_rating_no_star.svg b/editor/icons/icon_rating_no_star.svg
deleted file mode 100644
index f46f90eae9..0000000000
--- a/editor/icons/icon_rating_no_star.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<g fill="#c3ae65">
-<path transform="translate(0 1036.4)" d="m8 1.7246-2.375 4.0977-4.625 1.0977 3.2363 3.4063-0.35938 4.6738 4.1387-1.9766 4.1582 1.9414-0.39648-4.6523 3.2227-3.3926-4.625-1.0977z" fill="#ffd684" fill-opacity=".58824"/>
-</g>
-</g>
-</svg>
diff --git a/editor/icons/icon_rating_star.svg b/editor/icons/icon_rating_star.svg
deleted file mode 100644
index f4a0199007..0000000000
--- a/editor/icons/icon_rating_star.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path d="m8 1038.1-2.3741 4.0973-4.6259 1.0978l3.2361 3.4074-0.35866 4.6735 4.1389-1.9766 4.1572 1.9421-0.39534-4.6532 3.2218-3.3932-4.6259-1.0978-2.3741-4.0973z" fill="#ffd684"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_ray_cast.svg b/editor/icons/icon_ray_cast.svg
index ab2a9a58c8..97901fb010 100644
--- a/editor/icons/icon_ray_cast.svg
+++ b/editor/icons/icon_ray_cast.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fc9c9c" fill-opacity=".99608">
-<rect x="7" y="1037.4" width="2" height="9"/>
-<path d="m4 1046.4h8l-4 5z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m7 1v9h-3l4 5 4-5h-3v-9h-2z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_ray_shape.svg b/editor/icons/icon_ray_shape.svg
index 4591b0a3f9..48c53eae70 100644
--- a/editor/icons/icon_ray_shape.svg
+++ b/editor/icons/icon_ray_shape.svg
@@ -1,9 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill-rule="evenodd">
-<path d="m8 1051.4-2-2v-7l2 2z" fill="#a2d2ff"/>
-<path d="m8 1047.9-2-1.5v-4l2 2z" fill="#2998ff"/>
-<path d="m8 1037.4-6 5 6 4z" fill="#a2d2ff"/>
-<path d="m8 1051.4 2-2v-7l-2 2z" fill="#2998ff"/>
-<path d="m8 1037.4 6 5-6 4z" fill="#2998ff"/>
+<path transform="translate(0 1036.4)" d="m8 1l-6 5 4 2.666v4.334l2 2v-5-2-7z" fill="#a2d2ff"/>
+<path transform="translate(0 1036.4)" d="m8 1v7 2l-2-1.334v1.334l2 1.5v3.5l2-2v-4.334l4-2.666-6-5z" fill="#2998ff"/>
</g>
</svg>
diff --git a/editor/icons/icon_ray_shape_2d.svg b/editor/icons/icon_ray_shape_2d.svg
index 89533b8407..318d92e4ea 100644
--- a/editor/icons/icon_ray_shape_2d.svg
+++ b/editor/icons/icon_ray_shape_2d.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="none" stroke="#68b6ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
-<path d="m8 1038.4v12"/>
-<path d="m5 1047.4 3 3 3-3"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1a1 1 0 0 0 -1 1v9.5859l-1.293-1.293a1 1 0 0 0 -0.7207 -0.29102 1 1 0 0 0 -0.69336 0.29102 1 1 0 0 0 0 1.4141l3 3a1.0001 1.0001 0 0 0 0.0039062 0.003907 1 1 0 0 0 0.050781 0.044921 1.0001 1.0001 0 0 0 0.03125 0.027344 1 1 0 0 0 0.048828 0.035156 1.0001 1.0001 0 0 0 0.023438 0.015625 1 1 0 0 0 0.076172 0.044922 1.0001 1.0001 0 0 0 0.0058593 0.003906 1 1 0 0 0 0.013672 0.007813 1.0001 1.0001 0 0 0 0.078125 0.035156 1 1 0 0 0 0.074219 0.025391 1.0001 1.0001 0 0 0 0.025391 0.009766 1 1 0 0 0 0.039062 0.009765 1.0001 1.0001 0 0 0 0.068359 0.013672 1.0001 1.0001 0 0 0 0.097656 0.011719 1.0001 1.0001 0 0 0 0.0078125 0 1 1 0 0 0 0.0625 0.003906 1 1 0 0 0 0.015625 -0.001953 1.0001 1.0001 0 0 0 0.083984 -0.003906 1 1 0 0 0 0.015625 -0.001953 1.0001 1.0001 0 0 0 0.083984 -0.013672 1.0001 1.0001 0 0 0 0.052734 -0.013672 1 1 0 0 0 0.058594 -0.015625 1.0001 1.0001 0 0 0 0.078125 -0.029297 1 1 0 0 0 0.013672 -0.00586 1.0001 1.0001 0 0 0 0.076172 -0.037109 1 1 0 0 0 0.013672 -0.007812 1.0001 1.0001 0 0 0 0.072266 -0.044922 1 1 0 0 0 0.011719 -0.007813 1.0001 1.0001 0 0 0 0.068359 -0.052734 1 1 0 0 0 0.011719 -0.009766 1.0001 1.0001 0 0 0 0.050781 -0.046875l0.0097657-0.011719 2.9902-2.9883a1 1 0 0 0 0 -1.4141 1 1 0 0 0 -1.4141 0l-1.293 1.293v-9.5859a1 1 0 0 0 -1 -1z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#68b6ff" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_real.svg b/editor/icons/icon_real.svg
deleted file mode 100644
index 68f477f727..0000000000
--- a/editor/icons/icon_real.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="14" height="14" version="1.1" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1038.4)" fill="#cf68ea">
-<rect x="3" y="1040.4" width="2" height="11"/>
-<rect x="3" y="1039.4" width="4" height="2"/>
-<path transform="translate(0 1038.4)" d="m7 1v2a2 2 0 0 1 2 2 2 2 0 0 1 -2 2v2a4 4 0 0 0 4 -4 4 4 0 0 0 -4 -4z"/>
-<rect x="3" y="1045.4" width="4" height="2"/>
-<rect transform="rotate(90)" x="1049.4" y="-12" width="2" height="2"/>
-<path transform="translate(0 1038.4)" d="m8 7v2a2 2 0 0 1 2 2h2a4 4 0 0 0 -4 -4z"/>
-<rect transform="rotate(90)" x="1045.4" y="-8" width="2" height="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_reference_rect.svg b/editor/icons/icon_reference_rect.svg
index 6756d4bb2f..7a89e62e4e 100644
--- a/editor/icons/icon_reference_rect.svg
+++ b/editor/icons/icon_reference_rect.svg
@@ -1,12 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<rect x="1" y="1037.4" width="2" height="2"/>
-<rect x="13" y="1037.4" width="2" height="2"/>
-<rect x="4" y="1037.4" width="8" height="2"/>
-<rect x="4" y="1049.4" width="8" height="2"/>
-<rect x="13" y="1049.4" width="2" height="2"/>
-<rect x="1" y="1049.4" width="2" height="2"/>
-<rect transform="rotate(90)" x="1040.4" y="-3" width="8" height="2"/>
-<rect transform="rotate(90)" x="1040.4" y="-15" width="8" height="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v2h2v-2h-2zm3 0v2h8v-2h-8zm9 0v2h2v-2h-2zm-12 3v8h2v-8h-2zm12 0v8h2v-8h-2zm-12 9v2h2v-2h-2zm3 0v2h8v-2h-8zm9 0v2h2v-2h-2z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_region_edit.svg b/editor/icons/icon_region_edit.svg
index 484af3db71..c6ceef878c 100644
--- a/editor/icons/icon_region_edit.svg
+++ b/editor/icons/icon_region_edit.svg
@@ -1,13 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)" fill="#e0e0e0">
<rect x="6" y="1042.4" width="6" height="6"/>
-<rect x="6" y="1037.4" width="6" height="4" fill-opacity=".32549"/>
-<rect x="1" y="1037.4" width="4" height="4" fill-opacity=".32549"/>
-<rect x="1" y="1042.4" width="4" height="6" fill-opacity=".32549"/>
-<rect x="1" y="1049.4" width="4" height="2" fill-opacity=".32549"/>
-<rect x="6" y="1049.4" width="6" height="2" fill-opacity=".32549"/>
-<rect x="13" y="1042.4" width="2" height="6" fill-opacity=".32549"/>
-<rect x="13" y="1037.4" width="2" height="4" fill-opacity=".32549"/>
-<rect x="13" y="1049.4" width="2" height="2" fill-opacity=".32549"/>
+<path transform="translate(0 1036.4)" d="m1 1v4h4v-4h-4zm5 0v4h6v-4h-6zm7 0v4h2v-4h-2zm-12 5v6h4v-6h-4zm12 0v6h2v-6h-2zm-12 7v2h4v-2h-4zm5 0v2h6v-2h-6zm7 0v2h2v-2h-2z" fill-opacity=".32549"/>
</g>
</svg>
diff --git a/editor/icons/icon_remote.svg b/editor/icons/icon_remote.svg
deleted file mode 100644
index 2066464a82..0000000000
--- a/editor/icons/icon_remote.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<circle cx="8" cy="1043.4" r="2"/>
-<rect x="7" y="1044.4" width="2" height="7"/>
-<path transform="translate(0 1036.4)" d="m8.0879 1a6 6 0 0 0 -4.3301 1.7578 6 6 0 0 0 0 8.4844l1.416-1.416a4 4 0 0 1 -1.1738 -2.8262 4 4 0 0 1 4 -4 4 4 0 0 1 4 4 4 4 0 0 1 -1.1738 2.8262l1.416 1.416a6 6 0 0 0 0 -8.4844 6 6 0 0 0 -4.1543 -1.7578z"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_remote_transform.svg b/editor/icons/icon_remote_transform.svg
index 9cb1c67dfb..ab79ae2bb6 100644
--- a/editor/icons/icon_remote_transform.svg
+++ b/editor/icons/icon_remote_transform.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path d="m12 1047.4a4 4 0 0 1 -2 3.4641 4 4 0 0 1 -4 0 4 4 0 0 1 -2 -3.4641h4z" fill="#fc9c9c"/>
-<rect x="7" y="1045.4" width="2" height="4" ry="1" fill="#fc9c9c"/>
-<path d="m1.9378 1041.9a7 7 0 0 1 6.0622 -3.5 7 7 0 0 1 6.0622 3.5" fill="none" stroke="#fc9c9c" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
-<path d="m5.1022 1044.6a3 3 0 0 1 2.8978 -2.2235 3 3 0 0 1 2.8978 2.2235" fill="none" stroke="#fc9c9c" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+<g transform="translate(0 -1036.4)" fill="#fc9c9c">
+<path transform="translate(0 1036.4)" d="m8 1c-2.8565 0-5.4995 1.5262-6.9277 4a1 1 0 0 0 0.36523 1.3672 1 1 0 0 0 1.3672 -0.36719c1.0726-1.8578 3.0501-3 5.1953-3 2.1452 0 4.1227 1.1422 5.1953 3a1 1 0 0 0 1.3672 0.36719 1 1 0 0 0 0.36523 -1.3672c-1.4283-2.4738-4.0712-4-6.9277-4zm0 4c-1.8056 0-3.396 1.2207-3.8633 2.9648a1 1 0 0 0 0.70703 1.2246 1 1 0 0 0 1.2246 -0.70703c0.23553-0.8791 1.0216-1.4824 1.9316-1.4824s1.6961 0.60332 1.9316 1.4824a1 1 0 0 0 1.2246 0.70703 1 1 0 0 0 0.70703 -1.2246c-0.46732-1.7441-2.0577-2.9648-3.8633-2.9648zm0 4c-0.554 0-1 0.446-1 1v1h-3a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2 -3.4648h-3v-1c0-0.554-0.446-1-1-1z"/>
</g>
</svg>
diff --git a/editor/icons/icon_remote_transform_2d.svg b/editor/icons/icon_remote_transform_2d.svg
index f3c2d65e97..76b1d53cc7 100644
--- a/editor/icons/icon_remote_transform_2d.svg
+++ b/editor/icons/icon_remote_transform_2d.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m12 1047.4a4 4 0 0 1 -2 3.4641 4 4 0 0 1 -4 0 4 4 0 0 1 -2 -3.4641h4z" fill="#a5b7f3" fill-opacity=".98824"/>
-<rect x="7" y="1045.4" width="2" height="4" ry="1" fill="#a5b7f3" fill-opacity=".98824"/>
-<path d="m1.9378 1041.9a7 7 0 0 1 6.0622 -3.5 7 7 0 0 1 6.0622 3.5" fill="none" stroke="#a5b7f3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
-<path d="m5.1022 1044.6a3 3 0 0 1 2.8978 -2.2235 3 3 0 0 1 2.8978 2.2235" fill="none" stroke="#a5b7f3" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m8 1c-2.8565 0-5.4995 1.5262-6.9277 4a1 1 0 0 0 0.36523 1.3672 1 1 0 0 0 1.3672 -0.36719c1.0726-1.8578 3.0501-3 5.1953-3 2.1452 0 4.1227 1.1422 5.1953 3a1 1 0 0 0 1.3672 0.36719 1 1 0 0 0 0.36523 -1.3672c-1.4283-2.4738-4.0712-4-6.9277-4zm0 4c-1.8056 0-3.396 1.2207-3.8633 2.9648a1 1 0 0 0 0.70703 1.2246 1 1 0 0 0 1.2246 -0.70703c0.23553-0.8791 1.0216-1.4824 1.9316-1.4824s1.6961 0.60332 1.9316 1.4824a1 1 0 0 0 1.2246 0.70703 1 1 0 0 0 0.70703 -1.2246c-0.46732-1.7441-2.0577-2.9648-3.8633-2.9648zm0 4c-0.554 0-1 0.446-1 1v1h-3a4 4 0 0 0 2 3.4648 4 4 0 0 0 4 0 4 4 0 0 0 2 -3.4648h-3v-1c0-0.554-0.446-1-1-1z" fill="#a5b7f3" fill-opacity=".98824"/>
</g>
</svg>
diff --git a/editor/icons/icon_remove.svg b/editor/icons/icon_remove.svg
index 3b03aa9305..ee988ab719 100644
--- a/editor/icons/icon_remove.svg
+++ b/editor/icons/icon_remove.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0" fill-opacity=".99608">
-<path transform="translate(0 1036.4)" d="m2 5v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2v-8h-12zm1 2h2v6h-2v-6zm4 0h2v6h-2v-6zm4 0h2v6h-2v-6z"/>
-<rect x="1" y="1038.4" width="14" height="2"/>
-<rect x="5" y="1037.4" width="6" height="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m5 1v1h-4v2h14v-2h-4v-1h-6zm-3 4v8a2 2 0 0 0 2 2h8a2 2 0 0 0 2 -2v-8h-12zm1 2h2v6h-2v-6zm4 0h2v6h-2v-6zm4 0h2v6h-2v-6z" fill="#e0e0e0" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_resource_preloader.svg b/editor/icons/icon_resource_preloader.svg
index 82f24d7400..2d186e17da 100644
--- a/editor/icons/icon_resource_preloader.svg
+++ b/editor/icons/icon_resource_preloader.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<g fill="#e0e0e0" fill-rule="evenodd">
-<path transform="translate(0 1036.4)" d="m7.9629 1.002a1.0001 1.0001 0 0 0 -0.41016 0.10352l-6 3a1.0001 1.0001 0 0 0 -0.55273 0.89453v6a1.0001 1.0001 0 0 0 0.55273 0.89453l6 3a1.0001 1.0001 0 0 0 0.89453 0l6-3a1.0001 1.0001 0 0 0 0.55273 -0.89453v-6a1.0001 1.0001 0 0 0 -0.55273 -0.89453l-6-3a1.0001 1.0001 0 0 0 -0.48438 -0.10352zm0.037109 2.1172l3.7637 1.8809-3.7637 1.8828-3.7637-1.8828 3.7637-1.8809zm-5 3.5l4 2v3.7637l-4-2v-3.7637zm10 0v3.7637l-4 2v-3.7637l4-2z" color="#000000" color-rendering="auto" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
-<path d="m11 1042.4-6-3-3 2 6 3z"/>
-</g>
+<path transform="translate(0 1036.4)" d="m7.9629 1.002a1.0001 1.0001 0 0 0 -0.41016 0.10352l-6 3a1.0001 1.0001 0 0 0 -0.55273 0.89453v6a1.0001 1.0001 0 0 0 0.55273 0.89453l6 3a1.0001 1.0001 0 0 0 0.89453 0l6-3a1.0001 1.0001 0 0 0 0.55273 -0.89453v-6a1.0001 1.0001 0 0 0 -0.55273 -0.89453l-6-3a1.0001 1.0001 0 0 0 -0.48438 -0.10352zm0.037109 2.1172l3.7637 1.8809-1.3809 0.69141-3.7637-1.8828 1.3809-0.68945zm-5 3.5l4 2v3.7637l-4-2v-3.7637zm10 0v3.7637l-4 2v-3.7637l4-2z" color="#000000" color-rendering="auto" fill="#e0e0e0" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_rich_text_label.svg b/editor/icons/icon_rich_text_label.svg
index c0b4039e3a..3227547b41 100644
--- a/editor/icons/icon_rich_text_label.svg
+++ b/editor/icons/icon_rich_text_label.svg
@@ -1,11 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<rect x="1" y="1037.4" width="8" height="2"/>
-<rect x="1" y="1041.4" width="2" height="2"/>
-<rect x="5" y="1041.4" width="4" height="2"/>
-<rect x="1" y="1045.4" width="8" height="2"/>
-<rect x="1" y="1049.4" width="4" height="2"/>
-<rect x="7" y="1049.4" width="2" height="2"/>
-<path d="m12 1048.4h-2l3 3 3-3h-2v-8h2l-3-3-3 3h2z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 1v2h8v-2h-8zm12 0l-3 3h2v8h-2l3 3 3-3h-2v-8h2l-3-3zm-12 4v2h2v-2h-2zm4 0v2h4v-2h-4zm-4 4v2h8v-2h-8zm0 4v2h4v-2h-4zm6 0v2h2v-2h-2z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_rigid_body.svg b/editor/icons/icon_rigid_body.svg
index 61aa52162d..bb87d914b6 100644
--- a/editor/icons/icon_rigid_body.svg
+++ b/editor/icons/icon_rigid_body.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fc9c9c" fill-opacity=".99608">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 0.035156 0.69922 7 7 0 0 0 0.27734 1.3691 7 7 0 0 0 0.91016 1.8848 7 7 0 0 0 0.30273 0.4082c7.85e-4 -0.00256 0.0011667-0.005252 0.0019532-0.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422 -0.80273c0.001375 3.93e-4 0.002531 0.00156 0.003906 0.001953a7 7 0 0 0 0.035156 -0.021485 7 7 0 0 0 0.42578 -0.25 7 7 0 0 0 0.16992 -0.10352 7 7 0 0 0 0.36914 -0.26953 7 7 0 0 0 0.20508 -0.15625 7 7 0 0 0 0.3418 -0.30859 7 7 0 0 0 0.16406 -0.1543 7 7 0 0 0 0.33008 -0.36133 7 7 0 0 0 0.14062 -0.16016 7 7 0 0 0 0.27734 -0.37305 7 7 0 0 0 0.13867 -0.19531 7 7 0 0 0 0.21875 -0.36133 7 7 0 0 0 0.14258 -0.25 7 7 0 0 0 0.15625 -0.33398 7 7 0 0 0 0.13867 -0.31055 7 7 0 0 0 0.10742 -0.30859 7 7 0 0 0 0.11914 -0.35352 7 7 0 0 0 0.087891 -0.36914 7 7 0 0 0 0.066406 -0.29297 7 7 0 0 0 0.056641 -0.40039 7 7 0 0 0 0.037109 -0.3125 7 7 0 0 0 0.025391 -0.55273 7 7 0 0 0 -4.3848 -6.4883 7 7 0 0 0 -0.007812 -0.0039063 7 7 0 0 0 -0.001953 0 7 7 0 0 0 -0.61523 -0.21289 7 7 0 0 0 -0.044922 -0.015625 7 7 0 0 0 -0.0058594 -0.0019531 7 7 0 0 0 -0.55078 -0.13086 7 7 0 0 0 -0.14062 -0.03125 7 7 0 0 0 -0.55078 -0.072266 7 7 0 0 0 -0.14258 -0.017578 7 7 0 0 0 -0.55469 -0.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 1 -0.94922 1.6992c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473 0.33203 6 6 0 0 1 -5.0547 -2.7695c0.23771-0.5785 0.50336-1.1403 0.82617-1.6563a2 2 0 0 1 -0.77148 -1.5742h-1a6 6 0 0 1 1.123 -3.4863c0.14632 0.65093 0.35776 1.2833 0.68359 1.8848a2 2 0 0 1 1.1934 -0.39844 2 2 0 0 1 1.0508 0.30078c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668z"/>
-<circle cx="5" cy="1044.4" r="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 0.035156 0.69922 7 7 0 0 0 0.27734 1.3691 7 7 0 0 0 0.91016 1.8848 7 7 0 0 0 0.30273 0.4082c7.85e-4 -0.00256 0.0011667-0.005252 0.0019532-0.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422 -0.80273c0.001374 3.93e-4 0.002531 0.00156 0.003906 0.001953a7 7 0 0 0 0.035156 -0.021485 7 7 0 0 0 0.42578 -0.25 7 7 0 0 0 0.16992 -0.10352 7 7 0 0 0 0.36914 -0.26953 7 7 0 0 0 0.20508 -0.15625 7 7 0 0 0 0.3418 -0.30859 7 7 0 0 0 0.16406 -0.1543 7 7 0 0 0 0.33008 -0.36133 7 7 0 0 0 0.14062 -0.16016 7 7 0 0 0 0.27734 -0.37305 7 7 0 0 0 0.13867 -0.19531 7 7 0 0 0 0.21875 -0.36133 7 7 0 0 0 0.14258 -0.25 7 7 0 0 0 0.15625 -0.33398 7 7 0 0 0 0.13867 -0.31055 7 7 0 0 0 0.10742 -0.30859 7 7 0 0 0 0.11914 -0.35352 7 7 0 0 0 0.087891 -0.36914 7 7 0 0 0 0.066406 -0.29297 7 7 0 0 0 0.056641 -0.40039 7 7 0 0 0 0.037109 -0.3125 7 7 0 0 0 0.025391 -0.55273 7 7 0 0 0 -4.3848 -6.4883 7 7 0 0 0 -0.007812 -0.0039063 7 7 0 0 0 -0.001953 0 7 7 0 0 0 -0.61523 -0.21289 7 7 0 0 0 -0.044922 -0.015625 7 7 0 0 0 -0.0058594 -0.0019531 7 7 0 0 0 -0.55078 -0.13086 7 7 0 0 0 -0.14062 -0.03125 7 7 0 0 0 -0.55078 -0.072266 7 7 0 0 0 -0.14258 -0.017578 7 7 0 0 0 -0.55469 -0.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -0.94922 -1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c0.14632 0.65093 0.35776 1.2833 0.68359 1.8848a2 2 0 0 0 -0.80664 1.6016h-1a6 6 0 0 1 1.123 -3.4863zm1.877 1.4863a2 2 0 0 0 -0.10938 0.0039062 2 2 0 0 1 0.10938 -0.0039062zm-0.18945 0.011719a2 2 0 0 0 -0.12109 0.013672 2 2 0 0 1 0.12109 -0.013672zm-0.44141 0.09375a2 2 0 0 0 -0.056641 0.019531 2 2 0 0 1 0.056641 -0.019531zm-1.3594 2.0605a2 2 0 0 0 0.013672 0.11914 2 2 0 0 1 -0.013672 -0.11914zm0.027344 0.20898a2 2 0 0 0 0.017578 0.080078 2 2 0 0 1 -0.017578 -0.080078zm0.73438 1.1992a2 2 0 0 0 1.2285 0.42578 2 2 0 0 0 1.0508 -0.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473 0.33203 6 6 0 0 1 -5.0547 -2.7695c0.23771-0.5785 0.50336-1.1403 0.82617-1.6563z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_rigid_body_2d.svg b/editor/icons/icon_rigid_body_2d.svg
index c28e009e85..3f67f660fc 100644
--- a/editor/icons/icon_rigid_body_2d.svg
+++ b/editor/icons/icon_rigid_body_2d.svg
@@ -1,13 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m8 1037.4a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 1a6 6 0 0 1 6 6 6 6 0 0 1 -6 6 6 6 0 0 1 -6 -6 6 6 0 0 1 6 -6z" fill="#a5b7f3" fill-opacity=".98824"/>
-<path d="m8 1037.4a7 7 0 0 0 -5.0879 2.2051c0.10495 1.1207 0.35417 2.1959 0.89453 3.1933a2 2 0 0 1 1.1934 -0.3984 2 2 0 0 1 1.0508 0.3008c1.7873-2.6932 3.4181-3.9904 5.1914-4.4981a7 7 0 0 0 -3.2422 -0.8027zm-7 7a7 7 0 0 0 1.5254 4.3613c0.30281-0.9877 0.71628-1.9403 1.2461-2.7871a2 2 0 0 1 -0.77148 -1.5742h-2zm6 0a2 2 0 0 1 -0.94922 1.6992c1.7887 2.6953 3.4204 3.9932 5.1953 4.5a7 7 0 0 0 3.7539 -6.1992h-8z" fill="#a5b7f3" fill-opacity=".98824"/>
-<circle cx="5" cy="1044.4" r="2" fill="#a5b7f3" fill-opacity=".98824"/>
-<path d="m45 1037.4a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 1a6 6 0 0 1 6 6 6 6 0 0 1 -6 6 6 6 0 0 1 -6 -6 6 6 0 0 1 6 -6z" fill="#a5b7f3" fill-opacity=".98824"/>
-<path d="m38 1044.4c5 0.01 9 0.01 14 0-2-2.9934-5-4-7-4s-5 1.0066-7 4z" fill="#a5b7f3" fill-opacity=".98824" fill-rule="evenodd"/>
-<path d="m38 1044.4c0 3.866 3.134 7 7 7s7-3.134 7-7c-2 2.9933-5 4-7 4s-5-1.0067-7-4z" fill="#a3b6f2"/>
-<path d="m-9 1037.4a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 1a6 6 0 0 1 6 6 6 6 0 0 1 -6 6 6 6 0 0 1 -6 -6 6 6 0 0 1 6 -6z" fill="#a3b6f2"/>
-<circle cx="-9" cy="1044.4" r="2" fill="#a3b6f2"/>
-<path d="m-9 1037.4a7 7 0 0 0 -3.5 0.9375l3.5 6.0625 3.5-6.0625a7 7 0 0 0 -3.5 -0.9375zm0 7 3.5 6.0625a7 7 0 0 0 2.5625 -2.5625 7 7 0 0 0 0.9375 -3.5h-7zh-7a7 7 0 0 0 0.9375 3.5 7 7 0 0 0 2.5625 2.5625l3.5-6.0625z" fill="#a3b6f2"/>
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 1.2227 3.9531 7 7 0 0 0 0.30273 0.4082c7.85e-4 -0.00256 0.0011667-0.005252 0.0019532-0.007812a7 7 0 0 0 5.4727 2.6465 7 7 0 0 0 3.2422 -0.80273c0.001375 3.93e-4 0.002531 0.00156 0.003906 0.001953a7 7 0 0 0 0.035156 -0.021485 7 7 0 0 0 0.42578 -0.25 7 7 0 0 0 0.16992 -0.10352 7 7 0 0 0 0.36914 -0.26953 7 7 0 0 0 0.20508 -0.15625 7 7 0 0 0 0.3418 -0.30859 7 7 0 0 0 0.16406 -0.1543 7 7 0 0 0 0.33008 -0.36133 7 7 0 0 0 0.14062 -0.16016 7 7 0 0 0 0.27734 -0.37305 7 7 0 0 0 0.13867 -0.19531 7 7 0 0 0 0.21875 -0.36133 7 7 0 0 0 0.14258 -0.25 7 7 0 0 0 0.15625 -0.33398 7 7 0 0 0 0.13867 -0.31055 7 7 0 0 0 0.10742 -0.30859 7 7 0 0 0 0.11914 -0.35352 7 7 0 0 0 0.087891 -0.36914 7 7 0 0 0 0.066406 -0.29297 7 7 0 0 0 0.056641 -0.40039 7 7 0 0 0 0.037109 -0.3125 7 7 0 0 0 0.025391 -0.55273 7 7 0 0 0 -4.3926 -6.4922 7 7 0 0 0 -0.001953 0 7 7 0 0 0 -0.66016 -0.22852 7 7 0 0 0 -0.0058594 -0.0019531 7 7 0 0 0 -0.55078 -0.13086 7 7 0 0 0 -0.14062 -0.03125 7 7 0 0 0 -0.55078 -0.072266 7 7 0 0 0 -0.14258 -0.017578 7 7 0 0 0 -0.55469 -0.025391zm1.9512 1.334a6 6 0 0 1 4.0488 5.666h-7a2 2 0 0 0 -0.94922 -1.6992c1.3464-2.0289 2.6038-3.2631 3.9004-3.9668zm-6.8281 2.1797c0.14632 0.65093 0.35776 1.2833 0.68359 1.8848a2 2 0 0 0 -0.80664 1.6016h-1a6 6 0 0 1 1.123 -3.4863zm1.877 1.4863a2 2 0 0 0 -0.10938 0.0039062 2 2 0 0 1 0.10938 -0.0039062zm-0.18945 0.011719a2 2 0 0 0 -0.12109 0.013672 2 2 0 0 1 0.12109 -0.013672zm-0.44141 0.09375a2 2 0 0 0 -0.056641 0.019531 2 2 0 0 1 0.056641 -0.019531zm-1.3594 2.0605a2 2 0 0 0 0.013672 0.11914 2 2 0 0 1 -0.013672 -0.11914zm0.027344 0.20898a2 2 0 0 0 0.017578 0.080078 2 2 0 0 1 -0.017578 -0.080078zm0.73438 1.1992a2 2 0 0 0 1.2285 0.42578 2 2 0 0 0 1.0508 -0.30078c1.345 2.0268 2.6013 3.2645 3.8965 3.9688a6 6 0 0 1 -1.9473 0.33203 6 6 0 0 1 -5.0547 -2.7695c0.23771-0.5785 0.50336-1.1403 0.82617-1.6563z" fill="#a5b7f3" fill-opacity=".98824"/>
</g>
</svg>
diff --git a/editor/icons/icon_room_bounds.svg b/editor/icons/icon_room_bounds.svg
index f092865568..4c5c3387f6 100644
--- a/editor/icons/icon_room_bounds.svg
+++ b/editor/icons/icon_room_bounds.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m1 1v1 1h1v-1h1v-1h-1-1zm12 0v1h1v1h1v-1-1h-1-1zm-5.0371 0.0019531a1.0001 1.0001 0 0 0 -0.41016 0.10352l-6 3a1.0001 1.0001 0 0 0 -0.55273 0.89453v6a1.0001 1.0001 0 0 0 0.55273 0.89453l6 3a1.0001 1.0001 0 0 0 0.89453 0l6-3a1.0001 1.0001 0 0 0 0.55273 -0.89453v-6a1.0001 1.0001 0 0 0 -0.55273 -0.89453l-6-3a1.0001 1.0001 0 0 0 -0.48438 -0.10352zm1.0371 2.6172l4 2v3.7637l-4-2v-3.7637zm-1 5.5l3.7637 1.8809-3.7637 1.8828-3.7637-1.8828 3.7637-1.8809zm-7 3.8809v1 1h1 1v-1h-1v-1h-1zm13 0v1h-1v1h1 1v-1-1h-1z" color="#000000" color-rendering="auto" fill="#e0e0e0" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1036.4)" d="m1 1v2h1v-1h1v-1zm12 0v1h1v1h1v-2zm-5.0371 0.00195c-0.14254 0.00487-0.28238 0.04016-0.41016 0.10352l-6 3c-0.33878 0.16944-0.55276 0.51574-0.55273 0.89453v6c-2.576e-5 0.37879 0.21395 0.72509 0.55273 0.89453l6 3c0.28156 0.14078 0.61297 0.14078 0.89453 0l6-3c0.33878-0.16944 0.55276-0.51574 0.55273-0.89453v-6c2.6e-5 -0.37879-0.21395-0.72509-0.55273-0.89453l-6-3c-0.15022-0.074574-0.31679-0.11017-0.48438-0.10352zm1.0371 2.6172l4 2v3.7637l-4-2zm-1 5.5l3.7637 1.8809-3.7637 1.8828-3.7637-1.8828zm-7 3.8809v2h2v-1h-1v-1zm13 0v1h-1v1h2v-2z" color="#000000" color-rendering="auto" fill="#e0e0e0" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_rotate_0.svg b/editor/icons/icon_rotate_0.svg
index d9ad4eedea..861e2415a5 100644
--- a/editor/icons/icon_rotate_0.svg
+++ b/editor/icons/icon_rotate_0.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<rect x="7" y="1038.4" width="2" height="7"/>
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5 -5 5 5 0 0 1 5 -5z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm1 2.1016a5 5 0 0 1 4 4.8984 5 5 0 0 1 -5 5 5 5 0 0 1 -5 -5 5 5 0 0 1 4 -4.8945v5.8945h2v-5.8984z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_rotate_180.svg b/editor/icons/icon_rotate_180.svg
index 3344c16e3f..115ef13b7a 100644
--- a/editor/icons/icon_rotate_180.svg
+++ b/editor/icons/icon_rotate_180.svg
@@ -1,9 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m8 1038.4a6 6 0 0 1 6 6h-6z"/>
-<rect x="7" y="1038.4" width="2" height="7"/>
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5 -5 5 5 0 0 1 5 -5z"/>
-<rect transform="scale(-1)" x="-9" y="-1050.4" width="2" height="7"/>
-<path d="m14 1044.4a6 6 0 0 1 -6 6v-6z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 3.8541 0 7-3.1458 7-7 0-3.8541-3.1459-7-7-7zm0 2v10c-2.7733 0-5-2.2267-5-5 0-2.7732 2.2267-5 5-5z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_rotate_270.svg b/editor/icons/icon_rotate_270.svg
index 567e4edd5b..8c9e8d7736 100644
--- a/editor/icons/icon_rotate_270.svg
+++ b/editor/icons/icon_rotate_270.svg
@@ -1,10 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m8 1038.4a6 6 0 0 1 6 6h-6z"/>
-<rect x="7" y="1038.4" width="2" height="7"/>
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5 -5 5 5 0 0 1 5 -5z"/>
-<rect transform="rotate(-90)" x="-1045.4" y="2" width="2" height="7"/>
-<path d="m8 1050.4a6 6 0 0 1 -6 -6h6z"/>
-<path d="m14 1044.4a6 6 0 0 1 -6 6v-6z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2v5h-5a5 5 0 0 1 5 -5z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_rotate_90.svg b/editor/icons/icon_rotate_90.svg
index 6a3a449db6..ed8cb1eeb6 100644
--- a/editor/icons/icon_rotate_90.svg
+++ b/editor/icons/icon_rotate_90.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m8 1038.4a6 6 0 0 1 6 6h-6z"/>
-<rect x="7" y="1038.4" width="2" height="7"/>
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5 -5 5 5 0 0 1 5 -5z"/>
-<rect transform="rotate(90)" x="1043.4" y="-14" width="2" height="7"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1c-3.8541 0-7 3.1459-7 7 0 3.8542 3.1459 7 7 7 3.7179 0 6.7102-2.9486 6.9219-6.6152a1 1 0 0 0 0.078125 -0.38477 1 1 0 0 0 -0.078125 -0.38867 1 1 0 0 0 -0.001953 -0.0039062c-0.21589-3.6627-3.2049-6.6074-6.9199-6.6074zm0 2v5h5c0 2.7733-2.2267 5-5 5-2.7733 0-5-2.2267-5-5 0-2.7732 2.2267-5 5-5z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#e0e0e0" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_sample_library.svg b/editor/icons/icon_sample_library.svg
index b5ec2bb43c..403ea5ff42 100644
--- a/editor/icons/icon_sample_library.svg
+++ b/editor/icons/icon_sample_library.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#ff8484">
-<path transform="translate(0 1036.4)" d="m9 8v1 5 1h5c0.55228 0 1-0.44772 1-1v-5c0-0.55228-0.44772-1-1-1v4l-1-1-1 1v-4z"/>
-<path d="m7.0215 1037.4a1.0001 1.0001 0 0 0 -1 0.875l-0.58984 4.7226-0.52344-1.0468a1.0001 1.0001 0 0 0 -0.89453 -0.5528h-2a1.0001 1.0001 0 1 0 0 2h1.3828l1.7227 3.4473a1.0001 1.0001 0 0 0 1.8867 -0.3223l0.58984-4.7226 0.52344 1.0449a1.0001 1.0001 0 0 0 0.89453 0.5527h3a1.0001 1.0001 0 1 0 0 -2h-2.3809l-1.7246-3.4472a1.0001 1.0001 0 0 0 -0.88672 -0.5508z" color="#000000" color-rendering="auto" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="block-progression:tb;isolation:auto;mix-blend-mode:normal;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m7.0215 1.002a1.0001 1.0001 0 0 0 -1 0.875l-0.58984 4.7227-0.52344-1.0469a1.0001 1.0001 0 0 0 -0.89453 -0.55273h-2a1.0001 1.0001 0 1 0 0 2h1.3828l1.7227 3.4473a1.0001 1.0001 0 0 0 1.8867 -0.32227l0.58984-4.7227 0.52344 1.0449a1.0001 1.0001 0 0 0 0.89453 0.55273h3a1.0001 1.0001 0 1 0 0 -2h-2.3809l-1.7246-3.4473a1.0001 1.0001 0 0 0 -0.88672 -0.55078zm1.9785 6.998v1 5 1h5c0.55228 0 1-0.44772 1-1v-5c0-0.55228-0.44772-1-1-1v4l-1-1-1 1v-4h-3z" fill="#ff8484"/>
</g>
</svg>
diff --git a/editor/icons/icon_save.svg b/editor/icons/icon_save.svg
index dae6693b26..d85b7ce452 100644
--- a/editor/icons/icon_save.svg
+++ b/editor/icons/icon_save.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-8l-4-4zh8v6h-8zm5 8c1.1046 0 2 0.89543 2 2 0 1.1046-0.89543 2-2 2s-2-0.89543-2-2c0-1.1046 0.89543-2 2-2z"/>
-<rect x="4" y="1037.4" width="3" height="5"/>
-<path d="m11 1037.4h1l3 3v2h-4z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-7-1-1l-3-3h-1v5 1h-8v-6zm1 0v5h3v-5h-3zm4 8c1.1046 0 2 0.89543 2 2 0 1.1046-0.89543 2-2 2s-2-0.89543-2-2c0-1.1046 0.89543-2 2-2z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_scroll_bar.svg b/editor/icons/icon_scroll_bar.svg
index f956615ff1..c58c31464d 100644
--- a/editor/icons/icon_scroll_bar.svg
+++ b/editor/icons/icon_scroll_bar.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m3 3c-1.1046 0-2 0.89543-2 2v6c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-6c0-1.1046-0.89543-2-2-2zm0 2h10v6h-10z" fill="#a5efac"/>
-<rect x="4" y="1042.4" width="4" height="4" fill="none"/>
-<rect x="4" y="1042.4" width="4" height="4" fill="#a5efac"/>
+<path transform="translate(0 1036.4)" d="m3 3c-1.1046 0-2 0.89543-2 2v6c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-6c0-1.1046-0.89543-2-2-2h-10zm0 2h10v6h-10v-6zm1 1v4h4v-4h-4z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_scroll_container.svg b/editor/icons/icon_scroll_container.svg
index 83ca7f753d..786bae39ef 100644
--- a/editor/icons/icon_scroll_container.svg
+++ b/editor/icons/icon_scroll_container.svg
@@ -1,9 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2zm0 2h10v10h-10z"/>
-<path d="m10 1042.4v4l2-2z"/>
-<path d="m6 1042.4v4l-2-2z"/>
-<path d="m6 1042.4h4l-2-2z"/>
-<path d="m6 1046.4h4l-2 2z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 1c-1.1046 0-2 0.89543-2 2v10c0 1.1046 0.89543 2 2 2h10c1.1046 0 2-0.89543 2-2v-10c0-1.1046-0.89543-2-2-2h-10zm0 2h10v10h-10v-10zm5 1l-2 2h4l-2-2zm2 2v4l2-2-2-2zm0 4h-4l2 2 2-2zm-4 0v-4l-2 2 2 2z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_search.svg b/editor/icons/icon_search.svg
index 6ef1d42815..9178e6c51c 100644
--- a/editor/icons/icon_search.svg
+++ b/editor/icons/icon_search.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0" fill-opacity=".99608">
-<path d="m6 1037.4a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 5 -5 5 5 0 0 0 -5 -5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3 -3 3 3 0 0 1 3 -3z"/>
-<rect transform="matrix(.70711 -.70711 .70711 .70711 0 0)" x="-733.82" y="745.3" width="2" height="7"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m6 1a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 2.7539 -0.83203l4.3164 4.3164 1.4141-1.4141-4.3164-4.3164a5 5 0 0 0 0.83203 -2.7539 5 5 0 0 0 -5 -5zm0 2a3 3 0 0 1 3 3 3 3 0 0 1 -3 3 3 3 0 0 1 -3 -3 3 3 0 0 1 3 -3z" fill="#e0e0e0" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_shader.svg b/editor/icons/icon_shader.svg
deleted file mode 100644
index f77aa837c5..0000000000
--- a/editor/icons/icon_shader.svg
+++ /dev/null
@@ -1,11 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m2 1c-0.55226 1e-4 -0.99994 0.4477-1 1v1h2 6 3l-2-2h-8z" fill="#ff7070"/>
-<path transform="translate(0 1036.4)" d="m1 3v2h2v-2h-2zm8 0v2h5l-2-2h-3z" fill="#ffeb70"/>
-<path transform="translate(0 1036.4)" d="m1 5v2h2v-2h-2zm8 0v1c0 0.554 0.44599 1 1 1h3 2v-1l-1-1h-5z" fill="#9dff70"/>
-<path transform="translate(0 1036.4)" d="m1 7v2h2v-2h-2zm12 0v2h2v-2h-2z" fill="#70ffb9"/>
-<path transform="translate(0 1036.4)" d="m1 9v2h2v-2h-2zm12 0v2h2v-2h-2z" fill="#70deff"/>
-<path transform="translate(0 1036.4)" d="m1 13v1c5.52e-5 0.5523 0.44774 0.9999 1 1h12c0.55226-1e-4 0.99994-0.4477 1-1v-1h-2-10-2z" fill="#ff70ac"/>
-<path transform="translate(0 1036.4)" d="m1 11v2h2v-2h-2zm12 0v2h2v-2h-2z" fill="#9f70ff"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_signal.svg b/editor/icons/icon_signal.svg
index 74fbdf8520..85411702cd 100644
--- a/editor/icons/icon_signal.svg
+++ b/editor/icons/icon_signal.svg
@@ -1,9 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#ff8484">
-<rect x="5" y="1043.4" width="6" height="2"/>
-<path transform="matrix(0 1.281 -.9245 0 -948.3 1038)" d="m8.1225-1036.6h-3.1225-3.1225l1.5612-2.7042 1.5612-2.7041 1.5612 2.7041z"/>
-<rect x="1" y="1039.4" width="2" height="10"/>
-<rect x="3" y="1047.4" width="4" height="2"/>
-<rect x="3" y="1039.4" width="4" height="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m1 3v10h2 4v-2h-4v-6h4v-2h-4-2zm9 1v3h-5v2h5v3l2.5-2 2.5-2-2.5-2-2.5-2z" fill="#ff8484"/>
</g>
</svg>
diff --git a/editor/icons/icon_skeleton.svg b/editor/icons/icon_skeleton.svg
index 9716940906..d5c5f301bb 100644
--- a/editor/icons/icon_skeleton.svg
+++ b/editor/icons/icon_skeleton.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fc9c9c" fill-opacity=".99608">
-<path transform="translate(0 1036.4)" d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 3 3.8691v-0.86914h1v1h1v-1h1 1v1h1v-1h1v0.86719a4 4 0 0 0 3 -3.8672 4 4 0 0 0 -4 -4h-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-4 2h2v1h-2v-1z"/>
-<path transform="translate(0 1036.4)" d="m4 9v4h1v-4h-1zm7 0v4h1v-4h-1zm-5 3v1 2h4v-2-1h-1v1h-2v-1h-1z"/>
-<path d="m8 1049.4a2 2 0 0 1 -1 1.732 2 2 0 0 1 -2 0 2 2 0 0 1 -1 -1.732h2z"/>
-<path d="m12 1049.4a2 2 0 0 1 -1 1.732 2 2 0 0 1 -2 0 2 2 0 0 1 -1 -1.732h2z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m6 2a4 4 0 0 0 -4 4 4 4 0 0 0 2 3.4531v3.5469a2 2 0 0 0 1 1.7324 2 2 0 0 0 1 0.26562v0.001953h4v-0.001953a2 2 0 0 0 1 -0.26562 2 2 0 0 0 1 -1.7324v-3.5469a4 4 0 0 0 2 -3.4531 4 4 0 0 0 -4 -4h-4zm-1 3a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm6 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-4 2h2v1h-2v-1zm-2 2h1v1h1v-1h1 1v1h1v-1h1v0.86719 3.1328h-1v-1h-1v1h-1-1v-1h-1v1h-1v-3.1309-0.86914z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_slider_joint.svg b/editor/icons/icon_slider_joint.svg
index 479323bf9a..d1469058d1 100644
--- a/editor/icons/icon_slider_joint.svg
+++ b/editor/icons/icon_slider_joint.svg
@@ -1,10 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m3 1051.4h5l-1-4z" fill="#fc9c9c" fill-opacity=".99608"/>
-<path d="m6 1048.4 9-9v3l-8 8z" fill="#fb9b9b"/>
-<path d="m10 1040.4-9 9v-3l8-8z" fill="#fb9b9b"/>
-<path d="m13 1037.4h-5l1 4z" fill="#fc9c9c" fill-opacity=".99608"/>
-<path d="m10 1038.4h-5" fill="none" stroke="#fb9b9b" stroke-linecap="round" stroke-width="2"/>
-<path d="m11 1050.4h-5" fill="none" stroke="#fb9b9b" stroke-linecap="round" stroke-width="2"/>
+<path transform="translate(0 1036.4)" d="m5 1c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1h3l-7 7v3l12-12zm10 2-12 12h8c0.55228 0 1-0.44772 1-1s-0.44772-1-1-1h-3l7-7z" fill="#fc9c9c"/>
</g>
</svg>
diff --git a/editor/icons/icon_slot.svg b/editor/icons/icon_slot.svg
index f3d27ec55e..b31d7bfbc2 100644
--- a/editor/icons/icon_slot.svg
+++ b/editor/icons/icon_slot.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#84ffb1">
-<rect x="1" y="1043.4" width="6" height="2"/>
-<path transform="matrix(0 1.281 -.9245 0 -952.3 1038)" d="m8.1225-1036.6h-3.1225-3.1225l1.5612-2.7042 1.5612-2.7041 1.5612 2.7041z"/>
-<path d="m15 1039.4v10h-2-4v-2h4v-6h-4v-2h4 2z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m9 3v2h4v6h-4v2h4 2v-10h-2-4zm-3 1v3h-5v2h5v3l2.5-2 2.5-2-2.5-2-2.5-2z" fill="#84ffb1"/>
</g>
</svg>
diff --git a/editor/icons/icon_snap.svg b/editor/icons/icon_snap.svg
index b1f36cfe43..0e535b11ce 100644
--- a/editor/icons/icon_snap.svg
+++ b/editor/icons/icon_snap.svg
@@ -1,10 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path d="m3 1036.4v3h-3v2h3v4h-3v2h3v3h2v-3-2-4h4 2 3v-2h-3v-3h-2v3h-4v-3h-2z" fill="#f3f3f3"/>
-<path d="m11 1043.4a4 4 0 0 0 -4 4h2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2h2a4 4 0 0 0 -4 -4z" fill="#ff8484"/>
-<rect x="7" y="1047.4" width="2" height="2" fill="#ff8484"/>
-<rect x="13" y="1047.4" width="2" height="2" fill="#ff8484"/>
-<rect x="7" y="1049.4" width="2" height="2" fill="#fff"/>
-<rect x="13" y="1049.4" width="2" height="2" fill="#fff"/>
+<path transform="translate(0 1036.4)" d="m3 3v2h2v-2h-2zm6 0v2h2v-2h-2zm-6 6v2h2v-2h-2zm4 4v2h2v-2h-2zm6 0v2h2v-2h-2z" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m11 7a4 4 0 0 0 -4 4v2h2v-2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2v2h2v-2a4 4 0 0 0 -4 -4z" fill="#fff" fill-opacity=".68627"/>
</g>
</svg>
diff --git a/editor/icons/icon_snap_grid.svg b/editor/icons/icon_snap_grid.svg
new file mode 100644
index 0000000000..7124bd918e
--- /dev/null
+++ b/editor/icons/icon_snap_grid.svg
@@ -0,0 +1,6 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 0v3h-3v2h3v4h-3v2h3v3h2v-9h9v-2h-3v-3h-2v3h-4v-3zm4 13v2h2v-2zm6 0v2h2v-2z" fill="#e0e0e0"/>
+<path transform="translate(0 1036.4)" d="m11 7a4 4 0 0 0 -4 4v2h2v-2a2 2 0 0 1 2 -2 2 2 0 0 1 2 2v2h2v-2a4 4 0 0 0 -4 -4z" fill="#fff" fill-opacity=".68627"/>
+</g>
+</svg>
diff --git a/editor/icons/icon_sound_room_params.svg b/editor/icons/icon_sound_room_params.svg
deleted file mode 100644
index ddec8a3cf9..0000000000
--- a/editor/icons/icon_sound_room_params.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path d="m8 1037.4-4 5h-3v4h3l4 5v-14z"/>
-<path d="m13 1039.4v10h1v-10h-1z"/>
-<path d="m10 1039.4v10h1v-10h-1z"/>
-<rect x="9" y="1041.4" width="3" height="1"/>
-<rect x="12" y="1046.4" width="3" height="1"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_spatial_sample_player.svg b/editor/icons/icon_spatial_sample_player.svg
deleted file mode 100644
index 32f70cd2a6..0000000000
--- a/editor/icons/icon_spatial_sample_player.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m8 1l-4 5h-3v4h3l4 5v-14zm5 2v10h1v-10h-1zm-3 3v5h1v-5h-1z" fill="#fc9c9c" fill-opacity=".99608"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_spatial_stream_player.svg b/editor/icons/icon_spatial_stream_player.svg
deleted file mode 100644
index 20fadb59f8..0000000000
--- a/editor/icons/icon_spatial_stream_player.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m5 2c-0.55228 0-1 0.44772-1 1v1 7h-2c-0.55228 0-1 0.44772-1 1v2c0 0.55228 0.44772 1 1 1h2 1c0.55228 0 1-0.44772 1-1v-3-7h6v5h-2c-0.55228 0-1 0.44772-1 1v2c0 0.55228 0.44772 1 1 1h3c0.55228 0 1-0.44772 1-1v-3-6c0-0.55228-0.44772-1-1-1h-7z" fill="#fc9c9c" fill-opacity=".99608"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_spin_box.svg b/editor/icons/icon_spin_box.svg
index 965df69a02..c033df2c85 100644
--- a/editor/icons/icon_spin_box.svg
+++ b/editor/icons/icon_spin_box.svg
@@ -1,8 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#a5efac">
-<path transform="translate(0 1036.4)" d="m3 3c-1.1046 0-2 0.89543-2 2v6c0 1.1046 0.89543 2 2 2h7v-2h-7v-6h7v-2z"/>
-<rect x="8" y="1041.4" width="2" height="6"/>
-<path d="m11 1043.4h4l-2-3z" fill-rule="evenodd"/>
-<path d="m11 1045.4h4l-2 3z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m3 3c-1.1046 0-2 0.89543-2 2v6c0 1.1046 0.89543 2 2 2h7v-2-6-2h-7zm10 1l-2 3h4l-2-3zm-10 1h5v6h-5v-6zm8 4l2 3 2-3h-4z" fill="#a5efac"/>
</g>
</svg>
diff --git a/editor/icons/icon_status_error.svg b/editor/icons/icon_status_error.svg
new file mode 100644
index 0000000000..072964b02d
--- /dev/null
+++ b/editor/icons/icon_status_error.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-3.866-3.134-7-7-7zm-2.8281 2.7578l2.8281 2.8281 2.8281-2.8281 1.4141 1.4141-2.8281 2.8281 2.8281 2.8281-1.4141 1.4141-2.8281-2.8281-2.8281 2.8281-1.4141-1.4141 2.8281-2.8281-2.8281-2.8281 1.4141-1.4141z" fill="#ff5d5d"/>
+</svg>
diff --git a/editor/icons/icon_status_success.svg b/editor/icons/icon_status_success.svg
new file mode 100644
index 0000000000..d1ddc08579
--- /dev/null
+++ b/editor/icons/icon_status_success.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m8 1c-3.866 0-7 3.134-7 7 0 3.866 3.134 7 7 7 3.866 0 7-3.134 7-7 0-3.866-3.134-7-7-7zm3.293 3.877 1.4141 1.4141-5.707 5.709-3.707-3.709 1.4141-1.4141 2.293 2.293z" fill="#45ff8b"/>
+</svg>
diff --git a/editor/icons/icon_status_warning.svg b/editor/icons/icon_status_warning.svg
new file mode 100644
index 0000000000..28364bb274
--- /dev/null
+++ b/editor/icons/icon_status_warning.svg
@@ -0,0 +1,3 @@
+<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
+<path d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-1 2h2v7h-2v-7zm0 8h2v2h-2v-2z" fill="#ffdd65"/>
+</svg>
diff --git a/editor/icons/icon_stream_player.svg b/editor/icons/icon_stream_player.svg
deleted file mode 100644
index c135487de9..0000000000
--- a/editor/icons/icon_stream_player.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m5 2c-0.55228 0-1 0.44772-1 1v1 7h-2c-0.55228 0-1 0.44772-1 1v2c0 0.55228 0.44772 1 1 1h2 1c0.55228 0 1-0.44772 1-1v-3-7h6v5h-2c-0.55228 0-1 0.44772-1 1v2c0 0.55228 0.44772 1 1 1h3c0.55228 0 1-0.44772 1-1v-3-6c0-0.55228-0.44772-1-1-1h-7z" fill="#e0e0e0"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_string.svg b/editor/icons/icon_string.svg
deleted file mode 100644
index 515658aa1b..0000000000
--- a/editor/icons/icon_string.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m5 1v2h2v10h-2v2h2a1 1 0 0 0 1 -1 1 1 0 0 0 1 1h2v-2h-2v-10h2v-2h-2a1 1 0 0 0 -1 1 1 1 0 0 0 -1 -1h-2z" fill="#e0e0e0"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_tool_pan.svg b/editor/icons/icon_tool_pan.svg
index ff2b2eda1d..4c4866b999 100644
--- a/editor/icons/icon_tool_pan.svg
+++ b/editor/icons/icon_tool_pan.svg
@@ -1,13 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0" fill-opacity=".99608">
-<path transform="translate(0 1036.4)" d="m6 8v7h6v-2h2v-5h-8z"/>
-<rect x="6" y="1039.4" width="2" height="8"/>
-<rect x="9" y="1038.4" width="2" height="8"/>
-<rect x="12" y="1040.4" width="2" height="8"/>
-<circle cx="7" cy="1039.4" r="1"/>
-<circle cx="10" cy="1038.4" r="1"/>
-<circle cx="13" cy="1040.4" r="1"/>
-<circle cx="12" cy="1049.4" r="2"/>
-<path d="m3.5251 1045.6c-0.52015-0.3803-1.1943-0.4556-1.6499 0-0.45566 0.4556-0.45564 1.1943-2.36e-5 1.6499l4.1248 4.1248 1.6499-2.7593z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m10 1a1 1 0 0 0 -1 1v6h-1v-5a1 1 0 0 0 -1 -1 1 1 0 0 0 -1 1v8 0.033203l-2.4746-1.8086c-0.52015-0.3803-1.1948-0.4556-1.6504 0-0.45566 0.4556-0.45561 1.1948 0 1.6504l4.125 4.125h6a2 2 0 0 0 2 -2v-5-4a1 1 0 0 0 -1 -1 1 1 0 0 0 -1 1v4h-1v-6a1 1 0 0 0 -1 -1z" fill="#e0e0e0" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_track_discrete.svg b/editor/icons/icon_track_discrete.svg
index 80c9062365..6000d55e99 100644
--- a/editor/icons/icon_track_discrete.svg
+++ b/editor/icons/icon_track_discrete.svg
@@ -1,7 +1,5 @@
<svg width="16" height="8" version="1.1" viewBox="0 0 16 8" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1044.4)" fill="#e0e0e0">
-<circle cx="2" cy="1050.4" r="1"/>
-<circle cx="8" cy="1048.4" r="1"/>
-<circle cx="14" cy="1046.4" r="1"/>
+<g transform="translate(0 -1044.4)">
+<path transform="translate(0 1044.4)" d="m14 1a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm-6 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm-6 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_track_trigger.svg b/editor/icons/icon_track_trigger.svg
index f614943845..fd2505463f 100644
--- a/editor/icons/icon_track_trigger.svg
+++ b/editor/icons/icon_track_trigger.svg
@@ -1,9 +1,5 @@
<svg width="16" height="8" version="1.1" viewBox="0 0 16 8" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1044.4)" fill="#e0e0e0">
-<circle cx="11" cy="1048.4" r="1"/>
-<circle cx="14" cy="1046.4" r="1"/>
-<rect x="1" y="1045.4" width="6" height="2"/>
-<rect x="3" y="1047.4" width="2" height="4"/>
-<circle cx="8" cy="1050.4" r="1"/>
+<g transform="translate(0 -1044.4)">
+<path transform="translate(0 1044.4)" d="m1 1v2h2v4h2v-4h2v-2h-6zm13 0a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm-3 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm-3 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_unlock.svg b/editor/icons/icon_unlock.svg
index 10ea82cbcf..591b3d0102 100644
--- a/editor/icons/icon_unlock.svg
+++ b/editor/icons/icon_unlock.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<path transform="translate(0 1036.4)" d="m2 8v7h12v-7h-12zm5 2h2v3h-2v-3z"/>
-<path transform="translate(0 1036.4)" d="m8 1c-0.87738 0.001545-1.7389 0.23394-2.498 0.67383l1 1.7324c0.45506-0.26449 0.97171-0.40459 1.498-0.40625 1.6569 0 3 1.3431 3 3h2c0-2.7614-2.2386-5-5-5z"/>
-<rect x="11" y="1042.4" width="2" height="2"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1c-0.87738 0.001545-1.7389 0.23394-2.498 0.67383l1 1.7324c0.45506-0.26449 0.97171-0.40459 1.498-0.40625 1.6569 0 3 1.3431 3 3v2h-9v7h12v-7h-1v-2c0-2.7614-2.2386-5-5-5zm-1 9h2v3h-2v-3z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_v_slider.svg b/editor/icons/icon_v_slider.svg
index 2da5fc8dcd..45a61147ab 100644
--- a/editor/icons/icon_v_slider.svg
+++ b/editor/icons/icon_v_slider.svg
@@ -1,5 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m5.0156 0.98633a1.0001 1.0001 0 0 0 -0.25977 0.029297 2 2 0 0 0 -1.7559 1.9844 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -1.7539 -1.9824 1.0001 1.0001 0 0 0 -0.23047 -0.03125zm4.9844 0.013672a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h2a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-2zm-4 5.8672a4 4 0 0 1 -1 0.13281 4 4 0 0 1 -1 -0.13086v5 1.1309 1a1.0001 1.0001 0 1 0 2 0v-1-1.1328-5zm5 0.13281a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm-1 6a1 1 0 0 0 -1 1 1 1 0 0 0 1 1h2a1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1h-2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#a5efac" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+<path transform="translate(0 1036.4)" d="m5 1a2 2 0 0 0 -2 2 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2zm5 0c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1h2c0.55228 0 1-0.44772 1-1s-0.44772-1-1-1h-2zm-4 5.8672c-0.32639 0.086294-0.6624 0.13092-1 0.13281-0.33752-0.0012549-0.67352-0.045224-1-0.13086v5 1.1309 1c-0.019125 1.3523 2.0191 1.3523 2 0v-1-1.1328-5zm5 0.13281c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1 1-0.44772 1-1-0.44772-1-1-1zm-1 6c-0.55228 0-1 0.44772-1 1s0.44772 1 1 1h2c0.55228 0 1-0.44772 1-1s-0.44772-1-1-1h-2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#a5efac" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_vector.svg b/editor/icons/icon_vector.svg
deleted file mode 100644
index dda46edeaa..0000000000
--- a/editor/icons/icon_vector.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)" fill="none" stroke="#b8ea68" stroke-width="2">
-<path d="m7 1047.4-4 4"/>
-<path d="m7 1040.4v7h7"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_vector2.svg b/editor/icons/icon_vector2.svg
deleted file mode 100644
index ab92e7bb60..0000000000
--- a/editor/icons/icon_vector2.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="12" version="1.1" viewBox="0 0 16 12" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1040.4)">
-<path d="m4 1041.4v9h9" fill="none" stroke="#b8ea68" stroke-width="2"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_vehicle_wheel.svg b/editor/icons/icon_vehicle_wheel.svg
index fcee90e2e2..cbd33653e0 100644
--- a/editor/icons/icon_vehicle_wheel.svg
+++ b/editor/icons/icon_vehicle_wheel.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#fc9c9c" fill-opacity=".99608">
-<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5 -5 5 5 0 0 1 5 -5z"/>
-<path transform="translate(0 1036.4)" d="m8 4a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 4 -4 4 4 0 0 0 -4 -4zm0 1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-2 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-2 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm0 2a5 5 0 0 1 5 5 5 5 0 0 1 -5 5 5 5 0 0 1 -5 -5 5 5 0 0 1 5 -5zm0 1a4 4 0 0 0 -4 4 4 4 0 0 0 4 4 4 4 0 0 0 4 -4 4 4 0 0 0 -4 -4zm0 1a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-2 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm4 0a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1zm-2 2a1 1 0 0 1 1 1 1 1 0 0 1 -1 1 1 1 0 0 1 -1 -1 1 1 0 0 1 1 -1z" fill="#fc9c9c" fill-opacity=".99608"/>
</g>
</svg>
diff --git a/editor/icons/icon_video_player.svg b/editor/icons/icon_video_player.svg
index cbee054665..84aae1f1e1 100644
--- a/editor/icons/icon_video_player.svg
+++ b/editor/icons/icon_video_player.svg
@@ -1,7 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1036.4)">
-<rect x="2" y="1038.4" width="12" height="12" ry="1" fill="none" stroke="#a5efac" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
-<path d="m6 1045.4v-4l4 2z" fill="#a5efac" fill-rule="evenodd"/>
-<rect x="3" y="1047.4" width="10" height="2" ry="0" fill="#a5efac"/>
+<path transform="translate(0 1036.4)" d="m3 1c-1.0907 0-2 0.9093-2 2v10c0 1.0907 0.90929 2 2 2h10c1.0907 0 2-0.9093 2-2v-10c0-1.0907-0.90929-2-2-2h-10zm0 2h10v8h-10v-8zm3 2v4l4-2-4-2z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#a5efac" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="filter-blend-mode:normal;filter-gaussianBlur-deviation:0;font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
</g>
</svg>
diff --git a/editor/icons/icon_visual_shader_port.svg b/editor/icons/icon_visual_shader_port.svg
index 0f5d00dbc4..da94e48a21 100644
--- a/editor/icons/icon_visual_shader_port.svg
+++ b/editor/icons/icon_visual_shader_port.svg
@@ -1,5 +1,7 @@
<svg width="10" height="10" version="1.1" viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1042.4)">
-<path d="m2 1051.4v-8l6 4z" fill="#f3f3f3" fill-rule="evenodd" stroke="#e4e4e4" stroke-linejoin="round" stroke-width="2"/>
+<g>
+<path d="m1.9883 1042.4c-0.5469 0.01-0.98717 0.4511-0.98828 0.998v8c1.163e-4 0.7986 0.89011 1.275 1.5547 0.8321l6-4c0.59363-0.3959 0.59363-1.2682 0-1.6641l-6-4c-0.1678-0.1111-0.3652-0.1689-0.56641-0.166z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="#fff" fill-rule="evenodd" image-rendering="auto" shape-rendering="auto" solid-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;isolation:auto;mix-blend-mode:normal;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
+</g>
</g>
</svg>
diff --git a/editor/icons/icon_vu_empty.svg b/editor/icons/icon_vu_empty.svg
deleted file mode 100644
index 76bb913e38..0000000000
--- a/editor/icons/icon_vu_empty.svg
+++ /dev/null
@@ -1,13 +0,0 @@
-<svg width="128" height="4" version="1.1" viewBox="0 0 128 4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<linearGradient id="a" x2="128" y1="2" y2="2" gradientUnits="userSpaceOnUse">
-<stop stop-color="#84ffb1" offset="0"/>
-<stop stop-color="#e1dc7a" offset=".5"/>
-<stop stop-color="#ff8484" offset="1"/>
-</linearGradient>
-</defs>
-<g transform="translate(0 -1048.4)">
-<path transform="translate(0 1048.4)" d="m2 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2h75 3 2 3 15v-4h-15-3-2-3-75zm100 0v4h24a2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2h-24z" fill="url(#a)"/>
-<path transform="translate(0 1048.4)" d="m2 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2h75 3 2 3 15v-4h-15-3-2-3-75zm100 0v4h24a2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2h-24z" fill-opacity=".23529"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_vu_full.svg b/editor/icons/icon_vu_full.svg
deleted file mode 100644
index bacab2a83c..0000000000
--- a/editor/icons/icon_vu_full.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-<svg width="128" height="4" version="1.1" viewBox="0 0 128 4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
-<defs>
-<linearGradient id="a" x2="128" y1="2" y2="2" gradientUnits="userSpaceOnUse">
-<stop stop-color="#84ffb1" offset="0"/>
-<stop stop-color="#e1dc7a" offset=".5"/>
-<stop stop-color="#ff8484" offset="1"/>
-</linearGradient>
-</defs>
-<g transform="translate(0 -1048.4)">
-<path transform="translate(0 1048.4)" d="m2 0a2 2 0 0 0 -2 2 2 2 0 0 0 2 2h75 3 2 3 15v-4h-15-3-2-3-75zm100 0v4h24a2 2 0 0 0 2 -2 2 2 0 0 0 -2 -2h-24z" fill="url(#a)"/>
-</g>
-</svg>
diff --git a/editor/icons/icon_warning.svg b/editor/icons/icon_warning.svg
index 455e7b1877..8f6bf2184a 100644
--- a/editor/icons/icon_warning.svg
+++ b/editor/icons/icon_warning.svg
@@ -1,5 +1,5 @@
<svg width="8" height="8" version="1.1" viewBox="0 0 8 8" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(0 -1044.4)">
-<rect y="1044.4" width="8" height="8" ry="4" fill="#ffd684"/>
+<rect y="1044.4" width="8" height="8" ry="4" fill="#ffdd65"/>
</g>
</svg>
diff --git a/editor/icons/icon_world.svg b/editor/icons/icon_world.svg
index 4ea501e194..cf9b23b61b 100644
--- a/editor/icons/icon_world.svg
+++ b/editor/icons/icon_world.svg
@@ -1,6 +1,5 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<circle cx="6" cy="1046.4" r="5"/>
-<circle cx="12" cy="1039.4" r="1"/>
+<g transform="translate(0 -1036.4)">
+<path transform="translate(0 1036.4)" d="m12 2a1 1 0 0 0 -1 1 1 1 0 0 0 1 1 1 1 0 0 0 1 -1 1 1 0 0 0 -1 -1zm-6 3a5 5 0 0 0 -5 5 5 5 0 0 0 5 5 5 5 0 0 0 5 -5 5 5 0 0 0 -5 -5z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_zoom_less.svg b/editor/icons/icon_zoom_less.svg
index 46db300785..aebadf443f 100644
--- a/editor/icons/icon_zoom_less.svg
+++ b/editor/icons/icon_zoom_less.svg
@@ -1,5 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<rect x="1" y="1043.4" width="14" height="1.9999" fill="#e0e0e0"/>
+<g transform="translate(0 -1036.4)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+<circle cx="8" cy="1044.4" r="8" fill-opacity=".39216" stroke-opacity=".98824"/>
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-4 6h8v2h-8v-2z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_zoom_more.svg b/editor/icons/icon_zoom_more.svg
index 3cf2c7fbb1..be1e13d145 100644
--- a/editor/icons/icon_zoom_more.svg
+++ b/editor/icons/icon_zoom_more.svg
@@ -1,12 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<g transform="translate(-201.58 205.03)">
-<g transform="matrix(48.459 0 0 53.968 -126.63 -55836)">
-<g transform="translate(.51853 -.019888)" fill="#e0e0e0" fill-opacity=".99608">
-<rect x="6.3979" y="1050.1" width=".042995" height=".26205" rx="0" ry="0"/>
-<rect x="6.2806" y="1050.2" width=".28011" height=".040944" rx="0" ry="0"/>
-</g>
-</g>
-</g>
+<g transform="translate(0 -1036.4)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+<circle cx="8" cy="1044.4" r="8" fill-opacity=".39216" stroke-opacity=".98824"/>
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-1 3h2v3h3v2h-3v3h-2v-3h-3v-2h3v-3z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/icons/icon_zoom_reset.svg b/editor/icons/icon_zoom_reset.svg
index 053092445a..aa5ad03727 100644
--- a/editor/icons/icon_zoom_reset.svg
+++ b/editor/icons/icon_zoom_reset.svg
@@ -1,10 +1,6 @@
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)" fill="#e0e0e0">
-<rect x="3" y="1037.4" width="2" height="14"/>
-<rect x="12" y="1037.4" width="2" height="14"/>
-<rect x="7" y="1046.4" width="2" height="2"/>
-<rect x="7" y="1040.4" width="2" height="2"/>
-<path d="m1 1040.4 2-3h2v3z" fill-rule="evenodd"/>
-<path d="m10 1040.4 2-3h2v3z" fill-rule="evenodd"/>
+<g transform="translate(0 -1036.4)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
+<circle cx="8" cy="1044.4" r="8" fill-opacity=".39216" stroke-opacity=".98824"/>
+<path transform="translate(0 1036.4)" d="m8 1a7 7 0 0 0 -7 7 7 7 0 0 0 7 7 7 7 0 0 0 7 -7 7 7 0 0 0 -7 -7zm-0.029297 3.002a1.0001 1.0001 0 0 1 1.0293 0.99805v7h-2v-5.1309l-1.4453 0.96289-1.1094-1.6641 3-2a1.0001 1.0001 0 0 1 0.52539 -0.16602z" fill="#e0e0e0"/>
</g>
</svg>
diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp
index b1991d755b..6ef1758363 100644
--- a/editor/import/editor_import_collada.cpp
+++ b/editor/import/editor_import_collada.cpp
@@ -381,6 +381,9 @@ Error ColladaImport::_create_material(const String &p_target) {
String texfile = effect.get_texture_path(effect.diffuse.texture, collada);
if (texfile != "") {
+ if (texfile.begins_with("/")) {
+ texfile = texfile.replace_first("/", "res://");
+ }
Ref<Texture> texture = ResourceLoader::load(texfile, "Texture");
if (texture.is_valid()) {
@@ -402,6 +405,10 @@ Error ColladaImport::_create_material(const String &p_target) {
String texfile = effect.get_texture_path(effect.specular.texture, collada);
if (texfile != "") {
+ if (texfile.begins_with("/")) {
+ texfile = texfile.replace_first("/", "res://");
+ }
+
Ref<Texture> texture = ResourceLoader::load(texfile, "Texture");
if (texture.is_valid()) {
material->set_texture(SpatialMaterial::TEXTURE_METALLIC, texture);
@@ -425,6 +432,10 @@ Error ColladaImport::_create_material(const String &p_target) {
String texfile = effect.get_texture_path(effect.emission.texture, collada);
if (texfile != "") {
+ if (texfile.begins_with("/")) {
+ texfile = texfile.replace_first("/", "res://");
+ }
+
Ref<Texture> texture = ResourceLoader::load(texfile, "Texture");
if (texture.is_valid()) {
@@ -451,6 +462,10 @@ Error ColladaImport::_create_material(const String &p_target) {
String texfile = effect.get_texture_path(effect.bump.texture, collada);
if (texfile != "") {
+ if (texfile.begins_with("/")) {
+ texfile = texfile.replace_first("/", "res://");
+ }
+
Ref<Texture> texture = ResourceLoader::load(texfile, "Texture");
if (texture.is_valid()) {
material->set_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING, true);
diff --git a/editor/import/resource_importer_obj.cpp b/editor/import/resource_importer_obj.cpp
index 6a936649c3..4541c77085 100644
--- a/editor/import/resource_importer_obj.cpp
+++ b/editor/import/resource_importer_obj.cpp
@@ -40,12 +40,8 @@ uint32_t EditorOBJImporter::get_import_flags() const {
return IMPORT_SCENE;
}
-void EditorOBJImporter::get_extensions(List<String> *r_extensions) const {
- r_extensions->push_back("obj");
-}
-
-Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<String, Ref<SpatialMaterial> > &material_map, List<String> *r_missing_deps) {
+static Error _parse_material_library(const String &p_path, Map<String, Ref<SpatialMaterial> > &material_map, List<String> *r_missing_deps) {
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
@@ -134,7 +130,7 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
if (texture.is_valid()) {
current->set_texture(SpatialMaterial::TEXTURE_ALBEDO, texture);
- } else {
+ } else if (r_missing_deps) {
r_missing_deps->push_back(path);
}
@@ -149,7 +145,7 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
if (texture.is_valid()) {
current->set_texture(SpatialMaterial::TEXTURE_METALLIC, texture);
- } else {
+ } else if (r_missing_deps) {
r_missing_deps->push_back(path);
}
@@ -164,7 +160,7 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
if (texture.is_valid()) {
current->set_texture(SpatialMaterial::TEXTURE_ROUGHNESS, texture);
- } else {
+ } else if (r_missing_deps) {
r_missing_deps->push_back(path);
}
} else if (l.begins_with("map_bump ")) {
@@ -179,7 +175,7 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
if (texture.is_valid()) {
current->set_feature(SpatialMaterial::FEATURE_NORMAL_MAPPING, true);
current->set_texture(SpatialMaterial::TEXTURE_NORMAL, texture);
- } else {
+ } else if (r_missing_deps) {
r_missing_deps->push_back(path);
}
} else if (f->eof_reached()) {
@@ -190,28 +186,16 @@ Error EditorOBJImporter::_parse_material_library(const String &p_path, Map<Strin
return OK;
}
-Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+static Error _parse_obj(const String &p_path, List<Ref<Mesh> > &r_meshes, bool p_single_mesh, bool p_generate_tangents, List<String> *r_missing_deps) {
FileAccessRef f = FileAccess::open(p_path, FileAccess::READ);
- if (r_err) {
- *r_err = ERR_CANT_OPEN;
- }
-
- ERR_FAIL_COND_V(!f, NULL);
-
- if (r_err) {
- *r_err = OK;
- }
-
- Spatial *scene = memnew(Spatial);
+ ERR_FAIL_COND_V(!f, ERR_CANT_OPEN);
Ref<ArrayMesh> mesh;
mesh.instance();
- Map<String, Ref<Material> > name_map;
-
- bool generate_tangents = p_flags & IMPORT_GENERATE_TANGENT_ARRAYS;
+ bool generate_tangents = p_generate_tangents;
bool flip_faces = false;
//bool flip_faces = p_options["force/flip_faces"];
//bool force_smooth = p_options["force/smooth_shading"];
@@ -239,7 +223,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
if (l.begins_with("v ")) {
//vertex
Vector<String> v = l.split(" ", false);
- ERR_FAIL_COND_V(v.size() < 4, NULL);
+ ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT);
Vector3 vtx;
vtx.x = v[1].to_float();
vtx.y = v[2].to_float();
@@ -248,7 +232,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
} else if (l.begins_with("vt ")) {
//uv
Vector<String> v = l.split(" ", false);
- ERR_FAIL_COND_V(v.size() < 3, NULL);
+ ERR_FAIL_COND_V(v.size() < 3, ERR_FILE_CORRUPT);
Vector2 uv;
uv.x = v[1].to_float();
uv.y = 1.0 - v[2].to_float();
@@ -257,7 +241,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
} else if (l.begins_with("vn ")) {
//normal
Vector<String> v = l.split(" ", false);
- ERR_FAIL_COND_V(v.size() < 4, NULL);
+ ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT);
Vector3 nrm;
nrm.x = v[1].to_float();
nrm.y = v[2].to_float();
@@ -267,19 +251,19 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
//vertex
Vector<String> v = l.split(" ", false);
- ERR_FAIL_COND_V(v.size() < 4, NULL);
+ ERR_FAIL_COND_V(v.size() < 4, ERR_FILE_CORRUPT);
//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, NULL);
- ERR_FAIL_COND_V(face[0].size() != face[1].size(), NULL);
+ ERR_FAIL_COND_V(face[0].size() == 0, ERR_FILE_CORRUPT);
+ ERR_FAIL_COND_V(face[0].size() != face[1].size(), ERR_FILE_CORRUPT);
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(), NULL);
+ ERR_FAIL_COND_V(face[0].size() != face[2].size(), ERR_FILE_CORRUPT);
for (int j = 0; j < 3; j++) {
int idx = j;
@@ -292,7 +276,7 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
int norm = face[idx][2].to_int() - 1;
if (norm < 0)
norm += normals.size() + 1;
- ERR_FAIL_INDEX_V(norm, normals.size(), NULL);
+ ERR_FAIL_INDEX_V(norm, normals.size(), ERR_FILE_CORRUPT);
surf_tool->add_normal(normals[norm]);
}
@@ -300,14 +284,14 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
int uv = face[idx][1].to_int() - 1;
if (uv < 0)
uv += uvs.size() + 1;
- ERR_FAIL_INDEX_V(uv, uvs.size(), NULL);
+ ERR_FAIL_INDEX_V(uv, uvs.size(), ERR_FILE_CORRUPT);
surf_tool->add_uv(uvs[uv]);
}
int vtx = face[idx][0].to_int() - 1;
if (vtx < 0)
vtx += vertices.size() + 1;
- ERR_FAIL_INDEX_V(vtx, vertices.size(), NULL);
+ ERR_FAIL_INDEX_V(vtx, vertices.size(), ERR_FILE_CORRUPT);
Vector3 vertex = vertices[vtx];
//if (weld_vertices)
@@ -359,16 +343,13 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
if (l.begins_with("o ") || f->eof_reached()) {
- MeshInstance *mi = memnew(MeshInstance);
- mi->set_name(name);
- mi->set_mesh(mesh);
-
- scene->add_child(mi);
- mi->set_owner(scene);
-
- mesh.instance();
- current_group = "";
- current_material = "";
+ if (!p_single_mesh) {
+ mesh->set_name(name);
+ r_meshes.push_back(mesh);
+ mesh.instance();
+ current_group = "";
+ current_material = "";
+ }
}
if (f->eof_reached()) {
@@ -406,16 +387,40 @@ Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, in
}
}
- /*
- TODO, check existing materials and merge?
- //re-apply materials if exist
- for(int i=0;i<mesh->get_surface_count();i++) {
+ if (p_single_mesh) {
+
+ r_meshes.push_back(mesh);
+ }
+
+ return OK;
+}
+
+Node *EditorOBJImporter::import_scene(const String &p_path, uint32_t p_flags, int p_bake_fps, List<String> *r_missing_deps, Error *r_err) {
+
+ List<Ref<Mesh> > meshes;
+
+ Error err = _parse_obj(p_path, meshes, false, p_flags & IMPORT_GENERATE_TANGENT_ARRAYS, r_missing_deps);
+
+ if (err != OK) {
+ if (r_err) {
+ *r_err = err;
+ }
+ return NULL;
+ }
+
+ Spatial *scene = memnew(Spatial);
+
+ for (List<Ref<Mesh> >::Element *E = meshes.front(); E; E = E->next()) {
+
+ MeshInstance *mi = memnew(MeshInstance);
+ mi->set_name(E->get()->get_name());
+ scene->add_child(mi);
+ mi->set_owner(scene);
+ }
- String n = mesh->surface_get_name(i);
- if (name_map.has(n))
- mesh->surface_set_material(i,name_map[n]);
+ if (r_err) {
+ *r_err = OK;
}
-*/
return scene;
}
@@ -423,5 +428,68 @@ Ref<Animation> EditorOBJImporter::import_animation(const String &p_path, uint32_
return Ref<Animation>();
}
+
+void EditorOBJImporter::get_extensions(List<String> *r_extensions) const {
+
+ r_extensions->push_back("obj");
+}
+
EditorOBJImporter::EditorOBJImporter() {
}
+////////////////////////////////////////////////////
+
+String ResourceImporterOBJ::get_importer_name() const {
+ return "wavefront_obj";
+}
+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 "mesh";
+}
+String ResourceImporterOBJ::get_resource_type() const {
+ return "Mesh";
+}
+
+int ResourceImporterOBJ::get_preset_count() const {
+ return 0;
+}
+String ResourceImporterOBJ::get_preset_name(int p_idx) const {
+ return "";
+}
+
+void ResourceImporterOBJ::get_import_options(List<ImportOption> *r_options, int p_preset) const {
+
+ r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_tangents"), true));
+}
+bool ResourceImporterOBJ::get_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const {
+
+ return true;
+}
+
+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) {
+
+ List<Ref<Mesh> > meshes;
+
+ Error err = _parse_obj(p_source_file, meshes, true, p_options["generate_tangents"], NULL);
+
+ ERR_FAIL_COND_V(err != OK, err);
+ ERR_FAIL_COND_V(meshes.size() != 1, ERR_BUG);
+
+ String save_path = p_save_path + ".mesh";
+
+ err = ResourceSaver::save(save_path, meshes.front()->get());
+
+ ERR_FAIL_COND_V(err != OK, err);
+
+ r_gen_files->push_back(save_path);
+
+ return OK;
+}
+
+ResourceImporterOBJ::ResourceImporterOBJ() {
+}
diff --git a/editor/import/resource_importer_obj.h b/editor/import/resource_importer_obj.h
index 247d58e148..7eeceeabbe 100644
--- a/editor/import/resource_importer_obj.h
+++ b/editor/import/resource_importer_obj.h
@@ -36,8 +36,6 @@ class EditorOBJImporter : public EditorSceneImporter {
GDCLASS(EditorOBJImporter, EditorSceneImporter);
- Error _parse_material_library(const String &p_path, Map<String, Ref<SpatialMaterial> > &material_map, List<String> *r_missing_deps);
-
public:
virtual uint32_t get_import_flags() const;
virtual void get_extensions(List<String> *r_extensions) const;
@@ -47,4 +45,24 @@ public:
EditorOBJImporter();
};
+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
index cc519c1c4b..6d5ff822ef 100644
--- a/editor/import/resource_importer_scene.cpp
+++ b/editor/import/resource_importer_scene.cpp
@@ -114,19 +114,19 @@ bool ResourceImporterScene::get_option_visibility(const String &p_option, const
}
int ResourceImporterScene::get_preset_count() const {
- return 6;
+ return PRESET_MAX;
}
String ResourceImporterScene::get_preset_name(int p_idx) const {
switch (p_idx) {
case PRESET_SINGLE_SCENE: return TTR("Import as Single Scene");
- case PRESET_SEPERATE_ANIMATIONS: return TTR("Import with Seperate Animations");
+ case PRESET_SEPARATE_ANIMATIONS: return TTR("Import with Separate Animations");
case PRESET_SEPARATE_MATERIALS: return TTR("Import with Separate Materials");
case PRESET_SEPARATE_MESHES: return TTR("Import with Separate Objects");
case PRESET_SEPARATE_MESHES_AND_MATERIALS: return TTR("Import with Separate Objects+Materials");
- case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: return TTR("Import with Seperate Objects+Animations");
- case PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS: return TTR("Import with Seperate Materials+Animations");
- case PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS: return TTR("Import with Seperate Objects+Materials+Animations");
+ case PRESET_SEPARATE_MESHES_AND_ANIMATIONS: return TTR("Import with Separate Objects+Animations");
+ case PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS: return TTR("Import with Separate Materials+Animations");
+ case PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS: return TTR("Import with Separate Objects+Materials+Animations");
case PRESET_MULTIPLE_SCENES: return TTR("Import as Multiple Scenes");
case PRESET_MULTIPLE_SCENES_AND_MATERIALS: return TTR("Import as Multiple Scenes+Materials");
}
@@ -954,10 +954,10 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
script_ext_hint += "*." + E->get();
}
- bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS;
- bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS;
+ bool materials_out = p_preset == PRESET_SEPARATE_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
+ bool meshes_out = p_preset == PRESET_SEPARATE_MESHES || p_preset == PRESET_SEPARATE_MESHES_AND_MATERIALS || p_preset == PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
bool scenes_out = p_preset == PRESET_MULTIPLE_SCENES || p_preset == PRESET_MULTIPLE_SCENES_AND_MATERIALS;
- bool animations_out = p_preset == PRESET_SEPERATE_ANIMATIONS || PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS;
+ bool animations_out = p_preset == PRESET_SEPARATE_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS || p_preset == PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS;
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, "nodes/storage", PROPERTY_HINT_ENUM, "Single Scene,Instanced Sub-Scenes"), scenes_out ? 1 : 0));
@@ -966,7 +966,7 @@ void ResourceImporterScene::get_import_options(List<ImportOption> *r_options, in
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "materials/keep_on_reimport"), materials_out ? true : false));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/compress"), true));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "meshes/ensure_tangents"), true));
- r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files"), meshes_out ? true : false));
+ r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "meshes/storage", PROPERTY_HINT_ENUM, "Built-In,Files"), meshes_out ? 1 : 0));
r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "external_files/store_in_subdir"), false));
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));
diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h
index a483c3776f..9c7e791719 100644
--- a/editor/import/resource_importer_scene.h
+++ b/editor/import/resource_importer_scene.h
@@ -85,17 +85,18 @@ class ResourceImporterScene : public ResourceImporter {
enum Presets {
PRESET_SEPARATE_MATERIALS,
PRESET_SEPARATE_MESHES,
- PRESET_SEPERATE_ANIMATIONS,
+ PRESET_SEPARATE_ANIMATIONS,
PRESET_SINGLE_SCENE,
PRESET_SEPARATE_MESHES_AND_MATERIALS,
PRESET_SEPARATE_MESHES_AND_ANIMATIONS,
- PRESET_SEPERATE_MATERIALS_AND_ANIMATIONS,
- PRESET_SEPERATE_MESHES_MATERIALS_AND_ANIMATIONS,
+ PRESET_SEPARATE_MATERIALS_AND_ANIMATIONS,
+ PRESET_SEPARATE_MESHES_MATERIALS_AND_ANIMATIONS,
PRESET_MULTIPLE_SCENES,
PRESET_MULTIPLE_SCENES_AND_MATERIALS,
+ PRESET_MAX
};
void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner);
@@ -118,8 +119,9 @@ public:
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 int get_import_order() const { return 100; } //after everything
- void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animation, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes);
+ void _make_external_resources(Node *p_node, const String &p_base_path, bool p_make_animations, bool p_make_materials, bool p_keep_materials, bool p_make_meshes, Map<Ref<Animation>, Ref<Animation> > &p_animations, Map<Ref<Material>, Ref<Material> > &p_materials, Map<Ref<ArrayMesh>, Ref<ArrayMesh> > &p_meshes);
Node *_fix_node(Node *p_node, Node *p_root, Map<Ref<ArrayMesh>, Ref<Shape> > &collision_map);
diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp
index 025dbbaacf..bd15ed535b 100644
--- a/editor/import/resource_importer_wav.cpp
+++ b/editor/import/resource_importer_wav.cpp
@@ -141,7 +141,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s
/* 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
+ uint32_t file_pos = file->get_position(); //save file pos, so we can skip to next chunk safely
if (file->eof_reached()) {
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index d7762a66df..bdfe380211 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -76,14 +76,14 @@ void AnimationPlayerEditor::_notification(int p_what) {
}
}
}
- frame->set_value(player->get_current_animation_pos());
- key_editor->set_anim_pos(player->get_current_animation_pos());
+ frame->set_value(player->get_current_animation_position());
+ key_editor->set_anim_pos(player->get_current_animation_position());
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());
+ frame->set_value(player->get_current_animation_position());
}
last_active = player->is_playing();
@@ -103,13 +103,11 @@ void AnimationPlayerEditor::_notification(int p_what) {
get_tree()->connect("node_removed", this, "_node_removed");
add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel"));
- add_constant_override("separation", get_constant("separation", "VBoxContainer"));
} break;
case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
add_style_override("panel", editor->get_gui_base()->get_stylebox("panel", "Panel"));
- add_constant_override("separation", get_constant("separation", "VBoxContainer"));
} break;
case NOTIFICATION_THEME_CHANGED: {
@@ -199,7 +197,7 @@ void AnimationPlayerEditor::_play_from_pressed() {
if (current != "") {
- float time = player->get_current_animation_pos();
+ float time = player->get_current_animation_position();
if (current == player->get_current_animation() && player->is_playing()) {
@@ -247,7 +245,7 @@ void AnimationPlayerEditor::_play_bw_from_pressed() {
if (current != "") {
- float time = player->get_current_animation_pos();
+ float time = player->get_current_animation_position();
if (current == player->get_current_animation())
player->stop(); //so it wont blend with itself
@@ -946,7 +944,7 @@ void AnimationPlayerEditor::_seek_value_changed(float p_value, bool p_set) {
}
if (player->is_valid() && !p_set) {
- float cpos = player->get_current_animation_pos();
+ float cpos = player->get_current_animation_position();
player->seek_delta(pos, pos - cpos);
} else {
@@ -1428,7 +1426,7 @@ AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin(EditorNode *p_node) {
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_anchors_and_margins_preset(Control::PRESET_WIDE);
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);
diff --git a/editor/plugins/animation_tree_editor_plugin.cpp b/editor/plugins/animation_tree_editor_plugin.cpp
index 054124da8f..22d23e1c72 100644
--- a/editor/plugins/animation_tree_editor_plugin.cpp
+++ b/editor/plugins/animation_tree_editor_plugin.cpp
@@ -63,7 +63,7 @@ Size2 AnimationTreeEditor::_get_maximum_size() {
for (List<StringName>::Element *E = order.front(); E; E = E->next()) {
- Point2 pos = anim_tree->node_get_pos(E->get());
+ Point2 pos = anim_tree->node_get_position(E->get());
if (click_type == CLICK_NODE && click_node == E->get()) {
@@ -257,7 +257,7 @@ void AnimationTreeEditor::_popup_edit_dialog() {
filter_button->hide();
edit_check->hide();
- Point2 pos = anim_tree->node_get_pos(edited_node) - Point2(h_scroll->get_value(), v_scroll->get_value());
+ Point2 pos = anim_tree->node_get_position(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));
@@ -476,10 +476,10 @@ void AnimationTreeEditor::_draw_node(const StringName &p_node) {
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");
+ Ref<Texture> slot_icon = get_icon("VisualShaderPort", "EditorIcons");
Size2 size = get_node_size(p_node);
- Point2 pos = anim_tree->node_get_pos(p_node);
+ Point2 pos = anim_tree->node_get_position(p_node);
if (click_type == CLICK_NODE && click_node == p_node) {
pos += click_motion - click_pos;
@@ -599,7 +599,7 @@ void AnimationTreeEditor::_draw_node(const StringName &p_node) {
if (editable) {
- Ref<Texture> arrow = get_icon("arrow", "Tree");
+ Ref<Texture> arrow = get_icon("GuiDropdown", "EditorIcons");
Point2 arrow_ofs(w - arrow->get_width(), Math::floor((h - arrow->get_height()) / 2));
arrow->draw(ci, ofs + arrow_ofs);
}
@@ -618,7 +618,7 @@ AnimationTreeEditor::ClickType AnimationTreeEditor::_locate_click(const Point2 &
AnimationTreePlayer::NodeType type = anim_tree->node_get_type(node);
- Point2 pos = anim_tree->node_get_pos(node);
+ Point2 pos = anim_tree->node_get_position(node);
Size2 size = get_node_size(node);
pos -= Point2(h_scroll->get_value(), v_scroll->get_value());
@@ -671,10 +671,10 @@ Point2 AnimationTreeEditor::_get_slot_pos(const StringName &p_node_id, bool p_in
Ref<StyleBox> style = get_stylebox("panel", "PopupMenu");
Ref<Font> font = get_font("font", "PopupMenu");
- Ref<Texture> slot_icon = get_icon("NodeRealSlot", "EditorIcons");
+ Ref<Texture> slot_icon = get_icon("VisualShaderPort", "EditorIcons");
Size2 size = get_node_size(p_node_id);
- Point2 pos = anim_tree->node_get_pos(p_node_id);
+ Point2 pos = anim_tree->node_get_position(p_node_id);
if (click_type == CLICK_NODE && click_node == p_node_id) {
@@ -806,12 +806,12 @@ void AnimationTreeEditor::_gui_input(Ref<InputEvent> p_event) {
} break;
case CLICK_NODE: {
- Point2 new_pos = anim_tree->node_get_pos(click_node) + (click_motion - click_pos);
+ Point2 new_pos = anim_tree->node_get_position(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);
+ anim_tree->node_set_position(click_node, new_pos);
} break;
default: {}
@@ -1081,7 +1081,7 @@ StringName AnimationTreeEditor::_add_node(int p_item) {
}
anim_tree->add_node((AnimationTreePlayer::NodeType)p_item, name);
- anim_tree->node_set_pos(name, Point2(last_x, last_y));
+ anim_tree->node_set_position(name, Point2(last_x, last_y));
order.push_back(name);
last_x += 10;
last_y += 10;
@@ -1419,13 +1419,13 @@ void AnimationTreeEditorPlugin::make_visible(bool p_visible) {
//editor->animation_panel_make_visible(true);
button->show();
editor->make_bottom_panel_item_visible(anim_tree_editor);
- anim_tree_editor->set_fixed_process(true);
+ anim_tree_editor->set_physics_process(true);
} else {
if (anim_tree_editor->is_visible_in_tree())
editor->hide_bottom_panel();
button->hide();
- anim_tree_editor->set_fixed_process(false);
+ anim_tree_editor->set_physics_process(false);
}
}
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 626b4f5a7f..cd53264437 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -1434,7 +1434,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
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_label->add_color_override("color", get_color("error_color", "Editor"));
error_hb->add_child(error_label);
description = NULL;
@@ -1478,7 +1478,7 @@ AssetLibraryEditorPlugin::AssetLibraryEditorPlugin(EditorNode *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->set_anchors_and_margins_preset(Control::PRESET_WIDE);
addon_library->hide();
}
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index ad01d0a31e..1aa24c8172 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -53,6 +53,8 @@
#define MIN_ZOOM 0.01
#define MAX_ZOOM 100
+#define RULER_WIDTH 15 * EDSCALE
+
class SnapDialog : public ConfirmationDialog {
GDCLASS(SnapDialog, ConfirmationDialog);
@@ -109,13 +111,13 @@ public:
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_min(0.01);
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_min(0.01);
grid_step_y->set_max(SPIN_BOX_GRID_RANGE);
grid_step_y->set_suffix("px");
child_container->add_child(grid_step_y);
@@ -149,7 +151,7 @@ public:
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) {
+ void set_fields(const Point2 p_grid_offset, const Point2 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);
@@ -158,11 +160,9 @@ public:
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();
+ void get_fields(Point2 &p_grid_offset, Point2 &p_grid_step, float &p_rotation_offset, float &p_rotation_step) {
+ p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value());
+ p_grid_step = Point2(grid_step_x->get_value(), 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);
}
@@ -222,6 +222,135 @@ void CanvasItemEditor::_edit_set_pivot(const Vector2 &mouse_pos) {
undo_redo->commit_action();
}
+void CanvasItemEditor::_snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation, float p_radius) {
+ float radius = p_radius / zoom;
+ float dist;
+
+ Transform2D rot_trans = Transform2D(rotation, Point2());
+ p_value = rot_trans.inverse().xform(p_value);
+ p_target_snap = rot_trans.inverse().xform(p_target_snap);
+ r_current_snap = rot_trans.inverse().xform(r_current_snap);
+
+ dist = Math::abs(p_value.x - p_target_snap.x);
+ if (p_radius < 0 || dist < radius && (!r_snapped[0] || dist < Math::abs(r_current_snap.x - p_value.x))) {
+ r_current_snap.x = p_target_snap.x;
+ r_snapped[0] = true;
+ }
+
+ dist = Math::abs(p_value.y - p_target_snap.y);
+ if (p_radius < 0 || dist < radius && (!r_snapped[1] || dist < Math::abs(r_current_snap.y - p_value.y))) {
+ r_current_snap.y = p_target_snap.y;
+ r_snapped[1] = true;
+ }
+
+ r_current_snap = rot_trans.xform(r_current_snap);
+}
+
+void CanvasItemEditor::_snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap) {
+ const CanvasItem *canvas_item = Object::cast_to<CanvasItem>(p_current);
+ if (canvas_item && p_current != p_to_snap) {
+ Transform2D ci_transform = canvas_item->get_global_transform_with_canvas();
+ Transform2D to_snap_transform = p_to_snap->get_global_transform_with_canvas();
+ if (ci_transform.get_rotation() == to_snap_transform.get_rotation()) {
+ Point2 begin = ci_transform.xform(canvas_item->get_item_rect().get_position());
+ Point2 end = ci_transform.xform(canvas_item->get_item_rect().get_position() + canvas_item->get_item_rect().get_size());
+
+ _snap_if_closer(p_value, begin, r_current_snap, r_snapped, ci_transform.get_rotation());
+ _snap_if_closer(p_value, end, r_current_snap, r_snapped, ci_transform.get_rotation());
+ }
+ }
+ for (int i = 0; i < p_current->get_child_count(); i++) {
+ _snap_other_nodes(p_value, r_current_snap, r_snapped, p_current->get_child(i), p_to_snap);
+ }
+}
+
+Point2 CanvasItemEditor::snap_point(Point2 p_target, unsigned int p_modes, const CanvasItem *p_canvas_item, unsigned int p_forced_modes) {
+ Point2 dist[2];
+ bool snapped[2] = { false, false };
+
+ // Smart snap using the canvas position
+ Vector2 output = p_target;
+ real_t rotation = 0.0;
+
+ if (p_canvas_item) {
+ Point2 begin;
+ Point2 end;
+ rotation = p_canvas_item->get_global_transform_with_canvas().get_rotation();
+
+ if ((snap_active && snap_node_parent && (p_modes & SNAP_NODE_PARENT)) || (p_forced_modes & SNAP_NODE_PARENT)) {
+ // Parent sides and center
+ bool can_snap = false;
+ if (const Control *c = Object::cast_to<Control>(p_canvas_item)) {
+ begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(0, 0)));
+ end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(1, 1)));
+ can_snap = true;
+ } else if (const CanvasItem *parent_ci = Object::cast_to<CanvasItem>(p_canvas_item->get_parent())) {
+ begin = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position());
+ end = p_canvas_item->get_transform().affine_inverse().xform(parent_ci->get_item_rect().get_position() + parent_ci->get_item_rect().get_size());
+ can_snap = true;
+ }
+
+ if (can_snap) {
+ _snap_if_closer(p_target, begin, output, snapped, rotation);
+ _snap_if_closer(p_target, (begin + end) / 2.0, output, snapped, rotation);
+ _snap_if_closer(p_target, end, output, snapped, rotation);
+ }
+ }
+
+ // Self anchors (for sides)
+ if ((snap_active && snap_node_anchors && (p_modes & SNAP_NODE_ANCHORS)) || (p_forced_modes & SNAP_NODE_ANCHORS)) {
+ if (const Control *c = Object::cast_to<Control>(p_canvas_item)) {
+ begin = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_LEFT), c->get_anchor(MARGIN_TOP))));
+ end = p_canvas_item->get_global_transform_with_canvas().xform(_anchor_to_position(c, Point2(c->get_anchor(MARGIN_RIGHT), c->get_anchor(MARGIN_BOTTOM))));
+ _snap_if_closer(p_target, begin, output, snapped, rotation);
+ _snap_if_closer(p_target, end, output, snapped, rotation);
+ }
+ }
+
+ // Self sides (for anchors)
+ if ((snap_active && snap_node_sides && (p_modes & SNAP_NODE_SIDES)) || (p_forced_modes & SNAP_NODE_SIDES)) {
+ begin = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position());
+ end = p_canvas_item->get_global_transform_with_canvas().xform(p_canvas_item->get_item_rect().get_position() + p_canvas_item->get_item_rect().get_size());
+ _snap_if_closer(p_target, begin, output, snapped, rotation);
+ _snap_if_closer(p_target, end, output, snapped, rotation);
+ }
+
+ // Other nodes sides
+ if ((snap_active && snap_other_nodes && (p_modes & SNAP_OTHER_NODES)) || (p_forced_modes & SNAP_OTHER_NODES)) {
+ _snap_other_nodes(p_target, output, snapped, get_tree()->get_edited_scene_root(), p_canvas_item);
+ }
+ }
+
+ if (((snap_active && snap_grid && (p_modes & SNAP_GRID)) || (p_forced_modes & SNAP_GRID)) && rotation == 0.0) {
+ // Grid
+ Point2 offset = grid_offset;
+ if (snap_relative) {
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+ if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) {
+ offset = Object::cast_to<Node2D>(selection[0])->get_global_position();
+ } else {
+ offset = _find_topleftmost_point();
+ }
+ }
+ Point2 grid_output;
+ grid_output.x = Math::stepify(p_target.x - offset.x, grid_step.x * Math::pow(2.0, grid_step_multiplier)) + offset.x;
+ grid_output.y = Math::stepify(p_target.y - offset.y, grid_step.y * Math::pow(2.0, grid_step_multiplier)) + offset.y;
+ _snap_if_closer(p_target, grid_output, output, snapped, 0.0, -1.0);
+ }
+
+ if (((snap_pixel && (p_modes & SNAP_PIXEL)) || (p_forced_modes & SNAP_PIXEL)) && rotation == 0.0) {
+ // Pixel
+ output = output.snapped(Size2(1, 1));
+ }
+
+ return output;
+}
+
+float CanvasItemEditor::snap_angle(float p_target, float p_start) const {
+ float offset = snap_relative ? p_start : p_target;
+ return (snap_rotation && snap_rotation_step != 0) ? Math::stepify(p_target - snap_rotation_offset, snap_rotation_step) + snap_rotation_offset : p_target;
+}
+
void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventKey> k = p_ev;
@@ -232,22 +361,34 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
if (k->get_control())
return;
- if (k->is_pressed() && !k->is_echo() && k->get_scancode() == KEY_V && drag == DRAG_NONE && can_move_pivot) {
-
- if (k->get_shift()) {
+ if (k->is_pressed() && !k->is_echo()) {
+ if (drag_pivot_shortcut.is_valid() && drag_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) {
//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);
+ } else if (set_pivot_shortcut.is_valid() && set_pivot_shortcut->is_shortcut(p_ev) && drag == DRAG_NONE && can_move_pivot) {
+ 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_position();
+ 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, SNAP_DEFAULT, _get_single_item());
+
+ _edit_set_pivot(mouse_pos);
+ }
}
+ } else if ((snap_grid || show_grid) && multiply_grid_step_shortcut.is_valid() && multiply_grid_step_shortcut->is_shortcut(p_ev)) {
+ // Multiply the grid size
+ grid_step_multiplier = MIN(grid_step_multiplier + 1, 12);
+ viewport_base->update();
+ viewport->update();
+ } else if ((snap_grid || show_grid) && divide_grid_step_shortcut.is_valid() && divide_grid_step_shortcut->is_shortcut(p_ev)) {
+ // Divide the grid size
+ Point2 new_grid_step = grid_step * Math::pow(2.0, grid_step_multiplier - 1);
+ if (new_grid_step.x >= 1.0 && new_grid_step.y >= 1.0)
+ grid_step_multiplier--;
+ viewport_base->update();
+ viewport->update();
}
}
}
@@ -272,38 +413,25 @@ Object *CanvasItemEditor::_get_editor_data(Object *p_what) {
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["grid_offset"] = grid_offset;
+ state["grid_step"] = grid_step;
state["snap_rotation_offset"] = snap_rotation_offset;
state["snap_rotation_step"] = snap_rotation_step;
+ state["snap_active"] = snap_active;
+ state["snap_node_parent"] = snap_node_parent;
+ state["snap_node_anchors"] = snap_node_anchors;
+ state["snap_node_sides"] = snap_node_sides;
+ state["snap_other_nodes"] = snap_other_nodes;
state["snap_grid"] = snap_grid;
- state["snap_show_grid"] = snap_show_grid;
+ state["show_grid"] = show_grid;
+ state["show_rulers"] = show_rulers;
+ state["show_helpers"] = show_helpers;
state["snap_rotation"] = snap_rotation;
state["snap_relative"] = snap_relative;
state["snap_pixel"] = snap_pixel;
@@ -324,12 +452,12 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
v_scroll->set_value(ofs.y);
}
- if (state.has("snap_step")) {
- snap_step = state["snap_step"];
+ if (state.has("grid_offset")) {
+ grid_offset = state["grid_offset"];
}
- if (state.has("snap_offset")) {
- snap_offset = state["snap_offset"];
+ if (state.has("grid_step")) {
+ grid_step = state["grid_step"];
}
if (state.has("snap_rotation_step")) {
@@ -340,40 +468,81 @@ void CanvasItemEditor::set_state(const Dictionary &p_state) {
snap_rotation_offset = state["snap_rotation_offset"];
}
+ if (state.has("snap_active")) {
+ snap_active = state["snap_active"];
+ snap_button->set_pressed(snap_active);
+ }
+
+ if (state.has("snap_node_parent")) {
+ snap_node_parent = state["snap_node_parent"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_parent);
+ }
+
+ if (state.has("snap_node_anchors")) {
+ snap_node_anchors = state["snap_node_anchors"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_anchors);
+ }
+
+ if (state.has("snap_node_sides")) {
+ snap_node_sides = state["snap_node_sides"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
+ }
+
+ if (state.has("snap_other_nodes")) {
+ snap_other_nodes = state["snap_other_nodes"];
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
+ smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
+ }
+
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);
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID);
+ snap_config_menu->get_popup()->set_item_checked(idx, snap_grid);
+ }
+
+ if (state.has("show_grid")) {
+ show_grid = state["show_grid"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
+ view_menu->get_popup()->set_item_checked(idx, show_grid);
+ }
+
+ if (state.has("show_rulers")) {
+ show_rulers = state["show_rulers"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
+ view_menu->get_popup()->set_item_checked(idx, show_rulers);
}
- 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("show_helpers")) {
+ show_helpers = state["show_helpers"];
+ int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
+ view_menu->get_popup()->set_item_checked(idx, show_helpers);
}
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);
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+ snap_config_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);
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+ snap_config_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);
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
+ snap_config_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);
+ int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
+ skeleton_menu->get_popup()->set_item_checked(idx, skeleton_show_bones);
}
viewport->update();
@@ -495,6 +664,7 @@ void CanvasItemEditor::_select_click_on_empty_area(Point2 p_click_pos, bool p_ap
if (!p_append) {
editor_selection->clear();
viewport->update();
+ viewport_base->update();
};
if (p_box_selection) {
@@ -534,6 +704,7 @@ bool CanvasItemEditor::_select_click_on_item(CanvasItem *item, Point2 p_click_po
}
viewport->update();
+ viewport_base->update();
return still_selected;
}
@@ -566,7 +737,7 @@ void CanvasItemEditor::_key_move(const Vector2 &p_dir, bool p_snap, KeyMoveMODE
Vector2 drag = p_dir;
if (p_snap)
- drag *= snap_step;
+ drag *= grid_step * Math::pow(2.0, grid_step_multiplier);
undo_redo->add_undo_method(canvas_item, "edit_set_state", canvas_item->edit_get_state());
@@ -649,7 +820,7 @@ int CanvasItemEditor::get_item_count() {
return ic;
}
-CanvasItem *CanvasItemEditor::get_single_item() {
+CanvasItem *CanvasItemEditor::_get_single_item() {
Map<Node *, Object *> &selection = editor_selection->get_selection();
@@ -674,7 +845,7 @@ CanvasItem *CanvasItemEditor::get_single_item() {
CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const Point2 &p_click, Vector2 &r_point) {
// Returns a drag type if a resize handle is clicked
- CanvasItem *canvas_item = get_single_item();
+ CanvasItem *canvas_item = _get_single_item();
ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
@@ -738,35 +909,7 @@ CanvasItemEditor::DragType CanvasItemEditor::_get_resize_handle_drag_type(const
return DRAG_NONE;
}
-float CanvasItemEditor::_anchor_snap(float p_anchor, bool *p_snapped, float p_opposite_anchor) {
- bool snapped = false;
- float dist, dist_min = 0.0;
- float radius = 0.05 / zoom;
- float basic_anchors[3] = { 0.0, 0.5, 1.0 };
- for (int i = 0; i < 3; i++) {
- dist = fabs(p_anchor - basic_anchors[i]);
- if (dist < radius) {
- if (!snapped || dist <= dist_min) {
- p_anchor = basic_anchors[i];
- dist_min = dist;
- snapped = true;
- }
- }
- }
- dist = fabs(p_anchor - p_opposite_anchor);
- if (p_opposite_anchor >= 0 && dist < radius) {
- if (!snapped || dist <= dist_min) {
- p_anchor = p_opposite_anchor;
- dist_min = dist;
- snapped = true;
- }
- }
- if (p_snapped)
- *p_snapped = snapped;
- return p_anchor;
-}
-
-Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor) {
+Vector2 CanvasItemEditor::_anchor_to_position(const Control *p_control, Vector2 anchor) {
ERR_FAIL_COND_V(!p_control, Vector2());
Transform2D parent_transform = p_control->get_transform().affine_inverse();
@@ -775,7 +918,7 @@ Vector2 CanvasItemEditor::_anchor_to_position(Control *p_control, Vector2 anchor
return parent_transform.xform(Vector2(parent_size.x * anchor.x, parent_size.y * anchor.y));
}
-Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 position) {
+Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2 position) {
ERR_FAIL_COND_V(!p_control, Vector2());
Size2 parent_size = p_control->get_parent_area_size();
@@ -784,7 +927,7 @@ Vector2 CanvasItemEditor::_position_to_anchor(Control *p_control, Vector2 positi
CanvasItemEditor::DragType CanvasItemEditor::_get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point) {
// Returns a drag type if an anchor handle is clicked
- CanvasItem *canvas_item = get_single_item();
+ CanvasItem *canvas_item = _get_single_item();
ERR_FAIL_COND_V(!canvas_item, DRAG_NONE);
Control *control = Object::cast_to<Control>(canvas_item);
@@ -845,6 +988,8 @@ void CanvasItemEditor::_prepare_drag(const Point2 &p_click_pos) {
se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot();
if (Object::cast_to<Control>(canvas_item))
se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
+
+ se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
}
if (selection.size() == 1 && Object::cast_to<Node2D>(selection[0])) {
@@ -918,28 +1063,12 @@ void CanvasItemEditor::_append_canvas_item(CanvasItem *p_item) {
}
void CanvasItemEditor::_snap_changed() {
- ((SnapDialog *)snap_dialog)->get_fields(snap_offset, snap_step, snap_rotation_offset, snap_rotation_step);
+ ((SnapDialog *)snap_dialog)->get_fields(grid_offset, grid_step, snap_rotation_offset, snap_rotation_step);
+ grid_step_multiplier = 0;
+ viewport_base->update();
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)
@@ -960,7 +1089,7 @@ void CanvasItemEditor::_selection_menu_hide() {
void CanvasItemEditor::_list_select(const Ref<InputEventMouseButton> &b) {
- Point2 click = b->get_position();
+ Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
Node *scene = editor->get_edited_scene();
if (!scene)
@@ -1068,7 +1197,7 @@ void CanvasItemEditor::_update_cursor() {
viewport->set_default_cursor_shape(c);
}
-void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
+void CanvasItemEditor::_viewport_base_gui_input(const Ref<InputEvent> &p_event) {
{
EditorNode *en = editor;
@@ -1090,50 +1219,26 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
if (b->get_button_index() == BUTTON_WHEEL_DOWN) {
// Scroll or pan down
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
-
v_scroll->set_value(v_scroll->get_value() + int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor());
-
+ _update_scroll(0);
+ viewport->update();
} else {
-
- if (zoom < MIN_ZOOM)
- return;
-
- float prev_zoom = zoom;
- zoom = zoom * (1 - (0.05 * b->get_factor()));
- {
- Point2 ofs = b->get_position();
- 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);
- }
+ _zoom_on_position(zoom * (1 - (0.05 * b->get_factor())), viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()));
}
- _update_scroll(0);
- viewport->update();
return;
}
if (b->get_button_index() == BUTTON_WHEEL_UP) {
// Scroll or pan up
if (bool(EditorSettings::get_singleton()->get("editors/2d/scroll_to_pan"))) {
-
v_scroll->set_value(v_scroll->get_value() - int(EditorSettings::get_singleton()->get("editors/2d/pan_speed")) / zoom * b->get_factor());
-
+ _update_scroll(0);
+ viewport->update();
} else {
- if (zoom > MAX_ZOOM) return;
-
- float prev_zoom = zoom;
- zoom = zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95);
- {
- Point2 ofs = b->get_position();
- 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);
- }
+ _zoom_on_position(zoom * ((0.95 + (0.05 * b->get_factor())) / 0.95), viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()));
}
- _update_scroll(0);
- viewport->update();
return;
}
@@ -1214,9 +1319,9 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
if (b->get_button_index() == BUTTON_LEFT && tool == TOOL_EDIT_PIVOT) {
if (b->is_pressed()) {
// Set the pivot point
- Point2 mouse_pos = b->get_position();
+ Point2 mouse_pos = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
mouse_pos = transform.affine_inverse().xform(mouse_pos);
- mouse_pos = snap_point(mouse_pos);
+ mouse_pos = snap_point(mouse_pos, SNAP_DEFAULT, _get_single_item());
_edit_set_pivot(mouse_pos);
}
return;
@@ -1337,8 +1442,8 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
E->get().to
};
- Vector2 p = Geometry::get_closest_point_to_segment_2d(b->get_position(), s);
- float d = p.distance_to(b->get_position());
+ Vector2 p = Geometry::get_closest_point_to_segment_2d(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()), s);
+ float d = p.distance_to(viewport_scrollable->get_transform().affine_inverse().xform(b->get_position()));
if (d < bone_width && d < closest_dist) {
Cbone = E;
closest_dist = d;
@@ -1395,12 +1500,12 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
// Single selected item
- CanvasItem *canvas_item = get_single_item();
+ CanvasItem *canvas_item = _get_single_item();
if (canvas_item) {
CanvasItemEditorSelectedItem *se = editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item);
ERR_FAIL_COND(!se);
- Point2 click = b->get_position();
+ Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
// Rotation
if ((b->get_control() && tool == TOOL_SELECT) || tool == TOOL_ROTATE) {
@@ -1411,6 +1516,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot();
if (Object::cast_to<Control>(canvas_item))
se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
+ se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
return;
}
@@ -1432,15 +1538,18 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
se->undo_pivot = Object::cast_to<Node2D>(canvas_item)->edit_get_pivot();
if (Object::cast_to<Control>(canvas_item))
se->undo_pivot = Object::cast_to<Control>(canvas_item)->get_pivot_offset();
+ se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
return;
}
// Drag anchor handles
- if (Object::cast_to<Control>(canvas_item)) {
+ Control *control = Object::cast_to<Control>(canvas_item);
+ if (control && show_helpers && !Object::cast_to<Container>(control->get_parent())) {
drag = _get_anchor_handle_drag_type(click, drag_point_from);
if (drag != DRAG_NONE) {
drag_from = transform.affine_inverse().xform(click);
se->undo_state = canvas_item->edit_get_state();
+ se->pre_drag_xform = canvas_item->get_global_transform_with_canvas();
return;
}
}
@@ -1448,7 +1557,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
// Multiple selected items
- Point2 click = b->get_position();
+ Point2 click = viewport_scrollable->get_transform().affine_inverse().xform(b->get_position());
if ((b->get_alt() || tool == TOOL_MOVE) && get_item_count()) {
// Drag the nodes
@@ -1508,12 +1617,12 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
// Mouse motion event
_update_cursor();
- if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
- viewport->call_deferred("grab_focus");
+ if (!viewport_base->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field()))
+ viewport_base->call_deferred("grab_focus");
if (box_selecting) {
// Update box selection
- box_selecting_to = transform.affine_inverse().xform(m->get_position());
+ box_selecting_to = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position()));
viewport->update();
return;
}
@@ -1559,7 +1668,7 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
Vector2 dfrom = drag_from;
- Vector2 dto = transform.affine_inverse().xform(m->get_position());
+ Vector2 dto = transform.affine_inverse().xform(viewport_scrollable->get_transform().affine_inverse().xform(m->get_position()));
if (canvas_item->has_meta("_edit_lock_"))
continue;
@@ -1593,60 +1702,74 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
continue;
}
+ bool uniform = m->get_shift();
+ bool symmetric = m->get_alt();
+
+ 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);
+
+ switch (drag) {
+ case DRAG_ALL:
+ case DRAG_NODE_2D:
+ dto -= drag_from - drag_point_from;
+ if (uniform) {
+ 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;
+ }
+ }
+ break;
+ }
+
Control *control = Object::cast_to<Control>(canvas_item);
if (control) {
// Drag and snap the anchor
- Vector2 anchor = _position_to_anchor(control, canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto - drag_from + drag_point_from));
+ Transform2D c_trans_rev = canvas_item->get_global_transform_with_canvas().affine_inverse();
+
+ Vector2 anchor = c_trans_rev.xform(dto - drag_from + drag_point_from);
+ anchor = _position_to_anchor(control, anchor);
+
+ Vector2 anchor_snapped = c_trans_rev.xform(snap_point(dto - drag_from + drag_point_from, SNAP_GRID | SNAP_OTHER_NODES, _get_single_item(), SNAP_NODE_PARENT | SNAP_NODE_SIDES));
+ anchor_snapped = _position_to_anchor(control, anchor_snapped).snapped(Vector2(0.00001, 0.00001));
+
+ bool use_y = Math::abs(drag_vector.y) > Math::abs(drag_vector.x);
switch (drag) {
case DRAG_ANCHOR_TOP_LEFT:
- control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_RIGHT)), false, false);
- control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_BOTTOM)), false, false);
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y);
continue;
break;
case DRAG_ANCHOR_TOP_RIGHT:
- control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_LEFT)), false, false);
- control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_BOTTOM)), false, false);
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y);
continue;
break;
case DRAG_ANCHOR_BOTTOM_RIGHT:
- control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_LEFT)), false, false);
- control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_TOP)), false, false);
- continue;
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y);
break;
case DRAG_ANCHOR_BOTTOM_LEFT:
- control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x, NULL, control->get_anchor(MARGIN_RIGHT)), false, false);
- control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y, NULL, control->get_anchor(MARGIN_TOP)), false, false);
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y);
continue;
break;
case DRAG_ANCHOR_ALL:
- control->set_anchor(MARGIN_LEFT, _anchor_snap(anchor.x));
- control->set_anchor(MARGIN_RIGHT, _anchor_snap(anchor.x));
- control->set_anchor(MARGIN_TOP, _anchor_snap(anchor.y));
- control->set_anchor(MARGIN_BOTTOM, _anchor_snap(anchor.y));
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_LEFT, anchor_snapped.x);
+ if (!uniform || (uniform && !use_y)) control->set_anchor(MARGIN_RIGHT, anchor_snapped.x);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_TOP, anchor_snapped.y);
+ if (!uniform || (uniform && use_y)) control->set_anchor(MARGIN_BOTTOM, anchor_snapped.y);
continue;
break;
}
}
- bool uniform = m->get_shift();
- bool symmetric = m->get_alt();
-
- if (drag == DRAG_ALL || drag == DRAG_NODE_2D)
- dto -= drag_from - drag_point_from;
-
- if (uniform && (drag == DRAG_ALL || drag == DRAG_NODE_2D)) {
- 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);
+ dto = snap_point(dto, SNAP_NODE_ANCHORS | SNAP_NODE_PARENT | SNAP_OTHER_NODES | SNAP_GRID | SNAP_PIXEL, _get_single_item());
- Vector2 drag_vector =
+ drag_vector =
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dto) -
canvas_item->get_global_transform_with_canvas().affine_inverse().xform(dfrom);
@@ -1896,90 +2019,180 @@ void CanvasItemEditor::_viewport_gui_input(const Ref<InputEvent> &p_event) {
}
}
+void CanvasItemEditor::_draw_text_at_position(Point2 p_position, String p_string, Margin p_side) {
+ Color color = get_color("font_color", "Editor");
+ color.a = 0.8;
+ Ref<Font> font = get_font("font", "Label");
+ Size2 text_size = font->get_string_size(p_string);
+ switch (p_side) {
+ case MARGIN_LEFT:
+ p_position += Vector2(-text_size.x - 5, text_size.y / 2);
+ break;
+ case MARGIN_TOP:
+ p_position += Vector2(-text_size.x / 2, -5);
+ break;
+ case MARGIN_RIGHT:
+ p_position += Vector2(5, text_size.y / 2);
+ break;
+ case MARGIN_BOTTOM:
+ p_position += Vector2(-text_size.x / 2, text_size.y + 5);
+ break;
+ }
+ viewport->draw_string(font, p_position, p_string, color);
+}
+
+void CanvasItemEditor::_draw_margin_at_position(int p_value, Point2 p_position, Margin p_side) {
+ String str = vformat("%d px", p_value);
+ if (p_value != 0) {
+ _draw_text_at_position(p_position, str, p_side);
+ }
+}
+
void CanvasItemEditor::_draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side) {
+ String str = vformat("%.1f %%", p_value * 100.0);
if (p_value != 0) {
- Color color = Color(0.8, 0.8, 0.8, 0.5);
- Ref<Font> font = get_font("font", "Label");
- String str = vformat("%.1f %%", p_value * 100.0);
- Size2 text_size = font->get_string_size(str);
- switch (p_side) {
- case MARGIN_LEFT:
- p_position += Vector2(-text_size.x - 5, text_size.y / 2);
- break;
- case MARGIN_TOP:
- p_position += Vector2(-text_size.x / 2, -5);
- break;
- case MARGIN_RIGHT:
- p_position += Vector2(5, text_size.y / 2);
- break;
- case MARGIN_BOTTOM:
- p_position += Vector2(-text_size.x / 2, text_size.y + 5);
- break;
- }
- viewport->draw_string(font, p_position, str, color);
+ _draw_text_at_position(p_position, str, p_side);
}
}
-void CanvasItemEditor::_viewport_draw() {
+void CanvasItemEditor::_draw_rulers() {
+ Color graduation_color = get_color("font_color", "Editor");
+ graduation_color.a = 0.5;
+ Color bg_color = get_color("dark_color_2", "Editor");
+ Color font_color = get_color("font_color", "Editor");
+ font_color.a = 0.8;
+ Ref<Font> font = get_font("rulers", "EditorFonts");
+
+ // The rule transform
+ Transform2D ruler_transform;
+ if (show_grid || snap_grid) {
+ ruler_transform = Transform2D();
+ if (snap_relative && get_item_count() > 0) {
+ ruler_transform.translate(_find_topleftmost_point());
+ ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
+ } else {
+ ruler_transform.translate(grid_offset);
+ ruler_transform.scale_basis(grid_step * Math::pow(2.0, grid_step_multiplier));
+ }
+ while ((transform * ruler_transform).get_scale().x < 50 || (transform * ruler_transform).get_scale().y < 50) {
- // TODO fetch the viewport?
+ ruler_transform.scale_basis(Point2(2, 2));
+ }
+ } else {
+ float basic_rule = 100;
+ for (int i = 0; basic_rule * zoom > 100; i++) {
+ basic_rule /= (i % 2) ? 5.0 : 2.0;
+ }
+ for (int i = 0; basic_rule * zoom < 100; i++) {
+ basic_rule *= (i % 2) ? 2.0 : 5.0;
+ }
+ ruler_transform = Transform2D();
+ ruler_transform.scale(Size2(basic_rule, basic_rule));
+ }
- Ref<Texture> pivot = get_icon("EditorPivot", "EditorIcons");
- _update_scrollbars();
- RID ci = viewport->get_canvas_item();
+ // Subdivisions
+ int major_subdivision = 2;
+ Transform2D major_subdivide = Transform2D();
+ major_subdivide.scale(Size2(1.0 / major_subdivision, 1.0 / major_subdivision));
+
+ int minor_subdivision = 5;
+ Transform2D minor_subdivide = Transform2D();
+ minor_subdivide.scale(Size2(1.0 / minor_subdivision, 1.0 / minor_subdivision));
+
+ // First and last graduations to draw (in the ruler space)
+ Point2 first = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(Point2());
+ Point2 last = (transform * ruler_transform * major_subdivide * minor_subdivide).affine_inverse().xform(viewport->get_size());
+
+ // Draw top ruler
+ viewport_base->draw_rect(Rect2(Point2(RULER_WIDTH, 0), Size2(viewport->get_size().x, RULER_WIDTH)), bg_color);
+ for (int i = Math::ceil(first.x); i < last.x; i++) {
+ Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0));
+ if (i % (major_subdivision * minor_subdivision) == 0) {
+ viewport_base->draw_line(Point2(position.x + RULER_WIDTH, 0), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color);
+ float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(i, 0)).x;
+ viewport_base->draw_string(font, Point2(position.x + RULER_WIDTH + 2, font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
+ } else {
+ if (i % minor_subdivision == 0) {
+ viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.33), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color);
+ } else {
+ viewport_base->draw_line(Point2(position.x + RULER_WIDTH, RULER_WIDTH * 0.66), Point2(position.x + RULER_WIDTH, RULER_WIDTH), graduation_color);
+ }
+ }
+ }
+
+ // Draw left ruler
+ viewport_base->draw_rect(Rect2(Point2(0, RULER_WIDTH), Size2(RULER_WIDTH, viewport->get_size().y)), bg_color);
+ for (int i = Math::ceil(first.y); i < last.y; i++) {
+ Point2 position = (transform * ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i));
+ if (i % (major_subdivision * minor_subdivision) == 0) {
+ viewport_base->draw_line(Point2(0, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color);
+ float val = (ruler_transform * major_subdivide * minor_subdivide).xform(Point2(0, i)).y;
+ viewport_base->draw_string(font, Point2(2, position.y + RULER_WIDTH + 2 + font->get_height()), vformat(((int)val == val) ? "%d" : "%.1f", val), font_color);
+ } else {
+ if (i % minor_subdivision == 0) {
+ viewport_base->draw_line(Point2(RULER_WIDTH * 0.33, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color);
+ } else {
+ viewport_base->draw_line(Point2(RULER_WIDTH * 0.66, position.y + RULER_WIDTH), Point2(RULER_WIDTH, position.y + RULER_WIDTH), graduation_color);
+ }
+ }
+ }
+ viewport_base->draw_rect(Rect2(Point2(), Size2(RULER_WIDTH, RULER_WIDTH)), graduation_color);
+}
- if (snap_show_grid) {
+void CanvasItemEditor::_draw_focus() {
+ if (viewport_base->has_focus()) {
+ get_stylebox("Focus", "EditorStyles")->draw(viewport_base->get_canvas_item(), Rect2(Point2(), viewport_base->get_size()));
+ }
+}
+
+void CanvasItemEditor::_draw_grid() {
+ if (show_grid) {
//Draw the grid
Size2 s = viewport->get_size();
int last_cell = 0;
Transform2D xform = transform.affine_inverse();
- Vector2 grid_offset;
- if (snap_relative && snap_grid && get_item_count() > 0) {
+ Vector2 real_grid_offset;
+ if (snap_relative && get_item_count() > 0) {
Vector2 topleft = _find_topleftmost_point();
- grid_offset.x = fmod(topleft.x, snap_step.x);
- grid_offset.y = fmod(topleft.y, snap_step.y);
+ real_grid_offset.x = fmod(topleft.x, grid_step.x * Math::pow(2.0, grid_step_multiplier));
+ real_grid_offset.y = fmod(topleft.y, grid_step.y * Math::pow(2.0, grid_step_multiplier));
} else {
- grid_offset = snap_offset;
+ real_grid_offset = grid_offset;
}
- if (snap_step.x != 0) {
+ const Color grid_minor_color = get_color("grid_minor_color", "Editor");
+ if (grid_step.x != 0) {
for (int i = 0; i < s.width; i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - grid_offset.x) / snap_step.x));
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(i, 0)).x - real_grid_offset.x) / (grid_step.x * Math::pow(2.0, grid_step_multiplier))));
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));
+ viewport->draw_line(Point2(i, 0), Point2(i, s.height), grid_minor_color);
last_cell = cell;
}
}
- if (snap_step.y != 0) {
+ if (grid_step.y != 0) {
for (int i = 0; i < s.height; i++) {
- int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - grid_offset.y) / snap_step.y));
+ int cell = Math::fast_ftoi(Math::floor((xform.xform(Vector2(0, i)).y - real_grid_offset.y) / (grid_step.y * Math::pow(2.0, grid_step_multiplier))));
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));
+ viewport->draw_line(Point2(0, i), Point2(s.width, i), grid_minor_color);
last_cell = cell;
}
}
}
+}
- if (viewport->has_focus()) {
- Size2 size = viewport->get_size();
- get_stylebox("Focus", "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();
-
+void CanvasItemEditor::_draw_selection() {
bool pivot_found = false;
+ Ref<Texture> pivot_icon = get_icon("EditorPivot", "EditorIcons");
+ bool single = _get_single_item() != NULL;
+ RID ci = viewport->get_canvas_item();
+ Map<Node *, Object *> &selection = editor_selection->get_selection();
for (Map<Node *, Object *>::Element *E = selection.front(); E; E = E->next()) {
CanvasItem *canvas_item = Object::cast_to<CanvasItem>(E->key());
@@ -1993,6 +2206,23 @@ void CanvasItemEditor::_viewport_draw() {
Rect2 rect = canvas_item->get_item_rect();
+ if (drag != DRAG_NONE && drag != DRAG_PIVOT) {
+ const Transform2D pre_drag_xform = transform * se->pre_drag_xform;
+ const Color pre_drag_color = Color(0.4, 0.6, 1, 0.7);
+
+ Vector2 pre_drag_endpoints[4] = {
+
+ pre_drag_xform.xform(rect.position),
+ pre_drag_xform.xform(rect.position + Vector2(rect.size.x, 0)),
+ pre_drag_xform.xform(rect.position + rect.size),
+ pre_drag_xform.xform(rect.position + Vector2(0, rect.size.y))
+ };
+
+ for (int i = 0; i < 4; i++) {
+ viewport->draw_line(pre_drag_endpoints[i], pre_drag_endpoints[(i + 1) % 4], pre_drag_color, 2);
+ }
+ }
+
Transform2D xform = transform * canvas_item->get_global_transform_with_canvas();
VisualServer::get_singleton()->canvas_item_add_set_transform(ci, xform);
@@ -2014,10 +2244,10 @@ void CanvasItemEditor::_viewport_draw() {
if (single && (tool == TOOL_SELECT || tool == TOOL_MOVE || tool == TOOL_ROTATE || tool == TOOL_EDIT_PIVOT)) { //kind of sucks
- if (Object::cast_to<Node2D>(canvas_item)) {
-
- if (Object::cast_to<Node2D>(canvas_item)->edit_has_pivot()) {
- viewport->draw_texture(pivot, xform.get_origin() + (-pivot->get_size() / 2).floor());
+ Node2D *node2d = Object::cast_to<Node2D>(canvas_item);
+ if (node2d) {
+ if (node2d->edit_has_pivot()) {
+ viewport->draw_texture(pivot_icon, xform.get_origin() + (-pivot_icon->get_size() / 2).floor());
can_move_pivot = true;
pivot_found = true;
}
@@ -2027,12 +2257,15 @@ void CanvasItemEditor::_viewport_draw() {
if (control) {
Vector2 pivot_ofs = control->get_pivot_offset();
if (pivot_ofs != Vector2()) {
- viewport->draw_texture(pivot, xform.xform(pivot_ofs) + (-pivot->get_size() / 2).floor());
+ viewport->draw_texture(pivot_icon, xform.xform(pivot_ofs) + (-pivot_icon->get_size() / 2).floor());
}
can_move_pivot = true;
pivot_found = true;
- if (tool == TOOL_SELECT) {
+ if (tool == TOOL_SELECT && show_helpers && !Object::cast_to<Container>(control->get_parent())) {
+ // Draw the helpers
+ Color color_base = Color(0.8, 0.8, 0.8, 0.5);
+
float anchors_values[4];
anchors_values[0] = control->get_anchor(MARGIN_LEFT);
anchors_values[1] = control->get_anchor(MARGIN_TOP);
@@ -2047,6 +2280,7 @@ void CanvasItemEditor::_viewport_draw() {
anchors_pos[i] = xform.xform(_anchor_to_position(control, anchors[i]));
}
+ Map<Node *, Object *> &selection = editor_selection->get_selection();
// Get which anchor is dragged
int dragged_anchor = -1;
switch (drag) {
@@ -2069,7 +2303,6 @@ void CanvasItemEditor::_viewport_draw() {
// Draw the 4 lines when dragged
bool snapped;
Color color_snapped = Color(0.64, 0.93, 0.67, 0.5);
- Color color_base = Color(0.8, 0.8, 0.8, 0.5);
Vector2 corners_pos[4];
for (int i = 0; i < 4; i++) {
@@ -2082,7 +2315,7 @@ void CanvasItemEditor::_viewport_draw() {
float anchor_val = (i >= 2) ? ANCHOR_END - anchors_values[i] : anchors_values[i];
line_starts[i] = Vector2::linear_interpolate(corners_pos[i], corners_pos[(i + 1) % 4], anchor_val);
line_ends[i] = Vector2::linear_interpolate(corners_pos[(i + 3) % 4], corners_pos[(i + 2) % 4], anchor_val);
- _anchor_snap(anchors_values[i], &snapped);
+ snapped = anchors_values[i] == 0.0 || anchors_values[i] == 0.5 || anchors_values[i] == 1.0;
viewport->draw_line(line_starts[i], line_ends[i], snapped ? color_snapped : color_base, (i == dragged_anchor || (i + 3) % 4 == dragged_anchor) ? 2 : 1);
}
@@ -2114,6 +2347,83 @@ void CanvasItemEditor::_viewport_draw() {
for (int i = 0; i < 4; i++) {
anchor_handle->draw_rect(ci, anchor_rects[i]);
}
+
+ // Draw the margin values and the node width/height when dragging control side
+ float ratio = 0.33;
+ Transform2D parent_transform = xform * control->get_transform().affine_inverse();
+ float node_pos_in_parent[4];
+
+ node_pos_in_parent[0] = control->get_anchor(MARGIN_LEFT) * control->get_parent_area_size().width + control->get_margin(MARGIN_LEFT);
+ node_pos_in_parent[1] = control->get_anchor(MARGIN_TOP) * control->get_parent_area_size().height + control->get_margin(MARGIN_TOP);
+ node_pos_in_parent[2] = control->get_anchor(MARGIN_RIGHT) * control->get_parent_area_size().width + control->get_margin(MARGIN_RIGHT);
+ node_pos_in_parent[3] = control->get_anchor(MARGIN_BOTTOM) * control->get_parent_area_size().height + control->get_margin(MARGIN_BOTTOM);
+
+ switch (drag) {
+ case DRAG_LEFT:
+ case DRAG_TOP_LEFT:
+ case DRAG_BOTTOM_LEFT:
+ _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM);
+ case DRAG_ALL:
+ Point2 start = Vector2(node_pos_in_parent[0], Math::lerp(node_pos_in_parent[1], node_pos_in_parent[3], ratio));
+ Point2 end = start - Vector2(control->get_margin(MARGIN_LEFT), 0);
+ _draw_margin_at_position(control->get_margin(MARGIN_LEFT), parent_transform.xform((start + end) / 2), MARGIN_TOP);
+ viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1);
+ break;
+ }
+ switch (drag) {
+ case DRAG_RIGHT:
+ case DRAG_TOP_RIGHT:
+ case DRAG_BOTTOM_RIGHT:
+ _draw_margin_at_position(control->get_size().width, parent_transform.xform(Vector2((node_pos_in_parent[0] + node_pos_in_parent[2]) / 2, node_pos_in_parent[3])) + Vector2(0, 5), MARGIN_BOTTOM);
+ case DRAG_ALL:
+ Point2 start = Vector2(node_pos_in_parent[2], Math::lerp(node_pos_in_parent[3], node_pos_in_parent[1], ratio));
+ Point2 end = start - Vector2(control->get_margin(MARGIN_RIGHT), 0);
+ _draw_margin_at_position(control->get_margin(MARGIN_RIGHT), parent_transform.xform((start + end) / 2), MARGIN_BOTTOM);
+ viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1);
+ break;
+ }
+ switch (drag) {
+ case DRAG_TOP:
+ case DRAG_TOP_LEFT:
+ case DRAG_TOP_RIGHT:
+ _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2)) + Vector2(5, 0), MARGIN_RIGHT);
+ case DRAG_ALL:
+ Point2 start = Vector2(Math::lerp(node_pos_in_parent[0], node_pos_in_parent[2], ratio), node_pos_in_parent[1]);
+ Point2 end = start - Vector2(0, control->get_margin(MARGIN_TOP));
+ _draw_margin_at_position(control->get_margin(MARGIN_TOP), parent_transform.xform((start + end) / 2), MARGIN_LEFT);
+ viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1);
+ break;
+ }
+ switch (drag) {
+ case DRAG_BOTTOM:
+ case DRAG_BOTTOM_LEFT:
+ case DRAG_BOTTOM_RIGHT:
+ _draw_margin_at_position(control->get_size().height, parent_transform.xform(Vector2(node_pos_in_parent[2], (node_pos_in_parent[1] + node_pos_in_parent[3]) / 2) + Vector2(5, 0)), MARGIN_RIGHT);
+ case DRAG_ALL:
+ Point2 start = Vector2(Math::lerp(node_pos_in_parent[2], node_pos_in_parent[0], ratio), node_pos_in_parent[3]);
+ Point2 end = start - Vector2(0, control->get_margin(MARGIN_BOTTOM));
+ _draw_margin_at_position(control->get_margin(MARGIN_BOTTOM), parent_transform.xform((start + end) / 2), MARGIN_RIGHT);
+ viewport->draw_line(parent_transform.xform(start), parent_transform.xform(end), color_base, 1);
+ break;
+ }
+
+ switch (drag) {
+ //Draw the ghost rect if the node if rotated/scaled
+ case DRAG_LEFT:
+ case DRAG_TOP_LEFT:
+ case DRAG_TOP:
+ case DRAG_TOP_RIGHT:
+ case DRAG_RIGHT:
+ case DRAG_BOTTOM_RIGHT:
+ case DRAG_BOTTOM:
+ case DRAG_BOTTOM_LEFT:
+ case DRAG_ALL:
+ if (control->get_rotation() != 0.0 || control->get_scale() != Vector2(1, 1)) {
+ Rect2 rect = Rect2(Vector2(node_pos_in_parent[0], node_pos_in_parent[1]), control->get_size());
+ viewport->draw_rect(parent_transform.xform(rect), color_base, false);
+ }
+ break;
+ }
}
}
@@ -2136,33 +2446,32 @@ void CanvasItemEditor::_viewport_draw() {
}
}
}
-
- //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));
}
+ Color rotate_color(0.4, 0.7, 1.0, 0.8);
if (drag == DRAG_ROTATE) {
VisualServer::get_singleton()->canvas_item_add_line(ci, transform.xform(display_rotate_from), transform.xform(display_rotate_to), rotate_color);
}
+}
+
+void CanvasItemEditor::_draw_axis() {
+ RID ci = viewport->get_canvas_item();
+
+ 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);
+
+ Point2 origin = transform.get_origin();
+ VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(0, origin.y), Point2(viewport->get_size().x, origin.y), x_axis_color);
+ VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(origin.x, 0), Point2(origin.x, viewport->get_size().y), y_axis_color);
Size2 screen_size = Size2(ProjectSettings::get_singleton()->get("display/window/size/width"), ProjectSettings::get_singleton()->get("display/window/size/height"));
@@ -2174,34 +2483,12 @@ void CanvasItemEditor::_viewport_draw() {
};
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);
- }
- }
+void CanvasItemEditor::_draw_bones() {
+ RID ci = viewport->get_canvas_item();
if (skeleton_show_bones) {
int bone_width = EditorSettings::get_singleton()->get("editors/2d/bone_width");
@@ -2269,9 +2556,136 @@ void CanvasItemEditor::_viewport_draw() {
}
}
+void CanvasItemEditor::_draw_locks_and_groups(Node *p_node, const Transform2D &p_xform) {
+ ERR_FAIL_COND(!p_node);
+
+ RID viewport_ci = viewport->get_canvas_item();
+
+ Transform2D transform_ci = p_xform;
+ CanvasItem *ci = Object::cast_to<CanvasItem>(p_node);
+ if (ci)
+ transform_ci = transform_ci * ci->get_transform();
+
+ for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
+ _draw_locks_and_groups(p_node->get_child(i), transform_ci);
+ }
+
+ if (ci) {
+ Ref<Texture> lock = get_icon("LockViewport", "EditorIcons");
+ if (p_node->has_meta("_edit_lock_")) {
+ lock->draw(viewport_ci, transform_ci.xform(Point2(0, 0)));
+ }
+
+ Ref<Texture> group = get_icon("GroupViewport", "EditorIcons");
+ if (ci->has_meta("_edit_group_")) {
+ Vector2 ofs = transform_ci.xform(Point2(0, 0));
+ if (ci->has_meta("_edit_lock_"))
+ ofs = Point2(ofs.x + lock->get_size().x, ofs.y);
+ group->draw(viewport_ci, ofs);
+ }
+ }
+}
+
+void CanvasItemEditor::_build_bones_list(Node *p_node) {
+ ERR_FAIL_COND(!p_node);
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _build_bones_list(p_node->get_child(i));
+ }
+
+ CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
+ if (c && c->is_visible_in_tree()) {
+ 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;
+ }
+ }
+}
+
+void CanvasItemEditor::_get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform) {
+ ERR_FAIL_COND(!p_node);
+
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ _get_encompassing_rect(p_node->get_child(i), r_rect, p_xform);
+ }
+
+ CanvasItem *c = Object::cast_to<CanvasItem>(p_node);
+ if (c && c->is_visible_in_tree()) {
+ Rect2 rect = c->get_item_rect();
+ Transform2D xform = p_xform * c->get_transform();
+ r_rect.expand_to(xform.xform(rect.position));
+ r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
+ r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y)));
+ r_rect.expand_to(xform.xform(rect.position + rect.size));
+ }
+}
+
+void CanvasItemEditor::_draw_viewport_base() {
+ if (show_rulers)
+ _draw_rulers();
+ _draw_focus();
+}
+
+void CanvasItemEditor::_draw_viewport() {
+
+ // hide/show buttons depending on the selection
+ bool all_locked = true;
+ bool all_group = true;
+ List<Node *> &selection = editor_selection->get_selected_node_list();
+ if (selection.empty()) {
+ all_locked = false;
+ all_group = false;
+ } else {
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ if (Object::cast_to<CanvasItem>(E->get()) && !Object::cast_to<CanvasItem>(E->get())->has_meta("_edit_lock_")) {
+ all_locked = false;
+ break;
+ }
+ }
+ for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
+ if (Object::cast_to<CanvasItem>(E->get()) && !Object::cast_to<CanvasItem>(E->get())->has_meta("_edit_group_")) {
+ all_group = false;
+ break;
+ }
+ }
+ }
+
+ lock_button->set_visible(!all_locked);
+ lock_button->set_disabled(selection.empty());
+ unlock_button->set_visible(all_locked);
+ group_button->set_visible(!all_group);
+ group_button->set_disabled(selection.empty());
+ ungroup_button->set_visible(all_group);
+
+ _update_scrollbars();
+
+ _draw_grid();
+ _draw_selection();
+ _draw_axis();
+ if (editor->get_edited_scene())
+ _draw_locks_and_groups(editor->get_edited_scene(), transform);
+
+ RID ci = viewport->get_canvas_item();
+ VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());
+
+ EditorPluginList *over_plugin_list = editor->get_editor_plugins_over();
+ if (!over_plugin_list->empty()) {
+ over_plugin_list->forward_draw_over_canvas(transform, viewport);
+ }
+ _draw_focus();
+ _draw_bones();
+}
+
void CanvasItemEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
EditorNode::get_singleton()->get_scene_root()->set_snap_controls_to_pixels(GLOBAL_GET("gui/common/snap_controls_to_pixels"));
@@ -2319,6 +2733,7 @@ void CanvasItemEditor::_notification(int p_what) {
if (pivot != se->prev_pivot || anchors[MARGIN_LEFT] != se->prev_anchors[MARGIN_LEFT] || anchors[MARGIN_RIGHT] != se->prev_anchors[MARGIN_RIGHT] || anchors[MARGIN_TOP] != se->prev_anchors[MARGIN_TOP] || anchors[MARGIN_BOTTOM] != se->prev_anchors[MARGIN_BOTTOM]) {
viewport->update();
+ viewport_base->update();
se->prev_pivot = pivot;
se->prev_anchors[MARGIN_LEFT] = anchors[MARGIN_LEFT];
se->prev_anchors[MARGIN_RIGHT] = anchors[MARGIN_RIGHT];
@@ -2367,6 +2782,9 @@ void CanvasItemEditor::_notification(int p_what) {
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"));
+ snap_button->set_icon(get_icon("Snap", "EditorIcons"));
+ snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
+ skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
pivot_button->set_icon(get_icon("EditPivot", "EditorIcons"));
select_handle = get_icon("EditorHandle", "EditorIcons");
@@ -2377,6 +2795,10 @@ void CanvasItemEditor::_notification(int p_what) {
ungroup_button->set_icon(get_icon("Ungroup", "EditorIcons"));
key_insert_button->set_icon(get_icon("Key", "EditorIcons"));
+ zoom_minus->set_icon(get_icon("ZoomLess", "EditorIcons"));
+ zoom_reset->set_icon(get_icon("ZoomReset", "EditorIcons"));
+ zoom_plus->set_icon(get_icon("ZoomMore", "EditorIcons"));
+
anchor_menu->set_icon(get_icon("Anchor", "EditorIcons"));
PopupMenu *p = anchor_menu->get_popup();
@@ -2411,6 +2833,9 @@ void CanvasItemEditor::_notification(int p_what) {
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"));
+ snap_button->set_icon(get_icon("Snap", "EditorIcons"));
+ snap_config_menu->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons"));
+ skeleton_menu->set_icon(get_icon("Bone", "EditorIcons"));
pan_button->set_icon(get_icon("ToolPan", "EditorIcons"));
pivot_button->set_icon(get_icon("EditPivot", "EditorIcons"));
select_handle = get_icon("EditorHandle", "EditorIcons");
@@ -2452,66 +2877,23 @@ void CanvasItemEditor::edit(CanvasItem *p_canvas_item) {
drag = DRAG_NONE;
+ // Clear the selection
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 = Object::cast_to<CanvasItem>(p_node);
-
- 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.position);
- 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.position));
- r_rect.expand_to(xform.xform(rect.position + Point2(rect.size.x, 0)));
- r_rect.expand_to(xform.xform(rect.position + Point2(0, rect.size.y)));
- r_rect.expand_to(xform.xform(rect.position + rect.size));
- }
+ viewport_base->update();
}
void CanvasItemEditor::_update_scrollbars() {
updating_scroll = true;
+ if (show_rulers)
+ viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH));
+ else
+ viewport_scrollable->set_begin(Point2());
+
Size2 size = viewport->get_size();
Size2 hmin = h_scroll->get_minimum_size();
Size2 vmin = v_scroll->get_minimum_size();
@@ -2528,11 +2910,12 @@ void CanvasItemEditor::_update_scrollbars() {
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());
+ if (editor->get_edited_scene()) {
+ _build_bones_list(editor->get_edited_scene());
+ _get_encompassing_rect(editor->get_edited_scene(), canvas_item_rect, Transform2D());
+ }
List<Map<ObjectID, BoneList>::Element *> bone_to_erase;
@@ -2555,7 +2938,6 @@ void CanvasItemEditor::_update_scrollbars() {
Point2 ofs;
if (canvas_item_rect.size.height <= (local_rect.size.y / zoom)) {
-
v_scroll->hide();
ofs.y = canvas_item_rect.position.y;
} else {
@@ -2616,6 +2998,7 @@ void CanvasItemEditor::_update_scroll(float) {
editor->get_scene_root()->set_global_canvas_transform(transform);
viewport->update();
+ viewport_base->update();
}
void CanvasItemEditor::_set_anchors_preset(Control::LayoutPreset p_preset) {
@@ -2644,7 +3027,7 @@ void CanvasItemEditor::_set_full_rect() {
Control *c = Object::cast_to<Control>(E->get());
- undo_redo->add_do_method(c, "set_anchors_preset", PRESET_WIDE);
+ undo_redo->add_do_method(c, "set_anchors_preset", Control::PRESET_WIDE);
undo_redo->add_do_method(c, "set_margin", MARGIN_LEFT, 0);
undo_redo->add_do_method(c, "set_margin", MARGIN_TOP, 0);
undo_redo->add_do_method(c, "set_margin", MARGIN_RIGHT, 0);
@@ -2662,88 +3045,118 @@ void CanvasItemEditor::_set_full_rect() {
undo_redo->commit_action();
}
+void CanvasItemEditor::_zoom_on_position(float p_zoom, Point2 p_position) {
+ if (p_zoom < MIN_ZOOM || p_zoom > MAX_ZOOM)
+ return;
+
+ float prev_zoom = zoom;
+ zoom = p_zoom;
+ Point2 ofs = p_position;
+ 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();
+ viewport_base->update();
+}
+
+void CanvasItemEditor::_zoom_minus() {
+ _zoom_on_position(zoom / 2.0, viewport_scrollable->get_size() / 2.0);
+}
+
+void CanvasItemEditor::_zoom_reset() {
+ _zoom_on_position(1.0, viewport_scrollable->get_size() / 2.0);
+}
+
+void CanvasItemEditor::_zoom_plus() {
+ _zoom_on_position(zoom * 2.0, viewport_scrollable->get_size() / 2.0);
+}
+
+void CanvasItemEditor::_toggle_snap(bool p_status) {
+ snap_active = p_status;
+ viewport->update();
+ viewport_base->update();
+}
+
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);
+ case SHOW_GRID: {
+ show_grid = !show_grid;
+ int idx = view_menu->get_popup()->get_item_index(SHOW_GRID);
+ view_menu->get_popup()->set_item_checked(idx, show_grid);
viewport->update();
+ viewport_base->update();
} 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();
+ case SNAP_USE_NODE_PARENT: {
+ snap_node_parent = !snap_node_parent;
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_PARENT);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_parent);
+ } break;
+ case SNAP_USE_NODE_ANCHORS: {
+ snap_node_anchors = !snap_node_anchors;
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_ANCHORS);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_anchors);
+ } break;
+ case SNAP_USE_NODE_SIDES: {
+ snap_node_sides = !snap_node_sides;
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_NODE_SIDES);
+ smartsnap_config_popup->set_item_checked(idx, snap_node_sides);
+ } break;
+ case SNAP_USE_OTHER_NODES: {
+ snap_other_nodes = !snap_other_nodes;
+ int idx = smartsnap_config_popup->get_item_index(SNAP_USE_OTHER_NODES);
+ smartsnap_config_popup->set_item_checked(idx, snap_other_nodes);
+ } break;
+ case SNAP_USE_GRID: {
+ snap_grid = !snap_grid;
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_GRID);
+ snap_config_menu->get_popup()->set_item_checked(idx, snap_grid);
} 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);
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_ROTATION);
+ snap_config_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);
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_RELATIVE);
+ snap_config_menu->get_popup()->set_item_checked(idx, snap_relative);
viewport->update();
+ viewport_base->update();
} 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);
+ int idx = snap_config_menu->get_popup()->get_item_index(SNAP_USE_PIXEL);
+ snap_config_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);
+ ((SnapDialog *)snap_dialog)->set_fields(grid_offset, grid_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);
+ int idx = skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES);
+ skeleton_menu->get_popup()->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);
+ case SHOW_HELPERS: {
+ show_helpers = !show_helpers;
+ int idx = view_menu->get_popup()->get_item_index(SHOW_HELPERS);
+ view_menu->get_popup()->set_item_checked(idx, show_helpers);
viewport->update();
- return;
} break;
- case ZOOM_OUT: {
- if (zoom < MIN_ZOOM)
- return;
-
- zoom = zoom * 0.5;
- _update_scroll(0);
+ case SHOW_RULERS: {
+ show_rulers = !show_rulers;
+ int idx = view_menu->get_popup()->get_item_index(SHOW_RULERS);
+ view_menu->get_popup()->set_item_checked(idx, show_rulers);
viewport->update();
- return;
-
+ viewport_base->update();
} 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();
@@ -2866,7 +3279,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
_set_anchors_preset(PRESET_HCENTER_WIDE);
} break;
case ANCHOR_ALIGN_WIDE: {
- _set_anchors_preset(PRESET_WIDE);
+ _set_anchors_preset(Control::PRESET_WIDE);
} break;
case ANCHOR_ALIGN_WIDE_FIT: {
_set_full_rect();
@@ -3090,7 +3503,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
n2d->set_meta("_edit_bone_", true);
if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+ skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES));
}
viewport->update();
@@ -3109,7 +3522,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
n2d->set_meta("_edit_bone_", Variant());
if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+ skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES));
}
viewport->update();
@@ -3129,7 +3542,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
canvas_item->set_meta("_edit_ik_", true);
if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+ skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES));
}
viewport->update();
@@ -3149,7 +3562,7 @@ void CanvasItemEditor::_popup_callback(int p_op) {
n2d->set_meta("_edit_ik_", Variant());
if (!skeleton_show_bones)
- skeleton_menu->activate_item(skeleton_menu->get_item_index(SKELETON_SHOW_BONES));
+ skeleton_menu->get_popup()->activate_item(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES));
}
viewport->update();
@@ -3212,15 +3625,19 @@ void CanvasItemEditor::_focus_selection(int p_op) {
void CanvasItemEditor::_bind_methods() {
+ ClassDB::bind_method("_zoom_minus", &CanvasItemEditor::_zoom_minus);
+ ClassDB::bind_method("_zoom_reset", &CanvasItemEditor::_zoom_reset);
+ ClassDB::bind_method("_zoom_plus", &CanvasItemEditor::_zoom_plus);
+ ClassDB::bind_method("_toggle_snap", &CanvasItemEditor::_toggle_snap);
ClassDB::bind_method("_update_scroll", &CanvasItemEditor::_update_scroll);
ClassDB::bind_method("_popup_callback", &CanvasItemEditor::_popup_callback);
- 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("_draw_viewport", &CanvasItemEditor::_draw_viewport);
+ ClassDB::bind_method("_draw_viewport_base", &CanvasItemEditor::_draw_viewport_base);
+ ClassDB::bind_method("_viewport_base_gui_input", &CanvasItemEditor::_viewport_base_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);
@@ -3259,67 +3676,96 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb = memnew(HBoxContainer);
add_child(hb);
- hb->set_area_as_parent_rect();
+ hb->set_anchors_and_margins_preset(Control::PRESET_WIDE);
bottom_split = memnew(VSplitContainer);
- bottom_split->set_v_size_flags(SIZE_EXPAND_FILL);
add_child(bottom_split);
+ bottom_split->set_v_size_flags(SIZE_EXPAND_FILL);
palette_split = memnew(HSplitContainer);
- palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
bottom_split->add_child(palette_split);
+ palette_split->set_v_size_flags(SIZE_EXPAND_FILL);
- 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_base = memnew(Control);
+ palette_split->add_child(viewport_base);
+ viewport_base->set_clip_contents(true);
+ viewport_base->connect("draw", this, "_draw_viewport_base");
+ viewport_base->connect("gui_input", this, "_viewport_base_gui_input");
+ viewport_base->set_focus_mode(FOCUS_ALL);
+ viewport_base->set_v_size_flags(SIZE_EXPAND_FILL);
+ viewport_base->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ viewport_scrollable = memnew(Control);
+ viewport_base->add_child(viewport_scrollable);
+ viewport_scrollable->set_mouse_filter(MOUSE_FILTER_PASS);
+ viewport_scrollable->set_draw_behind_parent(true);
+ viewport_scrollable->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ viewport_scrollable->set_begin(Point2(RULER_WIDTH, RULER_WIDTH));
+
+ ViewportContainer *scene_tree = memnew(ViewportContainer);
+ viewport_scrollable->add_child(scene_tree);
+ scene_tree->set_stretch(true);
+ scene_tree->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ scene_tree->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_scrollable->add_child(viewport);
+ viewport->set_mouse_filter(MOUSE_FILTER_PASS);
+ viewport->set_anchors_and_margins_preset(Control::PRESET_WIDE);
viewport->set_clip_contents(true);
+ viewport->connect("draw", this, "_draw_viewport");
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 = memnew(VScrollBar);
+ viewport->add_child(v_scroll);
+ v_scroll->connect("value_changed", this, "_update_scroll", Vector<Variant>(), Object::CONNECT_DEFERRED);
v_scroll->hide();
+
+ HBoxContainer *zoom_hb = memnew(HBoxContainer);
+ viewport->add_child(zoom_hb);
+ zoom_hb->set_begin(Point2(5, 5));
+
+ zoom_minus = memnew(ToolButton);
+ zoom_hb->add_child(zoom_minus);
+ zoom_minus->connect("pressed", this, "_zoom_minus");
+ zoom_minus->set_focus_mode(FOCUS_NONE);
+
+ zoom_reset = memnew(ToolButton);
+ zoom_hb->add_child(zoom_reset);
+ zoom_reset->connect("pressed", this, "_zoom_reset");
+ zoom_reset->set_focus_mode(FOCUS_NONE);
+
+ zoom_plus = memnew(ToolButton);
+ zoom_hb->add_child(zoom_plus);
+ zoom_plus->connect("pressed", this, "_zoom_plus");
+ zoom_plus->set_focus_mode(FOCUS_NONE);
+
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->set_toggle_mode(true);
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->set_toggle_mode(true);
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->set_toggle_mode(true);
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"));
@@ -3327,25 +3773,59 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
hb->add_child(memnew(VSeparator));
list_select_button = memnew(ToolButton);
- list_select_button->set_toggle_mode(true);
hb->add_child(list_select_button);
+ list_select_button->set_toggle_mode(true);
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->set_toggle_mode(true);
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->set_toggle_mode(true);
pan_button->connect("pressed", this, "_tool_select", make_binds(TOOL_PAN));
pan_button->set_tooltip(TTR("Pan Mode"));
hb->add_child(memnew(VSeparator));
+ snap_button = memnew(ToolButton);
+ hb->add_child(snap_button);
+ snap_button->set_toggle_mode(true);
+ snap_button->connect("toggled", this, "_toggle_snap");
+ snap_button->set_tooltip(TTR("Toggles snapping"));
+ snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_snap", TTR("Use Snap"), KEY_S));
+
+ snap_config_menu = memnew(MenuButton);
+ hb->add_child(snap_config_menu);
+ snap_config_menu->set_h_size_flags(SIZE_SHRINK_END);
+ snap_config_menu->set_tooltip(TTR("Snapping options"));
+
+ PopupMenu *p = snap_config_menu->get_popup();
+ p->connect("id_pressed", this, "_popup_callback");
+ p->set_hide_on_checkable_item_selection(false);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_grid", TTR("Snap to grid")), SNAP_USE_GRID);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_rotation_snap", TTR("Use Rotation Snap")), SNAP_USE_ROTATION);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/configure_snap", TTR("Configure Snap...")), SNAP_CONFIGURE);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_relative", TTR("Snap Relative")), SNAP_RELATIVE);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
+ p->add_submenu_item(TTR("Smart snapping"), "SmartSnapping");
+
+ smartsnap_config_popup = memnew(PopupMenu);
+ p->add_child(smartsnap_config_popup);
+ smartsnap_config_popup->set_name("SmartSnapping");
+ smartsnap_config_popup->connect("id_pressed", this, "_popup_callback");
+ smartsnap_config_popup->set_hide_on_checkable_item_selection(false);
+ smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_parent", TTR("Snap to parent")), SNAP_USE_NODE_PARENT);
+ smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_anchors", TTR("Snap to node anchor")), SNAP_USE_NODE_ANCHORS);
+ smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_node_sides", TTR("Snap to node sides")), SNAP_USE_NODE_SIDES);
+ smartsnap_config_popup->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/snap_other_nodes", TTR("Snap to other nodes")), SNAP_USE_OTHER_NODES);
+
+ hb->add_child(memnew(VSeparator));
+
lock_button = memnew(ToolButton);
hb->add_child(lock_button);
@@ -3369,35 +3849,22 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
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");
+ skeleton_menu = memnew(MenuButton);
+ hb->add_child(skeleton_menu);
- PopupMenu *p;
- p = edit_menu->get_popup();
+ p = skeleton_menu->get_popup();
p->set_hide_on_checkable_item_selection(false);
- 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_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_make_bones", TTR("Make Bones"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B), SKELETON_MAKE_BONES);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_bones", TTR("Clear Bones")), SKELETON_CLEAR_BONES);
p->add_separator();
- p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/use_pixel_snap", TTR("Use Pixel Snap")), SNAP_USE_PIXEL);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_show_bones", TTR("Show Bones")), SKELETON_SHOW_BONES);
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->set_hide_on_checkable_item_selection(false);
- skeleton_menu->connect("id_pressed", this, "_popup_callback");
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_set_ik_chain", TTR("Make IK Chain")), SKELETON_SET_IK_CHAIN);
+ p->add_shortcut(ED_SHORTCUT("canvas_item_editor/skeleton_clear_ik_chain", TTR("Clear IK Chain")), SKELETON_CLEAR_IK_CHAIN);
+ p->set_hide_on_checkable_item_selection(false);
+ p->connect("id_pressed", this, "_popup_callback");
+
+ hb->add_child(memnew(VSeparator));
view_menu = memnew(MenuButton);
view_menu->set_text(TTR("View"));
@@ -3405,11 +3872,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
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_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid"), KEY_G), SHOW_GRID);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show helpers"), KEY_H), SHOW_HELPERS);
+ p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show rulers"), KEY_R), SHOW_RULERS);
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);
@@ -3480,23 +3945,6 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
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_position(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);
@@ -3505,22 +3953,35 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) {
selection_menu->connect("id_pressed", this, "_selection_result_pressed");
selection_menu->connect("popup_hide", this, "_selection_menu_hide");
+ drag_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/drag_pivot", TTR("Drag pivot from mouse position"), KEY_MASK_SHIFT | KEY_V);
+ set_pivot_shortcut = ED_SHORTCUT("canvas_item_editor/set_pivot", TTR("Set pivot at mouse position"), KEY_V);
+
+ multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY);
+ divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE);
+
key_pos = true;
key_rot = true;
key_scale = false;
+ show_grid = false;
+ show_helpers = false;
+ show_rulers = false;
zoom = 1;
- snap_offset = Vector2(0, 0);
- snap_step = Vector2(10, 10);
+ grid_offset = Point2();
+ grid_step = Point2(10, 10);
+ grid_step_multiplier = 0;
snap_rotation_offset = 0;
snap_rotation_step = 15 / (180 / Math_PI);
- snap_grid = false;
- snap_show_grid = false;
+ snap_active = false;
+ snap_node_parent = true;
+ snap_node_anchors = true;
+ snap_node_sides = true;
+ snap_other_nodes = true;
+ snap_grid = true;
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;
+ skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true);
box_selecting = false;
//zoom=0.5;
singleton = this;
@@ -3549,14 +4010,14 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
canvas_item_editor->show();
- canvas_item_editor->set_fixed_process(true);
+ canvas_item_editor->set_physics_process(true);
VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false);
- canvas_item_editor->viewport->grab_focus();
+ canvas_item_editor->viewport_base->grab_focus();
} else {
canvas_item_editor->hide();
- canvas_item_editor->set_fixed_process(false);
+ canvas_item_editor->set_physics_process(false);
VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), true);
}
}
@@ -3576,7 +4037,7 @@ CanvasItemEditorPlugin::CanvasItemEditorPlugin(EditorNode *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->set_anchors_and_margins_preset(Control::PRESET_WIDE);
canvas_item_editor->hide();
}
@@ -3698,7 +4159,7 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
editor_data->get_undo_redo().add_do_property(child, property, texture);
// make visible for certain node type
- if (default_type == "Patch9Rect") {
+ if (default_type == "NinePatchRect") {
editor_data->get_undo_redo().add_do_property(child, "rect/size", texture_size);
} else if (default_type == "Polygon2D") {
PoolVector<Vector2> list;
@@ -3715,13 +4176,13 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &
pos = parent->call("get_global_position");
}
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;
+ Point2 target_position = (p_point - trans.get_origin()) / trans.get_scale().x - pos;
+ if (default_type == "Polygon2D" || default_type == "TouchScreenButton" || default_type == "TextureRect" || default_type == "NinePatchRect") {
+ target_position -= texture_size / 2;
}
// there's nothing to be used as source position so snapping will work as absolute if enabled
- target_pos = canvas->snap_point(target_pos, Vector2());
- editor_data->get_undo_redo().add_do_method(child, "set_position", target_pos);
+ target_position = canvas->snap_point(target_position);
+ editor_data->get_undo_redo().add_do_method(child, "set_position", target_position);
}
bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
@@ -3754,22 +4215,13 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons
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 = Object::cast_to<Node2D>(parent);
- if (parent_node2d) {
- pos = parent_node2d->get_global_position();
- } else {
- Control *parent_control = Object::cast_to<Control>(parent);
- if (parent_control) {
- pos = parent_control->get_global_position();
- }
+ CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent);
+ if (parent_ci) {
+ Vector2 target_pos = canvas->get_canvas_transform().affine_inverse().xform(p_point);
+ target_pos = canvas->snap_point(target_pos);
+ target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos);
+ editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos);
}
- Transform2D trans = canvas->get_canvas_transform();
- Vector2 target_pos = (p_point - trans.get_origin()) / trans.get_scale().x - pos;
- // in relative snapping it may be useful for the user to take the original node position into account
- Vector2 start_pos = Object::cast_to<Node2D>(instanced_scene) ? Object::cast_to<Node2D>(instanced_scene)->get_position() : target_pos;
- target_pos = canvas->snap_point(target_pos, start_pos);
- editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos);
return true;
}
@@ -3801,7 +4253,7 @@ void CanvasItemEditorViewport::_perform_drop_data() {
child = memnew(TouchScreenButton);
else if (default_type == "TextureRect")
child = memnew(TextureRect);
- else if (default_type == "Patch9Rect")
+ else if (default_type == "NinePatchRect")
child = memnew(NinePatchRect);
else
child = memnew(Sprite); // default
@@ -3848,6 +4300,20 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian
continue;
}
memdelete(instanced_scene);
+ } else if (type == "Texture" ||
+ type == "ImageTexture" ||
+ type == "ViewportTexture" ||
+ type == "CurveTexture" ||
+ type == "GradientTexture" ||
+ type == "StreamTexture" ||
+ type == "AtlasTexture" ||
+ type == "LargeTexture") {
+ Ref<Texture> texture = ResourceLoader::load(files[i]);
+ if (texture.is_valid() == false) {
+ continue;
+ }
+ } else {
+ continue;
}
can_instance = true;
break;
@@ -3949,48 +4415,46 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte
types.push_back("TouchScreenButton");
// Control
types.push_back("TextureRect");
- types.push_back("Patch9Rect");
+ types.push_back("NinePatchRect");
target_node = NULL;
editor = p_node;
editor_data = editor->get_scene_tree_dock()->get_editor_data();
canvas = p_canvas;
preview_node = memnew(Node2D);
+
accept = memnew(AcceptDialog);
editor->get_gui_base()->add_child(accept);
selector = memnew(AcceptDialog);
+ editor->get_gui_base()->add_child(selector);
selector->set_title(TTR("Change default type"));
+ selector->connect("confirmed", this, "_on_change_type");
VBoxContainer *vbc = memnew(VBoxContainer);
+ selector->add_child(vbc);
vbc->set_h_size_flags(SIZE_EXPAND_FILL);
vbc->set_v_size_flags(SIZE_EXPAND_FILL);
vbc->set_custom_minimum_size(Size2(200, 260) * EDSCALE);
selector_label = memnew(Label);
+ vbc->add_child(selector_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);
+ vbc->add_child(btn_group);
btn_group->set_h_size_flags(0);
+ button_group.instance();
for (int i = 0; i < types.size(); i++) {
CheckBox *check = memnew(CheckBox);
+ btn_group->add_child(check);
check->set_text(types[i]);
check->connect("button_down", this, "_on_select_type", varray(check));
- btn_group->add_child(check);
check->set_button_group(button_group);
}
- vbc->add_child(btn_group);
-
- selector->connect("confirmed", this, "_on_change_type");
-
- selector->add_child(vbc);
- editor->get_gui_base()->add_child(selector);
label = memnew(Label);
label->add_color_override("font_color_shadow", Color(0, 0, 0, 1));
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 2e1a2eac5f..bb4e584f2a 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -58,6 +58,8 @@ public:
Vector2 prev_pivot;
float prev_anchors[4];
+ Transform2D pre_drag_xform;
+
CanvasItemEditorSelectedItem() { prev_rot = 0; }
};
@@ -68,7 +70,6 @@ class CanvasItemEditor : public VBoxContainer {
EditorNode *editor;
enum Tool {
-
TOOL_SELECT,
TOOL_LIST_SELECT,
TOOL_MOVE,
@@ -80,15 +81,18 @@ class CanvasItemEditor : public VBoxContainer {
enum MenuOption {
SNAP_USE,
- SNAP_SHOW_GRID,
+ SNAP_USE_NODE_PARENT,
+ SNAP_USE_NODE_ANCHORS,
+ SNAP_USE_NODE_SIDES,
+ SNAP_USE_OTHER_NODES,
+ SNAP_USE_GRID,
SNAP_USE_ROTATION,
SNAP_RELATIVE,
SNAP_CONFIGURE,
SNAP_USE_PIXEL,
- ZOOM_IN,
- ZOOM_OUT,
- ZOOM_RESET,
- ZOOM_SET,
+ SHOW_GRID,
+ SHOW_HELPERS,
+ SHOW_RULERS,
LOCK_SELECTED,
UNLOCK_SELECTED,
GROUP_SELECTED,
@@ -161,6 +165,8 @@ class CanvasItemEditor : public VBoxContainer {
Tool tool;
bool first_update;
Control *viewport;
+ Control *viewport_base;
+ Control *viewport_scrollable;
bool can_move_pivot;
@@ -168,14 +174,28 @@ class CanvasItemEditor : public VBoxContainer {
VScrollBar *v_scroll;
HBoxContainer *hb;
+ ToolButton *zoom_minus;
+ ToolButton *zoom_reset;
+ ToolButton *zoom_plus;
+
Transform2D transform;
+ bool show_grid;
+ bool show_rulers;
+ bool show_helpers;
float zoom;
- Vector2 snap_offset;
- Vector2 snap_step;
+
+ Point2 grid_offset;
+ Point2 grid_step;
+ int grid_step_multiplier;
+
float snap_rotation_step;
float snap_rotation_offset;
+ bool snap_active;
+ bool snap_node_parent;
+ bool snap_node_anchors;
+ bool snap_node_sides;
+ bool snap_other_nodes;
bool snap_grid;
- bool snap_show_grid;
bool snap_rotation;
bool snap_relative;
bool snap_pixel;
@@ -202,18 +222,6 @@ class CanvasItemEditor : public VBoxContainer {
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;
@@ -253,6 +261,10 @@ class CanvasItemEditor : public VBoxContainer {
ToolButton *move_button;
ToolButton *rotate_button;
+ ToolButton *snap_button;
+ MenuButton *snap_config_menu;
+ PopupMenu *smartsnap_config_popup;
+
ToolButton *pivot_button;
ToolButton *pan_button;
@@ -262,8 +274,7 @@ class CanvasItemEditor : public VBoxContainer {
ToolButton *group_button;
ToolButton *ungroup_button;
- MenuButton *edit_menu;
- PopupMenu *skeleton_menu;
+ MenuButton *skeleton_menu;
MenuButton *view_menu;
HBoxContainer *animation_hb;
MenuButton *animation_menu;
@@ -276,6 +287,9 @@ class CanvasItemEditor : public VBoxContainer {
PopupMenu *selection_menu;
+ Control *top_ruler;
+ Control *left_ruler;
+
//PopupMenu *popup;
DragType drag;
Point2 drag_from;
@@ -288,6 +302,11 @@ class CanvasItemEditor : public VBoxContainer {
Ref<Texture> select_handle;
Ref<Texture> anchor_handle;
+ Ref<ShortCut> drag_pivot_shortcut;
+ Ref<ShortCut> set_pivot_shortcut;
+ Ref<ShortCut> multiply_grid_step_shortcut;
+ Ref<ShortCut> divide_grid_step_shortcut;
+
int handle_len;
bool _is_part_of_subscene(CanvasItem *p_item);
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, int limit = 0);
@@ -298,10 +317,6 @@ class CanvasItemEditor : public VBoxContainer {
ConfirmationDialog *snap_dialog;
- AcceptDialog *value_dialog;
- Label *dialog_label;
- SpinBox *dialog_val;
-
CanvasItem *ref_item;
void _edit_set_pivot(const Vector2 &mouse_pos);
@@ -315,9 +330,8 @@ class CanvasItemEditor : public VBoxContainer {
void _prepare_drag(const Point2 &p_click_pos);
DragType _get_anchor_handle_drag_type(const Point2 &p_click, Vector2 &r_point);
- float _anchor_snap(float anchor, bool *snapped = NULL, float p_opposite_anchor = -1);
- Vector2 _anchor_to_position(Control *p_control, Vector2 anchor);
- Vector2 _position_to_anchor(Control *p_control, Vector2 position);
+ Vector2 _anchor_to_position(const Control *p_control, Vector2 anchor);
+ Vector2 _position_to_anchor(const Control *p_control, Vector2 position);
void _popup_callback(int p_op);
bool updating_scroll;
@@ -328,7 +342,6 @@ class CanvasItemEditor : public VBoxContainer {
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();
@@ -337,26 +350,50 @@ class CanvasItemEditor : public VBoxContainer {
Point2 _find_topleftmost_point();
- void _find_canvas_items_span(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform);
+ void _build_bones_list(Node *p_node);
+
+ void _get_encompassing_rect(Node *p_node, Rect2 &r_rect, const Transform2D &p_xform);
Object *_get_editor_data(Object *p_what);
- CanvasItem *get_single_item();
+ CanvasItem *_get_single_item();
int get_item_count();
void _keying_changed();
void _unhandled_key_input(const Ref<InputEvent> &p_ev);
+ void _draw_text_at_position(Point2 p_position, String p_string, Margin p_side);
+ void _draw_margin_at_position(int p_value, Point2 p_position, Margin p_side);
void _draw_percentage_at_position(float p_value, Point2 p_position, Margin p_side);
- void _viewport_gui_input(const Ref<InputEvent> &p_event);
- void _viewport_draw();
+ void _draw_rulers();
+ void _draw_focus();
+ void _draw_grid();
+ void _draw_selection();
+ void _draw_axis();
+ void _draw_bones();
+ void _draw_locks_and_groups(Node *p_node, const Transform2D &p_xform);
+
+ void _draw_viewport();
+
+ void _viewport_base_gui_input(const Ref<InputEvent> &p_event);
+ void _draw_viewport_base();
void _focus_selection(int p_op);
+ void _snap_if_closer(Point2 p_value, Point2 p_target_snap, Point2 &r_current_snap, bool (&r_snapped)[2], real_t rotation = 0.0, float p_radius = 10.0);
+ void _snap_other_nodes(Point2 p_value, Point2 &r_current_snap, bool (&r_snapped)[2], const Node *p_current, const CanvasItem *p_to_snap);
+
void _set_anchors_preset(Control::LayoutPreset p_preset);
void _set_full_rect();
+ void _zoom_on_position(float p_zoom, Point2 p_position = Point2());
+ void _zoom_minus();
+ void _zoom_reset();
+ void _zoom_plus();
+
+ void _toggle_snap(bool p_status);
+
HSplitContainer *palette_split;
VSplitContainer *bottom_split;
@@ -400,7 +437,18 @@ protected:
static CanvasItemEditor *singleton;
public:
- Vector2 snap_point(Vector2 p_target, Vector2 p_start = Vector2(0, 0)) const;
+ enum SnapMode {
+ SNAP_GRID = 1 << 0,
+ SNAP_PIXEL = 1 << 1,
+ SNAP_NODE_PARENT = 1 << 2,
+ SNAP_NODE_ANCHORS = 1 << 3,
+ SNAP_NODE_SIDES = 1 << 4,
+ SNAP_OTHER_NODES = 1 << 5,
+
+ SNAP_DEFAULT = 0x03,
+ };
+
+ Point2 snap_point(Point2 p_target, unsigned int p_modes = SNAP_DEFAULT, const CanvasItem *p_canvas_item = NULL, unsigned int p_forced_modes = 0);
float snap_angle(float p_target, float p_start = 0) const;
Transform2D get_canvas_transform() const { return transform; }
diff --git a/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
index 38f95d8278..4501136e19 100644
--- a/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -45,7 +45,7 @@ void CollisionPolygon2DEditor::_notification(int p_what) {
get_tree()->connect("node_removed", this, "_node_removed");
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
} break;
}
diff --git a/editor/plugins/cube_grid_theme_editor_plugin.cpp b/editor/plugins/cube_grid_theme_editor_plugin.cpp
index 1c17daf425..2b31f192b3 100644
--- a/editor/plugins/cube_grid_theme_editor_plugin.cpp
+++ b/editor/plugins/cube_grid_theme_editor_plugin.cpp
@@ -241,7 +241,7 @@ MeshLibraryEditor::MeshLibraryEditor(EditorNode *p_editor) {
file->connect("file_selected", this, "_import_scene_cbk");
Panel *panel = memnew(Panel);
- panel->set_area_as_parent_rect();
+ panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
add_child(panel);
MenuButton *options = memnew(MenuButton);
panel->add_child(options);
@@ -289,7 +289,7 @@ MeshLibraryEditorPlugin::MeshLibraryEditorPlugin(EditorNode *p_node) {
theme_editor = memnew(MeshLibraryEditor(p_node));
p_node->get_viewport()->add_child(theme_editor);
- theme_editor->set_area_as_parent_rect();
+ theme_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
theme_editor->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_BEGIN);
theme_editor->set_end(Point2(0, 22));
theme_editor->hide();
diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp
index 615cf85aa4..2754aeed06 100644
--- a/editor/plugins/curve_editor_plugin.cpp
+++ b/editor/plugins/curve_editor_plugin.cpp
@@ -53,12 +53,12 @@ CurveEditor::CurveEditor() {
_presets_menu = memnew(PopupMenu);
_presets_menu->set_name("_presets_menu");
- _presets_menu->add_item("Flat0", PRESET_FLAT0);
- _presets_menu->add_item("Flat1", PRESET_FLAT1);
- _presets_menu->add_item("Linear", PRESET_LINEAR);
- _presets_menu->add_item("Ease in", PRESET_EASE_IN);
- _presets_menu->add_item("Ease out", PRESET_EASE_OUT);
- _presets_menu->add_item("Smoothstep", PRESET_SMOOTHSTEP);
+ _presets_menu->add_item(TTR("Flat0"), PRESET_FLAT0);
+ _presets_menu->add_item(TTR("Flat1"), PRESET_FLAT1);
+ _presets_menu->add_item(TTR("Linear"), PRESET_LINEAR);
+ _presets_menu->add_item(TTR("Ease in"), PRESET_EASE_IN);
+ _presets_menu->add_item(TTR("Ease out"), PRESET_EASE_OUT);
+ _presets_menu->add_item(TTR("Smoothstep"), PRESET_SMOOTHSTEP);
_presets_menu->connect("id_pressed", this, "_on_preset_item_selected");
_context_menu->add_child(_presets_menu);
}
@@ -188,7 +188,7 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) {
} else {
// Drag tangent
- Vector2 point_pos = curve.get_point_pos(_selected_point);
+ Vector2 point_pos = curve.get_point_position(_selected_point);
Vector2 control_pos = get_world_pos(mpos);
Vector2 dir = (control_pos - point_pos).normalized();
@@ -344,19 +344,19 @@ void CurveEditor::open_context_menu(Vector2 pos) {
_curve_ref->get_point_left_mode(_selected_point) == Curve::TANGENT_LINEAR :
_curve_ref->get_point_right_mode(_selected_point) == Curve::TANGENT_LINEAR;
- _context_menu->set_item_checked(CONTEXT_LINEAR, is_linear);
+ _context_menu->set_item_checked(_context_menu->get_item_index(CONTEXT_LINEAR), is_linear);
} else {
_context_menu->add_separator();
if (_selected_point > 0) {
_context_menu->add_check_item(TTR("Left linear"), CONTEXT_LEFT_LINEAR);
- _context_menu->set_item_checked(CONTEXT_LEFT_LINEAR,
+ _context_menu->set_item_checked(_context_menu->get_item_index(CONTEXT_LEFT_LINEAR),
_curve_ref->get_point_left_mode(_selected_point) == Curve::TANGENT_LINEAR);
}
if (_selected_point + 1 < _curve_ref->get_point_count()) {
_context_menu->add_check_item(TTR("Right linear"), CONTEXT_RIGHT_LINEAR);
- _context_menu->set_item_checked(CONTEXT_RIGHT_LINEAR,
+ _context_menu->set_item_checked(_context_menu->get_item_index(CONTEXT_RIGHT_LINEAR),
_curve_ref->get_point_right_mode(_selected_point) == Curve::TANGENT_LINEAR);
}
}
@@ -378,7 +378,7 @@ int CurveEditor::get_point_at(Vector2 pos) const {
const float r = _hover_radius * _hover_radius;
for (int i = 0; i < curve.get_point_count(); ++i) {
- Vector2 p = get_view_pos(curve.get_point_pos(i));
+ Vector2 p = get_view_pos(curve.get_point_position(i));
if (p.distance_squared_to(pos) <= r) {
return i;
}
@@ -525,8 +525,8 @@ Vector2 CurveEditor::get_tangent_view_pos(int i, TangentIndex tangent) const {
else
dir = Vector2(1, _curve_ref->get_point_right_tangent(i));
- Vector2 point_pos = get_view_pos(_curve_ref->get_point_pos(i));
- Vector2 control_pos = get_view_pos(_curve_ref->get_point_pos(i) + dir);
+ Vector2 point_pos = get_view_pos(_curve_ref->get_point_position(i));
+ Vector2 control_pos = get_view_pos(_curve_ref->get_point_position(i) + dir);
return point_pos + _tangents_length * (control_pos - point_pos).normalized();
}
@@ -549,8 +549,8 @@ static void plot_curve_accurate(const Curve &curve, float step, T plot_func) {
plot_func(Vector2(0, y), Vector2(1.f, y), true);
} else {
- Vector2 first_point = curve.get_point_pos(0);
- Vector2 last_point = curve.get_point_pos(curve.get_point_count() - 1);
+ Vector2 first_point = curve.get_point_position(0);
+ Vector2 last_point = curve.get_point_position(curve.get_point_count() - 1);
// Edge lines
plot_func(Vector2(0, first_point.y), first_point, false);
@@ -559,8 +559,8 @@ static void plot_curve_accurate(const Curve &curve, float step, T plot_func) {
// Draw section by section, so that we get maximum precision near points.
// It's an accurate representation, but slower than using the baked one.
for (int i = 1; i < curve.get_point_count(); ++i) {
- Vector2 a = curve.get_point_pos(i - 1);
- Vector2 b = curve.get_point_pos(i);
+ Vector2 a = curve.get_point_position(i - 1);
+ Vector2 b = curve.get_point_position(i);
Vector2 pos = a;
Vector2 prev_pos = a;
@@ -613,8 +613,8 @@ void CurveEditor::_draw() {
Vector2 min_edge = get_world_pos(Vector2(0, view_size.y));
Vector2 max_edge = get_world_pos(Vector2(view_size.x, 0));
- const Color grid_color0(0, 0, 0, 0.5);
- const Color grid_color1(0, 0, 0, 0.15);
+ const Color grid_color0 = get_color("grid_major_color", "Editor");
+ const Color grid_color1 = get_color("grid_minor_color", "Editor");
draw_line(Vector2(min_edge.x, curve.get_min_value()), Vector2(max_edge.x, curve.get_min_value()), grid_color0);
draw_line(Vector2(max_edge.x, curve.get_max_value()), Vector2(min_edge.x, curve.get_max_value()), grid_color0);
draw_line(Vector2(0, min_edge.y), Vector2(0, max_edge.y), grid_color0);
@@ -636,7 +636,7 @@ void CurveEditor::_draw() {
Ref<Font> font = get_font("font", "Label");
float font_height = font->get_height();
- const Color text_color(1, 1, 1, 0.3);
+ const Color text_color = get_color("font_color", "Editor");
{
// X axis
@@ -664,10 +664,10 @@ void CurveEditor::_draw() {
if (_selected_point >= 0) {
- const Color tangent_color(0.5, 0.5, 1, 1);
+ const Color tangent_color = get_color("accent_color", "Editor");
int i = _selected_point;
- Vector2 pos = curve.get_point_pos(i);
+ Vector2 pos = curve.get_point_position(i);
if (i != 0) {
Vector2 control_pos = get_tangent_view_pos(i, TANGENT_LEFT);
@@ -686,8 +686,8 @@ void CurveEditor::_draw() {
draw_set_transform_matrix(_world_to_view);
- const Color line_color(1, 1, 1, 0.85);
- const Color edge_line_color(1, 1, 1, 0.4);
+ const Color line_color = get_color("highlight_color", "Editor");
+ const Color edge_line_color = get_color("font_color", "Editor");
CanvasItemPlotCurve plot_func(*this, line_color, edge_line_color);
plot_curve_accurate(curve, 4.f / view_size.x, plot_func);
@@ -714,11 +714,11 @@ void CurveEditor::_draw() {
draw_set_transform_matrix(Transform2D());
- const Color point_color(1, 1, 1);
- const Color selected_point_color(1, 0.5, 0.5);
+ const Color point_color = get_color("font_color", "Editor");
+ const Color selected_point_color = get_color("accent_color", "Editor");
for (int i = 0; i < curve.get_point_count(); ++i) {
- Vector2 pos = curve.get_point_pos(i);
+ Vector2 pos = curve.get_point_position(i);
draw_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(3), i == _selected_point ? selected_point_color : point_color);
// TODO Circles are prettier. Needs a fix! Or a texture
//draw_circle(pos, 2, point_color);
@@ -728,7 +728,7 @@ void CurveEditor::_draw() {
if (_hover_point != -1) {
const Color hover_color = line_color;
- Vector2 pos = curve.get_point_pos(_hover_point);
+ Vector2 pos = curve.get_point_position(_hover_point);
stroke_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(_hover_radius), hover_color);
}
diff --git a/editor/plugins/light_occluder_2d_editor_plugin.cpp b/editor/plugins/light_occluder_2d_editor_plugin.cpp
index e6b921c539..ed0bc60d2f 100644
--- a/editor/plugins/light_occluder_2d_editor_plugin.cpp
+++ b/editor/plugins/light_occluder_2d_editor_plugin.cpp
@@ -46,7 +46,7 @@ void LightOccluder2DEditor::_notification(int p_what) {
create_poly->connect("confirmed", this, "_create_poly");
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
} break;
}
diff --git a/editor/plugins/line_2d_editor_plugin.cpp b/editor/plugins/line_2d_editor_plugin.cpp
index 84620a75a5..ef3ee6a78f 100644
--- a/editor/plugins/line_2d_editor_plugin.cpp
+++ b/editor/plugins/line_2d_editor_plugin.cpp
@@ -66,7 +66,7 @@ int Line2DEditor::get_point_index_at(Vector2 gpos) {
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));
+ Point2 p = xform.xform(node->get_point_position(i));
if (gpos.distance_to(p) < grab_threshold) {
return i;
}
@@ -96,12 +96,12 @@ bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (mb->get_button_index() == BUTTON_LEFT && !mb->get_shift() && mode == MODE_EDIT) {
_dragging = true;
action_point = i;
- moving_from = node->get_point_pos(i);
+ moving_from = node->get_point_position(i);
moving_screen_from = gpoint;
} else if ((mb->get_button_index() == BUTTON_RIGHT && mode == MODE_EDIT) || (mb->get_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_undo_method(node, "add_point", node->get_point_position(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();
@@ -121,7 +121,7 @@ bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
_dragging = true;
action_point = node->get_point_count() - 1;
- moving_from = node->get_point_pos(action_point);
+ moving_from = node->get_point_position(action_point);
moving_screen_from = gpoint;
canvas_item_editor->get_viewport_control()->update();
@@ -131,8 +131,8 @@ bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (!mb->is_pressed() && mb->get_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(node, "set_point_position", action_point, cpoint);
+ undo_redo->add_undo_method(node, "set_point_position", 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();
@@ -147,7 +147,7 @@ bool Line2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
if (_dragging) {
Vector2 cpoint = mouse_to_local_pos(mm->get_position(), mm->get_alt());
- node->set_point_pos(action_point, cpoint);
+ node->set_point_position(action_point, cpoint);
canvas_item_editor->get_viewport_control()->update();
return true;
}
@@ -172,7 +172,7 @@ void Line2DEditor::_canvas_draw() {
Control *vpc = canvas_item_editor->get_viewport_control();
for (int i = 0; i < len; ++i) {
- Vector2 point = xform.xform(node->get_point_pos(i));
+ Vector2 point = xform.xform(node->get_point_position(i));
vpc->draw_texture_rect(handle, Rect2(point - handle_size * 0.5, handle_size), false);
}
}
diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp
index d2767bf1b2..6b613c1bcc 100644
--- a/editor/plugins/material_editor_plugin.cpp
+++ b/editor/plugins/material_editor_plugin.cpp
@@ -30,9 +30,11 @@
// FIXME: Disabled as (according to reduz) users were complaining that it gets in the way
// Waiting for PropertyEditor rewrite (planned for 3.1) to be refactored.
-#if 0
+
#include "material_editor_plugin.h"
+#if 0
+
#include "scene/main/viewport.h"
void MaterialEditor::_gui_input(InputEvent p_event) {
@@ -42,7 +44,7 @@ void MaterialEditor::_gui_input(InputEvent p_event) {
void MaterialEditor::_notification(int p_what) {
- if (p_what==NOTIFICATION_FIXED_PROCESS) {
+ if (p_what==NOTIFICATION_PHYSICS_PROCESS) {
}
@@ -335,7 +337,7 @@ MaterialEditor::MaterialEditor() {
HBoxContainer *hb = memnew( HBoxContainer );
add_child(hb);
- hb->set_area_as_parent_rect(2);
+ hb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2);
VBoxContainer *vb_shape = memnew( VBoxContainer );
hb->add_child(vb_shape);
@@ -416,3 +418,41 @@ MaterialEditorPlugin::~MaterialEditorPlugin()
}
#endif
+
+String SpatialMaterialConversionPlugin::converts_to() const {
+
+ return "ShaderMaterial";
+}
+bool SpatialMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const {
+
+ Ref<SpatialMaterial> mat = p_resource;
+ return mat.is_valid();
+}
+Ref<Resource> SpatialMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) {
+
+ Ref<SpatialMaterial> mat = p_resource;
+ ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>());
+
+ Ref<ShaderMaterial> smat;
+ smat.instance();
+
+ Ref<Shader> shader;
+ shader.instance();
+
+ String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid());
+
+ shader->set_code(code);
+
+ smat->set_shader(shader);
+
+ List<PropertyInfo> params;
+ VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), &params);
+
+ for (List<PropertyInfo>::Element *E = params.front(); E; E = E->next()) {
+ Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name);
+ smat->set_shader_param(E->get().name, value);
+ }
+
+ smat->set_render_priority(mat->get_render_priority());
+ return smat;
+}
diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h
index 10d7997a52..af9602f944 100644
--- a/editor/plugins/material_editor_plugin.h
+++ b/editor/plugins/material_editor_plugin.h
@@ -30,6 +30,7 @@
#ifndef MATERIAL_EDITOR_PLUGIN_H
#define MATERIAL_EDITOR_PLUGIN_H
+#include "editor/property_editor.h"
// FIXME: Disabled as (according to reduz) users were complaining that it gets in the way
// Waiting for PropertyEditor rewrite (planned for 3.1) to be refactored.
#if 0
@@ -101,4 +102,13 @@ public:
};
#endif
+
+class SpatialMaterialConversionPlugin : public EditorResourceConversionPlugin {
+ GDCLASS(SpatialMaterialConversionPlugin, EditorResourceConversionPlugin)
+public:
+ virtual String converts_to() const;
+ virtual bool handles(const Ref<Resource> &p_resource) const;
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
+};
+
#endif // MATERIAL_EDITOR_PLUGIN_H
diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp
index a77f022347..74618aecc2 100644
--- a/editor/plugins/mesh_editor_plugin.cpp
+++ b/editor/plugins/mesh_editor_plugin.cpp
@@ -47,7 +47,7 @@ void MeshEditor::_gui_input(Ref<InputEvent> p_event) {
void MeshEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
}
if (p_what == NOTIFICATION_READY) {
@@ -162,7 +162,7 @@ MeshEditor::MeshEditor() {
HBoxContainer *hb = memnew(HBoxContainer);
add_child(hb);
- hb->set_area_as_parent_rect(2);
+ hb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 2);
hb->add_spacer();
diff --git a/editor/plugins/navigation_mesh_editor_plugin.h b/editor/plugins/navigation_mesh_editor_plugin.h
index 3009e2addc..bac7f608ab 100644
--- a/editor/plugins/navigation_mesh_editor_plugin.h
+++ b/editor/plugins/navigation_mesh_editor_plugin.h
@@ -56,7 +56,7 @@ class NavigationMeshEditor : public Control {
protected:
void _node_removed(Node *p_node);
static void _bind_methods();
- void _notification(int p_what);
+ void _notification(int p_option);
public:
void edit(NavigationMeshInstance *p_nav_mesh_instance);
@@ -74,8 +74,8 @@ class NavigationMeshEditorPlugin : public EditorPlugin {
public:
virtual String get_name() const { return "NavigationMesh"; }
bool has_main_screen() const { return false; }
- virtual void edit(Object *p_node);
- virtual bool handles(Object *p_node) const;
+ virtual void edit(Object *p_object);
+ virtual bool handles(Object *p_object) const;
virtual void make_visible(bool p_visible);
NavigationMeshEditorPlugin(EditorNode *p_node);
diff --git a/editor/plugins/navigation_mesh_generator.h b/editor/plugins/navigation_mesh_generator.h
index 48e7dfe53f..0a1c497f8f 100644
--- a/editor/plugins/navigation_mesh_generator.h
+++ b/editor/plugins/navigation_mesh_generator.h
@@ -56,7 +56,7 @@ protected:
rcPolyMeshDetail *detail_mesh, Vector<float> &verticies, Vector<int> &indices);
public:
- static void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_base);
+ static void bake(Ref<NavigationMesh> p_nav_mesh, Node *p_node);
static void clear(Ref<NavigationMesh> p_nav_mesh);
};
diff --git a/editor/plugins/navigation_polygon_editor_plugin.cpp b/editor/plugins/navigation_polygon_editor_plugin.cpp
index de8d4f9618..69e553eefb 100644
--- a/editor/plugins/navigation_polygon_editor_plugin.cpp
+++ b/editor/plugins/navigation_polygon_editor_plugin.cpp
@@ -46,7 +46,7 @@ void NavigationPolygonEditor::_notification(int p_what) {
create_nav->connect("confirmed", this, "_create_nav");
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
} break;
}
diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp
index adc8d4f091..df10ac8929 100644
--- a/editor/plugins/path_2d_editor_plugin.cpp
+++ b/editor/plugins/path_2d_editor_plugin.cpp
@@ -46,7 +46,7 @@ void Path2DEditor::_notification(int p_what) {
//button_edit->set_pressed(true);
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
} break;
}
@@ -89,9 +89,9 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
for (int i = 0; i < curve->get_point_count(); i++) {
- real_t dist_to_p = gpoint.distance_to(xform.xform(curve->get_point_pos(i)));
- real_t dist_to_p_out = gpoint.distance_to(xform.xform(curve->get_point_pos(i) + curve->get_point_out(i)));
- real_t dist_to_p_in = gpoint.distance_to(xform.xform(curve->get_point_pos(i) + curve->get_point_in(i)));
+ real_t dist_to_p = gpoint.distance_to(xform.xform(curve->get_point_position(i)));
+ real_t dist_to_p_out = gpoint.distance_to(xform.xform(curve->get_point_position(i) + curve->get_point_out(i)));
+ real_t dist_to_p_in = gpoint.distance_to(xform.xform(curve->get_point_position(i) + curve->get_point_in(i)));
// Check for point movement start (for point + in/out controls).
if (mb->get_button_index() == BUTTON_LEFT) {
@@ -100,7 +100,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
action = ACTION_MOVING_POINT;
action_point = i;
- moving_from = curve->get_point_pos(i);
+ moving_from = curve->get_point_position(i);
moving_screen_from = gpoint;
return true;
} else if (mode == MODE_EDIT || mode == MODE_EDIT_CURVE) {
@@ -129,7 +129,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
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_undo_method(curve.ptr(), "add_point", curve->get_point_position(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();
@@ -171,7 +171,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
action = ACTION_MOVING_POINT;
action_point = curve->get_point_count() - 1;
- moving_from = curve->get_point_pos(action_point);
+ moving_from = curve->get_point_position(action_point);
moving_screen_from = gpoint;
canvas_item_editor->get_viewport_control()->update();
@@ -194,8 +194,8 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
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(curve.ptr(), "set_point_position", action_point, cpoint);
+ undo_redo->add_undo_method(curve.ptr(), "set_point_position", 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();
@@ -255,7 +255,7 @@ bool Path2DEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
break;
case ACTION_MOVING_POINT: {
- curve->set_point_pos(action_point, cpoint);
+ curve->set_point_position(action_point, cpoint);
} break;
case ACTION_MOVING_IN: {
@@ -296,17 +296,17 @@ void Path2DEditor::_canvas_draw() {
for (int i = 0; i < len; i++) {
- Vector2 point = xform.xform(curve->get_point_pos(i));
+ Vector2 point = xform.xform(curve->get_point_position(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));
+ Vector2 pointout = xform.xform(curve->get_point_position(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));
+ Vector2 pointin = xform.xform(curve->get_point_position(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));
}
@@ -389,8 +389,8 @@ void Path2DEditor::_mode_selected(int p_mode) {
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);
+ Vector2 begin = node->get_curve()->get_point_position(0);
+ Vector2 end = node->get_curve()->get_point_position(node->get_curve()->get_point_count() - 1);
if (begin.distance_to(end) < CMP_EPSILON)
return;
diff --git a/editor/plugins/path_editor_plugin.cpp b/editor/plugins/path_editor_plugin.cpp
index d0f2b19ed3..fa97c96614 100644
--- a/editor/plugins/path_editor_plugin.cpp
+++ b/editor/plugins/path_editor_plugin.cpp
@@ -64,7 +64,7 @@ Variant PathSpatialGizmo::get_handle_value(int p_idx) const {
if (p_idx < c->get_point_count()) {
- original = c->get_point_pos(p_idx);
+ original = c->get_point_position(p_idx);
return original;
}
@@ -79,7 +79,7 @@ Variant PathSpatialGizmo::get_handle_value(int p_idx) const {
else
ofs = c->get_point_out(idx);
- original = ofs + c->get_point_pos(idx);
+ original = ofs + c->get_point_position(idx);
return ofs;
}
@@ -108,7 +108,7 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p
}
Vector3 local = gi.xform(inters);
- c->set_point_pos(p_idx, local);
+ c->set_point_position(p_idx, local);
}
return;
@@ -119,7 +119,7 @@ void PathSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p_p
int idx = p_idx / 2;
int t = p_idx % 2;
- Vector3 base = c->get_point_pos(idx);
+ Vector3 base = c->get_point_position(idx);
Plane p(gt.xform(original), p_camera->get_transform().basis.get_axis(2));
@@ -148,12 +148,12 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p
if (p_cancel) {
- c->set_point_pos(p_idx, p_restore);
+ c->set_point_position(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->create_action(TTR("Set Curve Point Position"));
+ ur->add_do_method(c.ptr(), "set_point_position", p_idx, c->get_point_position(p_idx));
+ ur->add_undo_method(c.ptr(), "set_point_position", p_idx, p_restore);
ur->commit_action();
return;
@@ -178,7 +178,7 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p
c->set_point_in(p_idx, p_restore);
return;
}
- ur->create_action(TTR("Set Curve In Pos"));
+ ur->create_action(TTR("Set Curve In Position"));
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();
@@ -189,7 +189,7 @@ void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p
c->set_point_out(idx, p_restore);
return;
}
- ur->create_action(TTR("Set Curve Out Pos"));
+ ur->create_action(TTR("Set Curve Out Position"));
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();
@@ -234,7 +234,7 @@ void PathSpatialGizmo::redraw() {
for (int i = 0; i < c->get_point_count(); i++) {
- Vector3 p = c->get_point_pos(i);
+ Vector3 p = c->get_point_position(i);
handles.push_back(p);
if (i > 0) {
v3p.push_back(p);
@@ -307,16 +307,16 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp
if (rc >= 2) {
PoolVector<Vector3>::Read r = v3a.read();
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(0))).distance_to(mbpos) < click_dist)
+ if (p_camera->unproject_position(gt.xform(c->get_point_position(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)
+ if (p_camera->unproject_position(gt.xform(c->get_point_position(i + 1))).distance_to(mbpos) < click_dist)
return false; //nope, existing
- while (j < rc && c->get_point_pos(i + 1) != r[j]) {
+ while (j < rc && c->get_point_position(i + 1) != r[j]) {
Vector3 from = r[j];
Vector3 to = r[j + 1];
@@ -371,7 +371,7 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp
if (c->get_point_count() == 0)
org = path->get_transform().get_origin();
else
- org = gt.xform(c->get_point_pos(c->get_point_count() - 1));
+ org = gt.xform(c->get_point_position(c->get_point_count() - 1));
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);
@@ -392,9 +392,9 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp
} else if (mb->is_pressed() && ((mb->get_button_index() == BUTTON_LEFT && curve_del->is_pressed()) || (mb->get_button_index() == BUTTON_RIGHT && curve_edit->is_pressed()))) {
for (int i = 0; i < c->get_point_count(); i++) {
- real_t dist_to_p = p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos);
- real_t dist_to_p_out = p_camera->unproject_position(gt.xform(c->get_point_pos(i) + c->get_point_out(i))).distance_to(mbpos);
- real_t dist_to_p_in = p_camera->unproject_position(gt.xform(c->get_point_pos(i) + c->get_point_in(i))).distance_to(mbpos);
+ real_t dist_to_p = p_camera->unproject_position(gt.xform(c->get_point_position(i))).distance_to(mbpos);
+ real_t dist_to_p_out = p_camera->unproject_position(gt.xform(c->get_point_position(i) + c->get_point_out(i))).distance_to(mbpos);
+ real_t dist_to_p_in = p_camera->unproject_position(gt.xform(c->get_point_position(i) + c->get_point_in(i))).distance_to(mbpos);
// Find the offset and point index of the place to break up.
// Also check for the control points.
@@ -403,7 +403,7 @@ bool PathEditorPlugin::forward_spatial_gui_input(Camera *p_camera, const Ref<Inp
UndoRedo *ur = editor->get_undo_redo();
ur->create_action(TTR("Remove Path Point"));
ur->add_do_method(c.ptr(), "remove_point", i);
- ur->add_undo_method(c.ptr(), "add_point", c->get_point_pos(i), c->get_point_in(i), c->get_point_out(i), i);
+ ur->add_undo_method(c.ptr(), "add_point", c->get_point_position(i), c->get_point_in(i), c->get_point_out(i), i);
ur->commit_action();
return true;
} else if (dist_to_p_out < click_dist) {
@@ -496,7 +496,7 @@ void PathEditorPlugin::_close_curve() {
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));
+ c->add_point(c->get_point_position(0), c->get_point_in(0), c->get_point_out(0));
}
void PathEditorPlugin::_notification(int p_what) {
diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp
index 3917c700f0..af2349983d 100644
--- a/editor/plugins/polygon_2d_editor_plugin.cpp
+++ b/editor/plugins/polygon_2d_editor_plugin.cpp
@@ -52,13 +52,13 @@ void Polygon2DEditor::_notification(int p_what) {
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"));
+ b_snap_enable->set_icon(get_icon("SnapGrid", "EditorIcons"));
uv_icon_zoom->set_texture(get_icon("Zoom", "EditorIcons"));
get_tree()->connect("node_removed", this, "_node_removed");
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
} break;
}
diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp
index e157ddbf90..d421b3798b 100644
--- a/editor/plugins/resource_preloader_editor_plugin.cpp
+++ b/editor/plugins/resource_preloader_editor_plugin.cpp
@@ -38,7 +38,7 @@ void ResourcePreloaderEditor::_gui_input(Ref<InputEvent> p_event) {
void ResourcePreloaderEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
}
if (p_what == NOTIFICATION_ENTER_TREE) {
@@ -248,13 +248,13 @@ void ResourcePreloaderEditor::edit(ResourcePreloader *p_preloader) {
} else {
hide();
- set_fixed_process(false);
+ set_physics_process(false);
}
}
Variant ResourcePreloaderEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
- TreeItem *ti = tree->get_item_at_pos(p_point);
+ TreeItem *ti = tree->get_item_at_position(p_point);
if (!ti)
return Variant();
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 44a9bc6d2e..9af5885a17 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -1682,9 +1682,10 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool
break;
}
ERR_FAIL_COND_V(!se, false);
- tab_container->add_child(se);
+ // load script before adding as child else editor will crash at theme loading
se->set_edited_script(p_script);
+ tab_container->add_child(se);
se->set_tooltip_request_func("_get_debug_tooltip", this);
if (se->get_edit_menu()) {
se->get_edit_menu()->hide();
diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp
index d2cb96bf3b..b66e9598f9 100644
--- a/editor/plugins/script_text_editor.cpp
+++ b/editor/plugins/script_text_editor.cpp
@@ -75,35 +75,98 @@ void ScriptTextEditor::_load_theme_settings() {
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 background_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0));
+ Color completion_background_color = EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0, 0, 0, 0));
+ Color completion_selected_color = EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244"));
+ Color completion_existing_color = EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"));
+ Color completion_scroll_color = EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"));
+ Color completion_font_color = EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"));
+ Color text_color = EDITOR_DEF("text_editor/highlighting/text_color", Color(0, 0, 0));
+ Color line_number_color = EDITOR_DEF("text_editor/highlighting/line_number_color", Color(0, 0, 0));
+ Color caret_color = EDITOR_DEF("text_editor/highlighting/caret_color", Color(0, 0, 0));
+ Color caret_background_color = EDITOR_DEF("text_editor/highlighting/caret_background_color", Color(0, 0, 0));
+ Color text_selected_color = EDITOR_DEF("text_editor/highlighting/text_selected_color", Color(1, 1, 1));
+ Color selection_color = EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1));
+ Color brace_mismatch_color = EDITOR_DEF("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2));
+ Color current_line_color = EDITOR_DEF("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15));
+ Color line_length_guideline_color = EDITOR_DEF("text_editor/highlighting/line_length_guideline_color", Color(0, 0, 0));
+ Color word_highlighted_color = EDITOR_DEF("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15));
+ Color number_color = EDITOR_DEF("text_editor/highlighting/number_color", Color(0.9, 0.6, 0.0, 2));
+ Color function_color = EDITOR_DEF("text_editor/highlighting/function_color", Color(0.4, 0.6, 0.8));
+ Color member_variable_color = EDITOR_DEF("text_editor/highlighting/member_variable_color", Color(0.9, 0.3, 0.3));
+ Color mark_color = EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4));
+ Color breakpoint_color = EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2));
+ Color search_result_color = EDITOR_DEF("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1));
+ Color search_result_border_color = EDITOR_DEF("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1));
+ Color 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));
+ Color basetype_color = EDITOR_DEF("text_editor/highlighting/base_type_color", Color(0.3, 0.3, 0.0));
+ Color type_color = EDITOR_DEF("text_editor/highlighting/engine_type_color", Color(0.0, 0.2, 0.4));
+ Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color", Color::hex(0x797e7eff));
+ Color string_color = EDITOR_DEF("text_editor/highlighting/string_color", Color::hex(0x6b6f00ff));
+
+ // Adapt
+ if (EditorSettings::get_singleton()->get("text_editor/theme/color_theme") == "Adaptive") {
+ Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme();
+
+ symbol_color = tm->get_color("text_editor/theme/symbol_color", "Editor");
+ keyword_color = tm->get_color("text_editor/theme/keyword_color", "Editor");
+ basetype_color = tm->get_color("text_editor/theme/basetype_color", "Editor");
+ type_color = tm->get_color("text_editor/theme/type_color", "Editor");
+ comment_color = tm->get_color("text_editor/theme/comment_color", "Editor");
+ string_color = tm->get_color("text_editor/theme/string_color", "Editor");
+ background_color = tm->get_color("text_editor/theme/background_color", "Editor");
+ completion_background_color = tm->get_color("text_editor/theme/completion_background_color", "Editor");
+ completion_selected_color = tm->get_color("text_editor/theme/completion_selected_color", "Editor");
+ completion_existing_color = tm->get_color("text_editor/theme/completion_existing_color", "Editor");
+ completion_scroll_color = tm->get_color("text_editor/theme/completion_scroll_color", "Editor");
+ completion_font_color = tm->get_color("text_editor/theme/completion_font_color", "Editor");
+ text_color = tm->get_color("text_editor/theme/text_color", "Editor");
+ line_number_color = tm->get_color("text_editor/theme/line_number_color", "Editor");
+ caret_color = tm->get_color("text_editor/theme/caret_color", "Editor");
+ caret_background_color = tm->get_color("text_editor/theme/caret_background_color", "Editor");
+ text_selected_color = tm->get_color("text_editor/theme/text_selected_color", "Editor");
+ selection_color = tm->get_color("text_editor/theme/selection_color", "Editor");
+ brace_mismatch_color = tm->get_color("text_editor/theme/brace_mismatch_color", "Editor");
+ current_line_color = tm->get_color("text_editor/theme/current_line_color", "Editor");
+ line_length_guideline_color = tm->get_color("text_editor/theme/line_length_guideline_color", "Editor");
+ word_highlighted_color = tm->get_color("text_editor/theme/word_highlighted_color", "Editor");
+ number_color = tm->get_color("text_editor/theme/number_color", "Editor");
+ function_color = tm->get_color("text_editor/theme/function_color", "Editor");
+ member_variable_color = tm->get_color("text_editor/theme/member_variable_color", "Editor");
+ mark_color = tm->get_color("text_editor/theme/mark_color", "Editor");
+ breakpoint_color = tm->get_color("text_editor/theme/breakpoint_color", "Editor");
+ search_result_color = tm->get_color("text_editor/theme/search_result_color", "Editor");
+ search_result_border_color = tm->get_color("text_editor/theme/search_result_border_color", "Editor");
+ }
+
+ text_edit->add_color_override("background_color", background_color);
+ text_edit->add_color_override("completion_background_color", completion_background_color);
+ text_edit->add_color_override("completion_selected_color", completion_selected_color);
+ text_edit->add_color_override("completion_existing_color", completion_existing_color);
+ text_edit->add_color_override("completion_scroll_color", completion_scroll_color);
+ text_edit->add_color_override("completion_font_color", completion_font_color);
+ text_edit->add_color_override("font_color", text_color);
+ text_edit->add_color_override("line_number_color", line_number_color);
+ text_edit->add_color_override("caret_color", caret_color);
+ text_edit->add_color_override("caret_background_color", caret_background_color);
+ text_edit->add_color_override("font_selected_color", text_selected_color);
+ text_edit->add_color_override("selection_color", selection_color);
+ text_edit->add_color_override("brace_mismatch_color", brace_mismatch_color);
+ text_edit->add_color_override("current_line_color", current_line_color);
+ text_edit->add_color_override("line_length_guideline_color", line_length_guideline_color);
+ text_edit->add_color_override("word_highlighted_color", word_highlighted_color);
+ text_edit->add_color_override("number_color", number_color);
+ text_edit->add_color_override("function_color", function_color);
+ text_edit->add_color_override("member_variable_color", member_variable_color);
+ text_edit->add_color_override("mark_color", mark_color);
+ text_edit->add_color_override("breakpoint_color", breakpoint_color);
+ text_edit->add_color_override("search_result_color", search_result_color);
+ text_edit->add_color_override("search_result_border_color", search_result_border_color);
+ text_edit->add_color_override("symbol_color", symbol_color);
+
+ text_edit->add_constant_override("line_spacing", EDITOR_DEF("text_editor/theme/line_spacing", 4));
List<String> keywords;
script->get_language()->get_reserved_words(&keywords);
@@ -113,8 +176,6 @@ void ScriptTextEditor::_load_theme_settings() {
}
//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("String", basetype_color);
text_edit->add_keyword_color("Vector2", basetype_color);
text_edit->add_keyword_color("Rect2", basetype_color);
@@ -140,8 +201,6 @@ void ScriptTextEditor::_load_theme_settings() {
text_edit->add_keyword_color("PoolColorArray", 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);
@@ -155,7 +214,6 @@ void ScriptTextEditor::_load_theme_settings() {
}
//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);
@@ -169,7 +227,6 @@ void ScriptTextEditor::_load_theme_settings() {
}
//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);
@@ -209,6 +266,7 @@ void ScriptTextEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_READY) {
//emit_signal("name_changed");
+ _load_theme_settings();
}
}
@@ -248,7 +306,7 @@ Variant ScriptTextEditor::get_edit_state() {
Dictionary state;
- state["scroll_pos"] = code_editor->get_text_edit()->get_v_scroll();
+ state["scroll_position"] = 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();
@@ -451,7 +509,7 @@ void ScriptTextEditor::ensure_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()->set_v_scroll(state["scroll_position"]);
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();
@@ -492,8 +550,6 @@ void ScriptTextEditor::set_edited_script(const Ref<Script> &p_script) {
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();
@@ -1341,7 +1397,7 @@ void ScriptTextEditor::_text_edit_gui_input(const Ref<InputEvent> &ev) {
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_position(get_global_transform().xform(get_local_mouse_pos()));
+ color_panel->set_position(get_global_transform().xform(get_local_mouse_position()));
} else {
have_color = false;
}
@@ -1389,7 +1445,7 @@ void ScriptTextEditor::_make_context_menu(bool p_selection, bool p_color) {
context_menu->add_separator();
context_menu->add_item(TTR("Pick Color"), EDIT_PICK_COLOR);
}
- context_menu->set_position(get_global_transform().xform(get_local_mouse_pos()));
+ context_menu->set_position(get_global_transform().xform(get_local_mouse_position()));
context_menu->set_size(Vector2(1, 1));
context_menu->popup();
}
@@ -1399,7 +1455,7 @@ ScriptTextEditor::ScriptTextEditor() {
code_editor = memnew(CodeTextEditor);
add_child(code_editor);
code_editor->add_constant_override("separation", 0);
- code_editor->set_area_as_parent_rect();
+ code_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
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);
@@ -1501,11 +1557,7 @@ ScriptTextEditor::ScriptTextEditor() {
static ScriptEditorBase *create_editor(const Ref<Script> &p_script) {
- if (p_script->has_source_code()) {
- return memnew(ScriptTextEditor);
- }
-
- return NULL;
+ return memnew(ScriptTextEditor);
}
void ScriptTextEditor::register_editor() {
diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp
index 1b02f18d85..b0ee1a32ca 100644
--- a/editor/plugins/shader_editor_plugin.cpp
+++ b/editor/plugins/shader_editor_plugin.cpp
@@ -60,33 +60,96 @@ 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 background_color = EDITOR_DEF("text_editor/highlighting/background_color", Color(0, 0, 0, 0));
+ Color completion_background_color = EDITOR_DEF("text_editor/highlighting/completion_background_color", Color(0, 0, 0, 0));
+ Color completion_selected_color = EDITOR_DEF("text_editor/highlighting/completion_selected_color", Color::html("434244"));
+ Color completion_existing_color = EDITOR_DEF("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"));
+ Color completion_scroll_color = EDITOR_DEF("text_editor/highlighting/completion_scroll_color", Color::html("ffffff"));
+ Color completion_font_color = EDITOR_DEF("text_editor/highlighting/completion_font_color", Color::html("aaaaaa"));
+ Color text_color = EDITOR_DEF("text_editor/highlighting/text_color", Color(0, 0, 0));
+ Color line_number_color = EDITOR_DEF("text_editor/highlighting/line_number_color", Color(0, 0, 0));
+ Color caret_color = EDITOR_DEF("text_editor/highlighting/caret_color", Color(0, 0, 0));
+ Color caret_background_color = EDITOR_DEF("text_editor/highlighting/caret_background_color", Color(0, 0, 0));
+ Color text_selected_color = EDITOR_DEF("text_editor/highlighting/text_selected_color", Color(1, 1, 1));
+ Color selection_color = EDITOR_DEF("text_editor/highlighting/selection_color", Color(0.2, 0.2, 1));
+ Color brace_mismatch_color = EDITOR_DEF("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2));
+ Color current_line_color = EDITOR_DEF("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15));
+ Color line_length_guideline_color = EDITOR_DEF("text_editor/highlighting/line_length_guideline_color", Color(0, 0, 0));
+ Color word_highlighted_color = EDITOR_DEF("text_editor/highlighting/word_highlighted_color", Color(0.8, 0.9, 0.9, 0.15));
+ Color number_color = EDITOR_DEF("text_editor/highlighting/number_color", Color(0.9, 0.6, 0.0, 2));
+ Color function_color = EDITOR_DEF("text_editor/highlighting/function_color", Color(0.4, 0.6, 0.8));
+ Color member_variable_color = EDITOR_DEF("text_editor/highlighting/member_variable_color", Color(0.9, 0.3, 0.3));
+ Color mark_color = EDITOR_DEF("text_editor/highlighting/mark_color", Color(1.0, 0.4, 0.4, 0.4));
+ Color breakpoint_color = EDITOR_DEF("text_editor/highlighting/breakpoint_color", Color(0.8, 0.8, 0.4, 0.2));
+ Color search_result_color = EDITOR_DEF("text_editor/highlighting/search_result_color", Color(0.05, 0.25, 0.05, 1));
+ Color search_result_border_color = EDITOR_DEF("text_editor/highlighting/search_result_border_color", Color(0.1, 0.45, 0.1, 1));
+ Color 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));
+ Color basetype_color = EDITOR_DEF("text_editor/highlighting/base_type_color", Color(0.3, 0.3, 0.0));
+ Color type_color = EDITOR_DEF("text_editor/highlighting/engine_type_color", Color(0.0, 0.2, 0.4));
+ Color comment_color = EDITOR_DEF("text_editor/highlighting/comment_color", Color::hex(0x797e7eff));
+ Color string_color = EDITOR_DEF("text_editor/highlighting/string_color", Color::hex(0x6b6f00ff));
+
+ // Adapt
+ if (EditorSettings::get_singleton()->get("text_editor/theme/color_theme") == "Adaptive") {
+ Ref<Theme> tm = EditorNode::get_singleton()->get_theme_base()->get_theme();
+
+ symbol_color = tm->get_color("text_editor/theme/symbol_color", "Editor");
+ keyword_color = tm->get_color("text_editor/theme/keyword_color", "Editor");
+ basetype_color = tm->get_color("text_editor/theme/basetype_color", "Editor");
+ type_color = tm->get_color("text_editor/theme/type_color", "Editor");
+ comment_color = tm->get_color("text_editor/theme/comment_color", "Editor");
+ string_color = tm->get_color("text_editor/theme/string_color", "Editor");
+ background_color = tm->get_color("text_editor/theme/background_color", "Editor");
+ completion_background_color = tm->get_color("text_editor/theme/completion_background_color", "Editor");
+ completion_selected_color = tm->get_color("text_editor/theme/completion_selected_color", "Editor");
+ completion_existing_color = tm->get_color("text_editor/theme/completion_existing_color", "Editor");
+ completion_scroll_color = tm->get_color("text_editor/theme/completion_scroll_color", "Editor");
+ completion_font_color = tm->get_color("text_editor/theme/completion_font_color", "Editor");
+ text_color = tm->get_color("text_editor/theme/text_color", "Editor");
+ line_number_color = tm->get_color("text_editor/theme/line_number_color", "Editor");
+ caret_color = tm->get_color("text_editor/theme/caret_color", "Editor");
+ caret_background_color = tm->get_color("text_editor/theme/caret_background_color", "Editor");
+ text_selected_color = tm->get_color("text_editor/theme/text_selected_color", "Editor");
+ selection_color = tm->get_color("text_editor/theme/selection_color", "Editor");
+ brace_mismatch_color = tm->get_color("text_editor/theme/brace_mismatch_color", "Editor");
+ current_line_color = tm->get_color("text_editor/theme/current_line_color", "Editor");
+ line_length_guideline_color = tm->get_color("text_editor/theme/line_length_guideline_color", "Editor");
+ word_highlighted_color = tm->get_color("text_editor/theme/word_highlighted_color", "Editor");
+ number_color = tm->get_color("text_editor/theme/number_color", "Editor");
+ function_color = tm->get_color("text_editor/theme/function_color", "Editor");
+ member_variable_color = tm->get_color("text_editor/theme/member_variable_color", "Editor");
+ mark_color = tm->get_color("text_editor/theme/mark_color", "Editor");
+ breakpoint_color = tm->get_color("text_editor/theme/breakpoint_color", "Editor");
+ search_result_color = tm->get_color("text_editor/theme/search_result_color", "Editor");
+ search_result_border_color = tm->get_color("text_editor/theme/search_result_border_color", "Editor");
+ }
+
+ get_text_edit()->add_color_override("background_color", background_color);
+ get_text_edit()->add_color_override("completion_background_color", completion_background_color);
+ get_text_edit()->add_color_override("completion_selected_color", completion_selected_color);
+ get_text_edit()->add_color_override("completion_existing_color", completion_existing_color);
+ get_text_edit()->add_color_override("completion_scroll_color", completion_scroll_color);
+ get_text_edit()->add_color_override("completion_font_color", completion_font_color);
+ get_text_edit()->add_color_override("font_color", text_color);
+ get_text_edit()->add_color_override("line_number_color", line_number_color);
+ get_text_edit()->add_color_override("caret_color", caret_color);
+ get_text_edit()->add_color_override("caret_background_color", caret_background_color);
+ get_text_edit()->add_color_override("font_selected_color", text_selected_color);
+ get_text_edit()->add_color_override("selection_color", selection_color);
+ get_text_edit()->add_color_override("brace_mismatch_color", brace_mismatch_color);
+ get_text_edit()->add_color_override("current_line_color", current_line_color);
+ get_text_edit()->add_color_override("line_length_guideline_color", line_length_guideline_color);
+ get_text_edit()->add_color_override("word_highlighted_color", word_highlighted_color);
+ get_text_edit()->add_color_override("number_color", number_color);
+ get_text_edit()->add_color_override("function_color", function_color);
+ get_text_edit()->add_color_override("member_variable_color", member_variable_color);
+ get_text_edit()->add_color_override("mark_color", mark_color);
+ get_text_edit()->add_color_override("breakpoint_color", breakpoint_color);
+ get_text_edit()->add_color_override("search_result_color", search_result_color);
+ get_text_edit()->add_color_override("search_result_border_color", search_result_border_color);
+ get_text_edit()->add_color_override("symbol_color", symbol_color);
List<String> keywords;
ShaderLanguage::get_keyword_list(&keywords);
@@ -115,8 +178,6 @@ void ShaderTextEditor::_load_theme_settings() {
//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);
diff --git a/editor/plugins/shader_graph_editor_plugin.cpp b/editor/plugins/shader_graph_editor_plugin.cpp
index 732344cb78..cd90d47896 100644
--- a/editor/plugins/shader_graph_editor_plugin.cpp
+++ b/editor/plugins/shader_graph_editor_plugin.cpp
@@ -54,7 +54,7 @@ void GraphColorRampEdit::_gui_input(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event->get_button_index()==1 && p_event->is_pressed()) {
update();
- int x = p_event->get_pos().x;
+ int x = p_event->get_position().x;
int total_w = get_size().width-get_size().height-3;
if (x>total_w+3) {
@@ -333,7 +333,7 @@ void GraphCurveMapEdit::_gui_input(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_BUTTON && p_event->get_button_index()==1 && p_event->is_pressed()) {
update();
- Point2 p = Vector2(p_event->get_pos().x,p_event->get_pos().y)/get_size();
+ Point2 p = Vector2(p_event->get_position().x,p_event->get_position().y)/get_size();
p.y=1.0-p.y;
grabbed=-1;
grabbing=true;
@@ -384,7 +384,7 @@ void GraphCurveMapEdit::_gui_input(const InputEvent& p_event) {
if (p_event.type==InputEvent::MOUSE_MOTION && grabbing && grabbed != -1) {
- Point2 p = Vector2(p_event->get_pos().x,p_event->get_pos().y)/get_size();
+ Point2 p = Vector2(p_event->get_position().x,p_event->get_position().y)/get_size();
p.y=1.0-p.y;
p.x = CLAMP(p.x,0.0,1.0);
@@ -1205,7 +1205,7 @@ 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);
+ graph->node_set_position(type,p_id,p_to);
}
void ShaderGraphView::_duplicate_nodes_request()
@@ -2463,7 +2463,7 @@ void ShaderGraphView::_create_node(int 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));
+ gn->set_offset(graph->node_get_position(type,p_id));
}
@@ -2657,7 +2657,7 @@ void ShaderGraphView::add_node(int p_type, const Vector2 &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());
+ Vector2 pos = graph->node_get_position(type,E->get());
if (init_ofs==pos) {
init_ofs+=Vector2(20,20);
valid=false;
@@ -2672,7 +2672,7 @@ void ShaderGraphView::add_node(int p_type, const Vector2 &location) {
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_do_method(graph.ptr(),"node_set_position",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");
@@ -2765,7 +2765,7 @@ void ShaderGraphEditor::_add_node(int p_type) {
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;
+ next_location = get_local_mouse_position() + scroll_ofs;
popup->set_global_position(p_position);
popup->set_size( Size2( 200, 0) );
popup->popup();
@@ -2921,7 +2921,7 @@ ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node, bool p_2d)
//editor->get_viewport()->add_child(shader_editor);
- //shader_editor->set_area_as_parent_rect();
+ //shader_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
//shader_editor->hide();
}
diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp
index 704d474746..425390723c 100644
--- a/editor/plugins/spatial_editor_plugin.cpp
+++ b/editor/plugins/spatial_editor_plugin.cpp
@@ -49,13 +49,15 @@
#define DISTANCE_DEFAULT 4
-#define GIZMO_ARROW_SIZE 0.3
+#define GIZMO_ARROW_SIZE 0.35
#define GIZMO_RING_HALF_WIDTH 0.1
//#define GIZMO_SCALE_DEFAULT 0.28
#define GIZMO_SCALE_DEFAULT 0.15
#define GIZMO_PLANE_SIZE 0.2
#define GIZMO_PLANE_DST 0.3
-#define GIZMO_CIRCLE_SIZE 0.9
+#define GIZMO_CIRCLE_SIZE 1.1
+#define GIZMO_SCALE_OFFSET (GIZMO_CIRCLE_SIZE + 0.3)
+#define GIZMO_ARROW_OFFSET (GIZMO_CIRCLE_SIZE + 0.3)
#define ZOOM_MIN_DISTANCE 0.001
#define ZOOM_MULTIPLIER 1.08
@@ -70,42 +72,61 @@
#define MAX_FOV 179
void SpatialEditorViewport::_update_camera(float p_interp_delta) {
- 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());
- float inertia = EDITOR_DEF("editors/3d/orbit_inertia", 0.5);
- inertia = MAX(0, inertia);
+ bool is_orthogonal = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL;
+
+ //when not being manipulated, move softly
+ float free_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/orbit_inertia");
+ float free_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/translation_inertia");
+ //when being manipulated, move more quickly
+ float manip_orbit_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_orbit_inertia");
+ float manip_translation_inertia = EDITOR_GET("editors/3d/navigation_feel/manipulation_translation_inertia");
+
+ float zoom_inertia = EDITOR_GET("editors/3d/navigation_feel/zoom_inertia");
+
+ //determine if being manipulated
+ bool manipulated = (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+
+ float orbit_inertia = MAX(0.00001, manipulated ? manip_orbit_inertia : free_orbit_inertia);
+ float translation_inertia = MAX(0.0001, manipulated ? manip_translation_inertia : free_translation_inertia);
Cursor old_camera_cursor = camera_cursor;
camera_cursor = cursor;
- camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, p_interp_delta * (1 / inertia));
- camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, p_interp_delta * (1 / inertia));
+ camera_cursor.x_rot = Math::lerp(old_camera_cursor.x_rot, cursor.x_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia)));
+ camera_cursor.y_rot = Math::lerp(old_camera_cursor.y_rot, cursor.y_rot, MIN(1.f, p_interp_delta * (1 / orbit_inertia)));
- bool disable_interp = (Input::get_singleton()->get_mouse_button_mask() & (2 | 4)) || Input::get_singleton()->is_key_pressed(KEY_SHIFT) || Input::get_singleton()->is_key_pressed(KEY_ALT) || Input::get_singleton()->is_key_pressed(KEY_CONTROL);
+ camera_cursor.pos = old_camera_cursor.pos.linear_interpolate(cursor.pos, MIN(1.f, p_interp_delta * (1 / translation_inertia)));
+ camera_cursor.distance = Math::lerp(old_camera_cursor.distance, cursor.distance, MIN(1.f, p_interp_delta * (1 / zoom_inertia)));
- if (p_interp_delta == 0 || disable_interp || is_freelook_active()) {
+ if (p_interp_delta == 0 || is_freelook_active()) {
camera_cursor = cursor;
}
- float tolerance = 0.0001;
+ float tolerance = 0.001;
bool equal = true;
- if (Math::abs(old_camera_cursor.x_rot - camera_cursor.x_rot) > tolerance || Math::abs(old_camera_cursor.y_rot - camera_cursor.y_rot) > tolerance)
+ if (Math::abs(old_camera_cursor.x_rot - camera_cursor.x_rot) > tolerance || Math::abs(old_camera_cursor.y_rot - camera_cursor.y_rot) > tolerance) {
equal = false;
+ }
- if (equal && old_camera_cursor.pos.distance_squared_to(camera_cursor.pos) > tolerance * tolerance)
+ if (equal && old_camera_cursor.pos.distance_squared_to(camera_cursor.pos) > tolerance * tolerance) {
equal = false;
+ }
- if (equal && Math::abs(old_camera_cursor.distance - camera_cursor.distance) > tolerance)
+ if (equal && Math::abs(old_camera_cursor.distance - camera_cursor.distance) > tolerance) {
equal = false;
+ }
- if (!equal || p_interp_delta == 0 || is_freelook_active()) {
+ if (!equal || p_interp_delta == 0 || is_freelook_active() || is_orthogonal != orthogonal) {
camera->set_global_transform(to_camera_transform(camera_cursor));
update_transform_gizmo_view();
+
+ 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());
}
}
@@ -206,7 +227,7 @@ Transform SpatialEditorViewport::_get_camera_transform() const {
return camera->get_global_transform();
}
-Vector3 SpatialEditorViewport::_get_camera_pos() const {
+Vector3 SpatialEditorViewport::_get_camera_position() const {
return _get_camera_transform().origin;
}
@@ -453,8 +474,7 @@ void SpatialEditorViewport::_select_region() {
Vector<Plane> frustum;
- Vector3 cam_pos = _get_camera_pos();
- Set<Ref<SpatialEditorGizmo> > found_gizmos;
+ Vector3 cam_pos = _get_camera_position();
for (int i = 0; i < 4; i++) {
@@ -474,6 +494,9 @@ void SpatialEditorViewport::_select_region() {
frustum.push_back(far);
Vector<ObjectID> instances = VisualServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world()->get_scenario());
+ Vector<Spatial *> selected;
+
+ Node *edited_scene = get_tree()->get_edited_scene_root();
for (int i = 0; i < instances.size(); i++) {
@@ -486,11 +509,14 @@ void SpatialEditorViewport::_select_region() {
if (!seg.is_valid())
continue;
- if (found_gizmos.has(seg))
- continue;
+ Spatial *root_sp = sp;
+ while (root_sp && root_sp != edited_scene && root_sp->get_owner() != edited_scene && !edited_scene->is_editable_instance(root_sp->get_owner())) {
+ root_sp = Object::cast_to<Spatial>(root_sp->get_owner());
+ }
- if (seg->intersect_frustum(camera, frustum))
- _select(sp, true, false);
+ if (selected.find(root_sp) == -1)
+ if (seg->intersect_frustum(camera, frustum))
+ _select(root_sp, true, false);
}
}
@@ -514,8 +540,6 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) {
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 = Object::cast_to<Spatial>(E->get());
@@ -527,14 +551,8 @@ void SpatialEditorViewport::_compute_edit(const Point2 &p_point) {
continue;
se->original = se->sp->get_global_transform();
- //center+=se->original.origin;
- //nc++;
+ se->original_local = se->sp->get_transform();
}
-
- /*
- if (nc)
- _edit.center=center/float(nc);
- */
}
static int _get_key_modifier_setting(const String &p_property) {
@@ -585,7 +603,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig
for (int i = 0; i < 3; i++) {
- Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs;
+ Vector3 grabber_pos = gt.origin + gt.basis.get_axis(i) * gs * (GIZMO_ARROW_OFFSET + (GIZMO_ARROW_SIZE * 0.5));
float grabber_radius = gs * GIZMO_ARROW_SIZE;
Vector3 r;
@@ -600,7 +618,7 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig
}
bool is_plane_translate = false;
- // second try
+ // plane select
if (col_axis == -1) {
col_d = 1e20;
@@ -686,6 +704,43 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2 &p_screenpos, bool p_hig
}
}
+ if (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE) {
+
+ 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 * GIZMO_SCALE_OFFSET;
+ 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_highlight_only) {
+
+ spatial_editor->select_gizmo_highlight_axis(col_axis + 9);
+
+ } else {
+ //handle scale
+ _edit.mode = TRANSFORM_SCALE;
+ _compute_edit(Point2(p_screenpos.x, p_screenpos.y));
+ _edit.plane = TransformPlane(TRANSFORM_X_AXIS + col_axis);
+ }
+ return true;
+ }
+ }
+
if (p_highlight_only)
spatial_editor->select_gizmo_highlight_axis(-1);
@@ -786,20 +841,20 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
if (b.is_valid()) {
-
+ float zoom_factor = 1 + (ZOOM_MULTIPLIER - 1) * b->get_factor();
switch (b->get_button_index()) {
case BUTTON_WHEEL_UP: {
- scale_cursor_distance(is_freelook_active() ? ZOOM_MULTIPLIER : 1.0 / ZOOM_MULTIPLIER);
+ scale_cursor_distance(is_freelook_active() ? zoom_factor : 1.0 / zoom_factor);
} break;
case BUTTON_WHEEL_DOWN: {
- scale_cursor_distance(is_freelook_active() ? 1.0 / ZOOM_MULTIPLIER : ZOOM_MULTIPLIER);
+ scale_cursor_distance(is_freelook_active() ? 1.0 / zoom_factor : zoom_factor);
} break;
case BUTTON_RIGHT: {
- NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
+ NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
if (b->is_pressed() && _edit.gizmo.is_valid()) {
//restore
@@ -845,7 +900,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (b->is_pressed()) {
int mod = _get_key_modifier(b);
- if (mod == _get_key_modifier_setting("editors/3d/freelook_activation_modifier")) {
+ if (mod == _get_key_modifier_setting("editors/3d/freelook/freelook_activation_modifier")) {
freelook_active = true;
}
} else {
@@ -897,7 +952,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (b->is_pressed()) {
- NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
+ NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
if ((nav_scheme == NAVIGATION_MAYA || nav_scheme == NAVIGATION_MODO) && b->get_alt()) {
break;
}
@@ -1106,7 +1161,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
_gizmo_select(_edit.mouse_pos, true);
}
- NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation_scheme").operator int();
+ NavigationScheme nav_scheme = (NavigationScheme)EditorSettings::get_singleton()->get("editors/3d/navigation/navigation_scheme").operator int();
NavigationMode nav_mode = NAVIGATION_NONE;
if (_edit.gizmo.is_valid()) {
@@ -1158,7 +1213,28 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
case TRANSFORM_SCALE: {
- Plane plane = Plane(_edit.center, _get_camera_normal());
+ Vector3 motion_mask;
+ Plane plane;
+ bool plane_mv;
+
+ 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))
@@ -1168,42 +1244,78 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
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;
+ Vector3 motion = intersection - click;
+ print_line(String(intersection) + " --- " + String(click));
+ if (motion_mask != Vector3()) {
- float scale = (center_inters_dist / center_click_dist) * 100.0;
+ motion = motion_mask.dot(motion) * motion_mask;
+ } else {
- if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ float center_click_dist = click.distance_to(_edit.center);
+ float center_inters_dist = intersection.distance_to(_edit.center);
+ if (center_click_dist == 0)
+ break;
- scale = Math::stepify(scale, spatial_editor->get_scale_snap());
+ float scale = center_inters_dist - center_click_dist;
+ motion = Vector3(scale, scale, scale);
}
- set_message(vformat(TTR("Scaling to %s%%."), String::num(scale, 1)));
- scale /= 100.0;
+ List<Node *> &selection = editor_selection->get_selected_node_list();
- Transform r;
- r.basis.scale(Vector3(scale, scale, scale));
+ bool local_coords = (spatial_editor->are_local_coords_enabled() && motion_mask != Vector3()); // Disable local transformation for TRANSFORM_VIEW
- List<Node *> &selection = editor_selection->get_selected_node_list();
+ float snap = 0;
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+
+ snap = spatial_editor->get_scale_snap() / 100;
+ }
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
Spatial *sp = Object::cast_to<Spatial>(E->get());
- if (!sp)
+ if (!sp) {
continue;
+ }
SpatialEditorSelectedItem *se = editor_selection->get_node_editor_data<SpatialEditorSelectedItem>(sp);
- if (!se)
+ if (!se) {
continue;
+ }
Transform original = se->original;
-
+ Transform original_local = se->original_local;
Transform base = Transform(Basis(), _edit.center);
- Transform t = base * (r * (base.inverse() * original));
+ Transform t;
+ Vector3 local_scale;
- sp->set_global_transform(t);
+ if (local_coords) {
+
+ Basis g = original.basis.orthonormalized();
+ Vector3 local_motion = g.inverse().xform(motion);
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ local_motion.snap(Vector3(snap, snap, snap));
+ }
+
+ local_scale = original_local.basis.get_scale() * (local_motion + Vector3(1, 1, 1));
+
+ } else {
+
+ if (_edit.snap || spatial_editor->is_snap_enabled()) {
+ motion.snap(Vector3(snap, snap, snap));
+ }
+
+ Transform r;
+ r.basis.scale(motion + Vector3(1, 1, 1));
+ t = base * (r * (base.inverse() * original));
+ }
+
+ // Apply scale
+ if (local_coords) {
+ sp->set_scale(local_scale);
+ } else {
+ sp->set_global_transform(t);
+ }
}
surface->update();
@@ -1429,11 +1541,11 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
int mod = _get_key_modifier(m);
- if (mod == _get_key_modifier_setting("editors/3d/pan_modifier"))
+ if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier"))
nav_mode = NAVIGATION_PAN;
- else if (mod == _get_key_modifier_setting("editors/3d/zoom_modifier"))
+ else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier"))
nav_mode = NAVIGATION_ZOOM;
- else if (mod == _get_key_modifier_setting("editors/3d/orbit_modifier"))
+ else if (mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier"))
nav_mode = NAVIGATION_ORBIT;
} else if (nav_scheme == NAVIGATION_MAYA) {
@@ -1441,16 +1553,16 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
nav_mode = NAVIGATION_PAN;
}
- } else if (EditorSettings::get_singleton()->get("editors/3d/emulate_3_button_mouse")) {
+ } else if (EditorSettings::get_singleton()->get("editors/3d/navigation/emulate_3_button_mouse")) {
// Handle trackpad (no external mouse) use case
int mod = _get_key_modifier(m);
if (mod) {
- if (mod == _get_key_modifier_setting("editors/3d/pan_modifier"))
+ if (mod == _get_key_modifier_setting("editors/3d/navigation/pan_modifier"))
nav_mode = NAVIGATION_PAN;
- else if (mod == _get_key_modifier_setting("editors/3d/zoom_modifier"))
+ else if (mod == _get_key_modifier_setting("editors/3d/navigation/zoom_modifier"))
nav_mode = NAVIGATION_ZOOM;
- else if (mod == _get_key_modifier_setting("editors/3d/orbit_modifier"))
+ else if (mod == _get_key_modifier_setting("editors/3d/navigation/orbit_modifier"))
nav_mode = NAVIGATION_ORBIT;
}
}
@@ -1483,7 +1595,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (nav_scheme == NAVIGATION_MAYA && m->get_shift())
zoom_speed *= zoom_speed_modifier;
- NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/zoom_style").operator int();
+ NavigationZoomStyle zoom_style = (NavigationZoomStyle)EditorSettings::get_singleton()->get("editors/3d/navigation/zoom_style").operator int();
if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) {
if (m->get_relative().x > 0)
scale_cursor_distance(1 - m->get_relative().x * zoom_speed);
@@ -1501,7 +1613,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
case NAVIGATION_ORBIT: {
Point2i relative = _get_warped_mouse_motion(m);
- real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/orbit_sensitivity");
+ real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
cursor.x_rot += relative.y * radians_per_pixel;
@@ -1520,7 +1632,7 @@ void SpatialEditorViewport::_sinput(const Ref<InputEvent> &p_event) {
if (!orthogonal) {
Point2i relative = _get_warped_mouse_motion(m);
- real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/orbit_sensitivity");
+ real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity");
real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel);
cursor.x_rot += relative.y * radians_per_pixel;
@@ -1657,7 +1769,7 @@ void SpatialEditorViewport::scale_cursor_distance(real_t scale) {
Point2i SpatialEditorViewport::_get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_ev_mouse_motion) const {
Point2i relative;
- if (bool(EDITOR_DEF("editors/3d/warped_mouse_panning", false))) {
+ if (bool(EDITOR_DEF("editors/3d/navigation/warped_mouse_panning", false))) {
relative = Input::get_singleton()->warp_mouse_motion(p_ev_mouse_motion, surface->get_global_rect());
} else {
relative = p_ev_mouse_motion->get_relative();
@@ -1711,10 +1823,10 @@ void SpatialEditorViewport::_update_freelook(real_t delta) {
speed_modifier = true;
}
- real_t inertia = EDITOR_DEF("editors/3d/freelook_inertia", 0.2);
+ real_t inertia = EDITOR_DEF("editors/3d/freelook/freelook_inertia", 0.1);
inertia = MAX(0, inertia);
- const real_t base_speed = EDITOR_DEF("editors/3d/freelook_base_speed", 0.5);
- const real_t modifier_speed_factor = EDITOR_DEF("editors/3d/freelook_modifier_speed_factor", 5);
+ const real_t base_speed = EDITOR_DEF("editors/3d/freelook/freelook_base_speed", 0.5);
+ const real_t modifier_speed_factor = EDITOR_DEF("editors/3d/freelook/freelook_modifier_speed_factor", 3);
real_t speed = base_speed * cursor.distance;
if (speed_modifier)
@@ -1826,7 +1938,7 @@ void SpatialEditorViewport::_notification(int p_what) {
last_message = message;
}
- message_time -= get_fixed_process_delta_time();
+ message_time -= get_physics_process_delta_time();
if (message_time < 0)
surface->update();
}
@@ -2247,6 +2359,14 @@ void SpatialEditorViewport::_init_gizmo_instance(int p_idx) {
//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);
+
+ scale_gizmo_instance[i] = VS::get_singleton()->instance_create();
+ VS::get_singleton()->instance_set_base(scale_gizmo_instance[i], spatial_editor->get_scale_gizmo(i)->get_rid());
+ VS::get_singleton()->instance_set_scenario(scale_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario());
+ VS::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false);
+ //VS::get_singleton()->instance_geometry_set_flag(scale_gizmo_instance[i],VS::INSTANCE_FLAG_DEPH_SCALE,true);
+ VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF);
+ VS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer);
}
}
@@ -2256,6 +2376,7 @@ void SpatialEditorViewport::_finish_gizmo_instances() {
VS::get_singleton()->free(move_gizmo_instance[i]);
VS::get_singleton()->free(move_plane_gizmo_instance[i]);
VS::get_singleton()->free(rotate_gizmo_instance[i]);
+ VS::get_singleton()->free(scale_gizmo_instance[i]);
}
}
void SpatialEditorViewport::_toggle_camera_preview(bool p_activate) {
@@ -2350,14 +2471,16 @@ void SpatialEditorViewport::update_transform_gizmo_view() {
VisualServer::get_singleton()->instance_set_visible(move_plane_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));
+ VisualServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform);
+ VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == SpatialEditor::TOOL_MODE_SCALE));
}
}
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.pos = p_state["position"];
+ cursor.x_rot = p_state["x_rotation"];
+ cursor.y_rot = p_state["y_rotation"];
cursor.distance = p_state["distance"];
bool env = p_state["use_environment"];
bool orth = p_state["use_orthogonal"];
@@ -2399,9 +2522,9 @@ void SpatialEditorViewport::set_state(const Dictionary &p_state) {
Dictionary SpatialEditorViewport::get_state() const {
Dictionary d;
- d["pos"] = cursor.pos;
- d["x_rot"] = cursor.x_rot;
- d["y_rot"] = cursor.y_rot;
+ d["position"] = cursor.pos;
+ d["x_rotation"] = cursor.x_rot;
+ d["y_rotation"] = cursor.y_rot;
d["distance"] = cursor.distance;
d["use_environment"] = camera->get_environment().is_valid();
d["use_orthogonal"] = camera->get_projection() == Camera::PROJECTION_ORTHOGONAL;
@@ -2555,11 +2678,18 @@ void SpatialEditorViewport::_create_preview(const Vector<String> &files) const {
String path = files[i];
RES res = ResourceLoader::load(path);
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
- if (scene != NULL) {
- if (scene.is_valid()) {
- Node *instance = scene->instance();
- if (instance) {
- preview_node->add_child(instance);
+ Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res));
+ if (mesh != NULL || scene != NULL) {
+ if (mesh != NULL) {
+ MeshInstance *mesh_instance = memnew(MeshInstance);
+ mesh_instance->set_mesh(mesh);
+ preview_node->add_child(mesh_instance);
+ } else {
+ if (scene.is_valid()) {
+ Node *instance = scene->instance();
+ if (instance) {
+ preview_node->add_child(instance);
+ }
}
}
editor->get_scene_root()->add_child(preview_node);
@@ -2595,13 +2725,29 @@ bool SpatialEditorViewport::_cyclical_dependency_exists(const String &p_target_s
}
bool SpatialEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) {
- Ref<PackedScene> sdata = ResourceLoader::load(path);
- if (!sdata.is_valid()) { // invalid scene
- return false;
+ RES res = ResourceLoader::load(path);
+
+ Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
+ Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res));
+
+ Node *instanced_scene = NULL;
+
+ if (mesh != NULL || scene != NULL) {
+ if (mesh != NULL) {
+ MeshInstance *mesh_instance = memnew(MeshInstance);
+ mesh_instance->set_mesh(mesh);
+ mesh_instance->set_name(mesh->get_name());
+ instanced_scene = mesh_instance;
+ } else {
+ if (!scene.is_valid()) { // invalid scene
+ return false;
+ } else {
+ instanced_scene = scene->instance();
+ }
+ }
}
- Node *instanced_scene = sdata->instance(PackedScene::GEN_EDIT_STATE_INSTANCE);
- if (!instanced_scene) { // error on instancing
+ if (instanced_scene == NULL) {
return false;
}
@@ -2650,7 +2796,8 @@ void SpatialEditorViewport::_perform_drop_data() {
continue;
}
Ref<PackedScene> scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*res));
- if (scene != NULL) {
+ Ref<Mesh> mesh = Ref<Mesh>(Object::cast_to<Mesh>(*res));
+ if (mesh != NULL || scene != NULL) {
bool success = _create_instance(target_node, path, drop_pos);
if (!success) {
error_files.push_back(path);
@@ -2683,9 +2830,11 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian
List<String> scene_extensions;
ResourceLoader::get_recognized_extensions_for_type("PackedScene", &scene_extensions);
+ List<String> mesh_extensions;
+ ResourceLoader::get_recognized_extensions_for_type("Mesh", &mesh_extensions);
for (int i = 0; i < files.size(); i++) {
- if (scene_extensions.find(files[i].get_extension())) {
+ if (mesh_extensions.find(files[i].get_extension()) || scene_extensions.find(files[i].get_extension())) {
RES res = ResourceLoader::load(files[i]);
if (res.is_null()) {
continue;
@@ -2699,6 +2848,13 @@ bool SpatialEditorViewport::can_drop_data_fw(const Point2 &p_point, const Varian
continue;
}
memdelete(instanced_scene);
+ } else if (type == "Mesh" || "ArrayMesh" || "PrimitiveMesh") {
+ Ref<Mesh> mesh = ResourceLoader::load(files[i]);
+ if (!mesh.is_valid()) {
+ continue;
+ }
+ } else {
+ continue;
}
can_instance = true;
break;
@@ -2785,7 +2941,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
ViewportContainer *c = memnew(ViewportContainer);
c->set_stretch(true);
add_child(c);
- c->set_area_as_parent_rect();
+ c->set_anchors_and_margins_preset(Control::PRESET_WIDE);
viewport = memnew(Viewport);
viewport->set_disable_input(true);
@@ -2793,7 +2949,7 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
surface = memnew(Control);
surface->set_drag_forwarding(this);
add_child(surface);
- surface->set_area_as_parent_rect();
+ surface->set_anchors_and_margins_preset(Control::PRESET_WIDE);
surface->set_clip_contents(true);
camera = memnew(Camera);
camera->set_disable_gizmo(true);
@@ -2843,8 +2999,8 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed
ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D);
ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W);
ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S);
- ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_Q);
- ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E);
+ ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_E);
+ ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_Q);
ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT);
preview_camera = memnew(Button);
@@ -3202,6 +3358,7 @@ void SpatialEditor::select_gizmo_highlight_axis(int p_axis) {
move_gizmo[i]->surface_set_material(0, i == p_axis ? gizmo_hl : gizmo_color[i]);
move_plane_gizmo[i]->surface_set_material(0, (i + 6) == p_axis ? gizmo_hl : plane_gizmo_color[i]);
rotate_gizmo[i]->surface_set_material(0, (i + 3) == p_axis ? gizmo_hl : gizmo_color[i]);
+ scale_gizmo[i]->surface_set_material(0, (i + 9) == p_axis ? gizmo_hl : gizmo_color[i]);
}
}
@@ -3212,7 +3369,7 @@ void SpatialEditor::update_transform_gizmo() {
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));
+ bool local_gizmo_coords = are_local_coords_enabled();
for (List<Node *>::Element *E = selection.front(); E; E = E->next()) {
@@ -3663,20 +3820,13 @@ void SpatialEditor::_menu_item_pressed(int p_option) {
void SpatialEditor::_init_indicators() {
- //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(SpatialMaterial::FLAG_UNSHADED, true);
- //indicator_mat->set_flag(SpatialMaterial::FLAG_ONTOP,true);
indicator_mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
indicator_mat->set_flag(SpatialMaterial::FLAG_SRGB_VERTEX_COLOR, true);
- indicator_mat->set_feature(SpatialMaterial::FEATURE_TRANSPARENT, true);
-
PoolVector<Color> grid_colors[3];
PoolVector<Vector3> grid_points[3];
Vector<Color> origin_colors;
@@ -3696,50 +3846,31 @@ void SpatialEditor::_init_indicators() {
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 100
+#define ORIGIN_GRID_SIZE 50
for (int j = -ORIGIN_GRID_SIZE; j <= ORIGIN_GRID_SIZE; j++) {
- for (int k = -ORIGIN_GRID_SIZE; k <= ORIGIN_GRID_SIZE; k++) {
-
- Vector3 p = axis_n1 * j + axis_n2 * k;
- float trans = Math::pow(MAX(0, 1.0 - (Vector2(j, k).length() / ORIGIN_GRID_SIZE)), 2);
+ Vector3 p1 = axis_n1 * j + axis_n2 * -ORIGIN_GRID_SIZE;
+ Vector3 p1_dest = p1 * (-axis_n2 + axis_n1);
+ Vector3 p2 = axis_n2 * j + axis_n1 * -ORIGIN_GRID_SIZE;
+ Vector3 p2_dest = p2 * (-axis_n1 + axis_n2);
- Vector3 pj = axis_n1 * (j + 1) + axis_n2 * k;
- float transj = Math::pow(MAX(0, 1.0 - (Vector2(j + 1, k).length() / ORIGIN_GRID_SIZE)), 2);
-
- Vector3 pk = axis_n1 * j + axis_n2 * (k + 1);
- float transk = Math::pow(MAX(0, 1.0 - (Vector2(j, k + 1).length() / ORIGIN_GRID_SIZE)), 2);
-
- Color trans_color = grid_color;
- trans_color.a *= trans;
-
- Color transk_color = grid_color;
- transk_color.a *= transk;
-
- Color transj_color = grid_color;
- transj_color.a *= transj;
-
- if (j % 10 == 0 || k % 10 == 0) {
- trans_color.a *= 2;
- }
- if ((k + 1) % 10 == 0) {
- transk_color.a *= 2;
- }
- if ((j + 1) % 10 == 0) {
- transj_color.a *= 2;
- }
+ Color line_color = grid_color;
+ if (j == 0) {
+ continue;
+ } else if (j % 10 == 0) {
+ line_color *= 1.5;
+ }
- grid_points[i].push_back(p);
- grid_points[i].push_back(pk);
- grid_colors[i].push_back(trans_color);
- grid_colors[i].push_back(transk_color);
+ grid_points[i].push_back(p1);
+ grid_points[i].push_back(p1_dest);
+ grid_colors[i].push_back(line_color);
+ grid_colors[i].push_back(line_color);
- grid_points[i].push_back(p);
- grid_points[i].push_back(pj);
- grid_colors[i].push_back(trans_color);
- grid_colors[i].push_back(transj_color);
- }
+ grid_points[i].push_back(p2);
+ grid_points[i].push_back(p2_dest);
+ grid_colors[i].push_back(line_color);
+ grid_colors[i].push_back(line_color);
}
grid[i] = VisualServer::get_singleton()->mesh_create();
@@ -3783,32 +3914,6 @@ void SpatialEditor::_init_indicators() {
}
{
- 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(SpatialMaterial::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
@@ -3826,6 +3931,7 @@ void SpatialEditor::_init_indicators() {
move_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
move_plane_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
rotate_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
+ scale_gizmo[i] = Ref<ArrayMesh>(memnew(ArrayMesh));
Ref<SpatialMaterial> mat = memnew(SpatialMaterial);
mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
@@ -3848,25 +3954,25 @@ void SpatialEditor::_init_indicators() {
Vector3 ivec3;
ivec3[(i + 2) % 3] = 1;
+ //translate
{
Ref<SurfaceTool> surftool = memnew(SurfaceTool);
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
- //translate
-
+ // Arrow profile
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),
+ nivec * 0.01 + ivec * GIZMO_ARROW_OFFSET,
+ nivec * 0.065 + ivec * GIZMO_ARROW_OFFSET,
+ nivec * 0.0 + ivec * (GIZMO_ARROW_OFFSET + GIZMO_ARROW_SIZE),
};
int arrow_sides = 6;
- for (int k = 0; k < 7; k++) {
+ for (int k = 0; k < 6; k++) {
Basis ma(ivec, Math_PI * 2 * float(k) / arrow_sides);
Basis mb(ivec, Math_PI * 2 * float(k + 1) / arrow_sides);
@@ -3893,7 +3999,7 @@ void SpatialEditor::_init_indicators() {
surftool->commit(move_gizmo[i]);
}
- // plane translation
+ // Plane Translation
{
Ref<SurfaceTool> surftool = memnew(SurfaceTool);
surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
@@ -3936,6 +4042,7 @@ void SpatialEditor::_init_indicators() {
surftool->commit(move_plane_gizmo[i]);
}
+ // Rotate
{
Ref<SurfaceTool> surftool = memnew(SurfaceTool);
@@ -3949,7 +4056,7 @@ void SpatialEditor::_init_indicators() {
ivec * 0.02 + ivec2 * 0.02 + ivec2 * GIZMO_CIRCLE_SIZE,
};
- for (int k = 0; k < 33; k++) {
+ for (int k = 0; k < 32; k++) {
Basis ma(ivec, Math_PI * 2 * float(k) / 32);
Basis mb(ivec, Math_PI * 2 * float(k + 1) / 32);
@@ -3975,19 +4082,55 @@ void SpatialEditor::_init_indicators() {
surftool->set_material(mat);
surftool->commit(rotate_gizmo[i]);
}
- }
- }
- /*for(int i=0;i<4;i++) {
+ // Scale
+ {
+ Ref<SurfaceTool> surftool = memnew(SurfaceTool);
+ surftool->begin(Mesh::PRIMITIVE_TRIANGLES);
- viewports[i]->init_gizmo_instance(i);
- }*/
+ // Cube arrow profile
+ const int arrow_points = 6;
+ Vector3 arrow[6] = {
+ nivec * 0.0 + ivec * 0.0,
+ nivec * 0.01 + ivec * 0.0,
+ nivec * 0.01 + ivec * 1.0 * GIZMO_SCALE_OFFSET,
+ nivec * 0.07 + ivec * 1.0 * GIZMO_SCALE_OFFSET,
+ nivec * 0.07 + ivec * 1.11 * GIZMO_SCALE_OFFSET,
+ nivec * 0.0 + ivec * 1.11 * GIZMO_SCALE_OFFSET,
+ };
- _generate_selection_box();
+ int arrow_sides = 4;
+
+ for (int k = 0; k < 4; 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++) {
- //Object::cast_to<EditorNode>(get_scene()->get_root_node())->get_scene_root()->add_child(camera);
+ 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]);
- //current_camera=camera;
+ surftool->add_vertex(points[0]);
+ surftool->add_vertex(points[2]);
+ surftool->add_vertex(points[3]);
+ }
+ }
+
+ surftool->set_material(mat);
+ surftool->commit(scale_gizmo[i]);
+ }
+ }
+ }
+
+ _generate_selection_box();
}
void SpatialEditor::_finish_indicators() {
@@ -4001,9 +4144,6 @@ void SpatialEditor::_finish_indicators() {
//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);
}
bool SpatialEditor::is_any_freelook_active() const {
@@ -4165,7 +4305,7 @@ void SpatialEditor::_toggle_maximize_view(Object *p_viewport) {
for (uint32_t i = 0; i < VIEWPORTS_COUNT; i++) {
if (i == (uint32_t)index)
- viewports[i]->set_area_as_parent_rect();
+ viewports[i]->set_anchors_and_margins_preset(Control::PRESET_WIDE);
else
viewports[i]->hide();
}
@@ -4591,7 +4731,7 @@ SpatialEditorPlugin::SpatialEditorPlugin(EditorNode *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->set_anchors_and_margins_preset(Control::PRESET_WIDE);
spatial_editor->hide();
spatial_editor->connect("transform_key_request", editor, "_transform_keyed");
diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h
index 5f3ef2dbee..4f4c540048 100644
--- a/editor/plugins/spatial_editor_plugin.h
+++ b/editor/plugins/spatial_editor_plugin.h
@@ -157,7 +157,7 @@ private:
Transform _get_camera_transform() const;
int get_selected_count() const;
- Vector3 _get_camera_pos() const;
+ Vector3 _get_camera_position() const;
Vector3 _get_camera_normal() const;
Vector3 _get_screen_to_space(const Vector3 &p_vector3);
@@ -245,7 +245,7 @@ private:
real_t zoom_indicator_delay;
- RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3];
+ RID move_gizmo_instance[3], move_plane_gizmo_instance[3], rotate_gizmo_instance[3], scale_gizmo_instance[3];
String last_message;
String message;
@@ -319,6 +319,7 @@ class SpatialEditorSelectedItem : public Object {
public:
Rect3 aabb;
Transform original; // original location when moving
+ Transform original_local;
Transform last_xform; // last transform
Spatial *sp;
RID sbox_instance;
@@ -407,7 +408,7 @@ private:
bool grid_enable[3]; //should be always visible if true
bool grid_enabled;
- Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[3];
+ Ref<ArrayMesh> move_gizmo[3], move_plane_gizmo[3], rotate_gizmo[3], scale_gizmo[3];
Ref<SpatialMaterial> gizmo_color[3];
Ref<SpatialMaterial> plane_gizmo_color[3];
Ref<SpatialMaterial> gizmo_hl;
@@ -557,6 +558,7 @@ public:
Ref<ArrayMesh> get_move_gizmo(int idx) const { return move_gizmo[idx]; }
Ref<ArrayMesh> get_move_plane_gizmo(int idx) const { return move_plane_gizmo[idx]; }
Ref<ArrayMesh> get_rotate_gizmo(int idx) const { return rotate_gizmo[idx]; }
+ Ref<ArrayMesh> get_scale_gizmo(int idx) const { return scale_gizmo[idx]; }
void update_transform_gizmo();
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp
index 7b40f69082..3b6eeb61d6 100644
--- a/editor/plugins/sprite_frames_editor_plugin.cpp
+++ b/editor/plugins/sprite_frames_editor_plugin.cpp
@@ -39,7 +39,7 @@ void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) {
void SpriteFramesEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
}
if (p_what == NOTIFICATION_ENTER_TREE) {
@@ -535,7 +535,7 @@ void SpriteFramesEditor::edit(SpriteFrames *p_frames) {
} else {
hide();
- //set_fixed_process(false);
+ //set_physics_process(false);
}
}
@@ -544,7 +544,7 @@ Variant SpriteFramesEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f
if (!frames->has_animation(edited_anim))
return false;
- int idx = tree->get_item_at_pos(p_point, true);
+ int idx = tree->get_item_at_position(p_point, true);
if (idx < 0 || idx >= frames->get_frame_count(edited_anim))
return Variant();
@@ -609,7 +609,7 @@ void SpriteFramesEditor::drop_data_fw(const Point2 &p_point, const Variant &p_da
if (!d.has("type"))
return;
- int at_pos = tree->get_item_at_pos(p_point, true);
+ int at_pos = tree->get_item_at_position(p_point, true);
if (String(d["type"]) == "resource" && d.has("resource")) {
RES r = d["resource"];
@@ -643,7 +643,7 @@ void SpriteFramesEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_empty2_pressed"), &SpriteFramesEditor::_empty2_pressed);
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("_file_load_request", "files", "atpos"), &SpriteFramesEditor::_file_load_request, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("_file_load_request", "files", "at_position"), &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);
diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp
index 478ca2e972..5c965e4a05 100644
--- a/editor/plugins/style_box_editor_plugin.cpp
+++ b/editor/plugins/style_box_editor_plugin.cpp
@@ -57,7 +57,7 @@ StyleBoxEditor::StyleBoxEditor() {
panel = memnew(Panel);
add_child(panel);
- panel->set_area_as_parent_rect();
+ panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
Label *l = memnew(Label);
l->set_text(TTR("StyleBox Preview:"));
diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp
index 90dc4cf993..855e857d80 100644
--- a/editor/plugins/texture_editor_plugin.cpp
+++ b/editor/plugins/texture_editor_plugin.cpp
@@ -38,7 +38,7 @@ void TextureEditor::_gui_input(Ref<InputEvent> p_event) {
void TextureEditor::_notification(int p_what) {
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
}
if (p_what == NOTIFICATION_READY) {
diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp
index 38d1350b07..0a7f3ff8f9 100644
--- a/editor/plugins/texture_region_editor_plugin.cpp
+++ b/editor/plugins/texture_region_editor_plugin.cpp
@@ -39,7 +39,7 @@
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);
+ edit_draw->draw_line(from, from + line, EditorNode::get_singleton()->get_theme_base()->get_color("mono_color", "Editor"), 2);
from += line * 2;
}
}
@@ -66,6 +66,7 @@ void TextureRegionEditor::_region_draw() {
VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(), Transform2D());
if (snap_mode == SNAP_GRID) {
+ Color grid_color = get_color("grid_major_color", "Editor");
Size2 s = edit_draw->get_size();
int last_cell = 0;
@@ -76,7 +77,7 @@ void TextureRegionEditor::_region_draw() {
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));
+ edit_draw->draw_line(Point2(i, 0), Point2(i, s.height), grid_color);
last_cell = cell;
}
else
@@ -85,7 +86,7 @@ void TextureRegionEditor::_region_draw() {
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));
+ edit_draw->draw_rect(Rect2(i - snap_separation.x * draw_zoom, 0, snap_separation.x * draw_zoom, s.height), grid_color);
last_cell = cell;
}
}
@@ -97,7 +98,7 @@ void TextureRegionEditor::_region_draw() {
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));
+ edit_draw->draw_line(Point2(0, i), Point2(s.width, i), grid_color);
last_cell = cell;
}
else
@@ -106,7 +107,7 @@ void TextureRegionEditor::_region_draw() {
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));
+ edit_draw->draw_rect(Rect2(0, i - snap_separation.y * draw_zoom, s.width, snap_separation.y * draw_zoom), grid_color);
last_cell = cell;
}
}
@@ -137,7 +138,7 @@ void TextureRegionEditor::_region_draw() {
mtx.basis_xform(rect.position + rect.size),
mtx.basis_xform(rect.position + Vector2(0, rect.size.y))
};
- Color color(0.9, 0.5, 0.5);
+ Color color = get_color("mono_color", "Editor");
for (int i = 0; i < 4; i++) {
int prev = (i + 3) % 4;
@@ -773,7 +774,7 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) {
VBoxContainer *main_vb = memnew(VBoxContainer);
add_child(main_vb);
- main_vb->set_area_as_parent_rect(0);
+ main_vb->set_anchors_and_margins_preset(Control::PRESET_WIDE);
HBoxContainer *hb_tools = memnew(HBoxContainer);
main_vb->add_child(hb_tools);
@@ -906,7 +907,7 @@ void TextureRegionEditorPlugin::edit(Object *p_object) {
}
bool TextureRegionEditorPlugin::handles(Object *p_object) const {
- return p_object->is_class("Sprite") || p_object->is_class("Patch9Rect") || p_object->is_class("StyleBoxTexture") || p_object->is_class("AtlasTexture");
+ return p_object->is_class("Sprite") || p_object->is_class("NinePatchRect") || p_object->is_class("StyleBoxTexture") || p_object->is_class("AtlasTexture");
}
void TextureRegionEditorPlugin::make_visible(bool p_visible) {
diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp
index 86ef1a489f..e500dec0ef 100644
--- a/editor/plugins/theme_editor_plugin.cpp
+++ b/editor/plugins/theme_editor_plugin.cpp
@@ -607,7 +607,7 @@ ThemeEditor::ThemeEditor() {
scroll = memnew(ScrollContainer);
add_child(scroll);
- scroll->set_area_as_parent_rect(3);
+ scroll->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 3);
scroll->set_margin(MARGIN_TOP, 30 * EDSCALE);
//scroll->set_enable_h_scroll(true);
scroll->set_enable_v_scroll(true);
@@ -621,7 +621,7 @@ ThemeEditor::ThemeEditor() {
main_vb = memnew(VBoxContainer);
panel->add_child(main_vb);
- main_vb->set_area_as_parent_rect(4 * EDSCALE);
+ main_vb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 4 * EDSCALE);
HBoxContainer *hb_menu = memnew(HBoxContainer);
main_vb->add_child(hb_menu);
@@ -648,7 +648,7 @@ ThemeEditor::ThemeEditor() {
main_hb->add_child(first_vb);
//main_panel->add_child(panel);
- //panel->set_area_as_parent_rect();
+ //panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
//panel->set_margin( MARGIN_TOP,20 );
first_vb->add_child(memnew(Label("Label")));
diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp
index 43856116a6..2f2ed7bdf0 100644
--- a/editor/plugins/tile_map_editor_plugin.cpp
+++ b/editor/plugins/tile_map_editor_plugin.cpp
@@ -39,6 +39,14 @@ void TileMapEditor::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_PROCESS: {
+
+ if (bucket_queue.size() && canvas_item_editor) {
+ canvas_item_editor->update();
+ }
+
+ } break;
+
case NOTIFICATION_ENTER_TREE: {
transp->set_icon(get_icon("Transpose", "EditorIcons"));
@@ -72,6 +80,14 @@ void TileMapEditor::_menu_option(int p_option) {
switch (p_option) {
+ case OPTION_PAINTING: {
+ // NOTE: We do not set tool = TOOL_PAINTING as this begins painting
+ // immediately without pressing the left mouse button first
+ tool = TOOL_NONE;
+
+ canvas_item_editor->update();
+
+ } break;
case OPTION_BUCKET: {
tool = TOOL_BUCKET;
@@ -343,6 +359,10 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era
return PoolVector<Vector2>();
}
+ if (id == prev_id) {
+ return PoolVector<Vector2>();
+ }
+
Rect2i r = node->get_item_rect();
r.position = r.position / node->get_cell_size();
r.size = r.size / node->get_cell_size();
@@ -370,20 +390,26 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era
bucket_cache = PoolVector<Vector2>();
bucket_cache_tile = prev_id;
bucket_cache_rect = r;
- } else {
- return bucket_cache;
+ bucket_queue.clear();
}
}
PoolVector<Vector2> points;
+ int count = 0;
+ int limit = 0;
- List<Point2i> queue;
- queue.push_back(p_start);
+ if (preview) {
+ limit = 1024;
+ } else {
+ bucket_queue.clear();
+ }
- while (queue.size()) {
+ bucket_queue.push_back(p_start);
- Point2i n = queue.front()->get();
- queue.pop_front();
+ while (bucket_queue.size()) {
+
+ Point2i n = bucket_queue.front()->get();
+ bucket_queue.pop_front();
if (!r.has_point(n))
continue;
@@ -401,10 +427,15 @@ PoolVector<Vector2> TileMapEditor::_bucket_fill(const Point2i &p_start, bool era
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));
+ bucket_queue.push_back(Point2i(n.x, n.y + 1));
+ bucket_queue.push_back(Point2i(n.x, n.y - 1));
+ bucket_queue.push_back(Point2i(n.x + 1, n.y));
+ bucket_queue.push_back(Point2i(n.x - 1, n.y));
+ count++;
+ }
+
+ if (limit > 0 && count >= limit) {
+ break;
}
}
@@ -703,7 +734,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return true;
} else {
-
+ // Mousebutton was released
if (tool != TOOL_NONE) {
if (tool == TOOL_PAINTING) {
@@ -801,6 +832,9 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
undo_redo->add_undo_method(this, "_fill_points", points, pop);
undo_redo->commit_action();
+
+ // We want to keep the bucket-tool active
+ return true;
}
tool = TOOL_NONE;
@@ -1046,9 +1080,25 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) {
return true;
}
- if (tool != TOOL_NONE || !mouse_over)
+ if (!mouse_over) {
+ // Editor shortcuts should not fire if mouse not in viewport
return false;
+ }
+ if (ED_IS_SHORTCUT("tile_map_editor/paint_tile", p_event)) {
+ // NOTE: We do not set tool = TOOL_PAINTING as this begins painting
+ // immediately without pressing the left mouse button first
+ tool = TOOL_NONE;
+ canvas_item_editor->update();
+
+ return true;
+ }
+ if (ED_IS_SHORTCUT("tile_map_editor/bucket_fill", p_event)) {
+ tool = TOOL_BUCKET;
+ canvas_item_editor->update();
+
+ return true;
+ }
if (ED_IS_SHORTCUT("tile_map_editor/erase_selection", p_event)) {
_menu_option(OPTION_ERASE_SELECTION);
@@ -1458,7 +1508,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
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/transpose", TTR("Transpose"), KEY_T);
ED_SHORTCUT("tile_map_editor/mirror_x", TTR("Mirror X"), KEY_A);
ED_SHORTCUT("tile_map_editor/mirror_y", TTR("Mirror Y"), KEY_S);
@@ -1512,7 +1562,8 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) {
PopupMenu *p = options->get_popup();
- p->add_item(TTR("Bucket"), OPTION_BUCKET);
+ p->add_shortcut(ED_SHORTCUT("tile_map_editor/paint_tile", TTR("Paint Tile"), KEY_P), OPTION_PAINTING);
+ p->add_shortcut(ED_SHORTCUT("tile_map_editor/bucket_fill", TTR("Bucket Fill"), KEY_G), OPTION_BUCKET);
p->add_separator();
p->add_item(TTR("Pick Tile"), OPTION_PICK_TILE, KEY_CONTROL);
p->add_separator();
@@ -1616,6 +1667,7 @@ TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) {
tile_map_editor = memnew(TileMapEditor(p_node));
add_control_to_container(CONTAINER_CANVAS_EDITOR_SIDE, tile_map_editor);
tile_map_editor->hide();
+ tile_map_editor->set_process(true);
}
TileMapEditorPlugin::~TileMapEditorPlugin() {
diff --git a/editor/plugins/tile_map_editor_plugin.h b/editor/plugins/tile_map_editor_plugin.h
index e863c4bf3d..c8f29dfb7b 100644
--- a/editor/plugins/tile_map_editor_plugin.h
+++ b/editor/plugins/tile_map_editor_plugin.h
@@ -68,7 +68,8 @@ class TileMapEditor : public VBoxContainer {
OPTION_PICK_TILE,
OPTION_SELECT,
OPTION_DUPLICATE,
- OPTION_ERASE_SELECTION
+ OPTION_ERASE_SELECTION,
+ OPTION_PAINTING,
};
TileMap *node;
@@ -112,6 +113,7 @@ class TileMapEditor : public VBoxContainer {
Rect2i bucket_cache_rect;
int bucket_cache_tile;
PoolVector<Vector2> bucket_cache;
+ List<Point2i> bucket_queue;
struct CellOp {
int idx;
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 443c280428..f2f71ba6b1 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -238,7 +238,7 @@ void TileSetEditor::_bind_methods() {
TileSetEditor::TileSetEditor(EditorNode *p_editor) {
Panel *panel = memnew(Panel);
- panel->set_area_as_parent_rect();
+ panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
add_child(panel);
MenuButton *options = memnew(MenuButton);
panel->add_child(options);
@@ -293,7 +293,7 @@ TileSetEditorPlugin::TileSetEditorPlugin(EditorNode *p_node) {
tileset_editor = memnew(TileSetEditor(p_node));
p_node->get_viewport()->add_child(tileset_editor);
- tileset_editor->set_area_as_parent_rect();
+ tileset_editor->set_anchors_and_margins_preset(Control::PRESET_WIDE);
tileset_editor->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_BEGIN);
tileset_editor->set_end(Point2(0, 22));
tileset_editor->hide();
diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp
index 376d9d3158..09f5375bb4 100644
--- a/editor/progress_dialog.cpp
+++ b/editor/progress_dialog.cpp
@@ -49,7 +49,7 @@ void BackgroundProgress::_add_task(const String &p_task, const String &p_label,
Control *ec = memnew(Control);
ec->set_h_size_flags(SIZE_EXPAND_FILL);
ec->set_v_size_flags(SIZE_EXPAND_FILL);
- t.progress->set_area_as_parent_rect();
+ t.progress->set_anchors_and_margins_preset(Control::PRESET_WIDE);
ec->add_child(t.progress);
ec->set_custom_minimum_size(Size2(80, 5) * EDSCALE);
t.hb->add_child(ec);
@@ -222,7 +222,7 @@ ProgressDialog::ProgressDialog() {
main = memnew(VBoxContainer);
add_child(main);
- main->set_area_as_parent_rect();
+ main->set_anchors_and_margins_preset(Control::PRESET_WIDE);
set_exclusive(true);
last_progress_tick = 0;
singleton = this;
diff --git a/editor/project_export.cpp b/editor/project_export.cpp
index f4318a670c..fafd6805ca 100644
--- a/editor/project_export.cpp
+++ b/editor/project_export.cpp
@@ -434,7 +434,7 @@ void ProjectExportDialog::_delete_preset_confirm() {
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);
+ int pos = presets->get_item_at_position(p_point, true);
if (pos >= 0) {
Dictionary d;
@@ -455,7 +455,7 @@ Variant ProjectExportDialog::get_drag_data_fw(const Point2 &p_point, Control *p_
}
} else if (p_from == patches) {
- TreeItem *item = patches->get_item_at_pos(p_point);
+ TreeItem *item = patches->get_item_at_position(p_point);
if (item && item->get_cell_mode(0) == TreeItem::CELL_MODE_CHECK) {
@@ -482,7 +482,7 @@ bool ProjectExportDialog::can_drop_data_fw(const Point2 &p_point, const Variant
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))
+ if (presets->get_item_at_position(p_point, true) < 0 && !presets->is_pos_at_end_of_items(p_point))
return false;
} else if (p_from == patches) {
@@ -492,7 +492,7 @@ bool ProjectExportDialog::can_drop_data_fw(const Point2 &p_point, const Variant
patches->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM);
- TreeItem *item = patches->get_item_at_pos(p_point);
+ TreeItem *item = patches->get_item_at_position(p_point);
if (!item) {
@@ -511,8 +511,8 @@ void ProjectExportDialog::drop_data_fw(const Point2 &p_point, const Variant &p_d
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 (presets->get_item_at_position(p_point, true) >= 0) {
+ to_pos = presets->get_item_at_position(p_point, true);
}
if (to_pos == -1 && !presets->is_pos_at_end_of_items(p_point))
@@ -541,7 +541,7 @@ void ProjectExportDialog::drop_data_fw(const Point2 &p_point, const Variant &p_d
int from_pos = d["patch"];
- TreeItem *item = patches->get_item_at_pos(p_point);
+ TreeItem *item = patches->get_item_at_position(p_point);
if (!item)
return;
@@ -894,7 +894,7 @@ ProjectExportDialog::ProjectExportDialog() {
Panel *features_panel = memnew(Panel);
custom_feature_display = memnew(RichTextLabel);
features_panel->add_child(custom_feature_display);
- custom_feature_display->set_area_as_parent_rect(10 * EDSCALE);
+ custom_feature_display->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 10 * EDSCALE);
custom_feature_display->set_v_size_flags(SIZE_EXPAND_FILL);
feature_vb->add_margin_child(TTR("Feature List:"), features_panel, true);
sections->add_child(feature_vb);
@@ -929,7 +929,7 @@ ProjectExportDialog::ProjectExportDialog() {
export_error = memnew(Label);
main_vb->add_child(export_error);
export_error->hide();
- export_error->add_color_override("font_color", Color(1, 0.5, 0.5));
+ export_error->add_color_override("font_color", get_color("error_color", "Editor"));
export_templates_error = memnew(HBoxContainer);
main_vb->add_child(export_templates_error);
@@ -937,7 +937,7 @@ ProjectExportDialog::ProjectExportDialog() {
Label *export_error2 = memnew(Label);
export_templates_error->add_child(export_error2);
- export_error2->add_color_override("font_color", Color(1, 0.5, 0.5));
+ export_error2->add_color_override("font_color", get_color("error_color", "Editor"));
export_error2->set_text(" - " + TTR("Export templates for this platform are missing:") + " ");
LinkButton *download_templates = memnew(LinkButton);
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index 78d544fdcf..1a767dad05 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -51,9 +51,9 @@
#include "version.h"
#include "version_hash.gen.h"
-class NewProjectDialog : public ConfirmationDialog {
+class ProjectDialog : public ConfirmationDialog {
- GDCLASS(NewProjectDialog, ConfirmationDialog);
+ GDCLASS(ProjectDialog, ConfirmationDialog);
public:
enum Mode {
@@ -64,20 +64,56 @@ public:
};
private:
+ enum MessageType {
+ MESSAGE_ERROR,
+ MESSAGE_WARNING,
+ MESSAGE_SUCCESS
+ };
+
Mode mode;
Button *browse;
- Label *pp, *pn;
- Label *error;
+ Button *create_dir;
+ Container *name_container;
+ Container *path_container;
+ Label *msg;
LineEdit *project_path;
LineEdit *project_name;
+ ToolButton *status_btn;
FileDialog *fdialog;
String zip_path;
String zip_title;
AcceptDialog *dialog_error;
+ String fav_dir;
+
+ String created_folder_path;
+
+ void set_message(const String &p_msg, MessageType p_type = MESSAGE_SUCCESS) {
+ msg->set_text(p_msg);
+ if (p_msg == "") {
+ status_btn->set_icon(get_icon("StatusSuccess", "EditorIcons"));
+ return;
+ }
+ msg->hide();
+ switch (p_type) {
+ case MESSAGE_ERROR:
+ msg->add_color_override("font_color", get_color("error_color", "Editor"));
+ status_btn->set_icon(get_icon("StatusError", "EditorIcons"));
+ msg->show();
+ break;
+ case MESSAGE_WARNING:
+ msg->add_color_override("font_color", get_color("warning_color", "Editor"));
+ status_btn->set_icon(get_icon("StatusWarning", "EditorIcons"));
+ break;
+ case MESSAGE_SUCCESS:
+ msg->add_color_override("font_color", get_color("success_color", "Editor"));
+ status_btn->set_icon(get_icon("StatusSuccess", "EditorIcons"));
+ break;
+ }
+ }
String _test_path() {
- error->set_text("");
+ set_message(" ");
get_ok()->set_disabled(true);
DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String valid_path;
@@ -88,7 +124,7 @@ private:
}
if (valid_path == "") {
- error->set_text(TTR("Invalid project path, the path must exist!"));
+ set_message(TTR("The path does not exists."), MESSAGE_ERROR);
memdelete(d);
return "";
}
@@ -97,16 +133,35 @@ private:
if (valid_path != "" && !d->file_exists("project.godot")) {
- error->set_text(TTR("Invalid project path, project.godot must exist."));
+ set_message(TTR("Please choose a 'project.godot' file."), MESSAGE_ERROR);
memdelete(d);
return "";
}
+ } else if (mode == MODE_NEW) {
+
+ // check if the specified folder is empty, even though this is not an error, it is good to check here
+ d->list_dir_begin();
+ bool is_empty = true;
+ String n = d->get_next();
+ while (n != String()) {
+ if (!n.begins_with(".")) { // i dont know if this is enough to guarantee an empty dir
+ is_empty = false;
+ break;
+ }
+ n = d->get_next();
+ }
+ d->list_dir_end();
+
+ if (!is_empty) {
+ set_message(TTR("Your project will be created in a non empty folder (you might want to create a new folder)."), MESSAGE_WARNING);
+ }
+
} else {
if (d->file_exists("project.godot")) {
- error->set_text(TTR("Invalid project path, project.godot must not exist."));
+ set_message(TTR("Please choose a folder that does not contain a 'project.godot' file."), MESSAGE_ERROR);
memdelete(d);
return "";
}
@@ -122,16 +177,23 @@ private:
String sp = _test_path();
if (sp != "") {
- sp = sp.replace("\\", "/");
- int lidx = sp.find_last("/");
+ // set the project name to the select folder name
+ if (project_name->get_text() == "") {
+ sp = sp.replace("\\", "/");
+ int lidx = sp.find_last("/");
- if (lidx != -1) {
- sp = sp.substr(lidx + 1, sp.length());
+ if (lidx != -1) {
+ sp = sp.substr(lidx + 1, sp.length());
+ }
+ if (sp == "" && mode == MODE_IMPORT)
+ sp = TTR("Imported Project");
+
+ project_name->set_text(sp);
}
- if (sp == "" && mode == MODE_IMPORT)
- sp = TTR("Imported Project");
+ }
- project_name->set_text(sp);
+ if (created_folder_path != "" && created_folder_path != p_path) {
+ _remove_created_folder();
}
}
@@ -140,13 +202,17 @@ private:
String p = p_path;
if (mode == MODE_IMPORT) {
if (p.ends_with("project.godot")) {
-
p = p.get_base_dir();
+ get_ok()->set_disabled(false);
+ } else {
+ set_message(TTR("Please choose a 'project.godot' file."), MESSAGE_ERROR);
+ get_ok()->set_disabled(true);
+ return;
}
}
String sp = p.simplify_path();
project_path->set_text(sp);
- _path_text_changed(sp);
+ set_message(TTR(" ")); // just so it does not disappear
get_ok()->call_deferred("grab_focus");
}
@@ -155,12 +221,13 @@ private:
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() {
+ fdialog->set_current_dir(project_path->get_text());
+
if (mode == MODE_IMPORT) {
fdialog->set_mode(FileDialog::MODE_OPEN_FILE);
@@ -172,34 +239,46 @@ private:
fdialog->popup_centered_ratio();
}
- void _text_changed(const String &p_text) {
- _test_path();
- error->set_text("");
- if (p_text == "") {
+ void _create_folder() {
- error->set_text(TTR("Name cannot be empty"));
- get_ok()->set_disabled(true);
+ if (project_name->get_text() == "" || created_folder_path != "") {
return;
}
- get_ok()->set_disabled(false);
+
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (d->change_dir(project_path->get_text()) == OK) {
+ if (!d->dir_exists(project_name->get_text())) {
+ if (d->make_dir(project_name->get_text()) == OK) {
+ d->change_dir(project_name->get_text());
+ project_path->set_text(d->get_current_dir());
+ created_folder_path = d->get_current_dir();
+ create_dir->set_disabled(true);
+ }
+ }
+ }
+ memdelete(d);
}
- void _name_changed(const String &p_text) {
+ void _text_changed(const String &p_text) {
+
+ if (mode != MODE_NEW)
+ return;
+
+ _test_path();
+
+ if (p_text == "")
+ set_message(TTR("It would be a good idea to name your project."), MESSAGE_WARNING);
}
void ok_pressed() {
- String dir = _test_path();
- if (dir == "") {
- error->set_text(TTR("Invalid project path (changed anything?)."));
- return;
- }
+ String dir = project_path->get_text();
if (mode == MODE_RENAME) {
String dir = _test_path();
if (dir == "") {
- error->set_text(TTR("Invalid project path (changed anything?)."));
+ set_message(TTR("Invalid project path (changed anything?)."), MESSAGE_ERROR);
return;
}
@@ -207,13 +286,13 @@ private:
current->add_singleton(ProjectSettings::Singleton("Current"));
if (current->setup(dir, "")) {
- error->set_text(TTR("Couldn't get project.godot in project path."));
+ set_message(TTR("Couldn't get project.godot in project path."), MESSAGE_ERROR);
} else {
ProjectSettings::CustomMap edited_settings;
edited_settings["application/config/name"] = project_name->get_text();
if (current->save_custom(dir.plus_file("/project.godot"), edited_settings, Vector<String>(), true)) {
- error->set_text(TTR("Couldn't edit project.godot in project path."));
+ set_message(TTR("Couldn't edit project.godot in project path."), MESSAGE_ERROR);
}
}
@@ -232,13 +311,13 @@ private:
initial_settings["rendering/environment/default_environment"] = "res://default_env.tres";
if (ProjectSettings::get_singleton()->save_custom(dir.plus_file("/project.godot"), initial_settings, Vector<String>(), false)) {
- error->set_text(TTR("Couldn't create project.godot in project path."));
+ set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
} else {
ResourceSaver::save(dir.plus_file("/icon.png"), get_icon("DefaultProjectIcon", "EditorIcons"));
FileAccess *f = FileAccess::open(dir.plus_file("/default_env.tres"), FileAccess::WRITE);
if (!f) {
- error->set_text(TTR("Couldn't create project.godot in project path."));
+ set_message(TTR("Couldn't create project.godot in project path."), MESSAGE_ERROR);
} else {
f->store_line("[gd_resource type=\"Environment\" load_steps=2 format=2]");
f->store_line("[sub_resource type=\"ProceduralSky\" id=1]");
@@ -356,14 +435,40 @@ private:
}
}
+ void _remove_created_folder() {
+
+ if (created_folder_path != "") {
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ d->remove(created_folder_path);
+ memdelete(d);
+
+ create_dir->set_disabled(false);
+ created_folder_path = "";
+ }
+ }
+
+ void _toggle_message() {
+ msg->set_visible(!msg->is_visible());
+ }
+
+ void cancel_pressed() {
+
+ _remove_created_folder();
+
+ project_path->clear();
+ project_name->clear();
+ }
+
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);
+ ClassDB::bind_method("_browse_path", &ProjectDialog::_browse_path);
+ ClassDB::bind_method("_create_folder", &ProjectDialog::_create_folder);
+ ClassDB::bind_method("_text_changed", &ProjectDialog::_text_changed);
+ ClassDB::bind_method("_path_text_changed", &ProjectDialog::_path_text_changed);
+ ClassDB::bind_method("_path_selected", &ProjectDialog::_path_selected);
+ ClassDB::bind_method("_file_selected", &ProjectDialog::_file_selected);
+ ClassDB::bind_method("_toggle_message", &ProjectDialog::_toggle_message);
ADD_SIGNAL(MethodInfo("project_created"));
ADD_SIGNAL(MethodInfo("project_renamed"));
}
@@ -390,129 +495,129 @@ public:
if (mode == MODE_RENAME) {
project_path->set_editable(false);
- browse->set_disabled(true);
+ browse->hide();
set_title(TTR("Rename Project"));
get_ok()->set_text(TTR("Rename"));
- pp->set_text(TTR("Project Path:"));
- pn->set_text(TTR("Project Name:"));
- pn->show();
- project_name->show();
+ name_container->show();
- String dir = _test_path();
- if (dir == "") {
- error->set_text(TTR("Invalid project path (changed anything?)."));
- return;
- }
ProjectSettings *current = memnew(ProjectSettings);
current->add_singleton(ProjectSettings::Singleton("Current"));
- if (current->setup(dir, "")) {
- error->set_text(TTR("Couldn't get project.godot in project path."));
- } else {
- if (current->has("application/config/name")) {
- String appname = current->get("application/config/name");
- project_name->set_text(appname);
- }
+ if (current->setup(project_path->get_text(), "")) {
+ set_message(TTR("Couldn't get project.godot in the project path."), MESSAGE_ERROR);
+ } else if (current->has("application/config/name")) {
+ project_name->set_text(current->get("application/config/name"));
}
-
- popup_centered(Size2(500, 125) * EDSCALE);
project_name->grab_focus();
+ create_dir->hide();
+ status_btn->hide();
+
} else {
- project_path->clear();
- project_name->clear();
+ fav_dir = EditorSettings::get_singleton()->get("filesystem/directories/default_project_path");
+ if (fav_dir != "") {
+ project_path->set_text(fav_dir);
+ fdialog->set_current_dir(fav_dir);
+ } else {
+ DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ project_path->set_text(d->get_current_dir());
+ fdialog->set_current_dir(d->get_current_dir());
+ memdelete(d);
+ }
+ project_name->set_text(TTR("New Game Project"));
+
project_path->set_editable(true);
browse->set_disabled(false);
+ browse->show();
+ create_dir->show();
+ status_btn->show();
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);
+ name_container->hide();
+ project_path->grab_focus();
} 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();
+ name_container->show();
+ project_name->grab_focus();
- 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);
+ name_container->hide();
+ project_path->grab_focus();
}
- project_path->grab_focus();
_test_path();
}
+
+ popup_centered(Size2(500, 125) * EDSCALE);
}
- NewProjectDialog() {
+ ProjectDialog() {
VBoxContainer *vb = memnew(VBoxContainer);
add_child(vb);
- //set_child_rect(vb);
+
+ name_container = memnew(VBoxContainer);
+ vb->add_child(name_container);
Label *l = memnew(Label);
+ l->set_text(TTR("Project Name:"));
+ name_container->add_child(l);
+
+ HBoxContainer *pnhb = memnew(HBoxContainer);
+ name_container->add_child(pnhb);
+
+ project_name = memnew(LineEdit);
+ project_name->set_h_size_flags(SIZE_EXPAND_FILL);
+ pnhb->add_child(project_name);
+
+ create_dir = memnew(Button);
+ pnhb->add_child(create_dir);
+ create_dir->set_text(TTR("Create folder"));
+ create_dir->connect("pressed", this, "_create_folder");
+
+ path_container = memnew(VBoxContainer);
+ vb->add_child(path_container);
+
+ l = memnew(Label);
l->set_text(TTR("Project Path:"));
- vb->add_child(l);
- pp = l;
+ path_container->add_child(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);
+ path_container->add_child(pphb);
+
+ project_path = memnew(LineEdit);
project_path->set_h_size_flags(SIZE_EXPAND_FILL);
+ pphb->add_child(project_path);
+
+ // status button
+ status_btn = memnew(ToolButton);
+ status_btn->connect("pressed", this, "_toggle_message");
+ pphb->add_child(status_btn);
browse = memnew(Button);
- pphb->add_child(browse);
browse->set_text(TTR("Browse"));
browse->connect("pressed", this, "_browse_path");
+ pphb->add_child(browse);
- l = memnew(Label);
- l->set_text(TTR("Project Name:"));
- l->set_position(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);
+ msg = memnew(Label);
+ msg->set_text(TTR("That's a BINGO!"));
+ msg->set_align(Label::ALIGN_CENTER);
+ msg->hide();
+ vb->add_child(msg);
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"));
+ add_child(fdialog);
project_name->connect("text_changed", this, "_text_changed");
project_path->connect("text_changed", this, "_path_text_changed");
fdialog->connect("dir_selected", this, "_path_selected");
@@ -564,7 +669,7 @@ void ProjectManager::_panel_draw(Node *p_hb) {
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)));
+ hb->draw_style_box(gui_base->get_stylebox("selected", "Tree"), Rect2(Point2(), hb->get_size() - Size2(10, 0) * EDSCALE));
}
}
@@ -987,15 +1092,15 @@ void ProjectManager::_on_project_created(const String &dir) {
}
}
if (has_already) {
- _update_scroll_pos(dir);
+ _update_scroll_position(dir);
} else {
_load_recent_projects();
- _update_scroll_pos(dir);
+ _update_scroll_position(dir);
}
_open_project();
}
-void ProjectManager::_update_scroll_pos(const String &dir) {
+void ProjectManager::_update_scroll_position(const String &dir) {
for (int i = 0; i < scroll_childs->get_child_count(); i++) {
HBoxContainer *hb = Object::cast_to<HBoxContainer>(scroll_childs->get_child(i));
Label *fpath = Object::cast_to<Label>(hb->get_node(NodePath("project/path")));
@@ -1168,13 +1273,13 @@ void ProjectManager::_scan_projects() {
void ProjectManager::_new_project() {
- npdialog->set_mode(NewProjectDialog::MODE_NEW);
+ npdialog->set_mode(ProjectDialog::MODE_NEW);
npdialog->show_dialog();
}
void ProjectManager::_import_project() {
- npdialog->set_mode(NewProjectDialog::MODE_IMPORT);
+ npdialog->set_mode(ProjectDialog::MODE_IMPORT);
npdialog->show_dialog();
}
@@ -1188,7 +1293,7 @@ void ProjectManager::_rename_project() {
const String &selected = E->key();
String path = EditorSettings::get_singleton()->get("projects/" + selected);
npdialog->set_project_path(path);
- npdialog->set_mode(NewProjectDialog::MODE_RENAME);
+ npdialog->set_mode(ProjectDialog::MODE_RENAME);
npdialog->show_dialog();
}
}
@@ -1224,7 +1329,7 @@ void ProjectManager::_exit_dialog() {
void ProjectManager::_install_project(const String &p_zip_path, const String &p_title) {
- npdialog->set_mode(NewProjectDialog::MODE_INSTALL);
+ npdialog->set_mode(ProjectDialog::MODE_INSTALL);
npdialog->set_zip_path(p_zip_path);
npdialog->set_zip_title(p_title);
npdialog->show_dialog();
@@ -1294,7 +1399,7 @@ void ProjectManager::_bind_methods() {
ClassDB::bind_method("_load_recent_projects", &ProjectManager::_load_recent_projects);
ClassDB::bind_method("_on_project_renamed", &ProjectManager::_on_project_renamed);
ClassDB::bind_method("_on_project_created", &ProjectManager::_on_project_created);
- ClassDB::bind_method("_update_scroll_pos", &ProjectManager::_update_scroll_pos);
+ ClassDB::bind_method("_update_scroll_position", &ProjectManager::_update_scroll_position);
ClassDB::bind_method("_panel_draw", &ProjectManager::_panel_draw);
ClassDB::bind_method("_panel_input", &ProjectManager::_panel_input);
ClassDB::bind_method("_unhandled_input", &ProjectManager::_unhandled_input);
@@ -1313,7 +1418,7 @@ ProjectManager::ProjectManager() {
EditorSettings::get_singleton()->set_optimize_save(false); //just write settings as they came
{
- int dpi_mode = EditorSettings::get_singleton()->get("interface/hidpi_mode");
+ int dpi_mode = EditorSettings::get_singleton()->get("interface/editor/hidpi_mode");
if (dpi_mode == 0) {
editor_set_scale(OS::get_singleton()->get_screen_dpi(0) >= 192 && OS::get_singleton()->get_screen_size(OS::get_singleton()->get_current_screen()).x > 2000 ? 2.0 : 1.0);
} else if (dpi_mode == 1) {
@@ -1329,21 +1434,21 @@ ProjectManager::ProjectManager() {
FileDialog::set_default_show_hidden_files(EditorSettings::get_singleton()->get("filesystem/file_dialog/show_hidden_files"));
- set_area_as_parent_rect();
+ set_anchors_and_margins_preset(Control::PRESET_WIDE);
set_theme(create_editor_theme());
gui_base = memnew(Control);
add_child(gui_base);
- gui_base->set_area_as_parent_rect();
+ gui_base->set_anchors_and_margins_preset(Control::PRESET_WIDE);
gui_base->set_theme(create_custom_theme());
Panel *panel = memnew(Panel);
gui_base->add_child(panel);
- panel->set_area_as_parent_rect();
+ panel->set_anchors_and_margins_preset(Control::PRESET_WIDE);
VBoxContainer *vb = memnew(VBoxContainer);
panel->add_child(vb);
- vb->set_area_as_parent_rect(20 * EDSCALE);
+ vb->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 20 * EDSCALE);
vb->set_margin(MARGIN_TOP, 4 * EDSCALE);
vb->set_margin(MARGIN_BOTTOM, -4 * EDSCALE);
vb->add_constant_override("separation", 15 * EDSCALE);
@@ -1511,7 +1616,7 @@ ProjectManager::ProjectManager() {
OS::get_singleton()->set_low_processor_usage_mode(true);
- npdialog = memnew(NewProjectDialog);
+ npdialog = memnew(ProjectDialog);
gui_base->add_child(npdialog);
npdialog->connect("project_renamed", this, "_on_project_renamed");
diff --git a/editor/project_manager.h b/editor/project_manager.h
index 67fe0b503f..bfae0b2297 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -37,7 +37,7 @@
#include "scene/gui/tool_button.h"
#include "scene/gui/tree.h"
-class NewProjectDialog;
+class ProjectDialog;
class ProjectListFilter;
class ProjectManager : public Control {
@@ -60,7 +60,7 @@ class ProjectManager : public Control {
ConfirmationDialog *multi_scan_ask;
AcceptDialog *run_error_diag;
AcceptDialog *dialog_error;
- NewProjectDialog *npdialog;
+ ProjectDialog *npdialog;
ScrollContainer *scroll;
VBoxContainer *scroll_childs;
Map<String, String> selected_list; // name -> main_scene
@@ -90,7 +90,7 @@ class ProjectManager : public Control {
void _load_recent_projects();
void _on_project_created(const String &dir);
void _on_project_renamed();
- void _update_scroll_pos(const String &dir);
+ void _update_scroll_position(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);
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 1f65589643..56e593e34b 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -1504,7 +1504,6 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
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);
@@ -1552,7 +1551,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) {
l = memnew(Label);
l->set_text(TTR("Press a Key.."));
- l->set_area_as_parent_rect();
+ l->set_anchors_and_margins_preset(Control::PRESET_WIDE);
l->set_align(Label::ALIGN_CENTER);
l->set_margin(MARGIN_TOP, 20);
l->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_BEGIN, 30);
diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp
index c7a4e1fc3b..47ebf49c43 100644
--- a/editor/property_editor.cpp
+++ b/editor/property_editor.cpp
@@ -53,6 +53,49 @@
#include "scene/resources/packed_scene.h"
#include "scene/scene_string_names.h"
+void EditorResourceConversionPlugin::_bind_methods() {
+
+ MethodInfo mi;
+ mi.name = "_convert";
+ mi.return_val.type = Variant::OBJECT;
+ mi.return_val.class_name = "Resource";
+ mi.return_val.hint = PROPERTY_HINT_RESOURCE_TYPE;
+ mi.return_val.hint_string = "Resource";
+ mi.arguments.push_back(mi.return_val);
+ mi.arguments[0].name = "resource";
+
+ BIND_VMETHOD(mi)
+
+ mi.name = "_handles";
+ mi.return_val = PropertyInfo(Variant::BOOL, "");
+
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_converts_to"));
+}
+
+String EditorResourceConversionPlugin::converts_to() const {
+
+ if (get_script_instance())
+ return get_script_instance()->call("_converts_to");
+
+ return "";
+}
+
+bool EditorResourceConversionPlugin::handles(const Ref<Resource> &p_resource) const {
+
+ if (get_script_instance())
+ return get_script_instance()->call("_handles", p_resource);
+
+ return false;
+}
+
+Ref<Resource> EditorResourceConversionPlugin::convert(const Ref<Resource> &p_resource) {
+
+ if (get_script_instance())
+ return get_script_instance()->call("_convert", p_resource);
+
+ return Ref<Resource>();
+}
+
void CustomPropertyEditor::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
@@ -213,6 +256,20 @@ void CustomPropertyEditor::_menu_option(int p_which) {
} break;
default: {
+ if (p_which >= CONVERT_BASE_ID) {
+
+ int to_type = p_which - CONVERT_BASE_ID;
+
+ Vector<Ref<EditorResourceConversionPlugin> > conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(RES(v));
+
+ ERR_FAIL_INDEX(to_type, conversions.size());
+
+ Ref<Resource> new_res = conversions[to_type]->convert(v);
+
+ v = new_res;
+ emit_signal("variant_changed");
+ break;
+ }
ERR_FAIL_COND(inheritors_array.empty());
String intype = inheritors_array[p_which - TYPE_BASE_ID];
@@ -861,13 +918,13 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
menu->add_separator();
}
- menu->add_icon_item(get_icon("Load", "EditorIcons"), "Load", OBJ_MENU_LOAD);
+ menu->add_icon_item(get_icon("Load", "EditorIcons"), TTR("Load"), OBJ_MENU_LOAD);
if (!RES(v).is_null()) {
- menu->add_icon_item(get_icon("Edit", "EditorIcons"), "Edit", OBJ_MENU_EDIT);
- menu->add_icon_item(get_icon("Clear", "EditorIcons"), "Clear", OBJ_MENU_CLEAR);
- menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), "Make Unique", OBJ_MENU_MAKE_UNIQUE);
+ menu->add_icon_item(get_icon("Edit", "EditorIcons"), TTR("Edit"), OBJ_MENU_EDIT);
+ menu->add_icon_item(get_icon("Clear", "EditorIcons"), TTR("Clear"), OBJ_MENU_CLEAR);
+ menu->add_icon_item(get_icon("Duplicate", "EditorIcons"), TTR("Make Unique"), OBJ_MENU_MAKE_UNIQUE);
RES r = v;
if (r.is_valid() && r->get_path().is_resource_file()) {
menu->add_separator();
@@ -903,6 +960,27 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant::
}
}
+ if (!RES(v).is_null()) {
+
+ Vector<Ref<EditorResourceConversionPlugin> > conversions = EditorNode::get_singleton()->find_resource_conversion_plugin(RES(v));
+ if (conversions.size()) {
+ menu->add_separator();
+ }
+ for (int i = 0; i < conversions.size(); i++) {
+ String what = conversions[i]->converts_to();
+ Ref<Texture> icon;
+ if (has_icon(what, "EditorIcons")) {
+
+ icon = get_icon(what, "EditorIcons");
+ } else {
+
+ icon = get_icon(what, "Resource");
+ }
+
+ menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i);
+ }
+ }
+
menu->set_position(get_position());
menu->popup();
hide();
@@ -1811,7 +1889,7 @@ CustomPropertyEditor::CustomPropertyEditor() {
text_edit = memnew(TextEdit);
add_child(text_edit);
- text_edit->set_area_as_parent_rect(5);
+ text_edit->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
text_edit->set_margin(MARGIN_BOTTOM, -30);
text_edit->hide();
@@ -1870,12 +1948,12 @@ CustomPropertyEditor::CustomPropertyEditor() {
spinbox = memnew(SpinBox);
add_child(spinbox);
- spinbox->set_area_as_parent_rect(5);
+ spinbox->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
spinbox->connect("value_changed", this, "_range_modified");
slider = memnew(HSlider);
add_child(slider);
- slider->set_area_as_parent_rect(5);
+ slider->set_anchors_and_margins_preset(Control::PRESET_WIDE, Control::PRESET_MODE_MINSIZE, 5);
slider->connect("value_changed", this, "_range_modified");
create_dialog = NULL;
@@ -2355,7 +2433,7 @@ bool PropertyEditor::_is_drop_valid(const Dictionary &p_drag_data, const Diction
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);
+ p_at->set_custom_bg_color(1, get_color("accent_color", "Editor"), true);
if (p_at->get_children()) {
_mark_drop_fields(p_at->get_children());
@@ -2368,7 +2446,7 @@ void PropertyEditor::_mark_drop_fields(TreeItem *p_at) {
Variant PropertyEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) {
- TreeItem *item = tree->get_item_at_pos(p_point);
+ TreeItem *item = tree->get_item_at_position(p_point);
if (!item)
return Variant();
@@ -2376,7 +2454,7 @@ Variant PropertyEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from)
if (!d.has("name"))
return Variant();
- int col = tree->get_column_at_pos(p_point);
+ int col = tree->get_column_at_position(p_point);
if (col == 0) {
Dictionary dp;
@@ -2407,11 +2485,11 @@ Variant PropertyEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from)
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);
+ TreeItem *item = tree->get_item_at_position(p_point);
if (!item)
return false;
- int col = tree->get_column_at_pos(p_point);
+ int col = tree->get_column_at_position(p_point);
if (col != 1)
return false;
@@ -2419,11 +2497,11 @@ bool PropertyEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_da
}
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);
+ TreeItem *item = tree->get_item_at_position(p_point);
if (!item)
return;
- int col = tree->get_column_at_pos(p_point);
+ int col = tree->get_column_at_position(p_point);
if (col != 1)
return;
@@ -2507,10 +2585,10 @@ void PropertyEditor::_notification(int p_what) {
}
}
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
if (refresh_countdown > 0) {
- refresh_countdown -= get_fixed_process_delta_time();
+ refresh_countdown -= get_physics_process_delta_time();
if (refresh_countdown <= 0) {
TreeItem *root = tree->get_root();
_refresh_item(root);
@@ -2880,7 +2958,7 @@ void PropertyEditor::update_tree() {
item->set_metadata(1, p.name);
if (draw_red)
- item->set_custom_color(0, Color(0.8, 0.4, 0.20));
+ item->set_custom_color(0, get_color("error_color", "Editor"));
if (p.name == selected_property) {
@@ -3460,14 +3538,14 @@ void PropertyEditor::_draw_transparency(Object *t, const Rect2 &p_rect) {
return;
Color color = obj->get(ti->get_metadata(1));
- Ref<Texture> arrow = tree->get_icon("select_arrow");
+ Ref<Texture> arrow = tree->get_icon("select_option");
// make a little space between consecutive color fields
Rect2 area = p_rect;
area.position.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_texture_rect(get_icon("GuiMiniCheckerboard", "EditorIcons"), area, true);
tree->draw_rect(area, color);
}
@@ -4149,7 +4227,7 @@ PropertyEditor::PropertyEditor() {
tree->set_drag_forwarding(this);
- set_fixed_process(true);
+ set_physics_process(true);
custom_editor = memnew(CustomPropertyEditor);
add_child(custom_editor);
@@ -4179,7 +4257,7 @@ PropertyEditor::PropertyEditor() {
use_filter = false;
subsection_selectable = false;
property_selectable = false;
- show_type_icons = EDITOR_DEF("interface/show_type_icons", false);
+ show_type_icons = EDITOR_DEF("interface/editor/show_type_icons", false);
}
PropertyEditor::~PropertyEditor() {
diff --git a/editor/property_editor.h b/editor/property_editor.h
index bfd5ee401e..e69ca8bcd5 100644
--- a/editor/property_editor.h
+++ b/editor/property_editor.h
@@ -53,6 +53,19 @@ class PropertyValueEvaluator;
class CreateDialog;
class PropertySelector;
+class EditorResourceConversionPlugin : public Reference {
+
+ GDCLASS(EditorResourceConversionPlugin, Reference)
+
+protected:
+ static void _bind_methods();
+
+public:
+ virtual String converts_to() const;
+ virtual bool handles(const Ref<Resource> &p_resource) const;
+ virtual Ref<Resource> convert(const Ref<Resource> &p_resource);
+};
+
class CustomPropertyEditor : public Popup {
GDCLASS(CustomPropertyEditor, Popup);
@@ -68,7 +81,8 @@ class CustomPropertyEditor : public Popup {
OBJ_MENU_PASTE = 5,
OBJ_MENU_NEW_SCRIPT = 6,
OBJ_MENU_SHOW_IN_FILE_SYSTEM = 7,
- TYPE_BASE_ID = 100
+ TYPE_BASE_ID = 100,
+ CONVERT_BASE_ID = 1000
};
enum {
diff --git a/editor/quick_open.cpp b/editor/quick_open.cpp
index b92ebed167..4bcbe073ee 100644
--- a/editor/quick_open.cpp
+++ b/editor/quick_open.cpp
@@ -189,7 +189,7 @@ Vector<Pair<String, Ref<Texture> > > EditorQuickOpen::_sort_fs(Vector<Pair<Strin
Vector<Pair<String, Ref<Texture> > > sorted_list;
if (search_text == String() || list.size() == 0)
- return sorted_list;
+ return list;
Vector<float> scores;
scores.resize(list.size());
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 5b783493cb..f3e59932c4 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -270,6 +270,18 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
switch (p_tool) {
case TOOL_NEW: {
+
+ String preferred = "";
+ Node *current_edited_scene_root = EditorNode::get_singleton()->get_edited_scene();
+
+ if (current_edited_scene_root) {
+
+ if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Node2D"))
+ preferred = "Node2D";
+ else if (ClassDB::is_parent_class(current_edited_scene_root->get_class_name(), "Spatial"))
+ preferred = "Spatial";
+ }
+ create_dialog->set_preferred_search_result_type(preferred);
create_dialog->popup_create(true);
} break;
case TOOL_INSTANCE: {
@@ -2016,6 +2028,5 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel
clear_inherit_confirm->get_ok()->set_text(TTR("Clear!"));
add_child(clear_inherit_confirm);
- vbc->add_constant_override("separation", 4);
set_process_input(true);
}
diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp
index 87b4d2a867..6dcd5e54ec 100644
--- a/editor/scene_tree_editor.cpp
+++ b/editor/scene_tree_editor.cpp
@@ -185,7 +185,7 @@ bool SceneTreeEditor::_add_nodes(Node *p_node, TreeItem *p_parent) {
if (part_of_subscene) {
//item->set_selectable(0,marked_selectable);
- item->set_custom_color(0, get_color("error_color", "Editor").linear_interpolate(get_color("warning_color", "Editor"), 0.4));
+ item->set_custom_color(0, get_color("disabled_font_color", "Editor"));
} else if (marked.has(p_node)) {
@@ -345,7 +345,7 @@ void SceneTreeEditor::_update_visibility_color(Node *p_node, TreeItem *p_item) {
Color color(1, 1, 1, 1);
bool visible_on_screen = p_node->call("is_visible_in_tree");
if (!visible_on_screen) {
- color = Color(0.6, 0.6, 0.6, 1);
+ color.a = 0.6;
}
int idx = p_item->get_button_by_id(0, BUTTON_VISIBILITY);
p_item->set_button_color(0, idx, color);
@@ -817,11 +817,11 @@ bool SceneTreeEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_d
if (!d.has("type"))
return false;
- TreeItem *item = tree->get_item_at_pos(p_point);
+ TreeItem *item = tree->get_item_at_position(p_point);
if (!item)
return false;
- int section = tree->get_drop_section_at_pos(p_point);
+ int section = tree->get_drop_section_at_position(p_point);
if (section < -1 || (section == -1 && !item->get_parent()))
return false;
@@ -860,10 +860,10 @@ void SceneTreeEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data,
if (!can_drop_data_fw(p_point, p_data, p_from))
return;
- TreeItem *item = tree->get_item_at_pos(p_point);
+ TreeItem *item = tree->get_item_at_position(p_point);
if (!item)
return;
- int section = tree->get_drop_section_at_pos(p_point);
+ int section = tree->get_drop_section_at_position(p_point);
if (section < -1)
return;
@@ -950,7 +950,7 @@ void SceneTreeEditor::_bind_methods() {
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("rmb_pressed", PropertyInfo(Variant::VECTOR2, "position")));
ADD_SIGNAL(MethodInfo("open"));
ADD_SIGNAL(MethodInfo("open_script"));
diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp
index 284b25801c..5ad4674f7f 100644
--- a/editor/script_editor_debugger.cpp
+++ b/editor/script_editor_debugger.cpp
@@ -649,8 +649,8 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
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];
+ metric.physics_time = p_data[3];
+ metric.physics_frame_time = p_data[4];
int frame_data_amount = p_data[6];
int frame_function_amount = p_data[7];
@@ -664,9 +664,9 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
item.calls = 1;
item.line = 0;
item.name = "Fixed Time";
- item.total = metric.fixed_time;
+ item.total = metric.physics_time;
item.self = item.total;
- item.signature = "fixed_time";
+ item.signature = "physics_time";
frame_time.items.push_back(item);
@@ -678,9 +678,9 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da
frame_time.items.push_back(item);
item.name = "Fixed Frame Time";
- item.total = metric.fixed_frame_time;
+ item.total = metric.physics_frame_time;
item.self = item.total;
- item.signature = "fixed_frame_time";
+ item.signature = "physics_frame_time";
frame_time.items.push_back(item);
@@ -1045,6 +1045,8 @@ void ScriptEditorDebugger::_notification(int p_what) {
tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles"));
tabs->add_style_override("tab_fg", editor->get_gui_base()->get_stylebox("DebuggerTabFG", "EditorStyles"));
tabs->add_style_override("tab_bg", editor->get_gui_base()->get_stylebox("DebuggerTabBG", "EditorStyles"));
+ tabs->set_margin(MARGIN_LEFT, -EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT));
+ tabs->set_margin(MARGIN_RIGHT, EditorNode::get_singleton()->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT));
} break;
}
}
@@ -1065,7 +1067,7 @@ void ScriptEditorDebugger::start() {
int remote_port = (int)EditorSettings::get_singleton()->get("network/debug/remote_port");
if (server->listen(remote_port) != OK) {
- EditorNode::get_log()->add_message(String("** Error listening on port ") + itos(remote_port) + String(" **"));
+ EditorNode::get_log()->add_message(String("Error listening on port ") + itos(remote_port), true);
return;
}
set_process(true);
@@ -1622,8 +1624,10 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) {
tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles"));
tabs->add_style_override("tab_fg", editor->get_gui_base()->get_stylebox("DebuggerTabFG", "EditorStyles"));
tabs->add_style_override("tab_bg", editor->get_gui_base()->get_stylebox("DebuggerTabBG", "EditorStyles"));
- tabs->set_v_size_flags(SIZE_EXPAND_FILL);
- tabs->set_area_as_parent_rect();
+
+ tabs->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ tabs->set_margin(MARGIN_LEFT, -editor->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_LEFT));
+ tabs->set_margin(MARGIN_RIGHT, editor->get_gui_base()->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")->get_margin(MARGIN_RIGHT));
add_child(tabs);
{ //debugger
diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h
index 6cb5f0a70c..64ac2535a9 100644
--- a/editor/script_editor_debugger.h
+++ b/editor/script_editor_debugger.h
@@ -150,7 +150,7 @@ class ScriptEditorDebugger : public Control {
void _scene_tree_selected();
void _scene_tree_request();
void _parse_message(const String &p_msg, const Array &p_data);
- void _set_reason_text(const String &p_msg, MessageType p_type);
+ void _set_reason_text(const String &p_reason, MessageType p_type);
void _scene_tree_property_select_object(ObjectID p_object);
void _scene_tree_property_value_edited(const String &p_prop, const Variant &p_value);
diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp
index 05e3feedb5..5f6ffcb14e 100644
--- a/editor/settings_config_dialog.cpp
+++ b/editor/settings_config_dialog.cpp
@@ -58,6 +58,8 @@ void EditorSettingsDialog::_settings_property_edited(const String &p_name) {
// color theme is changed
if (full_name == "text_editor/theme/color_theme") {
property_editor->get_property_editor()->update_tree();
+ } else if (full_name == "interface/theme/accent_color" || full_name == "interface/theme/base_color" || full_name == "interface/theme/contrast") {
+ EditorSettings::get_singleton()->set_manually("interface/theme/preset", 6); // set preset to Custom
}
}
@@ -334,6 +336,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
property_editor->get_property_editor()->set_use_filter(true);
property_editor->register_search_box(search_box);
property_editor->set_v_size_flags(Control::SIZE_EXPAND_FILL);
+ property_editor->get_property_editor()->set_undo_redo(EditorNode::get_singleton()->get_undo_redo());
vbc->add_child(property_editor);
property_editor->get_property_editor()->connect("property_edited", this, "_settings_property_edited");
@@ -374,7 +377,7 @@ EditorSettingsDialog::EditorSettingsDialog() {
l = memnew(Label);
l->set_text(TTR("Press a Key.."));
- l->set_area_as_parent_rect();
+ l->set_anchors_and_margins_preset(Control::PRESET_WIDE);
l->set_align(Label::ALIGN_CENTER);
l->set_margin(MARGIN_TOP, 20);
l->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_BEGIN, 30);
diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp
index 9c7ea506aa..3c1889e829 100644
--- a/editor/spatial_editor_gizmos.cpp
+++ b/editor/spatial_editor_gizmos.cpp
@@ -211,9 +211,10 @@ void EditorSpatialGizmo::add_unscaled_billboard(const Ref<Material> &p_material,
instances.push_back(ins);
}
-void EditorSpatialGizmo::add_collision_triangles(const Ref<TriangleMesh> &p_tmesh) {
+void EditorSpatialGizmo::add_collision_triangles(const Ref<TriangleMesh> &p_tmesh, const Rect3 &p_bounds) {
collision_mesh = p_tmesh;
+ collision_mesh_bounds = p_bounds;
}
void EditorSpatialGizmo::add_collision_segments(const Vector<Vector3> &p_lines) {
@@ -359,6 +360,29 @@ bool EditorSpatialGizmo::intersect_frustum(const Camera *p_camera, const Vector<
return false;
}
+ if (collision_mesh_bounds.size != Vector3(0.0, 0.0, 0.0)) {
+ Transform t = spatial_node->get_global_transform();
+ const Plane *p = p_frustum.ptr();
+ int fc = p_frustum.size();
+
+ Vector3 mins = t.xform(collision_mesh_bounds.get_position());
+ Vector3 max = t.xform(collision_mesh_bounds.get_position() + collision_mesh_bounds.get_size());
+
+ bool any_out = false;
+
+ for (int j = 0; j < fc; j++) {
+
+ if (p[j].distance_to(mins) > 0 || p[j].distance_to(max) > 0) {
+
+ any_out = true;
+ break;
+ }
+ }
+
+ if (!any_out)
+ return true;
+ }
+
return false;
}
@@ -637,7 +661,7 @@ void EditorSpatialGizmo::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_lines", "lines", "material", "billboard"), &EditorSpatialGizmo::add_lines, DEFVAL(false));
ClassDB::bind_method(D_METHOD("add_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"), &EditorSpatialGizmo::add_collision_triangles);
+ ClassDB::bind_method(D_METHOD("add_collision_triangles", "triangles", "bounds"), &EditorSpatialGizmo::add_collision_triangles);
ClassDB::bind_method(D_METHOD("add_unscaled_billboard", "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"), &EditorSpatialGizmo::_set_spatial_node);
@@ -720,7 +744,7 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec
}
//min_p = p_arc_xform.affine_inverse().xform(min_p);
- float a = Vector2(min_p.x, -min_p.z).angle();
+ float a = (Math_PI * 0.5) - Vector2(min_p.x, -min_p.z).angle();
return a * 180.0 / Math_PI;
}
@@ -869,7 +893,7 @@ void LightSpatialGizmo::redraw() {
if (Object::cast_to<SpotLight>(light)) {
- Ref<Material> material = create_material("light_spot_material", gizmo_color, true);
+ Ref<Material> material = create_material("light_spot_material", gizmo_color);
Ref<Material> icon = create_icon_material("light_spot_icon", SpatialEditor::get_singleton()->get_icon("GizmoSpotLight", "EditorIcons"));
clear();
@@ -1249,8 +1273,10 @@ void MeshInstanceSpatialGizmo::redraw() {
return; //none
Ref<TriangleMesh> tm = m->generate_triangle_mesh();
- if (tm.is_valid())
- add_collision_triangles(tm);
+ if (tm.is_valid()) {
+ Rect3 aabb;
+ add_collision_triangles(tm, aabb);
+ }
}
MeshInstanceSpatialGizmo::MeshInstanceSpatialGizmo(MeshInstance *p_mesh) {
diff --git a/editor/spatial_editor_gizmos.h b/editor/spatial_editor_gizmos.h
index d63a804055..afe64c723c 100644
--- a/editor/spatial_editor_gizmos.h
+++ b/editor/spatial_editor_gizmos.h
@@ -78,6 +78,7 @@ class EditorSpatialGizmo : public SpatialEditorGizmo {
Vector<Vector3> collision_segments;
Ref<TriangleMesh> collision_mesh;
+ Rect3 collision_mesh_bounds;
struct Handle {
Vector3 pos;
@@ -99,7 +100,7 @@ protected:
void add_lines(const Vector<Vector3> &p_lines, const Ref<Material> &p_material, bool p_billboard = false);
void add_mesh(const Ref<ArrayMesh> &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_collision_triangles(const Ref<TriangleMesh> &p_tmesh, const Rect3 &p_bounds = Rect3());
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 add_solid_box(Ref<Material> &p_material, Vector3 size);
diff --git a/editor/translations/ar.po b/editor/translations/ar.po
index ac273ea41e..f98fa91e30 100644
--- a/editor/translations/ar.po
+++ b/editor/translations/ar.po
@@ -4449,15 +4449,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/bg.po b/editor/translations/bg.po
index 2ac4e53dd8..4e119a5fad 100644
--- a/editor/translations/bg.po
+++ b/editor/translations/bg.po
@@ -4470,15 +4470,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/bn.po b/editor/translations/bn.po
index 64b0c0c528..7be067aedd 100644
--- a/editor/translations/bn.po
+++ b/editor/translations/bn.po
@@ -4621,15 +4621,15 @@ msgid "Curve Point #"
msgstr "বক্ররেখার বিন্দু #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "বক্ররেখার বিন্দুর স্থান নির্ধারণ করুন"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "আন্ত-বক্ররেখার স্থান নির্ধারণ করুন"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "বহিঃ-বক্ররেখার স্থান নির্ধারণ করুন"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/ca.po b/editor/translations/ca.po
index 4b126e3b16..80f4b246b5 100644
--- a/editor/translations/ca.po
+++ b/editor/translations/ca.po
@@ -4582,15 +4582,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/cs.po b/editor/translations/cs.po
index c7871ef60d..929aa6eb30 100644
--- a/editor/translations/cs.po
+++ b/editor/translations/cs.po
@@ -4495,15 +4495,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/da.po b/editor/translations/da.po
index d33fef1743..47409d5293 100644
--- a/editor/translations/da.po
+++ b/editor/translations/da.po
@@ -4485,15 +4485,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/de.po b/editor/translations/de.po
index 837df7d62b..98e2e35922 100644
--- a/editor/translations/de.po
+++ b/editor/translations/de.po
@@ -4593,15 +4593,15 @@ msgid "Curve Point #"
msgstr "Kurvenpunkt #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Position des Kurvenpunkts setzen"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "Position der Eingangskurve setzen"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "Position der Ausgangskurve setzen"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/de_CH.po b/editor/translations/de_CH.po
index 4e40c4c9bb..c5234c20d9 100644
--- a/editor/translations/de_CH.po
+++ b/editor/translations/de_CH.po
@@ -4496,15 +4496,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/editor.pot b/editor/translations/editor.pot
index 7227b0ec2d..a1247ab925 100644
--- a/editor/translations/editor.pot
+++ b/editor/translations/editor.pot
@@ -4436,15 +4436,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/el.po b/editor/translations/el.po
index 21adc08c3f..0532753542 100644
--- a/editor/translations/el.po
+++ b/editor/translations/el.po
@@ -4577,15 +4577,15 @@ msgid "Curve Point #"
msgstr "Σημείο καμπύλης #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Ορισμός θέσης σημείου καμπύλης"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "Ορισμός θέσης εισόδου καμπύλης"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "Ορισμός θέσης εξόδου καμπύλης"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/es.po b/editor/translations/es.po
index da7bd97b83..8b2cab5fb9 100644
--- a/editor/translations/es.po
+++ b/editor/translations/es.po
@@ -4672,15 +4672,15 @@ msgid "Curve Point #"
msgstr "Nº de punto en curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Establecer pos. de punto de curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "Establecer pos. de entrada de curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "Establecer pos. de salida de curva"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/es_AR.po b/editor/translations/es_AR.po
index 64d65f70bb..dd5f8ad597 100644
--- a/editor/translations/es_AR.po
+++ b/editor/translations/es_AR.po
@@ -4572,15 +4572,15 @@ msgid "Curve Point #"
msgstr "Punto # de Curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Setear Pos. de Punto de Curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "Setear Pos. In de Curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "Setear Pos. Out de Curva"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/fa.po b/editor/translations/fa.po
index 8afc7bc844..7b77165a53 100644
--- a/editor/translations/fa.po
+++ b/editor/translations/fa.po
@@ -4514,15 +4514,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/fi.po b/editor/translations/fi.po
index 6cd55dbc6a..af1d46eae0 100644
--- a/editor/translations/fi.po
+++ b/editor/translations/fi.po
@@ -4577,15 +4577,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/fr.po b/editor/translations/fr.po
index c499138c77..4e3aad6cf6 100644
--- a/editor/translations/fr.po
+++ b/editor/translations/fr.po
@@ -4662,15 +4662,15 @@ msgid "Curve Point #"
msgstr "Point de courbe #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Définir la position du point de la courbe"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/hu.po b/editor/translations/hu.po
index d21541c339..a8681feaf5 100644
--- a/editor/translations/hu.po
+++ b/editor/translations/hu.po
@@ -4441,15 +4441,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/id.po b/editor/translations/id.po
index 6fbf6fabde..2f13c11082 100644
--- a/editor/translations/id.po
+++ b/editor/translations/id.po
@@ -4564,15 +4564,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/it.po b/editor/translations/it.po
index 9ca5debd55..060e9551e0 100644
--- a/editor/translations/it.po
+++ b/editor/translations/it.po
@@ -4573,15 +4573,15 @@ msgid "Curve Point #"
msgstr "Punto Curva #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Imposta Posizione Punti curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "Imposta Posizione Curve In"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "Imposta Posizione Curve Out"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/ja.po b/editor/translations/ja.po
index 0cbbe217bb..51c481f3d4 100644
--- a/editor/translations/ja.po
+++ b/editor/translations/ja.po
@@ -5250,17 +5250,17 @@ msgstr "曲線のポイント#"
#: editor/plugins/path_editor_plugin.cpp
#, fuzzy
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "曲線のポイントの位置を指定"
#: editor/plugins/path_editor_plugin.cpp
#, fuzzy
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "曲線のIn-ハンドルの位置を指定"
#: editor/plugins/path_editor_plugin.cpp
#, fuzzy
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "曲線のOut-ハンドルの位置を指定"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/ko.po b/editor/translations/ko.po
index b531720ebd..f559faf1f3 100644
--- a/editor/translations/ko.po
+++ b/editor/translations/ko.po
@@ -4606,15 +4606,15 @@ msgid "Curve Point #"
msgstr "커브 포인트 #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "커브 포인트 위치 설정"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "커브 포인트 In 설정"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "커브 포인트 Out 설정"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/nb.po b/editor/translations/nb.po
index eb230cc1ac..6dc635daa6 100644
--- a/editor/translations/nb.po
+++ b/editor/translations/nb.po
@@ -4454,15 +4454,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/nl.po b/editor/translations/nl.po
index 0b8a154735..b13d86e0f2 100644
--- a/editor/translations/nl.po
+++ b/editor/translations/nl.po
@@ -4517,15 +4517,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/pl.po b/editor/translations/pl.po
index d9234269fd..baffd09f33 100644
--- a/editor/translations/pl.po
+++ b/editor/translations/pl.po
@@ -4644,15 +4644,15 @@ msgid "Curve Point #"
msgstr "Punkt Krzywej #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Ustaw pozycje punktu krzywej"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/pr.po b/editor/translations/pr.po
index 418072c117..9fbc17c9ca 100644
--- a/editor/translations/pr.po
+++ b/editor/translations/pr.po
@@ -4452,15 +4452,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/pt_BR.po b/editor/translations/pt_BR.po
index 7d0ff7cb95..ed2bbb2fd3 100644
--- a/editor/translations/pt_BR.po
+++ b/editor/translations/pt_BR.po
@@ -4599,15 +4599,15 @@ msgid "Curve Point #"
msgstr "Ponto da Curva nº"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Definir Pos do Ponto da Curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "Definir Pos da Entrada da Curva"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "Definir Pos da Saída da Curva"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/pt_PT.po b/editor/translations/pt_PT.po
index 527bff68fd..7a178acdd5 100644
--- a/editor/translations/pt_PT.po
+++ b/editor/translations/pt_PT.po
@@ -4451,15 +4451,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/ru.po b/editor/translations/ru.po
index 92755d427b..61d7ae7dae 100644
--- a/editor/translations/ru.po
+++ b/editor/translations/ru.po
@@ -4571,15 +4571,15 @@ msgid "Curve Point #"
msgstr "Точка Кривой #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Установить позицию точки кривой"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "Установить позицию входа кривой"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "Установить позицию выхода кривой"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/sk.po b/editor/translations/sk.po
index b7ac0a7864..381e5c53d1 100644
--- a/editor/translations/sk.po
+++ b/editor/translations/sk.po
@@ -4462,15 +4462,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/sl.po b/editor/translations/sl.po
index daa7533a8c..ff62db99ae 100644
--- a/editor/translations/sl.po
+++ b/editor/translations/sl.po
@@ -4452,15 +4452,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/th.po b/editor/translations/th.po
index e89bbf043a..0ccaf81e71 100644
--- a/editor/translations/th.po
+++ b/editor/translations/th.po
@@ -4531,15 +4531,15 @@ msgid "Curve Point #"
msgstr "จุดเส้นโค้ง #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "กำหนดพิกัดจุดเส้นโค้ง"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "กำหนดเส้นโค้งขาเข้า"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "กำหนดเส้นโค้งขาออก"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/tr.po b/editor/translations/tr.po
index df749f5c9b..dd10336bca 100644
--- a/editor/translations/tr.po
+++ b/editor/translations/tr.po
@@ -4610,15 +4610,15 @@ msgid "Curve Point #"
msgstr "Eğrisel Nokta #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "Eğri Noktası Konumu Ayarla"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "Eğriyi Konumda Ayarla"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "Eğri Çıkış Konumunu Ayarla"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/ur_PK.po b/editor/translations/ur_PK.po
index 24796e1f32..41384a79da 100644
--- a/editor/translations/ur_PK.po
+++ b/editor/translations/ur_PK.po
@@ -4455,15 +4455,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/zh_CN.po b/editor/translations/zh_CN.po
index cf9013091a..f725bf6a5e 100644
--- a/editor/translations/zh_CN.po
+++ b/editor/translations/zh_CN.po
@@ -4525,15 +4525,15 @@ msgid "Curve Point #"
msgstr "曲线定点 #"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr "设置曲线顶点坐标"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr "设置的曲线输入位置(Pos)"
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr "设置曲线输出位置(Pos)"
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/zh_HK.po b/editor/translations/zh_HK.po
index f04322ff3c..ceb21d7b85 100644
--- a/editor/translations/zh_HK.po
+++ b/editor/translations/zh_HK.po
@@ -4515,15 +4515,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/editor/translations/zh_TW.po b/editor/translations/zh_TW.po
index 8ed54a0798..f845efea17 100644
--- a/editor/translations/zh_TW.po
+++ b/editor/translations/zh_TW.po
@@ -4474,15 +4474,15 @@ msgid "Curve Point #"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Point Pos"
+msgid "Set Curve Point Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve In Pos"
+msgid "Set Curve In Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
-msgid "Set Curve Out Pos"
+msgid "Set Curve Out Position"
msgstr ""
#: editor/plugins/path_editor_plugin.cpp
diff --git a/main/input_default.cpp b/main/input_default.cpp
index b4c9a6207f..2940f432d5 100644
--- a/main/input_default.cpp
+++ b/main/input_default.cpp
@@ -80,7 +80,7 @@ bool InputDefault::is_key_pressed(int p_scancode) const {
bool InputDefault::is_mouse_button_pressed(int p_button) const {
_THREAD_SAFE_METHOD_
- return (mouse_button_mask & (1 << p_button)) != 0;
+ return (mouse_button_mask & (1 << (p_button - 1))) != 0;
}
static int _combine_device(int p_value, int p_device) {
@@ -105,8 +105,8 @@ bool InputDefault::is_action_just_pressed(const StringName &p_action) const {
if (!E)
return false;
- if (Engine::get_singleton()->is_in_fixed_frame()) {
- return E->get().pressed && E->get().fixed_frame == Engine::get_singleton()->get_fixed_frames();
+ if (Engine::get_singleton()->is_in_physics_frame()) {
+ return E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
} else {
return E->get().pressed && E->get().idle_frame == Engine::get_singleton()->get_idle_frames();
}
@@ -118,8 +118,8 @@ bool InputDefault::is_action_just_released(const StringName &p_action) const {
if (!E)
return false;
- if (Engine::get_singleton()->is_in_fixed_frame()) {
- return !E->get().pressed && E->get().fixed_frame == Engine::get_singleton()->get_fixed_frames();
+ if (Engine::get_singleton()->is_in_physics_frame()) {
+ return !E->get().pressed && E->get().physics_frame == Engine::get_singleton()->get_physics_frames();
} else {
return !E->get().pressed && E->get().idle_frame == Engine::get_singleton()->get_idle_frames();
}
@@ -265,10 +265,11 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
if (mb.is_valid() && !mb->is_doubleclick()) {
- if (mb->is_pressed())
- mouse_button_mask |= (1 << mb->get_button_index());
- else
- mouse_button_mask &= ~(1 << mb->get_button_index());
+ if (mb->is_pressed()) {
+ mouse_button_mask |= (1 << (mb->get_button_index() - 1));
+ } else {
+ mouse_button_mask &= ~(1 << (mb->get_button_index() - 1));
+ }
if (main_loop && emulate_touch && mb->get_button_index() == 1) {
Ref<InputEventScreenTouch> touch_event;
@@ -323,7 +324,7 @@ void InputDefault::parse_input_event(const Ref<InputEvent> &p_event) {
if (InputMap::get_singleton()->event_is_action(p_event, E->key()) && is_action_pressed(E->key()) != p_event->is_pressed()) {
Action action;
- action.fixed_frame = Engine::get_singleton()->get_fixed_frames();
+ action.physics_frame = Engine::get_singleton()->get_physics_frames();
action.idle_frame = Engine::get_singleton()->get_idle_frames();
action.pressed = p_event->is_pressed();
action_state[E->key()] = action;
@@ -421,9 +422,9 @@ int InputDefault::get_mouse_button_mask() const {
return mouse_button_mask; // do not trust OS implementaiton, should remove it - OS::get_singleton()->get_mouse_button_state();
}
-void InputDefault::warp_mouse_pos(const Vector2 &p_to) {
+void InputDefault::warp_mouse_position(const Vector2 &p_to) {
- OS::get_singleton()->warp_mouse_pos(p_to);
+ OS::get_singleton()->warp_mouse_position(p_to);
}
Point2i InputDefault::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect) {
@@ -446,7 +447,7 @@ Point2i InputDefault::warp_mouse_motion(const Ref<InputEventMouseMotion> &p_moti
const Point2i pos_local = p_motion->get_global_position() - p_rect.position;
const Point2i pos_warped(Math::fposmod(pos_local.x, p_rect.size.x), Math::fposmod(pos_local.y, p_rect.size.y));
if (pos_warped != pos_local) {
- OS::get_singleton()->warp_mouse_pos(pos_warped + p_rect.position);
+ OS::get_singleton()->warp_mouse_position(pos_warped + p_rect.position);
}
return rel_warped;
@@ -459,7 +460,7 @@ void InputDefault::action_press(const StringName &p_action) {
Action action;
- action.fixed_frame = Engine::get_singleton()->get_fixed_frames();
+ action.physics_frame = Engine::get_singleton()->get_physics_frames();
action.idle_frame = Engine::get_singleton()->get_idle_frames();
action.pressed = true;
@@ -470,7 +471,7 @@ void InputDefault::action_release(const StringName &p_action) {
Action action;
- action.fixed_frame = Engine::get_singleton()->get_fixed_frames();
+ action.physics_frame = Engine::get_singleton()->get_physics_frames();
action.idle_frame = Engine::get_singleton()->get_idle_frames();
action.pressed = false;
diff --git a/main/input_default.h b/main/input_default.h
index 345c34c55e..e2cb03e67c 100644
--- a/main/input_default.h
+++ b/main/input_default.h
@@ -51,7 +51,7 @@ class InputDefault : public Input {
MainLoop *main_loop;
struct Action {
- uint64_t fixed_frame;
+ uint64_t physics_frame;
uint64_t idle_frame;
bool pressed;
};
@@ -200,7 +200,7 @@ public:
virtual Point2 get_last_mouse_speed() const;
virtual int get_mouse_button_mask() const;
- virtual void warp_mouse_pos(const Vector2 &p_to);
+ virtual void warp_mouse_position(const Vector2 &p_to);
virtual Point2i warp_mouse_motion(const Ref<InputEventMouseMotion> &p_motion, const Rect2 &p_rect);
virtual void parse_input_event(const Ref<InputEvent> &p_event);
diff --git a/main/main.cpp b/main/main.cpp
index bb601198db..48df37ac63 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -74,6 +74,7 @@
#include "performance.h"
#include "translation.h"
#include "version.h"
+#include "version_hash.gen.h"
static ProjectSettings *globals = NULL;
static Engine *engine = NULL;
@@ -122,6 +123,14 @@ static String unescape_cmdline(const String &p_str) {
return p_str.replace("%20", " ");
}
+static String get_full_version_string() {
+
+ String hash = String(VERSION_HASH);
+ if (hash.length() != 0)
+ hash = "." + hash.left(7);
+ return String(VERSION_MKSTRING) + hash;
+}
+
//#define DEBUG_INIT
#ifdef DEBUG_INIT
@@ -132,7 +141,7 @@ static String unescape_cmdline(const String &p_str) {
void Main::print_help(const char *p_binary) {
- OS::get_singleton()->print(VERSION_FULL_NAME " - https://godotengine.org\n");
+ print_line(String(_MKSTR(VERSION_NAME)) + " v" + get_full_version_string() + " - https://godotengine.org");
OS::get_singleton()->print("(c) 2007-2017 Juan Linietsky, Ariel Manzur.\n");
OS::get_singleton()->print("(c) 2014-2017 Godot Engine contributors.\n");
OS::get_singleton()->print("\n");
@@ -141,6 +150,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print("General options:\n");
OS::get_singleton()->print(" -h, --help Display this help message.\n");
+ OS::get_singleton()->print(" --version Display the version string.\n");
OS::get_singleton()->print(" -v, --verbose Use verbose stdout mode.\n");
OS::get_singleton()->print(" --quiet Quiet mode, silences stdout messages. Errors are still displayed.\n");
OS::get_singleton()->print("\n");
@@ -195,7 +205,7 @@ void Main::print_help(const char *p_binary) {
OS::get_singleton()->print(" --time-scale <scale> Force time scale (higher values are faster, 1.0 is normal speed).\n");
OS::get_singleton()->print(" --disable-render-loop Disable render loop so rendering only occurs when called explicitly from script.\n");
OS::get_singleton()->print(" --disable-crash-handler Disable crash handler when supported by the platform code.\n");
- OS::get_singleton()->print(" --fixed-fps <fps> Forces a fixed ratio between process and fixed_process timing, for use when precision is required, or when rendering to video files. Setting this will disable real-time syncronization, so that run speed is only capped by performance\n");
+ OS::get_singleton()->print(" --fixed-fps <fps> Force a fixed number of frames per second. This setting disables real-time synchronization.\n");
OS::get_singleton()->print("\n");
OS::get_singleton()->print("Standalone tools:\n");
@@ -203,7 +213,7 @@ void Main::print_help(const char *p_binary) {
#ifdef TOOLS_ENABLED
OS::get_singleton()->print(" --export <target> Export the project using the given export target.\n");
OS::get_singleton()->print(" --export-debug Use together with --export, enables debug mode for the template.\n");
- OS::get_singleton()->print(" --doctool <file> Dump the whole engine API to <file> in XML format. If <file> exists, it will be merged.\n");
+ OS::get_singleton()->print(" --doctool <path> Dump the engine API reference to the given <path> in XML format, merging if existing files are found.\n");
OS::get_singleton()->print(" --no-docbase Disallow dumping the base types (used with --doctool).\n");
#ifdef DEBUG_METHODS_ENABLED
OS::get_singleton()->print(" --gdnative-generate-json-api Generate JSON dump of the Godot API for GDNative bindings.\n");
@@ -221,7 +231,6 @@ void Main::print_help(const char *p_binary) {
}
Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_phase) {
-
RID_OwnerBase::init_rid();
OS::get_singleton()->initialize_core();
@@ -244,11 +253,13 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
register_core_settings(); //here globals is present
+ OS::get_singleton()->initialize_logger();
+
translation_server = memnew(TranslationServer);
performance = memnew(Performance);
globals->add_singleton(ProjectSettings::Singleton("Performance", performance));
- GLOBAL_DEF("debug/settings/backtrace/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
+ GLOBAL_DEF("debug/settings/crash_handler/message", String("Please include this when reporting the bug on https://github.com/godotengine/godot/issues"));
MAIN_PRINT("Main: Parse CMDLine");
@@ -268,7 +279,6 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
while (I) {
I->get() = unescape_cmdline(I->get().strip_escapes());
- //print_line("CMD: "+I->get());
I = I->next();
}
@@ -318,6 +328,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
show_help = true;
goto error;
+ } else if (I->get() == "--version") {
+
+ print_line(get_full_version_string());
+ goto error;
+
} else if (I->get() == "--resolution") { // force resolution
if (I->next()) {
@@ -990,8 +1005,10 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
#endif
}
+#ifdef TOOLS_ENABLED
Ref<Image> icon = memnew(Image(app_icon_png));
OS::get_singleton()->set_icon(icon);
+#endif
}
MAIN_PRINT("Main: DCC");
@@ -1082,6 +1099,7 @@ bool Main::start() {
ERR_FAIL_COND_V(!_start_success, false);
+ bool hasicon = false;
bool editor = false;
String doc_tool;
List<String> removal_docs;
@@ -1519,8 +1537,10 @@ bool Main::start() {
if (iconpath != "") {
Ref<Image> icon;
icon.instance();
- if (icon->load(iconpath) == OK)
+ if (icon->load(iconpath) == OK) {
OS::get_singleton()->set_icon(icon);
+ hasicon = true;
+ }
}
}
}
@@ -1537,6 +1557,11 @@ bool Main::start() {
#endif
}
+ if (!hasicon) {
+ Ref<Image> icon = memnew(Image(app_icon_png));
+ OS::get_singleton()->set_icon(icon);
+ }
+
OS::get_singleton()->set_main_loop(main_loop);
return true;
@@ -1550,7 +1575,7 @@ uint32_t Main::frame = 0;
bool Main::force_redraw_requested = false;
//for performance metrics
-static uint64_t fixed_process_max = 0;
+static uint64_t physics_process_max = 0;
static uint64_t idle_process_max = 0;
bool Main::iteration() {
@@ -1573,7 +1598,7 @@ bool Main::iteration() {
return false;
*/
- uint64_t fixed_process_ticks = 0;
+ uint64_t physics_process_ticks = 0;
uint64_t idle_process_ticks = 0;
frame += ticks_elapsed;
@@ -1591,7 +1616,7 @@ bool Main::iteration() {
int iters = 0;
- Engine::get_singleton()->_in_fixed = true;
+ Engine::get_singleton()->_in_physics = true;
while (time_accum > frame_slice) {
@@ -1618,13 +1643,13 @@ bool Main::iteration() {
time_accum -= frame_slice;
message_queue->flush();
- fixed_process_ticks = MAX(fixed_process_ticks, OS::get_singleton()->get_ticks_usec() - fixed_begin); // keep the largest one for reference
- fixed_process_max = MAX(OS::get_singleton()->get_ticks_usec() - fixed_begin, fixed_process_max);
+ physics_process_ticks = MAX(physics_process_ticks, OS::get_singleton()->get_ticks_usec() - fixed_begin); // keep the largest one for reference
+ physics_process_max = MAX(OS::get_singleton()->get_ticks_usec() - fixed_begin, physics_process_max);
iters++;
- Engine::get_singleton()->_fixed_frames++;
+ Engine::get_singleton()->_physics_frames++;
}
- Engine::get_singleton()->_in_fixed = false;
+ Engine::get_singleton()->_in_physics = false;
uint64_t idle_begin = OS::get_singleton()->get_ticks_usec();
@@ -1660,7 +1685,7 @@ bool Main::iteration() {
if (script_debugger) {
if (script_debugger->is_profiling()) {
- script_debugger->profiling_set_frame_times(USEC_TO_SEC(frame_time), USEC_TO_SEC(idle_process_ticks), USEC_TO_SEC(fixed_process_ticks), frame_slice);
+ script_debugger->profiling_set_frame_times(USEC_TO_SEC(frame_time), USEC_TO_SEC(idle_process_ticks), USEC_TO_SEC(physics_process_ticks), frame_slice);
}
script_debugger->idle_poll();
}
@@ -1676,9 +1701,9 @@ bool Main::iteration() {
Engine::get_singleton()->_fps = frames;
performance->set_process_time(USEC_TO_SEC(idle_process_max));
- performance->set_fixed_process_time(USEC_TO_SEC(fixed_process_max));
+ performance->set_physics_process_time(USEC_TO_SEC(physics_process_max));
idle_process_max = 0;
- fixed_process_max = 0;
+ physics_process_max = 0;
frame %= 1000000;
frames = 0;
diff --git a/main/performance.cpp b/main/performance.cpp
index e85d2bf736..0f3383c4a8 100644
--- a/main/performance.cpp
+++ b/main/performance.cpp
@@ -42,7 +42,7 @@ void Performance::_bind_methods() {
BIND_ENUM_CONSTANT(TIME_FPS);
BIND_ENUM_CONSTANT(TIME_PROCESS);
- BIND_ENUM_CONSTANT(TIME_FIXED_PROCESS);
+ BIND_ENUM_CONSTANT(TIME_PHYSICS_PROCESS);
BIND_ENUM_CONSTANT(MEMORY_STATIC);
BIND_ENUM_CONSTANT(MEMORY_DYNAMIC);
BIND_ENUM_CONSTANT(MEMORY_STATIC_MAX);
@@ -78,7 +78,7 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
"time/fps",
"time/process",
- "time/fixed_process",
+ "time/physics_process",
"memory/static",
"memory/dynamic",
"memory/static_max",
@@ -94,7 +94,7 @@ String Performance::get_monitor_name(Monitor p_monitor) const {
"raster/surface_changes",
"raster/draw_calls",
"video/video_mem",
- "video/texure_mem",
+ "video/texture_mem",
"video/vertex_mem",
"video/video_mem_max",
"physics_2d/active_objects",
@@ -114,7 +114,7 @@ float Performance::get_monitor(Monitor p_monitor) const {
switch (p_monitor) {
case TIME_FPS: return Engine::get_singleton()->get_frames_per_second();
case TIME_PROCESS: return _process_time;
- case TIME_FIXED_PROCESS: return _fixed_process_time;
+ case TIME_PHYSICS_PROCESS: return _physics_process_time;
case MEMORY_STATIC: return Memory::get_mem_usage();
case MEMORY_DYNAMIC: return MemoryPool::total_memory;
case MEMORY_STATIC_MAX: return Memory::get_mem_max_usage();
@@ -158,14 +158,14 @@ void Performance::set_process_time(float p_pt) {
_process_time = p_pt;
}
-void Performance::set_fixed_process_time(float p_pt) {
+void Performance::set_physics_process_time(float p_pt) {
- _fixed_process_time = p_pt;
+ _physics_process_time = p_pt;
}
Performance::Performance() {
_process_time = 0;
- _fixed_process_time = 0;
+ _physics_process_time = 0;
singleton = this;
}
diff --git a/main/performance.h b/main/performance.h
index a9e3c07d7c..900e6434b7 100644
--- a/main/performance.h
+++ b/main/performance.h
@@ -43,14 +43,14 @@ class Performance : public Object {
static void _bind_methods();
float _process_time;
- float _fixed_process_time;
+ float _physics_process_time;
public:
enum Monitor {
TIME_FPS,
TIME_PROCESS,
- TIME_FIXED_PROCESS,
+ TIME_PHYSICS_PROCESS,
MEMORY_STATIC,
MEMORY_DYNAMIC,
MEMORY_STATIC_MAX,
@@ -83,7 +83,7 @@ public:
String get_monitor_name(Monitor p_monitor) const;
void set_process_time(float p_pt);
- void set_fixed_process_time(float p_pt);
+ void set_physics_process_time(float p_pt);
static Performance *get_singleton() { return singleton; }
diff --git a/main/tests/test_main.cpp b/main/tests/test_main.cpp
index 645db2826e..d9b20254a8 100644
--- a/main/tests/test_main.cpp
+++ b/main/tests/test_main.cpp
@@ -37,6 +37,7 @@
#include "test_image.h"
#include "test_io.h"
#include "test_math.h"
+#include "test_oa_hash_map.h"
#include "test_ordered_hash_map.h"
#include "test_physics.h"
#include "test_physics_2d.h"
@@ -56,6 +57,7 @@ const char **tests_get_names() {
"io",
"shaderlang",
"physics",
+ "oa_hash_map",
NULL
};
@@ -89,6 +91,11 @@ MainLoop *test_main(String p_test, const List<String> &p_args) {
return TestRender::test();
}
+ if (p_test == "oa_hash_map") {
+
+ return TestOAHashMap::test();
+ }
+
#ifndef _3D_DISABLED
if (p_test == "gui") {
diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp
new file mode 100644
index 0000000000..302c259262
--- /dev/null
+++ b/main/tests/test_oa_hash_map.cpp
@@ -0,0 +1,97 @@
+/*************************************************************************/
+/* test_oa_hash_map.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "test_oa_hash_map.h"
+
+#include "core/os/os.h"
+
+#include "core/oa_hash_map.h"
+
+namespace TestOAHashMap {
+
+MainLoop *test() {
+
+ OS::get_singleton()->print("\n\n\nHello from test\n");
+
+ // test element tracking.
+ {
+ OAHashMap<int, int> map;
+
+ map.set(42, 1337);
+ map.set(1337, 21);
+ map.set(42, 11880);
+
+ int value;
+ map.lookup(42, &value);
+
+ OS::get_singleton()->print("capacity %d\n", map.get_capacity());
+ OS::get_singleton()->print("elements %d\n", map.get_num_elements());
+
+ OS::get_singleton()->print("map[42] = %d\n", value);
+ }
+
+ // rehashing and deletion
+ {
+ OAHashMap<int, int> map;
+
+ for (int i = 0; i < 500; i++) {
+ map.set(i, i * 2);
+ }
+
+ for (int i = 0; i < 500; i += 2) {
+ map.remove(i);
+ }
+
+ uint32_t num_elems = 0;
+ for (int i = 0; i < 500; i++) {
+ int tmp;
+ if (map.lookup(i, &tmp))
+ num_elems++;
+ }
+
+ OS::get_singleton()->print("elements %d == %d.\n", map.get_num_elements(), num_elems);
+ }
+
+ // iteration
+ {
+ OAHashMap<String, int> map;
+
+ map.set("Hello", 1);
+ map.set("World", 2);
+ map.set("Godot rocks", 42);
+
+ for (OAHashMap<String, int>::Iterator it = map.iter(); it.valid; it = map.next_iter(it)) {
+ OS::get_singleton()->print("map[\"%s\"] = %d\n", it.key->utf8().get_data(), *it.data);
+ }
+ }
+
+ return NULL;
+}
+} // namespace TestOAHashMap
diff --git a/main/tests/test_oa_hash_map.h b/main/tests/test_oa_hash_map.h
new file mode 100644
index 0000000000..92b4bc5e5a
--- /dev/null
+++ b/main/tests/test_oa_hash_map.h
@@ -0,0 +1,39 @@
+/*************************************************************************/
+/* test_oa_hash_map.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 TEST_OA_HASH_MAP_H
+#define TEST_OA_HASH_MAP_H
+
+#include "os/main_loop.h"
+
+namespace TestOAHashMap {
+
+MainLoop *test();
+}
+#endif // TEST_OA_HASH_MAP_H
diff --git a/methods.py b/methods.py
index 2ab76a5416..f1ef95f6fe 100644
--- a/methods.py
+++ b/methods.py
@@ -1706,9 +1706,9 @@ def generate_vs_project(env, num_jobs):
env.AddToVSProject(env.servers_sources)
env.AddToVSProject(env.editor_sources)
- env['MSVSBUILDCOM'] = build_commandline('scons platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs))
- env['MSVSREBUILDCOM'] = build_commandline('scons platform=windows target=$(Configuration) tools=!tools! vsproj=yes -j' + str(num_jobs))
- env['MSVSCLEANCOM'] = build_commandline('scons --clean platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs))
+ env['MSVSBUILDCOM'] = build_commandline('scons --directory=$(ProjectDir) platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs))
+ env['MSVSREBUILDCOM'] = build_commandline('scons --directory=$(ProjectDir) platform=windows target=$(Configuration) tools=!tools! vsproj=yes -j' + str(num_jobs))
+ env['MSVSCLEANCOM'] = build_commandline('scons --directory=$(ProjectDir) --clean platform=windows target=$(Configuration) tools=!tools! -j' + str(num_jobs))
# This version information (Win32, x64, Debug, Release, Release_Debug seems to be
# required for Visual Studio to understand that it needs to generate an NMAKE
diff --git a/misc/dist/ios_xcode/export_options.plist b/misc/dist/ios_xcode/export_options.plist
new file mode 100644
index 0000000000..86d89a6e42
--- /dev/null
+++ b/misc/dist/ios_xcode/export_options.plist
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>method</key>
+ <string>$export_method</string>
+ <key>teamID</key>
+ <string>$team_id</string>
+</dict>
+</plist> \ No newline at end of file
diff --git a/misc/dist/ios_xcode/godot_debug.iphone b/misc/dist/ios_xcode/godot.iphone.debug.arm
index e69de29bb2..e69de29bb2 100755
--- a/misc/dist/ios_xcode/godot_debug.iphone
+++ b/misc/dist/ios_xcode/godot.iphone.debug.arm
diff --git a/misc/dist/ios_xcode/godot_opt.iphone b/misc/dist/ios_xcode/godot.iphone.debug.arm64
index e69de29bb2..e69de29bb2 100755
--- a/misc/dist/ios_xcode/godot_opt.iphone
+++ b/misc/dist/ios_xcode/godot.iphone.debug.arm64
diff --git a/misc/dist/ios_xcode/godot.iphone.debug.fat b/misc/dist/ios_xcode/godot.iphone.debug.fat
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/misc/dist/ios_xcode/godot.iphone.debug.fat
diff --git a/misc/dist/ios_xcode/godot.iphone.release.arm b/misc/dist/ios_xcode/godot.iphone.release.arm
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/misc/dist/ios_xcode/godot.iphone.release.arm
diff --git a/misc/dist/ios_xcode/godot.iphone.release.arm64 b/misc/dist/ios_xcode/godot.iphone.release.arm64
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/misc/dist/ios_xcode/godot.iphone.release.arm64
diff --git a/misc/dist/ios_xcode/godot.iphone.release.fat b/misc/dist/ios_xcode/godot.iphone.release.fat
new file mode 100755
index 0000000000..e69de29bb2
--- /dev/null
+++ b/misc/dist/ios_xcode/godot.iphone.release.fat
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
index bdba8488c8..3f2db94193 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.pbxproj
@@ -7,18 +7,17 @@
objects = {
/* Begin PBXBuildFile section */
- D07CD43F1C5D573600B7FB28 /* Default-568h@2x~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4331C5D573600B7FB28 /* Default-568h@2x~iphone.png */; };
- D07CD4401C5D573600B7FB28 /* Default-667h.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4341C5D573600B7FB28 /* Default-667h.png */; };
+ 1F1575721F582BE20003B888 /* dylibs in Resources */ = {isa = PBXBuildFile; fileRef = 1F1575711F582BE20003B888 /* dylibs */; };
+ 1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1841F584E3F00A41E41 /* GameKit.framework */; };
+ 1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FF4C1861F584E5600A41E41 /* StoreKit.framework */; };
+ D07CD43F1C5D573600B7FB28 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */; };
D07CD4411C5D573600B7FB28 /* Default-667h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */; };
- D07CD4421C5D573600B7FB28 /* Default-736h.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4361C5D573600B7FB28 /* Default-736h.png */; };
- D07CD4431C5D573600B7FB28 /* Default-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4371C5D573600B7FB28 /* Default-736h@3x.png */; };
- D07CD4441C5D573600B7FB28 /* Default-Landscape-736h.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4381C5D573600B7FB28 /* Default-Landscape-736h.png */; };
- D07CD4451C5D573600B7FB28 /* Default-Landscape@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4391C5D573600B7FB28 /* Default-Landscape@2x~ipad.png */; };
- D07CD4461C5D573600B7FB28 /* Default-Landscape~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43A1C5D573600B7FB28 /* Default-Landscape~ipad.png */; };
- D07CD4471C5D573600B7FB28 /* Default-Portrait@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x~ipad.png */; };
- D07CD4481C5D573600B7FB28 /* Default-Portrait~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43C1C5D573600B7FB28 /* Default-Portrait~ipad.png */; };
- D07CD4491C5D573600B7FB28 /* Default@2x~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43D1C5D573600B7FB28 /* Default@2x~iphone.png */; };
- D07CD44A1C5D573600B7FB28 /* Default~iphone.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43E1C5D573600B7FB28 /* Default~iphone.png */; };
+ D07CD4421C5D573600B7FB28 /* Default-Portrait-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */; };
+ D07CD4441C5D573600B7FB28 /* Default-Landscape-736h@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4381C5D573600B7FB28 /* Default-Landscape-736h@3x.png */; };
+ D07CD4451C5D573600B7FB28 /* Default-Landscape@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD4391C5D573600B7FB28 /* Default-Landscape@2x.png */; };
+ D07CD4461C5D573600B7FB28 /* Default-Landscape-1366h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43A1C5D573600B7FB28 /* Default-Landscape-1366h@2x.png */; };
+ D07CD4471C5D573600B7FB28 /* Default-Portrait@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x.png */; };
+ D07CD4481C5D573600B7FB28 /* Default-Portrait-1366h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D07CD43C1C5D573600B7FB28 /* Default-Portrait-1366h@2x.png */; };
D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D07CD44D1C5D589C00B7FB28 /* Images.xcassets */; };
D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */; };
D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */; };
@@ -26,36 +25,36 @@
D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */; };
D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */; };
D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */; };
- D0BCFE7818AEBFEB004A7AAE /* data.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* data.pck */; };
- D0BCFE7A18AEC06A004A7AAE /* godot_opt.iphone in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */; };
+ D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7718AEBFEB004A7AAE /* $binary.pck */; };
+ D0BCFE7A18AEC06A004A7AAE /* $binary.iphone in Resources */ = {isa = PBXBuildFile; fileRef = D0BCFE7918AEC06A004A7AAE /* $binary.iphone */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
- D07CD4331C5D573600B7FB28 /* Default-568h@2x~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x~iphone.png"; sourceTree = "<group>"; };
- D07CD4341C5D573600B7FB28 /* Default-667h.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h.png"; sourceTree = "<group>"; };
+ 1F1575711F582BE20003B888 /* dylibs */ = {isa = PBXFileReference; lastKnownFileType = folder; name = dylibs; path = dylibs; sourceTree = "<group>"; };
+ 1FF4C1841F584E3F00A41E41 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
+ 1FF4C1861F584E5600A41E41 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
+ 1FF4C1881F584E6300A41E41 /* $binary.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = $binary.entitlements; sourceTree = "<group>"; };
+ D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-667h@2x.png"; sourceTree = "<group>"; };
- D07CD4361C5D573600B7FB28 /* Default-736h.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h.png"; sourceTree = "<group>"; };
- D07CD4371C5D573600B7FB28 /* Default-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-736h@3x.png"; sourceTree = "<group>"; };
- D07CD4381C5D573600B7FB28 /* Default-Landscape-736h.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape-736h.png"; sourceTree = "<group>"; };
- D07CD4391C5D573600B7FB28 /* Default-Landscape@2x~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape@2x~ipad.png"; sourceTree = "<group>"; };
- D07CD43A1C5D573600B7FB28 /* Default-Landscape~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape~ipad.png"; sourceTree = "<group>"; };
- D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait@2x~ipad.png"; sourceTree = "<group>"; };
- D07CD43C1C5D573600B7FB28 /* Default-Portrait~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait~ipad.png"; sourceTree = "<group>"; };
- D07CD43D1C5D573600B7FB28 /* Default@2x~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x~iphone.png"; sourceTree = "<group>"; };
- D07CD43E1C5D573600B7FB28 /* Default~iphone.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default~iphone.png"; sourceTree = "<group>"; };
+ D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait-736h@3x.png"; sourceTree = "<group>"; };
+ D07CD4381C5D573600B7FB28 /* Default-Landscape-736h@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape-736h@3x.png"; sourceTree = "<group>"; };
+ D07CD4391C5D573600B7FB28 /* Default-Landscape@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape@2x.png"; sourceTree = "<group>"; };
+ D07CD43A1C5D573600B7FB28 /* Default-Landscape-1366h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Landscape-1366h@2x.png"; sourceTree = "<group>"; };
+ D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait@2x.png"; sourceTree = "<group>"; };
+ D07CD43C1C5D573600B7FB28 /* Default-Portrait-1366h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-Portrait-1366h@2x.png"; sourceTree = "<group>"; };
D07CD44D1C5D589C00B7FB28 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
- D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = godot_ios.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ D0BCFE3418AEBDA2004A7AAE /* $binary.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = $binary.app; sourceTree = BUILT_PRODUCTS_DIR; };
D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
D0BCFE3D18AEBDA2004A7AAE /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
D0BCFE3F18AEBDA2004A7AAE /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; };
- D0BCFE4318AEBDA2004A7AAE /* godot_ios-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "godot_ios-Info.plist"; sourceTree = "<group>"; };
+ D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "$binary-Info.plist"; sourceTree = "<group>"; };
D0BCFE4518AEBDA2004A7AAE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
- D0BCFE4918AEBDA2004A7AAE /* godot_ios-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "godot_ios-Prefix.pch"; sourceTree = "<group>"; };
+ D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "$binary-Prefix.pch"; sourceTree = "<group>"; };
D0BCFE6118AEBDA3004A7AAE /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
- D0BCFE7718AEBFEB004A7AAE /* data.pck */ = {isa = PBXFileReference; lastKnownFileType = text; path = data.pck; sourceTree = "<group>"; };
- D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = godot_opt.iphone; sourceTree = "<group>"; };
+ D0BCFE7718AEBFEB004A7AAE /* $binary.pck */ = {isa = PBXFileReference; lastKnownFileType = file; path = $binary.pck; sourceTree = "<group>"; };
+ D0BCFE7918AEC06A004A7AAE /* $binary.iphone */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = $binary.iphone; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -64,8 +63,10 @@
buildActionMask = 2147483647;
files = (
D0BCFE4018AEBDA2004A7AAE /* OpenGLES.framework in Frameworks */,
+ 1FF4C1871F584E5600A41E41 /* StoreKit.framework in Frameworks */,
D0BCFE3A18AEBDA2004A7AAE /* CoreGraphics.framework in Frameworks */,
D0BCFE3C18AEBDA2004A7AAE /* UIKit.framework in Frameworks */,
+ 1FF4C1851F584E3F00A41E41 /* GameKit.framework in Frameworks */,
D0BCFE3E18AEBDA2004A7AAE /* GLKit.framework in Frameworks */,
D0BCFE3818AEBDA2004A7AAE /* Foundation.framework in Frameworks */,
);
@@ -77,9 +78,10 @@
D0BCFE2B18AEBDA2004A7AAE = {
isa = PBXGroup;
children = (
- D0BCFE7918AEC06A004A7AAE /* godot_opt.iphone */,
- D0BCFE7718AEBFEB004A7AAE /* data.pck */,
- D0BCFE4118AEBDA2004A7AAE /* godot_ios */,
+ 1F1575711F582BE20003B888 /* dylibs */,
+ D0BCFE7918AEC06A004A7AAE /* $binary.iphone */,
+ D0BCFE7718AEBFEB004A7AAE /* $binary.pck */,
+ D0BCFE4118AEBDA2004A7AAE /* $binary */,
D0BCFE3618AEBDA2004A7AAE /* Frameworks */,
D0BCFE3518AEBDA2004A7AAE /* Products */,
);
@@ -88,7 +90,7 @@
D0BCFE3518AEBDA2004A7AAE /* Products */ = {
isa = PBXGroup;
children = (
- D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */,
+ D0BCFE3418AEBDA2004A7AAE /* $binary.app */,
);
name = Products;
sourceTree = "<group>";
@@ -96,6 +98,8 @@
D0BCFE3618AEBDA2004A7AAE /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 1FF4C1861F584E5600A41E41 /* StoreKit.framework */,
+ 1FF4C1841F584E3F00A41E41 /* GameKit.framework */,
D0BCFE3718AEBDA2004A7AAE /* Foundation.framework */,
D0BCFE3918AEBDA2004A7AAE /* CoreGraphics.framework */,
D0BCFE3B18AEBDA2004A7AAE /* UIKit.framework */,
@@ -106,33 +110,30 @@
name = Frameworks;
sourceTree = "<group>";
};
- D0BCFE4118AEBDA2004A7AAE /* godot_ios */ = {
+ D0BCFE4118AEBDA2004A7AAE /* $binary */ = {
isa = PBXGroup;
children = (
- D07CD4331C5D573600B7FB28 /* Default-568h@2x~iphone.png */,
- D07CD4341C5D573600B7FB28 /* Default-667h.png */,
+ 1FF4C1881F584E6300A41E41 /* $binary.entitlements */,
+ D07CD4331C5D573600B7FB28 /* Default-568h@2x.png */,
D07CD4351C5D573600B7FB28 /* Default-667h@2x.png */,
- D07CD4361C5D573600B7FB28 /* Default-736h.png */,
- D07CD4371C5D573600B7FB28 /* Default-736h@3x.png */,
- D07CD4381C5D573600B7FB28 /* Default-Landscape-736h.png */,
- D07CD4391C5D573600B7FB28 /* Default-Landscape@2x~ipad.png */,
- D07CD43A1C5D573600B7FB28 /* Default-Landscape~ipad.png */,
- D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x~ipad.png */,
- D07CD43C1C5D573600B7FB28 /* Default-Portrait~ipad.png */,
- D07CD43D1C5D573600B7FB28 /* Default@2x~iphone.png */,
- D07CD43E1C5D573600B7FB28 /* Default~iphone.png */,
+ D07CD4361C5D573600B7FB28 /* Default-Portrait-736h@3x.png */,
+ D07CD4381C5D573600B7FB28 /* Default-Landscape-736h@3x.png */,
+ D07CD4391C5D573600B7FB28 /* Default-Landscape@2x.png */,
+ D07CD43A1C5D573600B7FB28 /* Default-Landscape-1366h@2x.png */,
+ D07CD43B1C5D573600B7FB28 /* Default-Portrait@2x.png */,
+ D07CD43C1C5D573600B7FB28 /* Default-Portrait-1366h@2x.png */,
D07CD44D1C5D589C00B7FB28 /* Images.xcassets */,
D0BCFE4218AEBDA2004A7AAE /* Supporting Files */,
);
- path = godot_ios;
+ path = $binary;
sourceTree = "<group>";
};
D0BCFE4218AEBDA2004A7AAE /* Supporting Files */ = {
isa = PBXGroup;
children = (
- D0BCFE4318AEBDA2004A7AAE /* godot_ios-Info.plist */,
+ D0BCFE4318AEBDA2004A7AAE /* $binary-Info.plist */,
D0BCFE4418AEBDA2004A7AAE /* InfoPlist.strings */,
- D0BCFE4918AEBDA2004A7AAE /* godot_ios-Prefix.pch */,
+ D0BCFE4918AEBDA2004A7AAE /* $binary-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "<group>";
@@ -140,9 +141,9 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
- D0BCFE3318AEBDA2004A7AAE /* godot_ios */ = {
+ D0BCFE3318AEBDA2004A7AAE /* $binary */ = {
isa = PBXNativeTarget;
- buildConfigurationList = D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "godot_ios" */;
+ buildConfigurationList = D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "$binary" */;
buildPhases = (
D0BCFE3018AEBDA2004A7AAE /* Sources */,
D0BCFE3118AEBDA2004A7AAE /* Frameworks */,
@@ -152,9 +153,9 @@
);
dependencies = (
);
- name = godot_ios;
- productName = godot_ios;
- productReference = D0BCFE3418AEBDA2004A7AAE /* godot_ios.app */;
+ name = "$binary";
+ productName = "$name";
+ productReference = D0BCFE3418AEBDA2004A7AAE /* $binary.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -165,8 +166,24 @@
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = GodotEngine;
+ TargetAttributes = {
+ D0BCFE3318AEBDA2004A7AAE = {
+ DevelopmentTeam = $team_id;
+ SystemCapabilities = {
+ com.apple.GameCenter = {
+ enabled = 1;
+ };
+ com.apple.InAppPurchase = {
+ enabled = 1;
+ };
+ com.apple.Push = {
+ enabled = 1;
+ };
+ };
+ };
+ };
};
- buildConfigurationList = D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "godot_ios" */;
+ buildConfigurationList = D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "$binary" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
@@ -179,7 +196,7 @@
projectDirPath = "";
projectRoot = "";
targets = (
- D0BCFE3318AEBDA2004A7AAE /* godot_ios */,
+ D0BCFE3318AEBDA2004A7AAE /* $binary */,
);
};
/* End PBXProject section */
@@ -189,22 +206,19 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- D07CD4471C5D573600B7FB28 /* Default-Portrait@2x~ipad.png in Resources */,
+ 1F1575721F582BE20003B888 /* dylibs in Resources */,
D07CD44E1C5D589C00B7FB28 /* Images.xcassets in Resources */,
- D0BCFE7818AEBFEB004A7AAE /* data.pck in Resources */,
- D07CD4461C5D573600B7FB28 /* Default-Landscape~ipad.png in Resources */,
+ D0BCFE7818AEBFEB004A7AAE /* $binary.pck in Resources */,
+ D07CD4471C5D573600B7FB28 /* Default-Portrait@2x.png in Resources */,
+ D07CD4461C5D573600B7FB28 /* Default-Landscape-1366h@2x.png in Resources */,
D07CD4411C5D573600B7FB28 /* Default-667h@2x.png in Resources */,
- D07CD4401C5D573600B7FB28 /* Default-667h.png in Resources */,
- D07CD4431C5D573600B7FB28 /* Default-736h@3x.png in Resources */,
- D07CD43F1C5D573600B7FB28 /* Default-568h@2x~iphone.png in Resources */,
- D07CD4451C5D573600B7FB28 /* Default-Landscape@2x~ipad.png in Resources */,
- D07CD44A1C5D573600B7FB28 /* Default~iphone.png in Resources */,
- D07CD4491C5D573600B7FB28 /* Default@2x~iphone.png in Resources */,
- D07CD4441C5D573600B7FB28 /* Default-Landscape-736h.png in Resources */,
- D07CD4421C5D573600B7FB28 /* Default-736h.png in Resources */,
+ D07CD43F1C5D573600B7FB28 /* Default-568h@2x.png in Resources */,
+ D07CD4451C5D573600B7FB28 /* Default-Landscape@2x.png in Resources */,
+ D07CD4441C5D573600B7FB28 /* Default-Landscape-736h@3x.png in Resources */,
+ D07CD4421C5D573600B7FB28 /* Default-Portrait-736h@3x.png in Resources */,
+ D07CD4481C5D573600B7FB28 /* Default-Portrait-1366h@2x.png in Resources */,
D0BCFE4618AEBDA2004A7AAE /* InfoPlist.strings in Resources */,
- D0BCFE7A18AEC06A004A7AAE /* godot_opt.iphone in Resources */,
- D07CD4481C5D573600B7FB28 /* Default-Portrait~ipad.png in Resources */,
+ D0BCFE7A18AEC06A004A7AAE /* $binary.iphone in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -249,7 +263,7 @@
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug";
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
@@ -265,7 +279,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 7.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -289,7 +303,8 @@
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ CODE_SIGN_IDENTITY = "$code_sign_identity_release";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release";
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
@@ -299,7 +314,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 7.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
@@ -311,13 +326,22 @@
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CODE_SIGN_ENTITLEMENTS = $binary/$binary.entitlements;
+ CODE_SIGN_IDENTITY = "$code_sign_identity_debug";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_debug";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+ DEVELOPMENT_TEAM = $team_id;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "godot_ios/godot_ios-Prefix.pch";
- INFOPLIST_FILE = "godot_ios/godot_ios-Info.plist";
- IPHONEOS_DEPLOYMENT_TARGET = 6.0;
- PRODUCT_BUNDLE_IDENTIFIER = org.godotengine.game.ios;
+ GCC_PREFIX_HEADER = "$binary/$binary-Prefix.pch";
+ INFOPLIST_FILE = "$binary/$binary-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/dylibs",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = $identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE = "$provisioning_profile_uuid_debug";
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = "armv7 armv7s";
WRAPPER_EXTENSION = app;
@@ -329,14 +353,22 @@
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CODE_SIGN_IDENTITY = "iPhone Distribution: Ariel Manzur (BYC57PA2Q5)";
+ CODE_SIGN_ENTITLEMENTS = $binary/$binary.entitlements;
+ CODE_SIGN_IDENTITY = "$code_sign_identity_release";
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "$code_sign_identity_release";
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)";
+ DEVELOPMENT_TEAM = $team_id;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "godot_ios/godot_ios-Prefix.pch";
- INFOPLIST_FILE = "godot_ios/godot_ios-Info.plist";
- IPHONEOS_DEPLOYMENT_TARGET = 6.0;
- PRODUCT_BUNDLE_IDENTIFIER = org.godotengine.game.ios;
+ GCC_PREFIX_HEADER = "$binary/$binary-Prefix.pch";
+ INFOPLIST_FILE = "$binary/$binary-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/dylibs",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = $identifier;
PRODUCT_NAME = "$(TARGET_NAME)";
+ PROVISIONING_PROFILE = "$provisioning_profile_uuid_release";
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = "armv7 armv7s";
WRAPPER_EXTENSION = app;
@@ -346,7 +378,7 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
- D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "godot_ios" */ = {
+ D0BCFE2F18AEBDA2004A7AAE /* Build configuration list for PBXProject "$binary" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D0BCFE6F18AEBDA3004A7AAE /* Debug */,
@@ -355,7 +387,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "godot_ios" */ = {
+ D0BCFE7118AEBDA3004A7AAE /* Build configuration list for PBXNativeTarget "$binary" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D0BCFE7218AEBDA3004A7AAE /* Debug */,
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index 3c9ba38bbe..c9c19829f4 100644
--- a/misc/dist/ios_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
- location = "self:godot_ios.xcodeproj">
+ location = "self:$binary.xcodeproj">
</FileRef>
</Workspace>
diff --git a/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme b/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme
new file mode 100644
index 0000000000..3f0df5c437
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0710"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "A340BDFEBCA49239A941883D"
+ BuildableName = "$binary.app"
+ BlueprintName = "$binary"
+ ReferencedContainer = "container:$binary.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ buildConfiguration = "Development"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES">
+ <Testables>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "A340BDFEBCA49239A941883D"
+ BuildableName = "$binary.app"
+ BlueprintName = "$binary"
+ ReferencedContainer = "container:$binary.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </TestAction>
+ <LaunchAction
+ buildConfiguration = "Development"
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ debugServiceExtension = "internal"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "A340BDFEBCA49239A941883D"
+ BuildableName = "$binary.app"
+ BlueprintName = "$binary"
+ ReferencedContainer = "container:$binary.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <CommandLineArguments>
+ </CommandLineArguments>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ buildConfiguration = "Development"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ debugDocumentVersioning = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "A340BDFEBCA49239A941883D"
+ BuildableName = "$binary.app"
+ BlueprintName = "$binary"
+ ReferencedContainer = "container:$binary.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Development">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Development"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/misc/dist/ios_xcode/godot_ios/Default-568h@2x~iphone.png b/misc/dist/ios_xcode/godot_ios/Default-568h@2x.png
index 1d5e472665..1d5e472665 100644
--- a/misc/dist/ios_xcode/godot_ios/Default-568h@2x~iphone.png
+++ b/misc/dist/ios_xcode/godot_ios/Default-568h@2x.png
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-667h.png b/misc/dist/ios_xcode/godot_ios/Default-667h.png
deleted file mode 100644
index b13a399c83..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Default-667h.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-736h@3x.png b/misc/dist/ios_xcode/godot_ios/Default-736h@3x.png
deleted file mode 100644
index 33847ac136..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Default-736h@3x.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-Landscape-1366h@2x.png b/misc/dist/ios_xcode/godot_ios/Default-Landscape-1366h@2x.png
new file mode 100644
index 0000000000..ec5b4f7888
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios/Default-Landscape-1366h@2x.png
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-Landscape-736h.png b/misc/dist/ios_xcode/godot_ios/Default-Landscape-736h@3x.png
index 2a025b745b..2a025b745b 100644
--- a/misc/dist/ios_xcode/godot_ios/Default-Landscape-736h.png
+++ b/misc/dist/ios_xcode/godot_ios/Default-Landscape-736h@3x.png
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-Landscape@2x~ipad.png b/misc/dist/ios_xcode/godot_ios/Default-Landscape@2x.png
index 7099f3e18d..7099f3e18d 100644
--- a/misc/dist/ios_xcode/godot_ios/Default-Landscape@2x~ipad.png
+++ b/misc/dist/ios_xcode/godot_ios/Default-Landscape@2x.png
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-Landscape~ipad.png b/misc/dist/ios_xcode/godot_ios/Default-Landscape~ipad.png
deleted file mode 100644
index 4a761c339a..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Default-Landscape~ipad.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-Portrait-1366h@2x.png b/misc/dist/ios_xcode/godot_ios/Default-Portrait-1366h@2x.png
new file mode 100644
index 0000000000..a6d054ba2a
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios/Default-Portrait-1366h@2x.png
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-736h.png b/misc/dist/ios_xcode/godot_ios/Default-Portrait-736h@3x.png
index 8c44edbccd..8c44edbccd 100644
--- a/misc/dist/ios_xcode/godot_ios/Default-736h.png
+++ b/misc/dist/ios_xcode/godot_ios/Default-Portrait-736h@3x.png
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-Portrait@2x.png b/misc/dist/ios_xcode/godot_ios/Default-Portrait@2x.png
new file mode 100644
index 0000000000..a6d054ba2a
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios/Default-Portrait@2x.png
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-Portrait@2x~ipad.png b/misc/dist/ios_xcode/godot_ios/Default-Portrait@2x~ipad.png
deleted file mode 100644
index b09cf21186..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Default-Portrait@2x~ipad.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default-Portrait~ipad.png b/misc/dist/ios_xcode/godot_ios/Default-Portrait~ipad.png
deleted file mode 100644
index fa698eb70c..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Default-Portrait~ipad.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default@2x~iphone.png b/misc/dist/ios_xcode/godot_ios/Default@2x~iphone.png
deleted file mode 100644
index ddf2861f4d..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Default@2x~iphone.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Default~iphone.png b/misc/dist/ios_xcode/godot_ios/Default~iphone.png
deleted file mode 100644
index c485a33b03..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Default~iphone.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json
deleted file mode 100644
index a458b67873..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Contents.json
+++ /dev/null
@@ -1,128 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "scale" : "1x",
- "filename": "Icon-29.png",
- },
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "scale" : "2x",
- "filename": "Icon-58.png",
- },
- {
- "idiom" : "iphone",
- "size" : "29x29",
- "scale" : "3x",
- "filename": "icon-87.png",
- },
- {
- "idiom" : "iphone",
- "size" : "40x40",
- "scale" : "2x",
- "filename": "Icon-80.png",
- },
- {
- "idiom" : "iphone",
- "size" : "40x40",
- "scale" : "3x",
- "filename": "Icon-120.png",
- },
- {
- "idiom" : "iphone",
- "size" : "57x57",
- "scale" : "1x",
- "filename": "Icon-57.png",
- },
- {
- "idiom" : "iphone",
- "size" : "57x57",
- "scale" : "2x",
- "filename": "Icon-114.png",
- },
- {
- "idiom" : "iphone",
- "size" : "60x60",
- "scale" : "2x",
- "filename": "Icon-120.png",
- },
- {
- "idiom" : "iphone",
- "size" : "60x60",
- "scale" : "3x",
- "filename": "Icon-180.png",
- },
- {
- "idiom" : "ipad",
- "size" : "29x29",
- "scale" : "1x",
- "filename": "Icon-29.png",
- },
- {
- "idiom" : "ipad",
- "size" : "29x29",
- "scale" : "2x",
- "filename": "Icon-58.png",
- },
- {
- "idiom" : "ipad",
- "size" : "40x40",
- "scale" : "1x",
- "filename": "Icon-40.png",
- },
- {
- "idiom" : "ipad",
- "size" : "40x40",
- "scale" : "2x",
- "filename": "Icon-80.png",
- },
- {
- "idiom" : "ipad",
- "size" : "50x50",
- "scale" : "1x",
- "filename": "Icon-50.png",
- },
- {
- "idiom" : "ipad",
- "size" : "50x50",
- "scale" : "2x",
- "filename": "Icon-100.png",
- },
- {
- "idiom" : "ipad",
- "size" : "72x72",
- "scale" : "1x",
- "filename": "Icon-72.png",
- },
- {
- "idiom" : "ipad",
- "size" : "72x72",
- "scale" : "2x",
- "filename": "Icon-144.png",
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "Icon-76.png",
- "scale" : "1x",
- },
- {
- "idiom" : "ipad",
- "size" : "76x76",
- "scale" : "2x",
- "filename": "Icon-152.png",
- },
- {
- "idiom" : "ipad",
- "size" : "83.5x83.5",
- "scale" : "2x",
- "filename": "icon-167.png",
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png
deleted file mode 100644
index 165f4423b3..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-100.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png
deleted file mode 100644
index 2e205e920c..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-114.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png
deleted file mode 100644
index 6245f83f48..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-120.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png
deleted file mode 100644
index 7b24e01bc6..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-144.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png
deleted file mode 100644
index 344b470fa3..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-152.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png
deleted file mode 100644
index 0dcebbc3f2..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-180.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png
deleted file mode 100644
index 9ae94e9aaf..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-29.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png
deleted file mode 100644
index 569f24df91..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-40.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png
deleted file mode 100644
index 9e69ed3121..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-50.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png
deleted file mode 100644
index b970fa3067..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-57.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png
deleted file mode 100644
index 6097a6c73b..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-58.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png
deleted file mode 100644
index 21b9622eb6..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-60.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png
deleted file mode 100644
index 34dea8e6ad..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-72.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png
deleted file mode 100644
index f72eb0b345..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-76.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png
deleted file mode 100644
index 793c9b1f5f..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/Icon-80.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png
deleted file mode 100644
index 7cd0e054ab..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-167.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png
deleted file mode 100644
index e9b2429754..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/icon-87.png
+++ /dev/null
Binary files differ
diff --git a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes b/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes
deleted file mode 100644
index e328a62cb6..0000000000
--- a/misc/dist/ios_xcode/godot_ios/Images.xcassets/AppIcon.appiconset/sizes
+++ /dev/null
@@ -1,17 +0,0 @@
-100
-114
-120
-144
-152
-167
-180
-29
-40
-50
-57
-58
-60
-72
-76
-80
-87
diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
index f97b0fca36..1531a41bd0 100644
--- a/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
+++ b/misc/dist/ios_xcode/godot_ios/godot_ios-Info.plist
@@ -5,32 +5,33 @@
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
- <string>Insert Name Here</string>
+ <string>$name</string>
<key>CFBundleExecutable</key>
- <string>godot_opt.iphone</string>
+ <string>$binary.iphone</string>
<key>CFBundleIcons</key>
<dict/>
<key>CFBundleIcons~ipad</key>
<dict/>
<key>CFBundleIdentifier</key>
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <string>$identifier</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
- <string>${PRODUCT_NAME}</string>
+ <string>$name</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>1.0</string>
+ <string>$short_version</string>
<key>CFBundleSignature</key>
- <string>????</string>
+ <string>$signature</string>
<key>CFBundleVersion</key>
- <string>1.0</string>
+ <string>$version</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
+ <string>gamekit</string>
</array>
<key>UIRequiresFullScreen</key>
<true/>
diff --git a/misc/dist/ios_xcode/godot_ios/godot_ios.entitlements b/misc/dist/ios_xcode/godot_ios/godot_ios.entitlements
new file mode 100644
index 0000000000..903def2af5
--- /dev/null
+++ b/misc/dist/ios_xcode/godot_ios/godot_ios.entitlements
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>aps-environment</key>
+ <string>development</string>
+</dict>
+</plist>
diff --git a/misc/dist/linux/godot.6 b/misc/dist/linux/godot.6
new file mode 100644
index 0000000000..946fa6c913
--- /dev/null
+++ b/misc/dist/linux/godot.6
@@ -0,0 +1,165 @@
+.TH GODOT "6" "September 2017" "godot 3.0-alpha" "Games"
+.SH NAME
+godot \- multi\-platform 2D and 3D game engine with a feature\-rich editor
+.SH SYNOPSIS
+.B godot
+[\fI\,options\/\fR] [path to scene or 'project.godot' file]
+.SH DESCRIPTION
+Godot Engine is an advanced, feature\-packed, multi\-platform 2D and 3D game
+engine.
+.br
+It provides a huge set of common tools, so you can just focus on making
+your game without reinventing the wheel.
+.SS "General options:"
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Display this help message.
+.TP
+\fB\-\-version\fR
+Display the version string.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Use verbose stdout mode.
+.TP
+\fB\-\-quiet\fR
+Quiet mode, silences stdout messages. Errors are still displayed.
+.SS "Run options:"
+.TP
+\fB\-e\fR, \fB\-\-editor\fR
+Start the editor instead of running the scene.
+.TP
+\fB\-p\fR, \fB\-\-project\-manager\fR
+Start the project manager, even if a project is auto\-detected.
+.TP
+\fB\-l\fR, \fB\-\-language\fR <locale>
+Use a specific locale (<locale> being a two\-letter code).
+.TP
+\fB\-\-path\fR <directory>
+Path to a project (<directory> must contain a 'project.godot' file).
+.TP
+\fB\-\-main\-pack\fR <file>
+Path to a pack (.pck) file to load.
+.TP
+\fB\-\-render\-thread\fR <mode>
+Render thread mode ('unsafe', 'safe', 'separate').
+.TP
+\fB\-\-remote\-fs\fR <address>
+Remote filesystem (<host/IP>[:<port>] address).
+.TP
+\fB\-\-remote\-fs\-password\fR <password>
+Password for remote filesystem.
+.TP
+\fB\-\-audio\-driver\fR <driver>
+Audio driver ('PulseAudio', 'ALSA').
+.TP
+\fB\-\-video\-driver\fR <driver>
+Video driver ('GLES3').
+.SS "Display options:"
+.TP
+\fB\-f\fR, \fB\-\-fullscreen\fR
+Request fullscreen mode.
+.TP
+\fB\-m\fR, \fB\-\-maximized\fR
+Request a maximized window.
+.TP
+\fB\-w\fR, \fB\-\-windowed\fR
+Request windowed mode.
+.TP
+\fB\-\-resolution\fR <W>x<H>
+Request window resolution.
+.TP
+\fB\-\-position\fR <X>,<Y>
+Request window position.
+.TP
+\fB\-\-low\-dpi\fR
+Force low\-DPI mode (macOS and Windows only).
+.TP
+\fB\-\-no\-window\fR
+Disable window creation (Windows only). Useful together with \fB\-\-script\fR.
+.SS "Debug options:"
+.TP
+\fB\-d\fR, \fB\-\-debug\fR
+Debug (local stdout debugger).
+.TP
+\fB\-b\fR, \fB\-\-breakpoints\fR
+Breakpoint list as source::line comma\-separated pairs, no spaces (use %20 instead).
+.TP
+\fB\-\-profiling\fR
+Enable profiling in the script debugger.
+.TP
+\fB\-\-remote\-debug\fR <address>
+Remote debug (<host/IP>:<port> address).
+.TP
+\fB\-\-debug\-collisions\fR
+Show collisions shapes when running the scene.
+.TP
+\fB\-\-debug\-navigation\fR
+Show navigation polygons when running the scene.
+.TP
+\fB\-\-frame\-delay\fR <ms>
+Simulate high CPU load (delay each frame by <ms> milliseconds).
+.TP
+\fB\-\-time\-scale\fR <scale>
+Force time scale (higher values are faster, 1.0 is normal speed).
+.TP
+\fB\-\-disable\-render\-loop\fR
+Disable render loop so rendering only occurs when called explicitly from script.
+.TP
+\fB\-\-disable\-crash\-handler\fR
+Disable crash handler when supported by the platform code.
+.TP
+\fB\-\-fixed\-fps\fR <fps>
+Force a fixed number of frames per second. This setting disables real\-time synchronization.
+.SS "Standalone tools:"
+.TP
+\fB\-s\fR, \fB\-\-script\fR <script>
+Run a script.
+.TP
+\fB\-\-export\fR <target>
+Export the project using the given export target.
+.TP
+\fB\-\-export\-debug\fR
+Use together with \fB\-\-export\fR, enables debug mode for the template.
+.TP
+\fB\-\-doctool\fR <path>
+Dump the engine API reference to the given <path> in XML format, merging if existing files are found.
+.TP
+\fB\-\-no\-docbase\fR
+Disallow dumping the base types (used with \fB\-\-doctool\fR).
+.TP
+\fB\-\-gdnative\-generate\-json\-api\fR
+Generate JSON dump of the Godot API for GDNative bindings.
+.TP
+\fB\-\-test\fR <test>
+Run a unit test ('string', 'containers', 'math', 'render', 'multimesh', 'gui', 'io', 'shaderlang', 'physics', 'oa_hash_map').
+.SH FILES
+~/.godot/
+.RS
+User\-specific configuration and cache folder, contains persistent editor and game configuration and saved files, temporary metadata, etc.
+.RE
+~/.godot/app_userdata/
+.RS
+Contains the default configuration and user data folders for Godot\-made games (\fIuser://\fR path).
+.RE
+~/.godot/templates/
+.RS
+Installation folder for "export templates", compiled binaries of the engine to deploy on the many supported platforms.
+.RE
+/usr/share/doc/godot/
+.RS
+Additional documentation files.
+.RE
+/usr/share/licenses/godot/
+.RS
+Detailed licensing information.
+.RE
+.SH "SEE ALSO"
+See the project website at \fIhttps://godotengine.org\fR and the source
+code repository at \fIhttps://github.com/godotengine/godot\fR for more details.
+.SH BUGS
+Godot Engine is a free and open source project and welcomes any kind of
+contributions. In particular, you can report issues or make suggestions on
+Godot's issue tracker at \fIhttps://github.com/godotengine/godot/issues\fR.
+.SH AUTHOR
+Man page written by Rémi Verschelde <akien@godotengine.org> on behalf of the
+Godot Engine development team.
diff --git a/misc/dist/linux/godot.appdata.xml b/misc/dist/linux/godot.appdata.xml
new file mode 100644
index 0000000000..907fe1f3be
--- /dev/null
+++ b/misc/dist/linux/godot.appdata.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2017 Rémi Verschelde <akien@godotengine.org> -->
+<component type="desktop">
+ <id>godot.desktop</id>
+ <metadata_license>CC0-1.0</metadata_license>
+ <project_license>MIT</project_license>
+ <name>Godot Engine</name>
+ <summary>Multi-platform 2D and 3D game engine with a feature-rich editor</summary>
+ <description>
+ <p>
+ Godot is an advanced, feature-packed, multi-platform 2D and 3D game
+ engine. It provides a huge set of common tools, so you can just focus on
+ making your game without reinventing the wheel.
+ </p>
+ <p>
+ Godot is completely free and open source under the very permissive MIT
+ license. No strings attached, no royalties, nothing. Your game is yours,
+ down to the last line of engine code.
+ </p>
+ </description>
+ <screenshots>
+ <screenshot type="default" width="1330" height="720">
+ <caption>3D project loaded in the Godot Engine editor</caption>
+ <image>https://download.tuxfamily.org/godotengine/media/screenshots/editor_3d_fracteed-720p.jpg</image>
+ </screenshot>
+ </screenshots>
+ <url type="homepage">https://godotengine.org</url>
+ <url type="bugtracker">https://github.com/godotengine/godot/issues</url>
+ <url type="help">http://docs.godotengine.org</url>
+ <url type="donation">https://godotengine.org/donate</url>
+ <url type="translate">https://hosted.weblate.org/projects/godot-engine/godot</url>
+ <developer_name>The Godot Engine Community</developer_name>
+ <update_contact>akien_at_godotengine_dot_org</update_contact>
+</component>
diff --git a/misc/dist/linux/godot.desktop b/misc/dist/linux/godot.desktop
new file mode 100644
index 0000000000..545c491256
--- /dev/null
+++ b/misc/dist/linux/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/osx_tools.app/Contents/Info.plist b/misc/dist/osx_tools.app/Contents/Info.plist
index 4d88e97503..5012d17c37 100755
--- a/misc/dist/osx_tools.app/Contents/Info.plist
+++ b/misc/dist/osx_tools.app/Contents/Info.plist
@@ -19,11 +19,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>2.2-dev</string>
+ <string>3.0-dev</string>
<key>CFBundleSignature</key>
<string>godot</string>
<key>CFBundleVersion</key>
- <string>2.2-dev</string>
+ <string>3.0-dev</string>
<key>NSHumanReadableCopyright</key>
<string>© 2007-2017 Juan Linietsky, Ariel Manzur</string>
<key>LSMinimumSystemVersion</key>
diff --git a/modules/dds/texture_loader_dds.cpp b/modules/dds/texture_loader_dds.cpp
index 95d93e6af6..ae9daa802f 100644
--- a/modules/dds/texture_loader_dds.cpp
+++ b/modules/dds/texture_loader_dds.cpp
@@ -152,7 +152,7 @@ RES ResourceFormatDDS::load(const String &p_path, const String &p_original_path,
*/
//must avoid this later
- while (f->get_pos() < 128)
+ while (f->get_position() < 128)
f->get_8();
DDSFormat dds_format;
diff --git a/modules/enet/SCsub b/modules/enet/SCsub
index 42a933a66d..4790c5099f 100644
--- a/modules/enet/SCsub
+++ b/modules/enet/SCsub
@@ -7,7 +7,7 @@ Import('env_modules')
env_enet = env_modules.Clone()
-if (env['builtin_enet'] != 'no'):
+if env['builtin_enet']:
thirdparty_dir = "#thirdparty/enet/"
thirdparty_sources = [
"godot.cpp",
diff --git a/modules/etc/config.py b/modules/etc/config.py
index 4b0b01b78e..7dc2cb59c1 100644
--- a/modules/etc/config.py
+++ b/modules/etc/config.py
@@ -6,6 +6,6 @@ def can_build(platform):
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
- if (env["tools"] == "no"):
- env["module_etc_enabled"] = "no"
+ if not env['tools']:
+ env['module_etc_enabled'] = False
env.disabled_modules.append("etc")
diff --git a/modules/freetype/SCsub b/modules/freetype/SCsub
index f22df4407c..19e384af73 100644
--- a/modules/freetype/SCsub
+++ b/modules/freetype/SCsub
@@ -6,7 +6,7 @@ from compat import isbasestring
# Not building in a separate env as scene needs it
# Thirdparty source files
-if (env['builtin_freetype'] != 'no'):
+if env['builtin_freetype']:
thirdparty_dir = "#thirdparty/freetype/"
thirdparty_sources = [
"src/autofit/autofit.c",
@@ -65,7 +65,7 @@ if (env['builtin_freetype'] != 'no'):
env.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "/include"])
# also requires libpng headers
- if (env['builtin_libpng'] != 'no'):
+ if env['builtin_libpng']:
env.Append(CPPPATH=["#thirdparty/libpng"])
lib = env.Library("freetype_builtin", thirdparty_sources)
diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub
index f386f2b542..39f5ec5378 100644
--- a/modules/gdnative/SCsub
+++ b/modules/gdnative/SCsub
@@ -11,7 +11,7 @@ gdn_env.add_source_files(env.modules_sources, "nativescript/*.cpp")
gdn_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
gdn_env.Append(CPPPATH=['#modules/gdnative/include/'])
-if "platform" in env and env["platform"] == "x11": # there has to be a better solution?
+if "platform" in env and env["platform"] in ["x11", "iphone"]:
env.Append(LINKFLAGS=["-rdynamic"])
env.use_ptrcall = True
diff --git a/modules/gdnative/gd_native_library_editor.cpp b/modules/gdnative/gd_native_library_editor.cpp
index 8aa931d6c9..cc2c2b69a6 100644
--- a/modules/gdnative/gd_native_library_editor.cpp
+++ b/modules/gdnative/gd_native_library_editor.cpp
@@ -1,9 +1,39 @@
+/*************************************************************************/
+/* gd_native_library_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 "gd_native_library_editor.h"
+
#include "gdnative.h"
void GDNativeLibraryEditor::_find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set<String> &enabled_list) {
-
// check children
for (int i = 0; i < p_dir->get_file_count(); i++) {
@@ -17,48 +47,45 @@ void GDNativeLibraryEditor::_find_gdnative_singletons(EditorFileSystemDirectory
if (lib.is_valid() && lib->is_singleton_gdnative()) {
String path = p_dir->get_file_path(i);
TreeItem *ti = libraries->create_item(libraries->get_root());
- ti->set_text(0,path.get_file());
- ti->set_tooltip(0,path);
- ti->set_metadata(0,path);
- ti->set_cell_mode(1,TreeItem::CELL_MODE_RANGE);
- ti->set_text(1,"Disabled,Enabled");
- bool enabled = enabled_list.has(path)?true:false;
-
- ti->set_range(1,enabled?1:0);
- ti->set_custom_color(1,enabled?Color(0,1,0):Color(1,0,0));
+ ti->set_text(0, path.get_file());
+ ti->set_tooltip(0, path);
+ ti->set_metadata(0, path);
+ ti->set_cell_mode(1, TreeItem::CELL_MODE_RANGE);
+ ti->set_text(1, "Disabled,Enabled");
+ bool enabled = enabled_list.has(path) ? true : false;
+
+ ti->set_range(1, enabled ? 1 : 0);
+ ti->set_custom_color(1, enabled ? Color(0, 1, 0) : Color(1, 0, 0));
}
}
// check subdirectories
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
- _find_gdnative_singletons(p_dir->get_subdir(i),enabled_list);
+ _find_gdnative_singletons(p_dir->get_subdir(i), enabled_list);
}
-
-
}
void GDNativeLibraryEditor::_update_libraries() {
- updating=true;
+ updating = true;
libraries->clear();
libraries->create_item(); //rppt
Vector<String> enabled_paths;
if (ProjectSettings::get_singleton()->has("gdnative/singletons")) {
- enabled_paths=ProjectSettings::get_singleton()->get("gdnative/singletons");
+ enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons");
}
Set<String> enabled_list;
- for(int i=0;i<enabled_paths.size();i++) {
+ for (int i = 0; i < enabled_paths.size(); i++) {
enabled_list.insert(enabled_paths[i]);
}
EditorFileSystemDirectory *fs = EditorFileSystem::get_singleton()->get_filesystem();
if (fs) {
- _find_gdnative_singletons(fs,enabled_list);
+ _find_gdnative_singletons(fs, enabled_list);
}
- updating=false;
-
+ updating = false;
}
void GDNativeLibraryEditor::_item_edited() {
@@ -74,11 +101,11 @@ void GDNativeLibraryEditor::_item_edited() {
Vector<String> enabled_paths;
if (ProjectSettings::get_singleton()->has("gdnative/singletons")) {
- enabled_paths=ProjectSettings::get_singleton()->get("gdnative/singletons");
+ enabled_paths = ProjectSettings::get_singleton()->get("gdnative/singletons");
}
if (enabled) {
- if (enabled_paths.find(path)==-1) {
+ if (enabled_paths.find(path) == -1) {
enabled_paths.push_back(path);
}
} else {
@@ -86,15 +113,15 @@ void GDNativeLibraryEditor::_item_edited() {
}
if (enabled_paths.size()) {
- ProjectSettings::get_singleton()->set("gdnative/singletons",enabled_paths);
+ ProjectSettings::get_singleton()->set("gdnative/singletons", enabled_paths);
} else {
- ProjectSettings::get_singleton()->set("gdnative/singletons",Variant());
+ ProjectSettings::get_singleton()->set("gdnative/singletons", Variant());
}
}
void GDNativeLibraryEditor::_notification(int p_what) {
- if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {
+ if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
if (is_visible_in_tree()) {
_update_libraries();
}
@@ -103,18 +130,19 @@ void GDNativeLibraryEditor::_notification(int p_what) {
void GDNativeLibraryEditor::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_item_edited"),&GDNativeLibraryEditor::_item_edited);
+ ClassDB::bind_method(D_METHOD("_item_edited"), &GDNativeLibraryEditor::_item_edited);
}
-GDNativeLibraryEditor::GDNativeLibraryEditor()
-{
- libraries = memnew( Tree );
+GDNativeLibraryEditor::GDNativeLibraryEditor() {
+ libraries = memnew(Tree);
libraries->set_columns(2);
libraries->set_column_titles_visible(true);
- libraries->set_column_title(0,TTR("Library"));
- libraries->set_column_title(1,TTR("Status"));
+ libraries->set_column_title(0, TTR("Library"));
+ libraries->set_column_title(1, TTR("Status"));
libraries->set_hide_root(true);
- add_margin_child(TTR("Libraries: "),libraries,true);
- updating=false;
- libraries->connect("item_edited",this,"_item_edited");
+ add_margin_child(TTR("Libraries: "), libraries, true);
+ updating = false;
+ libraries->connect("item_edited", this, "_item_edited");
}
+
+#endif // TOOLS_ENABLED
diff --git a/modules/gdnative/gd_native_library_editor.h b/modules/gdnative/gd_native_library_editor.h
index a6c8f31790..a11c4620dd 100644
--- a/modules/gdnative/gd_native_library_editor.h
+++ b/modules/gdnative/gd_native_library_editor.h
@@ -1,23 +1,52 @@
+/*************************************************************************/
+/* gd_native_library_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_NATIVE_LIBRARY_EDITOR_H
#define GD_NATIVE_LIBRARY_EDITOR_H
#ifdef TOOLS_ENABLED
-#include "editor/project_settings_editor.h"
#include "editor/editor_file_system.h"
+#include "editor/project_settings_editor.h"
-class GDNativeLibraryEditor : public VBoxContainer
-{
+class GDNativeLibraryEditor : public VBoxContainer {
Tree *libraries;
bool updating;
void _update_libraries();
- void _find_gdnative_singletons(EditorFileSystemDirectory *p_dir,const Set<String>& enabled_list);
+ void _find_gdnative_singletons(EditorFileSystemDirectory *p_dir, const Set<String> &enabled_list);
void _item_edited();
-protected:
+protected:
void _notification(int p_what);
static void _bind_methods();
+
public:
GDNativeLibraryEditor();
};
diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp
index 6da538844a..f0c09a3370 100644
--- a/modules/gdnative/gdnative.cpp
+++ b/modules/gdnative/gdnative.cpp
@@ -40,6 +40,16 @@
const String init_symbol = "godot_gdnative_init";
const String terminate_symbol = "godot_gdnative_terminate";
+#define GDAPI_FUNC(name, ret_type, ...) name,
+#define GDAPI_FUNC_VOID(name, ...) name,
+
+const godot_gdnative_api_struct api_struct = {
+ GODOT_GDNATIVE_API_FUNCTIONS
+};
+
+#undef GDAPI_FUNC
+#undef GDAPI_FUNC_VOID
+
String GDNativeLibrary::platform_names[NUM_PLATFORMS + 1] = {
"X11_32bit",
"X11_64bit",
@@ -91,7 +101,7 @@ GDNativeLibrary::Platform GDNativeLibrary::current_platform =
#endif
GDNativeLibrary::GDNativeLibrary()
- : library_paths() {
+ : library_paths(), singleton_gdnative(false) {
}
GDNativeLibrary::~GDNativeLibrary() {
@@ -100,6 +110,7 @@ GDNativeLibrary::~GDNativeLibrary() {
void GDNativeLibrary::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_library_path", "platform", "path"), &GDNativeLibrary::set_library_path);
ClassDB::bind_method(D_METHOD("get_library_path", "platform"), &GDNativeLibrary::get_library_path);
+ ClassDB::bind_method(D_METHOD("get_active_library_path"), &GDNativeLibrary::get_active_library_path);
ClassDB::bind_method(D_METHOD("is_singleton_gdnative"), &GDNativeLibrary::is_singleton_gdnative);
ClassDB::bind_method(D_METHOD("set_singleton_gdnative", "singleton"), &GDNativeLibrary::set_singleton_gdnative);
@@ -224,8 +235,11 @@ bool GDNative::initialize() {
ERR_PRINT("No library set for this platform");
return false;
}
-
+#ifdef IPHONE_ENABLED
+ String path = lib_path.replace("res://", "dylibs/");
+#else
String path = ProjectSettings::get_singleton()->globalize_path(lib_path);
+#endif
Error err = OS::get_singleton()->open_dynamic_library(path, native_handle);
if (err != OK) {
return false;
@@ -249,11 +263,13 @@ bool GDNative::initialize() {
godot_gdnative_init_options options;
+ options.api_struct = &api_struct;
options.in_editor = Engine::get_singleton()->is_editor_hint();
options.core_api_hash = ClassDB::get_api_hash(ClassDB::API_CORE);
options.editor_api_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR);
options.no_api_hash = ClassDB::get_api_hash(ClassDB::API_NONE);
options.gd_native_library = (godot_object *)(get_library().ptr());
+ options.active_library_path = (godot_string *)&path;
library_init_fpointer(&options);
diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h
index 4753c7efe5..29c6201641 100644
--- a/modules/gdnative/gdnative.h
+++ b/modules/gdnative/gdnative.h
@@ -36,6 +36,7 @@
#include "resource.h"
#include "gdnative/gdnative.h"
+#include "gdnative_api_struct.h"
class GDNativeLibrary : public Resource {
GDCLASS(GDNativeLibrary, Resource)
@@ -77,7 +78,7 @@ class GDNativeLibrary : public Resource {
String library_paths[NUM_PLATFORMS];
- bool singleton_gdnative = false;
+ bool singleton_gdnative;
protected:
bool _set(const StringName &p_name, const Variant &p_value);
diff --git a/modules/gdnative/gdnative/variant.cpp b/modules/gdnative/gdnative/variant.cpp
index 1b2aae607f..9ba4166c1d 100644
--- a/modules/gdnative/gdnative/variant.cpp
+++ b/modules/gdnative/gdnative/variant.cpp
@@ -480,10 +480,9 @@ godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const g
return self->hash_compare(*other);
}
-godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid) {
+godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self) {
const Variant *self = (const Variant *)p_self;
- bool &valid = *r_valid;
- return self->booleanize(valid);
+ return self->booleanize();
}
void GDAPI godot_variant_destroy(godot_variant *p_self) {
diff --git a/modules/gdnative/include/gdnative/gdnative.h b/modules/gdnative/include/gdnative/gdnative.h
index c574c56d5a..9134f1c581 100644
--- a/modules/gdnative/include/gdnative/gdnative.h
+++ b/modules/gdnative/include/gdnative/gdnative.h
@@ -49,8 +49,8 @@ extern "C" {
#elif defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
-#define GDCALLINGCONV
-#define GDAPI
+#define GDCALLINGCONV __attribute__((visibility("default")))
+#define GDAPI GDCALLINGCONV
#elif TARGET_OS_MAC
#define GDCALLINGCONV __attribute__((sysv_abi))
#define GDAPI GDCALLINGCONV
@@ -103,7 +103,7 @@ typedef enum {
GODOT_ERR_CANT_CONNECT, // (25)
GODOT_ERR_CANT_RESOLVE,
GODOT_ERR_CONNECTION_ERROR,
- GODOT_ERR_CANT_AQUIRE_RESOURCE,
+ GODOT_ERR_CANT_ACQUIRE_RESOURCE,
GODOT_ERR_CANT_FORK,
GODOT_ERR_INVALID_DATA, ///< Data passed is invalid (30)
GODOT_ERR_INVALID_PARAMETER, ///< Parameter passed is invalid
@@ -234,12 +234,16 @@ void GDAPI godot_method_bind_ptrcall(godot_method_bind *p_method_bind, godot_obj
godot_variant GDAPI godot_method_bind_call(godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error);
////// Script API
+struct godot_gdnative_api_struct; // Forward declaration
+
typedef struct {
godot_bool in_editor;
uint64_t core_api_hash;
uint64_t editor_api_hash;
uint64_t no_api_hash;
godot_object *gd_native_library; // pointer to GDNativeLibrary that is being initialized
+ const struct godot_gdnative_api_struct *api_struct;
+ const godot_string *active_library_path;
} godot_gdnative_init_options;
typedef struct {
diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h
index 969506585d..7b804c1eaf 100644
--- a/modules/gdnative/include/gdnative/variant.h
+++ b/modules/gdnative/include/gdnative/variant.h
@@ -190,7 +190,7 @@ godot_bool GDAPI godot_variant_operator_less(const godot_variant *p_self, const
godot_bool GDAPI godot_variant_hash_compare(const godot_variant *p_self, const godot_variant *p_other);
-godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self, godot_bool *r_valid);
+godot_bool GDAPI godot_variant_booleanize(const godot_variant *p_self);
void GDAPI godot_variant_destroy(godot_variant *p_self);
diff --git a/modules/gdnative/include/gdnative_api_struct.h b/modules/gdnative/include/gdnative_api_struct.h
new file mode 100644
index 0000000000..c345e27227
--- /dev/null
+++ b/modules/gdnative/include/gdnative_api_struct.h
@@ -0,0 +1,723 @@
+/*************************************************************************/
+/* gdnative_api_struct.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_GDNATIVE_API_STRUCT_H
+#define GODOT_GDNATIVE_API_STRUCT_H
+
+#include <gdnative/gdnative.h>
+#include <nativescript/godot_nativescript.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Using X_MACRO to keep api function signatures in a single list
+#define GODOT_GDNATIVE_API_FUNCTIONS \
+ GDAPI_FUNC_VOID(godot_color_new_rgba, godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b, const godot_real p_a) \
+ GDAPI_FUNC_VOID(godot_color_new_rgb, godot_color *r_dest, const godot_real p_r, const godot_real p_g, const godot_real p_b) \
+ GDAPI_FUNC(godot_color_get_r, godot_real, const godot_color *p_self) \
+ GDAPI_FUNC_VOID(godot_color_set_r, godot_color *p_self, const godot_real r) \
+ GDAPI_FUNC(godot_color_get_g, godot_real, const godot_color *p_self) \
+ GDAPI_FUNC_VOID(godot_color_set_g, godot_color *p_self, const godot_real g) \
+ GDAPI_FUNC(godot_color_get_b, godot_real, const godot_color *p_self) \
+ GDAPI_FUNC_VOID(godot_color_set_b, godot_color *p_self, const godot_real b) \
+ GDAPI_FUNC(godot_color_get_a, godot_real, const godot_color *p_self) \
+ GDAPI_FUNC_VOID(godot_color_set_a, godot_color *p_self, const godot_real a) \
+ GDAPI_FUNC(godot_color_get_h, godot_real, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_get_s, godot_real, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_get_v, godot_real, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_as_string, godot_string, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_to_rgba32, godot_int, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_to_argb32, godot_int, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_gray, godot_real, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_inverted, godot_color, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_contrasted, godot_color, const godot_color *p_self) \
+ GDAPI_FUNC(godot_color_linear_interpolate, godot_color, const godot_color *p_self, const godot_color *p_b, const godot_real p_t) \
+ GDAPI_FUNC(godot_color_blend, godot_color, const godot_color *p_self, const godot_color *p_over) \
+ GDAPI_FUNC(godot_color_to_html, godot_string, const godot_color *p_self, const godot_bool p_with_alpha) \
+ GDAPI_FUNC(godot_color_operator_equal, godot_bool, const godot_color *p_self, const godot_color *p_b) \
+ GDAPI_FUNC(godot_color_operator_less, godot_bool, const godot_color *p_self, const godot_color *p_b) \
+ GDAPI_FUNC_VOID(godot_vector2_new, godot_vector2 *r_dest, const godot_real p_x, const godot_real p_y) \
+ GDAPI_FUNC(godot_vector2_as_string, godot_string, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_normalized, godot_vector2, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_length, godot_real, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_angle, godot_real, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_length_squared, godot_real, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_is_normalized, godot_bool, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_distance_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \
+ GDAPI_FUNC(godot_vector2_distance_squared_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \
+ GDAPI_FUNC(godot_vector2_angle_to, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \
+ GDAPI_FUNC(godot_vector2_angle_to_point, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_to) \
+ GDAPI_FUNC(godot_vector2_linear_interpolate, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_real p_t) \
+ GDAPI_FUNC(godot_vector2_cubic_interpolate, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b, const godot_vector2 *p_pre_a, const godot_vector2 *p_post_b, const godot_real p_t) \
+ GDAPI_FUNC(godot_vector2_rotated, godot_vector2, const godot_vector2 *p_self, const godot_real p_phi) \
+ GDAPI_FUNC(godot_vector2_tangent, godot_vector2, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_floor, godot_vector2, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_snapped, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_by) \
+ GDAPI_FUNC(godot_vector2_aspect, godot_real, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_dot, godot_real, const godot_vector2 *p_self, const godot_vector2 *p_with) \
+ GDAPI_FUNC(godot_vector2_slide, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \
+ GDAPI_FUNC(godot_vector2_bounce, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \
+ GDAPI_FUNC(godot_vector2_reflect, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_n) \
+ GDAPI_FUNC(godot_vector2_abs, godot_vector2, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_clamped, godot_vector2, const godot_vector2 *p_self, const godot_real p_length) \
+ GDAPI_FUNC(godot_vector2_operator_add, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \
+ GDAPI_FUNC(godot_vector2_operator_substract, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \
+ GDAPI_FUNC(godot_vector2_operator_multiply_vector, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \
+ GDAPI_FUNC(godot_vector2_operator_multiply_scalar, godot_vector2, const godot_vector2 *p_self, const godot_real p_b) \
+ GDAPI_FUNC(godot_vector2_operator_divide_vector, godot_vector2, const godot_vector2 *p_self, const godot_vector2 *p_b) \
+ GDAPI_FUNC(godot_vector2_operator_divide_scalar, godot_vector2, const godot_vector2 *p_self, const godot_real p_b) \
+ GDAPI_FUNC(godot_vector2_operator_equal, godot_bool, const godot_vector2 *p_self, const godot_vector2 *p_b) \
+ GDAPI_FUNC(godot_vector2_operator_less, godot_bool, const godot_vector2 *p_self, const godot_vector2 *p_b) \
+ GDAPI_FUNC(godot_vector2_operator_neg, godot_vector2, const godot_vector2 *p_self) \
+ GDAPI_FUNC_VOID(godot_vector2_set_x, godot_vector2 *p_self, const godot_real p_x) \
+ GDAPI_FUNC_VOID(godot_vector2_set_y, godot_vector2 *p_self, const godot_real p_y) \
+ GDAPI_FUNC(godot_vector2_get_x, godot_real, const godot_vector2 *p_self) \
+ GDAPI_FUNC(godot_vector2_get_y, godot_real, const godot_vector2 *p_self) \
+ GDAPI_FUNC_VOID(godot_quat_new, godot_quat *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z, const godot_real p_w) \
+ GDAPI_FUNC_VOID(godot_quat_new_with_axis_angle, godot_quat *r_dest, const godot_vector3 *p_axis, const godot_real p_angle) \
+ GDAPI_FUNC(godot_quat_get_x, godot_real, const godot_quat *p_self) \
+ GDAPI_FUNC_VOID(godot_quat_set_x, godot_quat *p_self, const godot_real val) \
+ GDAPI_FUNC(godot_quat_get_y, godot_real, const godot_quat *p_self) \
+ GDAPI_FUNC_VOID(godot_quat_set_y, godot_quat *p_self, const godot_real val) \
+ GDAPI_FUNC(godot_quat_get_z, godot_real, const godot_quat *p_self) \
+ GDAPI_FUNC_VOID(godot_quat_set_z, godot_quat *p_self, const godot_real val) \
+ GDAPI_FUNC(godot_quat_get_w, godot_real, const godot_quat *p_self) \
+ GDAPI_FUNC_VOID(godot_quat_set_w, godot_quat *p_self, const godot_real val) \
+ GDAPI_FUNC(godot_quat_as_string, godot_string, const godot_quat *p_self) \
+ GDAPI_FUNC(godot_quat_length, godot_real, const godot_quat *p_self) \
+ GDAPI_FUNC(godot_quat_length_squared, godot_real, const godot_quat *p_self) \
+ GDAPI_FUNC(godot_quat_normalized, godot_quat, const godot_quat *p_self) \
+ GDAPI_FUNC(godot_quat_is_normalized, godot_bool, const godot_quat *p_self) \
+ GDAPI_FUNC(godot_quat_inverse, godot_quat, const godot_quat *p_self) \
+ GDAPI_FUNC(godot_quat_dot, godot_real, const godot_quat *p_self, const godot_quat *p_b) \
+ GDAPI_FUNC(godot_quat_xform, godot_vector3, const godot_quat *p_self, const godot_vector3 *p_v) \
+ GDAPI_FUNC(godot_quat_slerp, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_real p_t) \
+ GDAPI_FUNC(godot_quat_slerpni, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_real p_t) \
+ GDAPI_FUNC(godot_quat_cubic_slerp, godot_quat, const godot_quat *p_self, const godot_quat *p_b, const godot_quat *p_pre_a, const godot_quat *p_post_b, const godot_real p_t) \
+ GDAPI_FUNC(godot_quat_operator_multiply, godot_quat, const godot_quat *p_self, const godot_real p_b) \
+ GDAPI_FUNC(godot_quat_operator_add, godot_quat, const godot_quat *p_self, const godot_quat *p_b) \
+ GDAPI_FUNC(godot_quat_operator_substract, godot_quat, const godot_quat *p_self, const godot_quat *p_b) \
+ GDAPI_FUNC(godot_quat_operator_divide, godot_quat, const godot_quat *p_self, const godot_real p_b) \
+ GDAPI_FUNC(godot_quat_operator_equal, godot_bool, const godot_quat *p_self, const godot_quat *p_b) \
+ GDAPI_FUNC(godot_quat_operator_neg, godot_quat, const godot_quat *p_self) \
+ GDAPI_FUNC_VOID(godot_basis_new_with_rows, godot_basis *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis) \
+ GDAPI_FUNC_VOID(godot_basis_new_with_axis_and_angle, godot_basis *r_dest, const godot_vector3 *p_axis, const godot_real p_phi) \
+ GDAPI_FUNC_VOID(godot_basis_new_with_euler, godot_basis *r_dest, const godot_vector3 *p_euler) \
+ GDAPI_FUNC(godot_basis_as_string, godot_string, const godot_basis *p_self) \
+ GDAPI_FUNC(godot_basis_inverse, godot_basis, const godot_basis *p_self) \
+ GDAPI_FUNC(godot_basis_transposed, godot_basis, const godot_basis *p_self) \
+ GDAPI_FUNC(godot_basis_orthonormalized, godot_basis, const godot_basis *p_self) \
+ GDAPI_FUNC(godot_basis_determinant, godot_real, const godot_basis *p_self) \
+ GDAPI_FUNC(godot_basis_rotated, godot_basis, const godot_basis *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \
+ GDAPI_FUNC(godot_basis_scaled, godot_basis, const godot_basis *p_self, const godot_vector3 *p_scale) \
+ GDAPI_FUNC(godot_basis_get_scale, godot_vector3, const godot_basis *p_self) \
+ GDAPI_FUNC(godot_basis_get_euler, godot_vector3, const godot_basis *p_self) \
+ GDAPI_FUNC(godot_basis_tdotx, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \
+ GDAPI_FUNC(godot_basis_tdoty, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \
+ GDAPI_FUNC(godot_basis_tdotz, godot_real, const godot_basis *p_self, const godot_vector3 *p_with) \
+ GDAPI_FUNC(godot_basis_xform, godot_vector3, const godot_basis *p_self, const godot_vector3 *p_v) \
+ GDAPI_FUNC(godot_basis_xform_inv, godot_vector3, const godot_basis *p_self, const godot_vector3 *p_v) \
+ GDAPI_FUNC(godot_basis_get_orthogonal_index, godot_int, const godot_basis *p_self) \
+ GDAPI_FUNC_VOID(godot_basis_new, godot_basis *r_dest) \
+ GDAPI_FUNC_VOID(godot_basis_new_with_euler_quat, godot_basis *r_dest, const godot_quat *p_euler) \
+ GDAPI_FUNC_VOID(godot_basis_get_elements, godot_basis *p_self, godot_vector3 *p_elements) \
+ GDAPI_FUNC(godot_basis_get_axis, godot_vector3, const godot_basis *p_self, const godot_int p_axis) \
+ GDAPI_FUNC_VOID(godot_basis_set_axis, godot_basis *p_self, const godot_int p_axis, const godot_vector3 *p_value) \
+ GDAPI_FUNC(godot_basis_get_row, godot_vector3, const godot_basis *p_self, const godot_int p_row) \
+ GDAPI_FUNC_VOID(godot_basis_set_row, godot_basis *p_self, const godot_int p_row, const godot_vector3 *p_value) \
+ GDAPI_FUNC(godot_basis_operator_equal, godot_bool, const godot_basis *p_self, const godot_basis *p_b) \
+ GDAPI_FUNC(godot_basis_operator_add, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \
+ GDAPI_FUNC(godot_basis_operator_substract, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \
+ GDAPI_FUNC(godot_basis_operator_multiply_vector, godot_basis, const godot_basis *p_self, const godot_basis *p_b) \
+ GDAPI_FUNC(godot_basis_operator_multiply_scalar, godot_basis, const godot_basis *p_self, const godot_real p_b) \
+ GDAPI_FUNC_VOID(godot_vector3_new, godot_vector3 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_z) \
+ GDAPI_FUNC(godot_vector3_as_string, godot_string, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_min_axis, godot_int, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_max_axis, godot_int, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_length, godot_real, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_length_squared, godot_real, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_is_normalized, godot_bool, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_normalized, godot_vector3, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_inverse, godot_vector3, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_snapped, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_by) \
+ GDAPI_FUNC(godot_vector3_rotated, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \
+ GDAPI_FUNC(godot_vector3_linear_interpolate, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_real p_t) \
+ GDAPI_FUNC(godot_vector3_cubic_interpolate, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b, const godot_vector3 *p_pre_a, const godot_vector3 *p_post_b, const godot_real p_t) \
+ GDAPI_FUNC(godot_vector3_dot, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_cross, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_outer, godot_basis, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_to_diagonal_matrix, godot_basis, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_abs, godot_vector3, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_floor, godot_vector3, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_ceil, godot_vector3, const godot_vector3 *p_self) \
+ GDAPI_FUNC(godot_vector3_distance_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_distance_squared_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_angle_to, godot_real, const godot_vector3 *p_self, const godot_vector3 *p_to) \
+ GDAPI_FUNC(godot_vector3_slide, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \
+ GDAPI_FUNC(godot_vector3_bounce, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \
+ GDAPI_FUNC(godot_vector3_reflect, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_n) \
+ GDAPI_FUNC(godot_vector3_operator_add, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_operator_substract, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_operator_multiply_vector, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_operator_multiply_scalar, godot_vector3, const godot_vector3 *p_self, const godot_real p_b) \
+ GDAPI_FUNC(godot_vector3_operator_divide_vector, godot_vector3, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_operator_divide_scalar, godot_vector3, const godot_vector3 *p_self, const godot_real p_b) \
+ GDAPI_FUNC(godot_vector3_operator_equal, godot_bool, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_operator_less, godot_bool, const godot_vector3 *p_self, const godot_vector3 *p_b) \
+ GDAPI_FUNC(godot_vector3_operator_neg, godot_vector3, const godot_vector3 *p_self) \
+ GDAPI_FUNC_VOID(godot_vector3_set_axis, godot_vector3 *p_self, const godot_vector3_axis p_axis, const godot_real p_val) \
+ GDAPI_FUNC(godot_vector3_get_axis, godot_real, const godot_vector3 *p_self, const godot_vector3_axis p_axis) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_new, godot_pool_byte_array *r_dest) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_new_copy, godot_pool_byte_array *r_dest, const godot_pool_byte_array *p_src) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_new_with_array, godot_pool_byte_array *r_dest, const godot_array *p_a) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_append, godot_pool_byte_array *p_self, const uint8_t p_data) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_append_array, godot_pool_byte_array *p_self, const godot_pool_byte_array *p_array) \
+ GDAPI_FUNC(godot_pool_byte_array_insert, godot_error, godot_pool_byte_array *p_self, const godot_int p_idx, const uint8_t p_data) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_invert, godot_pool_byte_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_push_back, godot_pool_byte_array *p_self, const uint8_t p_data) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_remove, godot_pool_byte_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_resize, godot_pool_byte_array *p_self, const godot_int p_size) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_set, godot_pool_byte_array *p_self, const godot_int p_idx, const uint8_t p_data) \
+ GDAPI_FUNC(godot_pool_byte_array_get, uint8_t, const godot_pool_byte_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_pool_byte_array_size, godot_int, const godot_pool_byte_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_byte_array_destroy, godot_pool_byte_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_new, godot_pool_int_array *r_dest) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_new_copy, godot_pool_int_array *r_dest, const godot_pool_int_array *p_src) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_new_with_array, godot_pool_int_array *r_dest, const godot_array *p_a) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_append, godot_pool_int_array *p_self, const godot_int p_data) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_append_array, godot_pool_int_array *p_self, const godot_pool_int_array *p_array) \
+ GDAPI_FUNC(godot_pool_int_array_insert, godot_error, godot_pool_int_array *p_self, const godot_int p_idx, const godot_int p_data) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_invert, godot_pool_int_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_push_back, godot_pool_int_array *p_self, const godot_int p_data) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_remove, godot_pool_int_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_resize, godot_pool_int_array *p_self, const godot_int p_size) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_set, godot_pool_int_array *p_self, const godot_int p_idx, const godot_int p_data) \
+ GDAPI_FUNC(godot_pool_int_array_get, godot_int, const godot_pool_int_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_pool_int_array_size, godot_int, const godot_pool_int_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_int_array_destroy, godot_pool_int_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_new, godot_pool_real_array *r_dest) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_new_copy, godot_pool_real_array *r_dest, const godot_pool_real_array *p_src) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_new_with_array, godot_pool_real_array *r_dest, const godot_array *p_a) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_append, godot_pool_real_array *p_self, const godot_real p_data) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_append_array, godot_pool_real_array *p_self, const godot_pool_real_array *p_array) \
+ GDAPI_FUNC(godot_pool_real_array_insert, godot_error, godot_pool_real_array *p_self, const godot_int p_idx, const godot_real p_data) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_invert, godot_pool_real_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_push_back, godot_pool_real_array *p_self, const godot_real p_data) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_remove, godot_pool_real_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_resize, godot_pool_real_array *p_self, const godot_int p_size) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_set, godot_pool_real_array *p_self, const godot_int p_idx, const godot_real p_data) \
+ GDAPI_FUNC(godot_pool_real_array_get, godot_real, const godot_pool_real_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_pool_real_array_size, godot_int, const godot_pool_real_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_real_array_destroy, godot_pool_real_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_new, godot_pool_string_array *r_dest) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_new_copy, godot_pool_string_array *r_dest, const godot_pool_string_array *p_src) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_new_with_array, godot_pool_string_array *r_dest, const godot_array *p_a) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_append, godot_pool_string_array *p_self, const godot_string *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_append_array, godot_pool_string_array *p_self, const godot_pool_string_array *p_array) \
+ GDAPI_FUNC(godot_pool_string_array_insert, godot_error, godot_pool_string_array *p_self, const godot_int p_idx, const godot_string *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_invert, godot_pool_string_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_push_back, godot_pool_string_array *p_self, const godot_string *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_remove, godot_pool_string_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_resize, godot_pool_string_array *p_self, const godot_int p_size) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_set, godot_pool_string_array *p_self, const godot_int p_idx, const godot_string *p_data) \
+ GDAPI_FUNC(godot_pool_string_array_get, godot_string, const godot_pool_string_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_pool_string_array_size, godot_int, const godot_pool_string_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_string_array_destroy, godot_pool_string_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_new, godot_pool_vector2_array *r_dest) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_new_copy, godot_pool_vector2_array *r_dest, const godot_pool_vector2_array *p_src) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_new_with_array, godot_pool_vector2_array *r_dest, const godot_array *p_a) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_append, godot_pool_vector2_array *p_self, const godot_vector2 *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_append_array, godot_pool_vector2_array *p_self, const godot_pool_vector2_array *p_array) \
+ GDAPI_FUNC(godot_pool_vector2_array_insert, godot_error, godot_pool_vector2_array *p_self, const godot_int p_idx, const godot_vector2 *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_invert, godot_pool_vector2_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_push_back, godot_pool_vector2_array *p_self, const godot_vector2 *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_remove, godot_pool_vector2_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_resize, godot_pool_vector2_array *p_self, const godot_int p_size) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_set, godot_pool_vector2_array *p_self, const godot_int p_idx, const godot_vector2 *p_data) \
+ GDAPI_FUNC(godot_pool_vector2_array_get, godot_vector2, const godot_pool_vector2_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_pool_vector2_array_size, godot_int, const godot_pool_vector2_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_vector2_array_destroy, godot_pool_vector2_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_new, godot_pool_vector3_array *r_dest) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_new_copy, godot_pool_vector3_array *r_dest, const godot_pool_vector3_array *p_src) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_new_with_array, godot_pool_vector3_array *r_dest, const godot_array *p_a) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_append, godot_pool_vector3_array *p_self, const godot_vector3 *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_append_array, godot_pool_vector3_array *p_self, const godot_pool_vector3_array *p_array) \
+ GDAPI_FUNC(godot_pool_vector3_array_insert, godot_error, godot_pool_vector3_array *p_self, const godot_int p_idx, const godot_vector3 *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_invert, godot_pool_vector3_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_push_back, godot_pool_vector3_array *p_self, const godot_vector3 *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_remove, godot_pool_vector3_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_resize, godot_pool_vector3_array *p_self, const godot_int p_size) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_set, godot_pool_vector3_array *p_self, const godot_int p_idx, const godot_vector3 *p_data) \
+ GDAPI_FUNC(godot_pool_vector3_array_get, godot_vector3, const godot_pool_vector3_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_pool_vector3_array_size, godot_int, const godot_pool_vector3_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_vector3_array_destroy, godot_pool_vector3_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_new, godot_pool_color_array *r_dest) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_new_copy, godot_pool_color_array *r_dest, const godot_pool_color_array *p_src) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_new_with_array, godot_pool_color_array *r_dest, const godot_array *p_a) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_append, godot_pool_color_array *p_self, const godot_color *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_append_array, godot_pool_color_array *p_self, const godot_pool_color_array *p_array) \
+ GDAPI_FUNC(godot_pool_color_array_insert, godot_error, godot_pool_color_array *p_self, const godot_int p_idx, const godot_color *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_invert, godot_pool_color_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_push_back, godot_pool_color_array *p_self, const godot_color *p_data) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_remove, godot_pool_color_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_resize, godot_pool_color_array *p_self, const godot_int p_size) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_set, godot_pool_color_array *p_self, const godot_int p_idx, const godot_color *p_data) \
+ GDAPI_FUNC(godot_pool_color_array_get, godot_color, const godot_pool_color_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_pool_color_array_size, godot_int, const godot_pool_color_array *p_self) \
+ GDAPI_FUNC_VOID(godot_pool_color_array_destroy, godot_pool_color_array *p_self) \
+ GDAPI_FUNC_VOID(godot_array_new, godot_array *r_dest) \
+ GDAPI_FUNC_VOID(godot_array_new_copy, godot_array *r_dest, const godot_array *p_src) \
+ GDAPI_FUNC_VOID(godot_array_new_pool_color_array, godot_array *r_dest, const godot_pool_color_array *p_pca) \
+ GDAPI_FUNC_VOID(godot_array_new_pool_vector3_array, godot_array *r_dest, const godot_pool_vector3_array *p_pv3a) \
+ GDAPI_FUNC_VOID(godot_array_new_pool_vector2_array, godot_array *r_dest, const godot_pool_vector2_array *p_pv2a) \
+ GDAPI_FUNC_VOID(godot_array_new_pool_string_array, godot_array *r_dest, const godot_pool_string_array *p_psa) \
+ GDAPI_FUNC_VOID(godot_array_new_pool_real_array, godot_array *r_dest, const godot_pool_real_array *p_pra) \
+ GDAPI_FUNC_VOID(godot_array_new_pool_int_array, godot_array *r_dest, const godot_pool_int_array *p_pia) \
+ GDAPI_FUNC_VOID(godot_array_new_pool_byte_array, godot_array *r_dest, const godot_pool_byte_array *p_pba) \
+ GDAPI_FUNC_VOID(godot_array_set, godot_array *p_self, const godot_int p_idx, const godot_variant *p_value) \
+ GDAPI_FUNC(godot_array_get, godot_variant, const godot_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_array_operator_index, godot_variant *, godot_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_array_append, godot_array *p_self, const godot_variant *p_value) \
+ GDAPI_FUNC_VOID(godot_array_clear, godot_array *p_self) \
+ GDAPI_FUNC(godot_array_count, godot_int, const godot_array *p_self, const godot_variant *p_value) \
+ GDAPI_FUNC(godot_array_empty, godot_bool, const godot_array *p_self) \
+ GDAPI_FUNC_VOID(godot_array_erase, godot_array *p_self, const godot_variant *p_value) \
+ GDAPI_FUNC(godot_array_front, godot_variant, const godot_array *p_self) \
+ GDAPI_FUNC(godot_array_back, godot_variant, const godot_array *p_self) \
+ GDAPI_FUNC(godot_array_find, godot_int, const godot_array *p_self, const godot_variant *p_what, const godot_int p_from) \
+ GDAPI_FUNC(godot_array_find_last, godot_int, const godot_array *p_self, const godot_variant *p_what) \
+ GDAPI_FUNC(godot_array_has, godot_bool, const godot_array *p_self, const godot_variant *p_value) \
+ GDAPI_FUNC(godot_array_hash, godot_int, const godot_array *p_self) \
+ GDAPI_FUNC_VOID(godot_array_insert, godot_array *p_self, const godot_int p_pos, const godot_variant *p_value) \
+ GDAPI_FUNC_VOID(godot_array_invert, godot_array *p_self) \
+ GDAPI_FUNC(godot_array_pop_back, godot_variant, godot_array *p_self) \
+ GDAPI_FUNC(godot_array_pop_front, godot_variant, godot_array *p_self) \
+ GDAPI_FUNC_VOID(godot_array_push_back, godot_array *p_self, const godot_variant *p_value) \
+ GDAPI_FUNC_VOID(godot_array_push_front, godot_array *p_self, const godot_variant *p_value) \
+ GDAPI_FUNC_VOID(godot_array_remove, godot_array *p_self, const godot_int p_idx) \
+ GDAPI_FUNC_VOID(godot_array_resize, godot_array *p_self, const godot_int p_size) \
+ GDAPI_FUNC(godot_array_rfind, godot_int, const godot_array *p_self, const godot_variant *p_what, const godot_int p_from) \
+ GDAPI_FUNC(godot_array_size, godot_int, const godot_array *p_self) \
+ GDAPI_FUNC_VOID(godot_array_sort, godot_array *p_self) \
+ GDAPI_FUNC_VOID(godot_array_sort_custom, godot_array *p_self, godot_object *p_obj, const godot_string *p_func) \
+ GDAPI_FUNC_VOID(godot_array_destroy, godot_array *p_self) \
+ GDAPI_FUNC_VOID(godot_dictionary_new, godot_dictionary *r_dest) \
+ GDAPI_FUNC_VOID(godot_dictionary_new_copy, godot_dictionary *r_dest, const godot_dictionary *p_src) \
+ GDAPI_FUNC_VOID(godot_dictionary_destroy, godot_dictionary *p_self) \
+ GDAPI_FUNC(godot_dictionary_size, godot_int, const godot_dictionary *p_self) \
+ GDAPI_FUNC(godot_dictionary_empty, godot_bool, const godot_dictionary *p_self) \
+ GDAPI_FUNC_VOID(godot_dictionary_clear, godot_dictionary *p_self) \
+ GDAPI_FUNC(godot_dictionary_has, godot_bool, const godot_dictionary *p_self, const godot_variant *p_key) \
+ GDAPI_FUNC(godot_dictionary_has_all, godot_bool, const godot_dictionary *p_self, const godot_array *p_keys) \
+ GDAPI_FUNC_VOID(godot_dictionary_erase, godot_dictionary *p_self, const godot_variant *p_key) \
+ GDAPI_FUNC(godot_dictionary_hash, godot_int, const godot_dictionary *p_self) \
+ GDAPI_FUNC(godot_dictionary_keys, godot_array, const godot_dictionary *p_self) \
+ GDAPI_FUNC(godot_dictionary_values, godot_array, const godot_dictionary *p_self) \
+ GDAPI_FUNC(godot_dictionary_get, godot_variant, const godot_dictionary *p_self, const godot_variant *p_key) \
+ GDAPI_FUNC_VOID(godot_dictionary_set, godot_dictionary *p_self, const godot_variant *p_key, const godot_variant *p_value) \
+ GDAPI_FUNC(godot_dictionary_operator_index, godot_variant *, godot_dictionary *p_self, const godot_variant *p_key) \
+ GDAPI_FUNC(godot_dictionary_next, godot_variant *, const godot_dictionary *p_self, const godot_variant *p_key) \
+ GDAPI_FUNC(godot_dictionary_operator_equal, godot_bool, const godot_dictionary *p_self, const godot_dictionary *p_b) \
+ GDAPI_FUNC(godot_dictionary_to_json, godot_string, const godot_dictionary *p_self) \
+ GDAPI_FUNC_VOID(godot_node_path_new, godot_node_path *r_dest, const godot_string *p_from) \
+ GDAPI_FUNC_VOID(godot_node_path_new_copy, godot_node_path *r_dest, const godot_node_path *p_src) \
+ GDAPI_FUNC_VOID(godot_node_path_destroy, godot_node_path *p_self) \
+ GDAPI_FUNC(godot_node_path_as_string, godot_string, const godot_node_path *p_self) \
+ GDAPI_FUNC(godot_node_path_is_absolute, godot_bool, const godot_node_path *p_self) \
+ GDAPI_FUNC(godot_node_path_get_name_count, godot_int, const godot_node_path *p_self) \
+ GDAPI_FUNC(godot_node_path_get_name, godot_string, const godot_node_path *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_node_path_get_subname_count, godot_int, const godot_node_path *p_self) \
+ GDAPI_FUNC(godot_node_path_get_subname, godot_string, const godot_node_path *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_node_path_get_property, godot_string, const godot_node_path *p_self) \
+ GDAPI_FUNC(godot_node_path_is_empty, godot_bool, const godot_node_path *p_self) \
+ GDAPI_FUNC(godot_node_path_operator_equal, godot_bool, const godot_node_path *p_self, const godot_node_path *p_b) \
+ GDAPI_FUNC_VOID(godot_plane_new_with_reals, godot_plane *r_dest, const godot_real p_a, const godot_real p_b, const godot_real p_c, const godot_real p_d) \
+ GDAPI_FUNC_VOID(godot_plane_new_with_vectors, godot_plane *r_dest, const godot_vector3 *p_v1, const godot_vector3 *p_v2, const godot_vector3 *p_v3) \
+ GDAPI_FUNC_VOID(godot_plane_new_with_normal, godot_plane *r_dest, const godot_vector3 *p_normal, const godot_real p_d) \
+ GDAPI_FUNC(godot_plane_as_string, godot_string, const godot_plane *p_self) \
+ GDAPI_FUNC(godot_plane_normalized, godot_plane, const godot_plane *p_self) \
+ GDAPI_FUNC(godot_plane_center, godot_vector3, const godot_plane *p_self) \
+ GDAPI_FUNC(godot_plane_get_any_point, godot_vector3, const godot_plane *p_self) \
+ GDAPI_FUNC(godot_plane_is_point_over, godot_bool, const godot_plane *p_self, const godot_vector3 *p_point) \
+ GDAPI_FUNC(godot_plane_distance_to, godot_real, const godot_plane *p_self, const godot_vector3 *p_point) \
+ GDAPI_FUNC(godot_plane_has_point, godot_bool, const godot_plane *p_self, const godot_vector3 *p_point, const godot_real p_epsilon) \
+ GDAPI_FUNC(godot_plane_project, godot_vector3, const godot_plane *p_self, const godot_vector3 *p_point) \
+ GDAPI_FUNC(godot_plane_intersect_3, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_plane *p_b, const godot_plane *p_c) \
+ GDAPI_FUNC(godot_plane_intersects_ray, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_vector3 *p_from, const godot_vector3 *p_dir) \
+ GDAPI_FUNC(godot_plane_intersects_segment, godot_bool, const godot_plane *p_self, godot_vector3 *r_dest, const godot_vector3 *p_begin, const godot_vector3 *p_end) \
+ GDAPI_FUNC(godot_plane_operator_neg, godot_plane, const godot_plane *p_self) \
+ GDAPI_FUNC(godot_plane_operator_equal, godot_bool, const godot_plane *p_self, const godot_plane *p_b) \
+ GDAPI_FUNC_VOID(godot_plane_set_normal, godot_plane *p_self, const godot_vector3 *p_normal) \
+ GDAPI_FUNC(godot_plane_get_normal, godot_vector3, const godot_plane *p_self) \
+ GDAPI_FUNC(godot_plane_get_d, godot_real, const godot_plane *p_self) \
+ GDAPI_FUNC_VOID(godot_plane_set_d, godot_plane *p_self, const godot_real p_d) \
+ GDAPI_FUNC_VOID(godot_rect2_new_with_position_and_size, godot_rect2 *r_dest, const godot_vector2 *p_pos, const godot_vector2 *p_size) \
+ GDAPI_FUNC_VOID(godot_rect2_new, godot_rect2 *r_dest, const godot_real p_x, const godot_real p_y, const godot_real p_width, const godot_real p_height) \
+ GDAPI_FUNC(godot_rect2_as_string, godot_string, const godot_rect2 *p_self) \
+ GDAPI_FUNC(godot_rect2_get_area, godot_real, const godot_rect2 *p_self) \
+ GDAPI_FUNC(godot_rect2_intersects, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \
+ GDAPI_FUNC(godot_rect2_encloses, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \
+ GDAPI_FUNC(godot_rect2_has_no_area, godot_bool, const godot_rect2 *p_self) \
+ GDAPI_FUNC(godot_rect2_clip, godot_rect2, const godot_rect2 *p_self, const godot_rect2 *p_b) \
+ GDAPI_FUNC(godot_rect2_merge, godot_rect2, const godot_rect2 *p_self, const godot_rect2 *p_b) \
+ GDAPI_FUNC(godot_rect2_has_point, godot_bool, const godot_rect2 *p_self, const godot_vector2 *p_point) \
+ GDAPI_FUNC(godot_rect2_grow, godot_rect2, const godot_rect2 *p_self, const godot_real p_by) \
+ GDAPI_FUNC(godot_rect2_expand, godot_rect2, const godot_rect2 *p_self, const godot_vector2 *p_to) \
+ GDAPI_FUNC(godot_rect2_operator_equal, godot_bool, const godot_rect2 *p_self, const godot_rect2 *p_b) \
+ GDAPI_FUNC(godot_rect2_get_position, godot_vector2, const godot_rect2 *p_self) \
+ GDAPI_FUNC(godot_rect2_get_size, godot_vector2, const godot_rect2 *p_self) \
+ GDAPI_FUNC_VOID(godot_rect2_set_position, godot_rect2 *p_self, const godot_vector2 *p_pos) \
+ GDAPI_FUNC_VOID(godot_rect2_set_size, godot_rect2 *p_self, const godot_vector2 *p_size) \
+ GDAPI_FUNC_VOID(godot_rect3_new, godot_rect3 *r_dest, const godot_vector3 *p_pos, const godot_vector3 *p_size) \
+ GDAPI_FUNC(godot_rect3_get_position, godot_vector3, const godot_rect3 *p_self) \
+ GDAPI_FUNC_VOID(godot_rect3_set_position, const godot_rect3 *p_self, const godot_vector3 *p_v) \
+ GDAPI_FUNC(godot_rect3_get_size, godot_vector3, const godot_rect3 *p_self) \
+ GDAPI_FUNC_VOID(godot_rect3_set_size, const godot_rect3 *p_self, const godot_vector3 *p_v) \
+ GDAPI_FUNC(godot_rect3_as_string, godot_string, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_get_area, godot_real, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_has_no_area, godot_bool, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_has_no_surface, godot_bool, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_intersects, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_with) \
+ GDAPI_FUNC(godot_rect3_encloses, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_with) \
+ GDAPI_FUNC(godot_rect3_merge, godot_rect3, const godot_rect3 *p_self, const godot_rect3 *p_with) \
+ GDAPI_FUNC(godot_rect3_intersection, godot_rect3, const godot_rect3 *p_self, const godot_rect3 *p_with) \
+ GDAPI_FUNC(godot_rect3_intersects_plane, godot_bool, const godot_rect3 *p_self, const godot_plane *p_plane) \
+ GDAPI_FUNC(godot_rect3_intersects_segment, godot_bool, const godot_rect3 *p_self, const godot_vector3 *p_from, const godot_vector3 *p_to) \
+ GDAPI_FUNC(godot_rect3_has_point, godot_bool, const godot_rect3 *p_self, const godot_vector3 *p_point) \
+ GDAPI_FUNC(godot_rect3_get_support, godot_vector3, const godot_rect3 *p_self, const godot_vector3 *p_dir) \
+ GDAPI_FUNC(godot_rect3_get_longest_axis, godot_vector3, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_get_longest_axis_index, godot_int, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_get_longest_axis_size, godot_real, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_get_shortest_axis, godot_vector3, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_get_shortest_axis_index, godot_int, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_get_shortest_axis_size, godot_real, const godot_rect3 *p_self) \
+ GDAPI_FUNC(godot_rect3_expand, godot_rect3, const godot_rect3 *p_self, const godot_vector3 *p_to_point) \
+ GDAPI_FUNC(godot_rect3_grow, godot_rect3, const godot_rect3 *p_self, const godot_real p_by) \
+ GDAPI_FUNC(godot_rect3_get_endpoint, godot_vector3, const godot_rect3 *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_rect3_operator_equal, godot_bool, const godot_rect3 *p_self, const godot_rect3 *p_b) \
+ GDAPI_FUNC_VOID(godot_rid_new, godot_rid *r_dest) \
+ GDAPI_FUNC(godot_rid_get_id, godot_int, const godot_rid *p_self) \
+ GDAPI_FUNC_VOID(godot_rid_new_with_resource, godot_rid *r_dest, const godot_object *p_from) \
+ GDAPI_FUNC(godot_rid_operator_equal, godot_bool, const godot_rid *p_self, const godot_rid *p_b) \
+ GDAPI_FUNC(godot_rid_operator_less, godot_bool, const godot_rid *p_self, const godot_rid *p_b) \
+ GDAPI_FUNC_VOID(godot_transform_new_with_axis_origin, godot_transform *r_dest, const godot_vector3 *p_x_axis, const godot_vector3 *p_y_axis, const godot_vector3 *p_z_axis, const godot_vector3 *p_origin) \
+ GDAPI_FUNC_VOID(godot_transform_new, godot_transform *r_dest, const godot_basis *p_basis, const godot_vector3 *p_origin) \
+ GDAPI_FUNC(godot_transform_get_basis, godot_basis, const godot_transform *p_self) \
+ GDAPI_FUNC_VOID(godot_transform_set_basis, godot_transform *p_self, godot_basis *p_v) \
+ GDAPI_FUNC(godot_transform_get_origin, godot_vector3, const godot_transform *p_self) \
+ GDAPI_FUNC_VOID(godot_transform_set_origin, godot_transform *p_self, godot_vector3 *p_v) \
+ GDAPI_FUNC(godot_transform_as_string, godot_string, const godot_transform *p_self) \
+ GDAPI_FUNC(godot_transform_inverse, godot_transform, const godot_transform *p_self) \
+ GDAPI_FUNC(godot_transform_affine_inverse, godot_transform, const godot_transform *p_self) \
+ GDAPI_FUNC(godot_transform_orthonormalized, godot_transform, const godot_transform *p_self) \
+ GDAPI_FUNC(godot_transform_rotated, godot_transform, const godot_transform *p_self, const godot_vector3 *p_axis, const godot_real p_phi) \
+ GDAPI_FUNC(godot_transform_scaled, godot_transform, const godot_transform *p_self, const godot_vector3 *p_scale) \
+ GDAPI_FUNC(godot_transform_translated, godot_transform, const godot_transform *p_self, const godot_vector3 *p_ofs) \
+ GDAPI_FUNC(godot_transform_looking_at, godot_transform, const godot_transform *p_self, const godot_vector3 *p_target, const godot_vector3 *p_up) \
+ GDAPI_FUNC(godot_transform_xform_plane, godot_plane, const godot_transform *p_self, const godot_plane *p_v) \
+ GDAPI_FUNC(godot_transform_xform_inv_plane, godot_plane, const godot_transform *p_self, const godot_plane *p_v) \
+ GDAPI_FUNC_VOID(godot_transform_new_identity, godot_transform *r_dest) \
+ GDAPI_FUNC(godot_transform_operator_equal, godot_bool, const godot_transform *p_self, const godot_transform *p_b) \
+ GDAPI_FUNC(godot_transform_operator_multiply, godot_transform, const godot_transform *p_self, const godot_transform *p_b) \
+ GDAPI_FUNC(godot_transform_xform_vector3, godot_vector3, const godot_transform *p_self, const godot_vector3 *p_v) \
+ GDAPI_FUNC(godot_transform_xform_inv_vector3, godot_vector3, const godot_transform *p_self, const godot_vector3 *p_v) \
+ GDAPI_FUNC(godot_transform_xform_rect3, godot_rect3, const godot_transform *p_self, const godot_rect3 *p_v) \
+ GDAPI_FUNC(godot_transform_xform_inv_rect3, godot_rect3, const godot_transform *p_self, const godot_rect3 *p_v) \
+ GDAPI_FUNC_VOID(godot_transform2d_new, godot_transform2d *r_dest, const godot_real p_rot, const godot_vector2 *p_pos) \
+ GDAPI_FUNC_VOID(godot_transform2d_new_axis_origin, godot_transform2d *r_dest, const godot_vector2 *p_x_axis, const godot_vector2 *p_y_axis, const godot_vector2 *p_origin) \
+ GDAPI_FUNC(godot_transform2d_as_string, godot_string, const godot_transform2d *p_self) \
+ GDAPI_FUNC(godot_transform2d_inverse, godot_transform2d, const godot_transform2d *p_self) \
+ GDAPI_FUNC(godot_transform2d_affine_inverse, godot_transform2d, const godot_transform2d *p_self) \
+ GDAPI_FUNC(godot_transform2d_get_rotation, godot_real, const godot_transform2d *p_self) \
+ GDAPI_FUNC(godot_transform2d_get_origin, godot_vector2, const godot_transform2d *p_self) \
+ GDAPI_FUNC(godot_transform2d_get_scale, godot_vector2, const godot_transform2d *p_self) \
+ GDAPI_FUNC(godot_transform2d_orthonormalized, godot_transform2d, const godot_transform2d *p_self) \
+ GDAPI_FUNC(godot_transform2d_rotated, godot_transform2d, const godot_transform2d *p_self, const godot_real p_phi) \
+ GDAPI_FUNC(godot_transform2d_scaled, godot_transform2d, const godot_transform2d *p_self, const godot_vector2 *p_scale) \
+ GDAPI_FUNC(godot_transform2d_translated, godot_transform2d, const godot_transform2d *p_self, const godot_vector2 *p_offset) \
+ GDAPI_FUNC(godot_transform2d_xform_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \
+ GDAPI_FUNC(godot_transform2d_xform_inv_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \
+ GDAPI_FUNC(godot_transform2d_basis_xform_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \
+ GDAPI_FUNC(godot_transform2d_basis_xform_inv_vector2, godot_vector2, const godot_transform2d *p_self, const godot_vector2 *p_v) \
+ GDAPI_FUNC(godot_transform2d_interpolate_with, godot_transform2d, const godot_transform2d *p_self, const godot_transform2d *p_m, const godot_real p_c) \
+ GDAPI_FUNC(godot_transform2d_operator_equal, godot_bool, const godot_transform2d *p_self, const godot_transform2d *p_b) \
+ GDAPI_FUNC(godot_transform2d_operator_multiply, godot_transform2d, const godot_transform2d *p_self, const godot_transform2d *p_b) \
+ GDAPI_FUNC_VOID(godot_transform2d_new_identity, godot_transform2d *r_dest) \
+ GDAPI_FUNC(godot_transform2d_xform_rect2, godot_rect2, const godot_transform2d *p_self, const godot_rect2 *p_v) \
+ GDAPI_FUNC(godot_transform2d_xform_inv_rect2, godot_rect2, const godot_transform2d *p_self, const godot_rect2 *p_v) \
+ GDAPI_FUNC(godot_variant_get_type, godot_variant_type, const godot_variant *p_v) \
+ GDAPI_FUNC_VOID(godot_variant_new_copy, godot_variant *r_dest, const godot_variant *p_src) \
+ GDAPI_FUNC_VOID(godot_variant_new_nil, godot_variant *r_dest) \
+ GDAPI_FUNC_VOID(godot_variant_new_bool, godot_variant *p_v, const godot_bool p_b) \
+ GDAPI_FUNC_VOID(godot_variant_new_uint, godot_variant *r_dest, const uint64_t p_i) \
+ GDAPI_FUNC_VOID(godot_variant_new_int, godot_variant *r_dest, const int64_t p_i) \
+ GDAPI_FUNC_VOID(godot_variant_new_real, godot_variant *r_dest, const double p_r) \
+ GDAPI_FUNC_VOID(godot_variant_new_string, godot_variant *r_dest, const godot_string *p_s) \
+ GDAPI_FUNC_VOID(godot_variant_new_vector2, godot_variant *r_dest, const godot_vector2 *p_v2) \
+ GDAPI_FUNC_VOID(godot_variant_new_rect2, godot_variant *r_dest, const godot_rect2 *p_rect2) \
+ GDAPI_FUNC_VOID(godot_variant_new_vector3, godot_variant *r_dest, const godot_vector3 *p_v3) \
+ GDAPI_FUNC_VOID(godot_variant_new_transform2d, godot_variant *r_dest, const godot_transform2d *p_t2d) \
+ GDAPI_FUNC_VOID(godot_variant_new_plane, godot_variant *r_dest, const godot_plane *p_plane) \
+ GDAPI_FUNC_VOID(godot_variant_new_quat, godot_variant *r_dest, const godot_quat *p_quat) \
+ GDAPI_FUNC_VOID(godot_variant_new_rect3, godot_variant *r_dest, const godot_rect3 *p_rect3) \
+ GDAPI_FUNC_VOID(godot_variant_new_basis, godot_variant *r_dest, const godot_basis *p_basis) \
+ GDAPI_FUNC_VOID(godot_variant_new_transform, godot_variant *r_dest, const godot_transform *p_trans) \
+ GDAPI_FUNC_VOID(godot_variant_new_color, godot_variant *r_dest, const godot_color *p_color) \
+ GDAPI_FUNC_VOID(godot_variant_new_node_path, godot_variant *r_dest, const godot_node_path *p_np) \
+ GDAPI_FUNC_VOID(godot_variant_new_rid, godot_variant *r_dest, const godot_rid *p_rid) \
+ GDAPI_FUNC_VOID(godot_variant_new_object, godot_variant *r_dest, const godot_object *p_obj) \
+ GDAPI_FUNC_VOID(godot_variant_new_dictionary, godot_variant *r_dest, const godot_dictionary *p_dict) \
+ GDAPI_FUNC_VOID(godot_variant_new_array, godot_variant *r_dest, const godot_array *p_arr) \
+ GDAPI_FUNC_VOID(godot_variant_new_pool_byte_array, godot_variant *r_dest, const godot_pool_byte_array *p_pba) \
+ GDAPI_FUNC_VOID(godot_variant_new_pool_int_array, godot_variant *r_dest, const godot_pool_int_array *p_pia) \
+ GDAPI_FUNC_VOID(godot_variant_new_pool_real_array, godot_variant *r_dest, const godot_pool_real_array *p_pra) \
+ GDAPI_FUNC_VOID(godot_variant_new_pool_string_array, godot_variant *r_dest, const godot_pool_string_array *p_psa) \
+ GDAPI_FUNC_VOID(godot_variant_new_pool_vector2_array, godot_variant *r_dest, const godot_pool_vector2_array *p_pv2a) \
+ GDAPI_FUNC_VOID(godot_variant_new_pool_vector3_array, godot_variant *r_dest, const godot_pool_vector3_array *p_pv3a) \
+ GDAPI_FUNC_VOID(godot_variant_new_pool_color_array, godot_variant *r_dest, const godot_pool_color_array *p_pca) \
+ GDAPI_FUNC(godot_variant_as_bool, godot_bool, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_uint, uint64_t, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_int, int64_t, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_real, double, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_string, godot_string, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_vector2, godot_vector2, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_rect2, godot_rect2, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_vector3, godot_vector3, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_transform2d, godot_transform2d, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_plane, godot_plane, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_quat, godot_quat, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_rect3, godot_rect3, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_basis, godot_basis, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_transform, godot_transform, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_color, godot_color, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_node_path, godot_node_path, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_rid, godot_rid, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_object, godot_object *, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_dictionary, godot_dictionary, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_array, godot_array, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_pool_byte_array, godot_pool_byte_array, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_pool_int_array, godot_pool_int_array, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_pool_real_array, godot_pool_real_array, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_pool_string_array, godot_pool_string_array, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_pool_vector2_array, godot_pool_vector2_array, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_pool_vector3_array, godot_pool_vector3_array, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_as_pool_color_array, godot_pool_color_array, const godot_variant *p_self) \
+ GDAPI_FUNC(godot_variant_call, godot_variant, godot_variant *p_self, const godot_string *p_method, const godot_variant **p_args, const godot_int p_argcount, godot_variant_call_error *r_error) \
+ GDAPI_FUNC(godot_variant_has_method, godot_bool, const godot_variant *p_self, const godot_string *p_method) \
+ GDAPI_FUNC(godot_variant_operator_equal, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \
+ GDAPI_FUNC(godot_variant_operator_less, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \
+ GDAPI_FUNC(godot_variant_hash_compare, godot_bool, const godot_variant *p_self, const godot_variant *p_other) \
+ GDAPI_FUNC(godot_variant_booleanize, godot_bool, const godot_variant *p_self) \
+ GDAPI_FUNC_VOID(godot_variant_destroy, godot_variant *p_self) \
+ GDAPI_FUNC_VOID(godot_string_new, godot_string *r_dest) \
+ GDAPI_FUNC_VOID(godot_string_new_copy, godot_string *r_dest, const godot_string *p_src) \
+ GDAPI_FUNC_VOID(godot_string_new_data, godot_string *r_dest, const char *p_contents, const int p_size) \
+ GDAPI_FUNC_VOID(godot_string_new_unicode_data, godot_string *r_dest, const wchar_t *p_contents, const int p_size) \
+ GDAPI_FUNC_VOID(godot_string_get_data, const godot_string *p_self, char *p_dest, int *p_size) \
+ GDAPI_FUNC(godot_string_operator_index, wchar_t *, godot_string *p_self, const godot_int p_idx) \
+ GDAPI_FUNC(godot_string_c_str, const char *, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_unicode_str, const wchar_t *, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_operator_equal, godot_bool, const godot_string *p_self, const godot_string *p_b) \
+ GDAPI_FUNC(godot_string_operator_less, godot_bool, const godot_string *p_self, const godot_string *p_b) \
+ GDAPI_FUNC(godot_string_operator_plus, godot_string, const godot_string *p_self, const godot_string *p_b) \
+ GDAPI_FUNC(godot_string_length, godot_int, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_begins_with, godot_bool, const godot_string *p_self, const godot_string *p_string) \
+ GDAPI_FUNC(godot_string_begins_with_char_array, godot_bool, const godot_string *p_self, const char *p_char_array) \
+ GDAPI_FUNC(godot_string_bigrams, godot_array, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_chr, godot_string, wchar_t p_character) \
+ GDAPI_FUNC(godot_string_ends_with, godot_bool, const godot_string *p_self, const godot_string *p_string) \
+ GDAPI_FUNC(godot_string_find, godot_int, const godot_string *p_self, godot_string p_what) \
+ GDAPI_FUNC(godot_string_find_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \
+ GDAPI_FUNC(godot_string_findmk, godot_int, const godot_string *p_self, const godot_array *p_keys) \
+ GDAPI_FUNC(godot_string_findmk_from, godot_int, const godot_string *p_self, const godot_array *p_keys, godot_int p_from) \
+ GDAPI_FUNC(godot_string_findmk_from_in_place, godot_int, const godot_string *p_self, const godot_array *p_keys, godot_int p_from, godot_int *r_key) \
+ GDAPI_FUNC(godot_string_findn, godot_int, const godot_string *p_self, godot_string p_what) \
+ GDAPI_FUNC(godot_string_findn_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \
+ GDAPI_FUNC(godot_string_find_last, godot_int, const godot_string *p_self, godot_string p_what) \
+ GDAPI_FUNC(godot_string_format, godot_string, const godot_string *p_self, const godot_variant *p_values) \
+ GDAPI_FUNC(godot_string_format_with_custom_placeholder, godot_string, const godot_string *p_self, const godot_variant *p_values, const char *p_placeholder) \
+ GDAPI_FUNC(godot_string_hex_encode_buffer, godot_string, const uint8_t *p_buffer, godot_int p_len) \
+ GDAPI_FUNC(godot_string_hex_to_int, godot_int, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_hex_to_int_without_prefix, godot_int, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_insert, godot_string, const godot_string *p_self, godot_int p_at_pos, godot_string p_string) \
+ GDAPI_FUNC(godot_string_is_numeric, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_is_subsequence_of, godot_bool, const godot_string *p_self, const godot_string *p_string) \
+ GDAPI_FUNC(godot_string_is_subsequence_ofi, godot_bool, const godot_string *p_self, const godot_string *p_string) \
+ GDAPI_FUNC(godot_string_lpad, godot_string, const godot_string *p_self, godot_int p_min_length) \
+ GDAPI_FUNC(godot_string_lpad_with_custom_character, godot_string, const godot_string *p_self, godot_int p_min_length, const godot_string *p_character) \
+ GDAPI_FUNC(godot_string_match, godot_bool, const godot_string *p_self, const godot_string *p_wildcard) \
+ GDAPI_FUNC(godot_string_matchn, godot_bool, const godot_string *p_self, const godot_string *p_wildcard) \
+ GDAPI_FUNC(godot_string_md5, godot_string, const uint8_t *p_md5) \
+ GDAPI_FUNC(godot_string_num, godot_string, double p_num) \
+ GDAPI_FUNC(godot_string_num_int64, godot_string, int64_t p_num, godot_int p_base) \
+ GDAPI_FUNC(godot_string_num_int64_capitalized, godot_string, int64_t p_num, godot_int p_base, godot_bool p_capitalize_hex) \
+ GDAPI_FUNC(godot_string_num_real, godot_string, double p_num) \
+ GDAPI_FUNC(godot_string_num_scientific, godot_string, double p_num) \
+ GDAPI_FUNC(godot_string_num_with_decimals, godot_string, double p_num, godot_int p_decimals) \
+ GDAPI_FUNC(godot_string_pad_decimals, godot_string, const godot_string *p_self, godot_int p_digits) \
+ GDAPI_FUNC(godot_string_pad_zeros, godot_string, const godot_string *p_self, godot_int p_digits) \
+ GDAPI_FUNC(godot_string_replace_first, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \
+ GDAPI_FUNC(godot_string_replace, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \
+ GDAPI_FUNC(godot_string_replacen, godot_string, const godot_string *p_self, godot_string p_key, godot_string p_with) \
+ GDAPI_FUNC(godot_string_rfind, godot_int, const godot_string *p_self, godot_string p_what) \
+ GDAPI_FUNC(godot_string_rfindn, godot_int, const godot_string *p_self, godot_string p_what) \
+ GDAPI_FUNC(godot_string_rfind_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \
+ GDAPI_FUNC(godot_string_rfindn_from, godot_int, const godot_string *p_self, godot_string p_what, godot_int p_from) \
+ GDAPI_FUNC(godot_string_rpad, godot_string, const godot_string *p_self, godot_int p_min_length) \
+ GDAPI_FUNC(godot_string_rpad_with_custom_character, godot_string, const godot_string *p_self, godot_int p_min_length, const godot_string *p_character) \
+ GDAPI_FUNC(godot_string_similarity, godot_real, const godot_string *p_self, const godot_string *p_string) \
+ GDAPI_FUNC(godot_string_sprintf, godot_string, const godot_string *p_self, const godot_array *p_values, godot_bool *p_error) \
+ GDAPI_FUNC(godot_string_substr, godot_string, const godot_string *p_self, godot_int p_from, godot_int p_chars) \
+ GDAPI_FUNC(godot_string_to_double, double, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_to_float, godot_real, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_to_int, godot_int, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_camelcase_to_underscore, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_camelcase_to_underscore_lowercased, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_capitalize, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_char_to_double, double, const char *p_what) \
+ GDAPI_FUNC(godot_string_char_to_int, godot_int, const char *p_what) \
+ GDAPI_FUNC(godot_string_wchar_to_int, int64_t, const wchar_t *p_str) \
+ GDAPI_FUNC(godot_string_char_to_int_with_len, godot_int, const char *p_what, godot_int p_len) \
+ GDAPI_FUNC(godot_string_char_to_int64_with_len, int64_t, const wchar_t *p_str, int p_len) \
+ GDAPI_FUNC(godot_string_hex_to_int64, int64_t, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_hex_to_int64_with_prefix, int64_t, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_to_int64, int64_t, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_unicode_char_to_double, double, const wchar_t *p_str, const wchar_t **r_end) \
+ GDAPI_FUNC(godot_string_get_slice_count, godot_int, const godot_string *p_self, godot_string p_splitter) \
+ GDAPI_FUNC(godot_string_get_slice, godot_string, const godot_string *p_self, godot_string p_splitter, godot_int p_slice) \
+ GDAPI_FUNC(godot_string_get_slicec, godot_string, const godot_string *p_self, wchar_t p_splitter, godot_int p_slice) \
+ GDAPI_FUNC(godot_string_split, godot_array, const godot_string *p_self, const godot_string *p_splitter) \
+ GDAPI_FUNC(godot_string_split_allow_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \
+ GDAPI_FUNC(godot_string_split_floats, godot_array, const godot_string *p_self, const godot_string *p_splitter) \
+ GDAPI_FUNC(godot_string_split_floats_allows_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \
+ GDAPI_FUNC(godot_string_split_floats_mk, godot_array, const godot_string *p_self, const godot_array *p_splitters) \
+ GDAPI_FUNC(godot_string_split_floats_mk_allows_empty, godot_array, const godot_string *p_self, const godot_array *p_splitters) \
+ GDAPI_FUNC(godot_string_split_ints, godot_array, const godot_string *p_self, const godot_string *p_splitter) \
+ GDAPI_FUNC(godot_string_split_ints_allows_empty, godot_array, const godot_string *p_self, const godot_string *p_splitter) \
+ GDAPI_FUNC(godot_string_split_ints_mk, godot_array, const godot_string *p_self, const godot_array *p_splitters) \
+ GDAPI_FUNC(godot_string_split_ints_mk_allows_empty, godot_array, const godot_string *p_self, const godot_array *p_splitters) \
+ GDAPI_FUNC(godot_string_split_spaces, godot_array, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_char_lowercase, wchar_t, wchar_t p_char) \
+ GDAPI_FUNC(godot_string_char_uppercase, wchar_t, wchar_t p_char) \
+ GDAPI_FUNC(godot_string_to_lower, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_to_upper, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_get_basename, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_get_extension, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_left, godot_string, const godot_string *p_self, godot_int p_pos) \
+ GDAPI_FUNC(godot_string_ord_at, wchar_t, const godot_string *p_self, godot_int p_idx) \
+ GDAPI_FUNC(godot_string_plus_file, godot_string, const godot_string *p_self, const godot_string *p_file) \
+ GDAPI_FUNC(godot_string_right, godot_string, const godot_string *p_self, godot_int p_pos) \
+ GDAPI_FUNC(godot_string_strip_edges, godot_string, const godot_string *p_self, godot_bool p_left, godot_bool p_right) \
+ GDAPI_FUNC(godot_string_strip_escapes, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC_VOID(godot_string_erase, godot_string *p_self, godot_int p_pos, godot_int p_chars) \
+ GDAPI_FUNC_VOID(godot_string_ascii, godot_string *p_self, char *result) \
+ GDAPI_FUNC_VOID(godot_string_ascii_extended, godot_string *p_self, char *result) \
+ GDAPI_FUNC_VOID(godot_string_utf8, godot_string *p_self, char *result) \
+ GDAPI_FUNC(godot_string_parse_utf8, godot_bool, godot_string *p_self, const char *p_utf8) \
+ GDAPI_FUNC(godot_string_parse_utf8_with_len, godot_bool, godot_string *p_self, const char *p_utf8, godot_int p_len) \
+ GDAPI_FUNC(godot_string_chars_to_utf8, godot_string, const char *p_utf8) \
+ GDAPI_FUNC(godot_string_chars_to_utf8_with_len, godot_string, const char *p_utf8, godot_int p_len) \
+ GDAPI_FUNC(godot_string_hash, uint32_t, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_hash64, uint64_t, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_hash_chars, uint32_t, const char *p_cstr) \
+ GDAPI_FUNC(godot_string_hash_chars_with_len, uint32_t, const char *p_cstr, godot_int p_len) \
+ GDAPI_FUNC(godot_string_hash_utf8_chars, uint32_t, const wchar_t *p_str) \
+ GDAPI_FUNC(godot_string_hash_utf8_chars_with_len, uint32_t, const wchar_t *p_str, godot_int p_len) \
+ GDAPI_FUNC(godot_string_md5_buffer, godot_pool_byte_array, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_md5_text, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_sha256_buffer, godot_pool_byte_array, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_sha256_text, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_empty, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_get_base_dir, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_get_file, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_humanize_size, godot_string, size_t p_size) \
+ GDAPI_FUNC(godot_string_is_abs_path, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_is_rel_path, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_is_resource_file, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_path_to, godot_string, const godot_string *p_self, const godot_string *p_path) \
+ GDAPI_FUNC(godot_string_path_to_file, godot_string, const godot_string *p_self, const godot_string *p_path) \
+ GDAPI_FUNC(godot_string_simplify_path, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_c_escape, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_c_escape_multiline, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_c_unescape, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_http_escape, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_http_unescape, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_json_escape, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_word_wrap, godot_string, const godot_string *p_self, godot_int p_chars_per_line) \
+ GDAPI_FUNC(godot_string_xml_escape, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_xml_escape_with_quotes, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_xml_unescape, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_percent_decode, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_percent_encode, godot_string, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_is_valid_float, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_is_valid_hex_number, godot_bool, const godot_string *p_self, godot_bool p_with_prefix) \
+ GDAPI_FUNC(godot_string_is_valid_html_color, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_is_valid_identifier, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_is_valid_integer, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC(godot_string_is_valid_ip_address, godot_bool, const godot_string *p_self) \
+ GDAPI_FUNC_VOID(godot_string_destroy, godot_string *p_self) \
+ GDAPI_FUNC_VOID(godot_object_destroy, godot_object *p_o) \
+ GDAPI_FUNC(godot_global_get_singleton, godot_object *, char *p_name) \
+ GDAPI_FUNC(godot_get_stack_bottom, void *) \
+ GDAPI_FUNC(godot_method_bind_get_method, godot_method_bind *, const char *p_classname, const char *p_methodname) \
+ GDAPI_FUNC_VOID(godot_method_bind_ptrcall, godot_method_bind *p_method_bind, godot_object *p_instance, const void **p_args, void *p_ret) \
+ GDAPI_FUNC(godot_method_bind_call, godot_variant, godot_method_bind *p_method_bind, godot_object *p_instance, const godot_variant **p_args, const int p_arg_count, godot_variant_call_error *p_call_error) \
+ GDAPI_FUNC(godot_get_class_constructor, godot_class_constructor, const char *p_classname) \
+ GDAPI_FUNC(godot_get_global_constants, godot_dictionary) \
+ GDAPI_FUNC(godot_alloc, void *, int p_bytes) \
+ GDAPI_FUNC(godot_realloc, void *, void *p_ptr, int p_bytes) \
+ GDAPI_FUNC_VOID(godot_free, void *p_ptr) \
+ GDAPI_FUNC_VOID(godot_print_error, const char *p_description, const char *p_function, const char *p_file, int p_line) \
+ GDAPI_FUNC_VOID(godot_print_warning, const char *p_description, const char *p_function, const char *p_file, int p_line) \
+ GDAPI_FUNC_VOID(godot_print, const godot_string *p_message) \
+ GDAPI_FUNC_VOID(godot_nativescript_register_class, void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) \
+ GDAPI_FUNC_VOID(godot_nativescript_register_tool_class, void *p_gdnative_handle, const char *p_name, const char *p_base, godot_instance_create_func p_create_func, godot_instance_destroy_func p_destroy_func) \
+ GDAPI_FUNC_VOID(godot_nativescript_register_method, void *p_gdnative_handle, const char *p_name, const char *p_function_name, godot_method_attributes p_attr, godot_instance_method p_method) \
+ GDAPI_FUNC_VOID(godot_nativescript_register_property, void *p_gdnative_handle, const char *p_name, const char *p_path, godot_property_attributes *p_attr, godot_property_set_func p_set_func, godot_property_get_func p_get_func) \
+ GDAPI_FUNC_VOID(godot_nativescript_register_signal, void *p_gdnative_handle, const char *p_name, const godot_signal *p_signal) \
+ GDAPI_FUNC(godot_nativescript_get_userdata, void *, godot_object *p_instance)
+
+#define GDAPI_FUNC(name, ret_type, ...) \
+ ret_type (*name)(__VA_ARGS__);
+#define GDAPI_FUNC_VOID(name, ...) \
+ void (*name)(__VA_ARGS__);
+
+typedef struct godot_gdnative_api_struct {
+ GODOT_GDNATIVE_API_FUNCTIONS
+} godot_gdnative_api_struct;
+
+#undef GDAPI_FUNC
+#undef GDAPI_FUNC_VOID
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // GODOT_GDNATIVE_API_STRUCT_H
diff --git a/modules/gdnative/include/nativescript/godot_nativescript.h b/modules/gdnative/include/nativescript/godot_nativescript.h
index 96f213ead7..5095b7a83e 100644
--- a/modules/gdnative/include/nativescript/godot_nativescript.h
+++ b/modules/gdnative/include/nativescript/godot_nativescript.h
@@ -51,8 +51,8 @@ extern "C" {
#elif defined(__APPLE__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
-#define GDCALLINGCONV
-#define GDAPI
+#define GDCALLINGCONV __attribute__((visibility("default")))
+#define GDAPI GDCALLINGCONV
#elif TARGET_OS_MAC
#define GDCALLINGCONV __attribute__((sysv_abi))
#define GDAPI GDCALLINGCONV
diff --git a/modules/gdnative/nativescript/SCsub b/modules/gdnative/nativescript/SCsub
index e980e40e8e..178afec64a 100644
--- a/modules/gdnative/nativescript/SCsub
+++ b/modules/gdnative/nativescript/SCsub
@@ -7,4 +7,7 @@ mod_env.add_source_files(env.modules_sources, "*.cpp")
mod_env.Append(CPPPATH='#modules/gdnative')
mod_env.Append(CPPFLAGS=['-DGDAPI_BUILT_IN'])
+if "platform" in env and env["platform"] in ["x11", "iphone"]:
+ env.Append(LINKFLAGS=["-rdynamic"])
+
Export('mod_env')
diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp
index dc0da5021d..997c342045 100644
--- a/modules/gdnative/register_types.cpp
+++ b/modules/gdnative/register_types.cpp
@@ -99,7 +99,6 @@ Set<String> get_gdnative_singletons(EditorFileSystemDirectory *p_dir) {
void actual_discoverer_handler() {
EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->get_filesystem();
-
Set<String> file_paths = get_gdnative_singletons(dir);
Array files;
@@ -118,11 +117,10 @@ GDNativeSingletonDiscover *discoverer = NULL;
static void editor_init_callback() {
- GDNativeLibraryEditor *library_editor = memnew( GDNativeLibraryEditor );
+ GDNativeLibraryEditor *library_editor = memnew(GDNativeLibraryEditor);
library_editor->set_name(TTR("GDNative"));
ProjectSettingsEditor::get_singleton()->get_tabs()->add_child(library_editor);
-
discoverer = memnew(GDNativeSingletonDiscover);
EditorFileSystem::get_singleton()->connect("filesystem_changed", discoverer, "get_class");
}
diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp
index 4803781c67..7036a708e5 100644
--- a/modules/gdscript/gd_compiler.cpp
+++ b/modules/gdscript/gd_compiler.cpp
@@ -131,7 +131,7 @@ int GDCompiler::_parse_assign_right_expression(CodeGen &codegen, const GDParser:
switch (p_expression->op) {
case GDParser::OperatorNode::OP_ASSIGN_ADD: var_op = Variant::OP_ADD; break;
- case GDParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBSTRACT; break;
+ case GDParser::OperatorNode::OP_ASSIGN_SUB: var_op = Variant::OP_SUBTRACT; break;
case GDParser::OperatorNode::OP_ASSIGN_MUL: var_op = Variant::OP_MULTIPLY; break;
case GDParser::OperatorNode::OP_ASSIGN_DIV: var_op = Variant::OP_DIVIDE; break;
case GDParser::OperatorNode::OP_ASSIGN_MOD: var_op = Variant::OP_MODULE; break;
@@ -759,7 +759,7 @@ int GDCompiler::_parse_expression(CodeGen &codegen, const GDParser::Node *p_expr
if (!_create_binary_operator(codegen, on, Variant::OP_ADD, p_stack_level)) return -1;
} break;
case GDParser::OperatorNode::OP_SUB: {
- if (!_create_binary_operator(codegen, on, Variant::OP_SUBSTRACT, p_stack_level)) return -1;
+ if (!_create_binary_operator(codegen, on, Variant::OP_SUBTRACT, p_stack_level)) return -1;
} break;
case GDParser::OperatorNode::OP_MUL: {
if (!_create_binary_operator(codegen, on, Variant::OP_MULTIPLY, p_stack_level)) return -1;
diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp
index bc51b84047..b0408917a4 100644
--- a/modules/gdscript/gd_editor.cpp
+++ b/modules/gdscript/gd_editor.cpp
@@ -908,7 +908,7 @@ static bool _guess_expression_type(GDCompletionContext &context, const GDParser:
Variant::Operator vop = Variant::OP_MAX;
switch (op->op) {
case GDParser::OperatorNode::OP_ADD: vop = Variant::OP_ADD; break;
- case GDParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBSTRACT; break;
+ case GDParser::OperatorNode::OP_SUB: vop = Variant::OP_SUBTRACT; break;
case GDParser::OperatorNode::OP_MUL: vop = Variant::OP_MULTIPLY; break;
case GDParser::OperatorNode::OP_DIV: vop = Variant::OP_DIVIDE; break;
case GDParser::OperatorNode::OP_MOD: vop = Variant::OP_MODULE; break;
@@ -1952,7 +1952,6 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
//make sure identifier exists...
const GDParser::IdentifierNode *id = static_cast<const GDParser::IdentifierNode *>(op->arguments[1]);
-
if (op->arguments[0]->type == GDParser::Node::TYPE_SELF) {
//self, look up
@@ -2021,7 +2020,7 @@ static void _find_call_arguments(GDCompletionContext &context, const GDParser::N
base = script->get_native();
} else if (nc.is_valid()) {
- if (context.function && !context.function->_static) {
+ if (!(context.function && context.function->_static)) {
GDCompletionIdentifier ci;
ci.type = Variant::OBJECT;
diff --git a/modules/gdscript/gd_function.cpp b/modules/gdscript/gd_function.cpp
index ddee7b2521..9df2823c35 100644
--- a/modules/gdscript/gd_function.cpp
+++ b/modules/gdscript/gd_function.cpp
@@ -41,11 +41,12 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
switch ((p_address & ADDR_TYPE_MASK) >> ADDR_BITS) {
case ADDR_TYPE_SELF: {
-
- if (!p_instance) {
+#ifdef DEBUG_ENABLED
+ if (unlikely(!p_instance)) {
r_error = "Cannot access self without instance.";
return NULL;
}
+#endif
return &self;
} break;
case ADDR_TYPE_CLASS: {
@@ -53,18 +54,22 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
return &p_script->_static_ref;
} break;
case ADDR_TYPE_MEMBER: {
- //member indexing is O(1)
- if (!p_instance) {
+#ifdef DEBUG_ENABLED
+ if (unlikely(!p_instance)) {
r_error = "Cannot access member without instance.";
return NULL;
}
+#endif
+ //member indexing is O(1)
return &p_instance->members[address];
} break;
case ADDR_TYPE_CLASS_CONSTANT: {
//todo change to index!
GDScript *o = p_script;
+#ifdef DEBUG_ENABLED
ERR_FAIL_INDEX_V(address, _global_names_count, NULL);
+#endif
const StringName *sn = &_global_names_ptr[address];
while (o) {
@@ -84,18 +89,22 @@ Variant *GDFunction::_get_variant(int p_address, GDInstance *p_instance, GDScrip
ERR_FAIL_V(NULL);
} break;
case ADDR_TYPE_LOCAL_CONSTANT: {
+#ifdef DEBUG_ENABLED
ERR_FAIL_INDEX_V(address, _constant_count, NULL);
+#endif
return &_constants_ptr[address];
} break;
case ADDR_TYPE_STACK:
case ADDR_TYPE_STACK_VARIABLE: {
+#ifdef DEBUG_ENABLED
ERR_FAIL_INDEX_V(address, _stack_size, NULL);
+#endif
return &p_stack[address];
} break;
case ADDR_TYPE_GLOBAL: {
-
+#ifdef DEBUG_ENABLED
ERR_FAIL_INDEX_V(address, GDScriptLanguage::get_singleton()->get_global_array_size(), NULL);
-
+#endif
return &GDScriptLanguage::get_singleton()->get_global_array()[address];
} break;
case ADDR_TYPE_NIL: {
@@ -161,8 +170,71 @@ static String _get_var_type(const Variant *p_type) {
return basestr;
}
+#if defined(__GNUC__) && !defined(__clang__)
+#define OPCODES_TABLE \
+ static const void *switch_table_ops[] = { \
+ &&OPCODE_OPERATOR, \
+ &&OPCODE_EXTENDS_TEST, \
+ &&OPCODE_SET, \
+ &&OPCODE_GET, \
+ &&OPCODE_SET_NAMED, \
+ &&OPCODE_GET_NAMED, \
+ &&OPCODE_SET_MEMBER, \
+ &&OPCODE_GET_MEMBER, \
+ &&OPCODE_ASSIGN, \
+ &&OPCODE_ASSIGN_TRUE, \
+ &&OPCODE_ASSIGN_FALSE, \
+ &&OPCODE_CONSTRUCT, \
+ &&OPCODE_CONSTRUCT_ARRAY, \
+ &&OPCODE_CONSTRUCT_DICTIONARY, \
+ &&OPCODE_CALL, \
+ &&OPCODE_CALL_RETURN, \
+ &&OPCODE_CALL_BUILT_IN, \
+ &&OPCODE_CALL_SELF, \
+ &&OPCODE_CALL_SELF_BASE, \
+ &&OPCODE_YIELD, \
+ &&OPCODE_YIELD_SIGNAL, \
+ &&OPCODE_YIELD_RESUME, \
+ &&OPCODE_JUMP, \
+ &&OPCODE_JUMP_IF, \
+ &&OPCODE_JUMP_IF_NOT, \
+ &&OPCODE_JUMP_TO_DEF_ARGUMENT, \
+ &&OPCODE_RETURN, \
+ &&OPCODE_ITERATE_BEGIN, \
+ &&OPCODE_ITERATE, \
+ &&OPCODE_ASSERT, \
+ &&OPCODE_BREAKPOINT, \
+ &&OPCODE_LINE, \
+ &&OPCODE_END \
+ };
+
+#define OPCODE(m_op) \
+ m_op:
+#define OPCODE_WHILE(m_test)
+#define OPCODES_END \
+ OPSEXIT:
+#define OPCODES_OUT \
+ OPSOUT:
+#define DISPATCH_OPCODE goto *switch_table_ops[_code_ptr[ip]]
+#define OPCODE_SWITCH(m_test) DISPATCH_OPCODE;
+#define OPCODE_BREAK goto OPSEXIT
+#define OPCODE_OUT goto OPSOUT
+#else
+#define OPCODES_TABLE
+#define OPCODE(m_op) case m_op:
+#define OPCODE_WHILE(m_test) while (m_test)
+#define OPCODES_END
+#define OPCODES_OUT
+#define DISPATCH_OPCODE continue
+#define OPCODE_SWITCH(m_test) switch (m_test)
+#define OPCODE_BREAK break
+#define OPCODE_OUT break
+#endif
+
Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_argcount, Variant::CallError &r_err, CallState *p_state) {
+ OPCODES_TABLE;
+
if (!_code_ptr) {
return Variant();
@@ -271,16 +343,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (ScriptDebugger::get_singleton())
GDScriptLanguage::get_singleton()->enter_function(p_instance, this, stack, &ip, &line);
+#define GD_ERR_BREAK(m_cond) \
+ { \
+ if (unlikely(m_cond)) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, "Condition ' " _STR(m_cond) " ' is true. Breaking..:"); \
+ OPCODE_BREAK; \
+ } else \
+ _err_error_exists = false; \
+ }
+
#define CHECK_SPACE(m_space) \
- ERR_BREAK((ip + m_space) > _code_size)
+ GD_ERR_BREAK((ip + m_space) > _code_size)
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \
m_v = _get_variant(_code_ptr[ip + m_code_ofs], p_instance, _class, self, stack, err_text); \
- if (!m_v) \
- break;
+ if (unlikely(!m_v)) \
+ OPCODE_BREAK;
#else
+#define GD_ERR_BREAK(m_cond)
#define CHECK_SPACE(m_space)
#define GET_VARIANT_PTR(m_v, m_code_ofs) \
Variant *m_v; \
@@ -302,32 +384,36 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#endif
bool exit_ok = false;
- while (ip < _code_size) {
-
+#ifdef DEBUG_ENABLED
+ OPCODE_WHILE(ip < _code_size) {
int last_opcode = _code_ptr[ip];
- switch (_code_ptr[ip]) {
+#else
+ OPCODE_WHILE(true) {
+#endif
- case OPCODE_OPERATOR: {
+ OPCODE_SWITCH(_code_ptr[ip]) {
+
+ OPCODE(OPCODE_OPERATOR) {
CHECK_SPACE(5);
bool valid;
Variant::Operator op = (Variant::Operator)_code_ptr[ip + 1];
- ERR_BREAK(op >= Variant::OP_MAX);
+ GD_ERR_BREAK(op >= Variant::OP_MAX);
GET_VARIANT_PTR(a, 2);
GET_VARIANT_PTR(b, 3);
GET_VARIANT_PTR(dst, 4);
#ifdef DEBUG_ENABLED
+
Variant ret;
Variant::evaluate(op, *a, *b, ret, valid);
#else
Variant::evaluate(op, *a, *b, *dst, valid);
#endif
-
- if (!valid) {
#ifdef DEBUG_ENABLED
+ if (!valid) {
if (ret.get_type() == Variant::STRING) {
//return a string when invalid with the error
@@ -336,17 +422,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
} else {
err_text = "Invalid operands '" + Variant::get_type_name(a->get_type()) + "' and '" + Variant::get_type_name(b->get_type()) + "' in operator '" + Variant::get_operator_name(op) + "'.";
}
-#endif
- break;
+ OPCODE_BREAK;
}
-#ifdef DEBUG_ENABLED
*dst = ret;
#endif
-
ip += 5;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_EXTENDS_TEST: {
+ OPCODE(OPCODE_EXTENDS_TEST) {
CHECK_SPACE(4);
@@ -355,19 +438,17 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
GET_VARIANT_PTR(dst, 3);
#ifdef DEBUG_ENABLED
-
if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) {
err_text = "Left operand of 'is' is not an instance of anything.";
- break;
+ OPCODE_BREAK;
}
if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) {
err_text = "Right operand of 'is' is not a class.";
- break;
+ OPCODE_BREAK;
}
#endif
-
Object *obj_A = *a;
Object *obj_B = *b;
@@ -399,20 +480,21 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
GDNativeClass *nc = Object::cast_to<GDNativeClass>(obj_B);
+#ifdef DEBUG_ENABLED
if (!nc) {
err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "').";
- break;
+ OPCODE_BREAK;
}
-
+#endif
extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name());
}
*dst = extends_ok;
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_SET: {
+ OPCODE(OPCODE_SET) {
CHECK_SPACE(3);
@@ -423,6 +505,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
bool valid;
dst->set(*index, *value, &valid);
+#ifdef DEBUG_ENABLED
if (!valid) {
String v = index->operator String();
if (v != "") {
@@ -431,13 +514,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
v = "of type '" + _get_var_type(index) + "'";
}
err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "').";
- break;
+ OPCODE_BREAK;
}
-
+#endif
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_GET: {
+ OPCODE(OPCODE_GET) {
CHECK_SPACE(3);
@@ -453,6 +536,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = src->get(*index, &valid);
#endif
+#ifdef DEBUG_ENABLED
if (!valid) {
String v = index->operator String();
if (v != "") {
@@ -461,15 +545,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
v = "of type '" + _get_var_type(index) + "'";
}
err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "').";
- break;
+ OPCODE_BREAK;
}
-#ifdef DEBUG_ENABLED
*dst = ret;
#endif
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_SET_NAMED: {
+ OPCODE(OPCODE_SET_NAMED) {
CHECK_SPACE(3);
@@ -478,22 +561,23 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
int indexname = _code_ptr[ip + 2];
- ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
+ GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
bool valid;
dst->set_named(*index, *value, &valid);
+#ifdef DEBUG_ENABLED
if (!valid) {
String err_type;
err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "').";
- break;
+ OPCODE_BREAK;
}
-
+#endif
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_GET_NAMED: {
+ OPCODE(OPCODE_GET_NAMED) {
CHECK_SPACE(4);
@@ -502,7 +586,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
int indexname = _code_ptr[ip + 2];
- ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
+ GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
bool valid;
@@ -513,26 +597,25 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#else
*dst = src->get_named(*index, &valid);
#endif
-
+#ifdef DEBUG_ENABLED
if (!valid) {
if (src->has_method(*index)) {
err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "'). Did you mean '." + index->operator String() + "()' ?";
} else {
err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "').";
}
- break;
+ OPCODE_BREAK;
}
-#ifdef DEBUG_ENABLED
*dst = ret;
#endif
ip += 4;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_SET_MEMBER: {
+ OPCODE(OPCODE_SET_MEMBER) {
CHECK_SPACE(3);
int indexname = _code_ptr[ip + 1];
- ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
+ GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
GET_VARIANT_PTR(src, 2);
@@ -541,20 +624,20 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (!ok) {
err_text = "Internal error setting property: " + String(*index);
- break;
+ OPCODE_BREAK;
} else if (!valid) {
err_text = "Error setting property '" + String(*index) + "' with value of type " + Variant::get_type_name(src->get_type()) + ".";
- break;
+ OPCODE_BREAK;
}
#endif
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_GET_MEMBER: {
+ OPCODE(OPCODE_GET_MEMBER) {
CHECK_SPACE(3);
int indexname = _code_ptr[ip + 1];
- ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
+ GD_ERR_BREAK(indexname < 0 || indexname >= _global_names_count);
const StringName *index = &_global_names_ptr[indexname];
GET_VARIANT_PTR(dst, 2);
bool ok = ClassDB::get_property(p_instance->owner, *index, *dst);
@@ -562,13 +645,13 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
#ifdef DEBUG_ENABLED
if (!ok) {
err_text = "Internal error getting property: " + String(*index);
- break;
+ OPCODE_BREAK;
}
#endif
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ASSIGN: {
+ OPCODE(OPCODE_ASSIGN) {
CHECK_SPACE(3);
GET_VARIANT_PTR(dst, 1);
@@ -577,9 +660,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = *src;
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ASSIGN_TRUE: {
+ OPCODE(OPCODE_ASSIGN_TRUE) {
CHECK_SPACE(2);
GET_VARIANT_PTR(dst, 1);
@@ -587,9 +670,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = true;
ip += 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ASSIGN_FALSE: {
+ OPCODE(OPCODE_ASSIGN_FALSE) {
CHECK_SPACE(2);
GET_VARIANT_PTR(dst, 1);
@@ -597,9 +680,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = false;
ip += 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CONSTRUCT: {
+ OPCODE(OPCODE_CONSTRUCT) {
CHECK_SPACE(2);
Variant::Type t = Variant::Type(_code_ptr[ip + 1]);
@@ -615,17 +698,19 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
Variant::CallError err;
*dst = Variant::construct(t, (const Variant **)argptrs, argc, err);
+#ifdef DEBUG_ENABLED
if (err.error != Variant::CallError::CALL_OK) {
err_text = _get_call_error(err, "'" + Variant::get_type_name(t) + "' constructor", (const Variant **)argptrs);
- break;
+ OPCODE_BREAK;
}
+#endif
ip += 4 + argc;
//construct a basic type
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CONSTRUCT_ARRAY: {
+ OPCODE(OPCODE_CONSTRUCT_ARRAY) {
CHECK_SPACE(1);
int argc = _code_ptr[ip + 1];
@@ -643,9 +728,9 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = array;
ip += 3 + argc;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CONSTRUCT_DICTIONARY: {
+ OPCODE(OPCODE_CONSTRUCT_DICTIONARY) {
CHECK_SPACE(1);
int argc = _code_ptr[ip + 1];
@@ -665,10 +750,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
*dst = dict;
ip += 3 + argc * 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CALL_RETURN:
- case OPCODE_CALL: {
+ OPCODE(OPCODE_CALL_RETURN)
+ OPCODE(OPCODE_CALL) {
CHECK_SPACE(4);
bool call_ret = _code_ptr[ip] == OPCODE_CALL_RETURN;
@@ -677,10 +762,10 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
GET_VARIANT_PTR(base, 2);
int nameg = _code_ptr[ip + 3];
- ERR_BREAK(nameg < 0 || nameg >= _global_names_count);
+ GD_ERR_BREAK(nameg < 0 || nameg >= _global_names_count);
const StringName *methodname = &_global_names_ptr[nameg];
- ERR_BREAK(argc < 0);
+ GD_ERR_BREAK(argc < 0);
ip += 4;
CHECK_SPACE(argc + 1);
Variant **argptrs = call_args;
@@ -711,7 +796,6 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (GDScriptLanguage::get_singleton()->profiling) {
function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
}
-#endif
if (err.error != Variant::CallError::CALL_OK) {
@@ -731,29 +815,30 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
if (base->is_ref()) {
err_text = "Attempted to free a reference.";
- break;
+ OPCODE_BREAK;
} else if (base->get_type() == Variant::OBJECT) {
err_text = "Attempted to free a locked object (calling or emitting).";
- break;
+ OPCODE_BREAK;
}
}
}
err_text = _get_call_error(err, "function '" + methodstr + "' in base '" + basestr + "'", (const Variant **)argptrs);
- break;
+ OPCODE_BREAK;
}
+#endif
//_call_func(NULL,base,*methodname,ip,argc,p_instance,stack);
ip += argc + 1;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CALL_BUILT_IN: {
+ OPCODE(OPCODE_CALL_BUILT_IN) {
CHECK_SPACE(4);
GDFunctions::Function func = GDFunctions::Function(_code_ptr[ip + 1]);
int argc = _code_ptr[ip + 2];
- ERR_BREAK(argc < 0);
+ GD_ERR_BREAK(argc < 0);
ip += 3;
CHECK_SPACE(argc + 1);
@@ -770,6 +855,7 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
GDFunctions::call(func, (const Variant **)argptrs, argc, *dst, err);
+#ifdef DEBUG_ENABLED
if (err.error != Variant::CallError::CALL_OK) {
String methodstr = GDFunctions::get_func_name(func);
@@ -779,25 +865,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
} else {
err_text = _get_call_error(err, "built-in function '" + methodstr + "'", (const Variant **)argptrs);
}
- break;
+ OPCODE_BREAK;
}
+#endif
ip += argc + 1;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_CALL_SELF: {
+ OPCODE(OPCODE_CALL_SELF) {
- break;
+ OPCODE_BREAK;
}
- case OPCODE_CALL_SELF_BASE: {
+ OPCODE(OPCODE_CALL_SELF_BASE) {
CHECK_SPACE(2);
int self_fun = _code_ptr[ip + 1];
-#ifdef DEBUG_ENABLED
+#ifdef DEBUG_ENABLED
if (self_fun < 0 || self_fun >= _global_names_count) {
err_text = "compiler bug, function name not found";
- break;
+ OPCODE_BREAK;
}
#endif
const StringName *methodname = &_global_names_ptr[self_fun];
@@ -857,14 +944,14 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
String methodstr = *methodname;
err_text = _get_call_error(err, "function '" + methodstr + "'", (const Variant **)argptrs);
- break;
+ OPCODE_BREAK;
}
ip += 4 + argc;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_YIELD:
- case OPCODE_YIELD_SIGNAL: {
+ OPCODE(OPCODE_YIELD)
+ OPCODE(OPCODE_YIELD_SIGNAL) {
int ipofs = 1;
if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) {
@@ -898,133 +985,125 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
retvalue = gdfs;
if (_code_ptr[ip] == OPCODE_YIELD_SIGNAL) {
+ //do the oneshot connect
GET_VARIANT_PTR(argobj, 1);
GET_VARIANT_PTR(argname, 2);
- //do the oneshot connect
+#ifdef DEBUG_ENABLED
if (argobj->get_type() != Variant::OBJECT) {
err_text = "First argument of yield() not of type object.";
- break;
+ OPCODE_BREAK;
}
if (argname->get_type() != Variant::STRING) {
err_text = "Second argument of yield() not a string (for signal name).";
- break;
+ OPCODE_BREAK;
}
+#endif
Object *obj = argobj->operator Object *();
String signal = argname->operator String();
#ifdef DEBUG_ENABLED
if (!obj) {
err_text = "First argument of yield() is null.";
- break;
+ OPCODE_BREAK;
}
if (ScriptDebugger::get_singleton()) {
if (!ObjectDB::instance_validate(obj)) {
err_text = "First argument of yield() is a previously freed instance.";
- break;
+ OPCODE_BREAK;
}
}
if (signal.length() == 0) {
err_text = "Second argument of yield() is an empty string (for signal name).";
- break;
+ OPCODE_BREAK;
}
#endif
Error err = obj->connect(signal, gdfs.ptr(), "_signal_callback", varray(gdfs), Object::CONNECT_ONESHOT);
+#ifdef DEBUG_ENABLED
if (err != OK) {
err_text = "Error connecting to signal: " + signal + " during yield().";
- break;
+ OPCODE_BREAK;
}
+#endif
}
exit_ok = true;
- break;
+ OPCODE_BREAK;
}
- case OPCODE_YIELD_RESUME: {
+ OPCODE(OPCODE_YIELD_RESUME) {
CHECK_SPACE(2);
+#ifdef DEBUG_ENABLED
if (!p_state) {
err_text = ("Invalid Resume (bug?)");
- break;
+ OPCODE_BREAK;
}
+#endif
GET_VARIANT_PTR(result, 1);
*result = p_state->result;
ip += 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_JUMP: {
+ OPCODE(OPCODE_JUMP) {
CHECK_SPACE(2);
int to = _code_ptr[ip + 1];
- ERR_BREAK(to < 0 || to > _code_size);
+ GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_JUMP_IF: {
+ OPCODE(OPCODE_JUMP_IF) {
CHECK_SPACE(3);
GET_VARIANT_PTR(test, 1);
- bool valid;
- bool result = test->booleanize(valid);
-#ifdef DEBUG_ENABLED
- if (!valid) {
+ bool result = test->booleanize();
- err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
- break;
- }
-#endif
if (result) {
int to = _code_ptr[ip + 2];
- ERR_BREAK(to < 0 || to > _code_size);
+ GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- continue;
+ DISPATCH_OPCODE;
}
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_JUMP_IF_NOT: {
+ OPCODE(OPCODE_JUMP_IF_NOT) {
CHECK_SPACE(3);
GET_VARIANT_PTR(test, 1);
- bool valid;
- bool result = test->booleanize(valid);
-#ifdef DEBUG_ENABLED
- if (!valid) {
+ bool result = test->booleanize();
- err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
- break;
- }
-#endif
if (!result) {
int to = _code_ptr[ip + 2];
- ERR_BREAK(to < 0 || to > _code_size);
+ GD_ERR_BREAK(to < 0 || to > _code_size);
ip = to;
- continue;
+ DISPATCH_OPCODE;
}
ip += 3;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_JUMP_TO_DEF_ARGUMENT: {
+ OPCODE(OPCODE_JUMP_TO_DEF_ARGUMENT) {
CHECK_SPACE(2);
ip = _default_arg_ptr[defarg];
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_RETURN: {
+ OPCODE(OPCODE_RETURN) {
CHECK_SPACE(2);
GET_VARIANT_PTR(r, 1);
retvalue = *r;
exit_ok = true;
- break;
+ OPCODE_BREAK;
}
- case OPCODE_ITERATE_BEGIN: {
+ OPCODE(OPCODE_ITERATE_BEGIN) {
CHECK_SPACE(8); //space for this a regular iterate
@@ -1033,27 +1112,30 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
bool valid;
if (!container->iter_init(*counter, valid)) {
+#ifdef DEBUG_ENABLED
if (!valid) {
err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "'.";
- break;
+ OPCODE_BREAK;
}
+#endif
int jumpto = _code_ptr[ip + 3];
- ERR_BREAK(jumpto < 0 || jumpto > _code_size);
+ GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
ip = jumpto;
- continue;
+ DISPATCH_OPCODE;
}
GET_VARIANT_PTR(iterator, 4);
*iterator = container->iter_get(*counter, valid);
+#ifdef DEBUG_ENABLED
if (!valid) {
err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "'.";
- break;
+ OPCODE_BREAK;
}
-
+#endif
ip += 5; //skip regular iterate which is always next
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ITERATE: {
+ OPCODE(OPCODE_ITERATE) {
CHECK_SPACE(4);
@@ -1062,61 +1144,56 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
bool valid;
if (!container->iter_next(*counter, valid)) {
+#ifdef DEBUG_ENABLED
if (!valid) {
err_text = "Unable to iterate on object of type " + Variant::get_type_name(container->get_type()) + "' (type changed since first iteration?).";
- break;
+ OPCODE_BREAK;
}
+#endif
int jumpto = _code_ptr[ip + 3];
- ERR_BREAK(jumpto < 0 || jumpto > _code_size);
+ GD_ERR_BREAK(jumpto < 0 || jumpto > _code_size);
ip = jumpto;
- continue;
+ DISPATCH_OPCODE;
}
GET_VARIANT_PTR(iterator, 4);
*iterator = container->iter_get(*counter, valid);
+#ifdef DEBUG_ENABLED
if (!valid) {
err_text = "Unable to obtain iterator object of type " + Variant::get_type_name(container->get_type()) + "' (but was obtained on first iteration?).";
- break;
+ OPCODE_BREAK;
}
-
+#endif
ip += 5; //loop again
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_ASSERT: {
+ OPCODE(OPCODE_ASSERT) {
CHECK_SPACE(2);
GET_VARIANT_PTR(test, 1);
#ifdef DEBUG_ENABLED
- bool valid;
- bool result = test->booleanize(valid);
-
- if (!valid) {
-
- err_text = "cannot evaluate conditional expression of type: " + Variant::get_type_name(test->get_type());
- break;
- }
+ bool result = test->booleanize();
if (!result) {
err_text = "Assertion failed.";
- break;
+ OPCODE_BREAK;
}
#endif
-
ip += 2;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_BREAKPOINT: {
+ OPCODE(OPCODE_BREAKPOINT) {
#ifdef DEBUG_ENABLED
if (ScriptDebugger::get_singleton()) {
GDScriptLanguage::get_singleton()->debug_break("Breakpoint Statement", true);
}
#endif
ip += 1;
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_LINE: {
+ OPCODE(OPCODE_LINE) {
CHECK_SPACE(2);
line = _code_ptr[ip + 1];
@@ -1143,22 +1220,26 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
ScriptDebugger::get_singleton()->line_poll();
}
- continue;
+ DISPATCH_OPCODE;
}
- case OPCODE_END: {
+ OPCODE(OPCODE_END) {
exit_ok = true;
- break;
+ OPCODE_BREAK;
}
+#if 0
default: {
err_text = "Illegal opcode " + itos(_code_ptr[ip]) + " at address " + itos(ip);
- break;
+ OPCODE_BREAK;
}
+#endif
}
+ OPCODES_END
+#ifdef DEBUG_ENABLED
if (exit_ok)
- break;
+ OPCODE_OUT;
//error
// function, file, line, error, explanation
String err_file;
@@ -1182,9 +1263,11 @@ Variant GDFunction::call(GDInstance *p_instance, const Variant **p_args, int p_a
_err_print_error(err_func.utf8().get_data(), err_file.utf8().get_data(), err_line, err_text.utf8().get_data(), ERR_HANDLER_SCRIPT);
}
- break;
+#endif
+ OPCODE_OUT;
}
+ OPCODES_OUT
#ifdef DEBUG_ENABLED
if (GDScriptLanguage::get_singleton()->profiling) {
uint64_t time_taken = OS::get_singleton()->get_ticks_usec() - function_start_time;
diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp
index 72c3f9612a..36aaa1f807 100644
--- a/modules/gdscript/gd_parser.cpp
+++ b/modules/gdscript/gd_parser.cpp
@@ -1699,7 +1699,7 @@ GDParser::Node *GDParser::_reduce_expression(Node *p_node, bool p_to_const) {
_REDUCE_BINARY(Variant::OP_ADD);
} break;
case OperatorNode::OP_SUB: {
- _REDUCE_BINARY(Variant::OP_SUBSTRACT);
+ _REDUCE_BINARY(Variant::OP_SUBTRACT);
} break;
case OperatorNode::OP_MUL: {
_REDUCE_BINARY(Variant::OP_MULTIPLY);
diff --git a/modules/mobile_vr/SCsub b/modules/mobile_vr/SCsub
new file mode 100644
index 0000000000..b4e2edcca1
--- /dev/null
+++ b/modules/mobile_vr/SCsub
@@ -0,0 +1,13 @@
+#!/usr/bin/env python
+
+import os
+import methods
+
+Import('env')
+Import('env_modules')
+
+env_mobile_vr = env_modules.Clone()
+
+env_mobile_vr.add_source_files(env.modules_sources, '*.cpp')
+
+SConscript("shaders/SCsub")
diff --git a/modules/mobile_vr/config.py b/modules/mobile_vr/config.py
new file mode 100644
index 0000000000..d0156b1b77
--- /dev/null
+++ b/modules/mobile_vr/config.py
@@ -0,0 +1,6 @@
+def can_build(platform):
+ # should probably change this to only be true on iOS and Android
+ return True
+
+def configure(env):
+ pass \ No newline at end of file
diff --git a/modules/mobile_vr/mobile_interface.cpp b/modules/mobile_vr/mobile_interface.cpp
new file mode 100644
index 0000000000..f5c9bccaba
--- /dev/null
+++ b/modules/mobile_vr/mobile_interface.cpp
@@ -0,0 +1,511 @@
+/*************************************************************************/
+/* mobile_interface.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "mobile_interface.h"
+#include "core/os/input.h"
+#include "core/os/os.h"
+#include "servers/visual/visual_server_global.h"
+
+StringName MobileVRInterface::get_name() const {
+ return "Native mobile";
+};
+
+Vector3 MobileVRInterface::scale_magneto(const Vector3 &p_magnetometer) {
+ // Our magnetometer doesn't give us nice clean data.
+ // Well it may on Mac OS X because we're getting a calibrated value in the current implementation but Android we're getting raw data.
+ // This is a fairly simple adjustment we can do to correct for the magnetometer data being elliptical
+
+ Vector3 mag_raw = p_magnetometer;
+ Vector3 mag_scaled = p_magnetometer;
+
+ // update our variables every x frames
+ if (mag_count > 20) {
+ mag_current_min = mag_next_min;
+ mag_current_max = mag_next_max;
+ mag_count = 0;
+ } else {
+ mag_count++;
+ };
+
+ // adjust our min and max
+ if (mag_raw.x > mag_next_max.x) mag_next_max.x = mag_raw.x;
+ if (mag_raw.y > mag_next_max.y) mag_next_max.y = mag_raw.y;
+ if (mag_raw.z > mag_next_max.z) mag_next_max.z = mag_raw.z;
+
+ if (mag_raw.x < mag_next_min.x) mag_next_min.x = mag_raw.x;
+ if (mag_raw.y < mag_next_min.y) mag_next_min.y = mag_raw.y;
+ if (mag_raw.z < mag_next_min.z) mag_next_min.z = mag_raw.z;
+
+ // scale our x, y and z
+ if (!(mag_current_max.x - mag_current_min.x)) {
+ mag_raw.x -= (mag_current_min.x + mag_current_max.x) / 2.0;
+ mag_scaled.x = (mag_raw.x - mag_current_min.x) / ((mag_current_max.x - mag_current_min.x) * 2.0 - 1.0);
+ };
+
+ if (!(mag_current_max.y - mag_current_min.y)) {
+ mag_raw.y -= (mag_current_min.y + mag_current_max.y) / 2.0;
+ mag_scaled.y = (mag_raw.y - mag_current_min.y) / ((mag_current_max.y - mag_current_min.y) * 2.0 - 1.0);
+ };
+
+ if (!(mag_current_max.z - mag_current_min.z)) {
+ mag_raw.z -= (mag_current_min.z + mag_current_max.z) / 2.0;
+ mag_scaled.z = (mag_raw.z - mag_current_min.z) / ((mag_current_max.z - mag_current_min.z) * 2.0 - 1.0);
+ };
+
+ return mag_scaled;
+};
+
+Basis MobileVRInterface::combine_acc_mag(const Vector3 &p_grav, const Vector3 &p_magneto) {
+ // yup, stock standard cross product solution...
+ Vector3 up = -p_grav.normalized();
+
+ Vector3 magneto_east = up.cross(p_magneto.normalized()); // or is this west?, but should be horizon aligned now
+ magneto_east.normalize();
+
+ Vector3 magneto = up.cross(magneto_east); // and now we have a horizon aligned north
+ magneto.normalize();
+
+ // We use our gravity and magnetometer vectors to construct our matrix
+ Basis acc_mag_m3;
+ acc_mag_m3.elements[0] = -magneto_east;
+ acc_mag_m3.elements[1] = up;
+ acc_mag_m3.elements[2] = magneto;
+
+ return acc_mag_m3;
+};
+
+void MobileVRInterface::set_position_from_sensors() {
+ _THREAD_SAFE_METHOD_
+
+ // this is a helper function that attempts to adjust our transform using our 9dof sensors
+ // 9dof is a misleading marketing term coming from 3 accelerometer axis + 3 gyro axis + 3 magnetometer axis = 9 axis
+ // but in reality this only offers 3 dof (yaw, pitch, roll) orientation
+
+ uint64_t ticks = OS::get_singleton()->get_ticks_usec();
+ uint64_t ticks_elapsed = ticks - last_ticks;
+ float delta_time = (double)ticks_elapsed / 1000000.0;
+
+ // few things we need
+ Input *input = Input::get_singleton();
+ Vector3 down(0.0, -1.0, 0.0); // Down is Y negative
+ Vector3 north(0.0, 0.0, 1.0); // North is Z positive
+
+ // make copies of our inputs
+ Vector3 acc = input->get_accelerometer();
+ Vector3 gyro = input->get_gyroscope();
+ Vector3 grav = input->get_gravity();
+ Vector3 magneto = scale_magneto(input->get_magnetometer()); // this may be overkill on iOS because we're already getting a calibrated magnetometer reading
+
+ if (sensor_first) {
+ sensor_first = false;
+ } else {
+ acc = scrub(acc, last_accerometer_data, 2, 0.2);
+ magneto = scrub(magneto, last_magnetometer_data, 3, 0.3);
+ };
+
+ last_accerometer_data = acc;
+ last_magnetometer_data = magneto;
+
+ if (grav.length() < 0.1) {
+ // not ideal but use our accelerometer, this will contain shakey shakey user behaviour
+ // maybe look into some math but I'm guessing that if this isn't available, its because we lack the gyro sensor to actually work out
+ // what a stable gravity vector is
+ grav = acc;
+ if (grav.length() > 0.1) {
+ has_gyro = true;
+ };
+ } else {
+ has_gyro = true;
+ };
+
+ bool has_magneto = magneto.length() > 0.1;
+ bool has_grav = grav.length() > 0.1;
+
+#ifdef ANDROID_ENABLED
+ ///@TODO needs testing, i don't have a gyro, potentially can be removed depending on what comes out of issue #8101
+ // On Android x and z axis seem inverted
+ gyro.x = -gyro.x;
+ gyro.z = -gyro.z;
+ grav.x = -grav.x;
+ grav.z = -grav.z;
+ magneto.x = -magneto.x;
+ magneto.z = -magneto.z;
+#endif
+
+ if (has_gyro) {
+ // start with applying our gyro (do NOT smooth our gyro!)
+ Basis rotate;
+ rotate.rotate(orientation.get_axis(0), gyro.x * delta_time);
+ rotate.rotate(orientation.get_axis(1), gyro.y * delta_time);
+ rotate.rotate(orientation.get_axis(2), gyro.z * delta_time);
+ orientation = rotate * orientation;
+ };
+
+ ///@TODO improve this, the magnetometer is very fidgity sometimes flipping the axis for no apparent reason (probably a bug on my part)
+ // if you have a gyro + accelerometer that combo tends to be better then combining all three but without a gyro you need the magnetometer..
+ if (has_magneto && has_grav && !has_gyro) {
+ // convert to quaternions, easier to smooth those out
+ Quat transform_quat(orientation);
+ Quat acc_mag_quat(combine_acc_mag(grav, magneto));
+ transform_quat = transform_quat.slerp(acc_mag_quat, 0.1);
+ orientation = Basis(transform_quat);
+ } else if (has_grav) {
+ // use gravity vector to make sure down is down...
+ // transform gravity into our world space
+ grav.normalize();
+ Vector3 grav_adj = orientation.xform(grav);
+ float dot = grav_adj.dot(down);
+ if ((dot > -1.0) && (dot < 1.0)) {
+ // axis around which we have this rotation
+ Vector3 axis = grav_adj.cross(down);
+ axis.normalize();
+
+ Basis drift_compensation(axis, acos(dot) * delta_time * 10);
+ orientation = drift_compensation * orientation;
+ };
+ };
+
+ // JIC
+ orientation.orthonormalize();
+
+ last_ticks = ticks;
+};
+
+void MobileVRInterface::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_iod", "iod"), &MobileVRInterface::set_iod);
+ ClassDB::bind_method(D_METHOD("get_iod"), &MobileVRInterface::get_iod);
+
+ ClassDB::bind_method(D_METHOD("set_display_width", "display_width"), &MobileVRInterface::set_display_width);
+ ClassDB::bind_method(D_METHOD("get_display_width"), &MobileVRInterface::get_display_width);
+
+ ClassDB::bind_method(D_METHOD("set_display_to_lens", "display_to_lens"), &MobileVRInterface::set_display_to_lens);
+ ClassDB::bind_method(D_METHOD("get_display_to_lens"), &MobileVRInterface::get_display_to_lens);
+
+ ClassDB::bind_method(D_METHOD("set_oversample", "oversample"), &MobileVRInterface::set_oversample);
+ ClassDB::bind_method(D_METHOD("get_oversample"), &MobileVRInterface::get_oversample);
+
+ ClassDB::bind_method(D_METHOD("set_k1", "k"), &MobileVRInterface::set_k1);
+ ClassDB::bind_method(D_METHOD("get_k1"), &MobileVRInterface::get_k1);
+
+ ClassDB::bind_method(D_METHOD("set_k2", "k"), &MobileVRInterface::set_k2);
+ ClassDB::bind_method(D_METHOD("get_k2"), &MobileVRInterface::get_k2);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "iod", PROPERTY_HINT_RANGE, "4.0,10.0,0.1"), "set_iod", "get_iod");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "display_width", PROPERTY_HINT_RANGE, "5.0,25.0,0.1"), "set_display_width", "get_display_width");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "display_to_lens", PROPERTY_HINT_RANGE, "5.0,25.0,0.1"), "set_display_to_lens", "get_display_to_lens");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "oversample", PROPERTY_HINT_RANGE, "1.0,2.0,0.1"), "set_oversample", "get_oversample");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "k1", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k1", "get_k1");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "k2", PROPERTY_HINT_RANGE, "0.1,10.0,0.0001"), "set_k2", "get_k2");
+}
+
+void MobileVRInterface::set_iod(const real_t p_iod) {
+ intraocular_dist = p_iod;
+};
+
+real_t MobileVRInterface::get_iod() const {
+ return intraocular_dist;
+};
+
+void MobileVRInterface::set_display_width(const real_t p_display_width) {
+ display_width = p_display_width;
+};
+
+real_t MobileVRInterface::get_display_width() const {
+ return display_width;
+};
+
+void MobileVRInterface::set_display_to_lens(const real_t p_display_to_lens) {
+ display_to_lens = p_display_to_lens;
+};
+
+real_t MobileVRInterface::get_display_to_lens() const {
+ return display_to_lens;
+};
+
+void MobileVRInterface::set_oversample(const real_t p_oversample) {
+ oversample = p_oversample;
+};
+
+real_t MobileVRInterface::get_oversample() const {
+ return oversample;
+};
+
+void MobileVRInterface::set_k1(const real_t p_k1) {
+ k1 = p_k1;
+};
+
+real_t MobileVRInterface::get_k1() const {
+ return k1;
+};
+
+void MobileVRInterface::set_k2(const real_t p_k2) {
+ k2 = p_k2;
+};
+
+real_t MobileVRInterface::get_k2() const {
+ return k2;
+};
+
+bool MobileVRInterface::is_installed() {
+ // we don't have any middle ware here, if we have our interface, we can use it
+ return true;
+};
+
+bool MobileVRInterface::hmd_is_present() {
+ // our device is our HMD
+ return true;
+};
+
+bool MobileVRInterface::supports_hmd() {
+ // our device is our HMD
+ return true;
+};
+
+bool MobileVRInterface::is_stereo() {
+ // needs stereo...
+ return true;
+};
+
+bool MobileVRInterface::is_initialized() {
+ return (initialized);
+};
+
+bool MobileVRInterface::initialize() {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, false);
+
+ if (!initialized) {
+ // reset our sensor data and orientation
+ mag_count = 0;
+ has_gyro = false;
+ sensor_first = true;
+ mag_next_min = Vector3(10000, 10000, 10000);
+ mag_next_max = Vector3(-10000, -10000, -10000);
+ mag_current_min = Vector3(0, 0, 0);
+ mag_current_max = Vector3(0, 0, 0);
+
+ // reset our orientation
+ orientation = Basis();
+
+ // make this our primary interface
+ arvr_server->set_primary_interface(this);
+
+ last_ticks = OS::get_singleton()->get_ticks_usec();
+ ;
+ initialized = true;
+ };
+
+ return true;
+};
+
+void MobileVRInterface::uninitialize() {
+ if (initialized) {
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ if (arvr_server != NULL) {
+ // no longer our primary interface
+ arvr_server->clear_primary_interface_if(this);
+ }
+
+ initialized = false;
+ };
+};
+
+Size2 MobileVRInterface::get_recommended_render_targetsize() {
+ _THREAD_SAFE_METHOD_
+
+ // we use half our window size
+ Size2 target_size = OS::get_singleton()->get_window_size();
+ target_size.x *= 0.5 * oversample;
+ target_size.y *= oversample;
+
+ return target_size;
+};
+
+Transform MobileVRInterface::get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform) {
+ _THREAD_SAFE_METHOD_
+
+ Transform transform_for_eye;
+
+ ARVRServer *arvr_server = ARVRServer::get_singleton();
+ ERR_FAIL_NULL_V(arvr_server, transform_for_eye);
+
+ if (initialized) {
+ float world_scale = arvr_server->get_world_scale();
+
+ // we don't need to check for the existance of our HMD, doesn't effect our values...
+ // note * 0.01 to convert cm to m and * 0.5 as we're moving half in each direction...
+ if (p_eye == ARVRInterface::EYE_LEFT) {
+ transform_for_eye.origin.x = -(intraocular_dist * 0.01 * 0.5 * world_scale);
+ } else if (p_eye == ARVRInterface::EYE_RIGHT) {
+ transform_for_eye.origin.x = intraocular_dist * 0.01 * 0.5 * world_scale;
+ } else {
+ // for mono we don't reposition, we want our center position.
+ };
+
+ // just scale our origin point of our transform
+ Transform hmd_transform;
+ hmd_transform.basis = orientation;
+ hmd_transform.origin = Vector3(0.0, eye_height * world_scale, 0.0);
+
+ transform_for_eye = p_cam_transform * (arvr_server->get_reference_frame()) * hmd_transform * transform_for_eye;
+ } else {
+ // huh? well just return what we got....
+ transform_for_eye = p_cam_transform;
+ };
+
+ return transform_for_eye;
+};
+
+CameraMatrix MobileVRInterface::get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far) {
+ _THREAD_SAFE_METHOD_
+
+ CameraMatrix eye;
+
+ if (p_eye == ARVRInterface::EYE_MONO) {
+ ///@TODO for now hardcode some of this, what is really needed here is that this needs to be in sync with the real cameras properties
+ // which probably means implementing a specific class for iOS and Android. For now this is purely here as an example.
+ // Note also that if you use a normal viewport with AR/VR turned off you can still use the tracker output of this interface
+ // to position a stock standard Godot camera and have control over this.
+ // This will make more sense when we implement ARkit on iOS (probably a separate interface).
+ eye.set_perspective(60.0, p_aspect, p_z_near, p_z_far, false);
+ } else {
+ eye.set_for_hmd(p_eye == ARVRInterface::EYE_LEFT ? 1 : 2, p_aspect, intraocular_dist, display_width, display_to_lens, oversample, p_z_near, p_z_far);
+ };
+
+ return eye;
+};
+
+void MobileVRInterface::commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect) {
+ _THREAD_SAFE_METHOD_
+
+ // We must have a valid render target
+ ERR_FAIL_COND(!p_render_target.is_valid());
+
+ // Because we are rendering to our device we must use our main viewport!
+ ERR_FAIL_COND(p_screen_rect == Rect2());
+
+ float offset_x = 0.0;
+ float aspect_ratio = 0.5 * p_screen_rect.size.x / p_screen_rect.size.y;
+ Vector2 eye_center;
+
+ if (p_eye == ARVRInterface::EYE_LEFT) {
+ offset_x = -1.0;
+ eye_center.x = ((-intraocular_dist / 2.0) + (display_width / 4.0)) / (display_width / 2.0);
+ } else if (p_eye == ARVRInterface::EYE_RIGHT) {
+ eye_center.x = ((intraocular_dist / 2.0) - (display_width / 4.0)) / (display_width / 2.0);
+ }
+
+ // unset our render target so we are outputting to our main screen by making RasterizerStorageGLES3::system_fbo our current FBO
+ VSG::rasterizer->set_current_render_target(RID());
+
+ // now output to screen
+ // VSG::rasterizer->blit_render_target_to_screen(p_render_target, screen_rect, 0);
+
+ // get our render target
+ RID eye_texture = VSG::storage->render_target_get_texture(p_render_target);
+ uint32_t texid = VS::get_singleton()->texture_get_texid(eye_texture);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, texid);
+
+ lens_shader.bind();
+ lens_shader.set_uniform(LensDistortedShaderGLES3::OFFSET_X, offset_x);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::K1, k1);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::K2, k2);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::EYE_CENTER, eye_center);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::UPSCALE, oversample);
+ lens_shader.set_uniform(LensDistortedShaderGLES3::ASPECT_RATIO, aspect_ratio);
+
+ glBindVertexArray(half_screen_array);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glBindVertexArray(0);
+};
+
+void MobileVRInterface::process() {
+ _THREAD_SAFE_METHOD_
+
+ if (initialized) {
+ set_position_from_sensors();
+ };
+};
+
+MobileVRInterface::MobileVRInterface() {
+ initialized = false;
+
+ // Just set some defaults for these. At some point we need to look at adding a lookup table for common device + headset combos and/or support reading cardboard QR codes
+ eye_height = 1.85;
+ intraocular_dist = 6.0;
+ display_width = 13.0;
+ display_to_lens = 4.0;
+ oversample = 1.5;
+ k1 = 0.22;
+ k2 = 0.23;
+ last_ticks = 0;
+
+ // create our shader stuff
+ lens_shader.init();
+
+ {
+ glGenBuffers(1, &half_screen_quad);
+ glBindBuffer(GL_ARRAY_BUFFER, half_screen_quad);
+ {
+ const float qv[16] = {
+ 0, -1,
+ -1, -1,
+ 0, 1,
+ -1, 1,
+ 1, 1,
+ 1, 1,
+ 1, -1,
+ 1, -1,
+ };
+
+ glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, qv, GL_STATIC_DRAW);
+ }
+
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+
+ glGenVertexArrays(1, &half_screen_array);
+ glBindVertexArray(half_screen_array);
+ glBindBuffer(GL_ARRAY_BUFFER, half_screen_quad);
+ glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0);
+ glEnableVertexAttribArray(0);
+ glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, ((uint8_t *)NULL) + 8);
+ glEnableVertexAttribArray(4);
+ glBindVertexArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind
+ }
+};
+
+MobileVRInterface::~MobileVRInterface() {
+ // and make sure we cleanup if we haven't already
+ if (is_initialized()) {
+ uninitialize();
+ };
+};
diff --git a/modules/mobile_vr/mobile_interface.h b/modules/mobile_vr/mobile_interface.h
new file mode 100644
index 0000000000..dfe3cd200e
--- /dev/null
+++ b/modules/mobile_vr/mobile_interface.h
@@ -0,0 +1,155 @@
+/*************************************************************************/
+/* mobile_interface.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* http://www.godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 MOBILE_VR_INTERFACE_H
+#define MOBILE_VR_INTERFACE_H
+
+#include "servers/arvr/arvr_interface.h"
+#include "servers/arvr/arvr_positional_tracker.h"
+
+#include "shaders/lens_distorted.glsl.gen.h"
+
+/**
+ @author Bastiaan Olij <mux213@gmail.com>
+
+ The mobile interface is a native VR interface that can be used on Android and iOS phones.
+ It contains a basic implementation supporting 3DOF tracking if a gyroscope and accelerometer are
+ present and sets up the proper projection matrices based on the values provided.
+
+ We're planning to eventually do separate interfaces towards mobile SDKs that have far more capabilities and
+ do not rely on the user providing most of these settings (though enhancing this with auto detection features
+ based on the device we're running on would be cool). I'm mostly adding this as an example or base plate for
+ more advanced interfaces.
+*/
+
+class MobileVRInterface : public ARVRInterface {
+ GDCLASS(MobileVRInterface, ARVRInterface);
+
+private:
+ bool initialized;
+ Basis orientation;
+ float eye_height;
+ uint64_t last_ticks;
+
+ LensDistortedShaderGLES3 lens_shader;
+ GLuint half_screen_quad;
+ GLuint half_screen_array;
+
+ real_t intraocular_dist;
+ real_t display_width;
+ real_t display_to_lens;
+ real_t oversample;
+
+ //@TODO not yet used, these are needed in our distortion shader...
+ real_t k1;
+ real_t k2;
+
+ /*
+ logic for processing our sensor data, this was originally in our positional tracker logic but I think
+ that doesn't make sense in hindsight. It only makes marginally more sense to park it here for now,
+ this probably deserves an object of its own
+ */
+ Vector3 scale_magneto(const Vector3 &p_magnetometer);
+ Basis combine_acc_mag(const Vector3 &p_grav, const Vector3 &p_magneto);
+
+ int mag_count;
+ bool has_gyro;
+ bool sensor_first;
+ Vector3 last_accerometer_data;
+ Vector3 last_magnetometer_data;
+ Vector3 mag_current_min;
+ Vector3 mag_current_max;
+ Vector3 mag_next_min;
+ Vector3 mag_next_max;
+
+ ///@TODO a few support functions for trackers, most are math related and should likely be moved elsewhere
+ float floor_decimals(float p_value, float p_decimals) {
+ float power_of_10 = pow(10.0, p_decimals);
+ return floor(p_value * power_of_10) / power_of_10;
+ };
+
+ Vector3 floor_decimals(const Vector3 &p_vector, float p_decimals) {
+ return Vector3(floor_decimals(p_vector.x, p_decimals), floor_decimals(p_vector.y, p_decimals), floor_decimals(p_vector.z, p_decimals));
+ };
+
+ Vector3 low_pass(const Vector3 &p_vector, const Vector3 &p_last_vector, float p_factor) {
+ return p_vector + (p_factor * (p_last_vector - p_vector));
+ };
+
+ Vector3 scrub(const Vector3 &p_vector, const Vector3 &p_last_vector, float p_decimals, float p_factor) {
+ return low_pass(floor_decimals(p_vector, p_decimals), p_last_vector, p_factor);
+ };
+
+ void set_position_from_sensors();
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_iod(const real_t p_iod);
+ real_t get_iod() const;
+
+ void set_display_width(const real_t p_display_width);
+ real_t get_display_width() const;
+
+ void set_display_to_lens(const real_t p_display_to_lens);
+ real_t get_display_to_lens() const;
+
+ void set_oversample(const real_t p_oversample);
+ real_t get_oversample() const;
+
+ void set_k1(const real_t p_k1);
+ real_t get_k1() const;
+
+ void set_k2(const real_t p_k2);
+ real_t get_k2() const;
+
+ virtual StringName get_name() const;
+
+ virtual bool is_installed();
+ virtual bool hmd_is_present();
+ virtual bool supports_hmd();
+
+ virtual bool is_initialized();
+ virtual bool initialize();
+ virtual void uninitialize();
+
+ virtual Size2 get_recommended_render_targetsize();
+ virtual bool is_stereo();
+ virtual Transform get_transform_for_eye(ARVRInterface::Eyes p_eye, const Transform &p_cam_transform);
+ virtual CameraMatrix get_projection_for_eye(ARVRInterface::Eyes p_eye, real_t p_aspect, real_t p_z_near, real_t p_z_far);
+ virtual void commit_for_eye(ARVRInterface::Eyes p_eye, RID p_render_target, const Rect2 &p_screen_rect);
+
+ virtual void process();
+
+ MobileVRInterface();
+ ~MobileVRInterface();
+};
+
+#endif // MOBILE_VR_INTERFACE_H
diff --git a/modules/mobile_vr/register_types.cpp b/modules/mobile_vr/register_types.cpp
new file mode 100644
index 0000000000..f742ecbf00
--- /dev/null
+++ b/modules/mobile_vr/register_types.cpp
@@ -0,0 +1,43 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+#include "mobile_interface.h"
+
+void register_mobile_vr_types() {
+ ClassDB::register_class<MobileVRInterface>();
+
+ Ref<MobileVRInterface> mobile_vr;
+ mobile_vr.instance();
+ ARVRServer::get_singleton()->add_interface(mobile_vr);
+}
+
+void unregister_mobile_vr_types() {
+}
diff --git a/modules/mobile_vr/register_types.h b/modules/mobile_vr/register_types.h
new file mode 100644
index 0000000000..a492fff397
--- /dev/null
+++ b/modules/mobile_vr/register_types.h
@@ -0,0 +1,31 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+void register_mobile_vr_types();
+void unregister_mobile_vr_types();
diff --git a/modules/mobile_vr/shaders/SCsub b/modules/mobile_vr/shaders/SCsub
new file mode 100644
index 0000000000..cf53c9ebe0
--- /dev/null
+++ b/modules/mobile_vr/shaders/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import('env')
+
+if 'GLES3_GLSL' in env['BUILDERS']:
+ env.GLES3_GLSL('lens_distorted.glsl');
+
diff --git a/modules/mobile_vr/shaders/lens_distorted.glsl b/modules/mobile_vr/shaders/lens_distorted.glsl
new file mode 100644
index 0000000000..5a2975d737
--- /dev/null
+++ b/modules/mobile_vr/shaders/lens_distorted.glsl
@@ -0,0 +1,59 @@
+[vertex]
+
+layout(location=0) in highp vec4 vertex_attrib;
+layout(location=4) in vec2 uv_in;
+
+uniform float offset_x;
+
+out vec2 uv_interp;
+
+void main() {
+
+ uv_interp = uv_in;
+ gl_Position = vec4(vertex_attrib.x + offset_x, vertex_attrib.y, 0.0, 1.0);
+}
+
+[fragment]
+
+uniform sampler2D source; //texunit:0
+
+uniform vec2 eye_center;
+uniform float k1;
+uniform float k2;
+uniform float upscale;
+uniform float aspect_ratio;
+
+in vec2 uv_interp;
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+ vec2 coords = uv_interp;
+ vec2 offset = coords - eye_center;
+
+ // take aspect ratio into account
+ offset.y /= aspect_ratio;
+
+ // distort
+ vec2 offset_sq = offset * offset;
+ float radius_sq = offset_sq.x + offset_sq.y;
+ float radius_s4 = radius_sq * radius_sq;
+ float distortion_scale = 1.0 + (k1 * radius_sq) + (k2 * radius_s4);
+ offset *= distortion_scale;
+
+ // reapply aspect ratio
+ offset.y *= aspect_ratio;
+
+ // add our eye center back in
+ coords = offset + eye_center;
+ coords /= upscale;
+
+ // and check our color
+ if (coords.x < -1.0 || coords.y < -1.0 || coords.x > 1.0 || coords.y > 1.0) {
+ frag_color = vec4(0.0, 0.0, 0.0, 1.0);
+ } else {
+ coords = (coords + vec2(1.0)) / vec2(2.0);
+ frag_color = textureLod(source, coords, 0.0);
+ }
+}
+
diff --git a/modules/mono/SCsub b/modules/mono/SCsub
new file mode 100644
index 0000000000..0af2056c5c
--- /dev/null
+++ b/modules/mono/SCsub
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+
+Import('env')
+
+
+def make_cs_files_header(src, dst):
+ with open(dst, 'wb') as header:
+ header.write('/* This is an automatically generated file; DO NOT EDIT! OK THX */\n')
+ header.write('#ifndef _CS_FILES_DATA_H\n')
+ header.write('#define _CS_FILES_DATA_H\n\n')
+ header.write('#include "map.h"\n')
+ header.write('#include "ustring.h"\n')
+ inserted_files = ''
+ import os
+ for file in os.listdir(src):
+ if file.endswith('.cs'):
+ with open(os.path.join(src, file), 'rb') as f:
+ buf = f.read()
+ decomp_size = len(buf)
+ import zlib
+ buf = zlib.compress(buf)
+ name = os.path.splitext(file)[0]
+ header.write('\nstatic const int _cs_' + name + '_compressed_size = ' + str(len(buf)) + ';\n')
+ header.write('static const int _cs_' + name + '_uncompressed_size = ' + str(decomp_size) + ';\n')
+ header.write('static const unsigned char _cs_' + name + '_compressed[] = { ')
+ for i, buf_idx in enumerate(range(len(buf))):
+ if i > 0:
+ header.write(', ')
+ header.write(str(ord(buf[buf_idx])))
+ inserted_files += '\tr_files.insert(\"' + file + '\", ' \
+ 'CompressedFile(_cs_' + name + '_compressed_size, ' \
+ '_cs_' + name + '_uncompressed_size, ' \
+ '_cs_' + name + '_compressed));\n'
+ header.write(' };\n')
+ header.write('\nstruct CompressedFile\n' '{\n'
+ '\tint compressed_size;\n' '\tint uncompressed_size;\n' '\tconst unsigned char* data;\n'
+ '\n\tCompressedFile(int p_comp_size, int p_uncomp_size, const unsigned char* p_data)\n'
+ '\t{\n' '\t\tcompressed_size = p_comp_size;\n' '\t\tuncompressed_size = p_uncomp_size;\n'
+ '\t\tdata = p_data;\n' '\t}\n' '\n\tCompressedFile() {}\n' '};\n'
+ '\nvoid get_compressed_files(Map<String, CompressedFile>& r_files)\n' '{\n' + inserted_files + '}\n'
+ )
+ header.write('#endif // _CS_FILES_DATA_H')
+
+
+env.add_source_files(env.modules_sources, '*.cpp')
+env.add_source_files(env.modules_sources, 'mono_gd/*.cpp')
+env.add_source_files(env.modules_sources, 'utils/*.cpp')
+
+if env['tools']:
+ env.add_source_files(env.modules_sources, 'editor/*.cpp')
+ make_cs_files_header('glue/cs_files', 'glue/cs_compressed.gen.h')
+
+vars = Variables()
+vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True))
+vars.Update(env)
+
+# Glue sources
+if env['mono_glue']:
+ env.add_source_files(env.modules_sources, 'glue/*.cpp')
+else:
+ env.Append(CPPDEFINES = [ 'MONO_GLUE_DISABLED' ])
+
+if ARGUMENTS.get('yolo_copy', False):
+ env.Append(CPPDEFINES = [ 'YOLO_COPY' ])
+
+# Build GodotSharpTools solution
+
+import os
+import subprocess
+import mono_reg_utils as monoreg
+
+
+def mono_build_solution(source, target, env):
+ if os.name == 'nt':
+ msbuild_tools_path = monoreg.find_msbuild_tools_path_reg()
+ if not msbuild_tools_path:
+ raise RuntimeError('Cannot find MSBuild Tools Path in the registry')
+ msbuild_path = os.path.join(msbuild_tools_path, 'MSBuild.exe')
+ else:
+ msbuild_path = 'msbuild'
+
+ output_path = os.path.abspath(os.path.join(str(target[0]), os.pardir))
+
+ msbuild_args = [
+ msbuild_path,
+ os.path.abspath(str(source[0])),
+ '/p:Configuration=Release',
+ '/p:OutputPath=' + output_path
+ ]
+
+ msbuild_env = os.environ.copy()
+
+ # Needed when running from Developer Command Prompt for VS
+ if 'PLATFORM' in msbuild_env:
+ del msbuild_env['PLATFORM']
+
+ msbuild_alt_paths = [ 'xbuild' ]
+
+ while True:
+ try:
+ subprocess.check_call(msbuild_args, env = msbuild_env)
+ break
+ except subprocess.CalledProcessError:
+ raise RuntimeError('GodotSharpTools build failed')
+ except OSError:
+ if os.name != 'nt':
+ if not msbuild_alt_paths:
+ raise RuntimeError('Could not find commands msbuild or xbuild')
+ # Try xbuild
+ msbuild_args[0] = msbuild_alt_paths.pop(0)
+ else:
+ raise RuntimeError('Could not find command MSBuild.exe')
+
+
+mono_sln_builder = Builder(action = mono_build_solution)
+env.Append(BUILDERS = { 'MonoBuildSolution' : mono_sln_builder })
+env.MonoBuildSolution(
+ os.path.join(Dir('#bin').abspath, 'GodotSharpTools.dll'),
+ 'editor/GodotSharpTools/GodotSharpTools.sln'
+)
diff --git a/modules/mono/config.py b/modules/mono/config.py
new file mode 100644
index 0000000000..9de199bb5a
--- /dev/null
+++ b/modules/mono/config.py
@@ -0,0 +1,143 @@
+
+import imp
+import os
+import sys
+from shutil import copyfile
+
+from SCons.Script import BoolVariable, Environment, Variables
+
+
+monoreg = imp.load_source('mono_reg_utils', 'modules/mono/mono_reg_utils.py')
+
+
+def find_file_in_dir(directory, files, prefix='', extension=''):
+ if not extension.startswith('.'):
+ extension = '.' + extension
+ for curfile in files:
+ if os.path.isfile(os.path.join(directory, prefix + curfile + extension)):
+ return curfile
+
+ return None
+
+
+def can_build(platform):
+ if platform in ["javascript"]:
+ return False # Not yet supported
+ return True
+
+
+def is_enabled():
+ # The module is disabled by default. Use module_mono_enabled=yes to enable it.
+ return False
+
+
+def configure(env):
+ env.use_ptrcall = True
+
+ envvars = Variables()
+ envvars.Add(BoolVariable('mono_static', 'Statically link mono', False))
+ envvars.Update(env)
+
+ mono_static = env['mono_static']
+
+ mono_lib_names = ['mono-2.0-sgen', 'monosgen-2.0']
+
+ if env['platform'] == 'windows':
+ if mono_static:
+ raise RuntimeError('mono-static: Not supported on Windows')
+
+ if env['bits'] == '32':
+ if os.getenv('MONO32_PREFIX'):
+ mono_root = os.getenv('MONO32_PREFIX')
+ elif os.name == 'nt':
+ mono_root = monoreg.find_mono_root_dir()
+ else:
+ if os.getenv('MONO64_PREFIX'):
+ mono_root = os.getenv('MONO64_PREFIX')
+ elif os.name == 'nt':
+ mono_root = monoreg.find_mono_root_dir()
+
+ if mono_root is None:
+ raise RuntimeError('Mono installation directory not found')
+
+ mono_lib_path = os.path.join(mono_root, 'lib')
+
+ env.Append(LIBPATH=mono_lib_path)
+ env.Append(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0'))
+
+ mono_lib_name = find_file_in_dir(mono_lib_path, mono_lib_names, extension='.lib')
+
+ if mono_lib_name is None:
+ raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
+
+ if os.getenv('VCINSTALLDIR'):
+ env.Append(LINKFLAGS=mono_lib_name + Environment()['LIBSUFFIX'])
+ else:
+ env.Append(LIBS=mono_lib_name)
+
+ mono_bin_path = os.path.join(mono_root, 'bin')
+
+ mono_dll_name = find_file_in_dir(mono_bin_path, mono_lib_names, extension='.dll')
+
+ mono_dll_src = os.path.join(mono_bin_path, mono_dll_name + '.dll')
+ mono_dll_dst = os.path.join('bin', mono_dll_name + '.dll')
+ copy_mono_dll = True
+
+ if not os.path.isdir('bin'):
+ os.mkdir('bin')
+ elif os.path.exists(mono_dll_dst):
+ copy_mono_dll = False
+
+ if copy_mono_dll:
+ copyfile(mono_dll_src, mono_dll_dst)
+ else:
+ mono_root = None
+
+ if env['bits'] == '32':
+ if os.getenv('MONO32_PREFIX'):
+ mono_root = os.getenv('MONO32_PREFIX')
+ else:
+ if os.getenv('MONO64_PREFIX'):
+ mono_root = os.getenv('MONO64_PREFIX')
+
+ if mono_root is not None:
+ mono_lib_path = os.path.join(mono_root, 'lib')
+
+ env.Append(LIBPATH=mono_lib_path)
+ env.Append(CPPPATH=os.path.join(mono_root, 'include', 'mono-2.0'))
+
+ mono_lib = find_file_in_dir(mono_lib_path, mono_lib_names, prefix='lib', extension='.a')
+
+ if mono_lib is None:
+ raise RuntimeError('Could not find mono library in: ' + mono_lib_path)
+
+ env.Append(CPPFLAGS=['-D_REENTRANT'])
+
+ if mono_static:
+ mono_lib_file = os.path.join(mono_lib_path, 'lib' + mono_lib + '.a')
+
+ if sys.platform == "darwin":
+ env.Append(LINKFLAGS=['-Wl,-force_load,' + mono_lib_file])
+ elif sys.platform == "linux" or sys.platform == "linux2":
+ env.Append(LINKFLAGS=['-Wl,-whole-archive', mono_lib_file, '-Wl,-no-whole-archive'])
+ else:
+ raise RuntimeError('mono-static: Not supported on this platform')
+ else:
+ env.Append(LIBS=[mono_lib])
+
+ env.Append(LIBS=['m', 'rt', 'dl', 'pthread'])
+ else:
+ if mono_static:
+ raise RuntimeError('mono-static: Not supported with pkg-config. Specify a mono prefix manually')
+
+ env.ParseConfig('pkg-config mono-2 --cflags --libs')
+
+ env.Append(LINKFLAGS='-rdynamic')
+
+
+def get_doc_classes():
+ return ["@C#", "CSharpScript", "GodotSharp"]
+
+
+def get_doc_path():
+ return "doc_classes"
diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp
new file mode 100644
index 0000000000..67b4e67e2b
--- /dev/null
+++ b/modules/mono/csharp_script.cpp
@@ -0,0 +1,1853 @@
+/*************************************************************************/
+/* csharp_script.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "csharp_script.h"
+
+#include <mono/metadata/threads.h>
+
+#include "os/file_access.h"
+#include "os/os.h"
+#include "os/thread.h"
+#include "project_settings.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/bindings_generator.h"
+#include "editor/csharp_project.h"
+#include "editor/editor_node.h"
+#include "editor/godotsharp_editor.h"
+#endif
+
+#include "godotsharp_dirs.h"
+#include "mono_gd/gd_mono_class.h"
+#include "mono_gd/gd_mono_marshal.h"
+#include "signal_awaiter_utils.h"
+
+#define CACHED_STRING_NAME(m_var) (CSharpLanguage::get_singleton()->string_names.m_var)
+
+CSharpLanguage *CSharpLanguage::singleton = NULL;
+
+String CSharpLanguage::get_name() const {
+
+ return "C#";
+}
+
+String CSharpLanguage::get_type() const {
+
+ return "CSharpScript";
+}
+
+String CSharpLanguage::get_extension() const {
+
+ return "cs";
+}
+
+Error CSharpLanguage::execute_file(const String &p_path) {
+
+ // ??
+ return OK;
+}
+
+#ifdef TOOLS_ENABLED
+void gdsharp_editor_init_callback() {
+
+ EditorNode *editor = EditorNode::get_singleton();
+ editor->add_child(memnew(GodotSharpEditor(editor)));
+}
+#endif
+
+void CSharpLanguage::init() {
+
+ gdmono = memnew(GDMono);
+ gdmono->initialize();
+
+#ifdef MONO_GLUE_DISABLED
+ WARN_PRINT("This binary is built with `mono_glue=no` and cannot be used for scripting");
+#endif
+
+#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
+ if (gdmono->get_editor_tools_assembly() != NULL) {
+ List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
+ BindingsGenerator::handle_cmdline_args(cmdline_args);
+ }
+#endif
+
+#ifdef TOOLS_ENABLED
+ EditorNode::add_init_callback(&gdsharp_editor_init_callback);
+#endif
+}
+
+void CSharpLanguage::finish() {
+
+ if (gdmono) {
+ memdelete(gdmono);
+ gdmono = NULL;
+ }
+}
+
+void CSharpLanguage::get_reserved_words(List<String> *p_words) const {
+
+ static const char *_reserved_words[] = {
+ // Reserved keywords
+ "abstract",
+ "as",
+ "base",
+ "bool",
+ "break",
+ "byte",
+ "case",
+ "catch",
+ "char",
+ "checked",
+ "class",
+ "const",
+ "continue",
+ "decimal",
+ "default",
+ "delegate",
+ "do",
+ "double",
+ "else",
+ "enum",
+ "event",
+ "explicit",
+ "extern",
+ "false",
+ "finally",
+ "fixed",
+ "float",
+ "for",
+ "forech",
+ "goto",
+ "if",
+ "implicit",
+ "in",
+ "int",
+ "interface",
+ "internal",
+ "is",
+ "lock",
+ "long",
+ "namespace",
+ "new",
+ "null",
+ "object",
+ "operator",
+ "out",
+ "override",
+ "params",
+ "private",
+ "protected",
+ "public",
+ "readonly",
+ "ref",
+ "return",
+ "sbyte",
+ "sealed",
+ "short",
+ "sizeof",
+ "stackalloc",
+ "static",
+ "string",
+ "struct",
+ "switch",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typeof",
+ "uint",
+ "ulong",
+ "unchecked",
+ "unsafe",
+ "ushort",
+ "using",
+ "virtual",
+ "volatile",
+ "void",
+ "while",
+
+ // Contextual keywords. Not reserved words, but I guess we should include
+ // them because this seems to be used only for syntax highlighting.
+ "add",
+ "ascending",
+ "by",
+ "descending",
+ "dynamic",
+ "equals",
+ "from",
+ "get",
+ "global",
+ "group",
+ "in",
+ "into",
+ "join",
+ "let",
+ "on",
+ "orderby",
+ "partial",
+ "remove",
+ "select",
+ "set",
+ "value",
+ "var",
+ "where",
+ "yield",
+ 0
+ };
+
+ const char **w = _reserved_words;
+
+ while (*w) {
+ p_words->push_back(*w);
+ w++;
+ }
+}
+
+void CSharpLanguage::get_comment_delimiters(List<String> *p_delimiters) const {
+
+ p_delimiters->push_back("//"); // single-line comment
+ p_delimiters->push_back("/* */"); // delimited comment
+}
+
+void CSharpLanguage::get_string_delimiters(List<String> *p_delimiters) const {
+
+ p_delimiters->push_back("' '"); // character literal
+ p_delimiters->push_back("\" \""); // regular string literal
+ p_delimiters->push_back("@\" \""); // verbatim string literal
+}
+
+Ref<Script> CSharpLanguage::get_template(const String &p_class_name, const String &p_base_class_name) const {
+
+ String script_template = "using " BINDINGS_NAMESPACE ";\n"
+ "using System;\n"
+ "\n"
+ "public class %CLASS_NAME% : %BASE_CLASS_NAME%\n"
+ "{\n"
+ " // Member variables here, example:\n"
+ " // private int a = 2;\n"
+ " // private string b = \"textvar\";\n"
+ "\n"
+ " public override void _Ready()\n"
+ " {\n"
+ " // Called every time the node is added to the scene.\n"
+ " // Initialization here\n"
+ " \n"
+ " }\n"
+ "}\n";
+
+ script_template = script_template.replace("%BASE_CLASS_NAME%", p_base_class_name).replace("%CLASS_NAME%", p_class_name);
+
+ Ref<CSharpScript> script;
+ script.instance();
+ script->set_source_code(script_template);
+
+ return script;
+}
+
+Script *CSharpLanguage::create_script() const {
+
+ return memnew(CSharpScript);
+}
+
+bool CSharpLanguage::has_named_classes() const {
+
+ return true;
+}
+
+String CSharpLanguage::make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const {
+
+ // FIXME
+ // Due to Godot's API limitation this just appends the function to the end of the file
+ // Another limitation is that the parameter types are not specified, so we must use System.Object
+ String s = "private void " + p_name + "(";
+ for (int i = 0; i < p_args.size(); i++) {
+ if (i > 0)
+ s += ", ";
+ s += "object " + p_args[i];
+ }
+ s += ")\n{\n // Replace with function body\n}\n";
+
+ return s;
+}
+
+void CSharpLanguage::frame() {
+
+ const Ref<MonoGCHandle> &task_scheduler_handle = GDMonoUtils::mono_cache.task_scheduler_handle;
+
+ if (task_scheduler_handle.is_valid()) {
+ MonoObject *task_scheduler = task_scheduler_handle->get_target();
+
+ if (task_scheduler) {
+ GDMonoUtils::GodotTaskScheduler_Activate thunk = CACHED_METHOD_THUNK(GodotTaskScheduler, Activate);
+
+ ERR_FAIL_NULL(thunk);
+
+ MonoObject *ex;
+ thunk(task_scheduler, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL();
+ }
+ }
+ }
+}
+
+struct CSharpScriptDepSort {
+
+ // must support sorting so inheritance works properly (parent must be reloaded first)
+ bool operator()(const Ref<CSharpScript> &A, const Ref<CSharpScript> &B) const {
+ if (A == B)
+ return false; // shouldn't happen but..
+ GDMonoClass *I = B->base;
+ while (I) {
+ if (I == A->script_class) {
+ // A is a base of B
+ return true;
+ }
+
+ I = I->get_parent_class();
+ }
+
+ return false; // not a base
+ }
+};
+
+void CSharpLanguage::reload_all_scripts() {
+
+#ifdef DEBUG_ENABLED
+
+#ifndef NO_THREADS
+ lock->lock();
+#endif
+
+ List<Ref<CSharpScript> > scripts;
+
+ SelfList<CSharpScript> *elem = script_list.first();
+ while (elem) {
+ if (elem->self()->get_path().is_resource_file()) {
+ scripts.push_back(Ref<CSharpScript>(elem->self())); //cast to gdscript to avoid being erased by accident
+ }
+ elem = elem->next();
+ }
+
+#ifndef NO_THREADS
+ lock->unlock();
+#endif
+
+ //as scripts are going to be reloaded, must proceed without locking here
+
+ scripts.sort_custom<CSharpScriptDepSort>(); //update in inheritance dependency order
+
+ for (List<Ref<CSharpScript> >::Element *E = scripts.front(); E; E = E->next()) {
+ E->get()->load_source_code(E->get()->get_path());
+ E->get()->reload(true);
+ }
+#endif
+}
+
+void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload) {
+
+ (void)p_script; // UNUSED
+
+#ifdef TOOLS_ENABLED
+ reload_assemblies_if_needed(p_soft_reload);
+#endif
+}
+
+#ifdef TOOLS_ENABLED
+void CSharpLanguage::reload_assemblies_if_needed(bool p_soft_reload) {
+
+ if (gdmono->is_runtime_initialized()) {
+
+ GDMonoAssembly *proj_assembly = gdmono->get_project_assembly();
+
+ if (proj_assembly) {
+ String proj_asm_path = proj_assembly->get_path();
+
+ if (!FileAccess::exists(proj_assembly->get_path())) {
+ // Maybe it wasn't loaded from the default path, so check this as well
+ String proj_asm_name = ProjectSettings::get_singleton()->get("application/config/name");
+ proj_asm_path = GodotSharpDirs::get_res_temp_assemblies_dir().plus_file(proj_asm_name);
+ if (!FileAccess::exists(proj_asm_path))
+ return; // No assembly to load
+ }
+
+ if (FileAccess::get_modified_time(proj_asm_path) <= proj_assembly->get_modified_time())
+ return; // Already up to date
+ } else {
+ String proj_asm_name = ProjectSettings::get_singleton()->get("application/config/name");
+ if (!FileAccess::exists(GodotSharpDirs::get_res_temp_assemblies_dir().plus_file(proj_asm_name)))
+ return; // No assembly to load
+ }
+ }
+
+#ifndef NO_THREADS
+ lock->lock();
+#endif
+
+ List<Ref<CSharpScript> > scripts;
+
+ SelfList<CSharpScript> *elem = script_list.first();
+ while (elem) {
+ if (elem->self()->get_path().is_resource_file()) {
+
+ scripts.push_back(Ref<CSharpScript>(elem->self())); //cast to CSharpScript to avoid being erased by accident
+ }
+ elem = elem->next();
+ }
+
+#ifndef NO_THREADS
+ lock->unlock();
+#endif
+
+ //when someone asks you why dynamically typed languages are easier to write....
+
+ Map<Ref<CSharpScript>, Map<ObjectID, List<Pair<StringName, Variant> > > > to_reload;
+
+ //as scripts are going to be reloaded, must proceed without locking here
+
+ scripts.sort_custom<CSharpScriptDepSort>(); //update in inheritance dependency order
+
+ for (List<Ref<CSharpScript> >::Element *E = scripts.front(); E; E = E->next()) {
+
+ to_reload.insert(E->get(), Map<ObjectID, List<Pair<StringName, Variant> > >());
+
+ if (!p_soft_reload) {
+
+ //save state and remove script from instances
+ Map<ObjectID, List<Pair<StringName, Variant> > > &map = to_reload[E->get()];
+
+ while (E->get()->instances.front()) {
+ Object *obj = E->get()->instances.front()->get();
+ //save instance info
+ List<Pair<StringName, Variant> > state;
+ if (obj->get_script_instance()) {
+
+ obj->get_script_instance()->get_property_state(state);
+
+ Ref<MonoGCHandle> gchandle = CAST_CSHARP_INSTANCE(obj->get_script_instance())->gchandle;
+ if (gchandle.is_valid())
+ gchandle->release();
+
+ map[obj->get_instance_id()] = state;
+ obj->set_script(RefPtr());
+ }
+ }
+
+ //same thing for placeholders
+ while (E->get()->placeholders.size()) {
+
+ Object *obj = E->get()->placeholders.front()->get()->get_owner();
+ //save instance info
+ List<Pair<StringName, Variant> > state;
+ if (obj->get_script_instance()) {
+ obj->get_script_instance()->get_property_state(state);
+ map[obj->get_instance_id()] = state;
+ obj->set_script(RefPtr());
+ }
+ }
+
+ for (Map<ObjectID, List<Pair<StringName, Variant> > >::Element *F = E->get()->pending_reload_state.front(); F; F = F->next()) {
+ map[F->key()] = F->get(); //pending to reload, use this one instead
+ }
+
+ E->get()->_clear();
+ }
+ }
+
+ if (gdmono->reload_scripts_domain() != OK)
+ return;
+
+ for (Map<Ref<CSharpScript>, Map<ObjectID, List<Pair<StringName, Variant> > > >::Element *E = to_reload.front(); E; E = E->next()) {
+
+ Ref<CSharpScript> scr = E->key();
+ scr->exports_invalidated = true;
+ scr->reload(p_soft_reload);
+ scr->update_exports();
+
+ //restore state if saved
+ for (Map<ObjectID, List<Pair<StringName, Variant> > >::Element *F = E->get().front(); F; F = F->next()) {
+
+ Object *obj = ObjectDB::get_instance(F->key());
+ if (!obj)
+ continue;
+
+ if (!p_soft_reload) {
+ //clear it just in case (may be a pending reload state)
+ obj->set_script(RefPtr());
+ }
+ obj->set_script(scr.get_ref_ptr());
+ if (!obj->get_script_instance()) {
+ //failed, save reload state for next time if not saved
+ if (!scr->pending_reload_state.has(obj->get_instance_id())) {
+ scr->pending_reload_state[obj->get_instance_id()] = F->get();
+ }
+ continue;
+ }
+
+ for (List<Pair<StringName, Variant> >::Element *G = F->get().front(); G; G = G->next()) {
+ obj->get_script_instance()->set(G->get().first, G->get().second);
+ }
+
+ scr->pending_reload_state.erase(obj->get_instance_id()); //as it reloaded, remove pending state
+ }
+
+ //if instance states were saved, set them!
+ }
+}
+#endif
+
+void CSharpLanguage::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("cs");
+}
+
+#ifdef TOOLS_ENABLED
+Error CSharpLanguage::open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) {
+
+ return GodotSharpEditor::get_singleton()->open_in_external_editor(p_script, p_line, p_col);
+}
+
+bool CSharpLanguage::overrides_external_editor() {
+
+ return GodotSharpEditor::get_singleton()->overrides_external_editor();
+}
+#endif
+
+void CSharpLanguage::thread_enter() {
+
+#if 0
+ if (mono->is_runtime_initialized()) {
+ GDMonoUtils::attach_current_thread();
+ }
+#endif
+}
+
+void CSharpLanguage::thread_exit() {
+
+#if 0
+ if (mono->is_runtime_initialized()) {
+ GDMonoUtils::detach_current_thread();
+ }
+#endif
+}
+
+bool CSharpLanguage::debug_break_parse(const String &p_file, int p_line, const String &p_error) {
+
+ // Break because of parse error
+ if (ScriptDebugger::get_singleton() && Thread::get_caller_id() == Thread::get_main_id()) {
+ // TODO
+ //_debug_parse_err_line = p_line;
+ //_debug_parse_err_file = p_file;
+ //_debug_error = p_error;
+ ScriptDebugger::get_singleton()->debug(this, false);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool CSharpLanguage::debug_break(const String &p_error, bool p_allow_continue) {
+
+ if (ScriptDebugger::get_singleton() && Thread::get_caller_id() == Thread::get_main_id()) {
+ // TODO
+ //_debug_parse_err_line = -1;
+ //_debug_parse_err_file = "";
+ //_debug_error = p_error;
+ ScriptDebugger::get_singleton()->debug(this, p_allow_continue);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+void CSharpLanguage::set_language_index(int p_idx) {
+
+ ERR_FAIL_COND(lang_idx != -1);
+ lang_idx = p_idx;
+}
+
+CSharpLanguage::CSharpLanguage() {
+
+ ERR_FAIL_COND(singleton);
+ singleton = this;
+
+ gdmono = NULL;
+
+#ifdef NO_THREADS
+ lock = NULL;
+ gchandle_bind_lock = NULL;
+#else
+ lock = Mutex::create();
+ script_bind_lock = Mutex::create();
+#endif
+
+ lang_idx = -1;
+}
+
+CSharpLanguage::~CSharpLanguage() {
+
+ finish();
+
+ if (lock) {
+ memdelete(lock);
+ lock = NULL;
+ }
+
+ if (script_bind_lock) {
+ memdelete(script_bind_lock);
+ script_bind_lock = NULL;
+ }
+
+ singleton = NULL;
+}
+
+void *CSharpLanguage::alloc_instance_binding_data(Object *p_object) {
+
+#ifdef DEBUG_ENABLED
+ // I don't trust you
+ if (p_object->get_script_instance())
+ CRASH_COND(NULL != CAST_CSHARP_INSTANCE(p_object->get_script_instance()));
+#endif
+
+ StringName type_name = p_object->get_class_name();
+
+ GDMonoClass *type_class = GDMonoUtils::type_get_proxy_class(type_name);
+
+ ERR_FAIL_NULL_V(type_class, NULL);
+
+ MonoObject *mono_object = GDMonoUtils::create_managed_for_godot_object(type_class, type_name, p_object);
+
+ ERR_FAIL_NULL_V(mono_object, NULL);
+
+ // Tie managed to unmanaged
+ bool strong_handle = true;
+ Reference *ref = Object::cast_to<Reference>(p_object);
+
+ if (ref) {
+ strong_handle = false;
+
+ // Unsafe refcount increment. The managed instance also counts as a reference.
+ // This way if the unmanaged world has no references to our owner
+ // but the managed instance is alive, the refcount will be 1 instead of 0.
+ // See: _GodotSharp::_dispose_object(Object *p_object)
+
+ ref->reference();
+ }
+
+ Ref<MonoGCHandle> gchandle = strong_handle ? MonoGCHandle::create_strong(mono_object) :
+ MonoGCHandle::create_weak(mono_object);
+
+#ifndef NO_THREADS
+ script_bind_lock->lock();
+#endif
+
+ void *data = (void *)gchandle_bindings.insert(p_object, gchandle);
+
+#ifndef NO_THREADS
+ script_bind_lock->unlock();
+#endif
+
+ return data;
+}
+
+void CSharpLanguage::free_instance_binding_data(void *p_data) {
+
+#ifndef NO_THREADS
+ script_bind_lock->lock();
+#endif
+
+ gchandle_bindings.erase((Map<Object *, Ref<MonoGCHandle> >::Element *)p_data);
+
+#ifndef NO_THREADS
+ script_bind_lock->unlock();
+#endif
+}
+
+void CSharpInstance::_ml_call_reversed(GDMonoClass *klass, const StringName &p_method, const Variant **p_args, int p_argcount) {
+
+ GDMonoClass *base = klass->get_parent_class();
+ if (base && base != script->native)
+ _ml_call_reversed(base, p_method, p_args, p_argcount);
+
+ GDMonoMethod *method = klass->get_method(p_method, p_argcount);
+
+ if (method) {
+ method->invoke(get_mono_object(), p_args);
+ }
+}
+
+CSharpInstance *CSharpInstance::create_for_managed_type(Object *p_owner, CSharpScript *p_script, const Ref<MonoGCHandle> &p_gchandle) {
+
+ CSharpInstance *instance = memnew(CSharpInstance);
+
+ Reference *ref = Object::cast_to<Reference>(p_owner);
+
+ instance->base_ref = ref != NULL;
+ instance->script = Ref<CSharpScript>(p_script);
+ instance->owner = p_owner;
+ instance->gchandle = p_gchandle;
+
+ if (instance->base_ref)
+ instance->_reference_owner_unsafe();
+
+ p_script->instances.insert(p_owner);
+
+ return instance;
+}
+
+MonoObject *CSharpInstance::get_mono_object() const {
+#ifdef DEBUG_ENABLED
+ CRASH_COND(gchandle.is_null());
+#endif
+ return gchandle->get_target();
+}
+
+bool CSharpInstance::set(const StringName &p_name, const Variant &p_value) {
+
+ ERR_FAIL_COND_V(!script.is_valid(), false);
+
+ GDMonoClass *top = script->script_class;
+
+ while (top && top != script->native) {
+ GDMonoField *field = script->script_class->get_field(p_name);
+
+ if (field) {
+ MonoObject *mono_object = get_mono_object();
+
+ ERR_EXPLAIN("Reference has been garbage collected?");
+ ERR_FAIL_NULL_V(mono_object, false);
+
+ field->set_value(mono_object, p_value);
+
+ return true;
+ }
+
+ top = top->get_parent_class();
+ }
+
+ // Call _set
+
+ Variant name = p_name;
+ const Variant *args[2] = { &name, &p_value };
+
+ MonoObject *mono_object = get_mono_object();
+ top = script->script_class;
+
+ while (top && top != script->native) {
+ GDMonoMethod *method = top->get_method(CACHED_STRING_NAME(_set), 2);
+
+ if (method) {
+ MonoObject *ret = method->invoke(mono_object, args);
+
+ if (ret && UNBOX_BOOLEAN(ret))
+ return true;
+ }
+
+ top = top->get_parent_class();
+ }
+
+ return false;
+}
+
+bool CSharpInstance::get(const StringName &p_name, Variant &r_ret) const {
+
+ ERR_FAIL_COND_V(!script.is_valid(), false);
+
+ GDMonoClass *top = script->script_class;
+
+ while (top && top != script->native) {
+ GDMonoField *field = top->get_field(p_name);
+
+ if (field) {
+ MonoObject *mono_object = get_mono_object();
+
+ ERR_EXPLAIN("Reference has been garbage collected?");
+ ERR_FAIL_NULL_V(mono_object, false);
+
+ MonoObject *value = field->get_value(mono_object);
+ r_ret = GDMonoMarshal::mono_object_to_variant(value, field->get_type());
+ return true;
+ }
+
+ // Call _get
+
+ GDMonoMethod *method = top->get_method(CACHED_STRING_NAME(_get), 1);
+
+ if (method) {
+ Variant name = p_name;
+ const Variant *args[1] = { &name };
+
+ MonoObject *ret = method->invoke(get_mono_object(), args);
+
+ if (ret) {
+ r_ret = GDMonoMarshal::mono_object_to_variant(ret);
+ return true;
+ }
+ }
+
+ top = top->get_parent_class();
+ }
+
+ return false;
+}
+
+void CSharpInstance::get_property_list(List<PropertyInfo> *p_properties) const {
+
+ for (Map<StringName, PropertyInfo>::Element *E = script->member_info.front(); E; E = E->next()) {
+ p_properties->push_back(E->value());
+ }
+}
+
+Variant::Type CSharpInstance::get_property_type(const StringName &p_name, bool *r_is_valid) const {
+
+ if (script->member_info.has(p_name)) {
+ if (r_is_valid)
+ *r_is_valid = true;
+ return script->member_info[p_name].type;
+ }
+
+ if (r_is_valid)
+ *r_is_valid = false;
+
+ return Variant::NIL;
+}
+
+bool CSharpInstance::has_method(const StringName &p_method) const {
+
+ if (!script.is_valid())
+ return false;
+
+ GDMonoClass *top = script->script_class;
+
+ while (top && top != script->native) {
+ if (top->has_method(p_method)) {
+ return true;
+ }
+
+ top = top->get_parent_class();
+ }
+
+ return false;
+}
+
+Variant CSharpInstance::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+
+ MonoObject *mono_object = get_mono_object();
+
+ ERR_EXPLAIN("Reference has been garbage collected?");
+ ERR_FAIL_NULL_V(mono_object, Variant());
+
+ if (!script.is_valid())
+ return Variant();
+
+ GDMonoClass *top = script->script_class;
+
+ while (top && top != script->native) {
+ GDMonoMethod *method = top->get_method(p_method, p_argcount);
+
+ if (method) {
+ MonoObject *return_value = method->invoke(mono_object, p_args);
+
+ if (return_value) {
+ return GDMonoMarshal::mono_object_to_variant(return_value, method->get_return_type());
+ } else {
+ return Variant();
+ }
+ } else if (p_method == CACHED_STRING_NAME(_awaited_signal_callback)) {
+ // shitty hack..
+ // TODO move to its own function, thx
+
+ if (p_argcount < 1) {
+ r_error.error = Variant::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS;
+ r_error.argument = 1;
+ return Variant();
+ }
+
+ Ref<SignalAwaiterHandle> awaiter = *p_args[p_argcount - 1];
+
+ if (awaiter.is_null()) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_ARGUMENT;
+ r_error.argument = p_argcount - 1;
+ r_error.expected = Variant::OBJECT;
+ return Variant();
+ }
+
+ awaiter->set_completed(true);
+
+ int extra_argc = p_argcount - 1;
+ MonoArray *extra_args = mono_array_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(MonoObject), extra_argc);
+
+ for (int i = 0; i < extra_argc; i++) {
+ MonoObject *boxed = GDMonoMarshal::variant_to_mono_object(*p_args[i]);
+ mono_array_set(extra_args, MonoObject *, i, boxed);
+ }
+
+ GDMonoUtils::GodotObject__AwaitedSignalCallback thunk = CACHED_METHOD_THUNK(GodotObject, _AwaitedSignalCallback);
+
+ MonoObject *ex = NULL;
+ thunk(mono_object, &extra_args, awaiter->get_target(), &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL_V(Variant());
+ }
+
+ return Variant();
+ }
+
+ top = top->get_parent_class();
+ }
+
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+
+ return Variant();
+}
+
+void CSharpInstance::call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount) {
+
+ if (script.is_valid()) {
+ MonoObject *mono_object = get_mono_object();
+
+ GDMonoClass *top = script->script_class;
+
+ while (top && top != script->native) {
+ GDMonoMethod *method = top->get_method(p_method, p_argcount);
+
+ if (method)
+ method->invoke(mono_object, p_args);
+
+ top = top->get_parent_class();
+ }
+ }
+}
+
+void CSharpInstance::call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount) {
+
+ if (script.is_valid()) {
+ _ml_call_reversed(script->script_class, p_method, p_args, p_argcount);
+ }
+}
+
+void CSharpInstance::_reference_owner_unsafe() {
+
+#ifdef DEBUG_ENABLED
+ CRASH_COND(!base_ref);
+#endif
+
+ // Unsafe refcount increment. The managed instance also counts as a reference.
+ // This way if the unmanaged world has no references to our owner
+ // but the managed instance is alive, the refcount will be 1 instead of 0.
+ // See: _unreference_owner_unsafe()
+
+ // May not me referenced yet, so we must use init_ref() instead of reference()
+ Object::cast_to<Reference>(owner)->init_ref();
+}
+
+void CSharpInstance::_unreference_owner_unsafe() {
+
+#ifdef DEBUG_ENABLED
+ CRASH_COND(!base_ref);
+#endif
+
+ // Called from CSharpInstance::mono_object_disposed() or ~CSharpInstance()
+
+ // Unsafe refcount decrement. The managed instance also counts as a reference.
+ // See: _reference_owner_unsafe()
+
+ if (Object::cast_to<Reference>(owner)->unreference()) {
+ memdelete(owner);
+ owner = NULL;
+ }
+}
+
+void CSharpInstance::mono_object_disposed() {
+
+ if (base_ref)
+ _unreference_owner_unsafe();
+}
+
+void CSharpInstance::refcount_incremented() {
+
+ CRASH_COND(!base_ref);
+
+ Reference *ref_owner = Object::cast_to<Reference>(owner);
+
+ if (ref_owner->reference_get_count() > 1) { // Remember the managed side holds a reference, hence 1 instead of 0 here
+ // The reference count was increased after the managed side was the only one referencing our owner.
+ // This means the owner is being referenced again by the unmanaged side,
+ // so the owner must hold the managed side alive again to avoid it from being GCed.
+
+ // Release the current weak handle and replace it with a strong handle.
+ uint32_t strong_gchandle = MonoGCHandle::make_strong_handle(gchandle->get_target());
+ gchandle->release();
+ gchandle->set_handle(strong_gchandle);
+ }
+}
+
+bool CSharpInstance::refcount_decremented() {
+
+ CRASH_COND(!base_ref);
+
+ Reference *ref_owner = Object::cast_to<Reference>(owner);
+
+ int refcount = ref_owner->reference_get_count();
+
+ if (refcount == 1) { // Remember the managed side holds a reference, hence 1 instead of 0 here
+ // If owner owner is no longer referenced by the unmanaged side,
+ // the managed instance takes responsibility of deleting the owner when GCed.
+
+ // Release the current strong handle and replace it with a weak handle.
+ uint32_t weak_gchandle = MonoGCHandle::make_weak_handle(gchandle->get_target());
+ gchandle->release();
+ gchandle->set_handle(weak_gchandle);
+
+ return false;
+ }
+
+ ref_dying = (refcount == 0);
+
+ return ref_dying;
+}
+
+ScriptInstance::RPCMode CSharpInstance::get_rpc_mode(const StringName &p_method) const {
+
+ GDMonoClass *top = script->script_class;
+
+ while (top && top != script->native) {
+ GDMonoMethod *method = top->get_method(p_method);
+
+ if (method) { // TODO should we reject static methods?
+ // TODO cache result
+ if (method->has_attribute(CACHED_CLASS(RemoteAttribute)))
+ return RPC_MODE_REMOTE;
+ if (method->has_attribute(CACHED_CLASS(SyncAttribute)))
+ return RPC_MODE_SYNC;
+ if (method->has_attribute(CACHED_CLASS(MasterAttribute)))
+ return RPC_MODE_MASTER;
+ if (method->has_attribute(CACHED_CLASS(SlaveAttribute)))
+ return RPC_MODE_SLAVE;
+ }
+
+ top = top->get_parent_class();
+ }
+
+ return RPC_MODE_DISABLED;
+}
+
+ScriptInstance::RPCMode CSharpInstance::get_rset_mode(const StringName &p_variable) const {
+
+ GDMonoClass *top = script->script_class;
+
+ while (top && top != script->native) {
+ GDMonoField *field = top->get_field(p_variable);
+
+ if (field) { // TODO should we reject static fields?
+ // TODO cache result
+ if (field->has_attribute(CACHED_CLASS(RemoteAttribute)))
+ return RPC_MODE_REMOTE;
+ if (field->has_attribute(CACHED_CLASS(SyncAttribute)))
+ return RPC_MODE_SYNC;
+ if (field->has_attribute(CACHED_CLASS(MasterAttribute)))
+ return RPC_MODE_MASTER;
+ if (field->has_attribute(CACHED_CLASS(SlaveAttribute)))
+ return RPC_MODE_SLAVE;
+ }
+
+ top = top->get_parent_class();
+ }
+
+ return RPC_MODE_DISABLED;
+}
+
+void CSharpInstance::notification(int p_notification) {
+
+ Variant value = p_notification;
+ const Variant *args[1] = { &value };
+
+ call_multilevel(CACHED_STRING_NAME(_notification), args, 1);
+}
+
+Ref<Script> CSharpInstance::get_script() const {
+
+ return script;
+}
+
+ScriptLanguage *CSharpInstance::get_language() {
+
+ return CSharpLanguage::get_singleton();
+}
+
+CSharpInstance::CSharpInstance() {
+
+ owner = NULL;
+ base_ref = false;
+ ref_dying = false;
+}
+
+CSharpInstance::~CSharpInstance() {
+
+ if (gchandle.is_valid()) {
+ gchandle->release(); // Make sure it's released
+ }
+
+ if (base_ref && !ref_dying) { // it may be called from the owner's destructor
+#ifdef DEBUG_ENABLED
+ CRASH_COND(!owner); // dunno, just in case
+#endif
+ _unreference_owner_unsafe();
+ }
+
+ if (script.is_valid() && owner) {
+#ifndef NO_THREADS
+ CSharpLanguage::singleton->lock->lock();
+#endif
+
+#ifdef DEBUG_ENABLED
+ // CSharpInstance must not be created unless it's going to be added to the list for sure
+ Set<Object *>::Element *match = script->instances.find(owner);
+ CRASH_COND(!match);
+ script->instances.erase(match);
+#else
+ script->instances.erase(owner);
+#endif
+
+#ifndef NO_THREADS
+ CSharpLanguage::singleton->lock->unlock();
+#endif
+ }
+}
+
+#ifdef TOOLS_ENABLED
+void CSharpScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) {
+
+ placeholders.erase(p_placeholder);
+}
+#endif
+
+#ifdef TOOLS_ENABLED
+void CSharpScript::_update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames) {
+
+ if (base_cache.is_valid()) {
+ base_cache->_update_exports_values(values, propnames);
+ }
+
+ for (Map<StringName, Variant>::Element *E = exported_members_defval_cache.front(); E; E = E->next()) {
+ values[E->key()] = E->get();
+ }
+
+ for (List<PropertyInfo>::Element *E = exported_members_cache.front(); E; E = E->next()) {
+ propnames.push_back(E->get());
+ }
+}
+#endif
+
+bool CSharpScript::_update_exports() {
+
+#ifdef TOOLS_ENABLED
+ if (!valid)
+ return false;
+
+ bool changed = false;
+
+ if (exports_invalidated) {
+ exports_invalidated = false;
+
+ changed = true;
+
+ member_info.clear();
+ exported_members_cache.clear();
+ exported_members_defval_cache.clear();
+
+ const Vector<GDMonoField *> &fields = script_class->get_all_fields();
+
+ // We are creating a temporary new instance of the class here to get the default value
+ // TODO Workaround. Should be replaced with IL opcodes analysis
+
+ MonoObject *tmp_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_raw());
+
+ if (tmp_object) {
+ CACHED_FIELD(GodotObject, ptr)->set_value_raw(tmp_object, tmp_object); // FIXME WTF is this workaround
+
+ GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), 0);
+ MonoObject *ex = NULL;
+ ctor->invoke(tmp_object, NULL, &ex);
+
+ if (ex) {
+ ERR_PRINT("Exception thrown from constructor of temporary MonoObject:");
+ mono_print_unhandled_exception(ex);
+ tmp_object = NULL;
+ ERR_FAIL_V(false);
+ }
+ } else {
+ ERR_PRINT("Failed to create temporary MonoObject");
+ return false;
+ }
+
+ for (int i = 0; i < fields.size(); i++) {
+ GDMonoField *field = fields[i];
+
+ if (field->is_static() || field->get_visibility() != GDMono::PUBLIC)
+ continue;
+
+ String name = field->get_name();
+ StringName cname = name;
+
+ Variant::Type type = GDMonoMarshal::managed_to_variant_type(field->get_type());
+
+ if (field->has_attribute(CACHED_CLASS(ExportAttribute))) {
+ MonoObject *attr = field->get_attribute(CACHED_CLASS(ExportAttribute));
+
+ // Field has Export attribute
+ int hint = CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr);
+ String hint_string = CACHED_FIELD(ExportAttribute, hint_string)->get_string_value(attr);
+ int usage = CACHED_FIELD(ExportAttribute, usage)->get_int_value(attr);
+
+ PropertyInfo prop_info = PropertyInfo(type, name, PropertyHint(hint), hint_string, PropertyUsageFlags(usage));
+
+ member_info[cname] = prop_info;
+ exported_members_cache.push_back(prop_info);
+
+ if (tmp_object) {
+ exported_members_defval_cache[cname] = GDMonoMarshal::mono_object_to_variant(field->get_value(tmp_object));
+ }
+ } else {
+ member_info[cname] = PropertyInfo(type, name, PROPERTY_HINT_NONE, "", PROPERTY_USAGE_SCRIPT_VARIABLE);
+ }
+ }
+ }
+
+ if (placeholders.size()) {
+ // Update placeholders if any
+ Map<StringName, Variant> values;
+ List<PropertyInfo> propnames;
+ _update_exports_values(values, propnames);
+
+ for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
+ E->get()->update(propnames, values);
+ }
+ }
+
+ return changed;
+#endif
+ return false;
+}
+
+void CSharpScript::_clear() {
+
+ tool = false;
+ valid = false;
+
+ base = NULL;
+ native = NULL;
+ script_class = NULL;
+}
+
+Variant CSharpScript::call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+
+ GDMonoClass *top = script_class;
+
+ while (top && top != native) {
+ GDMonoMethod *method = top->get_method(p_method, p_argcount);
+
+ if (method && method->is_static()) {
+ MonoObject *result = method->invoke(NULL, p_args);
+
+ if (result) {
+ return GDMonoMarshal::mono_object_to_variant(result, method->get_return_type());
+ } else {
+ return Variant();
+ }
+ }
+
+ top = top->get_parent_class();
+ }
+
+ // No static method found. Try regular instance calls
+ return Script::call(p_method, p_args, p_argcount, r_error);
+}
+
+void CSharpScript::_resource_path_changed() {
+
+ String path = get_path();
+
+ if (!path.empty()) {
+ name = get_path().get_file().get_basename();
+ }
+}
+
+void CSharpScript::_bind_methods() {
+
+ ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &CSharpScript::_new, MethodInfo(Variant::OBJECT, "new"));
+}
+
+Ref<CSharpScript> CSharpScript::create_for_managed_type(GDMonoClass *p_class) {
+
+ // This method should not fail
+
+ CRASH_COND(!p_class);
+
+ Ref<CSharpScript> script = memnew(CSharpScript);
+
+ script->name = p_class->get_name();
+ script->script_class = p_class;
+ script->native = GDMonoUtils::get_class_native_base(script->script_class);
+
+ CRASH_COND(script->native == NULL);
+
+ GDMonoClass *base = script->script_class->get_parent_class();
+
+ if (base != script->native)
+ script->base = base;
+
+#ifdef DEBUG_ENABLED
+ // For debug builds, we must fetch from all native base methods as well.
+ // Native base methods must be fetched before the current class.
+ // Not needed if the script class itself is a native class.
+
+ if (script->script_class != script->native) {
+ GDMonoClass *native_top = script->native;
+ while (native_top) {
+ native_top->fetch_methods_with_godot_api_checks(script->native);
+
+ if (native_top == CACHED_CLASS(GodotObject))
+ break;
+
+ native_top = native_top->get_parent_class();
+ }
+ }
+#endif
+
+ script->script_class->fetch_methods_with_godot_api_checks(script->native);
+
+ // Need to fetch method from base classes as well
+ GDMonoClass *top = script->script_class;
+ while (top && top != script->native) {
+ top->fetch_methods_with_godot_api_checks(script->native);
+ top = top->get_parent_class();
+ }
+
+ return script;
+}
+
+bool CSharpScript::can_instance() const {
+
+ // TODO does the second condition even make sense?
+ return valid || (!tool && !ScriptServer::is_scripting_enabled());
+}
+
+StringName CSharpScript::get_instance_base_type() const {
+
+ if (native)
+ return native->get_name();
+ else
+ return StringName();
+}
+
+CSharpInstance *CSharpScript::_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error) {
+
+ /* STEP 1, CREATE */
+
+ CSharpInstance *instance = memnew(CSharpInstance);
+ instance->base_ref = p_isref;
+ instance->script = Ref<CSharpScript>(this);
+ instance->owner = p_owner;
+ instance->owner->set_script_instance(instance);
+
+ if (instance->base_ref)
+ instance->_reference_owner_unsafe();
+
+ /* STEP 2, INITIALIZE AND CONSTRUCT */
+
+ MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, script_class->get_raw());
+
+ if (!mono_object) {
+ instance->script = Ref<CSharpScript>();
+ instance->owner->set_script_instance(NULL);
+ r_error.error = Variant::CallError::CALL_ERROR_INSTANCE_IS_NULL;
+ ERR_EXPLAIN("Failed to allocate memory for the object");
+ ERR_FAIL_V(NULL);
+ }
+
+#ifndef NO_THREADS
+ CSharpLanguage::singleton->lock->lock();
+#endif
+
+ instances.insert(instance->owner);
+
+#ifndef NO_THREADS
+ CSharpLanguage::singleton->lock->unlock();
+#endif
+
+ CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, instance->owner);
+
+ // Construct
+ GDMonoMethod *ctor = script_class->get_method(CACHED_STRING_NAME(dotctor), p_argcount);
+ ctor->invoke(mono_object, p_args, NULL);
+
+ // Tie managed to unmanaged
+ instance->gchandle = MonoGCHandle::create_strong(mono_object);
+
+ /* STEP 3, PARTY */
+
+ //@TODO make thread safe
+ return instance;
+}
+
+Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Variant::CallError &r_error) {
+
+ if (!valid) {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ return Variant();
+ }
+
+ r_error.error = Variant::CallError::CALL_OK;
+ REF ref;
+ Object *owner = NULL;
+
+ ERR_FAIL_NULL_V(native, Variant());
+
+ owner = ClassDB::instance(NATIVE_GDMONOCLASS_NAME(native));
+
+ Reference *r = Object::cast_to<Reference>(owner);
+ if (r) {
+ ref = REF(r);
+ }
+
+ CSharpInstance *instance = _create_instance(p_args, p_argcount, owner, r != NULL, r_error);
+ if (!instance) {
+ if (ref.is_null()) {
+ memdelete(owner); //no owner, sorry
+ }
+ return Variant();
+ }
+
+ if (ref.is_valid()) {
+ return ref;
+ } else {
+ return owner;
+ }
+}
+
+ScriptInstance *CSharpScript::instance_create(Object *p_this) {
+
+ if (!valid)
+ return NULL;
+
+ if (!tool && !ScriptServer::is_scripting_enabled()) {
+#ifdef TOOLS_ENABLED
+ PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(CSharpLanguage::get_singleton(), Ref<Script>(this), p_this));
+ placeholders.insert(si);
+ _update_exports();
+ return si;
+#else
+ return NULL;
+#endif
+ }
+
+ if (native) {
+ String native_name = native->get_name();
+ if (!ClassDB::is_parent_class(p_this->get_class_name(), native_name)) {
+ if (ScriptDebugger::get_singleton()) {
+ CSharpLanguage::get_singleton()->debug_break_parse(get_path(), 0, "Script inherits from native type '" + native_name + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'");
+ }
+ ERR_EXPLAIN("Script inherits from native type '" + native_name + "', so it can't be instanced in object of type: '" + p_this->get_class() + "'");
+ ERR_FAIL_V(NULL);
+ }
+ }
+
+ Variant::CallError unchecked_error;
+ return _create_instance(NULL, 0, p_this, Object::cast_to<Reference>(p_this), unchecked_error);
+}
+
+bool CSharpScript::instance_has(const Object *p_this) const {
+
+#ifndef NO_THREADS
+ CSharpLanguage::singleton->lock->lock();
+#endif
+
+ bool ret = instances.has((Object *)p_this);
+
+#ifndef NO_THREADS
+ CSharpLanguage::singleton->lock->unlock();
+#endif
+
+ return ret;
+}
+
+bool CSharpScript::has_source_code() const {
+
+ return !source.empty();
+}
+
+String CSharpScript::get_source_code() const {
+
+ return source;
+}
+
+void CSharpScript::set_source_code(const String &p_code) {
+
+ if (source == p_code)
+ return;
+ source = p_code;
+#ifdef TOOLS_ENABLED
+ source_changed_cache = true;
+#endif
+}
+
+bool CSharpScript::has_method(const StringName &p_method) const {
+
+ return script_class->has_method(p_method);
+}
+
+Error CSharpScript::reload(bool p_keep_state) {
+
+#ifndef NO_THREADS
+ CSharpLanguage::singleton->lock->lock();
+#endif
+
+ bool has_instances = instances.size();
+
+#ifndef NO_THREADS
+ CSharpLanguage::singleton->lock->unlock();
+#endif
+
+ ERR_FAIL_COND_V(!p_keep_state && has_instances, ERR_ALREADY_IN_USE);
+
+ GDMonoAssembly *project_assembly = GDMono::get_singleton()->get_project_assembly();
+
+ if (project_assembly) {
+ script_class = project_assembly->get_object_derived_class(name);
+ valid = script_class != NULL;
+
+ if (script_class) {
+ tool = script_class->has_attribute(CACHED_CLASS(ToolAttribute));
+
+ native = GDMonoUtils::get_class_native_base(script_class);
+
+ CRASH_COND(native == NULL);
+
+ GDMonoClass *base_class = script_class->get_parent_class();
+
+ if (base_class != native)
+ base = base_class;
+
+#ifdef DEBUG_ENABLED
+ // For debug builds, we must fetch from all native base methods as well.
+ // Native base methods must be fetched before the current class.
+ // Not needed if the script class itself is a native class.
+
+ if (script_class != native) {
+ GDMonoClass *native_top = native;
+ while (native_top) {
+ native_top->fetch_methods_with_godot_api_checks(native);
+
+ if (native_top == CACHED_CLASS(GodotObject))
+ break;
+
+ native_top = native_top->get_parent_class();
+ }
+ }
+#endif
+
+ script_class->fetch_methods_with_godot_api_checks(native);
+
+ // Need to fetch method from base classes as well
+ GDMonoClass *top = script_class;
+ while (top && top != native) {
+ top->fetch_methods_with_godot_api_checks(native);
+ top = top->get_parent_class();
+ }
+ }
+
+ return OK;
+ }
+
+ return ERR_FILE_MISSING_DEPENDENCIES;
+}
+
+String CSharpScript::get_node_type() const {
+
+ return ""; // ?
+}
+
+ScriptLanguage *CSharpScript::get_language() const {
+
+ return CSharpLanguage::get_singleton();
+}
+
+bool CSharpScript::get_property_default_value(const StringName &p_property, Variant &r_value) const {
+
+#ifdef TOOLS_ENABLED
+
+ const Map<StringName, Variant>::Element *E = exported_members_defval_cache.find(p_property);
+ if (E) {
+ r_value = E->get();
+ return true;
+ }
+
+ if (base_cache.is_valid()) {
+ return base_cache->get_property_default_value(p_property, r_value);
+ }
+
+#endif
+ return false;
+}
+
+void CSharpScript::update_exports() {
+
+#ifdef TOOLS_ENABLED
+ _update_exports();
+
+ if (placeholders.size()) {
+ Map<StringName, Variant> values;
+ List<PropertyInfo> propnames;
+ _update_exports_values(values, propnames);
+
+ for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
+ E->get()->update(propnames, values);
+ }
+ }
+#endif
+}
+
+Ref<Script> CSharpScript::get_base_script() const {
+
+ // TODO search in metadata file once we have it, not important any way?
+ return Ref<Script>();
+}
+
+void CSharpScript::get_script_property_list(List<PropertyInfo> *p_list) const {
+
+ for (Map<StringName, PropertyInfo>::Element *E = member_info.front(); E; E = E->next()) {
+ p_list->push_back(E->value());
+ }
+}
+
+int CSharpScript::get_member_line(const StringName &p_member) const {
+
+ // TODO omnisharp
+ return -1;
+}
+
+Error CSharpScript::load_source_code(const String &p_path) {
+
+ PoolVector<uint8_t> sourcef;
+ Error err;
+ FileAccess *f = FileAccess::open(p_path, FileAccess::READ, &err);
+ ERR_FAIL_COND_V(err != OK, err);
+
+ int len = f->get_len();
+ sourcef.resize(len + 1);
+ PoolVector<uint8_t>::Write w = sourcef.write();
+ int r = f->get_buffer(w.ptr(), len);
+ f->close();
+ memdelete(f);
+ ERR_FAIL_COND_V(r != len, ERR_CANT_OPEN);
+ w[len] = 0;
+
+ String s;
+ if (s.parse_utf8((const char *)w.ptr())) {
+
+ ERR_EXPLAIN("Script '" + p_path + "' contains invalid unicode (utf-8), so it was not loaded. Please ensure that scripts are saved in valid utf-8 unicode.");
+ ERR_FAIL_V(ERR_INVALID_DATA);
+ }
+
+ source = s;
+
+#ifdef TOOLS_ENABLED
+ source_changed_cache = true;
+#endif
+
+ return OK;
+}
+
+StringName CSharpScript::get_script_name() const {
+
+ return name;
+}
+
+CSharpScript::CSharpScript()
+ : script_list(this) {
+
+ _clear();
+
+#ifdef TOOLS_ENABLED
+ source_changed_cache = false;
+ exports_invalidated = true;
+#endif
+
+ _resource_path_changed();
+
+#ifdef DEBUG_ENABLED
+
+#ifndef NO_THREADS
+ CSharpLanguage::get_singleton()->lock->lock();
+#endif
+
+ CSharpLanguage::get_singleton()->script_list.add(&script_list);
+
+#ifndef NO_THREADS
+ CSharpLanguage::get_singleton()->lock->unlock();
+#endif
+
+#endif // DEBUG_ENABLED
+}
+
+CSharpScript::~CSharpScript() {
+
+#ifdef DEBUG_ENABLED
+
+#ifndef NO_THREADS
+ CSharpLanguage::get_singleton()->lock->lock();
+#endif
+
+ CSharpLanguage::get_singleton()->script_list.remove(&script_list);
+
+#ifndef NO_THREADS
+ CSharpLanguage::get_singleton()->lock->unlock();
+#endif
+
+#endif // DEBUG_ENABLED
+}
+
+/*************** RESOURCE ***************/
+
+RES ResourceFormatLoaderCSharpScript::load(const String &p_path, const String &p_original_path, Error *r_error) {
+
+ if (r_error)
+ *r_error = ERR_FILE_CANT_OPEN;
+
+ // TODO ignore anything inside bin/ and obj/ in tools builds?
+
+ CSharpScript *script = memnew(CSharpScript);
+
+ Ref<CSharpScript> scriptres(script);
+
+#if defined(DEBUG_ENABLED) || defined(TOOLS_ENABLED)
+ Error err = script->load_source_code(p_path);
+ ERR_FAIL_COND_V(err != OK, RES());
+#endif
+
+ script->set_path(p_original_path);
+ script->reload();
+
+ if (r_error)
+ *r_error = OK;
+
+ return scriptres;
+}
+
+void ResourceFormatLoaderCSharpScript::get_recognized_extensions(List<String> *p_extensions) const {
+
+ p_extensions->push_back("cs");
+}
+
+bool ResourceFormatLoaderCSharpScript::handles_type(const String &p_type) const {
+
+ return p_type == "Script" || p_type == CSharpLanguage::get_singleton()->get_type();
+}
+
+String ResourceFormatLoaderCSharpScript::get_resource_type(const String &p_path) const {
+
+ return p_path.get_extension().to_lower() == "cs" ? CSharpLanguage::get_singleton()->get_type() : "";
+}
+
+Error ResourceFormatSaverCSharpScript::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
+
+ Ref<CSharpScript> sqscr = p_resource;
+ ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);
+
+ String source = sqscr->get_source_code();
+
+#ifdef TOOLS_ENABLED
+ if (!FileAccess::exists(p_path)) {
+ // The file does not yet exists, let's assume the user just created this script
+
+ String sln_path = GodotSharpDirs::get_project_sln_path();
+ String csproj_path = GodotSharpDirs::get_project_csproj_path();
+
+ if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) {
+ // A solution does not yet exist, create a new one
+
+ CRASH_COND(GodotSharpEditor::get_singleton() == NULL);
+ GodotSharpEditor::get_singleton()->call("_create_project_solution");
+ }
+
+ // Add the file to the C# project
+ if (FileAccess::exists(csproj_path)) {
+ CSharpProject::add_item(csproj_path, "Compile", ProjectSettings::get_singleton()->globalize_path(p_path));
+ } else {
+ ERR_PRINT("C# project not found!");
+ }
+ }
+#endif
+
+ Error err;
+ FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &err);
+ ERR_FAIL_COND_V(err, err);
+
+ file->store_string(source);
+
+ if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
+ memdelete(file);
+ return ERR_CANT_CREATE;
+ }
+
+ file->close();
+ memdelete(file);
+
+ if (ScriptServer::is_reload_scripts_on_save_enabled()) {
+ CSharpLanguage::get_singleton()->reload_tool_script(p_resource, false);
+ }
+
+ return OK;
+}
+
+void ResourceFormatSaverCSharpScript::get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const {
+
+ if (Object::cast_to<CSharpScript>(p_resource.ptr())) {
+ p_extensions->push_back("cs");
+ }
+}
+
+bool ResourceFormatSaverCSharpScript::recognize(const RES &p_resource) const {
+
+ return Object::cast_to<CSharpScript>(p_resource.ptr()) != NULL;
+}
+
+CSharpLanguage::StringNameCache::StringNameCache() {
+
+ _awaited_signal_callback = StaticCString::create("_AwaitedSignalCallback");
+ _set = StaticCString::create("_set");
+ _get = StaticCString::create("_get");
+ _notification = StaticCString::create("_notification");
+ dotctor = StaticCString::create(".ctor");
+}
diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h
new file mode 100644
index 0000000000..3fcc3bdf04
--- /dev/null
+++ b/modules/mono/csharp_script.h
@@ -0,0 +1,338 @@
+/*************************************************************************/
+/* csharp_script.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 CSHARP_SCRIPT_H
+#define CSHARP_SCRIPT_H
+
+#include "io/resource_loader.h"
+#include "io/resource_saver.h"
+#include "script_language.h"
+#include "self_list.h"
+
+#include "mono_gc_handle.h"
+#include "mono_gd/gd_mono.h"
+#include "mono_gd/gd_mono_header.h"
+#include "mono_gd/gd_mono_internals.h"
+
+class CSharpScript;
+class CSharpInstance;
+class CSharpLanguage;
+
+#ifdef NO_SAFE_CAST
+template <typename TScriptInstance, typename TScriptLanguage>
+TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
+ return p_inst->get_language() == TScriptLanguage::get_singleton() ? static_cast<TScriptInstance *>(p_inst) : NULL;
+}
+#else
+template <typename TScriptInstance, typename TScriptLanguage>
+TScriptInstance *cast_script_instance(ScriptInstance *p_inst) {
+ return dynamic_cast<TScriptInstance *>(p_inst);
+}
+#endif
+
+#define CAST_CSHARP_INSTANCE(m_inst) (cast_script_instance<CSharpInstance, CSharpLanguage>(m_inst))
+
+class CSharpScript : public Script {
+
+ GDCLASS(CSharpScript, Script)
+
+ friend class CSharpInstance;
+ friend class CSharpLanguage;
+ friend class CSharpScriptDepSort;
+
+ bool tool;
+ bool valid;
+
+ bool builtin;
+
+ GDMonoClass *base;
+ GDMonoClass *native;
+ GDMonoClass *script_class;
+
+ Ref<CSharpScript> base_cache; // TODO what's this for?
+
+ Set<Object *> instances;
+
+ String source;
+ StringName name;
+
+ SelfList<CSharpScript> script_list;
+
+#ifdef TOOLS_ENABLED
+ List<PropertyInfo> exported_members_cache; // members_cache
+ Map<StringName, Variant> exported_members_defval_cache; // member_default_values_cache
+ Set<PlaceHolderScriptInstance *> placeholders;
+ bool source_changed_cache;
+ bool exports_invalidated;
+
+ void _update_exports_values(Map<StringName, Variant> &values, List<PropertyInfo> &propnames);
+ virtual void _placeholder_erased(PlaceHolderScriptInstance *p_placeholder);
+#endif
+
+#ifdef DEBUG_ENABLED
+ Map<ObjectID, List<Pair<StringName, Variant> > > pending_reload_state;
+#endif
+
+ Map<StringName, PropertyInfo> member_info;
+
+ void _clear();
+
+ bool _update_exports();
+ CSharpInstance *_create_instance(const Variant **p_args, int p_argcount, Object *p_owner, bool p_isref, Variant::CallError &r_error);
+ Variant _new(const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+
+ // Do not use unless you know what you are doing
+ friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
+ static Ref<CSharpScript> create_for_managed_type(GDMonoClass *p_class);
+
+protected:
+ static void _bind_methods();
+
+ Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ virtual void _resource_path_changed();
+
+public:
+ virtual bool can_instance() const;
+ virtual StringName get_instance_base_type() const;
+ virtual ScriptInstance *instance_create(Object *p_this);
+ virtual bool instance_has(const Object *p_this) const;
+
+ virtual bool has_source_code() const;
+ virtual String get_source_code() const;
+ virtual void set_source_code(const String &p_code);
+
+ virtual Error reload(bool p_keep_state = false);
+
+ /* TODO */ virtual bool has_script_signal(const StringName &p_signal) const { return false; }
+ /* TODO */ virtual void get_script_signal_list(List<MethodInfo> *r_signals) const {}
+
+ /* TODO */ virtual bool get_property_default_value(const StringName &p_property, Variant &r_value) const;
+ virtual void get_script_property_list(List<PropertyInfo> *p_list) const;
+ virtual void update_exports();
+
+ virtual bool is_tool() const { return tool; }
+ virtual Ref<Script> get_base_script() const;
+ virtual String get_node_type() const;
+ virtual ScriptLanguage *get_language() const;
+
+ /* TODO */ virtual void get_script_method_list(List<MethodInfo> *p_list) const {}
+ bool has_method(const StringName &p_method) const;
+ /* TODO */ MethodInfo get_method_info(const StringName &p_method) const { return MethodInfo(); }
+
+ virtual int get_member_line(const StringName &p_member) const;
+
+ Error load_source_code(const String &p_path);
+
+ StringName get_script_name() const;
+
+ CSharpScript();
+ ~CSharpScript();
+};
+
+class CSharpInstance : public ScriptInstance {
+
+ friend class CSharpScript;
+ friend class CSharpLanguage;
+ Object *owner;
+ Ref<CSharpScript> script;
+ Ref<MonoGCHandle> gchandle;
+ bool base_ref;
+ bool ref_dying;
+
+ void _ml_call_reversed(GDMonoClass *klass, const StringName &p_method, const Variant **p_args, int p_argcount);
+
+ void _reference_owner_unsafe();
+ void _unreference_owner_unsafe();
+
+ // Do not use unless you know what you are doing
+ friend void GDMonoInternals::tie_managed_to_unmanaged(MonoObject *, Object *);
+ static CSharpInstance *create_for_managed_type(Object *p_owner, CSharpScript *p_script, const Ref<MonoGCHandle> &p_gchandle);
+
+public:
+ MonoObject *get_mono_object() const;
+
+ virtual bool set(const StringName &p_name, const Variant &p_value);
+ virtual bool get(const StringName &p_name, Variant &r_ret) const;
+ virtual void get_property_list(List<PropertyInfo> *p_properties) const;
+ virtual Variant::Type get_property_type(const StringName &p_name, bool *r_is_valid) const;
+
+ /* TODO */ virtual void get_method_list(List<MethodInfo> *p_list) const {}
+ virtual bool has_method(const StringName &p_method) const;
+ virtual Variant call(const StringName &p_method, const Variant **p_args, int p_argcount, Variant::CallError &r_error);
+ virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount);
+ virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount);
+
+ void mono_object_disposed();
+
+ void refcount_incremented();
+ bool refcount_decremented();
+
+ RPCMode get_rpc_mode(const StringName &p_method) const;
+ RPCMode get_rset_mode(const StringName &p_variable) const;
+
+ virtual void notification(int p_notification);
+
+ virtual Ref<Script> get_script() const;
+
+ virtual ScriptLanguage *get_language();
+
+ CSharpInstance();
+ ~CSharpInstance();
+};
+
+class CSharpLanguage : public ScriptLanguage {
+
+ friend class CSharpScript;
+ friend class CSharpInstance;
+
+ static CSharpLanguage *singleton;
+
+ GDMono *gdmono;
+ SelfList<CSharpScript>::List script_list;
+
+ Mutex *lock;
+ Mutex *script_bind_lock;
+
+ Map<Ref<CSharpScript>, Map<ObjectID, List<Pair<StringName, Variant> > > > to_reload;
+
+ Map<Object *, Ref<MonoGCHandle> > gchandle_bindings;
+
+ struct StringNameCache {
+
+ StringName _awaited_signal_callback;
+ StringName _set;
+ StringName _get;
+ StringName _notification;
+ StringName dotctor; // .ctor
+
+ StringNameCache();
+ };
+
+ StringNameCache string_names;
+
+ int lang_idx;
+
+public:
+ _FORCE_INLINE_ int get_language_index() { return lang_idx; }
+ void set_language_index(int p_idx);
+
+ _FORCE_INLINE_ static CSharpLanguage *get_singleton() { return singleton; }
+
+ bool debug_break(const String &p_error, bool p_allow_continue = true);
+ bool debug_break_parse(const String &p_file, int p_line, const String &p_error);
+
+#ifdef TOOLS_ENABLED
+ void reload_assemblies_if_needed(bool p_soft_reload);
+#endif
+
+ virtual String get_name() const;
+
+ /* LANGUAGE FUNCTIONS */
+ virtual String get_type() const;
+ virtual String get_extension() const;
+ virtual Error execute_file(const String &p_path);
+ virtual void init();
+ virtual void finish();
+
+ /* EDITOR FUNCTIONS */
+ virtual void get_reserved_words(List<String> *p_words) const;
+ virtual void get_comment_delimiters(List<String> *p_delimiters) const;
+ virtual void get_string_delimiters(List<String> *p_delimiters) const;
+ virtual Ref<Script> get_template(const String &p_class_name, const String &p_base_class_name) const;
+ /* TODO */ virtual bool validate(const String &p_script, int &r_line_error, int &r_col_error, String &r_test_error, const String &p_path, List<String> *r_functions) const { return true; }
+ virtual Script *create_script() const;
+ virtual bool has_named_classes() const;
+ /* TODO? */ virtual int find_function(const String &p_function, const String &p_code) const { return -1; }
+ virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
+ /* TODO? */ Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; }
+ /* TODO? */ virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const {}
+ /* TODO */ virtual void add_global_constant(const StringName &p_variable, const Variant &p_value) {}
+
+ /* DEBUGGER FUNCTIONS */
+ /* TODO */ virtual String debug_get_error() const { return ""; }
+ /* TODO */ virtual int debug_get_stack_level_count() const { return 1; }
+ /* TODO */ virtual int debug_get_stack_level_line(int p_level) const { return 1; }
+ /* TODO */ virtual String debug_get_stack_level_function(int p_level) const { return ""; }
+ /* TODO */ virtual String debug_get_stack_level_source(int p_level) const { return ""; }
+ /* TODO */ virtual void debug_get_stack_level_locals(int p_level, List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
+ /* TODO */ virtual void debug_get_stack_level_members(int p_level, List<String> *p_members, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
+ /* TODO */ virtual void debug_get_globals(List<String> *p_locals, List<Variant> *p_values, int p_max_subitems, int p_max_depth) {}
+ /* TODO */ virtual String debug_parse_stack_level_expression(int p_level, const String &p_expression, int p_max_subitems, int p_max_depth) { return ""; }
+ /* TODO */ virtual Vector<StackInfo> debug_get_current_stack_info() { return Vector<StackInfo>(); }
+
+ /* PROFILING FUNCTIONS */
+ /* TODO */ virtual void profiling_start() {}
+ /* TODO */ virtual void profiling_stop() {}
+ /* TODO */ virtual int profiling_get_accumulated_data(ProfilingInfo *p_info_arr, int p_info_max) { return 0; }
+ /* TODO */ virtual int profiling_get_frame_data(ProfilingInfo *p_info_arr, int p_info_max) { return 0; }
+
+ virtual void frame();
+
+ /* TODO? */ virtual void get_public_functions(List<MethodInfo> *p_functions) const {}
+ /* TODO? */ virtual void get_public_constants(List<Pair<String, Variant> > *p_constants) const {}
+
+ virtual void reload_all_scripts();
+ virtual void reload_tool_script(const Ref<Script> &p_script, bool p_soft_reload);
+
+ /* LOADER FUNCTIONS */
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+
+#ifdef TOOLS_ENABLED
+ virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col);
+ virtual bool overrides_external_editor();
+#endif
+
+ /* THREAD ATTACHING */
+ virtual void thread_enter();
+ virtual void thread_exit();
+
+ // Don't use these. I'm watching you
+ virtual void *alloc_instance_binding_data(Object *p_object);
+ virtual void free_instance_binding_data(void *p_data);
+
+ CSharpLanguage();
+ ~CSharpLanguage();
+};
+
+class ResourceFormatLoaderCSharpScript : public ResourceFormatLoader {
+public:
+ virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL);
+ virtual void get_recognized_extensions(List<String> *p_extensions) const;
+ virtual bool handles_type(const String &p_type) const;
+ virtual String get_resource_type(const String &p_path) const;
+};
+
+class ResourceFormatSaverCSharpScript : public ResourceFormatSaver {
+public:
+ virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
+ virtual void get_recognized_extensions(const RES &p_resource, List<String> *p_extensions) const;
+ virtual bool recognize(const RES &p_resource) const;
+};
+
+#endif // CSHARP_SCRIPT_H
diff --git a/modules/mono/doc_classes/@C#.xml b/modules/mono/doc_classes/@C#.xml
new file mode 100644
index 0000000000..487ba9835f
--- /dev/null
+++ b/modules/mono/doc_classes/@C#.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="@C#" category="Core" version="3.0.alpha.custom_build">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/modules/mono/doc_classes/CSharpScript.xml b/modules/mono/doc_classes/CSharpScript.xml
new file mode 100644
index 0000000000..5f21c9774d
--- /dev/null
+++ b/modules/mono/doc_classes/CSharpScript.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="CSharpScript" inherits="Script" category="Core" version="3.0.alpha.custom_build">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="new" qualifiers="vararg">
+ <return type="Object">
+ </return>
+ <description>
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml
new file mode 100644
index 0000000000..e7e06ddd8f
--- /dev/null
+++ b/modules/mono/doc_classes/GodotSharp.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<class name="GodotSharp" inherits="Object" category="Core" version="3.0.alpha.custom_build">
+ <brief_description>
+ </brief_description>
+ <description>
+ </description>
+ <tutorials>
+ </tutorials>
+ <demos>
+ </demos>
+ <methods>
+ <method name="attach_thread">
+ <return type="void">
+ </return>
+ <description>
+ Attaches the current thread to the mono runtime.
+ </description>
+ </method>
+ <method name="detach_thread">
+ <return type="void">
+ </return>
+ <description>
+ Detaches the current thread from the mono runtime.
+ </description>
+ </method>
+ <method name="is_domain_loaded">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether the scripts domain is loaded.
+ </description>
+ </method>
+ <method name="is_finalizing_domain">
+ <return type="bool">
+ </return>
+ <description>
+ Returns whether the scripts domain is being finalized.
+ </description>
+ </method>
+ </methods>
+ <constants>
+ </constants>
+</class>
diff --git a/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
new file mode 100644
index 0000000000..256e64ddde
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Build/BuildSystem.cs
@@ -0,0 +1,335 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Security;
+using Microsoft.Build.Framework;
+
+namespace GodotSharpTools.Build
+{
+ public class BuildInstance : IDisposable
+ {
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static void godot_icall_BuildInstance_ExitCallback(string solution, string config, int exitCode);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static string godot_icall_BuildInstance_get_MSBuildPath();
+
+ private static string MSBuildPath
+ {
+ get { return godot_icall_BuildInstance_get_MSBuildPath(); }
+ }
+
+ private string solution;
+ private string config;
+
+ private Process process;
+
+ private int exitCode;
+ public int ExitCode { get { return exitCode; } }
+
+ public bool IsRunning { get { return process != null && !process.HasExited; } }
+
+ public BuildInstance(string solution, string config)
+ {
+ this.solution = solution;
+ this.config = config;
+ }
+
+ public bool Build(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
+ {
+ string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customProperties);
+
+ ProcessStartInfo startInfo = new ProcessStartInfo(MSBuildPath, compilerArgs);
+
+ // No console output, thanks
+ startInfo.RedirectStandardOutput = true;
+ startInfo.RedirectStandardError = true;
+ startInfo.UseShellExecute = false;
+
+ // Needed when running from Developer Command Prompt for VS
+ RemovePlatformVariable(startInfo.EnvironmentVariables);
+
+ using (Process process = new Process())
+ {
+ process.StartInfo = startInfo;
+
+ process.Start();
+
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
+
+ process.WaitForExit();
+
+ exitCode = process.ExitCode;
+ }
+
+ return true;
+ }
+
+ public bool BuildAsync(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties = null)
+ {
+ if (process != null)
+ throw new InvalidOperationException("Already in use");
+
+ string compilerArgs = BuildArguments(loggerAssemblyPath, loggerOutputDir, customProperties);
+
+ ProcessStartInfo startInfo = new ProcessStartInfo("msbuild", compilerArgs);
+
+ // No console output, thanks
+ startInfo.RedirectStandardOutput = true;
+ startInfo.RedirectStandardError = true;
+ startInfo.UseShellExecute = false;
+
+ // Needed when running from Developer Command Prompt for VS
+ RemovePlatformVariable(startInfo.EnvironmentVariables);
+
+ process = new Process();
+ process.StartInfo = startInfo;
+ process.EnableRaisingEvents = true;
+ process.Exited += new EventHandler(BuildProcess_Exited);
+
+ process.Start();
+
+ return true;
+ }
+
+ private string BuildArguments(string loggerAssemblyPath, string loggerOutputDir, string[] customProperties)
+ {
+ string arguments = string.Format("{0} /v:normal /t:Build /p:{1} /l:{2},{3};{4}",
+ solution,
+ "Configuration=" + config,
+ typeof(GodotBuildLogger).FullName,
+ loggerAssemblyPath,
+ loggerOutputDir
+ );
+
+ if (customProperties != null)
+ {
+ foreach (string customProperty in customProperties)
+ {
+ arguments += " /p:" + customProperty;
+ }
+ }
+
+ return arguments;
+ }
+
+ private void RemovePlatformVariable(StringDictionary environmentVariables)
+ {
+ // EnvironmentVariables is case sensitive? Seriously?
+
+ List<string> platformEnvironmentVariables = new List<string>();
+
+ foreach (string env in environmentVariables.Keys)
+ {
+ if (env.ToUpper() == "PLATFORM")
+ platformEnvironmentVariables.Add(env);
+ }
+
+ foreach (string env in platformEnvironmentVariables)
+ environmentVariables.Remove(env);
+ }
+
+ private void BuildProcess_Exited(object sender, System.EventArgs e)
+ {
+ exitCode = process.ExitCode;
+
+ godot_icall_BuildInstance_ExitCallback(solution, config, exitCode);
+
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ if (process != null)
+ {
+ process.Dispose();
+ process = null;
+ }
+ }
+ }
+
+ public class GodotBuildLogger : ILogger
+ {
+ public string Parameters { get; set; }
+ public LoggerVerbosity Verbosity { get; set; }
+
+ public void Initialize(IEventSource eventSource)
+ {
+ if (null == Parameters)
+ throw new LoggerException("Log directory was not set.");
+
+ string[] parameters = Parameters.Split(';');
+
+ string logDir = parameters[0];
+
+ if (String.IsNullOrEmpty(logDir))
+ throw new LoggerException("Log directory was not set.");
+
+ if (parameters.Length > 1)
+ throw new LoggerException("Too many parameters passed.");
+
+ string logFile = Path.Combine(logDir, "msbuild_log.txt");
+ string issuesFile = Path.Combine(logDir, "msbuild_issues.csv");
+
+ try
+ {
+ if (!Directory.Exists(logDir))
+ Directory.CreateDirectory(logDir);
+
+ this.logStreamWriter = new StreamWriter(logFile);
+ this.issuesStreamWriter = new StreamWriter(issuesFile);
+ }
+ catch (Exception ex)
+ {
+ if
+ (
+ ex is UnauthorizedAccessException
+ || ex is ArgumentNullException
+ || ex is PathTooLongException
+ || ex is DirectoryNotFoundException
+ || ex is NotSupportedException
+ || ex is ArgumentException
+ || ex is SecurityException
+ || ex is IOException
+ )
+ {
+ throw new LoggerException("Failed to create log file: " + ex.Message);
+ }
+ else
+ {
+ // Unexpected failure
+ throw;
+ }
+ }
+
+ eventSource.ProjectStarted += new ProjectStartedEventHandler(eventSource_ProjectStarted);
+ eventSource.TaskStarted += new TaskStartedEventHandler(eventSource_TaskStarted);
+ eventSource.MessageRaised += new BuildMessageEventHandler(eventSource_MessageRaised);
+ eventSource.WarningRaised += new BuildWarningEventHandler(eventSource_WarningRaised);
+ eventSource.ErrorRaised += new BuildErrorEventHandler(eventSource_ErrorRaised);
+ eventSource.ProjectFinished += new ProjectFinishedEventHandler(eventSource_ProjectFinished);
+ }
+
+ void eventSource_ErrorRaised(object sender, BuildErrorEventArgs e)
+ {
+ string line = String.Format("{0}({1},{2}): error {3}: {4}", e.File, e.LineNumber, e.ColumnNumber, e.Code, e.Message);
+
+ if (e.ProjectFile.Length > 0)
+ line += string.Format(" [{0}]", e.ProjectFile);
+
+ WriteLine(line);
+
+ string errorLine = String.Format(@"error,{0},{1},{2},{3},{4},{5}",
+ e.File.CsvEscape(), e.LineNumber, e.ColumnNumber,
+ e.Code.CsvEscape(), e.Message.CsvEscape(), e.ProjectFile.CsvEscape());
+ issuesStreamWriter.WriteLine(errorLine);
+ }
+
+ void eventSource_WarningRaised(object sender, BuildWarningEventArgs e)
+ {
+ string line = String.Format("{0}({1},{2}): warning {3}: {4}", e.File, e.LineNumber, e.ColumnNumber, e.Code, e.Message, e.ProjectFile);
+
+ if (e.ProjectFile != null && e.ProjectFile.Length > 0)
+ line += string.Format(" [{0}]", e.ProjectFile);
+
+ WriteLine(line);
+
+ string warningLine = String.Format(@"warning,{0},{1},{2},{3},{4},{5}",
+ e.File.CsvEscape(), e.LineNumber, e.ColumnNumber,
+ e.Code.CsvEscape(), e.Message.CsvEscape(), e.ProjectFile != null ? e.ProjectFile.CsvEscape() : string.Empty);
+ issuesStreamWriter.WriteLine(warningLine);
+ }
+
+ void eventSource_MessageRaised(object sender, BuildMessageEventArgs e)
+ {
+ // BuildMessageEventArgs adds Importance to BuildEventArgs
+ // Let's take account of the verbosity setting we've been passed in deciding whether to log the message
+ if ((e.Importance == MessageImportance.High && IsVerbosityAtLeast(LoggerVerbosity.Minimal))
+ || (e.Importance == MessageImportance.Normal && IsVerbosityAtLeast(LoggerVerbosity.Normal))
+ || (e.Importance == MessageImportance.Low && IsVerbosityAtLeast(LoggerVerbosity.Detailed))
+ )
+ {
+ WriteLineWithSenderAndMessage(String.Empty, e);
+ }
+ }
+
+ void eventSource_TaskStarted(object sender, TaskStartedEventArgs e)
+ {
+ // TaskStartedEventArgs adds ProjectFile, TaskFile, TaskName
+ // To keep this log clean, this logger will ignore these events.
+ }
+
+ void eventSource_ProjectStarted(object sender, ProjectStartedEventArgs e)
+ {
+ WriteLine(e.Message);
+ indent++;
+ }
+
+ void eventSource_ProjectFinished(object sender, ProjectFinishedEventArgs e)
+ {
+ indent--;
+ WriteLine(e.Message);
+ }
+
+ /// <summary>
+ /// Write a line to the log, adding the SenderName
+ /// </summary>
+ private void WriteLineWithSender(string line, BuildEventArgs e)
+ {
+ if (0 == String.Compare(e.SenderName, "MSBuild", true /*ignore case*/))
+ {
+ // Well, if the sender name is MSBuild, let's leave it out for prettiness
+ WriteLine(line);
+ }
+ else
+ {
+ WriteLine(e.SenderName + ": " + line);
+ }
+ }
+
+ /// <summary>
+ /// Write a line to the log, adding the SenderName and Message
+ /// (these parameters are on all MSBuild event argument objects)
+ /// </summary>
+ private void WriteLineWithSenderAndMessage(string line, BuildEventArgs e)
+ {
+ if (0 == String.Compare(e.SenderName, "MSBuild", true /*ignore case*/))
+ {
+ // Well, if the sender name is MSBuild, let's leave it out for prettiness
+ WriteLine(line + e.Message);
+ }
+ else
+ {
+ WriteLine(e.SenderName + ": " + line + e.Message);
+ }
+ }
+
+ private void WriteLine(string line)
+ {
+ for (int i = indent; i > 0; i--)
+ {
+ logStreamWriter.Write("\t");
+ }
+ logStreamWriter.WriteLine(line);
+ }
+
+ public void Shutdown()
+ {
+ logStreamWriter.Close();
+ issuesStreamWriter.Close();
+ }
+
+ public bool IsVerbosityAtLeast(LoggerVerbosity checkVerbosity)
+ {
+ return this.Verbosity >= checkVerbosity;
+ }
+
+ private StreamWriter logStreamWriter;
+ private StreamWriter issuesStreamWriter;
+ private int indent;
+ }
+}
diff --git a/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs b/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs
new file mode 100644
index 0000000000..303be3b732
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Editor/MonoDevelopInstance.cs
@@ -0,0 +1,58 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace GodotSharpTools.Editor
+{
+ public class MonoDevelopInstance
+ {
+ private Process process;
+ private string solutionFile;
+
+ public void Execute(string[] files)
+ {
+ bool newWindow = process == null || process.HasExited;
+
+ List<string> args = new List<string>();
+
+ args.Add("--ipc-tcp");
+
+ if (newWindow)
+ args.Add("\"" + Path.GetFullPath(solutionFile) + "\"");
+
+ foreach (var file in files)
+ {
+ int semicolonIndex = file.IndexOf(';');
+
+ string filePath = semicolonIndex < 0 ? file : file.Substring(0, semicolonIndex);
+ string cursor = semicolonIndex < 0 ? string.Empty : file.Substring(semicolonIndex);
+
+ args.Add("\"" + Path.GetFullPath(filePath.NormalizePath()) + cursor + "\"");
+ }
+
+ if (newWindow)
+ {
+ ProcessStartInfo startInfo = new ProcessStartInfo(MonoDevelopFile, string.Join(" ", args));
+ process = Process.Start(startInfo);
+ }
+ else
+ {
+ Process.Start(MonoDevelopFile, string.Join(" ", args));
+ }
+ }
+
+ public MonoDevelopInstance(string solutionFile)
+ {
+ this.solutionFile = solutionFile;
+ }
+
+ private static string MonoDevelopFile
+ {
+ get
+ {
+ return "monodevelop";
+ }
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
new file mode 100644
index 0000000000..981083a3c2
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.csproj
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>GodotSharpTools</RootNamespace>
+ <AssemblyName>GodotSharpTools</AssemblyName>
+ <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="Microsoft.Build" />
+ <Reference Include="Microsoft.Build.Framework" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="StringExtensions.cs" />
+ <Compile Include="Build\BuildSystem.cs" />
+ <Compile Include="Editor\MonoDevelopInstance.cs" />
+ <Compile Include="Project\ProjectExtensions.cs" />
+ <Compile Include="Project\ProjectGenerator.cs" />
+ <Compile Include="Project\ProjectUtils.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.sln b/modules/mono/editor/GodotSharpTools/GodotSharpTools.sln
new file mode 100644
index 0000000000..7eabcdff5d
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.sln
@@ -0,0 +1,17 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GodotSharpTools", "GodotSharpTools.csproj", "{A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A8CDAD94-C6D4-4B19-A7E7-76C53CC92984}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+EndGlobal
diff --git a/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs b/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs
new file mode 100644
index 0000000000..0cbafdc20d
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/GodotSharpTools.userprefs
@@ -0,0 +1,14 @@
+<Properties StartupItem="GodotSharpTools.csproj">
+ <MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
+ <MonoDevelop.Ide.Workbench ActiveDocument="Build/BuildSystem.cs">
+ <Files>
+ <File FileName="Build/ProjectExtensions.cs" Line="1" Column="1" />
+ <File FileName="Build/ProjectGenerator.cs" Line="1" Column="1" />
+ <File FileName="Build/BuildSystem.cs" Line="37" Column="14" />
+ </Files>
+ </MonoDevelop.Ide.Workbench>
+ <MonoDevelop.Ide.DebuggingService.Breakpoints>
+ <BreakpointStore />
+ </MonoDevelop.Ide.DebuggingService.Breakpoints>
+ <MonoDevelop.Ide.DebuggingService.PinnedWatches />
+</Properties> \ No newline at end of file
diff --git a/modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs b/modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs
new file mode 100644
index 0000000000..6a97731539
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Project/ProjectExtensions.cs
@@ -0,0 +1,49 @@
+using System;
+using Microsoft.Build.Construction;
+
+namespace GodotSharpTools.Project
+{
+ public static class ProjectExtensions
+ {
+ public static bool HasItem(this ProjectRootElement root, string itemType, string include)
+ {
+ string includeNormalized = include.NormalizePath();
+
+ foreach (var itemGroup in root.ItemGroups)
+ {
+ if (itemGroup.Condition.Length != 0)
+ continue;
+
+ foreach (var item in itemGroup.Items)
+ {
+ if (item.ItemType == itemType)
+ {
+ if (item.Include.NormalizePath() == includeNormalized)
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ public static void AddItemChecked(this ProjectRootElement root, string itemType, string include)
+ {
+ if (!root.HasItem(itemType, include))
+ {
+ root.AddItem(itemType, include);
+ }
+ }
+
+ public static Guid GetGuid(this ProjectRootElement root)
+ {
+ foreach (var property in root.Properties)
+ {
+ if (property.Name == "ProjectGuid")
+ return Guid.Parse(property.Value);
+ }
+
+ return Guid.Empty;
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs b/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs
new file mode 100644
index 0000000000..6bf54a0156
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Project/ProjectGenerator.cs
@@ -0,0 +1,216 @@
+using System;
+using System.IO;
+using Microsoft.Build.Construction;
+
+namespace GodotSharpTools.Project
+{
+ public static class ProjectGenerator
+ {
+ public static string GenCoreApiProject(string dir, string[] compileItems)
+ {
+ string path = Path.Combine(dir, CoreApiProject + ".csproj");
+
+ ProjectPropertyGroupElement mainGroup;
+ var root = CreateLibraryProject(CoreApiProject, out mainGroup);
+
+ mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
+ mainGroup.SetProperty("RootNamespace", "Godot");
+
+ GenAssemblyInfoFile(root, dir, CoreApiProject,
+ new string[] { "[assembly: InternalsVisibleTo(\"" + EditorApiProject + "\")]" },
+ new string[] { "System.Runtime.CompilerServices" });
+
+ foreach (var item in compileItems)
+ {
+ root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
+ }
+
+ root.Save(path);
+
+ return root.GetGuid().ToString().ToUpper();
+ }
+
+ public static string GenEditorApiProject(string dir, string coreApiHintPath, string[] compileItems)
+ {
+ string path = Path.Combine(dir, EditorApiProject + ".csproj");
+
+ ProjectPropertyGroupElement mainGroup;
+ var root = CreateLibraryProject(EditorApiProject, out mainGroup);
+
+ mainGroup.AddProperty("DocumentationFile", Path.Combine("$(OutputPath)", "$(AssemblyName).xml"));
+ mainGroup.SetProperty("RootNamespace", "Godot");
+
+ GenAssemblyInfoFile(root, dir, EditorApiProject);
+
+ foreach (var item in compileItems)
+ {
+ root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
+ }
+
+ var coreApiRef = root.AddItem("Reference", CoreApiProject);
+ coreApiRef.AddMetadata("HintPath", coreApiHintPath);
+ coreApiRef.AddMetadata("Private", "False");
+
+ root.Save(path);
+
+ return root.GetGuid().ToString().ToUpper();
+ }
+
+ public static string GenGameProject(string dir, string name, string[] compileItems)
+ {
+ string path = Path.Combine(dir, name + ".csproj");
+
+ ProjectPropertyGroupElement mainGroup;
+ var root = CreateLibraryProject(name, out mainGroup);
+
+ mainGroup.SetProperty("OutputPath", Path.Combine(".mono", "temp", "bin", "$(Configuration)"));
+ mainGroup.SetProperty("BaseIntermediateOutputPath", Path.Combine(".mono", "temp", "obj"));
+ mainGroup.SetProperty("IntermediateOutputPath", Path.Combine("$(BaseIntermediateOutputPath)", "$(Configuration)"));
+
+ var toolsGroup = root.AddPropertyGroup();
+ toolsGroup.Condition = " '$(Configuration)|$(Platform)' == 'Tools|AnyCPU' ";
+ toolsGroup.AddProperty("DebugSymbols", "true");
+ toolsGroup.AddProperty("DebugType", "full");
+ toolsGroup.AddProperty("Optimize", "false");
+ toolsGroup.AddProperty("DefineConstants", "DEBUG;TOOLS;");
+ toolsGroup.AddProperty("ErrorReport", "prompt");
+ toolsGroup.AddProperty("WarningLevel", "4");
+ toolsGroup.AddProperty("ConsolePause", "false");
+
+ var coreApiRef = root.AddItem("Reference", CoreApiProject);
+ coreApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", CoreApiProject + ".dll"));
+ coreApiRef.AddMetadata("Private", "False");
+
+ var editorApiRef = root.AddItem("Reference", EditorApiProject);
+ editorApiRef.Condition = " '$(Configuration)' == 'Tools' ";
+ editorApiRef.AddMetadata("HintPath", Path.Combine("$(ProjectDir)", ".mono", "assemblies", EditorApiProject + ".dll"));
+ editorApiRef.AddMetadata("Private", "False");
+
+ GenAssemblyInfoFile(root, dir, name);
+
+ foreach (var item in compileItems)
+ {
+ root.AddItem("Compile", item.RelativeToPath(dir).Replace("/", "\\"));
+ }
+
+ root.Save(path);
+
+ return root.GetGuid().ToString().ToUpper();
+ }
+
+ public static void GenAssemblyInfoFile(ProjectRootElement root, string dir, string name, string[] assemblyLines = null, string[] usingDirectives = null)
+ {
+
+ string propertiesDir = Path.Combine(dir, "Properties");
+ if (!Directory.Exists(propertiesDir))
+ Directory.CreateDirectory(propertiesDir);
+
+ string usingDirectivesText = string.Empty;
+
+ if (usingDirectives != null)
+ {
+ foreach (var usingDirective in usingDirectives)
+ usingDirectivesText += "\nusing " + usingDirective + ";";
+ }
+
+ string assemblyLinesText = string.Empty;
+
+ if (assemblyLines != null)
+ {
+ foreach (var assemblyLine in assemblyLines)
+ assemblyLinesText += string.Join("\n", assemblyLines) + "\n";
+ }
+
+ string content = string.Format(assemblyInfoTemplate, usingDirectivesText, name, assemblyLinesText);
+
+ string assemblyInfoFile = Path.Combine(propertiesDir, "AssemblyInfo.cs");
+
+ File.WriteAllText(assemblyInfoFile, content);
+
+ root.AddItem("Compile", assemblyInfoFile.RelativeToPath(dir).Replace("/", "\\"));
+ }
+
+ public static ProjectRootElement CreateLibraryProject(string name, out ProjectPropertyGroupElement mainGroup)
+ {
+ var root = ProjectRootElement.Create();
+ root.DefaultTargets = "Build";
+
+ mainGroup = root.AddPropertyGroup();
+ mainGroup.AddProperty("Configuration", "Debug").Condition = " '$(Configuration)' == '' ";
+ mainGroup.AddProperty("Platform", "AnyCPU").Condition = " '$(Platform)' == '' ";
+ mainGroup.AddProperty("ProjectGuid", "{" + Guid.NewGuid().ToString().ToUpper() + "}");
+ mainGroup.AddProperty("OutputType", "Library");
+ mainGroup.AddProperty("OutputPath", Path.Combine("bin", "$(Configuration)"));
+ mainGroup.AddProperty("RootNamespace", name);
+ mainGroup.AddProperty("AssemblyName", name);
+ mainGroup.AddProperty("TargetFrameworkVersion", "v4.5");
+
+ var debugGroup = root.AddPropertyGroup();
+ debugGroup.Condition = " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ";
+ debugGroup.AddProperty("DebugSymbols", "true");
+ debugGroup.AddProperty("DebugType", "full");
+ debugGroup.AddProperty("Optimize", "false");
+ debugGroup.AddProperty("DefineConstants", "DEBUG;");
+ debugGroup.AddProperty("ErrorReport", "prompt");
+ debugGroup.AddProperty("WarningLevel", "4");
+ debugGroup.AddProperty("ConsolePause", "false");
+
+ var releaseGroup = root.AddPropertyGroup();
+ releaseGroup.Condition = " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ";
+ releaseGroup.AddProperty("DebugType", "full");
+ releaseGroup.AddProperty("Optimize", "true");
+ releaseGroup.AddProperty("ErrorReport", "prompt");
+ releaseGroup.AddProperty("WarningLevel", "4");
+ releaseGroup.AddProperty("ConsolePause", "false");
+
+ // References
+ var referenceGroup = root.AddItemGroup();
+ referenceGroup.AddItem("Reference", "System");
+
+ root.AddImport(Path.Combine("$(MSBuildBinPath)", "Microsoft.CSharp.targets").Replace("/", "\\"));
+
+ return root;
+ }
+
+ private static void AddItems(ProjectRootElement elem, string groupName, params string[] items)
+ {
+ var group = elem.AddItemGroup();
+
+ foreach (var item in items)
+ {
+ group.AddItem(groupName, item);
+ }
+ }
+
+ public const string CoreApiProject = "GodotSharp";
+ public const string EditorApiProject = "GodotSharpEditor";
+
+ private const string assemblyInfoTemplate =
+@"using System.Reflection;{0}
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle(""{1}"")]
+[assembly: AssemblyDescription("""")]
+[assembly: AssemblyConfiguration("""")]
+[assembly: AssemblyCompany("""")]
+[assembly: AssemblyProduct("""")]
+[assembly: AssemblyCopyright("""")]
+[assembly: AssemblyTrademark("""")]
+[assembly: AssemblyCulture("""")]
+
+// The assembly version has the format ""{{Major}}.{{Minor}}.{{Build}}.{{Revision}}"".
+// The form ""{{Major}}.{{Minor}}.*"" will automatically update the build and revision,
+// and ""{{Major}}.{{Minor}}.{{Build}}.*"" will update just the revision.
+
+[assembly: AssemblyVersion(""1.0.*"")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("""")]
+{2}";
+ }
+}
diff --git a/modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs b/modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs
new file mode 100644
index 0000000000..a50b4fb064
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Project/ProjectUtils.cs
@@ -0,0 +1,17 @@
+using System;
+using System.IO;
+using Microsoft.Build.Construction;
+
+namespace GodotSharpTools.Project
+{
+ public static class ProjectUtils
+ {
+ public static void AddItemToProjectChecked(string projectPath, string itemType, string include)
+ {
+ var dir = Directory.GetParent(projectPath).FullName;
+ var root = ProjectRootElement.Open(projectPath);
+ root.AddItemChecked(itemType, include.RelativeToPath(dir).Replace("/", "\\"));
+ root.Save();
+ }
+ }
+}
diff --git a/modules/mono/editor/GodotSharpTools/Properties/AssemblyInfo.cs b/modules/mono/editor/GodotSharpTools/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000000..7115d8fc71
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/Properties/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following attributes.
+// Change them to the values specific to your project.
+
+[assembly: AssemblyTitle("GodotSharpTools")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("ignacio")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
+// The form "{Major}.{Minor}.*" will automatically update the build and revision,
+// and "{Major}.{Minor}.{Build}.*" will update just the revision.
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes are used to specify the signing key for the assembly,
+// if desired. See the Mono documentation for more information about signing.
+
+//[assembly: AssemblyDelaySign(false)]
+//[assembly: AssemblyKeyFile("")]
+
diff --git a/modules/mono/editor/GodotSharpTools/StringExtensions.cs b/modules/mono/editor/GodotSharpTools/StringExtensions.cs
new file mode 100644
index 0000000000..b66c86f8ce
--- /dev/null
+++ b/modules/mono/editor/GodotSharpTools/StringExtensions.cs
@@ -0,0 +1,52 @@
+using System;
+using System.IO;
+
+namespace GodotSharpTools
+{
+ public static class StringExtensions
+ {
+ public static string RelativeToPath(this string path, string dir)
+ {
+ // Make sure the directory ends with a path separator
+ dir = Path.Combine(dir, " ").TrimEnd();
+
+ if (Path.DirectorySeparatorChar == '\\')
+ dir = dir.Replace("/", "\\") + "\\";
+
+ Uri fullPath = new Uri(Path.GetFullPath(path), UriKind.Absolute);
+ Uri relRoot = new Uri(Path.GetFullPath(dir), UriKind.Absolute);
+
+ return relRoot.MakeRelativeUri(fullPath).ToString();
+ }
+
+ public static string NormalizePath(this string path)
+ {
+ bool rooted = path.IsAbsolutePath();
+
+ path = path.Replace('\\', '/');
+
+ string[] parts = path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+
+ path = string.Join(Path.DirectorySeparatorChar.ToString(), parts).Trim();
+
+ return rooted ? Path.DirectorySeparatorChar.ToString() + path : path;
+ }
+
+ private static readonly string driveRoot = Path.GetPathRoot(Environment.CurrentDirectory);
+
+ public static bool IsAbsolutePath(this string path)
+ {
+ return path.StartsWith("/") || path.StartsWith("\\") || path.StartsWith(driveRoot);
+ }
+
+ public static string CsvEscape(this string value, char delimiter = ',')
+ {
+ bool hasSpecialChar = value.IndexOfAny(new char[] { '\"', '\n', '\r', delimiter }) != -1;
+
+ if (hasSpecialChar)
+ return "\"" + value.Replace("\"", "\"\"") + "\"";
+
+ return value;
+ }
+ }
+}
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp
new file mode 100644
index 0000000000..123f00ea10
--- /dev/null
+++ b/modules/mono/editor/bindings_generator.cpp
@@ -0,0 +1,2151 @@
+/*************************************************************************/
+/* bindings_generator.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "bindings_generator.h"
+
+#ifdef DEBUG_METHODS_ENABLED
+
+#include "global_constants.h"
+#include "io/compression.h"
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "os/os.h"
+#include "project_settings.h"
+#include "ucaps.h"
+
+#include "../glue/cs_compressed.gen.h"
+#include "../godotsharp_defs.h"
+#include "../mono_gd/gd_mono_marshal.h"
+#include "../utils/path_utils.h"
+#include "../utils/string_utils.h"
+#include "csharp_project.h"
+#include "net_solution.h"
+
+#define CS_INDENT " "
+
+#define INDENT1 CS_INDENT
+#define INDENT2 INDENT1 INDENT1
+#define INDENT3 INDENT2 INDENT1
+#define INDENT4 INDENT3 INDENT1
+#define INDENT5 INDENT4 INDENT1
+
+#define MEMBER_BEGIN "\n" INDENT2
+
+#define OPEN_BLOCK "{\n"
+#define CLOSE_BLOCK "}\n"
+
+#define OPEN_BLOCK_L2 INDENT2 OPEN_BLOCK INDENT3
+#define OPEN_BLOCK_L3 INDENT3 OPEN_BLOCK INDENT4
+#define OPEN_BLOCK_L4 INDENT4 OPEN_BLOCK INDENT5
+#define CLOSE_BLOCK_L2 INDENT2 CLOSE_BLOCK
+#define CLOSE_BLOCK_L3 INDENT3 CLOSE_BLOCK
+#define CLOSE_BLOCK_L4 INDENT4 CLOSE_BLOCK
+
+#define LOCAL_RET "ret"
+
+#define CS_CLASS_NATIVECALLS "NativeCalls"
+#define CS_CLASS_NATIVECALLS_EDITOR "EditorNativeCalls"
+#define CS_FIELD_MEMORYOWN "memoryOwn"
+#define CS_PARAM_METHODBIND "method"
+#define CS_PARAM_INSTANCE "ptr"
+#define CS_SMETHOD_GETINSTANCE "GetPtr"
+#define CS_FIELD_SINGLETON "instance"
+#define CS_PROP_SINGLETON "Instance"
+#define CS_CLASS_SIGNALAWAITER "SignalAwaiter"
+#define CS_METHOD_CALL "Call"
+
+#define GLUE_HEADER_FILE "glue_header.h"
+#define ICALL_PREFIX "godot_icall_"
+#define SINGLETON_ICALL_SUFFIX "_get_singleton"
+#define ICALL_GET_METHODBIND ICALL_PREFIX "ClassDB_get_method"
+#define ICALL_CONNECT_SIGNAL_AWAITER ICALL_PREFIX "Object_connect_signal_awaiter"
+#define ICALL_OBJECT_DTOR ICALL_PREFIX "Object_Dtor"
+#define C_LOCAL_PTRCALL_ARGS "call_args"
+#define C_MACRO_OBJECT_CONSTRUCT "GODOTSHARP_INSTANCE_OBJECT"
+
+#define C_NS_MONOUTILS "GDMonoUtils"
+#define C_NS_MONOINTERNALS "GDMonoInternals"
+#define C_METHOD_TIE_MANAGED_TO_UNMANAGED C_NS_MONOINTERNALS "::tie_managed_to_unmanaged"
+#define C_METHOD_UNMANAGED_GET_MANAGED C_NS_MONOUTILS "::unmanaged_get_managed"
+
+#define C_NS_MONOMARSHAL "GDMonoMarshal"
+#define C_METHOD_MANAGED_TO_VARIANT C_NS_MONOMARSHAL "::mono_object_to_variant"
+#define C_METHOD_MANAGED_FROM_VARIANT C_NS_MONOMARSHAL "::variant_to_mono_object"
+#define C_METHOD_MONOSTR_TO_GODOT C_NS_MONOMARSHAL "::mono_string_to_godot"
+#define C_METHOD_MONOSTR_FROM_GODOT C_NS_MONOMARSHAL "::mono_string_from_godot"
+#define C_METHOD_MONOARRAY_TO(m_type) C_NS_MONOMARSHAL "::mono_array_to_" #m_type
+#define C_METHOD_MONOARRAY_FROM(m_type) C_NS_MONOMARSHAL "::" #m_type "_to_mono_array"
+#define C_METHOD_MANAGED_TO_DICT C_NS_MONOMARSHAL "::mono_object_to_Dictionary"
+#define C_METHOD_MANAGED_FROM_DICT C_NS_MONOMARSHAL "::Dictionary_to_mono_object"
+
+const char *BindingsGenerator::TypeInterface::DEFAULT_VARARG_C_IN = "\t%0 %1_in = %1;\n";
+
+bool BindingsGenerator::verbose_output = false;
+
+static bool is_csharp_keyword(const String &p_name) {
+
+ // Reserved keywords
+
+ return p_name == "abstract" || p_name == "as" || p_name == "base" || p_name == "bool" ||
+ p_name == "break" || p_name == "byte" || p_name == "case" || p_name == "catch" ||
+ p_name == "char" || p_name == "checked" || p_name == "class" || p_name == "const" ||
+ p_name == "continue" || p_name == "decimal" || p_name == "default" || p_name == "delegate" ||
+ p_name == "do" || p_name == "double" || p_name == "else" || p_name == "enum" ||
+ p_name == "event" || p_name == "explicit" || p_name == "extern" || p_name == "false" ||
+ p_name == "finally" || p_name == "fixed" || p_name == "float" || p_name == "for" ||
+ p_name == "forech" || p_name == "goto" || p_name == "if" || p_name == "implicit" ||
+ p_name == "in" || p_name == "int" || p_name == "interface" || p_name == "internal" ||
+ p_name == "is" || p_name == "lock" || p_name == "long" || p_name == "namespace" ||
+ p_name == "new" || p_name == "null" || p_name == "object" || p_name == "operator" ||
+ p_name == "out" || p_name == "override" || p_name == "params" || p_name == "private" ||
+ p_name == "protected" || p_name == "public" || p_name == "readonly" || p_name == "ref" ||
+ p_name == "return" || p_name == "sbyte" || p_name == "sealed" || p_name == "short" ||
+ p_name == "sizeof" || p_name == "stackalloc" || p_name == "static" || p_name == "string" ||
+ p_name == "struct" || p_name == "switch" || p_name == "this" || p_name == "throw" ||
+ p_name == "true" || p_name == "try" || p_name == "typeof" || p_name == "uint" || p_name == "ulong" ||
+ p_name == "unchecked" || p_name == "unsafe" || p_name == "ushort" || p_name == "using" ||
+ p_name == "virtual" || p_name == "volatile" || p_name == "void" || p_name == "while";
+}
+
+static bool is_singleton_black_listed(const String &p_type) {
+
+ return p_type == "IP_Unix" || p_type == "InputDefault" || p_type == "AudioServerSW" || p_type == "PhysicsServerSW" ||
+ p_type == "Physics2DServerSW" || p_type == "SpatialSoundServerSW" || p_type == "SpatialSound2DServerSW";
+}
+
+inline static String escape_csharp_keyword(const String &p_name) {
+
+ return is_csharp_keyword(p_name) ? "@" + p_name : p_name;
+}
+
+static String snake_to_pascal_case(const String &p_identifier) {
+
+ String ret;
+ Vector<String> parts = p_identifier.split("_", true);
+
+ for (int i = 0; i < parts.size(); i++) {
+ String part = parts[i];
+
+ if (part.length()) {
+ part[0] = _find_upper(part[0]);
+ ret += part;
+ } else {
+ if (i == 0 || i == (parts.size() - 1)) {
+ // Preserve underscores at the beginning and end
+ ret += "_";
+ } else {
+ // Preserve contiguous underscores
+ if (parts[i - 1].length()) {
+ ret += "__";
+ } else {
+ ret += "_";
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+static String snake_to_camel_case(const String &p_identifier) {
+
+ String ret;
+ Vector<String> parts = p_identifier.split("_", true);
+
+ for (int i = 0; i < parts.size(); i++) {
+ String part = parts[i];
+
+ if (part.length()) {
+ if (i != 0)
+ part[0] = _find_upper(part[0]);
+ ret += part;
+ } else {
+ if (i == 0 || i == (parts.size() - 1)) {
+ // Preserve underscores at the beginning and end
+ ret += "_";
+ } else {
+ // Preserve contiguous underscores
+ if (parts[i - 1].length()) {
+ ret += "__";
+ } else {
+ ret += "_";
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+void BindingsGenerator::_generate_header_icalls() {
+
+ core_custom_icalls.clear();
+
+ core_custom_icalls.push_back(InternalCall(ICALL_GET_METHODBIND, "IntPtr", "string type, string method"));
+ core_custom_icalls.push_back(InternalCall(ICALL_OBJECT_DTOR, "void", "IntPtr ptr"));
+
+ core_custom_icalls.push_back(InternalCall(ICALL_CONNECT_SIGNAL_AWAITER, "Error",
+ "IntPtr source, string signal, IntPtr target, " CS_CLASS_SIGNALAWAITER " awaiter"));
+
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_Ctor", "IntPtr", "string path"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_Dtor", "void", "IntPtr ptr"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "NodePath_operator_String", "string", "IntPtr ptr"));
+
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "RID_Ctor", "IntPtr", "IntPtr from"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "RID_Dtor", "void", "IntPtr ptr"));
+
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_md5_buffer", "byte[]", "string str"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_md5_text", "string", "string str"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_rfind", "int", "string str, string what, int from"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_rfindn", "int", "string str, string what, int from"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_sha256_buffer", "byte[]", "string str"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "String_sha256_text", "string", "string str"));
+
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_bytes2var", "object", "byte[] bytes"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_convert", "object", "object what, int type"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_hash", "int", "object var"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_instance_from_id", "Object", "int instance_id"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_print", "void", "object[] what"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printerr", "void", "object[] what"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printraw", "void", "object[] what"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_prints", "void", "object[] what"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_printt", "void", "object[] what"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_seed", "void", "int seed"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_str", "string", "object[] what"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_str2var", "object", "string str"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_type_exists", "bool", "string type"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_var2bytes", "byte[]", "object what"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_var2str", "string", "object var"));
+ core_custom_icalls.push_back(InternalCall(ICALL_PREFIX "Godot_weakref", "WeakRef", "IntPtr obj"));
+}
+
+void BindingsGenerator::_generate_method_icalls(const TypeInterface &p_itype) {
+
+ if (p_itype.base_name.length() && obj_types[p_itype.base_name].is_singleton && is_singleton_black_listed(p_itype.name))
+ return;
+
+ for (const List<MethodInterface>::Element *E = p_itype.methods.front(); E; E = E->next()) {
+ const MethodInterface &imethod = E->get();
+
+ if (imethod.is_virtual)
+ continue;
+
+ const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type);
+
+ String im_sig = "IntPtr " CS_PARAM_METHODBIND ", IntPtr " CS_PARAM_INSTANCE;
+ String im_unique_sig = imethod.return_type + ",IntPtr,IntPtr";
+
+ // Get arguments information
+ int i = 0;
+ for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
+ const TypeInterface *arg_type = _get_type_by_name_or_placeholder(F->get().type);
+
+ im_sig += ", ";
+ im_sig += arg_type->im_type_in;
+ im_sig += " arg";
+ im_sig += itos(i + 1);
+
+ im_unique_sig += ",";
+ im_unique_sig += get_unique_sig(*arg_type);
+
+ i++;
+ }
+
+ // godot_icall_{argc}_{icallcount}
+ String icall_method = ICALL_PREFIX + itos(imethod.arguments.size()) + "_" + itos(method_icalls.size());
+
+ InternalCall im_icall = InternalCall(p_itype.api_type, icall_method, return_type->im_type_out, im_sig, im_unique_sig);
+
+ List<InternalCall>::Element *match = method_icalls.find(im_icall);
+
+ if (match) {
+ if (p_itype.api_type != ClassDB::API_EDITOR)
+ match->get().editor_only = false;
+ method_icalls_map.insert(&E->get(), &match->get());
+ } else {
+ List<InternalCall>::Element *added = method_icalls.push_back(im_icall);
+ method_icalls_map.insert(&E->get(), &added->get());
+ }
+ }
+}
+
+Error BindingsGenerator::generate_cs_core_project(const String &p_output_dir, bool p_verbose_output) {
+
+ verbose_output = p_verbose_output;
+
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+
+ if (!DirAccess::exists(p_output_dir)) {
+ Error err = da->make_dir_recursive(p_output_dir);
+ ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
+ }
+
+ da->change_dir(p_output_dir);
+ da->make_dir("Core");
+ da->make_dir("ObjectType");
+
+ String core_dir = path_join(p_output_dir, "Core");
+ String obj_type_dir = path_join(p_output_dir, "ObjectType");
+
+ Vector<String> compile_items;
+
+ NETSolution solution(API_ASSEMBLY_NAME);
+
+ if (!solution.set_path(p_output_dir))
+ return ERR_FILE_NOT_FOUND;
+
+ for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) {
+ const TypeInterface &itype = E->get();
+
+ if (itype.api_type == ClassDB::API_EDITOR)
+ continue;
+
+ String output_file = path_join(obj_type_dir, E->get().proxy_name + ".cs");
+ Error err = _generate_cs_type(E->get(), output_file);
+
+ if (err == ERR_SKIP)
+ continue;
+
+ if (err != OK)
+ return err;
+
+ compile_items.push_back(output_file);
+ }
+
+#define GENERATE_BUILTIN_TYPE(m_name) \
+ { \
+ String output_file = path_join(core_dir, #m_name ".cs"); \
+ Error err = _generate_cs_type(builtin_types[#m_name], output_file); \
+ if (err != OK) \
+ return err; \
+ compile_items.push_back(output_file); \
+ }
+
+ GENERATE_BUILTIN_TYPE(NodePath);
+ GENERATE_BUILTIN_TYPE(RID);
+
+#undef GENERATE_BUILTIN_TYPE
+
+ // Generate source for GlobalConstants
+
+ String constants_source;
+ int global_constants_count = GlobalConstants::get_global_constant_count();
+
+ if (global_constants_count > 0) {
+ Map<String, DocData::ClassDoc>::Element *match = EditorHelp::get_doc_data()->class_list.find("@Global Scope");
+
+ ERR_EXPLAIN("Could not find `@Global Scope` in DocData");
+ ERR_FAIL_COND_V(!match, ERR_BUG);
+
+ const DocData::ClassDoc &global_scope_doc = match->value();
+
+ for (int i = 0; i < global_constants_count; i++) {
+ const DocData::ConstantDoc &const_doc = global_scope_doc.constants[i];
+
+ if (i > 0)
+ constants_source += MEMBER_BEGIN;
+
+ if (const_doc.description.size()) {
+ constants_source += "/// <summary>\n";
+
+ Vector<String> description_lines = const_doc.description.split("\n");
+
+ for (int i = 0; i < description_lines.size(); i++) {
+ if (description_lines[i].size()) {
+ constants_source += INDENT2 "/// ";
+ constants_source += description_lines[i].strip_edges().xml_escape();
+ constants_source += "\n";
+ }
+ }
+
+ constants_source += INDENT2 "/// </summary>" MEMBER_BEGIN;
+ }
+
+ constants_source += "public const int ";
+ constants_source += GlobalConstants::get_global_constant_name(i);
+ constants_source += " = ";
+ constants_source += itos(GlobalConstants::get_global_constant_value(i));
+ constants_source += ";";
+ }
+ }
+
+ // Generate sources from compressed files
+
+ Map<String, CompressedFile> compressed_files;
+ get_compressed_files(compressed_files);
+
+ for (Map<String, CompressedFile>::Element *E = compressed_files.front(); E; E = E->next()) {
+ const String &file_name = E->key();
+ const CompressedFile &file_data = E->value();
+
+ String output_file = path_join(core_dir, file_name);
+
+ Vector<uint8_t> data;
+ data.resize(file_data.uncompressed_size);
+ Compression::decompress(data.ptr(), file_data.uncompressed_size, file_data.data, file_data.compressed_size, Compression::MODE_DEFLATE);
+
+ if (file_name.get_basename() == BINDINGS_GLOBAL_SCOPE_CLASS) {
+ // GD.cs must be formatted to include the generated global constants
+ String data_str = String::utf8(reinterpret_cast<const char *>(data.ptr()), data.size());
+
+ Dictionary format_keys;
+ format_keys["GodotGlobalConstants"] = constants_source;
+ data_str = data_str.format(format_keys, "/*{_}*/");
+
+ CharString data_utf8 = data_str.utf8();
+ data.resize(data_utf8.length());
+ copymem(data.ptr(), reinterpret_cast<const uint8_t *>(data_utf8.get_data()), data_utf8.length());
+ }
+
+ FileAccessRef file = FileAccess::open(output_file, FileAccess::WRITE);
+ ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
+ file->store_buffer(data.ptr(), data.size());
+ file->close();
+
+ compile_items.push_back(output_file);
+ }
+
+ List<String> cs_icalls_content;
+
+ cs_icalls_content.push_back("using System;\n"
+ "using System.Runtime.CompilerServices;\n"
+ "using System.Collections.Generic;\n"
+ "\n");
+ cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ cs_icalls_content.push_back(INDENT1 "internal static class " CS_CLASS_NATIVECALLS "\n" INDENT1 OPEN_BLOCK);
+
+#define ADD_INTERNAL_CALL(m_icall) \
+ if (!m_icall.editor_only) { \
+ cs_icalls_content.push_back(INDENT2 "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
+ cs_icalls_content.push_back(INDENT2 "internal extern static "); \
+ cs_icalls_content.push_back(m_icall.im_type_out + " "); \
+ cs_icalls_content.push_back(m_icall.name + "("); \
+ cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
+ }
+
+ for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next())
+ ADD_INTERNAL_CALL(E->get());
+ for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
+ ADD_INTERNAL_CALL(E->get());
+
+#undef ADD_INTERNAL_CALL
+
+ cs_icalls_content.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
+
+ String internal_methods_file = path_join(core_dir, CS_CLASS_NATIVECALLS ".cs");
+
+ Error err = _save_file(internal_methods_file, cs_icalls_content);
+ if (err != OK)
+ return err;
+
+ compile_items.push_back(internal_methods_file);
+
+ String guid = CSharpProject::generate_core_api_project(p_output_dir, compile_items);
+
+ solution.add_new_project(API_ASSEMBLY_NAME, guid);
+
+ Error sln_error = solution.save();
+ if (sln_error != OK) {
+ ERR_PRINT("Could not to save .NET solution.");
+ return sln_error;
+ }
+
+ return OK;
+}
+
+Error BindingsGenerator::generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output) {
+
+ verbose_output = p_verbose_output;
+
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(!da, ERR_CANT_CREATE);
+
+ if (!DirAccess::exists(p_output_dir)) {
+ Error err = da->make_dir_recursive(p_output_dir);
+ ERR_FAIL_COND_V(err != OK, ERR_CANT_CREATE);
+ }
+
+ da->change_dir(p_output_dir);
+ da->make_dir("Core");
+ da->make_dir("ObjectType");
+
+ String core_dir = path_join(p_output_dir, "Core");
+ String obj_type_dir = path_join(p_output_dir, "ObjectType");
+
+ Vector<String> compile_items;
+
+ NETSolution solution(EDITOR_API_ASSEMBLY_NAME);
+
+ if (!solution.set_path(p_output_dir))
+ return ERR_FILE_NOT_FOUND;
+
+ for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next()) {
+ const TypeInterface &itype = E->get();
+
+ if (itype.api_type != ClassDB::API_EDITOR)
+ continue;
+
+ String output_file = path_join(obj_type_dir, E->get().proxy_name + ".cs");
+ Error err = _generate_cs_type(E->get(), output_file);
+
+ if (err == ERR_SKIP)
+ continue;
+
+ if (err != OK)
+ return err;
+
+ compile_items.push_back(output_file);
+ }
+
+ List<String> cs_icalls_content;
+
+ cs_icalls_content.push_back("using System;\n"
+ "using System.Runtime.CompilerServices;\n"
+ "using System.Collections.Generic;\n"
+ "\n");
+ cs_icalls_content.push_back("namespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+ cs_icalls_content.push_back(INDENT1 "internal static class " CS_CLASS_NATIVECALLS_EDITOR "\n" INDENT1 OPEN_BLOCK);
+
+#define ADD_INTERNAL_CALL(m_icall) \
+ if (m_icall.editor_only) { \
+ cs_icalls_content.push_back(INDENT2 "[MethodImpl(MethodImplOptions.InternalCall)]\n"); \
+ cs_icalls_content.push_back(INDENT2 "internal extern static "); \
+ cs_icalls_content.push_back(m_icall.im_type_out + " "); \
+ cs_icalls_content.push_back(m_icall.name + "("); \
+ cs_icalls_content.push_back(m_icall.im_sig + ");\n"); \
+ }
+
+ for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
+ ADD_INTERNAL_CALL(E->get());
+ for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next())
+ ADD_INTERNAL_CALL(E->get());
+
+#undef ADD_INTERNAL_CALL
+
+ cs_icalls_content.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
+
+ String internal_methods_file = path_join(core_dir, CS_CLASS_NATIVECALLS_EDITOR ".cs");
+
+ Error err = _save_file(internal_methods_file, cs_icalls_content);
+ if (err != OK)
+ return err;
+
+ compile_items.push_back(internal_methods_file);
+
+ String guid = CSharpProject::generate_editor_api_project(p_output_dir, p_core_dll_path, compile_items);
+
+ solution.add_new_project(EDITOR_API_ASSEMBLY_NAME, guid);
+
+ Error sln_error = solution.save();
+ if (sln_error != OK) {
+ ERR_PRINT("Could not to save .NET solution.");
+ return sln_error;
+ }
+
+ return OK;
+}
+
+// TODO: there are constants that hide inherited members. must explicitly use `new` to avoid warnings
+// e.g.: warning CS0108: 'SpriteBase3D.FLAG_MAX' hides inherited member 'GeometryInstance.FLAG_MAX'. Use the new keyword if hiding was intended.
+Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const String &p_output_file) {
+
+ int method_bind_count = 0;
+
+ bool is_derived_type = itype.base_name.length();
+
+ if (is_derived_type && obj_types[itype.base_name].is_singleton && is_singleton_black_listed(itype.name))
+ return ERR_SKIP;
+
+ List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
+
+ if (verbose_output)
+ OS::get_singleton()->print(String("Generating " + itype.proxy_name + ".cs...\n").utf8());
+
+ String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
+
+ List<String> cs_file;
+
+ cs_file.push_back("using System;\n"); // IntPtr
+
+ if (itype.requires_collections)
+ cs_file.push_back("using System.Collections.Generic;\n"); // Dictionary
+
+ cs_file.push_back("\nnamespace " BINDINGS_NAMESPACE "\n" OPEN_BLOCK);
+
+ const DocData::ClassDoc *class_doc = itype.class_doc;
+
+ if (class_doc && class_doc->description.size()) {
+ cs_file.push_back(INDENT1 "/// <summary>\n");
+
+ Vector<String> description_lines = class_doc->description.split("\n");
+
+ for (int i = 0; i < description_lines.size(); i++) {
+ if (description_lines[i].size()) {
+ cs_file.push_back(INDENT1 "/// ");
+ cs_file.push_back(description_lines[i].strip_edges().xml_escape());
+ cs_file.push_back("\n");
+ }
+ }
+
+ cs_file.push_back(INDENT1 "/// </summary>\n");
+ }
+
+ cs_file.push_back(INDENT1 "public ");
+ cs_file.push_back(itype.is_singleton ? "static class " : "class ");
+ cs_file.push_back(itype.proxy_name);
+
+ if (itype.is_singleton || !itype.is_object_type) {
+ cs_file.push_back("\n");
+ } else if (!is_derived_type) {
+ cs_file.push_back(" : IDisposable\n");
+ } else if (obj_types.has(itype.base_name)) {
+ cs_file.push_back(" : ");
+ cs_file.push_back(obj_types[itype.base_name].proxy_name);
+ cs_file.push_back("\n");
+ } else {
+ ERR_PRINTS("Base type ' " + itype.base_name + "' does not exist");
+ return ERR_INVALID_DATA;
+ }
+
+ cs_file.push_back(INDENT1 "{");
+
+ if (class_doc) {
+
+ // Add constants
+
+ for (int i = 0; i < class_doc->constants.size(); i++) {
+ const DocData::ConstantDoc &const_doc = class_doc->constants[i];
+
+ if (const_doc.description.size()) {
+ cs_file.push_back(MEMBER_BEGIN "/// <summary>\n");
+
+ Vector<String> description_lines = const_doc.description.split("\n");
+
+ for (int i = 0; i < description_lines.size(); i++) {
+ if (description_lines[i].size()) {
+ cs_file.push_back(INDENT2 "/// ");
+ cs_file.push_back(description_lines[i].strip_edges().xml_escape());
+ cs_file.push_back("\n");
+ }
+ }
+
+ cs_file.push_back(INDENT2 "/// </summary>");
+ }
+
+ cs_file.push_back(MEMBER_BEGIN "public const int ");
+ cs_file.push_back(const_doc.name);
+ cs_file.push_back(" = ");
+ cs_file.push_back(const_doc.value);
+ cs_file.push_back(";");
+ }
+
+ if (class_doc->constants.size())
+ cs_file.push_back("\n");
+
+ // Add properties
+
+ const Vector<DocData::PropertyDoc> &properties = itype.class_doc->properties;
+
+ for (int i = 0; i < properties.size(); i++) {
+ const DocData::PropertyDoc &prop_doc = properties[i];
+
+ const MethodInterface *setter = itype.find_method_by_name(prop_doc.setter);
+
+ // Search it in base types too
+ const TypeInterface *current_type = &itype;
+ while (!setter && current_type->base_name.length()) {
+ Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
+ ERR_FAIL_NULL_V(base_match, ERR_BUG);
+ current_type = &base_match->get();
+ setter = current_type->find_method_by_name(prop_doc.setter);
+ }
+
+ const MethodInterface *getter = itype.find_method_by_name(prop_doc.getter);
+
+ // Search it in base types too
+ current_type = &itype;
+ while (!getter && current_type->base_name.length()) {
+ Map<String, TypeInterface>::Element *base_match = obj_types.find(current_type->base_name);
+ ERR_FAIL_NULL_V(base_match, ERR_BUG);
+ current_type = &base_match->get();
+ getter = current_type->find_method_by_name(prop_doc.getter);
+ }
+
+ ERR_FAIL_COND_V(!setter && !getter, ERR_BUG);
+
+ bool is_valid = false;
+ int prop_index = ClassDB::get_property_index(itype.name, prop_doc.name, &is_valid);
+ ERR_FAIL_COND_V(!is_valid, ERR_BUG);
+
+ if (setter) {
+ int setter_argc = prop_index != -1 ? 2 : 1;
+ ERR_FAIL_COND_V(setter->arguments.size() != setter_argc, ERR_BUG);
+ }
+
+ if (getter) {
+ int getter_argc = prop_index != -1 ? 1 : 0;
+ ERR_FAIL_COND_V(getter->arguments.size() != getter_argc, ERR_BUG);
+ }
+
+ if (getter && setter) {
+ ERR_FAIL_COND_V(getter->return_type != setter->arguments.back()->get().type, ERR_BUG);
+ }
+
+ // Let's not trust PropertyDoc::type
+ String proptype_name = getter ? getter->return_type : setter->arguments.back()->get().type;
+
+ const TypeInterface *prop_itype = _get_type_by_name_or_null(proptype_name);
+ if (!prop_itype) {
+ // Try with underscore prefix
+ prop_itype = _get_type_by_name_or_null("_" + proptype_name);
+ }
+
+ ERR_FAIL_NULL_V(prop_itype, ERR_BUG);
+
+ String prop_proxy_name = escape_csharp_keyword(snake_to_pascal_case(prop_doc.name));
+
+ // Prevent property and enclosing type from sharing the same name
+ if (prop_proxy_name == itype.proxy_name) {
+ if (verbose_output) {
+ WARN_PRINTS("Name of property `" + prop_proxy_name + "` is ambiguous with the name of its class `" +
+ itype.proxy_name + "`. Renaming property to `" + prop_proxy_name + "_`");
+ }
+
+ prop_proxy_name += "_";
+ }
+
+ if (prop_doc.description.size()) {
+ cs_file.push_back(MEMBER_BEGIN "/// <summary>\n");
+
+ Vector<String> description_lines = prop_doc.description.split("\n");
+
+ for (int i = 0; i < description_lines.size(); i++) {
+ if (description_lines[i].size()) {
+ cs_file.push_back(INDENT2 "/// ");
+ cs_file.push_back(description_lines[i].strip_edges().xml_escape());
+ cs_file.push_back("\n");
+ }
+ }
+
+ cs_file.push_back(INDENT2 "/// </summary>");
+ }
+
+ cs_file.push_back(MEMBER_BEGIN "public ");
+
+ if (itype.is_singleton)
+ cs_file.push_back("static ");
+
+ cs_file.push_back(prop_itype->cs_type);
+ cs_file.push_back(" ");
+ cs_file.push_back(prop_proxy_name.replace("/", "__"));
+ cs_file.push_back("\n" INDENT2 OPEN_BLOCK);
+
+ if (getter) {
+ cs_file.push_back(INDENT3 "get\n" OPEN_BLOCK_L3);
+ cs_file.push_back("return ");
+ cs_file.push_back(getter->proxy_name + "(");
+ if (prop_index != -1)
+ cs_file.push_back(itos(prop_index));
+ cs_file.push_back(");\n" CLOSE_BLOCK_L3);
+ }
+
+ if (setter) {
+ cs_file.push_back(INDENT3 "set\n" OPEN_BLOCK_L3);
+ cs_file.push_back(setter->proxy_name + "(");
+ if (prop_index != -1)
+ cs_file.push_back(itos(prop_index) + ", ");
+ cs_file.push_back("value);\n" CLOSE_BLOCK_L3);
+ }
+
+ cs_file.push_back(CLOSE_BLOCK_L2);
+ }
+
+ if (class_doc->properties.size())
+ cs_file.push_back("\n");
+ }
+
+ if (!itype.is_object_type) {
+ cs_file.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"" + itype.name + "\";\n");
+ cs_file.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
+ cs_file.push_back(MEMBER_BEGIN "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
+
+ cs_file.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(");
+ cs_file.push_back(itype.proxy_name);
+ cs_file.push_back(" instance)\n" OPEN_BLOCK_L2 "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
+
+ // Add Destructor
+ cs_file.push_back(MEMBER_BEGIN "~");
+ cs_file.push_back(itype.proxy_name);
+ cs_file.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
+
+ // Add the Dispose from IDisposable
+ cs_file.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
+
+ // Add the virtual Dispose
+ cs_file.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
+ "if (disposed) return;\n" INDENT3
+ "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3 "NativeCalls.godot_icall_");
+ cs_file.push_back(itype.proxy_name);
+ cs_file.push_back("_Dtor(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L3 INDENT3
+ "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
+
+ cs_file.push_back(MEMBER_BEGIN "internal ");
+ cs_file.push_back(itype.proxy_name);
+ cs_file.push_back("(IntPtr " BINDINGS_PTR_FIELD ")\n" OPEN_BLOCK_L2 "this." BINDINGS_PTR_FIELD " = " BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
+
+ cs_file.push_back(MEMBER_BEGIN "public bool HasValidHandle()\n" OPEN_BLOCK_L2
+ "return " BINDINGS_PTR_FIELD " == IntPtr.Zero;\n" CLOSE_BLOCK_L2);
+ } else if (itype.is_singleton) {
+ // Add the type name and the singleton pointer as static fields
+
+ cs_file.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
+ cs_file.push_back(itype.name);
+ cs_file.push_back("\";\n");
+
+ cs_file.push_back(INDENT2 "internal static IntPtr " BINDINGS_PTR_FIELD " = ");
+ cs_file.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS);
+ cs_file.push_back("." ICALL_PREFIX);
+ cs_file.push_back(itype.name);
+ cs_file.push_back(SINGLETON_ICALL_SUFFIX "();\n");
+ } else {
+ // Add member fields
+
+ cs_file.push_back(MEMBER_BEGIN "private const string " BINDINGS_NATIVE_NAME_FIELD " = \"");
+ cs_file.push_back(itype.name);
+ cs_file.push_back("\";\n");
+
+ // Only the base class stores the pointer to the native object
+ // This pointer is expected to be and must be of type Object*
+ if (!is_derived_type) {
+ cs_file.push_back(MEMBER_BEGIN "private bool disposed = false;\n");
+ cs_file.push_back(INDENT2 "internal IntPtr " BINDINGS_PTR_FIELD ";\n");
+ cs_file.push_back(INDENT2 "internal bool " CS_FIELD_MEMORYOWN ";\n");
+ }
+
+ // Add default constructor
+ if (itype.is_instantiable) {
+ cs_file.push_back(MEMBER_BEGIN "public ");
+ cs_file.push_back(itype.proxy_name);
+ cs_file.push_back("() : this(");
+ cs_file.push_back(itype.memory_own ? "true" : "false");
+
+ // The default constructor may also be called by the engine when instancing existing native objects
+ // The engine will initialize the pointer field of the managed side before calling the constructor
+ // This is why we only allocate a new native object from the constructor if the pointer field is not set
+ cs_file.push_back(")\n" OPEN_BLOCK_L2 "if (" BINDINGS_PTR_FIELD " == IntPtr.Zero)\n" INDENT4 BINDINGS_PTR_FIELD " = ");
+ cs_file.push_back(itype.api_type == ClassDB::API_EDITOR ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS);
+ cs_file.push_back("." + ctor_method);
+ cs_file.push_back("(this);\n" CLOSE_BLOCK_L2);
+ } else {
+ // Hide the constructor
+ cs_file.push_back(MEMBER_BEGIN "internal ");
+ cs_file.push_back(itype.proxy_name);
+ cs_file.push_back("() {}\n");
+ }
+
+ // Add.. em.. trick constructor. Sort of.
+ cs_file.push_back(MEMBER_BEGIN "internal ");
+ cs_file.push_back(itype.proxy_name);
+ if (is_derived_type) {
+ cs_file.push_back("(bool " CS_FIELD_MEMORYOWN ") : base(" CS_FIELD_MEMORYOWN ") {}\n");
+ } else {
+ cs_file.push_back("(bool " CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L2
+ "this." CS_FIELD_MEMORYOWN " = " CS_FIELD_MEMORYOWN ";\n" CLOSE_BLOCK_L2);
+ }
+
+ // Add methods
+
+ if (!is_derived_type) {
+ cs_file.push_back(MEMBER_BEGIN "public bool HasValidHandle()\n" OPEN_BLOCK_L2
+ "return " BINDINGS_PTR_FIELD " == IntPtr.Zero;\n" CLOSE_BLOCK_L2);
+
+ cs_file.push_back(MEMBER_BEGIN "internal static IntPtr " CS_SMETHOD_GETINSTANCE "(Object instance)\n" OPEN_BLOCK_L2
+ "return instance == null ? IntPtr.Zero : instance." BINDINGS_PTR_FIELD ";\n" CLOSE_BLOCK_L2);
+ }
+
+ if (!is_derived_type) {
+ // Add destructor
+ cs_file.push_back(MEMBER_BEGIN "~");
+ cs_file.push_back(itype.proxy_name);
+ cs_file.push_back("()\n" OPEN_BLOCK_L2 "Dispose(false);\n" CLOSE_BLOCK_L2);
+
+ // Add the Dispose from IDisposable
+ cs_file.push_back(MEMBER_BEGIN "public void Dispose()\n" OPEN_BLOCK_L2 "Dispose(true);\n" INDENT3 "GC.SuppressFinalize(this);\n" CLOSE_BLOCK_L2);
+
+ // Add the virtual Dispose
+ cs_file.push_back(MEMBER_BEGIN "public virtual void Dispose(bool disposing)\n" OPEN_BLOCK_L2
+ "if (disposed) return;\n" INDENT3
+ "if (" BINDINGS_PTR_FIELD " != IntPtr.Zero)\n" OPEN_BLOCK_L3
+ "if (" CS_FIELD_MEMORYOWN ")\n" OPEN_BLOCK_L4 CS_FIELD_MEMORYOWN
+ " = false;\n" INDENT5 CS_CLASS_NATIVECALLS "." ICALL_OBJECT_DTOR
+ "(" BINDINGS_PTR_FIELD ");\n" INDENT5 BINDINGS_PTR_FIELD
+ " = IntPtr.Zero;\n" CLOSE_BLOCK_L4 CLOSE_BLOCK_L3 INDENT3
+ "GC.SuppressFinalize(this);\n" INDENT3 "disposed = true;\n" CLOSE_BLOCK_L2);
+
+ Map<String, TypeInterface>::Element *array_itype = builtin_types.find("Array");
+
+ if (!array_itype) {
+ ERR_PRINT("BUG: Array type interface not found!");
+ return ERR_BUG;
+ }
+
+ cs_file.push_back(MEMBER_BEGIN "private void _AwaitedSignalCallback(");
+ cs_file.push_back(array_itype->get().cs_type);
+ cs_file.push_back(" args, SignalAwaiter awaiter)\n" OPEN_BLOCK_L2 "awaiter.SignalCallback(args);\n" CLOSE_BLOCK_L2);
+
+ Map<String, TypeInterface>::Element *object_itype = obj_types.find("Object");
+
+ if (!object_itype) {
+ ERR_PRINT("BUG: Array type interface not found!");
+ return ERR_BUG;
+ }
+
+ cs_file.push_back(MEMBER_BEGIN "public " CS_CLASS_SIGNALAWAITER " ToSignal(");
+ cs_file.push_back(object_itype->get().cs_type);
+ cs_file.push_back(" source, string signal)\n" OPEN_BLOCK_L2
+ "return new " CS_CLASS_SIGNALAWAITER "(source, signal, this);\n" CLOSE_BLOCK_L2);
+ }
+ }
+
+ Map<String, String>::Element *extra_member = extra_members.find(itype.name);
+ if (extra_member)
+ cs_file.push_back(extra_member->get());
+
+ for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
+ const MethodInterface &imethod = E->get();
+
+ const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type);
+
+ String method_bind_field = "method_bind_" + itos(method_bind_count);
+
+ String icall_params = method_bind_field + ", " + sformat(itype.cs_in, "this");
+ String arguments_sig;
+ String cs_in_statements;
+
+ List<String> default_args_doc;
+
+ // Retrieve information from the arguments
+ for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
+ const ArgumentInterface &iarg = F->get();
+ const TypeInterface *arg_type = _get_type_by_name_or_placeholder(iarg.type);
+
+ // Add the current arguments to the signature
+ // If the argument has a default value which is not a constant, we will make it Nullable
+ {
+ if (F != imethod.arguments.front())
+ arguments_sig += ", ";
+
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ arguments_sig += "Nullable<";
+
+ arguments_sig += arg_type->cs_type;
+
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ arguments_sig += "> ";
+ else
+ arguments_sig += " ";
+
+ arguments_sig += iarg.name;
+
+ if (iarg.default_argument.size()) {
+ if (iarg.def_param_mode != ArgumentInterface::CONSTANT)
+ arguments_sig += " = null";
+ else
+ arguments_sig += " = " + sformat(iarg.default_argument, arg_type->cs_type);
+ }
+ }
+
+ icall_params += ", ";
+
+ if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) {
+ // The default value of an argument must be constant. Otherwise we make it Nullable and do the following:
+ // Type arg_in = arg.HasValue ? arg.Value : <non-const default value>;
+ String arg_in = iarg.name;
+ arg_in += "_in";
+
+ cs_in_statements += arg_type->cs_type;
+ cs_in_statements += " ";
+ cs_in_statements += arg_in;
+ cs_in_statements += " = ";
+ cs_in_statements += iarg.name;
+
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ cs_in_statements += ".HasValue ? ";
+ else
+ cs_in_statements += " != null ? ";
+
+ cs_in_statements += iarg.name;
+
+ if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL)
+ cs_in_statements += ".Value : ";
+ else
+ cs_in_statements += " : ";
+
+ String def_arg = sformat(iarg.default_argument, arg_type->cs_type);
+
+ cs_in_statements += def_arg;
+ cs_in_statements += ";\n" INDENT3;
+
+ icall_params += arg_type->cs_in.empty() ? arg_in : sformat(arg_type->cs_in, arg_in);
+
+ default_args_doc.push_back(INDENT2 "/// <param name=\"" + iarg.name + "\">If the param is null, then the default value is " + def_arg + "</param>\n");
+ } else {
+ icall_params += arg_type->cs_in.empty() ? iarg.name : sformat(arg_type->cs_in, iarg.name);
+ }
+ }
+
+ // Generate method
+ {
+ if (!imethod.is_virtual && !imethod.requires_object_call) {
+ cs_file.push_back(MEMBER_BEGIN "private ");
+ cs_file.push_back(itype.is_singleton ? "static IntPtr " : "IntPtr ");
+ cs_file.push_back(method_bind_field + " = " CS_CLASS_NATIVECALLS "." ICALL_GET_METHODBIND "(" BINDINGS_NATIVE_NAME_FIELD ", \"");
+ cs_file.push_back(imethod.name);
+ cs_file.push_back("\");\n");
+ }
+
+ if (imethod.method_doc && imethod.method_doc->description.size()) {
+ cs_file.push_back(MEMBER_BEGIN "/// <summary>\n");
+
+ Vector<String> description_lines = imethod.method_doc->description.split("\n");
+
+ for (int i = 0; i < description_lines.size(); i++) {
+ if (description_lines[i].size()) {
+ cs_file.push_back(INDENT2 "/// ");
+ cs_file.push_back(description_lines[i].strip_edges().xml_escape());
+ cs_file.push_back("\n");
+ }
+ }
+
+ for (List<String>::Element *E = default_args_doc.front(); E; E = E->next()) {
+ cs_file.push_back(E->get().xml_escape());
+ }
+
+ cs_file.push_back(INDENT2 "/// </summary>");
+ }
+
+ if (!imethod.is_internal) {
+ cs_file.push_back(MEMBER_BEGIN "[GodotMethod(\"");
+ cs_file.push_back(imethod.name);
+ cs_file.push_back("\")]");
+ }
+
+ cs_file.push_back(MEMBER_BEGIN);
+ cs_file.push_back(imethod.is_internal ? "internal " : "public ");
+
+ if (itype.is_singleton) {
+ cs_file.push_back("static ");
+ } else if (imethod.is_virtual) {
+ cs_file.push_back("virtual ");
+ }
+
+ cs_file.push_back(return_type->cs_type + " ");
+ cs_file.push_back(imethod.proxy_name + "(");
+ cs_file.push_back(arguments_sig + ")\n" OPEN_BLOCK_L2);
+
+ if (imethod.is_virtual) {
+ // Godot virtual method must be overridden, therefore we return a default value by default.
+
+ if (return_type->name == "void") {
+ cs_file.push_back("return;\n" CLOSE_BLOCK_L2);
+ } else {
+ cs_file.push_back("return default(");
+ cs_file.push_back(return_type->cs_type);
+ cs_file.push_back(");\n" CLOSE_BLOCK_L2);
+ }
+
+ continue;
+ }
+
+ if (imethod.requires_object_call) {
+ // Fallback to Godot's object.Call(string, params)
+
+ cs_file.push_back(CS_METHOD_CALL "(\"");
+ cs_file.push_back(imethod.name);
+ cs_file.push_back("\"");
+
+ for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
+ cs_file.push_back(", ");
+ cs_file.push_back(F->get().name);
+ }
+
+ cs_file.push_back(");\n" CLOSE_BLOCK_L2);
+
+ continue;
+ }
+
+ const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&E->get());
+ ERR_FAIL_NULL_V(match, ERR_BUG);
+
+ const InternalCall *im_icall = match->value();
+
+ String im_call = im_icall->editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS;
+ im_call += "." + im_icall->name + "(" + icall_params + ");\n";
+
+ if (imethod.arguments.size())
+ cs_file.push_back(cs_in_statements);
+
+ if (return_type->name == "void") {
+ cs_file.push_back(im_call);
+ } else if (return_type->cs_out.empty()) {
+ cs_file.push_back("return " + im_call);
+ } else {
+ cs_file.push_back(return_type->im_type_out);
+ cs_file.push_back(" " LOCAL_RET " = ");
+ cs_file.push_back(im_call);
+ cs_file.push_back(INDENT3);
+ cs_file.push_back(sformat(return_type->cs_out, LOCAL_RET) + "\n");
+ }
+
+ cs_file.push_back(CLOSE_BLOCK_L2);
+ }
+
+ method_bind_count++;
+ }
+
+ if (itype.is_singleton) {
+ InternalCall singleton_icall = InternalCall(itype.api_type, ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX, "IntPtr");
+
+ if (!find_icall_by_name(singleton_icall.name, custom_icalls))
+ custom_icalls.push_back(singleton_icall);
+ }
+
+ if (itype.is_instantiable) {
+ InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
+
+ if (!find_icall_by_name(ctor_icall.name, custom_icalls))
+ custom_icalls.push_back(ctor_icall);
+ }
+
+ cs_file.push_back(INDENT1 CLOSE_BLOCK CLOSE_BLOCK);
+
+ return _save_file(p_output_file, cs_file);
+}
+
+Error BindingsGenerator::generate_glue(const String &p_output_dir) {
+
+ verbose_output = true;
+
+ bool dir_exists = DirAccess::exists(p_output_dir);
+ ERR_EXPLAIN("The output directory does not exist.");
+ ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH);
+
+ List<String> cpp_file;
+
+ cpp_file.push_back("#include \"" GLUE_HEADER_FILE "\"\n"
+ "\n");
+
+ List<const InternalCall *> generated_icall_funcs;
+
+ for (Map<String, TypeInterface>::Element *type_elem = obj_types.front(); type_elem; type_elem = type_elem->next()) {
+ const TypeInterface &itype = type_elem->get();
+
+ if (itype.base_name.length() && obj_types[itype.base_name].is_singleton && is_singleton_black_listed(itype.name))
+ continue;
+
+ List<InternalCall> &custom_icalls = itype.api_type == ClassDB::API_EDITOR ? editor_custom_icalls : core_custom_icalls;
+
+ OS::get_singleton()->print(String("Generating " + itype.name + "...\n").utf8());
+
+ String ctor_method(ICALL_PREFIX + itype.proxy_name + "_Ctor");
+
+ for (const List<MethodInterface>::Element *E = itype.methods.front(); E; E = E->next()) {
+ const MethodInterface &imethod = E->get();
+
+ if (imethod.is_virtual)
+ continue;
+
+ bool ret_void = imethod.return_type == "void";
+
+ const TypeInterface *return_type = _get_type_by_name_or_placeholder(imethod.return_type);
+
+ String argc_str = itos(imethod.arguments.size());
+
+ String c_func_sig = "MethodBind* " CS_PARAM_METHODBIND ", " + itype.c_type_in + " " CS_PARAM_INSTANCE;
+ String c_in_statements;
+ String c_args_var_content;
+
+ // Get arguments information
+ int i = 0;
+ for (const List<ArgumentInterface>::Element *F = imethod.arguments.front(); F; F = F->next()) {
+ const ArgumentInterface &iarg = F->get();
+ const TypeInterface *arg_type = _get_type_by_name_or_placeholder(iarg.type);
+
+ String c_param_name = "arg" + itos(i + 1);
+
+ if (imethod.is_vararg) {
+ if (i < imethod.arguments.size() - 1) {
+ c_in_statements += sformat(arg_type->c_in.size() ? arg_type->c_in : TypeInterface::DEFAULT_VARARG_C_IN, "Variant", c_param_name);
+ c_in_statements += "\t" C_LOCAL_PTRCALL_ARGS ".set(0, ";
+ c_in_statements += sformat("&%s_in", c_param_name);
+ c_in_statements += ");\n";
+ }
+ } else {
+ if (i > 0)
+ c_args_var_content += ", ";
+ if (arg_type->c_in.size())
+ c_in_statements += sformat(arg_type->c_in, arg_type->c_type, c_param_name);
+ c_args_var_content += sformat(arg_type->c_arg_in, c_param_name);
+ }
+
+ c_func_sig += ", ";
+ c_func_sig += arg_type->c_type_in;
+ c_func_sig += " ";
+ c_func_sig += c_param_name;
+
+ i++;
+ }
+
+ const Map<const MethodInterface *, const InternalCall *>::Element *match = method_icalls_map.find(&E->get());
+ ERR_FAIL_NULL_V(match, ERR_BUG);
+
+ const InternalCall *im_icall = match->value();
+ String icall_method = im_icall->name;
+
+ if (!generated_icall_funcs.find(im_icall)) {
+ generated_icall_funcs.push_back(im_icall);
+
+ if (im_icall->editor_only)
+ cpp_file.push_back("#ifdef TOOLS_ENABLED\n");
+
+ // Generate icall function
+
+ cpp_file.push_back(ret_void ? "void " : return_type->c_type_out + " ");
+ cpp_file.push_back(icall_method);
+ cpp_file.push_back("(");
+ cpp_file.push_back(c_func_sig);
+ cpp_file.push_back(") " OPEN_BLOCK);
+
+ String fail_ret = ret_void ? "" : ", " + (return_type->c_type_out.ends_with("*") ? "NULL" : return_type->c_type_out + "()");
+
+ if (!ret_void) {
+ String ptrcall_return_type;
+ String initialization;
+
+ if (return_type->is_object_type) {
+ ptrcall_return_type = return_type->is_reference ? "Ref<Reference>" : return_type->c_type;
+ initialization = return_type->is_reference ? "" : " = NULL";
+ } else {
+ ptrcall_return_type = return_type->c_type;
+ }
+
+ cpp_file.push_back("\t" + ptrcall_return_type);
+ cpp_file.push_back(" " LOCAL_RET);
+ cpp_file.push_back(initialization + ";\n");
+ cpp_file.push_back("\tERR_FAIL_NULL_V(" CS_PARAM_INSTANCE);
+ cpp_file.push_back(fail_ret);
+ cpp_file.push_back(");\n");
+ } else {
+ cpp_file.push_back("\tERR_FAIL_NULL(" CS_PARAM_INSTANCE ");\n");
+ }
+
+ if (imethod.arguments.size()) {
+ if (imethod.is_vararg) {
+ String err_fail_macro = ret_void ? "ERR_FAIL_COND" : "ERR_FAIL_COND_V";
+ String vararg_arg = "arg" + argc_str;
+ String real_argc_str = itos(imethod.arguments.size() - 1); // Arguments count without vararg
+
+ cpp_file.push_back("\tVector<Variant> varargs;\n"
+ "\tint vararg_length = mono_array_length(");
+ cpp_file.push_back(vararg_arg);
+ cpp_file.push_back(");\n\tint total_length = ");
+ cpp_file.push_back(real_argc_str);
+ cpp_file.push_back(" + vararg_length;\n\t");
+ cpp_file.push_back(err_fail_macro);
+ cpp_file.push_back("(varargs.resize(vararg_length) != OK");
+ cpp_file.push_back(fail_ret);
+ cpp_file.push_back(");\n\tVector<Variant*> " C_LOCAL_PTRCALL_ARGS ";\n\t");
+ cpp_file.push_back(err_fail_macro);
+ cpp_file.push_back("(call_args.resize(total_length) != OK");
+ cpp_file.push_back(fail_ret);
+ cpp_file.push_back(");\n");
+ cpp_file.push_back(c_in_statements);
+ cpp_file.push_back("\tfor (int i = 0; i < vararg_length; i++) " OPEN_BLOCK
+ "\t\tMonoObject* elem = mono_array_get(");
+ cpp_file.push_back(vararg_arg);
+ cpp_file.push_back(", MonoObject*, i);\n"
+ "\t\tvarargs.set(i, GDMonoMarshal::mono_object_to_variant(elem));\n"
+ "\t\t" C_LOCAL_PTRCALL_ARGS ".set(");
+ cpp_file.push_back(real_argc_str);
+ cpp_file.push_back(" + i, &varargs[i]);\n\t" CLOSE_BLOCK);
+ } else {
+ cpp_file.push_back(c_in_statements);
+ cpp_file.push_back("\tconst void* " C_LOCAL_PTRCALL_ARGS "[");
+ cpp_file.push_back(argc_str + "] = { ");
+ cpp_file.push_back(c_args_var_content + " };\n");
+ }
+ }
+
+ if (imethod.is_vararg) {
+ cpp_file.push_back("\tVariant::CallError vcall_error;\n\t");
+
+ if (!ret_void)
+ cpp_file.push_back(LOCAL_RET " = ");
+
+ cpp_file.push_back(CS_PARAM_METHODBIND "->call(" CS_PARAM_INSTANCE ", ");
+ cpp_file.push_back(imethod.arguments.size() ? "(const Variant**)" C_LOCAL_PTRCALL_ARGS ".ptr()" : "NULL");
+ cpp_file.push_back(", total_length, vcall_error);\n");
+ } else {
+ cpp_file.push_back("\t" CS_PARAM_METHODBIND "->ptrcall(" CS_PARAM_INSTANCE ", ");
+ cpp_file.push_back(imethod.arguments.size() ? C_LOCAL_PTRCALL_ARGS ", " : "NULL, ");
+ cpp_file.push_back(!ret_void ? "&" LOCAL_RET ");\n" : "NULL);\n");
+ }
+
+ if (!ret_void) {
+ if (return_type->c_out.empty())
+ cpp_file.push_back("\treturn " LOCAL_RET ";\n");
+ else
+ cpp_file.push_back(sformat(return_type->c_out, return_type->c_type_out, LOCAL_RET, return_type->name));
+ }
+
+ cpp_file.push_back(CLOSE_BLOCK "\n");
+
+ if (im_icall->editor_only)
+ cpp_file.push_back("#endif // TOOLS_ENABLED\n");
+ }
+ }
+
+ if (itype.is_singleton) {
+ String singleton_icall_name = ICALL_PREFIX + itype.name + SINGLETON_ICALL_SUFFIX;
+ InternalCall singleton_icall = InternalCall(itype.api_type, singleton_icall_name, "IntPtr");
+
+ if (!find_icall_by_name(singleton_icall.name, custom_icalls))
+ custom_icalls.push_back(singleton_icall);
+
+ cpp_file.push_back("Object* ");
+ cpp_file.push_back(singleton_icall_name);
+ cpp_file.push_back("() " OPEN_BLOCK "\treturn ProjectSettings::get_singleton()->get_singleton_object(\"");
+ cpp_file.push_back(itype.proxy_name);
+ cpp_file.push_back("\");\n" CLOSE_BLOCK "\n");
+ }
+
+ if (itype.is_instantiable) {
+ InternalCall ctor_icall = InternalCall(itype.api_type, ctor_method, "IntPtr", itype.proxy_name + " obj");
+
+ if (!find_icall_by_name(ctor_icall.name, custom_icalls))
+ custom_icalls.push_back(ctor_icall);
+
+ cpp_file.push_back("Object* ");
+ cpp_file.push_back(ctor_method);
+ cpp_file.push_back("(MonoObject* obj) " OPEN_BLOCK
+ "\t" C_MACRO_OBJECT_CONSTRUCT "(instance, \"");
+ cpp_file.push_back(itype.name);
+ cpp_file.push_back("\");\n"
+ "\t" C_METHOD_TIE_MANAGED_TO_UNMANAGED "(obj, instance);\n"
+ "\treturn instance;\n" CLOSE_BLOCK "\n");
+ }
+ }
+
+ cpp_file.push_back("namespace GodotSharpBindings\n" OPEN_BLOCK);
+ cpp_file.push_back("uint64_t get_core_api_hash() { return ");
+ cpp_file.push_back(itos(GDMono::get_singleton()->get_api_core_hash()) + "; }\n");
+ cpp_file.push_back("#ifdef TOOLS_ENABLED\n"
+ "uint64_t get_editor_api_hash() { return ");
+ cpp_file.push_back(itos(GDMono::get_singleton()->get_api_editor_hash()) +
+ "; }\n#endif // TOOLS_ENABLED\n");
+ cpp_file.push_back("void register_generated_icalls() " OPEN_BLOCK);
+
+#define ADD_INTERNAL_CALL_REGISTRATION(m_icall) \
+ { \
+ cpp_file.push_back("\tmono_add_internal_call("); \
+ cpp_file.push_back("\"" BINDINGS_NAMESPACE "."); \
+ cpp_file.push_back(m_icall.editor_only ? CS_CLASS_NATIVECALLS_EDITOR : CS_CLASS_NATIVECALLS); \
+ cpp_file.push_back("::"); \
+ cpp_file.push_back(m_icall.name); \
+ cpp_file.push_back("\", (void*)"); \
+ cpp_file.push_back(m_icall.name); \
+ cpp_file.push_back(");\n"); \
+ }
+
+ bool tools_sequence = false;
+ for (const List<InternalCall>::Element *E = core_custom_icalls.front(); E; E = E->next()) {
+
+ if (tools_sequence) {
+ if (!E->get().editor_only) {
+ tools_sequence = false;
+ cpp_file.push_back("#endif\n");
+ }
+ } else {
+ if (E->get().editor_only) {
+ cpp_file.push_back("#ifdef TOOLS_ENABLED\n");
+ tools_sequence = true;
+ }
+ }
+
+ ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ }
+
+ if (tools_sequence) {
+ tools_sequence = false;
+ cpp_file.push_back("#endif\n");
+ }
+
+ cpp_file.push_back("#ifdef TOOLS_ENABLED\n");
+ for (const List<InternalCall>::Element *E = editor_custom_icalls.front(); E; E = E->next())
+ ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ cpp_file.push_back("#endif // TOOLS_ENABLED\n");
+
+ for (const List<InternalCall>::Element *E = method_icalls.front(); E; E = E->next()) {
+
+ if (tools_sequence) {
+ if (!E->get().editor_only) {
+ tools_sequence = false;
+ cpp_file.push_back("#endif\n");
+ }
+ } else {
+ if (E->get().editor_only) {
+ cpp_file.push_back("#ifdef TOOLS_ENABLED\n");
+ tools_sequence = true;
+ }
+ }
+
+ ADD_INTERNAL_CALL_REGISTRATION(E->get());
+ }
+
+ if (tools_sequence) {
+ tools_sequence = false;
+ cpp_file.push_back("#endif\n");
+ }
+
+#undef ADD_INTERNAL_CALL_REGISTRATION
+
+ cpp_file.push_back(CLOSE_BLOCK "}\n");
+
+ return _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), cpp_file);
+}
+
+Error BindingsGenerator::_save_file(const String &p_path, const List<String> &p_content) {
+
+ FileAccessRef file = FileAccess::open(p_path, FileAccess::WRITE);
+
+ ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
+
+ for (const List<String>::Element *E = p_content.front(); E; E = E->next()) {
+ file->store_string(E->get());
+ }
+
+ file->close();
+
+ return OK;
+}
+
+const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_null(const String &p_name) {
+
+ const Map<String, TypeInterface>::Element *match = builtin_types.find(p_name);
+
+ if (match)
+ return &match->get();
+
+ match = obj_types.find(p_name);
+
+ if (match)
+ return &match->get();
+
+ return NULL;
+}
+
+const BindingsGenerator::TypeInterface *BindingsGenerator::_get_type_by_name_or_placeholder(const String &p_name) {
+
+ const TypeInterface *found = _get_type_by_name_or_null(p_name);
+
+ if (found)
+ return found;
+
+ ERR_PRINTS(String() + "Type not found. Creating placeholder: " + p_name);
+
+ const Map<String, TypeInterface>::Element *match = placeholder_types.find(p_name);
+
+ if (match)
+ return &match->get();
+
+ TypeInterface placeholder;
+ TypeInterface::create_placeholder_type(placeholder, p_name);
+
+ return &placeholder_types.insert(placeholder.name, placeholder)->get();
+}
+
+void BindingsGenerator::_populate_object_type_interfaces() {
+
+ obj_types.clear();
+
+ List<StringName> class_list;
+ ClassDB::get_class_list(&class_list);
+ class_list.sort_custom<StringName::AlphCompare>();
+
+ StringName refclass_name = String("Reference");
+
+ while (class_list.size()) {
+ StringName type_cname = class_list.front()->get();
+
+ ClassDB::APIType api_type = ClassDB::get_api_type(type_cname);
+
+ if (api_type == ClassDB::API_NONE) {
+ class_list.pop_front();
+ continue;
+ }
+
+ TypeInterface itype = TypeInterface::create_object_type(type_cname, api_type);
+
+ itype.base_name = ClassDB::get_parent_class(type_cname);
+ itype.is_singleton = ProjectSettings::get_singleton()->has_singleton(itype.proxy_name);
+ itype.is_instantiable = ClassDB::can_instance(type_cname) && !itype.is_singleton;
+ itype.is_reference = ClassDB::is_parent_class(type_cname, refclass_name);
+ itype.memory_own = itype.is_reference;
+
+ itype.c_out = "\treturn ";
+ itype.c_out += C_METHOD_UNMANAGED_GET_MANAGED;
+ itype.c_out += itype.is_reference ? "(%1.ptr());\n" : "(%1);\n";
+
+ itype.cs_in = itype.is_singleton ? BINDINGS_PTR_FIELD : "Object." CS_SMETHOD_GETINSTANCE "(%0)";
+
+ itype.c_type = "Object*";
+ itype.c_type_in = itype.c_type;
+ itype.c_type_out = "MonoObject*";
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = "IntPtr";
+ itype.im_type_out = itype.proxy_name;
+
+ List<MethodInfo> virtual_method_list;
+ ClassDB::get_virtual_methods(type_cname, &virtual_method_list, true);
+
+ List<MethodInfo> method_list;
+ ClassDB::get_method_list(type_cname, &method_list, true);
+ method_list.sort();
+
+ for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
+ const MethodInfo &method_info = E->get();
+
+ int argc = method_info.arguments.size();
+
+ if (method_info.name.empty())
+ continue;
+
+ MethodInterface imethod;
+ imethod.name = method_info.name;
+
+ if (method_info.flags & METHOD_FLAG_VIRTUAL)
+ imethod.is_virtual = true;
+
+ PropertyInfo return_info = method_info.return_val;
+
+ MethodBind *m = imethod.is_virtual ? NULL : ClassDB::get_method(type_cname, method_info.name);
+
+ imethod.is_vararg = m && m->is_vararg();
+
+ if (!m && !imethod.is_virtual) {
+ if (virtual_method_list.find(method_info)) {
+ // A virtual method without the virtual flag. This is a special case.
+
+ // This type of method can only be found in Object derived types.
+ ERR_FAIL_COND(!itype.is_object_type);
+
+ // There is no method bind, so let's fallback to Godot's object.Call(string, params)
+ imethod.requires_object_call = true;
+
+ // The method Object.free is registered as a virtual method, but without the virtual flag.
+ // This is because this method is not supposed to be overridden, but called.
+ // We assume the return type is void.
+ imethod.return_type = "void";
+
+ // Actually, more methods like this may be added in the future,
+ // which could actually will return something differnet.
+ // Let's put this to notify us if that ever happens.
+ if (itype.name != "Object" || imethod.name != "free") {
+ WARN_PRINTS("Notification: New unexpected virtual non-overridable method found.\n"
+ "We only expected Object.free, but found " +
+ itype.name + "." + imethod.name);
+ }
+ } else {
+ ERR_PRINTS("Missing MethodBind for non-virtual method: " + itype.name + "." + imethod.name);
+ }
+ } else if (return_info.type == Variant::INT && return_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ //imethod.return_type = return_info.class_name;
+ imethod.return_type = "int";
+ } else if (return_info.class_name != StringName()) {
+ imethod.return_type = return_info.class_name;
+ } else if (return_info.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ imethod.return_type = return_info.hint_string;
+ } else if (return_info.type == Variant::NIL && return_info.usage & PROPERTY_USAGE_NIL_IS_VARIANT) {
+ imethod.return_type = "Variant";
+ } else if (return_info.type == Variant::NIL) {
+ imethod.return_type = "void";
+ } else {
+ imethod.return_type = Variant::get_type_name(return_info.type);
+ }
+
+ if (!itype.requires_collections && imethod.return_type == "Dictionary")
+ itype.requires_collections = true;
+
+ for (int i = 0; i < argc; i++) {
+ PropertyInfo arginfo = method_info.arguments[i];
+
+ ArgumentInterface iarg;
+ iarg.name = arginfo.name;
+
+ if (arginfo.type == Variant::INT && arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
+ //iarg.type = arginfo.class_name;
+ iarg.type = "int";
+ } else if (arginfo.class_name != StringName()) {
+ iarg.type = arginfo.class_name;
+ } else if (arginfo.hint == PROPERTY_HINT_RESOURCE_TYPE) {
+ iarg.type = arginfo.hint_string;
+ } else if (arginfo.type == Variant::NIL) {
+ iarg.type = "Variant";
+ } else {
+ iarg.type = Variant::get_type_name(arginfo.type);
+ }
+
+ iarg.name = escape_csharp_keyword(snake_to_camel_case(iarg.name));
+
+ if (!itype.requires_collections && iarg.type == "Dictionary")
+ itype.requires_collections = true;
+
+ if (m && m->has_default_argument(i)) {
+ _default_argument_from_variant(m->get_default_argument(i), iarg);
+ }
+
+ imethod.add_argument(iarg);
+ }
+
+ if (imethod.is_vararg) {
+ ArgumentInterface ivararg;
+ ivararg.type = "VarArg";
+ ivararg.name = "@args";
+ imethod.add_argument(ivararg);
+ }
+
+ imethod.proxy_name = escape_csharp_keyword(snake_to_pascal_case(imethod.name));
+
+ // Prevent naming the property and its enclosing type from sharing the same name
+ if (imethod.proxy_name == itype.proxy_name) {
+ if (verbose_output) {
+ WARN_PRINTS("Name of method `" + imethod.proxy_name + "` is ambiguous with the name of its class `" +
+ itype.proxy_name + "`. Renaming method to `" + imethod.proxy_name + "_`");
+ }
+
+ imethod.proxy_name += "_";
+ }
+
+ if (itype.class_doc) {
+ for (int i = 0; i < itype.class_doc->methods.size(); i++) {
+ if (itype.class_doc->methods[i].name == imethod.name) {
+ imethod.method_doc = &itype.class_doc->methods[i];
+ break;
+ }
+ }
+ }
+
+ if (!imethod.is_virtual && imethod.name[0] == '_') {
+ const Vector<DocData::PropertyDoc> &properties = itype.class_doc->properties;
+
+ for (int i = 0; i < properties.size(); i++) {
+ const DocData::PropertyDoc &prop_doc = properties[i];
+
+ if (prop_doc.getter == imethod.name || prop_doc.setter == imethod.name) {
+ imethod.is_internal = true;
+ itype.methods.push_back(imethod);
+ break;
+ }
+ }
+ } else {
+ itype.methods.push_back(imethod);
+ }
+ }
+
+ obj_types.insert(itype.name, itype);
+
+ class_list.pop_front();
+ }
+}
+
+void BindingsGenerator::_default_argument_from_variant(const Variant &p_val, ArgumentInterface &r_iarg) {
+
+ r_iarg.default_argument = p_val;
+
+ switch (p_val.get_type()) {
+ case Variant::NIL:
+ if (ClassDB::class_exists(r_iarg.type)) {
+ // Object type
+ r_iarg.default_argument = "null";
+ } else {
+ // Variant
+ r_iarg.default_argument = "null";
+ }
+ break;
+ // Atomic types
+ case Variant::BOOL:
+ r_iarg.default_argument = bool(p_val) ? "true" : "false";
+ break;
+ case Variant::INT:
+ break; // Keep it
+ case Variant::REAL:
+#ifndef REAL_T_IS_DOUBLE
+ r_iarg.default_argument += "f";
+#endif
+ break;
+ case Variant::STRING:
+ case Variant::NODE_PATH:
+ r_iarg.default_argument = "\"" + r_iarg.default_argument + "\"";
+ break;
+ case Variant::TRANSFORM:
+ if (p_val.operator Transform() == Transform())
+ r_iarg.default_argument.clear();
+ r_iarg.default_argument = "new %s(" + r_iarg.default_argument + ")";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ break;
+ case Variant::PLANE:
+ case Variant::RECT3:
+ case Variant::COLOR:
+ r_iarg.default_argument = "new Color(1, 1, 1, 1)";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ break;
+ case Variant::VECTOR2:
+ case Variant::RECT2:
+ case Variant::VECTOR3:
+ r_iarg.default_argument = "new %s" + r_iarg.default_argument;
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ break;
+ case Variant::OBJECT:
+ if (p_val.is_zero()) {
+ r_iarg.default_argument = "null";
+ break;
+ }
+ case Variant::DICTIONARY:
+ case Variant::_RID:
+ r_iarg.default_argument = "new %s()";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+ break;
+ case Variant::ARRAY:
+ case Variant::POOL_BYTE_ARRAY:
+ case Variant::POOL_INT_ARRAY:
+ case Variant::POOL_REAL_ARRAY:
+ case Variant::POOL_STRING_ARRAY:
+ case Variant::POOL_VECTOR2_ARRAY:
+ case Variant::POOL_VECTOR3_ARRAY:
+ case Variant::POOL_COLOR_ARRAY:
+ r_iarg.default_argument = "new %s {}";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+ break;
+ case Variant::TRANSFORM2D:
+ case Variant::BASIS:
+ case Variant::QUAT:
+ r_iarg.default_argument = Variant::get_type_name(p_val.get_type()) + ".Identity";
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_VAL;
+ break;
+ default: {}
+ }
+
+ if (r_iarg.def_param_mode == ArgumentInterface::CONSTANT && r_iarg.type == "Variant" && r_iarg.default_argument != "null")
+ r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
+}
+
+void BindingsGenerator::_populate_builtin_type_interfaces() {
+
+ builtin_types.clear();
+
+ TypeInterface itype;
+
+#define INSERT_STRUCT_TYPE(m_type, m_type_in) \
+ { \
+ itype = TypeInterface::create_value_type(#m_type); \
+ itype.c_in = "\tMARSHALLED_IN(" #m_type ", %1, %1_in);\n"; \
+ itype.c_out = "\tMARSHALLED_OUT(" #m_type ", %1, ret_out)\n" \
+ "\treturn mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(%2), ret_out);\n"; \
+ itype.c_arg_in = "&%s_in"; \
+ itype.c_type_in = m_type_in; \
+ itype.cs_in = "ref %s"; \
+ itype.cs_out = "return (" #m_type ")%0;"; \
+ itype.im_type_out = "object"; \
+ builtin_types.insert(#m_type, itype); \
+ }
+
+ INSERT_STRUCT_TYPE(Vector2, "real_t*")
+ INSERT_STRUCT_TYPE(Rect2, "real_t*")
+ INSERT_STRUCT_TYPE(Transform2D, "real_t*")
+ INSERT_STRUCT_TYPE(Vector3, "real_t*")
+ INSERT_STRUCT_TYPE(Basis, "real_t*")
+ INSERT_STRUCT_TYPE(Quat, "real_t*")
+ INSERT_STRUCT_TYPE(Transform, "real_t*")
+ INSERT_STRUCT_TYPE(Rect3, "real_t*")
+ INSERT_STRUCT_TYPE(Color, "real_t*")
+ INSERT_STRUCT_TYPE(Plane, "real_t*")
+
+#undef INSERT_STRUCT_TYPE
+
+#define INSERT_PRIMITIVE_TYPE(m_type) \
+ { \
+ itype = TypeInterface::create_value_type(#m_type); \
+ itype.c_arg_in = "&%s"; \
+ itype.c_type_in = #m_type; \
+ itype.c_type_out = #m_type; \
+ itype.im_type_in = #m_type; \
+ itype.im_type_out = #m_type; \
+ builtin_types.insert(#m_type, itype); \
+ }
+
+ INSERT_PRIMITIVE_TYPE(bool)
+ //INSERT_PRIMITIVE_TYPE(int)
+
+ // int
+ itype = TypeInterface::create_value_type("int");
+ itype.c_arg_in = "&%s_in";
+ //* ptrcall only supports int64_t and uint64_t
+ itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+ itype.c_out = "\treturn (%0)%1;\n";
+ itype.c_type = "int64_t";
+ //*/
+ itype.c_type_in = itype.name;
+ itype.c_type_out = itype.name;
+ itype.im_type_in = itype.name;
+ itype.im_type_out = itype.name;
+ builtin_types.insert(itype.name, itype);
+
+#undef INSERT_PRIMITIVE_TYPE
+
+ // real_t
+ itype = TypeInterface();
+#ifdef REAL_T_IS_DOUBLE
+ itype.name = "double";
+#else
+ itype.name = "float";
+#endif
+ itype.proxy_name = itype.name;
+ itype.c_arg_in = "&%s_in";
+ //* ptrcall only supports double
+ itype.c_in = "\t%0 %1_in = (%0)%1;\n";
+ itype.c_out = "\treturn (%0)%1;\n";
+ itype.c_type = "double";
+ //*/
+ itype.c_type_in = "real_t";
+ itype.c_type_out = "real_t";
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = itype.proxy_name;
+ itype.im_type_out = itype.proxy_name;
+ builtin_types.insert(itype.name, itype);
+
+ // String
+ itype = TypeInterface();
+ itype.name = "String";
+ itype.proxy_name = "string";
+ itype.c_in = "\t%0 %1_in = " C_METHOD_MONOSTR_TO_GODOT "(%1);\n";
+ itype.c_out = "\treturn " C_METHOD_MONOSTR_FROM_GODOT "(%1);\n";
+ itype.c_arg_in = "&%s_in";
+ itype.c_type = itype.name;
+ itype.c_type_in = "MonoString*";
+ itype.c_type_out = "MonoString*";
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = itype.proxy_name;
+ itype.im_type_out = itype.proxy_name;
+ builtin_types.insert(itype.name, itype);
+
+ // NodePath
+ itype = TypeInterface();
+ itype.name = "NodePath";
+ itype.proxy_name = "NodePath";
+ itype.c_out = "\treturn memnew(NodePath(%1));\n";
+ itype.c_type = itype.name;
+ itype.c_type_in = itype.c_type + "*";
+ itype.c_type_out = itype.c_type + "*";
+ itype.cs_type = itype.proxy_name;
+ itype.cs_in = "NodePath." CS_SMETHOD_GETINSTANCE "(%0)";
+ itype.cs_out = "return new NodePath(%0);";
+ itype.im_type_in = "IntPtr";
+ itype.im_type_out = "IntPtr";
+ _populate_builtin_type(itype, Variant::NODE_PATH);
+ extra_members.insert(itype.name, MEMBER_BEGIN "public NodePath() : this(string.Empty) {}\n" MEMBER_BEGIN "public NodePath(string path)\n" OPEN_BLOCK_L2
+ "this." BINDINGS_PTR_FIELD " = NativeCalls.godot_icall_NodePath_Ctor(path);\n" CLOSE_BLOCK_L2
+ MEMBER_BEGIN "public static implicit operator NodePath(string from)\n" OPEN_BLOCK_L2 "return new NodePath(from);\n" CLOSE_BLOCK_L2
+ MEMBER_BEGIN "public static implicit operator string(NodePath from)\n" OPEN_BLOCK_L2
+ "return NativeCalls." ICALL_PREFIX "NodePath_operator_String(NodePath." CS_SMETHOD_GETINSTANCE "(from));\n" CLOSE_BLOCK_L2);
+ builtin_types.insert(itype.name, itype);
+
+ // RID
+ itype = TypeInterface();
+ itype.name = "RID";
+ itype.proxy_name = "RID";
+ itype.c_out = "\treturn memnew(RID(%1));\n";
+ itype.c_type = itype.name;
+ itype.c_type_in = itype.c_type + "*";
+ itype.c_type_out = itype.c_type + "*";
+ itype.cs_type = itype.proxy_name;
+ itype.cs_in = "RID." CS_SMETHOD_GETINSTANCE "(%0)";
+ itype.cs_out = "return new RID(%0);";
+ itype.im_type_in = "IntPtr";
+ itype.im_type_out = "IntPtr";
+ _populate_builtin_type(itype, Variant::_RID);
+ extra_members.insert(itype.name, MEMBER_BEGIN "internal RID()\n" OPEN_BLOCK_L2
+ "this." BINDINGS_PTR_FIELD " = IntPtr.Zero;\n" CLOSE_BLOCK_L2);
+ builtin_types.insert(itype.name, itype);
+
+ // Variant
+ itype = TypeInterface();
+ itype.name = "Variant";
+ itype.proxy_name = "object";
+ itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_VARIANT "(%1);\n";
+ itype.c_out = "\treturn " C_METHOD_MANAGED_FROM_VARIANT "(%1);\n";
+ itype.c_arg_in = "&%s_in";
+ itype.c_type = itype.name;
+ itype.c_type_in = "MonoObject*";
+ itype.c_type_out = "MonoObject*";
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = "object";
+ itype.im_type_out = itype.proxy_name;
+ builtin_types.insert(itype.name, itype);
+
+ // VarArg (fictitious type to represent variable arguments)
+ itype = TypeInterface();
+ itype.name = "VarArg";
+ itype.proxy_name = "object[]";
+ itype.c_in = "\t%0 %1_in = " C_METHOD_MONOARRAY_TO(Array) "(%1);\n";
+ itype.c_arg_in = "&%s_in";
+ itype.c_type = "Array";
+ itype.c_type_in = "MonoArray*";
+ itype.cs_type = "params object[]";
+ itype.im_type_in = "object[]";
+ builtin_types.insert(itype.name, itype);
+
+#define INSERT_ARRAY_FULL(m_name, m_type, m_proxy_t) \
+ { \
+ itype = TypeInterface(); \
+ itype.name = #m_name; \
+ itype.proxy_name = #m_proxy_t "[]"; \
+ itype.c_in = "\t%0 %1_in = " C_METHOD_MONOARRAY_TO(m_type) "(%1);\n"; \
+ itype.c_out = "\treturn " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \
+ itype.c_arg_in = "&%s_in"; \
+ itype.c_type = #m_type; \
+ itype.c_type_in = "MonoArray*"; \
+ itype.c_type_out = "MonoArray*"; \
+ itype.cs_type = itype.proxy_name; \
+ itype.im_type_in = itype.proxy_name; \
+ itype.im_type_out = itype.proxy_name; \
+ builtin_types.insert(itype.name, itype); \
+ }
+
+#define INSERT_ARRAY(m_type, m_proxy_t) INSERT_ARRAY_FULL(m_type, m_type, m_proxy_t)
+
+ INSERT_ARRAY(Array, object);
+ INSERT_ARRAY(PoolIntArray, int);
+ INSERT_ARRAY_FULL(PoolByteArray, PoolByteArray, byte);
+
+#ifdef REAL_T_IS_DOUBLE
+ INSERT_ARRAY(PoolRealArray, double);
+#else
+ INSERT_ARRAY(PoolRealArray, float);
+#endif
+
+ INSERT_ARRAY(PoolStringArray, string);
+
+ INSERT_ARRAY(PoolColorArray, Color);
+ INSERT_ARRAY(PoolVector2Array, Vector2);
+ INSERT_ARRAY(PoolVector3Array, Vector3);
+
+#undef INSERT_ARRAY
+
+ // Dictionary
+ itype = TypeInterface();
+ itype.name = "Dictionary";
+ itype.proxy_name = "Dictionary<object, object>";
+ itype.c_in = "\t%0 %1_in = " C_METHOD_MANAGED_TO_DICT "(%1);\n";
+ itype.c_out = "\treturn " C_METHOD_MANAGED_FROM_DICT "(%1);\n";
+ itype.c_arg_in = "&%s_in";
+ itype.c_type = itype.name;
+ itype.c_type_in = "MonoObject*";
+ itype.c_type_out = "MonoObject*";
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = itype.proxy_name;
+ itype.im_type_out = itype.proxy_name;
+ builtin_types.insert(itype.name, itype);
+
+ // void (fictitious type to represent the return type of methods that do not return anything)
+ itype = TypeInterface();
+ itype.name = "void";
+ itype.proxy_name = itype.name;
+ itype.c_type = itype.name;
+ itype.c_type_in = itype.c_type;
+ itype.c_type_out = itype.c_type;
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = itype.proxy_name;
+ itype.im_type_out = itype.proxy_name;
+ builtin_types.insert(itype.name, itype);
+
+ // Error
+ itype = TypeInterface();
+ itype.name = "Error";
+ itype.proxy_name = "Error";
+ itype.c_type = itype.name;
+ itype.c_type_in = itype.c_type;
+ itype.c_type_out = itype.c_type;
+ itype.cs_type = itype.proxy_name;
+ itype.cs_in = "(int)%0";
+ itype.cs_out = "return (Error)%s;";
+ itype.im_type_in = "int";
+ itype.im_type_out = "int";
+ builtin_types.insert(itype.name, itype);
+}
+
+void BindingsGenerator::_populate_builtin_type(TypeInterface &r_itype, Variant::Type vtype) {
+
+ Variant::CallError cerror;
+ Variant v = Variant::construct(vtype, NULL, 0, cerror);
+
+ List<MethodInfo> method_list;
+ v.get_method_list(&method_list);
+ method_list.sort();
+
+ for (List<MethodInfo>::Element *E = method_list.front(); E; E = E->next()) {
+ MethodInfo &mi = E->get();
+ MethodInterface imethod;
+
+ imethod.name = mi.name;
+ imethod.proxy_name = mi.name;
+
+ for (int i = 0; i < mi.arguments.size(); i++) {
+ ArgumentInterface iarg;
+ PropertyInfo pi = mi.arguments[i];
+
+ iarg.name = pi.name;
+
+ if (pi.type == Variant::NIL)
+ iarg.type = "Variant";
+ else
+ iarg.type = Variant::get_type_name(pi.type);
+
+ if (!r_itype.requires_collections && iarg.type == "Dictionary")
+ r_itype.requires_collections = true;
+
+ if ((mi.default_arguments.size() - mi.arguments.size() + i) >= 0)
+ _default_argument_from_variant(Variant::construct(pi.type, NULL, 0, cerror), iarg);
+
+ imethod.add_argument(iarg);
+ }
+
+ if (mi.return_val.type == Variant::NIL) {
+ if (mi.return_val.name != "")
+ imethod.return_type = "Variant";
+ } else {
+ imethod.return_type = Variant::get_type_name(mi.return_val.type);
+ }
+
+ if (!r_itype.requires_collections && imethod.return_type == "Dictionary")
+ r_itype.requires_collections = true;
+
+ if (r_itype.class_doc) {
+ for (int i = 0; i < r_itype.class_doc->methods.size(); i++) {
+ if (r_itype.class_doc->methods[i].name == imethod.name) {
+ imethod.method_doc = &r_itype.class_doc->methods[i];
+ break;
+ }
+ }
+ }
+
+ r_itype.methods.push_back(imethod);
+ }
+}
+
+BindingsGenerator::BindingsGenerator() {
+
+ EditorHelp::generate_doc();
+
+ _populate_object_type_interfaces();
+ _populate_builtin_type_interfaces();
+ _generate_header_icalls();
+
+ for (Map<String, TypeInterface>::Element *E = obj_types.front(); E; E = E->next())
+ _generate_method_icalls(E->get());
+
+ _generate_method_icalls(builtin_types["NodePath"]);
+ _generate_method_icalls(builtin_types["RID"]);
+}
+
+void BindingsGenerator::handle_cmdline_args(const List<String> &p_cmdline_args) {
+
+ int options_count = 3;
+
+ String mono_glue_option = "--generate-mono-glue";
+ String cs_core_api_option = "--generate-cs-core-api";
+ String cs_editor_api_option = "--generate-cs-editor-api";
+
+ verbose_output = true;
+
+ const List<String>::Element *elem = p_cmdline_args.front();
+
+ while (elem && options_count) {
+
+ if (elem->get() == mono_glue_option) {
+
+ const List<String>::Element *path_elem = elem->next();
+
+ if (path_elem) {
+ get_singleton().generate_glue(path_elem->get());
+ elem = elem->next();
+ } else {
+ ERR_PRINTS("--generate-mono-glue: No output directory specified");
+ }
+
+ --options_count;
+
+ } else if (elem->get() == cs_core_api_option) {
+
+ const List<String>::Element *path_elem = elem->next();
+
+ if (path_elem) {
+ get_singleton().generate_cs_core_project(path_elem->get());
+ elem = elem->next();
+ } else {
+ ERR_PRINTS(cs_core_api_option + ": No output directory specified");
+ }
+
+ --options_count;
+
+ } else if (elem->get() == cs_editor_api_option) {
+
+ const List<String>::Element *path_elem = elem->next();
+
+ if (path_elem) {
+ if (path_elem->next()) {
+ get_singleton().generate_cs_editor_project(path_elem->get(), path_elem->next()->get());
+ elem = path_elem->next();
+ } else {
+ ERR_PRINTS(cs_editor_api_option + ": No hint path for the Core API dll specified");
+ }
+ } else {
+ ERR_PRINTS(cs_editor_api_option + ": No output directory specified");
+ }
+
+ --options_count;
+ }
+
+ elem = elem->next();
+ }
+
+ verbose_output = false;
+}
+
+#endif
diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h
new file mode 100644
index 0000000000..437a566556
--- /dev/null
+++ b/modules/mono/editor/bindings_generator.h
@@ -0,0 +1,429 @@
+/*************************************************************************/
+/* bindings_generator.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 BINDINGS_GENERATOR_H
+#define BINDINGS_GENERATOR_H
+
+#include "class_db.h"
+#include "editor/doc/doc_data.h"
+#include "editor/editor_help.h"
+
+#ifdef DEBUG_METHODS_ENABLED
+
+#include "ustring.h"
+
+class BindingsGenerator {
+ struct ArgumentInterface {
+ enum DefaultParamMode {
+ CONSTANT,
+ NULLABLE_VAL,
+ NULLABLE_REF
+ };
+
+ String type;
+ String name;
+ String default_argument;
+ DefaultParamMode def_param_mode;
+
+ ArgumentInterface() {
+ def_param_mode = CONSTANT;
+ }
+ };
+
+ struct MethodInterface {
+ String name;
+
+ /**
+ * Name of the C# method
+ */
+ String proxy_name;
+
+ /**
+ * [TypeInterface::name] of the return type
+ */
+ String return_type;
+
+ /**
+ * Determines if the method has a variable number of arguments (VarArg)
+ */
+ bool is_vararg;
+
+ /**
+ * Virtual methods ("virtual" as defined by the Godot API) are methods that by default do nothing,
+ * but can be overridden by the user to add custom functionality.
+ * e.g.: _ready, _process, etc.
+ */
+ bool is_virtual;
+
+ /**
+ * Determines if the call should fallback to Godot's object.Call(string, params) in C#.
+ */
+ bool requires_object_call;
+
+ /**
+ * Determines if the method visibility is `internal` (visible only to files in the same assembly).
+ * Currently, we only use this for methods that are not meant to be exposed,
+ * but are required by properties as getters or setters.
+ * Methods that are not meant to be exposed are those that begin with underscore and are not virtual.
+ */
+ bool is_internal;
+
+ List<ArgumentInterface> arguments;
+
+ const DocData::MethodDoc *method_doc;
+
+ void add_argument(const ArgumentInterface &argument) {
+ arguments.push_back(argument);
+ }
+
+ MethodInterface() {
+ return_type = "void";
+ is_vararg = false;
+ is_virtual = false;
+ requires_object_call = false;
+ is_internal = false;
+ method_doc = NULL;
+ }
+ };
+
+ struct TypeInterface {
+ /**
+ * Identifier name for this type.
+ * Also used to format [c_out].
+ */
+ String name;
+
+ /**
+ * Identifier name of the base class.
+ */
+ String base_name;
+
+ /**
+ * Name of the C# class
+ */
+ String proxy_name;
+
+ ClassDB::APIType api_type;
+
+ bool is_object_type;
+ bool is_singleton;
+ bool is_reference;
+
+ /**
+ * Used only by Object-derived types.
+ * Determines if this type is not virtual (incomplete).
+ * e.g.: CanvasItem cannot be instantiated.
+ */
+ bool is_instantiable;
+
+ /**
+ * Used only by Object-derived types.
+ * Determines if the C# class owns the native handle and must free it somehow when disposed.
+ * e.g.: Reference types must notify when the C# instance is disposed, for proper refcounting.
+ */
+ bool memory_own;
+
+ /**
+ * Determines if the file must have a using directive for System.Collections.Generic
+ * e.g.: When the generated class makes use of Dictionary
+ */
+ bool requires_collections;
+
+ // !! The comments of the following fields make reference to other fields via square brackets, e.g.: [field_name]
+ // !! When renaming those fields, make sure to rename their references in the comments
+
+ // --- C INTERFACE ---
+
+ static const char *DEFAULT_VARARG_C_IN;
+
+ /**
+ * One or more statements that manipulate the parameter before being passed as argument of a ptrcall.
+ * If the statement adds a local that must be passed as the argument instead of the parameter,
+ * the name of that local must be specified with [c_arg_in].
+ * For variadic methods, this field is required and, if empty, [DEFAULT_VARARG_C_IN] is used instead.
+ * Formatting elements:
+ * %0: [c_type] of the parameter
+ * %1: name of the parameter
+ */
+ String c_in;
+
+ /**
+ * Determines the name of the variable that will be passed as argument to a ptrcall.
+ * By default the value equals the name of the parameter,
+ * this varies for types that require special manipulation via [c_in].
+ * Formatting elements:
+ * %0 or %s: name of the parameter
+ */
+ String c_arg_in;
+
+ /**
+ * One or more statements that determine how a variable of this type is returned from a function.
+ * It must contain the return statement(s).
+ * Formatting elements:
+ * %0: [c_type_out] of the return type
+ * %1: name of the variable to be returned
+ * %2: [name] of the return type
+ */
+ String c_out;
+
+ /**
+ * The actual expected type, as seen (in most cases) in Variant copy constructors
+ * Used for the type of the return variable and to format [c_in].
+ * The value must be the following depending of the type:
+ * Object-derived types: Object*
+ * Other types: [name]
+ * -- Exceptions --
+ * VarArg (fictitious type to represent variable arguments): Array
+ * float: double (because ptrcall only supports double)
+ * int: int64_t (because ptrcall only supports int64_t and uint64_t)
+ * Reference types override this for the type of the return variable: Ref<Reference>
+ */
+ String c_type;
+
+ /**
+ * Determines the type used for parameters in function signatures.
+ */
+ String c_type_in;
+
+ /**
+ * Determines the return type used for function signatures.
+ * Also used to construct a default value to return in case of errors,
+ * and to format [c_out].
+ */
+ String c_type_out;
+
+ // --- C# INTERFACE ---
+
+ /**
+ * An expression that overrides the way the parameter is passed to the internal call.
+ * If empty, the parameter is passed as is.
+ * Formatting elements:
+ * %0 or %s: name of the parameter
+ */
+ String cs_in;
+
+ /**
+ * One or more statements that determine how a variable of this type is returned from a method.
+ * It must contain the return statement(s).
+ * Formatting elements:
+ * %0 or %s: name of the variable to be returned
+ */
+ String cs_out;
+
+ /**
+ * Type used for method signatures, both for parameters and the return type.
+ * Same as [proxy_name] except for variable arguments (VarArg).
+ */
+ String cs_type;
+
+ /**
+ * Type used for parameters of internal call methods.
+ */
+ String im_type_in;
+
+ /**
+ * Type used for the return type of internal call methods.
+ * If [cs_out] is not empty and the method return type is not void,
+ * it is also used for the type of the return variable.
+ */
+ String im_type_out;
+
+ const DocData::ClassDoc *class_doc;
+
+ List<MethodInterface> methods;
+
+ const MethodInterface *find_method_by_name(const String &p_name) const {
+
+ for (const List<MethodInterface>::Element *E = methods.front(); E; E = E->next()) {
+ if (E->get().name == p_name)
+ return &E->get();
+ }
+
+ return NULL;
+ }
+
+ static TypeInterface create_value_type(const String &p_name) {
+ TypeInterface itype;
+
+ itype.name = p_name;
+ itype.proxy_name = p_name;
+
+ itype.c_type = itype.name;
+ itype.c_type_in = "void*";
+ itype.c_type_out = "MonoObject*";
+ itype.cs_type = itype.proxy_name;
+ itype.im_type_in = "ref " + itype.proxy_name;
+ itype.im_type_out = itype.proxy_name;
+ itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
+
+ return itype;
+ }
+
+ static TypeInterface create_object_type(const String &p_name, ClassDB::APIType p_api_type) {
+ TypeInterface itype;
+
+ itype.name = p_name;
+ itype.proxy_name = p_name.begins_with("_") ? p_name.substr(1, p_name.length()) : p_name;
+ itype.api_type = p_api_type;
+ itype.is_object_type = true;
+ itype.class_doc = &EditorHelp::get_doc_data()->class_list[itype.proxy_name];
+
+ return itype;
+ }
+
+ static void create_placeholder_type(TypeInterface &r_itype, const String &p_name) {
+ r_itype.name = p_name;
+ r_itype.proxy_name = p_name;
+
+ r_itype.c_type = r_itype.name;
+ r_itype.c_type_in = "MonoObject*";
+ r_itype.c_type_out = "MonoObject*";
+ r_itype.cs_type = r_itype.proxy_name;
+ r_itype.im_type_in = r_itype.proxy_name;
+ r_itype.im_type_out = r_itype.proxy_name;
+ }
+
+ TypeInterface() {
+
+ api_type = ClassDB::API_NONE;
+
+ is_object_type = false;
+ is_singleton = false;
+ is_reference = false;
+ is_instantiable = false;
+
+ memory_own = false;
+ requires_collections = false;
+
+ c_arg_in = "%s";
+
+ class_doc = NULL;
+ }
+ };
+
+ struct InternalCall {
+ String name;
+ String im_type_out; // Return type for the C# method declaration. Also used as companion of [unique_siq]
+ String im_sig; // Signature for the C# method declaration
+ String unique_sig; // Unique signature to avoid duplicates in containers
+ bool editor_only;
+
+ InternalCall() {}
+
+ InternalCall(const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
+ name = p_name;
+ im_type_out = p_im_type_out;
+ im_sig = p_im_sig;
+ unique_sig = p_unique_sig;
+ editor_only = false;
+ }
+
+ InternalCall(ClassDB::APIType api_type, const String &p_name, const String &p_im_type_out, const String &p_im_sig = String(), const String &p_unique_sig = String()) {
+ name = p_name;
+ im_type_out = p_im_type_out;
+ im_sig = p_im_sig;
+ unique_sig = p_unique_sig;
+ editor_only = api_type == ClassDB::API_EDITOR;
+ }
+
+ inline bool operator==(const InternalCall &p_a) const {
+ return p_a.unique_sig == unique_sig;
+ }
+ };
+
+ static bool verbose_output;
+
+ Map<String, TypeInterface> placeholder_types;
+ Map<String, TypeInterface> builtin_types;
+ Map<String, TypeInterface> obj_types;
+
+ Map<String, String> extra_members;
+
+ List<InternalCall> method_icalls;
+ Map<const MethodInterface *, const InternalCall *> method_icalls_map;
+
+ List<InternalCall> core_custom_icalls;
+ List<InternalCall> editor_custom_icalls;
+
+ const List<InternalCall>::Element *find_icall_by_name(const String &p_name, const List<InternalCall> &p_list) {
+
+ const List<InternalCall>::Element *it = p_list.front();
+ while (it) {
+ if (it->get().name == p_name) return it;
+ it = it->next();
+ }
+ return NULL;
+ }
+
+ inline String get_unique_sig(const TypeInterface &p_type) {
+ if (p_type.is_reference)
+ return "Ref";
+ else if (p_type.is_object_type)
+ return "Obj";
+
+ return p_type.name;
+ }
+
+ void _generate_header_icalls();
+ void _generate_method_icalls(const TypeInterface &p_itype);
+
+ const TypeInterface *_get_type_by_name_or_null(const String &p_name);
+ const TypeInterface *_get_type_by_name_or_placeholder(const String &p_name);
+
+ void _default_argument_from_variant(const Variant &p_var, ArgumentInterface &r_iarg);
+ void _populate_builtin_type(TypeInterface &r_type, Variant::Type vtype);
+
+ void _populate_object_type_interfaces();
+ void _populate_builtin_type_interfaces();
+
+ Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file);
+
+ Error _save_file(const String &path, const List<String> &content);
+
+ BindingsGenerator();
+
+ BindingsGenerator(const BindingsGenerator &);
+ BindingsGenerator &operator=(const BindingsGenerator &);
+
+public:
+ Error generate_cs_core_project(const String &p_output_dir, bool p_verbose_output = true);
+ Error generate_cs_editor_project(const String &p_output_dir, const String &p_core_dll_path, bool p_verbose_output = true);
+ Error generate_glue(const String &p_output_dir);
+
+ static BindingsGenerator &get_singleton() {
+ static BindingsGenerator singleton;
+ return singleton;
+ }
+
+ static void handle_cmdline_args(const List<String> &p_cmdline_args);
+};
+
+#endif
+
+#endif // BINDINGS_GENERATOR_H
diff --git a/modules/mono/editor/csharp_project.cpp b/modules/mono/editor/csharp_project.cpp
new file mode 100644
index 0000000000..bde5f0fd0b
--- /dev/null
+++ b/modules/mono/editor/csharp_project.cpp
@@ -0,0 +1,120 @@
+/*************************************************************************/
+/* csharp_project.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "csharp_project.h"
+
+#include "os/os.h"
+#include "project_settings.h"
+
+#include "../mono_gd/gd_mono_class.h"
+#include "../mono_gd/gd_mono_marshal.h"
+
+namespace CSharpProject {
+
+String generate_core_api_project(const String &p_dir, const Vector<String> &p_files) {
+
+ _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
+
+ GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectGenerator");
+
+ Variant dir = p_dir;
+ Variant compile_items = p_files;
+ const Variant *args[2] = { &dir, &compile_items };
+ MonoObject *ex = NULL;
+ MonoObject *ret = klass->get_method("GenCoreApiProject", 2)->invoke(NULL, args, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL_V(String());
+ }
+
+ return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : "";
+}
+
+String generate_editor_api_project(const String &p_dir, const String &p_core_dll_path, const Vector<String> &p_files) {
+
+ _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
+
+ GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectGenerator");
+
+ Variant dir = p_dir;
+ Variant core_dll_path = p_core_dll_path;
+ Variant compile_items = p_files;
+ const Variant *args[3] = { &dir, &core_dll_path, &compile_items };
+ MonoObject *ex = NULL;
+ MonoObject *ret = klass->get_method("GenEditorApiProject", 3)->invoke(NULL, args, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL_V(String());
+ }
+
+ return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : "";
+}
+
+String generate_game_project(const String &p_dir, const String &p_name, const Vector<String> &p_files) {
+
+ _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
+
+ GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectGenerator");
+
+ Variant dir = p_dir;
+ Variant name = p_name;
+ Variant compile_items = p_files;
+ const Variant *args[3] = { &dir, &name, &compile_items };
+ MonoObject *ex = NULL;
+ MonoObject *ret = klass->get_method("GenGameProject", 3)->invoke(NULL, args, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL_V(String());
+ }
+
+ return ret ? GDMonoMarshal::mono_string_to_godot((MonoString *)ret) : "";
+}
+
+void add_item(const String &p_project_path, const String &p_item_type, const String &p_include) {
+
+ _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
+
+ GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Project", "ProjectUtils");
+
+ Variant project_path = p_project_path;
+ Variant item_type = p_item_type;
+ Variant include = p_include;
+ const Variant *args[3] = { &project_path, &item_type, &include };
+ MonoObject *ex = NULL;
+ klass->get_method("AddItemToProjectChecked", 3)->invoke(NULL, args, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL();
+ }
+}
+} // CSharpProject
diff --git a/modules/mono/editor/csharp_project.h b/modules/mono/editor/csharp_project.h
new file mode 100644
index 0000000000..4832d2251e
--- /dev/null
+++ b/modules/mono/editor/csharp_project.h
@@ -0,0 +1,44 @@
+/*************************************************************************/
+/* csharp_project.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 CSHARP_PROJECT_H
+#define CSHARP_PROJECT_H
+
+#include "ustring.h"
+
+namespace CSharpProject {
+
+String generate_core_api_project(const String &p_dir, const Vector<String> &p_files = Vector<String>());
+String generate_editor_api_project(const String &p_dir, const String &p_core_dll_path, const Vector<String> &p_files = Vector<String>());
+String generate_game_project(const String &p_dir, const String &p_name, const Vector<String> &p_files = Vector<String>());
+
+void add_item(const String &p_project_path, const String &p_item_type, const String &p_include);
+}
+
+#endif // CSHARP_PROJECT_H
diff --git a/modules/mono/editor/godotsharp_builds.cpp b/modules/mono/editor/godotsharp_builds.cpp
new file mode 100644
index 0000000000..e7d9c83421
--- /dev/null
+++ b/modules/mono/editor/godotsharp_builds.cpp
@@ -0,0 +1,440 @@
+/*************************************************************************/
+/* godotsharp_builds.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "godotsharp_builds.h"
+
+#include "../godotsharp_dirs.h"
+#include "../mono_gd/gd_mono_class.h"
+#include "../mono_gd/gd_mono_marshal.h"
+#include "../utils/path_utils.h"
+#include "bindings_generator.h"
+#include "godotsharp_editor.h"
+#include "main/main.h"
+
+void godot_icall_BuildInstance_ExitCallback(MonoString *p_solution, MonoString *p_config, int p_exit_code) {
+
+ String solution = GDMonoMarshal::mono_string_to_godot(p_solution);
+ String config = GDMonoMarshal::mono_string_to_godot(p_config);
+ GodotSharpBuilds::get_singleton()->build_exit_callback(MonoBuildInfo(solution, config), p_exit_code);
+}
+
+MonoString *godot_icall_BuildInstance_get_MSBuildPath() {
+
+ GodotSharpBuilds::BuildTool build_tool = GodotSharpBuilds::BuildTool(int(EditorSettings::get_singleton()->get("mono/builds/build_tool")));
+
+#ifdef WINDOWS_ENABLED
+ switch (build_tool) {
+ case GodotSharpBuilds::MSBUILD: {
+ static String msbuild_tools_path = MonoRegUtils::find_msbuild_tools_path();
+
+ if (msbuild_tools_path.length()) {
+ if (!msbuild_tools_path.ends_with("\\"))
+ msbuild_tools_path += "\\";
+
+ return GDMonoMarshal::mono_string_from_godot(msbuild_tools_path + "MSBuild.exe");
+ }
+
+ OS::get_singleton()->print("Cannot find System's MSBuild. Trying with Mono's...\n");
+ }
+ case GodotSharpBuilds::MSBUILD_MONO: {
+ String msbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("msbuild.bat");
+
+ if (!FileAccess::exists(msbuild_path)) {
+ WARN_PRINTS("Cannot find msbuild ('mono/builds/build_tool'). Tried with path: " + msbuild_path);
+ }
+
+ return GDMonoMarshal::mono_string_from_godot(msbuild_path);
+ }
+ case GodotSharpBuilds::XBUILD: {
+ String xbuild_path = GDMono::get_singleton()->get_mono_reg_info().bin_dir.plus_file("xbuild.bat");
+
+ if (!FileAccess::exists(xbuild_path)) {
+ WARN_PRINTS("Cannot find xbuild ('mono/builds/build_tool'). Tried with path: " + xbuild_path);
+ }
+
+ return GDMonoMarshal::mono_string_from_godot(xbuild_path);
+ }
+ default:
+ ERR_EXPLAIN("You don't deserve to live");
+ CRASH_NOW();
+ }
+#else
+ static bool msbuild_found = path_which("msbuild").length();
+
+ if (build_tool != GodotSharpBuilds::XBUILD && !msbuild_found) {
+ WARN_PRINT("Cannot find msbuild ('mono/builds/build_tool').");
+ }
+
+ return GDMonoMarshal::mono_string_from_godot(build_tool != GodotSharpBuilds::XBUILD ? "msbuild" : "xbuild");
+#endif
+}
+
+void GodotSharpBuilds::_register_internal_calls() {
+
+ mono_add_internal_call("GodotSharpTools.Build.BuildSystem::godot_icall_BuildInstance_ExitCallback", (void *)godot_icall_BuildInstance_ExitCallback);
+ mono_add_internal_call("GodotSharpTools.Build.BuildInstance::godot_icall_BuildInstance_get_MSBuildPath", (void *)godot_icall_BuildInstance_get_MSBuildPath);
+}
+
+void GodotSharpBuilds::show_build_error_dialog(const String &p_message) {
+
+ GodotSharpEditor::get_singleton()->show_error_dialog(p_message, "Build error");
+ MonoBottomPanel::get_singleton()->show_build_tab();
+}
+
+bool GodotSharpBuilds::build_api_sln(const String &p_name, const String &p_api_sln_dir, const String &p_config) {
+
+ String api_sln_file = p_api_sln_dir.plus_file(p_name + ".sln");
+ String api_assembly_dir = p_api_sln_dir.plus_file("bin").plus_file(p_config);
+ String api_assembly_file = api_assembly_dir.plus_file(p_name + ".dll");
+
+ if (!FileAccess::exists(api_assembly_file)) {
+ MonoBuildInfo api_build_info(api_sln_file, p_config);
+ api_build_info.custom_props.push_back("NoWarn=1591"); // Ignore missing documentation warnings
+
+ if (!GodotSharpBuilds::get_singleton()->build(api_build_info)) {
+ show_build_error_dialog("Failed to build " + p_name + " solution.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool GodotSharpBuilds::copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name) {
+
+ String assembly_file = p_assembly_name + ".dll";
+ String assembly_src = p_src_dir.plus_file(assembly_file);
+ String assembly_dst = p_dst_dir.plus_file(assembly_file);
+
+ if (!FileAccess::exists(assembly_dst) || FileAccess::get_modified_time(assembly_src) > FileAccess::get_modified_time(assembly_dst)) {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+
+ String xml_file = p_assembly_name + ".xml";
+ if (da->copy(p_src_dir.plus_file(xml_file), p_dst_dir.plus_file(xml_file)) != OK)
+ WARN_PRINTS("Failed to copy " + xml_file);
+
+ String pdb_file = p_assembly_name + ".pdb";
+ if (da->copy(p_src_dir.plus_file(pdb_file), p_dst_dir.plus_file(pdb_file)) != OK)
+ WARN_PRINTS("Failed to copy " + pdb_file);
+
+ Error err = da->copy(assembly_src, assembly_dst);
+
+ memdelete(da);
+
+ if (err != OK) {
+ show_build_error_dialog("Failed to copy " API_ASSEMBLY_NAME ".dll");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool GodotSharpBuilds::make_api_sln(GodotSharpBuilds::APIType p_api_type) {
+
+ String api_name = p_api_type == API_CORE ? API_ASSEMBLY_NAME : EDITOR_API_ASSEMBLY_NAME;
+ String api_build_config = "Release";
+
+ EditorProgress pr("mono_build_release_" + api_name, "Building " + api_name + " solution...", 4);
+
+ pr.step("Generating " + api_name + " solution");
+
+ uint64_t core_hash = GDMono::get_singleton()->get_api_core_hash();
+ uint64_t editor_hash = GDMono::get_singleton()->get_api_editor_hash();
+
+ String core_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir().plus_file(API_ASSEMBLY_NAME "_" + itos(core_hash));
+ String editor_api_sln_dir = GodotSharpDirs::get_mono_solutions_dir().plus_file(EDITOR_API_ASSEMBLY_NAME "_" + itos(editor_hash));
+
+ String api_sln_dir = p_api_type == API_CORE ? core_api_sln_dir : editor_api_sln_dir;
+ String api_sln_file = api_sln_dir.plus_file(api_name + ".sln");
+
+ if (!DirAccess::exists(api_sln_dir) || !FileAccess::exists(api_sln_file)) {
+ String core_api_assembly;
+
+ if (p_api_type == API_EDITOR) {
+ core_api_assembly = core_api_sln_dir.plus_file("bin")
+ .plus_file(api_build_config)
+ .plus_file(API_ASSEMBLY_NAME ".dll");
+ }
+
+#ifndef DEBUG_METHODS_ENABLED
+#error "How am I supposed to generate the bindings?"
+#endif
+
+ BindingsGenerator &gen = BindingsGenerator::get_singleton();
+ bool gen_verbose = OS::get_singleton()->is_stdout_verbose();
+
+ Error err = p_api_type == API_CORE ?
+ gen.generate_cs_core_project(api_sln_dir, gen_verbose) :
+ gen.generate_cs_editor_project(api_sln_dir, core_api_assembly, gen_verbose);
+
+ if (err != OK) {
+ show_build_error_dialog("Failed to generate " + api_name + " solution. Error: " + itos(err));
+ return false;
+ }
+ }
+
+ pr.step("Building " + api_name + " solution");
+
+ if (!GodotSharpBuilds::build_api_sln(api_name, api_sln_dir, api_build_config))
+ return false;
+
+ pr.step("Copying " + api_name + " assembly");
+
+ String res_assemblies_dir = GodotSharpDirs::get_res_assemblies_dir();
+
+ // Create assemblies directory if needed
+ if (!DirAccess::exists(res_assemblies_dir)) {
+ DirAccess *da = DirAccess::create_for_path(res_assemblies_dir);
+ Error err = da->make_dir_recursive(res_assemblies_dir);
+ memdelete(da);
+
+ if (err != OK) {
+ show_build_error_dialog("Failed to create assemblies directory. Error: " + itos(err));
+ return false;
+ }
+ }
+
+ // Copy the built assembly to the assemblies directory
+ String api_assembly_dir = api_sln_dir.plus_file("bin").plus_file(api_build_config);
+ if (!GodotSharpBuilds::copy_api_assembly(api_assembly_dir, res_assemblies_dir, api_name))
+ return false;
+
+ pr.step("Done");
+
+ return true;
+}
+
+bool godotsharp_build_callback() {
+
+ if (!FileAccess::exists(GodotSharpDirs::get_project_sln_path()))
+ return true; // No solution to build
+
+ if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_CORE))
+ return false;
+
+ if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR))
+ return false;
+
+ EditorProgress pr("mono_project_debug_build", "Building project solution...", 2);
+
+ pr.step("Building project solution");
+
+ MonoBuildInfo build_info(GodotSharpDirs::get_project_sln_path(), "Tools");
+ if (!GodotSharpBuilds::get_singleton()->build(build_info)) {
+ GodotSharpBuilds::show_build_error_dialog("Failed to build project solution");
+ return false;
+ }
+
+ pr.step("Done");
+
+ return true;
+}
+
+GodotSharpBuilds *GodotSharpBuilds::singleton = NULL;
+
+void GodotSharpBuilds::build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code) {
+
+ BuildProcess *match = builds.getptr(p_build_info);
+ ERR_FAIL_COND(!match);
+
+ BuildProcess &bp = *match;
+ bp.on_exit(p_exit_code);
+}
+
+void GodotSharpBuilds::restart_build(MonoBuildTab *p_build_tab) {
+}
+
+void GodotSharpBuilds::stop_build(MonoBuildTab *p_build_tab) {
+}
+
+bool GodotSharpBuilds::build(const MonoBuildInfo &p_build_info) {
+
+ BuildProcess *match = builds.getptr(p_build_info);
+
+ if (match) {
+ BuildProcess &bp = *match;
+ bp.start(true);
+ return bp.exit_code == 0;
+ } else {
+ BuildProcess bp = BuildProcess(p_build_info);
+ bp.start(true);
+ builds.set(p_build_info, bp);
+ return bp.exit_code == 0;
+ }
+}
+
+bool GodotSharpBuilds::build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback) {
+
+ BuildProcess *match = builds.getptr(p_build_info);
+
+ if (match) {
+ BuildProcess &bp = *match;
+ bp.start();
+ return !bp.exited; // failed to start
+ } else {
+ BuildProcess bp = BuildProcess(p_build_info, p_callback);
+ bp.start();
+ builds.set(p_build_info, bp);
+ return !bp.exited; // failed to start
+ }
+}
+
+GodotSharpBuilds::GodotSharpBuilds() {
+
+ singleton = this;
+
+ EditorNode::get_singleton()->add_build_callback(&godotsharp_build_callback);
+
+ // Build tool settings
+ EditorSettings *ed_settings = EditorSettings::get_singleton();
+ if (!ed_settings->has("mono/builds/build_tool")) {
+ ed_settings->set("mono/builds/build_tool", MSBUILD);
+ }
+ ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/builds/build_tool", PROPERTY_HINT_ENUM, "MSBuild (System),MSBuild (Mono),xbuild"));
+}
+
+GodotSharpBuilds::~GodotSharpBuilds() {
+
+ singleton = NULL;
+}
+
+void GodotSharpBuilds::BuildProcess::on_exit(int p_exit_code) {
+
+ exited = true;
+ exit_code = p_exit_code;
+ build_tab->on_build_exit(p_exit_code == 0 ? MonoBuildTab::RESULT_SUCCESS : MonoBuildTab::RESULT_ERROR);
+ build_instance.unref();
+
+ if (exit_callback)
+ exit_callback(exit_code);
+}
+
+void GodotSharpBuilds::BuildProcess::start(bool p_blocking) {
+
+ _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
+
+ exit_code = -1;
+
+ String logs_dir = GodotSharpDirs::get_build_logs_dir().plus_file(build_info.solution.md5_text() + "_" + build_info.configuration);
+
+ if (build_tab) {
+ build_tab->on_build_start();
+ } else {
+ build_tab = memnew(MonoBuildTab(build_info, logs_dir));
+ MonoBottomPanel::get_singleton()->add_build_tab(build_tab);
+ }
+
+ if (p_blocking) {
+ // Required in order to update the build tasks list
+ Main::iteration();
+ }
+
+ if (!exited) {
+ ERR_PRINT("BuildProcess::start called, but process still running");
+ exited = true;
+ build_tab->on_build_exec_failed("!exited");
+ return;
+ }
+
+ exited = false;
+
+ // Remove old issues file
+
+ String issues_file = "msbuild_issues.csv";
+ DirAccessRef d = DirAccess::create_for_path(logs_dir);
+ if (d->file_exists(issues_file)) {
+ Error err = d->remove(issues_file);
+ if (err != OK) {
+ ERR_PRINTS("Cannot remove file: " + logs_dir.plus_file(issues_file));
+ exited = true;
+ build_tab->on_build_exec_failed("Cannot remove file: " + issues_file);
+ return;
+ }
+ }
+
+ GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Build", "BuildInstance");
+
+ MonoObject *mono_object = mono_object_new(mono_domain_get(), klass->get_raw());
+
+ // Construct
+
+ Variant solution = build_info.solution;
+ Variant config = build_info.configuration;
+
+ const Variant *ctor_args[2] = { &solution, &config };
+
+ MonoObject *ex = NULL;
+ GDMonoMethod *ctor = klass->get_method(".ctor", 2);
+ ctor->invoke(mono_object, ctor_args, &ex);
+
+ if (ex) {
+ exited = true;
+ build_tab->on_build_exec_failed("The build constructor threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex));
+ ERR_FAIL();
+ }
+
+ // Call Build
+
+ Variant logger_assembly = OS::get_singleton()->get_executable_path().get_base_dir().plus_file(EDITOR_TOOLS_ASSEMBLY_NAME) + ".dll";
+ Variant logger_output_dir = logs_dir;
+ Variant custom_props = build_info.custom_props;
+
+ const Variant *args[3] = { &logger_assembly, &logger_output_dir, &custom_props };
+
+ ex = NULL;
+ GDMonoMethod *build_method = klass->get_method(p_blocking ? "Build" : "BuildAsync", 3);
+ build_method->invoke(mono_object, args, &ex);
+
+ if (ex) {
+ exited = true;
+ build_tab->on_build_exec_failed("The build method threw an exception.\n" + GDMonoUtils::get_exception_name_and_message(ex));
+ ERR_FAIL();
+ }
+
+ // Build returned
+
+ if (p_blocking) {
+ exited = true;
+ exit_code = klass->get_field("exitCode")->get_int_value(mono_object);
+ build_tab->on_build_exit(exit_code == 0 ? MonoBuildTab::RESULT_SUCCESS : MonoBuildTab::RESULT_ERROR);
+ } else {
+ build_instance = MonoGCHandle::create_strong(mono_object);
+ exited = false;
+ }
+}
+
+GodotSharpBuilds::BuildProcess::BuildProcess(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback) {
+
+ build_info = p_build_info;
+ build_tab = NULL;
+ exit_callback = p_callback;
+ exited = true;
+ exit_code = -1;
+}
diff --git a/modules/mono/editor/godotsharp_builds.h b/modules/mono/editor/godotsharp_builds.h
new file mode 100644
index 0000000000..6d5fa3b44a
--- /dev/null
+++ b/modules/mono/editor/godotsharp_builds.h
@@ -0,0 +1,96 @@
+/*************************************************************************/
+/* godotsharp_builds.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 GODOTSHARP_BUILDS_H
+#define GODOTSHARP_BUILDS_H
+
+#include "mono_bottom_panel.h"
+#include "mono_build_info.h"
+
+typedef void (*GodotSharpBuild_ExitCallback)(int);
+
+class GodotSharpBuilds {
+
+private:
+ struct BuildProcess {
+ Ref<MonoGCHandle> build_instance;
+ MonoBuildInfo build_info;
+ MonoBuildTab *build_tab;
+ GodotSharpBuild_ExitCallback exit_callback;
+ bool exited;
+ int exit_code;
+
+ void on_exit(int p_exit_code);
+ void start(bool p_blocking = false);
+
+ BuildProcess() {}
+ BuildProcess(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback = NULL);
+ };
+
+ HashMap<MonoBuildInfo, BuildProcess, MonoBuildInfo::Hasher> builds;
+
+ static GodotSharpBuilds *singleton;
+
+ friend class GDMono;
+ static void _register_internal_calls();
+
+public:
+ enum APIType {
+ API_CORE,
+ API_EDITOR
+ };
+
+ enum BuildTool {
+ MSBUILD,
+ MSBUILD_MONO,
+ XBUILD
+ };
+
+ _FORCE_INLINE_ static GodotSharpBuilds *get_singleton() { return singleton; }
+
+ static void show_build_error_dialog(const String &p_message);
+
+ void build_exit_callback(const MonoBuildInfo &p_build_info, int p_exit_code);
+
+ void restart_build(MonoBuildTab *p_build_tab);
+ void stop_build(MonoBuildTab *p_build_tab);
+
+ bool build(const MonoBuildInfo &p_build_info);
+ bool build_async(const MonoBuildInfo &p_build_info, GodotSharpBuild_ExitCallback p_callback = NULL);
+
+ static bool build_api_sln(const String &p_name, const String &p_api_sln_dir, const String &p_config);
+ static bool copy_api_assembly(const String &p_src_dir, const String &p_dst_dir, const String &p_assembly_name);
+
+ static bool make_api_sln(APIType p_api_type);
+
+ GodotSharpBuilds();
+ ~GodotSharpBuilds();
+};
+
+#endif // GODOTSHARP_BUILDS_H
diff --git a/modules/mono/editor/godotsharp_editor.cpp b/modules/mono/editor/godotsharp_editor.cpp
new file mode 100644
index 0000000000..5aaf029495
--- /dev/null
+++ b/modules/mono/editor/godotsharp_editor.cpp
@@ -0,0 +1,256 @@
+/*************************************************************************/
+/* godotsharp_editor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "godotsharp_editor.h"
+
+#include "core/os/os.h"
+#include "core/project_settings.h"
+#include "scene/gui/control.h"
+#include "scene/main/node.h"
+
+#include "../csharp_script.h"
+#include "../godotsharp_dirs.h"
+#include "../mono_gd/gd_mono.h"
+#include "../utils/path_utils.h"
+#include "bindings_generator.h"
+#include "csharp_project.h"
+#include "net_solution.h"
+
+#ifdef WINDOWS_ENABLED
+#include "../utils/mono_reg_utils.h"
+#endif
+
+class MonoReloadNode : public Node {
+ GDCLASS(MonoReloadNode, Node)
+
+protected:
+ void _notification(int p_what) {
+ switch (p_what) {
+ case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
+ CSharpLanguage::get_singleton()->reload_assemblies_if_needed(true);
+ } break;
+ default: {
+ } break;
+ };
+ }
+};
+
+GodotSharpEditor *GodotSharpEditor::singleton = NULL;
+
+bool GodotSharpEditor::_create_project_solution() {
+
+ EditorProgress pr("create_csharp_solution", "Generating solution...", 2);
+
+ pr.step("Generating C# project...");
+
+ String path = OS::get_singleton()->get_resource_dir();
+ String name = ProjectSettings::get_singleton()->get("application/config/name");
+ String guid = CSharpProject::generate_game_project(path, name);
+
+ if (guid.length()) {
+
+ NETSolution solution(name);
+
+ if (!solution.set_path(path)) {
+ show_error_dialog("Failed to create solution.");
+ return false;
+ }
+
+ Vector<String> extra_configs;
+ extra_configs.push_back("Tools");
+
+ solution.add_new_project(name, guid, extra_configs);
+
+ Error sln_error = solution.save();
+
+ if (sln_error != OK) {
+ show_error_dialog("Failed to save solution.");
+ return false;
+ }
+
+ if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_CORE))
+ return false;
+
+ if (!GodotSharpBuilds::make_api_sln(GodotSharpBuilds::API_EDITOR))
+ return false;
+
+ pr.step("Done");
+
+ // Here, after all calls to progress_task_step
+ call_deferred("_remove_create_sln_menu_option");
+
+ } else {
+ show_error_dialog("Failed to create C# project.");
+ }
+
+ return true;
+}
+
+void GodotSharpEditor::_remove_create_sln_menu_option() {
+
+ menu_popup->remove_item(menu_popup->get_item_index(MENU_CREATE_SLN));
+
+ if (menu_popup->get_item_count() == 0)
+ menu_button->hide();
+
+ bottom_panel_btn->show();
+}
+
+void GodotSharpEditor::_menu_option_pressed(int p_id) {
+
+ switch (p_id) {
+ case MENU_CREATE_SLN: {
+
+ _create_project_solution();
+ } break;
+ default:
+ ERR_FAIL();
+ }
+}
+
+void GodotSharpEditor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_create_project_solution"), &GodotSharpEditor::_create_project_solution);
+ ClassDB::bind_method(D_METHOD("_remove_create_sln_menu_option"), &GodotSharpEditor::_remove_create_sln_menu_option);
+ ClassDB::bind_method(D_METHOD("_menu_option_pressed", "id"), &GodotSharpEditor::_menu_option_pressed);
+}
+
+void GodotSharpEditor::show_error_dialog(const String &p_message, const String &p_title) {
+
+ error_dialog->set_title(p_title);
+ error_dialog->set_text(p_message);
+ error_dialog->popup_centered_minsize();
+}
+
+Error GodotSharpEditor::open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) {
+
+ ExternalEditor editor = ExternalEditor(int(EditorSettings::get_singleton()->get("mono/editor/external_editor")));
+
+ switch (editor) {
+ case EDITOR_CODE: {
+ List<String> args;
+ args.push_back(ProjectSettings::get_singleton()->get_resource_path());
+
+ String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path());
+
+ if (p_line >= 0) {
+ args.push_back("-g");
+ args.push_back(script_path + ":" + itos(p_line) + ":" + itos(p_col));
+ } else {
+ args.push_back(script_path);
+ }
+
+ static String program = path_which("code");
+
+ Error err = OS::get_singleton()->execute(program.length() ? program : "code", args, false);
+
+ if (err != OK) {
+ ERR_PRINT("GodotSharp: Could not execute external editor");
+ return err;
+ }
+ } break;
+ case EDITOR_MONODEVELOP: {
+ if (!monodevel_instance)
+ monodevel_instance = memnew(MonoDevelopInstance(GodotSharpDirs::get_project_sln_path()));
+
+ String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path());
+ monodevel_instance->execute(script_path);
+ } break;
+ case EDITOR_VISUAL_STUDIO:
+ // TODO
+ // devenv <PathToSolutionFolder>
+ // devenv /edit <PathToCsFile> /command "edit.goto <Line>"
+ // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\SxS\VS7
+ default:
+ return ERR_UNAVAILABLE;
+ }
+
+ return OK;
+}
+
+bool GodotSharpEditor::overrides_external_editor() {
+
+ return ExternalEditor(int(EditorSettings::get_singleton()->get("mono/editor/external_editor"))) != EDITOR_NONE;
+}
+
+GodotSharpEditor::GodotSharpEditor(EditorNode *p_editor) {
+
+ singleton = this;
+
+ monodevel_instance = NULL;
+
+ editor = p_editor;
+
+ error_dialog = memnew(AcceptDialog);
+ editor->get_gui_base()->add_child(error_dialog);
+
+ bottom_panel_btn = editor->add_bottom_panel_item("Mono", memnew(MonoBottomPanel(editor)));
+
+ godotsharp_builds = memnew(GodotSharpBuilds);
+
+ editor->add_child(memnew(MonoReloadNode));
+
+ menu_button = memnew(MenuButton);
+ menu_button->set_text("Mono");
+ menu_popup = menu_button->get_popup();
+
+ String sln_path = GodotSharpDirs::get_project_sln_path();
+ String csproj_path = GodotSharpDirs::get_project_csproj_path();
+
+ if (!FileAccess::exists(sln_path) || !FileAccess::exists(csproj_path)) {
+ bottom_panel_btn->hide();
+ menu_popup->add_item("Create C# solution", MENU_CREATE_SLN);
+ }
+
+ menu_popup->connect("id_pressed", this, "_menu_option_pressed");
+
+ if (menu_popup->get_item_count() == 0)
+ menu_button->hide();
+
+ editor->get_menu_hb()->add_child(menu_button);
+
+ // External editor settings
+ EditorSettings *ed_settings = EditorSettings::get_singleton();
+ if (!ed_settings->has("mono/editor/external_editor")) {
+ ed_settings->set("mono/editor/external_editor", EDITOR_NONE);
+ }
+ ed_settings->add_property_hint(PropertyInfo(Variant::INT, "mono/editor/external_editor", PROPERTY_HINT_ENUM, "None,MonoDevelop,Visual Studio,Visual Studio Code"));
+}
+
+GodotSharpEditor::~GodotSharpEditor() {
+
+ singleton = NULL;
+
+ memdelete(godotsharp_builds);
+
+ if (monodevel_instance) {
+ memdelete(monodevel_instance);
+ monodevel_instance = NULL;
+ }
+}
diff --git a/modules/mono/editor/godotsharp_editor.h b/modules/mono/editor/godotsharp_editor.h
new file mode 100644
index 0000000000..1ecb8c7a94
--- /dev/null
+++ b/modules/mono/editor/godotsharp_editor.h
@@ -0,0 +1,87 @@
+/*************************************************************************/
+/* godotsharp_editor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 GODOTSHARP_EDITOR_H
+#define GODOTSHARP_EDITOR_H
+
+#include "godotsharp_builds.h"
+
+#include "monodevelop_instance.h"
+
+class GodotSharpEditor : public Node {
+ GDCLASS(GodotSharpEditor, Object)
+
+ EditorNode *editor;
+
+ MenuButton *menu_button;
+ PopupMenu *menu_popup;
+
+ AcceptDialog *error_dialog;
+
+ ToolButton *bottom_panel_btn;
+
+ GodotSharpBuilds *godotsharp_builds;
+
+ MonoDevelopInstance *monodevel_instance;
+
+ bool _create_project_solution();
+
+ void _remove_create_sln_menu_option();
+
+ void _menu_option_pressed(int p_id);
+
+ static GodotSharpEditor *singleton;
+
+protected:
+ static void _bind_methods();
+
+public:
+ enum MenuOptions {
+ MENU_CREATE_SLN
+ };
+
+ enum ExternalEditor {
+ EDITOR_NONE,
+ EDITOR_MONODEVELOP,
+ EDITOR_VISUAL_STUDIO,
+ EDITOR_CODE,
+ };
+
+ _FORCE_INLINE_ static GodotSharpEditor *get_singleton() { return singleton; }
+
+ void show_error_dialog(const String &p_message, const String &p_title = "Error");
+
+ Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col);
+ bool overrides_external_editor();
+
+ GodotSharpEditor(EditorNode *p_editor);
+ ~GodotSharpEditor();
+};
+
+#endif // GODOTSHARP_EDITOR_H
diff --git a/modules/mono/editor/mono_bottom_panel.cpp b/modules/mono/editor/mono_bottom_panel.cpp
new file mode 100644
index 0000000000..07109eaac7
--- /dev/null
+++ b/modules/mono/editor/mono_bottom_panel.cpp
@@ -0,0 +1,441 @@
+/*************************************************************************/
+/* mono_bottom_panel.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "mono_bottom_panel.h"
+
+#include "../csharp_script.h"
+#include "godotsharp_editor.h"
+
+MonoBottomPanel *MonoBottomPanel::singleton = NULL;
+
+void MonoBottomPanel::_update_build_tabs_list() {
+
+ build_tabs_list->clear();
+
+ int current_tab = build_tabs->get_current_tab();
+
+ bool no_current_tab = current_tab < 0 || current_tab >= build_tabs->get_tab_count();
+
+ for (int i = 0; i < build_tabs->get_child_count(); i++) {
+
+ MonoBuildTab *tab = Object::cast_to<MonoBuildTab>(build_tabs->get_child(i));
+
+ if (tab) {
+ String item_name = tab->build_info.solution.get_file().get_basename();
+ item_name += " [" + tab->build_info.configuration + "]";
+
+ build_tabs_list->add_item(item_name, tab->get_icon_texture());
+
+ String item_tooltip = String("Solution: ") + tab->build_info.solution;
+ item_tooltip += String("\nConfiguration: ") + tab->build_info.configuration;
+ item_tooltip += String("\nStatus: ");
+
+ if (tab->build_exited) {
+ item_tooltip += tab->build_result == MonoBuildTab::RESULT_SUCCESS ? "Succeeded" : "Errored";
+ } else {
+ item_tooltip += "Running";
+ }
+
+ if (!tab->build_exited || !tab->build_result == MonoBuildTab::RESULT_SUCCESS) {
+ item_tooltip += "\nErrors: " + itos(tab->error_count);
+ }
+
+ item_tooltip += "\nWarnings: " + itos(tab->warning_count);
+
+ build_tabs_list->set_item_tooltip(i, item_tooltip);
+
+ if (no_current_tab || current_tab == i) {
+ build_tabs_list->select(i);
+ _build_tab_item_selected(i);
+ }
+ }
+ }
+}
+
+void MonoBottomPanel::add_build_tab(MonoBuildTab *p_build_tab) {
+
+ build_tabs->add_child(p_build_tab);
+ raise_build_tab(p_build_tab);
+}
+
+void MonoBottomPanel::raise_build_tab(MonoBuildTab *p_build_tab) {
+
+ ERR_FAIL_COND(p_build_tab->get_parent() != build_tabs);
+ build_tabs->move_child(p_build_tab, 0);
+ _update_build_tabs_list();
+}
+
+void MonoBottomPanel::show_build_tab() {
+
+ for (int i = 0; i < panel_tabs->get_tab_count(); i++) {
+ if (panel_tabs->get_tab_control(i) == panel_builds_tab) {
+ panel_tabs->set_current_tab(i);
+ editor->make_bottom_panel_item_visible(this);
+ return;
+ }
+ }
+
+ ERR_PRINT("Builds tab not found");
+}
+
+void MonoBottomPanel::_build_tab_item_selected(int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx, build_tabs->get_tab_count());
+ build_tabs->set_current_tab(p_idx);
+}
+
+void MonoBottomPanel::_build_tab_changed(int p_idx) {
+
+ if (p_idx < 0 || p_idx >= build_tabs->get_tab_count()) {
+ warnings_btn->set_visible(false);
+ errors_btn->set_visible(false);
+ } else {
+ warnings_btn->set_visible(true);
+ errors_btn->set_visible(true);
+ }
+}
+
+void MonoBottomPanel::_warnings_toggled(bool p_pressed) {
+
+ int current_tab = build_tabs->get_current_tab();
+ ERR_FAIL_INDEX(current_tab, build_tabs->get_tab_count());
+ MonoBuildTab *build_tab = Object::cast_to<MonoBuildTab>(build_tabs->get_child(current_tab));
+ build_tab->warnings_visible = p_pressed;
+ build_tab->_update_issues_list();
+}
+
+void MonoBottomPanel::_errors_toggled(bool p_pressed) {
+
+ int current_tab = build_tabs->get_current_tab();
+ ERR_FAIL_INDEX(current_tab, build_tabs->get_tab_count());
+ MonoBuildTab *build_tab = Object::cast_to<MonoBuildTab>(build_tabs->get_child(current_tab));
+ build_tab->errors_visible = p_pressed;
+ build_tab->_update_issues_list();
+}
+
+void MonoBottomPanel::_notification(int p_what) {
+
+ switch (p_what) {
+
+ case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: {
+ panel_tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles"));
+ panel_tabs->add_style_override("tab_fg", editor->get_gui_base()->get_stylebox("DebuggerTabFG", "EditorStyles"));
+ panel_tabs->add_style_override("tab_bg", editor->get_gui_base()->get_stylebox("DebuggerTabBG", "EditorStyles"));
+ } break;
+ }
+}
+
+void MonoBottomPanel::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("_warnings_toggled", "pressed"), &MonoBottomPanel::_warnings_toggled);
+ ClassDB::bind_method(D_METHOD("_errors_toggled", "pressed"), &MonoBottomPanel::_errors_toggled);
+ ClassDB::bind_method(D_METHOD("_build_tab_item_selected", "idx"), &MonoBottomPanel::_build_tab_item_selected);
+ ClassDB::bind_method(D_METHOD("_build_tab_changed", "idx"), &MonoBottomPanel::_build_tab_changed);
+}
+
+MonoBottomPanel::MonoBottomPanel(EditorNode *p_editor) {
+
+ singleton = this;
+
+ editor = p_editor;
+
+ set_v_size_flags(SIZE_EXPAND_FILL);
+ set_anchors_and_margins_preset(Control::PRESET_WIDE);
+
+ panel_tabs = memnew(TabContainer);
+ panel_tabs->set_tab_align(TabContainer::ALIGN_LEFT);
+ panel_tabs->add_style_override("panel", editor->get_gui_base()->get_stylebox("DebuggerPanel", "EditorStyles"));
+ panel_tabs->add_style_override("tab_fg", editor->get_gui_base()->get_stylebox("DebuggerTabFG", "EditorStyles"));
+ panel_tabs->add_style_override("tab_bg", editor->get_gui_base()->get_stylebox("DebuggerTabBG", "EditorStyles"));
+ panel_tabs->set_custom_minimum_size(Size2(0, 228) * EDSCALE);
+ panel_tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(panel_tabs);
+
+ { // Builds
+ panel_builds_tab = memnew(VBoxContainer);
+ panel_builds_tab->set_name(TTR("Builds"));
+ panel_builds_tab->set_h_size_flags(SIZE_EXPAND_FILL);
+ panel_tabs->add_child(panel_builds_tab);
+
+ HBoxContainer *toolbar_hbc = memnew(HBoxContainer);
+ toolbar_hbc->set_h_size_flags(SIZE_EXPAND_FILL);
+ panel_builds_tab->add_child(toolbar_hbc);
+
+ toolbar_hbc->add_spacer();
+
+ warnings_btn = memnew(ToolButton);
+ warnings_btn->set_text("Warnings");
+ warnings_btn->set_toggle_mode(true);
+ warnings_btn->set_pressed(true);
+ warnings_btn->set_visible(false);
+ warnings_btn->set_focus_mode(FOCUS_NONE);
+ warnings_btn->connect("toggled", this, "_warnings_toggled");
+ toolbar_hbc->add_child(warnings_btn);
+
+ errors_btn = memnew(ToolButton);
+ errors_btn->set_text("Errors");
+ errors_btn->set_toggle_mode(true);
+ errors_btn->set_pressed(true);
+ errors_btn->set_visible(false);
+ errors_btn->set_focus_mode(FOCUS_NONE);
+ errors_btn->connect("toggled", this, "_errors_toggled");
+ toolbar_hbc->add_child(errors_btn);
+
+ HSplitContainer *hsc = memnew(HSplitContainer);
+ hsc->set_h_size_flags(SIZE_EXPAND_FILL);
+ hsc->set_v_size_flags(SIZE_EXPAND_FILL);
+ panel_builds_tab->add_child(hsc);
+
+ build_tabs_list = memnew(ItemList);
+ build_tabs_list->set_h_size_flags(SIZE_EXPAND_FILL);
+ build_tabs_list->connect("item_selected", this, "_build_tab_item_selected");
+ hsc->add_child(build_tabs_list);
+
+ build_tabs = memnew(TabContainer);
+ build_tabs->set_tab_align(TabContainer::ALIGN_LEFT);
+ build_tabs->set_h_size_flags(SIZE_EXPAND_FILL);
+ build_tabs->set_tabs_visible(false);
+ build_tabs->connect("tab_changed", this, "_build_tab_changed");
+ hsc->add_child(build_tabs);
+ }
+}
+
+MonoBottomPanel::~MonoBottomPanel() {
+
+ singleton = NULL;
+}
+
+void MonoBuildTab::_load_issues_from_file(const String &p_csv_file) {
+
+ FileAccessRef f = FileAccess::open(p_csv_file, FileAccess::READ);
+
+ if (!f)
+ return;
+
+ while (!f->eof_reached()) {
+ Vector<String> csv_line = f->get_csv_line();
+
+ if (csv_line.size() == 1 && csv_line[0].empty())
+ return;
+
+ ERR_CONTINUE(csv_line.size() != 7);
+
+ BuildIssue issue;
+ issue.warning = csv_line[0] == "warning";
+ issue.file = csv_line[1];
+ issue.line = csv_line[2].to_int();
+ issue.column = csv_line[3].to_int();
+ issue.code = csv_line[4];
+ issue.message = csv_line[5];
+ issue.project_file = csv_line[6];
+
+ if (issue.warning)
+ warning_count += 1;
+ else
+ error_count += 1;
+
+ issues.push_back(issue);
+ }
+}
+
+void MonoBuildTab::_update_issues_list() {
+
+ issues_list->clear();
+
+ Ref<Texture> warning_icon = get_icon("Warning", "EditorIcons");
+ Ref<Texture> error_icon = get_icon("Error", "EditorIcons");
+
+ for (int i = 0; i < issues.size(); i++) {
+
+ const BuildIssue &issue = issues[i];
+
+ if (!(issue.warning ? warnings_visible : errors_visible))
+ continue;
+
+ String tooltip;
+ tooltip += String("Message: ") + issue.message;
+ tooltip += String("\nCode: ") + issue.code;
+ tooltip += String("\nType: ") + (issue.warning ? "warning" : "error");
+
+ String text;
+
+ if (issue.file.length()) {
+ String sline = String::num_int64(issue.line);
+ String scolumn = String::num_int64(issue.column);
+
+ text += issue.file + "(";
+ text += sline + ",";
+ text += scolumn + "): ";
+
+ tooltip += "\nFile: " + issue.file;
+ tooltip += "\nLine: " + sline;
+ tooltip += "\nColumn: " + scolumn;
+ }
+
+ if (issue.project_file.length()) {
+ tooltip += "\nProject: " + issue.project_file;
+ }
+
+ text += issue.message;
+
+ int line_break_idx = text.find("\n");
+ issues_list->add_item(line_break_idx == -1 ? text : text.substr(0, line_break_idx),
+ issue.warning ? warning_icon : error_icon);
+ int index = issues_list->get_item_count() - 1;
+ issues_list->set_item_tooltip(index, tooltip);
+ issues_list->set_item_metadata(index, i);
+ }
+}
+
+Ref<Texture> MonoBuildTab::get_icon_texture() const {
+
+ // FIXME these icons were removed... find something better
+
+ if (build_exited) {
+ if (build_result == RESULT_ERROR) {
+ return get_icon("DependencyChangedHl", "EditorIcons");
+ } else {
+ return get_icon("DependencyOkHl", "EditorIcons");
+ }
+ } else {
+ return get_icon("GraphTime", "EditorIcons");
+ }
+}
+
+MonoBuildInfo MonoBuildTab::get_build_info() {
+
+ return build_info;
+}
+
+void MonoBuildTab::on_build_start() {
+
+ build_exited = false;
+
+ issues.clear();
+ warning_count = 0;
+ error_count = 0;
+ _update_issues_list();
+
+ MonoBottomPanel::get_singleton()->raise_build_tab(this);
+}
+
+void MonoBuildTab::on_build_exit(BuildResult result) {
+
+ build_exited = true;
+ build_result = result;
+
+ _load_issues_from_file(logs_dir.plus_file("msbuild_issues.csv"));
+ _update_issues_list();
+
+ MonoBottomPanel::get_singleton()->raise_build_tab(this);
+}
+
+void MonoBuildTab::on_build_exec_failed(const String &p_cause, const String &p_detailed) {
+
+ build_exited = true;
+ build_result = RESULT_ERROR;
+
+ issues_list->clear();
+
+ String tooltip;
+
+ tooltip += "Message: " + (p_detailed.length() ? p_detailed : p_cause);
+ tooltip += "\nType: error";
+
+ int line_break_idx = p_cause.find("\n");
+ issues_list->add_item(line_break_idx == -1 ? p_cause : p_cause.substr(0, line_break_idx),
+ get_icon("Error", "EditorIcons"));
+ int index = issues_list->get_item_count() - 1;
+ issues_list->set_item_tooltip(index, tooltip);
+
+ MonoBottomPanel::get_singleton()->raise_build_tab(this);
+}
+
+void MonoBuildTab::restart_build() {
+
+ ERR_FAIL_COND(!build_exited);
+ GodotSharpBuilds::get_singleton()->restart_build(this);
+}
+
+void MonoBuildTab::stop_build() {
+
+ ERR_FAIL_COND(build_exited);
+ GodotSharpBuilds::get_singleton()->stop_build(this);
+}
+
+void MonoBuildTab::_issue_activated(int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx, issues.size());
+
+ const BuildIssue &issue = issues[p_idx];
+
+ if (issue.project_file.empty() && issue.file.empty())
+ return;
+
+ String project_dir = issue.project_file.length() ? issue.project_file.get_base_dir() : build_info.solution.get_base_dir();
+
+ String file = project_dir.simplify_path().plus_file(issue.file.simplify_path());
+
+ if (!FileAccess::exists(file))
+ return;
+
+ file = ProjectSettings::get_singleton()->localize_path(file);
+
+ if (file.begins_with("res://")) {
+ Ref<Script> script = ResourceLoader::load(file, CSharpLanguage::get_singleton()->get_type());
+
+ if (script.is_valid() && ScriptEditor::get_singleton()->edit(script, issue.line, issue.column)) {
+ EditorNode::get_singleton()->call("_editor_select", EditorNode::EDITOR_SCRIPT);
+ }
+ }
+}
+
+void MonoBuildTab::_bind_methods() {
+
+ ClassDB::bind_method("_issue_activated", &MonoBuildTab::_issue_activated);
+}
+
+MonoBuildTab::MonoBuildTab(const MonoBuildInfo &p_build_info, const String &p_logs_dir) {
+
+ build_info = p_build_info;
+ logs_dir = p_logs_dir;
+
+ build_exited = false;
+
+ issues_list = memnew(ItemList);
+ issues_list->set_v_size_flags(SIZE_EXPAND_FILL);
+ issues_list->connect("item_activated", this, "_issue_activated");
+ add_child(issues_list);
+
+ error_count = 0;
+ warning_count = 0;
+
+ errors_visible = true;
+ warnings_visible = true;
+}
diff --git a/modules/mono/editor/mono_bottom_panel.h b/modules/mono/editor/mono_bottom_panel.h
new file mode 100644
index 0000000000..909fa4b385
--- /dev/null
+++ b/modules/mono/editor/mono_bottom_panel.h
@@ -0,0 +1,145 @@
+/*************************************************************************/
+/* mono_bottom_panel.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 MONO_BOTTOM_PANEL_H
+#define MONO_BOTTOM_PANEL_H
+
+#include "editor/editor_node.h"
+#include "scene/gui/control.h"
+
+#include "mono_build_info.h"
+
+class MonoBuildTab;
+
+class MonoBottomPanel : public VBoxContainer {
+
+ GDCLASS(MonoBottomPanel, VBoxContainer)
+
+ EditorNode *editor;
+
+ TabContainer *panel_tabs;
+
+ VBoxContainer *panel_builds_tab;
+
+ ItemList *build_tabs_list;
+ TabContainer *build_tabs;
+
+ Button *warnings_btn;
+ Button *errors_btn;
+
+ void _update_build_tabs_list();
+
+ void _build_tab_item_selected(int p_idx);
+ void _build_tab_changed(int p_idx);
+
+ void _warnings_toggled(bool p_pressed);
+ void _errors_toggled(bool p_pressed);
+
+ static MonoBottomPanel *singleton;
+
+protected:
+ void _notification(int p_what);
+
+ static void _bind_methods();
+
+public:
+ _FORCE_INLINE_ static MonoBottomPanel *get_singleton() { return singleton; }
+
+ void add_build_tab(MonoBuildTab *p_build_tab);
+ void raise_build_tab(MonoBuildTab *p_build_tab);
+
+ void show_build_tab();
+
+ MonoBottomPanel(EditorNode *p_editor = NULL);
+ ~MonoBottomPanel();
+};
+
+class MonoBuildTab : public VBoxContainer {
+
+ GDCLASS(MonoBuildTab, VBoxContainer)
+
+public:
+ enum BuildResult {
+ RESULT_ERROR,
+ RESULT_SUCCESS
+ };
+
+ struct BuildIssue {
+ bool warning;
+ String file;
+ int line;
+ int column;
+ String code;
+ String message;
+ String project_file;
+ };
+
+private:
+ friend class MonoBottomPanel;
+
+ bool build_exited;
+ BuildResult build_result;
+
+ Vector<BuildIssue> issues;
+ ItemList *issues_list;
+
+ int error_count;
+ int warning_count;
+
+ bool errors_visible;
+ bool warnings_visible;
+
+ String logs_dir;
+
+ MonoBuildInfo build_info;
+
+ void _load_issues_from_file(const String &p_csv_file);
+ void _update_issues_list();
+
+ void _issue_activated(int p_idx);
+
+protected:
+ static void _bind_methods();
+
+public:
+ Ref<Texture> get_icon_texture() const;
+
+ MonoBuildInfo get_build_info();
+
+ void on_build_start();
+ void on_build_exit(BuildResult result);
+ void on_build_exec_failed(const String &p_cause, const String &p_detailed = String());
+
+ void restart_build();
+ void stop_build();
+
+ MonoBuildTab(const MonoBuildInfo &p_build_info, const String &p_logs_dir);
+};
+
+#endif // MONO_BOTTOM_PANEL_H
diff --git a/modules/mono/editor/mono_build_info.h b/modules/mono/editor/mono_build_info.h
new file mode 100644
index 0000000000..f3b3e43b6d
--- /dev/null
+++ b/modules/mono/editor/mono_build_info.h
@@ -0,0 +1,64 @@
+/*************************************************************************/
+/* mono_build_info.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 MONO_BUILD_INFO_H
+#define MONO_BUILD_INFO_H
+
+#include "../mono_gd/gd_mono_utils.h"
+
+struct MonoBuildInfo {
+
+ struct Hasher {
+ static _FORCE_INLINE_ uint32_t hash(const MonoBuildInfo &p_key) {
+ uint32_t hash = 0;
+
+ GDMonoUtils::hash_combine(hash, p_key.solution.hash());
+ GDMonoUtils::hash_combine(hash, p_key.configuration.hash());
+
+ return hash;
+ }
+ };
+
+ String solution;
+ String configuration;
+ Vector<String> custom_props;
+
+ MonoBuildInfo() {}
+
+ MonoBuildInfo(const String &p_solution, const String &p_config) {
+ solution = p_solution;
+ configuration = p_config;
+ }
+
+ bool operator==(const MonoBuildInfo &p_b) const {
+ return p_b.solution == solution && p_b.configuration == configuration;
+ }
+};
+
+#endif // MONO_BUILD_INFO_H
diff --git a/modules/mono/editor/monodevelop_instance.cpp b/modules/mono/editor/monodevelop_instance.cpp
new file mode 100644
index 0000000000..a34d82ffcb
--- /dev/null
+++ b/modules/mono/editor/monodevelop_instance.cpp
@@ -0,0 +1,81 @@
+/*************************************************************************/
+/* monodevelop_instance.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "monodevelop_instance.h"
+
+#include "../mono_gd/gd_mono.h"
+#include "../mono_gd/gd_mono_class.h"
+
+void MonoDevelopInstance::execute(const Vector<String> &p_files) {
+
+ ERR_FAIL_NULL(execute_method);
+ ERR_FAIL_COND(gc_handle.is_null());
+
+ MonoObject *ex = NULL;
+
+ Variant files = p_files;
+ const Variant *args[1] = { &files };
+ execute_method->invoke(gc_handle->get_target(), args, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL();
+ }
+}
+
+void MonoDevelopInstance::execute(const String &p_file) {
+
+ Vector<String> files;
+ files.push_back(p_file);
+ execute(files);
+}
+
+MonoDevelopInstance::MonoDevelopInstance(const String &p_solution) {
+
+ _GDMONO_SCOPE_DOMAIN_(TOOLS_DOMAIN)
+
+ GDMonoClass *klass = GDMono::get_singleton()->get_editor_tools_assembly()->get_class("GodotSharpTools.Editor", "MonoDevelopInstance");
+
+ MonoObject *obj = mono_object_new(TOOLS_DOMAIN, klass->get_raw());
+
+ GDMonoMethod *ctor = klass->get_method(".ctor", 1);
+ MonoObject *ex = NULL;
+
+ Variant solution = p_solution;
+ const Variant *args[1] = { &solution };
+ ctor->invoke(obj, args, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL();
+ }
+
+ gc_handle = MonoGCHandle::create_strong(obj);
+ execute_method = klass->get_method("Execute", 1);
+}
diff --git a/modules/mono/editor/monodevelop_instance.h b/modules/mono/editor/monodevelop_instance.h
new file mode 100644
index 0000000000..9eb154eba1
--- /dev/null
+++ b/modules/mono/editor/monodevelop_instance.h
@@ -0,0 +1,50 @@
+/*************************************************************************/
+/* monodevelop_instance.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 MONODEVELOP_INSTANCE_H
+#define MONODEVELOP_INSTANCE_H
+
+#include "reference.h"
+
+#include "../mono_gc_handle.h"
+#include "../mono_gd/gd_mono_method.h"
+
+class MonoDevelopInstance {
+
+ Ref<MonoGCHandle> gc_handle;
+ GDMonoMethod *execute_method;
+
+public:
+ void execute(const Vector<String> &p_files);
+ void execute(const String &p_files);
+
+ MonoDevelopInstance(const String &p_solution);
+};
+
+#endif // MONODEVELOP_INSTANCE_H
diff --git a/modules/mono/editor/net_solution.cpp b/modules/mono/editor/net_solution.cpp
new file mode 100644
index 0000000000..fa60c310db
--- /dev/null
+++ b/modules/mono/editor/net_solution.cpp
@@ -0,0 +1,130 @@
+/*************************************************************************/
+/* net_solution.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "net_solution.h"
+
+#include "os/dir_access.h"
+#include "os/file_access.h"
+
+#include "../utils/path_utils.h"
+#include "../utils/string_utils.h"
+#include "csharp_project.h"
+
+#define SOLUTION_TEMPLATE \
+ "Microsoft Visual Studio Solution File, Format Version 12.00\n" \
+ "# Visual Studio 2012\n" \
+ "%0\n" \
+ "Global\n" \
+ "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n" \
+ "%1\n" \
+ "\tEndGlobalSection\n" \
+ "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n" \
+ "%2\n" \
+ "\tEndGlobalSection\n" \
+ "EndGlobal\n"
+
+#define PROJECT_DECLARATION "Project(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"%0\", \"%1\", \"{%2}\"\nEndProject"
+
+#define SOLUTION_PLATFORMS_CONFIG "\t\%0|Any CPU = %0|Any CPU"
+
+#define PROJECT_PLATFORMS_CONFIG \
+ "\t\t{%0}.%1|Any CPU.ActiveCfg = %1|Any CPU\n" \
+ "\t\t{%0}.%1|Any CPU.Build.0 = %1|Any CPU"
+
+void NETSolution::add_new_project(const String &p_name, const String &p_guid, const Vector<String> &p_extra_configs) {
+ if (projects.has(p_name))
+ WARN_PRINT("Overriding existing project.");
+
+ ProjectInfo procinfo;
+ procinfo.guid = p_guid;
+
+ procinfo.configs.push_back("Debug");
+ procinfo.configs.push_back("Release");
+
+ for (int i = 0; i < p_extra_configs.size(); i++) {
+ procinfo.configs.push_back(p_extra_configs[i]);
+ }
+
+ projects[p_name] = procinfo;
+}
+
+Error NETSolution::save() {
+ bool dir_exists = DirAccess::exists(path);
+ ERR_EXPLAIN("The directory does not exist.");
+ ERR_FAIL_COND_V(!dir_exists, ERR_FILE_BAD_PATH);
+
+ String projs_decl;
+ String sln_platform_cfg;
+ String proj_platform_cfg;
+
+ for (Map<String, ProjectInfo>::Element *E = projects.front(); E; E = E->next()) {
+ const String &name = E->key();
+ const ProjectInfo &procinfo = E->value();
+
+ projs_decl += sformat(PROJECT_DECLARATION, name, name + ".csproj", procinfo.guid);
+
+ for (int i = 0; i < procinfo.configs.size(); i++) {
+ const String &config = procinfo.configs[i];
+
+ if (i != 0) {
+ sln_platform_cfg += "\n";
+ proj_platform_cfg += "\n";
+ }
+
+ sln_platform_cfg += sformat(SOLUTION_PLATFORMS_CONFIG, config);
+ proj_platform_cfg += sformat(PROJECT_PLATFORMS_CONFIG, procinfo.guid, config);
+ }
+ }
+
+ String content = sformat(SOLUTION_TEMPLATE, projs_decl, sln_platform_cfg, proj_platform_cfg);
+
+ FileAccessRef file = FileAccess::open(path_join(path, name + ".sln"), FileAccess::WRITE);
+ ERR_FAIL_COND_V(!file, ERR_FILE_CANT_WRITE);
+ file->store_string(content);
+ file->close();
+
+ return OK;
+}
+
+bool NETSolution::set_path(const String &p_existing_path) {
+ if (p_existing_path.is_abs_path()) {
+ path = p_existing_path;
+ } else {
+ String abspath;
+ if (!rel_path_to_abs(p_existing_path, abspath))
+ return false;
+ path = abspath;
+ }
+
+ return true;
+}
+
+NETSolution::NETSolution(const String &p_name) {
+ name = p_name;
+}
diff --git a/modules/mono/editor/net_solution.h b/modules/mono/editor/net_solution.h
new file mode 100644
index 0000000000..d7ccebb7df
--- /dev/null
+++ b/modules/mono/editor/net_solution.h
@@ -0,0 +1,57 @@
+/*************************************************************************/
+/* net_solution.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 NET_SOLUTION_H
+#define NET_SOLUTION_H
+
+#include "map.h"
+#include "ustring.h"
+
+struct NETSolution {
+ String name;
+
+ void add_new_project(const String &p_name, const String &p_guid, const Vector<String> &p_extra_configs = Vector<String>());
+
+ Error save();
+
+ bool set_path(const String &p_existing_path);
+
+ NETSolution(const String &p_name);
+
+private:
+ struct ProjectInfo {
+ String guid;
+ Vector<String> configs;
+ };
+
+ String path;
+ Map<String, ProjectInfo> projects;
+};
+
+#endif // NET_SOLUTION_H
diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs
new file mode 100644
index 0000000000..6a73ebd554
--- /dev/null
+++ b/modules/mono/glue/cs_files/Basis.cs
@@ -0,0 +1,475 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Godot
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Basis : IEquatable<Basis>
+ {
+ private static readonly Basis identity = new Basis
+ (
+ new Vector3(1f, 0f, 0f),
+ new Vector3(0f, 1f, 0f),
+ new Vector3(0f, 0f, 1f)
+ );
+
+ private static readonly Basis[] orthoBases = new Basis[24]
+ {
+ new Basis(1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f),
+ new Basis(0f, -1f, 0f, 1f, 0f, 0f, 0f, 0f, 1f),
+ new Basis(-1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f),
+ new Basis(0f, 1f, 0f, -1f, 0f, 0f, 0f, 0f, 1f),
+ new Basis(1f, 0f, 0f, 0f, 0f, -1f, 0f, 1f, 0f),
+ new Basis(0f, 0f, 1f, 1f, 0f, 0f, 0f, 1f, 0f),
+ new Basis(-1f, 0f, 0f, 0f, 0f, 1f, 0f, 1f, 0f),
+ new Basis(0f, 0f, -1f, -1f, 0f, 0f, 0f, 1f, 0f),
+ new Basis(1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, -1f),
+ new Basis(0f, 1f, 0f, 1f, 0f, 0f, 0f, 0f, -1f),
+ new Basis(-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, -1f),
+ new Basis(0f, -1f, 0f, -1f, 0f, 0f, 0f, 0f, -1f),
+ new Basis(1f, 0f, 0f, 0f, 0f, 1f, 0f, -1f, 0f),
+ new Basis(0f, 0f, -1f, 1f, 0f, 0f, 0f, -1f, 0f),
+ new Basis(-1f, 0f, 0f, 0f, 0f, -1f, 0f, -1f, 0f),
+ new Basis(0f, 0f, 1f, -1f, 0f, 0f, 0f, -1f, 0f),
+ new Basis(0f, 0f, 1f, 0f, 1f, 0f, -1f, 0f, 0f),
+ new Basis(0f, -1f, 0f, 0f, 0f, 1f, -1f, 0f, 0f),
+ new Basis(0f, 0f, -1f, 0f, -1f, 0f, -1f, 0f, 0f),
+ new Basis(0f, 1f, 0f, 0f, 0f, -1f, -1f, 0f, 0f),
+ new Basis(0f, 0f, 1f, 0f, -1f, 0f, 1f, 0f, 0f),
+ new Basis(0f, 1f, 0f, 0f, 0f, 1f, 1f, 0f, 0f),
+ new Basis(0f, 0f, -1f, 0f, 1f, 0f, 1f, 0f, 0f),
+ new Basis(0f, -1f, 0f, 0f, 0f, -1f, 1f, 0f, 0f)
+ };
+
+ public Vector3 x;
+ public Vector3 y;
+ public Vector3 z;
+
+ public static Basis Identity
+ {
+ get { return identity; }
+ }
+
+ public Vector3 Scale
+ {
+ get
+ {
+ return new Vector3
+ (
+ new Vector3(this[0, 0], this[1, 0], this[2, 0]).length(),
+ new Vector3(this[0, 1], this[1, 1], this[2, 1]).length(),
+ new Vector3(this[0, 2], this[1, 2], this[2, 2]).length()
+ );
+ }
+ }
+
+ public Vector3 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ case 2:
+ z = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ public float this[int index, int axis]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x[axis];
+ case 1:
+ return y[axis];
+ case 2:
+ return z[axis];
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x[axis] = value;
+ return;
+ case 1:
+ y[axis] = value;
+ return;
+ case 2:
+ z[axis] = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ internal static Basis create_from_axes(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
+ {
+ return new Basis
+ (
+ new Vector3(xAxis.x, yAxis.x, zAxis.x),
+ new Vector3(xAxis.y, yAxis.y, zAxis.y),
+ new Vector3(xAxis.z, yAxis.z, zAxis.z)
+ );
+ }
+
+ public float determinant()
+ {
+ return this[0, 0] * (this[1, 1] * this[2, 2] - this[2, 1] * this[1, 2]) -
+ this[1, 0] * (this[0, 1] * this[2, 2] - this[2, 1] * this[0, 2]) +
+ this[2, 0] * (this[0, 1] * this[1, 2] - this[1, 1] * this[0, 2]);
+ }
+
+ public Vector3 get_axis(int axis)
+ {
+ return new Vector3(this[0, axis], this[1, axis], this[2, axis]);
+ }
+
+ public Vector3 get_euler()
+ {
+ Basis m = this.orthonormalized();
+
+ Vector3 euler;
+
+ euler.y = Mathf.asin(m.x[2]);
+
+ if (euler.y < Mathf.PI * 0.5f)
+ {
+ if (euler.y > -Mathf.PI * 0.5f)
+ {
+ euler.x = Mathf.atan2(-m.y[2], m.z[2]);
+ euler.z = Mathf.atan2(-m.x[1], m.x[0]);
+ }
+ else
+ {
+ euler.z = 0.0f;
+ euler.x = euler.z - Mathf.atan2(m.y[0], m.y[1]);
+ }
+ }
+ else
+ {
+ euler.z = 0f;
+ euler.x = Mathf.atan2(m.x[1], m.y[1]) - euler.z;
+ }
+
+ return euler;
+ }
+
+ public int get_orthogonal_index()
+ {
+ Basis orth = this;
+
+ for (int i = 0; i < 3; i++)
+ {
+ for (int j = 0; j < 3; j++)
+ {
+ float v = orth[i, j];
+
+ if (v > 0.5f)
+ v = 1.0f;
+ else if (v < -0.5f)
+ v = -1.0f;
+ else
+ v = 0f;
+
+ orth[i, j] = v;
+ }
+ }
+
+ for (int i = 0; i < 24; i++)
+ {
+ if (orthoBases[i] == orth)
+ return i;
+ }
+
+ return 0;
+ }
+
+ public Basis inverse()
+ {
+ Basis inv = this;
+
+ float[] co = new float[3]
+ {
+ inv[1, 1] * inv[2, 2] - inv[1, 2] * inv[2, 1],
+ inv[1, 2] * inv[2, 0] - inv[1, 0] * inv[2, 2],
+ inv[1, 0] * inv[2, 1] - inv[1, 1] * inv[2, 0]
+ };
+
+ float det = inv[0, 0] * co[0] + inv[0, 1] * co[1] + inv[0, 2] * co[2];
+
+ if (det == 0)
+ {
+ return new Basis
+ (
+ float.NaN, float.NaN, float.NaN,
+ float.NaN, float.NaN, float.NaN,
+ float.NaN, float.NaN, float.NaN
+ );
+ }
+
+ float s = 1.0f / det;
+
+ inv = new Basis
+ (
+ co[0] * s,
+ inv[0, 2] * inv[2, 1] - inv[0, 1] * inv[2, 2] * s,
+ inv[0, 1] * inv[1, 2] - inv[0, 2] * inv[1, 1] * s,
+ co[1] * s,
+ inv[0, 0] * inv[2, 2] - inv[0, 2] * inv[2, 0] * s,
+ inv[0, 2] * inv[1, 0] - inv[0, 0] * inv[1, 2] * s,
+ co[2] * s,
+ inv[0, 1] * inv[2, 0] - inv[0, 0] * inv[2, 1] * s,
+ inv[0, 0] * inv[1, 1] - inv[0, 1] * inv[1, 0] * s
+ );
+
+ return inv;
+ }
+
+ public Basis orthonormalized()
+ {
+ Vector3 xAxis = get_axis(0);
+ Vector3 yAxis = get_axis(1);
+ Vector3 zAxis = get_axis(2);
+
+ xAxis.normalize();
+ yAxis = (yAxis - xAxis * (xAxis.dot(yAxis)));
+ yAxis.normalize();
+ zAxis = (zAxis - xAxis * (xAxis.dot(zAxis)) - yAxis * (yAxis.dot(zAxis)));
+ zAxis.normalize();
+
+ return Basis.create_from_axes(xAxis, yAxis, zAxis);
+ }
+
+ public Basis rotated(Vector3 axis, float phi)
+ {
+ return this * new Basis(axis, phi);
+ }
+
+ public Basis scaled(Vector3 scale)
+ {
+ Basis m = this;
+
+ m[0, 0] *= scale.x;
+ m[1, 0] *= scale.x;
+ m[2, 0] *= scale.x;
+ m[0, 1] *= scale.y;
+ m[1, 1] *= scale.y;
+ m[2, 1] *= scale.y;
+ m[0, 2] *= scale.z;
+ m[1, 2] *= scale.z;
+ m[2, 2] *= scale.z;
+
+ return m;
+ }
+
+ public float tdotx(Vector3 with)
+ {
+ return this[0, 0] * with[0] + this[1, 0] * with[1] + this[2, 0] * with[2];
+ }
+
+ public float tdoty(Vector3 with)
+ {
+ return this[0, 1] * with[0] + this[1, 1] * with[1] + this[2, 1] * with[2];
+ }
+
+ public float tdotz(Vector3 with)
+ {
+ return this[0, 2] * with[0] + this[1, 2] * with[1] + this[2, 2] * with[2];
+ }
+
+ public Basis transposed()
+ {
+ Basis tr = this;
+
+ float temp = this[0, 1];
+ this[0, 1] = this[1, 0];
+ this[1, 0] = temp;
+
+ temp = this[0, 2];
+ this[0, 2] = this[2, 0];
+ this[2, 0] = temp;
+
+ temp = this[1, 2];
+ this[1, 2] = this[2, 1];
+ this[2, 1] = temp;
+
+ return tr;
+ }
+
+ public Vector3 xform(Vector3 v)
+ {
+ return new Vector3
+ (
+ this[0].dot(v),
+ this[1].dot(v),
+ this[2].dot(v)
+ );
+ }
+
+ public Vector3 xform_inv(Vector3 v)
+ {
+ return new Vector3
+ (
+ (this[0, 0] * v.x) + (this[1, 0] * v.y) + (this[2, 0] * v.z),
+ (this[0, 1] * v.x) + (this[1, 1] * v.y) + (this[2, 1] * v.z),
+ (this[0, 2] * v.x) + (this[1, 2] * v.y) + (this[2, 2] * v.z)
+ );
+ }
+
+ public Basis(Quat quat)
+ {
+ float s = 2.0f / quat.length_squared();
+
+ float xs = quat.x * s;
+ float ys = quat.y * s;
+ float zs = quat.z * s;
+ float wx = quat.w * xs;
+ float wy = quat.w * ys;
+ float wz = quat.w * zs;
+ float xx = quat.x * xs;
+ float xy = quat.x * ys;
+ float xz = quat.x * zs;
+ float yy = quat.y * ys;
+ float yz = quat.y * zs;
+ float zz = quat.z * zs;
+
+ this.x = new Vector3(1.0f - (yy + zz), xy - wz, xz + wy);
+ this.y = new Vector3(xy + wz, 1.0f - (xx + zz), yz - wx);
+ this.z = new Vector3(xz - wy, yz + wx, 1.0f - (xx + yy));
+ }
+
+ public Basis(Vector3 axis, float phi)
+ {
+ Vector3 axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z);
+
+ float cosine = Mathf.cos(phi);
+ float sine = Mathf.sin(phi);
+
+ this.x = new Vector3
+ (
+ axis_sq.x + cosine * (1.0f - axis_sq.x),
+ axis.x * axis.y * (1.0f - cosine) - axis.z * sine,
+ axis.z * axis.x * (1.0f - cosine) + axis.y * sine
+ );
+
+ this.y = new Vector3
+ (
+ axis.x * axis.y * (1.0f - cosine) + axis.z * sine,
+ axis_sq.y + cosine * (1.0f - axis_sq.y),
+ axis.y * axis.z * (1.0f - cosine) - axis.x * sine
+ );
+
+ this.z = new Vector3
+ (
+ axis.z * axis.x * (1.0f - cosine) - axis.y * sine,
+ axis.y * axis.z * (1.0f - cosine) + axis.x * sine,
+ axis_sq.z + cosine * (1.0f - axis_sq.z)
+ );
+ }
+
+ public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis)
+ {
+ this.x = xAxis;
+ this.y = yAxis;
+ this.z = zAxis;
+ }
+
+ public Basis(float xx, float xy, float xz, float yx, float yy, float yz, float zx, float zy, float zz)
+ {
+ this.x = new Vector3(xx, xy, xz);
+ this.y = new Vector3(yx, yy, yz);
+ this.z = new Vector3(zx, zy, zz);
+ }
+
+ public static Basis operator *(Basis left, Basis right)
+ {
+ return new Basis
+ (
+ right.tdotx(left[0]), right.tdoty(left[0]), right.tdotz(left[0]),
+ right.tdotx(left[1]), right.tdoty(left[1]), right.tdotz(left[1]),
+ right.tdotx(left[2]), right.tdoty(left[2]), right.tdotz(left[2])
+ );
+ }
+
+ public static bool operator ==(Basis left, Basis right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Basis left, Basis right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Basis)
+ {
+ return Equals((Basis)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Basis other)
+ {
+ return x.Equals(other.x) && y.Equals(other.y) && z.Equals(other.z);
+ }
+
+ public override int GetHashCode()
+ {
+ return x.GetHashCode() ^ y.GetHashCode() ^ z.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1}, {2})", new object[]
+ {
+ this.x.ToString(),
+ this.y.ToString(),
+ this.z.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1}, {2})", new object[]
+ {
+ this.x.ToString(format),
+ this.y.ToString(format),
+ this.z.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Color.cs b/modules/mono/glue/cs_files/Color.cs
new file mode 100644
index 0000000000..df88a46832
--- /dev/null
+++ b/modules/mono/glue/cs_files/Color.cs
@@ -0,0 +1,590 @@
+using System;
+
+namespace Godot
+{
+ public struct Color : IEquatable<Color>
+ {
+ public float r;
+ public float g;
+ public float b;
+ public float a;
+
+ public int r8
+ {
+ get
+ {
+ return (int)(r * 255.0f);
+ }
+ }
+
+ public int g8
+ {
+ get
+ {
+ return (int)(g * 255.0f);
+ }
+ }
+
+ public int b8
+ {
+ get
+ {
+ return (int)(b * 255.0f);
+ }
+ }
+
+ public int a8
+ {
+ get
+ {
+ return (int)(a * 255.0f);
+ }
+ }
+
+ public float h
+ {
+ get
+ {
+ float max = Mathf.max(r, Mathf.max(g, b));
+ float min = Mathf.min(r, Mathf.min(g, b));
+
+ float delta = max - min;
+
+ if (delta == 0)
+ return 0;
+
+ float h;
+
+ if (r == max)
+ h = (g - b) / delta; // Between yellow & magenta
+ else if (g == max)
+ h = 2 + (b - r) / delta; // Between cyan & yellow
+ else
+ h = 4 + (r - g) / delta; // Between magenta & cyan
+
+ h /= 6.0f;
+
+ if (h < 0)
+ h += 1.0f;
+
+ return h;
+ }
+ set
+ {
+ this = from_hsv(value, s, v);
+ }
+ }
+
+ public float s
+ {
+ get
+ {
+ float max = Mathf.max(r, Mathf.max(g, b));
+ float min = Mathf.min(r, Mathf.min(g, b));
+
+ float delta = max - min;
+
+ return max != 0 ? delta / max : 0;
+ }
+ set
+ {
+ this = from_hsv(h, value, v);
+ }
+ }
+
+ public float v
+ {
+ get
+ {
+ return Mathf.max(r, Mathf.max(g, b));
+ }
+ set
+ {
+ this = from_hsv(h, s, value);
+ }
+ }
+
+ private static readonly Color black = new Color(0f, 0f, 0f, 1.0f);
+
+ public Color Black
+ {
+ get
+ {
+ return black;
+ }
+ }
+
+ public float this [int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return r;
+ case 1:
+ return g;
+ case 2:
+ return b;
+ case 3:
+ return a;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ r = value;
+ return;
+ case 1:
+ g = value;
+ return;
+ case 2:
+ b = value;
+ return;
+ case 3:
+ a = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ public static void to_hsv(Color color, out float hue, out float saturation, out float value)
+ {
+ int max = Mathf.max(color.r8, Mathf.max(color.g8, color.b8));
+ int min = Mathf.min(color.r8, Mathf.min(color.g8, color.b8));
+
+ float delta = max - min;
+
+ if (delta == 0)
+ {
+ hue = 0;
+ }
+ else
+ {
+ if (color.r == max)
+ hue = (color.g - color.b) / delta; // Between yellow & magenta
+ else if (color.g == max)
+ hue = 2 + (color.b - color.r) / delta; // Between cyan & yellow
+ else
+ hue = 4 + (color.r - color.g) / delta; // Between magenta & cyan
+
+ hue /= 6.0f;
+
+ if (hue < 0)
+ hue += 1.0f;
+ }
+
+ saturation = (max == 0) ? 0 : 1f - (1f * min / max);
+ value = max / 255f;
+ }
+
+ public static Color from_hsv(float hue, float saturation, float value, float alpha = 1.0f)
+ {
+ if (saturation == 0)
+ {
+ // acp_hromatic (grey)
+ return new Color(value, value, value, alpha);
+ }
+
+ int i;
+ float f, p, q, t;
+
+ hue *= 6.0f;
+ hue %= 6f;
+ i = (int)hue;
+
+ f = hue - i;
+ p = value * (1 - saturation);
+ q = value * (1 - saturation * f);
+ t = value * (1 - saturation * (1 - f));
+
+ switch (i)
+ {
+ case 0: // Red is the dominant color
+ return new Color(value, t, p, alpha);
+ case 1: // Green is the dominant color
+ return new Color(q, value, p, alpha);
+ case 2:
+ return new Color(p, value, t, alpha);
+ case 3: // Blue is the dominant color
+ return new Color(p, q, value, alpha);
+ case 4:
+ return new Color(t, p, value, alpha);
+ default: // (5) Red is the dominant color
+ return new Color(value, p, q, alpha);
+ }
+ }
+
+ public Color blend(Color over)
+ {
+ Color res;
+
+ float sa = 1.0f - over.a;
+ res.a = a * sa + over.a;
+
+ if (res.a == 0)
+ {
+ return new Color(0, 0, 0, 0);
+ }
+ else
+ {
+ res.r = (r * a * sa + over.r * over.a) / res.a;
+ res.g = (g * a * sa + over.g * over.a) / res.a;
+ res.b = (b * a * sa + over.b * over.a) / res.a;
+ }
+
+ return res;
+ }
+
+ public Color contrasted()
+ {
+ return new Color(
+ (r + 0.5f) % 1.0f,
+ (g + 0.5f) % 1.0f,
+ (b + 0.5f) % 1.0f
+ );
+ }
+
+ public float gray()
+ {
+ return (r + g + b) / 3.0f;
+ }
+
+ public Color inverted()
+ {
+ return new Color(
+ 1.0f - r,
+ 1.0f - g,
+ 1.0f - b
+ );
+ }
+
+ public Color linear_interpolate(Color b, float t)
+ {
+ Color res = this;
+
+ res.r += (t * (b.r - this.r));
+ res.g += (t * (b.g - this.g));
+ res.b += (t * (b.b - this.b));
+ res.a += (t * (b.a - this.a));
+
+ return res;
+ }
+
+ public int to_32()
+ {
+ int c = (byte)(a * 255);
+ c <<= 8;
+ c |= (byte)(r * 255);
+ c <<= 8;
+ c |= (byte)(g * 255);
+ c <<= 8;
+ c |= (byte)(b * 255);
+
+ return c;
+ }
+
+ public int to_ARGB32()
+ {
+ int c = (byte)(a * 255);
+ c <<= 8;
+ c |= (byte)(r * 255);
+ c <<= 8;
+ c |= (byte)(g * 255);
+ c <<= 8;
+ c |= (byte)(b * 255);
+
+ return c;
+ }
+
+ public string to_html(bool include_alpha = true)
+ {
+ String txt = string.Empty;
+
+ txt += _to_hex(r);
+ txt += _to_hex(g);
+ txt += _to_hex(b);
+
+ if (include_alpha)
+ txt = _to_hex(a) + txt;
+
+ return txt;
+ }
+
+ public Color(float r, float g, float b, float a = 1.0f)
+ {
+ this.r = r;
+ this.g = g;
+ this.b = b;
+ this.a = a;
+ }
+
+ public Color(int rgba)
+ {
+ this.a = (rgba & 0xFF) / 255.0f;
+ rgba >>= 8;
+ this.b = (rgba & 0xFF) / 255.0f;
+ rgba >>= 8;
+ this.g = (rgba & 0xFF) / 255.0f;
+ rgba >>= 8;
+ this.r = (rgba & 0xFF) / 255.0f;
+ }
+
+ private static float _parse_col(string str, int ofs)
+ {
+ int ig = 0;
+
+ for (int i = 0; i < 2; i++)
+ {
+ int c = str[i + ofs];
+ int v = 0;
+
+ if (c >= '0' && c <= '9')
+ {
+ v = c - '0';
+ }
+ else if (c >= 'a' && c <= 'f')
+ {
+ v = c - 'a';
+ v += 10;
+ }
+ else if (c >= 'A' && c <= 'F')
+ {
+ v = c - 'A';
+ v += 10;
+ }
+ else
+ {
+ return -1;
+ }
+
+ if (i == 0)
+ ig += v * 16;
+ else
+ ig += v;
+ }
+
+ return ig;
+ }
+
+ private String _to_hex(float val)
+ {
+ int v = (int)Mathf.clamp(val * 255.0f, 0, 255);
+
+ string ret = string.Empty;
+
+ for (int i = 0; i < 2; i++)
+ {
+ char[] c = { (char)0, (char)0 };
+ int lv = v & 0xF;
+
+ if (lv < 10)
+ c[0] = (char)('0' + lv);
+ else
+ c[0] = (char)('a' + lv - 10);
+
+ v >>= 4;
+ ret = c + ret;
+ }
+
+ return ret;
+ }
+
+ internal static bool html_is_valid(string color)
+ {
+ if (color.Length == 0)
+ return false;
+
+ if (color[0] == '#')
+ color = color.Substring(1, color.Length - 1);
+
+ bool alpha = false;
+
+ if (color.Length == 8)
+ alpha = true;
+ else if (color.Length == 6)
+ alpha = false;
+ else
+ return false;
+
+ if (alpha)
+ {
+ if ((int)_parse_col(color, 0) < 0)
+ return false;
+ }
+
+ int from = alpha ? 2 : 0;
+
+ if ((int)_parse_col(color, from + 0) < 0)
+ return false;
+ if ((int)_parse_col(color, from + 2) < 0)
+ return false;
+ if ((int)_parse_col(color, from + 4) < 0)
+ return false;
+
+ return true;
+ }
+
+ public static Color Color8(byte r8, byte g8, byte b8, byte a8)
+ {
+ return new Color((float)r8 / 255f, (float)g8 / 255f, (float)b8 / 255f, (float)a8 / 255f);
+ }
+
+ public Color(string rgba)
+ {
+ if (rgba.Length == 0)
+ {
+ r = 0f;
+ g = 0f;
+ b = 0f;
+ a = 1.0f;
+ return;
+ }
+
+ if (rgba[0] == '#')
+ rgba = rgba.Substring(1);
+
+ bool alpha = false;
+
+ if (rgba.Length == 8)
+ {
+ alpha = true;
+ }
+ else if (rgba.Length == 6)
+ {
+ alpha = false;
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("Invalid color code. Length is " + rgba.Length + " but a length of 6 or 8 is expected: " + rgba);
+ }
+
+ if (alpha)
+ {
+ a = _parse_col(rgba, 0);
+
+ if (a < 0)
+ throw new ArgumentOutOfRangeException("Invalid color code. Alpha is " + a + " but zero or greater is expected: " + rgba);
+ }
+ else
+ {
+ a = 1.0f;
+ }
+
+ int from = alpha ? 2 : 0;
+
+ r = _parse_col(rgba, from + 0);
+
+ if (r < 0)
+ throw new ArgumentOutOfRangeException("Invalid color code. Red is " + r + " but zero or greater is expected: " + rgba);
+
+ g = _parse_col(rgba, from + 2);
+
+ if (g < 0)
+ throw new ArgumentOutOfRangeException("Invalid color code. Green is " + g + " but zero or greater is expected: " + rgba);
+
+ b = _parse_col(rgba, from + 4);
+
+ if (b < 0)
+ throw new ArgumentOutOfRangeException("Invalid color code. Blue is " + b + " but zero or greater is expected: " + rgba);
+ }
+
+ public static bool operator ==(Color left, Color right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Color left, Color right)
+ {
+ return !left.Equals(right);
+ }
+
+ public static bool operator <(Color left, Color right)
+ {
+ if (left.r == right.r)
+ {
+ if (left.g == right.g)
+ {
+ if (left.b == right.b)
+ return (left.a < right.a);
+ else
+ return (left.b < right.b);
+ }
+ else
+ {
+ return left.g < right.g;
+ }
+ }
+
+ return left.r < right.r;
+ }
+
+ public static bool operator >(Color left, Color right)
+ {
+ if (left.r == right.r)
+ {
+ if (left.g == right.g)
+ {
+ if (left.b == right.b)
+ return (left.a > right.a);
+ else
+ return (left.b > right.b);
+ }
+ else
+ {
+ return left.g > right.g;
+ }
+ }
+
+ return left.r > right.r;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Color)
+ {
+ return Equals((Color)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Color other)
+ {
+ return r == other.r && g == other.g && b == other.b && a == other.a;
+ }
+
+ public override int GetHashCode()
+ {
+ return r.GetHashCode() ^ g.GetHashCode() ^ b.GetHashCode() ^ a.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("{0},{1},{2},{3}", new object[]
+ {
+ this.r.ToString(),
+ this.g.ToString(),
+ this.b.ToString(),
+ this.a.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("{0},{1},{2},{3}", new object[]
+ {
+ this.r.ToString(format),
+ this.g.ToString(format),
+ this.b.ToString(format),
+ this.a.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Error.cs b/modules/mono/glue/cs_files/Error.cs
new file mode 100644
index 0000000000..3f4a92603d
--- /dev/null
+++ b/modules/mono/glue/cs_files/Error.cs
@@ -0,0 +1,48 @@
+namespace Godot
+{
+ public enum Error : int
+ {
+ OK = 0,
+ FAILED = 1,
+ ERR_UNAVAILABLE = 2,
+ ERR_UNCONFIGURED = 3,
+ ERR_UNAUTHORIZED = 4,
+ ERR_PARAMETER_RANGE_ERROR = 5,
+ ERR_OUT_OF_MEMORY = 6,
+ ERR_FILE_NOT_FOUND = 7,
+ ERR_FILE_BAD_DRIVE = 8,
+ ERR_FILE_BAD_PATH = 9,
+ ERR_FILE_NO_PERMISSION = 10,
+ ERR_FILE_ALREADY_IN_USE = 11,
+ ERR_FILE_CANT_OPEN = 12,
+ ERR_FILE_CANT_WRITE = 13,
+ ERR_FILE_CANT_READ = 14,
+ ERR_FILE_UNRECOGNIZED = 15,
+ ERR_FILE_CORRUPT = 16,
+ ERR_FILE_MISSING_DEPENDENCIES = 17,
+ ERR_FILE_EOF = 18,
+ ERR_CANT_OPEN = 19,
+ ERR_CANT_CREATE = 20,
+ ERR_PARSE_ERROR = 43,
+ ERROR_QUERY_FAILED = 21,
+ ERR_ALREADY_IN_USE = 22,
+ ERR_LOCKED = 23,
+ ERR_TIMEOUT = 24,
+ ERR_CANT_AQUIRE_RESOURCE = 28,
+ ERR_INVALID_DATA = 30,
+ ERR_INVALID_PARAMETER = 31,
+ ERR_ALREADY_EXISTS = 32,
+ ERR_DOES_NOT_EXIST = 33,
+ ERR_DATABASE_CANT_READ = 34,
+ ERR_DATABASE_CANT_WRITE = 35,
+ ERR_COMPILATION_FAILED = 36,
+ ERR_METHOD_NOT_FOUND = 37,
+ ERR_LINK_FAILED = 38,
+ ERR_SCRIPT_FAILED = 39,
+ ERR_CYCLIC_LINK = 40,
+ ERR_BUSY = 44,
+ ERR_HELP = 46,
+ ERR_BUG = 47,
+ ERR_WTF = 49
+ }
+}
diff --git a/modules/mono/glue/cs_files/ExportAttribute.cs b/modules/mono/glue/cs_files/ExportAttribute.cs
new file mode 100644
index 0000000000..af3f603d6d
--- /dev/null
+++ b/modules/mono/glue/cs_files/ExportAttribute.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
+ public class ExportAttribute : Attribute
+ {
+ private int hint;
+ private string hint_string;
+ private int usage;
+
+ public ExportAttribute(int hint = GD.PROPERTY_HINT_NONE, string hint_string = "", int usage = GD.PROPERTY_USAGE_DEFAULT)
+ {
+ this.hint = hint;
+ this.hint_string = hint_string;
+ this.usage = usage;
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/GD.cs b/modules/mono/glue/cs_files/GD.cs
new file mode 100644
index 0000000000..40a42d23b4
--- /dev/null
+++ b/modules/mono/glue/cs_files/GD.cs
@@ -0,0 +1,191 @@
+using System;
+
+namespace Godot
+{
+ public static class GD
+ {
+ /*{GodotGlobalConstants}*/
+
+ public static object bytes2var(byte[] bytes)
+ {
+ return NativeCalls.godot_icall_Godot_bytes2var(bytes);
+ }
+
+ public static object convert(object what, int type)
+ {
+ return NativeCalls.godot_icall_Godot_convert(what, type);
+ }
+
+ public static float db2linear(float db)
+ {
+ return (float)Math.Exp(db * 0.11512925464970228420089957273422);
+ }
+
+ public static float dectime(float value, float amount, float step)
+ {
+ float sgn = value < 0 ? -1.0f : 1.0f;
+ float val = Mathf.abs(value);
+ val -= amount * step;
+ if (val < 0.0f)
+ val = 0.0f;
+ return val * sgn;
+ }
+
+ public static FuncRef funcref(Object instance, string funcname)
+ {
+ var ret = new FuncRef();
+ ret.SetInstance(instance);
+ ret.SetFunction(funcname);
+ return ret;
+ }
+
+ public static int hash(object var)
+ {
+ return NativeCalls.godot_icall_Godot_hash(var);
+ }
+
+ public static Object instance_from_id(int instance_id)
+ {
+ return NativeCalls.godot_icall_Godot_instance_from_id(instance_id);
+ }
+
+ public static double linear2db(double linear)
+ {
+ return Math.Log(linear) * 8.6858896380650365530225783783321;
+ }
+
+ public static Resource load(string path)
+ {
+ return ResourceLoader.Load(path);
+ }
+
+ public static void print(params object[] what)
+ {
+ NativeCalls.godot_icall_Godot_print(what);
+ }
+
+ public static void print_stack()
+ {
+ print(System.Environment.StackTrace);
+ }
+
+ public static void printerr(params object[] what)
+ {
+ NativeCalls.godot_icall_Godot_printerr(what);
+ }
+
+ public static void printraw(params object[] what)
+ {
+ NativeCalls.godot_icall_Godot_printraw(what);
+ }
+
+ public static void prints(params object[] what)
+ {
+ NativeCalls.godot_icall_Godot_prints(what);
+ }
+
+ public static void printt(params object[] what)
+ {
+ NativeCalls.godot_icall_Godot_printt(what);
+ }
+
+ public static int[] range(int length)
+ {
+ int[] ret = new int[length];
+
+ for (int i = 0; i < length; i++)
+ {
+ ret[i] = i;
+ }
+
+ return ret;
+ }
+
+ public static int[] range(int from, int to)
+ {
+ if (to < from)
+ return new int[0];
+
+ int[] ret = new int[to - from];
+
+ for (int i = from; i < to; i++)
+ {
+ ret[i - from] = i;
+ }
+
+ return ret;
+ }
+
+ public static int[] range(int from, int to, int increment)
+ {
+ if (to < from && increment > 0)
+ return new int[0];
+ if (to > from && increment < 0)
+ return new int[0];
+
+ // Calculate count
+ int count = 0;
+
+ if (increment > 0)
+ count = ((to - from - 1) / increment) + 1;
+ else
+ count = ((from - to - 1) / -increment) + 1;
+
+ int[] ret = new int[count];
+
+ if (increment > 0)
+ {
+ int idx = 0;
+ for (int i = from; i < to; i += increment)
+ {
+ ret[idx++] = i;
+ }
+ }
+ else
+ {
+ int idx = 0;
+ for (int i = from; i > to; i += increment)
+ {
+ ret[idx++] = i;
+ }
+ }
+
+ return ret;
+ }
+
+ public static void seed(int seed)
+ {
+ NativeCalls.godot_icall_Godot_seed(seed);
+ }
+
+ public static string str(params object[] what)
+ {
+ return NativeCalls.godot_icall_Godot_str(what);
+ }
+
+ public static object str2var(string str)
+ {
+ return NativeCalls.godot_icall_Godot_str2var(str);
+ }
+
+ public static bool type_exists(string type)
+ {
+ return NativeCalls.godot_icall_Godot_type_exists(type);
+ }
+
+ public static byte[] var2bytes(object var)
+ {
+ return NativeCalls.godot_icall_Godot_var2bytes(var);
+ }
+
+ public static string var2str(object var)
+ {
+ return NativeCalls.godot_icall_Godot_var2str(var);
+ }
+
+ public static WeakRef weakref(Object obj)
+ {
+ return NativeCalls.godot_icall_Godot_weakref(Object.GetPtr(obj));
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/GodotMethodAttribute.cs b/modules/mono/glue/cs_files/GodotMethodAttribute.cs
new file mode 100644
index 0000000000..21333c8dab
--- /dev/null
+++ b/modules/mono/glue/cs_files/GodotMethodAttribute.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Method, Inherited = true)]
+ internal class GodotMethodAttribute : Attribute
+ {
+ private string methodName;
+
+ public string MethodName { get { return methodName; } }
+
+ public GodotMethodAttribute(string methodName)
+ {
+ this.methodName = methodName;
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/GodotSynchronizationContext.cs b/modules/mono/glue/cs_files/GodotSynchronizationContext.cs
new file mode 100644
index 0000000000..eb4d0bed1c
--- /dev/null
+++ b/modules/mono/glue/cs_files/GodotSynchronizationContext.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Godot
+{
+ public class GodotSynchronizationContext : SynchronizationContext
+ {
+ private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> queue = new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
+
+ public override void Post(SendOrPostCallback d, object state)
+ {
+ queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
+ }
+
+ public void ExecutePendingContinuations()
+ {
+ KeyValuePair<SendOrPostCallback, object> workItem;
+ while (queue.TryTake(out workItem))
+ {
+ workItem.Key(workItem.Value);
+ }
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/GodotTaskScheduler.cs b/modules/mono/glue/cs_files/GodotTaskScheduler.cs
new file mode 100644
index 0000000000..f587645a49
--- /dev/null
+++ b/modules/mono/glue/cs_files/GodotTaskScheduler.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Godot
+{
+ public class GodotTaskScheduler : TaskScheduler
+ {
+ private GodotSynchronizationContext Context { get; set; }
+ private readonly LinkedList<Task> _tasks = new LinkedList<Task>();
+
+ public GodotTaskScheduler()
+ {
+ Context = new GodotSynchronizationContext();
+ }
+
+ protected sealed override void QueueTask(Task task)
+ {
+ lock (_tasks)
+ {
+ _tasks.AddLast(task);
+ }
+ }
+
+ protected sealed override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
+ {
+ if (SynchronizationContext.Current != Context)
+ {
+ return false;
+ }
+
+ if (taskWasPreviouslyQueued)
+ {
+ TryDequeue(task);
+ }
+
+ return base.TryExecuteTask(task);
+ }
+
+ protected sealed override bool TryDequeue(Task task)
+ {
+ lock (_tasks)
+ {
+ return _tasks.Remove(task);
+ }
+ }
+
+ protected sealed override IEnumerable<Task> GetScheduledTasks()
+ {
+ lock (_tasks)
+ {
+ return _tasks.ToArray();
+ }
+ }
+
+ public void Activate()
+ {
+ SynchronizationContext.SetSynchronizationContext(Context);
+ ExecuteQueuedTasks();
+ Context.ExecutePendingContinuations();
+ }
+
+ private void ExecuteQueuedTasks()
+ {
+ while (true)
+ {
+ Task task;
+
+ lock (_tasks)
+ {
+ if (_tasks.Any())
+ {
+ task = _tasks.First.Value;
+ _tasks.RemoveFirst();
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (task != null)
+ {
+ if (!TryExecuteTask(task))
+ {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/IAwaitable.cs b/modules/mono/glue/cs_files/IAwaitable.cs
new file mode 100644
index 0000000000..0397957d00
--- /dev/null
+++ b/modules/mono/glue/cs_files/IAwaitable.cs
@@ -0,0 +1,12 @@
+namespace Godot
+{
+ public interface IAwaitable
+ {
+ IAwaiter GetAwaiter();
+ }
+
+ public interface IAwaitable<out TResult>
+ {
+ IAwaiter<TResult> GetAwaiter();
+ }
+}
diff --git a/modules/mono/glue/cs_files/IAwaiter.cs b/modules/mono/glue/cs_files/IAwaiter.cs
new file mode 100644
index 0000000000..73c71b5634
--- /dev/null
+++ b/modules/mono/glue/cs_files/IAwaiter.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace Godot
+{
+ public interface IAwaiter : INotifyCompletion
+ {
+ bool IsCompleted { get; }
+
+ void GetResult();
+ }
+
+ public interface IAwaiter<out TResult> : INotifyCompletion
+ {
+ bool IsCompleted { get; }
+
+ TResult GetResult();
+ }
+}
diff --git a/modules/mono/glue/cs_files/MarshalUtils.cs b/modules/mono/glue/cs_files/MarshalUtils.cs
new file mode 100644
index 0000000000..5d40111339
--- /dev/null
+++ b/modules/mono/glue/cs_files/MarshalUtils.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+
+namespace Godot
+{
+ internal static class MarshalUtils
+ {
+ private static Dictionary<object, object> ArraysToDictionary(object[] keys, object[] values)
+ {
+ Dictionary<object, object> ret = new Dictionary<object, object>();
+
+ for (int i = 0; i < keys.Length; i++)
+ {
+ ret.Add(keys[i], values[i]);
+ }
+
+ return ret;
+ }
+
+ private static void DictionaryToArrays(Dictionary<object, object> from, out object[] keysTo, out object[] valuesTo)
+ {
+ Dictionary<object, object>.KeyCollection keys = from.Keys;
+ keysTo = new object[keys.Count];
+ keys.CopyTo(keysTo, 0);
+
+ Dictionary<object, object>.ValueCollection values = from.Values;
+ valuesTo = new object[values.Count];
+ values.CopyTo(valuesTo, 0);
+ }
+
+ private static Type GetDictionaryType()
+ {
+ return typeof(Dictionary<object, object>);
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Mathf.cs b/modules/mono/glue/cs_files/Mathf.cs
new file mode 100644
index 0000000000..cb0eb1acdd
--- /dev/null
+++ b/modules/mono/glue/cs_files/Mathf.cs
@@ -0,0 +1,234 @@
+using System;
+
+namespace Godot
+{
+ public static class Mathf
+ {
+ public const float PI = 3.14159274f;
+ public const float Epsilon = 1e-06f;
+
+ private const float Deg2RadConst = 0.0174532924f;
+ private const float Rad2DegConst = 57.29578f;
+
+ public static float abs(float s)
+ {
+ return Math.Abs(s);
+ }
+
+ public static float acos(float s)
+ {
+ return (float)Math.Acos(s);
+ }
+
+ public static float asin(float s)
+ {
+ return (float)Math.Asin(s);
+ }
+
+ public static float atan(float s)
+ {
+ return (float)Math.Atan(s);
+ }
+
+ public static float atan2(float x, float y)
+ {
+ return (float)Math.Atan2(x, y);
+ }
+
+ public static float ceil(float s)
+ {
+ return (float)Math.Ceiling(s);
+ }
+
+ public static float clamp(float val, float min, float max)
+ {
+ if (val < min)
+ {
+ return min;
+ }
+ else if (val > max)
+ {
+ return max;
+ }
+
+ return val;
+ }
+
+ public static float cos(float s)
+ {
+ return (float)Math.Cos(s);
+ }
+
+ public static float cosh(float s)
+ {
+ return (float)Math.Cosh(s);
+ }
+
+ public static int decimals(float step)
+ {
+ return decimals(step);
+ }
+
+ public static int decimals(decimal step)
+ {
+ return BitConverter.GetBytes(decimal.GetBits(step)[3])[2];
+ }
+
+ public static float deg2rad(float deg)
+ {
+ return deg * Deg2RadConst;
+ }
+
+ public static float ease(float s, float curve)
+ {
+ if (s < 0f)
+ {
+ s = 0f;
+ }
+ else if (s > 1.0f)
+ {
+ s = 1.0f;
+ }
+
+ if (curve > 0f)
+ {
+ if (curve < 1.0f)
+ {
+ return 1.0f - pow(1.0f - s, 1.0f / curve);
+ }
+
+ return pow(s, curve);
+ }
+ else if (curve < 0f)
+ {
+ if (s < 0.5f)
+ {
+ return pow(s * 2.0f, -curve) * 0.5f;
+ }
+
+ return (1.0f - pow(1.0f - (s - 0.5f) * 2.0f, -curve)) * 0.5f + 0.5f;
+ }
+
+ return 0f;
+ }
+
+ public static float exp(float s)
+ {
+ return (float)Math.Exp(s);
+ }
+
+ public static float floor(float s)
+ {
+ return (float)Math.Floor(s);
+ }
+
+ public static float fposmod(float x, float y)
+ {
+ if (x >= 0f)
+ {
+ return x % y;
+ }
+ else
+ {
+ return y - (-x % y);
+ }
+ }
+
+ public static float lerp(float from, float to, float weight)
+ {
+ return from + (to - from) * clamp(weight, 0f, 1f);
+ }
+
+ public static float log(float s)
+ {
+ return (float)Math.Log(s);
+ }
+
+ public static int max(int a, int b)
+ {
+ return (a > b) ? a : b;
+ }
+
+ public static float max(float a, float b)
+ {
+ return (a > b) ? a : b;
+ }
+
+ public static int min(int a, int b)
+ {
+ return (a < b) ? a : b;
+ }
+
+ public static float min(float a, float b)
+ {
+ return (a < b) ? a : b;
+ }
+
+ public static int nearest_po2(int val)
+ {
+ val--;
+ val |= val >> 1;
+ val |= val >> 2;
+ val |= val >> 4;
+ val |= val >> 8;
+ val |= val >> 16;
+ val++;
+ return val;
+ }
+
+ public static float pow(float x, float y)
+ {
+ return (float)Math.Pow(x, y);
+ }
+
+ public static float rad2deg(float rad)
+ {
+ return rad * Rad2DegConst;
+ }
+
+ public static float round(float s)
+ {
+ return (float)Math.Round(s);
+ }
+
+ public static float sign(float s)
+ {
+ return (s < 0f) ? -1f : 1f;
+ }
+
+ public static float sin(float s)
+ {
+ return (float)Math.Sin(s);
+ }
+
+ public static float sinh(float s)
+ {
+ return (float)Math.Sinh(s);
+ }
+
+ public static float sqrt(float s)
+ {
+ return (float)Math.Sqrt(s);
+ }
+
+ public static float stepify(float s, float step)
+ {
+ if (step != 0f)
+ {
+ s = floor(s / step + 0.5f) * step;
+ }
+
+ return s;
+ }
+
+ public static float tan(float s)
+ {
+ return (float)Math.Tan(s);
+ }
+
+ public static float tanh(float s)
+ {
+ return (float)Math.Tanh(s);
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Plane.cs b/modules/mono/glue/cs_files/Plane.cs
new file mode 100644
index 0000000000..ada6e465ac
--- /dev/null
+++ b/modules/mono/glue/cs_files/Plane.cs
@@ -0,0 +1,209 @@
+using System;
+
+namespace Godot
+{
+ public struct Plane : IEquatable<Plane>
+ {
+ Vector3 normal;
+
+ public float x
+ {
+ get
+ {
+ return normal.x;
+ }
+ set
+ {
+ normal.x = value;
+ }
+ }
+
+ public float y
+ {
+ get
+ {
+ return normal.y;
+ }
+ set
+ {
+ normal.y = value;
+ }
+ }
+
+ public float z
+ {
+ get
+ {
+ return normal.z;
+ }
+ set
+ {
+ normal.z = value;
+ }
+ }
+
+ float d;
+
+ public Vector3 Center
+ {
+ get
+ {
+ return normal * d;
+ }
+ }
+
+ public float distance_to(Vector3 point)
+ {
+ return normal.dot(point) - d;
+ }
+
+ public Vector3 get_any_point()
+ {
+ return normal * d;
+ }
+
+ public bool has_point(Vector3 point, float epsilon = Mathf.Epsilon)
+ {
+ float dist = normal.dot(point) - d;
+ return Mathf.abs(dist) <= epsilon;
+ }
+
+ public Vector3 intersect_3(Plane b, Plane c)
+ {
+ float denom = normal.cross(b.normal).dot(c.normal);
+
+ if (Mathf.abs(denom) <= Mathf.Epsilon)
+ return new Vector3();
+
+ Vector3 result = (b.normal.cross(c.normal) * this.d) +
+ (c.normal.cross(normal) * b.d) +
+ (normal.cross(b.normal) * c.d);
+
+ return result / denom;
+ }
+
+ public Vector3 intersect_ray(Vector3 from, Vector3 dir)
+ {
+ float den = normal.dot(dir);
+
+ if (Mathf.abs(den) <= Mathf.Epsilon)
+ return new Vector3();
+
+ float dist = (normal.dot(from) - d) / den;
+
+ // This is a ray, before the emiting pos (from) does not exist
+ if (dist > Mathf.Epsilon)
+ return new Vector3();
+
+ return from + dir * -dist;
+ }
+
+ public Vector3 intersect_segment(Vector3 begin, Vector3 end)
+ {
+ Vector3 segment = begin - end;
+ float den = normal.dot(segment);
+
+ if (Mathf.abs(den) <= Mathf.Epsilon)
+ return new Vector3();
+
+ float dist = (normal.dot(begin) - d) / den;
+
+ if (dist < -Mathf.Epsilon || dist > (1.0f + Mathf.Epsilon))
+ return new Vector3();
+
+ return begin + segment * -dist;
+ }
+
+ public bool is_point_over(Vector3 point)
+ {
+ return normal.dot(point) > d;
+ }
+
+ public Plane normalized()
+ {
+ float len = normal.length();
+
+ if (len == 0)
+ return new Plane(0, 0, 0, 0);
+
+ return new Plane(normal / len, d / len);
+ }
+
+ public Vector3 project(Vector3 point)
+ {
+ return point - normal * distance_to(point);
+ }
+
+ public Plane(float a, float b, float c, float d)
+ {
+ normal = new Vector3(a, b, c);
+ this.d = d;
+ }
+
+ public Plane(Vector3 normal, float d)
+ {
+ this.normal = normal;
+ this.d = d;
+ }
+
+ public Plane(Vector3 v1, Vector3 v2, Vector3 v3)
+ {
+ normal = (v1 - v3).cross(v1 - v2);
+ normal.normalize();
+ d = normal.dot(v1);
+ }
+
+ public static Plane operator -(Plane plane)
+ {
+ return new Plane(-plane.normal, -plane.d);
+ }
+
+ public static bool operator ==(Plane left, Plane right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Plane left, Plane right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Plane)
+ {
+ return Equals((Plane)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Plane other)
+ {
+ return normal == other.normal && d == other.d;
+ }
+
+ public override int GetHashCode()
+ {
+ return normal.GetHashCode() ^ d.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1})", new object[]
+ {
+ this.normal.ToString(),
+ this.d.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1})", new object[]
+ {
+ this.normal.ToString(format),
+ this.d.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Quat.cs b/modules/mono/glue/cs_files/Quat.cs
new file mode 100644
index 0000000000..6345239f47
--- /dev/null
+++ b/modules/mono/glue/cs_files/Quat.cs
@@ -0,0 +1,328 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Godot
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Quat : IEquatable<Quat>
+ {
+ private static readonly Quat identity = new Quat(0f, 0f, 0f, 1f);
+
+ public float x;
+ public float y;
+ public float z;
+ public float w;
+
+ public static Quat Identity
+ {
+ get { return identity; }
+ }
+
+ public float this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ case 3:
+ return w;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ break;
+ case 1:
+ y = value;
+ break;
+ case 2:
+ z = value;
+ break;
+ case 3:
+ w = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ public Quat cubic_slerp(Quat b, Quat preA, Quat postB, float t)
+ {
+ float t2 = (1.0f - t) * t * 2f;
+ Quat sp = slerp(b, t);
+ Quat sq = preA.slerpni(postB, t);
+ return sp.slerpni(sq, t2);
+ }
+
+ public float dot(Quat b)
+ {
+ return x * b.x + y * b.y + z * b.z + w * b.w;
+ }
+
+ public Quat inverse()
+ {
+ return new Quat(-x, -y, -z, w);
+ }
+
+ public float length()
+ {
+ return Mathf.sqrt(length_squared());
+ }
+
+ public float length_squared()
+ {
+ return dot(this);
+ }
+
+ public Quat normalized()
+ {
+ return this / length();
+ }
+
+ public void set(float x, float y, float z, float w)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ public Quat slerp(Quat b, float t)
+ {
+ // Calculate cosine
+ float cosom = x * b.x + y * b.y + z * b.z + w * b.w;
+
+ float[] to1 = new float[4];
+
+ // Adjust signs if necessary
+ if (cosom < 0.0)
+ {
+ cosom = -cosom; to1[0] = -b.x;
+ to1[1] = -b.y;
+ to1[2] = -b.z;
+ to1[3] = -b.w;
+ }
+ else
+ {
+ to1[0] = b.x;
+ to1[1] = b.y;
+ to1[2] = b.z;
+ to1[3] = b.w;
+ }
+
+ float sinom, scale0, scale1;
+
+ // Calculate coefficients
+ if ((1.0 - cosom) > Mathf.Epsilon)
+ {
+ // Standard case (Slerp)
+ float omega = Mathf.acos(cosom);
+ sinom = Mathf.sin(omega);
+ scale0 = Mathf.sin((1.0f - t) * omega) / sinom;
+ scale1 = Mathf.sin(t * omega) / sinom;
+ }
+ else
+ {
+ // Quaternions are very close so we can do a linear interpolation
+ scale0 = 1.0f - t;
+ scale1 = t;
+ }
+
+ // Calculate final values
+ return new Quat
+ (
+ scale0 * x + scale1 * to1[0],
+ scale0 * y + scale1 * to1[1],
+ scale0 * z + scale1 * to1[2],
+ scale0 * w + scale1 * to1[3]
+ );
+ }
+
+ public Quat slerpni(Quat b, float t)
+ {
+ float dot = this.dot(b);
+
+ if (Mathf.abs(dot) > 0.9999f)
+ {
+ return this;
+ }
+
+ float theta = Mathf.acos(dot);
+ float sinT = 1.0f / Mathf.sin(theta);
+ float newFactor = Mathf.sin(t * theta) * sinT;
+ float invFactor = Mathf.sin((1.0f - t) * theta) * sinT;
+
+ return new Quat
+ (
+ invFactor * this.x + newFactor * b.x,
+ invFactor * this.y + newFactor * b.y,
+ invFactor * this.z + newFactor * b.z,
+ invFactor * this.w + newFactor * b.w
+ );
+ }
+
+ public Vector3 xform(Vector3 v)
+ {
+ Quat q = this * v;
+ q *= this.inverse();
+ return new Vector3(q.x, q.y, q.z);
+ }
+
+ public Quat(float x, float y, float z, float w)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.w = w;
+ }
+
+ public Quat(Vector3 axis, float angle)
+ {
+ float d = axis.length();
+
+ if (d == 0f)
+ {
+ x = 0f;
+ y = 0f;
+ z = 0f;
+ w = 0f;
+ }
+ else
+ {
+ float s = Mathf.sin(-angle * 0.5f) / d;
+
+ x = axis.x * s;
+ y = axis.y * s;
+ z = axis.z * s;
+ w = Mathf.cos(-angle * 0.5f);
+ }
+ }
+
+ public static Quat operator *(Quat left, Quat right)
+ {
+ return new Quat
+ (
+ left.w * right.x + left.x * right.w + left.y * right.z - left.z * right.y,
+ left.w * right.y + left.y * right.w + left.z * right.x - left.x * right.z,
+ left.w * right.z + left.z * right.w + left.x * right.y - left.y * right.x,
+ left.w * right.w - left.x * right.x - left.y * right.y - left.z * right.z
+ );
+ }
+
+ public static Quat operator +(Quat left, Quat right)
+ {
+ return new Quat(left.x + right.x, left.y + right.y, left.z + right.z, left.w + right.w);
+ }
+
+ public static Quat operator -(Quat left, Quat right)
+ {
+ return new Quat(left.x - right.x, left.y - right.y, left.z - right.z, left.w - right.w);
+ }
+
+ public static Quat operator -(Quat left)
+ {
+ return new Quat(-left.x, -left.y, -left.z, -left.w);
+ }
+
+ public static Quat operator *(Quat left, Vector3 right)
+ {
+ return new Quat
+ (
+ left.w * right.x + left.y * right.z - left.z * right.y,
+ left.w * right.y + left.z * right.x - left.x * right.z,
+ left.w * right.z + left.x * right.y - left.y * right.x,
+ -left.x * right.x - left.y * right.y - left.z * right.z
+ );
+ }
+
+ public static Quat operator *(Vector3 left, Quat right)
+ {
+ return new Quat
+ (
+ right.w * left.x + right.y * left.z - right.z * left.y,
+ right.w * left.y + right.z * left.x - right.x * left.z,
+ right.w * left.z + right.x * left.y - right.y * left.x,
+ -right.x * left.x - right.y * left.y - right.z * left.z
+ );
+ }
+
+ public static Quat operator *(Quat left, float right)
+ {
+ return new Quat(left.x * right, left.y * right, left.z * right, left.w * right);
+ }
+
+ public static Quat operator *(float left, Quat right)
+ {
+ return new Quat(right.x * left, right.y * left, right.z * left, right.w * left);
+ }
+
+ public static Quat operator /(Quat left, float right)
+ {
+ return left * (1.0f / right);
+ }
+
+ public static bool operator ==(Quat left, Quat right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Quat left, Quat right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Vector2)
+ {
+ return Equals((Vector2)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Quat other)
+ {
+ return x == other.x && y == other.y && z == other.z && w == other.w;
+ }
+
+ public override int GetHashCode()
+ {
+ return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode() ^ w.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1}, {2}, {3})", new object[]
+ {
+ this.x.ToString(),
+ this.y.ToString(),
+ this.z.ToString(),
+ this.w.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1}, {2}, {3})", new object[]
+ {
+ this.x.ToString(format),
+ this.y.ToString(format),
+ this.z.ToString(format),
+ this.w.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/RPCAttributes.cs b/modules/mono/glue/cs_files/RPCAttributes.cs
new file mode 100644
index 0000000000..08841ffd76
--- /dev/null
+++ b/modules/mono/glue/cs_files/RPCAttributes.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ public class RemoteAttribute : Attribute {}
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ public class SyncAttribute : Attribute {}
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ public class MasterAttribute : Attribute {}
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field)]
+ public class SlaveAttribute : Attribute {}
+}
diff --git a/modules/mono/glue/cs_files/Rect2.cs b/modules/mono/glue/cs_files/Rect2.cs
new file mode 100644
index 0000000000..019342134a
--- /dev/null
+++ b/modules/mono/glue/cs_files/Rect2.cs
@@ -0,0 +1,233 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Godot
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Rect2 : IEquatable<Rect2>
+ {
+ private Vector2 position;
+ private Vector2 size;
+
+ public Vector2 Position
+ {
+ get { return position; }
+ set { position = value; }
+ }
+
+ public Vector2 Size
+ {
+ get { return size; }
+ set { size = value; }
+ }
+
+ public Vector2 End
+ {
+ get { return position + size; }
+ }
+
+ public float Area
+ {
+ get { return get_area(); }
+ }
+
+ public Rect2 clip(Rect2 b)
+ {
+ Rect2 newRect = b;
+
+ if (!intersects(newRect))
+ return new Rect2();
+
+ newRect.position.x = Mathf.max(b.position.x, position.x);
+ newRect.position.y = Mathf.max(b.position.y, position.y);
+
+ Vector2 bEnd = b.position + b.size;
+ Vector2 end = position + size;
+
+ newRect.size.x = Mathf.min(bEnd.x, end.x) - newRect.position.x;
+ newRect.size.y = Mathf.min(bEnd.y, end.y) - newRect.position.y;
+
+ return newRect;
+ }
+
+ public bool encloses(Rect2 b)
+ {
+ return (b.position.x >= position.x) && (b.position.y >= position.y) &&
+ ((b.position.x + b.size.x) < (position.x + size.x)) &&
+ ((b.position.y + b.size.y) < (position.y + size.y));
+ }
+
+ public Rect2 expand(Vector2 to)
+ {
+ Rect2 expanded = this;
+
+ Vector2 begin = expanded.position;
+ Vector2 end = expanded.position + expanded.size;
+
+ if (to.x < begin.x)
+ begin.x = to.x;
+ if (to.y < begin.y)
+ begin.y = to.y;
+
+ if (to.x > end.x)
+ end.x = to.x;
+ if (to.y > end.y)
+ end.y = to.y;
+
+ expanded.position = begin;
+ expanded.size = end - begin;
+
+ return expanded;
+ }
+
+ public float get_area()
+ {
+ return size.x * size.y;
+ }
+
+ public Rect2 grow(float by)
+ {
+ Rect2 g = this;
+
+ g.position.x -= by;
+ g.position.y -= by;
+ g.size.x += by * 2;
+ g.size.y += by * 2;
+
+ return g;
+ }
+
+ public Rect2 grow_individual(float left, float top, float right, float bottom)
+ {
+ Rect2 g = this;
+
+ g.position.x -= left;
+ g.position.y -= top;
+ g.size.x += left + right;
+ g.size.y += top + bottom;
+
+ return g;
+ }
+
+ public Rect2 grow_margin(int margin, float by)
+ {
+ Rect2 g = this;
+
+ g.grow_individual((GD.MARGIN_LEFT == margin) ? by : 0,
+ (GD.MARGIN_TOP == margin) ? by : 0,
+ (GD.MARGIN_RIGHT == margin) ? by : 0,
+ (GD.MARGIN_BOTTOM == margin) ? by : 0);
+
+ return g;
+ }
+
+ public bool has_no_area()
+ {
+ return size.x <= 0 || size.y <= 0;
+ }
+
+ public bool has_point(Vector2 point)
+ {
+ if (point.x < position.x)
+ return false;
+ if (point.y < position.y)
+ return false;
+
+ if (point.x >= (position.x + size.x))
+ return false;
+ if (point.y >= (position.y + size.y))
+ return false;
+
+ return true;
+ }
+
+ public bool intersects(Rect2 b)
+ {
+ if (position.x > (b.position.x + b.size.x))
+ return false;
+ if ((position.x + size.x) < b.position.x)
+ return false;
+ if (position.y > (b.position.y + b.size.y))
+ return false;
+ if ((position.y + size.y) < b.position.y)
+ return false;
+
+ return true;
+ }
+
+ public Rect2 merge(Rect2 b)
+ {
+ Rect2 newRect;
+
+ newRect.position.x = Mathf.min(b.position.x, position.x);
+ newRect.position.y = Mathf.min(b.position.y, position.y);
+
+ newRect.size.x = Mathf.max(b.position.x + b.size.x, position.x + size.x);
+ newRect.size.y = Mathf.max(b.position.y + b.size.y, position.y + size.y);
+
+ newRect.size = newRect.size - newRect.position; // Make relative again
+
+ return newRect;
+ }
+
+ public Rect2(Vector2 position, Vector2 size)
+ {
+ this.position = position;
+ this.size = size;
+ }
+
+ public Rect2(float x, float y, float width, float height)
+ {
+ this.position = new Vector2(x, y);
+ this.size = new Vector2(width, height);
+ }
+
+ public static bool operator ==(Rect2 left, Rect2 right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Rect2 left, Rect2 right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Rect2)
+ {
+ return Equals((Rect2)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Rect2 other)
+ {
+ return position.Equals(other.position) && size.Equals(other.size);
+ }
+
+ public override int GetHashCode()
+ {
+ return position.GetHashCode() ^ size.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1})", new object[]
+ {
+ this.position.ToString(),
+ this.size.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1})", new object[]
+ {
+ this.position.ToString(format),
+ this.size.ToString(format)
+ });
+ }
+ }
+} \ No newline at end of file
diff --git a/modules/mono/glue/cs_files/Rect3.cs b/modules/mono/glue/cs_files/Rect3.cs
new file mode 100644
index 0000000000..0d25de1ec6
--- /dev/null
+++ b/modules/mono/glue/cs_files/Rect3.cs
@@ -0,0 +1,477 @@
+using System;
+
+// file: core/math/rect3.h
+// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
+// file: core/math/rect3.cpp
+// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
+// file: core/variant_call.cpp
+// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
+
+namespace Godot
+{
+ public struct Rect3 : IEquatable<Rect3>
+ {
+ private Vector3 position;
+ private Vector3 size;
+
+ public Vector3 Position
+ {
+ get
+ {
+ return position;
+ }
+ }
+
+ public Vector3 Size
+ {
+ get
+ {
+ return size;
+ }
+ }
+
+ public Vector3 End
+ {
+ get
+ {
+ return position + size;
+ }
+ }
+
+ public bool encloses(Rect3 with)
+ {
+ Vector3 src_min = position;
+ Vector3 src_max = position + size;
+ Vector3 dst_min = with.position;
+ Vector3 dst_max = with.position + with.size;
+
+ return ((src_min.x <= dst_min.x) &&
+ (src_max.x > dst_max.x) &&
+ (src_min.y <= dst_min.y) &&
+ (src_max.y > dst_max.y) &&
+ (src_min.z <= dst_min.z) &&
+ (src_max.z > dst_max.z));
+ }
+
+ public Rect3 expand(Vector3 to_point)
+ {
+ Vector3 begin = position;
+ Vector3 end = position + size;
+
+ if (to_point.x < begin.x)
+ begin.x = to_point.x;
+ if (to_point.y < begin.y)
+ begin.y = to_point.y;
+ if (to_point.z < begin.z)
+ begin.z = to_point.z;
+
+ if (to_point.x > end.x)
+ end.x = to_point.x;
+ if (to_point.y > end.y)
+ end.y = to_point.y;
+ if (to_point.z > end.z)
+ end.z = to_point.z;
+
+ return new Rect3(begin, end - begin);
+ }
+
+ public float get_area()
+ {
+ return size.x * size.y * size.z;
+ }
+
+ public Vector3 get_endpoint(int idx)
+ {
+ switch (idx)
+ {
+ case 0:
+ return new Vector3(position.x, position.y, position.z);
+ case 1:
+ return new Vector3(position.x, position.y, position.z + size.z);
+ case 2:
+ return new Vector3(position.x, position.y + size.y, position.z);
+ case 3:
+ return new Vector3(position.x, position.y + size.y, position.z + size.z);
+ case 4:
+ return new Vector3(position.x + size.x, position.y, position.z);
+ case 5:
+ return new Vector3(position.x + size.x, position.y, position.z + size.z);
+ case 6:
+ return new Vector3(position.x + size.x, position.y + size.y, position.z);
+ case 7:
+ return new Vector3(position.x + size.x, position.y + size.y, position.z + size.z);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(idx), String.Format("Index is {0}, but a value from 0 to 7 is expected.", idx));
+ }
+ }
+
+ public Vector3 get_longest_axis()
+ {
+ Vector3 axis = new Vector3(1f, 0f, 0f);
+ float max_size = size.x;
+
+ if (size.y > max_size)
+ {
+ axis = new Vector3(0f, 1f, 0f);
+ max_size = size.y;
+ }
+
+ if (size.z > max_size)
+ {
+ axis = new Vector3(0f, 0f, 1f);
+ max_size = size.z;
+ }
+
+ return axis;
+ }
+
+ public Vector3.Axis get_longest_axis_index()
+ {
+ Vector3.Axis axis = Vector3.Axis.X;
+ float max_size = size.x;
+
+ if (size.y > max_size)
+ {
+ axis = Vector3.Axis.Y;
+ max_size = size.y;
+ }
+
+ if (size.z > max_size)
+ {
+ axis = Vector3.Axis.Z;
+ max_size = size.z;
+ }
+
+ return axis;
+ }
+
+ public float get_longest_axis_size()
+ {
+ float max_size = size.x;
+
+ if (size.y > max_size)
+ max_size = size.y;
+
+ if (size.z > max_size)
+ max_size = size.z;
+
+ return max_size;
+ }
+
+ public Vector3 get_shortest_axis()
+ {
+ Vector3 axis = new Vector3(1f, 0f, 0f);
+ float max_size = size.x;
+
+ if (size.y < max_size)
+ {
+ axis = new Vector3(0f, 1f, 0f);
+ max_size = size.y;
+ }
+
+ if (size.z < max_size)
+ {
+ axis = new Vector3(0f, 0f, 1f);
+ max_size = size.z;
+ }
+
+ return axis;
+ }
+
+ public Vector3.Axis get_shortest_axis_index()
+ {
+ Vector3.Axis axis = Vector3.Axis.X;
+ float max_size = size.x;
+
+ if (size.y < max_size)
+ {
+ axis = Vector3.Axis.Y;
+ max_size = size.y;
+ }
+
+ if (size.z < max_size)
+ {
+ axis = Vector3.Axis.Z;
+ max_size = size.z;
+ }
+
+ return axis;
+ }
+
+ public float get_shortest_axis_size()
+ {
+ float max_size = size.x;
+
+ if (size.y < max_size)
+ max_size = size.y;
+
+ if (size.z < max_size)
+ max_size = size.z;
+
+ return max_size;
+ }
+
+ public Vector3 get_support(Vector3 dir)
+ {
+ Vector3 half_extents = size * 0.5f;
+ Vector3 ofs = position + half_extents;
+
+ return ofs + new Vector3(
+ (dir.x > 0f) ? -half_extents.x : half_extents.x,
+ (dir.y > 0f) ? -half_extents.y : half_extents.y,
+ (dir.z > 0f) ? -half_extents.z : half_extents.z);
+ }
+
+ public Rect3 grow(float by)
+ {
+ Rect3 res = this;
+
+ res.position.x -= by;
+ res.position.y -= by;
+ res.position.z -= by;
+ res.size.x += 2.0f * by;
+ res.size.y += 2.0f * by;
+ res.size.z += 2.0f * by;
+
+ return res;
+ }
+
+ public bool has_no_area()
+ {
+ return size.x <= 0f || size.y <= 0f || size.z <= 0f;
+ }
+
+ public bool has_no_surface()
+ {
+ return size.x <= 0f && size.y <= 0f && size.z <= 0f;
+ }
+
+ public bool has_point(Vector3 point)
+ {
+ if (point.x < position.x)
+ return false;
+ if (point.y < position.y)
+ return false;
+ if (point.z < position.z)
+ return false;
+ if (point.x > position.x + size.x)
+ return false;
+ if (point.y > position.y + size.y)
+ return false;
+ if (point.z > position.z + size.z)
+ return false;
+
+ return true;
+ }
+
+ public Rect3 intersection(Rect3 with)
+ {
+ Vector3 src_min = position;
+ Vector3 src_max = position + size;
+ Vector3 dst_min = with.position;
+ Vector3 dst_max = with.position + with.size;
+
+ Vector3 min, max;
+
+ if (src_min.x > dst_max.x || src_max.x < dst_min.x)
+ {
+ return new Rect3();
+ }
+ else
+ {
+ min.x = (src_min.x > dst_min.x) ? src_min.x : dst_min.x;
+ max.x = (src_max.x < dst_max.x) ? src_max.x : dst_max.x;
+ }
+
+ if (src_min.y > dst_max.y || src_max.y < dst_min.y)
+ {
+ return new Rect3();
+ }
+ else
+ {
+ min.y = (src_min.y > dst_min.y) ? src_min.y : dst_min.y;
+ max.y = (src_max.y < dst_max.y) ? src_max.y : dst_max.y;
+ }
+
+ if (src_min.z > dst_max.z || src_max.z < dst_min.z)
+ {
+ return new Rect3();
+ }
+ else
+ {
+ min.z = (src_min.z > dst_min.z) ? src_min.z : dst_min.z;
+ max.z = (src_max.z < dst_max.z) ? src_max.z : dst_max.z;
+ }
+
+ return new Rect3(min, max - min);
+ }
+
+ public bool intersects(Rect3 with)
+ {
+ if (position.x >= (with.position.x + with.size.x))
+ return false;
+ if ((position.x + size.x) <= with.position.x)
+ return false;
+ if (position.y >= (with.position.y + with.size.y))
+ return false;
+ if ((position.y + size.y) <= with.position.y)
+ return false;
+ if (position.z >= (with.position.z + with.size.z))
+ return false;
+ if ((position.z + size.z) <= with.position.z)
+ return false;
+
+ return true;
+ }
+
+ public bool intersects_plane(Plane plane)
+ {
+ Vector3[] points =
+ {
+ new Vector3(position.x, position.y, position.z),
+ new Vector3(position.x, position.y, position.z + size.z),
+ new Vector3(position.x, position.y + size.y, position.z),
+ new Vector3(position.x, position.y + size.y, position.z + size.z),
+ new Vector3(position.x + size.x, position.y, position.z),
+ new Vector3(position.x + size.x, position.y, position.z + size.z),
+ new Vector3(position.x + size.x, position.y + size.y, position.z),
+ new Vector3(position.x + size.x, position.y + size.y, position.z + size.z),
+ };
+
+ bool over = false;
+ bool under = false;
+
+ for (int i = 0; i < 8; i++)
+ {
+ if (plane.distance_to(points[i]) > 0)
+ over = true;
+ else
+ under = true;
+ }
+
+ return under && over;
+ }
+
+ public bool intersects_segment(Vector3 from, Vector3 to)
+ {
+ float min = 0f;
+ float max = 1f;
+
+ for (int i = 0; i < 3; i++)
+ {
+ float seg_from = from[i];
+ float seg_to = to[i];
+ float box_begin = position[i];
+ float box_end = box_begin + size[i];
+ float cmin, cmax;
+
+ if (seg_from < seg_to)
+ {
+ if (seg_from > box_end || seg_to < box_begin)
+ return false;
+
+ float length = seg_to - seg_from;
+ cmin = seg_from < box_begin ? (box_begin - seg_from) / length : 0f;
+ cmax = seg_to > box_end ? (box_end - seg_from) / length : 1f;
+ }
+ else
+ {
+ if (seg_to > box_end || seg_from < box_begin)
+ return false;
+
+ float length = seg_to - seg_from;
+ cmin = seg_from > box_end ? (box_end - seg_from) / length : 0f;
+ cmax = seg_to < box_begin ? (box_begin - seg_from) / length : 1f;
+ }
+
+ if (cmin > min)
+ {
+ min = cmin;
+ }
+
+ if (cmax < max)
+ max = cmax;
+ if (max < min)
+ return false;
+ }
+
+ return true;
+ }
+
+ public Rect3 merge(Rect3 with)
+ {
+ Vector3 beg_1 = position;
+ Vector3 beg_2 = with.position;
+ Vector3 end_1 = new Vector3(size.x, size.y, size.z) + beg_1;
+ Vector3 end_2 = new Vector3(with.size.x, with.size.y, with.size.z) + beg_2;
+
+ Vector3 min = new Vector3(
+ (beg_1.x < beg_2.x) ? beg_1.x : beg_2.x,
+ (beg_1.y < beg_2.y) ? beg_1.y : beg_2.y,
+ (beg_1.z < beg_2.z) ? beg_1.z : beg_2.z
+ );
+
+ Vector3 max = new Vector3(
+ (end_1.x > end_2.x) ? end_1.x : end_2.x,
+ (end_1.y > end_2.y) ? end_1.y : end_2.y,
+ (end_1.z > end_2.z) ? end_1.z : end_2.z
+ );
+
+ return new Rect3(min, max - min);
+ }
+
+ public Rect3(Vector3 position, Vector3 size)
+ {
+ this.position = position;
+ this.size = size;
+ }
+
+ public static bool operator ==(Rect3 left, Rect3 right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Rect3 left, Rect3 right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Rect3)
+ {
+ return Equals((Rect3)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Rect3 other)
+ {
+ return position == other.position && size == other.size;
+ }
+
+ public override int GetHashCode()
+ {
+ return position.GetHashCode() ^ size.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("{0} - {1}", new object[]
+ {
+ this.position.ToString(),
+ this.size.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("{0} - {1}", new object[]
+ {
+ this.position.ToString(format),
+ this.size.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/SignalAwaiter.cs b/modules/mono/glue/cs_files/SignalAwaiter.cs
new file mode 100644
index 0000000000..19ccc26e79
--- /dev/null
+++ b/modules/mono/glue/cs_files/SignalAwaiter.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace Godot
+{
+ public class SignalAwaiter : IAwaiter<object[]>, IAwaitable<object[]>
+ {
+ private bool completed = false;
+ private object[] result = null;
+ private Action action = null;
+
+ public SignalAwaiter(Godot.Object source, string signal, Godot.Object target)
+ {
+ NativeCalls.godot_icall_Object_connect_signal_awaiter(
+ Godot.Object.GetPtr(source),
+ signal, Godot.Object.GetPtr(target), this
+ );
+ }
+
+ public bool IsCompleted
+ {
+ get
+ {
+ return completed;
+ }
+ }
+
+ public void OnCompleted(Action action)
+ {
+ this.action = action;
+ }
+
+ public object[] GetResult()
+ {
+ return result;
+ }
+
+ public IAwaiter<object[]> GetAwaiter()
+ {
+ return this;
+ }
+
+ internal void SignalCallback(object[] args)
+ {
+ completed = true;
+ result = args;
+
+ if (action != null)
+ {
+ action();
+ }
+ }
+
+ internal void FailureCallback()
+ {
+ action = null;
+ completed = true;
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/StringExtensions.cs b/modules/mono/glue/cs_files/StringExtensions.cs
new file mode 100644
index 0000000000..96041827aa
--- /dev/null
+++ b/modules/mono/glue/cs_files/StringExtensions.cs
@@ -0,0 +1,962 @@
+//using System;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Security;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Godot
+{
+ public static class StringExtensions
+ {
+ private static int get_slice_count(this string instance, string splitter)
+ {
+ if (instance.empty() || splitter.empty())
+ return 0;
+
+ int pos = 0;
+ int slices = 1;
+
+ while ((pos = instance.find(splitter, pos)) >= 0)
+ {
+ slices++;
+ pos += splitter.Length;
+ }
+
+ return slices;
+ }
+
+ private static string get_slicec(this string instance, char splitter, int slice)
+ {
+ if (!instance.empty() && slice >= 0)
+ {
+ int i = 0;
+ int prev = 0;
+ int count = 0;
+
+ while (true)
+ {
+ if (instance[i] == 0 || instance[i] == splitter)
+ {
+ if (slice == count)
+ {
+ return instance.Substring(prev, i - prev);
+ }
+ else
+ {
+ count++;
+ prev = i + 1;
+ }
+ }
+
+ i++;
+ }
+ }
+
+ return string.Empty;
+ }
+
+ // <summary>
+ // If the string is a path to a file, return the path to the file without the extension.
+ // </summary>
+ public static string basename(this string instance)
+ {
+ int index = instance.LastIndexOf('.');
+
+ if (index > 0)
+ return instance.Substring(0, index);
+
+ return instance;
+ }
+
+ // <summary>
+ // Return true if the strings begins with the given string.
+ // </summary>
+ public static bool begins_with(this string instance, string text)
+ {
+ return instance.StartsWith(text);
+ }
+
+ // <summary>
+ // Return the bigrams (pairs of consecutive letters) of this string.
+ // </summary>
+ public static string[] bigrams(this string instance)
+ {
+ string[] b = new string[instance.Length - 1];
+
+ for (int i = 0; i < b.Length; i++)
+ {
+ b[i] = instance.Substring(i, 2);
+ }
+
+ return b;
+ }
+
+ // <summary>
+ // Return a copy of the string with special characters escaped using the C language standard.
+ // </summary>
+ public static string c_escape(this string instance)
+ {
+ StringBuilder sb = new StringBuilder(string.Copy(instance));
+
+ sb.Replace("\\", "\\\\");
+ sb.Replace("\a", "\\a");
+ sb.Replace("\b", "\\b");
+ sb.Replace("\f", "\\f");
+ sb.Replace("\n", "\\n");
+ sb.Replace("\r", "\\r");
+ sb.Replace("\t", "\\t");
+ sb.Replace("\v", "\\v");
+ sb.Replace("\'", "\\'");
+ sb.Replace("\"", "\\\"");
+ sb.Replace("?", "\\?");
+
+ return sb.ToString();
+ }
+
+ // <summary>
+ // Return a copy of the string with escaped characters replaced by their meanings according to the C language standard.
+ // </summary>
+ public static string c_unescape(this string instance)
+ {
+ StringBuilder sb = new StringBuilder(string.Copy(instance));
+
+ sb.Replace("\\a", "\a");
+ sb.Replace("\\b", "\b");
+ sb.Replace("\\f", "\f");
+ sb.Replace("\\n", "\n");
+ sb.Replace("\\r", "\r");
+ sb.Replace("\\t", "\t");
+ sb.Replace("\\v", "\v");
+ sb.Replace("\\'", "\'");
+ sb.Replace("\\\"", "\"");
+ sb.Replace("\\?", "?");
+ sb.Replace("\\\\", "\\");
+
+ return sb.ToString();
+ }
+
+ // <summary>
+ // Change the case of some letters. Replace underscores with spaces, convert all letters to lowercase then capitalize first and every letter following the space character. For [code]capitalize camelCase mixed_with_underscores[/code] it will return [code]Capitalize Camelcase Mixed With Underscores[/code].
+ // </summary>
+ public static string capitalize(this string instance)
+ {
+ string aux = instance.Replace("_", " ").ToLower();
+ string cap = string.Empty;
+
+ for (int i = 0; i < aux.get_slice_count(" "); i++)
+ {
+ string slice = aux.get_slicec(' ', i);
+ if (slice.Length > 0)
+ {
+ slice = char.ToUpper(slice[0]) + slice.Substring(1);
+ if (i > 0)
+ cap += " ";
+ cap += slice;
+ }
+ }
+
+ return cap;
+ }
+
+ // <summary>
+ // Perform a case-sensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ // </summary>
+ public static int casecmp_to(this string instance, string to)
+ {
+ if (instance.empty())
+ return to.empty() ? 0 : -1;
+
+ if (to.empty())
+ return 1;
+
+ int instance_idx = 0;
+ int to_idx = 0;
+
+ while (true)
+ {
+ if (to[to_idx] == 0 && instance[instance_idx] == 0)
+ return 0; // We're equal
+ else if (instance[instance_idx] == 0)
+ return -1; // If this is empty, and the other one is not, then we're less... I think?
+ else if (to[to_idx] == 0)
+ return 1; // Otherwise the other one is smaller...
+ else if (instance[instance_idx] < to[to_idx]) // More than
+ return -1;
+ else if (instance[instance_idx] > to[to_idx]) // Less than
+ return 1;
+
+ instance_idx++;
+ to_idx++;
+ }
+ }
+
+ // <summary>
+ // Return true if the string is empty.
+ // </summary>
+ public static bool empty(this string instance)
+ {
+ return string.IsNullOrEmpty(instance);
+ }
+
+ // <summary>
+ // Return true if the strings ends with the given string.
+ // </summary>
+ public static bool ends_with(this string instance, string text)
+ {
+ return instance.EndsWith(text);
+ }
+
+ // <summary>
+ // Erase [code]chars[/code] characters from the string starting from [code]pos[/code].
+ // </summary>
+ public static void erase(this StringBuilder instance, int pos, int chars)
+ {
+ instance.Remove(pos, chars);
+ }
+
+ // <summary>
+ // If the string is a path to a file, return the extension.
+ // </summary>
+ public static string extension(this string instance)
+ {
+ int pos = instance.find_last(".");
+
+ if (pos < 0)
+ return instance;
+
+ return instance.Substring(pos + 1, instance.Length);
+ }
+
+ // <summary>
+ // Find the first occurrence of a substring, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ // </summary>
+ public static int find(this string instance, string what, int from = 0)
+ {
+ return instance.IndexOf(what, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // <summary>
+ // Find the last occurrence of a substring, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ // </summary>
+ public static int find_last(this string instance, string what)
+ {
+ return instance.LastIndexOf(what, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // <summary>
+ // Find the first occurrence of a substring but search as case-insensitive, return the starting position of the substring or -1 if not found. Optionally, the initial search index can be passed.
+ // </summary>
+ public static int findn(this string instance, string what, int from = 0)
+ {
+ return instance.IndexOf(what, StringComparison.Ordinal);
+ }
+
+ // <summary>
+ // If the string is a path to a file, return the base directory.
+ // </summary>
+ public static string get_base_dir(this string instance)
+ {
+ int basepos = instance.find("://");
+
+ string rs = string.Empty;
+ string @base = string.Empty;
+
+ if (basepos != -1)
+ {
+ int end = basepos + 3;
+ rs = instance.Substring(end, instance.Length);
+ @base = instance.Substring(0, end);
+ }
+ else
+ {
+ if (instance.begins_with("/"))
+ {
+ rs = instance.Substring(1, instance.Length);
+ @base = "/";
+ }
+ else
+ {
+ rs = instance;
+ }
+ }
+
+ int sep = Mathf.max(rs.find_last("/"), rs.find_last("\\"));
+
+ if (sep == -1)
+ return @base;
+
+ return @base + rs.substr(0, sep);
+ }
+
+ // <summary>
+ // If the string is a path to a file, return the file and ignore the base directory.
+ // </summary>
+ public static string get_file(this string instance)
+ {
+ int sep = Mathf.max(instance.find_last("/"), instance.find_last("\\"));
+
+ if (sep == -1)
+ return instance;
+
+ return instance.Substring(sep + 1, instance.Length);
+ }
+
+ // <summary>
+ // Hash the string and return a 32 bits integer.
+ // </summary>
+ public static int hash(this string instance)
+ {
+ int index = 0;
+ int hashv = 5381;
+ int c;
+
+ while ((c = (int)instance[index++]) != 0)
+ hashv = ((hashv << 5) + hashv) + c; // hash * 33 + c
+
+ return hashv;
+ }
+
+ // <summary>
+ // Convert a string containing an hexadecimal number into an int.
+ // </summary>
+ public static int hex_to_int(this string instance)
+ {
+ int sign = 1;
+
+ if (instance[0] == '-')
+ {
+ sign = -1;
+ instance = instance.Substring(1);
+ }
+
+ if (!instance.StartsWith("0x"))
+ return 0;
+
+ return sign * int.Parse(instance.Substring(2), NumberStyles.HexNumber);
+ }
+
+ // <summary>
+ // Insert a substring at a given position.
+ // </summary>
+ public static string insert(this string instance, int pos, string what)
+ {
+ return instance.Insert(pos, what);
+ }
+
+ // <summary>
+ // If the string is a path to a file or directory, return true if the path is absolute.
+ // </summary>
+ public static bool is_abs_path(this string instance)
+ {
+ return System.IO.Path.IsPathRooted(instance);
+ }
+
+ // <summary>
+ // If the string is a path to a file or directory, return true if the path is relative.
+ // </summary>
+ public static bool is_rel_path(this string instance)
+ {
+ return !System.IO.Path.IsPathRooted(instance);
+ }
+
+ // <summary>
+ // Check whether this string is a subsequence of the given string.
+ // </summary>
+ public static bool is_subsequence_of(this string instance, string text, bool case_insensitive)
+ {
+ int len = instance.Length;
+
+ if (len == 0)
+ return true; // Technically an empty string is subsequence of any string
+
+ if (len > text.Length)
+ return false;
+
+ int src = 0;
+ int tgt = 0;
+
+ while (instance[src] != 0 && text[tgt] != 0)
+ {
+ bool match = false;
+
+ if (case_insensitive)
+ {
+ char srcc = char.ToLower(instance[src]);
+ char tgtc = char.ToLower(text[tgt]);
+ match = srcc == tgtc;
+ }
+ else
+ {
+ match = instance[src] == text[tgt];
+ }
+ if (match)
+ {
+ src++;
+ if (instance[src] == 0)
+ return true;
+ }
+
+ tgt++;
+ }
+
+ return false;
+ }
+
+ // <summary>
+ // Check whether this string is a subsequence of the given string, considering case.
+ // </summary>
+ public static bool is_subsequence_of(this string instance, string text)
+ {
+ return instance.is_subsequence_of(text, false);
+ }
+
+ // <summary>
+ // Check whether this string is a subsequence of the given string, without considering case.
+ // </summary>
+ public static bool is_subsequence_ofi(this string instance, string text)
+ {
+ return instance.is_subsequence_of(text, true);
+ }
+
+ // <summary>
+ // Check whether the string contains a valid float.
+ // </summary>
+ public static bool is_valid_float(this string instance)
+ {
+ float f;
+ return float.TryParse(instance, out f);
+ }
+
+ // <summary>
+ // Check whether the string contains a valid color in HTML notation.
+ // </summary>
+ public static bool is_valid_html_color(this string instance)
+ {
+ return Color.html_is_valid(instance);
+ }
+
+ // <summary>
+ // Check whether the string is a valid identifier. As is common in programming languages, a valid identifier may contain only letters, digits and underscores (_) and the first character may not be a digit.
+ // </summary>
+ public static bool is_valid_identifier(this string instance)
+ {
+ int len = instance.Length;
+
+ if (len == 0)
+ return false;
+
+ for (int i = 0; i < len; i++)
+ {
+ if (i == 0)
+ {
+ if (instance[0] >= '0' && instance[0] <= '9')
+ return false; // Don't start with number plz
+ }
+
+ bool valid_char = (instance[i] >= '0' && instance[i] <= '9') || (instance[i] >= 'a' && instance[i] <= 'z') || (instance[i] >= 'A' && instance[i] <= 'Z') || instance[i] == '_';
+
+ if (!valid_char)
+ return false;
+ }
+
+ return true;
+ }
+
+ // <summary>
+ // Check whether the string contains a valid integer.
+ // </summary>
+ public static bool is_valid_integer(this string instance)
+ {
+ int f;
+ return int.TryParse(instance, out f);
+ }
+
+ // <summary>
+ // Check whether the string contains a valid IP address.
+ // </summary>
+ public static bool is_valid_ip_address(this string instance)
+ {
+ string[] ip = instance.split(".");
+
+ if (ip.Length != 4)
+ return false;
+
+ for (int i = 0; i < ip.Length; i++)
+ {
+ string n = ip[i];
+ if (!n.is_valid_integer())
+ return false;
+
+ int val = n.to_int();
+ if (val < 0 || val > 255)
+ return false;
+ }
+
+ return true;
+ }
+
+ // <summary>
+ // Return a copy of the string with special characters escaped using the JSON standard.
+ // </summary>
+ public static string json_escape(this string instance)
+ {
+ StringBuilder sb = new StringBuilder(string.Copy(instance));
+
+ sb.Replace("\\", "\\\\");
+ sb.Replace("\b", "\\b");
+ sb.Replace("\f", "\\f");
+ sb.Replace("\n", "\\n");
+ sb.Replace("\r", "\\r");
+ sb.Replace("\t", "\\t");
+ sb.Replace("\v", "\\v");
+ sb.Replace("\"", "\\\"");
+
+ return sb.ToString();
+ }
+
+ // <summary>
+ // Return an amount of characters from the left of the string.
+ // </summary>
+ public static string left(this string instance, int pos)
+ {
+ if (pos <= 0)
+ return string.Empty;
+
+ if (pos >= instance.Length)
+ return instance;
+
+ return instance.Substring(0, pos);
+ }
+
+ /// <summary>
+ /// Return the length of the string in characters.
+ /// </summary>
+ public static int length(this string instance)
+ {
+ return instance.Length;
+ }
+
+ // <summary>
+ // Do a simple expression match, where '*' matches zero or more arbitrary characters and '?' matches any single character except '.'.
+ // </summary>
+ public static bool expr_match(this string instance, string expr, bool case_sensitive)
+ {
+ if (expr.Length == 0 || instance.Length == 0)
+ return false;
+
+ switch (expr[0])
+ {
+ case '\0':
+ return instance[0] == 0;
+ case '*':
+ return expr_match(expr + 1, instance, case_sensitive) || (instance[0] != 0 && expr_match(expr, instance + 1, case_sensitive));
+ case '?':
+ return instance[0] != 0 && instance[0] != '.' && expr_match(expr + 1, instance + 1, case_sensitive);
+ default:
+ return (case_sensitive ? instance[0] == expr[0] : char.ToUpper(instance[0]) == char.ToUpper(expr[0])) &&
+ expr_match(expr + 1, instance + 1, case_sensitive);
+ }
+ }
+
+ // <summary>
+ // Do a simple case sensitive expression match, using ? and * wildcards (see [method expr_match]).
+ // </summary>
+ public static bool match(this string instance, string expr)
+ {
+ return instance.expr_match(expr, true);
+ }
+
+ // <summary>
+ // Do a simple case insensitive expression match, using ? and * wildcards (see [method expr_match]).
+ // </summary>
+ public static bool matchn(this string instance, string expr)
+ {
+ return instance.expr_match(expr, false);
+ }
+
+ // <summary>
+ // Return the MD5 hash of the string as an array of bytes.
+ // </summary>
+ public static byte[] md5_buffer(this string instance)
+ {
+ return NativeCalls.godot_icall_String_md5_buffer(instance);
+ }
+
+ // <summary>
+ // Return the MD5 hash of the string as a string.
+ // </summary>
+ public static string md5_text(this string instance)
+ {
+ return NativeCalls.godot_icall_String_md5_text(instance);
+ }
+
+ // <summary>
+ // Perform a case-insensitive comparison to another string, return -1 if less, 0 if equal and +1 if greater.
+ // </summary>
+ public static int nocasecmp_to(this string instance, string to)
+ {
+ if (instance.empty())
+ return to.empty() ? 0 : -1;
+
+ if (to.empty())
+ return 1;
+
+ int instance_idx = 0;
+ int to_idx = 0;
+
+ while (true)
+ {
+ if (to[to_idx] == 0 && instance[instance_idx] == 0)
+ return 0; // We're equal
+ else if (instance[instance_idx] == 0)
+ return -1; // If this is empty, and the other one is not, then we're less... I think?
+ else if (to[to_idx] == 0)
+ return 1; // Otherwise the other one is smaller..
+ else if (char.ToUpper(instance[instance_idx]) < char.ToUpper(to[to_idx])) // More than
+ return -1;
+ else if (char.ToUpper(instance[instance_idx]) > char.ToUpper(to[to_idx])) // Less than
+ return 1;
+
+ instance_idx++;
+ to_idx++;
+ }
+ }
+
+ // <summary>
+ // Return the character code at position [code]at[/code].
+ // </summary>
+ public static int ord_at(this string instance, int at)
+ {
+ return instance[at];
+ }
+
+ // <summary>
+ // Format a number to have an exact number of [code]digits[/code] after the decimal point.
+ // </summary>
+ public static string pad_decimals(this string instance, int digits)
+ {
+ int c = instance.find(".");
+
+ if (c == -1)
+ {
+ if (digits <= 0)
+ return instance;
+
+ instance += ".";
+ c = instance.Length - 1;
+ }
+ else
+ {
+ if (digits <= 0)
+ return instance.Substring(0, c);
+ }
+
+ if (instance.Length - (c + 1) > digits)
+ {
+ instance = instance.Substring(0, c + digits + 1);
+ }
+ else
+ {
+ while (instance.Length - (c + 1) < digits)
+ {
+ instance += "0";
+ }
+ }
+
+ return instance;
+ }
+
+ // <summary>
+ // Format a number to have an exact number of [code]digits[/code] before the decimal point.
+ // </summary>
+ public static string pad_zeros(this string instance, int digits)
+ {
+ string s = instance;
+ int end = s.find(".");
+
+ if (end == -1)
+ end = s.Length;
+
+ if (end == 0)
+ return s;
+
+ int begin = 0;
+
+ while (begin < end && (s[begin] < '0' || s[begin] > '9'))
+ {
+ begin++;
+ }
+
+ if (begin >= end)
+ return s;
+
+ while (end - begin < digits)
+ {
+ s = s.Insert(begin, "0");
+ end++;
+ }
+
+ return s;
+ }
+
+ // <summary>
+ // Decode a percent-encoded string. See [method percent_encode].
+ // </summary>
+ public static string percent_decode(this string instance)
+ {
+ return Uri.UnescapeDataString(instance);
+ }
+
+ // <summary>
+ // Percent-encode a string. This is meant to encode parameters in a URL when sending a HTTP GET request and bodies of form-urlencoded POST request.
+ // </summary>
+ public static string percent_encode(this string instance)
+ {
+ return Uri.EscapeDataString(instance);
+ }
+
+ // <summary>
+ // If the string is a path, this concatenates [code]file[/code] at the end of the string as a subpath. E.g. [code]"this/is".plus_file("path") == "this/is/path"[/code].
+ // </summary>
+ public static string plus_file(this string instance, string file)
+ {
+ if (instance.Length > 0 && instance[instance.Length - 1] == '/')
+ return instance + file;
+ else
+ return instance + "/" + file;
+ }
+
+ // <summary>
+ // Replace occurrences of a substring for different ones inside the string.
+ // </summary>
+ public static string replace(this string instance, string what, string forwhat)
+ {
+ return instance.Replace(what, forwhat);
+ }
+
+ // <summary>
+ // Replace occurrences of a substring for different ones inside the string, but search case-insensitive.
+ // </summary>
+ public static string replacen(this string instance, string what, string forwhat)
+ {
+ return Regex.Replace(instance, what, forwhat, RegexOptions.IgnoreCase);
+ }
+
+ // <summary>
+ // Perform a search for a substring, but start from the end of the string instead of the beginning.
+ // </summary>
+ public static int rfind(this string instance, string what, int from = -1)
+ {
+ return NativeCalls.godot_icall_String_rfind(instance, what, from);
+ }
+
+ // <summary>
+ // Perform a search for a substring, but start from the end of the string instead of the beginning. Also search case-insensitive.
+ // </summary>
+ public static int rfindn(this string instance, string what, int from = -1)
+ {
+ return NativeCalls.godot_icall_String_rfindn(instance, what, from);
+ }
+
+ // <summary>
+ // Return the right side of the string from a given position.
+ // </summary>
+ public static string right(this string instance, int pos)
+ {
+ if (pos >= instance.Length)
+ return instance;
+
+ if (pos < 0)
+ return string.Empty;
+
+ return instance.Substring(pos, (instance.Length - pos));
+ }
+
+ public static byte[] sha256_buffer(this string instance)
+ {
+ return NativeCalls.godot_icall_String_sha256_buffer(instance);
+ }
+
+ // <summary>
+ // Return the SHA-256 hash of the string as a string.
+ // </summary>
+ public static string sha256_text(this string instance)
+ {
+ return NativeCalls.godot_icall_String_sha256_text(instance);
+ }
+
+ // <summary>
+ // Return the similarity index of the text compared to this string. 1 means totally similar and 0 means totally dissimilar.
+ // </summary>
+ public static float similarity(this string instance, string text)
+ {
+ if (instance == text)
+ {
+ // Equal strings are totally similar
+ return 1.0f;
+ }
+ if (instance.Length < 2 || text.Length < 2)
+ {
+ // No way to calculate similarity without a single bigram
+ return 0.0f;
+ }
+
+ string[] src_bigrams = instance.bigrams();
+ string[] tgt_bigrams = text.bigrams();
+
+ int src_size = src_bigrams.Length;
+ int tgt_size = tgt_bigrams.Length;
+
+ float sum = src_size + tgt_size;
+ float inter = 0;
+
+ for (int i = 0; i < src_size; i++)
+ {
+ for (int j = 0; j < tgt_size; j++)
+ {
+ if (src_bigrams[i] == tgt_bigrams[j])
+ {
+ inter++;
+ break;
+ }
+ }
+ }
+
+ return (2.0f * inter) / sum;
+ }
+
+ // <summary>
+ // Split the string by a divisor string, return an array of the substrings. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",".
+ // </summary>
+ public static string[] split(this string instance, string divisor, bool allow_empty = true)
+ {
+ return instance.Split(new string[] { divisor }, StringSplitOptions.RemoveEmptyEntries);
+ }
+
+ // <summary>
+ // Split the string in floats by using a divisor string, return an array of the substrings. Example "1,2.5,3" will return [1,2.5,3] if split by ",".
+ // </summary>
+ public static float[] split_floats(this string instance, string divisor, bool allow_empty = true)
+ {
+ List<float> ret = new List<float>();
+ int from = 0;
+ int len = instance.Length;
+
+ while (true)
+ {
+ int end = instance.find(divisor, from);
+ if (end < 0)
+ end = len;
+ if (allow_empty || (end > from))
+ ret.Add(float.Parse(instance.Substring(from)));
+ if (end == len)
+ break;
+
+ from = end + divisor.Length;
+ }
+
+ return ret.ToArray();
+ }
+
+ private static readonly char[] non_printable = {
+ (char)00, (char)01, (char)02, (char)03, (char)04, (char)05,
+ (char)06, (char)07, (char)08, (char)09, (char)10, (char)11,
+ (char)12, (char)13, (char)14, (char)15, (char)16, (char)17,
+ (char)18, (char)19, (char)20, (char)21, (char)22, (char)23,
+ (char)24, (char)25, (char)26, (char)27, (char)28, (char)29,
+ (char)30, (char)31, (char)32
+ };
+
+ // <summary>
+ // Return a copy of the string stripped of any non-printable character at the beginning and the end. The optional arguments are used to toggle stripping on the left and right edges respectively.
+ // </summary>
+ public static string strip_edges(this string instance, bool left = true, bool right = true)
+ {
+ if (left)
+ {
+ if (right)
+ return instance.Trim(non_printable);
+ else
+ return instance.TrimStart(non_printable);
+ }
+ else
+ {
+ return instance.TrimEnd(non_printable);
+ }
+ }
+
+ // <summary>
+ // Return part of the string from the position [code]from[/code], with length [code]len[/code].
+ // </summary>
+ public static string substr(this string instance, int from, int len)
+ {
+ return instance.Substring(from, len);
+ }
+
+ // <summary>
+ // Convert the String (which is a character array) to PoolByteArray (which is an array of bytes). The conversion is speeded up in comparison to to_utf8() with the assumption that all the characters the String contains are only ASCII characters.
+ // </summary>
+ public static byte[] to_ascii(this string instance)
+ {
+ return Encoding.ASCII.GetBytes(instance);
+ }
+
+ // <summary>
+ // Convert a string, containing a decimal number, into a [code]float[/code].
+ // </summary>
+ public static float to_float(this string instance)
+ {
+ return float.Parse(instance);
+ }
+
+ // <summary>
+ // Convert a string, containing an integer number, into an [code]int[/code].
+ // </summary>
+ public static int to_int(this string instance)
+ {
+ return int.Parse(instance);
+ }
+
+ // <summary>
+ // Return the string converted to lowercase.
+ // </summary>
+ public static string to_lower(this string instance)
+ {
+ return instance.ToLower();
+ }
+
+ // <summary>
+ // Return the string converted to uppercase.
+ // </summary>
+ public static string to_upper(this string instance)
+ {
+ return instance.ToUpper();
+ }
+
+ // <summary>
+ // Convert the String (which is an array of characters) to PoolByteArray (which is an array of bytes). The conversion is a bit slower than to_ascii(), but supports all UTF-8 characters. Therefore, you should prefer this function over to_ascii().
+ // </summary>
+ public static byte[] to_utf8(this string instance)
+ {
+ return Encoding.UTF8.GetBytes(instance);
+ }
+
+ // <summary>
+ // Return a copy of the string with special characters escaped using the XML standard.
+ // </summary>
+ public static string xml_escape(this string instance)
+ {
+ return SecurityElement.Escape(instance);
+ }
+
+ // <summary>
+ // Return a copy of the string with escaped characters replaced by their meanings according to the XML standard.
+ // </summary>
+ public static string xml_unescape(this string instance)
+ {
+ return SecurityElement.FromString(instance).Text;
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/ToolAttribute.cs b/modules/mono/glue/cs_files/ToolAttribute.cs
new file mode 100644
index 0000000000..0275982c7f
--- /dev/null
+++ b/modules/mono/glue/cs_files/ToolAttribute.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace Godot
+{
+ [AttributeUsage(AttributeTargets.Class)]
+ public class ToolAttribute : Attribute {}
+}
diff --git a/modules/mono/glue/cs_files/Transform.cs b/modules/mono/glue/cs_files/Transform.cs
new file mode 100644
index 0000000000..2010f0b3af
--- /dev/null
+++ b/modules/mono/glue/cs_files/Transform.cs
@@ -0,0 +1,168 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Godot
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Transform : IEquatable<Transform>
+ {
+ public Basis basis;
+ public Vector3 origin;
+
+ public Transform affine_inverse()
+ {
+ Basis basisInv = basis.inverse();
+ return new Transform(basisInv, basisInv.xform(-origin));
+ }
+
+ public Transform inverse()
+ {
+ Basis basisTr = basis.transposed();
+ return new Transform(basisTr, basisTr.xform(-origin));
+ }
+
+ public Transform looking_at(Vector3 target, Vector3 up)
+ {
+ Transform t = this;
+ t.set_look_at(origin, target, up);
+ return t;
+ }
+
+ public Transform orthonormalized()
+ {
+ return new Transform(basis.orthonormalized(), origin);
+ }
+
+ public Transform rotated(Vector3 axis, float phi)
+ {
+ return this * new Transform(new Basis(axis, phi), new Vector3());
+ }
+
+ public Transform scaled(Vector3 scale)
+ {
+ return new Transform(basis.scaled(scale), origin * scale);
+ }
+
+ public void set_look_at(Vector3 eye, Vector3 target, Vector3 up)
+ {
+ // Make rotation matrix
+ // Z vector
+ Vector3 zAxis = eye - target;
+
+ zAxis.normalize();
+
+ Vector3 yAxis = up;
+
+ Vector3 xAxis = yAxis.cross(zAxis);
+
+ // Recompute Y = Z cross X
+ yAxis = zAxis.cross(xAxis);
+
+ xAxis.normalize();
+ yAxis.normalize();
+
+ basis = Basis.create_from_axes(xAxis, yAxis, zAxis);
+
+ origin = eye;
+ }
+
+ public Transform translated(Vector3 ofs)
+ {
+ return new Transform(basis, new Vector3
+ (
+ origin[0] += basis[0].dot(ofs),
+ origin[1] += basis[1].dot(ofs),
+ origin[2] += basis[2].dot(ofs)
+ ));
+ }
+
+ public Vector3 xform(Vector3 v)
+ {
+ return new Vector3
+ (
+ basis[0].dot(v) + origin.x,
+ basis[1].dot(v) + origin.y,
+ basis[2].dot(v) + origin.z
+ );
+ }
+
+ public Vector3 xform_inv(Vector3 v)
+ {
+ Vector3 vInv = v - origin;
+
+ return new Vector3
+ (
+ (basis[0, 0] * vInv.x) + (basis[1, 0] * vInv.y) + (basis[2, 0] * vInv.z),
+ (basis[0, 1] * vInv.x) + (basis[1, 1] * vInv.y) + (basis[2, 1] * vInv.z),
+ (basis[0, 2] * vInv.x) + (basis[1, 2] * vInv.y) + (basis[2, 2] * vInv.z)
+ );
+ }
+
+ public Transform(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis, Vector3 origin)
+ {
+ this.basis = Basis.create_from_axes(xAxis, yAxis, zAxis);
+ this.origin = origin;
+ }
+
+ public Transform(Basis basis, Vector3 origin)
+ {
+ this.basis = basis;
+ this.origin = origin;
+ }
+
+ public static Transform operator *(Transform left, Transform right)
+ {
+ left.origin = left.xform(right.origin);
+ left.basis *= right.basis;
+ return left;
+ }
+
+ public static bool operator ==(Transform left, Transform right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Transform left, Transform right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Transform)
+ {
+ return Equals((Transform)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Transform other)
+ {
+ return basis.Equals(other.basis) && origin.Equals(other.origin);
+ }
+
+ public override int GetHashCode()
+ {
+ return basis.GetHashCode() ^ origin.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("{0} - {1}", new object[]
+ {
+ this.basis.ToString(),
+ this.origin.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("{0} - {1}", new object[]
+ {
+ this.basis.ToString(format),
+ this.origin.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Transform2D.cs b/modules/mono/glue/cs_files/Transform2D.cs
new file mode 100644
index 0000000000..526dc767c6
--- /dev/null
+++ b/modules/mono/glue/cs_files/Transform2D.cs
@@ -0,0 +1,356 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Godot
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Transform2D : IEquatable<Transform2D>
+ {
+ private static readonly Transform2D identity = new Transform2D
+ (
+ new Vector2(1f, 0f),
+ new Vector2(0f, 1f),
+ new Vector2(0f, 0f)
+ );
+
+ public Vector2 x;
+ public Vector2 y;
+ public Vector2 o;
+
+ public static Transform2D Identity
+ {
+ get { return identity; }
+ }
+
+ public Vector2 Origin
+ {
+ get { return o; }
+ }
+
+ public float Rotation
+ {
+ get { return Mathf.atan2(y.x, o.y); }
+ }
+
+ public Vector2 Scale
+ {
+ get { return new Vector2(x.length(), y.length()); }
+ }
+
+ public Vector2 this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return o;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ case 2:
+ o = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+
+ public float this[int index, int axis]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x[axis];
+ case 1:
+ return y[axis];
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x[axis] = value;
+ return;
+ case 1:
+ y[axis] = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ public Transform2D affine_inverse()
+ {
+ Transform2D inv = this;
+
+ float det = this[0, 0] * this[1, 1] - this[1, 0] * this[0, 1];
+
+ if (det == 0)
+ {
+ return new Transform2D
+ (
+ float.NaN, float.NaN,
+ float.NaN, float.NaN,
+ float.NaN, float.NaN
+ );
+ }
+
+ float idet = 1.0f / det;
+
+ float temp = this[0, 0];
+ this[0, 0] = this[1, 1];
+ this[1, 1] = temp;
+
+ this[0] *= new Vector2(idet, -idet);
+ this[1] *= new Vector2(-idet, idet);
+
+ this[2] = basis_xform(-this[2]);
+
+ return inv;
+ }
+
+ public Vector2 basis_xform(Vector2 v)
+ {
+ return new Vector2(tdotx(v), tdoty(v));
+ }
+
+ public Vector2 basis_xform_inv(Vector2 v)
+ {
+ return new Vector2(x.dot(v), y.dot(v));
+ }
+
+ public Transform2D interpolate_with(Transform2D m, float c)
+ {
+ float r1 = Rotation;
+ float r2 = m.Rotation;
+
+ Vector2 s1 = Scale;
+ Vector2 s2 = m.Scale;
+
+ // Slerp rotation
+ Vector2 v1 = new Vector2(Mathf.cos(r1), Mathf.sin(r1));
+ Vector2 v2 = new Vector2(Mathf.cos(r2), Mathf.sin(r2));
+
+ float dot = v1.dot(v2);
+
+ // Clamp dot to [-1, 1]
+ dot = (dot < -1.0f) ? -1.0f : ((dot > 1.0f) ? 1.0f : dot);
+
+ Vector2 v = new Vector2();
+
+ if (dot > 0.9995f)
+ {
+ // Linearly interpolate to avoid numerical precision issues
+ v = v1.linear_interpolate(v2, c).normalized();
+ }
+ else
+ {
+ float angle = c * Mathf.acos(dot);
+ Vector2 v3 = (v2 - v1 * dot).normalized();
+ v = v1 * Mathf.cos(angle) + v3 * Mathf.sin(angle);
+ }
+
+ // Extract parameters
+ Vector2 p1 = Origin;
+ Vector2 p2 = m.Origin;
+
+ // Construct matrix
+ Transform2D res = new Transform2D(Mathf.atan2(v.y, v.x), p1.linear_interpolate(p2, c));
+ Vector2 scale = s1.linear_interpolate(s2, c);
+ res.x *= scale;
+ res.y *= scale;
+
+ return res;
+ }
+
+ public Transform2D inverse()
+ {
+ Transform2D inv = this;
+
+ // Swap
+ float temp = inv.x.y;
+ inv.x.y = inv.y.x;
+ inv.y.x = temp;
+
+ inv.o = inv.basis_xform(-inv.o);
+
+ return inv;
+ }
+
+ public Transform2D orthonormalized()
+ {
+ Transform2D on = this;
+
+ Vector2 onX = on.x;
+ Vector2 onY = on.y;
+
+ onX.normalize();
+ onY = onY - onX * (onX.dot(onY));
+ onY.normalize();
+
+ on.x = onX;
+ on.y = onY;
+
+ return on;
+ }
+
+ public Transform2D rotated(float phi)
+ {
+ return this * new Transform2D(phi, new Vector2());
+ }
+
+ public Transform2D scaled(Vector2 scale)
+ {
+ Transform2D copy = this;
+ copy.x *= scale;
+ copy.y *= scale;
+ copy.o *= scale;
+ return copy;
+ }
+
+ private float tdotx(Vector2 with)
+ {
+ return this[0, 0] * with[0] + this[1, 0] * with[1];
+ }
+
+ private float tdoty(Vector2 with)
+ {
+ return this[0, 1] * with[0] + this[1, 1] * with[1];
+ }
+
+ public Transform2D translated(Vector2 offset)
+ {
+ Transform2D copy = this;
+ copy.o += copy.basis_xform(offset);
+ return copy;
+ }
+
+ public Vector2 xform(Vector2 v)
+ {
+ return new Vector2(tdotx(v), tdoty(v)) + o;
+ }
+
+ public Vector2 xform_inv(Vector2 v)
+ {
+ Vector2 vInv = v - o;
+ return new Vector2(x.dot(vInv), y.dot(vInv));
+ }
+
+ public Transform2D(Vector2 xAxis, Vector2 yAxis, Vector2 origin)
+ {
+ this.x = xAxis;
+ this.y = yAxis;
+ this.o = origin;
+ }
+ public Transform2D(float xx, float xy, float yx, float yy, float ox, float oy)
+ {
+ this.x = new Vector2(xx, xy);
+ this.y = new Vector2(yx, yy);
+ this.o = new Vector2(ox, oy);
+ }
+
+ public Transform2D(float rot, Vector2 pos)
+ {
+ float cr = Mathf.cos(rot);
+ float sr = Mathf.sin(rot);
+ x.x = cr;
+ y.y = cr;
+ x.y = -sr;
+ y.x = sr;
+ o = pos;
+ }
+
+ public static Transform2D operator *(Transform2D left, Transform2D right)
+ {
+ left.o = left.xform(right.o);
+
+ float x0, x1, y0, y1;
+
+ x0 = left.tdotx(right.x);
+ x1 = left.tdoty(right.x);
+ y0 = left.tdotx(right.y);
+ y1 = left.tdoty(right.y);
+
+ left.x.x = x0;
+ left.x.y = x1;
+ left.y.x = y0;
+ left.y.y = y1;
+
+ return left;
+ }
+
+ public static bool operator ==(Transform2D left, Transform2D right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Transform2D left, Transform2D right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Transform2D)
+ {
+ return Equals((Transform2D)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Transform2D other)
+ {
+ return x.Equals(other.x) && y.Equals(other.y) && o.Equals(other.o);
+ }
+
+ public override int GetHashCode()
+ {
+ return x.GetHashCode() ^ y.GetHashCode() ^ o.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1}, {2})", new object[]
+ {
+ this.x.ToString(),
+ this.y.ToString(),
+ this.o.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1}, {2})", new object[]
+ {
+ this.x.ToString(format),
+ this.y.ToString(format),
+ this.o.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Vector2.cs b/modules/mono/glue/cs_files/Vector2.cs
new file mode 100644
index 0000000000..28fedc365b
--- /dev/null
+++ b/modules/mono/glue/cs_files/Vector2.cs
@@ -0,0 +1,362 @@
+using System;
+using System.Runtime.InteropServices;
+
+// file: core/math/math_2d.h
+// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
+// file: core/math/math_2d.cpp
+// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
+// file: core/variant_call.cpp
+// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
+
+namespace Godot
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Vector2 : IEquatable<Vector2>
+ {
+ public float x;
+ public float y;
+
+ public float this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ internal void normalize()
+ {
+ float length = x * x + y * y;
+
+ if (length != 0f)
+ {
+ length = Mathf.sqrt(length);
+ x /= length;
+ y /= length;
+ }
+ }
+
+ private float cross(Vector2 b)
+ {
+ return x * b.y - y * b.x;
+ }
+
+ public Vector2 abs()
+ {
+ return new Vector2(Mathf.abs(x), Mathf.abs(y));
+ }
+
+ public float angle()
+ {
+ return Mathf.atan2(y, x);
+ }
+
+ public float angle_to(Vector2 to)
+ {
+ return Mathf.atan2(cross(to), dot(to));
+ }
+
+ public float angle_to_point(Vector2 to)
+ {
+ return Mathf.atan2(x - to.x, y - to.y);
+ }
+
+ public float aspect()
+ {
+ return x / y;
+ }
+
+ public Vector2 bounce(Vector2 n)
+ {
+ return -reflect(n);
+ }
+
+ public Vector2 clamped(float length)
+ {
+ Vector2 v = this;
+ float l = this.length();
+
+ if (l > 0 && length < l)
+ {
+ v /= l;
+ v *= length;
+ }
+
+ return v;
+ }
+
+ public Vector2 cubic_interpolate(Vector2 b, Vector2 preA, Vector2 postB, float t)
+ {
+ Vector2 p0 = preA;
+ Vector2 p1 = this;
+ Vector2 p2 = b;
+ Vector2 p3 = postB;
+
+ float t2 = t * t;
+ float t3 = t2 * t;
+
+ return 0.5f * ((p1 * 2.0f) +
+ (-p0 + p2) * t +
+ (2.0f * p0 - 5.0f * p1 + 4 * p2 - p3) * t2 +
+ (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3);
+ }
+
+ public float distance_squared_to(Vector2 to)
+ {
+ return (x - to.x) * (x - to.x) + (y - to.y) * (y - to.y);
+ }
+
+ public float distance_to(Vector2 to)
+ {
+ return Mathf.sqrt((x - to.x) * (x - to.x) + (y - to.y) * (y - to.y));
+ }
+
+ public float dot(Vector2 with)
+ {
+ return x * with.x + y * with.y;
+ }
+
+ public Vector2 floor()
+ {
+ return new Vector2(Mathf.floor(x), Mathf.floor(y));
+ }
+
+ public bool is_normalized()
+ {
+ return Mathf.abs(length_squared() - 1.0f) < Mathf.Epsilon;
+ }
+
+ public float length()
+ {
+ return Mathf.sqrt(x * x + y * y);
+ }
+
+ public float length_squared()
+ {
+ return x * x + y * y;
+ }
+
+ public Vector2 linear_interpolate(Vector2 b, float t)
+ {
+ Vector2 res = this;
+
+ res.x += (t * (b.x - x));
+ res.y += (t * (b.y - y));
+
+ return res;
+ }
+
+ public Vector2 normalized()
+ {
+ Vector2 result = this;
+ result.normalize();
+ return result;
+ }
+
+ public Vector2 reflect(Vector2 n)
+ {
+ return 2.0f * n * dot(n) - this;
+ }
+
+ public Vector2 rotated(float phi)
+ {
+ float rads = angle() + phi;
+ return new Vector2(Mathf.cos(rads), Mathf.sin(rads)) * length();
+ }
+
+ public Vector2 slide(Vector2 n)
+ {
+ return this - n * dot(n);
+ }
+
+ public Vector2 snapped(Vector2 by)
+ {
+ return new Vector2(Mathf.stepify(x, by.x), Mathf.stepify(y, by.y));
+ }
+
+ public Vector2 tangent()
+ {
+ return new Vector2(y, -x);
+ }
+
+ public Vector2(float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public static Vector2 operator +(Vector2 left, Vector2 right)
+ {
+ left.x += right.x;
+ left.y += right.y;
+ return left;
+ }
+
+ public static Vector2 operator -(Vector2 left, Vector2 right)
+ {
+ left.x -= right.x;
+ left.y -= right.y;
+ return left;
+ }
+
+ public static Vector2 operator -(Vector2 vec)
+ {
+ vec.x = -vec.x;
+ vec.y = -vec.y;
+ return vec;
+ }
+
+ public static Vector2 operator *(Vector2 vec, float scale)
+ {
+ vec.x *= scale;
+ vec.y *= scale;
+ return vec;
+ }
+
+ public static Vector2 operator *(float scale, Vector2 vec)
+ {
+ vec.x *= scale;
+ vec.y *= scale;
+ return vec;
+ }
+
+ public static Vector2 operator *(Vector2 left, Vector2 right)
+ {
+ left.x *= right.x;
+ left.y *= right.y;
+ return left;
+ }
+
+ public static Vector2 operator /(Vector2 vec, float scale)
+ {
+ vec.x /= scale;
+ vec.y /= scale;
+ return vec;
+ }
+
+ public static Vector2 operator /(Vector2 left, Vector2 right)
+ {
+ left.x /= right.x;
+ left.y /= right.y;
+ return left;
+ }
+
+ public static bool operator ==(Vector2 left, Vector2 right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Vector2 left, Vector2 right)
+ {
+ return !left.Equals(right);
+ }
+
+ public static bool operator <(Vector2 left, Vector2 right)
+ {
+ if (left.x.Equals(right.x))
+ {
+ return left.y < right.y;
+ }
+ else
+ {
+ return left.x < right.x;
+ }
+ }
+
+ public static bool operator >(Vector2 left, Vector2 right)
+ {
+ if (left.x.Equals(right.x))
+ {
+ return left.y > right.y;
+ }
+ else
+ {
+ return left.x > right.x;
+ }
+ }
+
+ public static bool operator <=(Vector2 left, Vector2 right)
+ {
+ if (left.x.Equals(right.x))
+ {
+ return left.y <= right.y;
+ }
+ else
+ {
+ return left.x <= right.x;
+ }
+ }
+
+ public static bool operator >=(Vector2 left, Vector2 right)
+ {
+ if (left.x.Equals(right.x))
+ {
+ return left.y >= right.y;
+ }
+ else
+ {
+ return left.x >= right.x;
+ }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Vector2)
+ {
+ return Equals((Vector2)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Vector2 other)
+ {
+ return x == other.x && y == other.y;
+ }
+
+ public override int GetHashCode()
+ {
+ return y.GetHashCode() ^ x.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1})", new object[]
+ {
+ this.x.ToString(),
+ this.y.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1})", new object[]
+ {
+ this.x.ToString(format),
+ this.y.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/cs_files/Vector3.cs b/modules/mono/glue/cs_files/Vector3.cs
new file mode 100644
index 0000000000..c023cd83cf
--- /dev/null
+++ b/modules/mono/glue/cs_files/Vector3.cs
@@ -0,0 +1,420 @@
+using System;
+using System.Runtime.InteropServices;
+
+// file: core/math/vector3.h
+// commit: bd282ff43f23fe845f29a3e25c8efc01bd65ffb0
+// file: core/math/vector3.cpp
+// commit: 7ad14e7a3e6f87ddc450f7e34621eb5200808451
+// file: core/variant_call.cpp
+// commit: 5ad9be4c24e9d7dc5672fdc42cea896622fe5685
+
+namespace Godot
+{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct Vector3 : IEquatable<Vector3>
+ {
+ public enum Axis
+ {
+ X = 0,
+ Y,
+ Z
+ }
+
+ public float x;
+ public float y;
+ public float z;
+
+ public float this[int index]
+ {
+ get
+ {
+ switch (index)
+ {
+ case 0:
+ return x;
+ case 1:
+ return y;
+ case 2:
+ return z;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set
+ {
+ switch (index)
+ {
+ case 0:
+ x = value;
+ return;
+ case 1:
+ y = value;
+ return;
+ case 2:
+ z = value;
+ return;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ }
+
+ internal void normalize()
+ {
+ float length = this.length();
+
+ if (length == 0f)
+ {
+ x = y = z = 0f;
+ }
+ else
+ {
+ x /= length;
+ y /= length;
+ z /= length;
+ }
+ }
+
+ public Vector3 abs()
+ {
+ return new Vector3(Mathf.abs(x), Mathf.abs(y), Mathf.abs(z));
+ }
+
+ public float angle_to(Vector3 to)
+ {
+ return Mathf.atan2(cross(to).length(), dot(to));
+ }
+
+ public Vector3 bounce(Vector3 n)
+ {
+ return -reflect(n);
+ }
+
+ public Vector3 ceil()
+ {
+ return new Vector3(Mathf.ceil(x), Mathf.ceil(y), Mathf.ceil(z));
+ }
+
+ public Vector3 cross(Vector3 b)
+ {
+ return new Vector3
+ (
+ (y * b.z) - (z * b.y),
+ (z * b.x) - (x * b.z),
+ (x * b.y) - (y * b.x)
+ );
+ }
+
+ public Vector3 cubic_interpolate(Vector3 b, Vector3 preA, Vector3 postB, float t)
+ {
+ Vector3 p0 = preA;
+ Vector3 p1 = this;
+ Vector3 p2 = b;
+ Vector3 p3 = postB;
+
+ float t2 = t * t;
+ float t3 = t2 * t;
+
+ return 0.5f * (
+ (p1 * 2.0f) + (-p0 + p2) * t +
+ (2.0f * p0 - 5.0f * p1 + 4f * p2 - p3) * t2 +
+ (-p0 + 3.0f * p1 - 3.0f * p2 + p3) * t3
+ );
+ }
+
+ public float distance_squared_to(Vector3 b)
+ {
+ return (b - this).length_squared();
+ }
+
+ public float distance_to(Vector3 b)
+ {
+ return (b - this).length();
+ }
+
+ public float dot(Vector3 b)
+ {
+ return x * b.x + y * b.y + z * b.z;
+ }
+
+ public Vector3 floor()
+ {
+ return new Vector3(Mathf.floor(x), Mathf.floor(y), Mathf.floor(z));
+ }
+
+ public Vector3 inverse()
+ {
+ return new Vector3(1.0f / x, 1.0f / y, 1.0f / z);
+ }
+
+ public bool is_normalized()
+ {
+ return Mathf.abs(length_squared() - 1.0f) < Mathf.Epsilon;
+ }
+
+ public float length()
+ {
+ float x2 = x * x;
+ float y2 = y * y;
+ float z2 = z * z;
+
+ return Mathf.sqrt(x2 + y2 + z2);
+ }
+
+ public float length_squared()
+ {
+ float x2 = x * x;
+ float y2 = y * y;
+ float z2 = z * z;
+
+ return x2 + y2 + z2;
+ }
+
+ public Vector3 linear_interpolate(Vector3 b, float t)
+ {
+ return new Vector3
+ (
+ x + (t * (b.x - x)),
+ y + (t * (b.y - y)),
+ z + (t * (b.z - z))
+ );
+ }
+
+ public Axis max_axis()
+ {
+ return x < y ? (y < z ? Axis.Z : Axis.Y) : (x < z ? Axis.Z : Axis.X);
+ }
+
+ public Axis min_axis()
+ {
+ return x < y ? (x < z ? Axis.X : Axis.Z) : (y < z ? Axis.Y : Axis.Z);
+ }
+
+ public Vector3 normalized()
+ {
+ Vector3 v = this;
+ v.normalize();
+ return v;
+ }
+
+ public Basis outer(Vector3 b)
+ {
+ return new Basis(
+ new Vector3(x * b.x, x * b.y, x * b.z),
+ new Vector3(y * b.x, y * b.y, y * b.z),
+ new Vector3(z * b.x, z * b.y, z * b.z)
+ );
+ }
+
+ public Vector3 reflect(Vector3 n)
+ {
+#if DEBUG
+ if (!n.is_normalized())
+ throw new ArgumentException(String.Format("{0} is not normalized", n), nameof(n));
+#endif
+ return 2.0f * n * dot(n) - this;
+ }
+
+ public Vector3 rotated(Vector3 axis, float phi)
+ {
+ return new Basis(axis, phi).xform(this);
+ }
+
+ public Vector3 slide(Vector3 n)
+ {
+ return this - n * dot(n);
+ }
+
+ public Vector3 snapped(Vector3 by)
+ {
+ return new Vector3
+ (
+ Mathf.stepify(x, by.x),
+ Mathf.stepify(y, by.y),
+ Mathf.stepify(z, by.z)
+ );
+ }
+
+ public Basis to_diagonal_matrix()
+ {
+ return new Basis(
+ x, 0f, 0f,
+ 0f, y, 0f,
+ 0f, 0f, z
+ );
+ }
+
+ public Vector3(float x, float y, float z)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public static Vector3 operator +(Vector3 left, Vector3 right)
+ {
+ left.x += right.x;
+ left.y += right.y;
+ left.z += right.z;
+ return left;
+ }
+
+ public static Vector3 operator -(Vector3 left, Vector3 right)
+ {
+ left.x -= right.x;
+ left.y -= right.y;
+ left.z -= right.z;
+ return left;
+ }
+
+ public static Vector3 operator -(Vector3 vec)
+ {
+ vec.x = -vec.x;
+ vec.y = -vec.y;
+ vec.z = -vec.z;
+ return vec;
+ }
+
+ public static Vector3 operator *(Vector3 vec, float scale)
+ {
+ vec.x *= scale;
+ vec.y *= scale;
+ vec.z *= scale;
+ return vec;
+ }
+
+ public static Vector3 operator *(float scale, Vector3 vec)
+ {
+ vec.x *= scale;
+ vec.y *= scale;
+ vec.z *= scale;
+ return vec;
+ }
+
+ public static Vector3 operator *(Vector3 left, Vector3 right)
+ {
+ left.x *= right.x;
+ left.y *= right.y;
+ left.z *= right.z;
+ return left;
+ }
+
+ public static Vector3 operator /(Vector3 vec, float scale)
+ {
+ vec.x /= scale;
+ vec.y /= scale;
+ vec.z /= scale;
+ return vec;
+ }
+
+ public static Vector3 operator /(Vector3 left, Vector3 right)
+ {
+ left.x /= right.x;
+ left.y /= right.y;
+ left.z /= right.z;
+ return left;
+ }
+
+ public static bool operator ==(Vector3 left, Vector3 right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Vector3 left, Vector3 right)
+ {
+ return !left.Equals(right);
+ }
+
+ public static bool operator <(Vector3 left, Vector3 right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ return left.z < right.z;
+ else
+ return left.y < right.y;
+ }
+
+ return left.x < right.x;
+ }
+
+ public static bool operator >(Vector3 left, Vector3 right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ return left.z > right.z;
+ else
+ return left.y > right.y;
+ }
+
+ return left.x > right.x;
+ }
+
+ public static bool operator <=(Vector3 left, Vector3 right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ return left.z <= right.z;
+ else
+ return left.y < right.y;
+ }
+
+ return left.x < right.x;
+ }
+
+ public static bool operator >=(Vector3 left, Vector3 right)
+ {
+ if (left.x == right.x)
+ {
+ if (left.y == right.y)
+ return left.z >= right.z;
+ else
+ return left.y > right.y;
+ }
+
+ return left.x > right.x;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Vector3)
+ {
+ return Equals((Vector3)obj);
+ }
+
+ return false;
+ }
+
+ public bool Equals(Vector3 other)
+ {
+ return x == other.x && y == other.y && z == other.z;
+ }
+
+ public override int GetHashCode()
+ {
+ return y.GetHashCode() ^ x.GetHashCode() ^ z.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return String.Format("({0}, {1}, {2})", new object[]
+ {
+ this.x.ToString(),
+ this.y.ToString(),
+ this.z.ToString()
+ });
+ }
+
+ public string ToString(string format)
+ {
+ return String.Format("({0}, {1}, {2})", new object[]
+ {
+ this.x.ToString(format),
+ this.y.ToString(format),
+ this.z.ToString(format)
+ });
+ }
+ }
+}
diff --git a/modules/mono/glue/glue_header.h b/modules/mono/glue/glue_header.h
new file mode 100644
index 0000000000..0751a0160f
--- /dev/null
+++ b/modules/mono/glue/glue_header.h
@@ -0,0 +1,302 @@
+/*************************************************************************/
+/* glue_header.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "../csharp_script.h"
+#include "../mono_gd/gd_mono_class.h"
+#include "../mono_gd/gd_mono_internals.h"
+#include "../mono_gd/gd_mono_marshal.h"
+#include "../signal_awaiter_utils.h"
+
+#include "bind/core_bind.h"
+#include "class_db.h"
+#include "io/marshalls.h"
+#include "object.h"
+#include "os/os.h"
+#include "project_settings.h"
+#include "reference.h"
+#include "variant_parser.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_node.h"
+#endif
+
+#define GODOTSHARP_INSTANCE_OBJECT(m_instance, m_type) \
+ static ClassDB::ClassInfo *ci = NULL; \
+ if (!ci) { \
+ ci = ClassDB::classes.getptr(m_type); \
+ } \
+ Object *m_instance = ci->creation_func();
+
+void godot_icall_Object_Dtor(Object *ptr) {
+ ERR_FAIL_NULL(ptr);
+ _GodotSharp::get_singleton()->queue_dispose(ptr);
+}
+
+// -- ClassDB --
+
+MethodBind *godot_icall_ClassDB_get_method(MonoString *p_type, MonoString *p_method) {
+ StringName type(GDMonoMarshal::mono_string_to_godot(p_type));
+ StringName method(GDMonoMarshal::mono_string_to_godot(p_method));
+ return ClassDB::get_method(type, method);
+}
+
+// -- SignalAwaiter --
+
+Error godot_icall_Object_connect_signal_awaiter(Object *p_source, MonoString *p_signal, Object *p_target, MonoObject *p_awaiter) {
+ String signal = GDMonoMarshal::mono_string_to_godot(p_signal);
+ return SignalAwaiterUtils::connect_signal_awaiter(p_source, signal, p_target, p_awaiter);
+}
+
+// -- NodePath --
+
+NodePath *godot_icall_NodePath_Ctor(MonoString *p_path) {
+ return memnew(NodePath(GDMonoMarshal::mono_string_to_godot(p_path)));
+}
+
+void godot_icall_NodePath_Dtor(NodePath *p_ptr) {
+ ERR_FAIL_NULL(p_ptr);
+ _GodotSharp::get_singleton()->queue_dispose(p_ptr);
+}
+
+MonoString *godot_icall_NodePath_operator_String(NodePath *p_np) {
+ return GDMonoMarshal::mono_string_from_godot(p_np->operator String());
+}
+
+MonoArray *godot_icall_String_md5_buffer(MonoString *p_str) {
+ Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_buffer();
+ // TODO Check possible Array/Vector<uint8_t> problem?
+ return GDMonoMarshal::Array_to_mono_array(Variant(ret));
+}
+
+// -- RID --
+
+RID *godot_icall_RID_Ctor(Object *p_from) {
+ Resource *res_from = Object::cast_to<Resource>(p_from);
+
+ if (res_from)
+ return memnew(RID(res_from->get_rid()));
+
+ return memnew(RID);
+}
+
+void godot_icall_RID_Dtor(RID *p_ptr) {
+ ERR_FAIL_NULL(p_ptr);
+ _GodotSharp::get_singleton()->queue_dispose(p_ptr);
+}
+
+// -- String --
+
+MonoString *godot_icall_String_md5_text(MonoString *p_str) {
+ String ret = GDMonoMarshal::mono_string_to_godot(p_str).md5_text();
+ return GDMonoMarshal::mono_string_from_godot(ret);
+}
+
+int godot_icall_String_rfind(MonoString *p_str, MonoString *p_what, int p_from) {
+ String what = GDMonoMarshal::mono_string_to_godot(p_what);
+ return GDMonoMarshal::mono_string_to_godot(p_str).rfind(what, p_from);
+}
+
+int godot_icall_String_rfindn(MonoString *p_str, MonoString *p_what, int p_from) {
+ String what = GDMonoMarshal::mono_string_to_godot(p_what);
+ return GDMonoMarshal::mono_string_to_godot(p_str).rfindn(what, p_from);
+}
+
+MonoArray *godot_icall_String_sha256_buffer(MonoString *p_str) {
+ Vector<uint8_t> ret = GDMonoMarshal::mono_string_to_godot(p_str).sha256_buffer();
+ return GDMonoMarshal::Array_to_mono_array(Variant(ret));
+}
+
+MonoString *godot_icall_String_sha256_text(MonoString *p_str) {
+ String ret = GDMonoMarshal::mono_string_to_godot(p_str).sha256_text();
+ return GDMonoMarshal::mono_string_from_godot(ret);
+}
+
+// -- Global Scope --
+
+MonoObject *godot_icall_Godot_bytes2var(MonoArray *p_bytes) {
+ Variant ret;
+ PoolByteArray varr = GDMonoMarshal::mono_array_to_PoolByteArray(p_bytes);
+ PoolByteArray::Read r = varr.read();
+ Error err = decode_variant(ret, r.ptr(), varr.size(), NULL);
+ if (err != OK) {
+ ret = RTR("Not enough bytes for decoding bytes, or invalid format.");
+ }
+ return GDMonoMarshal::variant_to_mono_object(ret);
+}
+
+MonoObject *godot_icall_Godot_convert(MonoObject *p_what, int p_type) {
+ Variant what = GDMonoMarshal::mono_object_to_variant(p_what);
+ const Variant *args[1] = { &what };
+ Variant::CallError ce;
+ Variant ret = Variant::construct(Variant::Type(p_type), args, 1, ce);
+ ERR_FAIL_COND_V(ce.error != Variant::CallError::CALL_OK, NULL);
+ return GDMonoMarshal::variant_to_mono_object(ret);
+}
+
+int godot_icall_Godot_hash(MonoObject *p_var) {
+ return GDMonoMarshal::mono_object_to_variant(p_var).hash();
+}
+
+MonoObject *godot_icall_Godot_instance_from_id(int p_instance_id) {
+ return GDMonoUtils::unmanaged_get_managed(ObjectDB::get_instance(p_instance_id));
+}
+
+void godot_icall_Godot_print(MonoArray *p_what) {
+ Array what = GDMonoMarshal::mono_array_to_Array(p_what);
+ String str;
+ for (int i = 0; i < what.size(); i++)
+ str += what[i].operator String();
+ print_line(str);
+}
+
+void godot_icall_Godot_printerr(MonoArray *p_what) {
+ Array what = GDMonoMarshal::mono_array_to_Array(p_what);
+ String str;
+ for (int i = 0; i < what.size(); i++)
+ str += what[i].operator String();
+ OS::get_singleton()->printerr("%s\n", str.utf8().get_data());
+}
+
+void godot_icall_Godot_printraw(MonoArray *p_what) {
+ Array what = GDMonoMarshal::mono_array_to_Array(p_what);
+ String str;
+ for (int i = 0; i < what.size(); i++)
+ str += what[i].operator String();
+ OS::get_singleton()->print("%s", str.utf8().get_data());
+}
+
+void godot_icall_Godot_prints(MonoArray *p_what) {
+ Array what = GDMonoMarshal::mono_array_to_Array(p_what);
+ String str;
+ for (int i = 0; i < what.size(); i++) {
+ if (i)
+ str += " ";
+ str += what[i].operator String();
+ }
+ print_line(str);
+}
+
+void godot_icall_Godot_printt(MonoArray *p_what) {
+ Array what = GDMonoMarshal::mono_array_to_Array(p_what);
+ String str;
+ for (int i = 0; i < what.size(); i++) {
+ if (i)
+ str += "\t";
+ str += what[i].operator String();
+ }
+ print_line(str);
+}
+
+void godot_icall_Godot_seed(int p_seed) {
+ Math::seed(p_seed);
+}
+
+MonoString *godot_icall_Godot_str(MonoArray *p_what) {
+ String str;
+ Array what = GDMonoMarshal::mono_array_to_Array(p_what);
+
+ for (int i = 0; i < what.size(); i++) {
+ String os = what[i].operator String();
+
+ if (i == 0)
+ str = os;
+ else
+ str += os;
+ }
+
+ return GDMonoMarshal::mono_string_from_godot(str);
+}
+
+MonoObject *godot_icall_Godot_str2var(MonoString *p_str) {
+ Variant ret;
+
+ VariantParser::StreamString ss;
+ ss.s = GDMonoMarshal::mono_string_to_godot(p_str);
+
+ String errs;
+ int line;
+ Error err = VariantParser::parse(&ss, ret, errs, line);
+ if (err != OK) {
+ String err_str = "Parse error at line " + itos(line) + ": " + errs;
+ ERR_PRINTS(err_str);
+ ret = err_str;
+ }
+
+ return GDMonoMarshal::variant_to_mono_object(ret);
+}
+
+bool godot_icall_Godot_type_exists(MonoString *p_type) {
+ return ClassDB::class_exists(GDMonoMarshal::mono_string_to_godot(p_type));
+}
+
+MonoArray *godot_icall_Godot_var2bytes(MonoObject *p_var) {
+ Variant var = GDMonoMarshal::mono_object_to_variant(p_var);
+
+ PoolByteArray barr;
+ int len;
+ Error err = encode_variant(var, NULL, len);
+ ERR_EXPLAIN("Unexpected error encoding variable to bytes, likely unserializable type found (Object or RID).");
+ ERR_FAIL_COND_V(err != OK, NULL);
+
+ barr.resize(len);
+ {
+ PoolByteArray::Write w = barr.write();
+ encode_variant(var, w.ptr(), len);
+ }
+
+ return GDMonoMarshal::PoolByteArray_to_mono_array(barr);
+}
+
+MonoString *godot_icall_Godot_var2str(MonoObject *p_var) {
+ String vars;
+ VariantWriter::write_to_string(GDMonoMarshal::mono_object_to_variant(p_var), vars);
+ return GDMonoMarshal::mono_string_from_godot(vars);
+}
+
+MonoObject *godot_icall_Godot_weakref(Object *p_obj) {
+ if (!p_obj)
+ return NULL;
+
+ Ref<WeakRef> wref;
+ Reference *ref = Object::cast_to<Reference>(p_obj);
+
+ if (ref) {
+ REF r = ref;
+ if (!r.is_valid())
+ return NULL;
+
+ wref.instance();
+ wref->set_ref(r);
+ } else {
+ wref.instance();
+ wref->set_obj(p_obj);
+ }
+
+ return GDMonoUtils::create_managed_for_godot_object(CACHED_CLASS(WeakRef), Reference::get_class_static(), Object::cast_to<Object>(wref.ptr()));
+}
diff --git a/modules/mono/godotsharp_defs.h b/modules/mono/godotsharp_defs.h
new file mode 100644
index 0000000000..f941a4d6c5
--- /dev/null
+++ b/modules/mono/godotsharp_defs.h
@@ -0,0 +1,41 @@
+/*************************************************************************/
+/* godotsharp_defs.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 GODOTSHARP_DEFS_H
+#define GODOTSHARP_DEFS_H
+
+#define BINDINGS_NAMESPACE "Godot"
+#define BINDINGS_GLOBAL_SCOPE_CLASS "GD"
+#define BINDINGS_PTR_FIELD "ptr"
+#define BINDINGS_NATIVE_NAME_FIELD "nativeName"
+#define API_ASSEMBLY_NAME "GodotSharp"
+#define EDITOR_API_ASSEMBLY_NAME "GodotSharpEditor"
+#define EDITOR_TOOLS_ASSEMBLY_NAME "GodotSharpTools"
+
+#endif // GODOTSHARP_DEFS_H
diff --git a/modules/mono/godotsharp_dirs.cpp b/modules/mono/godotsharp_dirs.cpp
new file mode 100644
index 0000000000..0a2010e99d
--- /dev/null
+++ b/modules/mono/godotsharp_dirs.cpp
@@ -0,0 +1,185 @@
+/*************************************************************************/
+/* godotsharp_dirs.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "godotsharp_dirs.h"
+
+#include "os/os.h"
+
+#ifdef TOOLS_ENABLED
+#include "editor/editor_settings.h"
+#include "project_settings.h"
+#include "version.h"
+#endif
+
+namespace GodotSharpDirs {
+
+String _get_expected_build_config() {
+#ifdef TOOLS_ENABLED
+ return "Tools";
+#else
+
+#ifdef DEBUG_ENABLED
+ return "Debug";
+#else
+ return "Release";
+#endif
+
+#endif
+}
+
+String _get_mono_user_dir() {
+#ifdef TOOLS_ENABLED
+ if (EditorSettings::get_singleton()) {
+ return EditorSettings::get_singleton()->get_settings_path().plus_file("mono");
+ } else {
+ String settings_path;
+
+ if (OS::get_singleton()->has_environment("APPDATA")) {
+ String app_data = OS::get_singleton()->get_environment("APPDATA").replace("\\", "/");
+ settings_path = app_data.plus_file(String(_MKSTR(VERSION_SHORT_NAME)).capitalize());
+ } else if (OS::get_singleton()->has_environment("HOME")) {
+ String home = OS::get_singleton()->get_environment("HOME");
+ settings_path = home.plus_file("." + String(_MKSTR(VERSION_SHORT_NAME)).to_lower());
+ }
+
+ return settings_path.plus_file("mono");
+ }
+#else
+ return OS::get_singleton()->get_data_dir().plus_file("mono");
+#endif
+}
+
+class _GodotSharpDirs {
+
+public:
+ String res_data_dir;
+ String res_metadata_dir;
+ String res_assemblies_dir;
+ String res_config_dir;
+ String res_temp_dir;
+ String res_temp_assemblies_base_dir;
+ String res_temp_assemblies_dir;
+ String mono_user_dir;
+ String mono_logs_dir;
+
+#ifdef TOOLS_ENABLED
+ String mono_solutions_dir;
+ String build_logs_dir;
+ String sln_filepath;
+ String csproj_filepath;
+#endif
+
+private:
+ _GodotSharpDirs() {
+ res_data_dir = "res://.mono";
+ res_metadata_dir = res_data_dir.plus_file("metadata");
+ res_assemblies_dir = res_data_dir.plus_file("assemblies");
+ res_config_dir = res_data_dir.plus_file("etc").plus_file("mono");
+
+ // TODO use paths from csproj
+ res_temp_dir = res_data_dir.plus_file("temp");
+ res_temp_assemblies_base_dir = res_temp_dir.plus_file("bin");
+ res_temp_assemblies_dir = res_temp_assemblies_base_dir.plus_file(_get_expected_build_config());
+
+ mono_user_dir = _get_mono_user_dir();
+ mono_logs_dir = mono_user_dir.plus_file("mono_logs");
+
+#ifdef TOOLS_ENABLED
+ mono_solutions_dir = mono_user_dir.plus_file("solutions");
+ build_logs_dir = mono_user_dir.plus_file("build_logs");
+ String base_path = String("res://") + ProjectSettings::get_singleton()->get("application/config/name");
+ sln_filepath = ProjectSettings::get_singleton()->globalize_path(base_path + ".sln");
+ csproj_filepath = ProjectSettings::get_singleton()->globalize_path(base_path + ".csproj");
+#endif
+ }
+
+ _GodotSharpDirs(const _GodotSharpDirs &);
+ _GodotSharpDirs &operator=(const _GodotSharpDirs &);
+
+public:
+ static _GodotSharpDirs &get_singleton() {
+ static _GodotSharpDirs singleton;
+ return singleton;
+ }
+};
+
+String get_res_data_dir() {
+ return _GodotSharpDirs::get_singleton().res_data_dir;
+}
+
+String get_res_metadata_dir() {
+ return _GodotSharpDirs::get_singleton().res_metadata_dir;
+}
+
+String get_res_assemblies_dir() {
+ return _GodotSharpDirs::get_singleton().res_assemblies_dir;
+}
+
+String get_res_config_dir() {
+ return _GodotSharpDirs::get_singleton().res_config_dir;
+}
+
+String get_res_temp_dir() {
+ return _GodotSharpDirs::get_singleton().res_temp_dir;
+}
+
+String get_res_temp_assemblies_base_dir() {
+ return _GodotSharpDirs::get_singleton().res_temp_assemblies_base_dir;
+}
+
+String get_res_temp_assemblies_dir() {
+ return _GodotSharpDirs::get_singleton().res_temp_assemblies_dir;
+}
+
+String get_mono_user_dir() {
+ return _GodotSharpDirs::get_singleton().mono_user_dir;
+}
+
+String get_mono_logs_dir() {
+ return _GodotSharpDirs::get_singleton().mono_logs_dir;
+}
+
+#ifdef TOOLS_ENABLED
+String get_mono_solutions_dir() {
+ return _GodotSharpDirs::get_singleton().mono_solutions_dir;
+}
+
+String get_build_logs_dir() {
+ return _GodotSharpDirs::get_singleton().build_logs_dir;
+}
+
+String get_project_sln_path() {
+ return _GodotSharpDirs::get_singleton().sln_filepath;
+}
+
+String get_project_csproj_path() {
+ return _GodotSharpDirs::get_singleton().csproj_filepath;
+}
+#endif
+}
diff --git a/modules/mono/godotsharp_dirs.h b/modules/mono/godotsharp_dirs.h
new file mode 100644
index 0000000000..ba2c065210
--- /dev/null
+++ b/modules/mono/godotsharp_dirs.h
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* godotsharp_dirs.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 GODOTSHARP_DIRS_H
+#define GODOTSHARP_DIRS_H
+
+#include "ustring.h"
+
+namespace GodotSharpDirs {
+
+String get_res_data_dir();
+String get_res_metadata_dir();
+String get_res_assemblies_dir();
+String get_res_config_dir();
+String get_res_temp_dir();
+String get_res_temp_assemblies_base_dir();
+String get_res_temp_assemblies_dir();
+
+String get_mono_user_dir();
+String get_mono_logs_dir();
+
+#ifdef TOOLS_ENABLED
+String get_mono_solutions_dir();
+String get_build_logs_dir();
+String get_custom_project_settings_dir();
+#endif
+
+String get_project_sln_path();
+String get_project_csproj_path();
+}
+
+#endif // GODOTSHARP_DIRS_H
diff --git a/modules/mono/mono_gc_handle.cpp b/modules/mono/mono_gc_handle.cpp
new file mode 100644
index 0000000000..d3ad968135
--- /dev/null
+++ b/modules/mono/mono_gc_handle.cpp
@@ -0,0 +1,77 @@
+/*************************************************************************/
+/* mono_gc_handle.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "mono_gc_handle.h"
+
+#include "mono_gd/gd_mono.h"
+
+uint32_t MonoGCHandle::make_strong_handle(MonoObject *p_object) {
+
+ return mono_gchandle_new(
+ p_object,
+ false /* do not pin the object */
+ );
+}
+
+uint32_t MonoGCHandle::make_weak_handle(MonoObject *p_object) {
+
+ return mono_gchandle_new_weakref(
+ p_object,
+ true /* track_resurrection: allows us to invoke _notification(NOTIFICATION_PREDELETE) while disposing */
+ );
+}
+
+Ref<MonoGCHandle> MonoGCHandle::create_strong(MonoObject *p_object) {
+
+ return memnew(MonoGCHandle(make_strong_handle(p_object)));
+}
+
+Ref<MonoGCHandle> MonoGCHandle::create_weak(MonoObject *p_object) {
+
+ return memnew(MonoGCHandle(make_weak_handle(p_object)));
+}
+
+void MonoGCHandle::release() {
+
+ if (!released && GDMono::get_singleton()->is_runtime_initialized()) {
+ mono_gchandle_free(handle);
+ released = true;
+ }
+}
+
+MonoGCHandle::MonoGCHandle(uint32_t p_handle) {
+
+ released = false;
+ handle = p_handle;
+}
+
+MonoGCHandle::~MonoGCHandle() {
+
+ release();
+}
diff --git a/modules/mono/mono_gc_handle.h b/modules/mono/mono_gc_handle.h
new file mode 100644
index 0000000000..cf5b6cec21
--- /dev/null
+++ b/modules/mono/mono_gc_handle.h
@@ -0,0 +1,63 @@
+/*************************************************************************/
+/* mono_gc_handle.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 CSHARP_GC_HANDLE_H
+#define CSHARP_GC_HANDLE_H
+
+#include <mono/jit/jit.h>
+
+#include "reference.h"
+
+class MonoGCHandle : public Reference {
+
+ GDCLASS(MonoGCHandle, Reference)
+
+ bool released;
+ uint32_t handle;
+
+public:
+ static uint32_t make_strong_handle(MonoObject *p_object);
+ static uint32_t make_weak_handle(MonoObject *p_object);
+
+ static Ref<MonoGCHandle> create_strong(MonoObject *p_object);
+ static Ref<MonoGCHandle> create_weak(MonoObject *p_object);
+
+ _FORCE_INLINE_ MonoObject *get_target() const { return released ? NULL : mono_gchandle_get_target(handle); }
+
+ _FORCE_INLINE_ void set_handle(uint32_t p_handle) {
+ handle = p_handle;
+ released = false;
+ }
+ void release();
+
+ MonoGCHandle(uint32_t p_handle);
+ ~MonoGCHandle();
+};
+
+#endif // CSHARP_GC_HANDLE_H
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
new file mode 100644
index 0000000000..77f01842bb
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -0,0 +1,771 @@
+/*************************************************************************/
+/* gd_mono.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono.h"
+
+#include <mono/metadata/mono-config.h>
+#include <mono/metadata/mono-debug.h>
+
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "os/os.h"
+#include "os/thread.h"
+#include "project_settings.h"
+
+#include "../csharp_script.h"
+#include "../utils/path_utils.h"
+#include "gd_mono_utils.h"
+
+#ifdef TOOLS_ENABLED
+#include "../editor/godotsharp_editor.h"
+#endif
+
+#ifdef MONO_PRINT_HANDLER_ENABLED
+void gdmono_MonoPrintCallback(const char *string, mono_bool is_stdout) {
+
+ if (is_stdout) {
+ OS::get_singleton()->print(string);
+ } else {
+ OS::get_singleton()->printerr(string);
+ }
+}
+#endif
+
+GDMono *GDMono::singleton = NULL;
+
+#ifdef DEBUG_ENABLED
+static bool _wait_for_debugger_msecs(uint32_t p_msecs) {
+
+ do {
+ if (mono_is_debugger_attached())
+ return true;
+
+ int last_tick = OS::get_singleton()->get_ticks_msec();
+
+ OS::get_singleton()->delay_usec((p_msecs < 25 ? p_msecs : 25) * 1000);
+
+ int tdiff = OS::get_singleton()->get_ticks_msec() - last_tick;
+
+ if (tdiff > p_msecs) {
+ p_msecs = 0;
+ } else {
+ p_msecs -= tdiff;
+ }
+ } while (p_msecs > 0);
+
+ return mono_is_debugger_attached();
+}
+#endif
+
+#ifdef TOOLS_ENABLED
+// temporary workaround. should be provided from Main::setup/setup2 instead
+bool _is_project_manager_requested() {
+
+ List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
+ for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) {
+ const String &arg = E->get();
+ if (arg == "-p" || arg == "--project-manager")
+ return true;
+ }
+
+ return false;
+}
+#endif
+
+#ifdef DEBUG_ENABLED
+void gdmono_debug_init() {
+
+ mono_debug_init(MONO_DEBUG_FORMAT_MONO);
+
+ int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685);
+ bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false);
+ int da_timeout = GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000);
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint() ||
+ ProjectSettings::get_singleton()->get_resource_path().empty() ||
+ _is_project_manager_requested()) {
+ return;
+ }
+#endif
+
+ CharString da_args = String("--debugger-agent=transport=dt_socket,address=127.0.0.1:" + itos(da_port) +
+ ",embedding=1,server=y,suspend=" + (da_suspend ? "y,timeout=" + itos(da_timeout) : "n"))
+ .utf8();
+ // --debugger-agent=help
+ const char *options[] = {
+ "--soft-breakpoints",
+ da_args.get_data()
+ };
+ mono_jit_parse_options(2, (char **)options);
+}
+#endif
+
+void GDMono::initialize() {
+
+ ERR_FAIL_NULL(Engine::get_singleton());
+
+ OS::get_singleton()->print("Initializing mono...\n");
+
+#ifdef DEBUG_METHODS_ENABLED
+ _initialize_and_check_api_hashes();
+#endif
+
+ GDMonoLog::get_singleton()->initialize();
+
+#ifdef MONO_PRINT_HANDLER_ENABLED
+ mono_trace_set_print_handler(gdmono_MonoPrintCallback);
+ mono_trace_set_printerr_handler(gdmono_MonoPrintCallback);
+#endif
+
+#ifdef WINDOWS_ENABLED
+ mono_reg_info = MonoRegUtils::find_mono();
+
+ CharString assembly_dir;
+ CharString config_dir;
+
+ if (mono_reg_info.assembly_dir.length() && DirAccess::exists(mono_reg_info.assembly_dir)) {
+ assembly_dir = mono_reg_info.assembly_dir.utf8();
+ }
+
+ if (mono_reg_info.config_dir.length() && DirAccess::exists(mono_reg_info.config_dir)) {
+ config_dir = mono_reg_info.config_dir.utf8();
+ }
+
+ mono_set_dirs(assembly_dir.length() ? assembly_dir.get_data() : NULL,
+ config_dir.length() ? config_dir.get_data() : NULL);
+#else
+ mono_set_dirs(NULL, NULL);
+#endif
+
+ GDMonoAssembly::initialize();
+
+#ifdef DEBUG_ENABLED
+ gdmono_debug_init();
+#endif
+
+ mono_config_parse(NULL);
+
+ root_domain = mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319");
+
+ ERR_EXPLAIN("Mono: Failed to initialize runtime");
+ ERR_FAIL_NULL(root_domain);
+
+ GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread());
+
+ runtime_initialized = true;
+
+ OS::get_singleton()->print("Mono: Runtime initialized\n");
+
+ // mscorlib assembly MUST be present at initialization
+ ERR_EXPLAIN("Mono: Failed to load mscorlib assembly");
+ ERR_FAIL_COND(!_load_corlib_assembly());
+
+#ifdef TOOLS_ENABLED
+ // The tools domain must be loaded here, before the scripts domain.
+ // Otherwise domain unload on the scripts domain will hang indefinitely.
+
+ ERR_EXPLAIN("Mono: Failed to load tools domain");
+ ERR_FAIL_COND(_load_tools_domain() != OK);
+
+ // TODO move to editor init callback, and do it lazily when required before editor init (e.g.: bindings generation)
+ ERR_EXPLAIN("Mono: Failed to load Editor Tools assembly");
+ ERR_FAIL_COND(!_load_editor_tools_assembly());
+#endif
+
+ ERR_EXPLAIN("Mono: Failed to load scripts domain");
+ ERR_FAIL_COND(_load_scripts_domain() != OK);
+
+#ifdef DEBUG_ENABLED
+ bool debugger_attached = _wait_for_debugger_msecs(500);
+ if (!debugger_attached && OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->printerr("Mono: Debugger wait timeout\n");
+#endif
+
+ _register_internal_calls();
+
+ // The following assemblies are not required at initialization
+ _load_all_script_assemblies();
+
+ OS::get_singleton()->print("Mono: EVERYTHING OK\n");
+}
+
+#ifndef MONO_GLUE_DISABLED
+namespace GodotSharpBindings {
+
+uint64_t get_core_api_hash();
+uint64_t get_editor_api_hash();
+
+void register_generated_icalls();
+} // namespace GodotSharpBindings
+#endif
+
+void GDMono::_register_internal_calls() {
+#ifndef MONO_GLUE_DISABLED
+ GodotSharpBindings::register_generated_icalls();
+#endif
+
+#ifdef TOOLS_ENABLED
+ GodotSharpBuilds::_register_internal_calls();
+#endif
+}
+
+#ifdef DEBUG_METHODS_ENABLED
+void GDMono::_initialize_and_check_api_hashes() {
+
+ api_core_hash = ClassDB::get_api_hash(ClassDB::API_CORE);
+
+#ifndef MONO_GLUE_DISABLED
+ if (api_core_hash != GodotSharpBindings::get_core_api_hash()) {
+ ERR_PRINT("Mono: Core API hash mismatch!");
+ }
+#endif
+
+#ifdef TOOLS_ENABLED
+ api_editor_hash = ClassDB::get_api_hash(ClassDB::API_EDITOR);
+
+#ifndef MONO_GLUE_DISABLED
+ if (api_editor_hash != GodotSharpBindings::get_editor_api_hash()) {
+ ERR_PRINT("Mono: Editor API hash mismatch!");
+ }
+#endif
+
+#endif // TOOLS_ENABLED
+}
+#endif // DEBUG_METHODS_ENABLED
+
+void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) {
+
+ assemblies[p_domain_id][p_assembly->get_name()] = p_assembly;
+}
+
+bool GDMono::_load_assembly(const String &p_name, GDMonoAssembly **r_assembly) {
+
+ CRASH_COND(!r_assembly);
+
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->print((String() + "Mono: Loading assembly " + p_name + "...\n").utf8());
+
+ MonoImageOpenStatus status;
+ MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8());
+ MonoAssembly *assembly = mono_assembly_load_full(aname, NULL, &status, false);
+ mono_assembly_name_free(aname);
+
+ if (!assembly)
+ return false;
+
+ uint32_t domain_id = mono_domain_get_id(mono_domain_get());
+
+ GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name);
+
+ if (stored_assembly) {
+ // Loaded by our preload hook (status is not initialized when returning from a preload hook)
+ ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false);
+ *r_assembly = *stored_assembly;
+ } else {
+ ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false);
+
+ MonoImage *assembly_image = mono_assembly_get_image(assembly);
+ ERR_FAIL_NULL_V(assembly_image, false);
+
+ const char *path = mono_image_get_filename(assembly_image);
+
+ *r_assembly = memnew(GDMonoAssembly(p_name, path));
+ Error error = (*r_assembly)->wrapper_for_image(assembly_image);
+
+ if (error != OK) {
+ memdelete(*r_assembly);
+ *r_assembly = NULL;
+ ERR_FAIL_V(false);
+ }
+ }
+
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->print(String("Mono: Assembly " + p_name + " loaded from path: " + (*r_assembly)->get_path() + "\n").utf8());
+
+ return true;
+}
+
+bool GDMono::_load_corlib_assembly() {
+
+ if (corlib_assembly)
+ return true;
+
+ bool success = _load_assembly("mscorlib", &corlib_assembly);
+
+ if (success)
+ GDMonoUtils::update_corlib_cache();
+
+ return success;
+}
+
+bool GDMono::_load_core_api_assembly() {
+
+ if (api_assembly)
+ return true;
+
+ bool success = _load_assembly(API_ASSEMBLY_NAME, &api_assembly);
+
+ if (success)
+ GDMonoUtils::update_godot_api_cache();
+
+ return success;
+}
+
+#ifdef TOOLS_ENABLED
+bool GDMono::_load_editor_api_assembly() {
+
+ if (editor_api_assembly)
+ return true;
+
+ return _load_assembly(EDITOR_API_ASSEMBLY_NAME, &editor_api_assembly);
+}
+#endif
+
+#ifdef TOOLS_ENABLED
+bool GDMono::_load_editor_tools_assembly() {
+
+ if (editor_tools_assembly)
+ return true;
+
+ _GDMONO_SCOPE_DOMAIN_(tools_domain)
+
+ return _load_assembly(EDITOR_TOOLS_ASSEMBLY_NAME, &editor_tools_assembly);
+}
+#endif
+
+bool GDMono::_load_project_assembly() {
+
+ if (project_assembly)
+ return true;
+
+ String project_assembly_name = ProjectSettings::get_singleton()->get("application/config/name");
+
+ bool success = _load_assembly(project_assembly_name, &project_assembly);
+
+ if (success)
+ mono_assembly_set_main(project_assembly->get_assembly());
+
+ return success;
+}
+
+bool GDMono::_load_all_script_assemblies() {
+
+#ifndef MONO_GLUE_DISABLED
+ if (!_load_core_api_assembly()) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->printerr("Mono: Failed to load Core API assembly\n");
+ return false;
+ } else {
+#ifdef TOOLS_ENABLED
+ if (!_load_editor_api_assembly()) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->printerr("Mono: Failed to load Editor API assembly\n");
+ return false;
+ }
+#endif
+ }
+
+ if (!_load_project_assembly()) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->printerr("Mono: Failed to load project assembly\n");
+ return false;
+ }
+
+ return true;
+#else
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->print("Mono: Glue disbled, ignoring script assemblies\n");
+
+ return true;
+#endif
+}
+
+Error GDMono::_load_scripts_domain() {
+
+ ERR_FAIL_COND_V(scripts_domain != NULL, ERR_BUG);
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ OS::get_singleton()->print("Mono: Loading scripts domain...\n");
+ }
+
+ scripts_domain = GDMonoUtils::create_domain("GodotEngine.ScriptsDomain");
+
+ ERR_EXPLAIN("Mono: Could not create scripts app domain");
+ ERR_FAIL_NULL_V(scripts_domain, ERR_CANT_CREATE);
+
+ mono_domain_set(scripts_domain, true);
+
+ return OK;
+}
+
+Error GDMono::_unload_scripts_domain() {
+
+ ERR_FAIL_NULL_V(scripts_domain, ERR_BUG);
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ OS::get_singleton()->print("Mono: Unloading scripts domain...\n");
+ }
+
+ _GodotSharp::get_singleton()->_dispose_callback();
+
+ if (mono_domain_get() != root_domain)
+ mono_domain_set(root_domain, true);
+
+ finalizing_scripts_domain = true;
+ mono_domain_finalize(scripts_domain, 2000);
+ finalizing_scripts_domain = false;
+
+ _domain_assemblies_cleanup(mono_domain_get_id(scripts_domain));
+
+ api_assembly = NULL;
+ project_assembly = NULL;
+#ifdef TOOLS_ENABLED
+ editor_api_assembly = NULL;
+#endif
+
+ MonoDomain *domain = scripts_domain;
+ scripts_domain = NULL;
+
+ _GodotSharp::get_singleton()->_dispose_callback();
+
+ MonoObject *ex = NULL;
+ mono_domain_try_unload(domain, &ex);
+
+ if (ex) {
+ ERR_PRINT("Exception thrown when unloading scripts domain:");
+ mono_print_unhandled_exception(ex);
+ return FAILED;
+ }
+
+ return OK;
+}
+
+#ifdef TOOLS_ENABLED
+Error GDMono::_load_tools_domain() {
+
+ ERR_FAIL_COND_V(tools_domain != NULL, ERR_BUG);
+
+ if (OS::get_singleton()->is_stdout_verbose()) {
+ OS::get_singleton()->print("Mono: Loading tools domain...\n");
+ }
+
+ tools_domain = GDMonoUtils::create_domain("GodotEngine.ToolsDomain");
+
+ ERR_EXPLAIN("Mono: Could not create tools app domain");
+ ERR_FAIL_NULL_V(tools_domain, ERR_CANT_CREATE);
+
+ return OK;
+}
+#endif
+
+#ifdef TOOLS_ENABLED
+Error GDMono::reload_scripts_domain() {
+
+ ERR_FAIL_COND_V(!runtime_initialized, ERR_BUG);
+
+ if (scripts_domain) {
+ Error err = _unload_scripts_domain();
+ if (err != OK) {
+ ERR_PRINT("Mono: Failed to unload scripts domain");
+ return err;
+ }
+ }
+
+ Error err = _load_scripts_domain();
+ if (err != OK) {
+ ERR_PRINT("Mono: Failed to load scripts domain");
+ return err;
+ }
+
+ if (!_load_all_script_assemblies()) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->printerr("Mono: Failed to load script assemblies\n");
+ return ERR_CANT_OPEN;
+ }
+
+ return OK;
+}
+#endif
+
+GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) {
+
+ MonoImage *image = mono_class_get_image(p_raw_class);
+
+ if (image == corlib_assembly->get_image())
+ return corlib_assembly->get_class(p_raw_class);
+
+ uint32_t domain_id = mono_domain_get_id(mono_domain_get());
+ HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[domain_id];
+
+ const String *k = NULL;
+ while ((k = domain_assemblies.next(k))) {
+ GDMonoAssembly *assembly = domain_assemblies.get(*k);
+ if (assembly->get_image() == image) {
+ GDMonoClass *klass = assembly->get_class(p_raw_class);
+
+ if (klass)
+ return klass;
+ }
+ }
+
+ return NULL;
+}
+
+void GDMono::_domain_assemblies_cleanup(uint32_t p_domain_id) {
+
+ HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id];
+
+ const String *k = NULL;
+ while ((k = domain_assemblies.next(k))) {
+ memdelete(domain_assemblies.get(*k));
+ }
+
+ assemblies.erase(p_domain_id);
+}
+
+GDMono::GDMono() {
+
+ singleton = this;
+
+ gdmono_log = memnew(GDMonoLog);
+
+ runtime_initialized = false;
+ finalizing_scripts_domain = false;
+
+ root_domain = NULL;
+ scripts_domain = NULL;
+#ifdef TOOLS_ENABLED
+ tools_domain = NULL;
+#endif
+
+ corlib_assembly = NULL;
+ api_assembly = NULL;
+ project_assembly = NULL;
+#ifdef TOOLS_ENABLED
+ editor_api_assembly = NULL;
+ editor_tools_assembly = NULL;
+#endif
+
+#ifdef DEBUG_METHODS_ENABLED
+ api_core_hash = 0;
+#ifdef TOOLS_ENABLED
+ api_editor_hash = 0;
+#endif
+#endif
+}
+
+GDMono::~GDMono() {
+
+ if (runtime_initialized) {
+
+ if (scripts_domain) {
+
+ Error err = _unload_scripts_domain();
+ if (err != OK) {
+ WARN_PRINT("Mono: Failed to unload scripts domain");
+ }
+ }
+
+ const uint32_t *k = NULL;
+ while ((k = assemblies.next(k))) {
+ HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies.get(*k);
+
+ const String *kk = NULL;
+ while ((kk = domain_assemblies.next(kk))) {
+ memdelete(domain_assemblies.get(*kk));
+ }
+ }
+ assemblies.clear();
+
+ GDMonoUtils::clear_cache();
+
+ OS::get_singleton()->print("Mono: Runtime cleanup...\n");
+
+ runtime_initialized = false;
+ mono_jit_cleanup(root_domain);
+ }
+
+ if (gdmono_log)
+ memdelete(gdmono_log);
+}
+
+_GodotSharp *_GodotSharp::singleton = NULL;
+
+void _GodotSharp::_dispose_object(Object *p_object) {
+
+ if (p_object->get_script_instance()) {
+ CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(p_object->get_script_instance());
+ if (cs_instance) {
+ cs_instance->mono_object_disposed();
+ return;
+ }
+ }
+
+ // Unsafe refcount decrement. The managed instance also counts as a reference.
+ // See: CSharpLanguage::alloc_instance_binding_data(Object *p_object)
+ if (Object::cast_to<Reference>(p_object)->unreference()) {
+ memdelete(p_object);
+ }
+}
+
+void _GodotSharp::_dispose_callback() {
+
+#ifndef NO_THREADS
+ queue_mutex->lock();
+#endif
+
+ for (List<Object *>::Element *E = obj_delete_queue.front(); E; E = E->next()) {
+ _dispose_object(E->get());
+ }
+
+ for (List<NodePath *>::Element *E = np_delete_queue.front(); E; E = E->next()) {
+ memdelete(E->get());
+ }
+
+ for (List<RID *>::Element *E = rid_delete_queue.front(); E; E = E->next()) {
+ memdelete(E->get());
+ }
+
+ obj_delete_queue.clear();
+ np_delete_queue.clear();
+ rid_delete_queue.clear();
+ queue_empty = true;
+
+#ifndef NO_THREADS
+ queue_mutex->unlock();
+#endif
+}
+
+void _GodotSharp::attach_thread() {
+
+ GDMonoUtils::attach_current_thread();
+}
+
+void _GodotSharp::detach_thread() {
+
+ GDMonoUtils::detach_current_thread();
+}
+
+bool _GodotSharp::is_finalizing_domain() {
+
+ return GDMono::get_singleton()->is_finalizing_scripts_domain();
+}
+
+bool _GodotSharp::is_domain_loaded() {
+
+ return GDMono::get_singleton()->get_scripts_domain() != NULL;
+}
+
+#define ENQUEUE_FOR_DISPOSAL(m_queue, m_inst) \
+ m_queue.push_back(m_inst); \
+ if (queue_empty) { \
+ queue_empty = false; \
+ call_deferred("_dispose_callback"); \
+ }
+
+void _GodotSharp::queue_dispose(Object *p_object) {
+
+ if (Thread::get_main_id() == Thread::get_caller_id() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
+ _dispose_object(p_object);
+ } else {
+#ifndef NO_THREADS
+ queue_mutex->lock();
+#endif
+
+ ENQUEUE_FOR_DISPOSAL(obj_delete_queue, p_object);
+
+#ifndef NO_THREADS
+ queue_mutex->unlock();
+#endif
+ }
+}
+
+void _GodotSharp::queue_dispose(NodePath *p_node_path) {
+
+ if (Thread::get_main_id() == Thread::get_caller_id() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
+ memdelete(p_node_path);
+ } else {
+#ifndef NO_THREADS
+ queue_mutex->lock();
+#endif
+
+ ENQUEUE_FOR_DISPOSAL(np_delete_queue, p_node_path);
+
+#ifndef NO_THREADS
+ queue_mutex->unlock();
+#endif
+ }
+}
+
+void _GodotSharp::queue_dispose(RID *p_rid) {
+
+ if (Thread::get_main_id() == Thread::get_caller_id() && !GDMono::get_singleton()->is_finalizing_scripts_domain()) {
+ memdelete(p_rid);
+ } else {
+#ifndef NO_THREADS
+ queue_mutex->lock();
+#endif
+
+ ENQUEUE_FOR_DISPOSAL(rid_delete_queue, p_rid);
+
+#ifndef NO_THREADS
+ queue_mutex->unlock();
+#endif
+ }
+}
+
+void _GodotSharp::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("attach_thread"), &_GodotSharp::attach_thread);
+ ClassDB::bind_method(D_METHOD("detach_thread"), &_GodotSharp::detach_thread);
+
+ ClassDB::bind_method(D_METHOD("is_finalizing_domain"), &_GodotSharp::is_finalizing_domain);
+ ClassDB::bind_method(D_METHOD("is_domain_loaded"), &_GodotSharp::is_domain_loaded);
+
+ ClassDB::bind_method(D_METHOD("_dispose_callback"), &_GodotSharp::_dispose_callback);
+}
+
+_GodotSharp::_GodotSharp() {
+
+ singleton = this;
+ queue_empty = true;
+#ifndef NO_THREADS
+ queue_mutex = Mutex::create();
+#endif
+}
+
+_GodotSharp::~_GodotSharp() {
+
+ singleton = NULL;
+
+ if (queue_mutex) {
+ memdelete(queue_mutex);
+ }
+}
diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h
new file mode 100644
index 0000000000..ab96d575e6
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono.h
@@ -0,0 +1,224 @@
+/*************************************************************************/
+/* gd_mono.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_MONO_H
+#define GD_MONO_H
+
+#include "../godotsharp_defs.h"
+#include "gd_mono_assembly.h"
+#include "gd_mono_log.h"
+
+#ifdef WINDOWS_ENABLED
+#include "../utils/mono_reg_utils.h"
+#endif
+
+#define SCRIPTS_DOMAIN GDMono::get_singleton()->get_scripts_domain()
+#ifdef TOOLS_ENABLED
+#define TOOLS_DOMAIN GDMono::get_singleton()->get_tools_domain()
+#endif
+
+class GDMono {
+
+ bool runtime_initialized;
+ bool finalizing_scripts_domain;
+
+ MonoDomain *root_domain;
+ MonoDomain *scripts_domain;
+#ifdef TOOLS_ENABLED
+ MonoDomain *tools_domain;
+#endif
+
+ GDMonoAssembly *corlib_assembly;
+ GDMonoAssembly *api_assembly;
+ GDMonoAssembly *project_assembly;
+#ifdef TOOLS_ENABLED
+ GDMonoAssembly *editor_api_assembly;
+ GDMonoAssembly *editor_tools_assembly;
+#endif
+
+ HashMap<uint32_t, HashMap<String, GDMonoAssembly *> > assemblies;
+
+ void _domain_assemblies_cleanup(uint32_t p_domain_id);
+
+ bool _load_corlib_assembly();
+ bool _load_core_api_assembly();
+#ifdef TOOLS_ENABLED
+ bool _load_editor_api_assembly();
+ bool _load_editor_tools_assembly();
+#endif
+ bool _load_project_assembly();
+
+ bool _load_all_script_assemblies();
+
+ void _register_internal_calls();
+
+ Error _load_scripts_domain();
+ Error _unload_scripts_domain();
+
+#ifdef TOOLS_ENABLED
+ Error _load_tools_domain();
+#endif
+
+#ifdef DEBUG_METHODS_ENABLED
+ uint64_t api_core_hash;
+#ifdef TOOLS_ENABLED
+ uint64_t api_editor_hash;
+#endif
+ void _initialize_and_check_api_hashes();
+#endif
+
+ bool _load_assembly(const String &p_name, GDMonoAssembly **r_assembly);
+
+ GDMonoLog *gdmono_log;
+
+#ifdef WINDOWS_ENABLED
+ MonoRegInfo mono_reg_info;
+#endif
+
+protected:
+ static GDMono *singleton;
+
+public:
+#ifdef DEBUG_METHODS_ENABLED
+ uint64_t get_api_core_hash() { return api_core_hash; }
+#ifdef TOOLS_ENABLED
+ uint64_t get_api_editor_hash() { return api_editor_hash; }
+#endif
+#endif
+
+ enum MemberVisibility {
+ PRIVATE,
+ PROTECTED_AND_INTERNAL, // FAM_AND_ASSEM
+ INTERNAL, // ASSEMBLY
+ PROTECTED, // FAMILY
+ PUBLIC
+ };
+
+ static GDMono *get_singleton() { return singleton; }
+
+ void add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly);
+
+ _FORCE_INLINE_ bool is_runtime_initialized() const { return runtime_initialized; }
+ _FORCE_INLINE_ bool is_finalizing_scripts_domain() const { return finalizing_scripts_domain; }
+
+ _FORCE_INLINE_ MonoDomain *get_scripts_domain() { return scripts_domain; }
+#ifdef TOOLS_ENABLED
+ _FORCE_INLINE_ MonoDomain *get_tools_domain() { return tools_domain; }
+#endif
+
+ _FORCE_INLINE_ GDMonoAssembly *get_corlib_assembly() const { return corlib_assembly; }
+ _FORCE_INLINE_ GDMonoAssembly *get_api_assembly() const { return api_assembly; }
+ _FORCE_INLINE_ GDMonoAssembly *get_project_assembly() const { return project_assembly; }
+#ifdef TOOLS_ENABLED
+ _FORCE_INLINE_ GDMonoAssembly *get_editor_api_assembly() const { return editor_api_assembly; }
+ _FORCE_INLINE_ GDMonoAssembly *get_editor_tools_assembly() const { return editor_tools_assembly; }
+#endif
+
+#ifdef WINDOWS_ENABLED
+ const MonoRegInfo &get_mono_reg_info() { return mono_reg_info; }
+#endif
+
+ GDMonoClass *get_class(MonoClass *p_raw_class);
+
+#ifdef TOOLS_ENABLED
+ Error reload_scripts_domain();
+#endif
+
+ void initialize();
+
+ GDMono();
+ ~GDMono();
+};
+
+class GDMonoScopeDomain {
+
+ MonoDomain *prev_domain;
+
+public:
+ GDMonoScopeDomain(MonoDomain *p_domain) {
+ MonoDomain *prev_domain = mono_domain_get();
+ if (prev_domain != p_domain) {
+ this->prev_domain = prev_domain;
+ mono_domain_set(p_domain, false);
+ } else {
+ this->prev_domain = NULL;
+ }
+ }
+
+ ~GDMonoScopeDomain() {
+ if (prev_domain)
+ mono_domain_set(prev_domain, false);
+ }
+};
+
+#define _GDMONO_SCOPE_DOMAIN_(m_mono_domain) \
+ GDMonoScopeDomain __gdmono__scope__domain__(m_mono_domain); \
+ (void)__gdmono__scope__domain__;
+
+class _GodotSharp : public Object {
+ GDCLASS(_GodotSharp, Object)
+
+ friend class GDMono;
+
+ void _dispose_object(Object *p_object);
+
+ void _dispose_callback();
+
+ List<Object *> obj_delete_queue;
+ List<NodePath *> np_delete_queue;
+ List<RID *> rid_delete_queue;
+
+ bool queue_empty;
+
+#ifndef NO_THREADS
+ Mutex *queue_mutex;
+#endif
+
+protected:
+ static _GodotSharp *singleton;
+ static void _bind_methods();
+
+public:
+ static _GodotSharp *get_singleton() { return singleton; }
+
+ void attach_thread();
+ void detach_thread();
+
+ bool is_finalizing_domain();
+ bool is_domain_loaded();
+
+ void queue_dispose(Object *p_object);
+ void queue_dispose(NodePath *p_node_path);
+ void queue_dispose(RID *p_rid);
+
+ _GodotSharp();
+ ~_GodotSharp();
+};
+
+#endif // GD_MONO_H
diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp
new file mode 100644
index 0000000000..a98537b9e1
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_assembly.cpp
@@ -0,0 +1,327 @@
+/*************************************************************************/
+/* gd_mono_assembly.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono_assembly.h"
+
+#include <mono/metadata/mono-debug.h>
+#include <mono/metadata/tokentype.h>
+
+#include "list.h"
+#include "os/file_access.h"
+#include "os/os.h"
+
+#include "../godotsharp_dirs.h"
+#include "gd_mono_class.h"
+
+MonoAssembly *gdmono_load_assembly_from(const String &p_name, const String &p_path) {
+
+ MonoDomain *domain = mono_domain_get();
+
+ GDMonoAssembly *assembly = memnew(GDMonoAssembly(p_name, p_path));
+ Error err = assembly->load(domain);
+ ERR_FAIL_COND_V(err != OK, NULL);
+
+ GDMono::get_singleton()->add_assembly(mono_domain_get_id(domain), assembly);
+
+ return assembly->get_assembly();
+}
+
+MonoAssembly *gdmono_MonoAssemblyPreLoad(MonoAssemblyName *aname, char **assemblies_path, void *user_data) {
+
+ (void)user_data; // UNUSED
+
+ MonoAssembly *assembly_loaded = mono_assembly_loaded(aname);
+ if (assembly_loaded) // Already loaded
+ return assembly_loaded;
+
+ static Vector<String> search_dirs;
+
+ if (search_dirs.empty()) {
+ search_dirs.push_back(GodotSharpDirs::get_res_temp_assemblies_dir());
+ search_dirs.push_back(GodotSharpDirs::get_res_assemblies_dir());
+ search_dirs.push_back(OS::get_singleton()->get_resource_dir());
+ search_dirs.push_back(OS::get_singleton()->get_executable_path().get_base_dir());
+
+ const char *rootdir = mono_assembly_getrootdir();
+ if (rootdir) {
+ search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5"));
+ }
+
+ while (assemblies_path) {
+ if (*assemblies_path)
+ search_dirs.push_back(*assemblies_path);
+ ++assemblies_path;
+ }
+ }
+
+ String name = mono_assembly_name_get_name(aname);
+ bool has_extension = name.ends_with(".dll") || name.ends_with(".exe");
+
+ String path;
+
+ for (int i = 0; i < search_dirs.size(); i++) {
+ const String &search_dir = search_dirs[i];
+
+ if (has_extension) {
+ path = search_dir.plus_file(name);
+ if (FileAccess::exists(path))
+ return gdmono_load_assembly_from(name.get_basename(), path);
+ } else {
+ path = search_dir.plus_file(name + ".dll");
+ if (FileAccess::exists(path))
+ return gdmono_load_assembly_from(name, path);
+
+ path = search_dir.plus_file(name + ".exe");
+ if (FileAccess::exists(path))
+ return gdmono_load_assembly_from(name, path);
+ }
+ }
+
+ return NULL;
+}
+
+void GDMonoAssembly::initialize() {
+
+ mono_install_assembly_preload_hook(&gdmono_MonoAssemblyPreLoad, NULL);
+}
+
+Error GDMonoAssembly::load(MonoDomain *p_domain) {
+
+ ERR_FAIL_COND_V(loaded, ERR_FILE_ALREADY_IN_USE);
+
+ uint64_t last_modified_time = FileAccess::get_modified_time(path);
+
+ Vector<uint8_t> data = FileAccess::get_file_as_array(path);
+ ERR_FAIL_COND_V(data.empty(), ERR_FILE_CANT_READ);
+
+ String image_filename(path);
+
+ MonoImageOpenStatus status;
+
+ image = mono_image_open_from_data_with_name(
+ (char *)&data[0], data.size(),
+ true, &status, false,
+ image_filename.utf8().get_data());
+
+ ERR_FAIL_COND_V(status != MONO_IMAGE_OK || image == NULL, ERR_FILE_CANT_OPEN);
+
+#ifdef DEBUG_ENABLED
+ String pdb_path(path + ".pdb");
+
+ if (!FileAccess::exists(pdb_path)) {
+ pdb_path = path.get_basename() + ".pdb"; // without .dll
+
+ if (!FileAccess::exists(pdb_path))
+ goto no_pdb;
+ }
+
+ pdb_data.clear();
+ pdb_data = FileAccess::get_file_as_array(pdb_path);
+ mono_debug_open_image_from_memory(image, &pdb_data[0], pdb_data.size());
+
+no_pdb:
+
+#endif
+
+ assembly = mono_assembly_load_from_full(image, image_filename.utf8().get_data(), &status, false);
+
+ ERR_FAIL_COND_V(status != MONO_IMAGE_OK || assembly == NULL, ERR_FILE_CANT_OPEN);
+
+ if (mono_image_get_entry_point(image)) {
+ // TODO should this be removed? do we want to call main? what other effects does this have?
+ mono_jit_exec(p_domain, assembly, 0, NULL);
+ }
+
+ loaded = true;
+ modified_time = last_modified_time;
+
+ return OK;
+}
+
+Error GDMonoAssembly::wrapper_for_image(MonoImage *p_image) {
+
+ ERR_FAIL_COND_V(loaded, ERR_FILE_ALREADY_IN_USE);
+
+ assembly = mono_image_get_assembly(p_image);
+ ERR_FAIL_NULL_V(assembly, FAILED);
+
+ image = p_image;
+
+ mono_image_addref(image);
+
+ loaded = true;
+
+ return OK;
+}
+
+void GDMonoAssembly::unload() {
+
+ ERR_FAIL_COND(!loaded);
+
+#ifdef DEBUG_ENABLED
+ if (pdb_data.size()) {
+ mono_debug_close_image(image);
+ pdb_data.clear();
+ }
+#endif
+
+ for (Map<MonoClass *, GDMonoClass *>::Element *E = cached_raw.front(); E; E = E->next()) {
+ memdelete(E->value());
+ }
+
+ cached_classes.clear();
+ cached_raw.clear();
+
+ mono_image_close(image);
+
+ assembly = NULL;
+ image = NULL;
+ loaded = false;
+}
+
+GDMonoClass *GDMonoAssembly::get_class(const StringName &p_namespace, const StringName &p_name) {
+
+ ERR_FAIL_COND_V(!loaded, NULL);
+
+ ClassKey key(p_namespace, p_name);
+
+ GDMonoClass **match = cached_classes.getptr(key);
+
+ if (match)
+ return *match;
+
+ MonoClass *mono_class = mono_class_from_name(image, String(p_namespace).utf8(), String(p_name).utf8());
+
+ if (!mono_class)
+ return NULL;
+
+ GDMonoClass *wrapped_class = memnew(GDMonoClass(p_namespace, p_name, mono_class, this));
+
+ cached_classes[key] = wrapped_class;
+ cached_raw[mono_class] = wrapped_class;
+
+ return wrapped_class;
+}
+
+GDMonoClass *GDMonoAssembly::get_class(MonoClass *p_mono_class) {
+
+ ERR_FAIL_COND_V(!loaded, NULL);
+
+ Map<MonoClass *, GDMonoClass *>::Element *match = cached_raw.find(p_mono_class);
+
+ if (match)
+ return match->value();
+
+ StringName namespace_name = mono_class_get_namespace(p_mono_class);
+ StringName class_name = mono_class_get_name(p_mono_class);
+
+ GDMonoClass *wrapped_class = memnew(GDMonoClass(namespace_name, class_name, p_mono_class, this));
+
+ cached_classes[ClassKey(namespace_name, class_name)] = wrapped_class;
+ cached_raw[p_mono_class] = wrapped_class;
+
+ return wrapped_class;
+}
+
+GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) {
+
+ GDMonoClass *match = NULL;
+
+ if (gdobject_class_cache_updated) {
+ Map<StringName, GDMonoClass *>::Element *result = gdobject_class_cache.find(p_class);
+
+ if (result)
+ match = result->get();
+ } else {
+ List<GDMonoClass *> nested_classes;
+
+ int rows = mono_image_get_table_rows(image, MONO_TABLE_TYPEDEF);
+
+ for (int i = 1; i < rows; i++) {
+ MonoClass *mono_class = mono_class_get(image, (i + 1) | MONO_TOKEN_TYPE_DEF);
+
+ if (!mono_class_is_assignable_from(CACHED_CLASS_RAW(GodotObject), mono_class))
+ continue;
+
+ GDMonoClass *current = get_class(mono_class);
+
+ if (!current)
+ continue;
+
+ nested_classes.push_back(current);
+
+ if (!match && current->get_name() == p_class)
+ match = current;
+
+ while (!nested_classes.empty()) {
+ GDMonoClass *current_nested = nested_classes.front()->get();
+ nested_classes.pop_back();
+
+ void *iter = NULL;
+
+ while (true) {
+ MonoClass *raw_nested = mono_class_get_nested_types(current_nested->get_raw(), &iter);
+
+ if (!raw_nested)
+ break;
+
+ GDMonoClass *nested_class = get_class(raw_nested);
+
+ if (nested_class) {
+ gdobject_class_cache.insert(nested_class->get_name(), nested_class);
+ nested_classes.push_back(nested_class);
+ }
+ }
+ }
+
+ gdobject_class_cache.insert(current->get_name(), current);
+ }
+
+ gdobject_class_cache_updated = true;
+ }
+
+ return match;
+}
+
+GDMonoAssembly::GDMonoAssembly(const String &p_name, const String &p_path) {
+
+ loaded = false;
+ gdobject_class_cache_updated = false;
+ name = p_name;
+ path = p_path;
+ modified_time = 0;
+ assembly = NULL;
+ image = NULL;
+}
+
+GDMonoAssembly::~GDMonoAssembly() {
+
+ if (loaded)
+ unload();
+}
diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h
new file mode 100644
index 0000000000..89e091549c
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_assembly.h
@@ -0,0 +1,113 @@
+/*************************************************************************/
+/* gd_mono_assembly.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_MONO_ASSEMBLY_H
+#define GD_MONO_ASSEMBLY_H
+
+#include <mono/jit/jit.h>
+#include <mono/metadata/assembly.h>
+
+#include "gd_mono_utils.h"
+#include "hash_map.h"
+#include "map.h"
+#include "ustring.h"
+
+class GDMonoAssembly {
+
+ struct ClassKey {
+ struct Hasher {
+ static _FORCE_INLINE_ uint32_t hash(const ClassKey &p_key) {
+ uint32_t hash = 0;
+
+ GDMonoUtils::hash_combine(hash, p_key.namespace_name.hash());
+ GDMonoUtils::hash_combine(hash, p_key.class_name.hash());
+
+ return hash;
+ }
+ };
+
+ _FORCE_INLINE_ bool operator==(const ClassKey &p_a) const {
+ return p_a.class_name == class_name && p_a.namespace_name == namespace_name;
+ }
+
+ ClassKey() {}
+
+ ClassKey(const StringName &p_namespace_name, const StringName &p_class_name) {
+ namespace_name = p_namespace_name;
+ class_name = p_class_name;
+ }
+
+ StringName namespace_name;
+ StringName class_name;
+ };
+
+ MonoAssembly *assembly;
+ MonoImage *image;
+
+ bool loaded;
+
+ String name;
+ String path;
+ uint64_t modified_time;
+
+ HashMap<ClassKey, GDMonoClass *, ClassKey::Hasher> cached_classes;
+ Map<MonoClass *, GDMonoClass *> cached_raw;
+
+ bool gdobject_class_cache_updated;
+ Map<StringName, GDMonoClass *> gdobject_class_cache;
+
+#ifdef DEBUG_ENABLED
+ Vector<uint8_t> pdb_data;
+#endif
+
+ friend class GDMono;
+ static void initialize();
+
+public:
+ Error load(MonoDomain *p_domain);
+ Error wrapper_for_image(MonoImage *p_image);
+ void unload();
+
+ _FORCE_INLINE_ bool is_loaded() const { return loaded; }
+ _FORCE_INLINE_ MonoImage *get_image() const { return image; }
+ _FORCE_INLINE_ MonoAssembly *get_assembly() const { return assembly; }
+ _FORCE_INLINE_ String get_name() const { return name; }
+ _FORCE_INLINE_ String get_path() const { return path; }
+ _FORCE_INLINE_ uint64_t get_modified_time() const { return modified_time; }
+
+ GDMonoClass *get_class(const StringName &p_namespace, const StringName &p_class);
+ GDMonoClass *get_class(MonoClass *p_mono_class);
+
+ GDMonoClass *get_object_derived_class(const StringName &p_class);
+
+ GDMonoAssembly(const String &p_name, const String &p_path = String());
+ ~GDMonoAssembly();
+};
+
+#endif // GD_MONO_ASSEMBLY_H
diff --git a/modules/mono/mono_gd/gd_mono_class.cpp b/modules/mono/mono_gd/gd_mono_class.cpp
new file mode 100644
index 0000000000..0134ace5d7
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_class.cpp
@@ -0,0 +1,381 @@
+/*************************************************************************/
+/* gd_mono_class.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono_class.h"
+
+#include <mono/metadata/attrdefs.h>
+
+#include "gd_mono_assembly.h"
+
+MonoType *GDMonoClass::get_raw_type(GDMonoClass *p_class) {
+
+ return mono_class_get_type(p_class->get_raw());
+}
+
+bool GDMonoClass::is_assignable_from(GDMonoClass *p_from) const {
+
+ return mono_class_is_assignable_from(mono_class, p_from->mono_class);
+}
+
+GDMonoClass *GDMonoClass::get_parent_class() {
+
+ if (assembly) {
+ MonoClass *parent_mono_class = mono_class_get_parent(mono_class);
+
+ if (parent_mono_class) {
+ return GDMono::get_singleton()->get_class(parent_mono_class);
+ }
+ }
+
+ return NULL;
+}
+
+bool GDMonoClass::has_method(const StringName &p_name) {
+
+ return get_method(p_name) != NULL;
+}
+
+bool GDMonoClass::has_attribute(GDMonoClass *p_attr_class) {
+
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_NULL_V(p_attr_class, false);
+#endif
+
+ if (!attrs_fetched)
+ fetch_attributes();
+
+ if (!attributes)
+ return false;
+
+ return mono_custom_attrs_has_attr(attributes, p_attr_class->get_raw());
+}
+
+MonoObject *GDMonoClass::get_attribute(GDMonoClass *p_attr_class) {
+
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_NULL_V(p_attr_class, NULL);
+#endif
+
+ if (!attrs_fetched)
+ fetch_attributes();
+
+ if (!attributes)
+ return NULL;
+
+ return mono_custom_attrs_get_attr(attributes, p_attr_class->get_raw());
+}
+
+void GDMonoClass::fetch_attributes() {
+
+ ERR_FAIL_COND(attributes != NULL);
+
+ attributes = mono_custom_attrs_from_class(get_raw());
+ attrs_fetched = true;
+}
+
+void GDMonoClass::fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base) {
+
+ CRASH_COND(!CACHED_CLASS(GodotObject)->is_assignable_from(this));
+
+ if (methods_fetched)
+ return;
+
+ void *iter = NULL;
+ MonoMethod *raw_method = NULL;
+ while ((raw_method = mono_class_get_methods(get_raw(), &iter)) != NULL) {
+ StringName name = mono_method_get_name(raw_method);
+
+ GDMonoMethod *method = get_method(raw_method, name);
+ ERR_CONTINUE(!method);
+
+ if (method->get_name() != name) {
+
+#ifdef DEBUG_ENABLED
+ String fullname = method->get_ret_type_full_name() + " " + name + "(" + method->get_signature_desc(true) + ")";
+ WARN_PRINTS("Method `" + fullname + "` is hidden by Godot API method. Should be `" +
+ method->get_full_name_no_class() + "`. In class `" + namespace_name + "." + class_name + "`.");
+#endif
+ continue;
+ }
+
+#ifdef DEBUG_ENABLED
+ // For debug builds, we also fetched from native base classes as well before if this is not a native base class.
+ // This allows us to warn the user here if he is using snake_case by mistake.
+
+ if (p_native_base != this) {
+
+ GDMonoClass *native_top = p_native_base;
+ while (native_top) {
+ GDMonoMethod *m = native_top->get_method(name, method->get_parameters_count());
+
+ if (m && m->get_name() != name) {
+ // found
+ String fullname = m->get_ret_type_full_name() + " " + name + "(" + m->get_signature_desc(true) + ")";
+ WARN_PRINTS("Method `" + fullname + "` should be `" + m->get_full_name_no_class() +
+ "`. In class `" + namespace_name + "." + class_name + "`.");
+ break;
+ }
+
+ if (native_top == CACHED_CLASS(GodotObject))
+ break;
+
+ native_top = native_top->get_parent_class();
+ }
+ }
+#endif
+
+ uint32_t flags = mono_method_get_flags(method->mono_method, NULL);
+
+ if (!(flags & MONO_METHOD_ATTR_VIRTUAL))
+ continue;
+
+ // Virtual method of Godot Object derived type, let's try to find GodotMethod attribute
+
+ GDMonoClass *top = p_native_base;
+
+ while (top) {
+ GDMonoMethod *base_method = top->get_method(name, method->get_parameters_count());
+
+ if (base_method && base_method->has_attribute(CACHED_CLASS(GodotMethodAttribute))) {
+ // Found base method with GodotMethod attribute.
+ // We get the original API method name from this attribute.
+ // This name must point to the virtual method.
+
+ MonoObject *attr = base_method->get_attribute(CACHED_CLASS(GodotMethodAttribute));
+
+ StringName godot_method_name = CACHED_FIELD(GodotMethodAttribute, methodName)->get_string_value(attr);
+#ifdef DEBUG_ENABLED
+ CRASH_COND(godot_method_name == StringName());
+#endif
+ MethodKey key = MethodKey(godot_method_name, method->get_parameters_count());
+ GDMonoMethod **existing_method = methods.getptr(key);
+ if (existing_method)
+ memdelete(*existing_method); // Must delete old one
+ methods.set(key, method);
+
+ break;
+ }
+
+ if (top == CACHED_CLASS(GodotObject))
+ break;
+
+ top = top->get_parent_class();
+ }
+ }
+
+ methods_fetched = true;
+}
+
+GDMonoMethod *GDMonoClass::get_method(const StringName &p_name) {
+
+ ERR_FAIL_COND_V(!methods_fetched, NULL);
+
+ const MethodKey *k = NULL;
+
+ while ((k = methods.next(k))) {
+ if (k->name == p_name)
+ return methods.get(*k);
+ }
+
+ return NULL;
+}
+
+GDMonoMethod *GDMonoClass::get_method(const StringName &p_name, int p_params_count) {
+
+ MethodKey key = MethodKey(p_name, p_params_count);
+
+ GDMonoMethod **match = methods.getptr(key);
+
+ if (match)
+ return *match;
+
+ if (methods_fetched)
+ return NULL;
+
+ MonoMethod *raw_method = mono_class_get_method_from_name(mono_class, String(p_name).utf8().get_data(), p_params_count);
+
+ if (raw_method) {
+ GDMonoMethod *method = memnew(GDMonoMethod(p_name, raw_method));
+ methods.set(key, method);
+
+ return method;
+ }
+
+ return NULL;
+}
+
+GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method) {
+
+ MonoMethodSignature *sig = mono_method_signature(p_raw_method);
+
+ int params_count = mono_signature_get_param_count(sig);
+ StringName method_name = mono_method_get_name(p_raw_method);
+
+ return get_method(p_raw_method, method_name, params_count);
+}
+
+GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name) {
+
+ MonoMethodSignature *sig = mono_method_signature(p_raw_method);
+ int params_count = mono_signature_get_param_count(sig);
+ return get_method(p_raw_method, p_name, params_count);
+}
+
+GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count) {
+
+ ERR_FAIL_NULL_V(p_raw_method, NULL);
+
+ MethodKey key = MethodKey(p_name, p_params_count);
+
+ GDMonoMethod **match = methods.getptr(key);
+
+ if (match)
+ return *match;
+
+ GDMonoMethod *method = memnew(GDMonoMethod(p_name, p_raw_method));
+ methods.set(key, method);
+
+ return method;
+}
+
+GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, bool p_include_namespace) {
+
+ MonoMethodDesc *desc = mono_method_desc_new(p_description.utf8().get_data(), p_include_namespace);
+ MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class);
+ mono_method_desc_free(desc);
+
+ return get_method(method);
+}
+
+GDMonoField *GDMonoClass::get_field(const StringName &p_name) {
+
+ Map<StringName, GDMonoField *>::Element *result = fields.find(p_name);
+
+ if (result)
+ return result->value();
+
+ if (fields_fetched)
+ return NULL;
+
+ MonoClassField *raw_field = mono_class_get_field_from_name(mono_class, String(p_name).utf8().get_data());
+
+ if (raw_field) {
+ GDMonoField *field = memnew(GDMonoField(raw_field, this));
+ fields.insert(p_name, field);
+
+ return field;
+ }
+
+ return NULL;
+}
+
+const Vector<GDMonoField *> &GDMonoClass::get_all_fields() {
+
+ if (fields_fetched)
+ return fields_list;
+
+ void *iter = NULL;
+ MonoClassField *raw_field = NULL;
+ while ((raw_field = mono_class_get_fields(get_raw(), &iter)) != NULL) {
+ StringName name = mono_field_get_name(raw_field);
+
+ Map<StringName, GDMonoField *>::Element *match = fields.find(name);
+
+ if (match) {
+ fields_list.push_back(match->get());
+ } else {
+ GDMonoField *field = memnew(GDMonoField(raw_field, this));
+ fields.insert(name, field);
+ fields_list.push_back(field);
+ }
+ }
+
+ fields_fetched = true;
+
+ return fields_list;
+}
+
+GDMonoClass::GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly) {
+
+ namespace_name = p_namespace;
+ class_name = p_name;
+ mono_class = p_class;
+ assembly = p_assembly;
+
+ attrs_fetched = false;
+ attributes = NULL;
+
+ methods_fetched = false;
+ fields_fetched = false;
+}
+
+GDMonoClass::~GDMonoClass() {
+
+ if (attributes) {
+ mono_custom_attrs_free(attributes);
+ }
+
+ for (Map<StringName, GDMonoField *>::Element *E = fields.front(); E; E = E->next()) {
+ memdelete(E->value());
+ }
+
+ {
+ // Ugly workaround...
+ // We may have duplicated values, because we redirect snake_case methods to PascalCasel (only Godot API methods).
+ // This way, we end with both the snake_case name and the PascalCasel name paired with the same method.
+ // Therefore, we must avoid deleting the same pointer twice.
+
+ int offset = 0;
+ Vector<GDMonoMethod *> deleted_methods;
+ deleted_methods.resize(methods.size());
+
+ const MethodKey *k = NULL;
+ while ((k = methods.next(k))) {
+ GDMonoMethod *method = methods.get(*k);
+
+ if (method) {
+ for (int i = 0; i < offset; i++) {
+ if (deleted_methods[i] == method) {
+ // Already deleted
+ goto already_deleted;
+ }
+ }
+
+ deleted_methods[offset] = method;
+ ++offset;
+
+ memdelete(method);
+ }
+
+ already_deleted:;
+ }
+
+ methods.clear();
+ }
+}
diff --git a/modules/mono/mono_gd/gd_mono_class.h b/modules/mono/mono_gd/gd_mono_class.h
new file mode 100644
index 0000000000..1e72553879
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_class.h
@@ -0,0 +1,124 @@
+/*************************************************************************/
+/* gd_mono_class.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_MONO_CLASS_H
+#define GD_MONO_CLASS_H
+
+#include <mono/metadata/debug-helpers.h>
+
+#include "map.h"
+#include "ustring.h"
+
+#include "gd_mono_field.h"
+#include "gd_mono_header.h"
+#include "gd_mono_method.h"
+#include "gd_mono_utils.h"
+
+class GDMonoClass {
+ struct MethodKey {
+ struct Hasher {
+ static _FORCE_INLINE_ uint32_t hash(const MethodKey &p_key) {
+ uint32_t hash = 0;
+
+ GDMonoUtils::hash_combine(hash, p_key.name.hash());
+ GDMonoUtils::hash_combine(hash, HashMapHasherDefault::hash(p_key.params_count));
+
+ return hash;
+ }
+ };
+
+ _FORCE_INLINE_ bool operator==(const MethodKey &p_a) const {
+ return p_a.params_count == params_count && p_a.name == name;
+ }
+
+ MethodKey() {}
+
+ MethodKey(const StringName &p_name, int p_params_count) {
+ name = p_name;
+ params_count = p_params_count;
+ }
+
+ StringName name;
+ int params_count;
+ };
+
+ StringName namespace_name;
+ StringName class_name;
+
+ MonoClass *mono_class;
+ GDMonoAssembly *assembly;
+
+ bool attrs_fetched;
+ MonoCustomAttrInfo *attributes;
+
+ bool methods_fetched;
+ HashMap<MethodKey, GDMonoMethod *, MethodKey::Hasher> methods;
+
+ bool fields_fetched;
+ Map<StringName, GDMonoField *> fields;
+ Vector<GDMonoField *> fields_list;
+
+ friend class GDMonoAssembly;
+ GDMonoClass(const StringName &p_namespace, const StringName &p_name, MonoClass *p_class, GDMonoAssembly *p_assembly);
+
+public:
+ static MonoType *get_raw_type(GDMonoClass *p_class);
+
+ bool is_assignable_from(GDMonoClass *p_from) const;
+
+ _FORCE_INLINE_ StringName get_namespace() const { return namespace_name; }
+ _FORCE_INLINE_ StringName get_name() const { return class_name; }
+
+ _FORCE_INLINE_ MonoClass *get_raw() const { return mono_class; }
+ _FORCE_INLINE_ const GDMonoAssembly *get_assembly() const { return assembly; }
+
+ GDMonoClass *get_parent_class();
+
+ bool has_method(const StringName &p_name);
+
+ bool has_attribute(GDMonoClass *p_attr_class);
+ MonoObject *get_attribute(GDMonoClass *p_attr_class);
+
+ void fetch_attributes();
+ void fetch_methods_with_godot_api_checks(GDMonoClass *p_native_base);
+
+ GDMonoMethod *get_method(const StringName &p_name);
+ GDMonoMethod *get_method(const StringName &p_name, int p_params_count);
+ GDMonoMethod *get_method(MonoMethod *p_raw_method);
+ GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name);
+ GDMonoMethod *get_method(MonoMethod *p_raw_method, const StringName &p_name, int p_params_count);
+ GDMonoMethod *get_method_with_desc(const String &p_description, bool p_includes_namespace);
+
+ GDMonoField *get_field(const StringName &p_name);
+ const Vector<GDMonoField *> &get_all_fields();
+
+ ~GDMonoClass();
+};
+
+#endif // GD_MONO_CLASS_H
diff --git a/modules/mono/mono_gd/gd_mono_field.cpp b/modules/mono/mono_gd/gd_mono_field.cpp
new file mode 100644
index 0000000000..0c64380e31
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_field.cpp
@@ -0,0 +1,362 @@
+/*************************************************************************/
+/* gd_mono_field.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono_field.h"
+
+#include <mono/metadata/attrdefs.h>
+
+#include "gd_mono_class.h"
+#include "gd_mono_marshal.h"
+
+void GDMonoField::set_value_raw(MonoObject *p_object, void *p_ptr) {
+ mono_field_set_value(p_object, mono_field, &p_ptr);
+}
+
+void GDMonoField::set_value(MonoObject *p_object, const Variant &p_value) {
+#define SET_FROM_STRUCT_AND_BREAK(m_type) \
+ { \
+ const m_type &val = p_value.operator m_type(); \
+ MARSHALLED_OUT(m_type, val, raw); \
+ mono_field_set_value(p_object, mono_field, raw); \
+ break; \
+ }
+
+#define SET_FROM_PRIMITIVE(m_type) \
+ { \
+ m_type val = p_value.operator m_type(); \
+ mono_field_set_value(p_object, mono_field, &val); \
+ }
+
+#define SET_FROM_ARRAY_AND_BREAK(m_type) \
+ { \
+ MonoArray *managed = GDMonoMarshal::m_type##_to_mono_array(p_value.operator m_type()); \
+ mono_field_set_value(p_object, mono_field, &managed); \
+ break; \
+ }
+
+ switch (type.type_encoding) {
+ case MONO_TYPE_BOOLEAN: {
+ SET_FROM_PRIMITIVE(bool);
+ } break;
+
+ case MONO_TYPE_I1: {
+ SET_FROM_PRIMITIVE(signed char);
+ } break;
+ case MONO_TYPE_I2: {
+ SET_FROM_PRIMITIVE(signed short);
+ } break;
+ case MONO_TYPE_I4: {
+ SET_FROM_PRIMITIVE(signed int);
+ } break;
+ case MONO_TYPE_I8: {
+ SET_FROM_PRIMITIVE(int64_t);
+ } break;
+
+ case MONO_TYPE_U1: {
+ SET_FROM_PRIMITIVE(unsigned char);
+ } break;
+ case MONO_TYPE_U2: {
+ SET_FROM_PRIMITIVE(unsigned short);
+ } break;
+ case MONO_TYPE_U4: {
+ SET_FROM_PRIMITIVE(unsigned int);
+ } break;
+ case MONO_TYPE_U8: {
+ SET_FROM_PRIMITIVE(uint64_t);
+ } break;
+
+ case MONO_TYPE_R4: {
+ SET_FROM_PRIMITIVE(float);
+ } break;
+
+ case MONO_TYPE_R8: {
+ SET_FROM_PRIMITIVE(double);
+ } break;
+
+ case MONO_TYPE_STRING: {
+ MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
+ mono_field_set_value(p_object, mono_field, mono_string);
+ } break;
+
+ case MONO_TYPE_VALUETYPE: {
+ GDMonoClass *tclass = type.type_class;
+
+ if (tclass == CACHED_CLASS(Vector2))
+ SET_FROM_STRUCT_AND_BREAK(Vector2);
+
+ if (tclass == CACHED_CLASS(Rect2))
+ SET_FROM_STRUCT_AND_BREAK(Rect2);
+
+ if (tclass == CACHED_CLASS(Transform2D))
+ SET_FROM_STRUCT_AND_BREAK(Transform2D);
+
+ if (tclass == CACHED_CLASS(Vector3))
+ SET_FROM_STRUCT_AND_BREAK(Vector3);
+
+ if (tclass == CACHED_CLASS(Basis))
+ SET_FROM_STRUCT_AND_BREAK(Basis);
+
+ if (tclass == CACHED_CLASS(Quat))
+ SET_FROM_STRUCT_AND_BREAK(Quat);
+
+ if (tclass == CACHED_CLASS(Transform))
+ SET_FROM_STRUCT_AND_BREAK(Transform);
+
+ if (tclass == CACHED_CLASS(Rect3))
+ SET_FROM_STRUCT_AND_BREAK(Rect3);
+
+ if (tclass == CACHED_CLASS(Color))
+ SET_FROM_STRUCT_AND_BREAK(Color);
+
+ if (tclass == CACHED_CLASS(Plane))
+ SET_FROM_STRUCT_AND_BREAK(Plane);
+
+ ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + tclass->get_name());
+ ERR_FAIL();
+ } break;
+
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY: {
+ MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(type.type_class));
+
+ if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
+ SET_FROM_ARRAY_AND_BREAK(Array);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(uint8_t))
+ SET_FROM_ARRAY_AND_BREAK(PoolByteArray);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(int32_t))
+ SET_FROM_ARRAY_AND_BREAK(PoolIntArray);
+
+ if (array_type->eklass == REAL_T_MONOCLASS)
+ SET_FROM_ARRAY_AND_BREAK(PoolRealArray);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(String))
+ SET_FROM_ARRAY_AND_BREAK(PoolStringArray);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector2))
+ SET_FROM_ARRAY_AND_BREAK(PoolVector2Array);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector3))
+ SET_FROM_ARRAY_AND_BREAK(PoolVector3Array);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Color))
+ SET_FROM_ARRAY_AND_BREAK(PoolColorArray);
+
+ ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed array of unmarshallable element type.");
+ ERR_FAIL();
+ } break;
+
+ case MONO_TYPE_CLASS: {
+ GDMonoClass *type_class = type.type_class;
+
+ // GodotObject
+ if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
+ MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
+ mono_field_set_value(p_object, mono_field, &managed);
+ break;
+ }
+
+ if (CACHED_CLASS(NodePath) == type_class) {
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
+ mono_field_set_value(p_object, mono_field, &managed);
+ break;
+ }
+
+ if (CACHED_CLASS(RID) == type_class) {
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator RID());
+ mono_field_set_value(p_object, mono_field, &managed);
+ break;
+ }
+
+ ERR_EXPLAIN(String() + "Attempted to set the value of a field of unmarshallable type: " + type_class->get_name());
+ ERR_FAIL();
+ } break;
+
+ case MONO_TYPE_OBJECT: {
+ GDMonoClass *type_class = type.type_class;
+
+ // Variant
+ switch (p_value.get_type()) {
+ case Variant::BOOL: {
+ SET_FROM_PRIMITIVE(bool);
+ } break;
+ case Variant::INT: {
+ SET_FROM_PRIMITIVE(int);
+ } break;
+ case Variant::REAL: {
+#ifdef REAL_T_IS_DOUBLE
+ SET_FROM_PRIMITIVE(double);
+#else
+ SET_FROM_PRIMITIVE(float);
+#endif
+ } break;
+ case Variant::STRING: {
+ MonoString *mono_string = GDMonoMarshal::mono_string_from_godot(p_value);
+ mono_field_set_value(p_object, mono_field, mono_string);
+ } break;
+ case Variant::VECTOR2: SET_FROM_STRUCT_AND_BREAK(Vector2);
+ case Variant::RECT2: SET_FROM_STRUCT_AND_BREAK(Rect2);
+ case Variant::VECTOR3: SET_FROM_STRUCT_AND_BREAK(Vector3);
+ case Variant::TRANSFORM2D: SET_FROM_STRUCT_AND_BREAK(Transform2D);
+ case Variant::PLANE: SET_FROM_STRUCT_AND_BREAK(Plane);
+ case Variant::QUAT: SET_FROM_STRUCT_AND_BREAK(Quat);
+ case Variant::RECT3: SET_FROM_STRUCT_AND_BREAK(Rect3);
+ case Variant::BASIS: SET_FROM_STRUCT_AND_BREAK(Basis);
+ case Variant::TRANSFORM: SET_FROM_STRUCT_AND_BREAK(Transform);
+ case Variant::COLOR: SET_FROM_STRUCT_AND_BREAK(Color);
+ case Variant::NODE_PATH: {
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator NodePath());
+ mono_field_set_value(p_object, mono_field, &managed);
+ } break;
+ case Variant::_RID: {
+ MonoObject *managed = GDMonoUtils::create_managed_from(p_value.operator RID());
+ mono_field_set_value(p_object, mono_field, &managed);
+ } break;
+ case Variant::OBJECT: {
+ MonoObject *managed = GDMonoUtils::unmanaged_get_managed(p_value.operator Object *());
+ mono_field_set_value(p_object, mono_field, managed);
+ break;
+ }
+ case Variant::DICTIONARY: {
+ MonoObject *managed = GDMonoMarshal::Dictionary_to_mono_object(p_value.operator Dictionary());
+ mono_field_set_value(p_object, mono_field, &managed);
+ } break;
+ case Variant::ARRAY: SET_FROM_ARRAY_AND_BREAK(Array);
+ case Variant::POOL_BYTE_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolByteArray);
+ case Variant::POOL_INT_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolIntArray);
+ case Variant::POOL_REAL_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolRealArray);
+ case Variant::POOL_STRING_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolStringArray);
+ case Variant::POOL_VECTOR2_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolVector2Array);
+ case Variant::POOL_VECTOR3_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolVector3Array);
+ case Variant::POOL_COLOR_ARRAY: SET_FROM_ARRAY_AND_BREAK(PoolColorArray);
+#undef SET_FROM_ARRAY_AND_BREAK
+ default: break;
+ }
+ } break;
+
+ case MONO_TYPE_GENERICINST: {
+ if (CACHED_RAW_MONO_CLASS(Dictionary) == type.type_class->get_raw()) {
+ MonoObject *managed = GDMonoMarshal::Dictionary_to_mono_object(p_value.operator Dictionary());
+ mono_field_set_value(p_object, mono_field, &managed);
+ break;
+ }
+ } break;
+
+ default: {
+ ERR_PRINTS(String() + "Attempted to set the value of a field of unexpected type encoding: " + itos(type.type_encoding));
+ } break;
+ }
+
+#undef SET_FROM_STRUCT_AND_BREAK
+#undef SET_FROM_PRIMITIVE
+}
+
+bool GDMonoField::get_bool_value(MonoObject *p_object) {
+ return UNBOX_BOOLEAN(get_value(p_object));
+}
+
+int GDMonoField::get_int_value(MonoObject *p_object) {
+ return UNBOX_INT32(get_value(p_object));
+}
+
+String GDMonoField::get_string_value(MonoObject *p_object) {
+ MonoObject *val = get_value(p_object);
+ return val ? GDMonoMarshal::mono_string_to_godot((MonoString *)val) : String();
+}
+
+bool GDMonoField::has_attribute(GDMonoClass *p_attr_class) {
+ ERR_FAIL_NULL_V(p_attr_class, false);
+
+ if (!attrs_fetched)
+ fetch_attributes();
+
+ if (!attributes)
+ return false;
+
+ return mono_custom_attrs_has_attr(attributes, p_attr_class->get_raw());
+}
+
+MonoObject *GDMonoField::get_attribute(GDMonoClass *p_attr_class) {
+ ERR_FAIL_NULL_V(p_attr_class, NULL);
+
+ if (!attrs_fetched)
+ fetch_attributes();
+
+ if (!attributes)
+ return NULL;
+
+ return mono_custom_attrs_get_attr(attributes, p_attr_class->get_raw());
+}
+
+void GDMonoField::fetch_attributes() {
+ ERR_FAIL_COND(attributes != NULL);
+ attributes = mono_custom_attrs_from_field(owner->get_raw(), get_raw());
+ attrs_fetched = true;
+}
+
+bool GDMonoField::is_static() {
+ return mono_field_get_flags(mono_field) & MONO_FIELD_ATTR_STATIC;
+}
+
+GDMono::MemberVisibility GDMonoField::get_visibility() {
+ switch (mono_field_get_flags(mono_field) & MONO_FIELD_ATTR_FIELD_ACCESS_MASK) {
+ case MONO_FIELD_ATTR_PRIVATE:
+ return GDMono::PRIVATE;
+ case MONO_FIELD_ATTR_FAM_AND_ASSEM:
+ return GDMono::PROTECTED_AND_INTERNAL;
+ case MONO_FIELD_ATTR_ASSEMBLY:
+ return GDMono::INTERNAL;
+ case MONO_FIELD_ATTR_FAMILY:
+ return GDMono::PROTECTED;
+ case MONO_FIELD_ATTR_PUBLIC:
+ return GDMono::PUBLIC;
+ default:
+ ERR_FAIL_V(GDMono::PRIVATE);
+ }
+}
+
+GDMonoField::GDMonoField(MonoClassField *p_raw_field, GDMonoClass *p_owner) {
+ owner = p_owner;
+ mono_field = p_raw_field;
+ name = mono_field_get_name(mono_field);
+ MonoType *field_type = mono_field_get_type(mono_field);
+ type.type_encoding = mono_type_get_type(field_type);
+ MonoClass *field_type_class = mono_class_from_mono_type(field_type);
+ type.type_class = GDMono::get_singleton()->get_class(field_type_class);
+
+ attrs_fetched = false;
+ attributes = NULL;
+}
+
+GDMonoField::~GDMonoField() {
+ if (attributes) {
+ mono_custom_attrs_free(attributes);
+ }
+}
diff --git a/modules/mono/mono_gd/gd_mono_field.h b/modules/mono/mono_gd/gd_mono_field.h
new file mode 100644
index 0000000000..b7e1942d71
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_field.h
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* gd_mono_field.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 GDMONOFIELD_H
+#define GDMONOFIELD_H
+
+#include "gd_mono.h"
+#include "gd_mono_header.h"
+
+class GDMonoField {
+ GDMonoClass *owner;
+ MonoClassField *mono_field;
+
+ String name;
+ ManagedType type;
+
+ bool attrs_fetched;
+ MonoCustomAttrInfo *attributes;
+
+public:
+ _FORCE_INLINE_ String get_name() const { return name; }
+ _FORCE_INLINE_ ManagedType get_type() const { return type; }
+
+ _FORCE_INLINE_ MonoClassField *get_raw() const { return mono_field; }
+
+ void set_value_raw(MonoObject *p_object, void *p_ptr);
+ void set_value(MonoObject *p_object, const Variant &p_value);
+
+ _FORCE_INLINE_ MonoObject *get_value(MonoObject *p_object) {
+ return mono_field_get_value_object(mono_domain_get(), mono_field, p_object);
+ }
+
+ bool get_bool_value(MonoObject *p_object);
+ int get_int_value(MonoObject *p_object);
+ String get_string_value(MonoObject *p_object);
+
+ bool has_attribute(GDMonoClass *p_attr_class);
+ MonoObject *get_attribute(GDMonoClass *p_attr_class);
+ void fetch_attributes();
+
+ bool is_static();
+ GDMono::MemberVisibility get_visibility();
+
+ GDMonoField(MonoClassField *p_raw_field, GDMonoClass *p_owner);
+ ~GDMonoField();
+};
+
+#endif // GDMONOFIELD_H
diff --git a/modules/mono/mono_gd/gd_mono_header.h b/modules/mono/mono_gd/gd_mono_header.h
new file mode 100644
index 0000000000..803d394f96
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_header.h
@@ -0,0 +1,59 @@
+/*************************************************************************/
+/* gd_mono_header.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_MONO_HEADER_H
+#define GD_MONO_HEADER_H
+
+#include "int_types.h"
+
+class GDMonoAssembly;
+class GDMonoClass;
+class GDMonoMethod;
+class GDMonoField;
+
+struct ManagedType {
+ int type_encoding;
+ GDMonoClass *type_class;
+
+ ManagedType() {
+ type_class = 0;
+ }
+};
+
+typedef union {
+ uint32_t _uint32;
+ float _float;
+} mono_float;
+
+typedef union {
+ uint64_t _uint64;
+ float _double;
+} mono_double;
+
+#endif // GD_MONO_HEADER_H
diff --git a/modules/mono/mono_gd/gd_mono_internals.cpp b/modules/mono/mono_gd/gd_mono_internals.cpp
new file mode 100644
index 0000000000..cfe2148b80
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_internals.cpp
@@ -0,0 +1,66 @@
+/*************************************************************************/
+/* godotsharp_internals.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono_internals.h"
+
+#include "../csharp_script.h"
+#include "../mono_gc_handle.h"
+#include "gd_mono_utils.h"
+
+namespace GDMonoInternals {
+
+void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
+
+ // This method should not fail
+
+ CRASH_COND(!unmanaged);
+
+ // All mono objects created from the managed world (e.g.: `new Player()`)
+ // need to have a CSharpScript in order for their methods to be callable from the unmanaged side
+
+ Reference *ref = Object::cast_to<Reference>(unmanaged);
+
+ GDMonoClass *klass = GDMonoUtils::get_object_class(managed);
+
+ CRASH_COND(!klass);
+
+ Ref<MonoGCHandle> gchandle = ref ? MonoGCHandle::create_weak(managed) :
+ MonoGCHandle::create_strong(managed);
+
+ Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass);
+
+ CRASH_COND(script.is_null());
+
+ ScriptInstance *si = CSharpInstance::create_for_managed_type(unmanaged, script.ptr(), gchandle);
+
+ unmanaged->set_script_and_instance(script.get_ref_ptr(), si);
+
+ return;
+}
+}
diff --git a/modules/mono/mono_gd/gd_mono_internals.h b/modules/mono/mono_gd/gd_mono_internals.h
new file mode 100644
index 0000000000..6bdf4a6c46
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_internals.h
@@ -0,0 +1,42 @@
+/*************************************************************************/
+/* godotsharp_internals.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_MONO_INTERNALS_H
+#define GD_MONO_INTERNALS_H
+
+#include <mono/jit/jit.h>
+
+#include "core/object.h"
+
+namespace GDMonoInternals {
+
+void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged);
+}
+
+#endif // GD_MONO_INTERNALS_H
diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp
new file mode 100644
index 0000000000..e473348897
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_log.cpp
@@ -0,0 +1,175 @@
+/*************************************************************************/
+/* gd_mono_log.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono_log.h"
+
+#include <mono/utils/mono-logger.h>
+#include <stdlib.h> // abort
+
+#include "os/dir_access.h"
+#include "os/os.h"
+
+#include "../godotsharp_dirs.h"
+
+static int log_level_get_id(const char *p_log_level) {
+
+ const char *valid_log_levels[] = { "error", "critical", "warning", "message", "info", "debug", NULL };
+
+ int i = 0;
+ while (valid_log_levels[i]) {
+ if (!strcmp(valid_log_levels[i], p_log_level))
+ return i;
+ i++;
+ }
+
+ return -1;
+}
+
+void gdmono_MonoLogCallback(const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data) {
+
+ FileAccess *f = GDMonoLog::get_singleton()->get_log_file();
+
+ if (GDMonoLog::get_singleton()->get_log_level_id() >= log_level_get_id(log_level)) {
+ String text(message);
+ text += " (in domain ";
+ text += log_domain;
+ if (log_level) {
+ text += ", ";
+ text += log_level;
+ }
+ text += ")\n";
+
+ f->seek_end();
+ f->store_string(text);
+ }
+
+ if (fatal) {
+ ERR_PRINTS("Mono: FALTAL ERROR, ABORTING! Logfile: " + GDMonoLog::get_singleton()->get_log_file_path() + "\n");
+ abort();
+ }
+}
+
+GDMonoLog *GDMonoLog::singleton = NULL;
+
+bool GDMonoLog::_try_create_logs_dir(const String &p_logs_dir) {
+
+ if (!DirAccess::exists(p_logs_dir)) {
+ DirAccessRef diraccess = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND_V(!diraccess, false);
+ Error logs_mkdir_err = diraccess->make_dir_recursive(p_logs_dir);
+ ERR_EXPLAIN("Failed to create mono logs directory");
+ ERR_FAIL_COND_V(logs_mkdir_err != OK, false);
+ }
+
+ return true;
+}
+
+void GDMonoLog::_open_log_file(const String &p_file_path) {
+
+ log_file = FileAccess::open(p_file_path, FileAccess::WRITE);
+
+ ERR_EXPLAIN("Failed to create log file");
+ ERR_FAIL_COND(!log_file);
+}
+
+void GDMonoLog::_delete_old_log_files(const String &p_logs_dir) {
+
+ static const uint64_t MAX_SECS = 5 * 86400;
+
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ ERR_FAIL_COND(!da);
+
+ Error err = da->change_dir(p_logs_dir);
+ ERR_FAIL_COND(err != OK);
+
+ ERR_FAIL_COND(da->list_dir_begin() != OK);
+
+ String current;
+ while ((current = da->get_next()).length()) {
+ if (da->current_is_dir())
+ continue;
+ if (!current.ends_with(".txt"))
+ continue;
+
+ String name = current.get_basename();
+ uint64_t unixtime = (uint64_t)name.to_int64();
+
+ if (OS::get_singleton()->get_unix_time() - unixtime > MAX_SECS) {
+ da->remove(current);
+ }
+ }
+
+ da->list_dir_end();
+}
+
+void GDMonoLog::initialize() {
+
+#ifdef DEBUG_ENABLED
+ const char *log_level = "debug";
+#else
+ const char *log_level = "warning";
+#endif
+
+ String logs_dir = GodotSharpDirs::get_mono_logs_dir();
+
+ if (_try_create_logs_dir(logs_dir)) {
+ _delete_old_log_files(logs_dir);
+
+ log_file_path = logs_dir.plus_file(String::num_int64(OS::get_singleton()->get_unix_time()) + ".txt");
+ _open_log_file(log_file_path);
+ }
+
+ mono_trace_set_level_string(log_level);
+ log_level_id = log_level_get_id(log_level);
+
+ if (log_file) {
+ if (OS::get_singleton()->is_stdout_verbose())
+ OS::get_singleton()->print(String("Mono: Logfile is " + log_file_path + "\n").utf8());
+ mono_trace_set_log_handler(gdmono_MonoLogCallback, this);
+ } else {
+ OS::get_singleton()->printerr("Mono: No log file, using default log handler\n");
+ }
+}
+
+GDMonoLog::GDMonoLog() {
+
+ singleton = this;
+
+ log_level_id = -1;
+}
+
+GDMonoLog::~GDMonoLog() {
+
+ singleton = NULL;
+
+ if (log_file) {
+ log_file->close();
+ memdelete(log_file);
+ }
+}
diff --git a/platform/iphone/audio_driver_iphone.h b/modules/mono/mono_gd/gd_mono_log.h
index 930ed168f7..497f1e5317 100644
--- a/platform/iphone/audio_driver_iphone.h
+++ b/modules/mono/mono_gd/gd_mono_log.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* audio_driver_iphone.h */
+/* gd_mono_log.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -27,40 +27,35 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GD_MONO_LOG_H
+#define GD_MONO_LOG_H
-#include "servers/audio_server.h"
+#include "os/file_access.h"
-#include <AudioUnit/AudioUnit.h>
+class GDMonoLog {
-class AudioDriverIphone : public AudioDriver {
+ int log_level_id;
- AudioComponentInstance audio_unit;
- bool active;
- Mutex *mutex;
+ FileAccess *log_file;
+ String log_file_path;
- int channels;
- int32_t *samples_in;
- int buffer_frames;
+ bool _try_create_logs_dir(const String &p_logs_dir);
+ void _open_log_file(const String &p_file_path);
+ void _delete_old_log_files(const String &p_logs_dir);
- static OSStatus output_callback(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber, UInt32 inNumberFrames,
- AudioBufferList *ioData);
+ static GDMonoLog *singleton;
public:
- const char *get_name() const {
- return "IPhone";
- };
+ _FORCE_INLINE_ static GDMonoLog *get_singleton() { return singleton; }
- virtual Error init();
- virtual void start();
- virtual int get_mix_rate() const;
- virtual SpeakerMode get_speaker_mode() const;
- virtual void lock();
- virtual void unlock();
- virtual void finish();
+ void initialize();
- AudioDriverIphone();
- ~AudioDriverIphone();
+ _FORCE_INLINE_ FileAccess *get_log_file() { return log_file; }
+ _FORCE_INLINE_ String get_log_file_path() { return log_file_path; }
+ _FORCE_INLINE_ int get_log_level_id() { return log_level_id; }
+
+ GDMonoLog();
+ ~GDMonoLog();
};
+
+#endif // GD_MONO_LOG_H
diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp
new file mode 100644
index 0000000000..b5419952de
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_marshal.cpp
@@ -0,0 +1,856 @@
+/*************************************************************************/
+/* gd_mono_marshal.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono_marshal.h"
+
+#include "gd_mono.h"
+#include "gd_mono_class.h"
+
+namespace GDMonoMarshal {
+
+#define RETURN_BOXED_STRUCT(m_t, m_var_in) \
+ { \
+ const m_t &m_in = m_var_in->operator m_t(); \
+ MARSHALLED_OUT(m_t, m_in, raw); \
+ return mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(m_t), raw); \
+ }
+
+#define RETURN_UNBOXED_STRUCT(m_t, m_var_in) \
+ { \
+ float *raw = UNBOX_FLOAT_PTR(m_var_in); \
+ MARSHALLED_IN(m_t, raw, ret); \
+ return ret; \
+ }
+
+Variant::Type managed_to_variant_type(const ManagedType &p_type) {
+ switch (p_type.type_encoding) {
+ case MONO_TYPE_BOOLEAN:
+ return Variant::BOOL;
+
+ case MONO_TYPE_I1:
+ return Variant::INT;
+ case MONO_TYPE_I2:
+ return Variant::INT;
+ case MONO_TYPE_I4:
+ return Variant::INT;
+ case MONO_TYPE_I8:
+ return Variant::INT;
+
+ case MONO_TYPE_U1:
+ return Variant::INT;
+ case MONO_TYPE_U2:
+ return Variant::INT;
+ case MONO_TYPE_U4:
+ return Variant::INT;
+ case MONO_TYPE_U8:
+ return Variant::INT;
+
+ case MONO_TYPE_R4:
+ return Variant::REAL;
+ case MONO_TYPE_R8:
+ return Variant::REAL;
+
+ case MONO_TYPE_STRING: {
+ return Variant::STRING;
+ } break;
+
+ case MONO_TYPE_VALUETYPE: {
+ GDMonoClass *tclass = p_type.type_class;
+
+ if (tclass == CACHED_CLASS(Vector2))
+ return Variant::VECTOR2;
+
+ if (tclass == CACHED_CLASS(Rect2))
+ return Variant::RECT2;
+
+ if (tclass == CACHED_CLASS(Transform2D))
+ return Variant::TRANSFORM2D;
+
+ if (tclass == CACHED_CLASS(Vector3))
+ return Variant::VECTOR3;
+
+ if (tclass == CACHED_CLASS(Basis))
+ return Variant::BASIS;
+
+ if (tclass == CACHED_CLASS(Quat))
+ return Variant::QUAT;
+
+ if (tclass == CACHED_CLASS(Transform))
+ return Variant::TRANSFORM;
+
+ if (tclass == CACHED_CLASS(Rect3))
+ return Variant::RECT3;
+
+ if (tclass == CACHED_CLASS(Color))
+ return Variant::COLOR;
+
+ if (tclass == CACHED_CLASS(Plane))
+ return Variant::PLANE;
+ } break;
+
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY: {
+ MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(p_type.type_class));
+
+ if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
+ return Variant::ARRAY;
+
+ if (array_type->eklass == CACHED_CLASS_RAW(uint8_t))
+ return Variant::POOL_BYTE_ARRAY;
+
+ if (array_type->eklass == CACHED_CLASS_RAW(int32_t))
+ return Variant::POOL_INT_ARRAY;
+
+ if (array_type->eklass == REAL_T_MONOCLASS)
+ return Variant::POOL_REAL_ARRAY;
+
+ if (array_type->eklass == CACHED_CLASS_RAW(String))
+ return Variant::POOL_STRING_ARRAY;
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector2))
+ return Variant::POOL_VECTOR2_ARRAY;
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector3))
+ return Variant::POOL_VECTOR3_ARRAY;
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Color))
+ return Variant::POOL_COLOR_ARRAY;
+ } break;
+
+ case MONO_TYPE_CLASS: {
+ GDMonoClass *type_class = p_type.type_class;
+
+ // GodotObject
+ if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
+ return Variant::OBJECT;
+ }
+
+ if (CACHED_CLASS(NodePath) == type_class) {
+ return Variant::NODE_PATH;
+ }
+
+ if (CACHED_CLASS(RID) == type_class) {
+ return Variant::_RID;
+ }
+ } break;
+
+ case MONO_TYPE_GENERICINST: {
+ if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_raw()) {
+ return Variant::DICTIONARY;
+ }
+ } break;
+ }
+
+ // No error, the caller will decide what to do in this case
+ return Variant::NIL;
+}
+
+String mono_to_utf8_string(MonoString *p_mono_string) {
+ MonoError error;
+ char *utf8 = mono_string_to_utf8_checked(p_mono_string, &error);
+
+ ERR_EXPLAIN("Conversion of MonoString to UTF8 failed.");
+ ERR_FAIL_COND_V(!mono_error_ok(&error), String());
+
+ String ret = String::utf8(utf8);
+
+ mono_free(utf8);
+
+ return ret;
+}
+
+String mono_to_utf16_string(MonoString *p_mono_string) {
+ int len = mono_string_length(p_mono_string);
+ String ret;
+
+ if (len == 0)
+ return ret;
+
+ ret.resize(len + 1);
+ ret.set(len, 0);
+
+ CharType *src = (CharType *)mono_string_chars(p_mono_string);
+ CharType *dst = &(ret.operator[](0));
+
+ for (int i = 0; i < len; i++) {
+ dst[i] = src[i];
+ }
+
+ return ret;
+}
+
+MonoObject *variant_to_mono_object(const Variant *p_var) {
+ ManagedType type;
+
+ type.type_encoding = MONO_TYPE_OBJECT;
+
+ return variant_to_mono_object(p_var, type);
+}
+
+MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type) {
+ switch (p_type.type_encoding) {
+ case MONO_TYPE_BOOLEAN: {
+ MonoBoolean val = p_var->operator bool();
+ return BOX_BOOLEAN(val);
+ }
+
+ case MONO_TYPE_I1: {
+ char val = p_var->operator signed char();
+ return BOX_INT8(val);
+ }
+ case MONO_TYPE_I2: {
+ short val = p_var->operator signed short();
+ return BOX_INT16(val);
+ }
+ case MONO_TYPE_I4: {
+ int val = p_var->operator signed int();
+ return BOX_INT32(val);
+ }
+ case MONO_TYPE_I8: {
+ int64_t val = p_var->operator int64_t();
+ return BOX_INT64(val);
+ }
+
+ case MONO_TYPE_U1: {
+ char val = p_var->operator unsigned char();
+ return BOX_UINT8(val);
+ }
+ case MONO_TYPE_U2: {
+ short val = p_var->operator unsigned short();
+ return BOX_UINT16(val);
+ }
+ case MONO_TYPE_U4: {
+ int val = p_var->operator unsigned int();
+ return BOX_UINT32(val);
+ }
+ case MONO_TYPE_U8: {
+ uint64_t val = p_var->operator uint64_t();
+ return BOX_UINT64(val);
+ }
+
+ case MONO_TYPE_R4: {
+ float val = p_var->operator float();
+ return BOX_FLOAT(val);
+ }
+ case MONO_TYPE_R8: {
+ double val = p_var->operator double();
+ return BOX_DOUBLE(val);
+ }
+
+ case MONO_TYPE_STRING: {
+ return (MonoObject *)mono_string_from_godot(p_var->operator String());
+ } break;
+
+ case MONO_TYPE_VALUETYPE: {
+ GDMonoClass *tclass = p_type.type_class;
+
+ if (tclass == CACHED_CLASS(Vector2))
+ RETURN_BOXED_STRUCT(Vector2, p_var);
+
+ if (tclass == CACHED_CLASS(Rect2))
+ RETURN_BOXED_STRUCT(Rect2, p_var);
+
+ if (tclass == CACHED_CLASS(Transform2D))
+ RETURN_BOXED_STRUCT(Transform2D, p_var);
+
+ if (tclass == CACHED_CLASS(Vector3))
+ RETURN_BOXED_STRUCT(Vector3, p_var);
+
+ if (tclass == CACHED_CLASS(Basis))
+ RETURN_BOXED_STRUCT(Basis, p_var);
+
+ if (tclass == CACHED_CLASS(Quat))
+ RETURN_BOXED_STRUCT(Quat, p_var);
+
+ if (tclass == CACHED_CLASS(Transform))
+ RETURN_BOXED_STRUCT(Transform, p_var);
+
+ if (tclass == CACHED_CLASS(Rect3))
+ RETURN_BOXED_STRUCT(Rect3, p_var);
+
+ if (tclass == CACHED_CLASS(Color))
+ RETURN_BOXED_STRUCT(Color, p_var);
+
+ if (tclass == CACHED_CLASS(Plane))
+ RETURN_BOXED_STRUCT(Plane, p_var);
+ } break;
+
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY: {
+ MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(p_type.type_class));
+
+ if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
+ return (MonoObject *)Array_to_mono_array(p_var->operator Array());
+
+ if (array_type->eklass == CACHED_CLASS_RAW(uint8_t))
+ return (MonoObject *)PoolByteArray_to_mono_array(p_var->operator PoolByteArray());
+
+ if (array_type->eklass == CACHED_CLASS_RAW(int32_t))
+ return (MonoObject *)PoolIntArray_to_mono_array(p_var->operator PoolIntArray());
+
+ if (array_type->eklass == REAL_T_MONOCLASS)
+ return (MonoObject *)PoolRealArray_to_mono_array(p_var->operator PoolRealArray());
+
+ if (array_type->eklass == CACHED_CLASS_RAW(String))
+ return (MonoObject *)PoolStringArray_to_mono_array(p_var->operator PoolStringArray());
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector2))
+ return (MonoObject *)PoolVector2Array_to_mono_array(p_var->operator PoolVector2Array());
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector3))
+ return (MonoObject *)PoolVector3Array_to_mono_array(p_var->operator PoolVector3Array());
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Color))
+ return (MonoObject *)PoolColorArray_to_mono_array(p_var->operator PoolColorArray());
+
+ ERR_EXPLAIN(String() + "Attempted to convert Variant to a managed array of unmarshallable element type.");
+ ERR_FAIL_V(NULL);
+ } break;
+
+ case MONO_TYPE_CLASS: {
+ GDMonoClass *type_class = p_type.type_class;
+
+ // GodotObject
+ if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
+ return GDMonoUtils::unmanaged_get_managed(p_var->operator Object *());
+ }
+
+ if (CACHED_CLASS(NodePath) == type_class) {
+ return GDMonoUtils::create_managed_from(p_var->operator NodePath());
+ }
+
+ if (CACHED_CLASS(RID) == type_class) {
+ return GDMonoUtils::create_managed_from(p_var->operator RID());
+ }
+ } break;
+ case MONO_TYPE_OBJECT: {
+ // Variant
+ switch (p_var->get_type()) {
+ case Variant::BOOL: {
+ MonoBoolean val = p_var->operator bool();
+ return BOX_BOOLEAN(val);
+ }
+ case Variant::INT: {
+ int val = p_var->operator signed int();
+ return BOX_INT32(val);
+ }
+ case Variant::REAL: {
+#ifdef REAL_T_IS_DOUBLE
+ double val = p_var->operator double();
+ return BOX_DOUBLE(val);
+#else
+ float val = p_var->operator float();
+ return BOX_FLOAT(val);
+#endif
+ }
+ case Variant::STRING:
+ return (MonoObject *)mono_string_from_godot(p_var->operator String());
+ case Variant::VECTOR2:
+ RETURN_BOXED_STRUCT(Vector2, p_var);
+ case Variant::RECT2:
+ RETURN_BOXED_STRUCT(Rect2, p_var);
+ case Variant::VECTOR3:
+ RETURN_BOXED_STRUCT(Vector3, p_var);
+ case Variant::TRANSFORM2D:
+ RETURN_BOXED_STRUCT(Transform2D, p_var);
+ case Variant::PLANE:
+ RETURN_BOXED_STRUCT(Plane, p_var);
+ case Variant::QUAT:
+ RETURN_BOXED_STRUCT(Quat, p_var);
+ case Variant::RECT3:
+ RETURN_BOXED_STRUCT(Rect3, p_var);
+ case Variant::BASIS:
+ RETURN_BOXED_STRUCT(Basis, p_var);
+ case Variant::TRANSFORM:
+ RETURN_BOXED_STRUCT(Transform, p_var);
+ case Variant::COLOR:
+ RETURN_BOXED_STRUCT(Color, p_var);
+ case Variant::NODE_PATH:
+ return GDMonoUtils::create_managed_from(p_var->operator NodePath());
+ case Variant::_RID:
+ return GDMonoUtils::create_managed_from(p_var->operator RID());
+ case Variant::OBJECT: {
+ return GDMonoUtils::unmanaged_get_managed(p_var->operator Object *());
+ }
+ case Variant::DICTIONARY:
+ return Dictionary_to_mono_object(p_var->operator Dictionary());
+ case Variant::ARRAY:
+ return (MonoObject *)Array_to_mono_array(p_var->operator Array());
+ case Variant::POOL_BYTE_ARRAY:
+ return (MonoObject *)PoolByteArray_to_mono_array(p_var->operator PoolByteArray());
+ case Variant::POOL_INT_ARRAY:
+ return (MonoObject *)PoolIntArray_to_mono_array(p_var->operator PoolIntArray());
+ case Variant::POOL_REAL_ARRAY:
+ return (MonoObject *)PoolRealArray_to_mono_array(p_var->operator PoolRealArray());
+ case Variant::POOL_STRING_ARRAY:
+ return (MonoObject *)PoolStringArray_to_mono_array(p_var->operator PoolStringArray());
+ case Variant::POOL_VECTOR2_ARRAY:
+ return (MonoObject *)PoolVector2Array_to_mono_array(p_var->operator PoolVector2Array());
+ case Variant::POOL_VECTOR3_ARRAY:
+ return (MonoObject *)PoolVector3Array_to_mono_array(p_var->operator PoolVector3Array());
+ case Variant::POOL_COLOR_ARRAY:
+ return (MonoObject *)PoolColorArray_to_mono_array(p_var->operator PoolColorArray());
+ default:
+ return NULL;
+ }
+ break;
+ case MONO_TYPE_GENERICINST: {
+ if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_raw()) {
+ return Dictionary_to_mono_object(p_var->operator Dictionary());
+ }
+ } break;
+ } break;
+ }
+
+ ERR_EXPLAIN(String() + "Attempted to convert Variant to an unmarshallable managed type. Name: \'" +
+ p_type.type_class->get_name() + "\' Encoding: " + itos(p_type.type_encoding));
+ ERR_FAIL_V(NULL);
+}
+
+Variant mono_object_to_variant(MonoObject *p_obj) {
+ if (!p_obj)
+ return Variant();
+
+ GDMonoClass *tclass = GDMono::get_singleton()->get_class(mono_object_get_class(p_obj));
+ ERR_FAIL_COND_V(!tclass, Variant());
+
+ MonoType *raw_type = tclass->get_raw_type(tclass);
+
+ ManagedType type;
+
+ type.type_encoding = mono_type_get_type(raw_type);
+ type.type_class = tclass;
+
+ return mono_object_to_variant(p_obj, type);
+}
+
+Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type) {
+ switch (p_type.type_encoding) {
+ case MONO_TYPE_BOOLEAN:
+ return (bool)UNBOX_BOOLEAN(p_obj);
+
+ case MONO_TYPE_I1:
+ return UNBOX_INT8(p_obj);
+ case MONO_TYPE_I2:
+ return UNBOX_INT16(p_obj);
+ case MONO_TYPE_I4:
+ return UNBOX_INT32(p_obj);
+ case MONO_TYPE_I8:
+ return UNBOX_INT64(p_obj);
+
+ case MONO_TYPE_U1:
+ return UNBOX_UINT8(p_obj);
+ case MONO_TYPE_U2:
+ return UNBOX_UINT16(p_obj);
+ case MONO_TYPE_U4:
+ return UNBOX_UINT32(p_obj);
+ case MONO_TYPE_U8:
+ return UNBOX_UINT64(p_obj);
+
+ case MONO_TYPE_R4:
+ return UNBOX_FLOAT(p_obj);
+ case MONO_TYPE_R8:
+ return UNBOX_DOUBLE(p_obj);
+
+ case MONO_TYPE_STRING: {
+ String str = mono_string_to_godot((MonoString *)p_obj);
+ return str;
+ } break;
+
+ case MONO_TYPE_VALUETYPE: {
+ GDMonoClass *tclass = p_type.type_class;
+
+ if (tclass == CACHED_CLASS(Vector2))
+ RETURN_UNBOXED_STRUCT(Vector2, p_obj);
+
+ if (tclass == CACHED_CLASS(Rect2))
+ RETURN_UNBOXED_STRUCT(Rect2, p_obj);
+
+ if (tclass == CACHED_CLASS(Transform2D))
+ RETURN_UNBOXED_STRUCT(Transform2D, p_obj);
+
+ if (tclass == CACHED_CLASS(Vector3))
+ RETURN_UNBOXED_STRUCT(Vector3, p_obj);
+
+ if (tclass == CACHED_CLASS(Basis))
+ RETURN_UNBOXED_STRUCT(Basis, p_obj);
+
+ if (tclass == CACHED_CLASS(Quat))
+ RETURN_UNBOXED_STRUCT(Quat, p_obj);
+
+ if (tclass == CACHED_CLASS(Transform))
+ RETURN_UNBOXED_STRUCT(Transform, p_obj);
+
+ if (tclass == CACHED_CLASS(Rect3))
+ RETURN_UNBOXED_STRUCT(Rect3, p_obj);
+
+ if (tclass == CACHED_CLASS(Color))
+ RETURN_UNBOXED_STRUCT(Color, p_obj);
+
+ if (tclass == CACHED_CLASS(Plane))
+ RETURN_UNBOXED_STRUCT(Plane, p_obj);
+ } break;
+
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY: {
+ MonoArrayType *array_type = mono_type_get_array_type(GDMonoClass::get_raw_type(p_type.type_class));
+
+ if (array_type->eklass == CACHED_CLASS_RAW(MonoObject))
+ return mono_array_to_Array((MonoArray *)p_obj);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(uint8_t))
+ return mono_array_to_PoolByteArray((MonoArray *)p_obj);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(int32_t))
+ return mono_array_to_PoolIntArray((MonoArray *)p_obj);
+
+ if (array_type->eklass == REAL_T_MONOCLASS)
+ return mono_array_to_PoolRealArray((MonoArray *)p_obj);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(String))
+ return mono_array_to_PoolStringArray((MonoArray *)p_obj);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector2))
+ return mono_array_to_PoolVector2Array((MonoArray *)p_obj);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Vector3))
+ return mono_array_to_PoolVector3Array((MonoArray *)p_obj);
+
+ if (array_type->eklass == CACHED_CLASS_RAW(Color))
+ return mono_array_to_PoolColorArray((MonoArray *)p_obj);
+
+ ERR_EXPLAIN(String() + "Attempted to convert a managed array of unmarshallable element type to Variant.");
+ ERR_FAIL_V(Variant());
+ } break;
+
+ case MONO_TYPE_CLASS: {
+ GDMonoClass *type_class = p_type.type_class;
+
+ // GodotObject
+ if (CACHED_CLASS(GodotObject)->is_assignable_from(type_class)) {
+ GDMonoField *ptr_field = CACHED_FIELD(GodotObject, ptr);
+
+ ERR_FAIL_NULL_V(ptr_field, Variant());
+
+ void *ptr_to_unmanaged = UNBOX_PTR(ptr_field->get_value(p_obj));
+
+ if (!ptr_to_unmanaged) // IntPtr.Zero
+ return Variant();
+
+ Object *object_ptr = static_cast<Object *>(ptr_to_unmanaged);
+
+ if (!object_ptr)
+ return Variant();
+
+ return object_ptr;
+ }
+
+ if (CACHED_CLASS(NodePath) == type_class) {
+ return UNBOX_PTR(CACHED_FIELD(NodePath, ptr)->get_value(p_obj));
+ }
+
+ if (CACHED_CLASS(RID) == type_class) {
+ return UNBOX_PTR(CACHED_FIELD(RID, ptr)->get_value(p_obj));
+ }
+ } break;
+
+ case MONO_TYPE_GENERICINST: {
+ if (CACHED_RAW_MONO_CLASS(Dictionary) == p_type.type_class->get_raw()) {
+ return mono_object_to_Dictionary(p_obj);
+ }
+ } break;
+ }
+
+ ERR_EXPLAIN(String() + "Attempted to convert an unmarshallable managed type to Variant. Name: \'" +
+ p_type.type_class->get_name() + "\' Encoding: " + itos(p_type.type_encoding));
+ ERR_FAIL_V(Variant());
+}
+
+MonoArray *Array_to_mono_array(const Array &p_array) {
+ MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+ MonoObject *boxed = variant_to_mono_object(p_array[i]);
+ mono_array_set(ret, MonoObject *, i, boxed);
+ }
+
+ return ret;
+}
+
+Array mono_array_to_Array(MonoArray *p_array) {
+ Array ret;
+ int length = mono_array_length(p_array);
+
+ for (int i = 0; i < length; i++) {
+ MonoObject *elem = mono_array_get(p_array, MonoObject *, i);
+ ret.push_back(mono_object_to_variant(elem));
+ }
+
+ return ret;
+}
+
+// TODO Optimize reading/writing from/to PoolArrays
+
+MonoArray *PoolIntArray_to_mono_array(const PoolIntArray &p_array) {
+ MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(int32_t), p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+ mono_array_set(ret, int32_t, i, p_array[i]);
+ }
+
+ return ret;
+}
+
+PoolIntArray mono_array_to_PoolIntArray(MonoArray *p_array) {
+ PoolIntArray ret;
+ int length = mono_array_length(p_array);
+
+ for (int i = 0; i < length; i++) {
+ int32_t elem = mono_array_get(p_array, int32_t, i);
+ ret.push_back(elem);
+ }
+
+ return ret;
+}
+
+MonoArray *PoolByteArray_to_mono_array(const PoolByteArray &p_array) {
+ MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+ mono_array_set(ret, uint8_t, i, p_array[i]);
+ }
+
+ return ret;
+}
+
+PoolByteArray mono_array_to_PoolByteArray(MonoArray *p_array) {
+ PoolByteArray ret;
+ int length = mono_array_length(p_array);
+
+ for (int i = 0; i < length; i++) {
+ uint8_t elem = mono_array_get(p_array, uint8_t, i);
+ ret.push_back(elem);
+ }
+
+ return ret;
+}
+
+MonoArray *PoolRealArray_to_mono_array(const PoolRealArray &p_array) {
+ MonoArray *ret = mono_array_new(mono_domain_get(), REAL_T_MONOCLASS, p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+ mono_array_set(ret, real_t, i, p_array[i]);
+ }
+
+ return ret;
+}
+
+PoolRealArray mono_array_to_PoolRealArray(MonoArray *p_array) {
+ PoolRealArray ret;
+ int length = mono_array_length(p_array);
+
+ for (int i = 0; i < length; i++) {
+ real_t elem = mono_array_get(p_array, real_t, i);
+ ret.push_back(elem);
+ }
+
+ return ret;
+}
+
+MonoArray *PoolStringArray_to_mono_array(const PoolStringArray &p_array) {
+ MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(String), p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+ MonoString *boxed = mono_string_from_godot(p_array[i]);
+ mono_array_set(ret, MonoString *, i, boxed);
+ }
+
+ return ret;
+}
+
+PoolStringArray mono_array_to_PoolStringArray(MonoArray *p_array) {
+ PoolStringArray ret;
+ int length = mono_array_length(p_array);
+
+ for (int i = 0; i < length; i++) {
+ MonoString *elem = mono_array_get(p_array, MonoString *, i);
+ ret.push_back(mono_string_to_godot(elem));
+ }
+
+ return ret;
+}
+
+MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array) {
+ MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Color), p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+#ifdef YOLOCOPY
+ mono_array_set(ret, Color, i, p_array[i]);
+#else
+ real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 4, i);
+ const Color &elem = p_array[i];
+ raw[0] = elem.r;
+ raw[4] = elem.g;
+ raw[8] = elem.b;
+ raw[12] = elem.a;
+#endif
+ }
+
+ return ret;
+}
+
+PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array) {
+ PoolColorArray ret;
+ int length = mono_array_length(p_array);
+
+ for (int i = 0; i < length; i++) {
+ real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ MARSHALLED_IN(Color, raw_elem, elem);
+ ret.push_back(elem);
+ }
+
+ return ret;
+}
+
+MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array) {
+ MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector2), p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+#ifdef YOLOCOPY
+ mono_array_set(ret, Vector2, i, p_array[i]);
+#else
+ real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 2, i);
+ const Vector2 &elem = p_array[i];
+ raw[0] = elem.x;
+ raw[4] = elem.y;
+#endif
+ }
+
+ return ret;
+}
+
+PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array) {
+ PoolVector2Array ret;
+ int length = mono_array_length(p_array);
+
+ for (int i = 0; i < length; i++) {
+ real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ MARSHALLED_IN(Vector2, raw_elem, elem);
+ ret.push_back(elem);
+ }
+
+ return ret;
+}
+
+MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array) {
+ MonoArray *ret = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(Vector3), p_array.size());
+
+ for (int i = 0; i < p_array.size(); i++) {
+#ifdef YOLOCOPY
+ mono_array_set(ret, Vector3, i, p_array[i]);
+#else
+ real_t *raw = (real_t *)mono_array_addr_with_size(ret, sizeof(real_t) * 3, i);
+ const Vector3 &elem = p_array[i];
+ raw[0] = elem.x;
+ raw[4] = elem.y;
+ raw[8] = elem.z;
+#endif
+ }
+
+ return ret;
+}
+
+PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) {
+ PoolVector3Array ret;
+ int length = mono_array_length(p_array);
+
+ for (int i = 0; i < length; i++) {
+ real_t *raw_elem = mono_array_get(p_array, real_t *, i);
+ MARSHALLED_IN(Vector3, raw_elem, elem);
+ ret.push_back(elem);
+ }
+
+ return ret;
+}
+
+MonoObject *Dictionary_to_mono_object(const Dictionary &p_dict) {
+ MonoArray *keys = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), p_dict.size());
+ MonoArray *values = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), p_dict.size());
+
+ int i = 0;
+ const Variant *dkey = NULL;
+ while ((dkey = p_dict.next(dkey))) {
+ mono_array_set(keys, MonoObject *, i, variant_to_mono_object(dkey));
+ mono_array_set(values, MonoObject *, i, variant_to_mono_object(p_dict[*dkey]));
+ i++;
+ }
+
+ GDMonoUtils::MarshalUtils_ArraysToDict arrays_to_dict = CACHED_METHOD_THUNK(MarshalUtils, ArraysToDictionary);
+
+ MonoObject *ex = NULL;
+ MonoObject *ret = arrays_to_dict(keys, values, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL_V(NULL);
+ }
+
+ return ret;
+}
+
+Dictionary mono_object_to_Dictionary(MonoObject *p_dict) {
+ Dictionary ret;
+
+ GDMonoUtils::MarshalUtils_DictToArrays dict_to_arrays = CACHED_METHOD_THUNK(MarshalUtils, DictionaryToArrays);
+
+ MonoArray *keys = NULL;
+ MonoArray *values = NULL;
+ MonoObject *ex = NULL;
+ dict_to_arrays(p_dict, &keys, &values, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL_V(Dictionary());
+ }
+
+ int length = mono_array_length(keys);
+
+ for (int i = 0; i < length; i++) {
+ MonoObject *key_obj = mono_array_get(keys, MonoObject *, i);
+ MonoObject *value_obj = mono_array_get(values, MonoObject *, i);
+
+ Variant key = key_obj ? mono_object_to_variant(key_obj) : Variant();
+ Variant value = value_obj ? mono_object_to_variant(value_obj) : Variant();
+
+ ret[key] = value;
+ }
+
+ return ret;
+}
+}
diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h
new file mode 100644
index 0000000000..5fbafa0acb
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_marshal.h
@@ -0,0 +1,229 @@
+/*************************************************************************/
+/* gd_mono_marshal.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 GDMONOMARSHAL_H
+#define GDMONOMARSHAL_H
+
+#include "gd_mono.h"
+#include "gd_mono_utils.h"
+#include "variant.h"
+
+namespace GDMonoMarshal {
+
+#define UNBOX_CHAR_PTR(x) (char *)mono_object_unbox(x)
+#define UNBOX_FLOAT_PTR(x) (float *)mono_object_unbox(x)
+
+#define UNBOX_DOUBLE(x) *(double *)mono_object_unbox(x)
+#define UNBOX_FLOAT(x) *(float *)mono_object_unbox(x)
+#define UNBOX_INT64(x) *(int64_t *)mono_object_unbox(x)
+#define UNBOX_INT32(x) *(int32_t *)mono_object_unbox(x)
+#define UNBOX_INT16(x) *(int16_t *)mono_object_unbox(x)
+#define UNBOX_INT8(x) *(int8_t *)mono_object_unbox(x)
+#define UNBOX_UINT64(x) *(uint64_t *)mono_object_unbox(x)
+#define UNBOX_UINT32(x) *(uint32_t *)mono_object_unbox(x)
+#define UNBOX_UINT16(x) *(uint16_t *)mono_object_unbox(x)
+#define UNBOX_UINT8(x) *(uint8_t *)mono_object_unbox(x)
+#define UNBOX_BOOLEAN(x) *(MonoBoolean *)mono_object_unbox(x)
+#define UNBOX_PTR(x) mono_object_unbox(x)
+
+#define BOX_DOUBLE(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(double), &x)
+#define BOX_FLOAT(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(float), &x)
+#define BOX_INT64(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(int64_t), &x)
+#define BOX_INT32(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(int32_t), &x)
+#define BOX_INT16(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(int16_t), &x)
+#define BOX_INT8(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(int8_t), &x)
+#define BOX_UINT64(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint64_t), &x)
+#define BOX_UINT32(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint32_t), &x)
+#define BOX_UINT16(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint16_t), &x)
+#define BOX_UINT8(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(uint8_t), &x)
+#define BOX_BOOLEAN(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(bool), &x)
+#define BOX_PTR(x) mono_value_box(mono_domain_get(), CACHED_CLASS_RAW(IntPtr), x)
+
+Variant::Type managed_to_variant_type(const ManagedType &p_type);
+
+// String
+
+String mono_to_utf8_string(MonoString *p_mono_string);
+String mono_to_utf16_string(MonoString *p_mono_string);
+
+_FORCE_INLINE_ String mono_string_to_godot(MonoString *p_mono_string) {
+ if (sizeof(CharType) == 2)
+ return mono_to_utf16_string(p_mono_string);
+
+ return mono_to_utf8_string(p_mono_string);
+}
+
+_FORCE_INLINE_ MonoString *mono_from_utf8_string(const String &p_string) {
+ return mono_string_new(mono_domain_get(), p_string.utf8().get_data());
+}
+
+_FORCE_INLINE_ MonoString *mono_from_utf16_string(const String &p_string) {
+ return mono_string_from_utf16((mono_unichar2 *)p_string.c_str());
+}
+
+_FORCE_INLINE_ MonoString *mono_string_from_godot(const String &p_string) {
+ if (sizeof(CharType) == 2)
+ return mono_from_utf16_string(p_string);
+
+ return mono_from_utf8_string(p_string);
+}
+
+// Variant
+
+MonoObject *variant_to_mono_object(const Variant *p_var, const ManagedType &p_type);
+MonoObject *variant_to_mono_object(const Variant *p_var);
+
+_FORCE_INLINE_ MonoObject *variant_to_mono_object(Variant p_var) {
+ return variant_to_mono_object(&p_var);
+}
+
+Variant mono_object_to_variant(MonoObject *p_obj);
+Variant mono_object_to_variant(MonoObject *p_obj, const ManagedType &p_type);
+
+// Array
+
+MonoArray *Array_to_mono_array(const Array &p_array);
+Array mono_array_to_Array(MonoArray *p_array);
+
+// PoolIntArray
+
+MonoArray *PoolIntArray_to_mono_array(const PoolIntArray &p_array);
+PoolIntArray mono_array_to_PoolIntArray(MonoArray *p_array);
+
+// PoolByteArray
+
+MonoArray *PoolByteArray_to_mono_array(const PoolByteArray &p_array);
+PoolByteArray mono_array_to_PoolByteArray(MonoArray *p_array);
+
+// PoolRealArray
+
+MonoArray *PoolRealArray_to_mono_array(const PoolRealArray &p_array);
+PoolRealArray mono_array_to_PoolRealArray(MonoArray *p_array);
+
+// PoolStringArray
+
+MonoArray *PoolStringArray_to_mono_array(const PoolStringArray &p_array);
+PoolStringArray mono_array_to_PoolStringArray(MonoArray *p_array);
+
+// PoolColorArray
+
+MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array);
+PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array);
+
+// PoolVector2Array
+
+MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array);
+PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array);
+
+// PoolVector3Array
+
+MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array);
+PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array);
+
+// Dictionary
+
+MonoObject *Dictionary_to_mono_object(const Dictionary &p_dict);
+Dictionary mono_object_to_Dictionary(MonoObject *p_dict);
+
+#ifdef YOLO_COPY
+#define MARSHALLED_OUT(m_t, m_in, m_out) m_t *m_out = (m_t *)&m_in;
+#define MARSHALLED_IN(m_t, m_in, m_out) m_t m_out = *reinterpret_cast<m_t *>(m_in);
+#else
+
+// Expects m_in to be of type float*
+
+#define MARSHALLED_OUT(m_t, m_in, m_out) MARSHALLED_OUT_##m_t(m_in, m_out)
+#define MARSHALLED_IN(m_t, m_in, m_out) MARSHALLED_IN_##m_t(m_in, m_out)
+
+// Vector2
+
+#define MARSHALLED_OUT_Vector2(m_in, m_out) real_t m_out[2] = { m_in.x, m_in.y };
+#define MARSHALLED_IN_Vector2(m_in, m_out) Vector2 m_out(m_in[0], m_in[1]);
+
+// Rect2
+
+#define MARSHALLED_OUT_Rect2(m_in, m_out) real_t m_out[4] = { m_in.position.x, m_in.position.y, m_in.size.width, m_in.size.height };
+#define MARSHALLED_IN_Rect2(m_in, m_out) Rect2 m_out(m_in[0], m_in[1], m_in[2], m_in[3]);
+
+// Transform2D
+
+#define MARSHALLED_OUT_Transform2D(m_in, m_out) real_t m_out[6] = { m_in[0].x, m_in[0].y, m_in[1].x, m_in[1].y, m_in[2].x, m_in[2].y };
+#define MARSHALLED_IN_Transform2D(m_in, m_out) Transform2D m_out(m_in[0], m_in[1], m_in[2], m_in[3], m_in[4], m_in[5]);
+
+// Vector3
+
+#define MARSHALLED_OUT_Vector3(m_in, m_out) real_t m_out[3] = { m_in.x, m_in.y, m_in.z };
+#define MARSHALLED_IN_Vector3(m_in, m_out) Vector3 m_out(m_in[0], m_in[1], m_in[2]);
+
+// Basis
+
+#define MARSHALLED_OUT_Basis(m_in, m_out) real_t m_out[9] = { \
+ m_in[0].x, m_in[0].y, m_in[0].z, \
+ m_in[1].x, m_in[1].y, m_in[1].z, \
+ m_in[2].x, m_in[2].y, m_in[2].z \
+};
+#define MARSHALLED_IN_Basis(m_in, m_out) Basis m_out(m_in[0], m_in[1], m_in[2], m_in[3], m_in[4], m_in[5], m_in[6], m_in[7], m_in[8]);
+
+// Quat
+
+#define MARSHALLED_OUT_Quat(m_in, m_out) real_t m_out[4] = { m_in.x, m_in.y, m_in.z, m_in.w };
+#define MARSHALLED_IN_Quat(m_in, m_out) Quat m_out(m_in[0], m_in[1], m_in[2], m_in[3]);
+
+// Transform
+
+#define MARSHALLED_OUT_Transform(m_in, m_out) real_t m_out[12] = { \
+ m_in.basis[0].x, m_in.basis[0].y, m_in.basis[0].z, \
+ m_in.basis[1].x, m_in.basis[1].y, m_in.basis[1].z, \
+ m_in.basis[2].x, m_in.basis[2].y, m_in.basis[2].z, \
+ m_in.origin.x, m_in.origin.y, m_in.origin.z \
+};
+#define MARSHALLED_IN_Transform(m_in, m_out) Transform m_out( \
+ Basis(m_in[0], m_in[1], m_in[2], m_in[3], m_in[4], m_in[5], m_in[6], m_in[7], m_in[8]), \
+ Vector3(m_in[9], m_in[10], m_in[11]));
+
+// Rect3
+
+#define MARSHALLED_OUT_Rect3(m_in, m_out) real_t m_out[6] = { m_in.position.x, m_in.position.y, m_in.position.z, m_in.size.x, m_in.size.y, m_in.size.z };
+#define MARSHALLED_IN_Rect3(m_in, m_out) Rect3 m_out(Vector3(m_in[0], m_in[1], m_in[2]), Vector3(m_in[3], m_in[4], m_in[5]));
+
+// Color
+
+#define MARSHALLED_OUT_Color(m_in, m_out) real_t m_out[4] = { m_in.r, m_in.g, m_in.b, m_in.a };
+#define MARSHALLED_IN_Color(m_in, m_out) Color m_out(m_in[0], m_in[1], m_in[2], m_in[3]);
+
+// Plane
+
+#define MARSHALLED_OUT_Plane(m_in, m_out) real_t m_out[4] = { m_in.normal.x, m_in.normal.y, m_in.normal.z, m_in.d };
+#define MARSHALLED_IN_Plane(m_in, m_out) Plane m_out(m_in[0], m_in[1], m_in[2], m_in[3]);
+
+#endif
+
+} // GDMonoMarshal
+
+#endif // GDMONOMARSHAL_H
diff --git a/modules/mono/mono_gd/gd_mono_method.cpp b/modules/mono/mono_gd/gd_mono_method.cpp
new file mode 100644
index 0000000000..6468e0d3d9
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_method.cpp
@@ -0,0 +1,192 @@
+/*************************************************************************/
+/* gd_mono_method.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono_method.h"
+
+#include "gd_mono_class.h"
+#include "gd_mono_marshal.h"
+
+void GDMonoMethod::_update_signature() {
+ // Apparently MonoMethodSignature needs not to be freed.
+ // mono_method_signature caches the result, we don't need to cache it ourselves.
+
+ MonoMethodSignature *method_sig = mono_method_signature(mono_method);
+ _update_signature(method_sig);
+}
+
+void GDMonoMethod::_update_signature(MonoMethodSignature *p_method_sig) {
+ is_instance = mono_signature_is_instance(p_method_sig);
+ params_count = mono_signature_get_param_count(p_method_sig);
+
+ MonoType *ret_type = mono_signature_get_return_type(p_method_sig);
+ if (ret_type) {
+ return_type.type_encoding = mono_type_get_type(ret_type);
+
+ if (return_type.type_encoding != MONO_TYPE_VOID) {
+ MonoClass *ret_type_class = mono_class_from_mono_type(ret_type);
+ return_type.type_class = GDMono::get_singleton()->get_class(ret_type_class);
+ }
+ }
+
+ void *iter = NULL;
+ MonoType *param_raw_type;
+ while ((param_raw_type = mono_signature_get_params(p_method_sig, &iter)) != NULL) {
+ ManagedType param_type;
+
+ param_type.type_encoding = mono_type_get_type(param_raw_type);
+
+ if (param_type.type_encoding != MONO_TYPE_VOID) {
+ MonoClass *param_type_class = mono_class_from_mono_type(param_raw_type);
+ param_type.type_class = GDMono::get_singleton()->get_class(param_type_class);
+ }
+
+ param_types.push_back(param_type);
+ }
+}
+
+void *GDMonoMethod::get_thunk() {
+ return mono_method_get_unmanaged_thunk(mono_method);
+}
+
+MonoObject *GDMonoMethod::invoke(MonoObject *p_object, const Variant **p_params, MonoObject **r_exc) {
+ if (get_return_type().type_encoding != MONO_TYPE_VOID || get_parameters_count() > 0) {
+ MonoArray *params = mono_array_new(mono_domain_get(), CACHED_CLASS_RAW(MonoObject), get_parameters_count());
+
+ for (int i = 0; i < params_count; i++) {
+ MonoObject *boxed_param = GDMonoMarshal::variant_to_mono_object(p_params[i], param_types[i]);
+ mono_array_set(params, MonoObject *, i, boxed_param);
+ }
+
+ return mono_runtime_invoke_array(mono_method, p_object, params, r_exc);
+ } else {
+ mono_runtime_invoke(mono_method, p_object, NULL, r_exc);
+ return NULL;
+ }
+}
+
+MonoObject *GDMonoMethod::invoke(MonoObject *p_object, MonoObject **r_exc) {
+ ERR_FAIL_COND_V(get_parameters_count() > 0, NULL);
+ return invoke_raw(p_object, NULL, r_exc);
+}
+
+MonoObject *GDMonoMethod::invoke_raw(MonoObject *p_object, void **p_params, MonoObject **r_exc) {
+ return mono_runtime_invoke(mono_method, p_object, p_params, r_exc);
+}
+
+bool GDMonoMethod::has_attribute(GDMonoClass *p_attr_class) {
+ ERR_FAIL_NULL_V(p_attr_class, false);
+
+ if (!attrs_fetched)
+ fetch_attributes();
+
+ if (!attributes)
+ return false;
+
+ return mono_custom_attrs_has_attr(attributes, p_attr_class->get_raw());
+}
+
+MonoObject *GDMonoMethod::get_attribute(GDMonoClass *p_attr_class) {
+ ERR_FAIL_NULL_V(p_attr_class, NULL);
+
+ if (!attrs_fetched)
+ fetch_attributes();
+
+ if (!attributes)
+ return NULL;
+
+ return mono_custom_attrs_get_attr(attributes, p_attr_class->get_raw());
+}
+
+void GDMonoMethod::fetch_attributes() {
+ ERR_FAIL_COND(attributes != NULL);
+ attributes = mono_custom_attrs_from_method(mono_method);
+ attrs_fetched = true;
+}
+
+String GDMonoMethod::get_full_name(bool p_signature) const {
+ char *res = mono_method_full_name(mono_method, p_signature);
+ String full_name(res);
+ mono_free(res);
+ return full_name;
+}
+
+String GDMonoMethod::get_full_name_no_class() const {
+ String res;
+
+ MonoMethodSignature *method_sig = mono_method_signature(mono_method);
+
+ char *ret_str = mono_type_full_name(mono_signature_get_return_type(method_sig));
+ res += ret_str;
+ mono_free(ret_str);
+
+ res += " ";
+ res += name;
+ res += "(";
+
+ char *sig_desc = mono_signature_get_desc(method_sig, true);
+ res += sig_desc;
+ mono_free(sig_desc);
+
+ res += ")";
+
+ return res;
+}
+
+String GDMonoMethod::get_ret_type_full_name() const {
+ MonoMethodSignature *method_sig = mono_method_signature(mono_method);
+ char *ret_str = mono_type_full_name(mono_signature_get_return_type(method_sig));
+ String res = ret_str;
+ mono_free(ret_str);
+ return res;
+}
+
+String GDMonoMethod::get_signature_desc(bool p_namespaces) const {
+ MonoMethodSignature *method_sig = mono_method_signature(mono_method);
+ char *sig_desc = mono_signature_get_desc(method_sig, p_namespaces);
+ String res = sig_desc;
+ mono_free(sig_desc);
+ return res;
+}
+
+GDMonoMethod::GDMonoMethod(StringName p_name, MonoMethod *p_method) {
+ name = p_name;
+
+ mono_method = p_method;
+
+ attrs_fetched = false;
+ attributes = NULL;
+
+ _update_signature();
+}
+
+GDMonoMethod::~GDMonoMethod() {
+ if (attributes) {
+ mono_custom_attrs_free(attributes);
+ }
+}
diff --git a/modules/mono/mono_gd/gd_mono_method.h b/modules/mono/mono_gd/gd_mono_method.h
new file mode 100644
index 0000000000..ea4bc8e707
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_method.h
@@ -0,0 +1,81 @@
+/*************************************************************************/
+/* gd_mono_method.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_MONO_METHOD_H
+#define GD_MONO_METHOD_H
+
+#include "gd_mono.h"
+#include "gd_mono_header.h"
+
+class GDMonoMethod {
+
+ StringName name;
+
+ bool is_instance;
+ int params_count;
+ ManagedType return_type;
+ Vector<ManagedType> param_types;
+
+ bool attrs_fetched;
+ MonoCustomAttrInfo *attributes;
+
+ void _update_signature();
+ void _update_signature(MonoMethodSignature *p_method_sig);
+
+ friend class GDMonoClass;
+
+ MonoMethod *mono_method;
+
+public:
+ _FORCE_INLINE_ StringName get_name() { return name; }
+
+ _FORCE_INLINE_ bool is_static() { return !is_instance; }
+ _FORCE_INLINE_ int get_parameters_count() { return params_count; }
+ _FORCE_INLINE_ ManagedType get_return_type() { return return_type; }
+
+ void *get_thunk();
+
+ MonoObject *invoke(MonoObject *p_object, const Variant **p_params, MonoObject **r_exc = NULL);
+ MonoObject *invoke(MonoObject *p_object, MonoObject **r_exc = NULL);
+ MonoObject *invoke_raw(MonoObject *p_object, void **p_params, MonoObject **r_exc = NULL);
+
+ bool has_attribute(GDMonoClass *p_attr_class);
+ MonoObject *get_attribute(GDMonoClass *p_attr_class);
+ void fetch_attributes();
+
+ String get_full_name(bool p_signature = false) const;
+ String get_full_name_no_class() const;
+ String get_ret_type_full_name() const;
+ String get_signature_desc(bool p_namespaces = false) const;
+
+ GDMonoMethod(StringName p_name, MonoMethod *p_method);
+ ~GDMonoMethod();
+};
+
+#endif // GD_MONO_METHOD_H
diff --git a/modules/mono/mono_gd/gd_mono_utils.cpp b/modules/mono/mono_gd/gd_mono_utils.cpp
new file mode 100644
index 0000000000..5deca8e64d
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_utils.cpp
@@ -0,0 +1,367 @@
+/*************************************************************************/
+/* gd_mono_utils.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_mono_utils.h"
+
+#include "os/dir_access.h"
+#include "project_settings.h"
+#include "reference.h"
+
+#include "../csharp_script.h"
+#include "gd_mono.h"
+#include "gd_mono_class.h"
+#include "gd_mono_marshal.h"
+
+namespace GDMonoUtils {
+
+MonoCache mono_cache;
+
+#define CACHE_AND_CHECK(m_var, m_val) \
+ { \
+ m_var = m_val; \
+ if (!m_var) ERR_PRINT("Mono Cache: Member " #m_var " is null. This is really bad!"); \
+ }
+
+#define CACHE_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_class, m_val)
+#define CACHE_NS_CLASS_AND_CHECK(m_ns, m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.class_##m_ns##_##m_class, m_val)
+#define CACHE_RAW_MONO_CLASS_AND_CHECK(m_class, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.rawclass_##m_class, m_val)
+#define CACHE_FIELD_AND_CHECK(m_class, m_field, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.field_##m_class##_##m_field, m_val)
+#define CACHE_METHOD_THUNK_AND_CHECK(m_class, m_method, m_val) CACHE_AND_CHECK(GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method, m_val)
+
+void MonoCache::clear_members() {
+
+ class_MonoObject = NULL;
+ class_bool = NULL;
+ class_int8_t = NULL;
+ class_int16_t = NULL;
+ class_int32_t = NULL;
+ class_int64_t = NULL;
+ class_uint8_t = NULL;
+ class_uint16_t = NULL;
+ class_uint32_t = NULL;
+ class_uint64_t = NULL;
+ class_float = NULL;
+ class_double = NULL;
+ class_String = NULL;
+ class_IntPtr = NULL;
+
+ rawclass_Dictionary = NULL;
+
+ class_Vector2 = NULL;
+ class_Rect2 = NULL;
+ class_Transform2D = NULL;
+ class_Vector3 = NULL;
+ class_Basis = NULL;
+ class_Quat = NULL;
+ class_Transform = NULL;
+ class_Rect3 = NULL;
+ class_Color = NULL;
+ class_Plane = NULL;
+ class_NodePath = NULL;
+ class_RID = NULL;
+ class_GodotObject = NULL;
+ class_Node = NULL;
+ class_Control = NULL;
+ class_Spatial = NULL;
+ class_WeakRef = NULL;
+ class_MarshalUtils = NULL;
+
+ class_ExportAttribute = NULL;
+ field_ExportAttribute_hint = NULL;
+ field_ExportAttribute_hint_string = NULL;
+ field_ExportAttribute_usage = NULL;
+ class_ToolAttribute = NULL;
+ class_RemoteAttribute = NULL;
+ class_SyncAttribute = NULL;
+ class_MasterAttribute = NULL;
+ class_SlaveAttribute = NULL;
+ class_GodotMethodAttribute = NULL;
+ field_GodotMethodAttribute_methodName = NULL;
+
+ field_GodotObject_ptr = NULL;
+ field_NodePath_ptr = NULL;
+ field_Image_ptr = NULL;
+ field_RID_ptr = NULL;
+
+ methodthunk_MarshalUtils_DictionaryToArrays = NULL;
+ methodthunk_MarshalUtils_ArraysToDictionary = NULL;
+ methodthunk_GodotObject__AwaitedSignalCallback = NULL;
+ methodthunk_SignalAwaiter_FailureCallback = NULL;
+ methodthunk_GodotTaskScheduler_Activate = NULL;
+
+ task_scheduler_handle = Ref<MonoGCHandle>();
+}
+
+#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
+
+void update_corlib_cache() {
+
+ CACHE_CLASS_AND_CHECK(MonoObject, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_object_class()));
+ CACHE_CLASS_AND_CHECK(bool, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_boolean_class()));
+ CACHE_CLASS_AND_CHECK(int8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_sbyte_class()));
+ CACHE_CLASS_AND_CHECK(int16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int16_class()));
+ CACHE_CLASS_AND_CHECK(int32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int32_class()));
+ CACHE_CLASS_AND_CHECK(int64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_int64_class()));
+ CACHE_CLASS_AND_CHECK(uint8_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_byte_class()));
+ CACHE_CLASS_AND_CHECK(uint16_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint16_class()));
+ CACHE_CLASS_AND_CHECK(uint32_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint32_class()));
+ CACHE_CLASS_AND_CHECK(uint64_t, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_uint64_class()));
+ CACHE_CLASS_AND_CHECK(float, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_single_class()));
+ CACHE_CLASS_AND_CHECK(double, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_double_class()));
+ CACHE_CLASS_AND_CHECK(String, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_string_class()));
+ CACHE_CLASS_AND_CHECK(IntPtr, GDMono::get_singleton()->get_corlib_assembly()->get_class(mono_get_intptr_class()));
+}
+
+void update_godot_api_cache() {
+
+ CACHE_CLASS_AND_CHECK(Vector2, GODOT_API_CLASS(Vector2));
+ CACHE_CLASS_AND_CHECK(Rect2, GODOT_API_CLASS(Rect2));
+ CACHE_CLASS_AND_CHECK(Transform2D, GODOT_API_CLASS(Transform2D));
+ CACHE_CLASS_AND_CHECK(Vector3, GODOT_API_CLASS(Vector3));
+ CACHE_CLASS_AND_CHECK(Basis, GODOT_API_CLASS(Basis));
+ CACHE_CLASS_AND_CHECK(Quat, GODOT_API_CLASS(Quat));
+ CACHE_CLASS_AND_CHECK(Transform, GODOT_API_CLASS(Transform));
+ CACHE_CLASS_AND_CHECK(Rect3, GODOT_API_CLASS(Rect3));
+ CACHE_CLASS_AND_CHECK(Color, GODOT_API_CLASS(Color));
+ CACHE_CLASS_AND_CHECK(Plane, GODOT_API_CLASS(Plane));
+ CACHE_CLASS_AND_CHECK(NodePath, GODOT_API_CLASS(NodePath));
+ CACHE_CLASS_AND_CHECK(RID, GODOT_API_CLASS(NodePath));
+ CACHE_CLASS_AND_CHECK(GodotObject, GODOT_API_CLASS(Object));
+ CACHE_CLASS_AND_CHECK(Node, GODOT_API_CLASS(Node));
+ CACHE_CLASS_AND_CHECK(Control, GODOT_API_CLASS(Control));
+ CACHE_CLASS_AND_CHECK(Spatial, GODOT_API_CLASS(Spatial));
+ CACHE_CLASS_AND_CHECK(WeakRef, GODOT_API_CLASS(WeakRef));
+ CACHE_CLASS_AND_CHECK(MarshalUtils, GODOT_API_CLASS(MarshalUtils));
+
+ // Attributes
+ CACHE_CLASS_AND_CHECK(ExportAttribute, GODOT_API_CLASS(ExportAttribute));
+ CACHE_FIELD_AND_CHECK(ExportAttribute, hint, CACHED_CLASS(ExportAttribute)->get_field("hint"));
+ CACHE_FIELD_AND_CHECK(ExportAttribute, hint_string, CACHED_CLASS(ExportAttribute)->get_field("hint_string"));
+ CACHE_FIELD_AND_CHECK(ExportAttribute, usage, CACHED_CLASS(ExportAttribute)->get_field("usage"));
+ CACHE_CLASS_AND_CHECK(ToolAttribute, GODOT_API_CLASS(ToolAttribute));
+ CACHE_CLASS_AND_CHECK(RemoteAttribute, GODOT_API_CLASS(RemoteAttribute));
+ CACHE_CLASS_AND_CHECK(SyncAttribute, GODOT_API_CLASS(SyncAttribute));
+ CACHE_CLASS_AND_CHECK(MasterAttribute, GODOT_API_CLASS(MasterAttribute));
+ CACHE_CLASS_AND_CHECK(SlaveAttribute, GODOT_API_CLASS(SlaveAttribute));
+ CACHE_CLASS_AND_CHECK(GodotMethodAttribute, GODOT_API_CLASS(GodotMethodAttribute));
+ CACHE_FIELD_AND_CHECK(GodotMethodAttribute, methodName, CACHED_CLASS(GodotMethodAttribute)->get_field("methodName"));
+
+ CACHE_FIELD_AND_CHECK(GodotObject, ptr, CACHED_CLASS(GodotObject)->get_field(BINDINGS_PTR_FIELD));
+ CACHE_FIELD_AND_CHECK(NodePath, ptr, CACHED_CLASS(NodePath)->get_field(BINDINGS_PTR_FIELD));
+ CACHE_FIELD_AND_CHECK(RID, ptr, CACHED_CLASS(RID)->get_field(BINDINGS_PTR_FIELD));
+
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, DictionaryToArrays, (MarshalUtils_DictToArrays)CACHED_CLASS(MarshalUtils)->get_method("DictionaryToArrays", 3)->get_thunk());
+ CACHE_METHOD_THUNK_AND_CHECK(MarshalUtils, ArraysToDictionary, (MarshalUtils_ArraysToDict)CACHED_CLASS(MarshalUtils)->get_method("ArraysToDictionary", 2)->get_thunk());
+ CACHE_METHOD_THUNK_AND_CHECK(GodotObject, _AwaitedSignalCallback, (GodotObject__AwaitedSignalCallback)CACHED_CLASS(GodotObject)->get_method("_AwaitedSignalCallback", 2)->get_thunk());
+ CACHE_METHOD_THUNK_AND_CHECK(SignalAwaiter, FailureCallback, (SignalAwaiter_FailureCallback)GODOT_API_CLASS(SignalAwaiter)->get_method("FailureCallback", 0)->get_thunk());
+ CACHE_METHOD_THUNK_AND_CHECK(GodotTaskScheduler, Activate, (GodotTaskScheduler_Activate)GODOT_API_CLASS(GodotTaskScheduler)->get_method("Activate", 0)->get_thunk());
+
+ {
+ /*
+ * TODO Right now we only support Dictionary<object, object>.
+ * It would be great if we could support other key/value types
+ * without forcing the user to copy the entries.
+ */
+ GDMonoMethod *method_get_dict_type = CACHED_CLASS(MarshalUtils)->get_method("GetDictionaryType", 0);
+ ERR_FAIL_NULL(method_get_dict_type);
+ MonoReflectionType *dict_refl_type = (MonoReflectionType *)method_get_dict_type->invoke(NULL);
+ ERR_FAIL_NULL(dict_refl_type);
+ MonoType *dict_type = mono_reflection_type_get_type(dict_refl_type);
+ ERR_FAIL_NULL(dict_type);
+
+ CACHE_RAW_MONO_CLASS_AND_CHECK(Dictionary, mono_class_from_mono_type(dict_type));
+ }
+
+ MonoObject *task_scheduler = mono_object_new(SCRIPTS_DOMAIN, GODOT_API_CLASS(GodotTaskScheduler)->get_raw());
+ mono_runtime_object_init(task_scheduler);
+ mono_cache.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
+}
+
+void clear_cache() {
+ mono_cache.cleanup();
+ mono_cache.clear_members();
+}
+
+MonoObject *unmanaged_get_managed(Object *unmanaged) {
+ if (unmanaged) {
+ if (unmanaged->get_script_instance()) {
+ CSharpInstance *cs_instance = CAST_CSHARP_INSTANCE(unmanaged->get_script_instance());
+
+ if (cs_instance) {
+ return cs_instance->get_mono_object();
+ }
+ }
+
+ // Only called if the owner does not have a CSharpInstance
+ void *data = unmanaged->get_script_instance_binding(CSharpLanguage::get_singleton()->get_language_index());
+
+ if (data) {
+ return ((Map<Object *, Ref<MonoGCHandle> >::Element *)data)->value()->get_target();
+ }
+ }
+
+ return NULL;
+}
+
+void set_main_thread(MonoThread *p_thread) {
+ mono_thread_set_main(p_thread);
+}
+
+void attach_current_thread() {
+ ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
+ MonoThread *mono_thread = mono_thread_attach(SCRIPTS_DOMAIN);
+ ERR_FAIL_NULL(mono_thread);
+}
+
+void detach_current_thread() {
+ ERR_FAIL_COND(!GDMono::get_singleton()->is_runtime_initialized());
+ MonoThread *mono_thread = mono_thread_current();
+ ERR_FAIL_NULL(mono_thread);
+ mono_thread_detach(mono_thread);
+}
+
+MonoThread *get_current_thread() {
+ return mono_thread_current();
+}
+
+GDMonoClass *get_object_class(MonoObject *p_object) {
+ return GDMono::get_singleton()->get_class(mono_object_get_class(p_object));
+}
+
+GDMonoClass *type_get_proxy_class(const StringName &p_type) {
+ String class_name = p_type;
+
+ if (class_name[0] == '_')
+ class_name = class_name.substr(1, class_name.length());
+
+ GDMonoClass *klass = GDMono::get_singleton()->get_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
+
+#ifdef TOOLS_ENABLED
+ if (!klass) {
+ return GDMono::get_singleton()->get_editor_api_assembly()->get_class(BINDINGS_NAMESPACE, class_name);
+ }
+#endif
+
+ return klass;
+}
+
+GDMonoClass *get_class_native_base(GDMonoClass *p_class) {
+ GDMonoClass *klass = p_class;
+
+ do {
+ const GDMonoAssembly *assembly = klass->get_assembly();
+ if (assembly == GDMono::get_singleton()->get_api_assembly())
+ return klass;
+#ifdef TOOLS_ENABLED
+ if (assembly == GDMono::get_singleton()->get_editor_api_assembly())
+ return klass;
+#endif
+ } while ((klass = klass->get_parent_class()) != NULL);
+
+ return NULL;
+}
+
+MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object) {
+ String object_type = p_object->get_class_name();
+
+ if (object_type[0] == '_')
+ object_type = object_type.substr(1, object_type.length());
+
+ if (!ClassDB::is_parent_class(object_type, p_native)) {
+ ERR_EXPLAIN("Type inherits from native type '" + p_native + "', so it can't be instanced in object of type: '" + p_object->get_class() + "'");
+ ERR_FAIL_V(NULL);
+ }
+
+ MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, p_class->get_raw());
+ ERR_FAIL_NULL_V(mono_object, NULL);
+
+ CACHED_FIELD(GodotObject, ptr)->set_value_raw(mono_object, p_object);
+
+ // Construct
+ mono_runtime_object_init(mono_object);
+
+ return mono_object;
+}
+
+MonoObject *create_managed_from(const NodePath &p_from) {
+ MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(NodePath));
+ ERR_FAIL_NULL_V(mono_object, NULL);
+
+ // Construct
+ mono_runtime_object_init(mono_object);
+
+ CACHED_FIELD(NodePath, ptr)->set_value_raw(mono_object, memnew(NodePath(p_from)));
+
+ return mono_object;
+}
+
+MonoObject *create_managed_from(const RID &p_from) {
+ MonoObject *mono_object = mono_object_new(SCRIPTS_DOMAIN, CACHED_CLASS_RAW(RID));
+ ERR_FAIL_NULL_V(mono_object, NULL);
+
+ // Construct
+ mono_runtime_object_init(mono_object);
+
+ CACHED_FIELD(RID, ptr)->set_value_raw(mono_object, memnew(RID(p_from)));
+
+ return mono_object;
+}
+
+MonoDomain *create_domain(const String &p_friendly_name) {
+ MonoDomain *domain = mono_domain_create_appdomain((char *)p_friendly_name.utf8().get_data(), NULL);
+
+ if (domain) {
+ // Workaround to avoid this exception:
+ // System.Configuration.ConfigurationErrorsException: Error Initializing the configuration system.
+ // ---> System.ArgumentException: The 'ExeConfigFilename' argument cannot be null.
+ mono_domain_set_config(domain, ".", "");
+ }
+
+ return domain;
+}
+
+String get_exception_name_and_message(MonoObject *p_ex) {
+ String res;
+
+ MonoClass *klass = mono_object_get_class(p_ex);
+ MonoType *type = mono_class_get_type(klass);
+
+ char *full_name = mono_type_full_name(type);
+ res += full_name;
+ mono_free(full_name);
+
+ res += ": ";
+
+ MonoProperty *prop = mono_class_get_property_from_name(klass, "Message");
+ MonoString *msg = (MonoString *)mono_property_get_value(prop, p_ex, NULL, NULL);
+ res += GDMonoMarshal::mono_string_to_godot(msg);
+
+ return res;
+}
+}
diff --git a/modules/mono/mono_gd/gd_mono_utils.h b/modules/mono/mono_gd/gd_mono_utils.h
new file mode 100644
index 0000000000..f97f048aa9
--- /dev/null
+++ b/modules/mono/mono_gd/gd_mono_utils.h
@@ -0,0 +1,182 @@
+/*************************************************************************/
+/* gd_mono_utils.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_MONOUTILS_H
+#define GD_MONOUTILS_H
+
+#include <mono/metadata/threads.h>
+
+#include "../mono_gc_handle.h"
+#include "gd_mono_header.h"
+
+#include "object.h"
+#include "reference.h"
+
+namespace GDMonoUtils {
+
+typedef MonoObject *(*MarshalUtils_DictToArrays)(MonoObject *, MonoArray **, MonoArray **, MonoObject **);
+typedef MonoObject *(*MarshalUtils_ArraysToDict)(MonoArray *, MonoArray *, MonoObject **);
+typedef MonoObject *(*GodotObject__AwaitedSignalCallback)(MonoObject *, MonoArray **, MonoObject *, MonoObject **);
+typedef MonoObject *(*SignalAwaiter_FailureCallback)(MonoObject *, MonoObject **);
+typedef MonoObject *(*GodotTaskScheduler_Activate)(MonoObject *, MonoObject **);
+
+struct MonoCache {
+ // Format for cached classes in the Godot namespace: class_<Class>
+ // Macro: CACHED_CLASS(<Class>)
+
+ // Format for cached classes in a different namespace: class_<Namespace>_<Class>
+ // Macro: CACHED_NS_CLASS(<Namespace>, <Class>)
+
+ // -----------------------------------------------
+ // corlib classes
+
+ // Let's use the no-namespace format for these too
+ GDMonoClass *class_MonoObject;
+ GDMonoClass *class_bool;
+ GDMonoClass *class_int8_t;
+ GDMonoClass *class_int16_t;
+ GDMonoClass *class_int32_t;
+ GDMonoClass *class_int64_t;
+ GDMonoClass *class_uint8_t;
+ GDMonoClass *class_uint16_t;
+ GDMonoClass *class_uint32_t;
+ GDMonoClass *class_uint64_t;
+ GDMonoClass *class_float;
+ GDMonoClass *class_double;
+ GDMonoClass *class_String;
+ GDMonoClass *class_IntPtr;
+
+ MonoClass *rawclass_Dictionary;
+ // -----------------------------------------------
+
+ GDMonoClass *class_Vector2;
+ GDMonoClass *class_Rect2;
+ GDMonoClass *class_Transform2D;
+ GDMonoClass *class_Vector3;
+ GDMonoClass *class_Basis;
+ GDMonoClass *class_Quat;
+ GDMonoClass *class_Transform;
+ GDMonoClass *class_Rect3;
+ GDMonoClass *class_Color;
+ GDMonoClass *class_Plane;
+ GDMonoClass *class_NodePath;
+ GDMonoClass *class_RID;
+ GDMonoClass *class_GodotObject;
+ GDMonoClass *class_Node;
+ GDMonoClass *class_Control;
+ GDMonoClass *class_Spatial;
+ GDMonoClass *class_WeakRef;
+ GDMonoClass *class_MarshalUtils;
+
+ GDMonoClass *class_ExportAttribute;
+ GDMonoField *field_ExportAttribute_hint;
+ GDMonoField *field_ExportAttribute_hint_string;
+ GDMonoField *field_ExportAttribute_usage;
+ GDMonoClass *class_ToolAttribute;
+ GDMonoClass *class_RemoteAttribute;
+ GDMonoClass *class_SyncAttribute;
+ GDMonoClass *class_MasterAttribute;
+ GDMonoClass *class_SlaveAttribute;
+ GDMonoClass *class_GodotMethodAttribute;
+ GDMonoField *field_GodotMethodAttribute_methodName;
+
+ GDMonoField *field_GodotObject_ptr;
+ GDMonoField *field_NodePath_ptr;
+ GDMonoField *field_Image_ptr;
+ GDMonoField *field_RID_ptr;
+
+ MarshalUtils_DictToArrays methodthunk_MarshalUtils_DictionaryToArrays;
+ MarshalUtils_ArraysToDict methodthunk_MarshalUtils_ArraysToDictionary;
+ GodotObject__AwaitedSignalCallback methodthunk_GodotObject__AwaitedSignalCallback;
+ SignalAwaiter_FailureCallback methodthunk_SignalAwaiter_FailureCallback;
+ GodotTaskScheduler_Activate methodthunk_GodotTaskScheduler_Activate;
+
+ Ref<MonoGCHandle> task_scheduler_handle;
+
+ void clear_members();
+ void cleanup() {}
+
+ MonoCache() {
+ clear_members();
+ }
+};
+
+extern MonoCache mono_cache;
+
+void update_corlib_cache();
+void update_godot_api_cache();
+void clear_cache();
+
+_FORCE_INLINE_ void hash_combine(uint32_t &p_hash, const uint32_t &p_with_hash) {
+ p_hash ^= p_with_hash + 0x9e3779b9 + (p_hash << 6) + (p_hash >> 2);
+}
+
+/**
+ * If the object has a csharp script, returns the target of the gchandle stored in the script instance
+ * Otherwise returns a newly constructed MonoObject* which is attached to the object
+ * Returns NULL on error
+ */
+MonoObject *unmanaged_get_managed(Object *unmanaged);
+
+void set_main_thread(MonoThread *p_thread);
+void attach_current_thread();
+void detach_current_thread();
+MonoThread *get_current_thread();
+
+GDMonoClass *get_object_class(MonoObject *p_object);
+GDMonoClass *type_get_proxy_class(const StringName &p_type);
+GDMonoClass *get_class_native_base(GDMonoClass *p_class);
+
+MonoObject *create_managed_for_godot_object(GDMonoClass *p_class, const StringName &p_native, Object *p_object);
+
+MonoObject *create_managed_from(const NodePath &p_from);
+MonoObject *create_managed_from(const RID &p_from);
+
+MonoDomain *create_domain(const String &p_friendly_name);
+
+String get_exception_name_and_message(MonoObject *p_ex);
+
+} // GDMonoUtils
+
+#define NATIVE_GDMONOCLASS_NAME(m_class) (GDMonoMarshal::mono_string_to_godot((MonoString *)m_class->get_field("nativeName")->get_value(NULL)))
+
+#define CACHED_CLASS(m_class) (GDMonoUtils::mono_cache.class_##m_class)
+#define CACHED_CLASS_RAW(m_class) (GDMonoUtils::mono_cache.class_##m_class->get_raw())
+#define CACHED_NS_CLASS(m_ns, m_class) (GDMonoUtils::mono_cache.class_##m_ns##_##m_class)
+#define CACHED_RAW_MONO_CLASS(m_class) (GDMonoUtils::mono_cache.rawclass_##m_class)
+#define CACHED_FIELD(m_class, m_field) (GDMonoUtils::mono_cache.field_##m_class##_##m_field)
+#define CACHED_METHOD_THUNK(m_class, m_method) (GDMonoUtils::mono_cache.methodthunk_##m_class##_##m_method)
+
+#ifdef REAL_T_IS_DOUBLE
+#define REAL_T_MONOCLASS CACHED_CLASS_RAW(double)
+#else
+#define REAL_T_MONOCLASS CACHED_CLASS_RAW(float)
+#endif
+
+#endif // GD_MONOUTILS_H
diff --git a/modules/mono/mono_reg_utils.py b/modules/mono/mono_reg_utils.py
new file mode 100644
index 0000000000..6f1620ff49
--- /dev/null
+++ b/modules/mono/mono_reg_utils.py
@@ -0,0 +1,54 @@
+import os
+
+if os.name == 'nt':
+ import _winreg as winreg
+
+
+def _reg_open_key(key, subkey):
+ try:
+ return winreg.OpenKey(key, subkey)
+ except (WindowsError, EnvironmentError) as e:
+ import platform
+ if platform.architecture()[0] == '32bit':
+ bitness_sam = winreg.KEY_WOW64_64KEY
+ else:
+ bitness_sam = winreg.KEY_WOW64_32KEY
+ return winreg.OpenKey(key, subkey, 0, winreg.KEY_READ | bitness_sam)
+
+
+def _find_mono_in_reg(subkey):
+ try:
+ with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
+ value, regtype = winreg.QueryValueEx(hKey, 'SdkInstallRoot')
+ return value
+ except (WindowsError, EnvironmentError) as e:
+ return None
+
+def _find_mono_in_reg_old(subkey):
+ try:
+ with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
+ default_clr, regtype = winreg.QueryValueEx(hKey, 'DefaultCLR')
+ if default_clr:
+ return _find_mono_in_reg(subkey + '\\' + default_clr)
+ return None
+ except (WindowsError, EnvironmentError):
+ return None
+
+
+def find_mono_root_dir():
+ dir = _find_mono_in_reg(r'SOFTWARE\Mono')
+ if dir:
+ return dir
+ dir = _find_mono_in_reg_old(r'SOFTWARE\Novell\Mono')
+ if dir:
+ return dir
+ return None
+
+
+def find_msbuild_tools_path_reg():
+ try:
+ with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\MSBuild\ToolsVersions\4.0') as hKey:
+ value, regtype = winreg.QueryValueEx(hKey, 'MSBuildToolsPath')
+ return value
+ except (WindowsError, EnvironmentError) as e:
+ return None
diff --git a/modules/mono/register_types.cpp b/modules/mono/register_types.cpp
new file mode 100644
index 0000000000..2a84f0d1a6
--- /dev/null
+++ b/modules/mono/register_types.cpp
@@ -0,0 +1,71 @@
+/*************************************************************************/
+/* register_types.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "register_types.h"
+
+#include "project_settings.h"
+
+#include "csharp_script.h"
+
+CSharpLanguage *script_language_cs = NULL;
+ResourceFormatLoaderCSharpScript *resource_loader_cs = NULL;
+ResourceFormatSaverCSharpScript *resource_saver_cs = NULL;
+
+_GodotSharp *_godotsharp = NULL;
+
+void register_mono_types() {
+ ClassDB::register_class<CSharpScript>();
+
+ _godotsharp = memnew(_GodotSharp);
+
+ ProjectSettings::get_singleton()->add_singleton(ProjectSettings::Singleton("GodotSharp", _GodotSharp::get_singleton()));
+
+ script_language_cs = memnew(CSharpLanguage);
+ script_language_cs->set_language_index(ScriptServer::get_language_count());
+ ScriptServer::register_language(script_language_cs);
+
+ resource_loader_cs = memnew(ResourceFormatLoaderCSharpScript);
+ ResourceLoader::add_resource_format_loader(resource_loader_cs);
+ resource_saver_cs = memnew(ResourceFormatSaverCSharpScript);
+ ResourceSaver::add_resource_format_saver(resource_saver_cs);
+}
+
+void unregister_mono_types() {
+ ScriptServer::unregister_language(script_language_cs);
+
+ if (script_language_cs)
+ memdelete(script_language_cs);
+ if (resource_loader_cs)
+ memdelete(resource_loader_cs);
+ if (resource_saver_cs)
+ memdelete(resource_saver_cs);
+
+ if (_godotsharp)
+ memdelete(_godotsharp);
+}
diff --git a/modules/mono/register_types.h b/modules/mono/register_types.h
new file mode 100644
index 0000000000..6cf706b944
--- /dev/null
+++ b/modules/mono/register_types.h
@@ -0,0 +1,31 @@
+/*************************************************************************/
+/* register_types.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+void register_mono_types();
+void unregister_mono_types();
diff --git a/modules/mono/signal_awaiter_utils.cpp b/modules/mono/signal_awaiter_utils.cpp
new file mode 100644
index 0000000000..012dd119b1
--- /dev/null
+++ b/modules/mono/signal_awaiter_utils.cpp
@@ -0,0 +1,77 @@
+/*************************************************************************/
+/* signal_awaiter_utils.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "signal_awaiter_utils.h"
+
+#include "mono_gd/gd_mono_utils.h"
+
+namespace SignalAwaiterUtils {
+
+Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p_target, MonoObject *p_awaiter) {
+
+ ERR_FAIL_NULL_V(p_source, ERR_INVALID_DATA);
+ ERR_FAIL_NULL_V(p_target, ERR_INVALID_DATA);
+
+ uint32_t awaiter_handle = MonoGCHandle::make_strong_handle(p_awaiter);
+ Ref<SignalAwaiterHandle> sa_con = memnew(SignalAwaiterHandle(awaiter_handle));
+ Vector<Variant> binds;
+ binds.push_back(sa_con);
+ Error err = p_source->connect(p_signal, p_target, "_AwaitedSignalCallback", binds, Object::CONNECT_ONESHOT);
+
+ if (err != OK) {
+ // set it as completed to prevent it from calling the failure callback when deleted
+ // the awaiter will be aware of the failure by checking the returned error
+ sa_con->set_completed(true);
+ }
+
+ return err;
+}
+}
+
+SignalAwaiterHandle::SignalAwaiterHandle(uint32_t p_handle)
+ : MonoGCHandle(p_handle) {
+}
+
+SignalAwaiterHandle::~SignalAwaiterHandle() {
+ if (!completed) {
+ GDMonoUtils::SignalAwaiter_FailureCallback thunk = CACHED_METHOD_THUNK(SignalAwaiter, FailureCallback);
+
+ MonoObject *awaiter = get_target();
+
+ if (awaiter) {
+ MonoObject *ex = NULL;
+ thunk(awaiter, &ex);
+
+ if (ex) {
+ mono_print_unhandled_exception(ex);
+ ERR_FAIL_V();
+ }
+ }
+ }
+}
diff --git a/modules/mono/signal_awaiter_utils.h b/modules/mono/signal_awaiter_utils.h
new file mode 100644
index 0000000000..422ed4754f
--- /dev/null
+++ b/modules/mono/signal_awaiter_utils.h
@@ -0,0 +1,53 @@
+/*************************************************************************/
+/* signal_awaiter_utils.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 SIGNAL_AWAITER_UTILS_H
+#define SIGNAL_AWAITER_UTILS_H
+
+#include "mono_gc_handle.h"
+#include "reference.h"
+
+namespace SignalAwaiterUtils {
+
+Error connect_signal_awaiter(Object *p_source, const String &p_signal, Object *p_target, MonoObject *p_awaiter);
+}
+
+class SignalAwaiterHandle : public MonoGCHandle {
+
+ bool completed;
+
+public:
+ _FORCE_INLINE_ bool is_completed() { return completed; }
+ _FORCE_INLINE_ void set_completed(bool p_completed) { completed = p_completed; }
+
+ SignalAwaiterHandle(uint32_t p_handle);
+ ~SignalAwaiterHandle();
+};
+
+#endif // SIGNAL_AWAITER_UTILS_H
diff --git a/modules/mono/utils/mono_reg_utils.cpp b/modules/mono/utils/mono_reg_utils.cpp
new file mode 100644
index 0000000000..2e90b3b716
--- /dev/null
+++ b/modules/mono/utils/mono_reg_utils.cpp
@@ -0,0 +1,228 @@
+/*************************************************************************/
+/* mono_reg_utils.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "mono_reg_utils.h"
+
+#ifdef WINDOWS_ENABLED
+
+#include "os/os.h"
+
+// Here, after os/os.h
+#include <windows.h>
+
+namespace MonoRegUtils {
+
+template <int>
+REGSAM bitness_sam_impl();
+
+template <>
+REGSAM bitness_sam_impl<4>() {
+ return KEY_WOW64_64KEY;
+}
+
+template <>
+REGSAM bitness_sam_impl<8>() {
+ return KEY_WOW64_32KEY;
+}
+
+REGSAM _get_bitness_sam() {
+ return bitness_sam_impl<sizeof(size_t)>();
+}
+
+LONG _RegOpenKey(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult) {
+
+ LONG res = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ, phkResult);
+
+ if (res != ERROR_SUCCESS)
+ res = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ | _get_bitness_sam(), phkResult);
+
+ return res;
+}
+
+LONG _RegKeyQueryString(HKEY hKey, const String &p_value_name, String &r_value) {
+
+ Vector<WCHAR> buffer;
+ buffer.resize(512);
+ DWORD dwBufferSize = buffer.size();
+
+ LONG res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, NULL, (LPBYTE)buffer.ptr(), &dwBufferSize);
+
+ if (res == ERROR_MORE_DATA) {
+ // dwBufferSize now contains the actual size
+ Vector<WCHAR> buffer;
+ buffer.resize(dwBufferSize);
+ res = RegQueryValueExW(hKey, p_value_name.c_str(), 0, NULL, (LPBYTE)buffer.ptr(), &dwBufferSize);
+ }
+
+ if (res == ERROR_SUCCESS) {
+ r_value = String(buffer.ptr(), buffer.size());
+ } else {
+ r_value = String();
+ }
+
+ return res;
+}
+
+LONG _find_mono_in_reg(const String &p_subkey, MonoRegInfo &r_info, bool p_old_reg = false) {
+
+ HKEY hKey;
+ LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, p_subkey.c_str(), &hKey);
+
+ if (res != ERROR_SUCCESS)
+ goto cleanup;
+
+ if (!p_old_reg) {
+ res = _RegKeyQueryString(hKey, "Version", r_info.version);
+ if (res != ERROR_SUCCESS)
+ goto cleanup;
+ }
+
+ res = _RegKeyQueryString(hKey, "SdkInstallRoot", r_info.install_root_dir);
+ if (res != ERROR_SUCCESS)
+ goto cleanup;
+
+ res = _RegKeyQueryString(hKey, "FrameworkAssemblyDirectory", r_info.assembly_dir);
+ if (res != ERROR_SUCCESS)
+ goto cleanup;
+
+ res = _RegKeyQueryString(hKey, "MonoConfigDir", r_info.config_dir);
+ if (res != ERROR_SUCCESS)
+ goto cleanup;
+
+ if (r_info.install_root_dir.ends_with("\\"))
+ r_info.bin_dir = r_info.install_root_dir + "bin";
+ else
+ r_info.bin_dir = r_info.install_root_dir + "\\bin";
+
+cleanup:
+ RegCloseKey(hKey);
+ return res;
+}
+
+LONG _find_mono_in_reg_old(const String &p_subkey, MonoRegInfo &r_info) {
+
+ String default_clr;
+
+ HKEY hKey;
+ LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, p_subkey.c_str(), &hKey);
+
+ if (res != ERROR_SUCCESS)
+ goto cleanup;
+
+ res = _RegKeyQueryString(hKey, "DefaultCLR", default_clr);
+
+ if (res == ERROR_SUCCESS && default_clr.length()) {
+ r_info.version = default_clr;
+ res = _find_mono_in_reg(p_subkey + "\\" + default_clr, r_info, true);
+ }
+
+cleanup:
+ RegCloseKey(hKey);
+ return res;
+}
+
+MonoRegInfo find_mono() {
+
+ MonoRegInfo info;
+
+ if (_find_mono_in_reg("Software\\Mono", info) == ERROR_SUCCESS)
+ return info;
+
+ if (_find_mono_in_reg_old("Software\\Novell\\Mono", info) == ERROR_SUCCESS)
+ return info;
+
+ ERR_PRINT("Cannot find mono in the registry");
+
+ return MonoRegInfo();
+}
+
+String find_msbuild_tools_path() {
+
+ String msbuild_tools_path;
+
+ // Try to find 15.0 with vswhere
+
+ String vswhere_path = OS::get_singleton()->get_environment(sizeof(size_t) == 8 ? "ProgramFiles(x86)" : "ProgramFiles");
+ vswhere_path += "\\Microsoft Visual Studio\\Installer\\vswhere.exe";
+
+ List<String> vswhere_args;
+ vswhere_args.push_back("-latest");
+ vswhere_args.push_back("-requires");
+ vswhere_args.push_back("Microsoft.Component.MSBuild");
+
+ String output;
+ int exit_code;
+ OS::get_singleton()->execute(vswhere_path, vswhere_args, true, NULL, &output, &exit_code);
+
+ if (exit_code == 0) {
+ Vector<String> lines = output.split("\n");
+
+ for (int i = 0; i < lines.size(); i++) {
+ const String &line = lines[i];
+ int sep_idx = line.find(":");
+
+ if (sep_idx > 0) {
+ String key = line.substr(0, sep_idx); // No need to trim
+
+ if (key == "installationPath") {
+ String val = line.substr(sep_idx + 1, line.length()).strip_edges();
+
+ ERR_BREAK(val.empty());
+
+ if (!val.ends_with("\\")) {
+ val += "\\";
+ }
+
+ return val + "MSBuild\\15.0\\Bin";
+ }
+ }
+ }
+ }
+
+ // Try to find 14.0 in the Registry
+
+ HKEY hKey;
+ LONG res = _RegOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\14.0", &hKey);
+
+ if (res != ERROR_SUCCESS)
+ goto cleanup;
+
+ res = _RegKeyQueryString(hKey, "MSBuildToolsPath", msbuild_tools_path);
+
+ if (res != ERROR_SUCCESS)
+ goto cleanup;
+
+cleanup:
+ RegCloseKey(hKey);
+
+ return msbuild_tools_path;
+}
+} // namespace MonoRegUtils
+
+#endif WINDOWS_ENABLED
diff --git a/modules/mono/utils/mono_reg_utils.h b/modules/mono/utils/mono_reg_utils.h
new file mode 100644
index 0000000000..4cc4965acb
--- /dev/null
+++ b/modules/mono/utils/mono_reg_utils.h
@@ -0,0 +1,54 @@
+/*************************************************************************/
+/* mono_reg_utils.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 MONO_REG_UTILS_H
+#define MONO_REG_UTILS_H
+
+#ifdef WINDOWS_ENABLED
+
+#include "ustring.h"
+
+struct MonoRegInfo {
+
+ String version;
+ String install_root_dir;
+ String assembly_dir;
+ String config_dir;
+ String bin_dir;
+};
+
+namespace MonoRegUtils {
+
+MonoRegInfo find_mono();
+String find_msbuild_tools_path();
+} // MonoRegUtils
+
+#endif // WINDOWS_ENABLED
+
+#endif // MONO_REG_UTILS_H
diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp
new file mode 100644
index 0000000000..c8581f6122
--- /dev/null
+++ b/modules/mono/utils/path_utils.cpp
@@ -0,0 +1,111 @@
+/*************************************************************************/
+/* path_utils.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 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_utils.h"
+
+#include "os/dir_access.h"
+#include "os/file_access.h"
+#include "os/os.h"
+#include "project_settings.h"
+
+#ifdef WINDOWS_ENABLED
+#define ENV_PATH_SEP ";"
+#else
+#define ENV_PATH_SEP ":"
+#include <limits.h>
+#endif
+
+#include <stdlib.h>
+
+String path_which(const String &p_name) {
+
+#ifdef WINDOWS_ENABLED
+ Vector<String> exts = OS::get_singleton()->get_environment("PATHEXT").split(ENV_PATH_SEP, false);
+#endif
+ Vector<String> env_path = OS::get_singleton()->get_environment("PATH").split(ENV_PATH_SEP, false);
+
+ if (env_path.empty())
+ return String();
+
+ for (int i = 0; i < env_path.size(); i++) {
+ String p = path_join(env_path[i], p_name);
+
+ if (FileAccess::exists(p))
+ return p;
+
+#ifdef WINDOWS_ENABLED
+ for (int j = 0; j < exts.size(); j++) {
+ String p2 = p + exts[j];
+
+ if (FileAccess::exists(p2))
+ return p2;
+ }
+#endif
+ }
+
+ return String();
+}
+
+void fix_path(const String &p_path, String &r_out) {
+ r_out = p_path.replace("\\", "/");
+
+ while (true) { // in case of using 2 or more slash
+ String compare = r_out.replace("//", "/");
+ if (r_out == compare)
+ break;
+ else
+ r_out = compare;
+ }
+}
+
+bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) {
+#ifdef WINDOWS_ENABLED
+ CharType ret[_MAX_PATH];
+ if (_wfullpath(ret, p_existing_path.c_str(), _MAX_PATH)) {
+ String abspath = String(ret).replace("\\", "/");
+ int pos = abspath.find(":/");
+ if (pos != -1) {
+ r_abs_path = abspath.substr(pos - 1, abspath.length());
+ } else {
+ r_abs_path = abspath;
+ }
+ return true;
+ }
+#else
+ char ret[PATH_MAX];
+ if (realpath(p_existing_path.utf8().get_data(), ret)) {
+ String retstr;
+ if (!retstr.parse_utf8(ret)) {
+ r_abs_path = retstr;
+ return true;
+ }
+ }
+#endif
+ return false;
+}
diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h
new file mode 100644
index 0000000000..445604300d
--- /dev/null
+++ b/modules/mono/utils/path_utils.h
@@ -0,0 +1,53 @@
+/*************************************************************************/
+/* path_utils.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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_UTILS_H
+#define PATH_UTILS_H
+
+#include "ustring.h"
+
+_FORCE_INLINE_ String path_join(const String &e1, const String &e2) {
+ return e1.plus_file(e2);
+}
+
+_FORCE_INLINE_ String path_join(const String &e1, const String &e2, const String &e3) {
+ return e1.plus_file(e2).plus_file(e3);
+}
+
+_FORCE_INLINE_ String path_join(const String &e1, const String &e2, const String &e3, const String &e4) {
+ return e1.plus_file(e2).plus_file(e3).plus_file(e4);
+}
+
+String path_which(const String &p_name);
+
+void fix_path(const String &p_path, String &r_out);
+
+bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path);
+
+#endif // PATH_UTILS_H
diff --git a/modules/mono/utils/string_utils.cpp b/modules/mono/utils/string_utils.cpp
new file mode 100644
index 0000000000..de1a60dbd1
--- /dev/null
+++ b/modules/mono/utils/string_utils.cpp
@@ -0,0 +1,128 @@
+/*************************************************************************/
+/* string_utils.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+#include "string_utils.h"
+
+namespace {
+
+int sfind(const String &p_text, int p_from) {
+ if (p_from < 0)
+ return -1;
+
+ int src_len = 2;
+ int len = p_text.length();
+
+ if (src_len == 0 || len == 0)
+ return -1;
+
+ const CharType *src = p_text.c_str();
+
+ for (int i = p_from; i <= (len - src_len); i++) {
+ bool found = true;
+
+ for (int j = 0; j < src_len; j++) {
+ int read_pos = i + j;
+
+ if (read_pos >= len) {
+ ERR_PRINT("read_pos >= len");
+ return -1;
+ };
+
+ switch (j) {
+ case 0:
+ found = src[read_pos] == '%';
+ break;
+ case 1: {
+ CharType c = src[read_pos];
+ found = src[read_pos] == 's' || (c >= '0' || c <= '4');
+ break;
+ }
+ default:
+ found = false;
+ }
+
+ if (!found) {
+ break;
+ }
+ }
+
+ if (found)
+ return i;
+ }
+
+ return -1;
+}
+}
+
+String sformat(const String &p_text, const Variant &p1, const Variant &p2, const Variant &p3, const Variant &p4, const Variant &p5) {
+ if (p_text.length() < 2)
+ return p_text;
+
+ Array args;
+
+ if (p1.get_type() != Variant::NIL) {
+ args.push_back(p1);
+
+ if (p2.get_type() != Variant::NIL) {
+ args.push_back(p2);
+
+ if (p3.get_type() != Variant::NIL) {
+ args.push_back(p3);
+
+ if (p4.get_type() != Variant::NIL) {
+ args.push_back(p4);
+
+ if (p5.get_type() != Variant::NIL) {
+ args.push_back(p5);
+ }
+ }
+ }
+ }
+ }
+
+ String new_string;
+
+ int findex = 0;
+ int search_from = 0;
+ int result = 0;
+
+ while ((result = sfind(p_text, search_from)) >= 0) {
+ CharType c = p_text[result + 1];
+
+ int req_index = (c == 's' ? findex++ : c - '0');
+
+ new_string += p_text.substr(search_from, result - search_from);
+ new_string += args[req_index].operator String();
+ search_from = result + 2;
+ }
+
+ new_string += p_text.substr(search_from, p_text.length() - search_from);
+
+ return new_string;
+}
diff --git a/modules/mono/utils/string_utils.h b/modules/mono/utils/string_utils.h
new file mode 100644
index 0000000000..2f2c3c2d89
--- /dev/null
+++ b/modules/mono/utils/string_utils.h
@@ -0,0 +1,38 @@
+/*************************************************************************/
+/* string_utils.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 STRING_FORMAT_H
+#define STRING_FORMAT_H
+
+#include "ustring.h"
+#include "variant.h"
+
+String sformat(const String &p_text, const Variant &p1 = Variant(), const Variant &p2 = Variant(), const Variant &p3 = Variant(), const Variant &p4 = Variant(), const Variant &p5 = Variant());
+
+#endif // STRING_FORMAT_H
diff --git a/modules/ogg/SCsub b/modules/ogg/SCsub
index 5eabaf6f2b..5e559bd4db 100644
--- a/modules/ogg/SCsub
+++ b/modules/ogg/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_ogg = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_libogg'] != 'no'):
+if env['builtin_libogg']:
thirdparty_dir = "#thirdparty/libogg/"
thirdparty_sources = [
"bitwise.c",
diff --git a/modules/openssl/SCsub b/modules/openssl/SCsub
index eb3c0e64d8..84c5e68439 100644
--- a/modules/openssl/SCsub
+++ b/modules/openssl/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_openssl = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_openssl'] != 'no'):
+if env['builtin_openssl']:
thirdparty_dir = "#thirdparty/openssl/"
thirdparty_sources = [
diff --git a/modules/openssl/stream_peer_openssl.cpp b/modules/openssl/stream_peer_openssl.cpp
index d40bf73883..c19bdc4214 100644
--- a/modules/openssl/stream_peer_openssl.cpp
+++ b/modules/openssl/stream_peer_openssl.cpp
@@ -29,6 +29,17 @@
/*************************************************************************/
#include "stream_peer_openssl.h"
+// Compatibility with OpenSSL 1.1.0.
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define BIO_set_num(b, n)
+#else
+#define BIO_set_num(b, n) ((b)->num = (n))
+
+#define BIO_set_init(b, i) ((b)->init = (i))
+#define BIO_set_data(b, p) ((b)->ptr = (p))
+#define BIO_get_data(b) ((b)->ptr)
+#endif
+
//hostname matching code from curl
bool StreamPeerOpenSSL::_match_host_name(const char *name, const char *hostname) {
@@ -157,10 +168,10 @@ int StreamPeerOpenSSL::_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg
}
int StreamPeerOpenSSL::_bio_create(BIO *b) {
- b->init = 1;
- b->num = 0;
- b->ptr = NULL;
- b->flags = 0;
+ BIO_set_init(b, 1);
+ BIO_set_num(b, 0);
+ BIO_set_data(b, NULL);
+ BIO_clear_flags(b, ~0);
return 1;
}
@@ -168,9 +179,9 @@ int StreamPeerOpenSSL::_bio_destroy(BIO *b) {
if (b == NULL)
return 0;
- b->ptr = NULL; /* sb_tls_remove() will free it */
- b->init = 0;
- b->flags = 0;
+ BIO_set_data(b, NULL); /* sb_tls_remove() will free it */
+ BIO_set_init(b, 0);
+ BIO_clear_flags(b, ~0);
return 1;
}
@@ -178,7 +189,7 @@ int StreamPeerOpenSSL::_bio_read(BIO *b, char *buf, int len) {
if (buf == NULL || len <= 0) return 0;
- StreamPeerOpenSSL *sp = (StreamPeerOpenSSL *)b->ptr;
+ StreamPeerOpenSSL *sp = (StreamPeerOpenSSL *)BIO_get_data(b);
ERR_FAIL_COND_V(sp == NULL, 0);
@@ -212,7 +223,7 @@ int StreamPeerOpenSSL::_bio_write(BIO *b, const char *buf, int len) {
if (buf == NULL || len <= 0) return 0;
- StreamPeerOpenSSL *sp = (StreamPeerOpenSSL *)b->ptr;
+ StreamPeerOpenSSL *sp = (StreamPeerOpenSSL *)BIO_get_data(b);
ERR_FAIL_COND_V(sp == NULL, 0);
@@ -258,6 +269,26 @@ int StreamPeerOpenSSL::_bio_puts(BIO *b, const char *str) {
return _bio_write(b, str, strlen(str));
}
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+BIO_METHOD *StreamPeerOpenSSL::_bio_method = NULL;
+
+BIO_METHOD *StreamPeerOpenSSL::_get_bio_method() {
+ if (_bio_method) // already initialized.
+ return _bio_method;
+
+ /* it's a source/sink BIO */
+ _bio_method = BIO_meth_new(100 | 0x400, "streampeer glue");
+ BIO_meth_set_write(_bio_method, _bio_write);
+ BIO_meth_set_read(_bio_method, _bio_read);
+ BIO_meth_set_puts(_bio_method, _bio_puts);
+ BIO_meth_set_gets(_bio_method, _bio_gets);
+ BIO_meth_set_ctrl(_bio_method, _bio_ctrl);
+ BIO_meth_set_create(_bio_method, _bio_create);
+ BIO_meth_set_destroy(_bio_method, _bio_destroy);
+
+ return _bio_method;
+}
+#else
BIO_METHOD StreamPeerOpenSSL::_bio_method = {
/* it's a source/sink BIO */
(100 | 0x400),
@@ -271,6 +302,11 @@ BIO_METHOD StreamPeerOpenSSL::_bio_method = {
_bio_destroy
};
+BIO_METHOD *StreamPeerOpenSSL::_get_bio_method() {
+ return &_bio_method;
+}
+#endif
+
Error StreamPeerOpenSSL::connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs, const String &p_for_hostname) {
if (connected)
@@ -330,8 +366,8 @@ Error StreamPeerOpenSSL::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida
}
ssl = SSL_new(ctx);
- bio = BIO_new(&_bio_method);
- bio->ptr = this;
+ bio = BIO_new(_get_bio_method());
+ BIO_set_data(bio, this);
SSL_set_bio(ssl, bio, bio);
if (p_for_hostname != String()) {
@@ -532,7 +568,9 @@ void StreamPeerOpenSSL::initialize_ssl() {
load_certs_func = _load_certs;
_create = _create_func;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_malloc_init(); // Initialize malloc, free, etc for OpenSSL's use
+#endif
SSL_library_init(); // Initialize OpenSSL's SSL libraries
SSL_load_error_strings(); // Load SSL error strings
ERR_load_BIO_strings(); // Load BIO error strings
diff --git a/modules/openssl/stream_peer_openssl.h b/modules/openssl/stream_peer_openssl.h
index 1e445ef681..535114058d 100644
--- a/modules/openssl/stream_peer_openssl.h
+++ b/modules/openssl/stream_peer_openssl.h
@@ -53,7 +53,12 @@ private:
static int _bio_gets(BIO *b, char *buf, int len);
static int _bio_puts(BIO *b, const char *str);
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ static BIO_METHOD *_bio_method;
+#else
static BIO_METHOD _bio_method;
+#endif
+ static BIO_METHOD *_get_bio_method();
static bool _match_host_name(const char *name, const char *hostname);
static Error _match_common_name(const char *hostname, const X509 *server_cert);
diff --git a/modules/opus/SCsub b/modules/opus/SCsub
index 4d3053c7ec..fee06bd267 100644
--- a/modules/opus/SCsub
+++ b/modules/opus/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_opus = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_opus'] != 'no'):
+if env['builtin_opus']:
thirdparty_dir = "#thirdparty/opus/"
thirdparty_sources = [
@@ -209,7 +209,7 @@ if (env['builtin_opus'] != 'no'):
env_opus.Append(CPPPATH=[thirdparty_dir + "/" + dir for dir in thirdparty_include_paths])
# also requires libogg
- if (env['builtin_libogg'] != 'no'):
+ if env['builtin_libogg']:
env_opus.Append(CPPPATH=["#thirdparty/libogg"])
# Module files
diff --git a/modules/opus/audio_stream_opus.cpp b/modules/opus/audio_stream_opus.cpp
index 1dac890eb8..c7748b9b21 100644
--- a/modules/opus/audio_stream_opus.cpp
+++ b/modules/opus/audio_stream_opus.cpp
@@ -56,7 +56,7 @@ int AudioStreamPlaybackOpus::_op_seek_func(void *_stream, opus_int64 _offset, in
fa->seek(_offset);
} break;
case SEEK_CUR: {
- fa->seek(fa->get_pos() + _offset);
+ fa->seek(fa->get_position() + _offset);
} break;
case SEEK_END: {
fa->seek_end(_offset);
@@ -83,7 +83,7 @@ int AudioStreamPlaybackOpus::_op_close_func(void *_stream) {
opus_int64 AudioStreamPlaybackOpus::_op_tell_func(void *_stream) {
FileAccess *_fa = (FileAccess *)_stream;
- return (opus_int64)_fa->get_pos();
+ return (opus_int64)_fa->get_position();
}
void AudioStreamPlaybackOpus::_clear_stream() {
@@ -247,7 +247,7 @@ void AudioStreamPlaybackOpus::play(float p_from) {
frames_mixed = pre_skip;
playing = true;
if (p_from > 0) {
- seek_pos(p_from);
+ seek(p_from);
}
}
@@ -256,7 +256,7 @@ void AudioStreamPlaybackOpus::stop() {
playing = false;
}
-void AudioStreamPlaybackOpus::seek_pos(float p_time) {
+void AudioStreamPlaybackOpus::seek(float p_time) {
if (!playing) return;
ogg_int64_t pcm_offset = (ogg_int64_t)(p_time * osrate);
bool ok = op_pcm_seek(opus_file, pcm_offset) == 0;
@@ -340,7 +340,7 @@ float AudioStreamPlaybackOpus::get_length() const {
return length;
}
-float AudioStreamPlaybackOpus::get_pos() const {
+float AudioStreamPlaybackOpus::get_playback_position() const {
int32_t frames = int32_t(frames_mixed);
if (frames < 0)
diff --git a/modules/opus/audio_stream_opus.h b/modules/opus/audio_stream_opus.h
index ccfe04e84e..7b7740a804 100644
--- a/modules/opus/audio_stream_opus.h
+++ b/modules/opus/audio_stream_opus.h
@@ -99,8 +99,8 @@ public:
virtual int get_loop_count() const { return repeats; }
- virtual float get_pos() const;
- virtual void seek_pos(float p_time);
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
virtual int get_channels() const { return stream_channels; }
virtual int get_mix_rate() const { return osrate; }
diff --git a/modules/pvr/texture_loader_pvr.cpp b/modules/pvr/texture_loader_pvr.cpp
index 90ee164b6f..03592047ad 100644
--- a/modules/pvr/texture_loader_pvr.cpp
+++ b/modules/pvr/texture_loader_pvr.cpp
@@ -74,7 +74,7 @@ RES ResourceFormatPVR::load(const String &p_path, const String &p_original_path,
uint32_t mipmaps = f->get_32();
uint32_t flags = f->get_32();
uint32_t surfsize = f->get_32();
- f->seek(f->get_pos() + 20); // bpp, rmask, gmask, bmask, amask
+ f->seek(f->get_position() + 20); // bpp, rmask, gmask, bmask, amask
uint8_t pvrid[5] = { 0, 0, 0, 0, 0 };
f->get_buffer(pvrid, 4);
ERR_FAIL_COND_V(String((char *)pvrid) != "PVR!", RES());
diff --git a/modules/recast/SCsub b/modules/recast/SCsub
index 349bd22efb..500c0ec055 100644
--- a/modules/recast/SCsub
+++ b/modules/recast/SCsub
@@ -5,7 +5,7 @@ Import('env')
# Not building in a separate env as core needs it
# Thirdparty source files
-if (env['builtin_recast'] != 'no'):
+if env['builtin_recast']:
thirdparty_dir = "#thirdparty/recastnavigation/Recast/"
thirdparty_sources = [
"Source/Recast.cpp",
@@ -24,10 +24,6 @@ if (env['builtin_recast'] != 'no'):
env.Append(CPPPATH=[thirdparty_dir, thirdparty_dir + "/Include"])
- # also requires recast headers
- if (env['builtin_recast'] != 'no'):
- env.Append(CPPPATH=["#thirdparty/recastnavigation/Recast"])
-
lib = env.Library("recast_builtin", thirdparty_sources)
env.Append(LIBS=[lib])
diff --git a/modules/recast/config.py b/modules/recast/config.py
index fb920482f5..d42f07b2a9 100644
--- a/modules/recast/config.py
+++ b/modules/recast/config.py
@@ -1,6 +1,6 @@
def can_build(platform):
- return True
+ return platform != "android"
def configure(env):
diff --git a/modules/regex/SCsub b/modules/regex/SCsub
index 2dfc2739e9..2bab144a28 100644
--- a/modules/regex/SCsub
+++ b/modules/regex/SCsub
@@ -7,7 +7,7 @@ env_regex = env_modules.Clone()
env_regex.Append(CPPFLAGS=["-DPCRE2_CODE_UNIT_WIDTH=0"])
env_regex.add_source_files(env.modules_sources, "*.cpp")
-if (env['builtin_pcre2'] != 'no'):
+if env['builtin_pcre2']:
jit_blacklist = ['javascript']
thirdparty_dir = '#thirdparty/pcre2/src/'
thirdparty_flags = ['-DPCRE2_STATIC', '-DHAVE_CONFIG_H']
diff --git a/modules/regex/regex.h b/modules/regex/regex.h
index 0d97bcce54..bfa9c84042 100644
--- a/modules/regex/regex.h
+++ b/modules/regex/regex.h
@@ -87,8 +87,8 @@ public:
Error compile(const String &p_pattern);
void _init(const String &p_pattern = "");
- Ref<RegExMatch> search(const String &p_subject, int offset = 0, int end = -1) const;
- String sub(const String &p_subject, const String &p_replacement, bool p_all = false, int p_start = 0, int p_end = -1) const;
+ Ref<RegExMatch> search(const String &p_subject, int p_offset = 0, int p_end = -1) const;
+ String sub(const String &p_subject, const String &p_replacement, bool p_all = false, int p_offset = 0, int p_end = -1) const;
bool is_valid() const;
String get_pattern() const;
diff --git a/modules/squish/SCsub b/modules/squish/SCsub
index cca7c038f1..127f22d798 100644
--- a/modules/squish/SCsub
+++ b/modules/squish/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_squish = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_squish'] != 'no'):
+if env['builtin_squish']:
thirdparty_dir = "#thirdparty/squish/"
thirdparty_sources = [
"alpha.cpp",
diff --git a/modules/squish/config.py b/modules/squish/config.py
index cc8f098010..9b7729bda4 100644
--- a/modules/squish/config.py
+++ b/modules/squish/config.py
@@ -6,6 +6,6 @@ def can_build(platform):
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
- if (env["tools"] == "no"):
- env["module_squish_enabled"] = "no"
+ if not env['tools']:
+ env['module_squish_enabled'] = False
env.disabled_modules.append("squish")
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
index 9457fbfaf6..27ea310780 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp
@@ -58,7 +58,7 @@ void AudioStreamPlaybackOGGVorbis::_mix_internal(AudioFrame *p_buffer, int p_fra
//end of file!
if (vorbis_stream->loop) {
//loop
- seek_pos(vorbis_stream->loop_offset);
+ seek(vorbis_stream->loop_offset);
loops++;
} else {
for (int i = mixed; i < p_frames; i++) {
@@ -78,7 +78,7 @@ float AudioStreamPlaybackOGGVorbis::get_stream_sampling_rate() {
void AudioStreamPlaybackOGGVorbis::start(float p_from_pos) {
active = true;
- seek_pos(p_from_pos);
+ seek(p_from_pos);
loops = 0;
_begin_resample();
}
@@ -97,11 +97,11 @@ int AudioStreamPlaybackOGGVorbis::get_loop_count() const {
return loops;
}
-float AudioStreamPlaybackOGGVorbis::get_pos() const {
+float AudioStreamPlaybackOGGVorbis::get_playback_position() const {
return float(frames_mixed) / vorbis_stream->sample_rate;
}
-void AudioStreamPlaybackOGGVorbis::seek_pos(float p_time) {
+void AudioStreamPlaybackOGGVorbis::seek(float p_time) {
if (!active)
return;
diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.h b/modules/stb_vorbis/audio_stream_ogg_vorbis.h
index bcd829a56a..f4d381897b 100644
--- a/modules/stb_vorbis/audio_stream_ogg_vorbis.h
+++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.h
@@ -67,8 +67,8 @@ public:
virtual int get_loop_count() const; //times it looped
- virtual float get_pos() const;
- virtual void seek_pos(float p_time);
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
virtual float get_length() const; //if supported, otherwise return 0
diff --git a/modules/svg/image_loader_svg.cpp b/modules/svg/image_loader_svg.cpp
index c575edbba3..9c198ea98e 100644
--- a/modules/svg/image_loader_svg.cpp
+++ b/modules/svg/image_loader_svg.cpp
@@ -51,7 +51,7 @@ inline void change_nsvg_paint_color(NSVGpaint *p_paint, const uint32_t p_old, co
if (p_paint->type == NSVG_PAINT_COLOR) {
if (p_paint->color << 8 == p_old << 8) {
- p_paint->color = p_new;
+ p_paint->color = (p_paint->color & 0xFF000000) | (p_new & 0x00FFFFFF);
}
}
@@ -128,13 +128,13 @@ Error ImageLoaderSVG::_create_image(Ref<Image> p_image, const PoolVector<uint8_t
return OK;
}
-Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *svg_str, float p_scale, bool upsample, bool convert_colors) {
+Error ImageLoaderSVG::create_image_from_string(Ref<Image> p_image, const char *p_svg_str, float p_scale, bool upsample, bool convert_colors) {
- size_t str_len = strlen(svg_str);
+ size_t str_len = strlen(p_svg_str);
PoolVector<uint8_t> src_data;
src_data.resize(str_len + 1);
PoolVector<uint8_t>::Write src_w = src_data.write();
- memcpy(src_w.ptr(), svg_str, str_len + 1);
+ memcpy(src_w.ptr(), p_svg_str, str_len + 1);
return _create_image(p_image, &src_data, p_scale, upsample, convert_colors);
}
@@ -160,4 +160,4 @@ void ImageLoaderSVG::get_recognized_extensions(List<String> *p_extensions) const
ImageLoaderSVG::ImageLoaderSVG() {
}
-ImageLoaderSVG::ReplaceColors ImageLoaderSVG::replace_colors; \ No newline at end of file
+ImageLoaderSVG::ReplaceColors ImageLoaderSVG::replace_colors;
diff --git a/modules/svg/image_loader_svg.h b/modules/svg/image_loader_svg.h
index 332ac214a5..cf44cd8c50 100644
--- a/modules/svg/image_loader_svg.h
+++ b/modules/svg/image_loader_svg.h
@@ -57,7 +57,7 @@ class ImageLoaderSVG : public ImageFormatLoader {
List<uint32_t> new_colors;
} replace_colors;
static SVGRasterizer rasterizer;
- static void _convert_colors(NSVGimage *p_svg_imge);
+ static void _convert_colors(NSVGimage *p_svg_image);
static Error _create_image(Ref<Image> p_image, const PoolVector<uint8_t> *p_data, float p_scale, bool upsample, bool convert_colors = false);
public:
diff --git a/modules/tga/image_loader_tga.cpp b/modules/tga/image_loader_tga.cpp
index 7c7cf5bcbe..d7a1ce7308 100644
--- a/modules/tga/image_loader_tga.cpp
+++ b/modules/tga/image_loader_tga.cpp
@@ -253,7 +253,7 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
err = FAILED;
if (err == OK) {
- f->seek(f->get_pos() + tga_header.id_length);
+ f->seek(f->get_position() + tga_header.id_length);
PoolVector<uint8_t> palette;
@@ -269,7 +269,7 @@ Error ImageLoaderTGA::load_image(Ref<Image> p_image, FileAccess *f, bool p_force
}
PoolVector<uint8_t>::Write src_image_w = src_image.write();
- f->get_buffer(&src_image_w[0], src_image_len - f->get_pos());
+ f->get_buffer(&src_image_w[0], src_image_len - f->get_position());
PoolVector<uint8_t>::Read src_image_r = src_image.read();
diff --git a/modules/theora/SCsub b/modules/theora/SCsub
index 2de4d29640..9015c2c354 100644
--- a/modules/theora/SCsub
+++ b/modules/theora/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_theora = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_libtheora'] != 'no'):
+if env['builtin_libtheora']:
thirdparty_dir = "#thirdparty/libtheora/"
thirdparty_sources = [
#"analyze.c",
@@ -74,9 +74,9 @@ if (env['builtin_libtheora'] != 'no'):
env_theora.Append(CPPPATH=[thirdparty_dir])
# also requires libogg and libvorbis
- if (env['builtin_libogg'] != 'no'):
+ if env['builtin_libogg']:
env_theora.Append(CPPPATH=["#thirdparty/libogg"])
- if (env['builtin_libvorbis'] != 'no'):
+ if env['builtin_libvorbis']:
env_theora.Append(CPPPATH=["#thirdparty/libvorbis"])
# Godot source files
diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp
index 02b994f8db..c75bec31df 100644
--- a/modules/theora/video_stream_theora.cpp
+++ b/modules/theora/video_stream_theora.cpp
@@ -634,12 +634,12 @@ int VideoStreamPlaybackTheora::get_loop_count() const {
return 0;
};
-float VideoStreamPlaybackTheora::get_pos() const {
+float VideoStreamPlaybackTheora::get_playback_position() const {
return get_time();
};
-void VideoStreamPlaybackTheora::seek_pos(float p_time){
+void VideoStreamPlaybackTheora::seek(float p_time){
// no
};
diff --git a/modules/theora/video_stream_theora.h b/modules/theora/video_stream_theora.h
index f04e49c662..484a1a7fb9 100644
--- a/modules/theora/video_stream_theora.h
+++ b/modules/theora/video_stream_theora.h
@@ -140,8 +140,8 @@ public:
virtual int get_loop_count() const;
- virtual float get_pos() const;
- virtual void seek_pos(float p_time);
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
void set_file(const String &p_file);
diff --git a/modules/tinyexr/config.py b/modules/tinyexr/config.py
index 2e4b96a6b0..3e16fd725e 100644
--- a/modules/tinyexr/config.py
+++ b/modules/tinyexr/config.py
@@ -6,6 +6,6 @@ def can_build(platform):
def configure(env):
# Tools only, disabled for non-tools
# TODO: Find a cleaner way to achieve that
- if (env["tools"] == "no"):
- env["module_tinyexr_enabled"] = "no"
+ if not env['tools']:
+ env['module_tinyexr_enabled'] = False
env.disabled_modules.append("tinyexr")
diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp
index fc43536f46..48145495e4 100644
--- a/modules/visual_script/visual_script.cpp
+++ b/modules/visual_script/visual_script.cpp
@@ -424,7 +424,7 @@ Ref<VisualScriptNode> VisualScript::get_node(const StringName &p_func, int p_id)
return func.nodes[p_id].node;
}
-void VisualScript::set_node_pos(const StringName &p_func, int p_id, const Point2 &p_pos) {
+void VisualScript::set_node_position(const StringName &p_func, int p_id, const Point2 &p_pos) {
ERR_FAIL_COND(instances.size());
ERR_FAIL_COND(!functions.has(p_func));
@@ -434,7 +434,7 @@ void VisualScript::set_node_pos(const StringName &p_func, int p_id, const Point2
func.nodes[p_id].pos = p_pos;
}
-Point2 VisualScript::get_node_pos(const StringName &p_func, int p_id) const {
+Point2 VisualScript::get_node_position(const StringName &p_func, int p_id) const {
ERR_FAIL_COND_V(!functions.has(p_func), Point2());
const Function &func = functions[p_func];
@@ -1274,14 +1274,14 @@ void VisualScript::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_function_scroll", "name", "ofs"), &VisualScript::set_function_scroll);
ClassDB::bind_method(D_METHOD("get_function_scroll", "name"), &VisualScript::get_function_scroll);
- ClassDB::bind_method(D_METHOD("add_node", "func", "id", "node", "pos"), &VisualScript::add_node, DEFVAL(Point2()));
+ ClassDB::bind_method(D_METHOD("add_node", "func", "id", "node", "position"), &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(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(D_METHOD("set_node_position", "func", "id", "position"), &VisualScript::set_node_position);
+ ClassDB::bind_method(D_METHOD("get_node_position", "func", "id"), &VisualScript::get_node_position);
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);
@@ -2009,8 +2009,8 @@ void VisualScriptInstance::create(const Ref<VisualScript> &p_script, Object *p_o
Node *node = Object::cast_to<Node>(p_owner);
if (p_script->functions.has("_process"))
node->set_process(true);
- if (p_script->functions.has("_fixed_process"))
- node->set_fixed_process(true);
+ if (p_script->functions.has("_physics_process"))
+ node->set_physics_process(true);
if (p_script->functions.has("_input"))
node->set_process_input(true);
if (p_script->functions.has("_unhandled_input"))
diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h
index 297e9e510f..4ae50ee829 100644
--- a/modules/visual_script/visual_script.h
+++ b/modules/visual_script/visual_script.h
@@ -278,8 +278,8 @@ public:
void remove_node(const StringName &p_func, int p_id);
bool has_node(const StringName &p_func, int p_id) const;
Ref<VisualScriptNode> get_node(const StringName &p_func, int p_id) const;
- void set_node_pos(const StringName &p_func, int p_id, const Point2 &p_pos);
- Point2 get_node_pos(const StringName &p_func, int p_id) const;
+ void set_node_position(const StringName &p_func, int p_id, const Point2 &p_pos);
+ Point2 get_node_position(const StringName &p_func, int p_id) const;
void get_node_list(const StringName &p_func, List<int> *r_nodes) const;
void sequence_connect(const StringName &p_func, int p_from_node, int p_from_output, int p_to_node);
diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp
index 671a507377..985f8a8d0e 100644
--- a/modules/visual_script/visual_script_editor.cpp
+++ b/modules/visual_script/visual_script_editor.cpp
@@ -481,7 +481,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
continue;
Ref<VisualScriptNode> node = script->get_node(edited_func, E->get());
- Vector2 pos = script->get_node_pos(edited_func, E->get());
+ Vector2 pos = script->get_node_position(edited_func, E->get());
GraphNode *gnode = memnew(GraphNode);
gnode->set_title(node->get_caption());
@@ -491,10 +491,6 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
gnode->set_overlay(GraphNode::OVERLAY_BREAKPOINT);
}
- if (node_styles.has(node->get_category())) {
- gnode->add_style_override("frame", node_styles[node->get_category()]);
- }
-
gnode->set_meta("__vnode", node);
gnode->set_name(itos(E->get()));
gnode->connect("dragged", this, "_node_moved", varray(E->get()));
@@ -527,6 +523,25 @@ void VisualScriptEditor::_update_graph(int p_only_id) {
gnode->connect("resize_request", this, "_comment_node_resized", varray(E->get()));
}
+ if (node_styles.has(node->get_category())) {
+ Ref<StyleBoxFlat> sbf = node_styles[node->get_category()];
+ if (gnode->is_comment())
+ sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox("comment", "GraphNode");
+
+ Color c = sbf->get_border_color(MARGIN_TOP);
+ c.a = 1;
+ if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) {
+ Color mono_color = ((c.r + c.g + c.b) / 3) < 0.5 ? Color(1.0, 1.0, 1.0) : Color(0, 0, 0);
+ mono_color.a = 0.85;
+ c = mono_color;
+ }
+
+ gnode->add_color_override("title_color", c);
+ c.a = 0.7;
+ gnode->add_color_override("close_color", c);
+ gnode->add_style_override("frame", sbf);
+ }
+
int slot_idx = 0;
bool single_seq_output = node->get_output_sequence_port_count() == 1 && node->get_output_sequence_port_text(0) == String();
@@ -1050,7 +1065,7 @@ void VisualScriptEditor::_available_node_doubleclicked() {
List<int> existing;
script->get_node_list(edited_func, &existing);
for (List<int>::Element *E = existing.front(); E; E = E->next()) {
- Point2 pos = script->get_node_pos(edited_func, E->get());
+ Point2 pos = script->get_node_position(edited_func, E->get());
if (pos.distance_to(ofs) < 15) {
ofs += Vector2(graph->get_snap(), graph->get_snap());
exists = true;
@@ -1171,7 +1186,7 @@ void VisualScriptEditor::_on_nodes_delete() {
for (List<int>::Element *F = to_erase.front(); F; F = F->next()) {
undo_redo->add_do_method(script.ptr(), "remove_node", edited_func, F->get());
- undo_redo->add_undo_method(script.ptr(), "add_node", edited_func, F->get(), script->get_node(edited_func, F->get()), script->get_node_pos(edited_func, F->get()));
+ undo_redo->add_undo_method(script.ptr(), "add_node", edited_func, F->get(), script->get_node(edited_func, F->get()), script->get_node_position(edited_func, F->get()));
List<VisualScript::SequenceConnection> sequence_conns;
script->get_sequence_connection_list(edited_func, &sequence_conns);
@@ -1228,7 +1243,7 @@ void VisualScriptEditor::_on_nodes_duplicate() {
int new_id = idc++;
to_select.insert(new_id);
- undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, dupe, script->get_node_pos(edited_func, F->get()) + Vector2(20, 20));
+ undo_redo->add_do_method(script.ptr(), "add_node", edited_func, new_id, dupe, script->get_node_position(edited_func, F->get()) + Vector2(20, 20));
undo_redo->add_undo_method(script.ptr(), "remove_node", edited_func, new_id);
}
undo_redo->add_do_method(this, "_update_graph");
@@ -1262,7 +1277,7 @@ Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f
if (p_from == nodes) {
- TreeItem *it = nodes->get_item_at_pos(p_point);
+ TreeItem *it = nodes->get_item_at_position(p_point);
if (!it)
return Variant();
String type = it->get_metadata(0);
@@ -1281,7 +1296,7 @@ Variant VisualScriptEditor::get_drag_data_fw(const Point2 &p_point, Control *p_f
if (p_from == members) {
- TreeItem *it = members->get_item_at_pos(p_point);
+ TreeItem *it = members->get_item_at_position(p_point);
if (!it)
return Variant();
@@ -2182,7 +2197,7 @@ void VisualScriptEditor::_move_node(String func, int p_id, const Vector2 &p_to)
if (Object::cast_to<GraphNode>(node))
Object::cast_to<GraphNode>(node)->set_offset(p_to);
}
- script->set_node_pos(edited_func, p_id, p_to / EDSCALE);
+ script->set_node_position(edited_func, p_id, p_to / EDSCALE);
}
void VisualScriptEditor::_node_moved(Vector2 p_from, Vector2 p_to, int p_id) {
@@ -2196,7 +2211,7 @@ void VisualScriptEditor::_remove_node(int p_id) {
undo_redo->create_action(TTR("Remove VisualScript Node"));
undo_redo->add_do_method(script.ptr(), "remove_node", edited_func, p_id);
- undo_redo->add_undo_method(script.ptr(), "add_node", edited_func, p_id, script->get_node(edited_func, p_id), script->get_node_pos(edited_func, p_id));
+ undo_redo->add_undo_method(script.ptr(), "add_node", edited_func, p_id, script->get_node(edited_func, p_id), script->get_node_position(edited_func, p_id));
List<VisualScript::SequenceConnection> sequence_conns;
script->get_sequence_connection_list(edited_func, &sequence_conns);
@@ -2753,12 +2768,12 @@ void VisualScriptEditor::_notification(int p_what) {
signal_editor->connect("changed", this, "_update_members");
List<Pair<String, Color> > colors;
- colors.push_back(Pair<String, Color>("functions", Color(1, 0.9, 0.9)));
- colors.push_back(Pair<String, Color>("data", Color(0.9, 1.0, 0.9)));
- colors.push_back(Pair<String, Color>("operators", Color(0.9, 0.9, 1.0)));
- colors.push_back(Pair<String, Color>("flow_control", Color(1.0, 1.0, 1.0)));
- colors.push_back(Pair<String, Color>("custom", Color(0.8, 1.0, 1.0)));
- colors.push_back(Pair<String, Color>("constants", Color(1.0, 0.8, 1.0)));
+ colors.push_back(Pair<String, Color>("flow_control", Color::html("#f4f4f4")));
+ colors.push_back(Pair<String, Color>("functions", Color::html("#f58581")));
+ colors.push_back(Pair<String, Color>("data", Color::html("#80f6cf")));
+ colors.push_back(Pair<String, Color>("operators", Color::html("#ab97df")));
+ colors.push_back(Pair<String, Color>("custom", Color::html("#80bbf6")));
+ colors.push_back(Pair<String, Color>("constants", Color::html("#f680b0")));
for (List<Pair<String, Color> >::Element *E = colors.front(); E; E = E->next()) {
print_line(E->get().first);
@@ -2880,7 +2895,7 @@ void VisualScriptEditor::_menu_option(int p_what) {
}
if (node.is_valid()) {
clipboard->nodes[id] = node->duplicate();
- clipboard->nodes_positions[id] = script->get_node_pos(edited_func, id);
+ clipboard->nodes_positions[id] = script->get_node_position(edited_func, id);
}
}
}
@@ -2940,7 +2955,7 @@ void VisualScriptEditor::_menu_option(int p_what) {
List<int> nodes;
script->get_node_list(edited_func, &nodes);
for (List<int>::Element *E = nodes.front(); E; E = E->next()) {
- Vector2 pos = script->get_node_pos(edited_func, E->get()).snapped(Vector2(2, 2));
+ Vector2 pos = script->get_node_position(edited_func, E->get()).snapped(Vector2(2, 2));
existing_positions.insert(pos);
}
}
@@ -3054,7 +3069,7 @@ void VisualScriptEditor::_member_option(int p_option) {
List<int> nodes;
script->get_node_list(name, &nodes);
for (List<int>::Element *E = nodes.front(); E; E = E->next()) {
- undo_redo->add_undo_method(script.ptr(), "add_node", name, E->get(), script->get_node(name, E->get()), script->get_node_pos(name, E->get()));
+ undo_redo->add_undo_method(script.ptr(), "add_node", name, E->get(), script->get_node(name, E->get()), script->get_node_position(name, E->get()));
}
List<VisualScript::SequenceConnection> seq_connections;
@@ -3252,8 +3267,7 @@ VisualScriptEditor::VisualScriptEditor() {
graph = memnew(GraphEdit);
add_child(graph);
- graph->set_area_as_parent_rect();
- graph->set_h_size_flags(SIZE_EXPAND_FILL);
+ graph->set_anchors_and_margins_preset(Control::PRESET_WIDE);
graph->connect("node_selected", this, "_node_selected");
graph->connect("_begin_node_move", this, "_begin_node_move");
graph->connect("_end_node_move", this, "_end_node_move");
diff --git a/modules/visual_script/visual_script_expression.cpp b/modules/visual_script/visual_script_expression.cpp
index eae866d167..897e910f20 100644
--- a/modules/visual_script/visual_script_expression.cpp
+++ b/modules/visual_script/visual_script_expression.cpp
@@ -1023,7 +1023,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() {
case TK_OP_OR: op = Variant::OP_OR; break;
case TK_OP_NOT: op = Variant::OP_NOT; break;
case TK_OP_ADD: op = Variant::OP_ADD; break;
- case TK_OP_SUB: op = Variant::OP_SUBSTRACT; break;
+ case TK_OP_SUB: op = Variant::OP_SUBTRACT; break;
case TK_OP_MUL: op = Variant::OP_MULTIPLY; break;
case TK_OP_DIV: op = Variant::OP_DIVIDE; break;
case TK_OP_MOD: op = Variant::OP_MODULE; break;
@@ -1085,7 +1085,7 @@ VisualScriptExpression::ENode *VisualScriptExpression::_parse_expression() {
case Variant::OP_MODULE: priority = 2; break;
case Variant::OP_ADD: priority = 3; break;
- case Variant::OP_SUBSTRACT: priority = 3; break;
+ case Variant::OP_SUBTRACT: priority = 3; break;
case Variant::OP_SHIFT_LEFT: priority = 4; break;
case Variant::OP_SHIFT_RIGHT: priority = 4; break;
diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp
index 267946750f..8d73de9889 100644
--- a/modules/visual_script/visual_script_func_nodes.cpp
+++ b/modules/visual_script/visual_script_func_nodes.cpp
@@ -42,7 +42,7 @@
int VisualScriptFunctionCall::get_output_sequence_port_count() const {
- if (method_cache.flags & METHOD_FLAG_CONST || call_mode == CALL_MODE_BASIC_TYPE)
+ if (method_cache.flags & METHOD_FLAG_CONST || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function)))
return 0;
else
return 1;
@@ -50,7 +50,7 @@ int VisualScriptFunctionCall::get_output_sequence_port_count() const {
bool VisualScriptFunctionCall::has_input_sequence_port() const {
- if (method_cache.flags & METHOD_FLAG_CONST || call_mode == CALL_MODE_BASIC_TYPE)
+ if (method_cache.flags & METHOD_FLAG_CONST || (call_mode == CALL_MODE_BASIC_TYPE && Variant::is_method_const(basic_type, function)))
return false;
else
return true;
@@ -763,7 +763,7 @@ public:
NodePath node_path;
int input_args;
bool validate;
- bool returns;
+ int returns;
VisualScriptFunctionCall::RPCCallMode rpc_mode;
StringName function;
StringName singleton;
@@ -856,7 +856,13 @@ public:
}
} else if (returns) {
if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) {
- *p_outputs[1] = v.call(function, p_inputs + 1, input_args, r_error);
+ if (returns >= 2) {
+ *p_outputs[1] = v.call(function, p_inputs + 1, input_args, r_error);
+ } else {
+ r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD;
+ r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE";
+ return 0;
+ }
} else {
*p_outputs[0] = v.call(function, p_inputs + 1, input_args, r_error);
}
@@ -1546,7 +1552,7 @@ public:
value = Variant::evaluate(Variant::OP_ADD, value, p_argument);
} break;
case VisualScriptPropertySet::ASSIGN_OP_SUB: {
- value = Variant::evaluate(Variant::OP_SUBSTRACT, value, p_argument);
+ value = Variant::evaluate(Variant::OP_SUBTRACT, value, p_argument);
} break;
case VisualScriptPropertySet::ASSIGN_OP_MUL: {
value = Variant::evaluate(Variant::OP_MULTIPLY, value, p_argument);
diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp
index 7fcd40e993..d96dfebe6c 100644
--- a/modules/visual_script/visual_script_nodes.cpp
+++ b/modules/visual_script/visual_script_nodes.cpp
@@ -3762,7 +3762,7 @@ void register_visual_script_nodes() {
VisualScriptLanguage::singleton->add_register_func("operators/compare/greater_equal", create_op_node<Variant::OP_GREATER_EQUAL>);
//mathematic
VisualScriptLanguage::singleton->add_register_func("operators/math/add", create_op_node<Variant::OP_ADD>);
- VisualScriptLanguage::singleton->add_register_func("operators/math/subtract", create_op_node<Variant::OP_SUBSTRACT>);
+ VisualScriptLanguage::singleton->add_register_func("operators/math/subtract", create_op_node<Variant::OP_SUBTRACT>);
VisualScriptLanguage::singleton->add_register_func("operators/math/multiply", create_op_node<Variant::OP_MULTIPLY>);
VisualScriptLanguage::singleton->add_register_func("operators/math/divide", create_op_node<Variant::OP_DIVIDE>);
VisualScriptLanguage::singleton->add_register_func("operators/math/negate", create_op_node<Variant::OP_NEGATE>);
diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp
index b6d4021ca3..bc033418ba 100644
--- a/modules/visual_script/visual_script_yield_nodes.cpp
+++ b/modules/visual_script/visual_script_yield_nodes.cpp
@@ -82,7 +82,7 @@ String VisualScriptYield::get_text() const {
switch (yield_mode) {
case YIELD_RETURN: return ""; break;
case YIELD_FRAME: return "Next Frame"; break;
- case YIELD_FIXED_FRAME: return "Next Fixed Frame"; break;
+ case YIELD_PHYSICS_FRAME: return "Next Fixed Frame"; break;
case YIELD_WAIT: return rtos(wait_time) + " sec(s)"; break;
}
@@ -122,7 +122,7 @@ public:
ret = STEP_EXIT_FUNCTION_BIT;
break; //return the yield
case VisualScriptYield::YIELD_FRAME: state->connect_to_signal(tree, "idle_frame", Array()); break;
- case VisualScriptYield::YIELD_FIXED_FRAME: state->connect_to_signal(tree, "fixed_frame", Array()); break;
+ case VisualScriptYield::YIELD_PHYSICS_FRAME: state->connect_to_signal(tree, "physics_frame", Array()); break;
case VisualScriptYield::YIELD_WAIT: state->connect_to_signal(tree->create_timer(wait_time).ptr(), "timeout", Array()); break;
}
@@ -190,7 +190,7 @@ void VisualScriptYield::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "wait_time"), "set_wait_time", "get_wait_time");
BIND_ENUM_CONSTANT(YIELD_FRAME);
- BIND_ENUM_CONSTANT(YIELD_FIXED_FRAME);
+ BIND_ENUM_CONSTANT(YIELD_PHYSICS_FRAME);
BIND_ENUM_CONSTANT(YIELD_WAIT);
}
@@ -597,7 +597,7 @@ static Ref<VisualScriptNode> create_yield_signal_node(const String &p_name) {
void register_visual_script_yield_nodes() {
VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_frame", create_yield_node<VisualScriptYield::YIELD_FRAME>);
- VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_fixed_frame", create_yield_node<VisualScriptYield::YIELD_FIXED_FRAME>);
+ VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_physics_frame", create_yield_node<VisualScriptYield::YIELD_PHYSICS_FRAME>);
VisualScriptLanguage::singleton->add_register_func("functions/wait/wait_time", create_yield_node<VisualScriptYield::YIELD_WAIT>);
VisualScriptLanguage::singleton->add_register_func("functions/yield", create_yield_node<VisualScriptYield::YIELD_RETURN>);
diff --git a/modules/visual_script/visual_script_yield_nodes.h b/modules/visual_script/visual_script_yield_nodes.h
index d074962471..4a595a875a 100644
--- a/modules/visual_script/visual_script_yield_nodes.h
+++ b/modules/visual_script/visual_script_yield_nodes.h
@@ -39,7 +39,7 @@ public:
enum YieldMode {
YIELD_RETURN,
YIELD_FRAME,
- YIELD_FIXED_FRAME,
+ YIELD_PHYSICS_FRAME,
YIELD_WAIT
};
diff --git a/modules/vorbis/SCsub b/modules/vorbis/SCsub
index d3e4f7e15a..9d2d0feb92 100644
--- a/modules/vorbis/SCsub
+++ b/modules/vorbis/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_vorbis = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_libvorbis'] != 'no'):
+if env['builtin_libvorbis']:
thirdparty_dir = "#thirdparty/libvorbis/"
thirdparty_sources = [
#"analysis.c",
@@ -42,7 +42,7 @@ if (env['builtin_libvorbis'] != 'no'):
env_vorbis.Append(CPPPATH=[thirdparty_dir])
# also requires libogg
- if (env['builtin_libogg'] != 'no'):
+ if env['builtin_libogg']:
env_vorbis.Append(CPPPATH=["#thirdparty/libogg"])
# Godot source files
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.cpp b/modules/vorbis/audio_stream_ogg_vorbis.cpp
index 6389c286c2..0afb889199 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.cpp
+++ b/modules/vorbis/audio_stream_ogg_vorbis.cpp
@@ -58,7 +58,7 @@ int AudioStreamPlaybackOGGVorbis::_ov_seek_func(void *_f, ogg_int64_t offs, int
fa->seek(offs);
} else if (whence == SEEK_CUR) {
- fa->seek(fa->get_pos() + offs);
+ fa->seek(fa->get_position() + offs);
} else if (whence == SEEK_END) {
fa->seek_end(offs);
@@ -89,7 +89,7 @@ long AudioStreamPlaybackOGGVorbis::_ov_tell_func(void *_f) {
//printf("close %p\n",_f);
FileAccess *fa = (FileAccess *)_f;
- return fa->get_pos();
+ return fa->get_position();
}
int AudioStreamPlaybackOGGVorbis::mix(int16_t *p_bufer, int p_frames) {
@@ -180,7 +180,7 @@ void AudioStreamPlaybackOGGVorbis::play(float p_from) {
frames_mixed = 0;
playing = true;
if (p_from > 0) {
- seek_pos(p_from);
+ seek(p_from);
}
}
@@ -203,7 +203,7 @@ void AudioStreamPlaybackOGGVorbis::stop() {
//_clear();
}
-float AudioStreamPlaybackOGGVorbis::get_pos() const {
+float AudioStreamPlaybackOGGVorbis::get_playback_position() const {
int32_t frames = int32_t(frames_mixed);
if (frames < 0)
@@ -211,7 +211,7 @@ float AudioStreamPlaybackOGGVorbis::get_pos() const {
return double(frames) / stream_srate;
}
-void AudioStreamPlaybackOGGVorbis::seek_pos(float p_time) {
+void AudioStreamPlaybackOGGVorbis::seek(float p_time) {
if (!playing)
return;
diff --git a/modules/vorbis/audio_stream_ogg_vorbis.h b/modules/vorbis/audio_stream_ogg_vorbis.h
index 03b3726b52..929b2651e9 100644
--- a/modules/vorbis/audio_stream_ogg_vorbis.h
+++ b/modules/vorbis/audio_stream_ogg_vorbis.h
@@ -96,8 +96,8 @@ public:
virtual int get_loop_count() const;
- virtual float get_pos() const;
- virtual void seek_pos(float p_time);
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
virtual int get_channels() const { return stream_channels; }
virtual int get_mix_rate() const { return stream_srate; }
diff --git a/modules/webm/SCsub b/modules/webm/SCsub
index 889f5e83aa..2f1a28a54c 100644
--- a/modules/webm/SCsub
+++ b/modules/webm/SCsub
@@ -19,14 +19,14 @@ env_webm.add_source_files(env.modules_sources, thirdparty_libsimplewebm_sources)
env_webm.Append(CPPPATH=[thirdparty_libsimplewebm_dir, thirdparty_libsimplewebm_dir + "libwebm/"])
# also requires libogg, libvorbis and libopus
-if (env['builtin_libogg'] != 'no'):
+if env['builtin_libogg']:
env_webm.Append(CPPPATH=["#thirdparty/libogg"])
-if (env['builtin_libvorbis'] != 'no'):
+if env['builtin_libvorbis']:
env_webm.Append(CPPPATH=["#thirdparty/libvorbis"])
-if (env['builtin_opus'] != 'no'):
+if env['builtin_opus']:
env_webm.Append(CPPPATH=["#thirdparty/opus"])
-if (env['builtin_libvpx'] != 'no'):
+if env['builtin_libvpx']:
Export('env_webm')
SConscript("libvpx/SCsub")
diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub
index 0ee2ed45b8..fd8d762a5e 100644
--- a/modules/webm/libvpx/SCsub
+++ b/modules/webm/libvpx/SCsub
@@ -265,7 +265,7 @@ if env["platform"] == 'uwp':
else:
import platform
is_x11_or_server_arm = ((env["platform"] == 'x11' or env["platform"] == 'server') and platform.machine().startswith('arm'))
- is_ios_x86 = (env["platform"] == 'iphone' and env["ios_sim"] == "yes")
+ is_ios_x86 = (env["platform"] == 'iphone' and env["ios_sim"])
is_android_x86 = (env["platform"] == 'android' and env["android_arch"] == 'x86')
if is_android_x86:
cpu_bits = '32'
diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp
index 0178ebab84..2ec6b27471 100644
--- a/modules/webm/video_stream_webm.cpp
+++ b/modules/webm/video_stream_webm.cpp
@@ -59,7 +59,7 @@ public:
if (file) {
- if (file->get_pos() != (size_t)pos)
+ if (file->get_position() != (size_t)pos)
file->seek(pos);
if (file->get_buffer(buf, len) == len)
return 0;
@@ -204,11 +204,11 @@ float VideoStreamPlaybackWebm::get_length() const {
return 0.0f;
}
-float VideoStreamPlaybackWebm::get_pos() const {
+float VideoStreamPlaybackWebm::get_playback_position() const {
return video_pos;
}
-void VideoStreamPlaybackWebm::seek_pos(float p_time) {
+void VideoStreamPlaybackWebm::seek(float p_time) {
//Not implemented
}
diff --git a/modules/webm/video_stream_webm.h b/modules/webm/video_stream_webm.h
index 9a331849be..fc0720967a 100644
--- a/modules/webm/video_stream_webm.h
+++ b/modules/webm/video_stream_webm.h
@@ -81,8 +81,8 @@ public:
virtual float get_length() const;
- virtual float get_pos() const;
- virtual void seek_pos(float p_time);
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
virtual void set_audio_track(int p_idx);
diff --git a/modules/webp/SCsub b/modules/webp/SCsub
index aa3486a2c5..f9295fed47 100644
--- a/modules/webp/SCsub
+++ b/modules/webp/SCsub
@@ -6,7 +6,7 @@ Import('env_modules')
env_webp = env_modules.Clone()
# Thirdparty source files
-if (env['builtin_libwebp'] != 'no'):
+if env['builtin_libwebp']:
thirdparty_dir = "#thirdparty/libwebp/"
thirdparty_sources = [
"dec/alpha_dec.c",
diff --git a/platform/android/AndroidManifest.xml.template b/platform/android/AndroidManifest.xml.template
index be5afb406a..9d8eb951c4 100644
--- a/platform/android/AndroidManifest.xml.template
+++ b/platform/android/AndroidManifest.xml.template
@@ -17,7 +17,7 @@
android:launchMode="singleTask"
android:screenOrientation="landscape"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize">
-
+
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -26,7 +26,7 @@
<service android:name="org.godotengine.godot.GodotDownloaderService" />
-
+
$$ADD_APPLICATION_CHUNKS$$
@@ -200,6 +200,6 @@ $$ADD_PERMISSION_CHUNKS$$
<uses-permission android:name="godot.custom.18"/>
<uses-permission android:name="godot.custom.19"/>
-<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="23"/>
-
-</manifest>
+<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="23"/>
+
+</manifest>
diff --git a/platform/android/SCsub b/platform/android/SCsub
index 87e7ee4747..e9a370869f 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -73,7 +73,7 @@ for x in env.android_gradle_plugins:
gradle_classpath = ""
for x in env.android_gradle_classpath:
gradle_classpath += "\t\tclasspath \"" + x + "\"\n"
-
+
gradle_res_dirs_text = ""
for x in env.android_res_dirs:
@@ -93,13 +93,13 @@ gradle_asset_dirs_text = ""
gradle_default_config_text = ""
-minSdk = 14
+minSdk = 18
targetSdk = 23
for x in env.android_default_config:
- if x.startswith("minSdkVersion") and int(x.split(" ")[-1]) < minSdk:
+ if x.startswith("minSdkVersion") and int(x.split(" ")[-1]) < minSdk:
x = "minSdkVersion " + str(minSdk)
- if x.startswith("targetSdkVersion") and int(x.split(" ")[-1]) > targetSdk:
+ if x.startswith("targetSdkVersion") and int(x.split(" ")[-1]) > targetSdk:
x = "targetSdkVersion " + str(targetSdk)
gradle_default_config_text += x + "\n\t\t"
diff --git a/platform/android/detect.py b/platform/android/detect.py
index c1ac54c587..13fc4ee810 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -18,20 +18,21 @@ def can_build():
def get_opts():
+ from SCons.Variables import BoolVariable, EnumVariable
return [
('ANDROID_NDK_ROOT', 'Path to the Android NDK', os.environ.get("ANDROID_NDK_ROOT", 0)),
('ndk_platform', 'Target platform (android-<api>, e.g. "android-18")', "android-18"),
- ('android_arch', 'Target architecture (armv7/armv6/arm64v8/x86)', "armv7"),
- ('android_neon', 'Enable NEON support (armv7 only)', "yes"),
- ('android_stl', 'Enable Android STL support (for modules)', "no")
+ EnumVariable('android_arch', 'Target architecture', "armv7", ('armv7', 'armv6', 'arm64v8', 'x86')),
+ BoolVariable('android_neon', 'Enable NEON support (armv7 only)', True),
+ BoolVariable('android_stl', 'Enable Android STL support (for modules)', False),
]
def get_flags():
return [
- ('tools', 'no'),
+ ('tools', False),
]
@@ -93,7 +94,7 @@ def configure(env):
env['android_arch'] = 'armv7'
neon_text = ""
- if env["android_arch"] == "armv7" and env['android_neon'] == 'yes':
+ if env["android_arch"] == "armv7" and env['android_neon']:
neon_text = " (with NEON)"
print("Building for Android (" + env['android_arch'] + ")" + neon_text)
@@ -117,7 +118,7 @@ def configure(env):
target_subpath = "arm-linux-androideabi-4.9"
abi_subpath = "arm-linux-androideabi"
arch_subpath = "armeabi-v7a"
- if env['android_neon'] == 'yes':
+ if env['android_neon']:
env.extra_suffix = ".armv7.neon" + env.extra_suffix
else:
env.extra_suffix = ".armv7" + env.extra_suffix
@@ -199,7 +200,7 @@ def configure(env):
elif env["android_arch"] == "armv7":
target_opts = ['-target', 'armv7-none-linux-androideabi']
env.Append(CPPFLAGS='-D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -march=armv7-a -mfloat-abi=softfp'.split())
- if env['android_neon'] == 'yes':
+ if env['android_neon']:
env['neon_enabled'] = True
env.Append(CPPFLAGS=['-mfpu=neon', '-D__ARM_NEON__'])
else:
@@ -213,7 +214,7 @@ def configure(env):
env.Append(CPPFLAGS=target_opts)
env.Append(CPPFLAGS=common_opts)
- if (env['android_stl'] == 'yes'):
+ if env['android_stl']:
env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/gnu-libstdc++/4.9/include"])
env.Append(CPPPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/gnu-libstdc++/4.9/libs/" + arch_subpath + "/include"])
env.Append(LIBPATH=[env["ANDROID_NDK_ROOT"] + "/sources/cxx-stl/gnu-libstdc++/4.9/libs/" + arch_subpath])
@@ -243,7 +244,7 @@ def configure(env):
env.Append(LIBS=['OpenSLES', 'EGL', 'GLESv3', 'android', 'log', 'z', 'dl'])
# TODO: Move that to opus module's config
- if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"):
+ if 'module_opus_enabled' in env and env['module_opus_enabled']:
if (env["android_arch"] == "armv6" or env["android_arch"] == "armv7"):
env.Append(CFLAGS=["-DOPUS_ARM_OPT"])
env.opus_fixed_point = "yes"
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index f207b81b4b..0fdf9002d7 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -95,7 +95,7 @@ void FileAccessAndroid::seek_end(int64_t p_position) {
pos = len + p_position;
}
-size_t FileAccessAndroid::get_pos() const {
+size_t FileAccessAndroid::get_position() const {
return pos;
}
@@ -146,6 +146,11 @@ Error FileAccessAndroid::get_error() const {
return eof ? ERR_FILE_EOF : OK; //not sure what else it may happen
}
+void FileAccessAndroid::flush() {
+
+ ERR_FAIL();
+}
+
void FileAccessAndroid::store_8(uint8_t p_dest) {
ERR_FAIL();
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index c2ce2b0bfe..c8fedbe684 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -53,7 +53,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -63,6 +63,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists
diff --git a/platform/android/file_access_jandroid.cpp b/platform/android/file_access_jandroid.cpp
index ad855c790d..980afd8f46 100644
--- a/platform/android/file_access_jandroid.cpp
+++ b/platform/android/file_access_jandroid.cpp
@@ -106,7 +106,7 @@ void FileAccessJAndroid::seek_end(int64_t p_position) {
seek(get_len());
}
-size_t FileAccessJAndroid::get_pos() const {
+size_t FileAccessJAndroid::get_position() const {
JNIEnv *env = ThreadAndroid::get_env();
ERR_FAIL_COND_V(!is_open(), 0);
@@ -157,6 +157,9 @@ Error FileAccessJAndroid::get_error() const {
return OK;
}
+void FileAccessJAndroid::flush() {
+}
+
void FileAccessJAndroid::store_8(uint8_t p_dest) {
}
diff --git a/platform/android/file_access_jandroid.h b/platform/android/file_access_jandroid.h
index 8060312182..368d2c98fa 100644
--- a/platform/android/file_access_jandroid.h
+++ b/platform/android/file_access_jandroid.h
@@ -57,7 +57,7 @@ public:
virtual void seek(size_t p_position); ///< seek to a given position
virtual void seek_end(int64_t p_position = 0); ///< seek from the end of file
- virtual size_t get_pos() const; ///< get position in the file
+ virtual size_t get_position() const; ///< get position in the file
virtual size_t get_len() const; ///< get size of the file
virtual bool eof_reached() const; ///< reading passed EOF
@@ -67,6 +67,7 @@ public:
virtual Error get_error() const; ///< get last error
+ virtual void flush();
virtual void store_8(uint8_t p_dest); ///< store a byte
virtual bool file_exists(const String &p_path); ///< return true if a file exists
diff --git a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
index c9532a5d01..3fc8c48397 100644
--- a/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
+++ b/platform/android/java/src/org/godotengine/godot/utils/CustomSSLSocketFactory.java
@@ -36,12 +36,9 @@ import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
+import javax.net.ssl.TrustManagerFactory;
import org.apache.http.conn.ssl.SSLSocketFactory;
@@ -56,19 +53,10 @@ public class CustomSSLSocketFactory extends SSLSocketFactory {
public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
super(truststore);
- TrustManager tm = new X509TrustManager() {
- public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- }
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
+ tmf.init(truststore);
- public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
- }
-
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- };
-
- sslContext.init(null, new TrustManager[] { tm }, null);
+ sslContext.init(null, tmf.getTrustManagers(), null);
}
@Override
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 1de2608b9e..0eb14f6af3 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -47,6 +47,15 @@
#include "file_access_jandroid.h"
#endif
+class AndroidLogger : public Logger {
+public:
+ virtual void logv(const char *p_format, va_list p_list, bool p_err) {
+ __android_log_vprint(p_err ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "godot", p_format, p_list);
+ }
+
+ virtual ~AndroidLogger() {}
+};
+
int OS_Android::get_video_driver_count() const {
return 1;
@@ -111,6 +120,13 @@ void OS_Android::initialize_core() {
#endif
}
+void OS_Android::initialize_logger() {
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(AndroidLogger));
+ loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
+ _set_logger(memnew(CompositeLogger(loggers)));
+}
+
void OS_Android::set_opengl_extensions(const char *p_gl_extensions) {
ERR_FAIL_COND(!p_gl_extensions);
@@ -137,12 +153,7 @@ void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int
visual_server->init();
// visual_server->cursor_set_visible(false, 0);
- AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
-
- if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
-
- ERR_PRINT("Initializing audio failed.");
- }
+ AudioDriverManager::initialize(p_audio_driver);
physics_server = memnew(PhysicsServerSW);
physics_server->init();
@@ -167,23 +178,9 @@ void OS_Android::delete_main_loop() {
}
void OS_Android::finalize() {
-
memdelete(input);
}
-void OS_Android::vprint(const char *p_format, va_list p_list, bool p_stderr) {
-
- __android_log_vprint(p_stderr ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO, "godot", p_format, p_list);
-}
-
-void OS_Android::print(const char *p_format, ...) {
-
- va_list argp;
- va_start(argp, p_format);
- __android_log_vprint(ANDROID_LOG_INFO, "godot", p_format, argp);
- va_end(argp);
-}
-
void OS_Android::alert(const String &p_alert, const String &p_title) {
//print("ALERT: %s\n", p_alert.utf8().get_data());
@@ -742,6 +739,8 @@ OS_Android::OS_Android(GFXInitFunc p_gfx_init_func, void *p_gfx_init_ud, OpenURI
set_keep_screen_on_func = p_set_keep_screen_on_func;
alert_func = p_alert_func;
use_reload_hooks = false;
+
+ _set_logger(memnew(AndroidLogger));
}
OS_Android::~OS_Android() {
diff --git a/platform/android/os_android.h b/platform/android/os_android.h
index 119c14bff3..a614bb8067 100644
--- a/platform/android/os_android.h
+++ b/platform/android/os_android.h
@@ -149,6 +149,7 @@ public:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
+ virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -161,8 +162,6 @@ public:
static OS *get_singleton();
- virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
- virtual void print(const char *p_format, ...);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual void set_mouse_show(bool p_show);
diff --git a/platform/haiku/detect.py b/platform/haiku/detect.py
index c0e003a3d2..50f9783dd2 100644
--- a/platform/haiku/detect.py
+++ b/platform/haiku/detect.py
@@ -19,9 +19,10 @@ def can_build():
def get_opts():
+ from SCons.Variables import EnumVariable
return [
- ('debug_release', 'Add debug symbols to release version', 'no')
+ EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')),
]
@@ -36,16 +37,21 @@ def configure(env):
## Build type
if (env["target"] == "release"):
- if (env["debug_release"] == "yes"):
+ env.Prepend(CCFLAGS=['-O3', '-ffast-math'])
+ if (env["debug_symbols"] == "yes"):
+ env.Prepend(CCFLAGS=['-g1'])
+ if (env["debug_symbols"] == "full"):
env.Prepend(CCFLAGS=['-g2'])
- else:
- env.Prepend(CCFLAGS=['-O3', '-ffast-math'])
elif (env["target"] == "release_debug"):
env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED'])
+ if (env["debug_symbols"] == "yes"):
+ env.Prepend(CCFLAGS=['-g1'])
+ if (env["debug_symbols"] == "full"):
+ env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "debug"):
- env.Prepend(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Prepend(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
## Architecture
diff --git a/platform/haiku/haiku_direct_window.cpp b/platform/haiku/haiku_direct_window.cpp
index 572df493ff..24a8a4b17b 100644
--- a/platform/haiku/haiku_direct_window.cpp
+++ b/platform/haiku/haiku_direct_window.cpp
@@ -157,8 +157,8 @@ void HaikuDirectWindow::HandleMouseButton(BMessage *message) {
mouse_event.mouse_button.mod = GetKeyModifierState(modifiers);
mouse_event->get_button_mask() = GetMouseButtonState(buttons);
- mouse_event->get_pos().x = where.x;
- mouse_event->get_pos().y = where.y;
+ mouse_event->get_position().x = where.x;
+ mouse_event->get_position().y = where.y;
mouse_event.mouse_button.global_x = where.x;
mouse_event.mouse_button.global_y = where.y;
@@ -242,8 +242,8 @@ void HaikuDirectWindow::HandleMouseWheelChanged(BMessage *message) {
mouse_event->get_button_index() = wheel_delta_y < 0 ? 4 : 5;
mouse_event.mouse_button.mod = GetKeyModifierState(last_key_modifier_state);
mouse_event->get_button_mask() = last_button_mask;
- mouse_event->get_pos().x = last_mouse_position.x;
- mouse_event->get_pos().y = last_mouse_position.y;
+ mouse_event->get_position().x = last_mouse_position.x;
+ mouse_event->get_position().y = last_mouse_position.y;
mouse_event.mouse_button.global_x = last_mouse_position.x;
mouse_event.mouse_button.global_y = last_mouse_position.y;
diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp
index de2f79a0ac..9f2f88bb4e 100644
--- a/platform/haiku/os_haiku.cpp
+++ b/platform/haiku/os_haiku.cpp
@@ -137,11 +137,7 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_
//physics_2d_server = Physics2DServerWrapMT::init_server<Physics2DServerSW>();
physics_2d_server->init();
- AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
-
- if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
- ERR_PRINT("Initializing audio failed.");
- }
+ AudioDriverManager::initialize(p_audio_driver);
power_manager = memnew(PowerHaiku);
}
diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 998d0a3f0d..61798c5f87 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -5,7 +5,6 @@ Import('env')
iphone_lib = [
'os_iphone.cpp',
- 'audio_driver_iphone.cpp',
'sem_iphone.cpp',
'gl_view.mm',
'main.m',
diff --git a/platform/iphone/app_delegate.mm b/platform/iphone/app_delegate.mm
index c7b65b476b..da6ceacdac 100644
--- a/platform/iphone/app_delegate.mm
+++ b/platform/iphone/app_delegate.mm
@@ -29,8 +29,8 @@
/*************************************************************************/
#import "app_delegate.h"
-#include "audio_driver_iphone.h"
#include "core/project_settings.h"
+#include "drivers/coreaudio/audio_driver_coreaudio.h"
#import "gl_view.h"
#include "main/main.h"
#include "os_iphone.h"
@@ -736,8 +736,8 @@ static int frame_count = 0;
};
// Fixed audio can not resume if it is interrupted cause by an incoming phone call
- if (AudioDriverIphone::get_singleton() != NULL)
- AudioDriverIphone::get_singleton()->start();
+ if (AudioDriverCoreAudio::get_singleton() != NULL)
+ AudioDriverCoreAudio::get_singleton()->start();
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
diff --git a/platform/iphone/audio_driver_iphone.cpp b/platform/iphone/audio_driver_iphone.cpp
deleted file mode 100644
index dbc5bdb654..0000000000
--- a/platform/iphone/audio_driver_iphone.cpp
+++ /dev/null
@@ -1,187 +0,0 @@
-/*************************************************************************/
-/* audio_driver_iphone.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-#include "audio_driver_iphone.h"
-
-Error AudioDriverIphone::init() {
-
- active = false;
- channels = 2;
-
- AudioStreamBasicDescription strdesc;
- strdesc.mFormatID = kAudioFormatLinearPCM;
- strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
- strdesc.mChannelsPerFrame = channels;
- strdesc.mSampleRate = 44100;
- strdesc.mFramesPerPacket = 1;
- strdesc.mBitsPerChannel = 16;
- strdesc.mBytesPerFrame =
- strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
- strdesc.mBytesPerPacket =
- strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
-
- AURenderCallbackStruct callback;
- AudioComponentDescription desc;
- const AudioUnitElement output_bus = 0;
- const AudioUnitElement bus = output_bus;
- const AudioUnitScope scope = kAudioUnitScope_Input;
-
- zeromem(&desc, sizeof(desc));
- desc.componentType = kAudioUnitType_Output;
- desc.componentSubType = kAudioUnitSubType_RemoteIO; /* !!! FIXME: ? */
- AudioComponent comp = AudioComponentFindNext(NULL, &desc);
- desc.componentManufacturer = kAudioUnitManufacturer_Apple;
-
- OSStatus result = AudioComponentInstanceNew(comp, &audio_unit);
- ERR_FAIL_COND_V(result != noErr, FAILED);
- ERR_FAIL_COND_V(comp == NULL, FAILED);
-
- result = AudioUnitSetProperty(audio_unit,
- kAudioUnitProperty_StreamFormat,
- scope, bus, &strdesc, sizeof(strdesc));
- ERR_FAIL_COND_V(result != noErr, FAILED);
-
- zeromem(&callback, sizeof(AURenderCallbackStruct));
- callback.inputProc = &AudioDriverIphone::output_callback;
- callback.inputProcRefCon = this;
- result = AudioUnitSetProperty(audio_unit,
- kAudioUnitProperty_SetRenderCallback,
- scope, bus, &callback, sizeof(callback));
- ERR_FAIL_COND_V(result != noErr, FAILED);
-
- result = AudioUnitInitialize(audio_unit);
- ERR_FAIL_COND_V(result != noErr, FAILED);
-
- result = AudioOutputUnitStart(audio_unit);
- ERR_FAIL_COND_V(result != noErr, FAILED);
-
- const int samples = 1024;
- samples_in = memnew_arr(int32_t, samples); // whatever
- buffer_frames = samples / channels;
-
- return FAILED;
-};
-
-OSStatus AudioDriverIphone::output_callback(void *inRefCon,
- AudioUnitRenderActionFlags *ioActionFlags,
- const AudioTimeStamp *inTimeStamp,
- UInt32 inBusNumber, UInt32 inNumberFrames,
- AudioBufferList *ioData) {
-
- AudioBuffer *abuf;
- AudioDriverIphone *ad = (AudioDriverIphone *)inRefCon;
-
- bool mix = true;
-
- if (!ad->active)
- mix = false;
- else if (ad->mutex) {
- mix = ad->mutex->try_lock() == OK;
- };
-
- if (!mix) {
- for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
- abuf = &ioData->mBuffers[i];
- zeromem(abuf->mData, abuf->mDataByteSize);
- };
- return 0;
- };
-
- int frames_left;
-
- for (unsigned int i = 0; i < ioData->mNumberBuffers; i++) {
-
- abuf = &ioData->mBuffers[i];
- frames_left = inNumberFrames;
- int16_t *out = (int16_t *)abuf->mData;
-
- while (frames_left) {
-
- int frames = MIN(frames_left, ad->buffer_frames);
- //ad->lock();
- ad->audio_server_process(frames, ad->samples_in);
- //ad->unlock();
-
- for (int i = 0; i < frames * ad->channels; i++) {
-
- out[i] = ad->samples_in[i] >> 16;
- }
-
- frames_left -= frames;
- out += frames * ad->channels;
- };
- };
-
- if (ad->mutex)
- ad->mutex->unlock();
-
- return 0;
-};
-
-void AudioDriverIphone::start() {
- active = true;
- // Resume audio
- // iOS audio-thread stoped if it is interrupted cause by an incoming phone call
- // Use AudioOutputUnitStart to re-create audio-thread
- OSStatus result = AudioOutputUnitStart(audio_unit);
- ERR_FAIL_COND(result != noErr);
-};
-
-int AudioDriverIphone::get_mix_rate() const {
- return 44100;
-};
-
-AudioDriver::SpeakerMode AudioDriverIphone::get_speaker_mode() const {
- return SPEAKER_MODE_STEREO;
-};
-
-void AudioDriverIphone::lock() {
-
- if (active && mutex)
- mutex->lock();
-};
-
-void AudioDriverIphone::unlock() {
- if (active && mutex)
- mutex->unlock();
-};
-
-void AudioDriverIphone::finish() {
-
- memdelete_arr(samples_in);
-};
-
-AudioDriverIphone::AudioDriverIphone() {
-
- mutex = Mutex::create(); //NULL;
-};
-
-AudioDriverIphone::~AudioDriverIphone(){
-
-};
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 0b81422fa3..00d8a59f74 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -20,24 +20,24 @@ def can_build():
def get_opts():
-
+ from SCons.Variables import BoolVariable
return [
('IPHONEPLATFORM', 'Name of the iPhone platform', 'iPhoneOS'),
('IPHONEPATH', 'Path to iPhone toolchain', '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain'),
('IPHONESDK', 'Path to the iPhone SDK', '/Applications/Xcode.app/Contents/Developer/Platforms/${IPHONEPLATFORM}.platform/Developer/SDKs/${IPHONEPLATFORM}.sdk/'),
- ('game_center', 'Support for game center', 'yes'),
- ('store_kit', 'Support for in-app store', 'yes'),
- ('icloud', 'Support for iCloud', 'yes'),
- ('ios_exceptions', 'Enable exceptions', 'no'),
+ BoolVariable('game_center', 'Support for game center', True),
+ BoolVariable('store_kit', 'Support for in-app store', True),
+ BoolVariable('icloud', 'Support for iCloud', True),
+ BoolVariable('ios_exceptions', 'Enable exceptions', False),
('ios_triple', 'Triple for ios toolchain', ''),
- ('ios_sim', 'Build simulator binary', 'no'),
+ BoolVariable('ios_sim', 'Build simulator binary', False),
]
def get_flags():
return [
- ('tools', 'no'),
+ ('tools', False),
]
@@ -58,7 +58,7 @@ def configure(env):
## Architecture
- if (env["ios_sim"] == "yes" or env["arch"] == "x86"): # i386, simulator
+ if env["ios_sim"] or env["arch"] == "x86": # i386, simulator
env["arch"] = "x86"
env["bits"] = "32"
elif (env["arch"] == "arm" or env["arch"] == "arm32" or env["arch"] == "armv7" or env["bits"] == "32"): # arm
@@ -91,7 +91,7 @@ def configure(env):
env.Append(CPPFLAGS=['-DNEED_LONG_INT'])
env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON'])
- if env['ios_exceptions'] == 'yes':
+ if env['ios_exceptions']:
env.Append(CPPFLAGS=['-fexceptions'])
else:
env.Append(CPPFLAGS=['-fno-exceptions'])
@@ -129,15 +129,15 @@ def configure(env):
])
# Feature options
- if env['game_center'] == 'yes':
+ if env['game_center']:
env.Append(CPPFLAGS=['-DGAME_CENTER_ENABLED'])
env.Append(LINKFLAGS=['-framework', 'GameKit'])
- if env['store_kit'] == 'yes':
+ if env['store_kit']:
env.Append(CPPFLAGS=['-DSTOREKIT_ENABLED'])
env.Append(LINKFLAGS=['-framework', 'StoreKit'])
- if env['icloud'] == 'yes':
+ if env['icloud']:
env.Append(CPPFLAGS=['-DICLOUD_ENABLED'])
env.Append(CPPPATH=['$IPHONESDK/usr/include',
@@ -148,10 +148,10 @@ def configure(env):
env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'
env.Append(CPPPATH=['#platform/iphone'])
- env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DMPC_FIXED_POINT'])
+ env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DMPC_FIXED_POINT', '-DCOREAUDIO_ENABLED'])
# TODO: Move that to opus module's config
- if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"):
+ if 'module_opus_enabled' in env and env['module_opus_enabled']:
env.opus_fixed_point = "yes"
if (env["arch"] == "arm"):
env.Append(CFLAGS=["-DOPUS_ARM_OPT"])
diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp
index 8bb7f23ead..c91781ce1d 100644
--- a/platform/iphone/export/export.cpp
+++ b/platform/iphone/export/export.cpp
@@ -52,7 +52,14 @@ class EditorExportPlatformIOS : public EditorExportPlatform {
Ref<ImageTexture> logo;
- void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary);
+ typedef Error (*FileHandler)(String p_file, void *p_userdata);
+ static Error _walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata);
+ static Error _codesign(String p_file, void *p_userdata);
+
+ void _fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary, bool p_debug);
+ static Error _export_dylibs(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total);
+ Error _export_loading_screens(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir);
+ Error _export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir);
protected:
virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
@@ -63,7 +70,7 @@ public:
virtual String get_os_name() const { return "iOS"; }
virtual Ref<Texture> get_logo() const { return logo; }
- virtual String get_binary_extension() const { return "xcodeproj"; }
+ virtual String get_binary_extension() const { return "ipa"; }
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
@@ -96,16 +103,44 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/debug", PROPERTY_HINT_GLOBAL_FILE, "zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_package/release", PROPERTY_HINT_GLOBAL_FILE, "zip"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), ""));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug"), "iPhone Developer"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release"), "iPhone Distribution"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_release", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 0));
+
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
- // r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "png"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier"), "org.godotengine.iosgame"));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "godotiosgame"));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), "????"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/bits_mode", PROPERTY_HINT_ENUM, "Fat (32 & 64 bits),64 bits,32 bits"), 1));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/iphone_120x120", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPhone/iPod Touch with retina display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "required_icons/ipad_76x76", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPad
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/iphone_180x180", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPhone with retina HD display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/ipad_152x152", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPad with retina display
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/ipad_167x167", PROPERTY_HINT_FILE, "png"), "")); // Home screen on iPad Pro
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_40x40", PROPERTY_HINT_FILE, "png"), "")); // Spotlight
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "optional_icons/spotlight_80x80", PROPERTY_HINT_FILE, "png"), "")); // Spotlight on devices with retina display
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "landscape_launch_screens/iphone_2208x1242", PROPERTY_HINT_FILE, "png"), "")); // iPhone 6 Plus, 6s Plus, 7 Plus
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "landscape_launch_screens/ipad_2732x2048", PROPERTY_HINT_FILE, "png"), "")); // 12.9-inch iPad Pro
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "landscape_launch_screens/ipad_2048x1536", PROPERTY_HINT_FILE, "png"), "")); // Other iPads
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "portrait_launch_screens/iphone_640x1136", PROPERTY_HINT_FILE, "png"), "")); // iPhone 5, 5s, SE
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "portrait_launch_screens/iphone_750x1334", PROPERTY_HINT_FILE, "png"), "")); // iPhone 6, 6s, 7
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "portrait_launch_screens/iphone_1242x2208", PROPERTY_HINT_FILE, "png"), "")); // iPhone 6 Plus, 6s Plus, 7 Plus
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "portrait_launch_screens/ipad_2048x2732", PROPERTY_HINT_FILE, "png"), "")); // 12.9-inch iPad Pro
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "portrait_launch_screens/ipad_1536x2048", PROPERTY_HINT_FILE, "png"), "")); // Other iPads
+
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false));
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), true));
@@ -113,11 +148,17 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options)
/* probably need some more info */
}
-void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary) {
-
+void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &pfile, const String &p_name, const String &p_binary, bool p_debug) {
+ static const String export_method_string[] = {
+ "app-store",
+ "development",
+ "ad-hoc",
+ "enterprise"
+ };
String str;
String strnew;
str.parse_utf8((const char *)pfile.ptr(), pfile.size());
+ print_line(str);
Vector<String> lines = str.split("\n");
for (int i = 0; i < lines.size(); i++) {
if (lines[i].find("$binary") != -1) {
@@ -136,6 +177,19 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
} else if (lines[i].find("$copyright") != -1) {
strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
+ } else if (lines[i].find("$team_id") != -1) {
+ strnew += lines[i].replace("$team_id", p_preset->get("application/app_store_team_id")) + "\n";
+ } else if (lines[i].find("$export_method") != -1) {
+ int export_method = p_preset->get(p_debug ? "application/export_method_debug" : "application/export_method_release");
+ strnew += lines[i].replace("$export_method", export_method_string[export_method]) + "\n";
+ } else if (lines[i].find("$provisioning_profile_uuid_release") != -1) {
+ strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n";
+ } else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) {
+ strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n";
+ } else if (lines[i].find("$code_sign_identity_debug") != -1) {
+ strnew += lines[i].replace("$code_sign_identity_debug", p_preset->get("application/code_sign_identity_debug")) + "\n";
+ } else if (lines[i].find("$code_sign_identity_release") != -1) {
+ strnew += lines[i].replace("$code_sign_identity_release", p_preset->get("application/code_sign_identity_release")) + "\n";
} else {
strnew += lines[i] + "\n";
}
@@ -150,12 +204,214 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_
}
}
+Error EditorExportPlatformIOS::_export_dylibs(void *p_userdata, const String &p_path, const Vector<uint8_t> &p_data, int p_file, int p_total) {
+ if (!p_path.ends_with(".dylib")) return OK;
+ const String &dest_dir = *(String *)p_userdata;
+ String rel_path = p_path.replace_first("res://", "dylibs/");
+ DirAccess *dest_dir_access = DirAccess::open(dest_dir);
+ ERR_FAIL_COND_V(!dest_dir_access, ERR_CANT_OPEN);
+
+ String base_dir = rel_path.get_base_dir();
+ Error make_dir_err = OK;
+ if (!dest_dir_access->dir_exists(base_dir)) {
+ make_dir_err = dest_dir_access->make_dir_recursive(base_dir);
+ }
+ if (make_dir_err != OK) {
+ memdelete(dest_dir_access);
+ return make_dir_err;
+ }
+
+ Error copy_err = dest_dir_access->copy(p_path, dest_dir + rel_path);
+ memdelete(dest_dir_access);
+
+ return copy_err;
+}
+
+struct IconInfo {
+ const char *preset_key;
+ const char *idiom;
+ const char *export_name;
+ const char *actual_size_side;
+ const char *scale;
+ const char *unscaled_size;
+ bool is_required;
+};
+
+static const IconInfo icon_infos[] = {
+ { "required_icons/iphone_120x120", "iphone", "Icon-120.png", "120", "2x", "60x60", true },
+ { "required_icons/iphone_120x120", "iphone", "Icon-120.png", "120", "3x", "40x40", true },
+
+ { "required_icons/ipad_76x76", "ipad", "Icon-76.png", "76", "1x", "76x76", false },
+
+ { "optional_icons/iphone_180x180", "iphone", "Icon-180.png", "180", "3x", "60x60", false },
+
+ { "optional_icons/ipad_152x152", "ipad", "Icon-152.png", "152", "2x", "76x76", false },
+
+ { "optional_icons/ipad_167x167", "ipad", "Icon-167.png", "167", "2x", "83.5x83.5", false },
+
+ { "optional_icons/spotlight_40x40", "ipad", "Icon-40.png", "40", "1x", "40x40", false },
+
+ { "optional_icons/spotlight_80x80", "iphone", "Icon-80.png", "80", "2x", "40x40", false },
+ { "optional_icons/spotlight_80x80", "ipad", "Icon-80.png", "80", "2x", "40x40", false }
+
+};
+
+Error EditorExportPlatformIOS::_export_icons(const Ref<EditorExportPreset> &p_preset, const String &p_iconset_dir) {
+ String json_description = "{\"images\":[";
+ String sizes;
+
+ DirAccess *da = DirAccess::open(p_iconset_dir);
+ ERR_FAIL_COND_V(!da, ERR_CANT_OPEN);
+
+ for (int i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
+ IconInfo info = icon_infos[i];
+ String icon_path = p_preset->get(info.preset_key);
+ if (icon_path.length() == 0) {
+ if (info.is_required) {
+ ERR_PRINT("Required icon is not specified in the preset");
+ return ERR_UNCONFIGURED;
+ }
+ continue;
+ }
+ Error err = da->copy(icon_path, p_iconset_dir + info.export_name);
+ if (err) {
+ memdelete(da);
+ String err_str = String("Failed to export icon: ") + icon_path;
+ ERR_PRINT(err_str.utf8().get_data());
+ return err;
+ }
+ sizes += String(info.actual_size_side) + "\n";
+ if (i > 0) {
+ json_description += ",";
+ }
+ json_description += String("{");
+ json_description += String("\"idiom\":") + "\"" + info.idiom + "\",";
+ json_description += String("\"size\":") + "\"" + info.unscaled_size + "\",";
+ json_description += String("\"scale\":") + "\"" + info.scale + "\",";
+ json_description += String("\"filename\":") + "\"" + info.export_name + "\"";
+ json_description += String("}");
+ }
+ json_description += "]}";
+ memdelete(da);
+
+ FileAccess *json_file = FileAccess::open(p_iconset_dir + "Contents.json", FileAccess::WRITE);
+ ERR_FAIL_COND_V(!json_file, ERR_CANT_CREATE);
+ CharString json_utf8 = json_description.utf8();
+ json_file->store_buffer((const uint8_t *)json_utf8.get_data(), json_utf8.length());
+ memdelete(json_file);
+
+ FileAccess *sizes_file = FileAccess::open(p_iconset_dir + "sizes", FileAccess::WRITE);
+ ERR_FAIL_COND_V(!sizes_file, ERR_CANT_CREATE);
+ CharString sizes_utf8 = sizes.utf8();
+ sizes_file->store_buffer((const uint8_t *)sizes_utf8.get_data(), sizes_utf8.length());
+ memdelete(sizes_file);
+
+ return OK;
+}
+
+struct LoadingScreenInfo {
+ const char *preset_key;
+ const char *export_name;
+};
+
+static const LoadingScreenInfo loading_screen_infos[] = {
+ { "landscape_launch_screens/iphone_2208x1242", "Default-Landscape-736h@3x.png" },
+ { "landscape_launch_screens/ipad_2732x2048", "Default-Landscape-1366h@2x.png" },
+ { "landscape_launch_screens/ipad_2048x1536", "Default-Landscape@2x.png" },
+
+ { "portrait_launch_screens/iphone_640x1136", "Default-568h@2x.png" },
+ { "portrait_launch_screens/iphone_750x1334", "Default-667h@2x.png" },
+ { "portrait_launch_screens/iphone_1242x2208", "Default-Portrait-736h@3x.png" },
+ { "portrait_launch_screens/ipad_2048x2732", "Default-Portrait-1366h@2x.png" },
+ { "portrait_launch_screens/ipad_1536x2048", "Default-Portrait@2x.png" }
+};
+
+Error EditorExportPlatformIOS::_export_loading_screens(const Ref<EditorExportPreset> &p_preset, const String &p_dest_dir) {
+ DirAccess *da = DirAccess::open(p_dest_dir);
+ ERR_FAIL_COND_V(!da, ERR_CANT_OPEN);
+
+ for (int i = 0; i < sizeof(loading_screen_infos) / sizeof(loading_screen_infos[0]); ++i) {
+ LoadingScreenInfo info = loading_screen_infos[i];
+ String loading_screen_file = p_preset->get(info.preset_key);
+ Error err = da->copy(loading_screen_file, p_dest_dir + info.export_name);
+ if (err) {
+ memdelete(da);
+ String err_str = String("Failed to export loading screen: ") + loading_screen_file;
+ ERR_PRINT(err_str.utf8().get_data());
+ return err;
+ }
+ }
+ memdelete(da);
+
+ return OK;
+}
+
+Error EditorExportPlatformIOS::_walk_dir_recursive(DirAccess *p_da, FileHandler p_handler, void *p_userdata) {
+ Vector<String> dirs;
+ String path;
+ String current_dir = p_da->get_current_dir();
+ p_da->list_dir_begin();
+ while ((path = p_da->get_next()).length() != 0) {
+ if (p_da->current_is_dir()) {
+ if (path != "." && path != "..") {
+ dirs.push_back(path);
+ }
+ } else {
+ Error err = p_handler(current_dir + "/" + path, p_userdata);
+ if (err) {
+ p_da->list_dir_end();
+ return err;
+ }
+ }
+ }
+ p_da->list_dir_end();
+
+ for (int i = 0; i < dirs.size(); ++i) {
+ String dir = dirs[i];
+ p_da->change_dir(dir);
+ Error err = _walk_dir_recursive(p_da, p_handler, p_userdata);
+ p_da->change_dir("..");
+ if (err) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+struct CodesignData {
+ const Ref<EditorExportPreset> &preset;
+ bool debug;
+
+ CodesignData(const Ref<EditorExportPreset> &p_preset, bool p_debug)
+ : preset(p_preset), debug(p_debug) {
+ }
+};
+
+Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) {
+ if (p_file.ends_with(".dylib")) {
+ CodesignData *data = (CodesignData *)p_userdata;
+ print_line(String("Signing ") + p_file);
+ List<String> codesign_args;
+ codesign_args.push_back("-f");
+ codesign_args.push_back("-s");
+ codesign_args.push_back(data->preset->get(data->debug ? "application/code_sign_identity_debug" : "application/code_sign_identity_release"));
+ codesign_args.push_back(p_file);
+ return OS::get_singleton()->execute("/usr/bin/codesign", codesign_args, true);
+ }
+ return OK;
+}
+
Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
String src_pkg_name;
String dest_dir = p_path.get_base_dir() + "/";
String binary_name = p_path.get_file().get_basename();
- EditorProgress ep("export", "Exporting for iOS", 3);
+ EditorProgress ep("export", "Exporting for iOS", 5);
+
+ String team_id = p_preset->get("application/app_store_team_id");
+ ERR_EXPLAIN("App Store Team ID not specified - cannot configure the project.");
+ ERR_FAIL_COND_V(team_id.length() == 0, ERR_CANT_OPEN);
if (p_debug)
src_pkg_name = p_preset->get("custom_package/debug");
@@ -206,6 +462,15 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
bool found_binary = false;
int total_size = 0;
+ Set<String> files_to_parse;
+ files_to_parse.insert("godot_ios/godot_ios-Info.plist");
+ files_to_parse.insert("godot_ios.xcodeproj/project.pbxproj");
+ files_to_parse.insert("export_options.plist");
+ files_to_parse.insert("godot_ios.xcodeproj/project.xcworkspace/contents.xcworkspacedata");
+ files_to_parse.insert("godot_ios.xcodeproj/xcshareddata/xcschemes/godot_ios.xcscheme");
+
+ print_line("Unzipping...");
+
while (ret == UNZ_OK) {
bool is_execute = false;
@@ -229,12 +494,9 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
file = file.replace_first("iphone/", "");
- if (file == "godot_ios.xcodeproj/project.pbxproj") {
- print_line("parse pbxproj");
- _fix_config_file(p_preset, data, pkg_name, binary_name);
- } else if (file == "godot_ios/godot_ios-Info.plist") {
- print_line("parse plist");
- _fix_config_file(p_preset, data, pkg_name, binary_name);
+ if (files_to_parse.has(file)) {
+ print_line(String("parse ") + file);
+ _fix_config_file(p_preset, data, pkg_name, binary_name, p_debug);
} else if (file.begins_with("godot.iphone")) {
if (file != binary_to_use) {
ret = unzGoToNextFile(src_pkg_zip);
@@ -264,6 +526,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (dir_err) {
ERR_PRINTS("Can't create '" + dir_name + "'.");
unzClose(src_pkg_zip);
+ memdelete(tmp_app_path);
return ERR_CANT_CREATE;
}
}
@@ -273,6 +536,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!f) {
ERR_PRINTS("Can't write '" + file + "'.");
unzClose(src_pkg_zip);
+ memdelete(tmp_app_path);
return ERR_CANT_CREATE;
};
f->store_buffer(data.ptr(), data.size());
@@ -295,26 +559,79 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p
if (!found_binary) {
ERR_PRINTS("Requested template binary '" + binary_to_use + "' not found. It might be missing from your template archive.");
- unzClose(src_pkg_zip);
+ memdelete(tmp_app_path);
return ERR_FILE_NOT_FOUND;
}
- ep.step("Making PKG", 1);
+ String iconset_dir = dest_dir + binary_name + "/Images.xcassets/AppIcon.appiconset/";
+ Error err = OK;
+ if (!tmp_app_path->dir_exists(iconset_dir)) {
+ Error err = tmp_app_path->make_dir_recursive(iconset_dir);
+ }
+ memdelete(tmp_app_path);
+ if (err)
+ return err;
+
+ err = _export_icons(p_preset, iconset_dir);
+ if (err)
+ return err;
+
+ err = _export_loading_screens(p_preset, dest_dir + binary_name + "/");
+ if (err)
+ return err;
+
+ ep.step("Making .pck", 1);
String pack_path = dest_dir + binary_name + ".pck";
- Error err = save_pack(p_preset, pack_path);
+ err = save_pack(p_preset, pack_path);
+ if (err)
+ return err;
- if (err) {
+ err = export_project_files(p_preset, _export_dylibs, &dest_dir);
+ if (err)
return err;
- }
#ifdef OSX_ENABLED
- /* and open up xcode with our new project.... */
- List<String> args;
- args.push_back(p_path);
- err = OS::get_singleton()->execute("/usr/bin/open", args, false);
+ ep.step("Making .xcarchive", 2);
+ String archive_path = p_path.get_basename() + ".xcarchive";
+ List<String> archive_args;
+ archive_args.push_back("-project");
+ archive_args.push_back(dest_dir + binary_name + ".xcodeproj");
+ archive_args.push_back("-scheme");
+ archive_args.push_back(binary_name);
+ archive_args.push_back("-sdk");
+ archive_args.push_back("iphoneos");
+ archive_args.push_back("-configuration");
+ archive_args.push_back(p_debug ? "Debug" : "Release");
+ archive_args.push_back("-destination");
+ archive_args.push_back("generic/platform=iOS");
+ archive_args.push_back("archive");
+ archive_args.push_back("-archivePath");
+ archive_args.push_back(archive_path);
+ err = OS::get_singleton()->execute("/usr/bin/xcodebuild", archive_args, true);
ERR_FAIL_COND_V(err, err);
+ ep.step("Code-signing dylibs", 3);
+ DirAccess *dylibs_dir = DirAccess::open(archive_path + "/Products/Applications/" + binary_name + ".app/dylibs");
+ ERR_FAIL_COND_V(!dylibs_dir, ERR_CANT_OPEN);
+ CodesignData codesign_data(p_preset, p_debug);
+ err = _walk_dir_recursive(dylibs_dir, _codesign, &codesign_data);
+ memdelete(dylibs_dir);
+ ERR_FAIL_COND_V(err, err);
+
+ ep.step("Making .ipa", 4);
+ List<String> export_args;
+ export_args.push_back("-exportArchive");
+ export_args.push_back("-archivePath");
+ export_args.push_back(archive_path);
+ export_args.push_back("-exportOptionsPlist");
+ export_args.push_back(dest_dir + "export_options.plist");
+ export_args.push_back("-exportPath");
+ export_args.push_back(dest_dir);
+ err = OS::get_singleton()->execute("/usr/bin/xcodebuild", export_args, true);
+ ERR_FAIL_COND_V(err, err);
+#else
+ print_line(".ipa can only be built on macOS. Leaving XCode project without building the package.");
#endif
return OK;
diff --git a/platform/iphone/game_center.mm b/platform/iphone/game_center.mm
index c05bdea005..821ef2a3ab 100644
--- a/platform/iphone/game_center.mm
+++ b/platform/iphone/game_center.mm
@@ -89,6 +89,7 @@ Error GameCenter::connect() {
ret["type"] = "authentication";
if (player.isAuthenticated) {
ret["result"] = "ok";
+ ret["player_id"] = player.playerID;
GameCenter::get_singleton()->connected = true;
} else {
ret["result"] = "error";
diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp
index 0e3eeed114..5009f7d8ae 100644
--- a/platform/iphone/os_iphone.cpp
+++ b/platform/iphone/os_iphone.cpp
@@ -35,13 +35,13 @@
#include "servers/visual/visual_server_raster.h"
//#include "servers/visual/visual_server_wrap_mt.h"
-#include "audio_driver_iphone.h"
#include "main/main.h"
#include "core/io/file_access_pack.h"
#include "core/os/dir_access.h"
#include "core/os/file_access.h"
#include "core/project_settings.h"
+#include "drivers/unix/syslog_logger.h"
#include "sem_iphone.h"
@@ -99,6 +99,13 @@ void OSIPhone::initialize_core() {
SemaphoreIphone::make_default();
};
+void OSIPhone::initialize_logger() {
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(SyslogLogger));
+ loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
+ _set_logger(memnew(CompositeLogger(loggers)));
+}
+
void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) {
supported_orientations = 0;
@@ -124,9 +131,8 @@ void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_
// reset this to what it should be, it will have been set to 0 after visual_server->init() is called
RasterizerStorageGLES3::system_fbo = gl_view_base_fb;
- audio_driver = memnew(AudioDriverIphone);
- audio_driver->set_singleton();
- audio_driver->init();
+ AudioDriverManager::add_driver(&audio_driver);
+ AudioDriverManager::initialize(p_audio_driver);
// init physics servers
physics_server = memnew(PhysicsServerSW);
@@ -570,6 +576,8 @@ OSIPhone::OSIPhone(int width, int height) {
vm.resizable = false;
set_video_mode(vm);
event_count = 0;
+
+ _set_logger(memnew(SyslogLogger));
};
OSIPhone::~OSIPhone() {
diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h
index 475dceebf2..11f4eed5e7 100644
--- a/platform/iphone/os_iphone.h
+++ b/platform/iphone/os_iphone.h
@@ -32,6 +32,7 @@
#ifndef OS_IPHONE_H
#define OS_IPHONE_H
+#include "drivers/coreaudio/audio_driver_coreaudio.h"
#include "drivers/unix/os_unix.h"
#include "os/input.h"
@@ -46,8 +47,6 @@
#include "servers/visual/rasterizer.h"
#include "servers/visual_server.h"
-class AudioDriverIphone;
-
class OSIPhone : public OS_Unix {
public:
@@ -70,7 +69,7 @@ private:
PhysicsServer *physics_server;
Physics2DServer *physics_2d_server;
- AudioDriverIphone *audio_driver;
+ AudioDriverCoreAudio audio_driver;
#ifdef GAME_CENTER_ENABLED
GameCenter *game_center;
@@ -91,6 +90,7 @@ private:
virtual VideoMode get_default_video_mode() const;
+ virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
diff --git a/platform/javascript/SCsub b/platform/javascript/SCsub
index e282041745..f01d9367d2 100644
--- a/platform/javascript/SCsub
+++ b/platform/javascript/SCsub
@@ -29,7 +29,7 @@ zip_dir = target_dir.Dir('.javascript_zip')
zip_files = env.InstallAs(zip_dir.File('godot.html'), '#misc/dist/html/default.html')
implicit_targets = []
-if env['wasm'] == 'yes':
+if env['wasm']:
wasm = target_dir.File(basename + '.wasm')
implicit_targets.append(wasm)
zip_files.append(InstallAs(zip_dir.File('godot.wasm'), wasm))
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index bea8f156af..cc29ad8956 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -17,18 +17,18 @@ def can_build():
def get_opts():
-
+ from SCons.Variables import BoolVariable
return [
- ['wasm', 'Compile to WebAssembly', 'no'],
- ['javascript_eval', 'Enable JavaScript eval interface', 'yes'],
+ BoolVariable('wasm', 'Compile to WebAssembly', False),
+ BoolVariable('javascript_eval', 'Enable JavaScript eval interface', True),
]
def get_flags():
return [
- ('tools', 'no'),
- ('module_theora_enabled', 'no'),
+ ('tools', False),
+ ('module_theora_enabled', False),
]
@@ -95,7 +95,7 @@ def configure(env):
# These flags help keep the file size down
env.Append(CPPFLAGS=["-fno-exceptions", '-DNO_SAFE_CAST', '-fno-rtti'])
- if env['javascript_eval'] == 'yes':
+ if env['javascript_eval']:
env.Append(CPPFLAGS=['-DJAVASCRIPT_EVAL_ENABLED'])
## Link flags
@@ -103,7 +103,7 @@ def configure(env):
env.Append(LINKFLAGS=['-s', 'EXTRA_EXPORTED_RUNTIME_METHODS="[\'FS\']"'])
env.Append(LINKFLAGS=['-s', 'USE_WEBGL2=1'])
- if (env['wasm'] == 'yes'):
+ if env['wasm']:
env.Append(LINKFLAGS=['-s', 'BINARYEN=1'])
# In contrast to asm.js, enabling memory growth on WebAssembly has no
# major performance impact, and causes only a negligible increase in
@@ -116,5 +116,5 @@ def configure(env):
env.Append(LINKFLAGS=['--memory-init-file', '1'])
# TODO: Move that to opus module's config
- if("module_opus_enabled" in env and env["module_opus_enabled"] != "no"):
+ if 'module_opus_enabled' in env and env['module_opus_enabled']:
env.opus_fixed_point = "yes"
diff --git a/platform/javascript/engine.js b/platform/javascript/engine.js
index 552f5a7e02..99d1c20bbd 100644
--- a/platform/javascript/engine.js
+++ b/platform/javascript/engine.js
@@ -84,10 +84,10 @@
rtenvOpts.print = stdout;
if (typeof stderr === 'function')
rtenvOpts.printErr = stderr;
- if (typeof WebAssembly === 'object' && initializer instanceof WebAssembly.Module) {
+ if (typeof WebAssembly === 'object' && initializer instanceof ArrayBuffer) {
rtenvOpts.instantiateWasm = function(imports, onSuccess) {
WebAssembly.instantiate(initializer, imports).then(function(result) {
- onSuccess(result);
+ onSuccess(result.instance);
});
return {};
};
@@ -241,7 +241,7 @@
return Promise.reject(new Error("Browser doesn't support WebAssembly"));
// TODO cache/retrieve module to/from idb
engineLoadPromise = loadPromise(basePath + '.wasm').then(function(xhr) {
- return WebAssembly.compile(xhr.response);
+ return xhr.response;
});
} else {
var asmjsPromise = loadPromise(basePath + '.asm.js').then(function(xhr) {
diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp
index 543d028576..82a8409615 100644
--- a/platform/javascript/os_javascript.cpp
+++ b/platform/javascript/os_javascript.cpp
@@ -85,6 +85,10 @@ void OS_JavaScript::initialize_core() {
FileAccess::make_default<FileAccessBufferedFA<FileAccessUnix> >(FileAccess::ACCESS_RESOURCES);
}
+void OS_JavaScript::initialize_logger() {
+ _set_logger(memnew(StdLogger));
+}
+
void OS_JavaScript::set_opengl_extensions(const char *p_gl_extensions) {
ERR_FAIL_COND(!p_gl_extensions);
@@ -172,14 +176,14 @@ static EM_BOOL _mousebutton_callback(int event_type, const EmscriptenMouseEvent
if (!is_canvas_focused()) {
focus_canvas();
}
- mask |= 1 << ev->get_button_index();
- } else if (mask & (1 << ev->get_button_index())) {
- mask &= ~(1 << ev->get_button_index());
+ mask |= ev->get_button_index();
+ } else if (mask & ev->get_button_index()) {
+ mask &= ~ev->get_button_index();
} else {
// release event, but press was outside the canvas, so ignore
return false;
}
- ev->set_button_mask(mask >> 1);
+ ev->set_button_mask(mask);
_input->parse_input_event(ev);
// prevent selection dragging
@@ -200,7 +204,7 @@ static EM_BOOL _mousemove_callback(int event_type, const EmscriptenMouseEvent *m
Ref<InputEventMouseMotion> ev;
ev.instance();
dom2godot_mod(mouse_event, ev);
- ev->set_button_mask(input_mask >> 1);
+ ev->set_button_mask(input_mask);
ev->set_position(pos);
ev->set_global_position(ev->get_position());
@@ -227,7 +231,7 @@ static EM_BOOL _wheel_callback(int event_type, const EmscriptenWheelEvent *wheel
Ref<InputEventMouseButton> ev;
ev.instance();
- ev->set_button_mask(_input->get_mouse_button_mask() >> 1);
+ ev->set_button_mask(_input->get_mouse_button_mask());
ev->set_position(_input->get_mouse_position());
ev->set_global_position(ev->get_position());
@@ -291,7 +295,7 @@ static EM_BOOL _touchpress_callback(int event_type, const EmscriptenTouchEvent *
Ref<InputEventMouseButton> ev_mouse;
ev_mouse.instance();
- ev_mouse->set_button_mask(_input->get_mouse_button_mask() >> 1);
+ ev_mouse->set_button_mask(_input->get_mouse_button_mask());
dom2godot_mod(touch_event, ev_mouse);
const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index];
@@ -334,7 +338,7 @@ static EM_BOOL _touchmove_callback(int event_type, const EmscriptenTouchEvent *t
Ref<InputEventMouseMotion> ev_mouse;
ev_mouse.instance();
dom2godot_mod(touch_event, ev_mouse);
- ev_mouse->set_button_mask(_input->get_mouse_button_mask() >> 1);
+ ev_mouse->set_button_mask(_input->get_mouse_button_mask());
const EmscriptenTouchPoint &first_touch = touch_event->touches[lowest_id_index];
ev_mouse->set_position(Point2(first_touch.canvasX, first_touch.canvasY));
@@ -464,11 +468,7 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i
print_line("Init Audio");
AudioDriverManager::add_driver(&audio_driver_javascript);
- audio_driver_javascript.set_singleton();
- if (audio_driver_javascript.init() != OK) {
-
- ERR_PRINT("Initializing audio failed.");
- }
+ AudioDriverManager::initialize(p_audio_driver);
RasterizerGLES3::register_config();
RasterizerGLES3::make_current();
diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h
index 4c6469cb58..1c7bcfef45 100644
--- a/platform/javascript/os_javascript.h
+++ b/platform/javascript/os_javascript.h
@@ -92,6 +92,7 @@ public:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
+ virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -104,11 +105,6 @@ public:
//static OS* get_singleton();
- virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
-
- OS::print_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
- }
-
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual void set_mouse_mode(MouseMode p_mode);
diff --git a/platform/osx/SCsub b/platform/osx/SCsub
index 5b2de54535..be3950bc6d 100644
--- a/platform/osx/SCsub
+++ b/platform/osx/SCsub
@@ -1,20 +1,22 @@
#!/usr/bin/env python
+import os
Import('env')
+def make_debug(target, source, env):
+ os.system('dsymutil %s -o %s.dSYM' % (target[0], target[0]))
+
files = [
'crash_handler_osx.mm',
'os_osx.mm',
'godot_main_osx.mm',
- 'audio_driver_osx.cpp',
'sem_osx.cpp',
'dir_access_osx.mm',
'joypad_osx.cpp',
'power_osx.cpp',
]
-prog = env.Program('#bin/godot', files)
-if (env['target'] == "debug" or env['target'] == "release_debug"):
- # Build the .dSYM file for atos
- action = "dsymutil " + File(prog)[0].path + " -o " + File(prog)[0].path + ".dSYM"
- env.AddPostAction(prog, action)
+binary = env.Program('#bin/godot', files)
+if env["debug_symbols"] == "full" or env["debug_symbols"] == "yes":
+ env.AddPostAction(binary, make_debug)
+
diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm
index 9239573734..2ed88db309 100644
--- a/platform/osx/crash_handler_osx.mm
+++ b/platform/osx/crash_handler_osx.mm
@@ -43,6 +43,7 @@
#include <dlfcn.h>
#include <execinfo.h>
#include <signal.h>
+#include <stdlib.h>
#include <mach-o/dyld.h>
#include <mach-o/getsect.h>
@@ -77,7 +78,7 @@ static void handle_crash(int sig) {
void *bt_buffer[256];
size_t size = backtrace(bt_buffer, 256);
String _execpath = OS::get_singleton()->get_executable_path();
- String msg = GLOBAL_GET("debug/settings/backtrace/message");
+ String msg = GLOBAL_GET("debug/settings/crash_handler/message");
// Dump the backtrace to stderr with a message to the user
fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig);
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index d3ebdfe992..f66c3f00da 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -19,9 +19,11 @@ def can_build():
def get_opts():
+ from SCons.Variables import EnumVariable
return [
('osxcross_sdk', 'OSXCross SDK version', 'darwin14'),
+ EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')),
]
@@ -36,10 +38,18 @@ def configure(env):
## Build type
if (env["target"] == "release"):
- env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-fomit-frame-pointer', '-ftree-vectorize', '-msse2'])
+ env.Prepend(CCFLAGS=['-O3', '-ffast-math', '-fomit-frame-pointer', '-ftree-vectorize', '-msse2'])
+ if (env["debug_symbols"] == "yes"):
+ env.Prepend(CCFLAGS=['-g1'])
+ if (env["debug_symbols"] == "full"):
+ env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "release_debug"):
env.Prepend(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ if (env["debug_symbols"] == "yes"):
+ env.Prepend(CCFLAGS=['-g1'])
+ if (env["debug_symbols"] == "full"):
+ env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "debug"):
env.Prepend(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
@@ -87,13 +97,13 @@ def configure(env):
## Dependencies
- if (env['builtin_libtheora'] != 'no'):
+ if env['builtin_libtheora']:
env["x86_libtheora_opt_gcc"] = True
## Flags
env.Append(CPPPATH=['#platform/osx'])
- env.Append(CPPFLAGS=['-DOSX_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DAPPLE_STYLE_KEYS'])
+ env.Append(CPPFLAGS=['-DOSX_ENABLED', '-DUNIX_ENABLED', '-DGLES2_ENABLED', '-DAPPLE_STYLE_KEYS', '-DCOREAUDIO_ENABLED'])
env.Append(LINKFLAGS=['-framework', 'Cocoa', '-framework', 'Carbon', '-framework', 'OpenGL', '-framework', 'AGL', '-framework', 'AudioUnit', '-framework', 'CoreAudio', '-lz', '-framework', 'IOKit', '-framework', 'ForceFeedback'])
env.Append(LIBS=['pthread'])
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 059dd5afd0..eb8c0566b4 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -31,13 +31,11 @@
#define OS_OSX_H
#include "crash_handler_osx.h"
-#include "drivers/alsa/audio_driver_alsa.h"
-#include "drivers/rtaudio/audio_driver_rtaudio.h"
+#include "drivers/coreaudio/audio_driver_coreaudio.h"
#include "drivers/unix/os_unix.h"
#include "joypad_osx.h"
#include "main/input_default.h"
#include "os/input.h"
-#include "platform/osx/audio_driver_osx.h"
#include "power_osx.h"
#include "servers/audio_server.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
@@ -69,7 +67,7 @@ public:
IP_Unix *ip_unix;
- AudioDriverOSX audio_driver_osx;
+ AudioDriverCoreAudio audio_driver;
InputDefault *input;
JoypadOSX *joypad_osx;
@@ -129,6 +127,7 @@ protected:
virtual const char *get_video_driver_name(int p_driver) const;
virtual VideoMode get_default_video_mode() const;
+ virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
virtual void finalize();
@@ -143,8 +142,6 @@ public:
virtual String get_name();
- virtual void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
-
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
virtual void set_cursor_shape(CursorShape p_shape);
@@ -152,7 +149,7 @@ public:
virtual void set_mouse_show(bool p_show);
virtual void set_mouse_grab(bool p_grab);
virtual bool is_mouse_grab_enabled() const;
- virtual void warp_mouse_pos(const Point2 &p_to);
+ virtual void warp_mouse_position(const Point2 &p_to);
virtual Point2 get_mouse_position() const;
virtual int get_mouse_button_state() const;
virtual void set_window_title(const String &p_title);
@@ -184,7 +181,6 @@ public:
virtual void get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen = 0) const;
virtual String get_executable_path() const;
- virtual String get_resource_dir() const;
virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
@@ -230,6 +226,8 @@ public:
void disable_crash_handler();
bool is_disable_crash_handler() const;
+ virtual Error move_to_trash(const String &p_path);
+
OS_OSX();
};
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 5a23d76755..8323aa84a8 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1071,7 +1071,7 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
bool use_gl2 = p_video_driver != 1;
- AudioDriverManager::add_driver(&audio_driver_osx);
+ AudioDriverManager::add_driver(&audio_driver);
// only opengl support here...
RasterizerGLES3::register_config();
@@ -1088,12 +1088,7 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
visual_server->init();
// visual_server->cursor_set_visible(false, 0);
- AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
-
- if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
-
- ERR_PRINT("Initializing audio failed.");
- }
+ AudioDriverManager::initialize(p_audio_driver);
//
physics_server = memnew(PhysicsServerSW);
@@ -1150,43 +1145,67 @@ String OS_OSX::get_name() {
return "OSX";
}
-void OS_OSX::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
-
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
- if (!_print_error_enabled)
- return;
-
- const char *err_details;
- if (p_rationale && p_rationale[0])
- err_details = p_rationale;
- else
- err_details = p_code;
+class OSXTerminalLogger : public StdLogger {
+public:
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR) {
+ if (!should_log(true)) {
+ return;
+ }
- switch (p_type) {
- case ERR_ERROR:
- os_log_error(OS_LOG_DEFAULT, "ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
- print("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- print("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
- break;
- case ERR_WARNING:
- os_log_info(OS_LOG_DEFAULT, "WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
- print("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function, err_details);
- print("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
- break;
- case ERR_SCRIPT:
- os_log_error(OS_LOG_DEFAULT, "SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
- print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- print("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
- break;
- case ERR_SHADER:
- os_log_error(OS_LOG_DEFAULT, "SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.", p_function, err_details, p_file, p_line);
- print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
- print("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
- break;
+ const char *err_details;
+ if (p_rationale && p_rationale[0])
+ err_details = p_rationale;
+ else
+ err_details = p_code;
+
+ switch (p_type) {
+ case ERR_WARNING:
+ os_log_info(OS_LOG_DEFAULT,
+ "WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.",
+ p_function, err_details, p_file, p_line);
+ logf_error("\E[1;33mWARNING: %s: \E[0m\E[1m%s\n", p_function,
+ err_details);
+ logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
+ break;
+ case ERR_SCRIPT:
+ os_log_error(OS_LOG_DEFAULT,
+ "SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
+ p_function, err_details, p_file, p_line);
+ logf_error("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n", p_function,
+ err_details);
+ logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
+ break;
+ case ERR_SHADER:
+ os_log_error(OS_LOG_DEFAULT,
+ "SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
+ p_function, err_details, p_file, p_line);
+ logf_error("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n", p_function,
+ err_details);
+ logf_error("\E[0;36m At: %s:%i.\E[0m\n", p_file, p_line);
+ break;
+ case ERR_ERROR:
+ default:
+ os_log_error(OS_LOG_DEFAULT,
+ "ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
+ p_function, err_details, p_file, p_line);
+ logf_error("\E[1;31mERROR: %s: \E[0m\E[1m%s\n", p_function, err_details);
+ logf_error("\E[0;31m At: %s:%i.\E[0m\n", p_file, p_line);
+ break;
+ }
}
+};
+
#else
- OS_Unix::print_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
+
+typedef UnixTerminalLogger OSXTerminalLogger;
#endif
+
+void OS_OSX::initialize_logger() {
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(OSXTerminalLogger));
+ loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
+ _set_logger(memnew(CompositeLogger(loggers)));
}
void OS_OSX::alert(const String &p_alert, const String &p_title) {
@@ -1245,7 +1264,7 @@ bool OS_OSX::is_mouse_grab_enabled() const {
return mouse_grab;
}
-void OS_OSX::warp_mouse_pos(const Point2 &p_to) {
+void OS_OSX::warp_mouse_position(const Point2 &p_to) {
//copied from windows impl with osx native calls
if (mouse_mode == MOUSE_MODE_CAPTURED) {
@@ -1738,17 +1757,6 @@ String OS_OSX::get_executable_path() const {
}
}
-String OS_OSX::get_resource_dir() const {
- // start with our executable path
- String path = get_executable_path();
-
- int pos = path.find_last("/Contents/MacOS/");
- if (pos < 0)
- return OS::get_resource_dir();
-
- return path.substr(0, pos) + "/Contents/Resources/";
-}
-
// Returns string representation of keys, if they are printable.
//
static NSString *createStringForKeys(const CGKeyCode *keyCode, int length) {
@@ -1926,6 +1934,19 @@ int OS_OSX::get_power_percent_left() {
return power_manager->get_power_percent_left();
}
+Error OS_OSX::move_to_trash(const String &p_path) {
+ NSFileManager *fm = [NSFileManager defaultManager];
+ NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
+ NSError *err;
+
+ if (![fm trashItemAtURL:url resultingItemURL:nil error:&err]) {
+ ERR_PRINTS("trashItemAtURL error: " + String(err.localizedDescription.UTF8String));
+ return FAILED;
+ }
+
+ return OK;
+}
+
OS_OSX *OS_OSX::singleton = NULL;
OS_OSX::OS_OSX() {
@@ -2019,6 +2040,8 @@ OS_OSX::OS_OSX() {
window_size = Vector2(1024, 600);
zoomed = false;
display_scale = 1.0;
+
+ _set_logger(memnew(OSXTerminalLogger));
}
bool OS_OSX::_check_internal_feature_support(const String &p_feature) {
diff --git a/platform/server/detect.py b/platform/server/detect.py
index 2bb4b59e94..04b38f280d 100644
--- a/platform/server/detect.py
+++ b/platform/server/detect.py
@@ -19,9 +19,9 @@ def can_build():
def get_opts():
-
+ from SCons.Variables import BoolVariable
return [
- ('use_llvm', 'Use the LLVM compiler', 'no'),
+ BoolVariable('use_llvm', 'Use the LLVM compiler', False),
]
@@ -52,7 +52,7 @@ def configure(env):
## Compiler configuration
- if (env["use_llvm"] == "yes"):
+ if env['use_llvm']:
if ('clang++' not in env['CXX']):
env["CC"] = "clang"
env["CXX"] = "clang++"
@@ -64,66 +64,60 @@ def configure(env):
# FIXME: Check for existence of the libs before parsing their flags with pkg-config
- if (env['builtin_openssl'] == 'no'):
- # Currently not compatible with OpenSSL 1.1.0+
- # https://github.com/godotengine/godot/issues/8624
- import subprocess
- openssl_version = subprocess.check_output(['pkg-config', 'openssl', '--modversion']).strip('\n')
- if (openssl_version >= "1.1.0"):
- print("Error: Found system-installed OpenSSL %s, currently only supporting version 1.0.x." % openssl_version)
- print("Aborting.. You can compile with 'builtin_openssl=yes' to use the bundled version.\n")
- sys.exit(255)
-
+ if not env['builtin_openssl']:
env.ParseConfig('pkg-config openssl --cflags --libs')
- if (env['builtin_libwebp'] == 'no'):
+ if not env['builtin_libwebp']:
env.ParseConfig('pkg-config libwebp --cflags --libs')
# freetype depends on libpng and zlib, so bundling one of them while keeping others
# as shared libraries leads to weird issues
- if (env['builtin_freetype'] == 'yes' or env['builtin_libpng'] == 'yes' or env['builtin_zlib'] == 'yes'):
- env['builtin_freetype'] = 'yes'
- env['builtin_libpng'] = 'yes'
- env['builtin_zlib'] = 'yes'
+ if env['builtin_freetype'] or env['builtin_libpng'] or env['builtin_zlib']:
+ env['builtin_freetype'] = True
+ env['builtin_libpng'] = True
+ env['builtin_zlib'] = True
- if (env['builtin_freetype'] == 'no'):
+ if not env['builtin_freetype']:
env.ParseConfig('pkg-config freetype2 --cflags --libs')
- if (env['builtin_libpng'] == 'no'):
+ if not env['builtin_libpng']:
env.ParseConfig('pkg-config libpng --cflags --libs')
- if (env['builtin_enet'] == 'no'):
+ if not env['builtin_enet']:
env.ParseConfig('pkg-config libenet --cflags --libs')
- if (env['builtin_squish'] == 'no' and env["tools"] == "yes"):
+ if not env['builtin_squish'] and env['tools']:
env.ParseConfig('pkg-config libsquish --cflags --libs')
+ if not env['builtin_zstd']:
+ env.ParseConfig('pkg-config libzstd --cflags --libs')
+
# Sound and video libraries
# Keep the order as it triggers chained dependencies (ogg needed by others, etc.)
- if (env['builtin_libtheora'] == 'no'):
- env['builtin_libogg'] = 'no' # Needed to link against system libtheora
- env['builtin_libvorbis'] = 'no' # Needed to link against system libtheora
+ if not env['builtin_libtheora']:
+ env['builtin_libogg'] = False # Needed to link against system libtheora
+ env['builtin_libvorbis'] = False # Needed to link against system libtheora
env.ParseConfig('pkg-config theora theoradec --cflags --libs')
- if (env['builtin_libvpx'] == 'no'):
+ if not env['builtin_libvpx']:
env.ParseConfig('pkg-config vpx --cflags --libs')
- if (env['builtin_libvorbis'] == 'no'):
- env['builtin_libogg'] = 'no' # Needed to link against system libvorbis
+ if not env['builtin_libvorbis']:
+ env['builtin_libogg'] = False # Needed to link against system libvorbis
env.ParseConfig('pkg-config vorbis vorbisfile --cflags --libs')
- if (env['builtin_opus'] == 'no'):
- env['builtin_libogg'] = 'no' # Needed to link against system opus
+ if not env['builtin_opus']:
+ env['builtin_libogg'] = False # Needed to link against system opus
env.ParseConfig('pkg-config opus opusfile --cflags --libs')
- if (env['builtin_libogg'] == 'no'):
+ if not env['builtin_libogg']:
env.ParseConfig('pkg-config ogg --cflags --libs')
## Flags
# Linkflags below this line should typically stay the last ones
- if (env['builtin_zlib'] == 'no'):
+ if not env['builtin_zlib']:
env.ParseConfig('pkg-config zlib --cflags --libs')
env.Append(CPPPATH=['#platform/server'])
diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp
index e2bb464e76..300c5cffcc 100644
--- a/platform/server/os_server.cpp
+++ b/platform/server/os_server.cpp
@@ -62,12 +62,7 @@ void OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p
//visual_server = memnew( VisualServerRaster(rasterizer) );
- AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
-
- if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
-
- ERR_PRINT("Initializing audio failed.");
- }
+ AudioDriverManager::initialize(p_audio_driver);
sample_manager = memnew(SampleManagerMallocSW);
audio_server = memnew(AudioServerSW(sample_manager));
@@ -232,7 +227,6 @@ void OS_Server::run() {
OS_Server::OS_Server() {
- AudioDriverManager::add_driver(&driver_dummy);
//adriver here
grab = false;
};
diff --git a/platform/server/os_server.h b/platform/server/os_server.h
index 8c0ca1a58d..ba12f649be 100644
--- a/platform/server/os_server.h
+++ b/platform/server/os_server.h
@@ -34,7 +34,6 @@
#include "drivers/rtaudio/audio_driver_rtaudio.h"
#include "drivers/unix/os_unix.h"
#include "main/input_default.h"
-#include "servers/audio/audio_driver_dummy.h"
#include "servers/audio_server.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
#include "servers/physics_server.h"
@@ -55,7 +54,6 @@ class OS_Server : public OS_Unix {
List<String> args;
MainLoop *main_loop;
- AudioDriverDummy driver_dummy;
bool grab;
PhysicsServer *physics_server;
diff --git a/platform/uwp/detect.py b/platform/uwp/detect.py
index 23929dd804..af53f97446 100644
--- a/platform/uwp/detect.py
+++ b/platform/uwp/detect.py
@@ -33,8 +33,8 @@ def get_opts():
def get_flags():
return [
- ('tools', 'no'),
- ('xaudio2', 'yes'),
+ ('tools', False),
+ ('xaudio2', True),
]
diff --git a/platform/uwp/export/export.cpp b/platform/uwp/export/export.cpp
index 25d44c24b5..d66bcaa91c 100644
--- a/platform/uwp/export/export.cpp
+++ b/platform/uwp/export/export.cpp
@@ -471,7 +471,7 @@ void AppxPackager::add_file(String p_file_name, const uint8_t *p_buffer, size_t
meta.uncompressed_size = p_len;
meta.compressed_size = p_len;
meta.compressed = p_compress;
- meta.zip_offset = package->get_pos();
+ meta.zip_offset = package->get_position();
Vector<uint8_t> file_buffer;
@@ -619,11 +619,11 @@ void AppxPackager::finish() {
// Write central directory
EditorNode::progress_task_step("export", "Finishing package...", 6);
- central_dir_offset = package->get_pos();
+ central_dir_offset = package->get_position();
package->store_buffer(central_dir_data.ptr(), central_dir_data.size());
// End record
- end_of_central_dir_offset = package->get_pos();
+ end_of_central_dir_offset = package->get_position();
Vector<uint8_t> end_record = make_end_of_central_record();
package->store_buffer(end_record.ptr(), end_record.size());
diff --git a/platform/uwp/gl_context_egl.cpp b/platform/uwp/gl_context_egl.cpp
index dd186c97d6..ed3db65cdf 100644
--- a/platform/uwp/gl_context_egl.cpp
+++ b/platform/uwp/gl_context_egl.cpp
@@ -31,7 +31,7 @@
#include "EGL/eglext.h"
-using namespace Platform;
+using Platform::Exception;
void ContextEGL::release_current() {
@@ -103,23 +103,23 @@ Error ContextEGL::initialize() {
const EGLint displayAttributes[] =
{
- /*EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
- EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
- EGL_NONE,*/
- // These are the default display attributes, used to request ANGLE's D3D11 renderer.
- // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
- EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
-
- // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
- // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
- //EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
-
- // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
- // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
- // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
- EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
- EGL_NONE,
+ /*EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
+ EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
+ EGL_NONE,*/
+ // These are the default display attributes, used to request ANGLE's D3D11 renderer.
+ // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
+ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+
+ // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
+ // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
+ //EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
+
+ // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
+ // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
+ // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
+ EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
+ EGL_NONE,
};
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp
index fd8904fa0a..031c714514 100644
--- a/platform/uwp/os_uwp.cpp
+++ b/platform/uwp/os_uwp.cpp
@@ -40,6 +40,7 @@
#include "platform/windows/packet_peer_udp_winsock.h"
#include "platform/windows/stream_peer_winsock.h"
#include "platform/windows/tcp_server_winsock.h"
+#include "platform/windows/windows_terminal_logger.h"
#include "project_settings.h"
#include "servers/audio_server.h"
#include "servers/visual/visual_server_raster.h"
@@ -182,6 +183,13 @@ void OSUWP::initialize_core() {
cursor_shape = CURSOR_ARROW;
}
+void OSUWP::initialize_logger() {
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(WindowsTerminalLogger));
+ loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
+ _set_logger(memnew(CompositeLogger(loggers)));
+}
+
bool OSUWP::can_draw() const {
return !minimized;
@@ -268,12 +276,7 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud
joypad = ref new JoypadUWP(input);
joypad->register_events();
- AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
-
- if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
-
- ERR_PRINT("Initializing audio failed.");
- }
+ AudioDriverManager::initialize(p_audio_driver);
power_manager = memnew(PowerUWP);
@@ -376,32 +379,6 @@ void OSUWP::finalize() {
void OSUWP::finalize_core() {
}
-void OSUWP::vprint(const char *p_format, va_list p_list, bool p_stderr) {
-
- char buf[16384 + 1];
- int len = vsnprintf(buf, 16384, p_format, p_list);
- if (len <= 0)
- return;
- buf[len] = 0;
-
- int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
- if (wlen < 0)
- return;
-
- wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
- MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
- wbuf[wlen] = 0;
-
- if (p_stderr)
- fwprintf(stderr, L"%s", wbuf);
- else
- wprintf(L"%s", wbuf);
-
- free(wbuf);
-
- fflush(stdout);
-};
-
void OSUWP::alert(const String &p_alert, const String &p_title) {
Platform::String ^ alert = ref new Platform::String(p_alert.c_str());
@@ -525,30 +502,6 @@ OS::VideoMode OSUWP::get_video_mode(int p_screen) const {
void OSUWP::get_fullscreen_mode_list(List<VideoMode> *p_list, int p_screen) const {
}
-void OSUWP::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
-
- const char *err_details;
- if (p_rationale && p_rationale[0])
- err_details = p_rationale;
- else
- err_details = p_code;
-
- switch (p_type) {
- case ERR_ERROR:
- print("ERROR: %s: %s\n", p_function, err_details);
- print(" At: %s:%i\n", p_file, p_line);
- break;
- case ERR_WARNING:
- print("WARNING: %s: %s\n", p_function, err_details);
- print(" At: %s:%i\n", p_file, p_line);
- break;
- case ERR_SCRIPT:
- print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
- print(" At: %s:%i\n", p_file, p_line);
- break;
- }
-}
-
String OSUWP::get_name() {
return "UWP";
@@ -895,6 +848,8 @@ OSUWP::OSUWP() {
mouse_mode_changed = CreateEvent(NULL, TRUE, FALSE, L"os_mouse_mode_changed");
AudioDriverManager::add_driver(&audio_driver);
+
+ _set_logger(memnew(WindowsTerminalLogger));
}
OSUWP::~OSUWP() {
diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h
index a7a5d32cb9..df38faa8e1 100644
--- a/platform/uwp/os_uwp.h
+++ b/platform/uwp/os_uwp.h
@@ -163,6 +163,7 @@ protected:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
+ virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -180,9 +181,6 @@ public:
// Event to send to the app wrapper
HANDLE mouse_mode_changed;
- void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
-
- virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
String get_stdin_string(bool p_block);
diff --git a/platform/windows/SCsub b/platform/windows/SCsub
index b56a5c6a80..aa9eb3e69b 100644
--- a/platform/windows/SCsub
+++ b/platform/windows/SCsub
@@ -1,7 +1,12 @@
#!/usr/bin/env python
+import os
Import('env')
+def make_debug_mingw(target, source, env):
+ os.system('objcopy --only-keep-debug %s %s.debug' % (target[0], target[0]))
+ os.system('strip --strip-debug --strip-unneeded %s' % (target[0]))
+ os.system('objcopy --add-gnu-debuglink=%s.debug %s' % (target[0], target[0]))
common_win = [
"context_gl_win.cpp",
@@ -14,6 +19,7 @@ common_win = [
"stream_peer_winsock.cpp",
"joypad.cpp",
"power_windows.cpp",
+ "windows_terminal_logger.cpp"
]
restarget = "godot_res" + env["OBJSUFFIX"]
@@ -22,10 +28,14 @@ obj = env.RES(restarget, 'godot_res.rc')
common_win.append(obj)
-env.Program('#bin/godot', ['godot_win.cpp'] + common_win, PROGSUFFIX=env["PROGSUFFIX"])
+binary = env.Program('#bin/godot', ['godot_win.cpp'] + common_win, PROGSUFFIX=env["PROGSUFFIX"])
# Microsoft Visual Studio Project Generation
-if (env['vsproj']) == "yes":
+if env['vsproj']:
env.vs_srcs = env.vs_srcs + ["platform/windows/godot_win.cpp"]
for x in common_win:
env.vs_srcs = env.vs_srcs + ["platform/windows/" + str(x)]
+
+if not os.getenv("VCINSTALLDIR"):
+ if env["debug_symbols"] == "full" or env["debug_symbols"] == "yes":
+ env.AddPostAction(binary, make_debug_mingw)
diff --git a/platform/windows/crash_handler_win.cpp b/platform/windows/crash_handler_win.cpp
index c9385f36d6..2f5ee7956e 100644
--- a/platform/windows/crash_handler_win.cpp
+++ b/platform/windows/crash_handler_win.cpp
@@ -116,7 +116,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
DWORD cbNeeded;
std::vector<HMODULE> module_handles(1);
- if (OS::get_singleton() == NULL || OS::get_singleton()->is_disable_crash_handler()) {
+ if (OS::get_singleton() == NULL || OS::get_singleton()->is_disable_crash_handler() || IsDebuggerPresent()) {
return EXCEPTION_CONTINUE_SEARCH;
}
@@ -159,7 +159,7 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) {
IMAGE_NT_HEADERS *h = ImageNtHeader(base);
DWORD image_type = h->FileHeader.Machine;
int n = 0;
- String msg = GLOBAL_GET("debug/settings/backtrace/message");
+ String msg = GLOBAL_GET("debug/settings/crash_handler/message");
fprintf(stderr, "Dumping the backtrace. %ls\n", msg.c_str());
diff --git a/platform/windows/detect.py b/platform/windows/detect.py
index 5bd9a78f49..031b397988 100644
--- a/platform/windows/detect.py
+++ b/platform/windows/detect.py
@@ -49,6 +49,7 @@ def can_build():
def get_opts():
+ from SCons.Variables import BoolVariable, EnumVariable
mingw32 = ""
mingw64 = ""
@@ -64,6 +65,8 @@ def get_opts():
return [
('mingw_prefix_32', 'MinGW prefix (Win32)', mingw32),
('mingw_prefix_64', 'MinGW prefix (Win64)', mingw64),
+ BoolVariable('use_lto', 'Use link time optimization (when using MingW)', False),
+ EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')),
]
@@ -213,11 +216,20 @@ def configure(env):
env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
+ if (env["debug_symbols"] == "yes"):
+ env.Prepend(CCFLAGS=['-g1'])
+ if (env["debug_symbols"] == "full"):
+ env.Prepend(CCFLAGS=['-g2'])
+
elif (env["target"] == "release_debug"):
env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
+ if (env["debug_symbols"] == "yes"):
+ env.Prepend(CCFLAGS=['-g1'])
+ if (env["debug_symbols"] == "full"):
+ env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "debug"):
- env.Append(CCFLAGS=['-g', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Append(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
## Compiler configuration
@@ -246,11 +258,18 @@ def configure(env):
env["CC"] = mingw_prefix + "gcc"
env['AS'] = mingw_prefix + "as"
env['CXX'] = mingw_prefix + "g++"
- env['AR'] = mingw_prefix + "ar"
- env['RANLIB'] = mingw_prefix + "ranlib"
+ env['AR'] = mingw_prefix + "gcc-ar"
+ env['RANLIB'] = mingw_prefix + "gcc-ranlib"
env['LD'] = mingw_prefix + "g++"
env["x86_libtheora_opt_gcc"] = True
+ if env['use_lto']:
+ env.Append(CCFLAGS=['-flto'])
+ if not env['use_llvm'] and env.GetOption("num_jobs") > 1:
+ env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))])
+ else:
+ env.Append(LINKFLAGS=['-flto'])
+
## Compile flags
env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows'])
diff --git a/platform/windows/godot_win.cpp b/platform/windows/godot_win.cpp
index 4450cb3670..cff2cbad42 100644
--- a/platform/windows/godot_win.cpp
+++ b/platform/windows/godot_win.cpp
@@ -156,32 +156,36 @@ int widechar_main(int argc, wchar_t **argv) {
return os.get_exit_code();
};
-int main(int _argc, char **_argv) {
-// _argc and _argv are ignored
-// we are going to use the WideChar version of them instead
+int _main() {
+ LPWSTR *wc_argv;
+ int argc;
+ int result;
-#ifdef CRASH_HANDLER_EXCEPTION
- __try {
-#endif
- LPWSTR *wc_argv;
- int argc;
- int result;
+ wc_argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+
+ if (NULL == wc_argv) {
+ wprintf(L"CommandLineToArgvW failed\n");
+ return 0;
+ }
- wc_argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ result = widechar_main(argc, wc_argv);
- if (NULL == wc_argv) {
- wprintf(L"CommandLineToArgvW failed\n");
- return 0;
- }
+ LocalFree(wc_argv);
+ return result;
+}
- result = widechar_main(argc, wc_argv);
+int main(int _argc, char **_argv) {
+// _argc and _argv are ignored
+// we are going to use the WideChar version of them instead
- LocalFree(wc_argv);
- return result;
#ifdef CRASH_HANDLER_EXCEPTION
+ __try {
+ return _main();
} __except (CrashHandlerException(GetExceptionInformation())) {
return 1;
}
+#else
+ return _main();
#endif
}
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 62954e1a56..bee8c90ad3 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -48,6 +48,7 @@
#include "servers/visual/visual_server_wrap_mt.h"
#include "stream_peer_winsock.h"
#include "tcp_server_winsock.h"
+#include "windows_terminal_logger.h"
#include <process.h>
#include <regstr.h>
@@ -205,6 +206,13 @@ void OS_Windows::initialize_core() {
cursor_shape = CURSOR_ARROW;
}
+void OS_Windows::initialize_logger() {
+ Vector<Logger *> loggers;
+ loggers.push_back(memnew(WindowsTerminalLogger));
+ loggers.push_back(memnew(RotatedFileLogger("user://logs/log.txt")));
+ _set_logger(memnew(CompositeLogger(loggers)));
+}
+
bool OS_Windows::can_draw() const {
return !minimized;
@@ -1081,12 +1089,7 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
power_manager = memnew(PowerWindows);
- AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
-
- if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
-
- ERR_PRINT("Initializing audio failed.");
- }
+ AudioDriverManager::initialize(p_audio_driver);
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
@@ -1236,38 +1239,6 @@ void OS_Windows::finalize_core() {
StreamPeerWinsock::cleanup();
}
-void OS_Windows::vprint(const char *p_format, va_list p_list, bool p_stderr) {
-
- const unsigned int BUFFER_SIZE = 16384;
- char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
- int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
- if (len <= 0)
- return;
- if (len >= BUFFER_SIZE)
- len = BUFFER_SIZE; // Output is too big, will be truncated
- buf[len] = 0;
-
- int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
- if (wlen < 0)
- return;
-
- wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
- MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
- wbuf[wlen] = 0;
-
- if (p_stderr)
- fwprintf(stderr, L"%ls", wbuf);
- else
- wprintf(L"%ls", wbuf);
-
-#ifdef STDOUT_FILE
-//vwfprintf(stdo,p_format,p_list);
-#endif
- free(wbuf);
-
- fflush(stdout);
-};
-
void OS_Windows::alert(const String &p_alert, const String &p_title) {
if (!is_no_window_mode_enabled())
@@ -1309,7 +1280,7 @@ OS_Windows::MouseMode OS_Windows::get_mouse_mode() const {
return mouse_mode;
}
-void OS_Windows::warp_mouse_pos(const Point2 &p_to) {
+void OS_Windows::warp_mouse_position(const Point2 &p_to) {
if (mouse_mode == MOUSE_MODE_CAPTURED) {
@@ -1681,107 +1652,6 @@ void OS_Windows::request_attention() {
FlashWindowEx(&info);
}
-void OS_Windows::print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
-
- HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
- if (!hCon || hCon == INVALID_HANDLE_VALUE) {
-
- const char *err_details;
- if (p_rationale && p_rationale[0])
- err_details = p_rationale;
- else
- err_details = p_code;
-
- switch (p_type) {
- case ERR_ERROR:
- print("ERROR: %s: %s\n", p_function, err_details);
- print(" At: %s:%i\n", p_file, p_line);
- break;
- case ERR_WARNING:
- print("WARNING: %s: %s\n", p_function, err_details);
- print(" At: %s:%i\n", p_file, p_line);
- break;
- case ERR_SCRIPT:
- print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
- print(" At: %s:%i\n", p_file, p_line);
- break;
- case ERR_SHADER:
- print("SHADER ERROR: %s: %s\n", p_function, err_details);
- print(" At: %s:%i\n", p_file, p_line);
- break;
- }
-
- } else {
-
- CONSOLE_SCREEN_BUFFER_INFO sbi; //original
- GetConsoleScreenBufferInfo(hCon, &sbi);
-
- WORD current_fg = sbi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
- WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
-
- uint32_t basecol = 0;
- switch (p_type) {
- case ERR_ERROR: basecol = FOREGROUND_RED; break;
- case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
- case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
- case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
- }
-
- basecol |= current_bg;
-
- if (p_rationale && p_rationale[0]) {
-
- SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
- switch (p_type) {
- case ERR_ERROR: print("ERROR: "); break;
- case ERR_WARNING: print("WARNING: "); break;
- case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
- case ERR_SHADER: print("SHADER ERROR: "); break;
- }
-
- SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
- print("%s\n", p_rationale);
-
- SetConsoleTextAttribute(hCon, basecol);
- switch (p_type) {
- case ERR_ERROR: print(" At: "); break;
- case ERR_WARNING: print(" At: "); break;
- case ERR_SCRIPT: print(" At: "); break;
- case ERR_SHADER: print(" At: "); break;
- }
-
- SetConsoleTextAttribute(hCon, current_fg | current_bg);
- print("%s:%i\n", p_file, p_line);
-
- } else {
-
- SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
- switch (p_type) {
- case ERR_ERROR: print("ERROR: %s: ", p_function); break;
- case ERR_WARNING: print("WARNING: %s: ", p_function); break;
- case ERR_SCRIPT: print("SCRIPT ERROR: %s: ", p_function); break;
- case ERR_SHADER: print("SCRIPT ERROR: %s: ", p_function); break;
- }
-
- SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
- print("%s\n", p_code);
-
- SetConsoleTextAttribute(hCon, basecol);
- switch (p_type) {
- case ERR_ERROR: print(" At: "); break;
- case ERR_WARNING: print(" At: "); break;
- case ERR_SCRIPT: print(" At: "); break;
- case ERR_SHADER: print(" At: "); break;
- }
-
- SetConsoleTextAttribute(hCon, current_fg | current_bg);
- print("%s:%i\n", p_file, p_line);
- }
-
- SetConsoleTextAttribute(hCon, sbi.wAttributes);
- }
-}
-
String OS_Windows::get_name() {
return "Windows";
@@ -2378,6 +2248,33 @@ bool OS_Windows::is_disable_crash_handler() const {
return crash_handler.is_disabled();
}
+Error OS_Windows::move_to_trash(const String &p_path) {
+ SHFILEOPSTRUCTA sf;
+ TCHAR *from = new TCHAR[p_path.length() + 2];
+ strcpy(from, p_path.utf8().get_data());
+ from[p_path.length()] = 0;
+ from[p_path.length() + 1] = 0;
+
+ sf.hwnd = hWnd;
+ sf.wFunc = FO_DELETE;
+ sf.pFrom = from;
+ sf.pTo = NULL;
+ sf.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION;
+ sf.fAnyOperationsAborted = FALSE;
+ sf.hNameMappings = NULL;
+ sf.lpszProgressTitle = NULL;
+
+ int ret = SHFileOperation(&sf);
+ delete[] from;
+
+ if (ret) {
+ ERR_PRINTS("SHFileOperation error: " + itos(ret));
+ return FAILED;
+ }
+
+ return OK;
+}
+
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
key_event_pos = 0;
@@ -2407,6 +2304,8 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
#ifdef XAUDIO2_ENABLED
AudioDriverManager::add_driver(&driver_xaudio2);
#endif
+
+ _set_logger(memnew(WindowsTerminalLogger));
}
OS_Windows::~OS_Windows() {
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 1a01ac950d..9560bc61ca 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -152,6 +152,7 @@ protected:
virtual int get_audio_driver_count() const;
virtual const char *get_audio_driver_name(int p_driver) const;
+ virtual void initialize_logger();
virtual void initialize_core();
virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver);
@@ -180,16 +181,13 @@ protected:
public:
LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
- void print_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type);
-
- virtual void vprint(const char *p_format, va_list p_list, bool p_stderr = false);
virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
String get_stdin_string(bool p_block);
void set_mouse_mode(MouseMode p_mode);
MouseMode get_mouse_mode() const;
- virtual void warp_mouse_pos(const Point2 &p_to);
+ virtual void warp_mouse_position(const Point2 &p_to);
virtual Point2 get_mouse_position() const;
virtual int get_mouse_button_state() const;
virtual void set_window_title(const String &p_title);
@@ -290,6 +288,8 @@ public:
void disable_crash_handler();
bool is_disable_crash_handler() const;
+ virtual Error move_to_trash(const String &p_path);
+
OS_Windows(HINSTANCE _hInstance);
~OS_Windows();
};
diff --git a/platform/windows/windows_terminal_logger.cpp b/platform/windows/windows_terminal_logger.cpp
new file mode 100644
index 0000000000..ef8140ffa7
--- /dev/null
+++ b/platform/windows/windows_terminal_logger.cpp
@@ -0,0 +1,157 @@
+/*************************************************************************/
+/* windows_terminal_logger.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "windows_terminal_logger.h"
+
+#ifdef WINDOWS_ENABLED
+
+#include <stdio.h>
+#include <windows.h>
+
+void WindowsTerminalLogger::logv(const char *p_format, va_list p_list, bool p_err) {
+ if (!should_log(p_err)) {
+ return;
+ }
+
+ const unsigned int BUFFER_SIZE = 16384;
+ char buf[BUFFER_SIZE + 1]; // +1 for the terminating character
+ int len = vsnprintf(buf, BUFFER_SIZE, p_format, p_list);
+ if (len <= 0)
+ return;
+ if (len >= BUFFER_SIZE)
+ len = BUFFER_SIZE; // Output is too big, will be truncated
+ buf[len] = 0;
+
+ int wlen = MultiByteToWideChar(CP_UTF8, 0, buf, len, NULL, 0);
+ if (wlen < 0)
+ return;
+
+ wchar_t *wbuf = (wchar_t *)malloc((len + 1) * sizeof(wchar_t));
+ MultiByteToWideChar(CP_UTF8, 0, buf, len, wbuf, wlen);
+ wbuf[wlen] = 0;
+
+ if (p_err)
+ fwprintf(stderr, L"%ls", wbuf);
+ else
+ wprintf(L"%ls", wbuf);
+
+ free(wbuf);
+
+#ifdef DEBUG_ENABLED
+ fflush(stdout);
+#endif
+}
+
+void WindowsTerminalLogger::log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type) {
+ if (!should_log(true)) {
+ return;
+ }
+
+#ifndef UWP_ENABLED
+ HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
+ if (!hCon || hCon == INVALID_HANDLE_VALUE) {
+#endif
+ StdLogger::log_error(p_function, p_file, p_line, p_code, p_rationale, p_type);
+#ifndef UWP_ENABLED
+ } else {
+
+ CONSOLE_SCREEN_BUFFER_INFO sbi; //original
+ GetConsoleScreenBufferInfo(hCon, &sbi);
+
+ WORD current_fg = sbi.wAttributes & (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
+ WORD current_bg = sbi.wAttributes & (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
+
+ uint32_t basecol = 0;
+ switch (p_type) {
+ case ERR_ERROR: basecol = FOREGROUND_RED; break;
+ case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
+ case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
+ case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
+ }
+
+ basecol |= current_bg;
+
+ if (p_rationale && p_rationale[0]) {
+
+ SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
+ switch (p_type) {
+ case ERR_ERROR: logf("ERROR: "); break;
+ case ERR_WARNING: logf("WARNING: "); break;
+ case ERR_SCRIPT: logf("SCRIPT ERROR: "); break;
+ case ERR_SHADER: logf("SHADER ERROR: "); break;
+ }
+
+ SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
+ logf("%s\n", p_rationale);
+
+ SetConsoleTextAttribute(hCon, basecol);
+ switch (p_type) {
+ case ERR_ERROR: logf(" At: "); break;
+ case ERR_WARNING: logf(" At: "); break;
+ case ERR_SCRIPT: logf(" At: "); break;
+ case ERR_SHADER: logf(" At: "); break;
+ }
+
+ SetConsoleTextAttribute(hCon, current_fg | current_bg);
+ logf("%s:%i\n", p_file, p_line);
+
+ } else {
+
+ SetConsoleTextAttribute(hCon, basecol | FOREGROUND_INTENSITY);
+ switch (p_type) {
+ case ERR_ERROR: logf("ERROR: %s: ", p_function); break;
+ case ERR_WARNING: logf("WARNING: %s: ", p_function); break;
+ case ERR_SCRIPT: logf("SCRIPT ERROR: %s: ", p_function); break;
+ case ERR_SHADER: logf("SCRIPT ERROR: %s: ", p_function); break;
+ }
+
+ SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
+ logf("%s\n", p_code);
+
+ SetConsoleTextAttribute(hCon, basecol);
+ switch (p_type) {
+ case ERR_ERROR: logf(" At: "); break;
+ case ERR_WARNING: logf(" At: "); break;
+ case ERR_SCRIPT: logf(" At: "); break;
+ case ERR_SHADER: logf(" At: "); break;
+ }
+
+ SetConsoleTextAttribute(hCon, current_fg | current_bg);
+ logf("%s:%i\n", p_file, p_line);
+ }
+
+ SetConsoleTextAttribute(hCon, sbi.wAttributes);
+ }
+#endif
+}
+
+WindowsTerminalLogger::~WindowsTerminalLogger() {}
+
+#endif \ No newline at end of file
diff --git a/platform/windows/windows_terminal_logger.h b/platform/windows/windows_terminal_logger.h
new file mode 100644
index 0000000000..f6b1a68d18
--- /dev/null
+++ b/platform/windows/windows_terminal_logger.h
@@ -0,0 +1,47 @@
+/*************************************************************************/
+/* windows_terminal_logger.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2017 Godot Engine contributors (cf. AUTHORS.md) */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 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 WINDOWS_TERMINAL_LOGGER_H
+#define WINDOWS_TERMINAL_LOGGER_H
+
+#ifdef WINDOWS_ENABLED
+
+#include "io/logger.h"
+
+class WindowsTerminalLogger : public StdLogger {
+public:
+ virtual void logv(const char *p_format, va_list p_list, bool p_err);
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR);
+ virtual ~WindowsTerminalLogger();
+};
+
+#endif
+
+#endif \ No newline at end of file
diff --git a/platform/x11/SCsub b/platform/x11/SCsub
index 62717f3221..aabc49149f 100644
--- a/platform/x11/SCsub
+++ b/platform/x11/SCsub
@@ -1,7 +1,12 @@
#!/usr/bin/env python
+import os
Import('env')
+def make_debug(target, source, env):
+ os.system('objcopy --only-keep-debug %s %s.debug' % (target[0], target[0]))
+ os.system('strip --strip-debug --strip-unneeded %s' % (target[0]))
+ os.system('objcopy --add-gnu-debuglink=%s.debug %s' % (target[0], target[0]))
common_x11 = [
"context_gl_x11.cpp",
@@ -12,4 +17,6 @@ common_x11 = [
"power_x11.cpp",
]
-env.Program('#bin/godot', ['godot_x11.cpp'] + common_x11)
+binary = env.Program('#bin/godot', ['godot_x11.cpp'] + common_x11)
+if env["debug_symbols"] == "full" or env["debug_symbols"] == "yes":
+ env.AddPostAction(binary, make_debug)
diff --git a/platform/x11/crash_handler_x11.cpp b/platform/x11/crash_handler_x11.cpp
index c926b7799d..3c54d5cbc2 100644
--- a/platform/x11/crash_handler_x11.cpp
+++ b/platform/x11/crash_handler_x11.cpp
@@ -39,6 +39,7 @@
#include <dlfcn.h>
#include <execinfo.h>
#include <signal.h>
+#include <stdlib.h>
static void handle_crash(int sig) {
if (OS::get_singleton() == NULL)
@@ -47,7 +48,7 @@ static void handle_crash(int sig) {
void *bt_buffer[256];
size_t size = backtrace(bt_buffer, 256);
String _execpath = OS::get_singleton()->get_executable_path();
- String msg = GLOBAL_GET("debug/settings/backtrace/message");
+ String msg = GLOBAL_GET("debug/settings/crash_handler/message");
// Dump the backtrace to stderr with a message to the user
fprintf(stderr, "%s: Program crashed with signal %d\n", __FUNCTION__, sig);
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index d61175da60..1f7f67fe10 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -44,28 +44,28 @@ def can_build():
return True
-
def get_opts():
+ from SCons.Variables import BoolVariable, EnumVariable
return [
- ('use_llvm', 'Use the LLVM compiler', 'no'),
- ('use_static_cpp', 'Link stdc++ statically', 'no'),
- ('use_sanitizer', 'Use LLVM compiler address sanitizer', 'no'),
- ('use_leak_sanitizer', 'Use LLVM compiler memory leaks sanitizer (implies use_sanitizer)', 'no'),
- ('use_lto', 'Use link time optimization', 'no'),
- ('pulseaudio', 'Detect & use pulseaudio', 'yes'),
- ('udev', 'Use udev for gamepad connection callbacks', 'no'),
- ('debug_release', 'Add debug symbols to release version', 'no'),
+ BoolVariable('use_llvm', 'Use the LLVM compiler', False),
+ BoolVariable('use_static_cpp', 'Link stdc++ statically', False),
+ BoolVariable('use_sanitizer', 'Use LLVM compiler address sanitizer', False),
+ BoolVariable('use_leak_sanitizer', 'Use LLVM compiler memory leaks sanitizer (implies use_sanitizer)', False),
+ BoolVariable('use_lto', 'Use link time optimization', False),
+ BoolVariable('pulseaudio', 'Detect & use pulseaudio', True),
+ BoolVariable('udev', 'Use udev for gamepad connection callbacks', False),
+ EnumVariable('debug_symbols', 'Add debug symbols to release version', 'yes', ('yes', 'no', 'full')),
]
def get_flags():
return [
- ('builtin_freetype', 'no'),
- ('builtin_libpng', 'no'),
- ('builtin_openssl', 'no'),
- ('builtin_zlib', 'no'),
+ ('builtin_freetype', False),
+ ('builtin_libpng', False),
+ ('builtin_openssl', False),
+ ('builtin_zlib', False),
]
@@ -77,16 +77,20 @@ def configure(env):
# -O3 -ffast-math is identical to -Ofast. We need to split it out so we can selectively disable
# -ffast-math in code for which it generates wrong results.
env.Prepend(CCFLAGS=['-O3', '-ffast-math'])
- if (env["debug_release"] == "yes"):
+ if (env["debug_symbols"] == "yes"):
+ env.Prepend(CCFLAGS=['-g1'])
+ if (env["debug_symbols"] == "full"):
env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "release_debug"):
env.Prepend(CCFLAGS=['-O2', '-ffast-math', '-DDEBUG_ENABLED'])
- if (env["debug_release"] == "yes"):
+ if (env["debug_symbols"] == "yes"):
+ env.Prepend(CCFLAGS=['-g1'])
+ if (env["debug_symbols"] == "full"):
env.Prepend(CCFLAGS=['-g2'])
elif (env["target"] == "debug"):
- env.Prepend(CCFLAGS=['-g2', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
+ env.Prepend(CCFLAGS=['-g3', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
env.Append(LINKFLAGS=['-rdynamic'])
## Architecture
@@ -97,7 +101,7 @@ def configure(env):
## Compiler configuration
- if (env["use_llvm"] == "yes"):
+ if env['use_llvm']:
if ('clang++' not in env['CXX']):
env["CC"] = "clang"
env["CXX"] = "clang++"
@@ -106,17 +110,23 @@ def configure(env):
env.extra_suffix = ".llvm" + env.extra_suffix
# leak sanitizer requires (address) sanitizer
- if (env["use_sanitizer"] == "yes" or env["use_leak_sanitizer"] == "yes"):
+ if env['use_sanitizer'] or env['use_leak_sanitizer']:
env.Append(CCFLAGS=['-fsanitize=address', '-fno-omit-frame-pointer'])
env.Append(LINKFLAGS=['-fsanitize=address'])
env.extra_suffix += "s"
- if (env["use_leak_sanitizer"] == "yes"):
+ if env['use_leak_sanitizer']:
env.Append(CCFLAGS=['-fsanitize=leak'])
env.Append(LINKFLAGS=['-fsanitize=leak'])
- if (env["use_lto"] == "yes"):
+ if env['use_lto']:
env.Append(CCFLAGS=['-flto'])
- env.Append(LINKFLAGS=['-flto'])
+ if not env['use_llvm'] and env.GetOption("num_jobs") > 1:
+ env.Append(LINKFLAGS=['-flto=' + str(env.GetOption("num_jobs"))])
+ else:
+ env.Append(LINKFLAGS=['-flto'])
+ if not env['use_llvm']:
+ env['RANLIB'] = 'gcc-ranlib'
+ env['AR'] = 'gcc-ar'
env.Append(CCFLAGS=['-pipe'])
env.Append(LINKFLAGS=['-pipe'])
@@ -130,70 +140,64 @@ def configure(env):
# FIXME: Check for existence of the libs before parsing their flags with pkg-config
- if (env['builtin_openssl'] == 'no'):
- # Currently not compatible with OpenSSL 1.1.0+
- # https://github.com/godotengine/godot/issues/8624
- import subprocess
- openssl_version = subprocess.check_output(['pkg-config', 'openssl', '--modversion']).strip('\n')
- if (openssl_version >= "1.1.0"):
- print("Error: Found system-installed OpenSSL %s, currently only supporting version 1.0.x." % openssl_version)
- print("Aborting.. You can compile with 'builtin_openssl=yes' to use the bundled version.\n")
- sys.exit(255)
-
+ if not env['builtin_openssl']:
env.ParseConfig('pkg-config openssl --cflags --libs')
- if (env['builtin_libwebp'] == 'no'):
+ if not env['builtin_libwebp']:
env.ParseConfig('pkg-config libwebp --cflags --libs')
# freetype depends on libpng and zlib, so bundling one of them while keeping others
# as shared libraries leads to weird issues
- if (env['builtin_freetype'] == 'yes' or env['builtin_libpng'] == 'yes' or env['builtin_zlib'] == 'yes'):
- env['builtin_freetype'] = 'yes'
- env['builtin_libpng'] = 'yes'
- env['builtin_zlib'] = 'yes'
+ if env['builtin_freetype'] or env['builtin_libpng'] or env['builtin_zlib']:
+ env['builtin_freetype'] = True
+ env['builtin_libpng'] = True
+ env['builtin_zlib'] = True
- if (env['builtin_freetype'] == 'no'):
+ if not env['builtin_freetype']:
env.ParseConfig('pkg-config freetype2 --cflags --libs')
- if (env['builtin_libpng'] == 'no'):
+ if not env['builtin_libpng']:
env.ParseConfig('pkg-config libpng --cflags --libs')
- if (env['builtin_enet'] == 'no'):
+ if not env['builtin_enet']:
env.ParseConfig('pkg-config libenet --cflags --libs')
- if (env['builtin_squish'] == 'no' and env["tools"] == "yes"):
+ if not env['builtin_squish'] and env['tools']:
env.ParseConfig('pkg-config libsquish --cflags --libs')
+ if not env['builtin_zstd']:
+ env.ParseConfig('pkg-config libzstd --cflags --libs')
+
# Sound and video libraries
# Keep the order as it triggers chained dependencies (ogg needed by others, etc.)
- if (env['builtin_libtheora'] == 'no'):
- env['builtin_libogg'] = 'no' # Needed to link against system libtheora
- env['builtin_libvorbis'] = 'no' # Needed to link against system libtheora
+ if not env['builtin_libtheora']:
+ env['builtin_libogg'] = False # Needed to link against system libtheora
+ env['builtin_libvorbis'] = False # Needed to link against system libtheora
env.ParseConfig('pkg-config theora theoradec --cflags --libs')
- if (env['builtin_libvpx'] == 'no'):
+ if not env['builtin_libvpx']:
env.ParseConfig('pkg-config vpx --cflags --libs')
- if (env['builtin_libvorbis'] == 'no'):
- env['builtin_libogg'] = 'no' # Needed to link against system libvorbis
+ if not env['builtin_libvorbis']:
+ env['builtin_libogg'] = False # Needed to link against system libvorbis
env.ParseConfig('pkg-config vorbis vorbisfile --cflags --libs')
- if (env['builtin_opus'] == 'no'):
- env['builtin_libogg'] = 'no' # Needed to link against system opus
+ if not env['builtin_opus']:
+ env['builtin_libogg'] = False # Needed to link against system opus
env.ParseConfig('pkg-config opus opusfile --cflags --libs')
- if (env['builtin_libogg'] == 'no'):
+ if not env['builtin_libogg']:
env.ParseConfig('pkg-config ogg --cflags --libs')
- if (env['builtin_libtheora'] != 'no'):
+ if env['builtin_libtheora']:
list_of_x86 = ['x86_64', 'x86', 'i386', 'i586']
if any(platform.machine() in s for s in list_of_x86):
env["x86_libtheora_opt_gcc"] = True
# On Linux wchar_t should be 32-bits
# 16-bit library shouldn't be required due to compiler optimisations
- if (env['builtin_pcre2'] == 'no'):
+ if not env['builtin_pcre2']:
env.ParseConfig('pkg-config libpcre2-32 --cflags --libs')
## Flags
@@ -205,7 +209,7 @@ def configure(env):
else:
print("ALSA libraries not found, disabling driver")
- if (env["pulseaudio"] == "yes"):
+ if env['pulseaudio']:
if (os.system("pkg-config --exists libpulse-simple") == 0): # 0 means found
print("Enabling PulseAudio")
env.Append(CPPFLAGS=["-DPULSEAUDIO_ENABLED"])
@@ -216,7 +220,7 @@ def configure(env):
if (platform.system() == "Linux"):
env.Append(CPPFLAGS=["-DJOYDEV_ENABLED"])
- if (env["udev"] == "yes"):
+ if env['udev']:
if (os.system("pkg-config --exists libudev") == 0): # 0 means found
print("Enabling udev support")
env.Append(CPPFLAGS=["-DUDEV_ENABLED"])
@@ -225,7 +229,7 @@ def configure(env):
print("libudev development libraries not found, disabling udev support")
# Linkflags below this line should typically stay the last ones
- if (env['builtin_zlib'] == 'no'):
+ if not env['builtin_zlib']:
env.ParseConfig('pkg-config zlib --cflags --libs')
env.Append(CPPPATH=['#platform/x11'])
@@ -244,5 +248,5 @@ def configure(env):
env.Append(CPPFLAGS=['-m64'])
env.Append(LINKFLAGS=['-m64', '-L/usr/lib/i686-linux-gnu'])
- if (env["use_static_cpp"] == "yes"):
+ if env['use_static_cpp']:
env.Append(LINKFLAGS=['-static-libstdc++'])
diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp
index 59b1a44247..fdb43c9ae0 100644
--- a/platform/x11/export/export.cpp
+++ b/platform/x11/export/export.cpp
@@ -50,6 +50,7 @@ void register_x11_exporter() {
platform->set_release_64("linux_x11_64_release");
platform->set_debug_64("linux_x11_64_debug");
platform->set_os_name("X11");
+ platform->set_chmod_flags(0755);
EditorExport::get_singleton()->add_export_platform(platform);
}
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 4e78e0318c..041666a594 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -35,6 +35,7 @@
#include "servers/physics/physics_server_sw.h"
#include "servers/visual/visual_server_raster.h"
#include "servers/visual/visual_server_wrap_mt.h"
+#include <mntent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -313,29 +314,7 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au
XFree(xsh);
}
- AudioDriverManager::get_driver(p_audio_driver)->set_singleton();
-
- audio_driver_index = p_audio_driver;
- if (AudioDriverManager::get_driver(p_audio_driver)->init() != OK) {
-
- bool success = false;
- audio_driver_index = -1;
- for (int i = 0; i < AudioDriverManager::get_driver_count(); i++) {
- if (i == p_audio_driver)
- continue;
- AudioDriverManager::get_driver(i)->set_singleton();
- if (AudioDriverManager::get_driver(i)->init() == OK) {
- success = true;
- print_line("Audio Driver Failed: " + String(AudioDriverManager::get_driver(p_audio_driver)->get_name()));
- print_line("Using alternate audio driver: " + String(AudioDriverManager::get_driver(i)->get_name()));
- audio_driver_index = i;
- break;
- }
- }
- if (!success) {
- ERR_PRINT("Initializing audio failed.");
- }
- }
+ AudioDriverManager::initialize(p_audio_driver);
ERR_FAIL_COND(!visual_server);
ERR_FAIL_COND(x11_window == 0);
@@ -635,7 +614,7 @@ void OS_X11::set_mouse_mode(MouseMode p_mode) {
XFlush(x11_display);
}
-void OS_X11::warp_mouse_pos(const Point2 &p_to) {
+void OS_X11::warp_mouse_position(const Point2 &p_to) {
if (mouse_mode == MOUSE_MODE_CAPTURED) {
@@ -730,6 +709,16 @@ void OS_X11::set_wm_fullscreen(bool p_enabled) {
XSetWMNormalHints(x11_display, x11_window, xsh);
XFree(xsh);
}
+
+ if (!p_enabled && !get_borderless_window()) {
+ // put decorations back if the window wasn't suppoesed to be borderless
+ Hints hints;
+ Atom property;
+ hints.flags = 2;
+ hints.decorations = 1;
+ property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True);
+ XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5);
+ }
}
int OS_X11::get_screen_count() const {
@@ -2187,11 +2176,78 @@ bool OS_X11::is_disable_crash_handler() const {
return crash_handler.is_disabled();
}
-OS_X11::OS_X11() {
+static String get_mountpoint(const String &p_path) {
+ struct stat s;
+ if (stat(p_path.utf8().get_data(), &s)) {
+ return "";
+ }
-#ifdef RTAUDIO_ENABLED
- AudioDriverManager::add_driver(&driver_rtaudio);
-#endif
+ dev_t dev = s.st_dev;
+ FILE *fd = setmntent("/proc/mounts", "r");
+ if (!fd) {
+ return "";
+ }
+
+ struct mntent mnt;
+ char buf[1024];
+ size_t buflen = 1024;
+ while (getmntent_r(fd, &mnt, buf, buflen)) {
+ if (!stat(mnt.mnt_dir, &s) && s.st_dev == dev) {
+ endmntent(fd);
+ return String(mnt.mnt_dir);
+ }
+ }
+
+ endmntent(fd);
+ return "";
+}
+
+Error OS_X11::move_to_trash(const String &p_path) {
+ String trashcan = "";
+ String mnt = get_mountpoint(p_path);
+
+ if (mnt != "") {
+ String path(mnt + "/.Trash-" + itos(getuid()) + "/files");
+ struct stat s;
+ if (!stat(path.utf8().get_data(), &s)) {
+ trashcan = path;
+ }
+ }
+
+ if (trashcan == "") {
+ char *dhome = getenv("XDG_DATA_HOME");
+ if (dhome) {
+ trashcan = String(dhome) + "/Trash/files";
+ }
+ }
+
+ if (trashcan == "") {
+ char *home = getenv("HOME");
+ if (home) {
+ trashcan = String(home) + "/.local/share/Trash/files";
+ }
+ }
+
+ if (trashcan == "") {
+ ERR_PRINTS("move_to_trash: Could not determine trashcan location");
+ return FAILED;
+ }
+
+ List<String> args;
+ args.push_back("-p");
+ args.push_back(trashcan);
+ Error err = execute("/bin/mkdir", args, true);
+ if (err == OK) {
+ List<String> args2;
+ args2.push_back(p_path);
+ args2.push_back(trashcan);
+ err = execute("/bin/mv", args2, true);
+ }
+
+ return err;
+}
+
+OS_X11::OS_X11() {
#ifdef PULSEAUDIO_ENABLED
AudioDriverManager::add_driver(&driver_pulseaudio);
@@ -2201,11 +2257,6 @@ OS_X11::OS_X11() {
AudioDriverManager::add_driver(&driver_alsa);
#endif
- if (AudioDriverManager::get_driver_count() == 0) {
- WARN_PRINT("No sound driver found... Defaulting to dummy driver");
- AudioDriverManager::add_driver(&driver_dummy);
- }
-
minimized = false;
xim_style = 0L;
mouse_mode = MOUSE_MODE_VISIBLE;
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 2ba7f07cef..0d5c272ed4 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -38,11 +38,9 @@
//#include "servers/visual/visual_server_wrap_mt.h"
#include "drivers/alsa/audio_driver_alsa.h"
#include "drivers/pulseaudio/audio_driver_pulseaudio.h"
-#include "drivers/rtaudio/audio_driver_rtaudio.h"
#include "joypad_linux.h"
#include "main/input_default.h"
#include "power_x11.h"
-#include "servers/audio/audio_driver_dummy.h"
#include "servers/audio_server.h"
#include "servers/physics_2d/physics_2d_server_sw.h"
#include "servers/physics_2d/physics_2d_server_wrap_mt.h"
@@ -154,10 +152,6 @@ class OS_X11 : public OS_Unix {
JoypadLinux *joypad;
#endif
-#ifdef RTAUDIO_ENABLED
- AudioDriverRtAudio driver_rtaudio;
-#endif
-
#ifdef ALSA_ENABLED
AudioDriverALSA driver_alsa;
#endif
@@ -165,7 +159,6 @@ class OS_X11 : public OS_Unix {
#ifdef PULSEAUDIO_ENABLED
AudioDriverPulseAudio driver_pulseaudio;
#endif
- AudioDriverDummy driver_dummy;
Atom net_wm_icon;
@@ -208,7 +201,7 @@ public:
void set_mouse_mode(MouseMode p_mode);
MouseMode get_mouse_mode() const;
- virtual void warp_mouse_pos(const Point2 &p_to);
+ virtual void warp_mouse_position(const Point2 &p_to);
virtual Point2 get_mouse_position() const;
virtual int get_mouse_button_state() const;
virtual void set_window_title(const String &p_title);
@@ -280,6 +273,8 @@ public:
void disable_crash_handler();
bool is_disable_crash_handler() const;
+ virtual Error move_to_trash(const String &p_path);
+
OS_X11();
};
diff --git a/scene/2d/animated_sprite.cpp b/scene/2d/animated_sprite.cpp
index 26241df660..c2edb173d7 100644
--- a/scene/2d/animated_sprite.cpp
+++ b/scene/2d/animated_sprite.cpp
@@ -223,7 +223,7 @@ void SpriteFrames::_bind_methods() {
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(D_METHOD("add_frame", "anim", "frame", "atpos"), &SpriteFrames::add_frame, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_frame", "anim", "frame", "at_position"), &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);
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 9fc6c8d23a..9ee77a710c 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -557,12 +557,12 @@ bool Area2D::is_overriding_audio_bus() const {
return audio_bus_override;
}
-void Area2D::set_audio_bus(const StringName &p_audio_bus) {
+void Area2D::set_audio_bus_name(const StringName &p_audio_bus) {
audio_bus = p_audio_bus;
}
-StringName Area2D::get_audio_bus() const {
+StringName Area2D::get_audio_bus_name() const {
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
if (AudioServer::get_singleton()->get_bus_name(i) == audio_bus) {
@@ -644,8 +644,8 @@ void Area2D::_bind_methods() {
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(D_METHOD("set_audio_bus", "name"), &Area2D::set_audio_bus);
- ClassDB::bind_method(D_METHOD("get_audio_bus"), &Area2D::get_audio_bus);
+ ClassDB::bind_method(D_METHOD("set_audio_bus_name", "name"), &Area2D::set_audio_bus_name);
+ ClassDB::bind_method(D_METHOD("get_audio_bus_name"), &Area2D::get_audio_bus_name);
ClassDB::bind_method(D_METHOD("set_audio_bus_override", "enable"), &Area2D::set_audio_bus_override);
ClassDB::bind_method(D_METHOD("is_overriding_audio_bus"), &Area2D::is_overriding_audio_bus);
@@ -679,7 +679,7 @@ void Area2D::_bind_methods() {
ADD_GROUP("Audio Bus", "audio_bus_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_bus_override"), "set_audio_bus_override", "is_overriding_audio_bus");
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus", "get_audio_bus");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "audio_bus_name", PROPERTY_HINT_ENUM, ""), "set_audio_bus_name", "get_audio_bus_name");
BIND_ENUM_CONSTANT(SPACE_OVERRIDE_DISABLED);
BIND_ENUM_CONSTANT(SPACE_OVERRIDE_COMBINE);
diff --git a/scene/2d/area_2d.h b/scene/2d/area_2d.h
index c56cf651a1..09ccb364e6 100644
--- a/scene/2d/area_2d.h
+++ b/scene/2d/area_2d.h
@@ -186,8 +186,8 @@ public:
void set_audio_bus_override(bool p_override);
bool is_overriding_audio_bus() const;
- void set_audio_bus(const StringName &p_audio_bus);
- StringName get_audio_bus() const;
+ void set_audio_bus_name(const StringName &p_audio_bus);
+ StringName get_audio_bus_name() const;
Area2D();
~Area2D();
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index b6abe90035..73e633139b 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -113,7 +113,7 @@ void AudioStreamPlayer2D::_notification(int p_what) {
AudioServer::get_singleton()->remove_callback(_mix_audios, this);
}
- if (p_what == NOTIFICATION_INTERNAL_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
//update anything related to position first, if possible of course
@@ -145,7 +145,7 @@ void AudioStreamPlayer2D::_notification(int p_what) {
if (!area2d->is_overriding_audio_bus())
continue;
- StringName bus_name = area2d->get_audio_bus();
+ StringName bus_name = area2d->get_audio_bus_name();
bus_index = AudioServer::get_singleton()->thread_find_bus_index(bus_name);
break;
}
@@ -203,7 +203,7 @@ void AudioStreamPlayer2D::_notification(int p_what) {
//stop playing if no longer active
if (!active) {
- set_fixed_process_internal(false);
+ set_physics_process_internal(false);
//do not update, this makes it easier to animate (will shut off otherise)
//_change_notify("playing"); //update property in editor
emit_signal("finished");
@@ -255,7 +255,7 @@ void AudioStreamPlayer2D::play(float p_from_pos) {
if (stream_playback.is_valid()) {
setplay = p_from_pos;
output_ready = false;
- set_fixed_process_internal(true);
+ set_physics_process_internal(true);
}
}
@@ -270,7 +270,7 @@ void AudioStreamPlayer2D::stop() {
if (stream_playback.is_valid()) {
active = false;
- set_fixed_process_internal(false);
+ set_physics_process_internal(false);
setplay = -1;
}
}
@@ -284,10 +284,10 @@ bool AudioStreamPlayer2D::is_playing() const {
return false;
}
-float AudioStreamPlayer2D::get_pos() {
+float AudioStreamPlayer2D::get_playback_position() {
if (stream_playback.is_valid()) {
- return stream_playback->get_pos();
+ return stream_playback->get_playback_position();
}
return 0;
@@ -390,12 +390,12 @@ void AudioStreamPlayer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer2D::set_volume_db);
ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer2D::get_volume_db);
- ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer2D::play, DEFVAL(0.0));
- ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer2D::seek);
+ ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer2D::play, DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer2D::seek);
ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer2D::stop);
ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer2D::is_playing);
- ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer2D::get_pos);
+ ClassDB::bind_method(D_METHOD("get_playback_position"), &AudioStreamPlayer2D::get_playback_position);
ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer2D::set_bus);
ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer2D::get_bus);
diff --git a/scene/2d/audio_stream_player_2d.h b/scene/2d/audio_stream_player_2d.h
index 25eff61b76..85104fce21 100644
--- a/scene/2d/audio_stream_player_2d.h
+++ b/scene/2d/audio_stream_player_2d.h
@@ -72,7 +72,7 @@ public:
void seek(float p_seconds);
void stop();
bool is_playing() const;
- float get_pos();
+ float get_playback_position();
void set_bus(const StringName &p_bus);
StringName get_bus() const;
diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp
index e39e6fc6da..4fcd6893b8 100644
--- a/scene/2d/camera_2d.cpp
+++ b/scene/2d/camera_2d.cpp
@@ -138,7 +138,7 @@ Transform2D Camera2D::get_camera_transform() {
if (smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) {
- float c = smoothing * get_fixed_process_delta_time();
+ float c = smoothing * get_physics_process_delta_time();
smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;
ret_camera_pos = smoothed_camera_pos;
//camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
@@ -212,14 +212,14 @@ void Camera2D::_notification(int p_what) {
switch (p_what) {
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
_update_scroll();
} break;
case NOTIFICATION_TRANSFORM_CHANGED: {
- if (!is_fixed_processing())
+ if (!is_physics_processing())
_update_scroll();
} break;
@@ -241,7 +241,7 @@ void Camera2D::_notification(int p_what) {
add_to_group(canvas_group_name);
if (Engine::get_singleton()->is_editor_hint()) {
- set_fixed_process(false);
+ set_physics_process(false);
}
_update_scroll();
@@ -452,7 +452,7 @@ float Camera2D::get_drag_margin(Margin p_margin) const {
return drag_margin[p_margin];
}
-Vector2 Camera2D::get_camera_pos() const {
+Vector2 Camera2D::get_camera_position() const {
return camera_pos;
}
@@ -498,9 +498,9 @@ void Camera2D::set_follow_smoothing(float p_speed) {
smoothing = p_speed;
if (smoothing > 0 && !(is_inside_tree() && Engine::get_singleton()->is_editor_hint()))
- set_fixed_process(true);
+ set_physics_process(true);
else
- set_fixed_process(false);
+ set_physics_process(false);
}
float Camera2D::get_follow_smoothing() const {
@@ -673,7 +673,7 @@ void Camera2D::_bind_methods() {
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(D_METHOD("get_camera_pos"), &Camera2D::get_camera_pos);
+ ClassDB::bind_method(D_METHOD("get_camera_position"), &Camera2D::get_camera_position);
ClassDB::bind_method(D_METHOD("get_camera_screen_center"), &Camera2D::get_camera_screen_center);
ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &Camera2D::set_zoom);
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index dfcadf65a6..13b6be3978 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -137,7 +137,7 @@ public:
void set_custom_viewport(Node *p_viewport);
Node *get_custom_viewport() const;
- Vector2 get_camera_pos() const;
+ Vector2 get_camera_position() const;
void force_update_scroll();
void reset_smoothing();
void align();
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index ec1ea7df38..d9bb6576d9 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -902,7 +902,7 @@ Ref<Material> CanvasItem::get_material() const {
return material;
}
-Vector2 CanvasItem::make_canvas_pos_local(const Vector2 &screen_point) const {
+Vector2 CanvasItem::make_canvas_position_local(const Vector2 &screen_point) const {
ERR_FAIL_COND_V(!is_inside_tree(), screen_point);
@@ -923,7 +923,8 @@ Vector2 CanvasItem::get_global_mouse_position() const {
ERR_FAIL_COND_V(!get_viewport(), Vector2());
return get_canvas_transform().affine_inverse().xform(get_viewport()->get_mouse_position());
}
-Vector2 CanvasItem::get_local_mouse_pos() const {
+
+Vector2 CanvasItem::get_local_mouse_position() const {
ERR_FAIL_COND_V(!get_viewport(), Vector2());
@@ -976,18 +977,18 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled"), &CanvasItem::draw_rect, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("draw_circle", "pos", "radius", "color"), &CanvasItem::draw_circle);
- ClassDB::bind_method(D_METHOD("draw_texture", "texture", "pos", "modulate", "normal_map"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::draw_circle);
+ ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate", "normal_map"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose", "normal_map"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true));
ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box);
ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width", "normal_map"), &CanvasItem::draw_primitive, DEFVAL(Variant()), DEFVAL(1.0), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &CanvasItem::draw_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture", "normal_map", "antialiased"), &CanvasItem::draw_colored_polygon, DEFVAL(PoolVector2Array()), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("draw_char", "font", "pos", "char", "next", "modulate"), &CanvasItem::draw_char, DEFVAL(Color(1, 1, 1)));
+ ClassDB::bind_method(D_METHOD("draw_string", "font", "position", "text", "modulate", "clip_w"), &CanvasItem::draw_string, DEFVAL(Color(1, 1, 1)), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("draw_char", "font", "position", "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", "position", "rotation", "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);
@@ -995,7 +996,7 @@ void CanvasItem::_bind_methods() {
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_local_mouse_position"), &CanvasItem::get_local_mouse_position);
ClassDB::bind_method(D_METHOD("get_global_mouse_position"), &CanvasItem::get_global_mouse_position);
ClassDB::bind_method(D_METHOD("get_canvas"), &CanvasItem::get_canvas);
ClassDB::bind_method(D_METHOD("get_world_2d"), &CanvasItem::get_world_2d);
@@ -1013,8 +1014,7 @@ void CanvasItem::_bind_methods() {
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(D_METHOD("make_canvas_position_local", "screen_point"), &CanvasItem::make_canvas_position_local);
ClassDB::bind_method(D_METHOD("make_input_local", "event"), &CanvasItem::make_input_local);
BIND_VMETHOD(MethodInfo("_draw"));
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index 5a0a9c6e6a..1afbd150a2 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -298,10 +298,10 @@ public:
bool get_use_parent_material() const;
Ref<InputEvent> make_input_local(const Ref<InputEvent> &p_event) const;
- Vector2 make_canvas_pos_local(const Vector2 &screen_point) const;
+ Vector2 make_canvas_position_local(const Vector2 &screen_point) const;
Vector2 get_global_mouse_position() const;
- Vector2 get_local_mouse_pos() const;
+ Vector2 get_local_mouse_position() const;
void set_notify_local_transform(bool p_enable);
bool is_local_transform_notification_enabled() const;
diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp
index ce56b85a9e..73e5dc6021 100644
--- a/scene/2d/collision_object_2d.cpp
+++ b/scene/2d/collision_object_2d.cpp
@@ -82,7 +82,7 @@ uint32_t CollisionObject2D::create_shape_owner(Object *p_owner) {
uint32_t id;
if (shapes.size() == 0) {
- id = 1;
+ id = 0;
} else {
id = shapes.back()->key() + 1;
}
diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp
index d8cef5b937..9131223ff3 100644
--- a/scene/2d/line_2d.cpp
+++ b/scene/2d/line_2d.cpp
@@ -68,12 +68,12 @@ PoolVector<Vector2> Line2D::get_points() const {
return _points;
}
-void Line2D::set_point_pos(int i, Vector2 pos) {
+void Line2D::set_point_position(int i, Vector2 pos) {
_points.set(i, pos);
update();
}
-Vector2 Line2D::get_point_pos(int i) const {
+Vector2 Line2D::get_point_position(int i) const {
return _points.get(i);
}
@@ -270,12 +270,12 @@ 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("set_point_position", "i", "position"), &Line2D::set_point_position);
+ ClassDB::bind_method(D_METHOD("get_point_position", "i"), &Line2D::get_point_position);
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("add_point", "position"), &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);
diff --git a/scene/2d/line_2d.h b/scene/2d/line_2d.h
index 36aadfd265..6426484f02 100644
--- a/scene/2d/line_2d.h
+++ b/scene/2d/line_2d.h
@@ -60,8 +60,8 @@ public:
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;
+ void set_point_position(int i, Vector2 pos);
+ Vector2 get_point_position(int i) const;
int get_point_count() const;
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index 0c7685a858..e62b59dd4d 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -414,7 +414,7 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("_get_rotd"), &Node2D::_get_rotd);
ClassDB::bind_method(D_METHOD("_set_rotd", "degrees"), &Node2D::_set_rotd);
- ClassDB::bind_method(D_METHOD("set_position", "pos"), &Node2D::set_position);
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &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);
@@ -431,7 +431,7 @@ void Node2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("global_translate", "offset"), &Node2D::global_translate);
ClassDB::bind_method(D_METHOD("apply_scale", "ratio"), &Node2D::apply_scale);
- ClassDB::bind_method(D_METHOD("set_global_position", "pos"), &Node2D::set_global_position);
+ ClassDB::bind_method(D_METHOD("set_global_position", "position"), &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);
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 9bd5576d91..8413be1ca9 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -43,7 +43,7 @@ void Path2D::_notification(int p_what) {
for (int i = 0; i < curve->get_point_count(); i++) {
- Vector2 prev_p = curve->get_point_pos(i);
+ Vector2 prev_p = curve->get_point_position(i);
for (int j = 1; j <= 8; j++) {
diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp
index c6cd3677cd..d3b37ae903 100644
--- a/scene/2d/physics_body_2d.cpp
+++ b/scene/2d/physics_body_2d.cpp
@@ -999,7 +999,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, Collision &r_col
Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
- Vector2 motion = (floor_velocity + p_linear_velocity) * get_fixed_process_delta_time();
+ Vector2 motion = (floor_velocity + p_linear_velocity) * get_physics_process_delta_time();
Vector2 lv = p_linear_velocity;
on_floor = false;
diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp
index f90331c411..b272da46f8 100644
--- a/scene/2d/ray_cast_2d.cpp
+++ b/scene/2d/ray_cast_2d.cpp
@@ -95,7 +95,7 @@ void RayCast2D::set_enabled(bool p_enabled) {
enabled = p_enabled;
if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint())
- set_fixed_process(p_enabled);
+ set_physics_process(p_enabled);
if (!p_enabled)
collided = false;
}
@@ -135,9 +135,9 @@ void RayCast2D::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled && !Engine::get_singleton()->is_editor_hint())
- set_fixed_process(true);
+ set_physics_process(true);
else
- set_fixed_process(false);
+ set_physics_process(false);
if (Object::cast_to<PhysicsBody2D>(get_parent())) {
if (exclude_parent_body)
@@ -149,7 +149,7 @@ void RayCast2D::_notification(int p_what) {
case NOTIFICATION_EXIT_TREE: {
if (enabled)
- set_fixed_process(false);
+ set_physics_process(false);
} break;
@@ -177,7 +177,7 @@ void RayCast2D::_notification(int p_what) {
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
if (!enabled)
break;
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index b1cc8c226a..4286d88ab1 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -1294,9 +1294,9 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_occluder_light_mask"), &TileMap::get_occluder_light_mask);
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("set_cellv", "position", "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("get_cellv", "position"), &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);
@@ -1307,8 +1307,8 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_used_cells_by_id", "id"), &TileMap::get_used_cells_by_id);
ClassDB::bind_method(D_METHOD("get_used_rect"), &TileMap::get_used_rect);
- 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(D_METHOD("map_to_world", "map_position", "ignore_half_ofs"), &TileMap::map_to_world, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("world_to_map", "world_position"), &TileMap::world_to_map);
ClassDB::bind_method(D_METHOD("_clear_quadrants"), &TileMap::_clear_quadrants);
ClassDB::bind_method(D_METHOD("_recreate_quadrants"), &TileMap::_recreate_quadrants);
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index 8fc8b65217..ca7b6aa0e4 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -154,8 +154,8 @@ void VisibilityEnabler2D::_screen_enter() {
_change_node_state(E->key(), true);
}
- if (enabler[ENABLER_PARENT_FIXED_PROCESS] && get_parent())
- get_parent()->set_fixed_process(true);
+ if (enabler[ENABLER_PARENT_PHYSICS_PROCESS] && get_parent())
+ get_parent()->set_physics_process(true);
if (enabler[ENABLER_PARENT_PROCESS] && get_parent())
get_parent()->set_process(true);
@@ -169,8 +169,8 @@ void VisibilityEnabler2D::_screen_exit() {
_change_node_state(E->key(), false);
}
- if (enabler[ENABLER_PARENT_FIXED_PROCESS] && get_parent())
- get_parent()->set_fixed_process(false);
+ if (enabler[ENABLER_PARENT_PHYSICS_PROCESS] && get_parent())
+ get_parent()->set_physics_process(false);
if (enabler[ENABLER_PARENT_PROCESS] && get_parent())
get_parent()->set_process(false);
@@ -246,8 +246,8 @@ void VisibilityEnabler2D::_notification(int p_what) {
_find_nodes(from);
- if (enabler[ENABLER_PARENT_FIXED_PROCESS] && get_parent())
- get_parent()->set_fixed_process(false);
+ if (enabler[ENABLER_PARENT_PHYSICS_PROCESS] && get_parent())
+ get_parent()->set_physics_process(false);
if (enabler[ENABLER_PARENT_PROCESS] && get_parent())
get_parent()->set_process(false);
}
@@ -339,14 +339,14 @@ void VisibilityEnabler2D::_bind_methods() {
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);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "physics_process_parent"), "set_enabler", "is_enabler_enabled", ENABLER_PARENT_PHYSICS_PROCESS);
BIND_ENUM_CONSTANT(ENABLER_FREEZE_BODIES);
BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATIONS);
BIND_ENUM_CONSTANT(ENABLER_PAUSE_PARTICLES);
BIND_ENUM_CONSTANT(ENABLER_PAUSE_ANIMATED_SPRITES);
BIND_ENUM_CONSTANT(ENABLER_PARENT_PROCESS);
- BIND_ENUM_CONSTANT(ENABLER_PARENT_FIXED_PROCESS);
+ BIND_ENUM_CONSTANT(ENABLER_PARENT_PHYSICS_PROCESS);
BIND_ENUM_CONSTANT(ENABLER_MAX);
}
@@ -366,7 +366,7 @@ VisibilityEnabler2D::VisibilityEnabler2D() {
for (int i = 0; i < ENABLER_MAX; i++)
enabler[i] = true;
enabler[ENABLER_PARENT_PROCESS] = false;
- enabler[ENABLER_PARENT_FIXED_PROCESS] = false;
+ enabler[ENABLER_PARENT_PHYSICS_PROCESS] = false;
visible = false;
}
diff --git a/scene/2d/visibility_notifier_2d.h b/scene/2d/visibility_notifier_2d.h
index ef0e1affd3..ee5152978b 100644
--- a/scene/2d/visibility_notifier_2d.h
+++ b/scene/2d/visibility_notifier_2d.h
@@ -74,7 +74,7 @@ public:
ENABLER_FREEZE_BODIES,
ENABLER_PAUSE_PARTICLES,
ENABLER_PARENT_PROCESS,
- ENABLER_PARENT_FIXED_PROCESS,
+ ENABLER_PARENT_PHYSICS_PROCESS,
ENABLER_PAUSE_ANIMATED_SPRITES,
ENABLER_MAX
};
diff --git a/scene/3d/SCsub b/scene/3d/SCsub
index 90e78ba8d3..72739b527e 100644
--- a/scene/3d/SCsub
+++ b/scene/3d/SCsub
@@ -3,7 +3,7 @@
Import('env')
-if (env["disable_3d"] == "yes"):
+if env['disable_3d']:
env.scene_sources.append("3d/spatial.cpp")
env.scene_sources.append("3d/skeleton.cpp")
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index b8c6a86f55..3c92814c87 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -214,7 +214,7 @@ void AudioStreamPlayer3D::_notification(int p_what) {
}
}
- if (p_what == NOTIFICATION_INTERNAL_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_INTERNAL_PHYSICS_PROCESS) {
//update anything related to position first, if possible of course
@@ -512,7 +512,7 @@ void AudioStreamPlayer3D::_notification(int p_what) {
//stop playing if no longer active
if (!active) {
- set_fixed_process_internal(false);
+ set_physics_process_internal(false);
//do not update, this makes it easier to animate (will shut off otherise)
//_change_notify("playing"); //update property in editor
emit_signal("finished");
@@ -582,7 +582,7 @@ void AudioStreamPlayer3D::play(float p_from_pos) {
if (stream_playback.is_valid()) {
setplay = p_from_pos;
output_ready = false;
- set_fixed_process_internal(true);
+ set_physics_process_internal(true);
}
}
@@ -597,7 +597,7 @@ void AudioStreamPlayer3D::stop() {
if (stream_playback.is_valid()) {
active = false;
- set_fixed_process_internal(false);
+ set_physics_process_internal(false);
setplay = -1;
}
}
@@ -611,10 +611,10 @@ bool AudioStreamPlayer3D::is_playing() const {
return false;
}
-float AudioStreamPlayer3D::get_pos() {
+float AudioStreamPlayer3D::get_playback_position() {
if (stream_playback.is_valid()) {
- return stream_playback->get_pos();
+ return stream_playback->get_playback_position();
}
return 0;
@@ -776,7 +776,7 @@ void AudioStreamPlayer3D::set_doppler_tracking(DopplerTracking p_tracking) {
if (doppler_tracking != DOPPLER_TRACKING_DISABLED) {
set_notify_transform(true);
- velocity_tracker->set_track_fixed_step(doppler_tracking == DOPPLER_TRACKING_FIXED_STEP);
+ velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP);
velocity_tracker->reset(get_global_transform().origin);
} else {
set_notify_transform(false);
@@ -802,12 +802,12 @@ void AudioStreamPlayer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_max_db", "max_db"), &AudioStreamPlayer3D::set_max_db);
ClassDB::bind_method(D_METHOD("get_max_db"), &AudioStreamPlayer3D::get_max_db);
- ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer3D::play, DEFVAL(0.0));
- ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer3D::seek);
+ ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer3D::play, DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer3D::seek);
ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer3D::stop);
ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer3D::is_playing);
- ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer3D::get_pos);
+ ClassDB::bind_method(D_METHOD("get_playback_position"), &AudioStreamPlayer3D::get_playback_position);
ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer3D::set_bus);
ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer3D::get_bus);
@@ -880,7 +880,7 @@ void AudioStreamPlayer3D::_bind_methods() {
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_DISABLED);
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_IDLE_STEP);
- BIND_ENUM_CONSTANT(DOPPLER_TRACKING_FIXED_STEP);
+ BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP);
ADD_SIGNAL(MethodInfo("finished"));
}
diff --git a/scene/3d/audio_stream_player_3d.h b/scene/3d/audio_stream_player_3d.h
index b729b55f7e..5982d7a3ac 100644
--- a/scene/3d/audio_stream_player_3d.h
+++ b/scene/3d/audio_stream_player_3d.h
@@ -26,7 +26,7 @@ public:
enum DopplerTracking {
DOPPLER_TRACKING_DISABLED,
DOPPLER_TRACKING_IDLE_STEP,
- DOPPLER_TRACKING_FIXED_STEP
+ DOPPLER_TRACKING_PHYSICS_STEP
};
private:
@@ -127,7 +127,7 @@ public:
void seek(float p_seconds);
void stop();
bool is_playing() const;
- float get_pos();
+ float get_playback_position();
void set_bus(const StringName &p_bus);
StringName get_bus() const;
diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp
index 02a7845e0b..7baf9a9deb 100644
--- a/scene/3d/camera.cpp
+++ b/scene/3d/camera.cpp
@@ -507,7 +507,7 @@ void Camera::set_doppler_tracking(DopplerTracking p_tracking) {
doppler_tracking = p_tracking;
if (p_tracking != DOPPLER_TRACKING_DISABLED) {
- velocity_tracker->set_track_fixed_step(doppler_tracking == DOPPLER_TRACKING_FIXED_STEP);
+ velocity_tracker->set_track_physics_step(doppler_tracking == DOPPLER_TRACKING_PHYSICS_STEP);
velocity_tracker->reset(get_global_transform().origin);
}
}
@@ -557,7 +557,7 @@ void Camera::_bind_methods() {
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_DISABLED)
BIND_ENUM_CONSTANT(DOPPLER_TRACKING_IDLE_STEP)
- BIND_ENUM_CONSTANT(DOPPLER_TRACKING_FIXED_STEP)
+ BIND_ENUM_CONSTANT(DOPPLER_TRACKING_PHYSICS_STEP)
}
float Camera::get_fov() const {
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index 243a7b9b39..3a725eaf66 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -56,7 +56,7 @@ public:
enum DopplerTracking {
DOPPLER_TRACKING_DISABLED,
DOPPLER_TRACKING_IDLE_STEP,
- DOPPLER_TRACKING_FIXED_STEP
+ DOPPLER_TRACKING_PHYSICS_STEP
};
private:
diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp
index c121ef4566..7b4770e435 100644
--- a/scene/3d/collision_object.cpp
+++ b/scene/3d/collision_object.cpp
@@ -145,9 +145,9 @@ void CollisionObject::_bind_methods() {
ClassDB::bind_method(D_METHOD("shape_owner_clear_shapes", "owner_id"), &CollisionObject::shape_owner_clear_shapes);
ClassDB::bind_method(D_METHOD("shape_find_owner", "shape_index"), &CollisionObject::shape_find_owner);
- BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_pos"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
+ BIND_VMETHOD(MethodInfo("_input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
- ADD_SIGNAL(MethodInfo("input_event", PropertyInfo(Variant::OBJECT, "camera"), PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), 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::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), PropertyInfo(Variant::VECTOR3, "click_position"), PropertyInfo(Variant::VECTOR3, "click_normal"), PropertyInfo(Variant::INT, "shape_idx")));
ADD_SIGNAL(MethodInfo("mouse_entered"));
ADD_SIGNAL(MethodInfo("mouse_exited"));
@@ -161,7 +161,7 @@ uint32_t CollisionObject::create_shape_owner(Object *p_owner) {
uint32_t id;
if (shapes.size() == 0) {
- id = 1;
+ id = 0;
} else {
id = shapes.back()->key() + 1;
}
diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp
index 64d3f4fcab..11f7efe066 100644
--- a/scene/3d/immediate_geometry.cpp
+++ b/scene/3d/immediate_geometry.cpp
@@ -149,7 +149,7 @@ void ImmediateGeometry::_bind_methods() {
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_vertex", "position"), &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/immediate_geometry.h b/scene/3d/immediate_geometry.h
index 6db825bf54..93ef726c6d 100644
--- a/scene/3d/immediate_geometry.h
+++ b/scene/3d/immediate_geometry.h
@@ -38,7 +38,7 @@ class ImmediateGeometry : public GeometryInstance {
GDCLASS(ImmediateGeometry, GeometryInstance);
RID im;
- //a list of texures drawn need to be kept, to avoid references
+ //a list of textures drawn need to be kept, to avoid references
// in VisualServer from becoming invalid if the texture is no longer used
List<Ref<Texture> > cached_textures;
bool empty;
diff --git a/scene/3d/interpolated_camera.cpp b/scene/3d/interpolated_camera.cpp
index 0f281b694d..3ff8317732 100644
--- a/scene/3d/interpolated_camera.cpp
+++ b/scene/3d/interpolated_camera.cpp
@@ -37,7 +37,7 @@ void InterpolatedCamera::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
if (Engine::get_singleton()->is_editor_hint() && enabled)
- set_fixed_process(false);
+ set_physics_process(false);
} break;
case NOTIFICATION_PROCESS: {
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index 7402e664d9..b7cd9bd2dc 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -369,6 +369,12 @@ DirectionalLight::DirectionalLight()
set_shadow_depth_range(SHADOW_DEPTH_RANGE_STABLE);
blend_splits = false;
+
+#ifdef TOOLS_ENABLED
+ if (Engine::get_singleton()->is_editor_hint())
+ // Create light with a default natural "sun" orientation in editor, instead of looking horizontally on X
+ set_rotation_in_degrees(Vector3(-50, 25, 30));
+#endif
}
void OmniLight::set_shadow_mode(ShadowMode p_mode) {
diff --git a/scene/3d/light.h b/scene/3d/light.h
index 6aa0220265..2f3ac8a5e7 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -150,7 +150,7 @@ public:
void set_shadow_mode(ShadowMode p_mode);
ShadowMode get_shadow_mode() const;
- void set_shadow_depth_range(ShadowDepthRange p_mode);
+ void set_shadow_depth_range(ShadowDepthRange p_range);
ShadowDepthRange get_shadow_depth_range() const;
void set_blend_splits(bool p_enable);
diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp
index 6551deabf2..d7fdf94d40 100644
--- a/scene/3d/physics_body.cpp
+++ b/scene/3d/physics_body.cpp
@@ -825,7 +825,7 @@ void RigidBody::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidBody::is_using_continuous_collision_detection);
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(D_METHOD("apply_impulse", "position", "impulse"), &RigidBody::apply_impulse);
ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody::set_sleeping);
ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody::is_sleeping);
@@ -960,7 +960,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, Collision &r_colli
Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction, float p_slope_stop_min_velocity, int p_max_slides, float p_floor_max_angle) {
- Vector3 motion = (floor_velocity + p_linear_velocity) * get_fixed_process_delta_time();
+ Vector3 motion = (floor_velocity + p_linear_velocity) * get_physics_process_delta_time();
Vector3 lv = p_linear_velocity;
on_floor = false;
diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp
index 72b7706b77..df6764ee1a 100644
--- a/scene/3d/ray_cast.cpp
+++ b/scene/3d/ray_cast.cpp
@@ -97,7 +97,7 @@ void RayCast::set_enabled(bool p_enabled) {
enabled = p_enabled;
if (is_inside_tree() && !Engine::get_singleton()->is_editor_hint())
- set_fixed_process(p_enabled);
+ set_physics_process(p_enabled);
if (!p_enabled)
collided = false;
@@ -121,25 +121,25 @@ void RayCast::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE: {
if (enabled && !Engine::get_singleton()->is_editor_hint()) {
- set_fixed_process(true);
+ set_physics_process(true);
if (get_tree()->is_debugging_collisions_hint())
_update_debug_shape();
} else
- set_fixed_process(false);
+ set_physics_process(false);
} break;
case NOTIFICATION_EXIT_TREE: {
if (enabled) {
- set_fixed_process(false);
+ set_physics_process(false);
}
if (debug_shape)
_clear_debug_shape();
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
if (!enabled)
break;
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index 91fe426b99..0dfd80ca90 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -651,7 +651,7 @@ void Spatial::look_at(const Vector3 &p_target, const Vector3 &p_up_normal) {
set_global_transform(lookat);
}
-void Spatial::look_at_from_pos(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up_normal) {
+void Spatial::look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up_normal) {
Transform lookat;
lookat.origin = p_pos;
@@ -749,7 +749,7 @@ void Spatial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_identity"), &Spatial::set_identity);
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);
+ ClassDB::bind_method(D_METHOD("look_at_from_position", "position", "target", "up"), &Spatial::look_at_from_position);
ClassDB::bind_method(D_METHOD("to_local", "global_point"), &Spatial::to_local);
ClassDB::bind_method(D_METHOD("to_global", "local_point"), &Spatial::to_global);
diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h
index 3f205ea86b..b912d1f906 100644
--- a/scene/3d/spatial.h
+++ b/scene/3d/spatial.h
@@ -172,7 +172,7 @@ public:
void global_translate(const Vector3 &p_offset);
void look_at(const Vector3 &p_target, const Vector3 &p_up_normal);
- void look_at_from_pos(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up_normal);
+ void look_at_from_position(const Vector3 &p_pos, const Vector3 &p_target, const Vector3 &p_up_normal);
Vector3 to_local(Vector3 p_global) const;
Vector3 to_global(Vector3 p_local) const;
diff --git a/scene/3d/spatial_velocity_tracker.cpp b/scene/3d/spatial_velocity_tracker.cpp
index dc822d0446..1c7423e645 100644
--- a/scene/3d/spatial_velocity_tracker.cpp
+++ b/scene/3d/spatial_velocity_tracker.cpp
@@ -1,21 +1,21 @@
#include "spatial_velocity_tracker.h"
#include "engine.h"
-void SpatialVelocityTracker::set_track_fixed_step(bool p_track_fixed_step) {
+void SpatialVelocityTracker::set_track_physics_step(bool p_track_physics_step) {
- fixed_step = p_track_fixed_step;
+ physics_step = p_track_physics_step;
}
-bool SpatialVelocityTracker::is_tracking_fixed_step() const {
+bool SpatialVelocityTracker::is_tracking_physics_step() const {
- return fixed_step;
+ return physics_step;
}
void SpatialVelocityTracker::update_position(const Vector3 &p_position) {
PositionHistory ph;
ph.position = p_position;
- if (fixed_step) {
- ph.frame = Engine::get_singleton()->get_fixed_frames();
+ if (physics_step) {
+ ph.frame = Engine::get_singleton()->get_physics_frames();
} else {
ph.frame = Engine::get_singleton()->get_idle_frame_ticks();
}
@@ -40,8 +40,8 @@ Vector3 SpatialVelocityTracker::get_tracked_linear_velocity() const {
float base_time = 0.0;
if (position_history_len) {
- if (fixed_step) {
- uint64_t base = Engine::get_singleton()->get_fixed_frames();
+ if (physics_step) {
+ uint64_t base = Engine::get_singleton()->get_physics_frames();
base_time = float(base - position_history[0].frame) / Engine::get_singleton()->get_iterations_per_second();
} else {
uint64_t base = Engine::get_singleton()->get_idle_frame_ticks();
@@ -54,7 +54,7 @@ Vector3 SpatialVelocityTracker::get_tracked_linear_velocity() const {
uint64_t diff = position_history[i].frame - position_history[i + 1].frame;
Vector3 distance = position_history[i].position - position_history[i + 1].position;
- if (fixed_step) {
+ if (physics_step) {
delta = float(diff) / Engine::get_singleton()->get_iterations_per_second();
} else {
delta = double(diff) / 1000000.0;
@@ -78,8 +78,8 @@ void SpatialVelocityTracker::reset(const Vector3 &p_new_pos) {
PositionHistory ph;
ph.position = p_new_pos;
- if (fixed_step) {
- ph.frame = Engine::get_singleton()->get_fixed_frames();
+ if (physics_step) {
+ ph.frame = Engine::get_singleton()->get_physics_frames();
} else {
ph.frame = Engine::get_singleton()->get_idle_frame_ticks();
}
@@ -90,8 +90,8 @@ void SpatialVelocityTracker::reset(const Vector3 &p_new_pos) {
void SpatialVelocityTracker::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_track_fixed_step", "enable"), &SpatialVelocityTracker::set_track_fixed_step);
- ClassDB::bind_method(D_METHOD("is_tracking_fixed_step"), &SpatialVelocityTracker::is_tracking_fixed_step);
+ ClassDB::bind_method(D_METHOD("set_track_physics_step", "enable"), &SpatialVelocityTracker::set_track_physics_step);
+ ClassDB::bind_method(D_METHOD("is_tracking_physics_step"), &SpatialVelocityTracker::is_tracking_physics_step);
ClassDB::bind_method(D_METHOD("update_position", "position"), &SpatialVelocityTracker::update_position);
ClassDB::bind_method(D_METHOD("get_tracked_linear_velocity"), &SpatialVelocityTracker::get_tracked_linear_velocity);
ClassDB::bind_method(D_METHOD("reset", "position"), &SpatialVelocityTracker::reset);
@@ -100,5 +100,5 @@ void SpatialVelocityTracker::_bind_methods() {
SpatialVelocityTracker::SpatialVelocityTracker() {
position_history.resize(4); // should be configurable
position_history_len = 0;
- fixed_step = false;
+ physics_step = false;
}
diff --git a/scene/3d/spatial_velocity_tracker.h b/scene/3d/spatial_velocity_tracker.h
index b8237613a7..c4371ff1f7 100644
--- a/scene/3d/spatial_velocity_tracker.h
+++ b/scene/3d/spatial_velocity_tracker.h
@@ -11,7 +11,7 @@ class SpatialVelocityTracker : public Reference {
Vector3 position;
};
- bool fixed_step;
+ bool physics_step;
Vector<PositionHistory> position_history;
int position_history_len;
@@ -20,8 +20,8 @@ protected:
public:
void reset(const Vector3 &p_new_pos);
- void set_track_fixed_step(bool p_track_fixed_step);
- bool is_tracking_fixed_step() const;
+ void set_track_physics_step(bool p_track_physics_step);
+ bool is_tracking_physics_step() const;
void update_position(const Vector3 &p_position);
Vector3 get_tracked_linear_velocity() const;
diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp
index 3518113130..a072572142 100644
--- a/scene/3d/vehicle_body.cpp
+++ b/scene/3d/vehicle_body.cpp
@@ -267,6 +267,8 @@ void VehicleWheel::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_roll_influence", "roll_influence"), &VehicleWheel::set_roll_influence);
ClassDB::bind_method(D_METHOD("get_roll_influence"), &VehicleWheel::get_roll_influence);
+ ClassDB::bind_method(D_METHOD("get_skidinfo"), &VehicleWheel::get_skidinfo);
+
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_");
@@ -303,6 +305,11 @@ bool VehicleWheel::is_used_as_steering() const {
return steers;
}
+float VehicleWheel::get_skidinfo() const {
+
+ return m_skidInfo;
+}
+
VehicleWheel::VehicleWheel() {
steers = false;
diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h
index eb661adb90..c642eb61b8 100644
--- a/scene/3d/vehicle_body.h
+++ b/scene/3d/vehicle_body.h
@@ -131,6 +131,8 @@ public:
void set_roll_influence(float p_value);
float get_roll_influence() const;
+ float get_skidinfo() const;
+
String get_configuration_warning() const;
VehicleWheel();
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index be0b652276..a38bee1b43 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -192,7 +192,7 @@ void AnimationPlayer::_notification(int p_what) {
if (!processing) {
//make sure that a previous process state was not saved
//only process if "processing" is set
- set_fixed_process(false);
+ set_physics_process(false);
set_process(false);
}
//_set_process(false);
@@ -207,19 +207,19 @@ void AnimationPlayer::_notification(int p_what) {
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- if (animation_process_mode == ANIMATION_PROCESS_FIXED)
+ if (animation_process_mode == ANIMATION_PROCESS_PHYSICS)
break;
if (processing)
_animation_process(get_process_delta_time());
} break;
- case NOTIFICATION_INTERNAL_FIXED_PROCESS: {
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (animation_process_mode == ANIMATION_PROCESS_IDLE)
break;
if (processing)
- _animation_process(get_fixed_process_delta_time());
+ _animation_process(get_physics_process_delta_time());
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -1045,7 +1045,7 @@ bool AnimationPlayer::is_valid() const {
return (playback.current.from);
}
-float AnimationPlayer::get_current_animation_pos() const {
+float AnimationPlayer::get_current_animation_position() const {
ERR_FAIL_COND_V(!playback.current.from, 0);
return playback.current.pos;
@@ -1140,7 +1140,7 @@ void AnimationPlayer::_set_process(bool p_process, bool p_force) {
switch (animation_process_mode) {
- case ANIMATION_PROCESS_FIXED: set_fixed_process_internal(p_process && active); break;
+ case ANIMATION_PROCESS_PHYSICS: set_physics_process_internal(p_process && active); break;
case ANIMATION_PROCESS_IDLE: set_process_internal(p_process && active); break;
}
@@ -1238,8 +1238,8 @@ void AnimationPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_root", "path"), &AnimationPlayer::set_root);
ClassDB::bind_method(D_METHOD("get_root"), &AnimationPlayer::get_root);
- 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(D_METHOD("seek", "seconds", "update"), &AnimationPlayer::seek, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_position"), &AnimationPlayer::get_current_animation_position);
ClassDB::bind_method(D_METHOD("find_animation", "animation"), &AnimationPlayer::find_animation);
@@ -1248,7 +1248,7 @@ void AnimationPlayer::_bind_methods() {
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(D_METHOD("get_current_animation_pos"), &AnimationPlayer::get_current_animation_pos);
+ ClassDB::bind_method(D_METHOD("get_current_animation_position"), &AnimationPlayer::get_current_animation_position);
ClassDB::bind_method(D_METHOD("get_current_animation_length"), &AnimationPlayer::get_current_animation_length);
ClassDB::bind_method(D_METHOD("advance", "delta"), &AnimationPlayer::advance);
@@ -1262,7 +1262,7 @@ void AnimationPlayer::_bind_methods() {
ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING, "old_name"), PropertyInfo(Variant::STRING, "new_name")));
ADD_SIGNAL(MethodInfo("animation_started", PropertyInfo(Variant::STRING, "name")));
- BIND_ENUM_CONSTANT(ANIMATION_PROCESS_FIXED);
+ BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS);
BIND_ENUM_CONSTANT(ANIMATION_PROCESS_IDLE);
}
diff --git a/scene/animation/animation_player.h b/scene/animation/animation_player.h
index c6e52145a8..83da3b2e5c 100644
--- a/scene/animation/animation_player.h
+++ b/scene/animation/animation_player.h
@@ -44,7 +44,7 @@ class AnimationPlayer : public Node {
public:
enum AnimationProcessMode {
- ANIMATION_PROCESS_FIXED,
+ ANIMATION_PROCESS_PHYSICS,
ANIMATION_PROCESS_IDLE,
};
@@ -279,7 +279,7 @@ public:
void seek(float p_time, bool p_update = false);
void seek_delta(float p_time, float p_delta);
- float get_current_animation_pos() const;
+ float get_current_animation_position() const;
float get_current_animation_length() const;
void advance(float p_time);
diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp
index 38d0527288..d564671bcf 100644
--- a/scene/animation/animation_tree_player.cpp
+++ b/scene/animation/animation_tree_player.cpp
@@ -56,7 +56,7 @@ void AnimationTreePlayer::_set_process(bool p_process, bool p_force) {
switch (animation_process_mode) {
- case ANIMATION_PROCESS_FIXED: set_fixed_process_internal(p_process && active); break;
+ case ANIMATION_PROCESS_PHYSICS: set_physics_process_internal(p_process && active); break;
case ANIMATION_PROCESS_IDLE: set_process_internal(p_process && active); break;
}
@@ -92,7 +92,7 @@ bool AnimationTreePlayer::_set(const StringName &p_name, const Variant &p_value)
Dictionary node = nodes[i];
StringName id = node.get_valid("id");
- Point2 pos = node.get_valid("pos");
+ Point2 pos = node.get_valid("position");
NodeType nt = NODE_MAX;
String type = node.get_valid("type");
@@ -122,7 +122,7 @@ bool AnimationTreePlayer::_set(const StringName &p_name, const Variant &p_value)
if (nt != NODE_OUTPUT)
add_node(nt, id);
- node_set_pos(id, pos);
+ node_set_position(id, pos);
switch (nt) {
case NODE_OUTPUT: {
@@ -245,7 +245,7 @@ bool AnimationTreePlayer::_get(const StringName &p_name, Variant &r_ret) const {
Dictionary node;
node["id"] = E->key();
- node["pos"] = n->pos;
+ node["position"] = n->pos;
switch (n->type) {
case NODE_OUTPUT: node["type"] = "output"; break;
@@ -405,7 +405,7 @@ void AnimationTreePlayer::_notification(int p_what) {
if (!processing) {
//make sure that a previous process state was not saved
//only process if "processing" is set
- set_fixed_process_internal(false);
+ set_physics_process_internal(false);
set_process_internal(false);
}
} break;
@@ -416,19 +416,19 @@ void AnimationTreePlayer::_notification(int p_what) {
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- if (animation_process_mode == ANIMATION_PROCESS_FIXED)
+ if (animation_process_mode == ANIMATION_PROCESS_PHYSICS)
break;
if (processing)
_process_animation(get_process_delta_time());
} break;
- case NOTIFICATION_INTERNAL_FIXED_PROCESS: {
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (animation_process_mode == ANIMATION_PROCESS_IDLE)
break;
if (processing)
- _process_animation(get_fixed_process_delta_time());
+ _process_animation(get_physics_process_delta_time());
} break;
}
}
@@ -1176,7 +1176,7 @@ void AnimationTreePlayer::transition_node_set_current(const StringName &p_node,
n->set_current(p_current);
}
-void AnimationTreePlayer::node_set_pos(const StringName &p_node, const Vector2 &p_pos) {
+void AnimationTreePlayer::node_set_position(const StringName &p_node, const Vector2 &p_pos) {
ERR_FAIL_COND(!node_map.has(p_node));
node_map[p_node]->pos = p_pos;
@@ -1187,7 +1187,7 @@ AnimationTreePlayer::NodeType AnimationTreePlayer::node_get_type(const StringNam
ERR_FAIL_COND_V(!node_map.has(p_node), NODE_OUTPUT);
return node_map[p_node]->type;
}
-Point2 AnimationTreePlayer::node_get_pos(const StringName &p_node) const {
+Point2 AnimationTreePlayer::node_get_position(const StringName &p_node) const {
ERR_FAIL_COND_V(!node_map.has(p_node), Point2());
return node_map[p_node]->pos;
@@ -1752,7 +1752,7 @@ void AnimationTreePlayer::_bind_methods() {
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(D_METHOD("timeseek_node_seek", "id", "pos_sec"), &AnimationTreePlayer::timeseek_node_seek);
+ ClassDB::bind_method(D_METHOD("timeseek_node_seek", "id", "seconds"), &AnimationTreePlayer::timeseek_node_seek);
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);
@@ -1767,8 +1767,8 @@ void AnimationTreePlayer::_bind_methods() {
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(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(D_METHOD("node_set_position", "id", "screen_position"), &AnimationTreePlayer::node_set_position);
+ ClassDB::bind_method(D_METHOD("node_get_position", "id"), &AnimationTreePlayer::node_get_position);
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);
@@ -1809,7 +1809,7 @@ void AnimationTreePlayer::_bind_methods() {
BIND_ENUM_CONSTANT(NODE_TIMESEEK);
BIND_ENUM_CONSTANT(NODE_TRANSITION);
- BIND_ENUM_CONSTANT(ANIMATION_PROCESS_FIXED);
+ BIND_ENUM_CONSTANT(ANIMATION_PROCESS_PHYSICS);
BIND_ENUM_CONSTANT(ANIMATION_PROCESS_IDLE);
}
diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h
index 609430340b..3e2bb88198 100644
--- a/scene/animation/animation_tree_player.h
+++ b/scene/animation/animation_tree_player.h
@@ -42,7 +42,7 @@ class AnimationTreePlayer : public Node {
public:
enum AnimationProcessMode {
- ANIMATION_PROCESS_FIXED,
+ ANIMATION_PROCESS_PHYSICS,
ANIMATION_PROCESS_IDLE,
};
@@ -417,10 +417,10 @@ public:
void transition_node_set_current(const StringName &p_node, int p_current);
int transition_node_get_current(const StringName &p_node) const;
- void node_set_pos(const StringName &p_node, const Vector2 &p_pos); //for display
+ void node_set_position(const StringName &p_node, const Vector2 &p_pos); //for display
/* GETS */
- Point2 node_get_pos(const StringName &p_node) const; //for display
+ Point2 node_get_position(const StringName &p_node) const; //for display
NodeType node_get_type(const StringName &p_node) const;
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index fb61c43d5c..fb327191b9 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -152,7 +152,7 @@ void Tween::_notification(int p_what) {
if (!processing) {
//make sure that a previous process state was not saved
//only process if "processing" is set
- set_fixed_process_internal(false);
+ set_physics_process_internal(false);
set_process_internal(false);
}
} break;
@@ -160,19 +160,19 @@ void Tween::_notification(int p_what) {
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- if (tween_process_mode == TWEEN_PROCESS_FIXED)
+ if (tween_process_mode == TWEEN_PROCESS_PHYSICS)
break;
if (processing)
_tween_process(get_process_delta_time());
} break;
- case NOTIFICATION_INTERNAL_FIXED_PROCESS: {
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
if (tween_process_mode == TWEEN_PROCESS_IDLE)
break;
if (processing)
- _tween_process(get_fixed_process_delta_time());
+ _tween_process(get_physics_process_delta_time());
} break;
case NOTIFICATION_EXIT_TREE: {
@@ -224,7 +224,7 @@ void Tween::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_process_mode", PROPERTY_HINT_ENUM, "Fixed,Idle"), "set_tween_process_mode", "get_tween_process_mode");
- BIND_ENUM_CONSTANT(TWEEN_PROCESS_FIXED);
+ BIND_ENUM_CONSTANT(TWEEN_PROCESS_PHYSICS);
BIND_ENUM_CONSTANT(TWEEN_PROCESS_IDLE);
BIND_ENUM_CONSTANT(TRANS_LINEAR);
@@ -642,7 +642,7 @@ void Tween::_set_process(bool p_process, bool p_force) {
switch (tween_process_mode) {
- case TWEEN_PROCESS_FIXED: set_fixed_process_internal(p_process && active); break;
+ case TWEEN_PROCESS_PHYSICS: set_physics_process_internal(p_process && active); break;
case TWEEN_PROCESS_IDLE: set_process_internal(p_process && active); break;
}
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index 929d63a7fc..fac1d346b4 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -38,7 +38,7 @@ class Tween : public Node {
public:
enum TweenProcessMode {
- TWEEN_PROCESS_FIXED,
+ TWEEN_PROCESS_PHYSICS,
TWEEN_PROCESS_IDLE,
};
diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp
index 661d085dfd..058b162e83 100644
--- a/scene/audio/audio_player.cpp
+++ b/scene/audio/audio_player.cpp
@@ -122,7 +122,6 @@ void AudioStreamPlayer::_notification(int p_what) {
void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) {
- ERR_FAIL_COND(!p_stream.is_valid());
AudioServer::get_singleton()->lock();
mix_buffer.resize(AudioServer::get_singleton()->thread_get_mix_buffer_size());
@@ -134,12 +133,14 @@ void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) {
setseek = -1;
}
- stream = p_stream;
- stream_playback = p_stream->instance_playback();
+ if (p_stream.is_valid()) {
+ stream = p_stream;
+ stream_playback = p_stream->instance_playback();
+ }
AudioServer::get_singleton()->unlock();
- if (stream_playback.is_null()) {
+ if (p_stream.is_valid() && stream_playback.is_null()) {
stream.unref();
ERR_FAIL_COND(stream_playback.is_null());
}
@@ -193,10 +194,10 @@ bool AudioStreamPlayer::is_playing() const {
return false;
}
-float AudioStreamPlayer::get_pos() {
+float AudioStreamPlayer::get_playback_position() {
if (stream_playback.is_valid()) {
- return stream_playback->get_pos();
+ return stream_playback->get_playback_position();
}
return 0;
@@ -279,12 +280,12 @@ void AudioStreamPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_volume_db", "volume_db"), &AudioStreamPlayer::set_volume_db);
ClassDB::bind_method(D_METHOD("get_volume_db"), &AudioStreamPlayer::get_volume_db);
- ClassDB::bind_method(D_METHOD("play", "from_pos"), &AudioStreamPlayer::play, DEFVAL(0.0));
- ClassDB::bind_method(D_METHOD("seek", "to_pos"), &AudioStreamPlayer::seek);
+ ClassDB::bind_method(D_METHOD("play", "from_position"), &AudioStreamPlayer::play, DEFVAL(0.0));
+ ClassDB::bind_method(D_METHOD("seek", "to_position"), &AudioStreamPlayer::seek);
ClassDB::bind_method(D_METHOD("stop"), &AudioStreamPlayer::stop);
ClassDB::bind_method(D_METHOD("is_playing"), &AudioStreamPlayer::is_playing);
- ClassDB::bind_method(D_METHOD("get_pos"), &AudioStreamPlayer::get_pos);
+ ClassDB::bind_method(D_METHOD("get_playback_position"), &AudioStreamPlayer::get_playback_position);
ClassDB::bind_method(D_METHOD("set_bus", "bus"), &AudioStreamPlayer::set_bus);
ClassDB::bind_method(D_METHOD("get_bus"), &AudioStreamPlayer::get_bus);
diff --git a/scene/audio/audio_player.h b/scene/audio/audio_player.h
index 4bfa84f766..4bfc44730d 100644
--- a/scene/audio/audio_player.h
+++ b/scene/audio/audio_player.h
@@ -83,7 +83,7 @@ public:
void seek(float p_seconds);
void stop();
bool is_playing() const;
- float get_pos();
+ float get_playback_position();
void set_bus(const StringName &p_bus);
StringName get_bus() const;
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 5713a35b7a..148277f2dd 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -39,7 +39,9 @@ void BaseButton::_unpress_group() {
if (!button_group.is_valid())
return;
- status.pressed = true;
+ if (toggle_mode) {
+ status.pressed = true;
+ }
for (Set<BaseButton *>::Element *E = button_group->buttons.front(); E; E = E->next()) {
if (E->get() == this)
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index 704c00b1d6..e58cbe373b 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -177,29 +177,14 @@ void ColorPicker::_update_color() {
void ColorPicker::_update_presets() {
Size2 size = bt_add_preset->get_size();
- preset->set_custom_minimum_size(Size2(size.width * presets.size(), size.height));
-
- PoolVector<uint8_t> img;
- img.resize(size.x * presets.size() * size.y * 3);
-
- {
- PoolVector<uint8_t>::Write w = img.write();
- for (int y = 0; y < size.y; y++) {
- for (int x = 0; x < size.x * presets.size(); x++) {
- int ofs = (y * (size.x * presets.size()) + x) * 3;
- w[ofs + 0] = uint8_t(CLAMP(presets[(int)x / size.x].r * 255.0, 0, 255));
- w[ofs + 1] = uint8_t(CLAMP(presets[(int)x / size.x].g * 255.0, 0, 255));
- w[ofs + 2] = uint8_t(CLAMP(presets[(int)x / size.x].b * 255.0, 0, 255));
- }
- }
- }
+ Size2 preset_size = Size2(size.width * presets.size(), size.height);
+ preset->set_custom_minimum_size(preset_size);
- Ref<Image> i = memnew(Image(size.x * presets.size(), size.y, false, Image::FORMAT_RGB8, img));
+ preset->draw_texture_rect(get_icon("preset_bg", "ColorPicker"), Rect2(Point2(), preset_size), true);
- Ref<ImageTexture> t;
- t.instance();
- t->create_from_image(i);
- preset->set_texture(t);
+ for (int i = 0; i < presets.size(); i++) {
+ preset->draw_rect(Rect2(Point2(size.width * i, 0), size), presets[i]);
+ }
}
void ColorPicker::_text_type_toggled() {
@@ -227,7 +212,7 @@ void ColorPicker::add_preset(const Color &p_color) {
} else {
presets.push_back(p_color);
}
- _update_presets();
+ preset->update();
if (presets.size() == 10)
bt_add_preset->hide();
}
@@ -266,7 +251,11 @@ void ColorPicker::_update_text_value() {
}
void ColorPicker::_sample_draw() {
- sample->draw_rect(Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95)), color);
+ Rect2 r = Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95));
+ if (color.a < 1.0) {
+ sample->draw_texture_rect(get_icon("preset_bg", "ColorPicker"), r, true);
+ }
+ sample->draw_rect(r, color);
}
void ColorPicker::_hsv_draw(int p_which, Control *c) {
@@ -399,7 +388,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) {
} else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT) {
int index = bev->get_position().x / (preset->get_size().x / presets.size());
presets.erase(presets[index]);
- _update_presets();
+ preset->update();
bt_add_preset->show();
}
_update_color();
@@ -461,7 +450,7 @@ void ColorPicker::_screen_pick_pressed() {
screen = memnew(Control);
r->add_child(screen);
screen->set_as_toplevel(true);
- screen->set_area_as_parent_rect();
+ screen->set_anchors_and_margins_preset(Control::PRESET_WIDE);
screen->set_default_cursor_shape(CURSOR_POINTING_HAND);
screen->connect("gui_input", this, "_screen_input");
}
@@ -484,6 +473,7 @@ void ColorPicker::_bind_methods() {
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("_update_presets"), &ColorPicker::_update_presets);
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);
@@ -608,6 +598,7 @@ ColorPicker::ColorPicker()
bbc->add_child(preset);
//preset->set_ignore_mouse(false);
preset->connect("gui_input", this, "_preset_input");
+ preset->connect("draw", this, "_update_presets");
bt_add_preset = memnew(Button);
bt_add_preset->set_icon(get_icon("add_preset"));
@@ -636,7 +627,9 @@ void ColorPickerButton::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
Ref<StyleBox> normal = get_stylebox("normal");
- draw_rect(Rect2(normal->get_offset(), get_size() - normal->get_minimum_size()), picker->get_pick_color());
+ Rect2 r = Rect2(normal->get_offset(), get_size() - normal->get_minimum_size());
+ draw_texture_rect(Control::get_icon("bg", "ColorPickerButton"), r, true);
+ draw_rect(r, picker->get_pick_color());
}
if (p_what == MainLoop::NOTIFICATION_WM_QUIT_REQUEST) {
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 87dfd95724..91c5263bf5 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -49,7 +49,7 @@ Variant Control::edit_get_state() const {
Dictionary s;
s["rect"] = get_rect();
- s["rot"] = get_rotation();
+ s["rotation"] = get_rotation();
s["scale"] = get_scale();
Array anchors;
anchors.push_back(get_anchor(MARGIN_LEFT));
@@ -66,7 +66,7 @@ void Control::edit_set_state(const Variant &p_state) {
Rect2 state = s["rect"];
set_position(state.position);
set_size(state.size);
- set_rotation(s["rot"]);
+ set_rotation(s["rotation"]);
set_scale(s["scale"]);
Array anchors = s["anchors"];
set_anchor(MARGIN_LEFT, anchors[0]);
@@ -809,9 +809,9 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName &
// try with custom themes
Control *theme_owner = data.theme_owner;
- while (theme_owner) {
+ StringName class_name = type;
- StringName class_name = type;
+ while (theme_owner) {
while (class_name != StringName()) {
if (theme_owner->data.theme->has_stylebox(p_name, class_name)) {
@@ -829,6 +829,14 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName &
theme_owner = NULL;
}
+ class_name = type;
+
+ while (class_name != StringName()) {
+ if (Theme::get_default()->has_stylebox(p_name, class_name))
+ return Theme::get_default()->get_stylebox(p_name, class_name);
+
+ class_name = ClassDB::get_parent_class_nocheck(class_name);
+ }
return Theme::get_default()->get_stylebox(p_name, type);
}
Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) const {
@@ -1463,6 +1471,140 @@ void Control::set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin) {
}
}
+void Control::set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode, int p_margin) {
+ // Calculate the size if the node is not resized
+ Size2 min_size = get_minimum_size();
+ Size2 new_size = get_size();
+ if (p_resize_mode == PRESET_MODE_MINSIZE || p_resize_mode == PRESET_MODE_KEEP_HEIGHT) {
+ new_size.x = min_size.x;
+ }
+ if (p_resize_mode == PRESET_MODE_MINSIZE || p_resize_mode == PRESET_MODE_KEEP_WIDTH) {
+ new_size.y = min_size.y;
+ }
+
+ float pw = _get_parent_range(0);
+ float ph = _get_parent_range(1);
+
+ //Left
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_CENTER_LEFT:
+ case PRESET_TOP_WIDE:
+ case PRESET_BOTTOM_WIDE:
+ case PRESET_LEFT_WIDE:
+ case PRESET_HCENTER_WIDE:
+ case PRESET_WIDE:
+ data.margin[0] = pw * (0.0 - data.anchor[0]) + p_margin;
+ break;
+
+ case PRESET_CENTER_TOP:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_CENTER:
+ case PRESET_VCENTER_WIDE:
+ data.margin[0] = pw * (0.5 - data.anchor[0]) - new_size.x / 2;
+ break;
+
+ case PRESET_TOP_RIGHT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_RIGHT_WIDE:
+ data.margin[0] = pw * (1.0 - data.anchor[0]) - new_size.x - p_margin;
+ break;
+ }
+
+ // Top
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_TOP_RIGHT:
+ case PRESET_CENTER_TOP:
+ case PRESET_LEFT_WIDE:
+ case PRESET_RIGHT_WIDE:
+ case PRESET_TOP_WIDE:
+ case PRESET_VCENTER_WIDE:
+ case PRESET_WIDE:
+ data.margin[1] = ph * (0.0 - data.anchor[1]) + p_margin;
+ break;
+
+ case PRESET_CENTER_LEFT:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_CENTER:
+ case PRESET_HCENTER_WIDE:
+ data.margin[1] = ph * (0.5 - data.anchor[1]) - new_size.y / 2;
+ break;
+
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_BOTTOM_WIDE:
+ data.margin[1] = ph * (1.0 - data.anchor[1]) - new_size.y - p_margin;
+ break;
+ }
+
+ // Right
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_CENTER_LEFT:
+ case PRESET_LEFT_WIDE:
+ data.margin[2] = pw * (0.0 - data.anchor[2]) + new_size.x + p_margin;
+ break;
+
+ case PRESET_CENTER_TOP:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_CENTER:
+ case PRESET_VCENTER_WIDE:
+ data.margin[2] = pw * (0.5 - data.anchor[2]) + new_size.x / 2;
+ break;
+
+ case PRESET_TOP_RIGHT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_TOP_WIDE:
+ case PRESET_RIGHT_WIDE:
+ case PRESET_BOTTOM_WIDE:
+ case PRESET_HCENTER_WIDE:
+ case PRESET_WIDE:
+ data.margin[2] = pw * (1.0 - data.anchor[2]) - p_margin;
+ break;
+ }
+
+ // Bottom
+ switch (p_preset) {
+ case PRESET_TOP_LEFT:
+ case PRESET_TOP_RIGHT:
+ case PRESET_CENTER_TOP:
+ case PRESET_TOP_WIDE:
+ data.margin[3] = ph * (0.0 - data.anchor[3]) + new_size.y + p_margin;
+ break;
+
+ case PRESET_CENTER_LEFT:
+ case PRESET_CENTER_RIGHT:
+ case PRESET_CENTER:
+ case PRESET_HCENTER_WIDE:
+ data.margin[3] = ph * (0.5 - data.anchor[3]) + new_size.y / 2;
+ break;
+
+ case PRESET_BOTTOM_LEFT:
+ case PRESET_BOTTOM_RIGHT:
+ case PRESET_CENTER_BOTTOM:
+ case PRESET_LEFT_WIDE:
+ case PRESET_RIGHT_WIDE:
+ case PRESET_BOTTOM_WIDE:
+ case PRESET_VCENTER_WIDE:
+ case PRESET_WIDE:
+ data.margin[3] = ph * (1.0 - data.anchor[3]) - p_margin;
+ break;
+ }
+
+ _size_changed();
+}
+
+void Control::set_anchors_and_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode, int p_margin) {
+ set_anchors_preset(p_preset);
+ set_margins_preset(p_preset, p_resize_mode, p_margin);
+}
+
float Control::get_anchor(Margin p_margin) const {
return data.anchor[p_margin];
@@ -1614,20 +1756,6 @@ Rect2 Control::get_item_rect() const {
return Rect2(Point2(), get_size());
}
-void Control::set_area_as_parent_rect(int p_margin) {
-
- data.anchor[MARGIN_LEFT] = ANCHOR_BEGIN;
- data.margin[MARGIN_LEFT] = p_margin;
- data.anchor[MARGIN_TOP] = ANCHOR_BEGIN;
- data.margin[MARGIN_TOP] = p_margin;
- data.anchor[MARGIN_RIGHT] = ANCHOR_END;
- data.margin[MARGIN_RIGHT] = -p_margin;
- data.anchor[MARGIN_BOTTOM] = ANCHOR_END;
- data.margin[MARGIN_BOTTOM] = -p_margin;
-
- _size_changed();
-}
-
void Control::add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon) {
ERR_FAIL_COND(p_icon.is_null());
@@ -2463,18 +2591,20 @@ void Control::_bind_methods() {
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_anchors_preset", "preset", "keep_margin"), &Control::set_anchors_preset, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_margins_preset", "preset", "resize_mode", "margin"), &Control::set_margins_preset, DEFVAL(PRESET_MODE_MINSIZE), DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("set_anchors_and_margins_preset", "preset", "resize_mode", "margin"), &Control::set_anchors_and_margins_preset, DEFVAL(PRESET_MODE_MINSIZE), DEFVAL(0));
ClassDB::bind_method(D_METHOD("set_anchor", "margin", "anchor", "keep_margin", "push_opposite_anchor"), &Control::set_anchor, DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("_set_anchor", "margin", "anchor"), &Control::_set_anchor);
- ClassDB::bind_method(D_METHOD("set_anchors_preset", "preset", "keep_margin"), &Control::set_anchors_preset, DEFVAL(false));
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", "offset", "push_opposite_anchor"), &Control::set_anchor_and_margin, DEFVAL(false));
- 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_position", "pos"), &Control::set_position);
+ ClassDB::bind_method(D_METHOD("set_begin", "position"), &Control::set_begin);
+ ClassDB::bind_method(D_METHOD("set_end", "position"), &Control::set_end);
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &Control::set_position);
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_position", "pos"), &Control::set_global_position);
+ ClassDB::bind_method(D_METHOD("set_global_position", "position"), &Control::set_global_position);
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)
@@ -2497,7 +2627,6 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position);
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);
@@ -2552,12 +2681,12 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_v_grow_direction"), &Control::get_v_grow_direction);
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", "at_position"), &Control::get_tooltip, DEFVAL(Point2()));
ClassDB::bind_method(D_METHOD("_get_tooltip"), &Control::_get_tooltip);
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(D_METHOD("get_cursor_shape", "position"), &Control::get_cursor_shape, DEFVAL(Point2()));
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);
@@ -2575,7 +2704,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_drag_forwarding", "target"), &Control::set_drag_forwarding);
ClassDB::bind_method(D_METHOD("set_drag_preview", "control"), &Control::set_drag_preview);
- ClassDB::bind_method(D_METHOD("warp_mouse", "to_pos"), &Control::warp_mouse);
+ ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Control::warp_mouse);
ClassDB::bind_method(D_METHOD("minimum_size_changed"), &Control::minimum_size_changed);
@@ -2585,9 +2714,9 @@ void Control::_bind_methods() {
BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size"));
- BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_drag_data", PropertyInfo(Variant::VECTOR2, "pos")));
- BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_drop_data", PropertyInfo(Variant::VECTOR2, "pos"), PropertyInfo(Variant::NIL, "data")));
- BIND_VMETHOD(MethodInfo("drop_data", PropertyInfo(Variant::VECTOR2, "pos"), PropertyInfo(Variant::NIL, "data")));
+ BIND_VMETHOD(MethodInfo(Variant::OBJECT, "get_drag_data", PropertyInfo(Variant::VECTOR2, "position")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "can_drop_data", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::NIL, "data")));
+ BIND_VMETHOD(MethodInfo("drop_data", PropertyInfo(Variant::VECTOR2, "position"), PropertyInfo(Variant::NIL, "data")));
ADD_GROUP("Anchor", "anchor_");
ADD_PROPERTYI(PropertyInfo(Variant::REAL, "anchor_left", PROPERTY_HINT_RANGE, "0,1,0.01"), "_set_anchor", "get_anchor", MARGIN_LEFT);
@@ -2681,6 +2810,11 @@ void Control::_bind_methods() {
BIND_ENUM_CONSTANT(PRESET_HCENTER_WIDE);
BIND_ENUM_CONSTANT(PRESET_WIDE);
+ BIND_ENUM_CONSTANT(PRESET_MODE_MINSIZE);
+ BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_HEIGHT);
+ BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_WIDTH);
+ BIND_ENUM_CONSTANT(PRESET_MODE_KEEP_SIZE);
+
BIND_ENUM_CONSTANT(SIZE_EXPAND);
BIND_ENUM_CONSTANT(SIZE_FILL);
BIND_ENUM_CONSTANT(SIZE_EXPAND_FILL);
diff --git a/scene/gui/control.h b/scene/gui/control.h
index da5c4d0908..5b146b4454 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -124,6 +124,13 @@ public:
PRESET_WIDE
};
+ enum LayoutPresetMode {
+ PRESET_MODE_MINSIZE,
+ PRESET_MODE_KEEP_WIDTH,
+ PRESET_MODE_KEEP_HEIGHT,
+ PRESET_MODE_KEEP_SIZE
+ };
+
private:
struct CComparator {
@@ -294,34 +301,32 @@ public:
/* POSITIONING */
- void set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin = false, bool p_push_opposite_anchor = true);
- void set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos, bool p_push_opposite_anchor = true);
void set_anchors_preset(LayoutPreset p_preset, bool p_keep_margin = false);
+ void set_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
+ void set_anchors_and_margins_preset(LayoutPreset p_preset, LayoutPresetMode p_resize_mode = PRESET_MODE_MINSIZE, int p_margin = 0);
+ void set_anchor(Margin p_margin, float p_anchor, bool p_keep_margin = false, bool p_push_opposite_anchor = true);
float get_anchor(Margin p_margin) const;
void set_margin(Margin p_margin, float p_value);
+ float get_margin(Margin p_margin) const;
+
+ void set_anchor_and_margin(Margin p_margin, float p_anchor, float p_pos, bool p_push_opposite_anchor = true);
void set_begin(const Point2 &p_point); // helper
void set_end(const Point2 &p_point); // helper
- void set_h_grow_direction(GrowDirection p_direction);
- GrowDirection get_h_grow_direction() const;
-
- void set_v_grow_direction(GrowDirection p_direction);
- GrowDirection get_v_grow_direction() const;
-
- float get_margin(Margin p_margin) const;
Point2 get_begin() const;
Point2 get_end() const;
void set_position(const Point2 &p_point);
- void set_size(const Size2 &p_size);
void set_global_position(const Point2 &p_point);
-
Point2 get_position() const;
Point2 get_global_position() const;
+
+ void set_size(const Size2 &p_size);
Size2 get_size() const;
+
Rect2 get_rect() const;
Rect2 get_global_rect() const;
Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server
@@ -331,14 +336,18 @@ public:
float get_rotation() const;
float get_rotation_deg() const;
+ void set_h_grow_direction(GrowDirection p_direction);
+ GrowDirection get_h_grow_direction() const;
+
+ void set_v_grow_direction(GrowDirection p_direction);
+ GrowDirection get_v_grow_direction() const;
+
void set_pivot_offset(const Vector2 &p_pivot);
Vector2 get_pivot_offset() const;
void set_scale(const Vector2 &p_scale);
Vector2 get_scale() const;
- void set_area_as_parent_rect(int p_margin = 0);
-
void show_modal(bool p_exclusive = false);
void set_theme(const Ref<Theme> &p_theme);
@@ -449,6 +458,7 @@ VARIANT_ENUM_CAST(Control::FocusMode);
VARIANT_ENUM_CAST(Control::SizeFlags);
VARIANT_ENUM_CAST(Control::CursorShape);
VARIANT_ENUM_CAST(Control::LayoutPreset);
+VARIANT_ENUM_CAST(Control::LayoutPresetMode);
VARIANT_ENUM_CAST(Control::MouseFilter);
VARIANT_ENUM_CAST(Control::GrowDirection);
VARIANT_ENUM_CAST(Control::Anchor);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 5b00aab2ef..0d3cccc2b5 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -352,14 +352,14 @@ bool GraphEdit::_filter_input(const Point2 &p_point) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
- Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
if (pos.distance_to(p_point) < grab_r)
return true;
}
for (int j = 0; j < gn->get_connection_input_count(); j++) {
- Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
if (pos.distance_to(p_point) < grab_r) {
return true;
}
@@ -386,7 +386,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
- Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
if (pos.distance_to(mpos) < grab_r) {
if (valid_left_disconnect_types.has(gn->get_connection_output_type(j))) {
@@ -433,7 +433,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_input_count(); j++) {
- Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
if (pos.distance_to(mpos) < grab_r) {
@@ -501,7 +501,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
if (!connecting_out) {
for (int j = 0; j < gn->get_connection_output_count(); j++) {
- Vector2 pos = gn->get_connection_output_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_output_position(j) + gn->get_position();
int type = gn->get_connection_output_type(j);
if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) {
@@ -516,7 +516,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
for (int j = 0; j < gn->get_connection_input_count(); j++) {
- Vector2 pos = gn->get_connection_input_pos(j) + gn->get_position();
+ Vector2 pos = gn->get_connection_input_position(j) + gn->get_position();
int type = gn->get_connection_input_type(j);
if ((type == connecting_type || valid_connection_types.has(ConnType(type, connecting_type))) && pos.distance_to(mpos) < grab_r) {
connecting_target = true;
@@ -657,9 +657,9 @@ void GraphEdit::_connections_layer_draw() {
continue;
}
- Vector2 frompos = gfrom->get_connection_output_pos(E->get().from_port) + gfrom->get_offset() * zoom;
+ Vector2 frompos = gfrom->get_connection_output_position(E->get().from_port) + gfrom->get_offset() * zoom;
Color color = gfrom->get_connection_output_color(E->get().from_port);
- Vector2 topos = gto->get_connection_input_pos(E->get().to_port) + gto->get_offset() * zoom;
+ Vector2 topos = gto->get_connection_input_position(E->get().to_port) + gto->get_offset() * zoom;
Color tocolor = gto->get_connection_input_color(E->get().to_port);
_draw_cos_line(connections_layer, frompos, topos, color, tocolor);
}
@@ -682,9 +682,9 @@ void GraphEdit::_top_layer_draw() {
ERR_FAIL_COND(!from);
Vector2 pos;
if (connecting_out)
- pos = from->get_connection_output_pos(connecting_index);
+ pos = from->get_connection_output_position(connecting_index);
else
- pos = from->get_connection_input_pos(connecting_index);
+ pos = from->get_connection_input_position(connecting_index);
pos += from->get_position();
Vector2 topos;
@@ -733,7 +733,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
just_selected = true;
// TODO: Remove local mouse pos hack if/when InputEventMouseMotion is fixed to support floats
//drag_accum+=Vector2(mm->get_relative().x,mm->get_relative().y);
- drag_accum = get_local_mouse_pos() - drag_origin;
+ drag_accum = get_local_mouse_position() - drag_origin;
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
if (gn && gn->is_selected()) {
@@ -750,7 +750,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
if (mm.is_valid() && box_selecting) {
- box_selecting_to = get_local_mouse_pos();
+ box_selecting_to = get_local_mouse_position();
box_selecting_rect = Rect2(MIN(box_selecting_from.x, box_selecting_to.x),
MIN(box_selecting_from.y, box_selecting_to.y),
@@ -810,7 +810,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (gn) {
Rect2 r = gn->get_rect();
r.size *= zoom;
- if (r.has_point(get_local_mouse_pos()))
+ if (r.has_point(get_local_mouse_position()))
gn->set_selected(false);
}
}
@@ -848,7 +848,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
if (gn_selected->is_resizing())
continue;
- if (gn_selected->has_point(gn_selected->get_local_mouse_pos())) {
+ if (gn_selected->has_point(gn_selected->get_local_mouse_position())) {
gn = gn_selected;
break;
}
@@ -862,7 +862,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
dragging = true;
drag_accum = Vector2();
- drag_origin = get_local_mouse_pos();
+ drag_origin = get_local_mouse_position();
just_selected = !gn->is_selected();
if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
for (int i = 0; i < get_child_count(); i++) {
@@ -888,7 +888,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
return;
box_selecting = true;
- box_selecting_from = get_local_mouse_pos();
+ box_selecting_from = get_local_mouse_position();
if (b->get_control()) {
box_selection_mode_aditive = true;
previus_selected.clear();
@@ -941,17 +941,17 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
//too difficult to get right
//set_zoom(zoom/ZOOM_SCALE);
}
- if (b->get_button_index() == BUTTON_WHEEL_UP) {
- h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8);
- }
- if (b->get_button_index() == BUTTON_WHEEL_DOWN) {
- h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8);
+ if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
}
- if (b->get_button_index() == BUTTON_WHEEL_RIGHT) {
+ if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8);
}
- if (b->get_button_index() == BUTTON_WHEEL_LEFT) {
- v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
+ if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8);
+ }
+ if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8);
}
}
@@ -1167,7 +1167,7 @@ void GraphEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2, "p_position")));
ADD_SIGNAL(MethodInfo("duplicate_nodes_request"));
ADD_SIGNAL(MethodInfo("node_selected", PropertyInfo(Variant::OBJECT, "node")));
- ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_pos")));
+ ADD_SIGNAL(MethodInfo("connection_to_empty", PropertyInfo(Variant::STRING, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::VECTOR2, "release_position")));
ADD_SIGNAL(MethodInfo("delete_nodes_request"));
ADD_SIGNAL(MethodInfo("_begin_node_move"));
ADD_SIGNAL(MethodInfo("_end_node_move"));
@@ -1182,7 +1182,7 @@ GraphEdit::GraphEdit() {
top_layer = memnew(GraphEditFilter(this));
add_child(top_layer);
top_layer->set_mouse_filter(MOUSE_FILTER_PASS);
- top_layer->set_area_as_parent_rect();
+ top_layer->set_anchors_and_margins_preset(Control::PRESET_WIDE);
top_layer->connect("draw", this, "_top_layer_draw");
top_layer->set_mouse_filter(MOUSE_FILTER_PASS);
top_layer->connect("gui_input", this, "_top_layer_input");
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index bef0808fd0..7655363631 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -208,8 +208,11 @@ void GraphNode::_notification(int p_what) {
Ref<Texture> close = get_icon("close");
Ref<Texture> resizer = get_icon("resizer");
int close_offset = get_constant("close_offset");
+ int close_h_offset = get_constant("close_h_offset");
+ Color close_color = get_color("close_color");
Ref<Font> title_font = get_font("title_font");
int title_offset = get_constant("title_offset");
+ int title_h_offset = get_constant("title_h_offset");
Color title_color = get_color("title_color");
Point2i icofs = -port->get_size() * 0.5;
int edgeofs = get_constant("port_offset");
@@ -236,10 +239,10 @@ void GraphNode::_notification(int p_what) {
if (show_close)
w -= close->get_width();
- draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT), -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w);
+ draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w);
if (show_close) {
- Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT), -close->get_height() + close_offset);
- draw_texture(close, cpos);
+ Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT) + close_h_offset, -close->get_height() + close_offset);
+ draw_texture(close, cpos, close_color);
close_rect.position = cpos;
close_rect.size = close->get_size();
} else {
@@ -515,7 +518,7 @@ int GraphNode::get_connection_output_count() {
return conn_output_cache.size();
}
-Vector2 GraphNode::get_connection_input_pos(int p_idx) {
+Vector2 GraphNode::get_connection_input_position(int p_idx) {
if (connpos_dirty)
_connpos_update();
@@ -545,7 +548,7 @@ Color GraphNode::get_connection_input_color(int p_idx) {
return conn_input_cache[p_idx].color;
}
-Vector2 GraphNode::get_connection_output_pos(int p_idx) {
+Vector2 GraphNode::get_connection_output_position(int p_idx) {
if (connpos_dirty)
_connpos_update();
@@ -687,10 +690,10 @@ void GraphNode::_bind_methods() {
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_position", "idx"), &GraphNode::get_connection_output_position);
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_position", "idx"), &GraphNode::get_connection_input_position);
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);
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index a606e47acd..a0840544dd 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -138,10 +138,10 @@ public:
int get_connection_input_count();
int get_connection_output_count();
- Vector2 get_connection_input_pos(int p_idx);
+ Vector2 get_connection_input_position(int p_idx);
int get_connection_input_type(int p_idx);
Color get_connection_input_color(int p_idx);
- Vector2 get_connection_output_pos(int p_idx);
+ Vector2 get_connection_output_position(int p_idx);
int get_connection_output_type(int p_idx);
Color get_connection_output_color(int p_idx);
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 9a605c98f3..a034c7224f 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -524,11 +524,6 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
}
return;
- } else {
- Vector<int> sItems = get_selected_items();
- for (int i = 0; i < sItems.size(); i++) {
- unselect(sItems[i]);
- }
}
}
if (mb.is_valid() && mb->get_button_index() == BUTTON_WHEEL_UP && mb->is_pressed()) {
@@ -750,8 +745,8 @@ void ItemList::_notification(int p_what) {
Ref<StyleBox> bg = get_stylebox("bg");
int mw = scroll_bar->get_minimum_size().x;
- scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -mw + bg->get_margin(MARGIN_RIGHT));
- scroll_bar->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, -bg->get_margin(MARGIN_RIGHT));
+ scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -mw);
+ scroll_bar->set_anchor_and_margin(MARGIN_RIGHT, ANCHOR_END, 0);
scroll_bar->set_anchor_and_margin(MARGIN_TOP, ANCHOR_BEGIN, bg->get_margin(MARGIN_TOP));
scroll_bar->set_anchor_and_margin(MARGIN_BOTTOM, ANCHOR_END, -bg->get_margin(MARGIN_BOTTOM));
@@ -838,6 +833,10 @@ void ItemList::_notification(int p_what) {
if (fixed_column_width > 0)
minsize.x = fixed_column_width;
max_column_width = MAX(max_column_width, minsize.x);
+
+ // elements need to adapt to the selected size
+ minsize.y += vseparation;
+ minsize.x += hseparation;
items[i].rect_cache.size = minsize;
items[i].min_rect_cache.size = minsize;
}
@@ -851,7 +850,6 @@ void ItemList::_notification(int p_what) {
while (true) {
//repeat util all fits
- //print_line("try with "+itos(current_columns));
bool all_fit = true;
Vector2 ofs;
int col = 0;
@@ -866,13 +864,11 @@ void ItemList::_notification(int p_what) {
break;
}
- items[i].rect_cache = items[i].min_rect_cache;
if (same_column_width)
items[i].rect_cache.size.x = max_column_width;
items[i].rect_cache.position = ofs;
max_h = MAX(max_h, items[i].rect_cache.size.y);
ofs.x += items[i].rect_cache.size.x + hseparation;
- //print_line("item "+itos(i)+" ofs "+rtos(items[i].rect_cache.size.x));
col++;
if (col == current_columns) {
@@ -901,7 +897,6 @@ void ItemList::_notification(int p_what) {
auto_height_value = ofs.y + max_h + bg->get_minimum_size().height;
scroll_bar->set_max(max);
scroll_bar->set_page(page);
- //print_line("max: "+rtos(max)+" page "+rtos(page));
if (max <= page) {
scroll_bar->set_value(0);
scroll_bar->hide();
@@ -950,23 +945,23 @@ void ItemList::_notification(int p_what) {
if (items[i].selected) {
Rect2 r = rcache;
r.position += base_ofs;
+ r.position.y -= vseparation / 2;
+ r.size.y += vseparation;
+ r.position.x -= hseparation / 2;
+ r.size.x += hseparation;
- // Use stylebox to dimension potential bg color
- r.position.x -= sbsel->get_margin(MARGIN_LEFT);
- r.size.x += sbsel->get_margin(MARGIN_LEFT) + sbsel->get_margin(MARGIN_RIGHT);
- r.position.y -= sbsel->get_margin(MARGIN_TOP);
- r.size.y += sbsel->get_margin(MARGIN_TOP) + sbsel->get_margin(MARGIN_BOTTOM);
draw_style_box(sbsel, r);
}
-
if (items[i].custom_bg.a > 0.001) {
-
Rect2 r = rcache;
r.position += base_ofs;
// Size rect to make the align the temperature colors
r.position.y -= vseparation / 2;
r.size.y += vseparation;
+ r.position.x -= hseparation / 2;
+ r.size.x += hseparation;
+
draw_rect(r, items[i].custom_bg);
}
@@ -1103,12 +1098,16 @@ void ItemList::_notification(int p_what) {
Rect2 r = rcache;
r.position += base_ofs;
+ r.position.y -= vseparation / 2;
+ r.size.y += vseparation;
+ r.position.x -= hseparation / 2;
+ r.size.x += hseparation;
draw_style_box(cursor, r);
}
}
for (int i = 0; i < separators.size(); i++) {
- draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(size.width - bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), guide_color);
+ draw_line(Vector2(bg->get_margin(MARGIN_LEFT), base_ofs.y + separators[i]), Vector2(size.width - bg->get_margin(MARGIN_RIGHT), base_ofs.y + separators[i]), guide_color);
}
}
}
@@ -1117,7 +1116,7 @@ void ItemList::_scroll_changed(double) {
update();
}
-int ItemList::get_item_at_pos(const Point2 &p_pos, bool p_exact) const {
+int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
Vector2 pos = p_pos;
Ref<StyleBox> bg = get_stylebox("bg");
@@ -1165,7 +1164,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const {
String ItemList::get_tooltip(const Point2 &p_pos) const {
- int closest = get_item_at_pos(p_pos);
+ int closest = get_item_at_position(p_pos);
if (closest != -1) {
if (!items[closest].tooltip_enabled) {
@@ -1362,7 +1361,7 @@ void ItemList::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_auto_height", "enable"), &ItemList::set_auto_height);
ClassDB::bind_method(D_METHOD("has_auto_height"), &ItemList::has_auto_height);
- ClassDB::bind_method(D_METHOD("get_item_at_pos", "pos", "exact"), &ItemList::get_item_at_pos, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_item_at_position", "position", "exact"), &ItemList::get_item_at_position, DEFVAL(false));
ClassDB::bind_method(D_METHOD("ensure_current_is_visible"), &ItemList::ensure_current_is_visible);
@@ -1395,7 +1394,7 @@ void ItemList::_bind_methods() {
BIND_ENUM_CONSTANT(SELECT_MULTI);
ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "index")));
- ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "atpos")));
+ ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::VECTOR2, "at_position")));
ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "selected")));
ADD_SIGNAL(MethodInfo("item_activated", PropertyInfo(Variant::INT, "index")));
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 673b7d8956..ccdd705325 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -199,7 +199,7 @@ public:
int find_metadata(const Variant &p_metadata) const;
virtual String get_tooltip(const Point2 &p_pos) const;
- int get_item_at_pos(const Point2 &p_pos, bool p_exact = false) const;
+ int get_item_at_position(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);
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 6a5f56c78c..ed8eff436c 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -49,7 +49,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (b.is_valid()) {
if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT) {
- menu->set_position(get_global_transform().xform(get_local_mouse_pos()));
+ menu->set_position(get_global_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
menu->popup();
grab_focus();
@@ -186,7 +186,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
cached_width += font->get_char_size(text[i]).width;
}
- set_cursor_pos(0);
+ set_cursor_position(0);
_text_changed();
}
@@ -273,7 +273,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
delete_text(cc, cursor_pos);
- set_cursor_pos(cc);
+ set_cursor_position(cc);
} else {
undo_text = text;
@@ -297,7 +297,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
#ifdef APPLE_STYLE_KEYS
if (k->get_command()) {
- set_cursor_pos(0);
+ set_cursor_position(0);
} else if (k->get_alt()) {
#else
@@ -319,10 +319,10 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
cc--;
}
- set_cursor_pos(cc);
+ set_cursor_position(cc);
} else {
- set_cursor_pos(get_cursor_pos() - 1);
+ set_cursor_position(get_cursor_position() - 1);
}
shift_selection_check_post(k->get_shift());
@@ -341,7 +341,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
#ifdef APPLE_STYLE_KEYS
if (k->get_command()) {
- set_cursor_pos(text.length());
+ set_cursor_position(text.length());
} else if (k->get_alt()) {
#else
if (k->get_alt()) {
@@ -362,10 +362,10 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
cc++;
}
- set_cursor_pos(cc);
+ set_cursor_position(cc);
} else {
- set_cursor_pos(get_cursor_pos() + 1);
+ set_cursor_position(get_cursor_position() + 1);
}
shift_selection_check_post(k->get_shift());
@@ -418,7 +418,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} else {
undo_text = text;
- set_cursor_pos(cursor_pos + 1);
+ set_cursor_position(cursor_pos + 1);
delete_char();
}
@@ -433,7 +433,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
case KEY_HOME: {
shift_selection_check_pre(k->get_shift());
- set_cursor_pos(0);
+ set_cursor_position(0);
shift_selection_check_post(k->get_shift());
} break;
case KEY_KP_1: {
@@ -446,7 +446,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
case KEY_END: {
shift_selection_check_pre(k->get_shift());
- set_cursor_pos(text.length());
+ set_cursor_position(text.length());
shift_selection_check_post(k->get_shift());
} break;
@@ -534,7 +534,7 @@ void LineEdit::_notification(int p_what) {
switch (p_what) {
#ifdef TOOLS_ENABLED
case NOTIFICATION_ENTER_TREE: {
- if (Engine::get_singleton()->is_editor_hint()) {
+ if (Engine::get_singleton()->is_editor_hint() && !get_tree()->is_node_being_edited(this)) {
cursor_set_blink_enabled(EDITOR_DEF("text_editor/cursor/caret_blink", false));
cursor_set_blink_speed(EDITOR_DEF("text_editor/cursor/caret_blink_speed", 0.65));
@@ -546,7 +546,7 @@ void LineEdit::_notification(int p_what) {
#endif
case NOTIFICATION_RESIZED: {
- set_cursor_pos(get_cursor_pos());
+ set_cursor_position(get_cursor_position());
} break;
case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
@@ -601,7 +601,10 @@ void LineEdit::_notification(int p_what) {
} break;
case ALIGN_CENTER: {
- x_ofs = int(size.width - (cached_width)) / 2;
+ if (window_pos != 0)
+ x_ofs = style->get_offset().x;
+ else
+ x_ofs = int(size.width - (cached_width)) / 2;
} break;
case ALIGN_RIGHT: {
@@ -742,7 +745,7 @@ void LineEdit::_notification(int p_what) {
draw_caret = true;
}
- Point2 cursor_pos = Point2(get_cursor_pos(), 1) * get_minimum_size().height;
+ Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height;
OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
OS::get_singleton()->set_ime_intermediate_text_callback(_ime_text_callback, this);
@@ -806,9 +809,9 @@ void LineEdit::undo() {
cached_width += font->get_char_size(text[i]).width;
if (old_cursor_pos > text.length()) {
- set_cursor_pos(text.length());
+ set_cursor_position(text.length());
} else {
- set_cursor_pos(old_cursor_pos);
+ set_cursor_position(old_cursor_pos);
}
_text_changed();
@@ -846,7 +849,10 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
} break;
case ALIGN_CENTER: {
- pixel_ofs = int(size.width - (cached_width)) / 2;
+ if (window_pos != 0)
+ pixel_ofs = int(style->get_offset().x);
+ else
+ pixel_ofs = int(size.width - (cached_width)) / 2;
} break;
case ALIGN_RIGHT: {
@@ -869,14 +875,14 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
ofs++;
}
- set_cursor_pos(ofs);
+ set_cursor_position(ofs);
/*
int new_cursor_pos=p_x;
int charwidth=draw_area->get_font_char_width(' ',0);
new_cursor_pos=( ( (new_cursor_pos-2)+ (charwidth/2) ) /charwidth );
if (new_cursor_pos>(int)text.length()) new_cursor_pos=text.length();
- set_cursor_pos(window_pos+new_cursor_pos); */
+ set_cursor_position(window_pos+new_cursor_pos); */
}
bool LineEdit::cursor_get_blink_enabled() const {
@@ -929,7 +935,7 @@ void LineEdit::delete_char() {
text.erase(cursor_pos - 1, 1);
- set_cursor_pos(get_cursor_pos() - 1);
+ set_cursor_position(get_cursor_position() - 1);
if (cursor_pos == window_pos) {
@@ -1011,7 +1017,7 @@ float LineEdit::get_placeholder_alpha() const {
return placeholder_alpha;
}
-void LineEdit::set_cursor_pos(int p_pos) {
+void LineEdit::set_cursor_position(int p_pos) {
if (p_pos > (int)text.length())
p_pos = text.length();
@@ -1065,7 +1071,7 @@ void LineEdit::set_cursor_pos(int p_pos) {
update();
}
-int LineEdit::get_cursor_pos() const {
+int LineEdit::get_cursor_position() const {
return cursor_pos;
}
@@ -1093,7 +1099,7 @@ void LineEdit::append_at_cursor(String p_text) {
String pre = text.substr(0, cursor_pos);
String post = text.substr(cursor_pos, text.length() - cursor_pos);
text = pre + p_text + post;
- set_cursor_pos(cursor_pos + p_text.length());
+ set_cursor_position(cursor_pos + p_text.length());
}
}
@@ -1330,8 +1336,8 @@ void LineEdit::_bind_methods() {
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_cursor_position", "position"), &LineEdit::set_cursor_position);
+ ClassDB::bind_method(D_METHOD("get_cursor_position"), &LineEdit::get_cursor_position);
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);
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 52a4a29a33..661f9b60b9 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -149,8 +149,8 @@ public:
String get_placeholder() const;
void set_placeholder_alpha(float p_alpha);
float get_placeholder_alpha() const;
- void set_cursor_pos(int p_pos);
- int get_cursor_pos() const;
+ void set_cursor_position(int p_pos);
+ int get_cursor_position() const;
void set_max_length(int p_max_length);
int get_max_length() const;
void append_at_cursor(String p_text);
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 5a2a552943..2110298950 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -265,7 +265,7 @@ void PopupPanel::set_child_rect(Control *p_child) {
ERR_FAIL_NULL(p_child);
Ref<StyleBox> p = get_stylebox("panel");
- p_child->set_area_as_parent_rect();
+ p_child->set_anchors_preset(Control::PRESET_WIDE);
p_child->set_margin(MARGIN_LEFT, p->get_margin(MARGIN_LEFT));
p_child->set_margin(MARGIN_RIGHT, -p->get_margin(MARGIN_RIGHT));
p_child->set_margin(MARGIN_TOP, p->get_margin(MARGIN_TOP));
diff --git a/scene/gui/range.cpp b/scene/gui/range.cpp
index 1dbec6e5a1..f8fb786fa7 100644
--- a/scene/gui/range.cpp
+++ b/scene/gui/range.cpp
@@ -208,10 +208,12 @@ void Range::_ref_shared(Shared *p_shared) {
void Range::_unref_shared() {
- shared->owners.erase(this);
- if (shared->owners.size() == 0) {
- memdelete(shared);
- shared = NULL;
+ if (shared) {
+ shared->owners.erase(this);
+ if (shared->owners.size() == 0) {
+ memdelete(shared);
+ shared = NULL;
+ }
}
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index ab2c2f445f..d9287e6f63 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -84,7 +84,7 @@ Rect2 RichTextLabel::_get_text_rect() {
Ref<StyleBox> style = get_stylebox("normal");
return Rect2(style->get_offset(), get_size() - style->get_minimum_size());
}
-void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count) {
+int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count) {
RID ci;
if (r_outside)
@@ -104,9 +104,11 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
int line = 0;
int spaces = 0;
+ int height = get_size().y;
+
if (p_mode != PROCESS_CACHE) {
- ERR_FAIL_INDEX(line, l.offset_caches.size());
+ ERR_FAIL_INDEX_V(line, l.offset_caches.size(), 0);
line_ofs = l.offset_caches[line];
}
@@ -133,12 +135,20 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
//line height should be the font height for the first time, this ensures that an empty line will never have zero height and successive newlines are displayed
int line_height = cfont->get_height();
+ int nonblank_line_count = 0; //number of nonblank lines as counted during PROCESS_DRAW
+
Variant meta;
+#define RETURN return nonblank_line_count
+
#define NEW_LINE \
{ \
if (p_mode != PROCESS_CACHE) { \
line++; \
+ if (!line_is_blank) { \
+ nonblank_line_count++; \
+ } \
+ line_is_blank = true; \
if (line < l.offset_caches.size()) \
line_ofs = l.offset_caches[line]; \
wofs = margin; \
@@ -168,7 +178,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
if (r_outside) *r_outside = true; \
*r_click_item = it; \
*r_click_char = rchar; \
- return; \
+ RETURN; \
} \
}
@@ -185,7 +195,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
if (r_outside) *r_outside = true; \
*r_click_item = it; \
*r_click_char = rchar; \
- return; \
+ RETURN; \
} \
NEW_LINE \
}
@@ -196,7 +206,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
if (r_outside) *r_outside = false; \
*r_click_item = it; \
*r_click_char = rchar; \
- return; \
+ RETURN; \
} \
wofs += m_width; \
}
@@ -206,6 +216,9 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
line_height = m_height; \
}
+#define YRANGE_VISIBLE(m_top, m_height) \
+ (m_height > 0 && ((m_top >= 0 && m_top < height) || ((m_top + m_height - 1) >= 0 && (m_top + m_height - 1) < height)))
+
Color selection_fg;
Color selection_bg;
@@ -214,8 +227,10 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
selection_fg = get_color("font_color_selected");
selection_bg = get_color("selection_color");
}
+
int rchar = 0;
int lh = 0;
+ bool line_is_blank = true;
while (it) {
@@ -327,7 +342,10 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
int cw = 0;
- bool visible = visible_characters < 0 || p_char_count < visible_characters;
+ bool visible = visible_characters < 0 || p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - (fh - 0 * ascent), fh); //getting rid of ascent seems to work??
+ if (visible)
+ line_is_blank = false;
+
if (c[i] == '\t')
visible = false;
@@ -384,7 +402,9 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
ENSURE_WIDTH(img->image->get_width());
- bool visible = visible_characters < 0 || p_char_count < visible_characters;
+ bool visible = visible_characters < 0 || p_char_count < visible_characters && YRANGE_VISIBLE(y + lh - font->get_descent() - img->image->get_height(), img->image->get_height());
+ if (visible)
+ line_is_blank = false;
if (p_mode == PROCESS_DRAW && visible) {
img->image->draw(ci, p_ofs + Point2(align_ofs + wofs, y + lh - font->get_descent() - img->image->get_height()));
@@ -398,8 +418,10 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
case ITEM_NEWLINE: {
lh = 0;
- if (p_mode != PROCESS_CACHE)
+ if (p_mode != PROCESS_CACHE) {
lh = line < l.height_caches.size() ? l.height_caches[line] : 1;
+ line_is_blank = true;
+ }
} break;
case ITEM_TABLE: {
@@ -436,7 +458,7 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
idx++;
}
- //compute available width and total radio (for expanders)
+ //compute available width and total ratio (for expanders)
int total_ratio = 0;
int available_width = p_width - hseparation * (table->columns.size() - 1);
@@ -494,12 +516,14 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
int lines_ofs = p_ofs.y + offset.y + draw_ofs.y;
bool visible = lines_ofs < get_size().height && lines_ofs + lines_h >= 0;
+ if (visible)
+ line_is_blank = false;
for (int i = 0; i < frame->lines.size(); i++) {
if (visible) {
if (p_mode == PROCESS_DRAW) {
- _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor);
+ nonblank_line_count += _process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_DRAW, cfont, ccolor);
} else if (p_mode == PROCESS_POINTER) {
_process_line(frame, p_ofs + offset + draw_ofs + Vector2(0, yofs), ly, table->columns[column].width, i, PROCESS_POINTER, cfont, ccolor, p_click_pos, r_click_item, r_click_char, r_outside);
}
@@ -540,14 +564,6 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
it = _get_next_item(it);
- if (p_mode == PROCESS_POINTER && r_click_item && itp && !it && p_click_pos.y > p_ofs.y + y + lh) {
- //at the end of all, return this
- if (r_outside) *r_outside = true;
- *r_click_item = itp;
- *r_click_char = rchar;
- return;
- }
-
if (it && (p_line + 1 < p_frame->lines.size()) && p_frame->lines[p_line + 1].from == it) {
if (p_mode == PROCESS_POINTER && r_click_item && p_click_pos.y >= p_ofs.y + y && p_click_pos.y <= p_ofs.y + y + lh) {
@@ -555,15 +571,17 @@ void RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int
if (r_outside) *r_outside = true;
*r_click_item = itp;
*r_click_char = rchar;
- return;
+ RETURN;
}
break;
}
}
-
NEW_LINE;
+ RETURN;
+
+#undef RETURN
#undef NEW_LINE
#undef ENSURE_WIDTH
#undef ADVANCE
@@ -673,14 +691,14 @@ void RichTextLabel::_notification(int p_what) {
if (from_line >= main->lines.size())
break; //nothing to draw
-
int y = (main->lines[from_line].height_accum_cache - main->lines[from_line].height_cache) - ofs;
Ref<Font> base_font = get_font("normal_font");
Color base_color = get_color("default_color");
+ visible_line_count = 0;
while (y < size.height && from_line < main->lines.size()) {
- _process_line(main, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_DRAW, base_font, base_color, Point2i(), NULL, NULL, NULL, total_chars);
+ visible_line_count += _process_line(main, text_rect.get_position(), y, text_rect.get_size().width - scroll_w, from_line, PROCESS_DRAW, base_font, base_color, Point2i(), NULL, NULL, NULL, total_chars);
total_chars += main->lines[from_line].char_count;
from_line++;
}
@@ -1021,7 +1039,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
if (p_frame->first_invalid_line == p_frame->lines.size())
return;
- //validate invalid lines!s
+ //validate invalid lines
Size2 size = get_size();
Rect2 text_rect = _get_text_rect();
@@ -1673,6 +1691,12 @@ int RichTextLabel::get_line_count() const {
return current_frame->lines.size();
}
+int RichTextLabel::get_visible_line_count() const {
+ if (!is_visible())
+ return 0;
+ return visible_line_count;
+}
+
void RichTextLabel::set_selection_enabled(bool p_enabled) {
selection.enabled = p_enabled;
@@ -1915,6 +1939,9 @@ void RichTextLabel::_bind_methods() {
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);
+ ClassDB::bind_method(D_METHOD("get_line_count"), &RichTextLabel::get_line_count);
+ ClassDB::bind_method(D_METHOD("get_visible_line_count"), &RichTextLabel::get_visible_line_count);
+
ADD_GROUP("BBCode", "bbcode_");
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");
@@ -2003,6 +2030,7 @@ RichTextLabel::RichTextLabel() {
visible_characters = -1;
percent_visible = 1;
+ visible_line_count = 0;
set_clip_contents(true);
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 4db2c3a8e9..24c1e5eb59 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -217,6 +217,7 @@ private:
int scroll_w;
bool updating_scroll;
int current_idx;
+ int visible_line_count;
int tab_size;
bool underline_meta;
@@ -260,7 +261,7 @@ private:
int visible_characters;
float percent_visible;
- void _process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos = Point2i(), Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL, int p_char_count = 0);
+ int _process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Point2i &p_click_pos = Point2i(), Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL, int p_char_count = 0);
void _find_click(ItemFrame *p_frame, const Point2i &p_click, Item **r_click_item = NULL, int *r_click_char = NULL, bool *r_outside = NULL);
Ref<Font> _find_font(Item *p_item);
@@ -325,6 +326,7 @@ public:
void scroll_to_line(int p_line);
int get_line_count() const;
+ int get_visible_line_count() const;
VScrollBar *get_v_scroll() { return vscroll; }
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index 16d1b320b7..c5ffec2d5e 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -106,14 +106,14 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
if (ofs < grabber_ofs) {
if (scrolling) {
- target_scroll = target_scroll - get_page();
+ target_scroll = CLAMP(target_scroll - get_page(), get_min(), get_max() - get_page());
} else {
- target_scroll = get_value() - get_page();
+ target_scroll = CLAMP(get_value() - get_page(), get_min(), get_max() - get_page());
}
if (smooth_scroll_enabled) {
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
} else {
set_value(target_scroll);
}
@@ -130,14 +130,14 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
update();
} else {
if (scrolling) {
- target_scroll = target_scroll + get_page();
+ target_scroll = CLAMP(target_scroll + get_page(), get_min(), get_max() - get_page());
} else {
- target_scroll = get_value() + get_page();
+ target_scroll = CLAMP(get_value() + get_page(), get_min(), get_max() - get_page());
}
if (smooth_scroll_enabled) {
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
} else {
set_value(target_scroll);
}
@@ -335,29 +335,29 @@ void ScrollBar::_notification(int p_what) {
drag_slave = NULL;
}
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
if (scrolling) {
if (get_value() != target_scroll) {
double target = target_scroll - get_value();
double dist = sqrt(target * target);
- double vel = ((target / dist) * 500) * get_fixed_process_delta_time();
+ double vel = ((target / dist) * 500) * get_physics_process_delta_time();
- if (vel >= dist) {
+ if (Math::abs(vel) >= dist) {
set_value(target_scroll);
} else {
set_value(get_value() + vel);
}
} else {
scrolling = false;
- set_fixed_process(false);
+ set_physics_process(false);
}
} else if (drag_slave_touching) {
if (drag_slave_touching_deaccel) {
Vector2 pos = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0);
- pos += drag_slave_speed * get_fixed_process_delta_time();
+ pos += drag_slave_speed * get_physics_process_delta_time();
bool turnoff = false;
@@ -377,7 +377,7 @@ void ScrollBar::_notification(int p_what) {
float sgn_x = drag_slave_speed.x < 0 ? -1 : 1;
float val_x = Math::abs(drag_slave_speed.x);
- val_x -= 1000 * get_fixed_process_delta_time();
+ val_x -= 1000 * get_physics_process_delta_time();
if (val_x < 0) {
turnoff = true;
@@ -401,7 +401,7 @@ void ScrollBar::_notification(int p_what) {
float sgn_y = drag_slave_speed.y < 0 ? -1 : 1;
float val_y = Math::abs(drag_slave_speed.y);
- val_y -= 1000 * get_fixed_process_delta_time();
+ val_y -= 1000 * get_physics_process_delta_time();
if (val_y < 0) {
turnoff = true;
@@ -410,7 +410,7 @@ void ScrollBar::_notification(int p_what) {
}
if (turnoff) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_slave_touching = false;
drag_slave_touching_deaccel = false;
}
@@ -421,10 +421,10 @@ void ScrollBar::_notification(int p_what) {
Vector2 diff = drag_slave_accum - last_drag_slave_accum;
last_drag_slave_accum = drag_slave_accum;
- drag_slave_speed = diff / get_fixed_process_delta_time();
+ drag_slave_speed = diff / get_physics_process_delta_time();
}
- time_since_motion += get_fixed_process_delta_time();
+ time_since_motion += get_physics_process_delta_time();
}
}
}
@@ -579,7 +579,7 @@ void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) {
if (mb->is_pressed()) {
if (drag_slave_touching) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_slave_touching_deaccel = false;
drag_slave_touching = false;
drag_slave_speed = Vector2();
@@ -599,7 +599,7 @@ void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) {
drag_slave_touching_deaccel = false;
time_since_motion = 0;
if (drag_slave_touching) {
- set_fixed_process(true);
+ set_physics_process(true);
time_since_motion = 0;
}
}
@@ -611,7 +611,7 @@ void ScrollBar::_drag_slave_input(const Ref<InputEvent> &p_input) {
if (drag_slave_speed == Vector2()) {
drag_slave_touching_deaccel = false;
drag_slave_touching = false;
- set_fixed_process(false);
+ set_physics_process(false);
} else {
drag_slave_touching_deaccel = true;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index e182e491d3..1ad1e3f638 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -67,7 +67,7 @@ Size2 ScrollContainer::get_minimum_size() const {
};
void ScrollContainer::_cancel_drag() {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching_deaccel = false;
drag_touching = false;
drag_speed = Vector2();
@@ -121,7 +121,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->is_pressed()) {
if (drag_touching) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching_deaccel = false;
drag_touching = false;
drag_speed = Vector2();
@@ -139,7 +139,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
drag_touching_deaccel = false;
time_since_motion = 0;
if (drag_touching) {
- set_fixed_process(true);
+ set_physics_process(true);
time_since_motion = 0;
}
}
@@ -150,7 +150,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (drag_speed == Vector2()) {
drag_touching_deaccel = false;
drag_touching = false;
- set_fixed_process(false);
+ set_physics_process(false);
} else {
drag_touching_deaccel = true;
@@ -182,7 +182,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
-void ScrollContainer::_update_scrollbar_pos() {
+void ScrollContainer::_update_scrollbar_position() {
Size2 hmin = h_scroll->get_combined_minimum_size();
Size2 vmin = v_scroll->get_combined_minimum_size();
@@ -205,7 +205,7 @@ void ScrollContainer::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- call_deferred("_update_scrollbar_pos");
+ call_deferred("_update_scrollbar_position");
};
if (p_what == NOTIFICATION_SORT_CHILDREN) {
@@ -257,14 +257,14 @@ void ScrollContainer::_notification(int p_what) {
update_scrollbars();
}
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
if (drag_touching) {
if (drag_touching_deaccel) {
Vector2 pos = Vector2(h_scroll->get_value(), v_scroll->get_value());
- pos += drag_speed * get_fixed_process_delta_time();
+ pos += drag_speed * get_physics_process_delta_time();
bool turnoff_h = false;
bool turnoff_v = false;
@@ -294,7 +294,7 @@ void ScrollContainer::_notification(int p_what) {
float sgn_x = drag_speed.x < 0 ? -1 : 1;
float val_x = Math::abs(drag_speed.x);
- val_x -= 1000 * get_fixed_process_delta_time();
+ val_x -= 1000 * get_physics_process_delta_time();
if (val_x < 0) {
turnoff_h = true;
@@ -302,7 +302,7 @@ void ScrollContainer::_notification(int p_what) {
float sgn_y = drag_speed.y < 0 ? -1 : 1;
float val_y = Math::abs(drag_speed.y);
- val_y -= 1000 * get_fixed_process_delta_time();
+ val_y -= 1000 * get_physics_process_delta_time();
if (val_y < 0) {
turnoff_v = true;
@@ -311,7 +311,7 @@ void ScrollContainer::_notification(int p_what) {
drag_speed = Vector2(sgn_x * val_x, sgn_y * val_y);
if (turnoff_h && turnoff_v) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching = false;
drag_touching_deaccel = false;
}
@@ -322,10 +322,10 @@ void ScrollContainer::_notification(int p_what) {
Vector2 diff = drag_accum - last_drag_accum;
last_drag_accum = drag_accum;
- drag_speed = diff / get_fixed_process_delta_time();
+ drag_speed = diff / get_physics_process_delta_time();
}
- time_since_motion += get_fixed_process_delta_time();
+ time_since_motion += get_physics_process_delta_time();
}
}
}
@@ -448,7 +448,7 @@ void ScrollContainer::_bind_methods() {
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("_update_scrollbar_position"), &ScrollContainer::_update_scrollbar_position);
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);
diff --git a/scene/gui/scroll_container.h b/scene/gui/scroll_container.h
index 9076be0d72..2c5d60de6c 100644
--- a/scene/gui/scroll_container.h
+++ b/scene/gui/scroll_container.h
@@ -70,7 +70,7 @@ protected:
void _scroll_moved(float);
static void _bind_methods();
- void _update_scrollbar_pos();
+ void _update_scrollbar_position();
public:
int get_v_scroll() const;
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 8fda5df53c..116e0ac354 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -181,7 +181,7 @@ void Slider::_notification(int p_what) {
for (int i = 0; i < ticks; i++) {
if (!ticks_on_borders && (i == 0 || i + 1 == ticks)) continue;
int ofs = i * tickarea / (ticks - 1);
- tick->draw(ci, Point2(0, ofs));
+ tick->draw(ci, Point2i((size.width - widget_width) / 2, ofs));
}
}
grabber->draw(ci, Point2i(size.width / 2 - grabber->get_size().width / 2, size.height - get_as_ratio() * areasize - grabber->get_size().height));
@@ -202,7 +202,7 @@ void Slider::_notification(int p_what) {
for (int i = 0; i < ticks; i++) {
if ((!ticks_on_borders) && ((i == 0) || ((i + 1) == ticks))) continue;
int ofs = i * tickarea / (ticks - 1);
- tick->draw(ci, Point2(ofs, 0));
+ tick->draw(ci, Point2i(ofs, (size.height - widget_height) / 2));
}
}
grabber->draw(ci, Point2i(get_as_ratio() * areasize, size.height / 2 - grabber->get_size().height / 2));
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index f462989f53..05f2809bfc 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -72,7 +72,7 @@ void SpinBox::_range_click_timeout() {
if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
- bool up = get_local_mouse_pos().y < (get_size().height / 2);
+ bool up = get_local_mouse_position().y < (get_size().height / 2);
set_value(get_value() + (up ? get_step() : -get_step()));
if (range_click_timer->is_one_shot()) {
@@ -268,7 +268,7 @@ SpinBox::SpinBox() {
line_edit = memnew(LineEdit);
add_child(line_edit);
- line_edit->set_area_as_parent_rect();
+ line_edit->set_anchors_and_margins_preset(Control::PRESET_WIDE);
//connect("value_changed",this,"_value_changed");
line_edit->connect("text_entered", this, "_text_entered", Vector<Variant>(), CONNECT_DEFERRED);
line_edit->connect("focus_exited", this, "_line_edit_focus_exit", Vector<Variant>(), CONNECT_DEFERRED);
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 657e8590d4..6e50614e8f 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -208,6 +208,9 @@ void TabContainer::_notification(int p_what) {
break;
}
+ // Draw the tab area.
+ panel->draw(canvas, Rect2(0, header_height, size.width, size.height - header_height));
+
// Draw all visible tabs.
int x = 0;
for (int i = 0; i < tab_widths.size(); i++) {
@@ -261,9 +264,9 @@ void TabContainer::_notification(int p_what) {
if (popup) {
x -= menu->get_width();
if (mouse_x_cache > x)
- menu_hl->draw(get_canvas_item(), Size2(x, 0));
+ menu_hl->draw(get_canvas_item(), Size2(x, (header_height - menu_hl->get_height()) / 2));
else
- menu->draw(get_canvas_item(), Size2(x, 0));
+ menu->draw(get_canvas_item(), Size2(x, (header_height - menu->get_height()) / 2));
}
// Draw the navigation buttons.
@@ -280,9 +283,6 @@ void TabContainer::_notification(int p_what) {
Point2(x, y_center - (decrement->get_height() / 2)),
Color(1, 1, 1, first_tab_cache > 0 ? 1.0 : 0.5));
}
-
- // 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) {
@@ -367,7 +367,7 @@ void TabContainer::add_child_notify(Node *p_child) {
current = 0;
previous = 0;
}
- c->set_area_as_parent_rect();
+ c->set_anchors_and_margins_preset(Control::PRESET_WIDE);
if (tabs_visible)
c->set_margin(MARGIN_TOP, _get_top_margin());
Ref<StyleBox> sb = get_stylebox("panel");
@@ -401,7 +401,7 @@ void TabContainer::set_current_tab(int p_current) {
Control *c = tabs[i];
if (i == current) {
c->show();
- c->set_area_as_parent_rect();
+ c->set_anchors_and_margins_preset(Control::PRESET_WIDE);
if (tabs_visible)
c->set_margin(MARGIN_TOP, _get_top_margin());
c->set_margin(Margin(MARGIN_TOP), c->get_margin(Margin(MARGIN_TOP)) + sb->get_margin(Margin(MARGIN_TOP)));
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 1738e303aa..d14d3ef947 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -36,6 +36,10 @@
#include "project_settings.h"
#include "scene/main/viewport.h"
+#ifdef TOOLS_ENABLED
+#include "editor/editor_scale.h"
+#endif
+
#define TAB_PIXELS
static bool _is_text_char(CharType c) {
@@ -424,22 +428,22 @@ void TextEdit::_notification(int p_what) {
draw_caret = false;
update();
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
if (scrolling && v_scroll->get_value() != target_v_scroll) {
double target_y = target_v_scroll - v_scroll->get_value();
double dist = sqrt(target_y * target_y);
- double vel = ((target_y / dist) * v_scroll_speed) * get_fixed_process_delta_time();
+ double vel = ((target_y / dist) * v_scroll_speed) * get_physics_process_delta_time();
if (Math::abs(vel) >= dist) {
v_scroll->set_value(target_v_scroll);
scrolling = false;
- set_fixed_process(false);
+ set_physics_process(false);
} else {
v_scroll->set_value(v_scroll->get_value() + vel);
}
} else {
scrolling = false;
- set_fixed_process(false);
+ set_physics_process(false);
}
} break;
case NOTIFICATION_DRAW: {
@@ -497,8 +501,7 @@ void TextEdit::_notification(int p_what) {
if (cache.background_color.a > 0.01) {
- Point2i ofs = Point2i(cache.style_normal->get_offset()) / 2.0;
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs, get_size() - cache.style_normal->get_minimum_size() + ofs), cache.background_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color);
}
//compute actual region to start (may be inside say, a comment).
//slow in very large documments :( but ok for source!
@@ -729,15 +732,18 @@ void TextEdit::_notification(int p_what) {
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color);
}
- if (text.is_breakpoint(line)) {
-
- VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color);
- }
-
if (line == cursor.line) {
VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_end, get_row_height()), cache.current_line_color);
}
+ if (text.is_breakpoint(line) && !draw_breakpoint_gutter) {
+#ifdef TOOLS_ENABLED
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color);
+#else
+ VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color);
+#endif
+ }
+
// draw breakpoint marker
if (text.is_breakpoint(line)) {
if (draw_breakpoint_gutter) {
@@ -1604,7 +1610,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
target_v_scroll = 0;
}
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
} else {
v_scroll->set_value(target_v_scroll);
}
@@ -1626,7 +1632,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
target_v_scroll = max_v_scroll;
}
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
} else {
v_scroll->set_value(target_v_scroll);
}
@@ -1766,7 +1772,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (mb->get_button_index() == BUTTON_RIGHT && context_menu_enabled) {
- menu->set_position(get_global_transform().xform(get_local_mouse_pos()));
+ menu->set_position(get_global_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
menu->popup();
grab_focus();
@@ -1837,7 +1843,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (k->is_pressed()) {
- highlighted_word = get_word_at_pos(get_local_mouse_pos());
+ highlighted_word = get_word_at_pos(get_local_mouse_position());
update();
} else {
@@ -2793,12 +2799,16 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
int ini = selection.from_line;
int end = selection.to_line;
for (int i = ini; i <= end; i++) {
- if (text[i][0] == '#')
+ if (get_line(i).begins_with("#"))
_remove_text(i, 0, i, 1);
}
} else {
- if (text[cursor.line][0] == '#')
+ if (get_line(cursor.line).begins_with("#")) {
_remove_text(cursor.line, 0, cursor.line, 1);
+ if (cursor.column >= get_line(cursor.line).length()) {
+ cursor.column = MAX(0, get_line(cursor.line).length() - 1);
+ }
+ }
}
update();
}
@@ -3488,7 +3498,7 @@ String TextEdit::get_text() {
String TextEdit::get_text_for_lookup_completion() {
int row, col;
- _get_mouse_pos(get_local_mouse_pos(), row, col);
+ _get_mouse_pos(get_local_mouse_position(), row, col);
String longthing;
int len = text.size();
@@ -4255,6 +4265,10 @@ bool TextEdit::is_insert_mode() const {
return insert_mode;
}
+bool TextEdit::is_insert_text_operation() {
+ return (current_op.type == TextOperation::TYPE_INSERT);
+}
+
uint32_t TextEdit::get_version() const {
return current_op.version;
}
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 68ef559f46..7e61c4e8b1 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -386,6 +386,8 @@ public:
void begin_complex_operation();
void end_complex_operation();
+ bool is_insert_text_operation();
+
void set_text(String p_text);
void insert_text_at_cursor(const String &p_text);
void insert_at(const String &p_text, int at);
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 7fa29d312e..178a1c272b 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -862,6 +862,7 @@ void Tree::update_cache() {
cache.arrow_collapsed = get_icon("arrow_collapsed");
cache.arrow = get_icon("arrow");
cache.select_arrow = get_icon("select_arrow");
+ cache.select_option = get_icon("select_option");
cache.updown = get_icon("updown");
cache.custom_button = get_stylebox("custom_button");
@@ -1528,7 +1529,7 @@ void Tree::_range_click_timeout() {
if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
- Point2 pos = get_local_mouse_pos() - cache.bg->get_offset();
+ Point2 pos = get_local_mouse_position() - cache.bg->get_offset();
if (show_column_titles) {
pos.y -= _get_title_button_height();
@@ -1676,7 +1677,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
p_item->select(col);
emit_signal("multi_selected", p_item, col, true);
if (p_button == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_pos());
+ emit_signal("item_rmb_selected", get_local_mouse_position());
}
//p_item->selected_signal.call(col);
@@ -1697,7 +1698,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
select_single_item(p_item, root, col, selected_item, &inrange);
if (p_button == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_pos());
+ emit_signal("item_rmb_selected", get_local_mouse_position());
}
} else {
@@ -1713,7 +1714,7 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
}
if (p_button == BUTTON_RIGHT) {
- emit_signal("item_rmb_selected", get_local_mouse_pos());
+ emit_signal("item_rmb_selected", get_local_mouse_position());
}
}
}
@@ -1914,7 +1915,7 @@ void Tree::_text_editor_modal_close() {
return;
}
- if (value_editor->has_point(value_editor->get_local_mouse_pos()))
+ if (value_editor->has_point(value_editor->get_local_mouse_position()))
return;
text_editor_enter(text_editor->get_text());
@@ -2010,7 +2011,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (!k->is_pressed())
return;
- if (k->get_alt() || k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey())
+ if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey())
return;
if (!root)
return;
@@ -2025,48 +2026,47 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
break; \
}
case KEY_RIGHT: {
+ bool dobreak = true;
//TreeItem *next = NULL;
if (!selected_item)
break;
- if (select_mode == SELECT_ROW)
+ if (select_mode == SELECT_ROW) {
EXIT_BREAK;
- if (selected_col >= (columns.size() - 1))
+ }
+ if (selected_col > (columns.size() - 1)) {
EXIT_BREAK;
- if (select_mode == SELECT_MULTI) {
- selected_col++;
- emit_signal("cell_selected");
+ }
+ if (k->get_alt()) {
+ selected_item->set_collapsed(false);
+ TreeItem *next = selected_item->get_children();
+ while (next && next != selected_item->next) {
+ next->set_collapsed(false);
+ next = next->get_next_visible();
+ }
+ } else if (selected_col == (columns.size() - 1)) {
+ if (selected_item->get_children() != NULL && selected_item->is_collapsed()) {
+ selected_item->set_collapsed(false);
+ } else {
+ selected_col = 0;
+ dobreak = false; // fall through to key_down
+ }
} else {
+ if (select_mode == SELECT_MULTI) {
+ selected_col++;
+ emit_signal("cell_selected");
+ } else {
- selected_item->select(selected_col + 1);
+ selected_item->select(selected_col + 1);
+ }
}
-
update();
ensure_cursor_is_visible();
accept_event();
-
- } break;
- case KEY_LEFT: {
-
- //TreeItem *next = NULL;
- if (!selected_item)
+ if (dobreak) {
break;
- if (select_mode == SELECT_ROW)
- EXIT_BREAK;
- if (selected_col <= 0)
- EXIT_BREAK;
- if (select_mode == SELECT_MULTI) {
- selected_col--;
- emit_signal("cell_selected");
- } else {
-
- selected_item->select(selected_col - 1);
}
-
- update();
- accept_event();
-
- } break;
+ }
case KEY_DOWN: {
TreeItem *next = NULL;
@@ -2113,6 +2113,56 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
accept_event();
} break;
+ case KEY_LEFT: {
+ bool dobreak = true;
+
+ //TreeItem *next = NULL;
+ if (!selected_item)
+ break;
+ if (select_mode == SELECT_ROW) {
+ EXIT_BREAK;
+ }
+ if (selected_col < 0) {
+ EXIT_BREAK;
+ }
+ if (k->get_alt()) {
+ selected_item->set_collapsed(true);
+ TreeItem *next = selected_item->get_children();
+ while (next && next != selected_item->next) {
+ next->set_collapsed(true);
+ next = next->get_next_visible();
+ }
+ } else if (selected_col == 0) {
+ if (selected_item->get_children() != NULL && !selected_item->is_collapsed()) {
+ selected_item->set_collapsed(true);
+ } else {
+ if (columns.size() == 1) { // goto parent with one column
+ TreeItem *parent = selected_item->get_parent();
+ if (selected_item != get_root() && parent && parent->is_selectable(selected_col) && !(hide_root && parent == get_root())) {
+ select_single_item(parent, get_root(), selected_col);
+ }
+ } else {
+ selected_col = columns.size() - 1;
+ dobreak = false; // fall through to key_up
+ }
+ }
+ } else {
+ if (select_mode == SELECT_MULTI) {
+ selected_col--;
+ emit_signal("cell_selected");
+ } else {
+
+ selected_item->select(selected_col - 1);
+ }
+ }
+ update();
+ accept_event();
+ ensure_cursor_is_visible();
+
+ if (dobreak) {
+ break;
+ }
+ }
case KEY_UP: {
TreeItem *prev = NULL;
@@ -2429,7 +2479,7 @@ void Tree::_gui_input(Ref<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);
+ cache.click_item = get_item_at_position(cache.click_pos);
emit_signal("button_pressed", cache.click_item, cache.click_column, cache.click_id);
}
cache.click_type = Cache::CLICK_NONE;
@@ -2443,7 +2493,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (drag_speed == 0) {
drag_touching_deaccel = false;
drag_touching = false;
- set_fixed_process(false);
+ set_physics_process(false);
} else {
drag_touching_deaccel = true;
@@ -2489,7 +2539,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
}
if (!root || (!root->get_children() && hide_root)) {
if (b->get_button_index() == BUTTON_RIGHT && allow_rmb_select) {
- emit_signal("empty_tree_rmb_selected", get_local_mouse_pos());
+ emit_signal("empty_tree_rmb_selected", get_local_mouse_position());
}
break;
}
@@ -2509,7 +2559,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
break;
if (drag_touching) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching_deaccel = false;
drag_touching = false;
drag_speed = 0;
@@ -2524,7 +2574,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
drag_touching = OS::get_singleton()->has_touchscreen_ui_hint();
drag_touching_deaccel = false;
if (drag_touching) {
- set_fixed_process(true);
+ set_physics_process(true);
}
}
@@ -2715,7 +2765,7 @@ void Tree::_notification(int p_what) {
drop_mode_flags = 0;
scrolling = false;
- set_fixed_process(false);
+ set_physics_process(false);
update();
}
if (p_what == NOTIFICATION_DRAG_BEGIN) {
@@ -2723,23 +2773,23 @@ void Tree::_notification(int p_what) {
single_select_defer = NULL;
if (cache.scroll_speed > 0 && get_rect().has_point(get_viewport()->get_mouse_position() - get_global_position())) {
scrolling = true;
- set_fixed_process(true);
+ set_physics_process(true);
}
}
- if (p_what == NOTIFICATION_FIXED_PROCESS) {
+ if (p_what == NOTIFICATION_PHYSICS_PROCESS) {
if (drag_touching) {
if (drag_touching_deaccel) {
float pos = v_scroll->get_value();
- pos += drag_speed * get_fixed_process_delta_time();
+ pos += drag_speed * get_physics_process_delta_time();
bool turnoff = false;
if (pos < 0) {
pos = 0;
turnoff = true;
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching = false;
drag_touching_deaccel = false;
}
@@ -2751,7 +2801,7 @@ void Tree::_notification(int p_what) {
v_scroll->set_value(pos);
float sgn = drag_speed < 0 ? -1 : 1;
float val = Math::abs(drag_speed);
- val -= 1000 * get_fixed_process_delta_time();
+ val -= 1000 * get_physics_process_delta_time();
if (val < 0) {
turnoff = true;
@@ -2759,7 +2809,7 @@ void Tree::_notification(int p_what) {
drag_speed = sgn * val;
if (turnoff) {
- set_fixed_process(false);
+ set_physics_process(false);
drag_touching = false;
drag_touching_deaccel = false;
}
@@ -2784,7 +2834,7 @@ void Tree::_notification(int p_what) {
} else {
point.y = 0;
}
- point *= cache.scroll_speed * get_fixed_process_delta_time();
+ point *= cache.scroll_speed * get_physics_process_delta_time();
point += get_scroll();
h_scroll->set_value(point.x);
v_scroll->set_value(point.y);
@@ -3387,7 +3437,7 @@ TreeItem *Tree::_find_item_at_pos(TreeItem *p_item, const Point2 &p_pos, int &r_
return NULL;
}
-int Tree::get_column_at_pos(const Point2 &p_pos) const {
+int Tree::get_column_at_position(const Point2 &p_pos) const {
if (root) {
@@ -3413,7 +3463,7 @@ int Tree::get_column_at_pos(const Point2 &p_pos) const {
return -1;
}
-int Tree::get_drop_section_at_pos(const Point2 &p_pos) const {
+int Tree::get_drop_section_at_position(const Point2 &p_pos) const {
if (root) {
@@ -3438,7 +3488,7 @@ int Tree::get_drop_section_at_pos(const Point2 &p_pos) const {
return -100;
}
-TreeItem *Tree::get_item_at_pos(const Point2 &p_pos) const {
+TreeItem *Tree::get_item_at_position(const Point2 &p_pos) const {
if (root) {
@@ -3611,9 +3661,9 @@ void Tree::_bind_methods() {
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", "column"), &Tree::_get_item_rect, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("get_item_at_pos", "pos"), &Tree::get_item_at_pos);
- ClassDB::bind_method(D_METHOD("get_column_at_pos", "pos"), &Tree::get_column_at_pos);
- ClassDB::bind_method(D_METHOD("get_drop_section_at_pos", "pos"), &Tree::get_drop_section_at_pos);
+ ClassDB::bind_method(D_METHOD("get_item_at_position", "position"), &Tree::get_item_at_position);
+ ClassDB::bind_method(D_METHOD("get_column_at_position", "position"), &Tree::get_column_at_position);
+ ClassDB::bind_method(D_METHOD("get_drop_section_at_position", "position"), &Tree::get_drop_section_at_position);
ClassDB::bind_method(D_METHOD("ensure_cursor_is_visible"), &Tree::ensure_cursor_is_visible);
@@ -3639,8 +3689,8 @@ void Tree::_bind_methods() {
ADD_SIGNAL(MethodInfo("item_selected"));
ADD_SIGNAL(MethodInfo("cell_selected"));
ADD_SIGNAL(MethodInfo("multi_selected", PropertyInfo(Variant::OBJECT, "item"), PropertyInfo(Variant::INT, "column"), PropertyInfo(Variant::BOOL, "selected")));
- ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::VECTOR2, "pos")));
- ADD_SIGNAL(MethodInfo("empty_tree_rmb_selected", PropertyInfo(Variant::VECTOR2, "pos")));
+ ADD_SIGNAL(MethodInfo("item_rmb_selected", PropertyInfo(Variant::VECTOR2, "position")));
+ ADD_SIGNAL(MethodInfo("empty_tree_rmb_selected", PropertyInfo(Variant::VECTOR2, "position")));
ADD_SIGNAL(MethodInfo("item_edited"));
ADD_SIGNAL(MethodInfo("item_rmb_edited"));
ADD_SIGNAL(MethodInfo("item_custom_button_pressed"));
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 5f19558597..2ee91a8b73 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -418,6 +418,7 @@ private:
Ref<Texture> arrow_collapsed;
Ref<Texture> arrow;
Ref<Texture> select_arrow;
+ Ref<Texture> select_option;
Ref<Texture> updown;
Color font_color;
@@ -525,9 +526,9 @@ protected:
public:
virtual String get_tooltip(const Point2 &p_pos) const;
- TreeItem *get_item_at_pos(const Point2 &p_pos) const;
- int get_column_at_pos(const Point2 &p_pos) const;
- int get_drop_section_at_pos(const Point2 &p_pos) const;
+ TreeItem *get_item_at_position(const Point2 &p_pos) const;
+ int get_column_at_position(const Point2 &p_pos) const;
+ int get_drop_section_at_position(const Point2 &p_pos) const;
void clear();
diff --git a/scene/gui/video_player.cpp b/scene/gui/video_player.cpp
index a92155cc4f..816556af30 100644
--- a/scene/gui/video_player.cpp
+++ b/scene/gui/video_player.cpp
@@ -278,11 +278,11 @@ String VideoPlayer::get_stream_name() const {
return stream->get_name();
};
-float VideoPlayer::get_stream_pos() const {
+float VideoPlayer::get_stream_position() const {
if (playback.is_null())
return 0;
- return playback->get_pos();
+ return playback->get_playback_position();
};
Ref<Texture> VideoPlayer::get_video_texture() {
@@ -327,7 +327,7 @@ void VideoPlayer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_stream_name"), &VideoPlayer::get_stream_name);
- ClassDB::bind_method(D_METHOD("get_stream_pos"), &VideoPlayer::get_stream_pos);
+ ClassDB::bind_method(D_METHOD("get_stream_position"), &VideoPlayer::get_stream_position);
ClassDB::bind_method(D_METHOD("set_autoplay", "enabled"), &VideoPlayer::set_autoplay);
ClassDB::bind_method(D_METHOD("has_autoplay"), &VideoPlayer::has_autoplay);
diff --git a/scene/gui/video_player.h b/scene/gui/video_player.h
index b78f3aabe7..bea10907bb 100644
--- a/scene/gui/video_player.h
+++ b/scene/gui/video_player.h
@@ -92,7 +92,7 @@ public:
float get_volume_db() const;
String get_stream_name() const;
- float get_stream_pos() const;
+ float get_stream_position() const;
void set_autoplay(bool p_enable);
bool has_autoplay() const;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index a30fc03aa9..c2a31b4a8b 100755
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "node.h"
+#include "core/core_string_names.h"
#include "instance_placeholder.h"
#include "io/resource_loader.h"
#include "message_queue.h"
@@ -53,13 +54,13 @@ void Node::_notification(int p_notification) {
get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_process, ptr, 1);
}
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
if (get_script_instance()) {
- Variant time = get_fixed_process_delta_time();
+ Variant time = get_physics_process_delta_time();
const Variant *ptr[1] = { &time };
- get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_fixed_process, ptr, 1);
+ get_script_instance()->call_multilevel(SceneStringNames::get_singleton()->_physics_process, ptr, 1);
}
} break;
@@ -128,8 +129,8 @@ void Node::_notification(int p_notification) {
set_process(true);
}
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_fixed_process)) {
- set_fixed_process(true);
+ if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_physics_process)) {
+ set_physics_process(true);
}
get_script_instance()->call_multilevel_reversed(SceneStringNames::get_singleton()->_ready, NULL, 0);
@@ -366,46 +367,46 @@ void Node::move_child_notify(Node *p_child) {
// to be used when not wanted
}
-void Node::set_fixed_process(bool p_process) {
+void Node::set_physics_process(bool p_process) {
- if (data.fixed_process == p_process)
+ if (data.physics_process == p_process)
return;
- data.fixed_process = p_process;
+ data.physics_process = p_process;
- if (data.fixed_process)
- add_to_group("fixed_process", false);
+ if (data.physics_process)
+ add_to_group("physics_process", false);
else
- remove_from_group("fixed_process");
+ remove_from_group("physics_process");
- data.fixed_process = p_process;
- _change_notify("fixed_process");
+ data.physics_process = p_process;
+ _change_notify("physics_process");
}
-bool Node::is_fixed_processing() const {
+bool Node::is_physics_processing() const {
- return data.fixed_process;
+ return data.physics_process;
}
-void Node::set_fixed_process_internal(bool p_process_internal) {
+void Node::set_physics_process_internal(bool p_process_internal) {
- if (data.fixed_process_internal == p_process_internal)
+ if (data.physics_process_internal == p_process_internal)
return;
- data.fixed_process_internal = p_process_internal;
+ data.physics_process_internal = p_process_internal;
- if (data.fixed_process_internal)
- add_to_group("fixed_process_internal", false);
+ if (data.physics_process_internal)
+ add_to_group("physics_process_internal", false);
else
- remove_from_group("fixed_process_internal");
+ remove_from_group("physics_process_internal");
- data.fixed_process_internal = p_process_internal;
- _change_notify("fixed_process_internal");
+ data.physics_process_internal = p_process_internal;
+ _change_notify("physics_process_internal");
}
-bool Node::is_fixed_processing_internal() const {
+bool Node::is_physics_processing_internal() const {
- return data.fixed_process_internal;
+ return data.physics_process_internal;
}
void Node::set_pause_mode(PauseMode p_mode) {
@@ -1009,10 +1010,10 @@ bool Node::can_process() const {
return true;
}
-float Node::get_fixed_process_delta_time() const {
+float Node::get_physics_process_delta_time() const {
if (data.tree)
- return data.tree->get_fixed_process_time();
+ return data.tree->get_physics_process_time();
else
return 0;
}
@@ -2104,12 +2105,22 @@ Node *Node::_duplicate(int p_flags) const {
get_property_list(&plist);
+ StringName script_property_name = CoreStringNames::get_singleton()->_script;
+
+ if (p_flags & DUPLICATE_SCRIPTS) {
+ bool is_valid = false;
+ Variant script = get(script_property_name, &is_valid);
+ if (is_valid) {
+ node->set(script_property_name, script);
+ }
+ }
+
for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) {
if (!(E->get().usage & PROPERTY_USAGE_STORAGE))
continue;
String name = E->get().name;
- if (!(p_flags & DUPLICATE_SCRIPTS) && name == "script/script")
+ if (name == script_property_name)
continue;
Variant value = get(name);
@@ -2572,8 +2583,11 @@ void Node::print_stray_nodes() {
void Node::queue_delete() {
- ERR_FAIL_COND(!is_inside_tree());
- get_tree()->queue_delete(this);
+ if (is_inside_tree()) {
+ get_tree()->queue_delete(this);
+ } else {
+ SceneTree::get_singleton()->queue_delete(this);
+ }
}
Array Node::_get_children() const {
@@ -2693,7 +2707,7 @@ void Node::_bind_methods() {
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", "to_pos"), &Node::move_child);
+ ClassDB::bind_method(D_METHOD("move_child", "child_node", "to_position"), &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::set_owner);
@@ -2705,9 +2719,9 @@ void Node::_bind_methods() {
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("propagate_call", "method", "args", "parent_first"), &Node::propagate_call, DEFVAL(Array()), DEFVAL(false));
- 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("set_physics_process", "enable"), &Node::set_physics_process);
+ ClassDB::bind_method(D_METHOD("get_physics_process_delta_time"), &Node::get_physics_process_delta_time);
+ ClassDB::bind_method(D_METHOD("is_physics_processing"), &Node::is_physics_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);
@@ -2728,8 +2742,8 @@ void Node::_bind_methods() {
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("set_physics_process_internal", "enable"), &Node::set_physics_process_internal);
+ ClassDB::bind_method(D_METHOD("is_physics_processing_internal"), &Node::is_physics_processing_internal);
ClassDB::bind_method(D_METHOD("get_tree"), &Node::get_tree);
@@ -2787,7 +2801,7 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_EXIT_TREE);
BIND_CONSTANT(NOTIFICATION_MOVED_IN_PARENT);
BIND_CONSTANT(NOTIFICATION_READY);
- BIND_CONSTANT(NOTIFICATION_FIXED_PROCESS);
+ BIND_CONSTANT(NOTIFICATION_PHYSICS_PROCESS);
BIND_CONSTANT(NOTIFICATION_PROCESS);
BIND_CONSTANT(NOTIFICATION_PARENTED);
BIND_CONSTANT(NOTIFICATION_UNPARENTED);
@@ -2799,7 +2813,7 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_PATH_CHANGED);
BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
BIND_CONSTANT(NOTIFICATION_INTERNAL_PROCESS);
- BIND_CONSTANT(NOTIFICATION_INTERNAL_FIXED_PROCESS);
+ BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
BIND_ENUM_CONSTANT(RPC_MODE_DISABLED);
BIND_ENUM_CONSTANT(RPC_MODE_REMOTE);
@@ -2821,7 +2835,7 @@ void Node::_bind_methods() {
ADD_SIGNAL(MethodInfo("tree_exited"));
//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/physics_process" ), "set_physics_process","is_physics_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_");
@@ -2829,7 +2843,7 @@ void Node::_bind_methods() {
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")));
+ BIND_VMETHOD(MethodInfo("_physics_process", PropertyInfo(Variant::REAL, "delta")));
BIND_VMETHOD(MethodInfo("_enter_tree"));
BIND_VMETHOD(MethodInfo("_exit_tree"));
BIND_VMETHOD(MethodInfo("_ready"));
@@ -2858,9 +2872,9 @@ Node::Node() {
data.blocked = 0;
data.parent = NULL;
data.tree = NULL;
- data.fixed_process = false;
+ data.physics_process = false;
data.idle_process = false;
- data.fixed_process_internal = false;
+ data.physics_process_internal = false;
data.idle_process_internal = false;
data.inside_tree = false;
data.ready_notified = false;
diff --git a/scene/main/node.h b/scene/main/node.h
index 12d6310062..c43e96063f 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -121,10 +121,10 @@ private:
// variables used to properly sort the node when processing, ignored otherwise
//should move all the stuff below to bits
- bool fixed_process;
+ bool physics_process;
bool idle_process;
- bool fixed_process_internal;
+ bool physics_process_internal;
bool idle_process_internal;
bool input;
@@ -213,7 +213,7 @@ public:
NOTIFICATION_READY = 13,
NOTIFICATION_PAUSED = 14,
NOTIFICATION_UNPAUSED = 15,
- NOTIFICATION_FIXED_PROCESS = 16,
+ NOTIFICATION_PHYSICS_PROCESS = 16,
NOTIFICATION_PROCESS = 17,
NOTIFICATION_PARENTED = 18,
NOTIFICATION_UNPARENTED = 19,
@@ -223,7 +223,7 @@ public:
NOTIFICATION_PATH_CHANGED = 23,
NOTIFICATION_TRANSLATION_CHANGED = 24,
NOTIFICATION_INTERNAL_PROCESS = 25,
- NOTIFICATION_INTERNAL_FIXED_PROCESS = 26,
+ NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26,
};
@@ -299,16 +299,16 @@ public:
void propagate_call(const StringName &p_method, const Array &p_args = Array(), const bool p_parent_first = false);
/* PROCESSING */
- void set_fixed_process(bool p_process);
- float get_fixed_process_delta_time() const;
- bool is_fixed_processing() const;
+ void set_physics_process(bool p_process);
+ float get_physics_process_delta_time() const;
+ bool is_physics_processing() const;
void set_process(bool p_idle_process);
float get_process_delta_time() const;
bool is_processing() const;
- void set_fixed_process_internal(bool p_process_internal);
- bool is_fixed_processing_internal() const;
+ void set_physics_process_internal(bool p_process_internal);
+ bool is_physics_processing_internal() const;
void set_process_internal(bool p_idle_process_internal);
bool is_processing_internal() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 4f62d88934..7a28e2a6f8 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -446,12 +446,12 @@ bool SceneTree::iteration(float p_time) {
_flush_transform_notifications();
MainLoop::iteration(p_time);
- fixed_process_time = p_time;
+ physics_process_time = p_time;
- emit_signal("fixed_frame");
+ emit_signal("physics_frame");
- _notify_group_pause("fixed_process_internal", Node::NOTIFICATION_INTERNAL_FIXED_PROCESS);
- _notify_group_pause("fixed_process", Node::NOTIFICATION_FIXED_PROCESS);
+ _notify_group_pause("physics_process_internal", Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
+ _notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS);
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
_flush_transform_notifications();
@@ -650,7 +650,7 @@ void SceneTree::set_quit_on_go_back(bool p_enable) {
bool SceneTree::is_node_being_edited(const Node *p_node) const {
- return Engine::get_singleton()->is_editor_hint() && edited_scene_root && edited_scene_root->is_a_parent_of(p_node);
+ return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_a_parent_of(p_node) || edited_scene_root == p_node);
}
#endif
@@ -2194,7 +2194,7 @@ void SceneTree::_bind_methods() {
ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node")));
ADD_SIGNAL(MethodInfo("idle_frame"));
- ADD_SIGNAL(MethodInfo("fixed_frame"));
+ ADD_SIGNAL(MethodInfo("physics_frame"));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::POOL_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen")));
ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
@@ -2216,6 +2216,7 @@ void SceneTree::_bind_methods() {
BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP);
BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_WIDTH);
BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_HEIGHT);
+ BIND_ENUM_CONSTANT(STRETCH_ASPECT_EXPAND);
}
SceneTree *SceneTree::singleton = NULL;
@@ -2253,7 +2254,7 @@ SceneTree::SceneTree() {
collision_debug_contacts = GLOBAL_DEF("debug/shapes/collision/max_contacts_displayed", 10000);
tree_version = 1;
- fixed_process_time = 1;
+ physics_process_time = 1;
idle_process_time = 1;
last_id = 1;
root = NULL;
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index c116bec4fc..f3e689adab 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -105,7 +105,7 @@ private:
Viewport *root;
uint64_t tree_version;
- float fixed_process_time;
+ float physics_process_time;
float idle_process_time;
bool accept_quit;
bool quit_on_go_back;
@@ -358,7 +358,7 @@ public:
void set_input_as_handled();
bool is_input_handled();
- _FORCE_INLINE_ float get_fixed_process_time() const { return fixed_process_time; }
+ _FORCE_INLINE_ float get_physics_process_time() const { return physics_process_time; }
_FORCE_INLINE_ float get_idle_process_time() const { return idle_process_time; }
#ifdef TOOLS_ENABLED
diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp
index df7d609ac0..23854b5f59 100755
--- a/scene/main/timer.cpp
+++ b/scene/main/timer.cpp
@@ -47,7 +47,7 @@ void Timer::_notification(int p_what) {
}
} break;
case NOTIFICATION_INTERNAL_PROCESS: {
- if (timer_process_mode == TIMER_PROCESS_FIXED || !is_processing_internal())
+ if (timer_process_mode == TIMER_PROCESS_PHYSICS || !is_processing_internal())
return;
time_left -= get_process_delta_time();
@@ -61,10 +61,10 @@ void Timer::_notification(int p_what) {
}
} break;
- case NOTIFICATION_INTERNAL_FIXED_PROCESS: {
- if (timer_process_mode == TIMER_PROCESS_IDLE || !is_fixed_processing_internal())
+ case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
+ if (timer_process_mode == TIMER_PROCESS_IDLE || !is_physics_processing_internal())
return;
- time_left -= get_fixed_process_delta_time();
+ time_left -= get_physics_process_delta_time();
if (time_left < 0) {
if (!one_shot)
@@ -144,16 +144,16 @@ void Timer::set_timer_process_mode(TimerProcessMode p_mode) {
return;
switch (timer_process_mode) {
- case TIMER_PROCESS_FIXED:
- if (is_fixed_processing_internal()) {
- set_fixed_process_internal(false);
+ case TIMER_PROCESS_PHYSICS:
+ if (is_physics_processing_internal()) {
+ set_physics_process_internal(false);
set_process_internal(true);
}
break;
case TIMER_PROCESS_IDLE:
if (is_processing_internal()) {
set_process_internal(false);
- set_fixed_process_internal(true);
+ set_physics_process_internal(true);
}
break;
}
@@ -167,7 +167,7 @@ Timer::TimerProcessMode Timer::get_timer_process_mode() const {
void Timer::_set_process(bool p_process, bool p_force) {
switch (timer_process_mode) {
- case TIMER_PROCESS_FIXED: set_fixed_process_internal(p_process && !paused); break;
+ case TIMER_PROCESS_PHYSICS: set_physics_process_internal(p_process && !paused); break;
case TIMER_PROCESS_IDLE: set_process_internal(p_process && !paused); break;
}
processing = p_process;
@@ -204,7 +204,7 @@ void Timer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "is_one_shot");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autostart"), "set_autostart", "has_autostart");
- BIND_ENUM_CONSTANT(TIMER_PROCESS_FIXED);
+ BIND_ENUM_CONSTANT(TIMER_PROCESS_PHYSICS);
BIND_ENUM_CONSTANT(TIMER_PROCESS_IDLE);
}
diff --git a/scene/main/timer.h b/scene/main/timer.h
index 0cd92f12de..a02adbb0a3 100755
--- a/scene/main/timer.h
+++ b/scene/main/timer.h
@@ -50,7 +50,7 @@ protected:
public:
enum TimerProcessMode {
- TIMER_PROCESS_FIXED,
+ TIMER_PROCESS_PHYSICS,
TIMER_PROCESS_IDLE,
};
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index d27a1a5641..37a393b55b 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -456,10 +456,10 @@ void Viewport::_notification(int p_what) {
VS::get_singleton()->viewport_set_active(viewport, false);
} break;
- case NOTIFICATION_FIXED_PROCESS: {
+ case NOTIFICATION_PHYSICS_PROCESS: {
if (gui.tooltip_timer >= 0) {
- gui.tooltip_timer -= get_fixed_process_delta_time();
+ gui.tooltip_timer -= get_physics_process_delta_time();
if (gui.tooltip_timer < 0) {
_gui_show_tooltip();
}
@@ -1339,7 +1339,7 @@ Vector2 Viewport::get_mouse_position() const {
void Viewport::warp_mouse(const Vector2 &p_pos) {
Vector2 gpos = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse().xform(p_pos);
- Input::get_singleton()->warp_mouse_pos(gpos);
+ Input::get_singleton()->warp_mouse_position(gpos);
}
void Viewport::_gui_sort_subwindows() {
@@ -2453,7 +2453,7 @@ Rect2 Viewport::get_attach_to_screen_rect() const {
void Viewport::set_physics_object_picking(bool p_enable) {
physics_object_picking = p_enable;
- set_fixed_process(physics_object_picking);
+ set_physics_process(physics_object_picking);
if (!physics_object_picking)
physics_picking_events.clear();
}
@@ -2673,7 +2673,7 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_attach_to_screen_rect", "rect"), &Viewport::set_attach_to_screen_rect);
ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position);
- ClassDB::bind_method(D_METHOD("warp_mouse", "to_pos"), &Viewport::warp_mouse);
+ ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Viewport::warp_mouse);
ClassDB::bind_method(D_METHOD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data);
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index eae95d9247..8dcc8d4e14 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -613,7 +613,7 @@ int Animation::transform_track_insert_key(int p_track, float p_time, const Vecto
return ret;
}
-void Animation::track_remove_key_at_pos(int p_track, float p_pos) {
+void Animation::track_remove_key_at_position(int p_track, float p_pos) {
int idx = track_find_key(p_track, p_pos, true);
ERR_FAIL_COND(idx < 0);
@@ -707,12 +707,12 @@ void Animation::track_insert_key(int p_track, float p_time, const Variant &p_key
Dictionary d = p_key;
Vector3 loc;
- if (d.has("loc"))
- loc = d["loc"];
+ if (d.has("location"))
+ loc = d["location"];
Quat rot;
- if (d.has("rot"))
- rot = d["rot"];
+ if (d.has("rotation"))
+ rot = d["rotation"];
Vector3 scale;
if (d.has("scale"))
@@ -799,8 +799,8 @@ Variant Animation::track_get_key_value(int p_track, int p_key_idx) const {
ERR_FAIL_INDEX_V(p_key_idx, tt->transforms.size(), Variant());
Dictionary d;
- d["loc"] = tt->transforms[p_key_idx].value.loc;
- d["rot"] = tt->transforms[p_key_idx].value.rot;
+ d["location"] = tt->transforms[p_key_idx].value.loc;
+ d["rotation"] = tt->transforms[p_key_idx].value.rot;
d["scale"] = tt->transforms[p_key_idx].value.scale;
return d;
@@ -903,10 +903,10 @@ void Animation::track_set_key_value(int p_track, int p_key_idx, const Variant &p
TransformTrack *tt = static_cast<TransformTrack *>(t);
ERR_FAIL_INDEX(p_key_idx, tt->transforms.size());
Dictionary d = p_value;
- if (d.has("loc"))
- tt->transforms[p_key_idx].value.loc = d["loc"];
- if (d.has("rot"))
- tt->transforms[p_key_idx].value.rot = d["rot"];
+ if (d.has("location"))
+ tt->transforms[p_key_idx].value.loc = d["location"];
+ if (d.has("rotation"))
+ tt->transforms[p_key_idx].value.rot = d["rotation"];
if (d.has("scale"))
tt->transforms[p_key_idx].value.scale = d["scale"];
@@ -1590,7 +1590,7 @@ float Animation::get_step() const {
void Animation::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_track", "type", "at_pos"), &Animation::add_track, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_track", "type", "at_position"), &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);
@@ -1604,10 +1604,10 @@ void Animation::_bind_methods() {
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(D_METHOD("transform_track_insert_key", "idx", "time", "loc", "rot", "scale"), &Animation::transform_track_insert_key);
+ ClassDB::bind_method(D_METHOD("transform_track_insert_key", "idx", "time", "location", "rotation", "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_remove_key_at_position", "idx", "position"), &Animation::track_remove_key_at_position);
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);
diff --git a/scene/resources/animation.h b/scene/resources/animation.h
index e653f6b124..6235e161a3 100644
--- a/scene/resources/animation.h
+++ b/scene/resources/animation.h
@@ -245,7 +245,7 @@ public:
void track_set_key_value(int p_track, int p_key_idx, const Variant &p_value);
int track_find_key(int p_track, float p_time, bool p_exact = false) const;
void track_remove_key(int p_track, int p_idx);
- void track_remove_key_at_pos(int p_track, float p_pos);
+ void track_remove_key_at_position(int p_track, float p_pos);
int track_get_key_count(int p_track) const;
Variant track_get_key_value(int p_track, int p_key_idx) const;
float track_get_key_time(int p_track, int p_key_idx) const;
diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp
index dff0fb8588..1fd84a860e 100644
--- a/scene/resources/audio_stream_sample.cpp
+++ b/scene/resources/audio_stream_sample.cpp
@@ -41,7 +41,7 @@ void AudioStreamPlaybackSample::start(float p_from_pos) {
ima_adpcm[i].window_ofs = 0;
}
- seek_pos(p_from_pos);
+ seek(p_from_pos);
sign = 1;
active = true;
}
@@ -61,11 +61,11 @@ int AudioStreamPlaybackSample::get_loop_count() const {
return 0;
}
-float AudioStreamPlaybackSample::get_pos() const {
+float AudioStreamPlaybackSample::get_playback_position() const {
return float(offset >> MIX_FRAC_BITS) / base->mix_rate;
}
-void AudioStreamPlaybackSample::seek_pos(float p_time) {
+void AudioStreamPlaybackSample::seek(float p_time) {
if (base->format == AudioStreamSample::FORMAT_IMA_ADPCM)
return; //no seeking in ima-adpcm
diff --git a/scene/resources/audio_stream_sample.h b/scene/resources/audio_stream_sample.h
index 6cb255fedf..fbb8010a9c 100644
--- a/scene/resources/audio_stream_sample.h
+++ b/scene/resources/audio_stream_sample.h
@@ -71,8 +71,8 @@ public:
virtual int get_loop_count() const; //times it looped
- virtual float get_pos() const;
- virtual void seek_pos(float p_time);
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
diff --git a/scene/resources/bit_mask.cpp b/scene/resources/bit_mask.cpp
index be994e3b33..029a9ef0e8 100644
--- a/scene/resources/bit_mask.cpp
+++ b/scene/resources/bit_mask.cpp
@@ -172,8 +172,8 @@ void BitMap::_bind_methods() {
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(D_METHOD("set_bit", "pos", "bit"), &BitMap::set_bit);
- ClassDB::bind_method(D_METHOD("get_bit", "pos"), &BitMap::get_bit);
+ ClassDB::bind_method(D_METHOD("set_bit", "position", "bit"), &BitMap::set_bit);
+ ClassDB::bind_method(D_METHOD("get_bit", "position"), &BitMap::get_bit);
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);
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 1066848dd1..79cc94c911 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -241,7 +241,7 @@ int Curve::set_point_offset(int p_index, float offset) {
return i;
}
-Vector2 Curve::get_point_pos(int p_index) const {
+Vector2 Curve::get_point_position(int p_index) const {
ERR_FAIL_INDEX_V(p_index, _points.size(), Vector2(0, 0));
return _points[p_index].pos;
}
@@ -480,23 +480,22 @@ real_t Curve::interpolate_baked(real_t offset) {
void Curve::_bind_methods() {
- ClassDB::bind_method(D_METHOD("add_point", "pos", "left_tangent", "right_tangent", "left_mode", "right_mode"),
- &Curve::add_point, DEFVAL(0), DEFVAL(0), DEFVAL(TANGENT_FREE), DEFVAL(TANGENT_FREE));
+ ClassDB::bind_method(D_METHOD("add_point", "position", "left_tangent", "right_tangent", "left_mode", "right_mode"), &Curve::add_point, DEFVAL(0), DEFVAL(0), DEFVAL(TANGENT_FREE), DEFVAL(TANGENT_FREE));
ClassDB::bind_method(D_METHOD("remove_point", "index"), &Curve::remove_point);
ClassDB::bind_method(D_METHOD("clear_points"), &Curve::clear_points);
- ClassDB::bind_method(D_METHOD("get_point_pos", "index"), &Curve::get_point_pos);
+ ClassDB::bind_method(D_METHOD("get_point_position", "index"), &Curve::get_point_position);
ClassDB::bind_method(D_METHOD("set_point_value", "index", "y"), &Curve::set_point_value);
- ClassDB::bind_method(D_METHOD("set_point_offset", "index", "offset"), &Curve::set_point_value);
+ ClassDB::bind_method(D_METHOD("set_point_offset", "index", "offset"), &Curve::set_point_offset);
ClassDB::bind_method(D_METHOD("interpolate", "offset"), &Curve::interpolate);
ClassDB::bind_method(D_METHOD("interpolate_baked", "offset"), &Curve::interpolate_baked);
ClassDB::bind_method(D_METHOD("get_point_left_tangent", "index"), &Curve::get_point_left_tangent);
- ClassDB::bind_method(D_METHOD("get_point_right_tangent", "index"), &Curve::get_point_left_tangent);
+ ClassDB::bind_method(D_METHOD("get_point_right_tangent", "index"), &Curve::get_point_right_tangent);
ClassDB::bind_method(D_METHOD("get_point_left_mode", "index"), &Curve::get_point_left_mode);
- ClassDB::bind_method(D_METHOD("get_point_right_mode", "index"), &Curve::get_point_left_mode);
+ ClassDB::bind_method(D_METHOD("get_point_right_mode", "index"), &Curve::get_point_right_mode);
ClassDB::bind_method(D_METHOD("set_point_left_tangent", "index", "tangent"), &Curve::set_point_left_tangent);
- ClassDB::bind_method(D_METHOD("set_point_right_tangent", "index", "tangent"), &Curve::set_point_left_tangent);
+ ClassDB::bind_method(D_METHOD("set_point_right_tangent", "index", "tangent"), &Curve::set_point_right_tangent);
ClassDB::bind_method(D_METHOD("set_point_left_mode", "index", "mode"), &Curve::set_point_left_mode);
- ClassDB::bind_method(D_METHOD("set_point_right_mode", "index", "mode"), &Curve::set_point_left_mode);
+ ClassDB::bind_method(D_METHOD("set_point_right_mode", "index", "mode"), &Curve::set_point_right_mode);
ClassDB::bind_method(D_METHOD("get_min_value"), &Curve::get_min_value);
ClassDB::bind_method(D_METHOD("set_min_value", "min"), &Curve::set_min_value);
ClassDB::bind_method(D_METHOD("get_max_value"), &Curve::get_max_value);
@@ -539,7 +538,7 @@ void Curve2D::add_point(const Vector2 &p_pos, const Vector2 &p_in, const Vector2
emit_signal(CoreStringNames::get_singleton()->changed);
}
-void Curve2D::set_point_pos(int p_index, const Vector2 &p_pos) {
+void Curve2D::set_point_position(int p_index, const Vector2 &p_pos) {
ERR_FAIL_INDEX(p_index, points.size());
@@ -547,7 +546,7 @@ void Curve2D::set_point_pos(int p_index, const Vector2 &p_pos) {
baked_cache_dirty = true;
emit_signal(CoreStringNames::get_singleton()->changed);
}
-Vector2 Curve2D::get_point_pos(int p_index) const {
+Vector2 Curve2D::get_point_position(int p_index) const {
ERR_FAIL_INDEX_V(p_index, points.size(), Vector2());
return points[p_index].pos;
@@ -891,12 +890,12 @@ PoolVector2Array Curve2D::tessellate(int p_max_stages, float p_tolerance) const
void Curve2D::_bind_methods() {
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("add_point", "position", "in", "out", "at_position"), &Curve2D::add_point, DEFVAL(Vector2()), DEFVAL(Vector2()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("set_point_position", "idx", "position"), &Curve2D::set_point_position);
+ ClassDB::bind_method(D_METHOD("get_point_position", "idx"), &Curve2D::get_point_position);
+ ClassDB::bind_method(D_METHOD("set_point_in", "idx", "position"), &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("set_point_out", "idx", "position"), &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);
@@ -916,9 +915,6 @@ void Curve2D::_bind_methods() {
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");
-*/
}
Curve2D::Curve2D() {
@@ -955,7 +951,7 @@ void Curve3D::add_point(const Vector3 &p_pos, const Vector3 &p_in, const Vector3
baked_cache_dirty = true;
emit_signal(CoreStringNames::get_singleton()->changed);
}
-void Curve3D::set_point_pos(int p_index, const Vector3 &p_pos) {
+void Curve3D::set_point_position(int p_index, const Vector3 &p_pos) {
ERR_FAIL_INDEX(p_index, points.size());
@@ -963,7 +959,7 @@ void Curve3D::set_point_pos(int p_index, const Vector3 &p_pos) {
baked_cache_dirty = true;
emit_signal(CoreStringNames::get_singleton()->changed);
}
-Vector3 Curve3D::get_point_pos(int p_index) const {
+Vector3 Curve3D::get_point_position(int p_index) const {
ERR_FAIL_INDEX_V(p_index, points.size(), Vector3());
return points[p_index].pos;
@@ -1386,14 +1382,14 @@ PoolVector3Array Curve3D::tessellate(int p_max_stages, float p_tolerance) const
void Curve3D::_bind_methods() {
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("add_point", "position", "in", "out", "at_position"), &Curve3D::add_point, DEFVAL(Vector3()), DEFVAL(Vector3()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("set_point_position", "idx", "position"), &Curve3D::set_point_position);
+ ClassDB::bind_method(D_METHOD("get_point_position", "idx"), &Curve3D::get_point_position);
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("set_point_in", "idx", "position"), &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("set_point_out", "idx", "position"), &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);
@@ -1414,9 +1410,6 @@ void Curve3D::_bind_methods() {
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");
-*/
}
Curve3D::Curve3D() {
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index 3071aee5de..e7d47f4056 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -92,7 +92,7 @@ public:
void set_point_value(int p_index, real_t pos);
int set_point_offset(int p_index, float offset);
- Vector2 get_point_pos(int p_index) const;
+ Vector2 get_point_position(int p_index) const;
Point get_point(int p_index) const;
@@ -180,8 +180,8 @@ protected:
public:
int get_point_count() const;
void add_point(const Vector2 &p_pos, const Vector2 &p_in = Vector2(), const Vector2 &p_out = Vector2(), int p_atpos = -1);
- void set_point_pos(int p_index, const Vector2 &p_pos);
- Vector2 get_point_pos(int p_index) const;
+ void set_point_position(int p_index, const Vector2 &p_pos);
+ Vector2 get_point_position(int p_index) const;
void set_point_in(int p_index, const Vector2 &p_in);
Vector2 get_point_in(int p_index) const;
void set_point_out(int p_index, const Vector2 &p_out);
@@ -245,8 +245,8 @@ protected:
public:
int get_point_count() const;
void add_point(const Vector3 &p_pos, const Vector3 &p_in = Vector3(), const Vector3 &p_out = Vector3(), int p_atpos = -1);
- void set_point_pos(int p_index, const Vector3 &p_pos);
- Vector3 get_point_pos(int p_index) const;
+ void set_point_position(int p_index, const Vector3 &p_pos);
+ Vector3 get_point_position(int p_index) const;
void set_point_tilt(int p_index, float p_tilt);
float get_point_tilt(int p_index) const;
void set_point_in(int p_index, const Vector3 &p_in);
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 1272e5a946..923639bc79 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -774,6 +774,9 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_icon("add_preset", "ColorPicker", make_icon(icon_add_png));
theme->set_icon("color_hue", "ColorPicker", make_icon(color_picker_hue_png));
theme->set_icon("color_sample", "ColorPicker", make_icon(color_picker_sample_png));
+ theme->set_icon("preset_bg", "ColorPicker", make_icon(mini_checkerboard_png));
+
+ theme->set_icon("bg", "ColorPickerButton", make_icon(mini_checkerboard_png));
// TooltipPanel
@@ -879,7 +882,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_icon("minus", "GraphEdit", make_icon(icon_zoom_less_png));
theme->set_icon("reset", "GraphEdit", make_icon(icon_zoom_reset_png));
theme->set_icon("more", "GraphEdit", make_icon(icon_zoom_more_png));
- theme->set_icon("snap", "GraphEdit", make_icon(icon_snap_png));
+ theme->set_icon("SnapGrid", "GraphEdit", make_icon(icon_snap_grid_png));
theme->set_stylebox("bg", "GraphEdit", make_stylebox(tree_bg_png, 4, 4, 4, 5));
theme->set_color("grid_minor", "GraphEdit", Color(1, 1, 1, 0.05));
theme->set_color("grid_major", "GraphEdit", Color(1, 1, 1, 0.2));
diff --git a/scene/resources/default_theme/icon_snap.png b/scene/resources/default_theme/icon_snap_grid.png
index 93194d34e7..44db9bdfdc 100644
--- a/scene/resources/default_theme/icon_snap.png
+++ b/scene/resources/default_theme/icon_snap_grid.png
Binary files differ
diff --git a/scene/resources/default_theme/mini_checkerboard.png b/scene/resources/default_theme/mini_checkerboard.png
new file mode 100644
index 0000000000..3e53183847
--- /dev/null
+++ b/scene/resources/default_theme/mini_checkerboard.png
Binary files differ
diff --git a/scene/resources/default_theme/source/arrow_down.svg b/scene/resources/default_theme/source/arrow_down.svg
deleted file mode 100644
index 354040b548..0000000000
--- a/scene/resources/default_theme/source/arrow_down.svg
+++ /dev/null
@@ -1,80 +0,0 @@
-<?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="12"
- height="12"
- viewBox="0 0 12 12"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="arrow_down.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="64"
- inkscape:cx="5.7299355"
- inkscape:cy="6.6875366"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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 />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-1040.3622)">
- <path
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 2,1043.3622 0,3 4,3 4,-3 0,-3 z"
- id="rect4174"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccc" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/arrow_right.svg b/scene/resources/default_theme/source/arrow_right.svg
deleted file mode 100644
index 4c4bc05e28..0000000000
--- a/scene/resources/default_theme/source/arrow_right.svg
+++ /dev/null
@@ -1,80 +0,0 @@
-<?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="12"
- height="12"
- viewBox="0 0 12 12"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="arrow_right.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="45.254836"
- inkscape:cx="3.0018179"
- inkscape:cy="6.0349408"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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 />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-1040.3622)">
- <path
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 3,1050.3622 3,0 3,-4 -3,-4 -3,0 z"
- id="rect4174"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccc" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/graph_node_close.svg b/scene/resources/default_theme/source/graph_node_close.svg
deleted file mode 100644
index 52a35a5b8a..0000000000
--- a/scene/resources/default_theme/source/graph_node_close.svg
+++ /dev/null
@@ -1,94 +0,0 @@
-<?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="12"
- height="12"
- viewBox="0 0 12 12"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_add_track.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="graph_node_close.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.627418"
- inkscape:cx="-1.9715406"
- inkscape:cy="8.1466063"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1">
- <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,-1040.3622)">
- <g
- id="layer1-4"
- inkscape:label="Layer 1"
- transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-738.13242,313.54349)"
- style="fill:#080808;fill-opacity:1">
- <rect
- y="1043.3622"
- x="1"
- height="1.9999478"
- width="14"
- id="rect4137"
- style="fill:#080808;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="fill:#080808;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect4158"
- width="13.999966"
- height="2.0000017"
- x="1037.3622"
- y="-9" />
- </g>
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/graph_port.svg b/scene/resources/default_theme/source/graph_port.svg
deleted file mode 100644
index de9b1d4827..0000000000
--- a/scene/resources/default_theme/source/graph_port.svg
+++ /dev/null
@@ -1,80 +0,0 @@
-<?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="10"
- height="10"
- viewBox="0 0 10 10"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="graph_port.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="32.000001"
- inkscape:cx="-5.0080069"
- inkscape:cy="6.2185379"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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 />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-1042.3622)">
- <circle
- style="fill:#f3f3f3;fill-rule:evenodd;stroke:#d8d8d8;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1"
- id="path3335"
- cx="5"
- cy="1047.3622"
- r="4" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/icon_close.svg b/scene/resources/default_theme/source/icon_close.svg
deleted file mode 100644
index 6e6ec16638..0000000000
--- a/scene/resources/default_theme/source/icon_close.svg
+++ /dev/null
@@ -1,94 +0,0 @@
-<?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="/home/djrm/Projects/godot/tools/editor/icons/icon_add_track.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="icon_close.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.627418"
- inkscape:cx="1.8501874"
- inkscape:cy="8.0543329"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1">
- <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 />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-1036.3622)">
- <g
- id="layer1-4"
- inkscape:label="Layer 1"
- transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-736.13242,311.54347)"
- style="fill:#080808;fill-opacity:1">
- <rect
- y="1043.3622"
- x="1"
- height="1.9999478"
- width="14"
- id="rect4137"
- style="fill:#080808;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="fill:#080808;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect4158"
- width="13.999966"
- height="2.0000017"
- x="1037.3622"
- y="-9" />
- </g>
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/option_arrow.svg b/scene/resources/default_theme/source/option_arrow.svg
deleted file mode 100644
index cd78404ff1..0000000000
--- a/scene/resources/default_theme/source/option_arrow.svg
+++ /dev/null
@@ -1,86 +0,0 @@
-<?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="12"
- height="12"
- viewBox="0 0 12 12"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="option_arrow.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="45.254836"
- inkscape:cx="6.0969578"
- inkscape:cy="7.5632913"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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,-1040.3622)">
- <path
- style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 3,1045.3622 6,0 -3,-4 z"
- id="path4158"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- inkscape:connector-curvature="0"
- id="path4160"
- d="m 3,1047.3622 6,0 -3,4 z"
- style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- sodipodi:nodetypes="cccc" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/popup_checked.svg b/scene/resources/default_theme/source/popup_checked.svg
deleted file mode 100644
index fbefd4138d..0000000000
--- a/scene/resources/default_theme/source/popup_checked.svg
+++ /dev/null
@@ -1,81 +0,0 @@
-<?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="8"
- height="8"
- viewBox="0 0 8 8"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_folder.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90"
- sodipodi:docname="popup_checked.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="45.254834"
- inkscape:cx="2.6626803"
- inkscape:cy="5.227737"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:object-paths="true"
- inkscape:snap-intersection-paths="true"
- inkscape:object-nodes="true"
- inkscape:snap-smooth-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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,-1044.3622)">
- <path
- style="fill:none;fill-rule:evenodd;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 7,1046.3622 -4,5 -2,-2"
- id="path4154"
- inkscape:connector-curvature="0" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/spinbox_updown.svg b/scene/resources/default_theme/source/spinbox_updown.svg
deleted file mode 100644
index 5b8e0a83eb..0000000000
--- a/scene/resources/default_theme/source/spinbox_updown.svg
+++ /dev/null
@@ -1,86 +0,0 @@
-<?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="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="spinbox_updown.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="45.254834"
- inkscape:cx="5.7914867"
- inkscape:cy="9.8174296"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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 />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-1036.3622)">
- <path
- style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="m 4,1042.3622 8,0 -4,-5 z"
- id="path4158"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccc" />
- <path
- inkscape:connector-curvature="0"
- id="path4160"
- d="m 4,1046.3622 8,0 -4,5 z"
- style="fill:#e0e0e0;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- sodipodi:nodetypes="cccc" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/submenu.svg b/scene/resources/default_theme/source/submenu.svg
deleted file mode 100644
index ef7f696571..0000000000
--- a/scene/resources/default_theme/source/submenu.svg
+++ /dev/null
@@ -1,80 +0,0 @@
-<?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="8"
- height="8"
- viewBox="0 0 8 8"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="submenu.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="64.000003"
- inkscape:cx="1.4039962"
- inkscape:cy="5.6866955"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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 />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-1044.3622)">
- <path
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1,1052.3622 3,0 3,-4 -3,-4 -3,0 z"
- id="rect4174"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccc" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/tab_close.svg b/scene/resources/default_theme/source/tab_close.svg
deleted file mode 100644
index 65b71ae860..0000000000
--- a/scene/resources/default_theme/source/tab_close.svg
+++ /dev/null
@@ -1,93 +0,0 @@
-<?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="/home/djrm/Projects/godot/tools/editor/icons/icon_add_track.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="icon_close.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="22.627418"
- inkscape:cx="3.3969834"
- inkscape:cy="11.678255"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1">
- <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)">
- <g
- id="layer1-4"
- inkscape:label="Layer 1"
- transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,-736.13242,311.54347)">
- <rect
- y="1043.3622"
- x="1"
- height="1.9999478"
- width="14"
- id="rect4137"
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
- <rect
- transform="matrix(0,1,-1,0,0,0)"
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- id="rect4158"
- width="13.999966"
- height="2.0000017"
- x="1037.3622"
- y="-9" />
- </g>
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/tab_menu.svg b/scene/resources/default_theme/source/tab_menu.svg
deleted file mode 100644
index 84f7c8095a..0000000000
--- a/scene/resources/default_theme/source/tab_menu.svg
+++ /dev/null
@@ -1,80 +0,0 @@
-<?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="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="tab_menu.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="45.254836"
- inkscape:cx="6.2944765"
- inkscape:cy="7.7343939"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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 />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-1036.3622)">
- <path
- style="fill:#e0e0e0;fill-opacity:1;stroke:none;stroke-width:6;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 4,1044.3622 0,3 4,3 4,-3 0,-3 z"
- id="rect4174"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="cccccc" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/source/updown.svg b/scene/resources/default_theme/source/updown.svg
deleted file mode 100644
index adc72b405d..0000000000
--- a/scene/resources/default_theme/source/updown.svg
+++ /dev/null
@@ -1,86 +0,0 @@
-<?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="8"
- height="16"
- viewBox="0 0 8 16"
- id="svg2"
- version="1.1"
- inkscape:version="0.91 r13725"
- inkscape:export-filename="/home/djrm/Projects/godot/tools/editor/icons/icon_collapse.png"
- inkscape:export-xdpi="45"
- inkscape:export-ydpi="45"
- sodipodi:docname="updown.svg">
- <defs
- id="defs4" />
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="32.000001"
- inkscape:cx="-3.4436559"
- inkscape:cy="10.099799"
- 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="false"
- inkscape:snap-object-midpoints="true"
- inkscape:snap-center="true"
- inkscape:window-width="1920"
- inkscape:window-height="1016"
- inkscape:window-x="0"
- inkscape:window-y="27"
- inkscape:window-maximized="1"
- inkscape:snap-smooth-nodes="true"
- inkscape:object-nodes="true">
- <inkscape:grid
- type="xygrid"
- id="grid3336" />
- </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 />
- </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-rule:evenodd;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- d="m 1,1042.3565 3,-2.9943 3,2.9943"
- id="path4155"
- inkscape:connector-curvature="0"
- sodipodi:nodetypes="ccc" />
- <path
- inkscape:connector-curvature="0"
- id="path4159"
- d="m 1,1046.3622 3,3 3,-3"
- style="fill:none;fill-rule:evenodd;stroke:#e0e0e0;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
- sodipodi:nodetypes="ccc" />
- </g>
-</svg>
diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h
index bed4bdb760..38e5f58b0d 100644
--- a/scene/resources/default_theme/theme_data.h
+++ b/scene/resources/default_theme/theme_data.h
@@ -182,8 +182,8 @@ static const unsigned char icon_reload_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x10, 0x0, 0x0, 0x0, 0x10, 0x8, 0x6, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff, 0x61, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x1, 0x59, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xcd, 0x92, 0x31, 0x4b, 0x3, 0x31, 0x18, 0x86, 0x9f, 0x5c, 0xe, 0xec, 0x20, 0x76, 0x70, 0x39, 0xd0, 0xe3, 0xba, 0x74, 0x51, 0x41, 0xdd, 0xfc, 0x7, 0xba, 0xb8, 0x8, 0x52, 0xec, 0x2e, 0x4e, 0x3a, 0x88, 0x3f, 0xa3, 0xa3, 0x53, 0x7, 0x47, 0x67, 0x41, 0x17, 0xdd, 0x9c, 0x5c, 0x3b, 0xd8, 0x82, 0x64, 0x68, 0xca, 0xd5, 0x55, 0x11, 0x3c, 0x1a, 0x87, 0x24, 0x2e, 0xd7, 0x72, 0x9e, 0x9e, 0xab, 0xbe, 0xd3, 0xc7, 0x1b, 0x9e, 0x37, 0xf9, 0xbe, 0x7c, 0xf0, 0xd7, 0x12, 0x3f, 0x99, 0x4a, 0xa9, 0xb9, 0x30, 0xc, 0x8f, 0x84, 0x10, 0x7, 0xc0, 0x5a, 0x6e, 0x3f, 0x3a, 0xe7, 0x2e, 0xad, 0xb5, 0xdd, 0x66, 0xb3, 0xf9, 0x51, 0x19, 0x90, 0xa6, 0xe9, 0x92, 0xb5, 0xf6, 0x6, 0x58, 0xaf, 0xb8, 0xb4, 0x27, 0xa5, 0xdc, 0x8d, 0xe3, 0xf8, 0x19, 0x20, 0x28, 0xdf, 0x5c, 0x80, 0x53, 0x60, 0xdf, 0x18, 0x53, 0x37, 0xc6, 0xd4, 0xbd, 0xf7, 0x7b, 0xc0, 0x13, 0xb0, 0x61, 0xad, 0xbd, 0x56, 0x4a, 0xcd, 0x1, 0x84, 0xc5, 0x80, 0x30, 0xc, 0x8f, 0xa6, 0xb0, 0x94, 0x72, 0x33, 0x8e, 0xe3, 0x97, 0xc2, 0xf1, 0xd5, 0x68, 0x34, 0xba, 0xf7, 0xde, 0xf7, 0x80, 0xd, 0x29, 0xe5, 0x21, 0x70, 0xfe, 0xe5, 0x5, 0x42, 0x88, 0x76, 0x5e, 0x9e, 0x96, 0x60, 0x0, 0x92, 0x24, 0x79, 0x75, 0xce, 0x9d, 0x1, 0x4, 0x41, 0xd0, 0xfe, 0xd6, 0x2, 0xb0, 0x2, 0x60, 0x8c, 0xb9, 0xab, 0xe8, 0x1f, 0x6b, 0xed, 0x6d, 0x5e, 0xae, 0xce, 0x2, 0xb4, 0xd6, 0x17, 0x5a, 0x6b, 0x7, 0xcc, 0x3, 0xd4, 0x6a, 0xb5, 0x37, 0xad, 0xf5, 0xc5, 0x4f, 0x1, 0x41, 0x10, 0x7c, 0x19, 0x7c, 0x90, 0x3, 0xc7, 0xc0, 0xa0, 0xe0, 0xf, 0x72, 0xef, 0x9b, 0x84, 0x10, 0xdb, 0x79, 0xd9, 0x9f, 0x5, 0x44, 0x51, 0x94, 0x9, 0x21, 0x5a, 0x40, 0x6, 0x64, 0x42, 0x88, 0x56, 0x14, 0x45, 0x59, 0x19, 0x1e, 0x8f, 0xc7, 0x8b, 0x52, 0xca, 0xe, 0x80, 0x73, 0xee, 0x12, 0xa, 0xbf, 0x90, 0x24, 0x49, 0x7f, 0x38, 0x1c, 0x1e, 0x3, 0x34, 0x1a, 0x8d, 0x7e, 0x11, 0x54, 0x4a, 0x2d, 0x48, 0x29, 0x77, 0xac, 0xb5, 0x1d, 0xef, 0xfd, 0x32, 0xd0, 0x9b, 0x4c, 0x26, 0x5d, 0xa8, 0xd8, 0xc4, 0xb2, 0xf2, 0xf9, 0x4c, 0x55, 0xbd, 0x48, 0xbf, 0xe8, 0x1d, 0x78, 0x70, 0xce, 0x9d, 0x64, 0x59, 0xb6, 0x35, 0x85, 0xff, 0x87, 0x3e, 0x1, 0x53, 0x7, 0x87, 0x11, 0xd3, 0x3a, 0x9b, 0x9e, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
-static const unsigned char icon_snap_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, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xad, 0x90, 0xbd, 0xa, 0xc2, 0x30, 0x14, 0x85, 0xbf, 0x5b, 0x5c, 0x23, 0xe8, 0x6c, 0x9f, 0xc1, 0xb7, 0xd0, 0x47, 0xd1, 0x47, 0x70, 0x48, 0xa1, 0x43, 0x57, 0xe9, 0xd3, 0x88, 0x93, 0xef, 0xe0, 0xea, 0x5c, 0x9d, 0x1d, 0xb2, 0x96, 0xc6, 0xa1, 0x9, 0xd4, 0xd8, 0xd8, 0x4a, 0xfd, 0x20, 0x10, 0xee, 0xcf, 0xe1, 0xdc, 0x3, 0x1d, 0x8c, 0x31, 0xd6, 0x18, 0x63, 0x9, 0x88, 0xd5, 0x1, 0x92, 0xbe, 0xe2, 0x2f, 0x4c, 0x16, 0x90, 0x98, 0xb5, 0x21, 0x94, 0x52, 0xf2, 0x17, 0x7, 0x6f, 0x7c, 0xb, 0x2b, 0xc6, 0x64, 0x7, 0xb3, 0xa1, 0x1, 0x5b, 0x14, 0x29, 0x50, 0x2, 0x1b, 0x0, 0x44, 0x2e, 0x34, 0xcd, 0x41, 0xb2, 0xec, 0x6, 0x20, 0xdd, 0x61, 0x6f, 0xdf, 0x7, 0xe4, 0x96, 0xaf, 0xc0, 0x32, 0xd0, 0x7d, 0x2, 0x6b, 0xd1, 0xba, 0x4a, 0xfc, 0xdd, 0x91, 0xdb, 0x4b, 0xb7, 0x7c, 0x2, 0x56, 0xd4, 0x75, 0xa, 0x9c, 0x81, 0x5, 0x70, 0x84, 0xe1, 0xc, 0x5a, 0xdb, 0x75, 0xbd, 0x17, 0xad, 0x1f, 0x92, 0xe7, 0x77, 0x60, 0xe7, 0x7a, 0x5b, 0x80, 0x44, 0x29, 0x25, 0xfe, 0xf5, 0x8, 0x28, 0x0, 0xb7, 0xd8, 0x46, 0xa0, 0x75, 0xe5, 0xbe, 0xf3, 0x31, 0xe, 0x7e, 0x23, 0xcc, 0xc2, 0x3a, 0xc2, 0xb9, 0x58, 0xfd, 0x83, 0xc9, 0x2, 0x63, 0x78, 0x1, 0x4a, 0x50, 0x70, 0x86, 0xcc, 0x86, 0x2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+static const unsigned char icon_snap_grid_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, 0x4, 0x73, 0x42, 0x49, 0x54, 0x8, 0x8, 0x8, 0x8, 0x7c, 0x8, 0x64, 0x88, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xe, 0xc4, 0x0, 0x0, 0xe, 0xc4, 0x1, 0x95, 0x2b, 0xe, 0x1b, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0xc2, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0xad, 0x90, 0xbd, 0xa, 0xc2, 0x30, 0x14, 0x85, 0xbf, 0x5b, 0x5c, 0x23, 0xe8, 0x6c, 0x9f, 0xc1, 0xb7, 0xd0, 0x47, 0xd1, 0x47, 0x70, 0x48, 0xa1, 0x43, 0x57, 0xe9, 0xd3, 0x88, 0x93, 0xef, 0xe0, 0xea, 0x5c, 0x9d, 0x1d, 0xb2, 0x96, 0xc6, 0xa1, 0x9, 0xd4, 0xd8, 0xd8, 0x4a, 0xfd, 0x20, 0x10, 0xee, 0xcf, 0xe1, 0xdc, 0x3, 0x1d, 0x8c, 0x31, 0xd6, 0x18, 0x63, 0x9, 0x88, 0xd5, 0x1, 0x92, 0xbe, 0xe2, 0x2f, 0x4c, 0x16, 0x90, 0x98, 0xb5, 0x21, 0x94, 0x52, 0xf2, 0x17, 0x7, 0x6f, 0x7c, 0xb, 0x2b, 0xc6, 0x64, 0x7, 0xb3, 0xa1, 0x1, 0x5b, 0x14, 0x29, 0x50, 0x2, 0x1b, 0x0, 0x44, 0x2e, 0x34, 0xcd, 0x41, 0xb2, 0xec, 0x6, 0x20, 0xdd, 0x61, 0x6f, 0xdf, 0x7, 0xe4, 0x96, 0xaf, 0xc0, 0x32, 0xd0, 0x7d, 0x2, 0x6b, 0xd1, 0xba, 0x4a, 0xfc, 0xdd, 0x91, 0xdb, 0x4b, 0xb7, 0x7c, 0x2, 0x56, 0xd4, 0x75, 0xa, 0x9c, 0x81, 0x5, 0x70, 0x84, 0xe1, 0xc, 0x5a, 0xdb, 0x75, 0xbd, 0x17, 0xad, 0x1f, 0x92, 0xe7, 0x77, 0x60, 0xe7, 0x7a, 0x5b, 0x80, 0x44, 0x29, 0x25, 0xfe, 0xf5, 0x8, 0x28, 0x0, 0xb7, 0xd8, 0x46, 0xa0, 0x75, 0xe5, 0xbe, 0xf3, 0x31, 0xe, 0x7e, 0x23, 0xcc, 0xc2, 0x3a, 0xc2, 0xb9, 0x58, 0xfd, 0x83, 0xc9, 0x2, 0x63, 0x78, 0x1, 0x4a, 0x50, 0x70, 0x86, 0xcc, 0x86, 0x2, 0x4, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
static const unsigned char icon_stop_png[] = {
@@ -218,6 +218,10 @@ static const unsigned char logo_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x80, 0x8, 0x6, 0x0, 0x0, 0x0, 0xc3, 0x3e, 0x61, 0xcb, 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, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0x2e, 0x23, 0x0, 0x0, 0x2e, 0x23, 0x1, 0x78, 0xa5, 0x3f, 0x76, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xdc, 0x9, 0x7, 0x13, 0x2, 0x0, 0x15, 0xb9, 0x53, 0x97, 0x0, 0x0, 0x21, 0x58, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x7d, 0x79, 0x9c, 0x1c, 0x55, 0xb5, 0xff, 0xf7, 0x7b, 0xab, 0x7b, 0x66, 0x48, 0x8, 0x61, 0xd1, 0x90, 0xb0, 0x88, 0x91, 0x27, 0x24, 0x24, 0x21, 0x3b, 0x8, 0x4, 0x42, 0x58, 0x54, 0xe0, 0x91, 0x80, 0x24, 0x1, 0x2, 0x9, 0x42, 0x80, 0x4, 0x11, 0x90, 0x9f, 0xf2, 0xd3, 0xa7, 0xcf, 0xe7, 0xf3, 0x3d, 0x1f, 0x1f, 0x7f, 0xea, 0xd3, 0x48, 0x4c, 0x8, 0x61, 0xd, 0x49, 0x64, 0x89, 0x82, 0x40, 0x58, 0x4, 0x64, 0xb, 0x44, 0x25, 0x9b, 0xd9, 0x51, 0x14, 0x41, 0x3, 0xc8, 0x16, 0x20, 0xfb, 0x4c, 0x77, 0xdd, 0xef, 0xef, 0x8f, 0xaa, 0xea, 0xae, 0xee, 0xa9, 0xea, 0x9e, 0xee, 0xae, 0x99, 0xe9, 0xe0, 0x9c, 0xf9, 0xd4, 0x74, 0xd5, 0xad, 0x5b, 0x77, 0x39, 0xe7, 0xdc, 0x7b, 0xcf, 0x39, 0xf7, 0xdc, 0x7b, 0x81, 0x2e, 0xe8, 0x82, 0x2e, 0xe8, 0x82, 0x2e, 0xe8, 0x82, 0x2e, 0xe8, 0x82, 0x2e, 0xe8, 0x82, 0x2e, 0xf8, 0xe7, 0x2, 0x76, 0x76, 0x1, 0xea, 0x1, 0xe, 0xff, 0xc2, 0xcc, 0xbd, 0x60, 0x5b, 0x6e, 0xb6, 0xd6, 0xf6, 0x2, 0xb8, 0x8d, 0xc6, 0x6c, 0x36, 0x34, 0x6f, 0x81, 0x7c, 0x43, 0x30, 0x7f, 0x27, 0xcd, 0xdf, 0x8c, 0xe3, 0x6c, 0xda, 0x70, 0xef, 0xf4, 0x37, 0x3b, 0xbb, 0xac, 0x49, 0x43, 0xaa, 0xb3, 0xb, 0x50, 0xf, 0x20, 0x9b, 0xfd, 0x96, 0xcd, 0xb6, 0x4c, 0x40, 0xd0, 0x20, 0x2c, 0xac, 0x4b, 0xb3, 0x3, 0xc0, 0x36, 0x80, 0x5b, 0x41, 0x6c, 0x75, 0x5b, 0xb8, 0xed, 0xb0, 0x71, 0xff, 0xbb, 0x83, 0xc6, 0x6c, 0x26, 0x9d, 0x65, 0x74, 0xd2, 0x4f, 0x6e, 0x5c, 0x74, 0xc5, 0xba, 0xce, 0x2e, 0x7b, 0xad, 0xf0, 0x4f, 0xdf, 0x3, 0xf4, 0x9f, 0x38, 0xb7, 0x5b, 0x76, 0xd7, 0x7, 0x2f, 0xcb, 0xda, 0x3, 0xc8, 0x42, 0x94, 0x48, 0x6a, 0x15, 0x9f, 0x24, 0x0, 0xbe, 0x43, 0xe3, 0xfc, 0xc1, 0x49, 0x37, 0x4d, 0xdd, 0xf8, 0x8b, 0x2b, 0xff, 0xde, 0xd9, 0x75, 0xa8, 0x5, 0x76, 0x2b, 0x6, 0xe8, 0x37, 0x7e, 0xf6, 0x18, 0xeb, 0xb6, 0x9c, 0x6, 0x69, 0xf, 0x1a, 0xf3, 0xc1, 0x1f, 0xef, 0xbb, 0xe6, 0xdb, 0xb5, 0xa4, 0x37, 0xf2, 0x9a, 0xa5, 0xdc, 0xb2, 0x69, 0xe5, 0x69, 0xca, 0xec, 0xf8, 0xa5, 0xa4, 0x26, 0x48, 0xf2, 0x29, 0x8c, 0x82, 0x7b, 0x40, 0x3e, 0xae, 0xfc, 0x5f, 0x41, 0x82, 0x4d, 0x37, 0xf5, 0x18, 0xb7, 0xd7, 0xc1, 0xc3, 0x1f, 0xfe, 0xfd, 0x4f, 0x3e, 0xa3, 0x2a, 0x8b, 0xd0, 0xe9, 0x50, 0xf7, 0xc, 0x70, 0xf8, 0x39, 0xb3, 0x3e, 0x9, 0xb9, 0xa7, 0x48, 0xf6, 0x70, 0xb9, 0xd9, 0xd1, 0x90, 0x3b, 0xd2, 0x2b, 0x39, 0x9b, 0x4d, 0xaa, 0x69, 0xfa, 0x1f, 0xef, 0xbb, 0xfa, 0x8e, 0x5a, 0xd2, 0x3f, 0x6c, 0xdc, 0x8f, 0x9f, 0x91, 0xcd, 0x8c, 0x2, 0xe9, 0xe4, 0x43, 0x3, 0x7a, 0xc7, 0x80, 0x4, 0x80, 0xbb, 0x9c, 0x74, 0xd3, 0x77, 0xdd, 0xcc, 0xce, 0x1f, 0xbc, 0xfc, 0xd0, 0xd7, 0x6d, 0x67, 0xe3, 0xa9, 0x5a, 0xa8, 0x5b, 0x19, 0xa0, 0xdf, 0xf8, 0xd9, 0x47, 0x42, 0xee, 0x51, 0x72, 0x5b, 0x3e, 0x6b, 0xdd, 0xcc, 0x69, 0x0, 0xf6, 0xf4, 0x8, 0xe3, 0x75, 0xc3, 0x92, 0x1a, 0x6d, 0x66, 0xd7, 0x8f, 0xfa, 0x8d, 0x9f, 0xf5, 0xe7, 0x97, 0x7e, 0x71, 0xe5, 0xf3, 0x55, 0xe5, 0x31, 0xe1, 0xc6, 0x83, 0xdc, 0x5d, 0x5b, 0x46, 0x3, 0x7e, 0xb3, 0xce, 0x51, 0xbd, 0x74, 0xbb, 0xf0, 0x9b, 0xbb, 0x23, 0xd9, 0x23, 0x59, 0xf7, 0x4d, 0xa8, 0x34, 0xd4, 0x1d, 0x3, 0xf4, 0x3b, 0x67, 0xf6, 0x20, 0xc0, 0x1d, 0x65, 0xb3, 0xcd, 0x67, 0xc9, 0xcd, 0x9c, 0xa, 0x9f, 0x1a, 0xfe, 0xd8, 0x5b, 0xd0, 0x15, 0xb, 0xda, 0xcf, 0x66, 0x9a, 0x7f, 0xd8, 0x7f, 0xc2, 0x9c, 0xb1, 0x1b, 0x17, 0x4d, 0x7f, 0xa7, 0x92, 0x7c, 0xe, 0xff, 0xc2, 0xd, 0x69, 0x58, 0x77, 0x1c, 0x40, 0x17, 0x84, 0x3, 0x54, 0x48, 0x4a, 0xd2, 0x91, 0x75, 0x7, 0x38, 0x4d, 0x7b, 0xef, 0xd6, 0x2c, 0x50, 0x37, 0xc, 0xd0, 0x7f, 0xc2, 0x8d, 0x7, 0x3, 0x1a, 0x65, 0x33, 0xcd, 0x97, 0x58, 0x9b, 0x3d, 0x5, 0x0, 0x40, 0xe6, 0x5a, 0xa6, 0x82, 0x47, 0xbf, 0x13, 0x0, 0x21, 0x82, 0x90, 0xdc, 0xcf, 0xc8, 0x66, 0xbe, 0xd6, 0x6f, 0xfc, 0xac, 0xef, 0xbc, 0xf4, 0x8b, 0x2b, 0x77, 0xb5, 0x35, 0x3f, 0x93, 0x6a, 0xb4, 0x36, 0xb3, 0xe3, 0x7c, 0x1a, 0xe3, 0x8f, 0xe9, 0xe1, 0x21, 0x3f, 0x4, 0xe1, 0xd1, 0x40, 0x80, 0x24, 0xd1, 0x90, 0x10, 0x8c, 0x64, 0xf, 0x31, 0xa9, 0xa6, 0x2e, 0x6, 0x48, 0x2, 0x64, 0xb3, 0xdf, 0xb0, 0xd9, 0xe6, 0x2f, 0x1, 0x41, 0x6b, 0xf7, 0x9, 0x2f, 0x91, 0x1e, 0x23, 0x78, 0x40, 0x9f, 0x8, 0x34, 0x41, 0x90, 0x75, 0x33, 0xbb, 0xfe, 0xaf, 0xd3, 0xd0, 0x7d, 0xd9, 0x61, 0xe3, 0x7e, 0x78, 0xdf, 0x9f, 0x1e, 0xb8, 0x2e, 0x72, 0x3c, 0x1e, 0x30, 0xe9, 0xce, 0x94, 0xdb, 0xb2, 0x7d, 0x1f, 0xd2, 0xf4, 0x0, 0x6c, 0x1a, 0xb2, 0xbd, 0x65, 0xdd, 0xcf, 0x0, 0x30, 0x0, 0x41, 0x42, 0x91, 0xbd, 0x0, 0xb, 0xef, 0x49, 0x52, 0x9e, 0x7a, 0x40, 0x48, 0x7b, 0xee, 0x6, 0x62, 0x54, 0x49, 0xa8, 0x1b, 0x6, 0xb0, 0xd9, 0xcc, 0x39, 0x7e, 0x6b, 0xb, 0xda, 0x5c, 0xa8, 0xeb, 0x2f, 0x4, 0x7a, 0x81, 0x41, 0x3c, 0x3, 0x10, 0x36, 0xbb, 0xeb, 0xc7, 0x4e, 0x43, 0x8f, 0xd7, 0xfa, 0x4f, 0xb8, 0x71, 0x3, 0x68, 0xf6, 0x7, 0xb0, 0x37, 0x81, 0x34, 0x8, 0xca, 0xda, 0x46, 0xb7, 0x65, 0xeb, 0x27, 0x20, 0x3b, 0xd8, 0x75, 0xdd, 0xbe, 0x4, 0xf6, 0x83, 0x74, 0x30, 0x80, 0x40, 0xf0, 0x53, 0x25, 0x43, 0x0, 0xfd, 0xff, 0x22, 0xad, 0xcd, 0xee, 0xac, 0x59, 0x3, 0xe8, 0x7f, 0xee, 0x2d, 0xdd, 0x36, 0xde, 0x73, 0xe9, 0x8e, 0xce, 0xc0, 0x7b, 0xdd, 0x30, 0x0, 0x8d, 0xf3, 0xb2, 0xac, 0x3e, 0xe, 0xc0, 0x20, 0x4e, 0xc, 0xf, 0xc8, 0x1e, 0x3c, 0xf9, 0x8a, 0x3a, 0x49, 0x40, 0xf6, 0x60, 0xeb, 0xb6, 0xfc, 0x1f, 0xd2, 0xac, 0xb3, 0xb6, 0xf9, 0x24, 0x78, 0xad, 0xbb, 0x9b, 0x17, 0xb5, 0x90, 0x46, 0xca, 0x25, 0x46, 0x85, 0x52, 0x8e, 0xcb, 0xa7, 0x30, 0xdc, 0x4a, 0xa0, 0x21, 0xe8, 0x7d, 0xed, 0x36, 0x6f, 0xad, 0x89, 0x1, 0x8e, 0x38, 0x77, 0x6e, 0x5f, 0xeb, 0xb6, 0x9c, 0xde, 0x7f, 0xc2, 0x9c, 0xe7, 0x36, 0x2e, 0x9a, 0xbe, 0xb6, 0xc3, 0xf1, 0xde, 0xd1, 0x19, 0xc6, 0x41, 0xff, 0x9, 0xb3, 0xbf, 0x67, 0x33, 0xcd, 0x5f, 0x96, 0x6c, 0xcf, 0x70, 0xab, 0x8f, 0xa3, 0x43, 0x41, 0xb8, 0x4, 0x90, 0x16, 0x80, 0x41, 0xd8, 0x78, 0x43, 0x6, 0xef, 0x8a, 0xf4, 0x7a, 0x9, 0xf2, 0xfa, 0x7d, 0xff, 0xb1, 0x40, 0x0, 0x60, 0x51, 0xde, 0xc5, 0xf9, 0x11, 0x39, 0x23, 0x51, 0xd6, 0x69, 0xdc, 0xf3, 0x18, 0xc9, 0xbe, 0x61, 0x9c, 0x86, 0xad, 0x1b, 0xee, 0x9e, 0xba, 0xb5, 0xad, 0xf5, 0x3d, 0xe2, 0xbc, 0x5b, 0xbb, 0xc1, 0xba, 0x9f, 0xc8, 0x66, 0xb6, 0x2f, 0x86, 0x74, 0x28, 0x80, 0xb7, 0x4d, 0xba, 0xdb, 0xb9, 0xc6, 0x38, 0x4b, 0x37, 0xdc, 0x73, 0x59, 0x4b, 0x47, 0xe1, 0xbd, 0x6e, 0x18, 0xa0, 0xdf, 0x84, 0x39, 0xa7, 0x2b, 0xb3, 0x73, 0x2e, 0xa0, 0x3, 0x81, 0x60, 0x9c, 0x6f, 0x73, 0xb7, 0x1c, 0xc8, 0xb, 0x20, 0xf3, 0xad, 0x3a, 0xf4, 0x9c, 0x78, 0x3d, 0x95, 0x37, 0x13, 0x92, 0xc6, 0xf9, 0xb, 0x9d, 0xf4, 0x22, 0x63, 0x52, 0xb7, 0x3, 0x78, 0x3d, 0xdb, 0xbc, 0x6d, 0xe7, 0x9f, 0x1e, 0xf8, 0x6a, 0xac, 0x6d, 0xa0, 0xff, 0x84, 0x39, 0xfb, 0x4b, 0xee, 0x14, 0x9b, 0x69, 0xfe, 0x41, 0x90, 0x9a, 0x2f, 0x5b, 0xc0, 0xa4, 0x9b, 0xfe, 0xcd, 0x18, 0xe7, 0x96, 0xd, 0xf7, 0x4e, 0x7f, 0xb7, 0x23, 0xf0, 0x5e, 0x37, 0xc, 0xd0, 0xff, 0xdc, 0x9b, 0x3f, 0x65, 0x5b, 0xb6, 0x3f, 0x21, 0xd9, 0x4f, 0x41, 0x8, 0x24, 0xed, 0xb6, 0x95, 0x56, 0x65, 0xde, 0x25, 0x55, 0x53, 0x3f, 0xad, 0x9c, 0x26, 0xe0, 0x3f, 0x14, 0xf4, 0x1e, 0x26, 0x75, 0x3f, 0x9d, 0x86, 0x9f, 0xd2, 0x49, 0xaf, 0xec, 0xd1, 0xfb, 0x88, 0x6d, 0xc5, 0x56, 0xc2, 0xfe, 0x13, 0x6f, 0x3a, 0xcc, 0x66, 0x9b, 0xe7, 0x40, 0xee, 0x18, 0x0, 0x5e, 0xaf, 0x15, 0x24, 0x3, 0x8, 0x24, 0x8d, 0xd3, 0x70, 0x13, 0x4c, 0xea, 0xfb, 0x1b, 0xef, 0x9d, 0xf6, 0x6a, 0x7b, 0xe3, 0xdd, 0xb4, 0x77, 0x6, 0x6d, 0x85, 0x8d, 0xf7, 0x5c, 0xf6, 0xa, 0x69, 0x9a, 0x3d, 0x51, 0x3b, 0xc0, 0x26, 0xfd, 0xb, 0xa5, 0x9, 0x58, 0xaa, 0xa3, 0x28, 0xf7, 0x6d, 0x25, 0xe0, 0xa7, 0x95, 0x27, 0x3e, 0x94, 0xcf, 0xc0, 0xd3, 0x26, 0xad, 0x9b, 0x3d, 0xdb, 0x6d, 0xd9, 0xf1, 0x8c, 0x6d, 0xd9, 0xfe, 0xdc, 0x96, 0xd7, 0x57, 0x9f, 0x11, 0xfe, 0xfc, 0x88, 0x73, 0xe7, 0x9e, 0xec, 0xb6, 0xec, 0xd8, 0x28, 0xeb, 0x8e, 0xf1, 0xbe, 0xf5, 0xf1, 0x2f, 0x88, 0xa0, 0xcf, 0x48, 0xb4, 0xd6, 0x6d, 0x99, 0x66, 0xb3, 0x2d, 0xf3, 0xfb, 0x4f, 0x9c, 0x7b, 0x5c, 0x7b, 0xe3, 0xbd, 0x6e, 0x7a, 0x0, 0x0, 0xe8, 0x77, 0xce, 0xcf, 0x9e, 0xb3, 0x6e, 0xe6, 0x78, 0x20, 0x5a, 0xfa, 0xaf, 0x3f, 0x8, 0x86, 0x81, 0x7c, 0x61, 0xfd, 0x91, 0x41, 0x64, 0xa0, 0x5a, 0x38, 0x2b, 0x4c, 0xba, 0xf1, 0x3b, 0x4, 0x7a, 0x66, 0x5b, 0x76, 0x2c, 0xf4, 0xf8, 0xbb, 0xd5, 0xb0, 0x54, 0xd0, 0x4f, 0x5, 0x6a, 0x26, 0x8d, 0x79, 0x8d, 0x4e, 0xd3, 0xbf, 0xbd, 0xb4, 0x68, 0xda, 0x5d, 0xed, 0x55, 0x3, 0xa7, 0xf6, 0x24, 0x92, 0x83, 0x8f, 0xf, 0x1c, 0x9b, 0x2, 0x34, 0x9c, 0x40, 0x8f, 0x78, 0xcb, 0x4c, 0x3d, 0x41, 0xd0, 0x45, 0xf9, 0xe0, 0xcb, 0x2d, 0xbe, 0xd5, 0x92, 0x14, 0x24, 0xa2, 0xb7, 0x6c, 0x76, 0x82, 0xac, 0x7b, 0x16, 0x29, 0x27, 0x50, 0x21, 0x1, 0x85, 0xba, 0xba, 0x5c, 0x37, 0xe2, 0xdb, 0xbb, 0x72, 0x36, 0xb0, 0xbd, 0x61, 0xdd, 0x13, 0xf7, 0x3f, 0xf2, 0xec, 0x96, 0x77, 0xd6, 0x2f, 0xfe, 0x5d, 0x7b, 0xd4, 0xa0, 0x6e, 0x86, 0x0, 0xaf, 0x34, 0xce, 0x12, 0x0, 0xef, 0x7b, 0xf7, 0x86, 0xf9, 0x21, 0x60, 0x37, 0xb9, 0x8c, 0xf1, 0x94, 0xc3, 0x80, 0x71, 0x69, 0x40, 0xd2, 0x90, 0x6c, 0x0, 0xd4, 0x0, 0x18, 0x79, 0x17, 0x8, 0x18, 0x45, 0xa4, 0xe1, 0x31, 0x81, 0x31, 0xfe, 0x7b, 0x3, 0x40, 0xfb, 0x65, 0x33, 0xbb, 0xbe, 0xde, 0x6f, 0xc2, 0x9c, 0xaf, 0xb4, 0x7, 0xca, 0xeb, 0xa6, 0x7, 0xe8, 0x3f, 0x71, 0xee, 0x4, 0x4f, 0x38, 0x52, 0x3f, 0xf8, 0xb6, 0x9e, 0xd0, 0xe8, 0xba, 0xfb, 0x5c, 0x44, 0xae, 0xfd, 0xe7, 0xee, 0x1, 0xbf, 0x67, 0x80, 0x7f, 0x11, 0xa1, 0x77, 0x45, 0xdf, 0x93, 0xa1, 0x74, 0x82, 0x1e, 0x61, 0x4f, 0xca, 0xe, 0xea, 0x35, 0xe8, 0x2c, 0xe7, 0x9d, 0xf5, 0x8b, 0x97, 0x26, 0x89, 0xf7, 0xba, 0x30, 0x4, 0xf5, 0x9f, 0x78, 0xd3, 0x2c, 0x9b, 0xdd, 0x75, 0x36, 0xa0, 0x3e, 0xde, 0x18, 0x69, 0x24, 0x28, 0x6c, 0x0, 0xde, 0x1d, 0x81, 0x31, 0xf7, 0x6d, 0x6, 0x6f, 0x14, 0xf4, 0x70, 0x21, 0xb0, 0x1b, 0xc8, 0xee, 0x49, 0x17, 0xb2, 0xd3, 0x19, 0xe0, 0xf0, 0x73, 0x66, 0x3d, 0xad, 0x6c, 0xcb, 0x48, 0x0, 0xdd, 0xbd, 0x39, 0x1e, 0xdf, 0x74, 0x53, 0xef, 0xc3, 0x7f, 0x87, 0x40, 0xce, 0xe4, 0xd, 0x1a, 0x67, 0xb5, 0x71, 0xd2, 0xd7, 0x27, 0x9d, 0x43, 0x62, 0xc, 0x70, 0xc4, 0xb9, 0x73, 0x7f, 0x24, 0x61, 0x1b, 0x8d, 0xf3, 0xd3, 0xd, 0x77, 0x4f, 0x7d, 0xbf, 0x5c, 0xfc, 0x81, 0x93, 0xee, 0xd8, 0x23, 0xdb, 0xb2, 0xe3, 0x31, 0xd9, 0xec, 0x9, 0x5e, 0x3f, 0x97, 0x13, 0x80, 0xbb, 0x88, 0xef, 0x83, 0x6f, 0xc0, 0x24, 0xe9, 0xbc, 0x63, 0x9c, 0xf4, 0xe2, 0x75, 0x3f, 0xbf, 0x38, 0x71, 0xb, 0x61, 0x22, 0x98, 0x3e, 0xe2, 0xbc, 0x5b, 0x47, 0xd8, 0xcc, 0xce, 0x7, 0x25, 0x75, 0xa3, 0x71, 0xd6, 0x80, 0xe6, 0x75, 0xd2, 0xfc, 0x99, 0xc6, 0x99, 0xb7, 0xe1, 0xee, 0xa9, 0x7f, 0x2e, 0x8e, 0xdf, 0xff, 0xdc, 0x5b, 0xe, 0x95, 0xdb, 0x72, 0x87, 0x6c, 0x76, 0x14, 0xe9, 0xab, 0xc2, 0x5e, 0x4d, 0xe1, 0x49, 0xc7, 0x51, 0xc5, 0x8c, 0x33, 0xb9, 0x87, 0xe7, 0x85, 0x54, 0xe2, 0x9b, 0x62, 0x3, 0x6f, 0xb9, 0xb4, 0x63, 0xb5, 0xb4, 0x88, 0xf0, 0xa8, 0xef, 0x2a, 0x29, 0x6f, 0xeb, 0x6f, 0x72, 0xbe, 0x67, 0x0, 0x41, 0xe7, 0x91, 0x74, 0xd3, 0x9e, 0xe3, 0xd7, 0x2e, 0x98, 0xb2, 0xb3, 0x1a, 0xfa, 0x94, 0x82, 0x9a, 0x19, 0xe0, 0x88, 0xf3, 0xe7, 0xf5, 0x50, 0x76, 0xc7, 0xc3, 0xb2, 0xee, 0x71, 0x80, 0x42, 0x5a, 0x85, 0xd9, 0x42, 0x63, 0xd6, 0x80, 0xce, 0x4a, 0x1a, 0xe7, 0x77, 0x26, 0x95, 0x7e, 0x74, 0xdd, 0x82, 0x29, 0x1f, 0x1c, 0x71, 0xfe, 0x6d, 0x43, 0x6c, 0x66, 0xd7, 0x4d, 0x90, 0x7b, 0x54, 0xa8, 0x18, 0xc2, 0x6e, 0x3e, 0xe0, 0x27, 0xa, 0xca, 0xd9, 0x1c, 0x9, 0x3a, 0xaf, 0x9a, 0x54, 0xc3, 0xbf, 0x6f, 0xb8, 0xfb, 0xd2, 0x85, 0xed, 0x91, 0x55, 0xcd, 0x43, 0x80, 0xdc, 0xe6, 0x1f, 0xcb, 0xba, 0xbe, 0xf1, 0xc6, 0x84, 0xed, 0xf0, 0x7b, 0xc9, 0xba, 0xa3, 0x0, 0x77, 0x94, 0xac, 0x73, 0x86, 0xac, 0x3b, 0xae, 0xff, 0xc4, 0xb9, 0x7f, 0x57, 0xb6, 0x79, 0x38, 0x64, 0x8f, 0xf2, 0x6c, 0xf4, 0xb9, 0x7e, 0xdf, 0x17, 0xf8, 0xca, 0xb5, 0xe0, 0xb6, 0x98, 0xf5, 0x2b, 0x69, 0x95, 0xc5, 0x3e, 0x9f, 0xe1, 0xfb, 0x72, 0x71, 0xdb, 0x52, 0xd6, 0xf0, 0x77, 0x71, 0xe5, 0x2c, 0xec, 0x11, 0x3c, 0xe9, 0x97, 0xb9, 0xf9, 0x26, 0x1a, 0xe7, 0xa9, 0xc6, 0x6e, 0x3d, 0xef, 0xa9, 0x95, 0x4e, 0x71, 0x50, 0x53, 0xab, 0x1b, 0x70, 0xfe, 0x6d, 0x5f, 0xb0, 0x99, 0x9d, 0xbf, 0x90, 0x37, 0x8b, 0x9f, 0xa3, 0x62, 0x48, 0x82, 0x97, 0x82, 0x3c, 0xa, 0x3c, 0xee, 0x68, 0x25, 0x85, 0xad, 0xfd, 0x5d, 0xad, 0x3f, 0x4, 0x9e, 0x25, 0x90, 0x34, 0x4e, 0xea, 0x45, 0x3a, 0xd, 0xd7, 0xad, 0xbf, 0xeb, 0xe2, 0xe7, 0xda, 0x2b, 0xaf, 0xaa, 0x7b, 0x80, 0x81, 0x93, 0xee, 0x38, 0xd8, 0xcd, 0xec, 0xfc, 0xbe, 0x2, 0xa3, 0x95, 0xef, 0x58, 0xc5, 0x90, 0xff, 0x4e, 0xce, 0x98, 0x27, 0x8, 0x26, 0x4f, 0x64, 0x8f, 0xf8, 0x7e, 0xb7, 0x5f, 0xcd, 0x5c, 0x5d, 0x12, 0xf3, 0x7b, 0xd5, 0xb0, 0x5e, 0xa9, 0x6f, 0x8a, 0x1c, 0xc7, 0x2b, 0xae, 0x47, 0xe1, 0x77, 0xde, 0x9d, 0x71, 0xee, 0x69, 0x4f, 0xe2, 0x3, 0x55, 0x5a, 0x2, 0x7, 0x4c, 0x9a, 0xd7, 0x60, 0x6d, 0xf6, 0x5a, 0x59, 0xfb, 0x69, 0x7f, 0xf2, 0xc6, 0x9b, 0x5d, 0x2f, 0x12, 0xdf, 0x73, 0xcf, 0x45, 0xe3, 0xbb, 0x37, 0xe7, 0x91, 0x73, 0xac, 0xa9, 0x1c, 0x2a, 0xfc, 0x46, 0x2a, 0xe8, 0x9f, 0x15, 0xfc, 0x13, 0x50, 0xe0, 0x3e, 0x20, 0x95, 0x49, 0xa8, 0xd4, 0xc4, 0x12, 0x8b, 0x7e, 0x2b, 0xad, 0x7, 0x8b, 0x5f, 0x30, 0x5e, 0x8e, 0x4c, 0x10, 0x2a, 0x66, 0x80, 0x81, 0x17, 0xce, 0x77, 0x20, 0x3b, 0xda, 0x66, 0x5b, 0xae, 0xcd, 0x9b, 0xc1, 0xc3, 0x53, 0x76, 0x9d, 0x7b, 0x29, 0x34, 0x43, 0xe7, 0xdf, 0xfb, 0x73, 0xed, 0x1e, 0x81, 0x25, 0xd0, 0x37, 0x34, 0xe4, 0xae, 0xe0, 0x1d, 0xa3, 0x6d, 0x73, 0xf2, 0xd3, 0xca, 0xdd, 0xb7, 0xff, 0xe5, 0x33, 0xa9, 0xdc, 0x2f, 0xc, 0x98, 0x74, 0xc7, 0xf1, 0xed, 0xc9, 0x0, 0x15, 0xb7, 0xbf, 0x41, 0x17, 0xce, 0xef, 0x93, 0x6d, 0xd9, 0xf9, 0x0, 0xac, 0x3b, 0xd2, 0xeb, 0xc0, 0xe3, 0x54, 0xb7, 0x4a, 0x8a, 0x50, 0x4a, 0x65, 0x2, 0x4a, 0xb, 0x5c, 0x39, 0xc8, 0x77, 0xa2, 0xa, 0xd4, 0xa7, 0x82, 0xb4, 0x3e, 0x0, 0xf9, 0x3e, 0x80, 0x6d, 0x0, 0x76, 0x92, 0xdc, 0x5, 0xd2, 0x42, 0x8, 0xe4, 0x91, 0x14, 0x80, 0x26, 0x9, 0xdd, 0x20, 0xbb, 0xf, 0xa0, 0x5e, 0x90, 0x6f, 0x2a, 0x67, 0x4c, 0x1e, 0x35, 0x6b, 0x2e, 0x11, 0xf5, 0x93, 0xe7, 0x13, 0x0, 0xc2, 0x42, 0x32, 0x34, 0xce, 0x93, 0x26, 0xd5, 0x78, 0xd9, 0xba, 0x85, 0x17, 0xbd, 0x5a, 0x5b, 0x5e, 0xa5, 0x4b, 0xd0, 0x26, 0x18, 0x7c, 0xc5, 0x33, 0xcc, 0x7e, 0xf8, 0xea, 0x19, 0x36, 0xb3, 0xf3, 0x21, 0x0, 0x16, 0x81, 0x12, 0x1f, 0xae, 0x8a, 0xe2, 0x13, 0x2d, 0x18, 0xf2, 0x22, 0x4, 0xe7, 0x3c, 0xef, 0x7, 0xe6, 0xaf, 0xfc, 0x87, 0xad, 0xc8, 0xee, 0x8b, 0x1d, 0xa, 0xd6, 0x8a, 0x84, 0xe6, 0x66, 0xfd, 0x98, 0x2d, 0x34, 0xce, 0x3f, 0x24, 0xbc, 0x4d, 0x9a, 0x4d, 0x30, 0x66, 0x1d, 0xc0, 0x97, 0x48, 0xfe, 0x15, 0xe0, 0x3b, 0x20, 0xdf, 0x23, 0xd4, 0xec, 0x5a, 0x65, 0xd2, 0xe9, 0x86, 0x46, 0xeb, 0x66, 0xba, 0x1, 0xd8, 0xd7, 0x5a, 0xdb, 0x7, 0xd2, 0x0, 0xc9, 0x8e, 0x24, 0x74, 0xb0, 0xa4, 0x8f, 0x1, 0x3a, 0x0, 0xb2, 0xfb, 0x86, 0xab, 0xc2, 0x90, 0xcf, 0x7a, 0x1, 0x33, 0xa8, 0x75, 0x7d, 0xa, 0xe4, 0xfd, 0x8, 0x33, 0x40, 0x41, 0x13, 0xa, 0x3b, 0xc6, 0x7a, 0x35, 0xb2, 0x74, 0x1a, 0xe6, 0x34, 0xef, 0xdc, 0x7e, 0xd5, 0x5f, 0x1e, 0xb8, 0x3a, 0xf1, 0x15, 0x48, 0x15, 0x9, 0x81, 0xee, 0x96, 0xbf, 0xd, 0x92, 0xdb, 0xf2, 0x7d, 0x80, 0xa0, 0x6f, 0xb0, 0xf7, 0xb0, 0x9f, 0x9b, 0xb7, 0x40, 0xde, 0x23, 0xab, 0x88, 0x82, 0xb9, 0xa7, 0xd0, 0xff, 0x1c, 0xc5, 0x43, 0x2c, 0xc3, 0xa8, 0xc6, 0xdb, 0x2a, 0x2c, 0xb0, 0x93, 0x4, 0x62, 0x86, 0xfc, 0x29, 0x78, 0x80, 0x7c, 0xf, 0x30, 0x9b, 0x4, 0xb3, 0x96, 0x4e, 0x6a, 0x71, 0x3a, 0xd5, 0xf0, 0xe0, 0xea, 0x3b, 0x27, 0x95, 0x33, 0xa0, 0xb4, 0x0, 0xd8, 0xa, 0xe0, 0x2d, 0x0, 0x1b, 0x1, 0x3c, 0x15, 0xbc, 0x18, 0x30, 0xe9, 0xce, 0x7e, 0xb2, 0x99, 0x89, 0x80, 0x8e, 0x83, 0xec, 0xa1, 0x92, 0x3d, 0x8, 0x42, 0x63, 0xa0, 0xc1, 0x7a, 0x79, 0x2a, 0x50, 0x79, 0x42, 0x66, 0xcc, 0xbc, 0xab, 0x40, 0x58, 0xd, 0xca, 0xd7, 0x3b, 0xa8, 0x17, 0xfc, 0x70, 0xbf, 0x4a, 0xfe, 0xa, 0x88, 0xc0, 0x30, 0x26, 0xc1, 0x48, 0xee, 0x99, 0x4d, 0xdd, 0xf7, 0x5a, 0xe, 0xe0, 0xf6, 0xa4, 0x19, 0xa0, 0xa2, 0x1e, 0x60, 0xe0, 0x5, 0x77, 0x9e, 0xea, 0x66, 0x76, 0x3e, 0x26, 0xc9, 0x84, 0xb1, 0xdf, 0x91, 0x10, 0xb2, 0x15, 0xcb, 0xd7, 0x32, 0x7c, 0xe, 0xe0, 0xfb, 0x24, 0xdf, 0xa2, 0x49, 0xdd, 0x6c, 0x1c, 0x67, 0xf6, 0xda, 0x5, 0x53, 0xda, 0xbc, 0x48, 0xa4, 0xad, 0x30, 0x60, 0xd2, 0xbc, 0x43, 0x21, 0xf7, 0xbb, 0x92, 0x1d, 0x29, 0xeb, 0x7e, 0x2, 0x52, 0x93, 0xbf, 0x4c, 0x2d, 0xd4, 0x10, 0x12, 0xad, 0x6b, 0xde, 0xa7, 0x91, 0xce, 0x12, 0xa6, 0xf6, 0x38, 0x75, 0xfd, 0xc2, 0xb, 0x9a, 0x93, 0xcc, 0xa3, 0x32, 0x6, 0x98, 0x7c, 0x57, 0xa3, 0xcd, 0x36, 0x9f, 0x23, 0xb7, 0xe5, 0x4e, 0x40, 0x4e, 0xe0, 0x80, 0xd9, 0x51, 0xf6, 0xfb, 0x80, 0xf8, 0x61, 0x84, 0x4b, 0xd8, 0x49, 0x60, 0x87, 0x49, 0x37, 0x7e, 0x7b, 0xdd, 0xc2, 0x8b, 0x6e, 0x6c, 0xf7, 0x42, 0x0, 0x18, 0x30, 0xf9, 0xee, 0x94, 0x32, 0xdb, 0xe7, 0xca, 0xba, 0xa7, 0x1, 0xda, 0x3f, 0xb7, 0x78, 0x25, 0xef, 0x26, 0x98, 0x38, 0x42, 0x24, 0xb9, 0x34, 0xa9, 0x7b, 0x36, 0xdc, 0x3d, 0xf5, 0x82, 0x24, 0xd3, 0xad, 0x5c, 0x8, 0x9c, 0xbc, 0x70, 0xf, 0xeb, 0x66, 0x2f, 0xb3, 0xd9, 0xe6, 0x19, 0xf0, 0xc7, 0x5b, 0x4f, 0x14, 0xc8, 0x69, 0x57, 0x25, 0xd2, 0x2c, 0x67, 0x15, 0xb, 0xc7, 0x29, 0xf2, 0xe5, 0xf7, 0xa7, 0x46, 0xe1, 0x59, 0x19, 0xe1, 0x79, 0xd2, 0x3a, 0x5b, 0x61, 0x9c, 0xdb, 0x68, 0x52, 0x5f, 0x5f, 0xbf, 0x70, 0x72, 0x87, 0xb9, 0x52, 0x7, 0x30, 0x70, 0xf2, 0xcf, 0xbb, 0xb9, 0x2d, 0xdb, 0x97, 0x41, 0xb6, 0x2f, 0xc0, 0x3d, 0x2, 0xe7, 0x64, 0x32, 0xf0, 0x48, 0xe, 0x44, 0xa4, 0x52, 0xe, 0xe6, 0xc5, 0x78, 0x88, 0x14, 0x72, 0x25, 0x89, 0xa0, 0x59, 0xed, 0xa4, 0x1a, 0x3f, 0xb7, 0x6e, 0xe1, 0x94, 0xb7, 0xc2, 0x2f, 0x47, 0x5e, 0xb3, 0x94, 0x3b, 0xdf, 0x7b, 0xc5, 0xd0, 0x69, 0xa0, 0xcd, 0x6c, 0x27, 0x4d, 0x9a, 0x0, 0xdd, 0x75, 0xb, 0x2e, 0x70, 0xcb, 0xd5, 0xa1, 0x2a, 0x2e, 0x1d, 0x34, 0xf9, 0xe7, 0x7b, 0x58, 0xb7, 0xe5, 0xdb, 0x36, 0xdb, 0xf2, 0x75, 0x2, 0x26, 0x34, 0xf0, 0x33, 0x69, 0x57, 0xae, 0x70, 0x97, 0xf, 0x8f, 0xf8, 0x2, 0x0, 0x63, 0xcc, 0x66, 0xa6, 0x1a, 0xc7, 0xae, 0x5b, 0x30, 0x39, 0x51, 0x7, 0x89, 0x6a, 0x60, 0xc0, 0xa4, 0x79, 0xd7, 0xd9, 0x6c, 0xf3, 0x37, 0x0, 0xed, 0xcb, 0xb0, 0x47, 0x50, 0x72, 0x26, 0xab, 0x80, 0xe9, 0x41, 0x93, 0x7a, 0x7e, 0xc3, 0xdd, 0x53, 0x8f, 0x1f, 0x34, 0xe5, 0xee, 0x46, 0x9b, 0x6d, 0xa6, 0x71, 0x1a, 0x9a, 0x24, 0xb7, 0x2f, 0xa4, 0x8f, 0x9, 0xea, 0x49, 0xa0, 0x87, 0xa4, 0x3, 0x69, 0x9c, 0x17, 0x20, 0xf7, 0xf9, 0x75, 0xb, 0x2f, 0xca, 0x94, 0x4a, 0xbc, 0xea, 0xc2, 0xd, 0xbc, 0x70, 0x61, 0x83, 0x6c, 0xf6, 0xdf, 0xe5, 0xb6, 0x7c, 0x13, 0x64, 0xb0, 0x20, 0x23, 0xbf, 0xd8, 0x22, 0x49, 0x8, 0x98, 0x4a, 0x82, 0xa4, 0xac, 0x71, 0x52, 0xcf, 0x3b, 0xd, 0xdd, 0xce, 0x5e, 0x33, 0xef, 0xbc, 0xf, 0x92, 0xcf, 0xac, 0x5a, 0x7c, 0x2c, 0x18, 0x63, 0xb3, 0xbb, 0xe6, 0xc9, 0xda, 0x83, 0x3d, 0x43, 0x17, 0x3, 0x49, 0xbe, 0xf6, 0x6, 0x91, 0x5f, 0xdc, 0x2, 0x1, 0xbb, 0x48, 0xf3, 0x1a, 0xa4, 0xde, 0x80, 0x7a, 0x2, 0x28, 0xd2, 0x81, 0x82, 0x7b, 0xae, 0x34, 0xa9, 0xc6, 0xeb, 0xd6, 0x2d, 0x9c, 0xfc, 0x54, 0xa9, 0xa4, 0xab, 0xf6, 0x9, 0x5c, 0xb7, 0xe0, 0x82, 0x16, 0xa7, 0xb1, 0xfb, 0x7f, 0x99, 0x54, 0xe3, 0x75, 0x4, 0xb2, 0x8, 0x69, 0x33, 0x89, 0x9b, 0x45, 0x7c, 0x24, 0x90, 0xcc, 0x1a, 0x27, 0xfd, 0xf0, 0xfa, 0xbb, 0x2e, 0x19, 0x53, 0x4f, 0xc4, 0xf7, 0xf0, 0x71, 0xe1, 0xd3, 0x26, 0xd5, 0x78, 0xa, 0xe9, 0x6c, 0x40, 0x41, 0xd9, 0x6b, 0x77, 0x6d, 0x43, 0xe1, 0x6f, 0x23, 0x64, 0xf, 0x3, 0xb4, 0x17, 0x8a, 0xde, 0x15, 0xde, 0x6b, 0x88, 0xa0, 0x7f, 0x29, 0x57, 0xee, 0x9a, 0x9c, 0x42, 0xd7, 0xdc, 0x3e, 0x3e, 0xeb, 0x34, 0x74, 0x9f, 0x69, 0x52, 0x4d, 0x53, 0x4, 0xbe, 0xdf, 0x76, 0x8b, 0x60, 0x18, 0x4a, 0x85, 0x31, 0xc7, 0xd6, 0x5e, 0xbf, 0x9f, 0x7a, 0x72, 0xfd, 0x5d, 0x17, 0x9f, 0x95, 0x18, 0xd5, 0x12, 0x86, 0x75, 0xb, 0x26, 0xff, 0xc9, 0x34, 0x34, 0x9d, 0x49, 0xe3, 0x2c, 0xf7, 0x2d, 0x8e, 0xfe, 0xf0, 0x15, 0x26, 0x63, 0x31, 0x59, 0x4b, 0x85, 0x79, 0xcf, 0x7e, 0x7, 0x2b, 0xd2, 0xc8, 0xf3, 0x31, 0xd, 0x2e, 0x8a, 0x34, 0xc1, 0xd4, 0x51, 0x51, 0x47, 0x6c, 0xc, 0x81, 0x4f, 0x7e, 0xea, 0xc2, 0x87, 0x4a, 0xf6, 0x3e, 0x35, 0x7b, 0x5, 0xaf, 0xbe, 0xfd, 0x9c, 0x2c, 0x53, 0xd, 0xf7, 0x93, 0xdc, 0x51, 0x64, 0xa, 0x29, 0x1, 0x51, 0xcc, 0x50, 0x18, 0x26, 0xbf, 0x1f, 0x83, 0xe7, 0x2b, 0x0, 0xe3, 0xa4, 0x9f, 0x6c, 0x49, 0xf7, 0x3a, 0xbd, 0xdd, 0xa8, 0x97, 0x10, 0xac, 0x9b, 0x7f, 0xc1, 0x2b, 0x26, 0xd5, 0x38, 0x85, 0xc6, 0x59, 0x82, 0xfc, 0xec, 0x28, 0xa2, 0x99, 0x1c, 0x65, 0xc2, 0xf2, 0xcf, 0xcc, 0xdb, 0xa9, 0xc3, 0xef, 0x99, 0x7f, 0x95, 0x8b, 0x27, 0x4f, 0x39, 0x12, 0xac, 0xcd, 0x9e, 0xd7, 0x9d, 0x1f, 0x4e, 0x2c, 0x55, 0xde, 0x44, 0xdc, 0xc2, 0x6d, 0x36, 0xd3, 0xf, 0x40, 0xda, 0xa3, 0x17, 0x13, 0x71, 0xe7, 0x26, 0xd, 0x5, 0x58, 0x6f, 0x4a, 0x3c, 0xfd, 0xa8, 0x93, 0x6e, 0x1a, 0xff, 0xf2, 0xbc, 0xd3, 0x77, 0x8b, 0xcd, 0x98, 0xd6, 0xce, 0xbf, 0x60, 0x23, 0x4c, 0x6a, 0x16, 0xe9, 0xbc, 0xec, 0x4d, 0x31, 0x18, 0xc9, 0x53, 0x97, 0x6a, 0xc6, 0x4b, 0x1b, 0x2e, 0x6, 0xb3, 0x6d, 0x90, 0xfa, 0xca, 0xaa, 0x7f, 0xfb, 0x33, 0x80, 0x9b, 0x99, 0x1, 0x70, 0xdf, 0x9a, 0x13, 0x2a, 0x4, 0x1, 0x34, 0x34, 0xce, 0x5a, 0x9a, 0xf4, 0xd, 0x6b, 0xe6, 0x9d, 0xf7, 0x61, 0x7b, 0x11, 0xac, 0x3d, 0x60, 0xfd, 0xc2, 0xc9, 0xf7, 0xc0, 0xa4, 0x6e, 0x7, 0xb9, 0xcd, 0xb7, 0x57, 0x75, 0x98, 0xd1, 0x2c, 0xbc, 0x48, 0x56, 0x50, 0x8f, 0x52, 0x71, 0x6b, 0x66, 0x80, 0x23, 0xa7, 0xdc, 0xb5, 0x17, 0x60, 0x87, 0x92, 0x48, 0xe5, 0xf5, 0xde, 0x44, 0xc4, 0x1e, 0x92, 0xdc, 0x42, 0x93, 0x5a, 0xb0, 0x76, 0xfe, 0xa4, 0xc7, 0x3a, 0xa, 0x79, 0x49, 0x82, 0x31, 0xce, 0x2c, 0x9a, 0xd4, 0xbd, 0xbe, 0x8d, 0x3a, 0x98, 0x25, 0x69, 0xf7, 0x19, 0xc5, 0x80, 0xf8, 0xbe, 0xf6, 0x7c, 0xe4, 0xc0, 0xc9, 0xb, 0x87, 0xc4, 0x96, 0xb1, 0x96, 0xa, 0x1e, 0x7d, 0xed, 0xef, 0x8, 0x72, 0x38, 0x80, 0xb4, 0x97, 0xa1, 0xd7, 0xcd, 0xd5, 0xd2, 0x83, 0xf9, 0x5, 0xf7, 0x2a, 0xe0, 0xa4, 0x1e, 0x0, 0x4d, 0xe2, 0xf6, 0xef, 0x8e, 0x82, 0xb5, 0xf3, 0x27, 0x6d, 0x31, 0x4e, 0xfa, 0x36, 0x18, 0x67, 0x29, 0xfc, 0x3e, 0xd9, 0x9f, 0xe9, 0xab, 0xc, 0x27, 0x11, 0xf7, 0x88, 0x9, 0xf7, 0x47, 0x1, 0xff, 0x3f, 0x1, 0x6b, 0x4f, 0x80, 0x74, 0x76, 0x5c, 0x19, 0x6b, 0x62, 0x80, 0x6d, 0xff, 0xd8, 0x48, 0xeb, 0x66, 0xcf, 0x25, 0x4d, 0xca, 0x2f, 0x51, 0xcd, 0xeb, 0x79, 0x7c, 0x75, 0x9f, 0xa0, 0x79, 0x15, 0x30, 0xf7, 0xaf, 0x9b, 0x3f, 0xa9, 0xa2, 0xdd, 0xbf, 0xea, 0xd, 0xd6, 0xde, 0x79, 0xfe, 0xb, 0x34, 0xa9, 0xc5, 0x0, 0x0, 0x1a, 0x11, 0xac, 0x58, 0x31, 0x64, 0xc4, 0x3d, 0x63, 0xc2, 0x8b, 0xf0, 0x28, 0x92, 0xd, 0x24, 0xfa, 0xc6, 0x95, 0xaf, 0x26, 0x6, 0x58, 0x7f, 0xd7, 0xc5, 0x56, 0x6e, 0x76, 0x2c, 0xa0, 0x34, 0x69, 0xc2, 0x5b, 0xaf, 0x54, 0x7e, 0x91, 0x81, 0xe4, 0xef, 0xf5, 0x22, 0xc6, 0x59, 0x44, 0x63, 0x1e, 0xef, 0x6c, 0x2, 0x26, 0x1, 0xa4, 0x59, 0x4c, 0x93, 0x7a, 0x12, 0xfe, 0x7e, 0x46, 0x28, 0x35, 0xc, 0xb0, 0xb6, 0x6, 0x54, 0x98, 0x16, 0x82, 0x6e, 0xb5, 0xf1, 0xd3, 0xe3, 0xe7, 0x46, 0xd2, 0xba, 0x26, 0x6, 0x18, 0x74, 0xd1, 0x3d, 0x7d, 0x41, 0xf4, 0xf6, 0xc4, 0x76, 0x28, 0xa7, 0xf2, 0x56, 0x39, 0xec, 0xfb, 0x92, 0x3f, 0x49, 0xf3, 0x16, 0x8d, 0xf3, 0xd4, 0xda, 0x3b, 0xcf, 0xdf, 0xde, 0xd9, 0xc4, 0x4b, 0x2, 0xd6, 0xde, 0x79, 0xfe, 0x5a, 0x3a, 0xa9, 0xf9, 0x5e, 0x25, 0x73, 0xe, 0x1f, 0x25, 0xc4, 0x9f, 0xda, 0x2f, 0xcf, 0xaf, 0xc4, 0x50, 0x9e, 0xf5, 0xb4, 0x67, 0x63, 0xb7, 0x1e, 0x7, 0x46, 0x95, 0xad, 0x6a, 0x6, 0x18, 0x7c, 0xc9, 0xfd, 0x29, 0x59, 0x3b, 0xa, 0xa0, 0x4d, 0xa2, 0xe4, 0x81, 0x1, 0x3, 0x20, 0x68, 0x9c, 0xf9, 0x34, 0xce, 0x8a, 0xce, 0x26, 0x5c, 0xa2, 0x40, 0xf3, 0x57, 0xd2, 0xbc, 0x8b, 0x76, 0x76, 0x9f, 0xb, 0x5c, 0xe2, 0xfc, 0x1d, 0x67, 0xe0, 0x73, 0xc3, 0xc1, 0x10, 0x3e, 0x1d, 0x55, 0xac, 0xaa, 0x19, 0x60, 0xf5, 0x6d, 0x67, 0x67, 0x9, 0x7d, 0x26, 0x34, 0xd3, 0x55, 0x93, 0x9a, 0xc3, 0xdc, 0x46, 0x4e, 0x0, 0x4d, 0x6a, 0xd9, 0x9a, 0x3b, 0x26, 0xee, 0xd6, 0x63, 0x7f, 0x31, 0x18, 0x63, 0xd6, 0x9b, 0x54, 0xc3, 0x6c, 0xff, 0x51, 0x91, 0x5b, 0x91, 0xd7, 0x0, 0x85, 0x3e, 0x9, 0x9e, 0x22, 0xe8, 0xd, 0xa5, 0xe6, 0x15, 0x3a, 0xa9, 0xfb, 0x49, 0xf3, 0x46, 0xd4, 0x77, 0x6d, 0xf6, 0x8, 0x1a, 0x74, 0xd1, 0xdd, 0x4d, 0xa4, 0xb3, 0xbf, 0xac, 0xed, 0x2b, 0xe8, 0x40, 0x2, 0x7b, 0x43, 0xee, 0x98, 0xdc, 0x86, 0x8d, 0xc9, 0xa8, 0xb9, 0x24, 0xb9, 0x9, 0xe0, 0xa6, 0x24, 0x91, 0x53, 0xf, 0xb0, 0xfa, 0xf6, 0x9, 0x9b, 0x7, 0x7f, 0x71, 0xd1, 0x43, 0x0, 0xfe, 0x3, 0x0, 0x61, 0x12, 0x30, 0xc1, 0x84, 0x26, 0x80, 0x48, 0x12, 0xb2, 0xca, 0xeb, 0x1, 0x7c, 0x97, 0xc6, 0x79, 0x96, 0x74, 0x16, 0x64, 0x65, 0x16, 0x6f, 0xb8, 0x73, 0x42, 0x36, 0x2a, 0x89, 0x58, 0x6, 0x18, 0x74, 0xd1, 0xbd, 0x3d, 0x21, 0x1d, 0xe, 0xe8, 0x40, 0x90, 0x7b, 0x41, 0xea, 0x25, 0x65, 0x8f, 0x90, 0x75, 0x8f, 0x83, 0xf4, 0xe9, 0x60, 0xe1, 0x7a, 0x68, 0x51, 0x67, 0xad, 0x1e, 0x31, 0x9e, 0x3b, 0x21, 0x53, 0x33, 0x4, 0xac, 0x69, 0x2f, 0x42, 0x74, 0x26, 0x8, 0xb0, 0xa0, 0x79, 0x1f, 0xd2, 0x3e, 0x9, 0x35, 0x97, 0xc0, 0x21, 0xc7, 0x73, 0x8e, 0x1, 0x29, 0x70, 0x33, 0xc9, 0x55, 0x34, 0xa9, 0x87, 0x8c, 0x93, 0x9a, 0xbf, 0xfa, 0xf6, 0xf1, 0x9b, 0x4b, 0x25, 0x11, 0xc9, 0x0, 0x83, 0xbf, 0xb8, 0x68, 0x7f, 0x2b, 0xf7, 0x7c, 0x59, 0x77, 0x3a, 0x64, 0xf, 0x2f, 0xcc, 0x33, 0xa7, 0xb0, 0x7b, 0x4e, 0xa, 0xf0, 0xf9, 0xad, 0xb6, 0x1e, 0x20, 0x67, 0x2c, 0x37, 0x8e, 0xf3, 0xfc, 0x9a, 0x3b, 0x26, 0x6e, 0x4b, 0x8, 0xe7, 0x75, 0x5, 0x92, 0xb6, 0x3, 0xf8, 0x33, 0x80, 0x91, 0x40, 0xa2, 0xdb, 0xd7, 0x51, 0xe0, 0x3f, 0xe8, 0x38, 0xaf, 0x11, 0xe6, 0x41, 0x90, 0x3f, 0x5d, 0x3b, 0xef, 0xdc, 0x36, 0x9, 0xd0, 0x31, 0x3d, 0x80, 0xc6, 0xcb, 0x75, 0xbf, 0x5, 0xe8, 0x63, 0x60, 0xd8, 0xf1, 0xb3, 0xc0, 0x41, 0x23, 0x34, 0x3f, 0xd1, 0x26, 0xb7, 0xed, 0x92, 0x15, 0xc8, 0xff, 0x7c, 0x74, 0xd7, 0x86, 0x93, 0x7c, 0x1b, 0x26, 0xf5, 0x88, 0x6c, 0x76, 0x24, 0x22, 0x5d, 0xca, 0x83, 0xa0, 0x72, 0x4b, 0x90, 0x82, 0x77, 0xca, 0xe1, 0x8d, 0x4e, 0xfa, 0x47, 0xae, 0xab, 0x19, 0x1b, 0x16, 0x9c, 0x57, 0xd6, 0xb, 0x28, 0xc, 0x91, 0x3, 0x91, 0x80, 0x5e, 0x0, 0x1a, 0xbc, 0x42, 0x7b, 0x53, 0x8f, 0x79, 0xe9, 0xd2, 0x14, 0x49, 0xb1, 0x40, 0xe9, 0xe7, 0x8a, 0x6c, 0x1, 0xbb, 0x4, 0x54, 0x54, 0x81, 0xdd, 0x9, 0xd6, 0xdc, 0x31, 0xe1, 0x7d, 0x1a, 0xe7, 0x49, 0x1f, 0x47, 0x11, 0xb6, 0x80, 0x0, 0x8a, 0x9f, 0x11, 0xf3, 0x2e, 0xf7, 0xed, 0x7, 0x80, 0xb9, 0xad, 0x52, 0xe2, 0x3, 0x31, 0x3d, 0x80, 0x64, 0xf, 0x0, 0xb0, 0x97, 0x37, 0xbf, 0xac, 0xfc, 0xc6, 0x36, 0xde, 0x5b, 0x54, 0xd6, 0x73, 0xb5, 0x69, 0x95, 0x6c, 0xb0, 0x2e, 0xe7, 0x1d, 0x82, 0x1d, 0xee, 0xdb, 0xd7, 0x91, 0x40, 0xf2, 0x3d, 0x1f, 0xaf, 0x3e, 0x46, 0x8b, 0x5b, 0x7d, 0x2e, 0x66, 0x4c, 0xa, 0xa1, 0xb5, 0x29, 0xc1, 0xa2, 0x8, 0xc3, 0xb4, 0xe3, 0x38, 0x4d, 0xd5, 0x94, 0x27, 0x7a, 0x8, 0x10, 0x7a, 0xe6, 0xed, 0xcb, 0xc5, 0x63, 0x55, 0xa5, 0x3d, 0x74, 0xb9, 0xf8, 0x61, 0x2c, 0xf0, 0x75, 0x10, 0x89, 0xbb, 0x73, 0xd7, 0x15, 0xd0, 0x8, 0x84, 0x65, 0x68, 0x51, 0x4d, 0x8, 0xf, 0x6d, 0x49, 0x20, 0x7f, 0x97, 0x1f, 0x2d, 0x53, 0x81, 0x3c, 0x56, 0x29, 0x44, 0x32, 0x0, 0x8d, 0x69, 0x90, 0x6b, 0xbd, 0x1d, 0x2c, 0x3b, 0x60, 0x1a, 0x33, 0xe7, 0xf2, 0x47, 0xf3, 0x6, 0xc0, 0x8f, 0x34, 0x3, 0x10, 0x70, 0x9, 0xbe, 0x2f, 0x69, 0xbf, 0x4, 0x51, 0x9b, 0xaa, 0x56, 0x9c, 0x4c, 0x68, 0x9f, 0xc0, 0x72, 0xe3, 0x15, 0x4b, 0xbe, 0xf3, 0x1a, 0x3, 0x41, 0xf2, 0x4d, 0x48, 0x1f, 0x69, 0x6, 0x10, 0xe0, 0xa, 0xfc, 0xb0, 0xd0, 0xc1, 0x27, 0x6a, 0xfc, 0x8f, 0xc3, 0x1d, 0xc3, 0x69, 0xe5, 0xce, 0x2f, 0xaa, 0xd6, 0x1b, 0x37, 0x46, 0xb, 0xc8, 0xa9, 0x7a, 0x68, 0xd5, 0xfb, 0xc7, 0xa, 0xf8, 0x8c, 0x7e, 0x9f, 0xb, 0x63, 0xc9, 0xef, 0xe5, 0x2f, 0xa2, 0xfb, 0xe8, 0xea, 0x0, 0x7e, 0x3d, 0x73, 0xf5, 0x67, 0xcc, 0x6f, 0x14, 0xc4, 0x31, 0x41, 0x58, 0xbe, 0xaa, 0xe, 0x71, 0xd1, 0x43, 0x0, 0x0, 0x5, 0xd4, 0x8a, 0xcc, 0x3b, 0x1c, 0xa8, 0x88, 0xf7, 0x25, 0xca, 0xcf, 0xf0, 0x4d, 0x78, 0x55, 0x2c, 0x1, 0xe0, 0x0, 0xd0, 0x54, 0x25, 0xcc, 0xec, 0x2e, 0x40, 0xd2, 0x11, 0xb0, 0x77, 0x69, 0x7a, 0x85, 0x9, 0x1c, 0x77, 0xf, 0xd0, 0x3f, 0x5b, 0x43, 0x82, 0x6b, 0xad, 0xad, 0xca, 0xb4, 0x1c, 0xad, 0x5, 0x0, 0x2d, 0x79, 0xcb, 0x5e, 0x39, 0x83, 0x45, 0x2d, 0x4d, 0xb6, 0x90, 0x91, 0x8, 0xf4, 0x21, 0xf9, 0x91, 0x67, 0x0, 0x92, 0xfb, 0xb4, 0x6d, 0xb9, 0x0, 0xdb, 0x78, 0xaf, 0x6c, 0xb5, 0x64, 0x88, 0x1e, 0x2, 0xc8, 0xf, 0x19, 0xd8, 0xaa, 0xb, 0x8e, 0xef, 0x8, 0xfa, 0xe8, 0xfc, 0x26, 0x56, 0x5e, 0x9c, 0x10, 0x8f, 0x94, 0xdd, 0x46, 0xa5, 0x88, 0x9f, 0x7c, 0x63, 0xa6, 0x9f, 0xcf, 0x81, 0x0, 0x1a, 0x13, 0xc1, 0x74, 0xdd, 0x82, 0xf2, 0x7b, 0xa9, 0x28, 0x68, 0x5f, 0xc5, 0x50, 0xac, 0x71, 0x17, 0xf5, 0x94, 0x2c, 0x5a, 0x73, 0xe, 0x66, 0x43, 0x1b, 0x74, 0x55, 0x4, 0x91, 0x42, 0x20, 0x61, 0xde, 0x20, 0xb8, 0x85, 0xe1, 0x15, 0x27, 0x40, 0x91, 0x5c, 0x10, 0xb2, 0x7, 0x15, 0xcb, 0x9, 0xa5, 0x64, 0xc2, 0xe2, 0x97, 0x21, 0x9b, 0xa2, 0xa4, 0x8f, 0xeb, 0x23, 0xcf, 0x0, 0xec, 0x5, 0x20, 0xd8, 0x53, 0x0, 0x28, 0x25, 0xf4, 0x15, 0xc, 0x97, 0x21, 0x9c, 0x7, 0x32, 0x9a, 0x2f, 0x48, 0x12, 0xcc, 0x0, 0xa8, 0xea, 0xd0, 0xa9, 0x18, 0x4b, 0xa0, 0xde, 0x2, 0xd9, 0x82, 0x60, 0xc1, 0x81, 0xc7, 0xb6, 0x8, 0x76, 0x44, 0x60, 0x3b, 0xfc, 0xf9, 0x5a, 0x40, 0x13, 0xeb, 0x68, 0x3, 0xeb, 0xa4, 0x61, 0xf0, 0xd4, 0x5f, 0xed, 0x6b, 0xad, 0x7b, 0x8a, 0x8f, 0x57, 0x26, 0x85, 0x3b, 0x49, 0x7b, 0x3, 0xfa, 0xe6, 0xe0, 0x8b, 0x7f, 0x51, 0xb1, 0x56, 0x17, 0xed, 0x26, 0xe4, 0xa4, 0x1e, 0x4, 0x9d, 0x6f, 0xd3, 0x38, 0xcf, 0x6, 0x3e, 0x5a, 0xde, 0xaf, 0xaf, 0xaf, 0x3, 0x40, 0xfe, 0x8, 0xc7, 0x3c, 0x37, 0x16, 0x34, 0xee, 0x98, 0x6e, 0x20, 0x1c, 0x3f, 0xb0, 0x68, 0x41, 0xa2, 0x31, 0x5, 0x61, 0x1f, 0x45, 0x20, 0x4d, 0x2f, 0x40, 0xa7, 0xe5, 0x10, 0x17, 0x65, 0xd5, 0xcd, 0xbd, 0x63, 0x99, 0x9e, 0x34, 0x7f, 0x43, 0x43, 0xc8, 0xba, 0x97, 0x3, 0x7c, 0x7a, 0xf0, 0x25, 0xf7, 0xfd, 0xf7, 0xe0, 0xa9, 0xf, 0xec, 0xdd, 0xe6, 0x32, 0xc5, 0xbd, 0x18, 0x3c, 0xf5, 0x57, 0xdd, 0x1, 0xf6, 0x85, 0xec, 0x41, 0x20, 0x7a, 0x43, 0x38, 0x4, 0xd0, 0x27, 0x25, 0x7b, 0x24, 0x81, 0x81, 0xf0, 0xe7, 0xa, 0x80, 0xf0, 0x36, 0xaf, 0x35, 0x51, 0xcf, 0x3f, 0xf, 0x32, 0xf5, 0x75, 0xe3, 0xa4, 0x6f, 0x5c, 0x75, 0xf3, 0xbf, 0xb6, 0xf9, 0x4, 0xae, 0xdd, 0x5, 0x86, 0x5c, 0xfa, 0xc0, 0x30, 0x9b, 0x6d, 0xf9, 0xd, 0x80, 0xbd, 0x93, 0x30, 0x2, 0x85, 0xf6, 0xc7, 0x9, 0x6f, 0xba, 0xb9, 0x85, 0x34, 0x2b, 0x5, 0x3e, 0x44, 0x63, 0xee, 0x5c, 0x7d, 0xeb, 0x59, 0x25, 0xf, 0x9f, 0x6a, 0x73, 0x29, 0x86, 0x5d, 0xfe, 0x70, 0xf, 0x6b, 0xdd, 0x7d, 0x65, 0xed, 0x1, 0x34, 0x66, 0x7f, 0x59, 0xdb, 0xb, 0x72, 0xaf, 0x96, 0x6c, 0xff, 0xd6, 0x66, 0xcd, 0x1a, 0x2a, 0x44, 0xbe, 0xe9, 0x38, 0xd, 0x13, 0x56, 0xdd, 0x32, 0xf6, 0x85, 0x24, 0xd2, 0xac, 0x27, 0x18, 0x3c, 0xf5, 0x57, 0x23, 0xe5, 0x66, 0x5e, 0xf4, 0x77, 0x15, 0x49, 0x62, 0x15, 0x7d, 0xab, 0xa3, 0x66, 0x82, 0xd3, 0xc7, 0x4, 0x6c, 0x26, 0xcd, 0xb, 0x34, 0xce, 0x42, 0xc7, 0x98, 0xfb, 0x56, 0xde, 0x3c, 0x36, 0x72, 0x99, 0x78, 0x9b, 0x3d, 0x82, 0x56, 0xce, 0x3d, 0x63, 0x2b, 0xbc, 0x7d, 0x74, 0x5e, 0xb, 0x55, 0x68, 0x20, 0x2d, 0xfa, 0x79, 0x25, 0x49, 0x64, 0xd3, 0x2c, 0x1, 0xe8, 0x63, 0xa5, 0x83, 0x6a, 0xc5, 0x4c, 0xbd, 0xc1, 0xd0, 0xcb, 0x16, 0xef, 0x67, 0x6d, 0x76, 0x9c, 0x3f, 0xcc, 0x55, 0x61, 0x62, 0x8f, 0xd4, 0xc6, 0xb, 0xf4, 0xe8, 0xd0, 0xbe, 0x8c, 0x22, 0xb0, 0x2f, 0xa0, 0x33, 0x61, 0xdd, 0xc1, 0x2e, 0x30, 0x74, 0xf0, 0xd4, 0x7, 0x17, 0xac, 0xbe, 0x75, 0xec, 0xba, 0xe2, 0x4, 0xaa, 0x6e, 0xb9, 0xc3, 0xa6, 0x3f, 0x96, 0x32, 0x34, 0xbf, 0xf7, 0x48, 0xef, 0x2f, 0x45, 0xaa, 0x68, 0xf6, 0x37, 0x34, 0xce, 0xf9, 0xaa, 0x65, 0xde, 0xb1, 0x44, 0x9f, 0x19, 0x7a, 0xd9, 0x83, 0xfb, 0x77, 0x14, 0x71, 0x3a, 0x6, 0x34, 0x0, 0xd6, 0x9d, 0xee, 0xf, 0x94, 0x2c, 0xa8, 0x7b, 0x9b, 0xfc, 0x44, 0x59, 0x6, 0x87, 0x41, 0xfb, 0xcb, 0x9d, 0x5b, 0x24, 0x6f, 0x22, 0x4f, 0x9f, 0x80, 0xec, 0x38, 0x52, 0x7d, 0xa2, 0x4a, 0x55, 0x35, 0x3, 0xac, 0x9c, 0xf3, 0xf9, 0xac, 0x80, 0x17, 0xe0, 0x9f, 0xa3, 0x5a, 0x9d, 0xdc, 0x9f, 0x2f, 0xb7, 0xa7, 0x6d, 0x4, 0x9a, 0x86, 0xbd, 0x40, 0xc2, 0x88, 0xce, 0x26, 0x59, 0x92, 0x20, 0xd9, 0x43, 0x1, 0xec, 0x7, 0x50, 0x85, 0xcb, 0x3b, 0xc2, 0x78, 0xa8, 0x1c, 0x87, 0x28, 0xfe, 0xb6, 0x50, 0xbb, 0xa0, 0xdf, 0xad, 0xbe, 0x4a, 0xe3, 0x6c, 0x8c, 0x2a, 0x57, 0x4d, 0x63, 0xf7, 0x1f, 0x6e, 0x19, 0xfb, 0x2a, 0x8d, 0x79, 0x33, 0x98, 0x32, 0x8e, 0x76, 0x74, 0x8d, 0x9a, 0xf4, 0x88, 0xb3, 0x6d, 0x53, 0x0, 0x5, 0xe9, 0xe3, 0xb2, 0xf6, 0xe4, 0x21, 0x97, 0x2d, 0xee, 0xd9, 0xb9, 0x64, 0x4b, 0x6, 0x6, 0x5f, 0xfa, 0xe0, 0x60, 0x59, 0x4d, 0xf6, 0x55, 0xdd, 0xdc, 0x36, 0x37, 0x49, 0x40, 0xac, 0xd7, 0x40, 0xce, 0x96, 0xf, 0x10, 0xdc, 0xd2, 0xd0, 0xfd, 0x63, 0xaf, 0x47, 0xc5, 0xab, 0x89, 0x1, 0x6, 0x5f, 0x72, 0x9f, 0x1, 0xcc, 0x3, 0x2, 0x32, 0x2, 0x90, 0x53, 0xe5, 0xa, 0x2e, 0x14, 0x75, 0x61, 0xc5, 0x5d, 0x5f, 0x41, 0x78, 0x9e, 0x71, 0xa1, 0xf1, 0xb2, 0xf6, 0xd4, 0xc4, 0xa9, 0xd1, 0x9, 0x40, 0xe0, 0xc, 0xc0, 0x8e, 0xf1, 0x1c, 0xab, 0x0, 0x76, 0xc0, 0x89, 0x68, 0x34, 0x39, 0x5f, 0x3e, 0x90, 0x66, 0x57, 0xf1, 0x9, 0xa6, 0x1, 0xd4, 0xc4, 0x0, 0xd, 0x3d, 0x7a, 0xb, 0x34, 0xf7, 0x4a, 0xc8, 0xfa, 0x54, 0x8c, 0x98, 0x19, 0x2a, 0x35, 0x25, 0x5c, 0x1c, 0xb7, 0x60, 0x37, 0xb0, 0x83, 0x49, 0x9d, 0x3d, 0xe4, 0xd2, 0x87, 0x7a, 0x77, 0x36, 0x1, 0x6b, 0x81, 0x21, 0x97, 0x3e, 0x74, 0x2, 0x64, 0xc7, 0xe6, 0x25, 0xff, 0xf0, 0xa, 0xea, 0xb6, 0xe0, 0xaa, 0x54, 0x58, 0xdc, 0xb7, 0x61, 0x13, 0x2d, 0x77, 0xd1, 0x98, 0x57, 0xe2, 0xca, 0x57, 0x13, 0x3, 0x2c, 0xfb, 0xe9, 0xb1, 0xa2, 0x71, 0x56, 0x80, 0x39, 0x37, 0x2e, 0x86, 0x57, 0xf8, 0xb4, 0x86, 0x52, 0x52, 0x8e, 0xf7, 0x3e, 0xef, 0x2e, 0x45, 0x48, 0x1a, 0x7, 0xe0, 0x92, 0x76, 0xa0, 0x4b, 0x87, 0xc0, 0xb0, 0x69, 0x8f, 0xf4, 0x4, 0xf4, 0x45, 0x49, 0x47, 0x7b, 0x92, 0xbf, 0x9, 0x26, 0x4f, 0x22, 0xf0, 0x11, 0x87, 0xab, 0x52, 0x61, 0xb1, 0xd, 0xcb, 0x77, 0x15, 0x20, 0x40, 0x2e, 0x91, 0x70, 0x7f, 0x5c, 0x19, 0x6b, 0xd6, 0xdf, 0x57, 0xcd, 0x3d, 0x7d, 0xab, 0x31, 0xce, 0x8b, 0x20, 0x4b, 0xc, 0x3, 0x95, 0x76, 0x5f, 0x26, 0x30, 0x3e, 0x76, 0x87, 0xec, 0x85, 0x43, 0x2e, 0x7d, 0x68, 0x6c, 0x47, 0x10, 0x2c, 0x69, 0x90, 0xb5, 0x57, 0x49, 0xf6, 0xdc, 0xd0, 0xce, 0x1d, 0x55, 0xe2, 0x4, 0x95, 0xc6, 0xb, 0xe5, 0x65, 0x56, 0xff, 0xe1, 0x96, 0x33, 0x63, 0xd7, 0x59, 0x24, 0x62, 0xc0, 0x31, 0x4e, 0xea, 0x1a, 0x0, 0x9b, 0xdb, 0xd2, 0xc9, 0xc7, 0x89, 0x7f, 0x45, 0xcf, 0x7e, 0x55, 0x68, 0x25, 0xdb, 0x1f, 0xd0, 0x15, 0xc3, 0xa7, 0x3f, 0xba, 0x17, 0x76, 0x23, 0x18, 0x7a, 0xf9, 0xc3, 0x17, 0xc9, 0xba, 0x97, 0x90, 0xec, 0xe6, 0x1f, 0x22, 0xdb, 0xca, 0x15, 0x24, 0xa, 0x3f, 0xa5, 0xde, 0xb0, 0x8d, 0xf1, 0x82, 0x85, 0x96, 0xfe, 0x53, 0xc9, 0x35, 0x16, 0xc9, 0x30, 0x80, 0x49, 0xfd, 0x15, 0x60, 0x16, 0x2c, 0xa7, 0xb4, 0xb4, 0x56, 0x78, 0xe2, 0x9e, 0x7d, 0x7f, 0x44, 0x43, 0x1a, 0x40, 0xfa, 0xbc, 0xeb, 0x66, 0xef, 0x4e, 0x88, 0x36, 0xed, 0xe, 0xc3, 0xa6, 0x3d, 0x72, 0x34, 0x64, 0xaf, 0x4, 0xd1, 0x97, 0x9e, 0xda, 0xc7, 0xb0, 0x7a, 0x86, 0x12, 0xf8, 0x29, 0x3b, 0x61, 0x56, 0x3e, 0x9e, 0x48, 0xe3, 0xef, 0x4b, 0x65, 0x5e, 0x26, 0xcd, 0xba, 0x52, 0x65, 0xad, 0x99, 0x1, 0x86, 0x5f, 0xf1, 0x44, 0xca, 0x75, 0x33, 0x17, 0x93, 0xdc, 0xb3, 0x60, 0x82, 0xa3, 0xc6, 0x8b, 0x86, 0x14, 0x4, 0x1a, 0x7a, 0x9b, 0x2b, 0xc9, 0x9e, 0x36, 0xf4, 0xf2, 0xc5, 0x8b, 0x3b, 0x9b, 0xb8, 0xe5, 0x60, 0xd8, 0xb4, 0x47, 0x87, 0x59, 0xd7, 0x9d, 0x2b, 0xd9, 0x91, 0xb9, 0x63, 0x71, 0x88, 0xa, 0x8d, 0x64, 0x85, 0x97, 0x2, 0xa5, 0x2e, 0x3e, 0x9d, 0x70, 0x78, 0x4e, 0x93, 0x22, 0x9d, 0x7b, 0xff, 0x70, 0xf3, 0xbf, 0xfe, 0xb2, 0x54, 0x79, 0x6b, 0x62, 0x80, 0x61, 0x57, 0x3c, 0x9e, 0x92, 0xcd, 0x5c, 0x27, 0xeb, 0xde, 0x0, 0xa0, 0x67, 0xc1, 0x92, 0xe4, 0x4, 0x2e, 0x7f, 0xdf, 0x3b, 0xfa, 0x27, 0x8c, 0xc1, 0xba, 0xf6, 0xb3, 0x43, 0x2e, 0x5b, 0x7c, 0x7f, 0x65, 0xa5, 0xec, 0x38, 0x18, 0x7a, 0xf9, 0xa3, 0x43, 0x25, 0xf7, 0x2e, 0x40, 0x47, 0xfa, 0x36, 0xd, 0x86, 0x7e, 0x6b, 0xc1, 0x3, 0xbd, 0x65, 0xfe, 0x8, 0x7e, 0xc3, 0x57, 0xee, 0x14, 0x94, 0xf0, 0x5, 0xc0, 0xa5, 0xe1, 0xdf, 0xca, 0x95, 0xb9, 0x6a, 0x6, 0x18, 0x7a, 0xf9, 0xa3, 0xd, 0x72, 0x33, 0xdf, 0xb3, 0xae, 0xfb, 0xdf, 0x0, 0xd3, 0x5e, 0x68, 0xb4, 0x64, 0x5f, 0x9d, 0x2a, 0xd3, 0x3a, 0xdc, 0x18, 0xa6, 0x21, 0x9d, 0x39, 0xe4, 0xd2, 0x87, 0x7e, 0x3b, 0xf4, 0xf2, 0x47, 0x92, 0xde, 0x95, 0xac, 0x26, 0x18, 0x36, 0xed, 0xb1, 0x93, 0xad, 0xcd, 0x3c, 0x28, 0xab, 0xc3, 0xa, 0xd7, 0x52, 0x94, 0xd2, 0x7a, 0xe2, 0x70, 0x81, 0xd6, 0x71, 0xf3, 0x9a, 0xdd, 0x2e, 0x92, 0x1b, 0x40, 0xf3, 0xa6, 0x84, 0x5d, 0xa, 0xb6, 0x53, 0x4, 0x43, 0x62, 0x86, 0x27, 0xfc, 0x9, 0x6c, 0x75, 0x68, 0x67, 0x31, 0x54, 0xc5, 0x0, 0xc3, 0xaf, 0x78, 0xbc, 0x1b, 0xa0, 0x1f, 0x59, 0x6b, 0xaf, 0x3, 0xe1, 0xd0, 0x10, 0xc1, 0x21, 0xc7, 0x85, 0x2b, 0xc7, 0xa2, 0x18, 0x9f, 0x45, 0xe1, 0xcc, 0x8b, 0x2b, 0x5, 0x78, 0x8, 0xb8, 0x9f, 0xa1, 0x74, 0x9, 0x10, 0x46, 0xd0, 0xd1, 0xd6, 0xba, 0x2f, 0xf, 0xb9, 0xfc, 0x91, 0xe3, 0x3a, 0x8c, 0xc2, 0x25, 0x60, 0xc8, 0x65, 0xf, 0xff, 0xa7, 0xb5, 0xd9, 0x45, 0x24, 0xf, 0xa, 0xd4, 0x6f, 0x1a, 0xe3, 0xf9, 0x39, 0x17, 0x8a, 0x3f, 0x85, 0xf5, 0x46, 0xc, 0x2e, 0xa, 0xf1, 0x26, 0x3f, 0x2e, 0x7d, 0x7c, 0xac, 0x5c, 0x75, 0xf3, 0x99, 0x3, 0x8d, 0x93, 0xfe, 0x94, 0x49, 0x35, 0xee, 0x63, 0x52, 0x4d, 0x4d, 0x26, 0x95, 0xee, 0x63, 0x9c, 0xf4, 0x20, 0x3a, 0xe9, 0xd1, 0x74, 0xd2, 0x67, 0xd1, 0x38, 0x5f, 0xa6, 0x71, 0xbe, 0x44, 0xf0, 0xd9, 0x72, 0x65, 0x2f, 0x27, 0xb8, 0x47, 0x10, 0xff, 0xd7, 0x7b, 0xca, 0xda, 0xaf, 0x4a, 0xf6, 0x3b, 0x8, 0x56, 0xa3, 0xb0, 0xd2, 0x95, 0xae, 0x55, 0x2d, 0x8c, 0xf5, 0xd8, 0x5b, 0x62, 0xc8, 0xb9, 0x70, 0x2b, 0x68, 0x1e, 0x4b, 0x77, 0xdb, 0xe7, 0xbc, 0x17, 0x67, 0x1c, 0xd3, 0xe1, 0x9b, 0x48, 0xe, 0xbf, 0xe2, 0x89, 0x46, 0xeb, 0x66, 0xd6, 0xca, 0xba, 0x7, 0x91, 0xdc, 0x23, 0x98, 0x92, 0x87, 0xc4, 0x44, 0x71, 0x12, 0x78, 0xe8, 0x92, 0xab, 0x40, 0xe7, 0xe4, 0x95, 0x73, 0x3e, 0xf7, 0x7e, 0x71, 0x94, 0xa3, 0xbe, 0xf2, 0x5b, 0xb6, 0x6c, 0x7b, 0x97, 0x4e, 0xba, 0x81, 0xb2, 0xd6, 0x48, 0xd6, 0x5d, 0x35, 0xf7, 0x8c, 0xb2, 0x47, 0xcc, 0x54, 0x44, 0x85, 0xa1, 0xd3, 0x1e, 0xed, 0xe, 0x60, 0x32, 0xac, 0x9d, 0x5, 0xf8, 0x67, 0xff, 0xa1, 0xe3, 0xf, 0x8c, 0x40, 0xe1, 0x3c, 0x78, 0xb, 0xc8, 0xb7, 0x4, 0xde, 0xea, 0x66, 0xb3, 0xd7, 0xaf, 0xb9, 0xf5, 0xcc, 0x4c, 0xd, 0x59, 0xb4, 0x9, 0x86, 0x5c, 0xfe, 0x48, 0x9a, 0xc0, 0x22, 0x12, 0x47, 0xc9, 0xda, 0xdc, 0x2c, 0x1b, 0x2b, 0x26, 0x7a, 0x25, 0x55, 0x46, 0x56, 0xe0, 0x5d, 0xab, 0xe6, 0x9e, 0x3e, 0x25, 0xc9, 0xba, 0x54, 0x54, 0xd8, 0x61, 0xd3, 0x1e, 0x3b, 0x49, 0x72, 0x7f, 0xe3, 0x89, 0xb5, 0x1e, 0x9b, 0xb7, 0x4a, 0x2d, 0xee, 0xec, 0x87, 0x70, 0xcc, 0xb8, 0xc5, 0x23, 0x2c, 0x8a, 0xab, 0xc8, 0x38, 0x91, 0xa7, 0x83, 0x49, 0xda, 0x4a, 0x9a, 0xd7, 0x40, 0x2e, 0x2, 0xcc, 0x4f, 0x56, 0xce, 0xf9, 0x6c, 0xe2, 0x1e, 0x45, 0xc3, 0xaf, 0x78, 0x7c, 0xa8, 0xb5, 0xee, 0xb5, 0xde, 0xde, 0x48, 0x3a, 0x88, 0xa4, 0xbf, 0x3f, 0x62, 0x20, 0xaa, 0x7b, 0xc7, 0x27, 0xb6, 0xaa, 0x53, 0xb8, 0x2e, 0x51, 0x38, 0x2a, 0xf6, 0xa4, 0x2e, 0xc4, 0x97, 0xbf, 0xf, 0x3, 0x9f, 0x4d, 0x35, 0x34, 0x7d, 0x6e, 0xd9, 0xcf, 0x4e, 0x4a, 0xf4, 0xc8, 0x98, 0x8a, 0xe, 0x8d, 0x12, 0xf0, 0x16, 0xc0, 0x55, 0x20, 0x86, 0x12, 0x85, 0x47, 0xb7, 0x14, 0x54, 0xa8, 0x18, 0xca, 0x59, 0x7f, 0xc2, 0x61, 0x2c, 0xfb, 0x5d, 0x1e, 0xb5, 0xb9, 0x19, 0x70, 0x89, 0x64, 0xf, 0xc9, 0xe, 0x84, 0x78, 0x10, 0xa9, 0xb, 0x87, 0x4e, 0x7b, 0x74, 0x29, 0xc0, 0xc5, 0x0, 0x9f, 0x58, 0x75, 0xd3, 0xe7, 0x3e, 0xac, 0x16, 0x41, 0x43, 0xa7, 0x3d, 0x76, 0x24, 0x81, 0x33, 0x41, 0x9c, 0x62, 0xdd, 0xec, 0x27, 0x1, 0xf4, 0x26, 0xd1, 0xe4, 0x17, 0x26, 0xe7, 0xa, 0x17, 0xb9, 0x8c, 0x92, 0x6d, 0xb8, 0x8f, 0x7f, 0xe, 0xed, 0xba, 0xc2, 0xd7, 0x68, 0xcc, 0x6d, 0x49, 0x13, 0x3f, 0x8e, 0x14, 0x25, 0x61, 0xd8, 0xf4, 0x5f, 0x9f, 0x2e, 0xeb, 0x3e, 0xc, 0x44, 0xad, 0x70, 0xed, 0x70, 0x28, 0x68, 0x57, 0xa1, 0x1d, 0x4b, 0x20, 0xa9, 0x19, 0xe4, 0x3f, 0x0, 0xbc, 0xb, 0xe0, 0x6d, 0x80, 0x7f, 0x34, 0xc6, 0xbc, 0x28, 0x61, 0x83, 0x64, 0x37, 0x1b, 0x63, 0xb6, 0x9, 0xcc, 0x2, 0x70, 0x8d, 0x31, 0x8e, 0x9b, 0xcd, 0x34, 0x2, 0xec, 0x66, 0xc, 0xf, 0x4, 0x74, 0x8c, 0xb5, 0x3a, 0xe, 0xd0, 0x1, 0x0, 0x7a, 0xc8, 0xda, 0xde, 0x24, 0xf7, 0xcb, 0x21, 0x2d, 0x7c, 0x42, 0xa, 0xa, 0xfb, 0xe9, 0x44, 0x2a, 0x15, 0x4a, 0x4f, 0x92, 0x5, 0xcd, 0x8d, 0x3d, 0xf7, 0xeb, 0x73, 0xd5, 0x33, 0xd7, 0xf, 0x4e, 0x5c, 0xce, 0xa9, 0xf8, 0xec, 0x60, 0x9, 0x2b, 0x40, 0xf3, 0x2, 0xa0, 0xe3, 0x2, 0x4f, 0x9e, 0xf0, 0x69, 0xd1, 0xed, 0xf, 0x5, 0x63, 0x49, 0xee, 0xc1, 0x3b, 0x69, 0x3b, 0x68, 0x3a, 0x10, 0xd, 0x1b, 0x25, 0x1c, 0x2, 0xe0, 0x10, 0x3f, 0xc6, 0x9, 0x92, 0x1d, 0x27, 0xe1, 0x7d, 0x48, 0xcd, 0x90, 0xcd, 0x10, 0xb4, 0x0, 0xe4, 0x66, 0xb2, 0x24, 0xe9, 0x0, 0x4a, 0x59, 0xab, 0xee, 0x80, 0xf6, 0x7, 0x90, 0xf3, 0x48, 0xa, 0x16, 0xc9, 0xf8, 0xe, 0xd1, 0x2c, 0x76, 0xe7, 0xab, 0x9c, 0xf8, 0xc5, 0xe3, 0x40, 0x1, 0x7e, 0x45, 0x43, 0x4a, 0xb0, 0x0, 0xc, 0x69, 0x9e, 0x14, 0xf9, 0x83, 0xf6, 0x20, 0x3e, 0x50, 0x5, 0x3, 0x90, 0x7c, 0x17, 0xe4, 0x77, 0x64, 0xdd, 0x27, 0xdb, 0xeb, 0xb8, 0xb4, 0xa, 0x4a, 0x13, 0x2a, 0x57, 0x48, 0x81, 0x24, 0xc2, 0x4e, 0x97, 0xc1, 0x88, 0xda, 0x1d, 0x40, 0x5f, 0x40, 0x7d, 0xc1, 0x9c, 0x4a, 0x91, 0x4b, 0x26, 0x70, 0x79, 0xf, 0x8c, 0x6e, 0xc8, 0x7f, 0x9b, 0xcb, 0x28, 0xbf, 0x59, 0x46, 0xb2, 0x65, 0x2f, 0xc4, 0x6f, 0xee, 0x5c, 0x24, 0x43, 0x72, 0x9, 0x8d, 0xf3, 0x5f, 0x2b, 0x67, 0x9f, 0x5a, 0xd6, 0xa0, 0x53, 0x2d, 0x54, 0xdc, 0x85, 0xaf, 0x9c, 0xf3, 0x59, 0x57, 0x56, 0xcf, 0x1, 0xe6, 0x7, 0xcc, 0x4f, 0x3b, 0x29, 0xce, 0xae, 0xf, 0xc4, 0xdb, 0xb2, 0x11, 0x11, 0x16, 0xf5, 0x1e, 0x31, 0xdf, 0x44, 0x7d, 0xe7, 0x3f, 0x33, 0x58, 0x72, 0xe, 0x7f, 0x5b, 0x4e, 0x7f, 0x7e, 0x1, 0x86, 0x6, 0x86, 0x26, 0xbf, 0xb6, 0xda, 0xf, 0xf3, 0xe6, 0x1c, 0x20, 0xd2, 0x0, 0xfe, 0x7d, 0xb1, 0x52, 0x5e, 0x6c, 0xcf, 0x47, 0x4c, 0x19, 0x4b, 0xc5, 0x61, 0x89, 0xfa, 0x86, 0x5d, 0xb9, 0xe8, 0x19, 0x73, 0x1e, 0x58, 0x31, 0xfb, 0xd4, 0x76, 0xf5, 0x8e, 0xae, 0x6a, 0xc, 0x5f, 0x75, 0xd3, 0xe7, 0x32, 0xc6, 0x71, 0x66, 0xd0, 0x98, 0x3f, 0x7a, 0x1e, 0x81, 0xf0, 0x14, 0x83, 0xbc, 0xcd, 0x1a, 0xa0, 0x77, 0x94, 0x27, 0x3, 0x79, 0x3d, 0xf8, 0xf1, 0xc3, 0xe4, 0x1b, 0x11, 0x7c, 0xbb, 0x49, 0x7e, 0x4d, 0x8, 0xb, 0xc3, 0xa, 0xec, 0x61, 0x21, 0x3b, 0x49, 0x2e, 0x6e, 0x48, 0x78, 0x6c, 0x65, 0x53, 0x2a, 0x8e, 0x1b, 0x32, 0x52, 0x79, 0xc6, 0x2b, 0x22, 0xbc, 0xcd, 0xa1, 0x77, 0xa, 0x8b, 0x1f, 0x25, 0x7c, 0x5f, 0x9c, 0x6f, 0x51, 0x18, 0x23, 0xca, 0x15, 0x67, 0xe3, 0x29, 0x28, 0x77, 0x44, 0x1d, 0xa, 0x3b, 0x6, 0x56, 0xdc, 0x43, 0x77, 0x8, 0x3, 0x0, 0xc0, 0x8a, 0xd9, 0xa7, 0xbc, 0x9, 0x98, 0x6f, 0x48, 0xb0, 0xc1, 0x4a, 0x97, 0x90, 0xcd, 0x3a, 0xa8, 0x72, 0x40, 0x71, 0xff, 0x40, 0x54, 0x13, 0xd8, 0xaa, 0x3d, 0xd3, 0x5e, 0xb0, 0xb5, 0x1d, 0x22, 0x30, 0x57, 0x80, 0xc5, 0x8, 0xec, 0xc6, 0xc5, 0x47, 0x1b, 0xe2, 0x17, 0x7f, 0xc7, 0x32, 0xf9, 0x97, 0xcb, 0xaf, 0x5c, 0x1e, 0x95, 0x94, 0xc5, 0xbb, 0xf7, 0x27, 0xc0, 0x34, 0x61, 0xd8, 0x15, 0x4f, 0x8c, 0xa9, 0x4b, 0x6, 0x0, 0x80, 0x15, 0x37, 0x9e, 0xf2, 0x2b, 0x81, 0x73, 0xfd, 0x59, 0x89, 0xe0, 0xbc, 0xdb, 0x9c, 0xdf, 0xa3, 0x1f, 0x6, 0x1, 0xaf, 0xd0, 0x38, 0xf3, 0x40, 0xf3, 0x3d, 0x90, 0x8f, 0xa3, 0x50, 0x4b, 0x66, 0x72, 0x3e, 0x92, 0x9d, 0x24, 0x8a, 0x24, 0x8, 0x61, 0x1c, 0x2, 0x1a, 0xe, 0x60, 0xca, 0x51, 0x57, 0x3d, 0x9d, 0x6e, 0xaf, 0xfc, 0x6a, 0x56, 0xe3, 0x68, 0x9c, 0xaf, 0xd2, 0x38, 0xbf, 0x1, 0xe8, 0x2, 0xc, 0x66, 0xa5, 0x8, 0xf0, 0x3, 0x81, 0x4f, 0x1, 0x9c, 0x4d, 0x9a, 0xff, 0x30, 0xc6, 0x4c, 0x5f, 0x31, 0xfb, 0x94, 0x6f, 0x3, 0xe6, 0x6b, 0xa0, 0xf9, 0x6d, 0x28, 0xae, 0xef, 0x27, 0x17, 0xb5, 0x6d, 0x5a, 0xa5, 0x17, 0x6a, 0xfc, 0xbe, 0xf3, 0x2f, 0x7f, 0xd2, 0x43, 0x79, 0xbc, 0x68, 0x8c, 0x9b, 0x75, 0xcf, 0x6b, 0x2f, 0x6, 0x48, 0xa4, 0xc9, 0x8c, 0xb8, 0xf2, 0xa9, 0x23, 0x24, 0xfb, 0x6b, 0x49, 0x69, 0x49, 0x1b, 0xc, 0xb9, 0x95, 0xc6, 0xac, 0x0, 0x78, 0xf3, 0xf2, 0x59, 0x27, 0xbd, 0x19, 0x11, 0xff, 0x13, 0xd6, 0xba, 0xf3, 0x25, 0x9d, 0x60, 0x72, 0xaa, 0x5b, 0xe8, 0xa0, 0xe4, 0x92, 0xc5, 0x6d, 0x4b, 0x6f, 0xd1, 0xd6, 0x78, 0x51, 0x71, 0xc3, 0xcf, 0x95, 0xa4, 0x53, 0xd, 0x4, 0x55, 0x8d, 0xcd, 0x43, 0x5e, 0x2f, 0xca, 0x47, 0x68, 0xcc, 0xf8, 0x95, 0xb3, 0x4f, 0x2e, 0x77, 0xa, 0x7a, 0xd5, 0x25, 0xa8, 0x19, 0x46, 0x5c, 0xf9, 0xd4, 0xf5, 0x92, 0x5e, 0x7, 0x39, 0x6f, 0xc5, 0xac, 0x93, 0xca, 0x6e, 0xf5, 0x3a, 0xfc, 0x4b, 0x4f, 0x35, 0x42, 0xf6, 0x69, 0x41, 0xc7, 0x78, 0x2, 0x1e, 0x73, 0x15, 0x66, 0x58, 0xa7, 0x8b, 0x41, 0x51, 0x78, 0xc, 0x29, 0x45, 0x22, 0x96, 0xf9, 0xbe, 0x38, 0x4e, 0x71, 0xfc, 0x28, 0x4, 0x29, 0x26, 0x8d, 0xf6, 0x60, 0x15, 0x7f, 0x78, 0x7c, 0x97, 0x34, 0x3f, 0x58, 0x31, 0xfb, 0xe4, 0x1f, 0x26, 0x9d, 0x7e, 0xa7, 0xe, 0x9a, 0x23, 0xaf, 0x59, 0x4a, 0xb7, 0x65, 0xfb, 0xe3, 0x24, 0x8e, 0x6, 0xd0, 0xc3, 0xdb, 0x3c, 0x23, 0xd8, 0x87, 0x24, 0x8a, 0x5, 0x18, 0xf1, 0x5c, 0xe9, 0xe4, 0x43, 0x5c, 0xba, 0xa5, 0x58, 0x24, 0xa, 0x65, 0xc5, 0xdf, 0x95, 0xcb, 0x2f, 0xae, 0x4c, 0x8c, 0xf9, 0x46, 0xc1, 0x7a, 0x4b, 0xff, 0xe0, 0x68, 0x3e, 0x63, 0x85, 0xcf, 0xaf, 0xba, 0xf1, 0x94, 0x44, 0xcd, 0xc1, 0x9d, 0x6a, 0xca, 0x5d, 0xf6, 0xd3, 0x63, 0xb5, 0xf2, 0xc6, 0x53, 0x4f, 0x25, 0x53, 0xb7, 0x4a, 0x7c, 0xc3, 0x57, 0xd5, 0x19, 0xbd, 0xce, 0x90, 0x31, 0xcf, 0x61, 0x4d, 0xa1, 0x54, 0xdc, 0x8, 0xbd, 0x32, 0x36, 0x9d, 0xb8, 0x30, 0x96, 0xf8, 0xae, 0x5c, 0x7e, 0x71, 0x71, 0xe2, 0xbe, 0xf1, 0xe4, 0xe3, 0x90, 0x6e, 0x3b, 0x84, 0xe4, 0xb7, 0x92, 0xa6, 0x41, 0x67, 0xdb, 0xf2, 0x1, 0x0, 0xcb, 0x67, 0x8d, 0xb9, 0x16, 0x34, 0xd7, 0x4a, 0x58, 0xf, 0xef, 0x4, 0x92, 0x28, 0x4a, 0xed, 0x56, 0x57, 0xb0, 0xb7, 0x72, 0xb9, 0xb0, 0x52, 0xdf, 0x6, 0x2e, 0x71, 0x7e, 0xf8, 0x36, 0x0, 0x1f, 0x24, 0x8d, 0xfb, 0xba, 0xd2, 0x9b, 0x86, 0x7f, 0xe9, 0xe9, 0xde, 0xa0, 0x1e, 0x25, 0x30, 0x24, 0x5f, 0xbc, 0xb8, 0x3d, 0x74, 0x6b, 0x19, 0x71, 0x4b, 0xa5, 0xd1, 0x16, 0xa9, 0x22, 0x4e, 0x7a, 0xc8, 0x7d, 0x17, 0xac, 0x95, 0xf4, 0x67, 0x2d, 0x73, 0x5d, 0x9b, 0xef, 0xc9, 0x62, 0x5b, 0x4f, 0xa5, 0x7, 0xdd, 0xbe, 0xb7, 0x4b, 0x46, 0xfe, 0x5b, 0x0, 0x92, 0x5e, 0x27, 0xf9, 0xff, 0x56, 0xcc, 0x3e, 0x69, 0x66, 0xd2, 0x38, 0x6f, 0x77, 0x4b, 0x53, 0x25, 0x60, 0xc, 0xcf, 0x12, 0xb0, 0x7f, 0xa1, 0x46, 0x10, 0xc7, 0xa3, 0x49, 0xf0, 0x6e, 0xb5, 0x69, 0xb3, 0xd5, 0x73, 0x89, 0x19, 0x41, 0x17, 0x40, 0xd6, 0x6f, 0xdc, 0x8d, 0x3e, 0x81, 0x63, 0x36, 0x88, 0x28, 0xdc, 0x37, 0xc0, 0x8f, 0xf3, 0xf, 0xc7, 0x38, 0xd7, 0x2f, 0xfb, 0xd9, 0x89, 0xb3, 0xd1, 0xe, 0x50, 0x17, 0x43, 0x40, 0x0, 0x56, 0x9a, 0x2, 0xb0, 0x4f, 0xcc, 0xa0, 0x19, 0x46, 0x54, 0x95, 0x57, 0xf8, 0xfb, 0xa8, 0xb4, 0xa2, 0xde, 0x17, 0x43, 0x41, 0x9a, 0xf2, 0xaf, 0x90, 0x15, 0x34, 0x6c, 0x14, 0x33, 0x24, 0xcd, 0x12, 0x63, 0x9c, 0x13, 0x49, 0x73, 0xa9, 0xf2, 0x7b, 0x39, 0xd2, 0x5b, 0xff, 0x58, 0xd0, 0xe5, 0xe7, 0xbc, 0x87, 0x83, 0xd6, 0xef, 0xf9, 0xf4, 0xf3, 0xb2, 0xf6, 0x22, 0x3e, 0x50, 0x6f, 0x3d, 0x0, 0xb9, 0xb7, 0x7f, 0xab, 0xe8, 0xa6, 0x5f, 0x6b, 0xab, 0x2f, 0x47, 0xe4, 0x36, 0x30, 0x41, 0x99, 0x11, 0x42, 0xc1, 0xc6, 0xf7, 0xc4, 0x12, 0x49, 0xff, 0x43, 0xf2, 0xe9, 0x65, 0x33, 0x47, 0x67, 0x0, 0xfc, 0x6e, 0xe4, 0x55, 0xcf, 0xbe, 0x2d, 0x6b, 0x7f, 0x9, 0x61, 0xcf, 0x12, 0xbe, 0x23, 0x16, 0xa0, 0x1, 0xf9, 0x24, 0xc9, 0x6f, 0x2e, 0x9b, 0x39, 0x7a, 0x59, 0x72, 0x18, 0x6e, 0xd, 0x75, 0xd3, 0x3, 0xc, 0xbf, 0xf2, 0x99, 0x43, 0xad, 0xd4, 0xd8, 0x7a, 0x7d, 0x21, 0x4a, 0x48, 0xe2, 0x40, 0xbc, 0x74, 0x8f, 0x98, 0x6f, 0xa3, 0x24, 0x7d, 0xc4, 0xe4, 0x17, 0x91, 0x6, 0x10, 0x78, 0xfb, 0x22, 0x98, 0xb4, 0xb, 0xc9, 0x76, 0xa4, 0x31, 0xf, 0xd2, 0x38, 0xa3, 0x40, 0xf3, 0x79, 0x3a, 0xd, 0x4f, 0x2c, 0xff, 0xd9, 0x89, 0x39, 0x1f, 0xc5, 0x65, 0x33, 0x47, 0x3f, 0xe, 0x9a, 0xa1, 0x2, 0x7e, 0xed, 0x37, 0x79, 0x81, 0x94, 0x37, 0xc9, 0xc8, 0x60, 0x1, 0x89, 0x1, 0x79, 0x9b, 0x80, 0x69, 0xed, 0x4d, 0x7c, 0xa0, 0x9e, 0x7a, 0x0, 0xa2, 0x1f, 0xc1, 0xc6, 0xdc, 0x53, 0x4e, 0xb2, 0x2a, 0xd7, 0x52, 0x5b, 0x79, 0xd0, 0xf8, 0xdd, 0x27, 0x83, 0x77, 0x88, 0x77, 0x57, 0x60, 0x44, 0x7a, 0xe5, 0x7b, 0x89, 0xfc, 0x9c, 0x7d, 0xe0, 0xe, 0x61, 0xfe, 0xa, 0x70, 0x11, 0xa8, 0x5b, 0x1, 0xbc, 0xe, 0x68, 0xe7, 0xf2, 0x99, 0xa3, 0x23, 0x3d, 0x72, 0x97, 0xff, 0x6c, 0xf4, 0x9f, 0x47, 0x5c, 0xf5, 0xec, 0x64, 0x8, 0x93, 0x24, 0x3b, 0x23, 0xa8, 0x82, 0xef, 0xdc, 0x42, 0x80, 0x5f, 0x3, 0x79, 0xc7, 0x8a, 0x99, 0x27, 0xbc, 0xd7, 0x11, 0x68, 0xaf, 0x1f, 0x6, 0x0, 0x8e, 0x5, 0xd8, 0xc3, 0xf7, 0xc9, 0xa8, 0xc8, 0xc9, 0xc4, 0x9f, 0x7d, 0xa, 0x3c, 0x68, 0x2, 0x46, 0x0, 0x80, 0xd0, 0x92, 0x6c, 0x0, 0x21, 0x71, 0xbd, 0x48, 0x66, 0xab, 0xc6, 0x9b, 0x97, 0x0, 0xb2, 0x20, 0x7, 0x81, 0xdc, 0x22, 0x69, 0xeb, 0xf2, 0x99, 0xa3, 0xdb, 0xe4, 0x88, 0xba, 0x7c, 0xe6, 0xe8, 0x77, 0x46, 0x5e, 0xbd, 0x64, 0x2e, 0xc4, 0xc5, 0x90, 0x9e, 0x5, 0x70, 0xa0, 0xa4, 0x77, 0x40, 0x4e, 0x4, 0xf4, 0xc2, 0xa, 0x6f, 0xc8, 0xe8, 0x10, 0xa8, 0x1b, 0x35, 0x70, 0xf8, 0x97, 0x9f, 0x7d, 0x9e, 0xc4, 0x31, 0xbe, 0x27, 0x47, 0x5b, 0x9, 0x92, 0xd7, 0xbb, 0x3c, 0xcf, 0xd9, 0xdb, 0x1, 0x2c, 0x5, 0x70, 0x32, 0xa0, 0xb3, 0x51, 0x62, 0xdb, 0xd9, 0x90, 0xb7, 0x50, 0x45, 0x6e, 0xed, 0x45, 0xbd, 0x4d, 0x66, 0xf9, 0xcc, 0xd1, 0xd, 0x6d, 0xfa, 0x30, 0x6, 0x46, 0x5e, 0xbd, 0xe4, 0x50, 0x49, 0xc3, 0x0, 0xac, 0x5f, 0x3e, 0xf3, 0x84, 0xd, 0xed, 0x89, 0xe3, 0x48, 0x3c, 0x74, 0x74, 0x86, 0x71, 0x30, 0xe2, 0xaa, 0xe7, 0xde, 0x2, 0xd0, 0x2b, 0xbc, 0xdf, 0x50, 0x29, 0xa2, 0x14, 0xbf, 0x97, 0xf4, 0x17, 0x80, 0x13, 0x1, 0xac, 0xa1, 0x77, 0x9e, 0x71, 0x2f, 0x0, 0x7b, 0x4a, 0x6a, 0x80, 0x77, 0xbc, 0x7d, 0xf, 0x0, 0x9f, 0x2, 0xd4, 0x17, 0xc0, 0xbe, 0x0, 0x3e, 0x9, 0x78, 0x1b, 0x51, 0x55, 0xea, 0xcf, 0x1f, 0xc, 0x33, 0x92, 0x32, 0xa4, 0xe9, 0xb6, 0x7c, 0xe6, 0xf1, 0xd9, 0xb6, 0x7e, 0x1b, 0x5, 0x47, 0x7f, 0x65, 0x69, 0xea, 0xf7, 0x33, 0x8e, 0xad, 0x29, 0x8d, 0x6a, 0xa1, 0x6e, 0x86, 0x0, 0x82, 0x3f, 0x17, 0xf4, 0x15, 0xf9, 0xb, 0xa1, 0x3c, 0xbf, 0x48, 0x8f, 0x28, 0x11, 0x94, 0xf1, 0x37, 0x44, 0xf4, 0x5, 0x32, 0x6f, 0x14, 0xb8, 0xce, 0xcd, 0xba, 0x7f, 0x58, 0x39, 0xfb, 0x44, 0xb, 0x60, 0x93, 0x7f, 0xe5, 0x60, 0xc4, 0xd5, 0x2f, 0x90, 0xb0, 0x3d, 0x0, 0xee, 0x9, 0x8f, 0x21, 0xfa, 0xc8, 0x6a, 0x89, 0x31, 0x74, 0x0, 0x6f, 0x71, 0x65, 0x5, 0x83, 0x8e, 0x7f, 0xca, 0x6d, 0x32, 0xde, 0x81, 0x9d, 0x45, 0x7c, 0xa0, 0x8e, 0x18, 0x40, 0xc0, 0x8f, 0x48, 0xb3, 0x44, 0xb2, 0x97, 0x82, 0x3c, 0x2d, 0x24, 0x4, 0x14, 0xf4, 0xba, 0x7e, 0x80, 0xbf, 0xf, 0x1e, 0x20, 0x6b, 0x9, 0xe0, 0xfb, 0x12, 0x1f, 0xf5, 0x89, 0x1f, 0x9, 0xcb, 0x6f, 0x38, 0x4e, 0x0, 0xb6, 0xf8, 0x17, 0x46, 0x5c, 0xb5, 0xe4, 0x75, 0x92, 0xbf, 0x15, 0x70, 0x1c, 0x80, 0x22, 0x51, 0xa1, 0x75, 0xe1, 0x42, 0x5c, 0xa8, 0xd0, 0x9e, 0x8c, 0xdb, 0xea, 0xa8, 0x13, 0xad, 0xa, 0xea, 0x46, 0xd, 0x5c, 0x3e, 0xf3, 0xf8, 0xd7, 0x97, 0xdd, 0x30, 0xea, 0x3e, 0x80, 0xd7, 0x1, 0xbc, 0x58, 0xc2, 0xaf, 0x3, 0xe7, 0x92, 0x22, 0x87, 0x11, 0x92, 0x46, 0xa1, 0x77, 0xbf, 0x7, 0xf8, 0xbf, 0xcb, 0x67, 0x1e, 0x5f, 0xd1, 0x59, 0x43, 0xc6, 0x18, 0xd2, 0x98, 0xbb, 0x42, 0xf6, 0xf9, 0x78, 0x3b, 0x7d, 0xa1, 0x4b, 0x97, 0x6f, 0xac, 0x81, 0x5, 0xf8, 0x1a, 0xda, 0xd7, 0x61, 0xa0, 0xdd, 0xa1, 0x6e, 0xd9, 0x77, 0xc4, 0x55, 0x4b, 0x8e, 0x4, 0x30, 0x82, 0xe4, 0x89, 0x0, 0xc6, 0x1, 0x8, 0x6f, 0x11, 0x13, 0x8c, 0xc1, 0x9b, 0x1, 0x9c, 0xb5, 0x7c, 0xe6, 0xf1, 0x4b, 0xaa, 0xc9, 0x63, 0xe4, 0xd5, 0x2f, 0x1c, 0x28, 0xd9, 0x4d, 0xfe, 0xb9, 0x88, 0xa5, 0x5c, 0x0, 0xa, 0xc0, 0xd7, 0x30, 0x32, 0x92, 0x16, 0x1, 0x98, 0xbc, 0x7c, 0xe6, 0xf1, 0x65, 0x17, 0x61, 0xd6, 0x2b, 0xd4, 0x2d, 0x3, 0x4, 0x30, 0xe2, 0xea, 0xe7, 0xfb, 0x0, 0x38, 0x3, 0xc0, 0xbf, 0x10, 0x3c, 0xa, 0xc0, 0x18, 0xdf, 0x4a, 0xb0, 0x43, 0xd0, 0x95, 0xcb, 0x6f, 0x18, 0x75, 0x47, 0x8d, 0xe9, 0x3f, 0x65, 0x68, 0x8e, 0x87, 0x77, 0xf6, 0x9e, 0xe7, 0x25, 0x1c, 0xc3, 0xa, 0xb2, 0x5, 0xea, 0xc2, 0x2e, 0x2b, 0xfb, 0x9f, 0x0, 0x7e, 0xb8, 0xfc, 0x86, 0x51, 0x5d, 0xc, 0xd0, 0x11, 0x70, 0xd4, 0x57, 0x96, 0xe, 0x7, 0x30, 0x9, 0x5e, 0x6f, 0xb0, 0xe9, 0xc5, 0x19, 0xc7, 0x7e, 0xb7, 0x96, 0xf4, 0x46, 0x5e, 0xb3, 0x94, 0x92, 0x3d, 0x95, 0xe4, 0xaf, 0x0, 0xec, 0x11, 0xee, 0x5, 0x22, 0xb4, 0x90, 0x9c, 0xfc, 0xe1, 0x3f, 0x5b, 0x0, 0x63, 0x49, 0xf3, 0x48, 0x67, 0x2c, 0x4d, 0x4f, 0xa, 0x76, 0x2b, 0x6, 0x68, 0xf, 0x18, 0x79, 0xcd, 0xd2, 0x3d, 0x24, 0xbd, 0x4c, 0xf2, 0xc0, 0x62, 0xb5, 0x33, 0xce, 0x5b, 0x59, 0xd2, 0x26, 0x92, 0x2f, 0x91, 0xbc, 0xf8, 0xc5, 0x19, 0xc7, 0x6c, 0x6a, 0x4b, 0x3e, 0xf5, 0xa, 0xff, 0xf4, 0xc, 0x0, 0x0, 0x23, 0xaf, 0x7e, 0xe1, 0x7a, 0x1a, 0x5e, 0x7, 0x20, 0xe5, 0xfb, 0x61, 0x65, 0x0, 0xec, 0x82, 0xb0, 0xb, 0xc4, 0xe, 0x0, 0x5b, 0x24, 0x6d, 0x26, 0xb9, 0xd, 0xc2, 0x66, 0x41, 0x4b, 0x8c, 0x31, 0xbf, 0xfb, 0xfd, 0x4f, 0x8e, 0x59, 0x57, 0x63, 0xd6, 0x9d, 0xe, 0x75, 0xa3, 0x6, 0x76, 0x26, 0xd0, 0x98, 0xff, 0x91, 0x74, 0x8, 0x80, 0x1e, 0x24, 0xb7, 0xc0, 0xdb, 0x5b, 0x6f, 0x33, 0xd, 0xdf, 0x3, 0xf0, 0xb6, 0xa4, 0x57, 0x1, 0xbc, 0xf4, 0xe2, 0x8c, 0x63, 0xdf, 0xe9, 0xec, 0xb2, 0x76, 0x41, 0x17, 0x74, 0x41, 0x17, 0x74, 0x41, 0x17, 0x74, 0x41, 0x17, 0x74, 0x41, 0x17, 0x74, 0x41, 0x17, 0xd4, 0x6, 0xff, 0x1f, 0x32, 0x68, 0x5, 0x7e, 0x99, 0xd5, 0x97, 0x49, 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 mini_checkerboard_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, 0xe, 0xc3, 0x0, 0x0, 0xe, 0xc3, 0x1, 0xc7, 0x6f, 0xa8, 0x64, 0x0, 0x0, 0x0, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x0, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, 0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x0, 0x0, 0x0, 0x33, 0x49, 0x44, 0x41, 0x54, 0x38, 0x8d, 0x63, 0x7c, 0xf0, 0xe0, 0xc1, 0x7f, 0x6, 0x3c, 0x40, 0x5e, 0x5e, 0x1e, 0x9f, 0x34, 0x3, 0x13, 0x5e, 0x59, 0x22, 0xc0, 0xa8, 0x1, 0x83, 0xc1, 0x0, 0xc6, 0xff, 0xff, 0xff, 0xe3, 0x4d, 0x7, 0xf, 0x1f, 0x3e, 0xa4, 0xad, 0xb, 0x46, 0xd, 0x18, 0xc, 0x6, 0x0, 0x0, 0x6e, 0x41, 0xa, 0xba, 0x94, 0xaa, 0x47, 0x57, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
static const unsigned char option_arrow_png[] = {
0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0xc, 0x8, 0x6, 0x0, 0x0, 0x0, 0x56, 0x75, 0x5c, 0xe7, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xa0, 0xbd, 0xa7, 0x93, 0x0, 0x0, 0x0, 0x98, 0x49, 0x44, 0x41, 0x54, 0x28, 0x91, 0xbd, 0x91, 0xb1, 0xd, 0xc2, 0x30, 0x10, 0x45, 0xdf, 0xd1, 0xb8, 0xf0, 0x2, 0xee, 0xdc, 0x87, 0x1, 0xd8, 0x24, 0xb5, 0xe9, 0x19, 0x87, 0x1e, 0xea, 0x6c, 0xc2, 0x0, 0xa4, 0xb5, 0xdc, 0x79, 0x1, 0x17, 0xae, 0x8e, 0x26, 0x48, 0x76, 0x14, 0x40, 0x48, 0x88, 0xdf, 0xfd, 0xf7, 0xef, 0x4b, 0x77, 0x3a, 0xf8, 0x85, 0x62, 0x8c, 0x21, 0xc6, 0x18, 0xb6, 0x32, 0x59, 0x83, 0x94, 0xd2, 0x5e, 0x55, 0x6f, 0x0, 0x22, 0x72, 0xf0, 0xde, 0xdf, 0xdb, 0x7c, 0xd7, 0x9a, 0x9c, 0xb3, 0x55, 0xd5, 0x9, 0xb0, 0x80, 0x55, 0xd5, 0x29, 0xe7, 0x6c, 0x5f, 0x16, 0x6a, 0xad, 0x67, 0x60, 0x68, 0xd0, 0xb0, 0xb0, 0x3f, 0xaa, 0x3b, 0x3a, 0xa5, 0x74, 0x51, 0xd5, 0xd0, 0xd, 0x88, 0x5c, 0xbd, 0xf7, 0xc7, 0xa7, 0xef, 0x6e, 0x30, 0xc6, 0x9c, 0x80, 0xb9, 0x41, 0xf3, 0xc2, 0xd8, 0x2c, 0x38, 0xe7, 0x8a, 0x88, 0x8c, 0x40, 0x1, 0x8a, 0x88, 0x8c, 0xce, 0xb9, 0xf2, 0x71, 0xcf, 0x77, 0x8f, 0xfb, 0x5a, 0xf, 0x28, 0x4a, 0x37, 0xff, 0x58, 0x46, 0x7b, 0x50, 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 82739b58a0..1ee76a4216 100644
--- a/scene/resources/dynamic_font.cpp
+++ b/scene/resources/dynamic_font.cpp
@@ -397,7 +397,7 @@ unsigned long DynamicFontAtSize::_ft_stream_io(FT_Stream stream, unsigned long o
FileAccess *f = (FileAccess *)stream->descriptor.pointer;
- if (f->get_pos() != offset) {
+ if (f->get_position() != offset) {
f->seek(offset);
}
@@ -560,8 +560,23 @@ void DynamicFontAtSize::_update_char(CharType p_char) {
int ofs = ((i + tex_y + rect_margin) * tex.texture_size + j + tex_x + rect_margin) * 2;
ERR_FAIL_COND(ofs >= tex.imgdata.size());
- wr[ofs + 0] = 255; //grayscale as 1
- wr[ofs + 1] = slot->bitmap.buffer[i * slot->bitmap.width + j];
+ switch (slot->bitmap.pixel_mode) {
+ case FT_PIXEL_MODE_MONO: {
+ int byte = i * slot->bitmap.pitch + (j >> 3);
+ int bit = 1 << (7 - (j % 8));
+ wr[ofs + 0] = 255; //grayscale as 1
+ wr[ofs + 1] = slot->bitmap.buffer[byte] & bit ? 255 : 0;
+ } break;
+ case FT_PIXEL_MODE_GRAY:
+ wr[ofs + 0] = 255; //grayscale as 1
+ wr[ofs + 1] = slot->bitmap.buffer[i * slot->bitmap.pitch + j];
+ break;
+ // TODO: FT_PIXEL_MODE_LCD, FT_PIXEL_MODE_BGRA
+ default:
+ ERR_EXPLAIN("Font uses unsupported pixel format: " + itos(slot->bitmap.pixel_mode));
+ ERR_FAIL();
+ break;
+ }
}
}
}
diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp
index da3bc6a95b..4c6fa7c8a1 100644
--- a/scene/resources/environment.cpp
+++ b/scene/resources/environment.cpp
@@ -55,12 +55,11 @@ void Environment::set_sky(const Ref<Sky> &p_sky) {
VS::get_singleton()->environment_set_sky(environment, sb_rid);
}
-void Environment::set_sky_scale(float p_scale) {
+void Environment::set_sky_custom_fov(float p_scale) {
- bg_sky_scale = p_scale;
- VS::get_singleton()->environment_set_sky_scale(environment, p_scale);
+ bg_sky_custom_fov = p_scale;
+ VS::get_singleton()->environment_set_sky_custom_fov(environment, p_scale);
}
-
void Environment::set_bg_color(const Color &p_color) {
bg_color = p_color;
@@ -101,9 +100,9 @@ Ref<Sky> Environment::get_sky() const {
return bg_sky;
}
-float Environment::get_sky_scale() const {
+float Environment::get_sky_custom_fov() const {
- return bg_sky_scale;
+ return bg_sky_custom_fov;
}
Color Environment::get_bg_color() const {
@@ -268,7 +267,7 @@ Ref<Texture> Environment::get_adjustment_color_correction() const {
void Environment::_validate_property(PropertyInfo &property) const {
- if (property.name == "background_sky" || property.name == "background_sky_scale" || property.name == "ambient_light/sky_contribution") {
+ if (property.name == "background_sky" || property.name == "background_sky_custom_fov" || property.name == "ambient_light/sky_contribution") {
if (bg_mode != BG_SKY && bg_mode != BG_COLOR_SKY) {
property.usage = PROPERTY_USAGE_NOEDITOR;
}
@@ -820,7 +819,7 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_background", "mode"), &Environment::set_background);
ClassDB::bind_method(D_METHOD("set_sky", "sky"), &Environment::set_sky);
- ClassDB::bind_method(D_METHOD("set_sky_scale", "scale"), &Environment::set_sky_scale);
+ ClassDB::bind_method(D_METHOD("set_sky_custom_fov", "scale"), &Environment::set_sky_custom_fov);
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);
@@ -830,7 +829,7 @@ void Environment::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_background"), &Environment::get_background);
ClassDB::bind_method(D_METHOD("get_sky"), &Environment::get_sky);
- ClassDB::bind_method(D_METHOD("get_sky_scale"), &Environment::get_sky_scale);
+ ClassDB::bind_method(D_METHOD("get_sky_custom_fov"), &Environment::get_sky_custom_fov);
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);
@@ -841,7 +840,7 @@ void Environment::_bind_methods() {
ADD_GROUP("Background", "background_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "background_mode", PROPERTY_HINT_ENUM, "Clear Color,Custom Color,Sky,Color+Sky,Canvas,Keep"), "set_background", "get_background");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "background_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_sky", "get_sky");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_sky_scale", PROPERTY_HINT_RANGE, "0,32,0.01"), "set_sky_scale", "get_sky_scale");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "background_sky_custom_fov", PROPERTY_HINT_RANGE, "0,180,0.1"), "set_sky_custom_fov", "get_sky_custom_fov");
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");
@@ -1142,7 +1141,7 @@ Environment::Environment() {
environment = VS::get_singleton()->environment_create();
bg_mode = BG_CLEAR_COLOR;
- bg_sky_scale = 1.0;
+ bg_sky_custom_fov = 0;
bg_energy = 1.0;
bg_canvas_max_layer = 0;
ambient_energy = 1.0;
diff --git a/scene/resources/environment.h b/scene/resources/environment.h
index 9046ec1e49..5909846074 100644
--- a/scene/resources/environment.h
+++ b/scene/resources/environment.h
@@ -76,7 +76,7 @@ private:
BGMode bg_mode;
Ref<Sky> bg_sky;
- float bg_sky_scale;
+ float bg_sky_custom_fov;
Color bg_color;
float bg_energy;
int bg_canvas_max_layer;
@@ -162,7 +162,7 @@ protected:
public:
void set_background(BGMode p_bg);
void set_sky(const Ref<Sky> &p_sky);
- void set_sky_scale(float p_scale);
+ void set_sky_custom_fov(float p_scale);
void set_bg_color(const Color &p_color);
void set_bg_energy(float p_energy);
void set_canvas_max_layer(int p_max_layer);
@@ -172,7 +172,7 @@ public:
BGMode get_background() const;
Ref<Sky> get_sky() const;
- float get_sky_scale() const;
+ float get_sky_custom_fov() const;
Color get_bg_color() const;
float get_bg_energy() const;
int get_canvas_max_layer() const;
diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp
index ea75748b3d..2b44ea4554 100644
--- a/scene/resources/font.cpp
+++ b/scene/resources/font.cpp
@@ -80,13 +80,13 @@ void Font::update_changes() {
void Font::_bind_methods() {
- 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("draw", "canvas_item", "position", "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("draw_char", "canvas_item", "position", "char", "next", "modulate"), &Font::draw_char, DEFVAL(-1), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("update_changes"), &Font::update_changes);
}
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index abe9a00c3f..2936df7a51 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -268,6 +268,12 @@ void SpatialMaterial::init_shaders() {
shader_names->grow = "grow";
+ shader_names->ao_light_affect = "ao_light_affect";
+
+ shader_names->proximity_fade_distance = "proximity_fade_distance";
+ shader_names->distance_fade_min = "distance_fade_min";
+ shader_names->distance_fade_max = "distance_fade_max";
+
shader_names->metallic_texture_channel = "metallic_texture_channel";
shader_names->roughness_texture_channel = "roughness_texture_channel";
shader_names->ao_texture_channel = "ao_texture_channel";
@@ -364,10 +370,10 @@ void SpatialMaterial::_update_shader() {
case CULL_DISABLED: code += ",cull_disabled"; break;
}
switch (diffuse_mode) {
+ case DIFFUSE_BURLEY: code += ",diffuse_burley"; break;
case DIFFUSE_LAMBERT: code += ",diffuse_lambert"; break;
case DIFFUSE_LAMBERT_WRAP: code += ",diffuse_lambert_wrap"; break;
case DIFFUSE_OREN_NAYAR: code += ",diffuse_oren_nayar"; break;
- case DIFFUSE_BURLEY: code += ",diffuse_burley"; break;
case DIFFUSE_TOON: code += ",diffuse_toon"; break;
}
switch (specular_mode) {
@@ -401,6 +407,14 @@ void SpatialMaterial::_update_shader() {
code += "uniform float grow;\n";
}
+ if (proximity_fade_enabled) {
+ code += "uniform float proximity_fade_distance;\n";
+ }
+ if (distance_fade_enabled) {
+ code += "uniform float distance_fade_min;\n";
+ code += "uniform float distance_fade_max;\n";
+ }
+
if (flags[FLAG_USE_ALPHA_SCISSOR]) {
code += "uniform float alpha_scissor_threshold;\n";
}
@@ -450,6 +464,7 @@ void SpatialMaterial::_update_shader() {
if (features[FEATURE_AMBIENT_OCCLUSION]) {
code += "uniform sampler2D texture_ambient_occlusion : hint_white;\n";
code += "uniform vec4 ao_texture_channel;\n";
+ code += "uniform float ao_light_affect;\n";
}
if (features[FEATURE_DETAIL]) {
@@ -725,10 +740,21 @@ void SpatialMaterial::_update_shader() {
code += "\tALBEDO *= 1.0 - ref_amount;\n";
code += "\tALPHA = 1.0;\n";
- } else if (features[FEATURE_TRANSPARENT] || features[FLAG_USE_ALPHA_SCISSOR]) {
+ } else if (features[FEATURE_TRANSPARENT] || flags[FLAG_USE_ALPHA_SCISSOR] || distance_fade_enabled || proximity_fade_enabled) {
code += "\tALPHA = albedo.a * albedo_tex.a;\n";
}
+ if (proximity_fade_enabled) {
+ code += "\tfloat depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_UV,0.0).r;\n";
+ code += "\tvec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV*2.0-1.0,depth_tex*2.0-1.0,1.0);\n";
+ code += "\tworld_pos.xyz/=world_pos.w;\n";
+ code += "\tALPHA*=clamp(1.0-smoothstep(world_pos.z+proximity_fade_distance,world_pos.z,VERTEX.z),0.0,1.0);\n";
+ }
+
+ if (distance_fade_enabled) {
+ code += "\tALPHA*=clamp(smoothstep(distance_fade_min,distance_fade_max,-VERTEX.z),0.0,1.0);\n";
+ }
+
if (features[FEATURE_RIM]) {
if (flags[FLAG_UV1_USE_TRIPLANAR]) {
code += "\tvec2 rim_tex = triplanar_texture(texture_rim,uv1_power_normal,uv1_triplanar_pos).xy;\n";
@@ -773,6 +799,8 @@ void SpatialMaterial::_update_shader() {
code += "\tAO = dot(texture(texture_ambient_occlusion,base_uv),ao_texture_channel);\n";
}
}
+
+ code += "\tAO_LIGHT_AFFECT = ao_light_affect;\n";
}
if (features[FEATURE_SUBSURACE_SCATTERING]) {
@@ -834,10 +862,10 @@ void SpatialMaterial::_update_shader() {
code += "\tvec3 detail_norm = mix(NORMALMAP,detail_norm_tex.rgb,detail_tex.a);\n";
code += "\tNORMALMAP = mix(NORMALMAP,detail_norm,detail_mask_tex.r);\n";
code += "\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n";
+ }
- if (flags[FLAG_USE_ALPHA_SCISSOR]) {
- code += "\tALPHA_SCISSOR=alpha_scissor_threshold;\n";
- }
+ if (flags[FLAG_USE_ALPHA_SCISSOR]) {
+ code += "\tALPHA_SCISSOR=alpha_scissor_threshold;\n";
}
code += "}\n";
@@ -989,6 +1017,16 @@ float SpatialMaterial::get_rim_tint() const {
return rim_tint;
}
+void SpatialMaterial::set_ao_light_affect(float p_ao_light_affect) {
+
+ ao_light_affect = p_ao_light_affect;
+ VS::get_singleton()->material_set_param(_get_material(), shader_names->ao_light_affect, p_ao_light_affect);
+}
+float SpatialMaterial::get_ao_light_affect() const {
+
+ return ao_light_affect;
+}
+
void SpatialMaterial::set_clearcoat(float p_clearcoat) {
clearcoat = p_clearcoat;
@@ -1231,6 +1269,14 @@ void SpatialMaterial::_validate_property(PropertyInfo &property) const {
property.usage = 0;
}
+ if (property.name == "proximity_fade_distacne" && !proximity_fade_enabled) {
+ property.usage = 0;
+ }
+
+ if ((property.name == "distance_fade_max_distance" || property.name == "distance_fade_min_distance") && !distance_fade_enabled) {
+ property.usage = 0;
+ }
+
if (property.name == "params_alpha_scissor_threshold" && !flags[FLAG_USE_ALPHA_SCISSOR]) {
property.usage = 0;
}
@@ -1526,6 +1572,66 @@ void SpatialMaterial::set_on_top_of_alpha() {
set_flag(FLAG_DISABLE_DEPTH_TEST, true);
}
+void SpatialMaterial::set_proximity_fade(bool p_enable) {
+
+ proximity_fade_enabled = p_enable;
+ _queue_shader_change();
+ _change_notify();
+}
+
+bool SpatialMaterial::is_proximity_fade_enabled() const {
+
+ return proximity_fade_enabled;
+}
+
+void SpatialMaterial::set_proximity_fade_distance(float p_distance) {
+
+ proximity_fade_distance = p_distance;
+ VS::get_singleton()->material_set_param(_get_material(), shader_names->proximity_fade_distance, p_distance);
+}
+float SpatialMaterial::get_proximity_fade_distance() const {
+
+ return proximity_fade_distance;
+}
+
+void SpatialMaterial::set_distance_fade(bool p_enable) {
+
+ distance_fade_enabled = p_enable;
+ _queue_shader_change();
+ _change_notify();
+}
+bool SpatialMaterial::is_distance_fade_enabled() const {
+
+ return distance_fade_enabled;
+}
+
+void SpatialMaterial::set_distance_fade_max_distance(float p_distance) {
+
+ distance_fade_max_distance = p_distance;
+ VS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_max, distance_fade_max_distance);
+}
+float SpatialMaterial::get_distance_fade_max_distance() const {
+
+ return distance_fade_max_distance;
+}
+
+void SpatialMaterial::set_distance_fade_min_distance(float p_distance) {
+
+ distance_fade_min_distance = p_distance;
+ VS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_min, distance_fade_min_distance);
+}
+
+float SpatialMaterial::get_distance_fade_min_distance() const {
+
+ return distance_fade_min_distance;
+}
+
+RID SpatialMaterial::get_shader_rid() const {
+
+ ERR_FAIL_COND_V(!shader_map.has(current_key), RID());
+ return shader_map[current_key].shader;
+}
+
void SpatialMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &SpatialMaterial::set_albedo);
@@ -1654,6 +1760,9 @@ void SpatialMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_grow", "amount"), &SpatialMaterial::set_grow);
ClassDB::bind_method(D_METHOD("get_grow"), &SpatialMaterial::get_grow);
+ ClassDB::bind_method(D_METHOD("set_ao_light_affect", "amount"), &SpatialMaterial::set_ao_light_affect);
+ ClassDB::bind_method(D_METHOD("get_ao_light_affect"), &SpatialMaterial::get_ao_light_affect);
+
ClassDB::bind_method(D_METHOD("set_alpha_scissor_threshold", "threshold"), &SpatialMaterial::set_alpha_scissor_threshold);
ClassDB::bind_method(D_METHOD("get_alpha_scissor_threshold"), &SpatialMaterial::get_alpha_scissor_threshold);
@@ -1672,6 +1781,21 @@ void SpatialMaterial::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_refraction_texture_channel", "channel"), &SpatialMaterial::set_refraction_texture_channel);
ClassDB::bind_method(D_METHOD("get_refraction_texture_channel"), &SpatialMaterial::get_refraction_texture_channel);
+ ClassDB::bind_method(D_METHOD("set_proximity_fade", "enabled"), &SpatialMaterial::set_proximity_fade);
+ ClassDB::bind_method(D_METHOD("is_proximity_fade_enabled"), &SpatialMaterial::is_proximity_fade_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_proximity_fade_distance", "distance"), &SpatialMaterial::set_proximity_fade_distance);
+ ClassDB::bind_method(D_METHOD("get_proximity_fade_distance"), &SpatialMaterial::get_proximity_fade_distance);
+
+ ClassDB::bind_method(D_METHOD("set_distance_fade", "enabled"), &SpatialMaterial::set_distance_fade);
+ ClassDB::bind_method(D_METHOD("is_distance_fade_enabled"), &SpatialMaterial::is_distance_fade_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_distance_fade_max_distance", "distance"), &SpatialMaterial::set_distance_fade_max_distance);
+ ClassDB::bind_method(D_METHOD("get_distance_fade_max_distance"), &SpatialMaterial::get_distance_fade_max_distance);
+
+ ClassDB::bind_method(D_METHOD("set_distance_fade_min_distance", "distance"), &SpatialMaterial::set_distance_fade_min_distance);
+ ClassDB::bind_method(D_METHOD("get_distance_fade_min_distance"), &SpatialMaterial::get_distance_fade_min_distance);
+
ADD_GROUP("Flags", "flags_");
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);
@@ -1685,7 +1809,7 @@ void SpatialMaterial::_bind_methods() {
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, "Lambert,Lambert Wrap,Oren Nayar,Burley,Toon"), "set_diffuse_mode", "get_diffuse_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Burley,Lambert,Lambert Wrap,Oren Nayar,Toon"), "set_diffuse_mode", "get_diffuse_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "params_specular_mode", PROPERTY_HINT_ENUM, "SchlickGGX,Blinn,Phong,Toon,Disabled"), "set_specular_mode", "get_specular_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");
@@ -1747,6 +1871,7 @@ void SpatialMaterial::_bind_methods() {
ADD_GROUP("Ambient Occlusion", "ao_");
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_enabled"), "set_feature", "get_feature", FEATURE_AMBIENT_OCCLUSION);
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "ao_light_affect", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_ao_light_affect", "get_ao_light_affect");
ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "ao_texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_texture", "get_texture", TEXTURE_AMBIENT_OCCLUSION);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "ao_on_uv2"), "set_flag", "get_flag", FLAG_AO_ON_UV2);
ADD_PROPERTY(PropertyInfo(Variant::INT, "ao_texture_channel", PROPERTY_HINT_ENUM, "Red,Green,Blue,Alpha,Gray"), "set_ao_texture_channel", "get_ao_texture_channel");
@@ -1795,6 +1920,14 @@ void SpatialMaterial::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "uv2_triplanar"), "set_flag", "get_flag", FLAG_UV2_USE_TRIPLANAR);
ADD_PROPERTY(PropertyInfo(Variant::REAL, "uv2_triplanar_sharpness", PROPERTY_HINT_EXP_EASING), "set_uv2_triplanar_blend_sharpness", "get_uv2_triplanar_blend_sharpness");
+ ADD_GROUP("Proximity Fade", "proximity_fade_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "proximity_fade_enable"), "set_proximity_fade", "is_proximity_fade_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "proximity_fade_distance", PROPERTY_HINT_RANGE, "0,4096,0.1"), "set_proximity_fade_distance", "get_proximity_fade_distance");
+ ADD_GROUP("Distance Fade", "distance_fade_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "distance_fade_enable"), "set_distance_fade", "is_distance_fade_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "distance_fade_min_distance", PROPERTY_HINT_RANGE, "0,4096,0.1"), "set_distance_fade_min_distance", "get_distance_fade_min_distance");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL, "distance_fade_max_distance", PROPERTY_HINT_RANGE, "0,4096,0.1"), "set_distance_fade_max_distance", "get_distance_fade_max_distance");
+
BIND_ENUM_CONSTANT(TEXTURE_ALBEDO);
BIND_ENUM_CONSTANT(TEXTURE_METALLIC);
BIND_ENUM_CONSTANT(TEXTURE_ROUGHNESS);
@@ -1858,10 +1991,10 @@ void SpatialMaterial::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_TRIPLANAR_USE_WORLD);
BIND_ENUM_CONSTANT(FLAG_MAX);
+ BIND_ENUM_CONSTANT(DIFFUSE_BURLEY);
BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT);
BIND_ENUM_CONSTANT(DIFFUSE_LAMBERT_WRAP);
BIND_ENUM_CONSTANT(DIFFUSE_OREN_NAYAR);
- BIND_ENUM_CONSTANT(DIFFUSE_BURLEY);
BIND_ENUM_CONSTANT(DIFFUSE_TOON);
BIND_ENUM_CONSTANT(SPECULAR_SCHLICK_GGX);
@@ -1916,6 +2049,14 @@ SpatialMaterial::SpatialMaterial()
set_particles_anim_loop(false);
set_alpha_scissor_threshold(0.98);
+ proximity_fade_enabled = false;
+ distance_fade_enabled = false;
+ set_proximity_fade_distance(1);
+ set_distance_fade_min_distance(0);
+ set_distance_fade_max_distance(10);
+
+ set_ao_light_affect(0.0);
+
set_metallic_texture_channel(TEXTURE_CHANNEL_RED);
set_roughness_texture_channel(TEXTURE_CHANNEL_RED);
set_ao_texture_channel(TEXTURE_CHANNEL_RED);
diff --git a/scene/resources/material.h b/scene/resources/material.h
index fdb11982a8..c0e007ac5f 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -185,10 +185,10 @@ public:
};
enum DiffuseMode {
+ DIFFUSE_BURLEY,
DIFFUSE_LAMBERT,
DIFFUSE_LAMBERT_WRAP,
DIFFUSE_OREN_NAYAR,
- DIFFUSE_BURLEY,
DIFFUSE_TOON,
};
@@ -232,6 +232,8 @@ private:
uint64_t deep_parallax : 1;
uint64_t billboard_mode : 2;
uint64_t grow : 1;
+ uint64_t proximity_fade : 1;
+ uint64_t distance_fade : 1;
};
uint64_t key;
@@ -274,6 +276,8 @@ private:
mk.billboard_mode = billboard_mode;
mk.deep_parallax = deep_parallax ? 1 : 0;
mk.grow = grow_enabled;
+ mk.proximity_fade = proximity_fade_enabled;
+ mk.distance_fade = distance_fade_enabled;
return mk;
}
@@ -308,6 +312,10 @@ private:
StringName uv1_blend_sharpness;
StringName uv2_blend_sharpness;
StringName grow;
+ StringName proximity_fade_distance;
+ StringName distance_fade_min;
+ StringName distance_fade_max;
+ StringName ao_light_affect;
StringName metallic_texture_channel;
StringName roughness_texture_channel;
@@ -351,6 +359,7 @@ private:
float point_size;
float alpha_scissor_threshold;
bool grow_enabled;
+ float ao_light_affect;
float grow;
int particles_anim_h_frames;
int particles_anim_v_frames;
@@ -370,6 +379,13 @@ private:
int deep_parallax_min_layers;
int deep_parallax_max_layers;
+ bool proximity_fade_enabled;
+ float proximity_fade_distance;
+
+ bool distance_fade_enabled;
+ float distance_fade_max_distance;
+ float distance_fade_min_distance;
+
BlendMode blend_mode;
BlendMode detail_blend_mode;
DepthDrawMode depth_draw_mode;
@@ -429,6 +445,9 @@ public:
void set_rim_tint(float p_rim_tint);
float get_rim_tint() const;
+ void set_ao_light_affect(float p_ao_light_affect);
+ float get_ao_light_affect() const;
+
void set_clearcoat(float p_clearcoat);
float get_clearcoat() const;
@@ -535,6 +554,21 @@ public:
void set_on_top_of_alpha();
+ void set_proximity_fade(bool p_enable);
+ bool is_proximity_fade_enabled() const;
+
+ void set_proximity_fade_distance(float p_distance);
+ float get_proximity_fade_distance() const;
+
+ void set_distance_fade(bool p_enable);
+ bool is_distance_fade_enabled() const;
+
+ void set_distance_fade_max_distance(float p_distance);
+ float get_distance_fade_max_distance() const;
+
+ void set_distance_fade_min_distance(float p_distance);
+ float get_distance_fade_min_distance() const;
+
void set_metallic_texture_channel(TextureChannel p_channel);
TextureChannel get_metallic_texture_channel() const;
void set_roughness_texture_channel(TextureChannel p_channel);
@@ -550,6 +584,8 @@ public:
static RID get_material_rid_for_2d(bool p_shaded, bool p_transparent, bool p_double_sided, bool p_cut_alpha, bool p_opaque_prepass);
+ RID get_shader_rid() const;
+
SpatialMaterial();
virtual ~SpatialMaterial();
};
diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp
index 14e2ef83f8..f0304bfaa5 100644
--- a/scene/resources/scene_format_text.cpp
+++ b/scene/resources/scene_format_text.cpp
@@ -679,7 +679,7 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const
String base_path = local_path.get_base_dir();
- uint64_t tag_end = f->get_pos();
+ uint64_t tag_end = f->get_position();
while (true) {
@@ -741,7 +741,7 @@ Error ResourceInteractiveLoaderText::rename_dependencies(FileAccess *p_f, const
fw->store_line("[ext_resource path=\"" + path + "\" type=\"" + type + "\" id=" + itos(index) + "]");
- tag_end = f->get_pos();
+ tag_end = f->get_position();
}
}
diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp
index 2ca9a14562..3813854922 100644
--- a/scene/resources/shader_graph.cpp
+++ b/scene/resources/shader_graph.cpp
@@ -172,8 +172,8 @@ void ShaderGraph::_bind_methods() {
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(D_METHOD("node_set_position","shader_type","id","position"),&ShaderGraph::node_set_position);
+ ClassDB::bind_method(D_METHOD("node_get_position","shader_type","id"),&ShaderGraph::node_get_position);
ClassDB::bind_method(D_METHOD("node_get_type","shader_type","id"),&ShaderGraph::node_get_type);
@@ -501,7 +501,7 @@ void ShaderGraph::node_add(ShaderType p_type, NodeType p_node_type,int p_id) {
_request_update();
}
-void ShaderGraph::node_set_pos(ShaderType p_type,int p_id, const Vector2& p_pos) {
+void ShaderGraph::node_set_position(ShaderType p_type,int p_id, const Vector2& p_pos) {
ERR_FAIL_INDEX(p_type,3);
ERR_FAIL_COND(!shader[p_type].node_map.has(p_id));
@@ -509,7 +509,7 @@ void ShaderGraph::node_set_pos(ShaderType p_type,int p_id, const Vector2& p_pos)
_request_update();
}
-Vector2 ShaderGraph::node_get_pos(ShaderType p_type,int p_id) const {
+Vector2 ShaderGraph::node_get_position(ShaderType p_type,int p_id) const {
ERR_FAIL_INDEX_V(p_type,3,Vector2());
ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Vector2());
@@ -1245,7 +1245,7 @@ Variant ShaderGraph::node_get_state(ShaderType p_type,int p_id) const {
ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Variant());
const Node& n = shader[p_type].node_map[p_id];
Dictionary s;
- s["pos"]=n.pos;
+ s["position"]=n.pos;
s["param1"]=n.param1;
s["param2"]=n.param2;
Array keys;
@@ -1263,12 +1263,12 @@ void ShaderGraph::node_set_state(ShaderType p_type,int p_id,const Variant& p_sta
ERR_FAIL_COND(!shader[p_type].node_map.has(p_id));
Node& n = shader[p_type].node_map[p_id];
Dictionary d = p_state;
- ERR_FAIL_COND(!d.has("pos"));
+ ERR_FAIL_COND(!d.has("position"));
ERR_FAIL_COND(!d.has("param1"));
ERR_FAIL_COND(!d.has("param2"));
ERR_FAIL_COND(!d.has("default_keys"));
- n.pos=d["pos"];
+ n.pos=d["position"];
n.param1=d["param1"];
n.param2=d["param2"];
Array keys = d["default_keys"];
diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h
index 9a74b6c53a..5d9dd7054f 100644
--- a/scene/resources/shader_graph.h
+++ b/scene/resources/shader_graph.h
@@ -195,8 +195,8 @@ public:
void node_add(ShaderType p_type, NodeType p_node_type, int p_id);
void node_remove(ShaderType p_which,int p_id);
- void node_set_pos(ShaderType p_which,int p_id,const Point2& p_pos);
- Point2 node_get_pos(ShaderType p_which,int p_id) const;
+ void node_set_position(ShaderType p_which,int p_id,const Point2& p_pos);
+ Point2 node_get_position(ShaderType p_which,int p_id) const;
void get_node_list(ShaderType p_which,List<int> *p_node_list) const;
NodeType node_get_type(ShaderType p_which,int p_id) const;
diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp
index 9af8c42110..2ef20f67f5 100644
--- a/scene/resources/sky_box.cpp
+++ b/scene/resources/sky_box.cpp
@@ -419,10 +419,10 @@ void ProceduralSky::_queue_update() {
call_deferred("_update_sky");
}
-void ProceduralSky::_thread_done(const Ref<Image> &image) {
+void ProceduralSky::_thread_done(const Ref<Image> &p_image) {
- VS::get_singleton()->texture_allocate(texture, image->get_width(), image->get_height(), Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
- VS::get_singleton()->texture_set_data(texture, image);
+ VS::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), Image::FORMAT_RGBE9995, VS::TEXTURE_FLAG_FILTER | VS::TEXTURE_FLAG_REPEAT);
+ VS::get_singleton()->texture_set_data(texture, p_image);
_radiance_changed();
Thread::wait_to_finish(sky_thread);
memdelete(sky_thread);
diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h
index 3d085f7166..4627c900ff 100644
--- a/scene/resources/style_box.h
+++ b/scene/resources/style_box.h
@@ -178,7 +178,7 @@ public:
void set_border_width_all(int p_size);
int get_border_width_min() const;
- void set_border_width(Margin p_margin, int p_size);
+ void set_border_width(Margin p_margin, int p_width);
int get_border_width(Margin p_margin) const;
//blend
@@ -214,7 +214,7 @@ public:
int get_shadow_size() const;
//ANTI_ALIASING
- void set_anti_aliased(const bool &p_anit_aliasing);
+ void set_anti_aliased(const bool &p_anti_aliased);
bool is_anti_aliased() const;
//tempAA
void set_aa_size(const int &p_aa_size);
diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp
index 6a9ded9ea3..c202fad1a4 100644
--- a/scene/resources/texture.cpp
+++ b/scene/resources/texture.cpp
@@ -70,7 +70,7 @@ void Texture::_bind_methods() {
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", "normal_map"), &Texture::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose", "normal_map"), &Texture::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map"), &Texture::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(true));
ClassDB::bind_method(D_METHOD("get_data"), &Texture::get_data);
@@ -488,7 +488,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla
while (mipmaps > 1 && p_size_limit > 0 && (sw > p_size_limit || sh > p_size_limit)) {
- f->seek(f->get_pos() + size);
+ f->seek(f->get_position() + size);
mipmaps = f->get_32();
size = f->get_32();
@@ -610,7 +610,7 @@ Error StreamTexture::_load_data(const String &p_path, int &tw, int &th, int &fla
ERR_FAIL_V(ERR_FILE_CORRUPT);
}
- f->seek(f->get_pos() + ofs);
+ f->seek(f->get_position() + ofs);
PoolVector<uint8_t> img_data;
img_data.resize(total_size - ofs);
diff --git a/scene/resources/video_stream.h b/scene/resources/video_stream.h
index e08be02a07..0f07233185 100644
--- a/scene/resources/video_stream.h
+++ b/scene/resources/video_stream.h
@@ -55,8 +55,8 @@ public:
virtual float get_length() const = 0;
- virtual float get_pos() const = 0;
- virtual void seek_pos(float p_time) = 0;
+ virtual float get_playback_position() const = 0;
+ virtual void seek(float p_time) = 0;
virtual void set_audio_track(int p_idx) = 0;
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index 6b7168a529..d9770ec3f3 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -87,7 +87,7 @@ SceneStringNames::SceneStringNames() {
_get_gizmo_geometry = StaticCString::create("_get_gizmo_geometry");
_can_gizmo_scale = StaticCString::create("_can_gizmo_scale");
- _fixed_process = StaticCString::create("_fixed_process");
+ _physics_process = StaticCString::create("_physics_process");
_process = StaticCString::create("_process");
_enter_tree = StaticCString::create("_enter_tree");
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 8676b8436e..3b110e7a62 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -106,7 +106,7 @@ public:
StringName _get_gizmo_geometry;
StringName _can_gizmo_scale;
- StringName _fixed_process;
+ StringName _physics_process;
StringName _process;
StringName _enter_world;
StringName _exit_world;
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index dd4240f028..0e3d5824d9 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -178,16 +178,16 @@ int AudioStreamPlaybackRandomPitch::get_loop_count() const {
return 0;
}
-float AudioStreamPlaybackRandomPitch::get_pos() const {
+float AudioStreamPlaybackRandomPitch::get_playback_position() const {
if (playing.is_valid()) {
- return playing->get_pos();
+ return playing->get_playback_position();
}
return 0;
}
-void AudioStreamPlaybackRandomPitch::seek_pos(float p_time) {
+void AudioStreamPlaybackRandomPitch::seek(float p_time) {
if (playing.is_valid()) {
- playing->seek_pos(p_time);
+ playing->seek(p_time);
}
}
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index c7cb63ef2c..3324597b41 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -45,8 +45,8 @@ public:
virtual int get_loop_count() const = 0; //times it looped
- virtual float get_pos() const = 0;
- virtual void seek_pos(float p_time) = 0;
+ virtual float get_playback_position() const = 0;
+ virtual void seek(float p_time) = 0;
virtual void mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames) = 0;
@@ -133,8 +133,8 @@ public:
virtual int get_loop_count() const; //times it looped
- virtual float get_pos() const;
- virtual void seek_pos(float p_time);
+ virtual float get_playback_position() const;
+ virtual void seek(float p_time);
virtual void mix(AudioFrame *p_bufer, float p_rate_scale, int p_frames);
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index 76dd585ffa..32631beb2c 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -182,9 +182,8 @@ Ref<AudioEffectInstance> AudioEffectChorus::instance() {
void AudioEffectChorus::set_voice_count(int p_voices) {
- ERR_FAIL_COND(p_voices < 1 || p_voices >= MAX_VOICES);
+ ERR_FAIL_COND(p_voices < 1 || p_voices > MAX_VOICES);
voice_count = p_voices;
- _change_notify();
}
int AudioEffectChorus::get_voice_count() const {
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
index 9787ba8109..c50dd804f2 100644
--- a/servers/audio/effects/audio_effect_limiter.cpp
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -110,7 +110,7 @@ void AudioEffectLimiter::set_soft_clip_ratio(float p_soft_clip) {
}
float AudioEffectLimiter::get_soft_clip_ratio() const {
- return soft_clip;
+ return soft_clip_ratio;
}
void AudioEffectLimiter::_bind_methods() {
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 4b728f821a..18b7014595 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -32,6 +32,7 @@
#include "os/file_access.h"
#include "os/os.h"
#include "project_settings.h"
+#include "servers/audio/audio_driver_dummy.h"
#include "servers/audio/effects/audio_effect_compressor.h"
#ifdef TOOLS_ENABLED
@@ -107,6 +108,7 @@ AudioDriver::AudioDriver() {
AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS];
int AudioDriverManager::driver_count = 0;
+AudioDriverDummy AudioDriverManager::dummy_driver;
void AudioDriverManager::add_driver(AudioDriver *p_driver) {
@@ -118,6 +120,43 @@ int AudioDriverManager::get_driver_count() {
return driver_count;
}
+
+void AudioDriverManager::initialize(int p_driver) {
+ AudioDriver *driver;
+ int failed_driver = -1;
+
+ // Check if there is a selected driver
+ if (p_driver >= 0 && p_driver < driver_count) {
+ if (drivers[p_driver]->init() == OK) {
+ drivers[p_driver]->set_singleton();
+ return;
+ } else {
+ failed_driver = p_driver;
+ }
+ }
+
+ // No selected driver, try them all in order
+ for (int i = 0; i < driver_count; i++) {
+ // Don't re-init the driver if it failed above
+ if (i == failed_driver) {
+ continue;
+ }
+
+ if (drivers[i]->init() == OK) {
+ drivers[i]->set_singleton();
+ return;
+ }
+ }
+
+ // Fallback to our dummy driver
+ if (dummy_driver.init() == OK) {
+ ERR_PRINT("AudioDriverManager: all drivers failed, falling back to dummy driver");
+ dummy_driver.set_singleton();
+ } else {
+ ERR_PRINT("AudioDriverManager: dummy driver faild to init()");
+ }
+}
+
AudioDriver *AudioDriverManager::get_driver(int p_driver) {
ERR_FAIL_INDEX_V(p_driver, driver_count, NULL);
@@ -1049,7 +1088,7 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_bus_count"), &AudioServer::get_bus_count);
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("add_bus", "at_position"), &AudioServer::add_bus, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("move_bus", "index", "to_index"), &AudioServer::move_bus);
ClassDB::bind_method(D_METHOD("set_bus_name", "bus_idx", "name"), &AudioServer::set_bus_name);
@@ -1071,7 +1110,7 @@ void AudioServer::_bind_methods() {
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(D_METHOD("add_bus_effect", "bus_idx", "effect", "at_pos"), &AudioServer::add_bus_effect, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("add_bus_effect", "bus_idx", "effect", "at_position"), &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(D_METHOD("get_bus_effect_count", "bus_idx"), &AudioServer::get_bus_effect_count);
diff --git a/servers/audio_server.h b/servers/audio_server.h
index c479d09a3c..55e9367308 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -35,6 +35,8 @@
#include "servers/audio/audio_effect.h"
#include "variant.h"
+class AudioDriverDummy;
+
class AudioDriver {
static AudioDriver *singleton;
@@ -90,8 +92,11 @@ class AudioDriverManager {
static AudioDriver *drivers[MAX_DRIVERS];
static int driver_count;
+ static AudioDriverDummy dummy_driver;
+
public:
static void add_driver(AudioDriver *p_driver);
+ static void initialize(int p_driver);
static int get_driver_count();
static AudioDriver *get_driver(int p_driver);
};
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 7e8d31f8eb..782bf14a4b 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -399,7 +399,7 @@ public:
virtual int get_contact_count() const { return body->contact_count; }
- virtual Vector3 get_contact_local_pos(int p_contact_idx) const {
+ virtual Vector3 get_contact_local_position(int p_contact_idx) const {
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
return body->contacts[p_contact_idx].local_pos;
}
@@ -416,7 +416,7 @@ public:
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
return body->contacts[p_contact_idx].collider;
}
- virtual Vector3 get_contact_collider_pos(int p_contact_idx) const {
+ virtual Vector3 get_contact_collider_position(int p_contact_idx) const {
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
return body->contacts[p_contact_idx].collider_pos;
}
@@ -428,7 +428,7 @@ public:
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0);
return body->contacts[p_contact_idx].collider_shape;
}
- virtual Vector3 get_contact_collider_velocity_at_pos(int p_contact_idx) const {
+ virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const {
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3());
return body->contacts[p_contact_idx].collider_velocity_at_pos;
}
diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h
index 51a24f4678..5c124c1792 100644
--- a/servers/physics/broad_phase_basic.h
+++ b/servers/physics/broad_phase_basic.h
@@ -82,7 +82,7 @@ class BroadPhaseBasic : public BroadPhaseSW {
public:
// 0 is an invalid ID
- virtual ID create(CollisionObjectSW *p_object_, int p_subindex = 0);
+ virtual ID create(CollisionObjectSW *p_object, int p_subindex = 0);
virtual void move(ID p_id, const Rect3 &p_aabb);
virtual void set_static(ID p_id, bool p_static);
virtual void remove(ID p_id);
diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h
index 670c1ab61f..ee9272ce06 100644
--- a/servers/physics/joints/pin_joint_sw.h
+++ b/servers/physics/joints/pin_joint_sw.h
@@ -86,8 +86,8 @@ public:
void set_pos_a(const Vector3 &p_pos) { m_pivotInA = p_pos; }
void set_pos_b(const Vector3 &p_pos) { m_pivotInB = p_pos; }
- Vector3 get_pos_a() { return m_pivotInB; }
- Vector3 get_pos_b() { return m_pivotInA; }
+ Vector3 get_position_a() { return m_pivotInB; }
+ Vector3 get_position_b() { return m_pivotInA; }
PinJointSW(BodySW *p_body_a, const Vector3 &p_pos_a, BodySW *p_body_b, const Vector3 &p_pos_b);
~PinJointSW();
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 2d46770924..1553c3c8e6 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -183,7 +183,7 @@ PhysicsDirectSpaceState *PhysicsServerSW::space_get_direct_state(RID p_space) {
ERR_FAIL_COND_V(!space, NULL);
if (!doing_sync || space->is_locked()) {
- ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or fixed process notification.");
+ ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or physics process notification.");
ERR_FAIL_V(NULL);
}
@@ -968,7 +968,7 @@ Vector3 PhysicsServerSW::pin_joint_get_local_a(RID p_joint) const {
ERR_FAIL_COND_V(!joint, Vector3());
ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3());
PinJointSW *pin_joint = static_cast<PinJointSW *>(joint);
- return pin_joint->get_pos_a();
+ return pin_joint->get_position_a();
}
void PhysicsServerSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) {
@@ -985,7 +985,7 @@ Vector3 PhysicsServerSW::pin_joint_get_local_b(RID p_joint) const {
ERR_FAIL_COND_V(!joint, Vector3());
ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3());
PinJointSW *pin_joint = static_cast<PinJointSW *>(joint);
- return pin_joint->get_pos_b();
+ return pin_joint->get_position_b();
}
RID PhysicsServerSW::joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) {
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 99ba302acd..aea3e150b0 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -95,7 +95,7 @@ public:
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value);
virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const;
- // this function only works on fixed process, errors and returns null otherwise
+ // this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space);
virtual void space_set_debug_contacts(RID p_space, int p_max_contacts);
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index 0ffad62f45..f7c717a5c6 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -353,7 +353,7 @@ public:
virtual int get_contact_count() const { return body->contact_count; }
- virtual Vector2 get_contact_local_pos(int p_contact_idx) const {
+ virtual Vector2 get_contact_local_position(int p_contact_idx) const {
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
return body->contacts[p_contact_idx].local_pos;
}
@@ -370,7 +370,7 @@ public:
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID());
return body->contacts[p_contact_idx].collider;
}
- virtual Vector2 get_contact_collider_pos(int p_contact_idx) const {
+ virtual Vector2 get_contact_collider_position(int p_contact_idx) const {
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
return body->contacts[p_contact_idx].collider_pos;
}
@@ -384,7 +384,7 @@ public:
}
virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const;
- virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const {
+ virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const {
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector2());
return body->contacts[p_contact_idx].collider_velocity_at_pos;
}
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index e9e7122af3..2b7505169a 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -270,7 +270,7 @@ Physics2DDirectSpaceState *Physics2DServerSW::space_get_direct_state(RID p_space
ERR_FAIL_COND_V(!space, NULL);
if ((using_threads && !doing_sync) || space->is_locked()) {
- ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or fixed process notification.");
+ ERR_EXPLAIN("Space state is inaccessible right now, wait for iteration or physics process notification.");
ERR_FAIL_V(NULL);
}
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index dd310d7a93..0ebd43be53 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -103,7 +103,7 @@ public:
virtual Vector<Vector2> space_get_contacts(RID p_space) const;
virtual int space_get_contact_count(RID p_space) const;
- // this function only works on fixed process, errors and returns null otherwise
+ // this function only works on physics process, errors and returns null otherwise
virtual Physics2DDirectSpaceState *space_get_direct_state(RID p_space);
/* AREA API */
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
index a4e6abfd45..f8f3b620d4 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
@@ -109,16 +109,13 @@ void Physics2DServerWrapMT::init() {
if (create_thread) {
step_sem = Semaphore::create();
- print_line("CREATING PHYSICS 2D THREAD");
//OS::get_singleton()->release_rendering_thread();
if (create_thread) {
thread = Thread::create(_thread_callback, this);
- print_line("STARTING PHYISICS 2D THREAD");
}
while (!step_thread_up) {
OS::get_singleton()->delay_usec(1000);
}
- print_line("DONE PHYSICS 2D THREAD");
} else {
physics_2d_server->init();
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 189419e8e4..5bec2f7cbd 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -111,7 +111,7 @@ public:
FUNC3(space_set_param, RID, SpaceParameter, real_t);
FUNC2RC(real_t, space_get_param, RID, SpaceParameter);
- // this function only works on fixed process, errors and returns null otherwise
+ // this function only works on physics process, errors and returns null otherwise
Physics2DDirectSpaceState *space_get_direct_state(RID p_space) {
ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), NULL);
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index 779f0d54ac..8f22d1cd44 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -518,7 +518,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
body_aabb = body_aabb.grow(p_margin);
static const int max_excluded_shape_pairs = 32;
- Pair<Shape2DSW *, Shape2DSW *> excluded_shape_pairs[max_excluded_shape_pairs];
+ ExcludedShapeSW excluded_shape_pairs[max_excluded_shape_pairs];
int excluded_shape_pair_count = 0;
Transform2D body_transform = p_from;
@@ -577,7 +577,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
if (!collided && cbk.invalid_by_dir > 0) {
//this shape must be excluded
if (excluded_shape_pair_count < max_excluded_shape_pairs) {
- excluded_shape_pairs[excluded_shape_pair_count++] = Pair<Shape2DSW *, Shape2DSW *>(body_shape, against_shape);
+ ExcludedShapeSW esp;
+ esp.local_shape = body_shape;
+ esp.against_object = col_obj;
+ esp.against_shape_index = shape_idx;
+ excluded_shape_pairs[excluded_shape_pair_count++] = esp;
}
}
}
@@ -645,7 +649,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int k = 0; k < excluded_shape_pair_count; k++) {
- if (excluded_shape_pairs[k].first == body_shape && excluded_shape_pairs[k].second == against_shape) {
+ if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) {
excluded = true;
break;
}
@@ -776,7 +780,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
bool excluded = false;
for (int k = 0; k < excluded_shape_pair_count; k++) {
- if (excluded_shape_pairs[k].first == body_shape && excluded_shape_pairs[k].second == against_shape) {
+ if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) {
excluded = true;
break;
}
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index ed6136e372..c7e7497397 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -71,6 +71,12 @@ public:
};
private:
+ struct ExcludedShapeSW {
+ Shape2DSW *local_shape;
+ const CollisionObject2DSW *against_object;
+ int against_shape_index;
+ };
+
uint64_t elapsed_time[ELAPSED_TIME_MAX];
Physics2DDirectSpaceStateSW *direct_access;
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index 06966e2452..b42b85b1be 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -92,16 +92,16 @@ void Physics2DDirectBodyState::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_contact_count"), &Physics2DDirectBodyState::get_contact_count);
- ClassDB::bind_method(D_METHOD("get_contact_local_pos", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_position);
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_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_position);
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", "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_contact_collider_velocity_at_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_velocity_at_position);
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"), &Physics2DDirectBodyState::get_space_state);
@@ -561,7 +561,7 @@ void Physics2DServer::_bind_methods() {
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(D_METHOD("body_apply_impulse", "body", "pos", "impulse"), &Physics2DServer::body_apply_impulse);
+ ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "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);
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index cd6a20e6b8..34f885db1d 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -65,17 +65,17 @@ public:
virtual int get_contact_count() const = 0;
- virtual Vector2 get_contact_local_pos(int p_contact_idx) const = 0;
+ virtual Vector2 get_contact_local_position(int p_contact_idx) const = 0;
virtual Vector2 get_contact_local_normal(int p_contact_idx) const = 0;
virtual int get_contact_local_shape(int p_contact_idx) const = 0;
virtual RID get_contact_collider(int p_contact_idx) const = 0;
- virtual Vector2 get_contact_collider_pos(int p_contact_idx) const = 0;
+ virtual Vector2 get_contact_collider_position(int p_contact_idx) const = 0;
virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0;
virtual Object *get_contact_collider_object(int p_contact_idx) const;
virtual int get_contact_collider_shape(int p_contact_idx) const = 0;
virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const = 0;
- virtual Vector2 get_contact_collider_velocity_at_pos(int p_contact_idx) const = 0;
+ virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0;
virtual real_t get_step() const = 0;
virtual void integrate_forces();
@@ -283,7 +283,7 @@ public:
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const = 0;
- // this function only works on fixed process, errors and returns null otherwise
+ // this function only works on physics process, errors and returns null otherwise
virtual Physics2DDirectSpaceState *space_get_direct_state(RID p_space) = 0;
virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) = 0;
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index 28ab31b8f6..0e54867ee1 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -89,8 +89,8 @@ void PhysicsDirectBodyState::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState::set_transform);
ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState::get_transform);
- 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("add_force", "force", "position"), &PhysicsDirectBodyState::add_force);
+ ClassDB::bind_method(D_METHOD("apply_impulse", "position", "j"), &PhysicsDirectBodyState::apply_impulse);
ClassDB::bind_method(D_METHOD("apply_torqe_impulse", "j"), &PhysicsDirectBodyState::apply_torque_impulse);
ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState::set_sleep_state);
@@ -98,15 +98,15 @@ void PhysicsDirectBodyState::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_contact_count"), &PhysicsDirectBodyState::get_contact_count);
- ClassDB::bind_method(D_METHOD("get_contact_local_pos", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_position);
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_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_position);
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_contact_collider_velocity_at_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_velocity_at_position);
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"), &PhysicsDirectBodyState::get_space_state);
@@ -482,7 +482,7 @@ void PhysicsServer::_bind_methods() {
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(D_METHOD("body_apply_impulse", "body", "pos", "impulse"), &PhysicsServer::body_apply_impulse);
+ ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "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);
diff --git a/servers/physics_server.h b/servers/physics_server.h
index c6d312e0fe..7012caeae6 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -71,16 +71,16 @@ public:
virtual int get_contact_count() const = 0;
- virtual Vector3 get_contact_local_pos(int p_contact_idx) const = 0;
+ virtual Vector3 get_contact_local_position(int p_contact_idx) const = 0;
virtual Vector3 get_contact_local_normal(int p_contact_idx) const = 0;
virtual int get_contact_local_shape(int p_contact_idx) const = 0;
virtual RID get_contact_collider(int p_contact_idx) const = 0;
- virtual Vector3 get_contact_collider_pos(int p_contact_idx) const = 0;
+ virtual Vector3 get_contact_collider_position(int p_contact_idx) const = 0;
virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0;
virtual Object *get_contact_collider_object(int p_contact_idx) const;
virtual int get_contact_collider_shape(int p_contact_idx) const = 0;
- virtual Vector3 get_contact_collider_velocity_at_pos(int p_contact_idx) const = 0;
+ virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0;
virtual real_t get_step() const = 0;
virtual void integrate_forces();
@@ -276,7 +276,7 @@ public:
virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0;
virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const = 0;
- // this function only works on fixed process, errors and returns null otherwise
+ // this function only works on physics process, errors and returns null otherwise
virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space) = 0;
virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) = 0;
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 344c10089a..b3f6b243de 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -53,7 +53,7 @@ public:
virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg) = 0;
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
- virtual void environment_set_sky_scale(RID p_env, float p_scale) = 0;
+ virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 6ad433268f..b2a11deea1 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -267,6 +267,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_CF_BREAK, "break" },
{ TK_CF_CONTINUE, "continue" },
{ TK_CF_RETURN, "return" },
+ { TK_CF_DISCARD, "discard" },
{ TK_UNIFORM, "uniform" },
{ TK_VARYING, "varying" },
{ TK_ARG_IN, "in" },
@@ -1377,6 +1378,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
{ "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
{ "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
+ { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
+ { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
+ { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
+ { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID } },
//builtins - common
{ "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
{ "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
@@ -1740,8 +1745,6 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID } },
{ "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID } },
- { "textureScreen", TYPE_VEC4, { TYPE_VEC2, TYPE_VOID } },
-
{ "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID } },
{ "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID } },
{ "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID } },
@@ -3800,6 +3803,10 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct
func_node->return_type = type;
func_node->return_precision = precision;
+ if (p_functions.has(name)) {
+ func_node->can_discard = p_functions[name].can_discard;
+ }
+
func_node->body = alloc_node<BlockNode>();
func_node->body->parent_function = func_node;
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 91c5d430f5..7489ca7e3e 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -50,12 +50,6 @@ ShaderTypes::ShaderTypes() {
/*************** SPATIAL ***********************/
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["SRC_VERTEX"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["SRC_NORMAL"] = ShaderLanguage::TYPE_VEC3;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["SRC_BONES"] = ShaderLanguage::TYPE_IVEC4;
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["SRC_WEIGHTS"] = ShaderLanguage::TYPE_VEC4;
-
- shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3;
@@ -75,6 +69,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2;
@@ -89,7 +84,6 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
- shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT;
@@ -104,6 +98,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
@@ -115,10 +110,31 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_SPATIAL].functions["fragment"].can_discard = true;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = ShaderLanguage::TYPE_VEC2;
+
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3;
+
+ shader_modes[VS::SHADER_SPATIAL].functions["light"].can_discard = true;
+
shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix");
shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add");
shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub");
@@ -156,21 +172,19 @@ ShaderTypes::ShaderTypes() {
/************ CANVAS ITEM **************************/
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SRC_VERTEX"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX_COLOR"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["EXTRA_MATRIX"] = ShaderLanguage::TYPE_MAT4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["PARTICLE_CUSTOM"] = ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SRC_COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3;
@@ -179,13 +193,13 @@ ShaderTypes::ShaderTypes() {
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TIME"] = ShaderLanguage::TYPE_FLOAT;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D;
- shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true;
shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC2;
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 7c7ce46268..888fb29f93 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -589,11 +589,29 @@ class VisualServerRaster : public VisualServer {
#endif
void _draw_margins();
+ static void _changes_changed() {}
public:
+//if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed()
+//#define DEBUG_CHANGES
+
+#ifdef DEBUG_CHANGES
+ _FORCE_INLINE_ static void redraw_request() {
+ changes++;
+ _changes_changed();
+ }
+
+#define DISPLAY_CHANGED \
+ changes++; \
+ _changes_changed();
+
+#else
_FORCE_INLINE_ static void redraw_request() { changes++; }
-#define DISPLAY_CHANGED changes++;
+#define DISPLAY_CHANGED \
+ changes++;
+#endif
+// print_line(String("CHANGED: ") + __FUNCTION__);
#define BIND0R(m_r, m_name) \
m_r m_name() { return BINDBASE->m_name(); }
@@ -950,7 +968,7 @@ public:
BIND2(environment_set_background, RID, EnvironmentBG)
BIND2(environment_set_sky, RID, RID)
- BIND2(environment_set_sky_scale, RID, float)
+ BIND2(environment_set_sky_custom_fov, RID, float)
BIND2(environment_set_bg_color, RID, const Color &)
BIND2(environment_set_bg_energy, RID, float)
BIND2(environment_set_canvas_max_layer, RID, int)
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 5cf941b93d..caec890217 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -381,7 +381,7 @@ public:
FUNC2(environment_set_background, RID, EnvironmentBG)
FUNC2(environment_set_sky, RID, RID)
- FUNC2(environment_set_sky_scale, RID, float)
+ FUNC2(environment_set_sky_custom_fov, RID, float)
FUNC2(environment_set_bg_color, RID, const Color &)
FUNC2(environment_set_bg_energy, RID, float)
FUNC2(environment_set_canvas_max_layer, RID, int)
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 72f36f6b65..1cc097f50e 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -85,7 +85,7 @@ public:
enum TextureFlags {
TEXTURE_FLAG_MIPMAPS = 1, /// Enable automatic mipmap generation - when available
TEXTURE_FLAG_REPEAT = 2, /// Repeat texture (Tiling), otherwise Clamping
- TEXTURE_FLAG_FILTER = 4, /// Create texure with linear (or available) filter
+ TEXTURE_FLAG_FILTER = 4, /// Create texture with linear (or available) filter
TEXTURE_FLAG_ANISOTROPIC_FILTER = 8,
TEXTURE_FLAG_CONVERT_TO_LINEAR = 16,
TEXTURE_FLAG_MIRRORED_REPEAT = 32, /// Repeat texture, with alternate sections mirrored
@@ -637,7 +637,7 @@ public:
virtual void environment_set_background(RID p_env, EnvironmentBG p_bg) = 0;
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
- virtual void environment_set_sky_scale(RID p_env, float p_scale) = 0;
+ virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
diff --git a/thirdparty/README.md b/thirdparty/README.md
index 80fab9442b..c081ad29b6 100644
--- a/thirdparty/README.md
+++ b/thirdparty/README.md
@@ -59,11 +59,11 @@ Files extracted from upstream source:
Use UI font if exists, because it has tight vertial metrix and good for UI.
-### Mononoki Regular
+### Hack Regular
-- Upstream: https://github.com/madmalik/mononoki
-- Version: 1.2
-- License: OFL-1.1
+- Upstream: https://github.com/source-foundry/Hack
+- Version: 2.020
+- License: Hack Open Font License v2.0
### DroidSans*.ttf
diff --git a/thirdparty/fonts/Hack_Regular.ttf b/thirdparty/fonts/Hack_Regular.ttf
new file mode 100644
index 0000000000..a35ea2e4f4
--- /dev/null
+++ b/thirdparty/fonts/Hack_Regular.ttf
Binary files differ
diff --git a/thirdparty/fonts/LICENSE_Hack.md b/thirdparty/fonts/LICENSE_Hack.md
new file mode 100644
index 0000000000..e9fc8a1f87
--- /dev/null
+++ b/thirdparty/fonts/LICENSE_Hack.md
@@ -0,0 +1,64 @@
+## License
+
+Hack Copyright 2015, Christopher Simpkins with Reserved Font Name "Hack".
+
+Bitstream Vera Sans Mono Copyright 2003 Bitstream Inc. and licensed under the Bitstream Vera License with Reserved Font Names "Bitstream" and "Vera"
+
+DejaVu modifications of the original Bitstream Vera Sans Mono typeface have been committed to the public domain.
+
+
+
+This Font Software is licensed under the Hack Open Font License v2.0 and the Bitstream Vera License.
+
+These licenses are copied below.
+
+
+### Hack Open Font License v2.0
+
+(Version 1.0 - 06 September 2015)
+
+(Version 2.0 - 27 September 2015)
+
+Copyright 2015 by Christopher Simpkins. All Rights Reserved.
+
+DEFINITIONS
+
+"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
+
+PERMISSION AND CONDITIONS
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated source code, documentation, and binary files (the "Font Software"), to reproduce and distribute the modifications to the Bitstream Vera Font Software, including without limitation the rights to use, study, copy, merge, embed, modify, redistribute, and/or sell modified or unmodified copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
+
+(1) The above copyright notice and this permission notice shall be included in all modified and unmodified copies of the Font Software typefaces. These notices can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
+
+(2) The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing the word "Hack".
+
+(3) Neither the Font Software nor any of its individual components, in original or modified versions, may be sold by itself.
+
+TERMINATION
+
+This license becomes null and void if any of the above conditions are not met.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the names of Christopher Simpkins and the Author(s) of the Font Software shall not be used to promote, endorse or advertise any modified version, except to acknowledge the contribution(s) of Christopher Simpkins and the Author(s) or with their explicit written permission. For further information, contact: chris at sourcefoundry dot org.
+
+
+
+### BITSTREAM VERA LICENSE
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
+
+The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names.
+
+The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.
diff --git a/thirdparty/fonts/LICENSE_Mononoki b/thirdparty/fonts/LICENSE_Mononoki
deleted file mode 100644
index 6ef130c5ef..0000000000
--- a/thirdparty/fonts/LICENSE_Mononoki
+++ /dev/null
@@ -1,94 +0,0 @@
-Copyright (c) 2013, Matthias Tellen matthias.tellen@googlemail.com,
-with Reserved Font Name monoOne.
-
-This Font Software is licensed under the SIL Open Font License, Version 1.1.
-This license is copied below, and is also available with a FAQ at:
-http://scripts.sil.org/OFL
-
-
------------------------------------------------------------
-SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
------------------------------------------------------------
-
-PREAMBLE
-The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font creation
-efforts of academic and linguistic communities, and to provide a free and
-open framework in which fonts may be shared and improved in partnership
-with others.
-
-The OFL allows the licensed fonts to be used, studied, modified and
-redistributed freely as long as they are not sold by themselves. The
-fonts, including any derivative works, can be bundled, embedded,
-redistributed and/or sold with any software provided that any reserved
-names are not used by derivative works. The fonts and derivatives,
-however, cannot be released under any other type of license. The
-requirement for fonts to remain under this license does not apply
-to any document created using the fonts or their derivatives.
-
-DEFINITIONS
-"Font Software" refers to the set of files released by the Copyright
-Holder(s) under this license and clearly marked as such. This may
-include source files, build scripts and documentation.
-
-"Reserved Font Name" refers to any names specified as such after the
-copyright statement(s).
-
-"Original Version" refers to the collection of Font Software components as
-distributed by the Copyright Holder(s).
-
-"Modified Version" refers to any derivative made by adding to, deleting,
-or substituting -- in part or in whole -- any of the components of the
-Original Version, by changing formats or by porting the Font Software to a
-new environment.
-
-"Author" refers to any designer, engineer, programmer, technical
-writer or other person who contributed to the Font Software.
-
-PERMISSION & CONDITIONS
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the Font Software, to use, study, copy, merge, embed, modify,
-redistribute, and sell modified and unmodified copies of the Font
-Software, subject to the following conditions:
-
-1) Neither the Font Software nor any of its individual components,
-in Original or Modified Versions, may be sold by itself.
-
-2) Original or Modified Versions of the Font Software may be bundled,
-redistributed and/or sold with any software, provided that each copy
-contains the above copyright notice and this license. These can be
-included either as stand-alone text files, human-readable headers or
-in the appropriate machine-readable metadata fields within text or
-binary files as long as those fields can be easily viewed by the user.
-
-3) No Modified Version of the Font Software may use the Reserved Font
-Name(s) unless explicit written permission is granted by the corresponding
-Copyright Holder. This restriction only applies to the primary font name as
-presented to the users.
-
-4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
-Software shall not be used to promote, endorse or advertise any
-Modified Version, except to acknowledge the contribution(s) of the
-Copyright Holder(s) and the Author(s) or with their explicit written
-permission.
-
-5) The Font Software, modified or unmodified, in part or in whole,
-must be distributed entirely under this license, and must not be
-distributed under any other license. The requirement for fonts to
-remain under this license does not apply to any document created
-using the Font Software.
-
-TERMINATION
-This license becomes null and void if any of the above conditions are
-not met.
-
-DISCLAIMER
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
-DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
-OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/thirdparty/fonts/mononoki_Regular.ttf b/thirdparty/fonts/mononoki_Regular.ttf
deleted file mode 100644
index 9510ac85d1..0000000000
--- a/thirdparty/fonts/mononoki_Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/thirdparty/zstd/SCsub b/thirdparty/zstd/SCsub
new file mode 100644
index 0000000000..e8be1aaf44
--- /dev/null
+++ b/thirdparty/zstd/SCsub
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+
+Import('env')
+
+thirdparty_zstd_dir = "#thirdparty/zstd/"
+thirdparty_zstd_sources = [
+ "common/entropy_common.c",
+ "common/error_private.c",
+ "common/fse_decompress.c",
+ "common/pool.c",
+ "common/threading.c",
+ "common/xxhash.c",
+ "common/zstd_common.c",
+ "compress/fse_compress.c",
+ "compress/huf_compress.c",
+ "compress/zstd_compress.c",
+ "compress/zstdmt_compress.c",
+ "decompress/huf_decompress.c",
+ "decompress/zstd_decompress.c",
+]
+thirdparty_zstd_sources = [thirdparty_zstd_dir + file for file in thirdparty_zstd_sources]
+env.add_source_files(env.core_sources, thirdparty_zstd_sources)
+env.Append(CPPPATH=["#thirdparty/zstd", "#thirdparty/zstd/common"])