From 098fb976b62cf83c45ba16a955e828a06ef527bc Mon Sep 17 00:00:00 2001 From: Francois Belair Date: Sat, 15 Feb 2020 23:34:09 -0500 Subject: [PATCH] Add debugger to project Step-in/over/out Continue Pause (though since Godot pausing doesn't report a breakpoint, the editor doesn't change, but hitting pause again will resume) Locals, members and globals scopes for variables while broken Scope drilling and objects-within-objects, including for Object types Exceptions breaking to not allow continue/step-in/step/resume Stack trace and jumping between those frames The ability to launch a game instance to debug with or to attach to a debugger after the fact, a game instance pointing at the currently opened TSCN, or to specify a TSCN file. Active scene tree is displayed and its nodes can be accessed in the Inspector Inspector allows to browse nodes and values, and edit primitives (int, float, strings, bools.) --- .vscode/settings.json | 5 +- CHANGELOG.md | 3 + README.md | 11 + package.json | 166 +++- .../dark/icon_GUI_visibility_visible.svg | 3 + resources/dark/icon_a_r_v_r_anchor.svg | 3 + resources/dark/icon_a_r_v_r_camera.svg | 3 + resources/dark/icon_a_r_v_r_controller.svg | 3 + resources/dark/icon_a_r_v_r_origin.svg | 3 + resources/dark/icon_accept_dialog.svg | 3 + resources/dark/icon_animated_sprite.svg | 7 + resources/dark/icon_animated_sprite_3d.svg | 7 + resources/dark/icon_animation_player.svg | 3 + resources/dark/icon_animation_tree.svg | 3 + resources/dark/icon_animation_tree_player.svg | 3 + resources/dark/icon_area.svg | 3 + resources/dark/icon_area_2d.svg | 3 + resources/dark/icon_audio_stream_player.svg | 11 + .../dark/icon_audio_stream_player_2_d.svg | 11 + .../dark/icon_audio_stream_player_3_d.svg | 11 + resources/dark/icon_back_buffer_copy.svg | 3 + resources/dark/icon_baked_lightmap.svg | 3 + resources/dark/icon_bone_2_d.svg | 3 + resources/dark/icon_bone_attachment.svg | 3 + resources/dark/icon_button.svg | 3 + resources/dark/icon_c_p_u_particles.svg | 3 + resources/dark/icon_c_p_u_particles_2_d.svg | 3 + resources/dark/icon_camera.svg | 3 + resources/dark/icon_camera_2d.svg | 3 + resources/dark/icon_canvas_layer.svg | 3 + resources/dark/icon_canvas_modulate.svg | 10 + resources/dark/icon_center_container.svg | 3 + resources/dark/icon_check_box.svg | 3 + resources/dark/icon_check_button.svg | 3 + resources/dark/icon_clipped_camera.svg | 3 + resources/dark/icon_collision_polygon.svg | 3 + resources/dark/icon_collision_polygon_2d.svg | 3 + resources/dark/icon_collision_shape.svg | 3 + resources/dark/icon_collision_shape_2d.svg | 3 + resources/dark/icon_color_picker.svg | 3 + resources/dark/icon_color_picker_button.svg | 3 + resources/dark/icon_color_rect.svg | 10 + resources/dark/icon_cone_twist_joint.svg | 3 + resources/dark/icon_confirmation_dialog.svg | 3 + resources/dark/icon_container.svg | 3 + resources/dark/icon_control.svg | 3 + .../dark/icon_damped_spring_joint_2d.svg | 6 + resources/dark/icon_directional_light.svg | 3 + resources/dark/icon_edit.svg | 5 + resources/dark/icon_file_dialog.svg | 3 + resources/dark/icon_g_i_probe.svg | 3 + resources/dark/icon_generic_6_d_o_f_joint.svg | 3 + resources/dark/icon_graph_edit.svg | 6 + resources/dark/icon_graph_node.svg | 6 + resources/dark/icon_grid_container.svg | 3 + resources/dark/icon_groove_joint_2d.svg | 3 + resources/dark/icon_h_box_container.svg | 3 + resources/dark/icon_h_scroll_bar.svg | 3 + resources/dark/icon_h_separator.svg | 3 + resources/dark/icon_h_slider.svg | 3 + resources/dark/icon_h_split_container.svg | 3 + resources/dark/icon_h_t_t_p_request.svg | 3 + resources/dark/icon_hinge_joint.svg | 3 + resources/dark/icon_immediate_geometry.svg | 3 + resources/dark/icon_interpolated_camera.svg | 3 + resources/dark/icon_item_list.svg | 3 + resources/dark/icon_kinematic_body.svg | 3 + resources/dark/icon_kinematic_body_2d.svg | 3 + resources/dark/icon_label.svg | 3 + resources/dark/icon_light_2d.svg | 3 + resources/dark/icon_light_occluder_2d.svg | 3 + resources/dark/icon_line_2d.svg | 3 + resources/dark/icon_line_edit.svg | 3 + resources/dark/icon_link_button.svg | 3 + resources/dark/icon_listener.svg | 3 + resources/dark/icon_margin_container.svg | 6 + resources/dark/icon_menu_button.svg | 3 + resources/dark/icon_mesh_instance.svg | 3 + resources/dark/icon_mesh_instance_2d.svg | 3 + resources/dark/icon_multi_mesh_instance.svg | 3 + .../dark/icon_multi_mesh_instance_2d.svg | 4 + resources/dark/icon_navigation.svg | 3 + resources/dark/icon_navigation_2d.svg | 3 + .../dark/icon_navigation_mesh_instance.svg | 3 + .../dark/icon_navigation_polygon_instance.svg | 6 + resources/dark/icon_nine_patch_rect.svg | 14 + resources/dark/icon_node.svg | 3 + resources/dark/icon_node_2d.svg | 3 + resources/dark/icon_omni_light.svg | 3 + resources/dark/icon_option_button.svg | 6 + resources/dark/icon_panel.svg | 3 + resources/dark/icon_panel_container.svg | 3 + resources/dark/icon_parallax_background.svg | 6 + resources/dark/icon_parallax_layer.svg | 6 + resources/dark/icon_particles.svg | 3 + resources/dark/icon_particles_2d.svg | 3 + resources/dark/icon_path.svg | 3 + resources/dark/icon_path_2d.svg | 3 + resources/dark/icon_path_follow.svg | 3 + resources/dark/icon_path_follow_2d.svg | 3 + resources/dark/icon_physical_bone.svg | 8 + resources/dark/icon_pin_joint.svg | 3 + resources/dark/icon_pin_joint_2d.svg | 3 + resources/dark/icon_polygon_2_d.svg | 3 + resources/dark/icon_popup.svg | 3 + resources/dark/icon_popup_dialog.svg | 3 + resources/dark/icon_popup_menu.svg | 3 + resources/dark/icon_popup_panel.svg | 3 + resources/dark/icon_position_2d.svg | 3 + resources/dark/icon_position_3d.svg | 3 + resources/dark/icon_progress_bar.svg | 3 + resources/dark/icon_ray_cast.svg | 3 + resources/dark/icon_ray_cast_2d.svg | 3 + resources/dark/icon_reference_rect.svg | 3 + resources/dark/icon_reflection_probe.svg | 3 + resources/dark/icon_refresh.svg | 3 + resources/dark/icon_remote_transform.svg | 3 + resources/dark/icon_remote_transform_2d.svg | 3 + resources/dark/icon_resource_preloader.svg | 3 + resources/dark/icon_rich_text_label.svg | 3 + resources/dark/icon_rigid_body.svg | 3 + resources/dark/icon_rigid_body_2d.svg | 3 + resources/dark/icon_scroll_container.svg | 3 + resources/dark/icon_skeleton.svg | 3 + resources/dark/icon_skeleton_2d.svg | 3 + resources/dark/icon_skeleton_i_k.svg | 3 + resources/dark/icon_slider_joint.svg | 3 + resources/dark/icon_soft_body.svg | 3 + resources/dark/icon_spatial.svg | 3 + resources/dark/icon_spin_box.svg | 3 + resources/dark/icon_spot_light.svg | 3 + resources/dark/icon_spring_arm.svg | 8 + resources/dark/icon_sprite.svg | 3 + resources/dark/icon_sprite_3d.svg | 3 + resources/dark/icon_static_body.svg | 3 + resources/dark/icon_static_body_2d.svg | 6 + resources/dark/icon_tab_container.svg | 3 + resources/dark/icon_tabs.svg | 3 + resources/dark/icon_text_edit.svg | 6 + resources/dark/icon_texture_button.svg | 3 + resources/dark/icon_texture_progress.svg | 8 + resources/dark/icon_texture_rect.svg | 3 + resources/dark/icon_tile_map.svg | 3 + resources/dark/icon_timer.svg | 3 + resources/dark/icon_tool_button.svg | 3 + resources/dark/icon_touch_screen_button.svg | 3 + resources/dark/icon_tree.svg | 3 + resources/dark/icon_tween.svg | 3 + resources/dark/icon_v_box_container.svg | 3 + resources/dark/icon_v_scroll_bar.svg | 3 + resources/dark/icon_v_separator.svg | 3 + resources/dark/icon_v_slider.svg | 3 + resources/dark/icon_v_split_container.svg | 3 + resources/dark/icon_vehicle_body.svg | 3 + resources/dark/icon_vehicle_wheel.svg | 3 + resources/dark/icon_video_player.svg | 3 + resources/dark/icon_viewport.svg | 3 + resources/dark/icon_viewport_container.svg | 3 + resources/dark/icon_visibility_enabler.svg | 3 + resources/dark/icon_visibility_enabler_2d.svg | 3 + resources/dark/icon_visibility_notifier.svg | 3 + .../dark/icon_visibility_notifier_2d.svg | 3 + resources/dark/icon_window_dialog.svg | 3 + resources/dark/icon_world_environment.svg | 6 + resources/dark/icon_y_sort.svg | 3 + resources/hashes | 161 ++++ .../light/icon_GUI_visibility_visible.svg | 3 + resources/light/icon_a_r_v_r_anchor.svg | 3 + resources/light/icon_a_r_v_r_camera.svg | 3 + resources/light/icon_a_r_v_r_controller.svg | 3 + resources/light/icon_a_r_v_r_origin.svg | 3 + resources/light/icon_accept_dialog.svg | 3 + resources/light/icon_animated_sprite.svg | 7 + resources/light/icon_animated_sprite_3d.svg | 7 + resources/light/icon_animation_player.svg | 3 + resources/light/icon_animation_tree.svg | 3 + .../light/icon_animation_tree_player.svg | 3 + resources/light/icon_area.svg | 3 + resources/light/icon_area_2d.svg | 3 + resources/light/icon_audio_stream_player.svg | 11 + .../light/icon_audio_stream_player_2_d.svg | 11 + .../light/icon_audio_stream_player_3_d.svg | 11 + resources/light/icon_back_buffer_copy.svg | 3 + resources/light/icon_baked_lightmap.svg | 3 + resources/light/icon_bone_2_d.svg | 3 + resources/light/icon_bone_attachment.svg | 3 + resources/light/icon_button.svg | 3 + resources/light/icon_c_p_u_particles.svg | 3 + resources/light/icon_c_p_u_particles_2_d.svg | 3 + resources/light/icon_camera.svg | 3 + resources/light/icon_camera_2d.svg | 3 + resources/light/icon_canvas_layer.svg | 3 + resources/light/icon_canvas_modulate.svg | 10 + resources/light/icon_center_container.svg | 3 + resources/light/icon_check_box.svg | 3 + resources/light/icon_check_button.svg | 3 + resources/light/icon_clipped_camera.svg | 3 + resources/light/icon_collision_polygon.svg | 3 + resources/light/icon_collision_polygon_2d.svg | 3 + resources/light/icon_collision_shape.svg | 3 + resources/light/icon_collision_shape_2d.svg | 3 + resources/light/icon_color_picker.svg | 3 + resources/light/icon_color_picker_button.svg | 3 + resources/light/icon_color_rect.svg | 10 + resources/light/icon_cone_twist_joint.svg | 3 + resources/light/icon_confirmation_dialog.svg | 3 + resources/light/icon_container.svg | 3 + resources/light/icon_control.svg | 3 + .../light/icon_damped_spring_joint_2d.svg | 6 + resources/light/icon_directional_light.svg | 3 + resources/light/icon_edit.svg | 5 + resources/light/icon_file_dialog.svg | 3 + resources/light/icon_g_i_probe.svg | 3 + .../light/icon_generic_6_d_o_f_joint.svg | 3 + resources/light/icon_graph_edit.svg | 6 + resources/light/icon_graph_node.svg | 6 + resources/light/icon_grid_container.svg | 3 + resources/light/icon_groove_joint_2d.svg | 3 + resources/light/icon_h_box_container.svg | 3 + resources/light/icon_h_scroll_bar.svg | 3 + resources/light/icon_h_separator.svg | 3 + resources/light/icon_h_slider.svg | 3 + resources/light/icon_h_split_container.svg | 3 + resources/light/icon_h_t_t_p_request.svg | 3 + resources/light/icon_hinge_joint.svg | 3 + resources/light/icon_immediate_geometry.svg | 3 + resources/light/icon_interpolated_camera.svg | 3 + resources/light/icon_item_list.svg | 3 + resources/light/icon_kinematic_body.svg | 3 + resources/light/icon_kinematic_body_2d.svg | 3 + resources/light/icon_label.svg | 3 + resources/light/icon_light_2d.svg | 3 + resources/light/icon_light_occluder_2d.svg | 3 + resources/light/icon_line_2d.svg | 3 + resources/light/icon_line_edit.svg | 3 + resources/light/icon_link_button.svg | 3 + resources/light/icon_listener.svg | 3 + resources/light/icon_margin_container.svg | 6 + resources/light/icon_menu_button.svg | 3 + resources/light/icon_mesh_instance.svg | 3 + resources/light/icon_mesh_instance_2d.svg | 3 + resources/light/icon_multi_mesh_instance.svg | 3 + .../light/icon_multi_mesh_instance_2d.svg | 4 + resources/light/icon_navigation.svg | 3 + resources/light/icon_navigation_2d.svg | 3 + .../light/icon_navigation_mesh_instance.svg | 3 + .../icon_navigation_polygon_instance.svg | 6 + resources/light/icon_nine_patch_rect.svg | 14 + resources/light/icon_node.svg | 3 + resources/light/icon_node_2d.svg | 3 + resources/light/icon_omni_light.svg | 3 + resources/light/icon_option_button.svg | 6 + resources/light/icon_panel.svg | 3 + resources/light/icon_panel_container.svg | 3 + resources/light/icon_parallax_background.svg | 6 + resources/light/icon_parallax_layer.svg | 6 + resources/light/icon_particles.svg | 3 + resources/light/icon_particles_2d.svg | 3 + resources/light/icon_path.svg | 3 + resources/light/icon_path_2d.svg | 3 + resources/light/icon_path_follow.svg | 3 + resources/light/icon_path_follow_2d.svg | 3 + resources/light/icon_physical_bone.svg | 8 + resources/light/icon_pin_joint.svg | 3 + resources/light/icon_pin_joint_2d.svg | 3 + resources/light/icon_polygon_2_d.svg | 3 + resources/light/icon_popup.svg | 3 + resources/light/icon_popup_dialog.svg | 3 + resources/light/icon_popup_menu.svg | 3 + resources/light/icon_popup_panel.svg | 3 + resources/light/icon_position_2d.svg | 3 + resources/light/icon_position_3d.svg | 3 + resources/light/icon_progress_bar.svg | 3 + resources/light/icon_ray_cast.svg | 3 + resources/light/icon_ray_cast_2d.svg | 3 + resources/light/icon_reference_rect.svg | 3 + resources/light/icon_reflection_probe.svg | 3 + resources/light/icon_refresh.svg | 3 + resources/light/icon_remote_transform.svg | 3 + resources/light/icon_remote_transform_2d.svg | 3 + resources/light/icon_resource_preloader.svg | 3 + resources/light/icon_rich_text_label.svg | 3 + resources/light/icon_rigid_body.svg | 3 + resources/light/icon_rigid_body_2d.svg | 3 + resources/light/icon_scroll_container.svg | 3 + resources/light/icon_skeleton.svg | 3 + resources/light/icon_skeleton_2d.svg | 3 + resources/light/icon_skeleton_i_k.svg | 3 + resources/light/icon_slider_joint.svg | 3 + resources/light/icon_soft_body.svg | 3 + resources/light/icon_spatial.svg | 3 + resources/light/icon_spin_box.svg | 3 + resources/light/icon_spot_light.svg | 3 + resources/light/icon_spring_arm.svg | 8 + resources/light/icon_sprite.svg | 3 + resources/light/icon_sprite_3d.svg | 3 + resources/light/icon_static_body.svg | 3 + resources/light/icon_static_body_2d.svg | 6 + resources/light/icon_tab_container.svg | 3 + resources/light/icon_tabs.svg | 3 + resources/light/icon_text_edit.svg | 6 + resources/light/icon_texture_button.svg | 3 + resources/light/icon_texture_progress.svg | 8 + resources/light/icon_texture_rect.svg | 3 + resources/light/icon_tile_map.svg | 3 + resources/light/icon_timer.svg | 3 + resources/light/icon_tool_button.svg | 3 + resources/light/icon_touch_screen_button.svg | 3 + resources/light/icon_tree.svg | 3 + resources/light/icon_tween.svg | 3 + resources/light/icon_v_box_container.svg | 3 + resources/light/icon_v_scroll_bar.svg | 3 + resources/light/icon_v_separator.svg | 3 + resources/light/icon_v_slider.svg | 3 + resources/light/icon_v_split_container.svg | 3 + resources/light/icon_vehicle_body.svg | 3 + resources/light/icon_vehicle_wheel.svg | 3 + resources/light/icon_video_player.svg | 3 + resources/light/icon_viewport.svg | 3 + resources/light/icon_viewport_container.svg | 3 + resources/light/icon_visibility_enabler.svg | 3 + .../light/icon_visibility_enabler_2d.svg | 3 + resources/light/icon_visibility_notifier.svg | 3 + .../light/icon_visibility_notifier_2d.svg | 3 + resources/light/icon_window_dialog.svg | 3 + resources/light/icon_world_environment.svg | 6 + resources/light/icon_y_sort.svg | 3 + src/debugger/SceneTree/inspector_provider.ts | 433 +++++++++ src/debugger/SceneTree/scene_tree_provider.ts | 127 +++ src/debugger/SceneTree/tree_builders.ts | 164 ++++ src/debugger/communication/command.ts | 60 ++ src/debugger/communication/command_builder.ts | 58 ++ src/debugger/communication/godot_commands.ts | 147 +++ .../communication/server_controller.ts | 454 +++++++++ src/debugger/debug_adapter.ts | 3 + src/debugger/debugger_context.ts | 215 +++++ src/debugger/godot_debug.ts | 588 ++++++++++++ src/debugger/godot_debug_runtime.ts | 177 ++++ src/debugger/stringify.ts | 91 ++ src/debugger/variable_scope.ts | 316 ++++++ src/debugger/variant_parser.ts | 905 ++++++++++++++++++ src/extension.ts | 3 +- 342 files changed, 5261 insertions(+), 8 deletions(-) create mode 100644 resources/dark/icon_GUI_visibility_visible.svg create mode 100644 resources/dark/icon_a_r_v_r_anchor.svg create mode 100644 resources/dark/icon_a_r_v_r_camera.svg create mode 100644 resources/dark/icon_a_r_v_r_controller.svg create mode 100644 resources/dark/icon_a_r_v_r_origin.svg create mode 100644 resources/dark/icon_accept_dialog.svg create mode 100644 resources/dark/icon_animated_sprite.svg create mode 100644 resources/dark/icon_animated_sprite_3d.svg create mode 100644 resources/dark/icon_animation_player.svg create mode 100644 resources/dark/icon_animation_tree.svg create mode 100644 resources/dark/icon_animation_tree_player.svg create mode 100644 resources/dark/icon_area.svg create mode 100644 resources/dark/icon_area_2d.svg create mode 100644 resources/dark/icon_audio_stream_player.svg create mode 100644 resources/dark/icon_audio_stream_player_2_d.svg create mode 100644 resources/dark/icon_audio_stream_player_3_d.svg create mode 100644 resources/dark/icon_back_buffer_copy.svg create mode 100644 resources/dark/icon_baked_lightmap.svg create mode 100644 resources/dark/icon_bone_2_d.svg create mode 100644 resources/dark/icon_bone_attachment.svg create mode 100644 resources/dark/icon_button.svg create mode 100644 resources/dark/icon_c_p_u_particles.svg create mode 100644 resources/dark/icon_c_p_u_particles_2_d.svg create mode 100644 resources/dark/icon_camera.svg create mode 100644 resources/dark/icon_camera_2d.svg create mode 100644 resources/dark/icon_canvas_layer.svg create mode 100644 resources/dark/icon_canvas_modulate.svg create mode 100644 resources/dark/icon_center_container.svg create mode 100644 resources/dark/icon_check_box.svg create mode 100644 resources/dark/icon_check_button.svg create mode 100644 resources/dark/icon_clipped_camera.svg create mode 100644 resources/dark/icon_collision_polygon.svg create mode 100644 resources/dark/icon_collision_polygon_2d.svg create mode 100644 resources/dark/icon_collision_shape.svg create mode 100644 resources/dark/icon_collision_shape_2d.svg create mode 100644 resources/dark/icon_color_picker.svg create mode 100644 resources/dark/icon_color_picker_button.svg create mode 100644 resources/dark/icon_color_rect.svg create mode 100644 resources/dark/icon_cone_twist_joint.svg create mode 100644 resources/dark/icon_confirmation_dialog.svg create mode 100644 resources/dark/icon_container.svg create mode 100644 resources/dark/icon_control.svg create mode 100644 resources/dark/icon_damped_spring_joint_2d.svg create mode 100644 resources/dark/icon_directional_light.svg create mode 100644 resources/dark/icon_edit.svg create mode 100644 resources/dark/icon_file_dialog.svg create mode 100644 resources/dark/icon_g_i_probe.svg create mode 100644 resources/dark/icon_generic_6_d_o_f_joint.svg create mode 100644 resources/dark/icon_graph_edit.svg create mode 100644 resources/dark/icon_graph_node.svg create mode 100644 resources/dark/icon_grid_container.svg create mode 100644 resources/dark/icon_groove_joint_2d.svg create mode 100644 resources/dark/icon_h_box_container.svg create mode 100644 resources/dark/icon_h_scroll_bar.svg create mode 100644 resources/dark/icon_h_separator.svg create mode 100644 resources/dark/icon_h_slider.svg create mode 100644 resources/dark/icon_h_split_container.svg create mode 100644 resources/dark/icon_h_t_t_p_request.svg create mode 100644 resources/dark/icon_hinge_joint.svg create mode 100644 resources/dark/icon_immediate_geometry.svg create mode 100644 resources/dark/icon_interpolated_camera.svg create mode 100644 resources/dark/icon_item_list.svg create mode 100644 resources/dark/icon_kinematic_body.svg create mode 100644 resources/dark/icon_kinematic_body_2d.svg create mode 100644 resources/dark/icon_label.svg create mode 100644 resources/dark/icon_light_2d.svg create mode 100644 resources/dark/icon_light_occluder_2d.svg create mode 100644 resources/dark/icon_line_2d.svg create mode 100644 resources/dark/icon_line_edit.svg create mode 100644 resources/dark/icon_link_button.svg create mode 100644 resources/dark/icon_listener.svg create mode 100644 resources/dark/icon_margin_container.svg create mode 100644 resources/dark/icon_menu_button.svg create mode 100644 resources/dark/icon_mesh_instance.svg create mode 100644 resources/dark/icon_mesh_instance_2d.svg create mode 100644 resources/dark/icon_multi_mesh_instance.svg create mode 100644 resources/dark/icon_multi_mesh_instance_2d.svg create mode 100644 resources/dark/icon_navigation.svg create mode 100644 resources/dark/icon_navigation_2d.svg create mode 100644 resources/dark/icon_navigation_mesh_instance.svg create mode 100644 resources/dark/icon_navigation_polygon_instance.svg create mode 100644 resources/dark/icon_nine_patch_rect.svg create mode 100644 resources/dark/icon_node.svg create mode 100644 resources/dark/icon_node_2d.svg create mode 100644 resources/dark/icon_omni_light.svg create mode 100644 resources/dark/icon_option_button.svg create mode 100644 resources/dark/icon_panel.svg create mode 100644 resources/dark/icon_panel_container.svg create mode 100644 resources/dark/icon_parallax_background.svg create mode 100644 resources/dark/icon_parallax_layer.svg create mode 100644 resources/dark/icon_particles.svg create mode 100644 resources/dark/icon_particles_2d.svg create mode 100644 resources/dark/icon_path.svg create mode 100644 resources/dark/icon_path_2d.svg create mode 100644 resources/dark/icon_path_follow.svg create mode 100644 resources/dark/icon_path_follow_2d.svg create mode 100644 resources/dark/icon_physical_bone.svg create mode 100644 resources/dark/icon_pin_joint.svg create mode 100644 resources/dark/icon_pin_joint_2d.svg create mode 100644 resources/dark/icon_polygon_2_d.svg create mode 100644 resources/dark/icon_popup.svg create mode 100644 resources/dark/icon_popup_dialog.svg create mode 100644 resources/dark/icon_popup_menu.svg create mode 100644 resources/dark/icon_popup_panel.svg create mode 100644 resources/dark/icon_position_2d.svg create mode 100644 resources/dark/icon_position_3d.svg create mode 100644 resources/dark/icon_progress_bar.svg create mode 100644 resources/dark/icon_ray_cast.svg create mode 100644 resources/dark/icon_ray_cast_2d.svg create mode 100644 resources/dark/icon_reference_rect.svg create mode 100644 resources/dark/icon_reflection_probe.svg create mode 100644 resources/dark/icon_refresh.svg create mode 100644 resources/dark/icon_remote_transform.svg create mode 100644 resources/dark/icon_remote_transform_2d.svg create mode 100644 resources/dark/icon_resource_preloader.svg create mode 100644 resources/dark/icon_rich_text_label.svg create mode 100644 resources/dark/icon_rigid_body.svg create mode 100644 resources/dark/icon_rigid_body_2d.svg create mode 100644 resources/dark/icon_scroll_container.svg create mode 100644 resources/dark/icon_skeleton.svg create mode 100644 resources/dark/icon_skeleton_2d.svg create mode 100644 resources/dark/icon_skeleton_i_k.svg create mode 100644 resources/dark/icon_slider_joint.svg create mode 100644 resources/dark/icon_soft_body.svg create mode 100644 resources/dark/icon_spatial.svg create mode 100644 resources/dark/icon_spin_box.svg create mode 100644 resources/dark/icon_spot_light.svg create mode 100644 resources/dark/icon_spring_arm.svg create mode 100644 resources/dark/icon_sprite.svg create mode 100644 resources/dark/icon_sprite_3d.svg create mode 100644 resources/dark/icon_static_body.svg create mode 100644 resources/dark/icon_static_body_2d.svg create mode 100644 resources/dark/icon_tab_container.svg create mode 100644 resources/dark/icon_tabs.svg create mode 100644 resources/dark/icon_text_edit.svg create mode 100644 resources/dark/icon_texture_button.svg create mode 100644 resources/dark/icon_texture_progress.svg create mode 100644 resources/dark/icon_texture_rect.svg create mode 100644 resources/dark/icon_tile_map.svg create mode 100644 resources/dark/icon_timer.svg create mode 100644 resources/dark/icon_tool_button.svg create mode 100644 resources/dark/icon_touch_screen_button.svg create mode 100644 resources/dark/icon_tree.svg create mode 100644 resources/dark/icon_tween.svg create mode 100644 resources/dark/icon_v_box_container.svg create mode 100644 resources/dark/icon_v_scroll_bar.svg create mode 100644 resources/dark/icon_v_separator.svg create mode 100644 resources/dark/icon_v_slider.svg create mode 100644 resources/dark/icon_v_split_container.svg create mode 100644 resources/dark/icon_vehicle_body.svg create mode 100644 resources/dark/icon_vehicle_wheel.svg create mode 100644 resources/dark/icon_video_player.svg create mode 100644 resources/dark/icon_viewport.svg create mode 100644 resources/dark/icon_viewport_container.svg create mode 100644 resources/dark/icon_visibility_enabler.svg create mode 100644 resources/dark/icon_visibility_enabler_2d.svg create mode 100644 resources/dark/icon_visibility_notifier.svg create mode 100644 resources/dark/icon_visibility_notifier_2d.svg create mode 100644 resources/dark/icon_window_dialog.svg create mode 100644 resources/dark/icon_world_environment.svg create mode 100644 resources/dark/icon_y_sort.svg create mode 100644 resources/hashes create mode 100644 resources/light/icon_GUI_visibility_visible.svg create mode 100644 resources/light/icon_a_r_v_r_anchor.svg create mode 100644 resources/light/icon_a_r_v_r_camera.svg create mode 100644 resources/light/icon_a_r_v_r_controller.svg create mode 100644 resources/light/icon_a_r_v_r_origin.svg create mode 100644 resources/light/icon_accept_dialog.svg create mode 100644 resources/light/icon_animated_sprite.svg create mode 100644 resources/light/icon_animated_sprite_3d.svg create mode 100644 resources/light/icon_animation_player.svg create mode 100644 resources/light/icon_animation_tree.svg create mode 100644 resources/light/icon_animation_tree_player.svg create mode 100644 resources/light/icon_area.svg create mode 100644 resources/light/icon_area_2d.svg create mode 100644 resources/light/icon_audio_stream_player.svg create mode 100644 resources/light/icon_audio_stream_player_2_d.svg create mode 100644 resources/light/icon_audio_stream_player_3_d.svg create mode 100644 resources/light/icon_back_buffer_copy.svg create mode 100644 resources/light/icon_baked_lightmap.svg create mode 100644 resources/light/icon_bone_2_d.svg create mode 100644 resources/light/icon_bone_attachment.svg create mode 100644 resources/light/icon_button.svg create mode 100644 resources/light/icon_c_p_u_particles.svg create mode 100644 resources/light/icon_c_p_u_particles_2_d.svg create mode 100644 resources/light/icon_camera.svg create mode 100644 resources/light/icon_camera_2d.svg create mode 100644 resources/light/icon_canvas_layer.svg create mode 100644 resources/light/icon_canvas_modulate.svg create mode 100644 resources/light/icon_center_container.svg create mode 100644 resources/light/icon_check_box.svg create mode 100644 resources/light/icon_check_button.svg create mode 100644 resources/light/icon_clipped_camera.svg create mode 100644 resources/light/icon_collision_polygon.svg create mode 100644 resources/light/icon_collision_polygon_2d.svg create mode 100644 resources/light/icon_collision_shape.svg create mode 100644 resources/light/icon_collision_shape_2d.svg create mode 100644 resources/light/icon_color_picker.svg create mode 100644 resources/light/icon_color_picker_button.svg create mode 100644 resources/light/icon_color_rect.svg create mode 100644 resources/light/icon_cone_twist_joint.svg create mode 100644 resources/light/icon_confirmation_dialog.svg create mode 100644 resources/light/icon_container.svg create mode 100644 resources/light/icon_control.svg create mode 100644 resources/light/icon_damped_spring_joint_2d.svg create mode 100644 resources/light/icon_directional_light.svg create mode 100644 resources/light/icon_edit.svg create mode 100644 resources/light/icon_file_dialog.svg create mode 100644 resources/light/icon_g_i_probe.svg create mode 100644 resources/light/icon_generic_6_d_o_f_joint.svg create mode 100644 resources/light/icon_graph_edit.svg create mode 100644 resources/light/icon_graph_node.svg create mode 100644 resources/light/icon_grid_container.svg create mode 100644 resources/light/icon_groove_joint_2d.svg create mode 100644 resources/light/icon_h_box_container.svg create mode 100644 resources/light/icon_h_scroll_bar.svg create mode 100644 resources/light/icon_h_separator.svg create mode 100644 resources/light/icon_h_slider.svg create mode 100644 resources/light/icon_h_split_container.svg create mode 100644 resources/light/icon_h_t_t_p_request.svg create mode 100644 resources/light/icon_hinge_joint.svg create mode 100644 resources/light/icon_immediate_geometry.svg create mode 100644 resources/light/icon_interpolated_camera.svg create mode 100644 resources/light/icon_item_list.svg create mode 100644 resources/light/icon_kinematic_body.svg create mode 100644 resources/light/icon_kinematic_body_2d.svg create mode 100644 resources/light/icon_label.svg create mode 100644 resources/light/icon_light_2d.svg create mode 100644 resources/light/icon_light_occluder_2d.svg create mode 100644 resources/light/icon_line_2d.svg create mode 100644 resources/light/icon_line_edit.svg create mode 100644 resources/light/icon_link_button.svg create mode 100644 resources/light/icon_listener.svg create mode 100644 resources/light/icon_margin_container.svg create mode 100644 resources/light/icon_menu_button.svg create mode 100644 resources/light/icon_mesh_instance.svg create mode 100644 resources/light/icon_mesh_instance_2d.svg create mode 100644 resources/light/icon_multi_mesh_instance.svg create mode 100644 resources/light/icon_multi_mesh_instance_2d.svg create mode 100644 resources/light/icon_navigation.svg create mode 100644 resources/light/icon_navigation_2d.svg create mode 100644 resources/light/icon_navigation_mesh_instance.svg create mode 100644 resources/light/icon_navigation_polygon_instance.svg create mode 100644 resources/light/icon_nine_patch_rect.svg create mode 100644 resources/light/icon_node.svg create mode 100644 resources/light/icon_node_2d.svg create mode 100644 resources/light/icon_omni_light.svg create mode 100644 resources/light/icon_option_button.svg create mode 100644 resources/light/icon_panel.svg create mode 100644 resources/light/icon_panel_container.svg create mode 100644 resources/light/icon_parallax_background.svg create mode 100644 resources/light/icon_parallax_layer.svg create mode 100644 resources/light/icon_particles.svg create mode 100644 resources/light/icon_particles_2d.svg create mode 100644 resources/light/icon_path.svg create mode 100644 resources/light/icon_path_2d.svg create mode 100644 resources/light/icon_path_follow.svg create mode 100644 resources/light/icon_path_follow_2d.svg create mode 100644 resources/light/icon_physical_bone.svg create mode 100644 resources/light/icon_pin_joint.svg create mode 100644 resources/light/icon_pin_joint_2d.svg create mode 100644 resources/light/icon_polygon_2_d.svg create mode 100644 resources/light/icon_popup.svg create mode 100644 resources/light/icon_popup_dialog.svg create mode 100644 resources/light/icon_popup_menu.svg create mode 100644 resources/light/icon_popup_panel.svg create mode 100644 resources/light/icon_position_2d.svg create mode 100644 resources/light/icon_position_3d.svg create mode 100644 resources/light/icon_progress_bar.svg create mode 100644 resources/light/icon_ray_cast.svg create mode 100644 resources/light/icon_ray_cast_2d.svg create mode 100644 resources/light/icon_reference_rect.svg create mode 100644 resources/light/icon_reflection_probe.svg create mode 100644 resources/light/icon_refresh.svg create mode 100644 resources/light/icon_remote_transform.svg create mode 100644 resources/light/icon_remote_transform_2d.svg create mode 100644 resources/light/icon_resource_preloader.svg create mode 100644 resources/light/icon_rich_text_label.svg create mode 100644 resources/light/icon_rigid_body.svg create mode 100644 resources/light/icon_rigid_body_2d.svg create mode 100644 resources/light/icon_scroll_container.svg create mode 100644 resources/light/icon_skeleton.svg create mode 100644 resources/light/icon_skeleton_2d.svg create mode 100644 resources/light/icon_skeleton_i_k.svg create mode 100644 resources/light/icon_slider_joint.svg create mode 100644 resources/light/icon_soft_body.svg create mode 100644 resources/light/icon_spatial.svg create mode 100644 resources/light/icon_spin_box.svg create mode 100644 resources/light/icon_spot_light.svg create mode 100644 resources/light/icon_spring_arm.svg create mode 100644 resources/light/icon_sprite.svg create mode 100644 resources/light/icon_sprite_3d.svg create mode 100644 resources/light/icon_static_body.svg create mode 100644 resources/light/icon_static_body_2d.svg create mode 100644 resources/light/icon_tab_container.svg create mode 100644 resources/light/icon_tabs.svg create mode 100644 resources/light/icon_text_edit.svg create mode 100644 resources/light/icon_texture_button.svg create mode 100644 resources/light/icon_texture_progress.svg create mode 100644 resources/light/icon_texture_rect.svg create mode 100644 resources/light/icon_tile_map.svg create mode 100644 resources/light/icon_timer.svg create mode 100644 resources/light/icon_tool_button.svg create mode 100644 resources/light/icon_touch_screen_button.svg create mode 100644 resources/light/icon_tree.svg create mode 100644 resources/light/icon_tween.svg create mode 100644 resources/light/icon_v_box_container.svg create mode 100644 resources/light/icon_v_scroll_bar.svg create mode 100644 resources/light/icon_v_separator.svg create mode 100644 resources/light/icon_v_slider.svg create mode 100644 resources/light/icon_v_split_container.svg create mode 100644 resources/light/icon_vehicle_body.svg create mode 100644 resources/light/icon_vehicle_wheel.svg create mode 100644 resources/light/icon_video_player.svg create mode 100644 resources/light/icon_viewport.svg create mode 100644 resources/light/icon_viewport_container.svg create mode 100644 resources/light/icon_visibility_enabler.svg create mode 100644 resources/light/icon_visibility_enabler_2d.svg create mode 100644 resources/light/icon_visibility_notifier.svg create mode 100644 resources/light/icon_visibility_notifier_2d.svg create mode 100644 resources/light/icon_window_dialog.svg create mode 100644 resources/light/icon_world_environment.svg create mode 100644 resources/light/icon_y_sort.svg create mode 100644 src/debugger/SceneTree/inspector_provider.ts create mode 100644 src/debugger/SceneTree/scene_tree_provider.ts create mode 100644 src/debugger/SceneTree/tree_builders.ts create mode 100644 src/debugger/communication/command.ts create mode 100644 src/debugger/communication/command_builder.ts create mode 100644 src/debugger/communication/godot_commands.ts create mode 100644 src/debugger/communication/server_controller.ts create mode 100644 src/debugger/debug_adapter.ts create mode 100644 src/debugger/debugger_context.ts create mode 100644 src/debugger/godot_debug.ts create mode 100644 src/debugger/godot_debug_runtime.ts create mode 100644 src/debugger/stringify.ts create mode 100644 src/debugger/variable_scope.ts create mode 100644 src/debugger/variant_parser.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 30bf8c2..3017901 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,8 @@ "out": true // set this to false to include "out" folder in search results }, // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" + "typescript.tsc.autoDetect": "off", + + "prettier.useTabs": true, + } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bbceac..c978dbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +### 1.1 +* Add the debugger to the extension + ### 1.0.3 * Fix hover popup position for VSCode 1.42+ diff --git a/README.md b/README.md index a8595ed..b2a7d39 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ experience as comfortable as possible: - Ctrl + click on a variable or method call to jump to its definition - Full documentation of the Godot Engine's API supported - Run a Godot project from VS Code +- Debug your Godot project from VS Code with breakpoints, step-in, and call stack ![Showing the documentation on hover feature](img/godot-tools.png) @@ -32,6 +33,16 @@ The extension adds a few entries to the VS Code Command Palette under "Godot Too - Run the workspace as a Godot project - List Godot's native classes +## Debugger + +To configure the debugger: + +1. Open the command palette: +2. `>Debug: Open launch.json` +3. Select the Debug Godot configuration. +4. Change any relevant settings. +5. Press F5 to launch. + ## Settings ### Godot diff --git a/package.json b/package.json index c05f0d4..4a3dc19 100644 --- a/package.json +++ b/package.json @@ -2,20 +2,25 @@ "name": "godot-tools", "displayName": "godot-tools", "icon": "icon.png", - "version": "1.0.3", + "version": "1.1.0", "description": "Tools for game development with godot game engine", - "repository": "https://github.com/godotengine/godot-vscode-plugin", + "repository": { + "type": "git", + "url": "https://github.com/godotengine/godot-vscode-plugin" + }, "author": "The Godot Engine community", "publisher": "geequlim", "engines": { "vscode": "^1.33.0" }, "categories": [ - "Other" + "Other", + "Debuggers" ], "activationEvents": [ "workspaceContains:project.godot", - "onLanguage:gdscript" + "onLanguage:gdscript", + "onDebugResolve:godot" ], "main": "./out/extension.js", "scripts": { @@ -37,6 +42,38 @@ { "command": "godot-tool.list_native_classes", "title": "Godot Tools: List native classes of godot" + }, + { + "command": "godot-tool.debugger.inspect_node", + "title": "Inspect Remote Node", + "icon": { + "light": "resources/light/icon_GUI_visibility_visible.svg", + "dark": "resources/dark/icon_GUI_visibility_visible.svg" + } + }, + { + "command": "godot-tool.debugger.refresh_scene_tree", + "title": "Refresh", + "icon": { + "light": "resources/light/icon_refresh.svg", + "dark": "resources/dark/icon_refresh.svg" + } + }, + { + "command": "godot-tool.debugger.refresh_inspector", + "title": "Refresh", + "icon": { + "light": "resources/light/icon_refresh.svg", + "dark": "resources/dark/icon_refresh.svg" + } + }, + { + "command": "godot-tool.debugger.edit_value", + "title": "Edit value", + "icon": { + "light": "resources/light/icon_edit.svg", + "dark": "resources/dark/icon_edit.svg" + } } ], "configuration": { @@ -96,7 +133,121 @@ "language": "gdscript", "path": "./configurations/snippets.json" } - ] + ], + "debuggers": [ + { + "type": "godot", + "label": "Godot Debug", + "program": "./out/debugger/debugAdapter.js", + "runtime": "node", + "configurationAttributes": { + "launch": { + "required": [ + "project", + "port", + "address" + ], + "properties": { + "project": { + "type": "string", + "description": "Absolute path to a directory with a project.godot file.", + "default": "${workspaceFolder}" + }, + "port": { + "type": "number", + "description": "The port number for the Godot remote debugger to use.", + "default": 6007 + }, + "address": { + "type": "string", + "description": "The IP address for the Godot remote debugger to use.", + "default": "127.0.0.1" + }, + "launch_game_instance": { + "type": "boolean", + "description": "Whether to launch an instance of the workspace's game, or wait for a debug session to connect.", + "default": true + } + } + } + }, + "initialConfigurations": [ + { + "name": "Godot", + "type": "godot", + "request": "launch", + "project": "${workspaceFolder}", + "port": 6007, + "address": "127.0.0.1", + "launch_game_instance": true + } + ], + "configurationSnippets": [ + { + "label": "Godot Debug: Launch", + "description": "A new configuration for debugging a Godot project.", + "body": { + "type": "godot", + "request": "launch", + "project": "${workspaceFolder}", + "port": 6007, + "address": "127.0.0.1", + "launch_game_instance": true + } + } + ] + } + ], + "breakpoints": [ + { + "language": "gdscript" + } + ], + "views": { + "debug": [ + { + "id": "active-scene-tree", + "name": "Active Scene Tree", + "when": "inDebugMode && debugType == 'godot'" + }, + { + "id": "inspect-node", + "name": "Inspector", + "when": "inDebugMode && debugType == 'godot'" + } + ] + }, + "menus": { + "view/title": [ + { + "command": "godot-tool.debugger.refresh_scene_tree", + "when": "view == active-scene-tree", + "group": "navigation" + }, + { + "command": "godot-tool.debugger.refresh_inspector", + "when": "view == inspect-node", + "group": "navigation" + } + ], + "view/item/context": [ + { + "command": "godot-tool.debugger.inspect_node", + "when": "view == active-scene-tree", + "group": "inline" + }, + { + "command": "godot-tool.debugger.inspect_node", + "when": "view == inspect-node && viewItem == remote_object", + "group": "inline" + }, + { + "command": "godot-tool.debugger.edit_value", + "when": "view == inspect-node && viewItem == editable_value", + "group": "inline" + } + ] + } }, "devDependencies": { "@types/marked": "^0.6.5", @@ -112,6 +263,9 @@ "global": "^4.4.0", "marked": "^0.7.0", "vscode-languageclient": "^5.2.1", - "ws": "^7.0.0" + "ws": "^7.0.0", + "await-notify": "^1.0.1", + "terminate": "^2.1.2", + "vscode-debugadapter": "^1.38.0" } } diff --git a/resources/dark/icon_GUI_visibility_visible.svg b/resources/dark/icon_GUI_visibility_visible.svg new file mode 100644 index 0000000..e203119 --- /dev/null +++ b/resources/dark/icon_GUI_visibility_visible.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_a_r_v_r_anchor.svg b/resources/dark/icon_a_r_v_r_anchor.svg new file mode 100644 index 0000000..5bb7c53 --- /dev/null +++ b/resources/dark/icon_a_r_v_r_anchor.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_a_r_v_r_camera.svg b/resources/dark/icon_a_r_v_r_camera.svg new file mode 100644 index 0000000..123f277 --- /dev/null +++ b/resources/dark/icon_a_r_v_r_camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_a_r_v_r_controller.svg b/resources/dark/icon_a_r_v_r_controller.svg new file mode 100644 index 0000000..60487e3 --- /dev/null +++ b/resources/dark/icon_a_r_v_r_controller.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_a_r_v_r_origin.svg b/resources/dark/icon_a_r_v_r_origin.svg new file mode 100644 index 0000000..558fe79 --- /dev/null +++ b/resources/dark/icon_a_r_v_r_origin.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_accept_dialog.svg b/resources/dark/icon_accept_dialog.svg new file mode 100644 index 0000000..bed006d --- /dev/null +++ b/resources/dark/icon_accept_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_animated_sprite.svg b/resources/dark/icon_animated_sprite.svg new file mode 100644 index 0000000..044168b --- /dev/null +++ b/resources/dark/icon_animated_sprite.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/dark/icon_animated_sprite_3d.svg b/resources/dark/icon_animated_sprite_3d.svg new file mode 100644 index 0000000..69546be --- /dev/null +++ b/resources/dark/icon_animated_sprite_3d.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/dark/icon_animation_player.svg b/resources/dark/icon_animation_player.svg new file mode 100644 index 0000000..a68af49 --- /dev/null +++ b/resources/dark/icon_animation_player.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_animation_tree.svg b/resources/dark/icon_animation_tree.svg new file mode 100644 index 0000000..75ae516 --- /dev/null +++ b/resources/dark/icon_animation_tree.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_animation_tree_player.svg b/resources/dark/icon_animation_tree_player.svg new file mode 100644 index 0000000..75ae516 --- /dev/null +++ b/resources/dark/icon_animation_tree_player.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_area.svg b/resources/dark/icon_area.svg new file mode 100644 index 0000000..1ab7106 --- /dev/null +++ b/resources/dark/icon_area.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_area_2d.svg b/resources/dark/icon_area_2d.svg new file mode 100644 index 0000000..6ccd61e --- /dev/null +++ b/resources/dark/icon_area_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_audio_stream_player.svg b/resources/dark/icon_audio_stream_player.svg new file mode 100644 index 0000000..21e95af --- /dev/null +++ b/resources/dark/icon_audio_stream_player.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/dark/icon_audio_stream_player_2_d.svg b/resources/dark/icon_audio_stream_player_2_d.svg new file mode 100644 index 0000000..75b5241 --- /dev/null +++ b/resources/dark/icon_audio_stream_player_2_d.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/dark/icon_audio_stream_player_3_d.svg b/resources/dark/icon_audio_stream_player_3_d.svg new file mode 100644 index 0000000..85217f6 --- /dev/null +++ b/resources/dark/icon_audio_stream_player_3_d.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/dark/icon_back_buffer_copy.svg b/resources/dark/icon_back_buffer_copy.svg new file mode 100644 index 0000000..c7abc53 --- /dev/null +++ b/resources/dark/icon_back_buffer_copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_baked_lightmap.svg b/resources/dark/icon_baked_lightmap.svg new file mode 100644 index 0000000..b540a60 --- /dev/null +++ b/resources/dark/icon_baked_lightmap.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_bone_2_d.svg b/resources/dark/icon_bone_2_d.svg new file mode 100644 index 0000000..5585202 --- /dev/null +++ b/resources/dark/icon_bone_2_d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_bone_attachment.svg b/resources/dark/icon_bone_attachment.svg new file mode 100644 index 0000000..54c0a30 --- /dev/null +++ b/resources/dark/icon_bone_attachment.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_button.svg b/resources/dark/icon_button.svg new file mode 100644 index 0000000..37e627a --- /dev/null +++ b/resources/dark/icon_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_c_p_u_particles.svg b/resources/dark/icon_c_p_u_particles.svg new file mode 100644 index 0000000..01634eb --- /dev/null +++ b/resources/dark/icon_c_p_u_particles.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_c_p_u_particles_2_d.svg b/resources/dark/icon_c_p_u_particles_2_d.svg new file mode 100644 index 0000000..261659a --- /dev/null +++ b/resources/dark/icon_c_p_u_particles_2_d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_camera.svg b/resources/dark/icon_camera.svg new file mode 100644 index 0000000..42dcab8 --- /dev/null +++ b/resources/dark/icon_camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_camera_2d.svg b/resources/dark/icon_camera_2d.svg new file mode 100644 index 0000000..b12126e --- /dev/null +++ b/resources/dark/icon_camera_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_canvas_layer.svg b/resources/dark/icon_canvas_layer.svg new file mode 100644 index 0000000..8bd2541 --- /dev/null +++ b/resources/dark/icon_canvas_layer.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_canvas_modulate.svg b/resources/dark/icon_canvas_modulate.svg new file mode 100644 index 0000000..93e21ab --- /dev/null +++ b/resources/dark/icon_canvas_modulate.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/resources/dark/icon_center_container.svg b/resources/dark/icon_center_container.svg new file mode 100644 index 0000000..2159a20 --- /dev/null +++ b/resources/dark/icon_center_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_check_box.svg b/resources/dark/icon_check_box.svg new file mode 100644 index 0000000..aa63e1a --- /dev/null +++ b/resources/dark/icon_check_box.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_check_button.svg b/resources/dark/icon_check_button.svg new file mode 100644 index 0000000..0b60838 --- /dev/null +++ b/resources/dark/icon_check_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_clipped_camera.svg b/resources/dark/icon_clipped_camera.svg new file mode 100644 index 0000000..0e31510 --- /dev/null +++ b/resources/dark/icon_clipped_camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_collision_polygon.svg b/resources/dark/icon_collision_polygon.svg new file mode 100644 index 0000000..8b4b415 --- /dev/null +++ b/resources/dark/icon_collision_polygon.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_collision_polygon_2d.svg b/resources/dark/icon_collision_polygon_2d.svg new file mode 100644 index 0000000..e435366 --- /dev/null +++ b/resources/dark/icon_collision_polygon_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_collision_shape.svg b/resources/dark/icon_collision_shape.svg new file mode 100644 index 0000000..1ab14b1 --- /dev/null +++ b/resources/dark/icon_collision_shape.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_collision_shape_2d.svg b/resources/dark/icon_collision_shape_2d.svg new file mode 100644 index 0000000..71ab11b --- /dev/null +++ b/resources/dark/icon_collision_shape_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_color_picker.svg b/resources/dark/icon_color_picker.svg new file mode 100644 index 0000000..2f08260 --- /dev/null +++ b/resources/dark/icon_color_picker.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_color_picker_button.svg b/resources/dark/icon_color_picker_button.svg new file mode 100644 index 0000000..4eb3f9a --- /dev/null +++ b/resources/dark/icon_color_picker_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_color_rect.svg b/resources/dark/icon_color_rect.svg new file mode 100644 index 0000000..542361f --- /dev/null +++ b/resources/dark/icon_color_rect.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/resources/dark/icon_cone_twist_joint.svg b/resources/dark/icon_cone_twist_joint.svg new file mode 100644 index 0000000..2941436 --- /dev/null +++ b/resources/dark/icon_cone_twist_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_confirmation_dialog.svg b/resources/dark/icon_confirmation_dialog.svg new file mode 100644 index 0000000..86ce894 --- /dev/null +++ b/resources/dark/icon_confirmation_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_container.svg b/resources/dark/icon_container.svg new file mode 100644 index 0000000..345cb19 --- /dev/null +++ b/resources/dark/icon_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_control.svg b/resources/dark/icon_control.svg new file mode 100644 index 0000000..f767760 --- /dev/null +++ b/resources/dark/icon_control.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_damped_spring_joint_2d.svg b/resources/dark/icon_damped_spring_joint_2d.svg new file mode 100644 index 0000000..32163c5 --- /dev/null +++ b/resources/dark/icon_damped_spring_joint_2d.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_directional_light.svg b/resources/dark/icon_directional_light.svg new file mode 100644 index 0000000..f55d8b9 --- /dev/null +++ b/resources/dark/icon_directional_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_edit.svg b/resources/dark/icon_edit.svg new file mode 100644 index 0000000..96850e4 --- /dev/null +++ b/resources/dark/icon_edit.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/dark/icon_file_dialog.svg b/resources/dark/icon_file_dialog.svg new file mode 100644 index 0000000..1bfb86f --- /dev/null +++ b/resources/dark/icon_file_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_g_i_probe.svg b/resources/dark/icon_g_i_probe.svg new file mode 100644 index 0000000..8cbef11 --- /dev/null +++ b/resources/dark/icon_g_i_probe.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_generic_6_d_o_f_joint.svg b/resources/dark/icon_generic_6_d_o_f_joint.svg new file mode 100644 index 0000000..234f8c4 --- /dev/null +++ b/resources/dark/icon_generic_6_d_o_f_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_graph_edit.svg b/resources/dark/icon_graph_edit.svg new file mode 100644 index 0000000..9962d51 --- /dev/null +++ b/resources/dark/icon_graph_edit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_graph_node.svg b/resources/dark/icon_graph_node.svg new file mode 100644 index 0000000..7b803bc --- /dev/null +++ b/resources/dark/icon_graph_node.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_grid_container.svg b/resources/dark/icon_grid_container.svg new file mode 100644 index 0000000..f891f59 --- /dev/null +++ b/resources/dark/icon_grid_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_groove_joint_2d.svg b/resources/dark/icon_groove_joint_2d.svg new file mode 100644 index 0000000..cb34d30 --- /dev/null +++ b/resources/dark/icon_groove_joint_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_h_box_container.svg b/resources/dark/icon_h_box_container.svg new file mode 100644 index 0000000..32e6a1f --- /dev/null +++ b/resources/dark/icon_h_box_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_h_scroll_bar.svg b/resources/dark/icon_h_scroll_bar.svg new file mode 100644 index 0000000..fda3ce9 --- /dev/null +++ b/resources/dark/icon_h_scroll_bar.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_h_separator.svg b/resources/dark/icon_h_separator.svg new file mode 100644 index 0000000..19a7769 --- /dev/null +++ b/resources/dark/icon_h_separator.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_h_slider.svg b/resources/dark/icon_h_slider.svg new file mode 100644 index 0000000..cda1d01 --- /dev/null +++ b/resources/dark/icon_h_slider.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_h_split_container.svg b/resources/dark/icon_h_split_container.svg new file mode 100644 index 0000000..705cc0b --- /dev/null +++ b/resources/dark/icon_h_split_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_h_t_t_p_request.svg b/resources/dark/icon_h_t_t_p_request.svg new file mode 100644 index 0000000..f291bd4 --- /dev/null +++ b/resources/dark/icon_h_t_t_p_request.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_hinge_joint.svg b/resources/dark/icon_hinge_joint.svg new file mode 100644 index 0000000..053d0b7 --- /dev/null +++ b/resources/dark/icon_hinge_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_immediate_geometry.svg b/resources/dark/icon_immediate_geometry.svg new file mode 100644 index 0000000..ce11351 --- /dev/null +++ b/resources/dark/icon_immediate_geometry.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_interpolated_camera.svg b/resources/dark/icon_interpolated_camera.svg new file mode 100644 index 0000000..7d254e1 --- /dev/null +++ b/resources/dark/icon_interpolated_camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_item_list.svg b/resources/dark/icon_item_list.svg new file mode 100644 index 0000000..7a21d17 --- /dev/null +++ b/resources/dark/icon_item_list.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_kinematic_body.svg b/resources/dark/icon_kinematic_body.svg new file mode 100644 index 0000000..d6f9eed --- /dev/null +++ b/resources/dark/icon_kinematic_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_kinematic_body_2d.svg b/resources/dark/icon_kinematic_body_2d.svg new file mode 100644 index 0000000..b4058cd --- /dev/null +++ b/resources/dark/icon_kinematic_body_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_label.svg b/resources/dark/icon_label.svg new file mode 100644 index 0000000..d8b2d82 --- /dev/null +++ b/resources/dark/icon_label.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_light_2d.svg b/resources/dark/icon_light_2d.svg new file mode 100644 index 0000000..2b92eee --- /dev/null +++ b/resources/dark/icon_light_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_light_occluder_2d.svg b/resources/dark/icon_light_occluder_2d.svg new file mode 100644 index 0000000..c4e838f --- /dev/null +++ b/resources/dark/icon_light_occluder_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_line_2d.svg b/resources/dark/icon_line_2d.svg new file mode 100644 index 0000000..15a21f5 --- /dev/null +++ b/resources/dark/icon_line_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_line_edit.svg b/resources/dark/icon_line_edit.svg new file mode 100644 index 0000000..32a8794 --- /dev/null +++ b/resources/dark/icon_line_edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_link_button.svg b/resources/dark/icon_link_button.svg new file mode 100644 index 0000000..b3bba30 --- /dev/null +++ b/resources/dark/icon_link_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_listener.svg b/resources/dark/icon_listener.svg new file mode 100644 index 0000000..98c7069 --- /dev/null +++ b/resources/dark/icon_listener.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_margin_container.svg b/resources/dark/icon_margin_container.svg new file mode 100644 index 0000000..183b2bd --- /dev/null +++ b/resources/dark/icon_margin_container.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_menu_button.svg b/resources/dark/icon_menu_button.svg new file mode 100644 index 0000000..c1cac77 --- /dev/null +++ b/resources/dark/icon_menu_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_mesh_instance.svg b/resources/dark/icon_mesh_instance.svg new file mode 100644 index 0000000..2ed890f --- /dev/null +++ b/resources/dark/icon_mesh_instance.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_mesh_instance_2d.svg b/resources/dark/icon_mesh_instance_2d.svg new file mode 100644 index 0000000..3199be2 --- /dev/null +++ b/resources/dark/icon_mesh_instance_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_multi_mesh_instance.svg b/resources/dark/icon_multi_mesh_instance.svg new file mode 100644 index 0000000..78aabcc --- /dev/null +++ b/resources/dark/icon_multi_mesh_instance.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_multi_mesh_instance_2d.svg b/resources/dark/icon_multi_mesh_instance_2d.svg new file mode 100644 index 0000000..cc57849 --- /dev/null +++ b/resources/dark/icon_multi_mesh_instance_2d.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/dark/icon_navigation.svg b/resources/dark/icon_navigation.svg new file mode 100644 index 0000000..d10b990 --- /dev/null +++ b/resources/dark/icon_navigation.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_navigation_2d.svg b/resources/dark/icon_navigation_2d.svg new file mode 100644 index 0000000..c5c8382 --- /dev/null +++ b/resources/dark/icon_navigation_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_navigation_mesh_instance.svg b/resources/dark/icon_navigation_mesh_instance.svg new file mode 100644 index 0000000..7fbd8e8 --- /dev/null +++ b/resources/dark/icon_navigation_mesh_instance.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_navigation_polygon_instance.svg b/resources/dark/icon_navigation_polygon_instance.svg new file mode 100644 index 0000000..3989433 --- /dev/null +++ b/resources/dark/icon_navigation_polygon_instance.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_nine_patch_rect.svg b/resources/dark/icon_nine_patch_rect.svg new file mode 100644 index 0000000..33d7570 --- /dev/null +++ b/resources/dark/icon_nine_patch_rect.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/resources/dark/icon_node.svg b/resources/dark/icon_node.svg new file mode 100644 index 0000000..dc3c027 --- /dev/null +++ b/resources/dark/icon_node.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_node_2d.svg b/resources/dark/icon_node_2d.svg new file mode 100644 index 0000000..75d5e43 --- /dev/null +++ b/resources/dark/icon_node_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_omni_light.svg b/resources/dark/icon_omni_light.svg new file mode 100644 index 0000000..9e101f0 --- /dev/null +++ b/resources/dark/icon_omni_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_option_button.svg b/resources/dark/icon_option_button.svg new file mode 100644 index 0000000..78f435f --- /dev/null +++ b/resources/dark/icon_option_button.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_panel.svg b/resources/dark/icon_panel.svg new file mode 100644 index 0000000..6928d34 --- /dev/null +++ b/resources/dark/icon_panel.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_panel_container.svg b/resources/dark/icon_panel_container.svg new file mode 100644 index 0000000..9a4c113 --- /dev/null +++ b/resources/dark/icon_panel_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_parallax_background.svg b/resources/dark/icon_parallax_background.svg new file mode 100644 index 0000000..a81d69e --- /dev/null +++ b/resources/dark/icon_parallax_background.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_parallax_layer.svg b/resources/dark/icon_parallax_layer.svg new file mode 100644 index 0000000..afa6288 --- /dev/null +++ b/resources/dark/icon_parallax_layer.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_particles.svg b/resources/dark/icon_particles.svg new file mode 100644 index 0000000..c006658 --- /dev/null +++ b/resources/dark/icon_particles.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_particles_2d.svg b/resources/dark/icon_particles_2d.svg new file mode 100644 index 0000000..35b67ef --- /dev/null +++ b/resources/dark/icon_particles_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_path.svg b/resources/dark/icon_path.svg new file mode 100644 index 0000000..1d7b838 --- /dev/null +++ b/resources/dark/icon_path.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_path_2d.svg b/resources/dark/icon_path_2d.svg new file mode 100644 index 0000000..529b130 --- /dev/null +++ b/resources/dark/icon_path_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_path_follow.svg b/resources/dark/icon_path_follow.svg new file mode 100644 index 0000000..89a475c --- /dev/null +++ b/resources/dark/icon_path_follow.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_path_follow_2d.svg b/resources/dark/icon_path_follow_2d.svg new file mode 100644 index 0000000..46c9fca --- /dev/null +++ b/resources/dark/icon_path_follow_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_physical_bone.svg b/resources/dark/icon_physical_bone.svg new file mode 100644 index 0000000..93794b3 --- /dev/null +++ b/resources/dark/icon_physical_bone.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources/dark/icon_pin_joint.svg b/resources/dark/icon_pin_joint.svg new file mode 100644 index 0000000..2ee5773 --- /dev/null +++ b/resources/dark/icon_pin_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_pin_joint_2d.svg b/resources/dark/icon_pin_joint_2d.svg new file mode 100644 index 0000000..91f3ffc --- /dev/null +++ b/resources/dark/icon_pin_joint_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_polygon_2_d.svg b/resources/dark/icon_polygon_2_d.svg new file mode 100644 index 0000000..5a32403 --- /dev/null +++ b/resources/dark/icon_polygon_2_d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_popup.svg b/resources/dark/icon_popup.svg new file mode 100644 index 0000000..2eb53e9 --- /dev/null +++ b/resources/dark/icon_popup.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_popup_dialog.svg b/resources/dark/icon_popup_dialog.svg new file mode 100644 index 0000000..422be97 --- /dev/null +++ b/resources/dark/icon_popup_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_popup_menu.svg b/resources/dark/icon_popup_menu.svg new file mode 100644 index 0000000..140635b --- /dev/null +++ b/resources/dark/icon_popup_menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_popup_panel.svg b/resources/dark/icon_popup_panel.svg new file mode 100644 index 0000000..d8980ce --- /dev/null +++ b/resources/dark/icon_popup_panel.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_position_2d.svg b/resources/dark/icon_position_2d.svg new file mode 100644 index 0000000..b813033 --- /dev/null +++ b/resources/dark/icon_position_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_position_3d.svg b/resources/dark/icon_position_3d.svg new file mode 100644 index 0000000..5e94db9 --- /dev/null +++ b/resources/dark/icon_position_3d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_progress_bar.svg b/resources/dark/icon_progress_bar.svg new file mode 100644 index 0000000..ca6e417 --- /dev/null +++ b/resources/dark/icon_progress_bar.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_ray_cast.svg b/resources/dark/icon_ray_cast.svg new file mode 100644 index 0000000..0a6e4cb --- /dev/null +++ b/resources/dark/icon_ray_cast.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_ray_cast_2d.svg b/resources/dark/icon_ray_cast_2d.svg new file mode 100644 index 0000000..1468cd9 --- /dev/null +++ b/resources/dark/icon_ray_cast_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_reference_rect.svg b/resources/dark/icon_reference_rect.svg new file mode 100644 index 0000000..140b4a2 --- /dev/null +++ b/resources/dark/icon_reference_rect.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_reflection_probe.svg b/resources/dark/icon_reflection_probe.svg new file mode 100644 index 0000000..ff85399 --- /dev/null +++ b/resources/dark/icon_reflection_probe.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_refresh.svg b/resources/dark/icon_refresh.svg new file mode 100644 index 0000000..3e7938b --- /dev/null +++ b/resources/dark/icon_refresh.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_remote_transform.svg b/resources/dark/icon_remote_transform.svg new file mode 100644 index 0000000..59408fe --- /dev/null +++ b/resources/dark/icon_remote_transform.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_remote_transform_2d.svg b/resources/dark/icon_remote_transform_2d.svg new file mode 100644 index 0000000..1f515e2 --- /dev/null +++ b/resources/dark/icon_remote_transform_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_resource_preloader.svg b/resources/dark/icon_resource_preloader.svg new file mode 100644 index 0000000..98d6e18 --- /dev/null +++ b/resources/dark/icon_resource_preloader.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_rich_text_label.svg b/resources/dark/icon_rich_text_label.svg new file mode 100644 index 0000000..ae87273 --- /dev/null +++ b/resources/dark/icon_rich_text_label.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_rigid_body.svg b/resources/dark/icon_rigid_body.svg new file mode 100644 index 0000000..1f7ffcb --- /dev/null +++ b/resources/dark/icon_rigid_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_rigid_body_2d.svg b/resources/dark/icon_rigid_body_2d.svg new file mode 100644 index 0000000..424e0c4 --- /dev/null +++ b/resources/dark/icon_rigid_body_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_scroll_container.svg b/resources/dark/icon_scroll_container.svg new file mode 100644 index 0000000..930c0a2 --- /dev/null +++ b/resources/dark/icon_scroll_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_skeleton.svg b/resources/dark/icon_skeleton.svg new file mode 100644 index 0000000..1f34427 --- /dev/null +++ b/resources/dark/icon_skeleton.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_skeleton_2d.svg b/resources/dark/icon_skeleton_2d.svg new file mode 100644 index 0000000..b298c87 --- /dev/null +++ b/resources/dark/icon_skeleton_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_skeleton_i_k.svg b/resources/dark/icon_skeleton_i_k.svg new file mode 100644 index 0000000..0b5759d --- /dev/null +++ b/resources/dark/icon_skeleton_i_k.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_slider_joint.svg b/resources/dark/icon_slider_joint.svg new file mode 100644 index 0000000..80d956b --- /dev/null +++ b/resources/dark/icon_slider_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_soft_body.svg b/resources/dark/icon_soft_body.svg new file mode 100644 index 0000000..d5f32d5 --- /dev/null +++ b/resources/dark/icon_soft_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_spatial.svg b/resources/dark/icon_spatial.svg new file mode 100644 index 0000000..7f68d62 --- /dev/null +++ b/resources/dark/icon_spatial.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_spin_box.svg b/resources/dark/icon_spin_box.svg new file mode 100644 index 0000000..3fe639f --- /dev/null +++ b/resources/dark/icon_spin_box.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_spot_light.svg b/resources/dark/icon_spot_light.svg new file mode 100644 index 0000000..622326f --- /dev/null +++ b/resources/dark/icon_spot_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_spring_arm.svg b/resources/dark/icon_spring_arm.svg new file mode 100644 index 0000000..a79efde --- /dev/null +++ b/resources/dark/icon_spring_arm.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources/dark/icon_sprite.svg b/resources/dark/icon_sprite.svg new file mode 100644 index 0000000..592bdd2 --- /dev/null +++ b/resources/dark/icon_sprite.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_sprite_3d.svg b/resources/dark/icon_sprite_3d.svg new file mode 100644 index 0000000..ed1e7c3 --- /dev/null +++ b/resources/dark/icon_sprite_3d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_static_body.svg b/resources/dark/icon_static_body.svg new file mode 100644 index 0000000..450ced8 --- /dev/null +++ b/resources/dark/icon_static_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_static_body_2d.svg b/resources/dark/icon_static_body_2d.svg new file mode 100644 index 0000000..cdea347 --- /dev/null +++ b/resources/dark/icon_static_body_2d.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_tab_container.svg b/resources/dark/icon_tab_container.svg new file mode 100644 index 0000000..736fee2 --- /dev/null +++ b/resources/dark/icon_tab_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_tabs.svg b/resources/dark/icon_tabs.svg new file mode 100644 index 0000000..468fcae --- /dev/null +++ b/resources/dark/icon_tabs.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_text_edit.svg b/resources/dark/icon_text_edit.svg new file mode 100644 index 0000000..52725ea --- /dev/null +++ b/resources/dark/icon_text_edit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_texture_button.svg b/resources/dark/icon_texture_button.svg new file mode 100644 index 0000000..0834ce7 --- /dev/null +++ b/resources/dark/icon_texture_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_texture_progress.svg b/resources/dark/icon_texture_progress.svg new file mode 100644 index 0000000..b48f38e --- /dev/null +++ b/resources/dark/icon_texture_progress.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources/dark/icon_texture_rect.svg b/resources/dark/icon_texture_rect.svg new file mode 100644 index 0000000..416bbe5 --- /dev/null +++ b/resources/dark/icon_texture_rect.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_tile_map.svg b/resources/dark/icon_tile_map.svg new file mode 100644 index 0000000..d65feaf --- /dev/null +++ b/resources/dark/icon_tile_map.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_timer.svg b/resources/dark/icon_timer.svg new file mode 100644 index 0000000..6aed859 --- /dev/null +++ b/resources/dark/icon_timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_tool_button.svg b/resources/dark/icon_tool_button.svg new file mode 100644 index 0000000..c3f2ea6 --- /dev/null +++ b/resources/dark/icon_tool_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_touch_screen_button.svg b/resources/dark/icon_touch_screen_button.svg new file mode 100644 index 0000000..1a08e36 --- /dev/null +++ b/resources/dark/icon_touch_screen_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_tree.svg b/resources/dark/icon_tree.svg new file mode 100644 index 0000000..58338e6 --- /dev/null +++ b/resources/dark/icon_tree.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_tween.svg b/resources/dark/icon_tween.svg new file mode 100644 index 0000000..ad8bd94 --- /dev/null +++ b/resources/dark/icon_tween.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_v_box_container.svg b/resources/dark/icon_v_box_container.svg new file mode 100644 index 0000000..0e37156 --- /dev/null +++ b/resources/dark/icon_v_box_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_v_scroll_bar.svg b/resources/dark/icon_v_scroll_bar.svg new file mode 100644 index 0000000..d793e3a --- /dev/null +++ b/resources/dark/icon_v_scroll_bar.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_v_separator.svg b/resources/dark/icon_v_separator.svg new file mode 100644 index 0000000..bb07e5d --- /dev/null +++ b/resources/dark/icon_v_separator.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_v_slider.svg b/resources/dark/icon_v_slider.svg new file mode 100644 index 0000000..fa9ff88 --- /dev/null +++ b/resources/dark/icon_v_slider.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_v_split_container.svg b/resources/dark/icon_v_split_container.svg new file mode 100644 index 0000000..3ac0a63 --- /dev/null +++ b/resources/dark/icon_v_split_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_vehicle_body.svg b/resources/dark/icon_vehicle_body.svg new file mode 100644 index 0000000..92120a4 --- /dev/null +++ b/resources/dark/icon_vehicle_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_vehicle_wheel.svg b/resources/dark/icon_vehicle_wheel.svg new file mode 100644 index 0000000..cbe7552 --- /dev/null +++ b/resources/dark/icon_vehicle_wheel.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_video_player.svg b/resources/dark/icon_video_player.svg new file mode 100644 index 0000000..52b4365 --- /dev/null +++ b/resources/dark/icon_video_player.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_viewport.svg b/resources/dark/icon_viewport.svg new file mode 100644 index 0000000..e7ea83f --- /dev/null +++ b/resources/dark/icon_viewport.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_viewport_container.svg b/resources/dark/icon_viewport_container.svg new file mode 100644 index 0000000..a251833 --- /dev/null +++ b/resources/dark/icon_viewport_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_visibility_enabler.svg b/resources/dark/icon_visibility_enabler.svg new file mode 100644 index 0000000..222f5d7 --- /dev/null +++ b/resources/dark/icon_visibility_enabler.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_visibility_enabler_2d.svg b/resources/dark/icon_visibility_enabler_2d.svg new file mode 100644 index 0000000..27dd937 --- /dev/null +++ b/resources/dark/icon_visibility_enabler_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_visibility_notifier.svg b/resources/dark/icon_visibility_notifier.svg new file mode 100644 index 0000000..96d0cbf --- /dev/null +++ b/resources/dark/icon_visibility_notifier.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_visibility_notifier_2d.svg b/resources/dark/icon_visibility_notifier_2d.svg new file mode 100644 index 0000000..3e90d8a --- /dev/null +++ b/resources/dark/icon_visibility_notifier_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_window_dialog.svg b/resources/dark/icon_window_dialog.svg new file mode 100644 index 0000000..dbf49fd --- /dev/null +++ b/resources/dark/icon_window_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/dark/icon_world_environment.svg b/resources/dark/icon_world_environment.svg new file mode 100644 index 0000000..06cff10 --- /dev/null +++ b/resources/dark/icon_world_environment.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/dark/icon_y_sort.svg b/resources/dark/icon_y_sort.svg new file mode 100644 index 0000000..18b0a03 --- /dev/null +++ b/resources/dark/icon_y_sort.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/hashes b/resources/hashes new file mode 100644 index 0000000..7ca3616 --- /dev/null +++ b/resources/hashes @@ -0,0 +1,161 @@ +icon_accept_dialog acd6ad21bbb15e44cda96d9063a8901f +icon_animated_sprite 270529e7145defc9e9f25a9662673536 +icon_animated_sprite_3d 7b0302f87d63ed013ba494a8d9218dc5 +icon_animation_player b2ede8ebdb67a4c8cbcb9c59d7b7e6b6 +icon_animation_tree a2fdc32212441cff75b0e5494c1b925e +icon_animation_tree_player a2fdc32212441cff75b0e5494c1b925e +icon_area 91092ba21aea2dd4928fcdd938ff6e46 +icon_area_2d 05545caafbc5d05bba2fc6de5928181e +icon_audio_stream_player 45e9947805241cce604d16b441ce6949 +icon_audio_stream_player_2_d c1e674966c627afa39068d8b8b88ddaf +icon_audio_stream_player_3_d ea1f6cc9624afa009419246b1e040ad6 +icon_a_r_v_r_anchor c2fa7d8b07c8753708ccd51fbfb750fb +icon_a_r_v_r_camera 57c9ee0a702fe1a03dd2f396ff304615 +icon_a_r_v_r_controller 5f39b1c4684b3a48a660f740fa9995d3 +icon_a_r_v_r_origin 9ee2aae61803f98f1913cbbfe6086e95 +icon_back_buffer_copy 1e8f39900ca051e8a9eeabc36a407135 +icon_baked_lightmap 99174fff2b5652da2c9bdf7c8869ef6c +icon_bone_2_d 04b832eadd359da67c3b51ac5198c2d2 +icon_bone_attachment b69dccb74bec608ea2bf6aedc3554d8d +icon_button a446868b97eb18615b1c0a649134535c +icon_camera 6b0ecdc420e94bdd635029132b7cf46a +icon_camera_2d f80f29d6af02ef6375c57fdf047900f8 +icon_canvas_layer 9d9d90ac888f833a0380b5b79819bda8 +icon_canvas_modulate eda1bd7d03c35d1f0762aa186b300480 +icon_center_container 04c7fecadc8f545fa39531e4398305e5 +icon_check_box a52807384ac7c3ad00ea2ef342501873 +icon_check_button 10c5f6800dd76afd34131a7cfc5208b5 +icon_clipped_camera 8c35cee49100276370afdb1492d8b649 +icon_collision_polygon c34c38ea1b38d6fb6d4f53817df41360 +icon_collision_polygon_2d 4bc34f2d5ff14a1c2ebf71c73942c21c +icon_collision_shape 8d4af566441db96cbc91b39d96912b27 +icon_collision_shape_2d c0e2b1ff8f25204d410ca0999d63c73d +icon_color_picker 720b46e85ba2f78e9192d6ed256340c1 +icon_color_picker_button 257604d44e7e23830d1983c86d4b555c +icon_color_rect 895c788b6b267baf2362622ff6f4f63b +icon_cone_twist_joint 79de179e62442e6571f5308a4605a6d2 +icon_confirmation_dialog 492c281c1d2512085ddbc8aaaa2ccf4f +icon_container df91572922e2a08dada37efbc1c4fea2 +icon_control ec59a74f624ed7a94a1ff24fd7bf3b93 +icon_c_p_u_particles b0e67fd89e1dee6663d87609b91c97a3 +icon_c_p_u_particles_2_d 221a2e65f720f258fb840f846cf3b191 +icon_damped_spring_joint_2d 483fc5a895c9b61b12c08e4ec78f14d8 +icon_directional_light ae154b892f967b6007dd56cf1b48555f +icon_edit dc3fff822c1ee004b92abbde27c7c682 +icon_file_dialog ca184caa0803a839bd8b6a1741c488c4 +icon_generic_6_d_o_f_joint 2bda3edbadf5cdda95fdcba6d16f8298 +icon_graph_edit 6a702bc4f31f63480019ba02cccbe6c0 +icon_graph_node fcf82785241eff77ea9972fc6fc2ef6e +icon_grid_container ea1012684b85a26c83ca7a491f9ab69e +icon_groove_joint_2d c3a49e1857964a04f7ed79866f3a8593 +icon_GUI_visibility_visible d956e435dec554864979aeee1bded043 +icon_g_i_probe a9aa9a6c2dc9ec58e0866e68e32ee24a +icon_hinge_joint 6b6364c48a664b654b841e48f794c4b0 +icon_h_box_container e2bf20d71fd7e612fcd787fa2c578bfc +icon_h_scroll_bar f4caa08c6ba15499e9e887ff9c701b0d +icon_h_separator 6a85f7720840b049fb9f9b47aa573329 +icon_h_slider 024c37595249a0e528206ecfed2ce983 +icon_h_split_container 74af42ae4779ef2dac29edaae1796c8d +icon_h_t_t_p_request 0f4d11fea914d437e713592e78bcd177 +icon_immediate_geometry 462129d475ce79f04670e2bcd1e47d32 +icon_interpolated_camera 2613060b44a5de86691362e07421192d +icon_item_list 82c5e66a1a2760c6701e66963c643118 +icon_kinematic_body baf39f197a9bed032b00783ce2b6c24b +icon_kinematic_body_2d 2ad0acbb50e157b9dfc46bf9af6e2449 +icon_label b8145440a57c66e2ac5e137cb907e640 +icon_light_2d 3e2947b328601f54f04ad885062c0726 +icon_light_occluder_2d 4c8471724f261ee26e4bfd428e4fa629 +icon_line_2d e21071cf08d2c0d89460aff3325a786d +icon_line_edit 4b4df6e706db709878cfffc97719145c +icon_link_button a505b74407b6259e96bf8c7f250a4557 +icon_listener 25920e978223a76a1ed8638d3e91dfca +icon_margin_container 7c7987b67b00a6ce200bd11414347ce8 +icon_menu_button 92af7cdf26a019204c853d6e4dad0e2f +icon_mesh_instance 417906bfc6e01952a01b12ce411a34b9 +icon_mesh_instance_2d 74e10998b51ae9fb88a4435933e63536 +icon_multi_mesh_instance 7f282664fe0b8a5c2a4be1a7c79b6090 +icon_multi_mesh_instance_2d 3bec394a3502b2b93292964b40cffb34 +icon_navigation 1cbcea8e75045c000204ac8a1ac08c7d +icon_navigation_2d 813a74261535fe2aec60a85b803ab26e +icon_navigation_mesh_instance 45706f13916f2d5997a376282337b150 +icon_navigation_polygon_instance 2bde0514ce8a5b758b4d515487bfc671 +icon_nine_patch_rect 146f15b2dd23bcd6c71bc262750c75ae +icon_node 8eed32d4596a4ac5573c98f8b8db554d +icon_node_2d 2c21bd745d7b8242048e1cba9d036d36 +icon_omni_light 56662c10dea4add3ecbab319d5fc19b8 +icon_option_button 5f0ab46ce7953dafef13f58430c412e4 +icon_panel ec03c4f34c36bdfcbf34291550acc18f +icon_panel_container 20aded28be4f4094c432a9ae617da43b +icon_parallax_background fb28ab07c87d2abd63a0a897d0e22668 +icon_parallax_layer 7a7782d2622475c351ae9194a37a3de9 +icon_particles 876f1f2b496c0a7cd7fdf698d5744c5a +icon_particles_2d f0cc98af251a7ddd1b7f3783d56998c1 +icon_path bd3a8f248df5492e785ff9774f6c14ff +icon_path_2d ad4c04049cc0dab5b73f67970f871502 +icon_path_follow 3c96e4979e645b6278984a4165b7451e +icon_path_follow_2d 0e5ed2a4bec5117ba72a1da8bfcdc370 +icon_physical_bone 477ad88c7ee226caa82c9fd4f9c4fe03 +icon_pin_joint 0859ac5caf660107e4e981e7f4bd4292 +icon_pin_joint_2d ac9b958e5029c3e517ff02863b3de602 +icon_polygon_2_d 1e9aaa8f172ed5df66af9c80c491f446 +icon_popup 70dd3a76942d94f4a50eab4937eb8de8 +icon_popup_dialog 8750584d6ad520368fc36dae74a25e96 +icon_popup_menu faa11ffe4722a1ed4cc212c0473325cb +icon_popup_panel e6d82be16a1f4cbd995c3628a7221743 +icon_position_2d 272e1b2f9c31550e8dd6aee94cf814c8 +icon_position_3d a21e92e39df5f17111eb6a751c258f36 +icon_progress_bar f0457c45b4b062743f6e17992d91fd4f +icon_ray_cast 3da43b7484ca367cb63dd7e8089038e1 +icon_ray_cast_2d 6dcd2660cb0da6620af18c2f15ca1f2d +icon_reference_rect 7bb50d353c0fbe4c66c65aad105a3710 +icon_reflection_probe 34acdd090988fd2432f046ed9daae7b2 +icon_refresh 6a7635d996186118ca7bdec52940fa47 +icon_remote_transform cbe7a93c44f0aa2fd6c1b4ce791f7d18 +icon_remote_transform_2d da99738feafc61c71990da52d09217c5 +icon_resource_preloader 54f8797edfb1a591469bd8a495693ecd +icon_rich_text_label 90c5820d0690ccbbc2417abddf10a065 +icon_rigid_body 384368c095922e9ca71cf241b1959e7d +icon_rigid_body_2d a5d7985831fe85fa523a9c4de7949a29 +icon_scroll_container c16f92706fe8b478fa1e4b4cb989bceb +icon_skeleton 4380f3accb79e3f21221d8094fec7f00 +icon_skeleton_2d c23ad7d61b470c55741e340adccd258c +icon_skeleton_i_k 33310ed7229c0f427bd024e5e09aa583 +icon_slider_joint b3ea8ca937ae99391356917bd4828f7f +icon_soft_body e3bcbf442155f984d4a221d0bb2d51bd +icon_spatial 8c3b8eb9e610cf9f9f408cfda48eb22f +icon_spin_box dde10cb14e0b9b747e771f5ab24cfefa +icon_spot_light 6770b4669be1bc20dd3577c65048432b +icon_spring_arm d74a1036e477174520013ab462b4e1c3 +icon_sprite ac17b5a5be395600db43ddbca3d463d4 +icon_sprite_3d 5dac01bc8de8c2dfcede3c999842f2a3 +icon_static_body 0f92bf400c4623adbb64c15b01e0382e +icon_static_body_2d 3dd22d2168d5372b3dee50429c4b6ecb +icon_tabs 7e78ecce029538648eb6ef5cc3f94d57 +icon_tab_container 9270d0970d93715da62075751ae88bc9 +icon_texture_button 488e98f85acc4ba2cdd9558a5af29344 +icon_texture_progress b8b440d119ea40edcbeade9e10ee35b5 +icon_texture_rect 92ced3405382fa051b6560e714b4b8ed +icon_text_edit 9d93c58e090d546b5f1ee3e0a693fbd2 +icon_tile_map e1558aa483145cd909169b9ec1cfa1ae +icon_timer d1419c36011566b646e568d77be7cb09 +icon_tool_button 4a65d7656827a1a1b5ac38f10b4646e8 +icon_touch_screen_button 30adb0de710d854b0cb0bf15b1536835 +icon_tree bad9393472d4c2f33bbe3afb8cb64f39 +icon_tween edf1c6b9262a66c22ecf96982c557337 +icon_vehicle_body 49ab6b5393e04b3285ca459b77078713 +icon_vehicle_wheel 7ffca5bd273ac964bfac6a7de017edc9 +icon_video_player 56452495f2f5a67026259ac4d765b2ba +icon_viewport f4d16e71d5ede737174bd18800757696 +icon_viewport_container f1d6d0ef263589f8a59fad13ac648d45 +icon_visibility_enabler 7c774f0c24f95fd89e419ea28cedd33f +icon_visibility_enabler_2d a38023de192b545a8834ad4e2547c659 +icon_visibility_notifier b7114d0e69234903d554819775947360 +icon_visibility_notifier_2d c93ff4ad11f6cc5d63b65346698bc5fc +icon_v_box_container 53ab4bb91711b591043e9207219d983f +icon_v_scroll_bar 8dcfef3ee1fb291f07c278786c4af788 +icon_v_separator cdbf0a84486f142e1776e16b4c50c918 +icon_v_slider 17b523456407d17b95bc2895e5baf528 +icon_v_split_container 4c3c0ae52be2afe50860a3c622eefe49 +icon_window_dialog 174b718610528486f3f8445f0bfba263 +icon_world_environment 451ec32bf9d7a89d2e1e34dfa1158e26 +icon_y_sort f76aa85d366d9d55e4b86d2390cf988c diff --git a/resources/light/icon_GUI_visibility_visible.svg b/resources/light/icon_GUI_visibility_visible.svg new file mode 100644 index 0000000..cad97b6 --- /dev/null +++ b/resources/light/icon_GUI_visibility_visible.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_a_r_v_r_anchor.svg b/resources/light/icon_a_r_v_r_anchor.svg new file mode 100644 index 0000000..2a9ad42 --- /dev/null +++ b/resources/light/icon_a_r_v_r_anchor.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_a_r_v_r_camera.svg b/resources/light/icon_a_r_v_r_camera.svg new file mode 100644 index 0000000..82cf4ca --- /dev/null +++ b/resources/light/icon_a_r_v_r_camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_a_r_v_r_controller.svg b/resources/light/icon_a_r_v_r_controller.svg new file mode 100644 index 0000000..ee3d772 --- /dev/null +++ b/resources/light/icon_a_r_v_r_controller.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_a_r_v_r_origin.svg b/resources/light/icon_a_r_v_r_origin.svg new file mode 100644 index 0000000..3ac4a06 --- /dev/null +++ b/resources/light/icon_a_r_v_r_origin.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_accept_dialog.svg b/resources/light/icon_accept_dialog.svg new file mode 100644 index 0000000..d35907f --- /dev/null +++ b/resources/light/icon_accept_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_animated_sprite.svg b/resources/light/icon_animated_sprite.svg new file mode 100644 index 0000000..cab15ea --- /dev/null +++ b/resources/light/icon_animated_sprite.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/light/icon_animated_sprite_3d.svg b/resources/light/icon_animated_sprite_3d.svg new file mode 100644 index 0000000..9c26784 --- /dev/null +++ b/resources/light/icon_animated_sprite_3d.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/resources/light/icon_animation_player.svg b/resources/light/icon_animation_player.svg new file mode 100644 index 0000000..15e210d --- /dev/null +++ b/resources/light/icon_animation_player.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_animation_tree.svg b/resources/light/icon_animation_tree.svg new file mode 100644 index 0000000..578dc19 --- /dev/null +++ b/resources/light/icon_animation_tree.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_animation_tree_player.svg b/resources/light/icon_animation_tree_player.svg new file mode 100644 index 0000000..578dc19 --- /dev/null +++ b/resources/light/icon_animation_tree_player.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_area.svg b/resources/light/icon_area.svg new file mode 100644 index 0000000..adb2881 --- /dev/null +++ b/resources/light/icon_area.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_area_2d.svg b/resources/light/icon_area_2d.svg new file mode 100644 index 0000000..bfb4be4 --- /dev/null +++ b/resources/light/icon_area_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_audio_stream_player.svg b/resources/light/icon_audio_stream_player.svg new file mode 100644 index 0000000..6b5ee1a --- /dev/null +++ b/resources/light/icon_audio_stream_player.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/light/icon_audio_stream_player_2_d.svg b/resources/light/icon_audio_stream_player_2_d.svg new file mode 100644 index 0000000..b2efc1e --- /dev/null +++ b/resources/light/icon_audio_stream_player_2_d.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/light/icon_audio_stream_player_3_d.svg b/resources/light/icon_audio_stream_player_3_d.svg new file mode 100644 index 0000000..6981acc --- /dev/null +++ b/resources/light/icon_audio_stream_player_3_d.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/resources/light/icon_back_buffer_copy.svg b/resources/light/icon_back_buffer_copy.svg new file mode 100644 index 0000000..e7fd1a6 --- /dev/null +++ b/resources/light/icon_back_buffer_copy.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_baked_lightmap.svg b/resources/light/icon_baked_lightmap.svg new file mode 100644 index 0000000..2a4bde3 --- /dev/null +++ b/resources/light/icon_baked_lightmap.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_bone_2_d.svg b/resources/light/icon_bone_2_d.svg new file mode 100644 index 0000000..18dc6c8 --- /dev/null +++ b/resources/light/icon_bone_2_d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_bone_attachment.svg b/resources/light/icon_bone_attachment.svg new file mode 100644 index 0000000..9ebcfc9 --- /dev/null +++ b/resources/light/icon_bone_attachment.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_button.svg b/resources/light/icon_button.svg new file mode 100644 index 0000000..d233dfb --- /dev/null +++ b/resources/light/icon_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_c_p_u_particles.svg b/resources/light/icon_c_p_u_particles.svg new file mode 100644 index 0000000..c5d04d2 --- /dev/null +++ b/resources/light/icon_c_p_u_particles.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_c_p_u_particles_2_d.svg b/resources/light/icon_c_p_u_particles_2_d.svg new file mode 100644 index 0000000..7b1aeb9 --- /dev/null +++ b/resources/light/icon_c_p_u_particles_2_d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_camera.svg b/resources/light/icon_camera.svg new file mode 100644 index 0000000..1bbff56 --- /dev/null +++ b/resources/light/icon_camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_camera_2d.svg b/resources/light/icon_camera_2d.svg new file mode 100644 index 0000000..08bd9e7 --- /dev/null +++ b/resources/light/icon_camera_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_canvas_layer.svg b/resources/light/icon_canvas_layer.svg new file mode 100644 index 0000000..5a4c8df --- /dev/null +++ b/resources/light/icon_canvas_layer.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_canvas_modulate.svg b/resources/light/icon_canvas_modulate.svg new file mode 100644 index 0000000..2a1e91b --- /dev/null +++ b/resources/light/icon_canvas_modulate.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/resources/light/icon_center_container.svg b/resources/light/icon_center_container.svg new file mode 100644 index 0000000..edd2211 --- /dev/null +++ b/resources/light/icon_center_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_check_box.svg b/resources/light/icon_check_box.svg new file mode 100644 index 0000000..d8735cb --- /dev/null +++ b/resources/light/icon_check_box.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_check_button.svg b/resources/light/icon_check_button.svg new file mode 100644 index 0000000..094d9b2 --- /dev/null +++ b/resources/light/icon_check_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_clipped_camera.svg b/resources/light/icon_clipped_camera.svg new file mode 100644 index 0000000..f9f117f --- /dev/null +++ b/resources/light/icon_clipped_camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_collision_polygon.svg b/resources/light/icon_collision_polygon.svg new file mode 100644 index 0000000..e6efc22 --- /dev/null +++ b/resources/light/icon_collision_polygon.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_collision_polygon_2d.svg b/resources/light/icon_collision_polygon_2d.svg new file mode 100644 index 0000000..c10933c --- /dev/null +++ b/resources/light/icon_collision_polygon_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_collision_shape.svg b/resources/light/icon_collision_shape.svg new file mode 100644 index 0000000..5a6c301 --- /dev/null +++ b/resources/light/icon_collision_shape.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_collision_shape_2d.svg b/resources/light/icon_collision_shape_2d.svg new file mode 100644 index 0000000..70278bc --- /dev/null +++ b/resources/light/icon_collision_shape_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_color_picker.svg b/resources/light/icon_color_picker.svg new file mode 100644 index 0000000..b11fe60 --- /dev/null +++ b/resources/light/icon_color_picker.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_color_picker_button.svg b/resources/light/icon_color_picker_button.svg new file mode 100644 index 0000000..25b6613 --- /dev/null +++ b/resources/light/icon_color_picker_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_color_rect.svg b/resources/light/icon_color_rect.svg new file mode 100644 index 0000000..bb205e2 --- /dev/null +++ b/resources/light/icon_color_rect.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/resources/light/icon_cone_twist_joint.svg b/resources/light/icon_cone_twist_joint.svg new file mode 100644 index 0000000..c420963 --- /dev/null +++ b/resources/light/icon_cone_twist_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_confirmation_dialog.svg b/resources/light/icon_confirmation_dialog.svg new file mode 100644 index 0000000..64f2941 --- /dev/null +++ b/resources/light/icon_confirmation_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_container.svg b/resources/light/icon_container.svg new file mode 100644 index 0000000..c04c212 --- /dev/null +++ b/resources/light/icon_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_control.svg b/resources/light/icon_control.svg new file mode 100644 index 0000000..63a1aa7 --- /dev/null +++ b/resources/light/icon_control.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_damped_spring_joint_2d.svg b/resources/light/icon_damped_spring_joint_2d.svg new file mode 100644 index 0000000..6c5741f --- /dev/null +++ b/resources/light/icon_damped_spring_joint_2d.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_directional_light.svg b/resources/light/icon_directional_light.svg new file mode 100644 index 0000000..2cddf9a --- /dev/null +++ b/resources/light/icon_directional_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_edit.svg b/resources/light/icon_edit.svg new file mode 100644 index 0000000..b826c1c --- /dev/null +++ b/resources/light/icon_edit.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/resources/light/icon_file_dialog.svg b/resources/light/icon_file_dialog.svg new file mode 100644 index 0000000..8027951 --- /dev/null +++ b/resources/light/icon_file_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_g_i_probe.svg b/resources/light/icon_g_i_probe.svg new file mode 100644 index 0000000..6a1282d --- /dev/null +++ b/resources/light/icon_g_i_probe.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_generic_6_d_o_f_joint.svg b/resources/light/icon_generic_6_d_o_f_joint.svg new file mode 100644 index 0000000..f1b7b55 --- /dev/null +++ b/resources/light/icon_generic_6_d_o_f_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_graph_edit.svg b/resources/light/icon_graph_edit.svg new file mode 100644 index 0000000..36c9ae5 --- /dev/null +++ b/resources/light/icon_graph_edit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_graph_node.svg b/resources/light/icon_graph_node.svg new file mode 100644 index 0000000..468aaf0 --- /dev/null +++ b/resources/light/icon_graph_node.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_grid_container.svg b/resources/light/icon_grid_container.svg new file mode 100644 index 0000000..40953c9 --- /dev/null +++ b/resources/light/icon_grid_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_groove_joint_2d.svg b/resources/light/icon_groove_joint_2d.svg new file mode 100644 index 0000000..e7b2929 --- /dev/null +++ b/resources/light/icon_groove_joint_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_h_box_container.svg b/resources/light/icon_h_box_container.svg new file mode 100644 index 0000000..efcdffa --- /dev/null +++ b/resources/light/icon_h_box_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_h_scroll_bar.svg b/resources/light/icon_h_scroll_bar.svg new file mode 100644 index 0000000..a5b2b2a --- /dev/null +++ b/resources/light/icon_h_scroll_bar.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_h_separator.svg b/resources/light/icon_h_separator.svg new file mode 100644 index 0000000..2a8ca25 --- /dev/null +++ b/resources/light/icon_h_separator.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_h_slider.svg b/resources/light/icon_h_slider.svg new file mode 100644 index 0000000..2f3483d --- /dev/null +++ b/resources/light/icon_h_slider.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_h_split_container.svg b/resources/light/icon_h_split_container.svg new file mode 100644 index 0000000..76650dd --- /dev/null +++ b/resources/light/icon_h_split_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_h_t_t_p_request.svg b/resources/light/icon_h_t_t_p_request.svg new file mode 100644 index 0000000..ed6981a --- /dev/null +++ b/resources/light/icon_h_t_t_p_request.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_hinge_joint.svg b/resources/light/icon_hinge_joint.svg new file mode 100644 index 0000000..aa66c4c --- /dev/null +++ b/resources/light/icon_hinge_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_immediate_geometry.svg b/resources/light/icon_immediate_geometry.svg new file mode 100644 index 0000000..c01f380 --- /dev/null +++ b/resources/light/icon_immediate_geometry.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_interpolated_camera.svg b/resources/light/icon_interpolated_camera.svg new file mode 100644 index 0000000..87c1e3b --- /dev/null +++ b/resources/light/icon_interpolated_camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_item_list.svg b/resources/light/icon_item_list.svg new file mode 100644 index 0000000..93d6b68 --- /dev/null +++ b/resources/light/icon_item_list.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_kinematic_body.svg b/resources/light/icon_kinematic_body.svg new file mode 100644 index 0000000..c7abf9a --- /dev/null +++ b/resources/light/icon_kinematic_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_kinematic_body_2d.svg b/resources/light/icon_kinematic_body_2d.svg new file mode 100644 index 0000000..baebfa2 --- /dev/null +++ b/resources/light/icon_kinematic_body_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_label.svg b/resources/light/icon_label.svg new file mode 100644 index 0000000..8a818bd --- /dev/null +++ b/resources/light/icon_label.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_light_2d.svg b/resources/light/icon_light_2d.svg new file mode 100644 index 0000000..9edaaee --- /dev/null +++ b/resources/light/icon_light_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_light_occluder_2d.svg b/resources/light/icon_light_occluder_2d.svg new file mode 100644 index 0000000..3c38f92 --- /dev/null +++ b/resources/light/icon_light_occluder_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_line_2d.svg b/resources/light/icon_line_2d.svg new file mode 100644 index 0000000..13752b5 --- /dev/null +++ b/resources/light/icon_line_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_line_edit.svg b/resources/light/icon_line_edit.svg new file mode 100644 index 0000000..cd487c5 --- /dev/null +++ b/resources/light/icon_line_edit.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_link_button.svg b/resources/light/icon_link_button.svg new file mode 100644 index 0000000..f88c1f2 --- /dev/null +++ b/resources/light/icon_link_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_listener.svg b/resources/light/icon_listener.svg new file mode 100644 index 0000000..0b4fd72 --- /dev/null +++ b/resources/light/icon_listener.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_margin_container.svg b/resources/light/icon_margin_container.svg new file mode 100644 index 0000000..47fe297 --- /dev/null +++ b/resources/light/icon_margin_container.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_menu_button.svg b/resources/light/icon_menu_button.svg new file mode 100644 index 0000000..a2180e9 --- /dev/null +++ b/resources/light/icon_menu_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_mesh_instance.svg b/resources/light/icon_mesh_instance.svg new file mode 100644 index 0000000..df548c3 --- /dev/null +++ b/resources/light/icon_mesh_instance.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_mesh_instance_2d.svg b/resources/light/icon_mesh_instance_2d.svg new file mode 100644 index 0000000..6a7f305 --- /dev/null +++ b/resources/light/icon_mesh_instance_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_multi_mesh_instance.svg b/resources/light/icon_multi_mesh_instance.svg new file mode 100644 index 0000000..b2b9b65 --- /dev/null +++ b/resources/light/icon_multi_mesh_instance.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_multi_mesh_instance_2d.svg b/resources/light/icon_multi_mesh_instance_2d.svg new file mode 100644 index 0000000..e09a1f5 --- /dev/null +++ b/resources/light/icon_multi_mesh_instance_2d.svg @@ -0,0 +1,4 @@ + + + + diff --git a/resources/light/icon_navigation.svg b/resources/light/icon_navigation.svg new file mode 100644 index 0000000..778ce5b --- /dev/null +++ b/resources/light/icon_navigation.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_navigation_2d.svg b/resources/light/icon_navigation_2d.svg new file mode 100644 index 0000000..dc3c552 --- /dev/null +++ b/resources/light/icon_navigation_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_navigation_mesh_instance.svg b/resources/light/icon_navigation_mesh_instance.svg new file mode 100644 index 0000000..84ffabf --- /dev/null +++ b/resources/light/icon_navigation_mesh_instance.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_navigation_polygon_instance.svg b/resources/light/icon_navigation_polygon_instance.svg new file mode 100644 index 0000000..c93b7d1 --- /dev/null +++ b/resources/light/icon_navigation_polygon_instance.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_nine_patch_rect.svg b/resources/light/icon_nine_patch_rect.svg new file mode 100644 index 0000000..74072b5 --- /dev/null +++ b/resources/light/icon_nine_patch_rect.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/resources/light/icon_node.svg b/resources/light/icon_node.svg new file mode 100644 index 0000000..cae7079 --- /dev/null +++ b/resources/light/icon_node.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_node_2d.svg b/resources/light/icon_node_2d.svg new file mode 100644 index 0000000..356a1bd --- /dev/null +++ b/resources/light/icon_node_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_omni_light.svg b/resources/light/icon_omni_light.svg new file mode 100644 index 0000000..87f8ab1 --- /dev/null +++ b/resources/light/icon_omni_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_option_button.svg b/resources/light/icon_option_button.svg new file mode 100644 index 0000000..d84f205 --- /dev/null +++ b/resources/light/icon_option_button.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_panel.svg b/resources/light/icon_panel.svg new file mode 100644 index 0000000..9f723a0 --- /dev/null +++ b/resources/light/icon_panel.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_panel_container.svg b/resources/light/icon_panel_container.svg new file mode 100644 index 0000000..1d1f1ab --- /dev/null +++ b/resources/light/icon_panel_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_parallax_background.svg b/resources/light/icon_parallax_background.svg new file mode 100644 index 0000000..bfe6bad --- /dev/null +++ b/resources/light/icon_parallax_background.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_parallax_layer.svg b/resources/light/icon_parallax_layer.svg new file mode 100644 index 0000000..54d0b55 --- /dev/null +++ b/resources/light/icon_parallax_layer.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_particles.svg b/resources/light/icon_particles.svg new file mode 100644 index 0000000..4ece220 --- /dev/null +++ b/resources/light/icon_particles.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_particles_2d.svg b/resources/light/icon_particles_2d.svg new file mode 100644 index 0000000..5ddd269 --- /dev/null +++ b/resources/light/icon_particles_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_path.svg b/resources/light/icon_path.svg new file mode 100644 index 0000000..f1cd7bc --- /dev/null +++ b/resources/light/icon_path.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_path_2d.svg b/resources/light/icon_path_2d.svg new file mode 100644 index 0000000..43492dd --- /dev/null +++ b/resources/light/icon_path_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_path_follow.svg b/resources/light/icon_path_follow.svg new file mode 100644 index 0000000..a165202 --- /dev/null +++ b/resources/light/icon_path_follow.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_path_follow_2d.svg b/resources/light/icon_path_follow_2d.svg new file mode 100644 index 0000000..d7f4fbc --- /dev/null +++ b/resources/light/icon_path_follow_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_physical_bone.svg b/resources/light/icon_physical_bone.svg new file mode 100644 index 0000000..5f25040 --- /dev/null +++ b/resources/light/icon_physical_bone.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources/light/icon_pin_joint.svg b/resources/light/icon_pin_joint.svg new file mode 100644 index 0000000..3a732c2 --- /dev/null +++ b/resources/light/icon_pin_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_pin_joint_2d.svg b/resources/light/icon_pin_joint_2d.svg new file mode 100644 index 0000000..dfe0bf5 --- /dev/null +++ b/resources/light/icon_pin_joint_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_polygon_2_d.svg b/resources/light/icon_polygon_2_d.svg new file mode 100644 index 0000000..0dd196b --- /dev/null +++ b/resources/light/icon_polygon_2_d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_popup.svg b/resources/light/icon_popup.svg new file mode 100644 index 0000000..af3ac1b --- /dev/null +++ b/resources/light/icon_popup.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_popup_dialog.svg b/resources/light/icon_popup_dialog.svg new file mode 100644 index 0000000..3d99858 --- /dev/null +++ b/resources/light/icon_popup_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_popup_menu.svg b/resources/light/icon_popup_menu.svg new file mode 100644 index 0000000..f78dd50 --- /dev/null +++ b/resources/light/icon_popup_menu.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_popup_panel.svg b/resources/light/icon_popup_panel.svg new file mode 100644 index 0000000..55f4af5 --- /dev/null +++ b/resources/light/icon_popup_panel.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_position_2d.svg b/resources/light/icon_position_2d.svg new file mode 100644 index 0000000..fd9116c --- /dev/null +++ b/resources/light/icon_position_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_position_3d.svg b/resources/light/icon_position_3d.svg new file mode 100644 index 0000000..58dea0e --- /dev/null +++ b/resources/light/icon_position_3d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_progress_bar.svg b/resources/light/icon_progress_bar.svg new file mode 100644 index 0000000..01d3387 --- /dev/null +++ b/resources/light/icon_progress_bar.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_ray_cast.svg b/resources/light/icon_ray_cast.svg new file mode 100644 index 0000000..69a2281 --- /dev/null +++ b/resources/light/icon_ray_cast.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_ray_cast_2d.svg b/resources/light/icon_ray_cast_2d.svg new file mode 100644 index 0000000..7791071 --- /dev/null +++ b/resources/light/icon_ray_cast_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_reference_rect.svg b/resources/light/icon_reference_rect.svg new file mode 100644 index 0000000..3fb547a --- /dev/null +++ b/resources/light/icon_reference_rect.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_reflection_probe.svg b/resources/light/icon_reflection_probe.svg new file mode 100644 index 0000000..ddf10f6 --- /dev/null +++ b/resources/light/icon_reflection_probe.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_refresh.svg b/resources/light/icon_refresh.svg new file mode 100644 index 0000000..f8e9ae3 --- /dev/null +++ b/resources/light/icon_refresh.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_remote_transform.svg b/resources/light/icon_remote_transform.svg new file mode 100644 index 0000000..359fa93 --- /dev/null +++ b/resources/light/icon_remote_transform.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_remote_transform_2d.svg b/resources/light/icon_remote_transform_2d.svg new file mode 100644 index 0000000..f2afdd4 --- /dev/null +++ b/resources/light/icon_remote_transform_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_resource_preloader.svg b/resources/light/icon_resource_preloader.svg new file mode 100644 index 0000000..fc31ea4 --- /dev/null +++ b/resources/light/icon_resource_preloader.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_rich_text_label.svg b/resources/light/icon_rich_text_label.svg new file mode 100644 index 0000000..9b86f48 --- /dev/null +++ b/resources/light/icon_rich_text_label.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_rigid_body.svg b/resources/light/icon_rigid_body.svg new file mode 100644 index 0000000..9968a6a --- /dev/null +++ b/resources/light/icon_rigid_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_rigid_body_2d.svg b/resources/light/icon_rigid_body_2d.svg new file mode 100644 index 0000000..057cb01 --- /dev/null +++ b/resources/light/icon_rigid_body_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_scroll_container.svg b/resources/light/icon_scroll_container.svg new file mode 100644 index 0000000..2eeb60e --- /dev/null +++ b/resources/light/icon_scroll_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_skeleton.svg b/resources/light/icon_skeleton.svg new file mode 100644 index 0000000..a82f891 --- /dev/null +++ b/resources/light/icon_skeleton.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_skeleton_2d.svg b/resources/light/icon_skeleton_2d.svg new file mode 100644 index 0000000..a9a925c --- /dev/null +++ b/resources/light/icon_skeleton_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_skeleton_i_k.svg b/resources/light/icon_skeleton_i_k.svg new file mode 100644 index 0000000..4585882 --- /dev/null +++ b/resources/light/icon_skeleton_i_k.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_slider_joint.svg b/resources/light/icon_slider_joint.svg new file mode 100644 index 0000000..bf5e467 --- /dev/null +++ b/resources/light/icon_slider_joint.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_soft_body.svg b/resources/light/icon_soft_body.svg new file mode 100644 index 0000000..a912f12 --- /dev/null +++ b/resources/light/icon_soft_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_spatial.svg b/resources/light/icon_spatial.svg new file mode 100644 index 0000000..e59eff4 --- /dev/null +++ b/resources/light/icon_spatial.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_spin_box.svg b/resources/light/icon_spin_box.svg new file mode 100644 index 0000000..becdaca --- /dev/null +++ b/resources/light/icon_spin_box.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_spot_light.svg b/resources/light/icon_spot_light.svg new file mode 100644 index 0000000..44a1dd6 --- /dev/null +++ b/resources/light/icon_spot_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_spring_arm.svg b/resources/light/icon_spring_arm.svg new file mode 100644 index 0000000..8869e94 --- /dev/null +++ b/resources/light/icon_spring_arm.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources/light/icon_sprite.svg b/resources/light/icon_sprite.svg new file mode 100644 index 0000000..82cadaa --- /dev/null +++ b/resources/light/icon_sprite.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_sprite_3d.svg b/resources/light/icon_sprite_3d.svg new file mode 100644 index 0000000..aa0518e --- /dev/null +++ b/resources/light/icon_sprite_3d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_static_body.svg b/resources/light/icon_static_body.svg new file mode 100644 index 0000000..45b0d5b --- /dev/null +++ b/resources/light/icon_static_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_static_body_2d.svg b/resources/light/icon_static_body_2d.svg new file mode 100644 index 0000000..3004e89 --- /dev/null +++ b/resources/light/icon_static_body_2d.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_tab_container.svg b/resources/light/icon_tab_container.svg new file mode 100644 index 0000000..f97cab1 --- /dev/null +++ b/resources/light/icon_tab_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_tabs.svg b/resources/light/icon_tabs.svg new file mode 100644 index 0000000..0df9d7e --- /dev/null +++ b/resources/light/icon_tabs.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_text_edit.svg b/resources/light/icon_text_edit.svg new file mode 100644 index 0000000..4a41e95 --- /dev/null +++ b/resources/light/icon_text_edit.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_texture_button.svg b/resources/light/icon_texture_button.svg new file mode 100644 index 0000000..778346c --- /dev/null +++ b/resources/light/icon_texture_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_texture_progress.svg b/resources/light/icon_texture_progress.svg new file mode 100644 index 0000000..465f4b5 --- /dev/null +++ b/resources/light/icon_texture_progress.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/resources/light/icon_texture_rect.svg b/resources/light/icon_texture_rect.svg new file mode 100644 index 0000000..3696914 --- /dev/null +++ b/resources/light/icon_texture_rect.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_tile_map.svg b/resources/light/icon_tile_map.svg new file mode 100644 index 0000000..64ff6ec --- /dev/null +++ b/resources/light/icon_tile_map.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_timer.svg b/resources/light/icon_timer.svg new file mode 100644 index 0000000..c7bc63d --- /dev/null +++ b/resources/light/icon_timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_tool_button.svg b/resources/light/icon_tool_button.svg new file mode 100644 index 0000000..7aaad76 --- /dev/null +++ b/resources/light/icon_tool_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_touch_screen_button.svg b/resources/light/icon_touch_screen_button.svg new file mode 100644 index 0000000..2ca363e --- /dev/null +++ b/resources/light/icon_touch_screen_button.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_tree.svg b/resources/light/icon_tree.svg new file mode 100644 index 0000000..0480f94 --- /dev/null +++ b/resources/light/icon_tree.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_tween.svg b/resources/light/icon_tween.svg new file mode 100644 index 0000000..10f7a99 --- /dev/null +++ b/resources/light/icon_tween.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_v_box_container.svg b/resources/light/icon_v_box_container.svg new file mode 100644 index 0000000..3e9390f --- /dev/null +++ b/resources/light/icon_v_box_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_v_scroll_bar.svg b/resources/light/icon_v_scroll_bar.svg new file mode 100644 index 0000000..38d0196 --- /dev/null +++ b/resources/light/icon_v_scroll_bar.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_v_separator.svg b/resources/light/icon_v_separator.svg new file mode 100644 index 0000000..58781a9 --- /dev/null +++ b/resources/light/icon_v_separator.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_v_slider.svg b/resources/light/icon_v_slider.svg new file mode 100644 index 0000000..728de39 --- /dev/null +++ b/resources/light/icon_v_slider.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_v_split_container.svg b/resources/light/icon_v_split_container.svg new file mode 100644 index 0000000..7fc7990 --- /dev/null +++ b/resources/light/icon_v_split_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_vehicle_body.svg b/resources/light/icon_vehicle_body.svg new file mode 100644 index 0000000..4bca6e1 --- /dev/null +++ b/resources/light/icon_vehicle_body.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_vehicle_wheel.svg b/resources/light/icon_vehicle_wheel.svg new file mode 100644 index 0000000..9783eec --- /dev/null +++ b/resources/light/icon_vehicle_wheel.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_video_player.svg b/resources/light/icon_video_player.svg new file mode 100644 index 0000000..adcc5de --- /dev/null +++ b/resources/light/icon_video_player.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_viewport.svg b/resources/light/icon_viewport.svg new file mode 100644 index 0000000..a9be724 --- /dev/null +++ b/resources/light/icon_viewport.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_viewport_container.svg b/resources/light/icon_viewport_container.svg new file mode 100644 index 0000000..7284518 --- /dev/null +++ b/resources/light/icon_viewport_container.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_visibility_enabler.svg b/resources/light/icon_visibility_enabler.svg new file mode 100644 index 0000000..283f75d --- /dev/null +++ b/resources/light/icon_visibility_enabler.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_visibility_enabler_2d.svg b/resources/light/icon_visibility_enabler_2d.svg new file mode 100644 index 0000000..d3151a6 --- /dev/null +++ b/resources/light/icon_visibility_enabler_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_visibility_notifier.svg b/resources/light/icon_visibility_notifier.svg new file mode 100644 index 0000000..52d38f9 --- /dev/null +++ b/resources/light/icon_visibility_notifier.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_visibility_notifier_2d.svg b/resources/light/icon_visibility_notifier_2d.svg new file mode 100644 index 0000000..6be2ab7 --- /dev/null +++ b/resources/light/icon_visibility_notifier_2d.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_window_dialog.svg b/resources/light/icon_window_dialog.svg new file mode 100644 index 0000000..19db82a --- /dev/null +++ b/resources/light/icon_window_dialog.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/light/icon_world_environment.svg b/resources/light/icon_world_environment.svg new file mode 100644 index 0000000..1ecc4a2 --- /dev/null +++ b/resources/light/icon_world_environment.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/light/icon_y_sort.svg b/resources/light/icon_y_sort.svg new file mode 100644 index 0000000..1fd9bd0 --- /dev/null +++ b/resources/light/icon_y_sort.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/debugger/SceneTree/inspector_provider.ts b/src/debugger/SceneTree/inspector_provider.ts new file mode 100644 index 0000000..9a0fba0 --- /dev/null +++ b/src/debugger/SceneTree/inspector_provider.ts @@ -0,0 +1,433 @@ +import { + TreeDataProvider, + EventEmitter, + Event, + ProviderResult, + TreeItem, + TreeItemCollapsibleState +} from "vscode"; +import { RemotePropertyBuilder } from "./tree_builders"; + +export class InspectorProvider implements TreeDataProvider { + private _on_did_change_tree_data: EventEmitter< + RemoteProperty | undefined + > = new EventEmitter(); + private tree: RemoteProperty | undefined; + + public readonly onDidChangeTreeData: Event | undefined = this + ._on_did_change_tree_data.event; + + constructor() {} + + public clean_up() { + if (this.tree) { + this.tree = undefined; + this._on_did_change_tree_data.fire(); + } + } + + public fill_tree( + element_name: string, + class_name: string, + object_id: number, + properties: any[] + ) { + this.tree = RemotePropertyBuilder.build( + element_name, + class_name, + object_id, + properties + ); + + this.tree.description = class_name; + this._on_did_change_tree_data.fire(); + } + + public getChildren( + element?: RemoteProperty + ): ProviderResult { + if (!this.tree) { + return Promise.resolve([]); + } + + if (!element) { + return Promise.resolve([this.tree]); + } else { + return Promise.resolve(element.properties); + } + } + + public getTreeItem(element: RemoteProperty): TreeItem | Thenable { + return element; + } + + public get_changed_value( + parents: RemoteProperty[], + property: RemoteProperty, + new_parsed_value: any + ) { + let idx = parents.length - 1; + let value = parents[idx].value; + switch (value.__type__) { + case "Vector2": + { + let name = property.label; + switch (name) { + case "x": + value.x = new_parsed_value; + break; + case "y": + value.y = new_parsed_value; + break; + } + } + break; + case "Rect2": + { + let name = property.label; + let vector = parents[idx - 1].label; + switch (vector) { + case "position": + switch (name) { + case "x": + value.position.x = new_parsed_value; + break; + case "y": + value.position.y = new_parsed_value; + break; + } + break; + case "size": + switch (name) { + case "x": + value.size.x = new_parsed_value; + break; + case "y": + value.size.y = new_parsed_value; + break; + } + break; + } + } + break; + case "Vector3": + { + let name = property.label; + switch (name) { + case "x": + value.x = new_parsed_value; + break; + case "y": + value.y = new_parsed_value; + break; + case "z": + value.z = new_parsed_value; + break; + } + } + break; + case "Transform2D": + { + let name = property.label; + let vector = parents[idx - 1].label; + switch (vector) { + case "origin": + switch (name) { + case "x": + value.position.x = new_parsed_value; + break; + case "y": + value.position.y = new_parsed_value; + break; + } + break; + case "x": + switch (name) { + case "x": + value.size.x = new_parsed_value; + break; + case "y": + value.size.y = new_parsed_value; + break; + } + break; + case "y": + switch (name) { + case "x": + value.size.x = new_parsed_value; + break; + case "y": + value.size.y = new_parsed_value; + break; + } + break; + } + } + break; + case "Plane": + { + let name = property.label; + let subprop = parents[idx - 1].label; + switch (subprop) { + case "d": + value.d = new_parsed_value; + break; + case "x": + value.x = new_parsed_value; + break; + case "y": + value.y = new_parsed_value; + break; + case "z": + value.z = new_parsed_value; + break; + case "normal": + switch (name) { + case "x": + value.normal.x = new_parsed_value; + break; + case "y": + value.normal.y = new_parsed_value; + break; + case "z": + value.normal.z = new_parsed_value; + break; + } + break; + } + } + break; + case "Quat": + { + let name = property.label; + switch (name) { + case "x": + value.x = new_parsed_value; + break; + case "y": + value.y = new_parsed_value; + break; + case "z": + value.z = new_parsed_value; + break; + case "w": + value.w = new_parsed_value; + break; + } + } + break; + case "AABB": + { + let name = property.label; + let vector = parents[idx - 1].label; + switch (vector) { + case "end": + switch (name) { + case "x": + value.end.x = new_parsed_value; + break; + case "y": + value.end.y = new_parsed_value; + break; + case "z": + value.end.z = new_parsed_value; + break; + } + break; + case "position": + switch (name) { + case "x": + value.position.x = new_parsed_value; + break; + case "y": + value.position.y = new_parsed_value; + break; + case "z": + value.position.z = new_parsed_value; + break; + } + break; + case "size": + switch (name) { + case "x": + value.size.x = new_parsed_value; + break; + case "y": + value.size.y = new_parsed_value; + break; + case "z": + value.size.z = new_parsed_value; + break; + } + break; + } + } + break; + case "Basis": + { + let name = property.label; + let vector = parents[idx - 1].label; + switch (vector) { + case "x": + switch (name) { + case "x": + value.x.x = new_parsed_value; + break; + case "y": + value.x.y = new_parsed_value; + break; + case "z": + value.x.z = new_parsed_value; + break; + } + break; + case "y": + switch (name) { + case "x": + value.y.x = new_parsed_value; + break; + case "y": + value.y.y = new_parsed_value; + break; + case "z": + value.y.z = new_parsed_value; + break; + } + break; + case "z": + switch (name) { + case "x": + value.z.x = new_parsed_value; + break; + case "y": + value.z.y = new_parsed_value; + break; + case "z": + value.z.z = new_parsed_value; + break; + } + break; + } + } + break; + case "Transform": + { + let name = property.label; + let parent_name = parents[idx - 1].label; + if ( + parent_name === "x" || + parent_name === "y" || + parent_name === "z" + ) { + switch (name) { + case "x": + switch (parent_name) { + case "x": + value.basis.x.x = new_parsed_value; + break; + case "y": + value.basis.x.y = new_parsed_value; + break; + case "z": + value.basis.x.z = new_parsed_value; + break; + } + break; + case "y": + switch (parent_name) { + case "x": + value.basis.y.x = new_parsed_value; + break; + case "y": + value.basis.y.y = new_parsed_value; + break; + case "z": + value.basis.y.z = new_parsed_value; + break; + } + break; + case "z": + switch (parent_name) { + case "x": + value.basis.z.x = new_parsed_value; + break; + case "y": + value.basis.z.y = new_parsed_value; + break; + case "z": + value.basis.z.z = new_parsed_value; + break; + } + break; + } + } else { + switch (name) { + case "x": + value.origin.x = new_parsed_value; + break; + case "y": + value.origin.y = new_parsed_value; + break; + case "z": + value.origin.z = new_parsed_value; + break; + } + } + } + break; + case "Color": + { + let name = property.label; + switch (name) { + case "r": + value.r = new_parsed_value; + break; + case "g": + value.g = new_parsed_value; + break; + case "b": + value.b = new_parsed_value; + break; + case "a": + value.a = new_parsed_value; + break; + } + } + break; + default: + if (Array.isArray(value)) { + let idx = parseInt(property.label); + if (idx < value.length) { + value[idx] = new_parsed_value; + } + } + else if(value instanceof Map) { + value.set(property.parent.value.key, new_parsed_value); + } + break; + } + + return value; + } + + public has_tree() { + return this.tree !== undefined; + } +} + +export class RemoteProperty extends TreeItem { + public changes_parent?: boolean; + public parent?: RemoteProperty; + + constructor( + public label: string, + public value: any, + public object_id: number, + public properties: RemoteProperty[], + public collapsibleState?: TreeItemCollapsibleState + ) { + super(label, collapsibleState); + } +} + +export class RemoteObject extends RemoteProperty {} diff --git a/src/debugger/SceneTree/scene_tree_provider.ts b/src/debugger/SceneTree/scene_tree_provider.ts new file mode 100644 index 0000000..91c95ac --- /dev/null +++ b/src/debugger/SceneTree/scene_tree_provider.ts @@ -0,0 +1,127 @@ +import { + TreeDataProvider, + EventEmitter, + Event, + ProviderResult, + TreeItem, + TreeItemCollapsibleState +} from "vscode"; +import path = require("path"); +import fs = require("fs"); + +export class SceneTreeProvider implements TreeDataProvider { + private _on_did_change_tree_data: EventEmitter< + SceneNode | undefined + > = new EventEmitter(); + private tree: SceneNode | undefined; + + public readonly onDidChangeTreeData: Event | undefined = this + ._on_did_change_tree_data.event; + + constructor() {} + + public fill_tree(tree: SceneNode) { + this.tree = tree; + this._on_did_change_tree_data.fire(); + } + + public getChildren(element?: SceneNode): ProviderResult { + if (!this.tree) { + return Promise.resolve([]); + } + + if (!element) { + return Promise.resolve([this.tree]); + } else { + return Promise.resolve(element.children); + } + } + + public getTreeItem(element: SceneNode): TreeItem | Thenable { + let has_children = element.children.length > 0; + let tree_item: TreeItem | undefined; + tree_item = new TreeItem( + element.label, + has_children + ? element === this.tree + ? TreeItemCollapsibleState.Expanded + : TreeItemCollapsibleState.Collapsed + : TreeItemCollapsibleState.None + ); + + tree_item.description = element.class_name; + tree_item.iconPath = element.iconPath; + + return tree_item; + } +} + +function match_icon_to_class(class_name: string) { + let icon_name = `icon${class_name + .replace(/(2|3)D/, "$1d") + .replace(/([A-Z0-9])/g, "_$1") + .toLowerCase()}.svg`; + return icon_name; +} + +export class SceneNode extends TreeItem { + constructor( + public label: string, + public class_name: string, + public object_id: number, + public children: SceneNode[], + public collapsibleState?: TreeItemCollapsibleState + ) { + super(label, collapsibleState); + + let light = path.join( + __filename, + "..", + "..", + "..", + "..", + "resources", + "light", + match_icon_to_class(class_name) + ); + if (!fs.existsSync(light)) { + path.join( + __filename, + "..", + "..", + "..", + "..", + "resources", + "light", + "node.svg" + ); + } + let dark = path.join( + __filename, + "..", + "..", + "..", + "..", + "resources", + "dark", + match_icon_to_class(class_name) + ); + if (!fs.existsSync(light)) { + path.join( + __filename, + "..", + "..", + "..", + "..", + "resources", + "dark", + "node.svg" + ); + } + + this.iconPath = { + light: light, + dark: dark + }; + } +} diff --git a/src/debugger/SceneTree/tree_builders.ts b/src/debugger/SceneTree/tree_builders.ts new file mode 100644 index 0000000..b322a03 --- /dev/null +++ b/src/debugger/SceneTree/tree_builders.ts @@ -0,0 +1,164 @@ +import { SceneNode } from "./scene_tree_provider"; +import { RemoteProperty, RemoteObject } from "./inspector_provider"; +import stringify from "../stringify"; +import { TreeItemCollapsibleState } from "vscode"; + +export class SceneTreeBuilder { + public static build(params: any[]) { + return this.parse_next(params, { offset: 0 }); + } + + private static parse_next(params: any[], ofs: { offset: number }): SceneNode { + let child_count: number = params[ofs.offset++]; + let name: string = params[ofs.offset++]; + let class_name: string = params[ofs.offset++]; + let id: number = params[ofs.offset++]; + + let children: SceneNode[] = []; + for (let i = 0; i < child_count; ++i) { + children.push(this.parse_next(params, ofs)); + } + + return new SceneNode(name, class_name, id, children); + } +} + +export class RemotePropertyBuilder { + private static build_property(object_id: number, property: any[], is_dict_key?: boolean) { + let prop_name: string = property[0]; + let prop_value: any = property[5]; + let is_remote_object = false; + let is_primitive = false; + + let child_props: RemoteProperty[] = []; + if (Array.isArray(prop_value) || prop_value instanceof Map) { + let length = 0; + let values: any[]; + if (prop_value instanceof Map) { + length = prop_value.size; + let keys = Array.from(prop_value.keys()); + values = keys.map(key => { + let value = prop_value.get(key); + let stringified_key = stringify(key).value; + + return { + __type__: "Pair", + key: key, + value: value, + __render__: () => stringified_key + }; + }); + } else { + length = prop_value.length; + values = prop_value; + } + for (let i = 0; i < length; i++) { + let name = `${i}`; + let child_prop = this.build_property(object_id, [ + name, + 0, + 0, + 0, + 0, + values[i] + ]); + child_prop.changes_parent = true; + child_props.push(child_prop); + } + } else if (typeof prop_value === "object") { + if (prop_value.__type__ && prop_value.__type__ === "Object") { + is_remote_object = true; + } else { + for (const PROP in prop_value) { + if (PROP !== "__type__" && PROP !== "__render__") { + let name = `${PROP}`; + let child_prop = this.build_property(object_id, [ + name, + 0, + 0, + 0, + 0, + prop_value[PROP] + ], prop_value.__type__ === "Pair" && name === "key"); + child_prop.changes_parent = true; + child_props.push(child_prop); + } + } + } + } else if (!is_dict_key) { + is_primitive = true; + } + + let out_prop = new RemoteProperty( + prop_name, + prop_value, + object_id, + child_props, + child_props.length === 0 + ? TreeItemCollapsibleState.None + : TreeItemCollapsibleState.Collapsed + ); + out_prop.properties.forEach(prop => { + prop.parent = out_prop; + }); + out_prop.description = stringify(prop_value).value; + if (is_remote_object) { + out_prop.contextValue = "remote_object"; + } else if (is_primitive) { + out_prop.contextValue = "editable_value"; + } + return out_prop; + } + + public static build( + element_name: string, + class_name: string, + object_id: number, + properties: any[][] + ) { + let categories = [ + ["Node", 0, 0, 0, 0, undefined], + ...properties.filter(value => value[5] === undefined) + ]; + + let categorized_props: RemoteProperty[] = []; + for (let i = 0; i < categories.length - 1; i++) { + const category = categories[i]; + + let props = + i > 0 + ? properties.slice( + properties.findIndex(value => category === value) + 1, + properties.findIndex(value => categories[i + 1] === value) + ) + : properties.slice( + 0, + properties.findIndex(value => categories[1] === value) + ); + + let out_props = props.map(value => { + return this.build_property(object_id, value); + }); + + let category_prop = new RemoteProperty( + category[0], + undefined, + object_id, + out_props, + TreeItemCollapsibleState.Expanded + ); + + categorized_props.push(category_prop); + } + + let out = new RemoteProperty( + element_name, + undefined, + object_id, + categorized_props, + TreeItemCollapsibleState.Expanded + ); + out.description = class_name; + return out; + } +} diff --git a/src/debugger/communication/command.ts b/src/debugger/communication/command.ts new file mode 100644 index 0000000..112d9a7 --- /dev/null +++ b/src/debugger/communication/command.ts @@ -0,0 +1,60 @@ +export class Command { + private callback?: ( + parameters: Array + ) => void | undefined; + private param_count = -1; + private param_count_callback?: (paramCount: number) => number; + private parameters: Array< + boolean | number | string | {} | [] | undefined + > = []; + + public name: string; + + constructor( + name: string, + parameters_fulfilled?: (parameters: Array) => void | undefined, + modify_param_count?: (param_count: number) => number + ) { + this.name = name; + this.callback = parameters_fulfilled; + this.param_count_callback = modify_param_count; + } + + public append_parameters( + parameter: boolean | number | string | {} | [] | undefined + ) { + if (this.param_count <= 0) { + this.param_count = parameter as number; + if (this.param_count === 0) { + if (this.callback) { + this.callback([]); + } + } + return; + } + + this.parameters.push(parameter); + + if (this.parameters.length === this.get_param_count()) { + if (this.callback) { + this.callback(this.parameters); + } + } + } + + public chain() { + if (this.parameters.length === this.get_param_count()) { + this.parameters.length = 0; + this.param_count = -1; + return undefined; + } else { + return this; + } + } + + protected get_param_count() { + return this.param_count_callback + ? this.param_count_callback(this.param_count) + : this.param_count; + } +} diff --git a/src/debugger/communication/command_builder.ts b/src/debugger/communication/command_builder.ts new file mode 100644 index 0000000..980636d --- /dev/null +++ b/src/debugger/communication/command_builder.ts @@ -0,0 +1,58 @@ +import { Command } from "./command"; +import { VariantParser } from "../variant_parser"; + +export class CommandBuilder { + private commands = new Map(); + private current_command?: Command; + private dummy_command = new Command("---"); + + constructor() {} + + public create_buffered_command( + command: string, + parser: VariantParser, + parameters?: any[] + ): Buffer { + let command_array: any[] = [command]; + if (parameters) { + parameters?.forEach(param => { + command_array.push(param); + }); + } + + let buffer = parser.encode_variant(command_array); + return buffer; + } + + public parse_data( + dataset: Array, + error_callback: (error: string) => void + ): void { + while (dataset && dataset.length > 0) { + if (this.current_command) { + let next_command = this.current_command.chain(); + if (next_command === this.current_command) { + this.current_command.append_parameters(dataset.shift()); + } else { + this.current_command = next_command; + } + } else { + let data = dataset.shift(); + if (data) { + let command = this.commands.get(data); + if (command) { + this.current_command = command; + } else { + error_callback(`Unsupported command: ${data}. Skipping.`); + this.current_command = this.dummy_command; + } + } + } + } + } + + public register_command(command: Command) { + let name = command.name; + this.commands.set(name, command); + } +} diff --git a/src/debugger/communication/godot_commands.ts b/src/debugger/communication/godot_commands.ts new file mode 100644 index 0000000..3951837 --- /dev/null +++ b/src/debugger/communication/godot_commands.ts @@ -0,0 +1,147 @@ +import { CommandBuilder } from "./command_builder"; +import { VariantParser } from "../variant_parser"; +import net = require("net"); + +export class GodotCommands { + private builder: CommandBuilder; + private can_write = false; + private command_buffer: Buffer[] = []; + private connection: net.Socket | undefined; + private parser: VariantParser; + + constructor( + builder: CommandBuilder, + parser: VariantParser, + connection?: net.Socket + ) { + this.builder = builder; + this.parser = parser; + this.connection = connection; + } + + public send_break_command() { + let buffer = this.builder.create_buffered_command("break", this.parser); + this.add_and_send(buffer); + } + + public send_continue_Command() { + let buffer = this.builder.create_buffered_command("continue", this.parser); + this.add_and_send(buffer); + } + + public send_inspect_object_command(object_id: number) { + let buffer = this.builder.create_buffered_command( + "inspect_object", + this.parser, + [object_id] + ); + + this.add_and_send(buffer); + } + + public set_object_property( + object_id: number, + label: string, + new_parsed_value: any + ) { + let buffer = this.builder.create_buffered_command( + "set_object_property", + this.parser, + [BigInt(object_id), label, new_parsed_value] + ); + this.add_and_send(buffer); + } + + public send_next_command() { + let buffer = this.builder.create_buffered_command("next", this.parser); + this.add_and_send(buffer); + } + + public send_remove_breakpoint_command(file: string, line: number) { + this.send_breakpoint_command(false, file, line); + } + + public send_request_scene_tree_command() { + let buffer = this.builder.create_buffered_command( + "request_scene_tree", + this.parser + ); + this.add_and_send(buffer); + } + + public send_set_breakpoint_command(file: string, line: number) { + this.send_breakpoint_command(true, file, line); + } + + public send_skip_breakpoints_command(skip_breakpoints: boolean) { + let buffer = this.builder.create_buffered_command( + "set_skip_breakpoints", + this.parser, + [skip_breakpoints] + ); + + this.add_and_send(buffer); + } + + public send_stack_dump_command() { + let buffer = this.builder.create_buffered_command( + "get_stack_dump", + this.parser + ); + + this.add_and_send(buffer); + } + + public send_stack_frame_vars_command(level: number) { + let buffer = this.builder.create_buffered_command( + "get_stack_frame_vars", + this.parser, + [level] + ); + + this.add_and_send(buffer); + } + + public send_step_command() { + let buffer = this.builder.create_buffered_command("step", this.parser); + this.add_and_send(buffer); + } + + public set_can_write(value: boolean) { + this.can_write = value; + if (this.can_write) { + this.send_buffer(); + } + } + + public set_connection(connection: net.Socket) { + this.connection = connection; + this.can_write = true; + } + + private add_and_send(buffer: Buffer) { + this.command_buffer.push(buffer); + this.send_buffer(); + } + + private send_breakpoint_command(set: boolean, file: string, line: number) { + let buffer = this.builder.create_buffered_command( + "breakpoint", + this.parser, + [file, line, set] + ); + this.add_and_send(buffer); + } + + private send_buffer() { + if (!this.connection) { + return; + } + + while (this.can_write && this.command_buffer.length > 0) { + this.can_write = this.connection.write( + this.command_buffer.shift() as Buffer + ); + } + } +} diff --git a/src/debugger/communication/server_controller.ts b/src/debugger/communication/server_controller.ts new file mode 100644 index 0000000..20272a7 --- /dev/null +++ b/src/debugger/communication/server_controller.ts @@ -0,0 +1,454 @@ +const TERMINATE = require("terminate"); +import { EventEmitter } from "events"; +import net = require("net"); +import cp = require("child_process"); +import path = require("path"); +import { VariantParser } from "../variant_parser"; +import { Command } from "./command"; +import vscode = require("vscode"); +import { GodotCommands } from "./godot_commands"; +import { CommandBuilder } from "./command_builder"; +import { GodotBreakpoint, GodotStackFrame } from "../godot_debug_runtime"; +import utils = require("../../utils"); +import { SceneTreeBuilder } from "../SceneTree/tree_builders"; +import { SceneTreeProvider } from "../SceneTree/scene_tree_provider"; + +export class ServerController { + private breakpoints: { file: string; line: number }[] = []; + private builder: CommandBuilder | undefined; + private connection: net.Socket | undefined; + private emitter: EventEmitter; + private exception = ""; + private godot_commands: GodotCommands | undefined; + private godot_pid: number | undefined; + private initial_output = false; + private inspected_callbacks: (( + class_name: string, + properties: any[] + ) => void)[] = []; + private last_frame: + | { line: number; file: string; function: string } + | undefined; + private log_output = ""; + private logging = false; + private output_channel: vscode.OutputChannel | undefined; + private parser: VariantParser | undefined; + private project_path: string; + private scope_callbacks: (( + stack_level: number, + stack_files: string[], + scopes: { + locals: { name: string; value: any }[]; + members: { name: string; value: any }[]; + globals: { name: string; value: any }[]; + } + ) => void)[] = []; + private server: net.Server | undefined; + private stack_count = 0; + private stack_files: string[] = []; + private stack_level = 0; + private stepping_out = false; + private tree_provider: SceneTreeProvider | undefined; + + constructor( + event_emitter: EventEmitter, + output_channel?: vscode.OutputChannel, + tree_provider?: SceneTreeProvider + ) { + this.emitter = event_emitter; + this.output_channel = output_channel; + this.tree_provider = tree_provider; + } + + public break() { + this.godot_commands?.send_break_command(); + } + + public continue() { + this.godot_commands?.send_continue_Command(); + } + + public get_scope( + level: number, + callback?: ( + stack_level: number, + stack_files: string[], + scopes: { + locals: { name: string; value: any }[]; + members: { name: string; value: any }[]; + globals: { name: string; value: any }[]; + } + ) => void + ) { + this.godot_commands?.send_stack_frame_vars_command(level); + this.stack_level = level; + if (callback) { + this.scope_callbacks.push(callback); + } + } + + public inspect_object( + id: number, + inspected: (class_name: string, properties: any[]) => void + ) { + this.inspected_callbacks.push(inspected); + this.godot_commands?.send_inspect_object_command(id); + } + + public next() { + this.godot_commands?.send_next_command(); + } + + public remove_breakpoint(path_to: string, line: number) { + this.breakpoints.splice( + this.breakpoints.findIndex(bp => bp.file === path_to && bp.line === line), + 1 + ); + this.godot_commands?.send_remove_breakpoint_command(path_to, line); + } + + public request_scene_tree() { + this.godot_commands.send_request_scene_tree_command(); + } + + public set_object_property( + object_id: number, + label: string, + new_parsed_value: any + ) { + this.godot_commands.set_object_property(object_id, label, new_parsed_value); + } + + public set_breakpoint(path_to: string, line: number) { + this.breakpoints.push({ file: path_to, line: line }); + this.godot_commands?.send_set_breakpoint_command(path_to, line); + } + + public start( + project_path: string, + port: number, + address: string, + launch_game_instance?: boolean, + breakpoints?: GodotBreakpoint[] + ) { + this.builder = new CommandBuilder(); + this.parser = new VariantParser(); + this.project_path = project_path.replace(/\\/g, "/"); + if (this.project_path.match(/^[A-Z]:\//)) { + this.project_path = + this.project_path[0].toLowerCase() + this.project_path.slice(1); + } + this.godot_commands = new GodotCommands(this.builder, this.parser); + + if (breakpoints) { + this.breakpoints = breakpoints.map(bp => { + return { file: bp.file, line: bp.line }; + }); + } + + this.builder.register_command(new Command("debug_exit", params => {})); + + this.builder.register_command( + new Command("debug_enter", params => { + let reason = params[1]; + if (reason !== "Breakpoint") { + this.exception = params[1]; + } else { + this.exception = ""; + } + this.godot_commands?.send_stack_dump_command(); + }) + ); + + this.builder.register_command( + new Command("stack_dump", params => { + let frames: Map[] = params; + this.trigger_breakpoint( + frames.map((sf, i) => { + return { + id: i, + thread_id: sf.get("id"), + file: sf.get("file"), + function: sf.get("function"), + line: sf.get("line") + }; + }) + ); + this.request_scene_tree(); + }) + ); + + this.builder.register_command( + new Command("output", params => { + if (!this.initial_output) { + this.initial_output = true; + this.request_scene_tree(); + } + params.forEach(line => { + this.output_channel?.appendLine(line); + }); + }) + ); + + this.builder.register_command( + new Command("error", params => { + params.forEach(param => {}); + }) + ); + + this.builder.register_command(new Command("performance", params => {})); + + this.builder.register_command( + new Command("message:inspect_object", params => { + let id = params[0]; + let class_name = params[1]; + let properties = params[2]; + + let callback = this.inspected_callbacks.shift(); + if (callback) { + callback(class_name, properties); + } + }) + ); + + this.builder.register_command( + new Command("message:scene_tree", params => { + if (this.tree_provider) { + let tree = SceneTreeBuilder.build(params); + this.tree_provider.fill_tree(tree); + } + }) + ); + + this.builder.register_command( + new Command("stack_frame_vars", params => { + let locals: any[] = []; + let members: any[] = []; + let globals: any[] = []; + + let local_count = (params[0] as number) * 2; + let member_count = params[1 + local_count] * 2; + let global_count = params[2 + local_count + member_count] * 2; + + if (local_count > 0) { + locals = params.slice(1, 1 + local_count); + } + if (member_count > 0) { + members = params.slice( + 2 + local_count, + 2 + local_count + member_count + ); + } + if (global_count > 0) { + globals = params.slice( + 3 + local_count + member_count, + 3 + local_count + member_count + global_count + ); + } + + this.pumpScope( + { + locals: locals, + members: members, + globals: globals + }, + project_path + ); + }) + ); + + this.server = net.createServer(connection => { + this.connection = connection; + this.godot_commands?.set_connection(connection); + + if (!launch_game_instance) { + this.breakpoints.forEach(bp => { + let path_to = path + .relative(this.project_path, bp.file) + .replace(/\\/g, "/"); + this.godot_commands?.send_set_breakpoint_command( + `res://${path_to}`, + bp.line + ); + }); + } + + connection.on("data", buffer => { + if (!this.parser || !this.builder) { + return; + } + + let split_buffers = this.split_buffer(buffer); + while(split_buffers.length > 0) { + let sub_buffer = split_buffers.shift() + let data = this.parser.get_buffer_dataset(sub_buffer, 0); + this.builder.parse_data(data.slice(1), error => { + console.log(error); + console.log(this.log_output); + }) + } + }); + + connection.on("close", hadError => { + if (hadError) { + this.send_event("terminated"); + } + }); + + connection.on("end", () => { + this.send_event("terminated"); + }); + + connection.on("error", error => { + console.error(error); + }); + + connection.on("drain", () => { + connection.resume(); + this.godot_commands?.set_can_write(true); + }); + }); + + this.server?.listen(port, address); + + if (launch_game_instance) { + let godot_path = utils.get_configuration( + "editor_path", + "godot" + ) as string; + let executable_line = `${godot_path} --path ${project_path} --remote-debug ${address}:${port}`; + executable_line += this.build_breakpoint_string( + breakpoints, + project_path + ); + let godot_exec = cp.exec(executable_line); + this.godot_pid = godot_exec.pid; + } + } + + private split_buffer(buffer: Buffer) { + let len = buffer.byteLength; + let offset = 0; + let buffers: Buffer[] = []; + + while(len > 0) { + let sub_len = buffer.readUInt32LE(offset)+4; + buffers.push(buffer.slice(offset, offset+sub_len)); + offset += sub_len; + len -= sub_len; + } + + return buffers; + } + + public step() { + this.godot_commands?.send_step_command(); + } + + public step_out() { + this.stepping_out = true; + this.next(); + } + + public stop() { + this.connection?.end(() => { + this.server?.close(); + if (this.godot_pid) { + TERMINATE(this.godot_pid, (error: string | undefined) => { + if (error) { + console.error(error); + } + }); + } + }); + this.send_event("terminated"); + } + + private build_breakpoint_string( + breakpoints: GodotBreakpoint[], + project: string + ): string { + let output = ""; + if (breakpoints.length > 0) { + output += " --breakpoints "; + + breakpoints.forEach(bp => { + let relative_path = path.relative(project, bp.file).replace(/\\/g, "/"); + if (relative_path.length !== 0) { + output += `res://${relative_path}:${bp.line},`; + } + }); + output = output.slice(0, -1); + } + + return output; + } + + private pumpScope( + scopes: { + locals: any[]; + members: any[]; + globals: any[]; + }, + projectPath: string + ) { + if (this.scope_callbacks.length > 0) { + let cb = this.scope_callbacks.shift(); + if (cb) { + let stack_files = this.stack_files.map(sf => { + return sf.replace("res://", `${projectPath}/`); + }); + cb(this.stack_level, stack_files, scopes); + } + } + } + + private send_event(event: string, ...args: any[]) { + setImmediate(_ => { + this.emitter.emit(event, ...args); + }); + } + + private trigger_breakpoint(stack_frames: GodotStackFrame[]) { + let continue_stepping = false; + let stack_count = stack_frames.length; + + let file = stack_frames[0].file.replace("res://", `${this.project_path}/`); + let line = stack_frames[0].line; + + if (this.stepping_out) { + let breakpoint = this.breakpoints.find( + k => k.file === file && k.line === line + ); + if (!breakpoint) { + if (this.stack_count > 1) { + continue_stepping = this.stack_count === stack_count; + } else { + let file_same = stack_frames[0].file === this.last_frame.file; + let func_same = stack_frames[0].function === this.last_frame.function; + let line_greater = stack_frames[0].line >= this.last_frame.line; + + continue_stepping = file_same && func_same && line_greater; + } + } + } + this.stack_count = stack_count; + this.last_frame = stack_frames[0]; + + if (continue_stepping) { + this.next(); + return; + } + + this.stepping_out = false; + + this.stack_files = stack_frames.map(sf => { + return sf.file; + }); + if (this.exception.length === 0) { + this.send_event("stopOnBreakpoint", stack_frames); + } else { + this.send_event("stopOnException", stack_frames, this.exception); + } + } +} diff --git a/src/debugger/debug_adapter.ts b/src/debugger/debug_adapter.ts new file mode 100644 index 0000000..e557f3b --- /dev/null +++ b/src/debugger/debug_adapter.ts @@ -0,0 +1,3 @@ +import { GodotDebugSession } from "./godot_debug"; + +GodotDebugSession.run(GodotDebugSession); diff --git a/src/debugger/debugger_context.ts b/src/debugger/debugger_context.ts new file mode 100644 index 0000000..2710a0f --- /dev/null +++ b/src/debugger/debugger_context.ts @@ -0,0 +1,215 @@ +import { + ExtensionContext, + debug, + DebugConfigurationProvider, + WorkspaceFolder, + DebugAdapterInlineImplementation, + DebugAdapterDescriptorFactory, + DebugConfiguration, + DebugAdapterDescriptor, + DebugSession, + CancellationToken, + ProviderResult, + window, + commands +} from "vscode"; +import { GodotDebugSession } from "./godot_debug"; +import fs = require("fs"); +import { SceneTreeProvider, SceneNode } from "./SceneTree/scene_tree_provider"; +import { + InspectorProvider, + RemoteProperty +} from "./SceneTree/inspector_provider"; + +export function register_debugger(context: ExtensionContext) { + let provider = new GodotConfigurationProvider(); + context.subscriptions.push( + debug.registerDebugConfigurationProvider("godot", provider) + ); + + let inspector_provider = new InspectorProvider(); + window.registerTreeDataProvider("inspect-node", inspector_provider); + + let scene_tree_provider = new SceneTreeProvider(); + window.registerTreeDataProvider("active-scene-tree", scene_tree_provider); + + let factory = new GodotDebugAdapterFactory( + scene_tree_provider, + inspector_provider + ); + context.subscriptions.push( + debug.registerDebugAdapterDescriptorFactory("godot", factory) + ); + + commands.registerCommand( + "godot-tool.debugger.inspect_node", + (element: SceneNode | RemoteProperty) => { + if (element instanceof SceneNode) { + factory.session.inspect_node( + element.label, + element.object_id, + (class_name, properties) => { + inspector_provider.fill_tree( + element.label, + class_name, + element.object_id, + properties + ); + } + ); + } else if (element instanceof RemoteProperty) { + factory.session.inspect_node( + element.label, + element.value.id, + (class_name, properties) => { + inspector_provider.fill_tree( + element.label, + class_name, + element.value.id, + properties + ); + } + ); + } + } + ); + + commands.registerCommand("godot-tool.debugger.refresh_scene_tree", () => { + factory.session.request_scene_tree(); + }); + + commands.registerCommand("godot-tool.debugger.refresh_inspector", () => { + if (inspector_provider.has_tree()) { + factory.session.reinspect_node((name, class_name, properties) => { + inspector_provider.fill_tree( + name, + class_name, + factory.session.get_last_id(), + properties + ); + }); + } + }); + + commands.registerCommand( + "godot-tool.debugger.edit_value", + (property: RemoteProperty) => { + let previous_value = property.value; + let type = typeof previous_value; + let is_float = type === "number" && !Number.isInteger(previous_value); + window.showInputBox({ value: `${property.description}` }).then(value => { + let new_parsed_value: any; + switch (type) { + case "string": + new_parsed_value = value; + break; + case "number": + if (is_float) { + new_parsed_value = parseFloat(value); + if (new_parsed_value === NaN) { + return; + } + } else { + new_parsed_value = parseInt(value); + if (new_parsed_value === NaN) { + return; + } + } + break; + case "boolean": + new_parsed_value = value.toLowerCase() === "true"; + break; + } + if (property.changes_parent) { + let parents = [property.parent]; + let idx = 0; + while (parents[idx].changes_parent) { + parents.push(parents[idx++].parent); + } + let changed_value = inspector_provider.get_changed_value( + parents, + property, + new_parsed_value + ); + factory.session.set_object_property( + property.object_id, + parents[idx].label, + changed_value + ); + } else { + factory.session.set_object_property( + property.object_id, + property.label, + new_parsed_value + ); + } + factory.session.reinspect_node((name, class_name, properties) => { + inspector_provider.fill_tree( + name, + class_name, + factory.session.get_last_id(), + properties + ); + }); + }); + } + ); + + context.subscriptions.push(factory); +} + +class GodotConfigurationProvider implements DebugConfigurationProvider { + public resolveDebugConfiguration( + folder: WorkspaceFolder | undefined, + config: DebugConfiguration, + token?: CancellationToken + ): ProviderResult { + if (!config.type && !config.request && !config.name) { + const editor = window.activeTextEditor; + if (editor && fs.existsSync(`${folder}/project.godot`)) { + config.type = "godot"; + config.name = "Debug Godot"; + config.request = "launch"; + config.project = "${workspaceFolder}"; + config.port = 6007; + config.address = "127.0.0.1"; + config.launch_game_instance = true; + } + } + + if (!config.project) { + return window + .showInformationMessage( + "Cannot find a project.godot in active workspace." + ) + .then(() => { + return undefined; + }); + } + + return config; + } +} + +class GodotDebugAdapterFactory implements DebugAdapterDescriptorFactory { + public session: GodotDebugSession | undefined; + + constructor( + private tree_provider: SceneTreeProvider, + private inspector_provider: InspectorProvider + ) {} + + public createDebugAdapterDescriptor( + session: DebugSession + ): ProviderResult { + this.session = new GodotDebugSession(); + this.inspector_provider.clean_up(); + this.session.set_tree_provider(this.tree_provider); + return new DebugAdapterInlineImplementation(this.session); + } + + public dispose() { + this.session.dispose(); + this.session = undefined; + } +} diff --git a/src/debugger/godot_debug.ts b/src/debugger/godot_debug.ts new file mode 100644 index 0000000..bfc2694 --- /dev/null +++ b/src/debugger/godot_debug.ts @@ -0,0 +1,588 @@ +import { + LoggingDebugSession, + InitializedEvent, + TerminatedEvent, + StoppedEvent, + Thread, + Source, + Breakpoint +} from "vscode-debugadapter"; +import { DebugProtocol } from "vscode-debugprotocol"; +import { window, OutputChannel } from "vscode"; +const { Subject } = require("await-notify"); +import { GodotDebugRuntime, GodotStackFrame } from "./godot_debug_runtime"; +import { VariableScope, VariableScopeBuilder } from "./variable_scope"; +import { SceneTreeProvider } from "./SceneTree/scene_tree_provider"; +import stringify from "./stringify"; +import fs = require("fs"); + +interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments { + address: string; + launch_game_instance: boolean; + port: number; + project: string; +} + +var output_channel: OutputChannel | undefined; + +export class GodotDebugSession extends LoggingDebugSession { + private static MAIN_THREAD_ID = 0; + + private configuration_done = new Subject(); + private current_stack_level = 0; + private excepted = false; + private have_scopes: (() => void)[] = []; + private last_frames: GodotStackFrame[] = []; + private last_inspection_id = -1; + private last_inspection_name = ""; + private runtime: GodotDebugRuntime; + private scope_builder: VariableScopeBuilder | undefined; + private tree_provider: SceneTreeProvider | undefined; + + public constructor() { + super(); + + if (!output_channel) { + output_channel = window.createOutputChannel("Godot"); + } else { + output_channel.clear(); + } + + this.setDebuggerLinesStartAt1(false); + this.setDebuggerColumnsStartAt1(false); + + this.runtime = new GodotDebugRuntime(); + + this.runtime.on("stopOnBreakpoint", frames => { + this.last_frames = frames; + this.sendEvent( + new StoppedEvent("breakpoint", GodotDebugSession.MAIN_THREAD_ID) + ); + }); + + this.runtime.on("stopOnException", (frames, exception) => { + this.last_frames = frames; + this.sendEvent( + new StoppedEvent( + "exception", + GodotDebugSession.MAIN_THREAD_ID, + exception + ) + ); + }); + + this.runtime.on("terminated", () => { + this.sendEvent(new TerminatedEvent(false)); + }); + } + + public dispose() {} + + public get_last_id(): number { + return this.last_inspection_id; + } + + public inspect_node( + object_name: string, + object_id: number, + inspected: (class_name: string, properties: any[]) => void + ) { + this.last_inspection_id = object_id; + this.last_inspection_name = object_name; + this.runtime.inspect_object(object_id, inspected); + } + + public reinspect_node( + callback: (name: string, class_name: string, properties: any[]) => void + ) { + this.inspect_node( + this.last_inspection_name, + this.last_inspection_id, + (class_name, properties) => { + callback(this.last_inspection_name, class_name, properties); + } + ); + } + + public request_scene_tree() { + this.runtime.request_scene_tree(); + } + + public set_object_property( + object_id: number, + label: string, + new_parsed_value: any + ) { + this.runtime.set_object_property(object_id, label, new_parsed_value); + } + + public set_tree_provider(tree_provider: SceneTreeProvider) { + this.tree_provider = tree_provider; + } + + protected configurationDoneRequest( + response: DebugProtocol.ConfigurationDoneResponse, + args: DebugProtocol.ConfigurationDoneArguments + ): void { + super.configurationDoneRequest(response, args); + + this.configuration_done.notify(); + } + + protected continueRequest( + response: DebugProtocol.ContinueResponse, + args: DebugProtocol.ContinueArguments + ): void { + if (this.excepted) { + return; + } + + response.body = { + allThreadsContinued: true + }; + + this.runtime.continue(); + + this.sendResponse(response); + } + + protected evaluateRequest( + response: DebugProtocol.EvaluateResponse, + args: DebugProtocol.EvaluateArguments + ) { + this.have_scopes.push(() => { + if (args.expression.match(/[^a-zA-Z0-9_\[\]\.]/g)) { + response.body = { + result: "not supported", + variablesReference: 0 + }; + this.sendResponse(response); + return; + } + + let is_self = args.expression.match(/^self\./); + let expression = args.expression + .replace(/[\[\]]/g, ".") + .replace(/\.$/, "") + .replace(/^self./, ""); + let variable: { name: string; value: any } | undefined; + let scope_keys = this.scope_builder.get_keys(this.current_stack_level); + let variable_id = -1; + for (let i = 0; i < scope_keys.length; ++i) { + let scopes = this.scope_builder.get( + this.current_stack_level, + scope_keys[i] + ); + + for (let l = is_self ? 1 : 0; l < 3; ++l) { + variable_id = scopes[l].get_id_for(expression); + if (variable_id !== -1) { + variable = scopes[l].get_variable(variable_id); + break; + } + } + + if (variable) { + break; + } + } + + if (!variable) { + response.body = { + result: "not available", + variablesReference: 0 + }; + + this.sendResponse(response); + return; + } + + let value_type_pair = stringify(variable.value); + + response.body = { + result: value_type_pair.value, + type: value_type_pair.type, + variablesReference: variable_id + }; + + this.sendResponse(response); + }); + if ( + this.scope_builder.size() > 0 && + this.scope_builder.get_keys(this.current_stack_level).length > 0 + ) { + this.have_scopes.shift()(); + } + } + + protected initializeRequest( + response: DebugProtocol.InitializeResponse, + args: DebugProtocol.InitializeRequestArguments + ): void { + response.body = response.body || {}; + + response.body.supportsConfigurationDoneRequest = true; + response.body.supportsTerminateRequest = true; + + response.body.supportsEvaluateForHovers = false; + + response.body.supportsStepBack = false; + response.body.supportsGotoTargetsRequest = false; + + response.body.supportsCancelRequest = false; + + response.body.supportsCompletionsRequest = false; + + response.body.supportsFunctionBreakpoints = false; + response.body.supportsDataBreakpoints = false; + response.body.supportsBreakpointLocationsRequest = false; + response.body.supportsConditionalBreakpoints = false; + response.body.supportsHitConditionalBreakpoints = false; + + response.body.supportsLogPoints = false; + + response.body.supportsModulesRequest = false; + + response.body.supportsReadMemoryRequest = false; + + response.body.supportsRestartFrame = false; + response.body.supportsRestartRequest = false; + + response.body.supportsSetExpression = false; + + //TODO: Implement + response.body.supportsSetVariable = false; + + response.body.supportsStepInTargetsRequest = false; + + response.body.supportsTerminateThreadsRequest = false; + + this.sendResponse(response); + + this.sendEvent(new InitializedEvent()); + } + + protected async launchRequest( + response: DebugProtocol.LaunchResponse, + args: LaunchRequestArguments + ) { + await this.configuration_done.wait(1000); + this.excepted = false; + this.runtime.start( + args.project, + args.address, + args.port, + args.launch_game_instance, + output_channel, + this.tree_provider + ); + this.sendResponse(response); + } + + protected nextRequest( + response: DebugProtocol.NextResponse, + args: DebugProtocol.NextArguments + ): void { + if (this.excepted) { + return; + } + this.runtime.next(); + this.sendResponse(response); + } + + protected pauseRequest( + response: DebugProtocol.PauseResponse, + args: DebugProtocol.PauseArguments + ): void { + if (this.excepted) { + return; + } + this.runtime.break(); + this.sendResponse(response); + } + + protected scopesRequest( + response: DebugProtocol.ScopesResponse, + args: DebugProtocol.ScopesArguments + ): void { + this.runtime.getScope(args.frameId, (stack_level, stack_files, scopes) => { + this.current_stack_level = stack_level; + this.scope_builder = new VariableScopeBuilder( + this.runtime, + stack_level, + stack_files, + scopes, + this.have_scopes + ); + this.scope_builder.parse(over_scopes => { + response.body = { scopes: over_scopes }; + this.sendResponse(response); + }); + }); + } + + protected setBreakPointsRequest( + response: DebugProtocol.SetBreakpointsResponse, + args: DebugProtocol.SetBreakpointsArguments + ): void { + let path = (args.source.path as string).replace(/\\/g, "/"); + let client_lines = args.lines || []; + + if (fs.existsSync(path)) { + let bps = this.runtime.get_breakpoints(path); + let bp_lines = bps.map(bp => bp.line); + + bps.forEach(bp => { + if (client_lines.indexOf(bp.line) === -1) { + this.runtime.remove_breakpoint(path, bp.line); + } + }); + client_lines.forEach(l => { + if (bp_lines.indexOf(l) === -1) { + this.runtime.set_breakpoint(path, l); + } + }); + + bps = this.runtime.get_breakpoints(path); + + response.body = { + breakpoints: bps.map(bp => { + return new Breakpoint( + true, + bp.line, + 1, + new Source(bp.file.split("/").reverse()[0], bp.file, bp.id) + ); + }) + }; + + this.sendResponse(response); + } + } + + protected setExceptionBreakPointsRequest( + response: DebugProtocol.SetExceptionBreakpointsResponse, + args: DebugProtocol.SetExceptionBreakpointsArguments + ) { + this.excepted = true; + this.sendResponse(response); + } + + protected stackTraceRequest( + response: DebugProtocol.StackTraceResponse, + args: DebugProtocol.StackTraceArguments + ): void { + if (this.last_frames) { + response.body = { + totalFrames: this.last_frames.length, + stackFrames: this.last_frames.map(sf => { + return { + id: sf.id, + name: sf.function, + line: sf.line, + column: 1, + source: new Source( + sf.file, + `${this.runtime.getProject()}/${sf.file.replace("res://", "")}` + ) + }; + }) + }; + } + this.sendResponse(response); + } + + protected stepInRequest( + response: DebugProtocol.StepInResponse, + args: DebugProtocol.StepInArguments + ) { + if (this.excepted) { + return; + } + this.runtime.step(); + this.sendResponse(response); + } + + protected stepOutRequest( + response: DebugProtocol.StepOutResponse, + args: DebugProtocol.StepOutArguments + ) { + if (this.excepted) { + return; + } + + this.runtime.step_out(); + + this.sendResponse(response); + } + + protected terminateRequest( + response: DebugProtocol.TerminateResponse, + args: DebugProtocol.TerminateArguments + ) { + this.runtime.terminate(); + this.sendResponse(response); + } + + protected threadsRequest(response: DebugProtocol.ThreadsResponse): void { + response.body = { + threads: [new Thread(GodotDebugSession.MAIN_THREAD_ID, "thread_1")] + }; + this.sendResponse(response); + } + + protected async variablesRequest( + response: DebugProtocol.VariablesResponse, + args: DebugProtocol.VariablesArguments, + request?: DebugProtocol.Request + ) { + let out_id = args.variablesReference; + let files = this.scope_builder.get_keys(this.current_stack_level); + + let out_scope_object = this.get_variable_scope(files, out_id); + let is_scope = out_scope_object.isScope; + let out_scope = out_scope_object.scope; + + if (out_scope) { + if (is_scope) { + let var_ids = out_scope.get_variable_ids(); + response.body = { + variables: this.parse_scope(var_ids, out_scope) + }; + } else { + let variable = out_scope.get_variable(out_id); + if (variable) { + let sub_variables = out_scope.get_sub_variables_for(out_id); + if (sub_variables) { + let ids = out_scope.get_variable_ids(); + let path_to = variable.name; + response.body = { + variables: [] + }; + + if (args.filter === "indexed") { + let count = args.count || 0; + for (let i = 0; i < count; i++) { + let name = `${path_to}.${i}`; + let id_index = ids.findIndex(id => { + let variable = out_scope?.get_variable(id); + return variable && name === variable.name; + }); + + response.body.variables.push( + this.get_variable_response( + name, + variable.value[i], + ids[id_index] + ) + ); + } + } else { + sub_variables.forEach(sv => { + let name = sv.name; + let id_index = ids.findIndex(id => { + let variable = out_scope?.get_variable(id); + return variable && name === variable.name; + }); + + response.body.variables.push( + this.get_variable_response(name, sv.value, ids[id_index]) + ); + }); + } + } else { + response.body = { + variables: [ + this.get_variable_response( + variable.name, + variable.value, + 0, + true + ) + ] + }; + } + } else { + response.body = { variables: [] }; + } + } + + this.sendResponse(response); + } + } + + private get_variable_response( + var_name: string, + var_value: any, + id: number, + skip_sub_var?: boolean + ) { + let value = ""; + let ref_id = 0; + let array_count = 0; + let type = ""; + if (!skip_sub_var) { + let output = stringify(var_value); + + value = output.value; + type = output.type; + ref_id = output.skip_id ? 0 : id; + } + return { + name: var_name.replace(/([a-zA-Z0-9_]+?\.)*/g, ""), + value: value, + variablesReference: ref_id, + indexedVariables: array_count, + type: type + }; + } + + private get_variable_scope(files: string[], scope_id: number) { + let out_scope: VariableScope | undefined; + let is_scope = false; + for (let i = 0; i < files.length; i++) { + let file = files[i]; + + let scopes = this.scope_builder.get(this.current_stack_level, file); + if (scopes) { + let index = scopes.findIndex(s => { + return s.id === scope_id; + }); + if (index !== -1) { + out_scope = scopes[index]; + is_scope = true; + break; + } else { + for (let l = 0; l < scopes.length; l++) { + let scope = scopes[l]; + let ids = scope.get_variable_ids(); + for (let k = 0; k < ids.length; k++) { + let id = ids[k]; + if (scope_id === id) { + out_scope = scope; + is_scope = false; + break; + } + } + } + } + } + } + + return { isScope: is_scope, scope: out_scope }; + } + + private parse_scope(var_ids: number[], out_scope: VariableScope) { + let output: DebugProtocol.Variable[] = []; + var_ids.forEach(id => { + let variable = out_scope?.get_variable(id); + if (variable && variable.name.indexOf(".") === -1) { + output.push( + this.get_variable_response(variable.name, variable.value, id) + ); + } + }); + + return output; + } +} diff --git a/src/debugger/godot_debug_runtime.ts b/src/debugger/godot_debug_runtime.ts new file mode 100644 index 0000000..5d5d3ad --- /dev/null +++ b/src/debugger/godot_debug_runtime.ts @@ -0,0 +1,177 @@ +import vscode = require("vscode"); +import { EventEmitter } from "events"; +import { ServerController } from "./communication/server_controller"; +import { SceneTreeProvider } from "./SceneTree/scene_tree_provider"; +import { InspectorProvider } from "./SceneTree/inspector_provider"; + +export interface GodotBreakpoint { + file: string; + id: number; + line: number; +} + +export interface GodotStackFrame { + file: string; + function: string; + id: number; + line: number; +} + +export class GodotDebugRuntime extends EventEmitter { + private breakpointId = 0; + private breakpoints = new Map(); + private out: vscode.OutputChannel | undefined; + private paused = false; + private project = ""; + private server_controller: ServerController | undefined; + + constructor() { + super(); + } + + public break() { + if (this.paused) { + this.server_controller?.continue(); + } else { + this.server_controller?.break(); + } + } + + public continue() { + this.server_controller?.continue(); + } + + public getProject(): string { + return this.project; + } + + public getScope( + level: number, + callback?: ( + stackLevel: number, + stackFiles: string[], + scopes: { + locals: any[]; + members: any[]; + globals: any[]; + } + ) => void + ) { + this.server_controller?.get_scope(level, callback); + } + + public get_breakpoints(path: string): GodotBreakpoint[] { + let bps = this.breakpoints.get(path); + return bps ? bps : []; + } + + public inspect_object( + objectId: number, + inspected: (className: string, properties: any[]) => void + ) { + this.server_controller?.inspect_object(objectId, inspected); + } + + public next() { + this.server_controller?.next(); + } + + public remove_breakpoint(pathTo: string, line: number) { + let bps = this.breakpoints.get(pathTo); + if (bps) { + let index = bps.findIndex(bp => { + return bp.line === line; + }); + if (index !== -1) { + let bp = bps[index]; + bps.splice(index, 1); + this.breakpoints.set(pathTo, bps); + this.server_controller?.remove_breakpoint( + bp.file.replace(new RegExp(`${this.project}/`), "res://"), + bp.line + ); + } + } + } + + public request_scene_tree() { + this.server_controller.request_scene_tree(); + } + + public set_object_property( + object_id: number, + label: string, + new_parsed_value: any + ) { + this.server_controller.set_object_property(object_id, label, new_parsed_value); + } + + public set_breakpoint(pathTo: string, line: number): GodotBreakpoint { + const BP = { + file: pathTo.replace(/\\/g, "/"), + line: line, + id: this.breakpointId++ + }; + + let bps = this.breakpoints.get(BP.file); + if (!bps) { + bps = new Array(); + this.breakpoints.set(BP.file, bps); + } + + bps.push(BP); + + this.server_controller?.set_breakpoint( + BP.file.replace(new RegExp(`${this.project}/`), "res://"), + line + ); + + return BP; + } + + public start( + project: string, + address: string, + port: number, + launchGameInstance: boolean, + out: vscode.OutputChannel, + tree_provider: SceneTreeProvider + ) { + this.out = out; + this.out.show(); + + this.project = project.replace(/\\/g, "/"); + if (this.project.match(/^[A-Z]:\//)) { + this.project = this.project[0].toLowerCase() + this.project.slice(1); + } + + this.server_controller = new ServerController( + this, + this.out, + tree_provider + ); + let breakpointList: GodotBreakpoint[] = []; + Array.from(this.breakpoints.values()).forEach(fbp => { + breakpointList = breakpointList.concat(fbp); + }); + this.server_controller.start( + project, + port, + address, + launchGameInstance, + breakpointList + ); + } + + public step() { + this.server_controller?.step(); + } + + public step_out() { + this.server_controller?.step_out(); + } + + public terminate() { + this.server_controller?.stop(); + } +} diff --git a/src/debugger/stringify.ts b/src/debugger/stringify.ts new file mode 100644 index 0000000..d6cca5f --- /dev/null +++ b/src/debugger/stringify.ts @@ -0,0 +1,91 @@ +export default function stringify( + var_value: any, + decimal_precision: number = 4 +) { + let type = ""; + let value = ""; + let skip_id = true; + if (typeof var_value === "number" && !Number.isInteger(var_value)) { + value = String( + +Number.parseFloat(no_exponents(var_value)).toFixed(decimal_precision) + ); + type = "Float"; + } else if (Array.isArray(var_value)) { + value = "Array"; + type = "Array"; + skip_id = false; + } else if (var_value instanceof Map) { + value = "Dictionary"; + type = "Dictionary"; + skip_id = false; + } else if (typeof var_value === "object") { + skip_id = false; + if (var_value.__type__) { + if (var_value.__type__ === "Object") { + skip_id = true; + } + if (var_value.__render__) { + value = var_value.__render__(); + } else { + value = var_value.__type__; + } + type = var_value.__type__; + } else { + value = "Object"; + } + } else { + if (var_value) { + if (Number.isInteger(var_value)) { + type = "Int"; + value = `${var_value}`; + } else if (typeof var_value === "string") { + type = "String"; + value = String(var_value); + } else if (typeof var_value === "boolean") { + type = "Bool"; + value = "true"; + } else { + type = "unknown"; + value = `${var_value}`; + } + } else { + if (Number.isInteger(var_value)) { + type = "Int"; + value = "0"; + } else if (typeof var_value === "boolean") { + type = "Bool"; + value = "false"; + } else { + type = "unknown"; + value = "null"; + } + } + } + + return { type: type, value: value, skip_id: skip_id }; +} + +function no_exponents(value: number): string { + let data = String(value).split(/[eE]/); + if (data.length === 1) { + return data[0]; + } + + let z = "", + sign = value < 0 ? "-" : ""; + let str = data[0].replace(".", ""); + let mag = Number(data[1]) + 1; + + if (mag < 0) { + z = sign + "0."; + while (mag++) { + z += "0"; + } + return z + str.replace(/^\-/, ""); + } + mag -= str.length; + while (mag--) { + z += 0; + } + return str + z; +} diff --git a/src/debugger/variable_scope.ts b/src/debugger/variable_scope.ts new file mode 100644 index 0000000..a055c9a --- /dev/null +++ b/src/debugger/variable_scope.ts @@ -0,0 +1,316 @@ +import { DebugProtocol } from "vscode-debugprotocol"; + +import { GodotDebugRuntime } from "./godot_debug_runtime"; +import stringify from "./stringify"; + +export class VariableScopeBuilder { + private inspect_callback: (() => void) | undefined; + private inspected: number[] = []; + private inspected_cache = new Map< + number, + { class_name: string; properties: any[] } + >(); + private over_scopes: DebugProtocol.Scope[]; + private scope_id = 1; + private scopes = new Map>(); + + constructor( + private runtime: GodotDebugRuntime, + private stack_level: number, + private stack_files: string[], + private raw_scopes: { locals: any[]; members: any[]; globals: any[] }, + private have_scopes: (() => void)[] = [] + ) {} + + public get(level: number, file: string) { + return this.scopes.get(level).get(file); + } + + public get_keys(level: number) { + return Array.from(this.scopes.get(level).keys()); + } + + public parse(callback: (over_scopes: DebugProtocol.Scope[]) => void) { + let file = this.stack_files[this.stack_level]; + + let file_scopes: VariableScope[] = []; + + let local_scope = new VariableScope(this.scope_id++); + let member_scope = new VariableScope(this.scope_id++); + let global_scope = new VariableScope(this.scope_id++); + + file_scopes.push(local_scope); + file_scopes.push(member_scope); + file_scopes.push(global_scope); + + this.scopes.set( + this.stack_level, + new Map([[file, file_scopes]]) + ); + + let out_local_scope: DebugProtocol.Scope = { + name: "Locals", + namedVariables: this.raw_scopes.locals.length / 2, + presentationHint: "locals", + expensive: false, + variablesReference: local_scope.id + }; + + for (let i = 0; i < this.raw_scopes.locals.length; i += 2) { + let name = this.raw_scopes.locals[i]; + let value = this.raw_scopes.locals[i + 1]; + + this.drill_scope( + local_scope, + { + name: name, + value: value ? value : undefined + }, + !value && typeof value === "number" + ); + } + + let out_member_scope: DebugProtocol.Scope = { + name: "Members", + namedVariables: this.raw_scopes.members.length / 2, + presentationHint: "locals", + expensive: false, + variablesReference: member_scope.id + }; + + for (let i = 0; i < this.raw_scopes.members.length; i += 2) { + let name = this.raw_scopes.members[i]; + let value = this.raw_scopes.members[i + 1]; + + this.drill_scope( + member_scope, + { name: name, value: value }, + !value && typeof value === "number" + ); + } + + let out_global_scope: DebugProtocol.Scope = { + name: "Globals", + namedVariables: this.raw_scopes.globals.length / 2, + presentationHint: "locals", + expensive: false, + variablesReference: global_scope.id + }; + + for (let i = 0; i < this.raw_scopes.globals.length; i += 2) { + let name = this.raw_scopes.globals[i]; + let value = this.raw_scopes.globals[i + 1]; + + this.drill_scope( + global_scope, + { name: name, value: value }, + !value && typeof value === "number" + ); + } + + this.over_scopes = [out_local_scope, out_member_scope, out_global_scope]; + + if (this.inspected.length === 0) { + while (this.have_scopes.length > 0) { + this.have_scopes.shift()(); + } + callback(this.over_scopes); + } else { + this.inspect_callback = () => { + while (this.have_scopes.length > 0) { + this.have_scopes.shift()(); + } + callback(this.over_scopes); + }; + } + } + + public size() { + return this.scopes.size; + } + + private drill_scope( + scope: VariableScope, + variable: any, + is_zero_number?: boolean + ) { + if (is_zero_number) { + variable.value = 0; + } + let id = scope.get_id_for(variable.name); + if (id === -1) { + id = this.scope_id++; + } + scope.set_variable(variable.name, variable.value, id); + if (Array.isArray(variable.value) || variable.value instanceof Map) { + let length = 0; + let values: any[]; + if (variable.value instanceof Map) { + length = variable.value.size; + let keys = Array.from(variable.value.keys()); + values = keys.map(key => { + let value = variable.value.get(key); + let stringified_key = stringify(key).value; + + return { + __type__: "Pair", + key: key, + value: value, + __render__: () => stringified_key + }; + }); + variable.value = values; + } else { + length = variable.value.length; + values = variable.value; + } + for (let i = 0; i < length; i++) { + let name = `${variable.name}.${i}`; + scope.set_sub_variable_for(id, name, values[i]); + this.drill_scope(scope, { + name: name, + value: values[i] + }); + } + } else if (typeof variable.value === "object") { + if (variable.value.__type__ && variable.value.__type__ === "Object") { + if (!this.inspected_cache.has(id)) { + if (this.inspected.indexOf(id) === -1) { + this.inspected.push(id); + this.runtime.inspect_object( + variable.value.id, + (class_name, properties) => { + this.inspected_cache.set(id, { + class_name: class_name, + properties: properties + }); + this.parse_deeper(variable, scope, id, class_name, properties); + } + ); + } + } else { + let cached = this.inspected_cache.get(id); + this.parse_deeper( + variable, + scope, + id, + cached.class_name, + cached.properties + ); + } + } else { + for (const PROP in variable.value) { + if (PROP !== "__type__" && PROP !== "__render__") { + let name = `${variable.name}.${PROP}`; + scope.set_sub_variable_for(id, name, variable.value[PROP]); + this.drill_scope(scope, { + name: name, + value: variable.value[PROP] + }); + } + } + } + } + } + + private parse_deeper( + variable: any, + scope: VariableScope, + id: number, + class_name: string, + properties: any[][] + ) { + variable.value.__type__ = class_name; + let start_index = 0; + variable.value.__render__ = () => `${class_name}`; + let relevant_properties = properties.slice(start_index + 1).filter(p => { + if (!p[5]) { + return Number.isInteger(p[5]); + } + + return true; + }); + relevant_properties.forEach(p => { + let sub_name = `${variable.name}.${p[0]}`; + scope.set_sub_variable_for(id, sub_name, p[5]); + this.drill_scope(scope, { name: sub_name, value: p[5] }); + }); + + let inspected_idx = this.inspected.indexOf(variable.value.id); + if (inspected_idx !== -1) { + this.inspected.splice(inspected_idx, 1); + } + + if (this.inspected.length === 0 && this.inspect_callback) { + this.inspect_callback(); + } + } +} + +export class VariableScope { + private sub_variables = new Map(); + private variables = new Map(); + + public readonly id: number; + + constructor(id: number) { + this.id = id; + } + + public get_id_for(name: string) { + let ids = Array.from(this.variables.keys()); + return ( + ids.find(v => { + let var_name = this.variables.get(v).name; + return var_name === name; + }) || -1 + ); + } + + public get_sub_variable_for(name: string, id: number) { + let sub_variables = this.sub_variables.get(id); + if (sub_variables) { + let index = sub_variables.findIndex(sv => { + return sv.name === name; + }); + if (index !== -1) { + return sub_variables[index]; + } + } + + return undefined; + } + + public get_sub_variables_for(id: number) { + return this.sub_variables.get(id); + } + + public get_variable(id: number): { name: string; value: any } | undefined { + return this.variables.get(id); + } + + public get_variable_ids() { + return Array.from(this.variables.keys()); + } + + public set_sub_variable_for(variable_id: number, name: string, value: any) { + let sub_variables = this.sub_variables.get(variable_id); + if (!sub_variables) { + sub_variables = []; + this.sub_variables.set(variable_id, sub_variables); + } + + let index = sub_variables.findIndex(sv => { + return sv.name === name; + }); + + if (index === -1) { + sub_variables.push({ name: name, value: value }); + } + } + + public set_variable(name: string, value: any, id: number) { + let variable = { name: name, value: value }; + this.variables.set(id, variable); + } +} diff --git a/src/debugger/variant_parser.ts b/src/debugger/variant_parser.ts new file mode 100644 index 0000000..1817fef --- /dev/null +++ b/src/debugger/variant_parser.ts @@ -0,0 +1,905 @@ +enum GDScriptTypes { + NIL, + + // atomic types + BOOL, + INT, + REAL, + STRING, + + // math types + + VECTOR2, // 5 + RECT2, + VECTOR3, + TRANSFORM2D, + PLANE, + QUAT, // 10 + AABB, + BASIS, + TRANSFORM, + + // misc types + COLOR, + NODE_PATH, // 15 + _RID, + OBJECT, + DICTIONARY, + ARRAY, + + // arrays + POOL_BYTE_ARRAY, // 20 + POOL_INT_ARRAY, + POOL_REAL_ARRAY, + POOL_STRING_ARRAY, + POOL_VECTOR2_ARRAY, + POOL_VECTOR3_ARRAY, // 25 + POOL_COLOR_ARRAY, + + VARIANT_MAX +} + +interface BufferModel { + buffer: Buffer; + len: number; + offset: number; +} + +export class VariantParser { + public decode_variant(model: BufferModel) { + let type = this.decode_UInt32(model); + switch (type & 0xff) { + case GDScriptTypes.BOOL: + return this.decode_UInt32(model) !== 0; + case GDScriptTypes.INT: + if (type & (1 << 16)) { + return this.decode_Int64(model); + } else { + return this.decode_Int32(model); + } + case GDScriptTypes.REAL: + if (type & (1 << 16)) { + return this.decode_Double(model); + } else { + return this.decode_Float(model); + } + case GDScriptTypes.STRING: + return this.decode_String(model); + case GDScriptTypes.VECTOR2: + return this.decode_Vector2(model); + case GDScriptTypes.RECT2: + return this.decode_Rect2(model); + case GDScriptTypes.VECTOR3: + return this.decode_Vector3(model); + case GDScriptTypes.TRANSFORM2D: + return this.decode_Transform2D(model); + case GDScriptTypes.PLANE: + return this.decode_Plane(model); + case GDScriptTypes.QUAT: + return this.decode_Quat(model); + case GDScriptTypes.AABB: + return this.decode_AABB(model); + case GDScriptTypes.BASIS: + return this.decode_Basis(model); + case GDScriptTypes.TRANSFORM: + return this.decode_Transform(model); + case GDScriptTypes.COLOR: + return this.decode_Color(model); + case GDScriptTypes.NODE_PATH: + return this.decode_NodePath(model); + case GDScriptTypes.OBJECT: + if (type & (1 << 16)) { + return this.decode_Object_id(model); + } else { + return this.decode_Object(model); + } + case GDScriptTypes.DICTIONARY: + return this.decode_Dictionary(model); + case GDScriptTypes.ARRAY: + return this.decode_Array(model); + case GDScriptTypes.POOL_BYTE_ARRAY: + return this.decode_PoolByteArray(model); + case GDScriptTypes.POOL_INT_ARRAY: + return this.decode_PoolIntArray(model); + case GDScriptTypes.POOL_REAL_ARRAY: + return this.decode_PoolFloatArray(model); + case GDScriptTypes.POOL_STRING_ARRAY: + return this.decode_PoolStringArray(model); + case GDScriptTypes.POOL_VECTOR2_ARRAY: + return this.decode_PoolVector2Array(model); + case GDScriptTypes.POOL_VECTOR3_ARRAY: + return this.decode_PoolVector3Array(model); + case GDScriptTypes.POOL_COLOR_ARRAY: + return this.decode_PoolColorArray(model); + default: + return undefined; + } + } + + public encode_variant( + value: + | number + | bigint + | boolean + | string + | Map + | Array + | object + | undefined, + model?: BufferModel + ) { + if(typeof value === "number" && (value > 2147483647 || value < -2147483648)) { + value = BigInt(value); + } + + if (!model) { + let size = this.size_variant(value); + let buffer = Buffer.alloc(size + 4); + model = { + buffer: buffer, + offset: 0, + len: 0 + }; + this.encode_UInt32(size, model); + } + + switch (typeof value) { + case "number": + { + let is_integer = Number.isInteger(value); + if (is_integer) { + this.encode_UInt32(GDScriptTypes.INT, model); + this.encode_UInt32(value, model); + } else { + this.encode_UInt32(GDScriptTypes.REAL | (1 << 16), model); + this.encode_Float(value, model); + } + } + break; + case "bigint": + this.encode_UInt32(GDScriptTypes.INT | (1 << 16), model); + this.encode_UInt64(value, model); + break; + case "boolean": + this.encode_UInt32(GDScriptTypes.BOOL, model); + this.encode_Bool(value, model); + break; + case "string": + this.encode_UInt32(GDScriptTypes.STRING, model); + this.encode_String(value, model); + break; + case "undefined": + break; + default: + if (Array.isArray(value)) { + this.encode_UInt32(GDScriptTypes.ARRAY, model); + this.encode_Array(value, model); + } else if (value instanceof Map) { + this.encode_UInt32(GDScriptTypes.DICTIONARY, model); + this.encode_Dictionary(value, model); + } else { + switch (value["__type__"]) { + case "Vector2": + this.encode_UInt32(GDScriptTypes.VECTOR2, model); + this.encode_Vector2(value, model); + break; + case "Rect2": + this.encode_UInt32(GDScriptTypes.RECT2, model); + this.encode_Rect2(value, model); + break; + case "Vector3": + this.encode_UInt32(GDScriptTypes.VECTOR3, model); + this.encode_Vector3(value, model); + break; + case "Transform2D": + this.encode_UInt32(GDScriptTypes.TRANSFORM2D, model); + this.encode_Transform2D(value, model); + break; + case "Plane": + this.encode_UInt32(GDScriptTypes.PLANE, model); + this.encode_Plane(value, model); + break; + case "Quat": + this.encode_UInt32(GDScriptTypes.QUAT, model); + this.encode_Quat(value, model); + break; + case "AABB": + this.encode_UInt32(GDScriptTypes.AABB, model); + this.encode_AABB(value, model); + break; + case "Basis": + this.encode_UInt32(GDScriptTypes.BASIS, model); + this.encode_Basis(value, model); + break; + case "Transform": + this.encode_UInt32(GDScriptTypes.TRANSFORM, model); + this.encode_Transform(value, model); + break; + case "Color": + this.encode_UInt32(GDScriptTypes.COLOR, model); + this.encode_Color(value, model); + break; + } + } + } + + return model.buffer; + } + + public get_buffer_dataset(buffer: Buffer, offset: number) { + let len = buffer.readUInt32LE(offset); + let model: BufferModel = { + buffer: buffer, + offset: offset + 4, + len: len + }; + + let output = []; + output.push(len + 4); + do { + let value = this.decode_variant(model); + output.push(value); + } while (model.len > 0); + + return output; + } + + private clean(value: number) { + return +Number.parseFloat(String(value)).toFixed(1); + } + + private decode_AABB(model: BufferModel) { + let px = this.decode_Float(model); + let py = this.decode_Float(model); + let pz = this.decode_Float(model); + let sx = this.decode_Float(model); + let sy = this.decode_Float(model); + let sz = this.decode_Float(model); + + return { + __type__: "AABB", + position: this.make_Vector3(px, py, pz), + size: this.make_Vector3(sx, sy, sz), + __render__: () => + `AABB (${this.clean(px)}, ${this.clean(py)}, ${this.clean( + pz + )} - ${this.clean(sx)}, ${this.clean(sy)}, ${this.clean(sz)})` + }; + } + + private decode_Array(model: BufferModel) { + let output: Array = []; + + let count = this.decode_UInt32(model); + + for (let i = 0; i < count; i++) { + let value = this.decode_variant(model); + output.push(value); + } + + return output; + } + + private decode_Basis(model: BufferModel) { + let x = this.decode_Vector3(model); + let y = this.decode_Vector3(model); + let z = this.decode_Vector3(model); + + return this.make_Basis( + [x.x, x.y, z.z as number], + [y.x, y.y, y.z as number], + [z.x, z.y, z.z as number] + ); + } + + private decode_Color(model: BufferModel) { + let r = this.decode_Float(model); + let g = this.decode_Float(model); + let b = this.decode_Float(model); + let a = this.decode_Float(model); + + return { + __type__: "Color", + r: r, + g: g, + b: b, + a: a, + __render__: () => + `Color (${this.clean(r)}, ${this.clean(g)}, ${this.clean( + b + )}, ${this.clean(a)})` + }; + } + + private decode_Dictionary(model: BufferModel) { + let output = new Map(); + + let count = this.decode_UInt32(model); + for (let i = 0; i < count; i++) { + let key = this.decode_variant(model); + let value = this.decode_variant(model); + output.set(key, value); + } + + return output; + } + + private decode_Double(model: BufferModel) { + let view = new DataView(model.buffer.buffer, model.offset, 8); + let d = view.getFloat64(0, true); + + model.offset += 8; + model.len -= 8; + + return d + 0.00000000001; + } + + private decode_Float(model: BufferModel) { + let view = new DataView(model.buffer.buffer, model.offset, 4); + let f = view.getFloat32(0, true); + + model.offset += 4; + model.len -= 4; + + return f + 0.00000000001; + } + + private decode_Int32(model: BufferModel) { + let u = model.buffer.readInt32LE(model.offset); + model.len -= 4; + model.offset += 4; + + return u; + } + + private decode_Int64(model: BufferModel) { + let view = new DataView(model.buffer.buffer, model.offset, 8); + let u = view.getBigInt64(0, true); + model.len -= 8; + model.offset += 8; + + return Number(u); + } + + private decode_NodePath(model: BufferModel) { + let name_count = this.decode_UInt32(model) & 0x7fffffff; + let subname_count = this.decode_UInt32(model); + let flags = this.decode_UInt32(model); + let is_absolute = (flags & 1) === 1; + if (flags & 2) { + //Obsolete format with property separate from subPath + subname_count++; + } + + let total = name_count + subname_count; + let names: string[] = []; + let sub_names: string[] = []; + for (let i = 0; i < total; i++) { + let str = this.decode_String(model); + if (i < name_count) { + names.push(str); + } else { + sub_names.push(str); + } + } + + return { + __type__: "NodePath", + path: names, + subpath: sub_names, + absolute: is_absolute, + __render__: () => `NodePath (${names.join(".")}:${sub_names.join(":")})` + }; + } + + private decode_Object(model: BufferModel) { + let class_name = this.decode_String(model); + let prop_count = this.decode_UInt32(model); + let props: { name: string; value: any }[] = []; + for (let i = 0; i < prop_count; i++) { + let name = this.decode_String(model); + let value = this.decode_variant(model); + props.push({ name: name, value: value }); + } + + return { __type__: class_name, properties: props }; + } + + private decode_Object_id(model: BufferModel) { + let id = this.decode_UInt64(model); + return { + __type__: "Object", + id: id, + __render__: () => `Object<${id}>` + }; + } + + private decode_Plane(model: BufferModel) { + let x = this.decode_Float(model); + let y = this.decode_Float(model); + let z = this.decode_Float(model); + let d = this.decode_Float(model); + + return { + __type__: "Plane", + x: x, + y: y, + z: z, + d: d, + __render__: () => + `Plane (${this.clean(x)}, ${this.clean(y)}, ${this.clean( + z + )}, ${this.clean(d)})` + }; + } + + private decode_PoolByteArray(model: BufferModel) { + let count = this.decode_UInt32(model); + let output: number[] = []; + for (let i = 0; i < count; i++) { + output.push(model.buffer.readUInt8(model.offset)); + model.offset++; + model.len--; + } + + return output; + } + + private decode_PoolColorArray(model: BufferModel) { + let count = this.decode_UInt32(model); + let output: { r: number; g: number; b: number; a: number }[] = []; + for (let i = 0; i < count; i++) { + output.push(this.decode_Color(model)); + } + + return output; + } + + private decode_PoolFloatArray(model: BufferModel) { + let count = this.decode_UInt32(model); + let output: number[] = []; + for (let i = 0; i < count; i++) { + output.push(this.decode_Float(model)); + } + + return output; + } + + private decode_PoolIntArray(model: BufferModel) { + let count = this.decode_UInt32(model); + let output: number[] = []; + for (let i = 0; i < count; i++) { + output.push(this.decode_Int32(model)); + } + + return output; + } + + private decode_PoolStringArray(model: BufferModel) { + let count = this.decode_UInt32(model); + let output: string[] = []; + for (let i = 0; i < count; i++) { + output.push(this.decode_String(model)); + } + + return output; + } + + private decode_PoolVector2Array(model: BufferModel) { + let count = this.decode_UInt32(model); + let output: { x: number; y: number }[] = []; + for (let i = 0; i < count; i++) { + output.push(this.decode_Vector2(model)); + } + + return output; + } + + private decode_PoolVector3Array(model: BufferModel) { + let count = this.decode_UInt32(model); + let output: { x: number; y: number; z: number | undefined }[] = []; + for (let i = 0; i < count; i++) { + output.push(this.decode_Vector3(model)); + } + + return output; + } + + private decode_Quat(model: BufferModel) { + let x = this.decode_Float(model); + let y = this.decode_Float(model); + let z = this.decode_Float(model); + let w = this.decode_Float(model); + + return { + __type__: "Quat", + x: x, + y: y, + z: z, + w: w, + __render__: () => + `Quat (${this.clean(x)}, ${this.clean(y)}, ${this.clean( + z + )}, ${this.clean(w)})` + }; + } + + private decode_Rect2(model: BufferModel) { + let x = this.decode_Float(model); + let y = this.decode_Float(model); + let sizeX = this.decode_Float(model); + let sizeY = this.decode_Float(model); + + return { + __type__: "Rect2", + position: this.make_Vector2(x, y), + size: this.make_Vector2(sizeX, sizeY), + __render__: () => + `Rect2 (${this.clean(x)}, ${this.clean(y)} - ${this.clean( + sizeX + )}, ${this.clean(sizeY)})` + }; + } + + private decode_String(model: BufferModel) { + let len = this.decode_UInt32(model); + let pad = 0; + if (len % 4 !== 0) { + pad = 4 - (len % 4); + } + + let str = model.buffer.toString("utf8", model.offset, model.offset + len); + len += pad; + + model.offset += len; + model.len -= len; + + return str; + } + + private decode_Transform(model: BufferModel) { + let b = this.decode_Basis(model); + let o = this.decode_Vector3(model); + + return { + __type__: "Transform", + basis: this.make_Basis( + [b.x.x, b.x.y, b.x.z as number], + [b.y.x, b.y.y, b.y.z as number], + [b.z.x, b.z.y, b.z.z as number] + ), + origin: this.make_Vector3(o.x, o.y, o.z), + __render__: () => + `Transform ((${this.clean(b.x.x)}, ${this.clean(b.x.y)}, ${this.clean( + b.x.z as number + )}), (${this.clean(b.y.x)}, ${this.clean(b.y.y)}, ${this.clean( + b.y.z as number + )}), (${this.clean(b.z.x)}, ${this.clean(b.z.y)}, ${this.clean( + b.z.z as number + )}) - (${this.clean(o.x)}, ${this.clean(o.y)}, ${this.clean( + o.z as number + )}))` + }; + } + + private decode_Transform2D(model: BufferModel) { + let origin = this.decode_Vector2(model); + let x = this.decode_Vector2(model); + let y = this.decode_Vector2(model); + + return { + __type__: "Transform2D", + origin: this.make_Vector2(origin.x, origin.y), + x: this.make_Vector2(x.x, x.y), + y: this.make_Vector2(y.x, y.y), + __render__: () => + `Transform2D ((${this.clean(origin.x)}, ${this.clean( + origin.y + )}) - (${this.clean(x.x)}, ${this.clean(x.y)}), (${this.clean( + y.x + )}, ${this.clean(y.x)}))` + }; + } + + private decode_UInt32(model: BufferModel) { + let u = model.buffer.readUInt32LE(model.offset); + model.len -= 4; + model.offset += 4; + + return u; + } + + private decode_UInt64(model: BufferModel) { + let view = new DataView(model.buffer.buffer, model.offset, 8); + let u = view.getBigUint64(0, true); + model.len -= 8; + model.offset += 8; + + return Number(u); + } + + private decode_Vector2(model: BufferModel) { + let x = this.decode_Float(model); + let y = this.decode_Float(model); + + return this.make_Vector2(x, y); + } + + private decode_Vector3(model: BufferModel) { + let x = this.decode_Float(model); + let y = this.decode_Float(model); + let z = this.decode_Float(model); + + return this.make_Vector3(x, y, z); + } + + private encode_AABB(value: object, model: BufferModel) { + this.encode_Vector3(value["position"], model); + this.encode_Vector3(value["size"], model); + } + + private encode_Array(arr: any[], model: BufferModel) { + let size = arr.length; + this.encode_UInt32(size, model); + arr.forEach(e => { + this.encode_variant(e, model); + }); + } + + private encode_Basis(value: object, model: BufferModel) { + this.encode_Vector3(value["x"], model); + this.encode_Vector3(value["y"], model); + this.encode_Vector3(value["z"], model); + } + + private encode_Bool(bool: boolean, model: BufferModel) { + this.encode_UInt32(bool ? 1 : 0, model); + } + + private encode_Color(value: object, model: BufferModel) { + this.encode_Float(value["r"], model); + this.encode_Float(value["g"], model); + this.encode_Float(value["b"], model); + this.encode_Float(value["a"], model); + } + + private encode_Dictionary(dict: Map, model: BufferModel) { + let size = dict.size; + this.encode_UInt32(size, model); + let keys = Array.from(dict.keys()); + keys.forEach(key => { + let value = dict.get(key); + this.encode_variant(key, model); + this.encode_variant(value, model); + }); + } + + private encode_Float(value: number, model: BufferModel) { + let view = new DataView(model.buffer.buffer, model.offset); + view.setFloat32(0, value, true); + model.offset += 4; + } + + private encode_Double(value: number, model: BufferModel) { + let view = new DataView(model.buffer.buffer, model.offset); + view.setFloat64(0, value, true); + model.offset += 8; + } + + private encode_Plane(value: object, model: BufferModel) { + this.encode_Vector3(value["normal"], model); + this.encode_Float(value["d"], model); + } + + private encode_Quat(value: object, model: BufferModel) { + this.encode_Float(value["x"], model); + this.encode_Float(value["y"], model); + this.encode_Float(value["z"], model); + this.encode_Float(value["w"], model); + } + + private encode_Rect2(value: object, model: BufferModel) { + this.encode_Vector2(value["position"], model); + this.encode_Vector2(value["size"], model); + } + + private encode_String(str: string, model: BufferModel) { + let str_len = str.length; + this.encode_UInt32(str_len, model); + model.buffer.write(str, model.offset, str_len, "utf8"); + model.offset += str_len; + str_len += 4; + while (str_len % 4) { + str_len++; + model.buffer.writeUInt8(0, model.offset); + model.offset++; + } + } + + private encode_Transform(value: object, model: BufferModel) { + this.encode_Basis(value["basis"], model); + this.encode_Vector3(value["origin"], model); + } + + private encode_Transform2D(value: object, model: BufferModel) { + this.encode_Vector2(value["origin"], model); + this.encode_Vector2(value["x"], model); + this.encode_Vector2(value["y"], model); + } + + private encode_UInt32(int: number, model: BufferModel) { + model.buffer.writeUInt32LE(int, model.offset); + model.offset += 4; + } + + private encode_UInt64(value: bigint, model: BufferModel) { + let view = new DataView(model.buffer.buffer, model.offset, 8); + view.setBigUint64(0, value, true); + model.offset += 8; + } + + private encode_Vector2(value: any, model: BufferModel) { + this.encode_Float(value.x, model); + this.encode_Float(value.y, model); + } + + private encode_Vector3(value: any, model: BufferModel) { + this.encode_Float(value.x, model); + this.encode_Float(value.y, model); + this.encode_Float(value.z, model); + } + + private make_Basis(x: number[], y: number[], z: number[]) { + return { + __type__: "Basis", + x: this.make_Vector3(x[0], x[1], x[2]), + y: this.make_Vector3(y[0], y[1], y[2]), + z: this.make_Vector3(z[0], z[1], z[2]), + __render__: () => + `Basis ((${this.clean(x[0])}, ${this.clean(x[1])}, ${this.clean( + x[2] + )}), (${this.clean(y[0])}, ${this.clean(y[1])}, ${this.clean( + y[2] + )}), (${this.clean(z[0])}, ${this.clean(z[1])}, ${this.clean(z[2])}))` + }; + } + + private make_Vector2(x: number, y: number) { + return { + __type__: `Vector2`, + x: x, + y: y, + __render__: () => `Vector2 (${this.clean(x)}, ${this.clean(y)})` + }; + } + + private make_Vector3(x: number, y: number, z: number) { + return { + __type__: `Vector3`, + x: x, + y: y, + z: z, + __render__: () => + `Vector3 (${this.clean(x)}, ${this.clean(y)}, ${this.clean(z)})` + }; + } + + private size_Bool(): number { + return this.size_UInt32(); + } + + private size_Dictionary(dict: Map): number { + let size = this.size_UInt32(); + let keys = Array.from(dict.keys()); + keys.forEach(key => { + let value = dict.get(key); + size += this.size_variant(key); + size += this.size_variant(value); + }); + + return size; + } + + private size_String(str: string): number { + let size = this.size_UInt32() + str.length; + while (size % 4) { + size++; + } + return size; + } + + private size_UInt32(): number { + return 4; + } + + private size_UInt64(): number { + return 8; + } + + private size_array(arr: any[]): number { + let size = this.size_UInt32(); + arr.forEach(e => { + size += this.size_variant(e); + }); + + return size; + } + + private size_variant( + value: + | number + | bigint + | boolean + | string + | Map + | any[] + | object + | undefined + ): number { + let size = 4; + + if(typeof value === "number" && (value > 2147483647 || value < -2147483648)) { + value = BigInt(value); + } + + switch (typeof value) { + case "number": + size += this.size_UInt32(); + break; + case "bigint": + size += this.size_UInt64(); + break; + case "boolean": + size += this.size_Bool(); + break; + case "string": + size += this.size_String(value); + break; + case "undefined": + break; + default: + if (Array.isArray(value)) { + size += this.size_array(value); + break; + } else if (value instanceof Map) { + size += this.size_Dictionary(value); + break; + } else { + switch (value["__type__"]) { + case "Vector2": + size += this.size_UInt32() * 2; + break; + case "Rect2": + size += this.size_UInt32() * 4; + break; + case "Vector3": + size += this.size_UInt32() * 3; + break; + case "Transform2D": + size += this.size_UInt32() * 6; + break; + case "Plane": + size += this.size_UInt32() * 4; + break; + case "Quat": + size += this.size_UInt32() * 4; + break; + case "AABB": + size += this.size_UInt32() * 6; + break; + case "Basis": + size += this.size_UInt32() * 9; + break; + case "Transform": + size += this.size_UInt32() * 12; + break; + case "Color": + size += this.size_UInt32() * 4; + break; + } + } + } + + return size; + } +} diff --git a/src/extension.ts b/src/extension.ts index 21f9ae0..f535488 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,12 +1,13 @@ import { ExtensionContext } from "vscode"; import { GodotTools } from "./godot-tools"; - +import debuggerContext = require("./debugger/debugger_context"); let tools: GodotTools = null; export function activate(context: ExtensionContext) { tools = new GodotTools(context); tools.activate(); + debuggerContext.register_debugger(context); } export function deactivate(): Thenable {