From 98a37cdc508b77f7be6d53b7a6c4d2f04f9b1ae4 Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 29 May 2025 14:18:23 +0200 Subject: [PATCH] Added cyclops --- Scenes/Hacking/HackingBackground.tscn | 280 ++++ addons/cyclops_level_builder/LICENSE.md | 7 + .../actions/action_convert_to_mesh.gd | 138 ++ .../actions/action_convert_to_mesh.gd.uid | 1 + .../actions/action_delete_selected_blocks.gd | 46 + .../action_delete_selected_blocks.gd.uid | 1 + .../action_duplicate_selected_blocks.gd | 45 + .../action_duplicate_selected_blocks.gd.uid | 1 + .../actions/action_intersect_block.gd | 57 + .../actions/action_intersect_block.gd.uid | 1 + .../actions/action_merge_selected_blocks.gd | 45 + .../action_merge_selected_blocks.gd.uid | 1 + .../actions/action_merge_vertices_center.gd | 56 + .../action_merge_vertices_center.gd.uid | 1 + .../actions/action_mirror_selection_x.gd | 30 + .../actions/action_mirror_selection_x.gd.uid | 1 + .../actions/action_mirror_selection_y.gd | 30 + .../actions/action_mirror_selection_y.gd.uid | 1 + .../actions/action_mirror_selection_z.gd | 30 + .../actions/action_mirror_selection_z.gd.uid | 1 + .../actions/action_rotate_selection.gd | 55 + .../actions/action_rotate_selection.gd.uid | 1 + .../actions/action_rotate_x_180.gd | 31 + .../actions/action_rotate_x_180.gd.uid | 1 + .../actions/action_rotate_x_90_ccw.gd | 31 + .../actions/action_rotate_x_90_ccw.gd.uid | 1 + .../actions/action_rotate_x_90_cw.gd | 31 + .../actions/action_rotate_x_90_cw.gd.uid | 1 + .../actions/action_rotate_y_180.gd | 31 + .../actions/action_rotate_y_180.gd.uid | 1 + .../actions/action_rotate_y_90_ccw.gd | 31 + .../actions/action_rotate_y_90_ccw.gd.uid | 1 + .../actions/action_rotate_y_90_cw.gd | 31 + .../actions/action_rotate_y_90_cw.gd.uid | 1 + .../actions/action_rotate_z_180.gd | 31 + .../actions/action_rotate_z_180.gd.uid | 1 + .../actions/action_rotate_z_90_ccw.gd | 31 + .../actions/action_rotate_z_90_ccw.gd.uid | 1 + .../actions/action_rotate_z_90_cw.gd | 31 + .../actions/action_rotate_z_90_cw.gd.uid | 1 + .../actions/action_scale_selection.gd | 54 + .../actions/action_scale_selection.gd.uid | 1 + .../actions/action_snap_to_grid.gd | 57 + .../actions/action_snap_to_grid.gd.uid | 1 + .../actions/action_subtract_block.gd | 57 + .../actions/action_subtract_block.gd.uid | 1 + .../actions/action_tool_duplicate.gd | 33 + .../actions/action_tool_duplicate.gd.uid | 1 + .../actions/cyclops_action.gd | 53 + .../actions/cyclops_action.gd.uid | 1 + .../actions/io/action_export_as_cyclops.gd | 44 + .../io/action_export_as_cyclops.gd.uid | 1 + .../actions/io/action_export_as_gltf.gd | 49 + .../actions/io/action_export_as_gltf.gd.uid | 1 + .../io/action_export_as_godot_scene.gd | 42 + .../io/action_export_as_godot_scene.gd.uid | 1 + .../actions/io/action_import_cyclops_file.gd | 39 + .../io/action_import_cyclops_file.gd.uid | 1 + .../actions/io/action_import_mesh_instance.gd | 66 + .../io/action_import_mesh_instance.gd.uid | 1 + addons/cyclops_level_builder/art/cyclops.svg | 142 ++ .../art/cyclops.svg.import | 37 + addons/cyclops_level_builder/art/cyclops1.png | 3 + .../art/cyclops1.png.import | 34 + addons/cyclops_level_builder/art/cyclops2.png | 3 + .../art/cyclops2.png.import | 34 + .../cyclops_level_builder/art/cyclops_16.png | 3 + .../art/cyclops_16.png.import | 34 + .../cyclops_level_builder/art/cyclops_17.png | 3 + .../art/cyclops_17.png.import | 34 + .../cyclops_level_builder/art/cyclops_3.png | 3 + .../art/cyclops_3.png.import | 34 + .../cyclops_level_builder/art/cyclops_4.png | 3 + .../art/cyclops_4.png.import | 34 + .../art/cyclops_closed.png | 3 + .../art/cyclops_closed.png.import | 34 + .../art/cyclops_open.png | 3 + .../art/cyclops_open.png.import | 34 + .../art/fonts/Roboto/LICENSE.txt | 202 +++ .../art/fonts/Roboto/Roboto-Black.ttf | Bin 0 -> 168060 bytes .../art/fonts/Roboto/Roboto-Black.ttf.import | 35 + .../art/fonts/Roboto/Roboto-BlackItalic.ttf | Bin 0 -> 174108 bytes .../Roboto/Roboto-BlackItalic.ttf.import | 35 + .../art/fonts/Roboto/Roboto-Bold.ttf | Bin 0 -> 167336 bytes .../art/fonts/Roboto/Roboto-Bold.ttf.import | 35 + .../art/fonts/Roboto/Roboto-BoldItalic.ttf | Bin 0 -> 171508 bytes .../fonts/Roboto/Roboto-BoldItalic.ttf.import | 35 + .../art/fonts/Roboto/Roboto-Italic.ttf | Bin 0 -> 170504 bytes .../art/fonts/Roboto/Roboto-Italic.ttf.import | 35 + .../art/fonts/Roboto/Roboto-Light.ttf | Bin 0 -> 167000 bytes .../art/fonts/Roboto/Roboto-Light.ttf.import | 35 + .../art/fonts/Roboto/Roboto-LightItalic.ttf | Bin 0 -> 173172 bytes .../Roboto/Roboto-LightItalic.ttf.import | 35 + .../art/fonts/Roboto/Roboto-Medium.ttf | Bin 0 -> 168644 bytes .../art/fonts/Roboto/Roboto-Medium.ttf.import | 35 + .../art/fonts/Roboto/Roboto-MediumItalic.ttf | Bin 0 -> 173416 bytes .../Roboto/Roboto-MediumItalic.ttf.import | 35 + .../art/fonts/Roboto/Roboto-Regular.ttf | Bin 0 -> 168260 bytes .../fonts/Roboto/Roboto-Regular.ttf.import | 35 + .../art/fonts/Roboto/Roboto-Thin.ttf | Bin 0 -> 168488 bytes .../art/fonts/Roboto/Roboto-Thin.ttf.import | 35 + .../art/fonts/Roboto/Roboto-ThinItalic.ttf | Bin 0 -> 172860 bytes .../fonts/Roboto/Roboto-ThinItalic.ttf.import | 35 + .../art/gizmos/gizmo_rotate.glb | Bin 0 -> 152608 bytes .../art/gizmos/gizmo_rotate.glb.import | 37 + .../art/gizmos/gizmo_rotate.obj.import | 22 + .../art/gizmos/gizmo_scale.glb | Bin 0 -> 11160 bytes .../art/gizmos/gizmo_scale.glb.import | 37 + .../art/gizmos/gizmo_scale.obj.import | 22 + .../art/gizmos/gizmo_translate.glb | Bin 0 -> 10528 bytes .../art/gizmos/gizmo_translate.glb.import | 37 + .../art/gizmos/gizmo_translate.obj.import | 22 + .../art/icons/arrow_down.svg | 67 + .../art/icons/arrow_down.svg.import | 37 + .../art/icons/arrow_left.svg | 67 + .../art/icons/arrow_left.svg.import | 37 + .../art/icons/arrow_right.svg | 67 + .../art/icons/arrow_right.svg.import | 37 + .../art/icons/arrow_up.svg | 67 + .../art/icons/arrow_up.svg.import | 37 + .../cyclops_level_builder/art/icons/block.svg | 48 + .../art/icons/block.svg.import | 37 + .../art/icons/create_cylinder.svg | 50 + .../art/icons/create_cylinder.svg.import | 37 + .../art/icons/create_prism.svg | 50 + .../art/icons/create_prism.svg.import | 37 + .../art/icons/create_stairs.svg | 59 + .../art/icons/create_stairs.svg.import | 37 + .../art/icons/edit_clip.svg | 59 + .../art/icons/edit_clip.svg.import | 37 + .../art/icons/eye_closed.svg | 79 + .../art/icons/eye_closed.svg.import | 37 + .../art/icons/eye_open.svg | 94 ++ .../art/icons/eye_open.svg.import | 37 + .../art/icons/material_brush.svg | 53 + .../art/icons/material_brush.svg.import | 37 + .../cyclops_level_builder/art/icons/move.svg | 16 + .../art/icons/move.svg.import | 38 + .../art/icons/rotate.svg | 47 + .../art/icons/rotate.svg.import | 37 + .../art/icons/select_edge.svg | 53 + .../art/icons/select_edge.svg.import | 37 + .../art/icons/select_face.svg | 55 + .../art/icons/select_face.svg.import | 37 + .../art/icons/select_vertex.svg | 54 + .../art/icons/select_vertex.svg.import | 37 + .../cyclops_level_builder/art/icons/snap.svg | 54 + .../art/icons/snap.svg.import | 37 + .../art/icons/snap_grid.svg | 54 + .../art/icons/snap_grid.svg.import | 38 + .../art/icons/snap_vertex.svg | 52 + .../art/icons/snap_vertex.svg.import | 38 + .../art/icons/uv_lock.svg | 62 + .../art/icons/uv_lock.svg.import | 37 + .../art/icons/vertex_color_brush.svg | 67 + .../art/icons/vertex_color_brush.svg.import | 37 + .../art/icons/xray_normal.svg | 108 ++ .../art/icons/xray_normal.svg.import | 37 + .../art/materialTest.glb | Bin 0 -> 3668 bytes .../art/materialTest.glb.import | 37 + .../art/textures/checkerboard.png | 3 + .../art/textures/checkerboard.png.import | 35 + .../art/textures/checkerboard_colored.png | 3 + .../textures/checkerboard_colored.png.import | 34 + .../art/textures/grid_cell.png | 3 + .../art/textures/grid_cell.png.import | 35 + .../art/textures/grid_cell2.png | 3 + .../art/textures/grid_cell2.png.import | 34 + .../art/textures/vertex.png | 3 + .../art/textures/vertex.png.import | 35 + .../commands/cmd_add_block.gd | 86 + .../commands/cmd_add_block.gd.uid | 1 + .../commands/cmd_add_cylinder.gd | 115 ++ .../commands/cmd_add_cylinder.gd.uid | 1 + .../commands/cmd_add_prism.gd | 80 + .../commands/cmd_add_prism.gd.uid | 1 + .../commands/cmd_add_stairs.gd | 139 ++ .../commands/cmd_add_stairs.gd.uid | 1 + .../commands/cmd_add_vertices.gd | 74 + .../commands/cmd_add_vertices.gd.uid | 1 + .../commands/cmd_clip_block.gd | 106 ++ .../commands/cmd_clip_block.gd.uid | 1 + .../commands/cmd_delete_blocks.gd | 82 + .../commands/cmd_delete_blocks.gd.uid | 1 + .../commands/cmd_duplicate_blocks.gd | 90 + .../commands/cmd_duplicate_blocks.gd.uid | 1 + .../commands/cmd_intersect_block.gd | 152 ++ .../commands/cmd_intersect_block.gd.uid | 1 + .../commands/cmd_merge_blocks.gd | 148 ++ .../commands/cmd_merge_blocks.gd.uid | 1 + .../commands/cmd_merge_vertices.gd | 142 ++ .../commands/cmd_merge_vertices.gd.uid | 1 + .../commands/cmd_move_edges.gd | 150 ++ .../commands/cmd_move_edges.gd.uid | 1 + .../commands/cmd_move_face_planar.gd | 102 ++ .../commands/cmd_move_face_planar.gd.uid | 1 + .../commands/cmd_move_faces.gd | 144 ++ .../commands/cmd_move_faces.gd.uid | 1 + .../commands/cmd_move_vertices.gd | 117 ++ .../commands/cmd_move_vertices.gd.uid | 1 + .../commands/cmd_select_blocks.gd | 239 +++ .../commands/cmd_select_blocks.gd.uid | 1 + .../commands/cmd_select_edges.gd | 176 ++ .../commands/cmd_select_edges.gd.uid | 1 + .../commands/cmd_select_faces.gd | 168 ++ .../commands/cmd_select_faces.gd.uid | 1 + .../commands/cmd_select_vertices.gd | 174 ++ .../commands/cmd_select_vertices.gd.uid | 1 + .../commands/cmd_set_face_color.gd | 112 ++ .../commands/cmd_set_face_color.gd.uid | 1 + .../commands/cmd_set_face_uv_transform.gd | 114 ++ .../commands/cmd_set_face_uv_transform.gd.uid | 1 + .../commands/cmd_set_face_vertex_color.gd | 121 ++ .../commands/cmd_set_face_vertex_color.gd.uid | 1 + .../commands/cmd_set_face_visible.gd | 112 ++ .../commands/cmd_set_face_visible.gd.uid | 1 + .../commands/cmd_set_material.gd | 158 ++ .../commands/cmd_set_material.gd.uid | 1 + .../commands/cmd_snap_to_grid.gd | 84 + .../commands/cmd_snap_to_grid.gd.uid | 1 + .../commands/cmd_subtract_block.gd | 158 ++ .../commands/cmd_subtract_block.gd.uid | 1 + .../commands/cmd_transform_blocks.gd | 76 + .../commands/cmd_transform_blocks.gd.uid | 1 + .../commands/cmd_transform_vertices.gd | 73 + .../commands/cmd_transform_vertices.gd.uid | 1 + .../commands/cmd_vertex_paint_stroke.gd | 130 ++ .../commands/cmd_vertex_paint_stroke.gd.uid | 1 + .../commands/cyclops_command.gd | 77 + .../commands/cyclops_command.gd.uid | 1 + .../commands/io/cmd_import_cyclops_file.gd | 87 + .../io/cmd_import_cyclops_file.gd.uid | 1 + .../commands/io/cmd_import_godot_meshes.gd | 99 ++ .../io/cmd_import_godot_meshes.gd.uid | 1 + .../controls/enum_line_edit.gd | 59 + .../controls/enum_line_edit.gd.uid | 1 + .../controls/enum_line_edit.tscn | 8 + .../controls/fold_out_panel.gd | 51 + .../controls/fold_out_panel.gd.uid | 1 + .../controls/fold_out_panel.tscn | 37 + .../controls/numeric_line_edit.gd | 139 ++ .../controls/numeric_line_edit.gd.uid | 1 + .../controls/numeric_line_edit.tscn | 44 + .../resource_inspector/line_editor_bool.gd | 66 + .../line_editor_bool.gd.uid | 1 + .../resource_inspector/line_editor_bool.tscn | 10 + .../resource_inspector/line_editor_float.gd | 65 + .../line_editor_float.gd.uid | 1 + .../resource_inspector/line_editor_float.tscn | 11 + .../resource_inspector/line_editor_int.gd | 71 + .../resource_inspector/line_editor_int.gd.uid | 1 + .../resource_inspector/line_editor_int.tscn | 10 + .../resource_inspector/resource_inspector.gd | 86 + .../resource_inspector.gd.uid | 1 + .../resource_inspector.tscn | 18 + .../controls/test_line_edit.gd | 16 + .../controls/test_line_edit.gd.uid | 1 + .../controls/test_line_edit.tscn | 18 + .../controls/tree/TreeTextComponent.gd | 18 + .../controls/tree/TreeTextComponent.gd.uid | 1 + .../controls/tree/TreeTextComponent.tscn | 18 + .../tree/abstract_cyclops_tree_model.gd | 32 + .../tree/abstract_cyclops_tree_model.gd.uid | 1 + .../controls/tree/cyclops_tree.gd | 65 + .../controls/tree/cyclops_tree.gd.uid | 1 + .../controls/tree/cyclops_tree.tscn | 8 + .../controls/tree/tree_tier_component.tscn | 37 + .../controls/vector3_edit.gd | 44 + .../controls/vector3_edit.gd.uid | 1 + .../controls/vector3_edit.tscn | 40 + .../controls/vertex_billboard.gd | 56 + .../controls/vertex_billboard.gd.uid | 1 + .../controls/vertex_billboard.tscn | 14 + .../cyclops_global_scene.gd | 365 +++++ .../cyclops_global_scene.gd.uid | 1 + .../cyclops_global_scene.tscn | 34 + .../cyclops_level_builder.gd | 462 ++++++ .../cyclops_level_builder.gd.uid | 1 + .../cyclops_level_builder/cyclops_overlay.gd | 69 + .../cyclops_overlay.gd.uid | 1 + .../data/configuration.tres | 22 + .../data/snapping_tags/snap_tag_grid.tres | 12 + .../data/snapping_tags/snap_tag_vertex.tres | 12 + .../data/tool_tags/tool_tag_clip.tres | 31 + .../data/tool_tags/tool_tag_create_block.tres | 33 + .../tool_tags/tool_tag_create_cylinder.tres | 27 + .../data/tool_tags/tool_tag_create_prism.tres | 29 + .../tool_tags/tool_tag_create_stairs.tres | 26 + .../data/tool_tags/tool_tag_duplicate.tres | 11 + .../data/tool_tags/tool_tag_edit_edge.tres | 27 + .../data/tool_tags/tool_tag_edit_face.tres | 31 + .../data/tool_tags/tool_tag_edit_vertex.tres | 27 + .../tool_tags/tool_tag_material_brush.tres | 24 + .../data/tool_tags/tool_tag_move.tres | 37 + .../data/tool_tags/tool_tag_rotate.tres | 23 + .../tool_tag_vertex_color_brush.tres | 24 + .../convex_face_editor_preview.gd | 77 + .../convex_face_editor_preview.gd.uid | 1 + .../convex_face_editor_preview.tscn | 16 + .../convex_face_editor_preview_studio.gd | 77 + .../convex_face_editor_preview_studio.gd.uid | 1 + .../convex_face_editor_preview_studio.tscn | 19 + .../convex_face_editor_viewport.gd | 241 +++ .../convex_face_editor_viewport.gd.uid | 1 + .../convex_face_editor_viewport.tscn | 163 ++ .../docks/cyclops_console/cyclops_console.gd | 67 + .../cyclops_console/cyclops_console.gd.uid | 1 + .../cyclops_console/cyclops_console.tscn | 58 + .../commands/cmd_mat_dock_add_materials.gd | 56 + .../cmd_mat_dock_add_materials.gd.uid | 1 + .../commands/cmd_mat_dock_remove_materials.gd | 52 + .../cmd_mat_dock_remove_materials.gd.uid | 1 + .../material_palette_viewport.gd | 242 +++ .../material_palette_viewport.gd.uid | 1 + .../material_palette_viewport.tscn | 27 + .../material_viewer/create_material_dialog.gd | 124 ++ .../create_material_dialog.gd.uid | 1 + .../create_material_dialog.tscn | 182 +++ .../material_viewer/line_input.gd | 69 + .../material_viewer/line_input.gd.uid | 1 + .../material_viewer/line_input.tscn | 40 + .../material_viewer/mat_bn_active_theme.tres | 16 + .../material_viewer/mat_bn_normal_theme.tres | 17 + .../mat_bn_selected_theme.tres | 16 + .../material_viewer/material_button.gd | 154 ++ .../material_viewer/material_button.gd.uid | 1 + .../material_viewer/material_button.tscn | 38 + .../material_viewer/material_group.gd | 58 + .../material_viewer/material_group.gd.uid | 1 + .../material_viewer/material_groups_tree.gd | 321 ++++ .../material_groups_tree.gd.uid | 1 + .../material_viewer/material_groups_tree.tscn | 29 + .../material_viewer/material_viewer.gd | 240 +++ .../material_viewer/material_viewer.gd.uid | 1 + .../material_viewer/material_viewer.tscn | 66 + .../material_viewer/material_viewer_state.gd | 32 + .../material_viewer_state.gd.uid | 1 + .../material_viewer_state_res.tres | 7 + .../material_viewer/radio_button_group.gd | 40 + .../material_viewer/radio_button_group.gd.uid | 1 + .../snapping_properties_dock.gd | 93 ++ .../snapping_properties_dock.gd.uid | 1 + .../snapping_properties_dock.tscn | 21 + .../tool_properties/tool_properties_dock.gd | 56 + .../tool_properties_dock.gd.uid | 1 + .../tool_properties/tool_properties_dock.tscn | 20 + .../handles/handle_edge.gd | 40 + .../handles/handle_edge.gd.uid | 1 + .../handles/handle_face.gd | 38 + .../handles/handle_face.gd.uid | 1 + .../handles/handle_vertex.gd | 36 + .../handles/handle_vertex.gd.uid | 1 + .../io/cyclops_io/buffer_archive.gd | 82 + .../io/cyclops_io/buffer_archive.gd.uid | 1 + .../io/cyclops_io/cyclops_file_builder.gd | 199 +++ .../io/cyclops_io/cyclops_file_builder.gd.uid | 1 + .../io/cyclops_io/cyclops_file_loader.gd | 209 +++ .../io/cyclops_io/cyclops_file_loader.gd.uid | 1 + .../io/cyclops_io/item_indexer.gd | 36 + .../io/cyclops_io/item_indexer.gd.uid | 1 + .../io/exporter/exporter_cyclops_wizard.gd | 85 + .../exporter/exporter_cyclops_wizard.gd.uid | 1 + .../io/exporter/exporter_cyclops_wizard.tscn | 60 + .../io/exporter/exporter_gltf_wizard.gd | 167 ++ .../io/exporter/exporter_gltf_wizard.gd.uid | 1 + .../io/exporter/exporter_gltf_wizard.tscn | 75 + .../exporter/exporter_godot_scene_wizard.gd | 155 ++ .../exporter_godot_scene_wizard.gd.uid | 1 + .../exporter/exporter_godot_scene_wizard.tscn | 61 + .../importer/importer_cyclops_file_wizard.gd | 82 + .../importer_cyclops_file_wizard.gd.uid | 1 + .../importer_cyclops_file_wizard.tscn | 59 + .../gizmo_axis_selected_material.tres | 6 + .../gizmo_axis_special_material.tres | 7 + .../materials/gizmo_axis_x_material.tres | 8 + .../materials/gizmo_axis_y_material.tres | 8 + .../materials/gizmo_axis_z_material.tres | 8 + .../cyclops_level_builder/materials/grid.tres | 10 + .../materials/outline_material.tres | 8 + .../materials/selection_rect_material.tres | 9 + .../materials/test_materials.tscn | 19 + .../tool_edit_active_fill_material.tres | 9 + .../materials/tool_edit_active_material.tres | 8 + .../tool_edit_selected_fill_material.tres | 9 + .../tool_edit_selected_material.tres | 9 + .../tool_edit_unselected_material.tres | 8 + .../materials/tool_material.tres | 9 + .../tool_object_active_material.tres | 10 + .../tool_object_selected_material.tres | 10 + .../materials/vertex_active_material.tres | 12 + .../materials/vertex_selected_material.tres | 13 + .../materials/vertex_tool_material.tres | 13 + .../materials/vertex_unselected_material.tres | 13 + .../math/clip_poly_result.gd | 33 + .../math/clip_poly_result.gd.uid | 1 + .../math/convex_volume.gd | 1447 +++++++++++++++++ .../math/convex_volume.gd.uid | 1 + .../cyclops_level_builder/math/face_packer.gd | 253 +++ .../math/face_packer.gd.uid | 1 + .../math/general_mesh.gd | 446 +++++ .../math/general_mesh.gd.uid | 1 + .../math/geometry_mesh.gd | 63 + .../math/geometry_mesh.gd.uid | 1 + addons/cyclops_level_builder/math/loop_2d.gd | 36 + .../cyclops_level_builder/math/loop_2d.gd.uid | 1 + .../math/math_geometry.gd | 182 +++ .../math/math_geometry.gd.uid | 1 + .../cyclops_level_builder/math/math_util.gd | 934 +++++++++++ .../math/math_util.gd.uid | 1 + .../cyclops_level_builder/math/pen_stroke.gd | 94 ++ .../math/pen_stroke.gd.uid | 1 + .../cyclops_level_builder/math/quick_hull.gd | 360 ++++ .../math/quick_hull.gd.uid | 1 + addons/cyclops_level_builder/math/segent_3.gd | 43 + .../math/segent_3.gd.uid | 1 + .../menu/action_popup_menu.gd | 46 + .../menu/action_popup_menu.gd.uid | 1 + .../menu/editor_toolbar.gd | 231 +++ .../menu/editor_toolbar.gd.uid | 1 + .../menu/editor_toolbar.tscn | 129 ++ .../menu/main_toolbar.gd | 39 + .../menu/main_toolbar.gd.uid | 1 + .../menu/main_toolbar.tscn | 19 + .../menu/upgrade_cyclops_blocks_toolbar.gd | 84 + .../upgrade_cyclops_blocks_toolbar.gd.uid | 1 + .../menu/upgrade_cyclops_blocks_toolbar.tscn | 14 + .../nodes/cyclops_block.gd | 293 ++++ .../nodes/cyclops_block.gd.uid | 1 + .../nodes/cyclops_blocks.gd | 155 ++ .../nodes/cyclops_blocks.gd.uid | 1 + .../nodes/cyclops_blocks_icon.png | 3 + .../nodes/cyclops_blocks_icon.png.import | 34 + .../nodes/cyclops_blocks_icon.svg | 66 + .../nodes/cyclops_blocks_icon.svg.import | 37 + .../nodes/cyclops_convex_block.gd | 124 ++ .../nodes/cyclops_convex_block.gd.uid | 1 + .../nodes/cyclops_convex_block_body.gd | 142 ++ .../nodes/cyclops_convex_block_body.gd.uid | 1 + .../nodes/cyclops_scene.gd | 35 + .../nodes/cyclops_scene.gd.uid | 1 + .../nodes/intersect_results.gd | 44 + .../nodes/intersect_results.gd.uid | 1 + addons/cyclops_level_builder/plugin.cfg | 7 + .../resources/block_data.gd | 32 + .../resources/block_data.gd.uid | 1 + .../resources/convex_block_data.gd | 137 ++ .../resources/convex_block_data.gd.uid | 1 + .../resources/cyclops_config.gd | 30 + .../resources/cyclops_config.gd.uid | 1 + .../resources/data_vector.gd | 84 + .../resources/data_vector.gd.uid | 1 + .../resources/data_vector_byte.gd | 62 + .../resources/data_vector_byte.gd.uid | 1 + .../resources/data_vector_float.gd | 140 ++ .../resources/data_vector_float.gd.uid | 1 + .../resources/data_vector_int.gd | 85 + .../resources/data_vector_int.gd.uid | 1 + .../resources/data_vector_string.gd | 61 + .../resources/data_vector_string.gd.uid | 1 + .../resources/mesh_vector_data.gd | 369 +++++ .../resources/mesh_vector_data.gd.uid | 1 + .../resources/tool_tag.gd | 50 + .../resources/tool_tag.gd.uid | 1 + .../shaders/outline_shader.tres | 67 + .../shaders/tool_outline_shader.tres | 38 + .../shaders/vertex_shader.tres | 60 + .../snapping/cyclops_snapping_system.gd | 67 + .../snapping/cyclops_snapping_system.gd.uid | 1 + .../snapping/move_constraint.gd | 28 + .../snapping/move_constraint.gd.uid | 1 + .../snapping/snap_to_grid_util.gd | 92 ++ .../snapping/snap_to_grid_util.gd.uid | 1 + .../snapping/snapping_manager.gd | 45 + .../snapping/snapping_manager.gd.uid | 1 + .../snapping/snapping_query.gd | 35 + .../snapping/snapping_query.gd.uid | 1 + .../snapping/snapping_system_grid.gd | 68 + .../snapping/snapping_system_grid.gd.uid | 1 + .../snapping_system_grid_properties_editor.gd | 204 +++ ...pping_system_grid_properties_editor.gd.uid | 1 + ...napping_system_grid_properties_editor.tscn | 153 ++ .../snapping/snapping_system_vertex.gd | 117 ++ .../snapping/snapping_system_vertex.gd.uid | 1 + ...napping_system_vertex_properties_editor.gd | 62 + ...ing_system_vertex_properties_editor.gd.uid | 1 + ...pping_system_vertex_properties_editor.tscn | 25 + .../snapping_system_vertex_settings.gd | 37 + .../snapping_system_vertex_settings.gd.uid | 1 + .../snapping/snapping_tag.gd | 45 + .../snapping/snapping_tag.gd.uid | 1 + .../tools/block_alignment.gd | 39 + .../tools/block_alignment.gd.uid | 1 + .../tools/cyclops_tool.gd | 189 +++ .../tools/cyclops_tool.gd.uid | 1 + .../tools/gizmos/gizmo_base.gd | 92 ++ .../tools/gizmos/gizmo_base.gd.uid | 1 + .../tools/gizmos/gizmo_rotate.gd | 72 + .../tools/gizmos/gizmo_rotate.gd.uid | 1 + .../tools/gizmos/gizmo_rotate.tscn | 37 + .../tools/gizmos/gizmo_test.gd | 23 + .../tools/gizmos/gizmo_test.gd.uid | 1 + .../tools/gizmos/gizmo_test.tscn | 37 + .../tools/gizmos/gizmo_translate.gd | 73 + .../tools/gizmos/gizmo_translate.gd.uid | 1 + .../tools/gizmos/gizmo_translate.tscn | 45 + .../cyclops_level_builder/tools/tool_block.gd | 360 ++++ .../tools/tool_block.gd.uid | 1 + .../tools/tool_block_settings.gd | 54 + .../tools/tool_block_settings.gd.uid | 1 + .../tools/tool_block_settings_editor.gd | 92 ++ .../tools/tool_block_settings_editor.gd.uid | 1 + .../tools/tool_block_settings_editor.tscn | 132 ++ .../cyclops_level_builder/tools/tool_clip.gd | 170 ++ .../tools/tool_clip.gd.uid | 1 + .../tools/tool_cylinder.gd | 297 ++++ .../tools/tool_cylinder.gd.uid | 1 + .../tools/tool_cylinder_settings.gd | 62 + .../tools/tool_cylinder_settings.gd.uid | 1 + .../tools/tool_cylinder_settings_editor.gd | 104 ++ .../tool_cylinder_settings_editor.gd.uid | 1 + .../tools/tool_cylinder_settings_editor.tscn | 157 ++ .../tools/tool_duplicate.gd | 124 ++ .../tools/tool_duplicate.gd.uid | 1 + .../tools/tool_edit_base.gd | 100 ++ .../tools/tool_edit_base.gd.uid | 1 + .../tools/tool_edit_edge.gd | 646 ++++++++ .../tools/tool_edit_edge.gd.uid | 1 + .../tools/tool_edit_edge_settings.gd | 39 + .../tools/tool_edit_edge_settings.gd.uid | 1 + .../tools/tool_edit_edge_settings_editor.gd | 60 + .../tool_edit_edge_settings_editor.gd.uid | 1 + .../tools/tool_edit_edge_settings_editor.tscn | 49 + .../tools/tool_edit_face.gd | 642 ++++++++ .../tools/tool_edit_face.gd.uid | 1 + .../tools/tool_edit_face_settings.gd | 39 + .../tools/tool_edit_face_settings.gd.uid | 1 + .../tools/tool_edit_face_settings_editor.gd | 60 + .../tool_edit_face_settings_editor.gd.uid | 1 + .../tools/tool_edit_face_settings_editor.tscn | 49 + .../tools/tool_edit_vertex.gd | 632 +++++++ .../tools/tool_edit_vertex.gd.uid | 1 + .../tools/tool_edit_vertex_settings.gd | 39 + .../tools/tool_edit_vertex_settings.gd.uid | 1 + .../tools/tool_edit_vertex_settings_editor.gd | 60 + .../tool_edit_vertex_settings_editor.gd.uid | 1 + .../tool_edit_vertex_settings_editor.tscn | 49 + .../tools/tool_material_brush.gd | 209 +++ .../tools/tool_material_brush.gd.uid | 1 + .../tools/tool_material_brush_settings.gd | 91 ++ .../tools/tool_material_brush_settings.gd.uid | 1 + .../tool_material_brush_settings_editor.gd | 142 ++ ...tool_material_brush_settings_editor.gd.uid | 1 + .../tool_material_brush_settings_editor.tscn | 83 + .../cyclops_level_builder/tools/tool_move.gd | 451 +++++ .../tools/tool_move.gd.uid | 1 + .../tools/tool_move_settings.gd | 39 + .../tools/tool_move_settings.gd.uid | 1 + .../tools/tool_move_settings_editor.gd | 60 + .../tools/tool_move_settings_editor.gd.uid | 1 + .../tools/tool_move_settings_editor.tscn | 49 + .../cyclops_level_builder/tools/tool_prism.gd | 265 +++ .../tools/tool_prism.gd.uid | 1 + .../tools/tool_prism_settings.gd | 56 + .../tools/tool_prism_settings.gd.uid | 1 + .../tools/tool_prism_settings_editor.gd | 90 + .../tools/tool_prism_settings_editor.gd.uid | 1 + .../tools/tool_prism_settings_editor.tscn | 132 ++ .../tools/tool_rotate.gd | 336 ++++ .../tools/tool_rotate.gd.uid | 1 + .../tools/tool_stairs.gd | 319 ++++ .../tools/tool_stairs.gd.uid | 1 + .../tools/tool_stairs_settings.gd | 66 + .../tools/tool_stairs_settings.gd.uid | 1 + .../tools/tool_stairs_settings_editor.gd | 116 ++ .../tools/tool_stairs_settings_editor.gd.uid | 1 + .../tools/tool_stairs_settings_editor.tscn | 163 ++ .../tools/tool_vertex_color_brush.gd | 198 +++ .../tools/tool_vertex_color_brush.gd.uid | 1 + .../tools/tool_vertex_color_brush_settings.gd | 94 ++ .../tool_vertex_color_brush_settings.gd.uid | 1 + ...tool_vertex_color_brush_settings_editor.gd | 104 ++ ..._vertex_color_brush_settings_editor.gd.uid | 1 + ...ol_vertex_color_brush_settings_editor.tscn | 80 + .../cyclops_level_builder/util/collision.gd | 27 + .../util/collision.gd.uid | 1 + .../util/cyclops_logger.gd | 31 + .../util/cyclops_logger.gd.uid | 1 + .../util/cyclops_settings.gd | 228 +++ .../util/cyclops_settings.gd.uid | 1 + .../util/display_mode.gd | 28 + .../util/display_mode.gd.uid | 1 + .../util/general_util.gd | 71 + .../util/general_util.gd.uid | 1 + .../util/geometry_component_type.gd | 28 + .../util/geometry_component_type.gd.uid | 1 + .../cyclops_level_builder/util/selection.gd | 37 + .../util/selection.gd.uid | 1 + .../util/selection_list.gd | 37 + .../util/selection_list.gd.uid | 1 + .../cyclops_level_builder/util/serial_util.gd | 72 + .../util/serial_util.gd.uid | 1 + .../util/transform_space.gd | 29 + .../util/transform_space.gd.uid | 1 + .../cyclops_level_builder/util/tree_vistor.gd | 35 + .../util/tree_vistor.gd.uid | 1 + .../cyclops_level_builder/util/unit_system.gd | 28 + .../util/unit_system.gd.uid | 1 + .../util/xml/XML_attribute.gd | 33 + .../util/xml/XML_attribute.gd.uid | 1 + .../util/xml/XML_document.gd | 35 + .../util/xml/XML_document.gd.uid | 1 + .../util/xml/XML_element.gd | 82 + .../util/xml/XML_element.gd.uid | 1 + .../util/xml/XML_node.gd | 29 + .../util/xml/XML_node.gd.uid | 1 + .../util/xml/XML_text.gd | 31 + .../util/xml/XML_text.gd.uid | 1 + project.godot | 3 +- 618 files changed, 32322 insertions(+), 1 deletion(-) create mode 100644 Scenes/Hacking/HackingBackground.tscn create mode 100644 addons/cyclops_level_builder/LICENSE.md create mode 100644 addons/cyclops_level_builder/actions/action_convert_to_mesh.gd create mode 100644 addons/cyclops_level_builder/actions/action_convert_to_mesh.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_delete_selected_blocks.gd create mode 100644 addons/cyclops_level_builder/actions/action_delete_selected_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_duplicate_selected_blocks.gd create mode 100644 addons/cyclops_level_builder/actions/action_duplicate_selected_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_intersect_block.gd create mode 100644 addons/cyclops_level_builder/actions/action_intersect_block.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_merge_selected_blocks.gd create mode 100644 addons/cyclops_level_builder/actions/action_merge_selected_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_merge_vertices_center.gd create mode 100644 addons/cyclops_level_builder/actions/action_merge_vertices_center.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_mirror_selection_x.gd create mode 100644 addons/cyclops_level_builder/actions/action_mirror_selection_x.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_mirror_selection_y.gd create mode 100644 addons/cyclops_level_builder/actions/action_mirror_selection_y.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_mirror_selection_z.gd create mode 100644 addons/cyclops_level_builder/actions/action_mirror_selection_z.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_selection.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_selection.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_x_180.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_x_180.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_x_90_ccw.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_x_90_ccw.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_x_90_cw.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_x_90_cw.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_y_180.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_y_180.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_y_90_ccw.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_y_90_ccw.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_y_90_cw.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_y_90_cw.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_z_180.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_z_180.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_z_90_ccw.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_z_90_ccw.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_rotate_z_90_cw.gd create mode 100644 addons/cyclops_level_builder/actions/action_rotate_z_90_cw.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_scale_selection.gd create mode 100644 addons/cyclops_level_builder/actions/action_scale_selection.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_snap_to_grid.gd create mode 100644 addons/cyclops_level_builder/actions/action_snap_to_grid.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_subtract_block.gd create mode 100644 addons/cyclops_level_builder/actions/action_subtract_block.gd.uid create mode 100644 addons/cyclops_level_builder/actions/action_tool_duplicate.gd create mode 100644 addons/cyclops_level_builder/actions/action_tool_duplicate.gd.uid create mode 100644 addons/cyclops_level_builder/actions/cyclops_action.gd create mode 100644 addons/cyclops_level_builder/actions/cyclops_action.gd.uid create mode 100644 addons/cyclops_level_builder/actions/io/action_export_as_cyclops.gd create mode 100644 addons/cyclops_level_builder/actions/io/action_export_as_cyclops.gd.uid create mode 100644 addons/cyclops_level_builder/actions/io/action_export_as_gltf.gd create mode 100644 addons/cyclops_level_builder/actions/io/action_export_as_gltf.gd.uid create mode 100644 addons/cyclops_level_builder/actions/io/action_export_as_godot_scene.gd create mode 100644 addons/cyclops_level_builder/actions/io/action_export_as_godot_scene.gd.uid create mode 100644 addons/cyclops_level_builder/actions/io/action_import_cyclops_file.gd create mode 100644 addons/cyclops_level_builder/actions/io/action_import_cyclops_file.gd.uid create mode 100644 addons/cyclops_level_builder/actions/io/action_import_mesh_instance.gd create mode 100644 addons/cyclops_level_builder/actions/io/action_import_mesh_instance.gd.uid create mode 100644 addons/cyclops_level_builder/art/cyclops.svg create mode 100644 addons/cyclops_level_builder/art/cyclops.svg.import create mode 100644 addons/cyclops_level_builder/art/cyclops1.png create mode 100644 addons/cyclops_level_builder/art/cyclops1.png.import create mode 100644 addons/cyclops_level_builder/art/cyclops2.png create mode 100644 addons/cyclops_level_builder/art/cyclops2.png.import create mode 100644 addons/cyclops_level_builder/art/cyclops_16.png create mode 100644 addons/cyclops_level_builder/art/cyclops_16.png.import create mode 100644 addons/cyclops_level_builder/art/cyclops_17.png create mode 100644 addons/cyclops_level_builder/art/cyclops_17.png.import create mode 100644 addons/cyclops_level_builder/art/cyclops_3.png create mode 100644 addons/cyclops_level_builder/art/cyclops_3.png.import create mode 100644 addons/cyclops_level_builder/art/cyclops_4.png create mode 100644 addons/cyclops_level_builder/art/cyclops_4.png.import create mode 100644 addons/cyclops_level_builder/art/cyclops_closed.png create mode 100644 addons/cyclops_level_builder/art/cyclops_closed.png.import create mode 100644 addons/cyclops_level_builder/art/cyclops_open.png create mode 100644 addons/cyclops_level_builder/art/cyclops_open.png.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/LICENSE.txt create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Black.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Black.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BlackItalic.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BlackItalic.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Bold.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Bold.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BoldItalic.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BoldItalic.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Italic.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Italic.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Light.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Light.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-LightItalic.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-LightItalic.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Medium.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Medium.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-MediumItalic.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-MediumItalic.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Regular.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Regular.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Thin.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Thin.ttf.import create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-ThinItalic.ttf create mode 100644 addons/cyclops_level_builder/art/fonts/Roboto/Roboto-ThinItalic.ttf.import create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb.import create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_rotate.obj.import create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_scale.glb create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_scale.glb.import create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_scale.obj.import create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_translate.glb create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_translate.glb.import create mode 100644 addons/cyclops_level_builder/art/gizmos/gizmo_translate.obj.import create mode 100644 addons/cyclops_level_builder/art/icons/arrow_down.svg create mode 100644 addons/cyclops_level_builder/art/icons/arrow_down.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/arrow_left.svg create mode 100644 addons/cyclops_level_builder/art/icons/arrow_left.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/arrow_right.svg create mode 100644 addons/cyclops_level_builder/art/icons/arrow_right.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/arrow_up.svg create mode 100644 addons/cyclops_level_builder/art/icons/arrow_up.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/block.svg create mode 100644 addons/cyclops_level_builder/art/icons/block.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/create_cylinder.svg create mode 100644 addons/cyclops_level_builder/art/icons/create_cylinder.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/create_prism.svg create mode 100644 addons/cyclops_level_builder/art/icons/create_prism.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/create_stairs.svg create mode 100644 addons/cyclops_level_builder/art/icons/create_stairs.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/edit_clip.svg create mode 100644 addons/cyclops_level_builder/art/icons/edit_clip.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/eye_closed.svg create mode 100644 addons/cyclops_level_builder/art/icons/eye_closed.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/eye_open.svg create mode 100644 addons/cyclops_level_builder/art/icons/eye_open.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/material_brush.svg create mode 100644 addons/cyclops_level_builder/art/icons/material_brush.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/move.svg create mode 100644 addons/cyclops_level_builder/art/icons/move.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/rotate.svg create mode 100644 addons/cyclops_level_builder/art/icons/rotate.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/select_edge.svg create mode 100644 addons/cyclops_level_builder/art/icons/select_edge.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/select_face.svg create mode 100644 addons/cyclops_level_builder/art/icons/select_face.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/select_vertex.svg create mode 100644 addons/cyclops_level_builder/art/icons/select_vertex.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/snap.svg create mode 100644 addons/cyclops_level_builder/art/icons/snap.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/snap_grid.svg create mode 100644 addons/cyclops_level_builder/art/icons/snap_grid.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/snap_vertex.svg create mode 100644 addons/cyclops_level_builder/art/icons/snap_vertex.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/uv_lock.svg create mode 100644 addons/cyclops_level_builder/art/icons/uv_lock.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/vertex_color_brush.svg create mode 100644 addons/cyclops_level_builder/art/icons/vertex_color_brush.svg.import create mode 100644 addons/cyclops_level_builder/art/icons/xray_normal.svg create mode 100644 addons/cyclops_level_builder/art/icons/xray_normal.svg.import create mode 100644 addons/cyclops_level_builder/art/materialTest.glb create mode 100644 addons/cyclops_level_builder/art/materialTest.glb.import create mode 100644 addons/cyclops_level_builder/art/textures/checkerboard.png create mode 100644 addons/cyclops_level_builder/art/textures/checkerboard.png.import create mode 100644 addons/cyclops_level_builder/art/textures/checkerboard_colored.png create mode 100644 addons/cyclops_level_builder/art/textures/checkerboard_colored.png.import create mode 100644 addons/cyclops_level_builder/art/textures/grid_cell.png create mode 100644 addons/cyclops_level_builder/art/textures/grid_cell.png.import create mode 100644 addons/cyclops_level_builder/art/textures/grid_cell2.png create mode 100644 addons/cyclops_level_builder/art/textures/grid_cell2.png.import create mode 100644 addons/cyclops_level_builder/art/textures/vertex.png create mode 100644 addons/cyclops_level_builder/art/textures/vertex.png.import create mode 100644 addons/cyclops_level_builder/commands/cmd_add_block.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_add_block.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_add_cylinder.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_add_cylinder.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_add_prism.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_add_prism.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_add_stairs.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_add_stairs.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_add_vertices.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_add_vertices.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_clip_block.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_clip_block.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_delete_blocks.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_delete_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_duplicate_blocks.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_duplicate_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_intersect_block.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_intersect_block.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_merge_blocks.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_merge_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_merge_vertices.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_merge_vertices.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_move_edges.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_move_edges.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_move_face_planar.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_move_face_planar.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_move_faces.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_move_faces.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_move_vertices.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_move_vertices.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_select_blocks.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_select_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_select_edges.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_select_edges.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_select_faces.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_select_faces.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_select_vertices.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_select_vertices.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_set_face_color.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_set_face_color.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_set_face_uv_transform.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_set_face_uv_transform.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_set_face_vertex_color.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_set_face_vertex_color.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_set_face_visible.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_set_face_visible.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_set_material.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_set_material.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_subtract_block.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_subtract_block.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_transform_blocks.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_transform_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_transform_vertices.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_transform_vertices.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cmd_vertex_paint_stroke.gd create mode 100644 addons/cyclops_level_builder/commands/cmd_vertex_paint_stroke.gd.uid create mode 100644 addons/cyclops_level_builder/commands/cyclops_command.gd create mode 100644 addons/cyclops_level_builder/commands/cyclops_command.gd.uid create mode 100644 addons/cyclops_level_builder/commands/io/cmd_import_cyclops_file.gd create mode 100644 addons/cyclops_level_builder/commands/io/cmd_import_cyclops_file.gd.uid create mode 100644 addons/cyclops_level_builder/commands/io/cmd_import_godot_meshes.gd create mode 100644 addons/cyclops_level_builder/commands/io/cmd_import_godot_meshes.gd.uid create mode 100644 addons/cyclops_level_builder/controls/enum_line_edit.gd create mode 100644 addons/cyclops_level_builder/controls/enum_line_edit.gd.uid create mode 100644 addons/cyclops_level_builder/controls/enum_line_edit.tscn create mode 100644 addons/cyclops_level_builder/controls/fold_out_panel.gd create mode 100644 addons/cyclops_level_builder/controls/fold_out_panel.gd.uid create mode 100644 addons/cyclops_level_builder/controls/fold_out_panel.tscn create mode 100644 addons/cyclops_level_builder/controls/numeric_line_edit.gd create mode 100644 addons/cyclops_level_builder/controls/numeric_line_edit.gd.uid create mode 100644 addons/cyclops_level_builder/controls/numeric_line_edit.tscn create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd.uid create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.tscn create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd.uid create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.tscn create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd.uid create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.tscn create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd.uid create mode 100644 addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.tscn create mode 100644 addons/cyclops_level_builder/controls/test_line_edit.gd create mode 100644 addons/cyclops_level_builder/controls/test_line_edit.gd.uid create mode 100644 addons/cyclops_level_builder/controls/test_line_edit.tscn create mode 100644 addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd create mode 100644 addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd.uid create mode 100644 addons/cyclops_level_builder/controls/tree/TreeTextComponent.tscn create mode 100644 addons/cyclops_level_builder/controls/tree/abstract_cyclops_tree_model.gd create mode 100644 addons/cyclops_level_builder/controls/tree/abstract_cyclops_tree_model.gd.uid create mode 100644 addons/cyclops_level_builder/controls/tree/cyclops_tree.gd create mode 100644 addons/cyclops_level_builder/controls/tree/cyclops_tree.gd.uid create mode 100644 addons/cyclops_level_builder/controls/tree/cyclops_tree.tscn create mode 100644 addons/cyclops_level_builder/controls/tree/tree_tier_component.tscn create mode 100644 addons/cyclops_level_builder/controls/vector3_edit.gd create mode 100644 addons/cyclops_level_builder/controls/vector3_edit.gd.uid create mode 100644 addons/cyclops_level_builder/controls/vector3_edit.tscn create mode 100644 addons/cyclops_level_builder/controls/vertex_billboard.gd create mode 100644 addons/cyclops_level_builder/controls/vertex_billboard.gd.uid create mode 100644 addons/cyclops_level_builder/controls/vertex_billboard.tscn create mode 100644 addons/cyclops_level_builder/cyclops_global_scene.gd create mode 100644 addons/cyclops_level_builder/cyclops_global_scene.gd.uid create mode 100644 addons/cyclops_level_builder/cyclops_global_scene.tscn create mode 100644 addons/cyclops_level_builder/cyclops_level_builder.gd create mode 100644 addons/cyclops_level_builder/cyclops_level_builder.gd.uid create mode 100644 addons/cyclops_level_builder/cyclops_overlay.gd create mode 100644 addons/cyclops_level_builder/cyclops_overlay.gd.uid create mode 100644 addons/cyclops_level_builder/data/configuration.tres create mode 100644 addons/cyclops_level_builder/data/snapping_tags/snap_tag_grid.tres create mode 100644 addons/cyclops_level_builder/data/snapping_tags/snap_tag_vertex.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_clip.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_create_block.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_create_cylinder.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_create_prism.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_create_stairs.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_duplicate.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_edge.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_face.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_vertex.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_material_brush.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_move.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_rotate.tres create mode 100644 addons/cyclops_level_builder/data/tool_tags/tool_tag_vertex_color_brush.tres create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd.uid create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.tscn create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd.uid create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.tscn create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd.uid create mode 100644 addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.tscn create mode 100644 addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd create mode 100644 addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd.uid create mode 100644 addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.tscn create mode 100644 addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_add_materials.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_add_materials.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_remove_materials.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_remove_materials.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.tscn create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.tscn create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.tscn create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_active_theme.tres create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_normal_theme.tres create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_selected_theme.tres create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.tscn create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_group.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_group.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.tscn create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.tscn create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd.uid create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state_res.tres create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/radio_button_group.gd create mode 100644 addons/cyclops_level_builder/docks/material_palette/material_viewer/radio_button_group.gd.uid create mode 100644 addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd create mode 100644 addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd.uid create mode 100644 addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.tscn create mode 100644 addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd create mode 100644 addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd.uid create mode 100644 addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.tscn create mode 100644 addons/cyclops_level_builder/handles/handle_edge.gd create mode 100644 addons/cyclops_level_builder/handles/handle_edge.gd.uid create mode 100644 addons/cyclops_level_builder/handles/handle_face.gd create mode 100644 addons/cyclops_level_builder/handles/handle_face.gd.uid create mode 100644 addons/cyclops_level_builder/handles/handle_vertex.gd create mode 100644 addons/cyclops_level_builder/handles/handle_vertex.gd.uid create mode 100644 addons/cyclops_level_builder/io/cyclops_io/buffer_archive.gd create mode 100644 addons/cyclops_level_builder/io/cyclops_io/buffer_archive.gd.uid create mode 100644 addons/cyclops_level_builder/io/cyclops_io/cyclops_file_builder.gd create mode 100644 addons/cyclops_level_builder/io/cyclops_io/cyclops_file_builder.gd.uid create mode 100644 addons/cyclops_level_builder/io/cyclops_io/cyclops_file_loader.gd create mode 100644 addons/cyclops_level_builder/io/cyclops_io/cyclops_file_loader.gd.uid create mode 100644 addons/cyclops_level_builder/io/cyclops_io/item_indexer.gd create mode 100644 addons/cyclops_level_builder/io/cyclops_io/item_indexer.gd.uid create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd.uid create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.tscn create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd.uid create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.tscn create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd.uid create mode 100644 addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.tscn create mode 100644 addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd create mode 100644 addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd.uid create mode 100644 addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.tscn create mode 100644 addons/cyclops_level_builder/materials/gizmo_axis_selected_material.tres create mode 100644 addons/cyclops_level_builder/materials/gizmo_axis_special_material.tres create mode 100644 addons/cyclops_level_builder/materials/gizmo_axis_x_material.tres create mode 100644 addons/cyclops_level_builder/materials/gizmo_axis_y_material.tres create mode 100644 addons/cyclops_level_builder/materials/gizmo_axis_z_material.tres create mode 100644 addons/cyclops_level_builder/materials/grid.tres create mode 100644 addons/cyclops_level_builder/materials/outline_material.tres create mode 100644 addons/cyclops_level_builder/materials/selection_rect_material.tres create mode 100644 addons/cyclops_level_builder/materials/test_materials.tscn create mode 100644 addons/cyclops_level_builder/materials/tool_edit_active_fill_material.tres create mode 100644 addons/cyclops_level_builder/materials/tool_edit_active_material.tres create mode 100644 addons/cyclops_level_builder/materials/tool_edit_selected_fill_material.tres create mode 100644 addons/cyclops_level_builder/materials/tool_edit_selected_material.tres create mode 100644 addons/cyclops_level_builder/materials/tool_edit_unselected_material.tres create mode 100644 addons/cyclops_level_builder/materials/tool_material.tres create mode 100644 addons/cyclops_level_builder/materials/tool_object_active_material.tres create mode 100644 addons/cyclops_level_builder/materials/tool_object_selected_material.tres create mode 100644 addons/cyclops_level_builder/materials/vertex_active_material.tres create mode 100644 addons/cyclops_level_builder/materials/vertex_selected_material.tres create mode 100644 addons/cyclops_level_builder/materials/vertex_tool_material.tres create mode 100644 addons/cyclops_level_builder/materials/vertex_unselected_material.tres create mode 100644 addons/cyclops_level_builder/math/clip_poly_result.gd create mode 100644 addons/cyclops_level_builder/math/clip_poly_result.gd.uid create mode 100644 addons/cyclops_level_builder/math/convex_volume.gd create mode 100644 addons/cyclops_level_builder/math/convex_volume.gd.uid create mode 100644 addons/cyclops_level_builder/math/face_packer.gd create mode 100644 addons/cyclops_level_builder/math/face_packer.gd.uid create mode 100644 addons/cyclops_level_builder/math/general_mesh.gd create mode 100644 addons/cyclops_level_builder/math/general_mesh.gd.uid create mode 100644 addons/cyclops_level_builder/math/geometry_mesh.gd create mode 100644 addons/cyclops_level_builder/math/geometry_mesh.gd.uid create mode 100644 addons/cyclops_level_builder/math/loop_2d.gd create mode 100644 addons/cyclops_level_builder/math/loop_2d.gd.uid create mode 100644 addons/cyclops_level_builder/math/math_geometry.gd create mode 100644 addons/cyclops_level_builder/math/math_geometry.gd.uid create mode 100644 addons/cyclops_level_builder/math/math_util.gd create mode 100644 addons/cyclops_level_builder/math/math_util.gd.uid create mode 100644 addons/cyclops_level_builder/math/pen_stroke.gd create mode 100644 addons/cyclops_level_builder/math/pen_stroke.gd.uid create mode 100644 addons/cyclops_level_builder/math/quick_hull.gd create mode 100644 addons/cyclops_level_builder/math/quick_hull.gd.uid create mode 100644 addons/cyclops_level_builder/math/segent_3.gd create mode 100644 addons/cyclops_level_builder/math/segent_3.gd.uid create mode 100644 addons/cyclops_level_builder/menu/action_popup_menu.gd create mode 100644 addons/cyclops_level_builder/menu/action_popup_menu.gd.uid create mode 100644 addons/cyclops_level_builder/menu/editor_toolbar.gd create mode 100644 addons/cyclops_level_builder/menu/editor_toolbar.gd.uid create mode 100644 addons/cyclops_level_builder/menu/editor_toolbar.tscn create mode 100644 addons/cyclops_level_builder/menu/main_toolbar.gd create mode 100644 addons/cyclops_level_builder/menu/main_toolbar.gd.uid create mode 100644 addons/cyclops_level_builder/menu/main_toolbar.tscn create mode 100644 addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd create mode 100644 addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd.uid create mode 100644 addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.tscn create mode 100644 addons/cyclops_level_builder/nodes/cyclops_block.gd create mode 100644 addons/cyclops_level_builder/nodes/cyclops_block.gd.uid create mode 100644 addons/cyclops_level_builder/nodes/cyclops_blocks.gd create mode 100644 addons/cyclops_level_builder/nodes/cyclops_blocks.gd.uid create mode 100644 addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png create mode 100644 addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png.import create mode 100644 addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg create mode 100644 addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg.import create mode 100644 addons/cyclops_level_builder/nodes/cyclops_convex_block.gd create mode 100644 addons/cyclops_level_builder/nodes/cyclops_convex_block.gd.uid create mode 100644 addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd create mode 100644 addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd.uid create mode 100644 addons/cyclops_level_builder/nodes/cyclops_scene.gd create mode 100644 addons/cyclops_level_builder/nodes/cyclops_scene.gd.uid create mode 100644 addons/cyclops_level_builder/nodes/intersect_results.gd create mode 100644 addons/cyclops_level_builder/nodes/intersect_results.gd.uid create mode 100644 addons/cyclops_level_builder/plugin.cfg create mode 100644 addons/cyclops_level_builder/resources/block_data.gd create mode 100644 addons/cyclops_level_builder/resources/block_data.gd.uid create mode 100644 addons/cyclops_level_builder/resources/convex_block_data.gd create mode 100644 addons/cyclops_level_builder/resources/convex_block_data.gd.uid create mode 100644 addons/cyclops_level_builder/resources/cyclops_config.gd create mode 100644 addons/cyclops_level_builder/resources/cyclops_config.gd.uid create mode 100644 addons/cyclops_level_builder/resources/data_vector.gd create mode 100644 addons/cyclops_level_builder/resources/data_vector.gd.uid create mode 100644 addons/cyclops_level_builder/resources/data_vector_byte.gd create mode 100644 addons/cyclops_level_builder/resources/data_vector_byte.gd.uid create mode 100644 addons/cyclops_level_builder/resources/data_vector_float.gd create mode 100644 addons/cyclops_level_builder/resources/data_vector_float.gd.uid create mode 100644 addons/cyclops_level_builder/resources/data_vector_int.gd create mode 100644 addons/cyclops_level_builder/resources/data_vector_int.gd.uid create mode 100644 addons/cyclops_level_builder/resources/data_vector_string.gd create mode 100644 addons/cyclops_level_builder/resources/data_vector_string.gd.uid create mode 100644 addons/cyclops_level_builder/resources/mesh_vector_data.gd create mode 100644 addons/cyclops_level_builder/resources/mesh_vector_data.gd.uid create mode 100644 addons/cyclops_level_builder/resources/tool_tag.gd create mode 100644 addons/cyclops_level_builder/resources/tool_tag.gd.uid create mode 100644 addons/cyclops_level_builder/shaders/outline_shader.tres create mode 100644 addons/cyclops_level_builder/shaders/tool_outline_shader.tres create mode 100644 addons/cyclops_level_builder/shaders/vertex_shader.tres create mode 100644 addons/cyclops_level_builder/snapping/cyclops_snapping_system.gd create mode 100644 addons/cyclops_level_builder/snapping/cyclops_snapping_system.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/move_constraint.gd create mode 100644 addons/cyclops_level_builder/snapping/move_constraint.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snap_to_grid_util.gd create mode 100644 addons/cyclops_level_builder/snapping/snap_to_grid_util.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snapping_manager.gd create mode 100644 addons/cyclops_level_builder/snapping/snapping_manager.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snapping_query.gd create mode 100644 addons/cyclops_level_builder/snapping/snapping_query.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_grid.gd create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_grid.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.tscn create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_vertex.gd create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_vertex.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.tscn create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_vertex_settings.gd create mode 100644 addons/cyclops_level_builder/snapping/snapping_system_vertex_settings.gd.uid create mode 100644 addons/cyclops_level_builder/snapping/snapping_tag.gd create mode 100644 addons/cyclops_level_builder/snapping/snapping_tag.gd.uid create mode 100644 addons/cyclops_level_builder/tools/block_alignment.gd create mode 100644 addons/cyclops_level_builder/tools/block_alignment.gd.uid create mode 100644 addons/cyclops_level_builder/tools/cyclops_tool.gd create mode 100644 addons/cyclops_level_builder/tools/cyclops_tool.gd.uid create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_base.gd create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_base.gd.uid create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd.uid create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.tscn create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd.uid create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_test.tscn create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd.uid create mode 100644 addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_block.gd create mode 100644 addons/cyclops_level_builder/tools/tool_block.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_block_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_block_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_block_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_block_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_block_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_clip.gd create mode 100644 addons/cyclops_level_builder/tools/tool_clip.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_cylinder.gd create mode 100644 addons/cyclops_level_builder/tools/tool_cylinder.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_cylinder_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_cylinder_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_duplicate.gd create mode 100644 addons/cyclops_level_builder/tools/tool_duplicate.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_base.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_base.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_edge.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_edge.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_edge_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_edge_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_edit_face.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_face.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_face_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_face_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_edit_vertex.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_vertex.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_vertex_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_vertex_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_material_brush.gd create mode 100644 addons/cyclops_level_builder/tools/tool_material_brush.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_material_brush_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_material_brush_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_move.gd create mode 100644 addons/cyclops_level_builder/tools/tool_move.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_move_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_move_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_move_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_move_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_move_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_prism.gd create mode 100644 addons/cyclops_level_builder/tools/tool_prism.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_prism_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_prism_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_prism_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_rotate.gd create mode 100644 addons/cyclops_level_builder/tools/tool_rotate.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_stairs.gd create mode 100644 addons/cyclops_level_builder/tools/tool_stairs.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_stairs_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_stairs_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_stairs_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd create mode 100644 addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings.gd create mode 100644 addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd create mode 100644 addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd.uid create mode 100644 addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.tscn create mode 100644 addons/cyclops_level_builder/util/collision.gd create mode 100644 addons/cyclops_level_builder/util/collision.gd.uid create mode 100644 addons/cyclops_level_builder/util/cyclops_logger.gd create mode 100644 addons/cyclops_level_builder/util/cyclops_logger.gd.uid create mode 100644 addons/cyclops_level_builder/util/cyclops_settings.gd create mode 100644 addons/cyclops_level_builder/util/cyclops_settings.gd.uid create mode 100644 addons/cyclops_level_builder/util/display_mode.gd create mode 100644 addons/cyclops_level_builder/util/display_mode.gd.uid create mode 100644 addons/cyclops_level_builder/util/general_util.gd create mode 100644 addons/cyclops_level_builder/util/general_util.gd.uid create mode 100644 addons/cyclops_level_builder/util/geometry_component_type.gd create mode 100644 addons/cyclops_level_builder/util/geometry_component_type.gd.uid create mode 100644 addons/cyclops_level_builder/util/selection.gd create mode 100644 addons/cyclops_level_builder/util/selection.gd.uid create mode 100644 addons/cyclops_level_builder/util/selection_list.gd create mode 100644 addons/cyclops_level_builder/util/selection_list.gd.uid create mode 100644 addons/cyclops_level_builder/util/serial_util.gd create mode 100644 addons/cyclops_level_builder/util/serial_util.gd.uid create mode 100644 addons/cyclops_level_builder/util/transform_space.gd create mode 100644 addons/cyclops_level_builder/util/transform_space.gd.uid create mode 100644 addons/cyclops_level_builder/util/tree_vistor.gd create mode 100644 addons/cyclops_level_builder/util/tree_vistor.gd.uid create mode 100644 addons/cyclops_level_builder/util/unit_system.gd create mode 100644 addons/cyclops_level_builder/util/unit_system.gd.uid create mode 100644 addons/cyclops_level_builder/util/xml/XML_attribute.gd create mode 100644 addons/cyclops_level_builder/util/xml/XML_attribute.gd.uid create mode 100644 addons/cyclops_level_builder/util/xml/XML_document.gd create mode 100644 addons/cyclops_level_builder/util/xml/XML_document.gd.uid create mode 100644 addons/cyclops_level_builder/util/xml/XML_element.gd create mode 100644 addons/cyclops_level_builder/util/xml/XML_element.gd.uid create mode 100644 addons/cyclops_level_builder/util/xml/XML_node.gd create mode 100644 addons/cyclops_level_builder/util/xml/XML_node.gd.uid create mode 100644 addons/cyclops_level_builder/util/xml/XML_text.gd create mode 100644 addons/cyclops_level_builder/util/xml/XML_text.gd.uid diff --git a/Scenes/Hacking/HackingBackground.tscn b/Scenes/Hacking/HackingBackground.tscn new file mode 100644 index 00000000..2210caf4 --- /dev/null +++ b/Scenes/Hacking/HackingBackground.tscn @@ -0,0 +1,280 @@ +[gd_scene load_steps=32 format=3 uid="uid://bsgh7lw6kjci3"] + +[ext_resource type="Script" uid="uid://cvisn0b641od4" path="res://addons/cyclops_level_builder/nodes/cyclops_block.gd" id="1_wrk2a"] +[ext_resource type="Script" uid="uid://djeq3sxhsep3c" path="res://addons/cyclops_level_builder/resources/data_vector_byte.gd" id="2_idys7"] +[ext_resource type="Script" uid="uid://civ3w78ahacnu" path="res://addons/cyclops_level_builder/resources/data_vector_int.gd" id="3_lad6o"] +[ext_resource type="Script" uid="uid://db41w3h28c2la" path="res://addons/cyclops_level_builder/resources/data_vector_float.gd" id="4_wgaie"] +[ext_resource type="Script" uid="uid://c43o57os2lmc3" path="res://addons/cyclops_level_builder/resources/mesh_vector_data.gd" id="5_msw1m"] + +[sub_resource type="Resource" id="Resource_rbva8"] +script = ExtResource("2_idys7") +data = PackedByteArray(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) +name = &"selected" +category = "" +data_type = 0 +stride = 1 + +[sub_resource type="Resource" id="Resource_bqhgn"] +script = ExtResource("3_lad6o") +data = PackedInt32Array(-1, -1, -1, -1, -1, -1) +name = &"material_index" +category = "" +data_type = 1 +stride = 1 + +[sub_resource type="Resource" id="Resource_f6dmw"] +script = ExtResource("2_idys7") +data = PackedByteArray(1, 1, 1, 1, 1, 1) +name = &"visible" +category = "" +data_type = 0 +stride = 1 + +[sub_resource type="Resource" id="Resource_5oni7"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) +name = &"color" +category = "" +data_type = 4 +stride = 4 + +[sub_resource type="Resource" id="Resource_0tm5b"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0) +name = &"uv_transform" +category = "" +data_type = 8 +stride = 6 + +[sub_resource type="Resource" id="Resource_gp8qv"] +script = ExtResource("2_idys7") +data = PackedByteArray(0, 0, 0, 0, 0, 0) +name = &"selected" +category = "" +data_type = 0 +stride = 1 + +[sub_resource type="Resource" id="Resource_awppo"] +script = ExtResource("3_lad6o") +data = PackedInt32Array(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5) +name = &"face_index" +category = "" +data_type = 1 +stride = 1 + +[sub_resource type="Resource" id="Resource_55odd"] +script = ExtResource("3_lad6o") +data = PackedInt32Array(0, 1, 2, 3, 7, 6, 5, 4, 1, 0, 4, 5, 2, 1, 5, 6, 3, 2, 6, 7, 0, 3, 7, 4) +name = &"vertex_index" +category = "" +data_type = 1 +stride = 1 + +[sub_resource type="Resource" id="Resource_ip31u"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) +name = &"color" +category = "" +data_type = 4 +stride = 4 + +[sub_resource type="Resource" id="Resource_ml8l3"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1) +name = &"normal" +category = "" +data_type = 6 +stride = 3 + +[sub_resource type="Resource" id="Resource_nvynb"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0) +name = &"position" +category = "" +data_type = 6 +stride = 3 + +[sub_resource type="Resource" id="Resource_lod1m"] +script = ExtResource("2_idys7") +data = PackedByteArray(0, 0, 0, 0, 0, 0, 0, 0) +name = &"selected" +category = "" +data_type = 0 +stride = 1 + +[sub_resource type="Resource" id="Resource_j714y"] +script = ExtResource("5_msw1m") +num_vertices = 8 +num_edges = 12 +num_faces = 6 +num_face_vertices = 24 +active_vertex = -1 +active_edge = -1 +active_face = -1 +active_face_vertex = -1 +edge_vertex_indices = PackedInt32Array(0, 1, 1, 2, 2, 3, 3, 0, 7, 6, 6, 5, 5, 4, 4, 7, 0, 4, 5, 1, 6, 2, 7, 3) +edge_face_indices = PackedInt32Array(0, 2, 0, 3, 0, 4, 0, 5, 1, 4, 1, 3, 1, 2, 1, 5, 2, 5, 2, 3, 3, 4, 4, 5) +face_vertex_count = PackedInt32Array(4, 4, 4, 4, 4, 4) +face_vertex_indices = PackedInt32Array(0, 1, 2, 3, 7, 6, 5, 4, 1, 0, 4, 5, 2, 1, 5, 6, 3, 2, 6, 7, 0, 3, 7, 4) +vertex_data = { +&"position": SubResource("Resource_nvynb"), +&"selected": SubResource("Resource_lod1m") +} +edge_data = { +&"selected": SubResource("Resource_rbva8") +} +face_data = { +&"color": SubResource("Resource_5oni7"), +&"material_index": SubResource("Resource_bqhgn"), +&"selected": SubResource("Resource_gp8qv"), +&"uv_transform": SubResource("Resource_0tm5b"), +&"visible": SubResource("Resource_f6dmw") +} +face_vertex_data = { +&"color": SubResource("Resource_ip31u"), +&"face_index": SubResource("Resource_awppo"), +&"normal": SubResource("Resource_ml8l3"), +&"vertex_index": SubResource("Resource_55odd") +} + +[sub_resource type="Resource" id="Resource_wrk2a"] +script = ExtResource("2_idys7") +data = PackedByteArray(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) +name = &"selected" +category = "" +data_type = 0 +stride = 1 + +[sub_resource type="Resource" id="Resource_idys7"] +script = ExtResource("3_lad6o") +data = PackedInt32Array(-1, -1, -1, -1, -1, -1) +name = &"material_index" +category = "" +data_type = 1 +stride = 1 + +[sub_resource type="Resource" id="Resource_lad6o"] +script = ExtResource("2_idys7") +data = PackedByteArray(1, 1, 1, 1, 1, 1) +name = &"visible" +category = "" +data_type = 0 +stride = 1 + +[sub_resource type="Resource" id="Resource_wgaie"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) +name = &"color" +category = "" +data_type = 4 +stride = 4 + +[sub_resource type="Resource" id="Resource_msw1m"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0) +name = &"uv_transform" +category = "" +data_type = 8 +stride = 6 + +[sub_resource type="Resource" id="Resource_1nv3l"] +script = ExtResource("2_idys7") +data = PackedByteArray(0, 0, 0, 0, 0, 0) +name = &"selected" +category = "" +data_type = 0 +stride = 1 + +[sub_resource type="Resource" id="Resource_wja3m"] +script = ExtResource("3_lad6o") +data = PackedInt32Array(0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5) +name = &"face_index" +category = "" +data_type = 1 +stride = 1 + +[sub_resource type="Resource" id="Resource_gcw4q"] +script = ExtResource("3_lad6o") +data = PackedInt32Array(0, 1, 2, 3, 7, 6, 5, 4, 1, 0, 4, 5, 2, 1, 5, 6, 3, 2, 6, 7, 0, 3, 7, 4) +name = &"vertex_index" +category = "" +data_type = 1 +stride = 1 + +[sub_resource type="Resource" id="Resource_32acy"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1) +name = &"color" +category = "" +data_type = 4 +stride = 4 + +[sub_resource type="Resource" id="Resource_2m5ey"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(-1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1) +name = &"normal" +category = "" +data_type = 6 +stride = 3 + +[sub_resource type="Resource" id="Resource_4opuo"] +script = ExtResource("4_wgaie") +data = PackedFloat32Array(0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0) +name = &"position" +category = "" +data_type = 6 +stride = 3 + +[sub_resource type="Resource" id="Resource_rnchs"] +script = ExtResource("2_idys7") +data = PackedByteArray(0, 0, 0, 0, 0, 0, 0, 0) +name = &"selected" +category = "" +data_type = 0 +stride = 1 + +[sub_resource type="Resource" id="Resource_083x5"] +script = ExtResource("5_msw1m") +num_vertices = 8 +num_edges = 12 +num_faces = 6 +num_face_vertices = 24 +active_vertex = -1 +active_edge = -1 +active_face = -1 +active_face_vertex = -1 +edge_vertex_indices = PackedInt32Array(0, 1, 1, 2, 2, 3, 3, 0, 7, 6, 6, 5, 5, 4, 4, 7, 0, 4, 5, 1, 6, 2, 7, 3) +edge_face_indices = PackedInt32Array(0, 2, 0, 3, 0, 4, 0, 5, 1, 4, 1, 3, 1, 2, 1, 5, 2, 5, 2, 3, 3, 4, 4, 5) +face_vertex_count = PackedInt32Array(4, 4, 4, 4, 4, 4) +face_vertex_indices = PackedInt32Array(0, 1, 2, 3, 7, 6, 5, 4, 1, 0, 4, 5, 2, 1, 5, 6, 3, 2, 6, 7, 0, 3, 7, 4) +vertex_data = { +&"position": SubResource("Resource_4opuo"), +&"selected": SubResource("Resource_rnchs") +} +edge_data = { +&"selected": SubResource("Resource_wrk2a") +} +face_data = { +&"color": SubResource("Resource_wgaie"), +&"material_index": SubResource("Resource_idys7"), +&"selected": SubResource("Resource_1nv3l"), +&"uv_transform": SubResource("Resource_msw1m"), +&"visible": SubResource("Resource_lad6o") +} +face_vertex_data = { +&"color": SubResource("Resource_32acy"), +&"face_index": SubResource("Resource_wja3m"), +&"normal": SubResource("Resource_2m5ey"), +&"vertex_index": SubResource("Resource_gcw4q") +} + +[node name="HackingBackground" type="Node3D"] + +[node name="block0" type="Node3D" parent="."] +script = ExtResource("1_wrk2a") +mesh_vector_data = SubResource("Resource_j714y") + +[node name="block1" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, 1) +script = ExtResource("1_wrk2a") +mesh_vector_data = SubResource("Resource_083x5") diff --git a/addons/cyclops_level_builder/LICENSE.md b/addons/cyclops_level_builder/LICENSE.md new file mode 100644 index 00000000..17f9cf98 --- /dev/null +++ b/addons/cyclops_level_builder/LICENSE.md @@ -0,0 +1,7 @@ +Copyright 2023 Mark McKay + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/addons/cyclops_level_builder/actions/action_convert_to_mesh.gd b/addons/cyclops_level_builder/actions/action_convert_to_mesh.gd new file mode 100644 index 00000000..89ceabee --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_convert_to_mesh.gd @@ -0,0 +1,138 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionConvertToMesh +extends CyclopsAction + + + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Convert To Godot Mesh") + +func _execute(): + var root:Node = plugin.get_editor_interface().get_edited_scene_root() + + #var ed_sel:EditorSelection = plugin.get_editor_interface().get_selection() + #var sel_nodes:Array[Node] = ed_sel.get_selected_nodes() + # + #if sel_nodes.is_empty(): + #return + + #var branch_to_clone:Node = sel_nodes[0] + #var root = branch_to_clone.get_parent() + + var converted_branch:Node3D = clone_branch(root) + converted_branch.name = GeneralUtil.find_unique_name(root, "converted_blocks") + root.add_child(converted_branch) + + set_owner_recursive(converted_branch, plugin.get_editor_interface().get_edited_scene_root()) + + pass + +func set_owner_recursive(node:Node3D, new_owner): + node.owner = new_owner + for child in node.get_children(): + if child is Node3D: + set_owner_recursive(child, new_owner) + +func clone_branch(node:Node3D)->Node3D: + if node is CyclopsBlock: + var block:CyclopsBlock = node + var name_root:String = block.name + + var new_node:Node3D = Node3D.new() + new_node.name = name_root + new_node.transform = node.transform + new_node.set_meta("_edit_group_", true) +# new_node.owner = plugin.get_editor_interface().get_edited_scene_root() + + var new_mesh_node:MeshInstance3D = block.mesh_instance.duplicate() + new_mesh_node.name = name_root + "_mesh" +# new_mesh_node.owner = plugin.get_editor_interface().get_edited_scene_root() + new_node.add_child(new_mesh_node) + + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_convex_block_data(block.block_data) + + + var collision_body:PhysicsBody3D + + match block.collision_type: + Collision.Type.STATIC: + collision_body = StaticBody3D.new() + Collision.Type.KINEMATIC: + collision_body = CharacterBody3D.new() + Collision.Type.RIGID: + collision_body = RigidBody3D.new() + + if collision_body: + +# collision_body.owner = plugin.get_editor_interface().get_edited_scene_root() + collision_body.name = name_root + "_col" + collision_body.collision_layer = block.collision_layer + collision_body.collision_mask = block.collision_mask + new_node.add_child(collision_body) + + var collision_shape:CollisionShape3D = CollisionShape3D.new() +# collision_shape.owner = plugin.get_editor_interface().get_edited_scene_root() + collision_body.add_child(collision_shape) + collision_shape.name = name_root + "_col_shp" + + var shape:ConvexPolygonShape3D = ConvexPolygonShape3D.new() + shape.points = vol.get_points() + collision_shape.shape = shape + + #var occluder:OccluderInstance3D = OccluderInstance3D.new() + #occluder.name = name_root + "_occ" +## occluder.owner = plugin.get_editor_interface().get_edited_scene_root() + #new_node.add_child(occluder) + # + #var occluder_object:ArrayOccluder3D = ArrayOccluder3D.new() + #occluder.name = name_root + "_occ" + #occluder_object.vertices = vol.get_points() + #occluder_object.indices = vol.get_trimesh_indices() + #occluder.occluder = occluder_object + + return new_node + + else: + var new_node:Node3D = Node3D.new() +# new_node.owner = plugin.get_editor_interface().get_edited_scene_root() + new_node.transform = node.transform + new_node.name = node.name + for child in node.get_children(): + if branch_is_valid(child): + new_node.add_child(clone_branch(child)) + return new_node + +func branch_is_valid(node:Node)->bool: + if node is CyclopsBlock: + return true + + for child in node.get_children(): + if child is Node3D and branch_is_valid(child): + return true + + return false diff --git a/addons/cyclops_level_builder/actions/action_convert_to_mesh.gd.uid b/addons/cyclops_level_builder/actions/action_convert_to_mesh.gd.uid new file mode 100644 index 00000000..cced40ad --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_convert_to_mesh.gd.uid @@ -0,0 +1 @@ +uid://c67esxkkra8m5 diff --git a/addons/cyclops_level_builder/actions/action_delete_selected_blocks.gd b/addons/cyclops_level_builder/actions/action_delete_selected_blocks.gd new file mode 100644 index 00000000..36270bb1 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_delete_selected_blocks.gd @@ -0,0 +1,46 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionDeleteSelectedBlocks +extends CyclopsAction + + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Delete Selected Blocks") + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.is_empty(): + return + + var cmd:CommandDeleteBlocks = CommandDeleteBlocks.new() + cmd.builder = plugin + + for block in blocks: + cmd.block_paths.append(block.get_path()) + + + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) + diff --git a/addons/cyclops_level_builder/actions/action_delete_selected_blocks.gd.uid b/addons/cyclops_level_builder/actions/action_delete_selected_blocks.gd.uid new file mode 100644 index 00000000..0189df74 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_delete_selected_blocks.gd.uid @@ -0,0 +1 @@ +uid://con7ymkgu4il1 diff --git a/addons/cyclops_level_builder/actions/action_duplicate_selected_blocks.gd b/addons/cyclops_level_builder/actions/action_duplicate_selected_blocks.gd new file mode 100644 index 00000000..2a115994 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_duplicate_selected_blocks.gd @@ -0,0 +1,45 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionDuplicateSelectedBlocks +extends CyclopsAction + + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Duplicate Selected Blocks") + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.is_empty(): + return + + var cmd:CommandDuplicateBlocks = CommandDuplicateBlocks.new() + cmd.builder = plugin + + for block in blocks: + cmd.blocks_to_duplicate.append(block.get_path()) + + + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/actions/action_duplicate_selected_blocks.gd.uid b/addons/cyclops_level_builder/actions/action_duplicate_selected_blocks.gd.uid new file mode 100644 index 00000000..197ba2ec --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_duplicate_selected_blocks.gd.uid @@ -0,0 +1 @@ +uid://k3uujw61kti0 diff --git a/addons/cyclops_level_builder/actions/action_intersect_block.gd b/addons/cyclops_level_builder/actions/action_intersect_block.gd new file mode 100644 index 00000000..22f081cb --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_intersect_block.gd @@ -0,0 +1,57 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionIntersectBlock +extends CyclopsAction + + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Intersect Blocks") + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.size() < 2: + plugin.log("Not enough objects selected") + return + + var active:CyclopsBlock = plugin.get_active_block() + if !active: + plugin.log("No active object selected") + return + + var cmd:CommandIntersectBlock = CommandIntersectBlock.new() + cmd.builder = plugin + + for block in blocks: + if plugin.is_active_block(block): + cmd.main_block_path = block.get_path() + else: + cmd.block_paths.append(block.get_path()) + + if cmd.main_block_path.is_empty(): + return + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/actions/action_intersect_block.gd.uid b/addons/cyclops_level_builder/actions/action_intersect_block.gd.uid new file mode 100644 index 00000000..da7d9e3e --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_intersect_block.gd.uid @@ -0,0 +1 @@ +uid://byy1ns51y1lbo diff --git a/addons/cyclops_level_builder/actions/action_merge_selected_blocks.gd b/addons/cyclops_level_builder/actions/action_merge_selected_blocks.gd new file mode 100644 index 00000000..01a73548 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_merge_selected_blocks.gd @@ -0,0 +1,45 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionMergeSelectedBlocks +extends CyclopsAction + + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Merge Selected Blocks") + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.is_empty(): + return + + var cmd:CommandMergeBlocks = CommandMergeBlocks.new() + cmd.builder = plugin + + for block in blocks: + cmd.block_paths.append(block.get_path()) + + + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/actions/action_merge_selected_blocks.gd.uid b/addons/cyclops_level_builder/actions/action_merge_selected_blocks.gd.uid new file mode 100644 index 00000000..830e1df0 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_merge_selected_blocks.gd.uid @@ -0,0 +1 @@ +uid://bxyvhyhhevya5 diff --git a/addons/cyclops_level_builder/actions/action_merge_vertices_center.gd b/addons/cyclops_level_builder/actions/action_merge_vertices_center.gd new file mode 100644 index 00000000..9b75face --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_merge_vertices_center.gd @@ -0,0 +1,56 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionMergeVerticesCenter +extends CyclopsAction + + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Merge Vertices Center") + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.is_empty(): + return + + var cmd:CommandMergeVertices = CommandMergeVertices.new() + cmd.builder = plugin + + for block in blocks: + var sel_vec:DataVector = block.mesh_vector_data.get_vertex_data(MeshVectorData.V_SELECTED) + + if sel_vec.size() < 2: + continue + + var indices:Array[int] + #print("sel vert bytes ", block.block_data.vertex_selected) + for idx in sel_vec.size(): + if sel_vec.get_value(idx): + indices.append(idx) + cmd.add_vertices(block.get_path(), indices) + + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/actions/action_merge_vertices_center.gd.uid b/addons/cyclops_level_builder/actions/action_merge_vertices_center.gd.uid new file mode 100644 index 00000000..1f82cef8 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_merge_vertices_center.gd.uid @@ -0,0 +1 @@ +uid://dq5ebr2ytm531 diff --git a/addons/cyclops_level_builder/actions/action_mirror_selection_x.gd b/addons/cyclops_level_builder/actions/action_mirror_selection_x.gd new file mode 100644 index 00000000..5d94e1ac --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_mirror_selection_x.gd @@ -0,0 +1,30 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionMirrorSelectionX2 +extends ActionScaleSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Mirror Selection X") + scale = Vector3(-1, 1, 1) diff --git a/addons/cyclops_level_builder/actions/action_mirror_selection_x.gd.uid b/addons/cyclops_level_builder/actions/action_mirror_selection_x.gd.uid new file mode 100644 index 00000000..4cde7ed2 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_mirror_selection_x.gd.uid @@ -0,0 +1 @@ +uid://bypeipqdgy6n3 diff --git a/addons/cyclops_level_builder/actions/action_mirror_selection_y.gd b/addons/cyclops_level_builder/actions/action_mirror_selection_y.gd new file mode 100644 index 00000000..aa344144 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_mirror_selection_y.gd @@ -0,0 +1,30 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionMirrorSelectionY2 +extends ActionScaleSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Mirror Selection Y") + scale = Vector3(1, -1, 1) diff --git a/addons/cyclops_level_builder/actions/action_mirror_selection_y.gd.uid b/addons/cyclops_level_builder/actions/action_mirror_selection_y.gd.uid new file mode 100644 index 00000000..cdc40af9 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_mirror_selection_y.gd.uid @@ -0,0 +1 @@ +uid://ctu1dxl3t8iqt diff --git a/addons/cyclops_level_builder/actions/action_mirror_selection_z.gd b/addons/cyclops_level_builder/actions/action_mirror_selection_z.gd new file mode 100644 index 00000000..2f919e6d --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_mirror_selection_z.gd @@ -0,0 +1,30 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionMirrorSelectionZ +extends ActionScaleSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Mirror Selection Z") + scale = Vector3(1, 1, -1) diff --git a/addons/cyclops_level_builder/actions/action_mirror_selection_z.gd.uid b/addons/cyclops_level_builder/actions/action_mirror_selection_z.gd.uid new file mode 100644 index 00000000..9b95c363 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_mirror_selection_z.gd.uid @@ -0,0 +1 @@ +uid://ggertsmt2up5 diff --git a/addons/cyclops_level_builder/actions/action_rotate_selection.gd b/addons/cyclops_level_builder/actions/action_rotate_selection.gd new file mode 100644 index 00000000..a99a5ad8 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_selection.gd @@ -0,0 +1,55 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateSelection +extends CyclopsAction + +var rotation_axis:Vector3 = Vector3.ONE +var rotation_angle:float + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, name, accellerator) + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.is_empty(): + return + + var pivot:Vector3 = calc_pivot_of_blocks(blocks) + + var cmd:CommandTransformVertices = CommandTransformVertices.new() + cmd.builder = plugin + + for block in blocks: + cmd.add_block(block.get_path()) + + var xform:Transform3D = Transform3D.IDENTITY + xform = xform.translated_local(pivot) + xform = xform.rotated_local(rotation_axis, rotation_angle) + xform = xform.translated_local(-pivot) + cmd.transform = xform + #print("cform %s" % xform) + + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/actions/action_rotate_selection.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_selection.gd.uid new file mode 100644 index 00000000..ae77ff57 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_selection.gd.uid @@ -0,0 +1 @@ +uid://c8plx08lpik4l diff --git a/addons/cyclops_level_builder/actions/action_rotate_x_180.gd b/addons/cyclops_level_builder/actions/action_rotate_x_180.gd new file mode 100644 index 00000000..5f48b609 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_x_180.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateX180 +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 180 X") + rotation_axis = Vector3(1, 0, 0) + rotation_angle = deg_to_rad(180) diff --git a/addons/cyclops_level_builder/actions/action_rotate_x_180.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_x_180.gd.uid new file mode 100644 index 00000000..53b46733 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_x_180.gd.uid @@ -0,0 +1 @@ +uid://i5qnhsk8ldww diff --git a/addons/cyclops_level_builder/actions/action_rotate_x_90_ccw.gd b/addons/cyclops_level_builder/actions/action_rotate_x_90_ccw.gd new file mode 100644 index 00000000..9bec89a0 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_x_90_ccw.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateX90Ccw +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 90 Ccw X") + rotation_axis = Vector3(1, 0, 0) + rotation_angle = deg_to_rad(90) diff --git a/addons/cyclops_level_builder/actions/action_rotate_x_90_ccw.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_x_90_ccw.gd.uid new file mode 100644 index 00000000..db88d0cb --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_x_90_ccw.gd.uid @@ -0,0 +1 @@ +uid://cfkx3w6hj24yh diff --git a/addons/cyclops_level_builder/actions/action_rotate_x_90_cw.gd b/addons/cyclops_level_builder/actions/action_rotate_x_90_cw.gd new file mode 100644 index 00000000..7fe123a9 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_x_90_cw.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateX90Cw +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 90 Cw X") + rotation_axis = Vector3(1, 0, 0) + rotation_angle = deg_to_rad(-90) diff --git a/addons/cyclops_level_builder/actions/action_rotate_x_90_cw.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_x_90_cw.gd.uid new file mode 100644 index 00000000..a888afe8 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_x_90_cw.gd.uid @@ -0,0 +1 @@ +uid://dm5xdf33bnn4s diff --git a/addons/cyclops_level_builder/actions/action_rotate_y_180.gd b/addons/cyclops_level_builder/actions/action_rotate_y_180.gd new file mode 100644 index 00000000..64f6fb92 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_y_180.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateY180 +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 180 Y") + rotation_axis = Vector3(0, 1, 0) + rotation_angle = deg_to_rad(180) diff --git a/addons/cyclops_level_builder/actions/action_rotate_y_180.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_y_180.gd.uid new file mode 100644 index 00000000..081173c9 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_y_180.gd.uid @@ -0,0 +1 @@ +uid://dqj8te2dab30y diff --git a/addons/cyclops_level_builder/actions/action_rotate_y_90_ccw.gd b/addons/cyclops_level_builder/actions/action_rotate_y_90_ccw.gd new file mode 100644 index 00000000..5d736a4d --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_y_90_ccw.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateY90Ccw +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 90 Ccw Y") + rotation_axis = Vector3(0, 1, 0) + rotation_angle = deg_to_rad(90) diff --git a/addons/cyclops_level_builder/actions/action_rotate_y_90_ccw.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_y_90_ccw.gd.uid new file mode 100644 index 00000000..7fe64db6 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_y_90_ccw.gd.uid @@ -0,0 +1 @@ +uid://bib4eaaibtxvm diff --git a/addons/cyclops_level_builder/actions/action_rotate_y_90_cw.gd b/addons/cyclops_level_builder/actions/action_rotate_y_90_cw.gd new file mode 100644 index 00000000..ea29d282 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_y_90_cw.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateY90Cw +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 90 Cw Y") + rotation_axis = Vector3(0, 1, 0) + rotation_angle = deg_to_rad(-90) diff --git a/addons/cyclops_level_builder/actions/action_rotate_y_90_cw.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_y_90_cw.gd.uid new file mode 100644 index 00000000..f1459a50 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_y_90_cw.gd.uid @@ -0,0 +1 @@ +uid://64qdecseke77 diff --git a/addons/cyclops_level_builder/actions/action_rotate_z_180.gd b/addons/cyclops_level_builder/actions/action_rotate_z_180.gd new file mode 100644 index 00000000..9884000e --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_z_180.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateZ180 +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 180 Z") + rotation_axis = Vector3(0, 0, 1) + rotation_angle = deg_to_rad(180) diff --git a/addons/cyclops_level_builder/actions/action_rotate_z_180.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_z_180.gd.uid new file mode 100644 index 00000000..a0064d72 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_z_180.gd.uid @@ -0,0 +1 @@ +uid://8h737ai4emey diff --git a/addons/cyclops_level_builder/actions/action_rotate_z_90_ccw.gd b/addons/cyclops_level_builder/actions/action_rotate_z_90_ccw.gd new file mode 100644 index 00000000..5e26b487 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_z_90_ccw.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateZ90Ccw +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 90 Ccw Z") + rotation_axis = Vector3(0, 0, 1) + rotation_angle = deg_to_rad(90) diff --git a/addons/cyclops_level_builder/actions/action_rotate_z_90_ccw.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_z_90_ccw.gd.uid new file mode 100644 index 00000000..cd07533a --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_z_90_ccw.gd.uid @@ -0,0 +1 @@ +uid://dg0kbay1h4wks diff --git a/addons/cyclops_level_builder/actions/action_rotate_z_90_cw.gd b/addons/cyclops_level_builder/actions/action_rotate_z_90_cw.gd new file mode 100644 index 00000000..f8f4576d --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_z_90_cw.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionRotateZ90Cw +extends ActionRotateSelection + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Rotate 90 Cw Z") + rotation_axis = Vector3(0, 0, 1) + rotation_angle = deg_to_rad(-90) diff --git a/addons/cyclops_level_builder/actions/action_rotate_z_90_cw.gd.uid b/addons/cyclops_level_builder/actions/action_rotate_z_90_cw.gd.uid new file mode 100644 index 00000000..679787e2 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_rotate_z_90_cw.gd.uid @@ -0,0 +1 @@ +uid://nf3l845gj2cb diff --git a/addons/cyclops_level_builder/actions/action_scale_selection.gd b/addons/cyclops_level_builder/actions/action_scale_selection.gd new file mode 100644 index 00000000..a3d7ea17 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_scale_selection.gd @@ -0,0 +1,54 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionScaleSelection +extends CyclopsAction + +var scale:Vector3 = Vector3.ONE + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, name, accellerator) + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.is_empty(): + return + + var pivot:Vector3 = calc_pivot_of_blocks(blocks) + + var cmd:CommandTransformVertices = CommandTransformVertices.new() + cmd.builder = plugin + + for block in blocks: + cmd.add_block(block.get_path()) + + var xform:Transform3D = Transform3D.IDENTITY + xform = xform.translated_local(pivot) + xform = xform.scaled_local(scale) + xform = xform.translated_local(-pivot) + cmd.transform = xform + #print("cform %s" % xform) + + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/actions/action_scale_selection.gd.uid b/addons/cyclops_level_builder/actions/action_scale_selection.gd.uid new file mode 100644 index 00000000..cf2fc1cd --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_scale_selection.gd.uid @@ -0,0 +1 @@ +uid://cnvfk7vmgymua diff --git a/addons/cyclops_level_builder/actions/action_snap_to_grid.gd b/addons/cyclops_level_builder/actions/action_snap_to_grid.gd new file mode 100644 index 00000000..4e7b46f2 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_snap_to_grid.gd @@ -0,0 +1,57 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionSnapToGrid +extends CyclopsAction + +func _init(plugin:CyclopsLevelBuilder): + super._init(plugin, "Snap to grid") + + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.is_empty(): + return + + var pivot:Vector3 = calc_pivot_of_blocks(blocks) + + var cmd:CommandSnapToGrid = CommandSnapToGrid.new() + cmd.builder = plugin + + for block in blocks: + cmd.add_block(block.get_path()) + + + #cmd.grid_size = pow(2, plugin.get_global_scene().grid_size) + #var snap_to_grid_util:SnapToGridUtil = CyclopsAutoload.calc_snap_to_grid_util() + #print("snap_to_grid_util %s" % snap_to_grid_util) + #cmd.snap_to_grid_util = snap_to_grid_util + + + #print("cform %s" % xform) + + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) + + diff --git a/addons/cyclops_level_builder/actions/action_snap_to_grid.gd.uid b/addons/cyclops_level_builder/actions/action_snap_to_grid.gd.uid new file mode 100644 index 00000000..a1ae4f37 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_snap_to_grid.gd.uid @@ -0,0 +1 @@ +uid://cx8x3ggdgb5rp diff --git a/addons/cyclops_level_builder/actions/action_subtract_block.gd b/addons/cyclops_level_builder/actions/action_subtract_block.gd new file mode 100644 index 00000000..2a93eb27 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_subtract_block.gd @@ -0,0 +1,57 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionSubtractBlock +extends CyclopsAction + + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Subtract Block") + +func _execute(): + var blocks:Array[CyclopsBlock] = plugin.get_selected_blocks() + if blocks.size() < 2: + plugin.log("Not enough objects selected") + return + + var active:CyclopsBlock = plugin.get_active_block() + if !active: + plugin.log("No active object selected") + return + + var cmd:CommandSubtractBlock = CommandSubtractBlock.new() + cmd.builder = plugin + + for block in blocks: + if plugin.is_active_block(block): + cmd.block_to_subtract_path = block.get_path() + else: + cmd.block_paths.append(block.get_path()) + + if cmd.block_to_subtract_path.is_empty(): + return + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/actions/action_subtract_block.gd.uid b/addons/cyclops_level_builder/actions/action_subtract_block.gd.uid new file mode 100644 index 00000000..06dd37d0 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_subtract_block.gd.uid @@ -0,0 +1 @@ +uid://1afista7wgi2 diff --git a/addons/cyclops_level_builder/actions/action_tool_duplicate.gd b/addons/cyclops_level_builder/actions/action_tool_duplicate.gd new file mode 100644 index 00000000..9ec1a52b --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_tool_duplicate.gd @@ -0,0 +1,33 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionToolDuplicate +extends CyclopsAction + + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Duplicate Selected Blocks") + +func _execute(): + plugin.switch_to_tool(ToolDuplicate.new()) diff --git a/addons/cyclops_level_builder/actions/action_tool_duplicate.gd.uid b/addons/cyclops_level_builder/actions/action_tool_duplicate.gd.uid new file mode 100644 index 00000000..17c137e6 --- /dev/null +++ b/addons/cyclops_level_builder/actions/action_tool_duplicate.gd.uid @@ -0,0 +1 @@ +uid://dlbttyma1at62 diff --git a/addons/cyclops_level_builder/actions/cyclops_action.gd b/addons/cyclops_level_builder/actions/cyclops_action.gd new file mode 100644 index 00000000..5b111e9f --- /dev/null +++ b/addons/cyclops_level_builder/actions/cyclops_action.gd @@ -0,0 +1,53 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CyclopsAction +extends RefCounted + +var plugin:CyclopsLevelBuilder + +var name:String = "" +var accellerator:Key = KEY_NONE + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + self.plugin = plugin + self.name= name + self.accellerator = accellerator + +func _execute(): + pass + +func calc_pivot_of_blocks(blocks:Array[CyclopsBlock])->Vector3: + var snap_to_grid_util:SnapToGridUtil = CyclopsAutoload.calc_snap_to_grid_util() + + var bounds:AABB = blocks[0].control_mesh.bounds + for idx in range(1, blocks.size()): + var block:CyclopsBlock = blocks[idx] + bounds = bounds.merge(block.control_mesh.bounds) + + var center:Vector3 = bounds.get_center() + center = snap_to_grid_util.snap_point(center) + + return center + diff --git a/addons/cyclops_level_builder/actions/cyclops_action.gd.uid b/addons/cyclops_level_builder/actions/cyclops_action.gd.uid new file mode 100644 index 00000000..e63b10fe --- /dev/null +++ b/addons/cyclops_level_builder/actions/cyclops_action.gd.uid @@ -0,0 +1 @@ +uid://cn1ewmmdut0jo diff --git a/addons/cyclops_level_builder/actions/io/action_export_as_cyclops.gd b/addons/cyclops_level_builder/actions/io/action_export_as_cyclops.gd new file mode 100644 index 00000000..cff5a56e --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_export_as_cyclops.gd @@ -0,0 +1,44 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionExportAsCyclops +extends CyclopsAction + +var wizard:ExporterCyclopsWizard = preload("res://addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.tscn").instantiate() + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Export As Cyclops File...") + +func _execute(): + if !wizard.get_parent(): + var base_control:Node = plugin.get_editor_interface().get_base_control() + base_control.add_child(wizard) + + wizard.plugin = plugin + wizard.popup_centered() + + + + + diff --git a/addons/cyclops_level_builder/actions/io/action_export_as_cyclops.gd.uid b/addons/cyclops_level_builder/actions/io/action_export_as_cyclops.gd.uid new file mode 100644 index 00000000..f5d9c7ca --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_export_as_cyclops.gd.uid @@ -0,0 +1 @@ +uid://3jyps2n0glin diff --git a/addons/cyclops_level_builder/actions/io/action_export_as_gltf.gd b/addons/cyclops_level_builder/actions/io/action_export_as_gltf.gd new file mode 100644 index 00000000..5c6ef373 --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_export_as_gltf.gd @@ -0,0 +1,49 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionExportAsGltf +extends CyclopsAction + +var wizard:ExporterGltfWizard = preload("res://addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.tscn").instantiate() + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Export As Gltf...") + +func _execute(): + if !wizard.get_parent(): + var base_control:Node = plugin.get_editor_interface().get_base_control() + base_control.add_child(wizard) + + wizard.plugin = plugin + wizard.popup_centered() + + #await base_control.get_tree().process_frame + +# wizard.popup_hide.connect(func(): wizard.queue_free() ) + + #wizard.popup_centered() + + + + diff --git a/addons/cyclops_level_builder/actions/io/action_export_as_gltf.gd.uid b/addons/cyclops_level_builder/actions/io/action_export_as_gltf.gd.uid new file mode 100644 index 00000000..4c3581cc --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_export_as_gltf.gd.uid @@ -0,0 +1 @@ +uid://eogrrte28ts2 diff --git a/addons/cyclops_level_builder/actions/io/action_export_as_godot_scene.gd b/addons/cyclops_level_builder/actions/io/action_export_as_godot_scene.gd new file mode 100644 index 00000000..79dd875e --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_export_as_godot_scene.gd @@ -0,0 +1,42 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionExportAsGodotScene +extends CyclopsAction + +var wizard:ExporterGodotSceneWizard = preload("res://addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.tscn").instantiate() + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Export As Godot Scene...") + +func _execute(): + if !wizard.get_parent(): + var base_control:Node = plugin.get_editor_interface().get_base_control() + base_control.add_child(wizard) + + wizard.plugin = plugin + wizard.popup_centered() + + + diff --git a/addons/cyclops_level_builder/actions/io/action_export_as_godot_scene.gd.uid b/addons/cyclops_level_builder/actions/io/action_export_as_godot_scene.gd.uid new file mode 100644 index 00000000..dcb5a9e6 --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_export_as_godot_scene.gd.uid @@ -0,0 +1 @@ +uid://dn1p2b5ga5uv4 diff --git a/addons/cyclops_level_builder/actions/io/action_import_cyclops_file.gd b/addons/cyclops_level_builder/actions/io/action_import_cyclops_file.gd new file mode 100644 index 00000000..3b1e1efc --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_import_cyclops_file.gd @@ -0,0 +1,39 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionImportCyclopsFile +extends CyclopsAction + +var wizard:ImporterCyclopsFileWizard = preload("res://addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.tscn").instantiate() + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Import Cyclops File...") + +func _execute(): + if !wizard.get_parent(): + var base_control:Node = plugin.get_editor_interface().get_base_control() + base_control.add_child(wizard) + + wizard.plugin = plugin + wizard.popup_centered() diff --git a/addons/cyclops_level_builder/actions/io/action_import_cyclops_file.gd.uid b/addons/cyclops_level_builder/actions/io/action_import_cyclops_file.gd.uid new file mode 100644 index 00000000..0aa84327 --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_import_cyclops_file.gd.uid @@ -0,0 +1 @@ +uid://pnx5r14k1y73 diff --git a/addons/cyclops_level_builder/actions/io/action_import_mesh_instance.gd b/addons/cyclops_level_builder/actions/io/action_import_mesh_instance.gd new file mode 100644 index 00000000..67eb83f1 --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_import_mesh_instance.gd @@ -0,0 +1,66 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ActionImportMeshInstance +extends CyclopsAction + +func _init(plugin:CyclopsLevelBuilder, name:String = "", accellerator:Key = KEY_NONE): + super._init(plugin, "Import Godot MeshInstance...") + +func _execute(): + var nodes:Array[Node] = plugin.get_editor_interface().get_selection().get_selected_nodes() + + if nodes.is_empty(): + return + + if !(nodes[-1] is Node3D): + return + + var tgt_parent:Node3D = nodes[-1] + if tgt_parent is MeshInstance3D: + tgt_parent = tgt_parent.get_parent() + + var cmd:CommandImportGodotMeshes = CommandImportGodotMeshes.new() + cmd.builder = plugin + cmd.target_parent = tgt_parent.get_path() + #print("parent ", tgt_parent.get_path()) + + for node in nodes: + import_branch_recursive(node, cmd) + + if !cmd.will_change_anything(): + return + + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) + +func import_branch_recursive(node:Node3D, cmd:CommandImportGodotMeshes): + if node is MeshInstance3D: + cmd.source_nodes.append(node.get_path()) + #print("src ", node.get_path()) + + for child in node.get_children(): + import_branch_recursive(child, cmd) + + diff --git a/addons/cyclops_level_builder/actions/io/action_import_mesh_instance.gd.uid b/addons/cyclops_level_builder/actions/io/action_import_mesh_instance.gd.uid new file mode 100644 index 00000000..1920f4d5 --- /dev/null +++ b/addons/cyclops_level_builder/actions/io/action_import_mesh_instance.gd.uid @@ -0,0 +1 @@ +uid://in5pkw0ilavw diff --git a/addons/cyclops_level_builder/art/cyclops.svg b/addons/cyclops_level_builder/art/cyclops.svg new file mode 100644 index 00000000..a2fc7e11 --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops.svg @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/cyclops_level_builder/art/cyclops.svg.import b/addons/cyclops_level_builder/art/cyclops.svg.import new file mode 100644 index 00000000..fbb96479 --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bmbwskudf7ldr" +path="res://.godot/imported/cyclops.svg-62ab1cb5293c5a489284f34e0c642019.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops.svg" +dest_files=["res://.godot/imported/cyclops.svg-62ab1cb5293c5a489284f34e0c642019.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/cyclops1.png b/addons/cyclops_level_builder/art/cyclops1.png new file mode 100644 index 00000000..13c28226 --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8b481f216d05acd7f5ba0f2bb5a866ac7e0f233014bad624ebfea7d9adad4ca +size 369 diff --git a/addons/cyclops_level_builder/art/cyclops1.png.import b/addons/cyclops_level_builder/art/cyclops1.png.import new file mode 100644 index 00000000..881ae35c --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops1.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://l4qj0lbj3ioa" +path="res://.godot/imported/cyclops1.png-6f459321d21304ca30333893d06ffb09.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops1.png" +dest_files=["res://.godot/imported/cyclops1.png-6f459321d21304ca30333893d06ffb09.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/art/cyclops2.png b/addons/cyclops_level_builder/art/cyclops2.png new file mode 100644 index 00000000..2d2c554f --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7be7ee2c5d48c0f25018663cf43bc12dba8796c031da5ff8b781ac5ca883d19 +size 433 diff --git a/addons/cyclops_level_builder/art/cyclops2.png.import b/addons/cyclops_level_builder/art/cyclops2.png.import new file mode 100644 index 00000000..83336817 --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops2.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://oxrgrpeaamq3" +path="res://.godot/imported/cyclops2.png-510e6418526608a41b6474466da5ef6e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops2.png" +dest_files=["res://.godot/imported/cyclops2.png-510e6418526608a41b6474466da5ef6e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/art/cyclops_16.png b/addons/cyclops_level_builder/art/cyclops_16.png new file mode 100644 index 00000000..70b2339a --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_16.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b7158b35681f51d0b85dec944319310b279c380af64f812832a5dbfbf142b35f +size 258 diff --git a/addons/cyclops_level_builder/art/cyclops_16.png.import b/addons/cyclops_level_builder/art/cyclops_16.png.import new file mode 100644 index 00000000..0c2777ff --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_16.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://df0a5uffpuqg3" +path="res://.godot/imported/cyclops_16.png-f07e4f06ecdf5a5bd3bf65311c5a89e7.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops_16.png" +dest_files=["res://.godot/imported/cyclops_16.png-f07e4f06ecdf5a5bd3bf65311c5a89e7.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/art/cyclops_17.png b/addons/cyclops_level_builder/art/cyclops_17.png new file mode 100644 index 00000000..a81230bf --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_17.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b3b9a11b89780efd5ecd8d5e5976a80479556ce1f226f2a8ca9127b76e6e958 +size 272 diff --git a/addons/cyclops_level_builder/art/cyclops_17.png.import b/addons/cyclops_level_builder/art/cyclops_17.png.import new file mode 100644 index 00000000..c60a735b --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_17.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ynphxd22kahd" +path="res://.godot/imported/cyclops_17.png-c21222671fab466b90ffb528051b4f8e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops_17.png" +dest_files=["res://.godot/imported/cyclops_17.png-c21222671fab466b90ffb528051b4f8e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/art/cyclops_3.png b/addons/cyclops_level_builder/art/cyclops_3.png new file mode 100644 index 00000000..502b677f --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:069b4924dd88e345092702d18308aed633f097a489cd3e5634ba6552a7481cd4 +size 588 diff --git a/addons/cyclops_level_builder/art/cyclops_3.png.import b/addons/cyclops_level_builder/art/cyclops_3.png.import new file mode 100644 index 00000000..f473f9b3 --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_3.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d0krdms4l6ns4" +path="res://.godot/imported/cyclops_3.png-6415cec0c5295619847f207c8fb5e88e.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops_3.png" +dest_files=["res://.godot/imported/cyclops_3.png-6415cec0c5295619847f207c8fb5e88e.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/art/cyclops_4.png b/addons/cyclops_level_builder/art/cyclops_4.png new file mode 100644 index 00000000..120929dc --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bc1da650595d21972b18dac09edadf0a5a37b82c7387b8d3ff3fb5ddc855c92e +size 643 diff --git a/addons/cyclops_level_builder/art/cyclops_4.png.import b/addons/cyclops_level_builder/art/cyclops_4.png.import new file mode 100644 index 00000000..1bb0fc12 --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_4.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cg3yjatinkymb" +path="res://.godot/imported/cyclops_4.png-e03a17198c56b52428203cf1953feb8c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops_4.png" +dest_files=["res://.godot/imported/cyclops_4.png-e03a17198c56b52428203cf1953feb8c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/art/cyclops_closed.png b/addons/cyclops_level_builder/art/cyclops_closed.png new file mode 100644 index 00000000..38479cd7 --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_closed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1c21a04613c21c5c50bbc7a65fe07f141d84cb158418ab7a9fb7c79eff8d9e68 +size 1151 diff --git a/addons/cyclops_level_builder/art/cyclops_closed.png.import b/addons/cyclops_level_builder/art/cyclops_closed.png.import new file mode 100644 index 00000000..d4091e14 --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_closed.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dd8xjcq5k2kia" +path="res://.godot/imported/cyclops_closed.png-8f54cf7552f8e17ac6aa0c8d6378241b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops_closed.png" +dest_files=["res://.godot/imported/cyclops_closed.png-8f54cf7552f8e17ac6aa0c8d6378241b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/art/cyclops_open.png b/addons/cyclops_level_builder/art/cyclops_open.png new file mode 100644 index 00000000..0effac5a --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_open.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abe637103491445936c21b9cf21404ad215d74e72e71a8545297c17894d7d360 +size 1250 diff --git a/addons/cyclops_level_builder/art/cyclops_open.png.import b/addons/cyclops_level_builder/art/cyclops_open.png.import new file mode 100644 index 00000000..a71ecaae --- /dev/null +++ b/addons/cyclops_level_builder/art/cyclops_open.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dv78ucvwmycdh" +path="res://.godot/imported/cyclops_open.png-44d55f3db65056f90cc00f3559bf1cb3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/cyclops_open.png" +dest_files=["res://.godot/imported/cyclops_open.png-44d55f3db65056f90cc00f3559bf1cb3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/LICENSE.txt b/addons/cyclops_level_builder/art/fonts/Roboto/LICENSE.txt new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Black.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Black.ttf new file mode 100644 index 0000000000000000000000000000000000000000..0112e7da626ca2f959eca850c806779ba55dbfbd GIT binary patch literal 168060 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
TJYyt(6q>rW4S(W4gHIq&3$utU3y8!9=k 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 WVelBb2)1!{_R^~ms-+tiJp5mlrotHj literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Black.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Black.ttf.import new file mode 100644 index 00000000..07d52d4a --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Black.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://yhi2wxrd3vdl" +path="res://.godot/imported/Roboto-Black.ttf-bf53e1e350116bdc6b4fb4a05660f669.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Black.ttf" +dest_files=["res://.godot/imported/Roboto-Black.ttf-bf53e1e350116bdc6b4fb4a05660f669.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BlackItalic.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BlackItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b2c6aca57bc0d92ab3197d595766bf9285deea00 GIT binary patch literal 174108 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�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 literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BlackItalic.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BlackItalic.ttf.import new file mode 100644 index 00000000..c82e6a82 --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BlackItalic.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://du5gqvb4yc1dj" +path="res://.godot/imported/Roboto-BlackItalic.ttf-bf8690d15b3cf8cd5d6a2b817379e64e.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BlackItalic.ttf" +dest_files=["res://.godot/imported/Roboto-BlackItalic.ttf-bf8690d15b3cf8cd5d6a2b817379e64e.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Bold.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..43da14d84ecb949ca5f5e8ecca3a514aa7fe1c7d GIT binary patch literal 167336 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

CI1`9yZA;krY|pfYv_=)r#TI})&gnG! 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 }T0zx*PitjbVP(pkGu*HnX1(-EMz?0WEMAX) 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 literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BoldItalic.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BoldItalic.ttf.import new file mode 100644 index 00000000..8377d525 --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BoldItalic.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://c3x3cd47jhq2" +path="res://.godot/imported/Roboto-BoldItalic.ttf-a6c74f542f3344ae20ca33a53a2a23a5.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-BoldItalic.ttf" +dest_files=["res://.godot/imported/Roboto-BoldItalic.ttf-a6c74f542f3344ae20ca33a53a2a23a5.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Italic.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..1b5eaa361c7306b4246c48497c79475c0e05c5e2 GIT binary patch literal 170504 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 JyV?28{{co6(@+2a literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Italic.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Italic.ttf.import new file mode 100644 index 00000000..15fe6b3a --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Italic.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://b7wdow3eps416" +path="res://.godot/imported/Roboto-Italic.ttf-16e369b2270cffe6321292c293333ba2.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Italic.ttf" +dest_files=["res://.godot/imported/Roboto-Italic.ttf-16e369b2270cffe6321292c293333ba2.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Light.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..e7307e72c5e7bced5d36c776d0986bf71b605f15 GIT binary patch literal 167000 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 T&&O!b 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

1!1exG)EK6u~BkmExnKuQI2?mS0J2 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 Og7zwfTI$9`zx;34o!sdF literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Light.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Light.ttf.import new file mode 100644 index 00000000..72b7674a --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Light.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://r0x2ql45ygwl" +path="res://.godot/imported/Roboto-Light.ttf-32e2bbbc31f4a36b674db4f07c8dde61.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Light.ttf" +dest_files=["res://.godot/imported/Roboto-Light.ttf-32e2bbbc31f4a36b674db4f07c8dde61.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-LightItalic.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-LightItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..2d277afb231f7613a49d983217c1aba871741433 GIT binary patch literal 173172 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 literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-LightItalic.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-LightItalic.ttf.import new file mode 100644 index 00000000..899de6ba --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-LightItalic.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://bhhr80f3d5x6w" +path="res://.godot/imported/Roboto-LightItalic.ttf-df475dd7032319cbfacce9bda56b5428.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-LightItalic.ttf" +dest_files=["res://.godot/imported/Roboto-LightItalic.ttf-df475dd7032319cbfacce9bda56b5428.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Medium.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ac0f908b9c9c73da558b45d65cc5c6094874d3e8 GIT binary patch literal 168644 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 X76wnEi(n^v8!x?bp_;lO!DIggn3ZN8 literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Medium.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Medium.ttf.import new file mode 100644 index 00000000..2afdbb4e --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Medium.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://c8a6t7tcg764a" +path="res://.godot/imported/Roboto-Medium.ttf-1aacbf46d243718027ec489d66f94134.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Medium.ttf" +dest_files=["res://.godot/imported/Roboto-Medium.ttf-1aacbf46d243718027ec489d66f94134.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-MediumItalic.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-MediumItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..fc36a4785c50c04c9b18260e4709cda077ed352d GIT binary patch literal 173416 zcma&P2Vhgx7eD^)cuCr(ZQ8U=TT1s}7brBe>^)^~WbeH<$SzB!$es$y)bv>t6hWDS zs6`M5h^RPFz=eRcdHsLxO<$Av_4oh%zJ5vik~Z(&bI(2Jb3W&s8-*x}5{?J1B(`kU zyhTA1*FuF>Xr?H1P|J=Tx*YmFZ=^yi?N^kc)mnDx)@0U#CDRqU<_krMT-%{bX3b4M z<_}S5`S6 z_^VH+DU?|7``IJ#g7rrD8+d;Pu2V;hoibzUH(Tc8{YHusQD@Bf!2?}EmETgxqn{Ne zFn;X7857J6SOTs;!0#uH8#s1o^V})t6`F?6V<8j9Po7dTP{DjEM2q()Od2{N=j-Kv zD>S7m#?(_$@t(pes4j&mCM7_zDxu1F&1wq^3(s*`Z7!uyJeuTVfP4%tR9s5)o-UeM zE}teg=p`={Tqw2%y);f0{H3OPp3I&ni+pkg-qfs~7lJ)6P@5~{X7w6LNnuGWjF2$G zl1Ocm#45P!(X-k51O07cy+fI<6Y6%WuBUrdvwJR`UKB=Wxckw5%V2D;A-=l?ox0&&*etcbdG=RbDP79)k*9L7Dj$pLc_> z7I@L-3dc}wt_b>|7M0pi~-{lZRt7_CEc zppZ(FlB&FuX`516S*RscsfuYRuE0z=y#P!vz?gUym zL`6BG%qElBoZ?JRcREbC%%*xkr(atg3<>K4Vwb*1$682?A+jhjz2d%78-Q_ zMC$gm{jPxf=3#?It|N=uO&sK0@X5h1Bfq+p@aL&{s~DXysNI-hRTqAB0Q+Ccq435HHoRGiR|Ra!>9`eJe!HkVo`9XnUR%a8WCOtHD*3SDuTt`u8-RiD@6Z27gkmk<*~194

>Lm_m;)d~S=y9Q;dl?qBN zWr|j{cD9ghRhuiUP&_7;S`t46jD{qmjhz>Vi#VZx;Q`V3Q!P?HO zL-T8T->hE44i$s=va=oWRBD!Zftnpj8A7aTRJN0uh2q&w4u=yaDm^9HRL6RLQvC|t zdgpN8jU82WT2qPim!*iBSWl517GrH-ENLgU+LJ zT93ruT+52dMrrS&{>$2xnm4kb>yA!G)#>^Y%EgWzq1RxErU6QrV$)3Fc8EuDu}qg0 z=FlFlI2{VZ#KIlsbc#98uT45UN!1SyOCxm1pgM=%vQR5+N5;~eaclJ_?#mya`cS{p zW63D;9;q~-yFyAf=$W*msXx4yO$(4-OM#_zDfo1jksWS#+A^F`QQ>Avm6mDOevjp6 zb0)vsfd{;y-_kQz?4y}v-W;;;a9#_yzW1np*ZsG?31c2k+p>MI!68bbXQmtr%;hF3 zjKPOTy8`eWkQt3Rr#V%a!8C_zH#3$&=IK9oAdaf8wxn9L{{E&H=iJO=S9u?dSUYFg^LNBn`BOc)lCu>m%d9TX6S3% z{?tx?z5vYMV{4bIIqRRxq&29*57bJdH`t3;)h=15A$2wV<%te*Ht zKQp}EFXmt}4l?`=*lUJ*6v!*rGiVihrW(fD7_`O}RZNa&<}>eLHOj=RfKMrQ)tQz> z7u>s~uT7(kQu*_hckl6=ZTAA#++T6>>)^0E4fH;A zX+CYfFR%YR&R>{E@~%&3{F-+8`}+D6p@ZoqKl2>*oKi^{rCBOhDI0Sr1QTiqrW`KH z3EL}?n=90oZ}yG~mjd1pKVPmzRwQC}e&p?Wp_~o(4<9^si`6=L%of&? zJU4RiL`o<1B~y+A+Of!c)t4Chnx(5X9gKCmGNcc#!q1c+8ltjss!B+gw1L5 z9||lDknk`hfQyNc%zWydf&l15Ok1;bQfGE#^2*gf|H3-H5kFxMspZZ9KC04-x> z-abX2Cb>TuK5WME3*q7V&ClQb-t@hBXrJ+$Lan1lHX2%;enxM6s=u5|^@pF`(0}3l zyW_(qQ?~#4Ia?^LT0z*1!O$+ddQ5QuulLhp(lf-MVgxAm%+L=jNtF{bgx34WS~Dx5 z;?FR{XzyHv5+-^tA$fB~IyXyy9zw-r(w*T-5)tsx5m7oVb~z&WJ^jayiw{iQ+sh<}Y&ii`d>iY{Ae{g#A8)PWi z=x$AWbsk!I{zlAn*}Rv;9?F9*ZO8hVl&t@-DsmOYv{e6vQ%cPVAxXm4^CfPsyXimf zN(ts|#Vo%D4fK8Ksi6Lp|(@@L^3cLiA?m^|y6}!*Ryk7W& zUOg(XaIP(b%i&o1C~ zzMP)p8ui|N&c8YO*WBzq&z|^!vmph=Plhg{bj{e|vngFci+WF^bpEh@lPCqVpsX(W zhi5`2(Mr0~M~lg*P^wjtrLvG)#gIi5WDx~f9?1y`*Sg86R#{7y<1|%QS6{@KGL>EIOWyi_#v~DjXH02g zL{56c{YeF8PA;BNg)aF12Yu!H`twi4m|iUTgM9&2JLvvk+Q^!oJRiDto z-H7%n=N});e|cEaL*~}sj#r&3WUVN9Z}RoOu}v0rCH#wJTom~(aK4) z0?fO#m0LT0b!-Oapiy}5tBs(FGja{!CDYxQ>Gy2!tIp0YV$@q)! zk=U)AFZjtlSRGYodie!aD=y4WjihbbZ)f!A?meW#Yn0|xcVDd6ur=jtiT!Zi^_J^7 zTc>}cuRM7~f4Gv+w$FDbdr6(EUn5@WozK`y`o#~f>g&&vb}unDx*ho=jH*RHK=vhj zVY6R@%{Bu8bk%r}Rmh%ub;}!o7}T4w1STk&Ni2bdQ}IVY{Jy3oP`(O%!qxx?NWn9k z>;C37{SgblMPi@mA!PGl(nUW4eyt--puGV}vEvke0;36rosU<>XweCY;-jN&uHZuP zXe-rt1D*SEfG$U&%aN(=a*)3HAwCLj4snPNfnwOauY#$|FYmpqUL(t{N>!JJK7}#W z1I^MTM9WCaaFbK_?uUf`(R+|NM8EO-kq(4S-5VOxdxZYv`&nBd2UIX91e@*~xVstI)rhdPEkQiSI>g;K#8aXUYlrn~-Fd1ac})a-o{bNEZQ ztWYa0&>?6CSD?)mTDmfRSk1ur0u)=lgB45Rvp`bzHF-F=9LiJd%uzGd zV}UY?$%;3Ld72|A{v-Xw=}K>|KTp)OSaZOpJc#j(#^Do>%Nqkt1EnUh z_uU_ieq78Jr@E)Kr8#t@dy}|h2i$RV$uDXY@IVqUWpHU2{qsnE|~6zLb{IDHsF3wxfQtVC~HX0p>>g zrtSXt#$(%WQQsfDQNck?YnH!0F&mGSY;oePFeWV+GNX z#XxlM6^|ykS4?>9emsg!8~K~b{V;!-KeNb?J3q*~2w40q=E0s0>0j9BN3SL5-(R`>dEldv z_lB&AR9(gF+7r%yxj=s4Ja3jEvx&H?Rq65{+9!drAuKry!>R{Cj6u@)NWCl=rOZ-j zU(MvX8fuzqqJ1$UvlN&UkewvatPh@nz@}~?k4QcD46;SPM<>6fH-q2??;^T;eDSxX zBVuPTA{AV+wA=r=AAENs6b&kmoJC{0FtvD@`|%}gE{{H#K9&+4_aCD4TNGpM^)Xcz#+vzWI8)&ff12nCh$JiQtufXl-yL zz?3zk&)GjhOtq%>+V@?B?jNjpXeE@SKAKBfllWc>Ia^q?y?gf_`Z#ib)VN~Hp;S8AP(Mx=>mi8@k%cW39@mfB zlRHeUiE!Iwwwsd-iY$$8)PEU-#rW`kaahnR8$T!dQ@!(V3yy?_j+>xAp*7r}U^VW1 zxayO-?pH!-FMPytsf&dXCXa z1Lw6a*ZJ#Bv)>v*$+Rm=$ecV%M`5<89#E69PG-cN(&+g)$ud(9VB-gSB;St>Abhv3 zxBBwYS9;r2J_yh%j^7cSZl97L)l7VDxKdvWwF}8pxCI>34iNJ z*xA+0eaZUKU%zq(v3-yBg-@Hkv>*n+sW|Jdeve}bKTc;K7uQ&c_-N}|b`4|MhB+?4 zSWHSCzbM}id-@sHGV`fOQ-D>1=R!zAJJDzo?N0nnze`M{A)olPBR-cXZ-H#c#ZOkm z+iGw~*=+sp;AgF+-!%5MaXaqQ?hJ|Uxci>DoVYSB&D^HaPrd`Za}%)cc@7i9Q$zhU|5wXq0tBxcwivu7k?TWTg@ z)^aoyV2CFVI`W7Ho6zIhUna9iCHD=|K!0#kpQC?9Yv>n=jlE2R-6`&>G}8Smy-P1Z zVtX*AXD}vOjr{sE9!Iyh2E4QC-!o*{sck(vU91P2ag z$eEEWf+YHamF8_*b=+hj(f787m`o9~+f5F>Z=Qc`TK@U4E*2I}^rW`)tENrN+Z|+S zTcQ43PV<)?I!oJRB#&XVQ!_ebQ&-AAdRbR{*R2!&8f~5X5gFREDXPO18+h_i$Tkcd z!!V6|_!ICsV>+=aL^EsVH4y#W#Tafiw&X$$tMvbMtXOT5QI;P1?yv?n0ba7 zio#?#7?n{A(>F7ql5A%-H%Bc0aNf~p)4wEv55~-VWe4>4Uhi&e2Dh)WZpOAK3yt2V z|2?1arPEA``^o~&Z@phHbL?!&SL=WCMW%?so6MB_+-*_#?Vu%v6IY(? z9m>L9ytmf%>8(E9SMD~MkI>;=$Y|FfMxTGYIb}!53eLYR=sOJ&>@EE-tU_JHe9N#3 z;mBnT*0{`NL2hytP?#lFLCV?~xRJZ|u8%O&CN6U6T9AD5OCMtie8P0t4M|oyg!zzK zh@_9K4)So3%_5%v__=+3M?BE~zGi#w;HINyX1Z(c(|h@lPMJ%Wy+Y$(C4q|=pH8bh zRVFOw^oNrT>b9D*p7Q17%3P4~V$anDilV#|Sf2zXPYX*-!pK};ay* z{a;8C5eTY%1WOC*C`o_`OxncKnJVcc@^sZFgRLxl$1lr2{4gfO-6LSu=q(FoG`p2> zq91u5I6tU&1Y34*UB!LGybNsDSNBFN*h$qD&kY>SUNY&wlgMgST6Pw?*B_>;pD9*} zREBDiQG!hL%vq|ND7q8tDQ%x206(oXq=9-o-_iz=bPD#)QshzXg{XfMbQntAoY|Nd zs#8*g9TC~o!8`UO?zY9=I8wi3Y?Z3r#)O7mPyB2L%PW|&|1729Cj&{pF2f3n5&hGW z$9f0e1gjN?e0HA3Wjv9%IA$IMR%?hndp$tYZh_7bZ)zu zoPKwzUW2TtHD>j5W8Wp$lc7|A_wm?Dh zeR4?Hu%Zw!Dl^~aO*%m+%p@FxGb*d5({3*tP;xpsb0O-)rbaCzs-@41y;#0gJu$L+ zZFp|c@cnO48unh$i~L0rnTvYY)^#w-mSPto!N=P`SpJNbvHkos+JJ&`>AZ}VMPR`) zM$2>M%V@!Wc^EBnDz7e9>;C30q$kPL6G=V2gnT?*KVVXdH+LuP^qTGs7?D^r2S&tT z<>js9eT@+rizG>!EUWrQf6pTK0K|T3Gthd-wGJamAs{q)|D4! zQ7o~DJPx+4Oy|JR_-tF$R$^()LSY^LTI;L7c5)yx@9kkrqc@)3xy3#eO3ZDGU+Bi> zJdi&v>9zd+JG}1X6`b~NbCB~ZC)`cxsVZqGE!h|4&ZH+Qr_E$^X7O)4SIk)Kxu=+M zxYAXlKGCD!jQu9*hf8FFQ+Pze1TGPV)W>ofv+*DPtI;dp+`Qg1^56wahbZMm;Y-bF&f{J5&??-*CUIX zN?;=q^$YU`b0>ijFktJjEx)f{d8u!RZQCC&thm@O_?|kn_pE)9reOm&_pBXap-H<4 zhpAZmbjxA=$tq6Q{IhY&$a##N-alymdd|1>o!J#T_kuov2TQreD-a(Y6(Ucl$W$%wiAE7c?cAB>z6Y9!exnH}{YKCVVA`DosOfdd~9{$==_ zL&GVddtO<)nD|F1qwVi99*QUnrBSwyXa79^j1IVUkczf@qEt3qWy3>e^` zs9cl_=y6cZB36Gq@9?u3*Y)E2gJy2uRscZt05j~_c6`;IwH8j=6-N^ek$`!O&mBvi zrW5y6PQO3duwJXBD=BMUhdh|XnYPzs3FvRU3-(7#Eg(d&Vm`>iSSo42jEgeLFvu@c zr3D0eit-2mgV+dSWokO;wQ8B$pIvzWoo}PZuS?2h&jzBrrW`!L>=#%l?jHwKeHM{a zsxnf`zSiB&CL{(1qAkBFyzMG2e_ zN)V1SRaUwS_bJ#i5g>7tm;jO^m=fEjW;Wdvrhi@gW3yVK9sZL3O1ro1Ffky6#5Fr_ zR_A^?E&ne4fez`>b1JDa_!&pfg7v2;J-L;%?MB--?9(#7$MNA?Ix%`_C+X3fv=-K= zZpnT6n%Wpxwx1RyGnk%POUl9!bOZv62;)MswooGB6=f}jh`W7iA_al#>kmQrhRfht z05@P8M@^?0wdl;jpHffo*Hf`t34jy_W@o+V@vHnki`=ywO#w_4u zB;B`+jw&E#G2%9`Pc>kw>`Et%NY>jkV!4ZrK}suWT!drz;bO!Bn;QO5Q*7Z_I)CE{ zW*G)b&~X?iAXpYlp+{yPAGxxw6=t8az{xuXF1!EEt-n1jHtFtm|N8Oy2gJ!((Rq*Wm=0#? z34Z)fF3$K!KX2)`VT_weK^T}$Q-Z{uHP!PJD4&dRlyY(GTT=0Xo_?mk{?ggOw=0tF zZ;(#(Zqa#q#~sIW-O2P8R;J`QW^c#n{JA(|Sbiqgu(EO_hJVwPKo1w^dHOdO2Rg?N zb})%RIwd6}QXllklTG>~{T?}V_X+)i407Lg|41h4YiM;ED8_SCZ_dLpo=~M3R$HJ* zkETcfYYfXz(dE*>T4FVX0rJ&jA(144otS~02=9eK93x$c$vrRcMt1Xv%H1cV=Nx@R z`q7(3K_v>K;U_q2*>(a)vVfHQ1fPEgBk^bJj3F2*=^v{9zp{08XnJz-p?JE??M`9N z@~2N9q92~!Cw5A8eG5}fjZoQ+Y-?P3IsXtJnk^a=4G1yvz!q=NsYS@jbxaxCR1!ES z$aaROIZUDhA}R`{6b|yy&h7R%l?UgAT}VjCA%j!iPbr^tymfX!JY$RWEm^<6cDZWC ztROA$>)WK`h&3(rr(c~L;C!j)k1Y>M9F(a4Nj?StCfUFLsWi7EYB;->gzVM-G@XP5 zx9Bg@@us?n;+$G+Dd$l-7uonB<`NYWhdB!9?eLk4>WIRt)oYkBg={ArSVLM1I9#;L zV3W%Nb9MN!ipeP_CxobKJYV2^d2P6u*wXM1;uCW89XA?1d3dHzo3)jz{@ChZ&hqR( z_Ft}+J_i%K@r{0X806fCJjXAg_$o?ipsA%cRE(`qV-CTWi&hI5MW2#xpf*&j3GC*d zc0-I%jlpT9WCKgEER@~wOV+a+Iz2a~Y0}c%4G6vxH`SZ7kxopE+$aC6&GR z`b|#TO-dd4ERaIUkNO7kF}xTS_L?8Bdr$5@9l> z*Ou|h>zB6{k)PX4Yu83}3v4XX)w(&)@HTaF(2v(v=v%vzAZ}9Af#uPJG9rpR>N!8+n~>|f zGtX8Zy*xLB#yonz+L>yLU!Y$<+hxsxXOGYkoyn>T<$t+X?uBm_NBlsNlfV5w>CZ_1Pai@Z)67Xu2Xs~N9+HJKGG}H`^ADoJdeQx<#XPn7khtg_DVq{(E5Dpq z@S){5wR4x=^Fqp#YALk)YYY3cOBZRXcKkxoybB{a|ME@Je>kUk6Mne>G-)aML7m6{ zz+S4NG}e-q_DHl|fek=>pXA+7AiDA^dM`x*3~Zt~L+q?@CyXQFD2LNw z7Ofi&Gm-h&?CjEXxQShR^Te5@n`dk-7ijM}Z1SdYuWQGb9h`ZfK}77L@tcdEgf`nc za^jUWHt{^^>hmK(fzDdIZGN}zFOayY+m@`E!s(<9+gBfd_2SMK^XQ~;7iV%l^ULYu zF3i9$ihNj2tegv0B}$p71^pY(7+Du@7#t)z5;QXrMF`#kSJkH{6X}uwpNdH=9kevG z(1m<2#Djedq6$bTQa~Iy2;@7&f1dQA6X^$*MYG9pV%KxNE~np!AsKkA{iv4ySvgWE zM!#0>@fDqQqW#_3n^$bouac^pR&1u1#7@2k`}joKM>DtxqZh|WVT#mQW%O5JkJ?eM z6S4A}75i^5zODbs$`${>KA?~A2{-i=p0A!qjd+f-Sj)(*D<+8!#agfhqCX30NJhyJ zi$*Q7Q4?LKR?%td3t~YRi}$qH1Oa)G5JQNn!c2++H>a#3FGaoSP#gh!)9{o)@hb>MLp~T79I)p1b+?Pu-%ZcWn6V=` z^7#5*`md28=LZCbkV@ZQ|25#AY0Ah+?Yo3TkvUy|aF3fA5%uPo3JW5lPLofLjvTRn z=HXt9es^y4OggB`jK~Xa$HR3{E+$8&SBSd3y%_z}Zm7HEHTZO?iu1LG=7A1du&0@ZE<17I6fqrhW{ThTCXNC#o#KVS%mO9QhMFBsVIrTeg#-$`=ht)! zM-=0u4g*#u|$~UX6I`y4ho~mt|yqe&yZztr$G1B_2aC`B4$Mv_44+>j; zn*^`bNc@_}s2}xxr{2_mTuZxd+|T(JuMRzNlkx*=Nbg>hu6|OkO52{yd_4NHUPSo~ zGX4EagsA*0eR+kA#PQ{LM$hT5oV}=T{ebhcM0iT&Bz=Q*gtW_}o@2ZgUZJ88R=CX- zU+O6(n%MxrbVi83FtA?+3}r1nL*o4rIJ9q<2Mvhf}yhy+S+VS^Q{LGAP^=ptyX ztYAmj0VSQRzlX#=Sx;I?9&SFF#xAimRHUH~5>xebbzu^I<$)jpkicZ~&Q^18N??`A zG{O(T;FfCc2SC~hN*$%K^0JoOq^S^EuFZvHCLYVnN6{56%#MWrh6WoPUVemE$t2I> zz0{JdvUnybQ%mKN$4iA)r`l4X)rm=|;!cT~T4ExqopXHts$yb}cq_@~s!`}lwdFVR zz9;iUeyZsdRr(n4RwUgnH?kpo?a?~x-@0`DKuCP9L z@wx3Jff*#Uq)!t z?7H>Q#fG9$)ym#d55k_rXp{?NA{$A4P9cE)iB;U`9vn-ztJa-jH{4-|=^gBbAoOLG zRxQYAQ7jU?9jcamy&&vGq*u9xET!^#?1Bj#w~!Rtqkp7(#}CeE*5L4H8n)!B?^Mna@aj$vW7plX9@MC$H+5@dO`iG_4R#;q*uMG1B)*tupGANfGV(?)>*jPi;@qlz#P8dxQveP~Lv_`GSA zuWEMrBv-=Iy$Q0%Tq?y-s?r1QBhjS$K&!cO#oVUWHv?Z^IB&hGZtSpw^rzdFl9(<{ zD`t|GwaCoPlr9?a-1K_mD8@XTuBJ~g=2T^p7U08S`Bgp3Ocuthk!ZmJ&OzBhv=E`$ zXOw|NqHi!eDL$_vC=)Y6cFV`KX>lnc1&yg>iH(7Zud;~8O+Lwm2 zE*QTMQyois(K?yER1t4{fZB;qWzHc*s5mO@K)^{GT_6k*7&hdD7@EYHY!Vk$PDe?3 z{p`mkMZW@+|20_Eu87L*=*lX z0xI&+Fbh?eZ0^0{{yU$Cj(C1d=kE6i2aB@4TZJ8r&tdkW^WDeM9KF8!m6#<05_VI~ z2Lh?AQQ4E?(L*^fKRpyEfG7f_AJ82V=&$?m9#b~Uwo*XS+0lv8_Z@S8qzVn&7_1m|vSGPSqUmuCH4t46v#&JmV zs$QRD!WV=nl}b;5k)RbNLcZ!BY!RCR!xXBAb~-bB9$cL;tr;24bM^)e3DsVu%WVOj z>r~}+L%KB_JKeO()Vp4=X}OTbZS2bV>T6)wa#5Wl=IW7#495JVAvB!J(qQ3Cm{*Ol zEGc#~y0wXZbnxYJWSj$^nVq=>=X?lMaD>f8&1wjuqb6FIWEwkdi^pEA8lJJa5361QueZi4+Cc$m~cbY>2FS4g5_${zk|ZzpMO$$~Ez~&FD5_ zCg&LS{*6)9DF0?7{$>}fjrjZ>;%{go5QKvJBq%S@ZN_~Pflw16vg$PulYFYrVkyYR zi~haAT9T)K4-VSkCzA2Y$p%*-SzN(SB!dO;YGf%6`|lP$qgmc);S*eefKr0A%ks1i zWD6n)#D>{mHt6V}9{oGd2nlM_zRTpW`(b+ViMK8Whn^YRKY~Vbyg`A8}4c&`M{C9hah9=Mg*)7NU+g zG(-#Vv|t5fYJmZgIOa^2<`Bu+iilV()KF@TttlLK5CUU6VNN@75H!ET29GY<`IL;B zr@vUVvq;}Wrjy2`=}P?+X}kyJ?(eQ7jr8|K9yzjPkGfgC5C5Bl+O{5Ayr;Ge^ofT= zF`^*}AN_VdMC)5`;YurX#foFId^1}pKSIT_XmQLC+y&T8(JST zC5o5{UJJ)rFg>=Z)Z;F#>_HuE4`8dl@OTmOXG^pAcmu6^IVt=qTr4~K?K7^S-Op9%Tp^oI|L zehn9CdMu^OCyt)Og`Si{omV?l231vhYf05aEb3!s{#^(lhb?(Q;j}_jLI3$uVOnCO ztsXl02p-!&6iN|AFOlHV};fqGXL&?!Oxci16ykV4gZ4&TOf+ ztTqjJ^6sID&4!QZIW5Riv&C}(yk@;x=78ocdQXkuoj!fc`McX|^w`=Yy~eODJGS(StuTJ zN>`~otXX-(n#JHE#<=ja0cA`glTJkoQe{g)P$oK4@_nnnB7#H~1ErV|aS>G_>P7Ir zS~<_3#PCo*{T8StC2TNW*%bi(rz!OufMQIqixcYr!v~LwSCZ*E>xYr46N>- z*He| zE4HssV~5qT|K9R>=LT4Vm)%~nVl*FcyWz1u`}*A4aIt~@B>RPVhioAu2Tgl9Mvd5} zpLnDDtNOj=jL*NhVD0aDocG$YV%f|wt*f8TUNmc_J7=Iu-+W=lKBg8Pffmg`fAu1gj{6}^KiMo z)mS{DxMCXn!hO1ZZvFOc8`SNvx?TO8PU0VJag9{055L;3P7ZKpD|cWH&I@Z@Pq^Av z7;&YN=^QNr7?wkz53(Dj8DZ8H@n@}=g3;-#%<=U;$?*`qLTJ!H3svDg}+;b z=3sH8iS+Ked}yc4Wz%-?4~ptcSjNf7^E2x7e2D}uWPI9R2Uo8y-jr2$Lj6U{hvvA}k^^?TX0MY!UJ&m>+CcOvNYZ=>q8nDqlqn zE#i8g8RKj&#x|eYX3RqXTKp^fFHdvBW_03$JOYx zs*j2*(`iZW75ufAiXMuVU~YYhPAr%wcpDEKM+@A?tAo0#z3nW4hJZp?e z;wUDOuK93s+j}SOwQWV#k!;;en(IH1!#X$ty(4kCe{z5085R_d>XKa3e(@;+h zjGh<)T1BuL;7zEHHexlPc|PZ)2$YP3AP#f&HmWD*A&Zpzr^8u4K9|KrGz z(URl9Xe`D!M1U+tae7PK=J^jMJs-DX-hDQ&*7n-&c)BukdnWx7_fOGVs3Oj>Dnv^eRcGiW z(Vy?D+b$)$;(}ze-s-JK?g!+Zw{Vz7^qZGy#QBi36?j6?w`dysj>lu%VR{R00(vWl z2$YuAMF?$@*2Pddsj9|>6s$3BiQ|O-CrrXLbie$o2=ffQtT5V6 z_Brz2*|RZfT6E#djhm(9WGqOSrc(3DMMGCTIKk^~ex0))&$<(jo~OiqF7zFGwQ9xZ zRX(ct8|)RTbS!ybUV(Gk#7SBkwQ`=5v{0!TRqFfv6xFZU*07^e^v0%ip+>>xvt#Uv zEMBm~vU*tDSa4uAA+cgR3F*7J8b!PUq4 z2)(c3BW94?)xDQ8TOriQfd>Oo3qTFnogo|+d=$JDC=RFRq{K3Ko!&KK^MehO-m3A+ z$7e3aM!6>hj~=mgYvZPu5y{qg<%bogd)n@yq5Sady^&^1!KB@Btf=#nZ1SpVRxMp< z;vT}Er?g+E0`#N*_4%45yO`R4cZ0_0I%uEI>FR$rwypM!nVsJ^u>7AEmcN&DA+w&3 zt6CB5SJ-Fq2;&nG5e6$+8uh8@lp;3FRGIeqZ+y}Dk&VeZ%;};IlEq(ie08wipej|W zb{r9UiSNq4M2X{=l@9JzG)(x<_COMu>KP!3R3P|Z53ht{Jp>{Wds{+3!webs)GXnW z#6vPX+^>vUXt@s-f-n8|5tXUnxt&fG0gOOI8QDoV_DFzwo`FS35~W2^wDncJD3+_% zDE4}2VEDn6d#}Xjk%W^ZXnIU&{D=DW9qYbo>TYfh3AC+?;J;q0*|ql?(x=PPO^mg^ z*p<2TGiOKOte4k5XCGckZr^kaivLJS8@&Zw=3aEgl8Psk_}#v zs@OcnxeZ`_JZA-oa~oQ%xi;HkZn$O4pHSIjqeiU_Uk*Zq%<*EA~1_Un3JN!dR zfW=f>o+S{$7Cheb9O+2Hd!Ti!XUEX_OZ3-T4j-DQ@6d1boQ-oFjuvuNfADvskz-GI z&lAW-Ke@{HgA>ib%*%T+(KsOdKP&FbNE0*n)J$dOhxp9gzg|jM6~EIHJmuUlBPg3P zAw44xu)~B=)95iD9`?l4DSXEt8wS1JV0gKZJt33Fg)(YM(=UB}?RNApY;dnx`=iZl z@Ss_*#8_zJZqai@TR&5APP?@SGFr84*;@ZYzpR=_?H?wOoX6Se1B2$i$l000orFyg zt9-;nvC7>wM>%0fJ*z9Xq_Mg(&0<^_FabFOnfb-3n--r5!{hwh-C}Z>n`o{tE#{R| z!+{nRMoo`AV*l);G0FPz-(S2rJWTZ1Po2B;4bfx&P0;e~?#HehTwY3blHqzNj6@X=8ctVZJ~S?@$N zljl{Knt#^>qJ~{YB>-e)`6M&cRvj3+ci#)QB8>v&shpXo?d-qoenRKY;e5ku2du@P z{70qo%HU^b!;*yRt;kJ@xl7NWk%IOcIShp_7{m4lib*MjUv_fyO!VcK>$ga#U1?s@ zX*4V?J9;kcecNe14!b$KF$R3kK-r|T1Ohk;GxdK)(@lZ;hnuS$=u^Ti_J z_%;NfYY4|@u?3|Y?Sq~fmljsuRna@GZgpDn z=Gi&TC~XeidJ0Uk-&7fKkE~TdCL%NdXUWV8a`XO#c!~S>O&<$X)2FsN0exRzE~106es!l)Ft9DM+BOPBN5M|6bU&I z(8XAvaPRNP^+`#th9pL5d65H#pIx*r=oejebgl9o%Dou4a6t8q$uXVc)VtH44?zJI z8)})fiIQHNFo~-U^DFEwQWWA0&_@5)EV}>>ARSauG>To}Q5oob43u7+)9z_)NTI(y z)h~Y9{V)CDIkiOplvL9{1p+8}ppPWal$?_5+E8&tV?LN+W}{Gr*;pd0&Kj|fYydO& zH7Zg9%9d5kJkooKYVZGAWgyA$QEgif9NDVPkbyj{d{VYajZaL;`TLpSgPOG&)~`iE z<*cOg=)=KExV!Qz`j?2V88TpHCo>p3oQRAiwsh(C!_?5Tp?_I$rC1)!K-{16D6xz#liA__HpJ)#y&MBIiUi8QCksyoo&Z8p2Fhh+8-2ppXpR)JU<+a1V% zT(1V@*5hOjjoLFezJ)@IPw_h?Z>SICYCFZO%S;+3>{(d3s&9sx1kb`skE#&M&auc` zE^-QTj`*jq`}%JZPQLs2JybW`A%XfMBDyk)ckAoihf7vtm2txTze^27;iR$si+79f zd=bUwe`mL*w3#!fIi)RN4Xg3HbeX9!M(L0zfnXn?f51AuY0Mwx!MFQ}gUvtxT`$*K1a9MQM{-wP4AbWXZ=`;+1B|z?W8HP?Iu4 z+GH?-9LZQz=#&sSq>TUZWpX9W z*hTFyOdQkY0J5+Y_sSUG%I$>UBY?-mLeHT5Izl9oBp4#aF3 zGJMI;&B79ug&x%J9!!0ldb>o43Ozz%_NPB~_q5N=Te$TsYZ^Xl$$}m4^5P)<*Q?cc z7q3 z$B)yM<%GtvNF*dA;P8;nBBO(oi2Y880PT(W!DfnZMiC9Vf*_Qk4W^gH8s{B~>GrsL zCH?(Jtsb?yd82%nM_nyU9o%c@L)x(1xvk`}PXEzAbLh*-^aRrQXYz+0(xBd;rO|Ax zm;p+m_+wPErl4+9Nlh!8fuwDXaY}~7*nYC+2p4`CKnxqnci-FzRt$_tlE^Tk>qUI8 zO>Kl4o+BQiU`~odA4L&~SUIXX%}I3rnnOvZpikDGY{1k`of7qkv@3hkf@2Fv_}(42 zheZb0)*oF-)ysbjneV;l-G0!g^U+xK2=q>j&?4m7hG4HG{}&1+gvs@z7|K|MNDr%k z{Gm^dUQ;t9x$-X>5b>r@l2~j~@;9q_{uixCcbP7>D6;_ta_GzcHqp^YHv?n za%DW@o%L*W|MatC-5cnXkv+$8eB(j!t&Vifq@mBNL1U3 z^=oVOYmJsW8Ie5>Jrgv9u#Z_HlY*4kMKV%%f7AYc7uP);eP3Mko!*q(Vs63C)j@Sn z9aAcDPStSo5A|f*0lCsk?Vz;B2LEVqR05Uzm_02dQWT5U51xX1LpaUsJ7%-R>tzkBfrr8Umhp^cr-I3o`0QzLdfU52xA z{@8G`BrY@~&po+z-4Sycd-ue=cjDRG08d1zPK|*9^Bua7mM~)Xyry@Uz6cssCo0jMhExrXT(Vi&E-tkRdq5@bLq(~e>CeBV0Z481da+5+Q&`=1az?4Kt>j`gC!D)(v3wg&lJ?c9%Jm&_EYuW;zADQlL+@MoCLaE4|w=xzts9k16%LgJ36yft}`yR4+&mDDrqG2 z48|U&50sffaW;$P|NU$hBQt0iSY!qzT?O_3zn;yqFJi^fJulkdxqm`sA$iM&E*FWv zB{<;o+IvNZc-JZ!I1X-Z@dIpeppr4zg$?ERZN&hUEY}h}s01hi?n+__k4740x?ZUZ zjr5!yHpgWbNZT%uws@F?hk`=;ZM#6);swP{CW`Ej8u1h*_Q0mL0ENd zf4zMKC+e?lTV5tjNNbhr#Xq%e`L%vdKfyXJ>hzo0qQ9hnw5aXOh0IEZV7aUAf+l;E7lP4DO+~U8hHo}P$NCv#TTpZ{K zwx{HGc3mw3W8FmyH5hA;J{#o+Qq0EUi*h+%-Nm=!3B?XC`}Qs$1{0$Jn>5s58dQ&ukK4Zdhq|ldmEJj~(hdfLlnyjpvu~uhRRpf1Q%^WXtNl zi{jEk>#gm4;F(c1TGg)^6PlGWiI7zv)~T?(=WFMyVZMD!{^nmn7sN>>!9Jb8e%f=Bbw; z`MUaY_B-a0h|{oxeY)lSHly*yxN@(^s7Vy|L$;Eylr596D!zCdc+=l{!s?eEA}u_b zSJN;V5dPr`om_Cya!c*jb@HAl9`|7EZZn%bW@g2v0X!}Dqf>TTp40%x|7`&oG7jh8 zy_|BtM@IcMoen)Sx=NddNfm4j2tOM^C=p+60KD@vf0Nfmg^m5Y0kz>!^l+A*VH9m5F0qqSV^vx==fyK2rljw3 zgF?4G*>d1mARC8hV|2TA{qdDWQ%LH9x#Ym-Mf&+YoPGXYI$bApp{Aa!j^)jOXi~*@ zi+O4b@SOpowjkEy31oSJF+@MOEypX2OiZEg$zeiXs5$VXtk8=f>JA}0)K0@MWP84e z7AFIxAY8_#g=-~GA50n%W8apyY~na;;KTtFLtdG^^vbZ1Sp9YVuO9bFzay6@8{R$J zYE3z~{q}AW&}ZWa{o&lfd9ifK)E6jS`}eAc`juF{23?o>$DsvlO*|WtZ-^PLfaJ@= z$A$cVq1~ru0wKN769^>q-h1!8Lx2FG6FSn1AX0)fL8`!JL=;6) zKtO6xLBTExFC`#KQOTbC_c^n(nNj?|_xu0rg2~S8ZgR?Vo^n6U9aUhon)I0o+SYGO zj8)$W%*zDHhyr^6E07V6%?O8fz!PhY2EVjr$C~3!{JaystKbv!a4&n@y|DX_*JC>s zcJh{_;r(BSOr9S94hh&lYbu>Qn>G1yYb2{mK8q(!o{>8&v{8esl~K}sPCs3Wf3^n6 zbzv6|P!oh*tZ73gk`WcW^eMza5XSM%;e?-zn`GP=nULxiC*lj@;8-c4caWG3Vop<| z1#*F@fwA(V%4do8SDeN2OJ^<&*eC5Umc?|As?QA#kfcjuo#EPiISPY ztD*X7Zvd+cGQ0uY13BD)M9fB-6|zNi=(J~w>^6HQ_BJB}^lL)_No%-0vlaArRAZ1GLbuFZ%POAEVxoKpGYlROSGD-EZYq1f$2rMVap5$QFVwkyIfSWg0be{b{fAl;+HgB4i`9naB#oB18xx`cnq7< zqy@gP7aA`z!z>9r1ro?3 z%0=;QhC+gFcG`X`u_Sou7sGsm*(Z-(-(P2)#z!}PexkP{arW!w>`SH9vwM?}+0Kx_ z@gpTfK~BCf57B(`&#otH*k$%mIY+#|f0j+xyOLdxDP22r>|(T6;64!>8XrNUFKu~A zC0afWT&JP#`3oPLP6t9{>Nh6CL`SDpLPcRB^aW6~SMaQ3rUtc`8!LvCJ|~O-L*OD9 z7kWnNNq&4SP%DV&D?r|+S)-p0Ec%Hd*Y7kIVXW)bu}_Ph((k&Gkhuo~1IA}bO=*_v zGeRDnyu|2q7rHjNyjTRK%X3C(S%2HWc{gCj4oiQP7<4wF9O#oX?X*WzFk4-!jH>kF z3>$M<`H9udF0>^UVx^?8v^cImve;(x7T&!V(fU~%FI(7$Lk`V+dY!$RC^y7W&5NS) zlP_5f@@a##l~yUr)rKEb@SY^LLCM9qeNhobPni*Vf<9)G=+K3xAYxr7Hd@b4(IsBw zPM|Fv_y~!Ac7u+-@yx|~)_+!?HvmH@=&ipxunlAcm)QyMQf$ZH=lPuj4f&nkZb}jK zppQidGWcd2*`DMp+)OAh$Aer9!kR}zl-zPEFwlT!|K*vk$#vOHS8xzJ^Vsz*yv0So zb<=i!Tox8@D^qAy6HsjGTr{Pg=Zyh#!>_gfE5izCjY##M=)Kc;esfms=ne1CS(Y2iam+W-2Ya1OP{-M*53E=t>ydi3gg^X9XS|CxT^GhpScn*LOyz+5>ILPE3v8M>E zwv6^B>~ynN1hHV63q)^6FY4&Pm6@Cf+r}Xvh*X+Mr_9>!=QnfA@YjQ%c(43p`44{t z1T)v*J~lsg{g>*Wv0~fr^1NZQJ`N~-CGqV9spZsB{h;rS8%U?e^DIg1rR_Ov+N-j=2Y6F@&s!amb)OdITR#B05BRBsF4T2Lb* zKI|aLbYQW?u4ih|J%%fH$4jgT;cG<%`@p52_^ZL_$0i#rY7<{EIsQEd8_#;Bt^zO^QzTaKz8rUf!{kk4KYG=h?6H9JPJ%>pZ%iQ^+PnXmkek z2k}a%!CV*AmPHIkUkOvbnNI3xKf}!gqf&+8fPA4s@<7l`o`(}h*ORTJjH_*z6SGqr zhF6Oj+qen)l2H0C{o{GpP4lVktc{G$m4T;9mTtwTtajx-Jk0TkY#FSEYxM__nTDiG zT)7_;{({I<)euCqWQu4qA!86=ZvcEWisVLwaNIlO zOuI75^)xH*z^z{++dOR(G=NwyLA?Ief!3=i)8D@#pR$ZO^Q`6R9*hP?t8FkwBV;e< ztEOQH^;oA#(^1t=i^={$%!gPE-m%pEpT=A#2d+Q6LH6Bv>iYAOBKK+t`HMfxN5Ebe zBM7u~weYyf|HUALsNg7p(FhZR;OTq_#-w~}Jfji2V>gcI>o+D`ultvuVN}mUTtAS0 zd}P$J1Ut1EFEzaYcrEsd%S}Co%CuDaf}m}gt_XnqjrPy~pcjCtaFq%LAfOvUFVHym zemZG@>&Id!g=e0+zW)8U2hC`pAEiH`Je=0eymY9d8qpfw%sFS-w6b}Q`F<{e7^ueqD zf8#y!;<3JPn4FT^7vDj&%UNM@Y90iQvy0`^Pmw4?!D-eYV^ptD?k>(ncyWZ9hA?b( z0>AvkFOB$R0KXLQ3rYu#H-ciomW&#l8Z3U38e4`N;n)Z6azJ(hs-L>mfDDW1jDWH# zym2RKY@3z4_EIgTB$5YS()?LVoe59MlGgWDelgA4+WZ4{fA@FH@R2`wl_>l332l$Lb^-QA^k=vrtCHgg&IVMyLHIRcdxt<60 z4tOri7C1)r^dcY)p0==Z>P=Qe-W>@-obYDK!-Ltm|K1!{A$5p%ifac>;P{_NmnIcq zga2P!#6nXCOOZcE?XUox$iZreb|T%HIzMD4y;ran{rGu63cJ4mK#>J%V0fxx7nR@; zgK5YOMY<=r2*4!X@)L!}H0g?f1Nwb`_KdyE?vecAJ$!uEvn}L~%XKa=E9X(qFBcx5 zv92FzcEeAmthktks$|lSeeBgKk9~Q(;g&h=XSVgV$+kf~CT$C&{=?zg zVE4a##!%4oo@719Tr;gWWt;NNXJ_)b|ll6I!{xRCRd-5TpJP*%1gmc^Fa5e;kjv z9DxXwsECTVQ+we9`GF<5G^$r%1Qv`_wh;sd%QfWHiDvaewc;^QSR6?T*RYioct>&e zQ{s=2Eo%qu^!6#}GLR~FE?h``JTTkar+KH}j(p+pZaV~(0*G9p<-TnlBd2#;yGtS$ z+3!SZ)v#t`=@6M$t3C=^g2y5LU0Q-wFh@e`)AcCuFOGzkhOwG?g=kwTO)grBUxHKd z68lgdB33mNQH~*DqMR#E1<$v0N2&y~zmj>SXq3M*ZUhAMPV_(cQa0 zNiyBdp0LNTEe=4sPQaMMEb|Tat3E<;j`bU1zv?%h)#1loKObfR8x-ueU)5DXpaSD0 z|3@R1>p5;C7E>#p-=?rl4m-gvle71Tedokhg{_98>1P`2{0B-$y~Wz{|Fk}N&bpJm z{J-m0*EQ_01HD&{AzQ4RWtSRhuwaw9OGclHz71+*vZ!(unR@tPWN{>DIVLg{Kh)!q z;MV;kv-zXrk(VO@k1mgd{OW~EzQaJ=l0#42H-N)xfP)uTIxGd)1CXAPY$A0vK9bkK zKI|7C6)$Rvg4#jzB7zE;lv>48o@ycJU-YTV;NCmwh|+IZi>9)Y`{hjM*T`EK)S>${ z->^5{jd`u>aBo}tCarS<3;q6lH^hkzlVXo^p zenmpxX?ns{5AM-={1kFtG#7u>&oWY@K+_p9c?L~?RYx|FOTgm|b3ug>hd;O8w1WFI zwsyu3)owM%_Ww(xd!M*tdpa9S>YzVU)$ki;Lx!7-bN*!T)aQ z=&Pa|H{u+WfRkn$900Qce&#wox4~id>QJ)W^8E*S?8e~g7q)hCB=*jU2^_%JOq$H< z+`33UmAuv;>O?MSE2rd%mFsCRyY<0{_0ey1u`5PqI<6jF-`uXn%hRrf!;T0|;iII7 z$OokIvBK$W^y|Ck6dof|*1?R?MGjNWi1V=NjKHODJo%R+5b;?L;=5r<8`(Itu) zmDqN!D0yqC*WPGo>3!K7yV>76+nWm*?_&H=`+JiKhf}@ld(#Q(ac`W=81Gd6d=+x_ z4zKdwiswcI70Lr&U#>H8OK#bNHf&Uz2ge??C+piiAaAqQD9TcooaB_K)4w_M;Qu;U z=f7nhNXxN@Bl8{{lXBbwf}oSMMfSqV*w9U&WFz$7?;&pdN;9uSh7`zz&jD^E=@xr) zQ(+!EB%&RP7D>}S<`TUw8=!PVURWHkj~bR)s=a0{911w~cufjid2N2+xgLX5|Es1` zEtGpb=ur4nbhXU`u0wEV7&O#mUeGJQis4BGK2`)7XtkXXS>Op`wjwc-7dJp4H)^r$yc zUQVboKPCB=OZJw07Dr?*NR0ckw%h@6IG0(aI7%N~X;33^$FCD4B))YeyCbi^TPL%^ zVIt3Ro#Z-h)jqkGWo>=q>^d7E4nhg3-hfG1qJUb@Tm_ z!D#z~QBVsKv*lfQrC}z18fF5`Ovg-29Ja(x_tkL)_#O-;hd9h&^rb-OHTzOLFatm3 zy2eX8UUOdd_GLxqSzI2w5>KQ0*8QqauD@@aHuNVVpV+?liZuBY(z$jJ+OKolp0cLh zD~~X44Kc}9sb-%csy>)|Nz90ezNe=80{UbG9h4v@Hh~7AP=XN(GNUIr{GNFLE^+Ja z0xnrqGLvJ4?pd^LO}~Kb)u#fTpkyYlpTsUeKM*~x_-xw$8(N~zLLWG4IR8J7^}n0TN06X9E51haCkvhs>xb4kz|g-Y4bG^kcn671SF_Q4>3iAfrzcJptKt5 zC~-BLyNyNO8E?6Z?A0L9%cLZF*0Y2^zU-e)$RQRfSloYr6 z{=r5~8lp#U4$%zi5ESkxnU-pkL~soxt{INR+_;|)yPS~-KF>W3DORiOICj73=j;Y> zpLQMEDn7*PlY74Hn*5$|zRzr~K9UtIhrCy5UGMED*!l+T5Y1hKP%N~?pEVb~niCLP zBDwS0;xtXcw2Ok<>B@ob^*gdP?oizEI0;1)Aj;kICsc^jHM;T}s#S>{M zuB&setkL|(ei}kpv7d23MR=r_719jOAl}>9tucsVf~ZOrM=vmzzG(l(_4erzpT5z! zQB3s;vtx77UTywM=tFyXWAw%{52BGFe&8-zyngOkc zo1j-ukO&%j@x4NQ5s;w4WO1VNgu%Y$EX|lO4L7_A%kk8L=3ye#>WP@ab8gh8$Y~9) zsSt6+mJ3|OJ!+l#>8>GRNqw@TLk7?pnP2ss=^wHKO8O$AytDBQZU*gVS05>`gVt>x zN-nuRVILFPr~P6d@F-~T);^f^-{WNL?pX^RTbC6k-AcD6%}YRn^*9+>d&N80m_TaI ziwwt;Q??1Yd|{l7E){2x_01nN;Bom<)6EZrDHV>qaW*cq*|X&n8L{apF)-PsEkMK6ka5JMv6w|~R2 zG&gCN-`=-9ajMb3mD>P9Z;x_@@rsy-V?z-8e4@b3GINvjp2ACrs znCKj!MfAdQ&?T1frLFRzGVI}{(c6+%-gy6V*uiIq6iI2_c*v5_L(dN>imgM_{&T|) z!58T&cqY^CZT8CYU#DdG`SbD>T6CA>`BP=(`SVH@T6dJB*)!0%f>@dq-?BzyuJJ%A z!$mCJ3nY~Z`V%Dz^>d?73KEXj46=#pgFI5mcn+eq*>PpWGdmkEbqnCqFi&fAPSkJj z^j;Z1@4daMJ*RMjT%$(kiS`_HZ$>4H+U-XK<$&fpo%#tqDI2YpS_-vv>mvYKbc@lI~a|#QC47hG}tfDA6mq&%fYpI;yYFLk$TOx+27{ zrG)CyYeYO1><@u9JP--B>%iTN)5NU*cHG^L&y+a5>aCm4C8yAv>~_YPqgVa>+2a!| z=GfloJsE`=q!gRb`1*icU!P{}!R0 zBM@}jlvh8iLw<^96@2_>&L-jQpQf;bzb?5l)hY+PJ^pFYGpRixRY@zP>iu>9HN=Bn z{*jyCXI-CfhM6LC$%NdMTVG!`iu zi-a5nJ|SUPtDOSC6C2>-M0p+a`lwz3LM}ipHTX8rfzwz;OpSDiI?91O@EU8xbyQu{ zONf&dxQ7Ug=4h|3v*xU9N}^64Dxlx?>~^IanHJ5~DT;5aq*^`Z+JEp}{Q0;~ehk^( zjthzLg-;auhqwDrL?!y~$o{HTN2f&)O^+W0A7=0w!fN4=Ll-y*4Rrz5$rt{f?i#@e ziLcX$2YKRh!vqfMD2M8=)%ZZPhQWFP15g9R8@~=*cQHs`;Ht)v>8$3z85tE?3Pxt|Bl3|2nn#9e z;}}`GlwzY>2d8~lrPI3Sw8xJ(e`0U_nxRxC;p`6oFEr&-#NK5LxC!8C>k6!!9h&`2 zZQaCx^mQ}U{xtD@lS1W*u;A zTjQP_^m}2u@r@!`zmk4G-n^aBx2o8$O$VzKzW;zs5*v1kPKHtA-ZpLPTua5qVSb_5 zxgprO(#TzzruxOiavlfdMz7i`%olwdP4hEtmT&^|&5F>>7Oq+ez|)B1co(Qq+S>?N zG+3$FHEzN{GlIjC|KzNZ-zFx7F!#a`a1E9krg;j3uQB z34SVnVPi6c!~Ccs3e54%&L~ zUH7a9rvmIgZC*RP8{3_Q(>hKn!{igpF36#l%^IQ(_XRzSU9i;GgKfHA`~k zAw**aeaSV^O%Zh~FSSbku7f&BNVUjbt_1-xvsD5u@KxHRmey7Y^|DN>q|<^}CH>}q zxk^qHo`jnkogsY8Nr<2x*qT@;P#|9?U$L0~SSQ3lnAXWiHwc~-bVDPeO0{JlwgODk ziLN^e0(y1(w$RAJQZ{PKOW*`lA!lxADM3Jcw+xY34`@*-1HWum!TK zUsqoq9JHwS#Fwnf>3!8E>OoQ{N@7C1TZzvGt6XsUR)za<+m;Neu%(W4U%KeV6`9h`d_HYi|00E81b zif(LpfJIL*DD8d;V$p$?8aT1DLXft)hXX6cRDxePxq>Kegbpob`HFKC0=?0}xZr%} zL5m50UvBtjvD)EKa;k@u1wV&}oM7L@J-l?s=5ysu6lnYXTGA`QL9=^~m?ta8x2KI* z;U9Wydo*dkuYj-%uiQCF$68lUvK=KPZ^h<5&GNP!QbrAIw5oFcnAxjHhh__HdnNlu zIhYla&|r?=4?gs8?JhclF-g{`t%%KWU3h~6xAWTsan2Q z4$t!9Nnae%F$OCkEitxa74<^aqR5Lo!c5|NJ*P|p3r?|yg*s>lQQfXa(*Y#?15bEa zsf{=4(LG3JT)>XyU9IQpVO1Po?cEbvruZq}{YKKN?|$$31?B69BrSb6 zpi~JJes9aksIDIj?5d1qj2fZU_(g1%pXeSG0xJ6lz~S-#7-W@N%3T2v=$zWA6xZf) z$qy@;C>L%9RNY+--vgr~`JXuKiq&CHmXb1(n}uxp{S^_D75dumYtH`YBaz*o4P*gc zLw~tAggo*ZL1VWNWfj7(iq<)Rp)Z#e5_zL6LV`&mnZJ&HV`D#%nH#tr2iQ^RhYsq2 zh?}NC99q%lB$RJ`M@@0_x?X~QAi}DElh}|~3L*~AB!~>*1v6|Q({x&1u1dPMK0LW< zWN`0#uAd&iOUajH?sFc1ijkoByW9k;%_F!`FVQm+lfGaALiMFqiN7dD z13kb14vLZ3Lr|8(mTVJ4$s~Je;_)e$Yt%@I2x*U zL1ajErm{~O-K;x^4C+qSqN*6GKrE80%Wp&fPC!>Xt(u%CnNOT#op_Se~n!x3-n z2(u*=e~~@YDvu32>=-l6W*Z%TSZjm-uFd=9I=WfqrTN~`wa1SilbPPYo6e_R^G2ujdV7$outJJg$Q%B_TaKX7yqK1RQ?0|u&JdjcCJ>t_I&4RiSvbP zGxyG!N;K#U0amQGbNoDd6{x=cLQ#SOWT;HUPpLsPt8rnxN-J-c<_L18aZA`)x4>C9 zRa21is~9$^YLK%=fwM+xenZ1UkWzH@?m8(>GsENmTbydba^k%TT@ zqN-wY3i;>0Y1<}ejo;GJKd#Juwdab2InF%?LlfhcPdOB}HziS)Gc!752glqhBTG`# z+RX?MMEvSE?P?`=7t^Gw2_?JLHjFLqTE8C| zn%#%<%K^nd+bY?D!9yxo7O7S(h8e&?dG{^}MxviD6Z147);bQV6}wn{*@A6y*ydh)94$Ipen0NL(4 zKkQJ^OovoAjOB;thYOJVPk`L*_Q}@gCp3_|RaY~}Ju6pMZcm>+dp1@`Al-;lkB6qe zObyp6As`p5oNEwvJXK8mc4xU%ZLRVX4Xac>2$d3? zDcUL-NHiU#Z8VZJAmjQXafJN$BS6UKA1y)1bL!|01`tM z1sOOo@Nttyg~*R&fSYy!5Zh9a3I{IA(cy49{YlfA2U^+7S0a6X`}vvQ(~v(_osWgH zed4IyY&jWGYA>N{(B3wNbO8$d>=q%hHtDCc?8gSH_sY;0h@~m&Llpt_ec{;kjTDFA z-^XrrWWH$ZyZ{tWv@n#2;$u%NY`W<+2Pw00D<^i0%6&zqeAG3dalNP1gY379dg~rt7Rn6Qo@^;7%Y%qt{@)i=UrTPj*{f(T^R9ob#oQI!>$rb&p*k#Z%*2W4#(^FPufp%_D|VQniDo?|3shw zr0ACXdht(+3(e07pg4+u zw}#?-=-L2}rx(f}1Nb$xBbSA756m^7$z^D-8H_3W^!q*wS|G!;eNP;q4|YSp~r8uZHXd zfzSlX91dQYYN>5$j#$k8mf03({ZuaXyF*dX>{g*wf@S7=mlXYX))%Q}^@H-88Xlr6 zL~CAv0@wVGhUakw&hFxzcMr<%Yj_UxK0PSEX2}x_7n%Y(Mxp6_NU$dJ%hY~VeJXa#|nt$(vfXv!9H_(HL1fdHm=i2!CEy51g zC21B^=1*a>lw4a9tR2)O$E>!KR-_)WSrBDae429y&Kf+P8vk$5=pNsSWV7VS$_;$$ zSM6Jtmy3Vr-;xIX?OU7$if=&@YM#+S0#lgs0?(*PJrEd;zKXiM;~{7!|ERy&KME!N zf9D+KQ9K^!sAOfgdzLsyzlU=)wh(~=tbJp*b5v1W%Mq&^m2)7RP;4h6qvLD zz)TRKuX%pKro!ElUO(7kP4y@&)gkKQgOE&aEtri4^9tt_#G_Q@%`SMMCe%z50G$+< zkqHnkx8E}tfpn7X_O<=T51+T6l&L-5i$T?#b9~kR~1Ve-(@fiV{hRDgZ39iG7I!fG+D+*0xhT)j5)TQJ2c7un# z!MpOx*F$pOd@UcjhDyT6v`<&`<*mG+cFT@AO=^Vr%$w75Y6hh_E~eZd;}*&CH>VoZ zO?*h^XU(F#Kkrl;KfmXQf#X|pNysxlzPAP8Y^SS|5BI3P00r^rUVo3YCkZwY5^qnJ zSK5ec^z~;hy1DKxxzL+;rXU0OUkC=EbV1313^ew-&==FA$p8j2xHYli?q4iTWJw4W zA>U-)*Mj&-P5xUevs0pjMmQ>hN+Pz_!dvC=(`w2)_Bc}juNi*7Dru3AkXyW}lmU(c z;TiBNF%AfY5FivNCdFL{$tm1B7RS4AwA`@wK~`{ScBv@jVe?pj|AkWykI@=)uzvC? z=Gx1ivkTVutt5QT__5Pu7jNvqSA>0!<{doWtBt!ljA!g(xcb@%4iEU9)i@5^S6y6O{07Uj@p>xBmK)%1HrmlT&%&P{V0j`>E!pxwd#=>s&#@PI z$_)N_T2Xs02Z`tLEKg(=C0ib8&!wLDiD+FQZ@jxisAZ5wY$hYgR8Px89(-eU97YZF z5yc|{Q`N13KobohoJzD7%1~Y4^XDy)y=ffWmlNJOF(BY0Fy=U%lZ#j$WEE;-Hd!jBZPSM-h*5{g z)Bqo0WTQU1As!tG<)S`1h8v&_m%vSD9xobH%NN93v&pV7t+1FBceZ+2McyD(PNPR3$KQba ztA2#L{Xux*Kp&Zg)A3DzUvV8xP>oq#WRofMY zQH};3AnG5Zba%!6_bjCskJ8&mj1o=4QjvtDE=Tr}@t`>WK3-u}|8u;-vsxjUXL3B9 z(x$)2KZ{2G*>^nu3}OAETXdo8y3iH!lttoP=yX0((0L^2d?eIfOKck z_3D2!$k9mtq74(+!MwsYY$Q(yqf^MqQ$8wO8(1%e>Moi9f% zLlM<=9TgZVSZY~bRwHZI;hGWr0kzzkQ7po?Vs(->6{QkPol7siE4l`Oj!?1uHz1;q z2W}ar0{L(B9KbnN!SF6JW>O1K1>czX#!J&fajJ~SEnXp-gTqu{!&NhrdAk;&O2M}P zC$%G-7p};_)9NT$3hYB^_1Vt-ufKffU&%LHqNe6^^K(1h&87t zuYTJu6I*@uNpwOW+s5w8ukzahTXb9Oeh zZT3qN-FtfF^izE#`Qt6sQfFOV=S#`T-Q$MtoZEe)WPQr@kdx3inhQP*{e$Z#sCmtw z9|a$_3qA~JmOrN_1Rvhawp+*I^MRI*qB|TXNRLU!Z%lkyPmbX{*PwOrbUKi%G1$O| zhZG`F44jvzwTg5@@;lp?AnizC``)Evu0OrLKj&t>=f6VkoqGPAe5<5tQ#WKfeuc3H z0^{c$>-aE)uAuL@o&vxfXhzl#m<6%_#$iYt>4&U?|BcHwj3>b`o+c0CsWah=sboF! z{#K3o3Q3UCl#?f2tvzXwkZhk|MR^UWWXq4*%AsB~*X+h&MQb9jCfV|*d!+&WfHNP3 z^yq`nM_4+jilHX2Ns%+f{^+Z!Dgh!o0L3mbXqZAq(&WvT0A7b{sjEClIl&IvOUOjj zg`I}9wkdvlYj3U5Z`=&7vUQwYd0XmNpNF?roUD4S$}55qrSr9K1l@zmRCOJG_iy_> zy-YsEXkUWvRt>WV!)RrZL8ys5p$F;fZBpU%6Q%}+iqQs|`>MeS=+-Wg*Q}2Z2r^0{ zrvt`Fm!>^vI;qUIn9Z9)GVa%qrJmKdRi8MZkc_e~TM_>CP9%M*4YJ~iFMAM*v`>sM z93$lQm4e{`4lq=g6GpPmUG+f;TG0^!Re>zWu}9}OgJ9s*JKV{?SVBkwSd!sbvJHoL z4X&XpXLv!|gNh3j%s2mR+}`!$(~J&_Mbo3+e!N+9V5P53+^by*HQGIU!YIGra7BWmYL{!M0?wO zC1vu6MW-?yWG9I`)FSHhH%OC-We=0MjR=Fdd$&`^C8S2@R+AP>Qj4>lrJ+h(qekQA zO3LZWScl@r;L!7dZAXFr*ScexxnC{%MW}$jJ8GOp;BknliMt%fV`}2E<9KRa9M6-F zOXaUuAxG=*!?j-U*9qjGoR({6Hg`|sRHLf`?q-qx0^%_E1UORz6>H@*bxS-$6!c3W zuX^Qx7mON014td$J7>>ElxAm&?Bic+;qSj-f{RXYtpt_tq;Ph;X@TpUYCel zAGVUc#Vi2LTdhXjOiYQsvua&H;BRW9Nele~CX78I?7J3ZKFOqg%HP_&<5^`jY4xBn zi>yR5@raYlx^o=26de0o&Y6K%b}T-P=f{CeP7yNjH|@DJ7>Fd-rJE`9@cB^7WYtGh z#nE`6iDR1pI+Iqd!(1x0aIHEQA~WLf0E(KOeGjM62Kd3XY@^lz>1oiiIbVm2)GJH! zWI}GP(AcqbRQ5B*BChSqY?qKxZcbdbYhBjUB5c}xI`gmacR!`}GXbaQYS(%U9`guh z&E@)-U#KNp_5J%i^vyB}(tnwUNbJ<+(SUaNZzsUBA>&grMK&a#0C^uZEZP^IjJUX? zc8ln`33K8)30ns7k0@yIe9__4A;@<`F9Vdg5EkStqXmgw>&JIZ;K>ukt_cegIPw7T z9O$(5lGx=c+HNYF#q)UV{#o()-`%@^7`sd@EugJuDkqVPmWa%$FfC>c?tDGw+O*p` zPN4=_M9m$3c+C+WfW{03r~g(NjT5vi6hU74jjM`^#-BNb+Z`FuLpblI4?iG*b?Zk4 zl{v?*z4_K}LrOWMLxDaa`ad*Ld_4P(dmxhrNb%DUH~)NOvEye<*T7XXXZoS&>uS z^v-g{&SAm#bv<^xMV!u7>; z)=b9Pg}lt~U;!SOe6Sq!@Gb;+3EuT)O{A{{)!v5$NukNbONyt9_h~T`dVMpKUf)I9 z<<{$)ne_TDR0Y+G3<~)V{54)1qLW%u8$!>9H)&5EAkKoSt>Dgx9foFY_{R{JilQ1wF!iVJugM+t?&ExAU%7tYi!dwKB*N`$6->KRdZx8 zc0`_E0_@lMs#UXJVTG6?-1R&^J*Hm>))-(0FWE$#P>Xb(GP8Zy((`j)>p72qWqLV3G`+^K94b$03cj@u{P{gl zLV3$DHB3apXj0hZ`Afm_r10gjRuGV})l`yz2X7gvAyg6=VTy@WtFitmSXt1p;7uZ2 z9pUUEl3f%x6AdCfE5sKklMeCj+Wp7GRj=+0h`hx%Cz8~MPXfJGZyeO$+on{iG%pVo z#s1?j+m;mXUcbeQ%osXDp%=;2iKzc{k&tU2W$&*SzjIczj26_Jq!A+4<6E}#14^Bn zxa1yKd{ZFkyiaNu>!(N9w0+G_lHO@>M2p{uLPFWNG_R8G>0b{e+jhH`v`7JP*{nfmSmuz!L zmrIpBGk-|MSCeGPCnTV6KicOcnU*tVyo_m)?>_o&QuNd=>D8zB$=ja2)^SlbsocC` zo0((gfEN(Ua<)f03eKK@nZ~&DwIj8e3PV-jUcFeYN)q+bFvgi8-pv4OLoX3EE`d!M z!cN6Zh0HCXXRd{KCMu@6Jm#}&;XYluup80D|AVVO%Fy9s{bj55!^q^b^RvosOt1!e zw{1fXc#r(HW zPLW{9M>n0@SPq49eS>eX?h59|)i^~U9)>A$MAHC(sFD8MZ_GusWa?}34~~ZOD)(gB zFE{@4qkiG(6E~F$T_#O>4_vHzGy2M2eNz_DXM&?x2?Q}Ts&rKG32G2++Ci@@tNw>`+}JoJN|)Q z4N$cjq0bZz7p*CJ**(~I{o^Qe*I3eBS$29;SeY_1(gLl zU?-!I)8P;qdM~hpOsR<``$3n^$V4|{aH_9G)B-9ae&jmKz&c7R)1VAW3mf8Yv9Ipn zWe?}&nsX*RXChI}u1tLgbwSfBE!pqc!aw)!J`|ARTF-OTvgycdgkQc>COV@&@gngg zKy2R+Y{&Z&y_8?fZ6t0s@e}C_>0A!`7!7;R%P>!2n(N0=Satf1o|rDkSNFH6Hj%-b zi`Jnij%4Hc8@QM#8u{o39A6F9Q-1YH>G6~y=oVJ8sq{AM*B1F??a1qG3#Xx`ckQ$( zD`@a{*wCpDHtvOpdk?x~Ei|eAz*R9OHlrc268l53n;$auU5TFKe$F=NgLd(Ej3vsO18E$I;<1tff(qws)2izWLYROkW!h=SZ{r>1 zqK=dJH!rN}Fn!bOccaVtc>Ax&e&rw`{`dTSma*T$1P(n8TwtCN)hJEKw-52g_^&WkQ zj$Ai(%$AcwC3)qOwdFS=x0N<|zwYtP{p*jI&ME8V;#*2JoS;&O@$uGs=7JBHKy(qh z`%l}8j~9qwc#tt&MGc}_O&&Lvj^eApvOGLM91+@-wN8}#C$cu{2zcD0-M)l|{3k%N zEn$D`-*YHHzIpLt(Mz?#)~qDBI9i;G>umc+{9ItnIiQpEI1P~)vyUOdRyVB#&5O8^ ze;qSiZHDR$7&EUd%sI8d|1}0JCBKOJj(van^Wha6cOAC)qal*=8dGRya)HRY$lS4_UQm+K5d;T7m;7C6heae2K6}eeWFz^bSaFyCF#4 zh>*Yt1~sT_=Q=~u8iW7An$4izvRwG1&6UWg@ zMGK;&++cBK12zwT4fJ$Sj-~O|QuqsHz|pztWsrK@MiUE!UlI;(hs1HRe@a$VnS#({ zYpM1tW^c{Cjo-0UM$j+n9P!^l4ZlN36k+G-0l<*oSW956qoSe<97(dJ{j#}lEdB}F z#ZGpOgjvqvcSL%|ffy6n-w+mUhq}tYUuyEO(otX76WFy5OXlXy_<^5`i!vdfVGO84 zsCxNwbOZB9)pir3=Y}125E7Mq6zS*Voj9XuQ$L5*vbtT1md#o=KRak8_TU{kRvM4B zNG1!sF&nagv={rg9%-NL@w=1BOYq6q$V;Rnr>5fV>;&zNL|8BEbG+&=yfe^sz{e~I zeKn39$=1+L-NUycc38~AT6%hRsn{>dgv|JU`ozfCtI;8|*oh9?)*d}F{&MpUJ60ck zXX2-PZipq3;mSgUG%9a$#mWSn{}-V#uoH}$reL+4E}&e1E`SNd$raezr4N>|^|54l z?FY5V7->S$N@>DbGMO#K?mR~n-8_vkl*i|R3u9%;*`pu7Ez zx)S%I8dYHA)1tb1u<&4p@J8HeRpRt9yT{EPtkN;|O2fj2Y-0==Hkx0D*WxpXVQa^b zv1|a@c7h&0#V2yg)ds7%1!B6b^bO)$!c{4Nr)!GZyFQ%IctdKA7w~BBFdIj7ldEsF z&K%Ht9JS5t-)kH#8j?#V_p2}@XCgKps8;cB5+xG&ObDz2#PXBlf@1JoKInO#qCMyD zOIrL-Z*m9G*AKCtk#HpPL@XZ4pC4eN_G|IiBBz4CM|)#imMDj$+EflKZs*E1J6Ywx?^Nmnpiqnj;XYB7yKP3 z-zLSI5j_%Tp`0&yy+UyMwX zfK;?w5cnB#Y>;V#rcBU3Dwbp*a8NDXa9fdwitvQLhWKz$ehb4}&;r_*+=5awGH`tH zp9dFMp%@F$CR1cIhkOYa^Hnda|9guX zjE^0L*VdT_($=d_#V~2hty3;D~utD?;#(V zNF@0i$_^YR_1}>8vfMB>oopft@Xa4B+0v&<5+snfV5eLrW@4RtO_Rn=&E`|!r(g)( zL<^OCbSjIrQpBB*X6F76fQuuBy+|MM6Lmdamt!fA<}S?f}DW} z3P^S0g&j;R^+=#S#-3`2&<-l0ajy6p9Jp#}y9n9A(L%;bP>@KDMij3oLYWDm3hjH- zGkGmPt!z~arVaUwcoQ&0iT!8`?M?S27RiZChs5~oDYYqNL*y&=2oiSY@OiI?-ursZ z3J4(?rC32Q>UDilX>Nb%+@~ZlzXn-7?d5H!pIGJVN605KeQD&jm#0Bjg3z<}2lp=x zOC$m7RL*i-^$|E7&v-`eA+8uEuF2wB7JP*Bc$2YgT27AxhJUOiV8L7TDCFHvQHTij zHwe^K^hE(ZziT%hoU#D6rk;GRglR?<^=$UVtSQC55wb)_`^cYF91%kTEI+r_90 zrSZSpgKMO7w8e)>bn)$Qj{YJJWIr7SVBj!wZ!!cas;G4d$I|!u|L@XD!tjK?@BMixlKy(9j{QV zTrwmZm$}_h-I+_hC|qjeIj7MS*hiHu09DkoRns|-L<%fq60RT&TtNxABIyg)RQHOT ztW*<$>d>?5rMb=EcyXU_QGm&6AW8ULd`fQBvf3BQLbR7W*NBpym(Ko=>AAhex;H>p{8n2(|FjFXw{ z`&ZkQ+26P>kIC3dV@71;F;^3`Qr^(C4vlP7OD>OS?&;fJ-{yLkw&4Hql0P8}T{T{R z{q;Ar(nLRg)t{ox)_ZEcxeYg%S+T0N#cxh{XXB;)rpiIv_&q1`!fz@^|ozeQ-ob z5MEe=@PdZWh7kWFDsXEIkEi{@D&n$36CF+1es3?|=_7mR*rw-f{B~&Qp~zj~dm^_r zA}xL$yu3>P{%cQECIchc?r_qJ1~#cXc)Ud8FPEm$(mywm6?0Y)xWFlmzL-Gi!QCt7 zATzKLPGulYWhtD?MDV)r)lwR-DdY3JugV!JJr=#1dA-xxP3Xh=o200g*XZ4@)=oah>W$RSmA-- zb&CkcgOY%iBq41$DT5sE_iWi)We$YBTSiSKMThSu-6@mr75HKFrH+gpA#J@~mqKZp z>ko1>buto)*RnFfr1TV?uO`K8qiyIm;!T$4ZlmQArEO&XY;vkxoBzl)iNxxV+Eip< zBO+7gSqYJrk!p|u+cJg7d(ISm$%eo(KqAmdG>ye6aXK=EqhW1B+-kouf*ypH;J|cw zc`yRB$OLK2r-3ui5cQRA*v1(g&7(gE?i~sL)98_g0SJ({{Rt{YAB|yMk_qX3zJ4< zJ&--r8L1Ch2##XQvHaq-Y(%rrXzl-sr z#ce)kZy%&IjCSvKrTeUIpLHi0S9*TdYgW(CdLmVi*zUK5p87L(^G)!~Qm6~;Z$MWC zZ_$+lT~8JIfS$7>ZggjbYVj9su#j_Za2E6VS-21qOp<%exZ{Oq9@?!EUWZufgIm_x z{C==^K$*fgFQskgX%D9V(JZ+zp&F@p!>>Z2G@|TZ$FfHsx-@d`J7rxX>4t%9*SF_M zBl7#07UATDxN3t;ugBbClW{H1QdKF?l!1N^lSEMxu<2%B%ZdP zNjQ_svq#}O`mK9|-D~fAP%)Vx-v-S&|zljhUiCmq-Ja7VG zb_Ynp3k*0X*ueK;S4WoIs!`g95(TR&!+Rv>S1x&*$MaV&xy5!{g*KO&kpTgLY7KbwmLHU1M>ksWCY#^96Qx~SwdXc*@0Jf?dbWceQKk5<^pjGIGm(f>;n1Sm zAoxmSRRgpo)lnza%ObFFfQp9LOMc7|-D5b^TrWf204Nf1B@#yqsLcc?&wvAnuN0OA zWt&iGEnITvIoRm1`R{jd$gL-b_8!)y)cIHEtn`&b*t4cb}gmkc+3vbXnY#)en=Y?q)3B@%W+>a3ktZL$HCpVaWucnW{-( zCBjMw#);ZaQ6;x(d{Qjeuu{YiP!n)Dt>A%9H|`)Z&PCVTLdR+>MsP=c zRXp$nw?PHIg?CgE=1#0bB}pD*prW%CKei}Y?4|X@#sP-F0Q(VO9Y+lLnFjv^@(Ue} zXOXT|^x8RyU z_=hnH0$j)tt>i>qt`sBxLDM#vE#eHNfd7Qp!+2k1w;PvZKW;xG&y=7;c4kS`XTjK} z^BeiCe!bvZtN#}E=ia3!(Xcjn^-mio??TL)tPJcv{f$`vfQhmq&nTbvswzvdVMiMi znSIIbHp6AgXEI&-=oQE6yE9Kqd)9_!)I^tB<DD6An>;TyFc|j_bgkLSmCse^I{ptD^N){Kn$l?05Muabhz)?eILV z4oEp#vLH_Qin*1xnoyfH>EOI>gXE{-i6 z1Lu?1=}6rCJ*X6H(}2P7k*0IT0B-q=R{z#j?xV2<38W{fB+o~VQbW%5TLQ&Dh_fG! zdMXXk1=-rDF{djqo^pcy)OPcIJph1X63`R`#t02pwMFvLsSfdjYq#|civ<7#C%?Mk zNkzVVNR#A528qup%bh4G4{8c$O{I8iBzR|imALaa_%;c6L61Ha+XM%d$?pV-XDAy6 zvc-Cc(0+ggd@*1$^PmY56LxM#&9(_O!&a64Fzm~H)rXf$E7xJDfBQop$YI93zcl`%+2A4>)FuA()C#WpRlB)(J{~zw&J3NZ2jT_!`W@b0pY1z0iXM5(p)r z^xk{#y@T{By%(iP6%bG%836@p0-_WJJ1UA5EF_|js6cl1``u@DHZ#EUT<`n-`FY81 zc5`y(ocrA8?uEiIA!b0oB(&2#m1F{fW&(4v$%=t5%?T4whRJ+{k&s5;l&1hYUP={?a=MPkzF9eHMXxVfRh~XCYSfH614j(b zU${7X)RJCbwX8gCQOt-rPj%kgsmh}H(&}MTqi23Gf|svbfzP<){ZOW744*+1qQ7mP z93j6Ae*i8CGGWX%Ng!)@2vso0tI(}2TLcV{Mi)RRne51fv<|UCRK!A28t|l--49+G zK7My93*D(rOk@APGJI-bs`lLuwuue=zR}i;H!uCxXz!()uoikgwM8JZe5`Ek7OdHC4N)fkO9> zDk&2tSzHyq3vaiP7YyPiyJ;6ObVoA9!O2Pqr=vmXX70i%us<^;`>P09u}w$ zVS9k&2z5+fu%POeJ7}z4sHw&WVW==Z7=pY2y)PmMY{6WI0zAPS$OXX+^e_VZ$L4dR zbLsYq>zhGgp)mdfB5hvWk+d-=wd7pu=bP7>HTIKofuARRu$6ZzK2ansJj~ji`bcIO z(eGvROHZ@ICDWjRGupSj8?+?`xkh28ELR~$8v7E=&{)02sOclwghj&APih`Ww3)+! z2$-GWE;2^o98tFy7gqQ#!c+6Pphu{mC2b#7qt}$+pwE*&-CDGDXVUhdxZmFzHR?;x z9p&i|)~9!OES=L|m@Vg*YA7BA0imoA1Rg(3a~1~Ttjtxhakk0V$es^3P=@z};SclD zXA+5!){Rl+_;QGFCk@K)qPS(4_VAk&_J^&}4;$EbX77E1BF~fe}9uKYmpc-z9Wf*^p`=gmu~)ePYEX+KzCAPY); z5U(@{>Di;Nz{?U5KiCJ>^M|-qnYImTh&L*p@I%1Cz(Wh_St=n2I2hm(Rxtt!O<-8u zVL-Pqp~p?_U`5cXQ!H`i;qd$ZJP zq0O65pAk6dwWL?Go*vL@NbqI4oIt(L4~+k6Sl%(+`Bfj%y5apg{2--Q*N1%s)ZXJP zzoNF1cxg0xOKrtnZEm}umT%D#tVO4!^>Fz0j7>MfheigVgxAXWO*8zanem|#K2$Pb z^q%ga5kN_ph zL|7mxOazG>wiWzDQHGR6=*_1?30CT?kVb)qY0=f9Dc(?+VY2PBjt%5e3xFEV#wo#l zUryW`=xpAq*93n#+%6aM_AOga2nc2&4c~Vvvp$_%_#?kHpmX<0u28Kw>R&$xQwm%3 z3AYFRw(r#=Aj$=Qrk+lU+uAKHG#B;$c)D;9D;a-LlCb|iPt*fwVrrw zEMA+7*Y@JIi+JrPUI&QRVd8a^cpWQVr-|2D;&q;QeNMbC7O%^}qfz0R?oDGLN@KE$ z%+8Z4s?W~D%k*h@X*LTlOIqV)!D76ucn&WOmgB`)w=u0A<<^89$!k-BRw6_^b&LqN zno%$Y4LREe_)HUOBnmdupFssK{g${vy6GbXLMT2c-5V5AP~}=dm8`<*rr*{LDHw6B zV92!sY`WgH!u(R3M!}$K1%Lqn0LV2CDQsf;RUhma6+y2R0ECT03i@6v=y|Q6E2@SH z17JJT{HUxkx%4B@*G`%e6d!?w;o-nkJMyO@BcK=PrY?#Zh3SOBy=YIhXJkg(bIGC# z%NK-L&<#|(L}{i}2V5i21DPWm=$$DvSMn3#U%2<3er7N{=45fy@DPy-_=D_p)6Y_{ zb8+8(6J?-(Fm8&KPCSep(*cvrb| z)@BnydjkBVf$ zk?zrvEGY6y1PhLEkB(qL5$-V&EHHv~={zmOSwFRJ$p>RAkBJ;pY3w1qJ8YvWjgG*- zL!&E?VxJ72%K6ORWBbnHd`f@qO`eYAsLYy4WxF=(EU}jLVcPBZ%((jPIB(a8wb2%| z>cu*A;(d6n3MCg=?MvgvUDDpMC$h2=_wS#m{jk5}=zgVB6Nl7dqWJHA&2i#C=`6Fi z%kh)A_F>7a2PKjBXX$ScRc$@ppE^GGn*b@g4DolM(gtK`NXBZQO&HB!)DeC^)GDAN_-br~-Yd&rQmW&ekY6d7LbeD?ii`ke zL`J7Z!rLB+-Vc$fa*TAkq(MnTIXEG$dC!-hU%i80=6Mxs)$G+H>(Zr52w38>Y;Rxk zRLN7))j#s`Vlo#spR-}v?Ck3GtM{qXpl8b-2iz@X=Qf1hdVYYoJxfZ1CeuUp^VW`{ zt1GMD%F ziUXx^L~K;kS(vb;8B6uKd==8OC@4}YT^1ICsw%nZ*=*U70axPL=xCmkwP^xr9MPV; zh%QS9wT-nkRYP@+Ba}2u{UO2zZal<*2N|=?o)p;NqRmf3!iRCgafabYQ^^SC5nx&@ z{kf$9A>r!c=avKnhZUCPohKvxqub2^~up6YK>a7<6xlwb01Hc@oLLJd#W}^yAT(_DopGeq{xmI`JHFF z0@@zstJd}6{G)wSE{v4;w9gjT(#~kFpgqV`d1#Mv<(sr)e9nMQ<0wi!*;6E)l6PQt zDTuzAt0revC9;k?1$`c`nclMy8#8w4i~gzmfmn)YSu=! z&-!TUgu{L9&R^%*9lsxY^}Ke~zk92$Q~dqAw(c^mkzcE)n-6vPwQSIIgw$vMpbASn zkK77Dpv}7eX9suPu<1BgUUiRb)Twv#MxA=`r}JBOdAeR(n2nhYA_4l4uK?EPsmwvu z5lzT%z`}(5mNZwJJYXyXts;lU|dzz~7OK z+Na@qHaV~>(hGNi_QtbHox>Kj6TNUnYOy2BoLWi7YLo5-&^pMQlM@a2B6x;MJix34 z-PEu`=VVBOA_HFkx52Y7Y&sYir2Xf_sjHFx71$iKP5o(Mw*bYz?bBW6Is-b&Ti#=Q z}bT6JW6dXJ97073Hg-2en1t?VFx_Smja%19EY&oCYr_)GY58m(+ zT$sbyjT13YUDTjpQNs_Cjgk2;u7$BHBUm0qL5b18(rmR9z&C~DCi(>#&D20K3Wo%R z4Zd#BZj|3d{p`f&Q=YF>RLOlOjIVp>9?de_#<3IU|NZx6UhK|dTj6kIHb30qv$(^V zwzX=CNe2`53u8To`l+%Y5wXd#4j*EtQRwmT7&e=sicvnp<;_C)rs|=e5Xd6D zp$2&W6nEC7QG{m*r(0S5mq_}zIAIZCNL(nDlzT51^4@R|YB(CRLH1yzW+TTAp6T@O z(4xhdpkn94H;;Yb@4VTmy<(sH&5Xk9@^8FP+ir6MB0rwR_cN(;t7ls9#`$dhVXhRc zd96p%q8=l6bdva6TUetuynCCiB9_MU2hQs>;1Z2097a`PAD=bgV(=9+ZB}_SG1yoL z6)|RJYeG(!V8M?wTd_?fRpE}on4w7ROSUJ#ffMR%)}-&$;5&iLdH(f_0j@6wYd3l2 zL+p*ILmMD~d}vR8@C&XS-|*Uz_SZO_DQaR!0fP3_|L?TNSbIS!<25ajdnpk3uLAzd zn-*`>&ZP0kBxyv4%LhPv@<4mOkayVvAz3w5wO&(!_rsg%j~#Q|d2y;!WkS zDdCd55C~F3{VKZ+{5Jz78YKrVAP$-xJ#{KJK7~0hoH-F&CQU2prZj7GqDnfdea-Ja zJt_q6-<|uH*-@+Nk8jSEXdeDWkInA;?ADkC_Qx^jz=K_ z$#d{jKXhRdPqh#+%MyHd-^O$y6Fx5Tp|fo6V*Oc|`$oe%EwsP?;WKz>$pdXFJIHTh zU%Rm{dO`qtDLnoJq4XP@G@ekpeb@$&LrafS?fRQ!BQLn>kCZlH)W#Z+J|tdwMfMa+ z)6!8k`JV#qUF`Gcjg837&2mI*nD|~o1OhmmVY`T*-AWv#!E6P&^QR^`eUEnu?`3IXCTrg zAZhH=!1Mx`ovnTvJQ)fqC5p+p+R}YR`?Qs*(x=kJl3Wrym@Nn#!y|8p4`8esYKnQa za4-?UPLSheNXk=P{$<3Q3*8PO#f6lT8n`XYl82h4kCc)y5~--BFi%4MnuJ#VaF*Yk&cePijql)Sn*?-e%r!untoWqGxEw{~j&%vKZTb_6p z%39dvwc7oidD>~t$IL+s^^#jn$1RkVHx4}Og?|pNNqZ-#hV5fKw~_{PV9zEO!O;?D{X;qzwV6 zLjQ;p{wfcEju&D}0+bVyQ-J8?diC?J&T=n&To;$XR1bnUp(!1R zIH6#LqH-}o*hWF@;D#K`Q0ImZ*L~P4)IVlV$;Ndb^a7lkcah0Tj-=9Q^q1H~V6lrpha{fLZKW_Z{~l?8);dWVZsWBnWlB zmH!5LgC3Y86Yw~)ZUPfQYe^>K=ZY4_{`12Q-E!e{#O?6Wszr$DN2D#j7Jw;kZgAN zkpF3av>DE)#sF981wV~fJ@ivBemXqHf3`n*8{hQ*ord+HugdsW!p~-40%4`yJ<;@3||t1JzAJ#au3^fxdw!ia2Uw07*3{or5rs zLQ|WhEBrh^e9Y9ZK(rip~U?fc~Is=E(7Z{owX&?aRF9 zKj|9^Yifg{x4#bgG3?~RBk?YW;x}>dqVDDXlf=GWyFQTd)t+s+Ajfs=^2ImV3A^&v zf$j|&jGiv>y!Q%?+i(k~;*XwPrQkO1r-8Przs~T`jiLFYjTpf0tZ`97)(~mkm9zvv zR0>OV->A-h)M0vF`;?v=&R z|A*HrZLPfKC5Rt`JCXRYwcdL>{rtZ?T;;_oyH7y=7(KeLkUzp|zBX&+;m|K`#=o_c zb?yQQq;J)*y06b!`AX<_Kg7JdUWg!oKqzDof9P9@wxMc#QZg2%AArTS=985Z?PRAW ztO~wn?g~d%ZwP!QJ%&tmu%nsKON~w>B_DS^9h*a>d@faXr~Ff01xHvI;a9R0uWbyi zoyV7?mCP>d*DEDZ+EeBQSIi%8zIM{DIAB%#A%RXdnf=5%uB|VfJIm4!H3?GI4gL6c zS^n%zcEQ1)o7ErtlAx;+Mp0yi%@kQ-QILG(-R2VJ0zW2G0$dfZ>( zXlxRvX_ zK)tY8bd$k@?mT>pPcGV}l+g~c&q1}0_ipI!k02~#FV#T zks1w_tV)5zoWx-q?kkOzs2Z>YKesi#3bLg+F9%?-q-v0{lj)*mZVqmjF8P?`p0Hdg zL>rXKwrCgEeF*6?xp3!?B>u<{f96B76vEHQ{u|B&u$$-Hts!5^+sd%A`!*^NfJ(L{ zYem{I{&3WMk}!X60`bSr(6JTmD z5rk@K1^{2GDSC*`8+0H4NRQ*6xTRF?4s)+gn6;=+V9iSbHJQ<@VJ7Khi9$7Xhg71vo8c`x@v@BAPqJ_g08RF&~ zGJo0**dpX1>9eshHZK6>mPHAYhFH|P_3w%ACua3oK?iWj5~IK zw^?jiR_k|`rCqC4XV}shUO+p*fASRQRcY{a+Jxs!KNVq&Hr6S2fKw58 znF;}bvRlkXWV&83E1T{HbS-d2@=sCfMmpB-b&}c1&e?G==W1R= zrtpJ`Yl~;g()^!SRn%_3D3kr9zvnk45GNCD8?7oP53YsQ_~ISu%!DnTHVIRSiEWU- zRDml%)E`5QAhNgzm)h1TUfv|?5R;)RVmNUqwFw)?u`yLENR`&6YOhv%Zt4 z&xpIRaUTrXKA;FTpYy+$m-wg0PQ1%cDsNx1OPOw@_K}_Ij@%4#ZUVYpmoepNK3UGS z2{~5{(#2iKx+X1LjTGO`Ky-7AdN&eY1Y0CJBvg&89|<-xCvtTp#Phz9WAVwNG()tr zI;r5AGRwgbgeC0QD+x;_Wwe{0tiISS%$~#={QCCy&flcIBZ_*mnJL;@NYI12{7{Q6 zIC(>c6uiAU3t|oI^4BNXkg>8ud-r_JoE}3Zzc0a)-}ZRy=W%{i!x<;2d)>g31cd>gBwFv(6;$D_Pf~S-b2@Q1;Y*Vrmc;r&hTvtfIWs7 zh+!}hGb~=92HJ4q$jvd`xD%#4Z2}(Iz{t&?9!|N3GHQsIk)TC!k!YtnrraEU0QbGOnVVFQqO$tkbDMf4}#R&O$`%$ zBq-J0Si6N^8eGx5@B$HDrmG&;VCog@5`wKsmq!gH;*#i!h{GnJDpm9rQ3h#KR>S4SCcd9$u8HQxmjNgo%CC0Fs&;X|&|F3{su zuI(;9o)k-SAU@?w1`FF;IHOP^oD&(ck^CjveE@@~B_y_eX>hxu_MNoj+7)*0GV_12 zONZi)%~(Ttl=|J$irJ@HMf%74@k&|}`&$$bL=`K&P^t-$Reurn&B*X6ju>_cI z)Z$hBZKC+DOT3wN3o@{#mGVZcPPp_<;Z3EEWz>T6I+k;}GI);DIjCTGaIwpM_S`pq z&R^Pfmz5cJmL2;>{+0LaJbbk)^2VYhexO6EhAkV_V;fa2?OkzXQ0l^N!?$+f{Md_4 zT1ws8>;R~UX9hr~If&EqN55B_smHFx=4la#4KtkOz>vB}N(X$9UJ;lO3t`*Yl63ip z%fGI252jb4eLPhH+gr&;L@Ds>QFyk?Hs!y|-xj;Cpn8UIWl%ksAw{(XJMhC!_+cmf zz)yz{*-zUEKkVD>e7qSsN{y9-5;`UT8IF!>58~Xh3mV*HXdws``Grm%8Y!LmF*jwZ zyp1()z?ws$o5-eaSQdEs)Dc1jVG$B*wgiOW!0~9oIU#w|b<7QyH(V;-uN5|qt@Hii zCNXJ4rk4pGCSV4>I8!Ss;#VZ+{x`d^2Xu1dQ8#uTbcSGfAXo^Q=6rd8g1Z^y%`i*D zq)lg|a`8q9UuMGu0zl}uknFIqXutv?qnWwH!=+pv;$S^lu>0$t>ckPD?ekivKDfu5 z*W}YnCcZRTId5lqNUeo)`7z+iD>S}1^lP!@7;BS~0LCmauv z`-dmTUawu!N2m6`pCdx#CHHtPYOBfv@!T-#QD&;^WSkJ^zB{o)L`4wYJe9bo&HJCr1pTrAf$k5S_C}`e0uU0I)DeKO;0zUf>;7L zZ*$K>`3J0l`kwSt19ZrzyV_URR^=05G!R9>&~hCwK|H>&Gb4fwyxrCqOoAv0(Z+DP|BKB8Oe zp5VMIDfcbF^HBK?YtP_*Q1u+_2RRJyBuzXN(gbMr4Tv%ZxqI?F#kD zlV(U`Po~^TTsLDA*`-_HVVZek$r8}nAk zCHiT(X@)QWgQs9!WPdCbsNj+$dxL4|MBH4UY`PeT>R8akrEEUuYNw)(A0)irO$tbL z|B!PH!9#KE)&b@|uf0oa*{>ZE@@=f`Rn^a1!^%rlEgZ#QV-_Ha4@RJ?8tpGy@}VG9 zel!Ux(Ilwgr^AP$Pe+rW61_bdf{LjqgKBe#3WiA-1I| zm?!Rxul#~Vv9gFE23iS-821l>qCy=F1VjP}B7p=E{B-zG;ORhuNZ|HBK*VG$10B*k z4_P3BQw5VW_A3NBKJ)#{*ygGqOhO%Rtj#cXri*o6ZmpzYKM{x+S4@5T9`|G!WKT6#QbRp-18uChZ+L6bm<&P+zcZ3 zTf~3sqvz{Xc|Yu~S+<3$RP`yM^AMDbx|tUHo@fYWKA7;-xaI%I&BrTjK1I+ji$S&2lLT507mvM8tIJyF;3~A4szgCk46| z9nbU+b7a@!oHb$L323QOLw=vXez4-%Yg`)k-K>m1Sg;~re67ut`=A$tUhg^U&z08{ zyLP1?NixWAkty~vgMCbr49~DBa9dN2`$OXUU|6u7R-M7(-n86Yi{Z?;#;PrttRt3_ zb_RI$Y@o0AHVQ;G;xpg8(DQQbg^xvOYV*aFERE9ak9ya~vHD=-5cqpniDP?=0a*CE zanu$|2pE9Lw@;!i3MawZ?oDO)Dj32FO-hFR@buU(YM1ogryWd{7NuxM7qWZ%iiEB~ zR_BrjFfN(2jYm67TkudM)f;$dFjzG-KxiAGC;?WAPDBv|`PS7Ahwh011WEG%IS~Gg z&Bg5+_pGqJ!l8nQTE%$|E=_uBdsf3*K|S0=GwoeyM5dU{w=mgSZL zWJ%&2K}yZRf$(x!Ebt_K;a*a3P_#FWJDG$od?P_DO(su^)OGWplR`FZ3OIq#?g@3- z(_h^By=-*JH(_hn%-x^$?97>OROWf10l^c4+5FpU!oE7fGSjBS|IC8Xr}_F{n^tb) zQvS*2Qn9psLxZ@I*|5WEzR+h<<9Qh>oBmHnOaqcmisW4s` zH!8c|wFfvuCds>`rT@M-=%IF5mX_SxzG=-CZ0SUck}zy3wr+OYF2E)iYD_7>ra1I9 z4L4PPe6l6l>KHOwg2uT-_9E(nnVjzMIf)z&m|x8i{h z=o!3t{X-`Ak?uF5!!_-`03~uv9u_0eQbbNs(g8y31fFI{bfWes_HZr586>i1zf(A? z&=SVKmd(?hV>}aHsph`n92??|G6-d@?0l{EfRuzk)=Ndo#vRLdm3*UY+PZKr(J>iZ z!U-(RupLm-4f`de>;!l%6Ab!LYGq3hq8hAh!FEJ|LA*wR^sC6QsqdeNe5riahRM*C zsA4+WD*7s>!z1r7eZ(P~I&u+3hAfLf7}z=>zJl38e1!^!l0xXnU<$QXlUbS<9S{M8 z|I>{~pj=eCjiwiKIFQ6nv3YUYx?n#xIbK_mn&S-$s-76WvCIqhkR9URuXPTky3ppWm0|4_{|zP}AN+FiY^a zE8k#a z%d%ca6U%0m%`YnfxcF3tS= z5R1rx>;@$r>GZzXVTaTGNj$H(Wz}A%J?Pq|)q9(knf#!Xs`2y!|aH*PsHNJ}(@ z7r*zs^tAlenx|hpE6b-=)Zcnu>(#9@dqFWi#I*i}mYk4@)o@FP~gjEL?Mnsr24ktRZV7WLN?4%#0UPo6sw>uBv2Xpmg zx`X%w1f8H_Li9CM1}bR+z3*Gl5FcIXYG5uu8-i#a~Lg7<4)L;sEx+u`dv` ze)l6Sh{>P-*ne4|t4l}srcIlUwt9o-G3CnkS3YB{7_u&hcWcv!D%Ud4U!MQ)1;{8* zLu@5C#aReF+Q^{xd01Es>4P&sjbbQMz(j0R*d6dIa^R+xB7+JS5Pgek(+Q?;;}cQ^ zeF;a-JY@FF44ABPAj<EH;Q(vy9}YgTzCkn@&o*fcIZ+rM^~jPi5Gz>+tA6zj%oW_5!-WebYhWoOlC>gUL*(Vzx2;%!k#7olk|M#vU+3$D5jB4024|Q?+fc!P8{<=={a&osL-T;;XIl6iIS+&Tema zWJ_sVnABrLqvaE(@8G;}MWeUB_1C)AON)=|-nvG$+Bl_D;LBS$CA%$KKOSLrGPYn) zg#y@%QR`|VwrvgY!aD~JQS@gr93a2Yvtsspn zL?o3V86b(Z0^vbm1-+NJ-aJrD8^f1`d1Wj0*L6vszut)f+b!E`nzV&S;Z2 za0IG@Ow<~c%c@ziT(#J9o@`3IT}BwvI27>io|-qzUdx349q}bijt9#Bvjn)pj@%GwxZCiU>SuD zf8QZfq%NuM(7Ms+AQ)^d%a)H4M15>yY>r+e?@8BUMZ7fbQ)ubm;lQJnOhL=At%d^XA2^qQe=g}+qR+|w+8@3wSze&5?w6v#C zELG^i(tU8%08~B_6xI@l;-jzuc9G2zkfk;YfShG^*+70Ug_VLunk|wfYEe{|uqP)= zHMF=KUOTnqi%U{^s{3LV`5Q~h0St9z5+Sru~p@wM{kwRwbwc>~>M^iXZpFK)&yr3+zxe9GMDS$#v za)@Dw;mR&m>d9PJ*YvSmNMXa$k3`o=0-;& zQd$hs$z3K1Q6PL?Axh4fpX4t`YemPOXxUi62JOd1SAUTm*OKjy&b6C7 zqevn5-Y8dLESpqvw`RhCApdbg7Q7kgpWo%Qy>HvD3j!s)bzB^TeiJ==C%*J9kEoWJ zl!7{E8|M$+)n8IpPT4cKTHR)YGIBO{O@84Wq~wM_{00q9yX80Q(LB4R#9wRHmk(_n z*{TocgFBLKu{JutuaP^#Mv{u`(OBJw1pUwHJq2MRHBLbooQw}XT1&EjX>S8AYTgFw zwXJcl&8i-pn-8&(eOYcs%l5R1{4>eT4yPlBlmhl6iu6zrsUp6eu?$aKxoC+|_E5B;+R; zWK3z8sxu*pa1gOk)~eAk%A*SjaE5BF32qqeaA0qOcx9#wfr=WEEFb!J3H$rI--G>D zty>?e*drXWoW}2^Dv~qIZjV^6-SsTn6%;sZsP+Z#>^^|*OkbTHyT5MzSE}bM%T23W zKAu%-Ua95Osuh;|UuMsa9X>|LlBfb>Q>J6TzKm~i-HiT&! z6iKYgsGBEN^+YuDtx9iwO(FLtGKBmVn&L)C3lne}0yz0Pd|D7ecnu6V8HgaTqSW~zumXJ-0#pWp~$2- za119ju|{f;?mdO2@_%NzSRxg0^Gzl@s{Tq{%3!5S4wrPQ2ojpS#*qUFF_X$*o;L!oq#__K`|W>JJ?clTB%ya~VWfhMOdHi~U)^ zjiitN73WOX)#SSd=76+660i)iAC20FQMuM|6!8Il6Q)dsi*0j>$QLu!m}b&D}FdZN5k$l{DJtZpi_6e2M(S?cK+q(mNyIUNHJ z)R>srF(~-riGh16n7&^Xvpt57SNq^+^(uXvkC(%VFAt1)XHC1@hg<{)yvp7LUi~Hy<2m-q zcy^Rdl?3GJ?#T#A5`kfMa!%y1BXiqDMST#OXs_I5=HzM5B9(|U*vX`6_F14H@Ggn! z`A|;nS@i>g?PQtAx3@w2D_s&KwDY%@3W+c|i1Li&mvNDt=t^{Dx$<3YTzy<)T#yq{ zc`*obVo+8Lp{Sj%4q5b32PQgIn&x+8`LZ4SfIMemy!PR))}xfdp;IJj%0Q03rxV^k zW8>}&`J`v6eL3QHqHQb1+8i)E(%Kw}jx0yMqm2V=gG&)1Q2tpY5(Sp3v9#Jy)5ky~ zb1w?1eo+aq!c4?@+`(0>!!^-&QKyS3@s!dZDi%7sHUe{SC=m7Q5tlI28lZ zgEnDAh{Zw0nD$S=IjX}3$_mm}ofv|!7(gEo&vc*)1WV;9Tkjs5r{0o={p_(FP`-Px zVg=jJw7;>MaQRDVpMAb*H8LiU@eHHSIbba;$Yj9)lK2})0uwTq$do~=K_)1YNF4Z6 z2mX}86=9gd!n`IdVsuzbdbWaME7HEV=Bhuj##^;TOLx61f4O4CgPtq^Yq>7pme<=a zV=a-WZVp`o*!*ACf=3FdVL3{olBMJ;VmTtZ6u%QV14INKs`){nBYqB&s|$lmQCW@f zGgxq@BNONeF^6bFE{V-($93T4H5Wf*wT|u!Na^lyw5kyN>|7=-_Lpz(+{x}woGCf8 zVZ$3Pb!a*wwl3EGxqMsNZ@-4M$Jti@zpq_@t-gQ0vyHQlbBq&6AT|NK3`z{j3d#>^ z6VxXNcnPB)ydNPVZzrO3Q~16x#`F<^^l>7NMgTwe2?#9h-}C%CAF~##ZuxhrojN)# zEIX;YvqPQa3CUr#%E-4@tSGwKut!~gE|w0k{2CO0C!M%*D%IS=}itxEqb@6Q)z z^JuCc_4TMb;cN1BwysUCwQ}n!5P^W8xI=O5i|IgG3Htay6PJxMmS%LY1Z36oQ zjtSJMQwUHhKTs+1#d;r!$f7k=z`+OyjB=lT5DE~3!(@J3kAg*4GfKriX;pj?O(Wf{w}^(o|V@% z=$f-?7k~dg6#|=Hmp1q-g(D_%K6x-7$ytrO*vZ^pwW5ryi|{GEV(K93U@2eBJ<3Uh z?Y)aG%o{;%1()&(kD)*sicT2FH=v|0KeGO zk6F3bZZfCyUZDFuk1dQ#>lQCNmcefPpcTu~a}T#oSo=O}vRjh1zizWMhh5vC-O4(7 zUADit3Og9*`B`a>9i-X%sF5anyikW9+d*iM$c=@Q+LRF#b5QBI2irRL&it75I3me^ea%o`P@4U4OYgdq-WtS|t}OlxZlBP8 z$_nj=-iOd(SOJ7;XzbLGN6n!TWWjq>-mfO>{#yr0{5G=HWn@+}e{_Wu>0}b`3n1T`T&f~8)qr&ZNBLMTqsDG^EHgvzEJrZ6 z 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

S&jh1n&JeeMOkU4{=4@cYr6k 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≤FHXCuU9Qce=@vmZ{%9^5??OaVQJ8!4u8-w;yt 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 Aj{pDw literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Thin.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Thin.ttf.import new file mode 100644 index 00000000..9e4bcbba --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Thin.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://bci3pwej3h1vb" +path="res://.godot/imported/Roboto-Thin.ttf-be0d3f6dcdbb5e1125fcb2eb5b3585da.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Thin.ttf" +dest_files=["res://.godot/imported/Roboto-Thin.ttf-be0d3f6dcdbb5e1125fcb2eb5b3585da.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-ThinItalic.ttf b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-ThinItalic.ttf new file mode 100644 index 0000000000000000000000000000000000000000..084f9c0f5365952d4d860431a1c2dca147e4a9b5 GIT binary patch literal 172860 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 E0iT6KoB#j- literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-ThinItalic.ttf.import b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-ThinItalic.ttf.import new file mode 100644 index 00000000..2e1dbe8e --- /dev/null +++ b/addons/cyclops_level_builder/art/fonts/Roboto/Roboto-ThinItalic.ttf.import @@ -0,0 +1,35 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://cgr0ds5yvswhi" +path="res://.godot/imported/Roboto-ThinItalic.ttf-73ae85a31d5331b097d04b58d0a0ed22.fontdata" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-ThinItalic.ttf" +dest_files=["res://.godot/imported/Roboto-ThinItalic.ttf-73ae85a31d5331b097d04b58d0a0ed22.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +disable_embedded_bitmaps=true +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +keep_rounding_remainders=true +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb b/addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb new file mode 100644 index 0000000000000000000000000000000000000000..6009a3348167d7163d08757b2063963128b7edbc GIT binary patch literal 152608 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πr&z@ zoR?c)-kZQH&l!*2GsSaw>+5?V3h$?i&Pgu3pDKFqKugZq@sC%opR~l;&OFb&C48w; zt{FLBx~0DFqNTj&B6^<`{jIh7TWj^V*3<)kE4-g7vRkp*t?+)T$lrRxKlqPV`Ww#_ zr@!&cZ~7b4qyMAlw5R%8FQn7oda1wlQh#GQ{jKnRs>p7I_ftjhRVlomDmtgX@O~=x zJAB_1d!6XY_Zt-6PZhlvqVRsIDE?Fz-cKd(l);M&5Kr-_=zB;q`W_Od%Rl~|&yv1} zB!k$?xXr&aZfE4Z9lS>G2WiT3h}%u|{UA;C{UA(d+-|Dx2WhJB2a)`EKZyKY%CUX; zd-Q$~rgN-7J$ye1_40iuZKa;*JyLuZOIxWYO6U7d+UomG+UomGBtQBCUfCZM-cJ?v z2V>N3W2Ajxd$rpbwHwpfkILUUb`w9~mF*Ly%a~5uhrdVfZxNq@e^iSf@EX0>i|Nt- zQQWRpf0O*EN&Y6~pi8cizcHQuMm>D*4fWCw7LuP_qx)H?_rrAh!9u;Cg?c}dANM1F zmvXF!zeo4Oblwm3@Vz$+rJm?LQ}pXaazD{~r8wVSB=ztby?1Sq)DxxiJ#zAQDaU&F zd*s(lr(Z9UdU%cOb|ca=xW5~v9$q86F`YIjyq_wv+Y+_g61Ce3wc84{+X}TC(`mQD z`>7(ktx>zJQM;{GyRB8btyQ}*opvj{pDME3IMrV zue`iZap(%?^A*nLE1b_)en)XG*sgFsU*UYdS7wL(ah}jgI9KTMm#V{uC%^3OyQiUt zb0fk|*{SZbqDF=D`3mRr`4=@QoX^*4SvUWIc`ZY%lNZkC!`O0mG`953*wWwQ%WU`{ z`jBN?4)aU;)(iJWAM)w+;l4RD+rO&essQOcGuuDo{guH(IKOJ_4io)3-#-Fen^Z8C0*4rOh(t_vG70%}i z3+MBFee6%(K3f;g=bJJ294|l|Wvsto{ygsj#8Jlj)#sk&W!{?TGuBVtevY^1%?UnZ zefx#gwPelXm`BSxmQ|gOI?qAOM(lR13u}Tt$07UtFyA|3=~?)ULngD=-HkZM@rw}a z7hsOF=%s4^K0K$lV(!DURWW8LKOTKK`*d8Mlda;&RxK3}Gq->3Pwa6X?uX*JM4 zWZE|Yp3fd*e?HS6bW=Zf=VD);Q#`L;>veYqZ-86>UykshN9K~yQ%lx7A@gY2kY!b8 zNS#_&$hwq6Kn~`dvk+&MdB1(N-s71*INQg=8D>7u`l*>UiD&8gJOfD2*zAS_YWOf<*s|@tmW$u7~*#r`jdC=wI3}%4ClL` z@Asic_&`rBS@VRovsZ89kJ7_MXo(eJDr&_pbH?lzM3Y`mzyE1b_K;~kEBI7Z?)h+`w#l4B(+ zYo3sKI5xugD&$y+V2;(ssmvL-_aazE!63_ghPL474oJf!3J3T+r=eSSL zmGn6t)bl1~oM@hf!ufnr-|LyaH$KOdeQyub_ZH6QgTL|oT%IS7bLBmrFMr#rM}s*W zldpP|=g_;!h*`Lnn^+&1SRb16cWcS!EZ$Jd@*1d4o^4;Qb%m@;Imj9JpS;>!o`v0a zKElTtNa4?4toQm{QS2YL!wrF+ZSOVwcq=yp+<2DWyR)wHR%5;}>(P|~&Is}+V!rS` z&J2Pc>BFF>maKU~=Fzfpu8`_1oX;1{!83*P`3mRr70&0I$MulH`FzoO9p}y-TO3yd!rjSCxO%@fB3mW|^Ab;falb%kdPT~n zi)+%D>Q<{SreAD?T{TqnkysGNNW=R}w*1zd~fTnTfi(9E-B9H{fG4YKBm=UFTp z&$FmAo@cSHc%DTLGS31nKmMQR1yGK@U(a-Y-#H`a=J6VxUnTkRtNdNcM&}anEC4wN z18F@aJvx^lqvu!Em$bt9e2rm;YW&|AXDRSJhsJ6*rqgbX^}Mvg`Fw@*`FP$&TX}vm znPT_`pE;hR$LEyi>ea|KdQOY=IW5-bRPv(;uk^QK^|xa6H>T6y3g`1h=dScryU`~6 z$1Ck7XSv8V>fe|i{U7yjh4cBM=d?HM!hgKdZoSptdaJ)Nopvjn&sR8~FM6h;^MnfL z^A*nLYbt$4bbeJ0-+zF*S&KND{+3~959sFI!J96F=)A^j@Z!9NQ*2CY~ zK2bW)HLTS0-zxR|H_4Cl-*~N-a?$y3l~PZX&hy`>hvynrNt^=ruwzm~tlZJOwZfxXti zKD65!wc8rC+gi0-;e5WRA6=*Zwod(Ro!V`k+HIZKtzwHu7!&!gI*mMX{!+gMzJtR2 zY2^NUEaCTBB!3$D@y?6oyDZe7Mjm+hgZ`QLzRSul`n5|VKehIL|8{&QhWgXU`wYBa zzSG0}X=K&ujQ&JfIZK{2vf9M8Uf=(oG_u-U^rw-vO(lOCdEjYF#D8Ag!w=HPxBd9A z-wgg!a?u{ZSj_28u|YIcgXjl zFSu!oFpWI!(%Zy;wrSfaOe4>K?iTT%vIiT6Y2>N1Zx;WVa&3b!jr?8iX7QgNJ2wc^ z$g0yB{fV-2c7}hVtTu7RK8dp0+!^~P%G##Rv~Qw(%Dn5ve|m1wB}^l?*#3GM|BRX6 zIZPurc>7v^DdN|FJ<7r~a_dgl$oGuH&ZS`**`0f}jDLn4UJ|B}7xli%zYhJ+%C#NB zH1dkKuN41jH?TvPMpm89=uecDvorh?WwnVj_DPi0=FZqZQPwtfrhOCT)?F?U|M~Ha z!C@Ntgw+?zcewBAF*r;kAH4V?@t?=$4-C`DTerVZ{HLnpfG~|b_Kx%YYQ(S4-{>Ev zk3Z1m_{D3`+4F&-R4w=X=K&ujQ&JfIXlBYQC6EcW1mD>ZSIWy6J>2v zXWBPWUO8@#_|G%r=7eeF1Debc|LN6aPMAjCZii}r3HqNMcBl^1$bBZw7XRrxX?B=K z{{69;;y<}%Gs86U4a;Wu_rrf~UN$34Bk%P4bn&0&zfTX-$kd554_vIjE?GG{!#`10 zn>b^iL|JX_jQta3ZBu93H&OoejltqSMO`il)5s6@80_O5sq%iSFAmel!Tf1JDr z{|st=SC~e=Y4Mgaf1iExonabz(M?;({QbWEcZ6x=rfnP1KINxedRv%AE`PA0^gri3 zcT1Q?o^@>lIqzrk?3=?h@^76Ri2r<(yE#lFt4?S1C(6p%8UBf~+Qb?AB+6=YXY8LS zYnwXLzKL?TGnaGSK7+NNFpa$ON9S#g{s-#>VH&yV*^hfXCkg8iVH&yZxsQ2R(%F<-A9DmR>p5QNlEGlcr0(ThRYtohD2pKYQL1k7r6@?I%nlt4?S1C(6p%8UBef zZNl>@WBb%4tIeIUf1<2y>P-74$}9Hp#ecB&9Hxhf589_3>#SiK`GuC<#DB1k8>W%F+|kA3`ZLyv!!+^}yLJ)(!P;|}Mpm89=uec% z8T&6T=3kdgn{drAwohHM+T0oYC(7EU&a`i${O?g8l(PT9-dC7L9&_f0rCdM6-bk2A zzUhNfo~MYtmvBr9`OvT4Ev5gs&Wpn|@-auhSIYhedq-g!`N%8YExil=gMF$njlAOn z|0!kvgT1dXjjTGI(Vr+QXJ_~)%0GQA_HndN8hN){#Qu)=YB(SJ@v z|C2`EANyYPANpq+c_8+^IDfwl{ZAUXG4^#BzxaHmk-xyc*DUx?6ZAi6-Z;)yeIa(=s#02{z)T`z`hs#=S_@%(#Tt2-|JEM z&mxR}(#TI?-zy&fq>)vpGx`%{_ZR$+>CdyA>-;4e; z81t_*@^#qvY6br}1M{ym@+H{!;^#N84-=-5n_%AyHYp#A`Bxgb8}_|s!hbk_Nh43k zzSrIGpDCDsrICNZz8C%HTg<=G$g0yB{fV-2mN{1%S#9EseG+B0xij`pl-Z_x;_TSC zee06DVc(1XGalP-74%B!&NMgRFbu4!cMi_m}e$2E=I6#HKEpC-7bk^5uci~e&A zuPNlsu(2KT%fB&hSr^)h5o^ zCs9_LJ7fPunQe;qnYg%p>yp{;(0|zXq><^D^dI_Z8kv4i|KW3xM&@%x|KW3%M&@%% z|KW3-MrOaT68^(}B8|*`hy4%xo;0%RbVh%otel--VNg(j(^5s9F#_`k8uzEXAs6gY2-aI?xFuYi8!A|#^+~3yw|Aw zr0DZMb;|gBPPhX8vnu-hPn~jzaS#2c1I9sVWYzDC{zRGlv3})Z{&mS}6KCv`D67q# zv45hhZR$+>Cd!<5vHw|tc~}~m(BxmOxlbvmOzQ6^`Od1C%`$!Zg4?2{;~{hhIYqO5J| zO#3FvT=${>aP23J%yj{-|8Sikjm&))etv^%4{2nsYtVnV&XGpux(VlBTt`VGb6sW$ z{DdPd*Bs9VOmGyUg8tV44Rv@V(Js`Q_2qwg2gDRbQx&usapScgs{bKRNi z&wZosU(_jc-I@OL4%VU5$g1BN{fV-2cAx#hKT)QA5Z_&FpSonVxij`pmZSD{rhOA- z?t9UHX0NROa2k0O_PzN1ixH>Re>jcIeHZ#n#Z{XJ|Kp{S(dTgg3;yr%S*S}k{g0PMj{6)uzg`;I^gmu2 z+4MPH8rk$ev3~YHd1cf8#QfR+MwKY3*{{)yX{%CwL|NO^nf6VT&6=~HMmB5Cej3@VIs0j3v*zrl zktd{v7k?`g2~HHo^17HD|F;U9wq! zj_uF&=e)96e~#Oi>(6;*v*+cfk-0z87X1(QNBlIh+4J(#$lTvy|AYM5Bpz!8d-I6&nwoSD4YGSm_PTw^2)RczjG1Wr!Lv-f5rCa z{#RaE+m!oXar-99o4pzBzqiEqP}9hdV&AJB{HHIzhnhxSsr&B-;CrZPgySE?VLy#*KJ(+Jk@=Y!t{-9? z;ir-L`5d1AgK>(VMmC@M@zcnvlb`vC^(V^8nVW11rxfP^rIA}<-;4g!ALjt2k-O^WpC>oJ*H0s#hJ7!dKgM%( z(#X5(=btabIX!9Q*YxwxXW$&5G%|H!eZa-~>yni-zw;IIPn6Xr&e$hWR+~Fx|3sN> zT7u92#O+&`yj9VL?_c<7H`0{73Ywpkr!a!i}CALoI{pI?xEkm=z(*#(#XyB z=oaw&jqPv_SsHl`_Pw4)|8p_UAxk4~v0L>0i=A-}SsGb&I-@^PR?g1wPn6Xr&e$hW zR+~Fx|3sN>+8O>6w{KnYzVkMG|I1G!_sxD#%J{{z@zTiiPIxc={+FLd?)urgrCfi; zK98S9Zam<L^(K7`13no z*ubt^R-5qqU$K1>Gg zM42|>oE`gMVxPKXwK>0Y8rwfn);8t$zvA{ymi7DZS7Q8AltR8Adm%01KiDVn)5yQh zd)(vx`w1BTq>;DBz87r5?|=De^CcL+aK40}M&|hy^dHV&(#Sj?gP&i;`51m0*_^rIr;$}B z&)kUhC(6oM=3HrHwF%GMi0zXoUmn??XKwguWNlNPxe>Q-qHNCm@zcmW9|qqk%iIY|i}g)5z5M56r(}{dLL8S=M~g z$Z8Xw{}bCMQ8wrQ#P;X;KY3+sQ=a(~w{N2Sy`DeDvk%kAcVRDt@r&o=rID9nuZ8{3 zAv^~$g?y5pKei3lpVP>nV6TYt_iZSIWy6J>2vXWBPWep1grd>+>{vX6Zc#;?P0O(SoMy%vstcEUA{ ze1x8VI0)A?@=w?+V*J`-*-Sr;d=>Vkxc^>*YZ|$Uo`2X1*EF)~bVh%otel=Fjt2^UCJ@)!05fe>JbHHs_hEvHcTe zZBw4P8n_|I*ahozD4#kilJdA<_!fHX4a6`X(Vgn3vR`E1O)`1!-0 zn1`j2IWOY+&l#A9rIB&&q0i5cWxF)+)5xmR8U2Z}a(0G)qO3M?#y*L%+T0oYC(7EU z&a`i$jL$ra|LlvkpENSxkHG!+N3jl+M#krFW&G11`pj*eGS@ZeKf6Vrf38!;=ZAgn zpAL>bKU}BGbs4Td*NZ-%T&IlBJd6Lh==0BY%BtTP{fV;jcZPqWtoCunK8dp0-x>QS z%G##Rv~Qwp-nrwYk-09(_=Weg@H6>!%3Sy4`9FC7iXgkpcf2&R>f}3jV*QD-a^^dCV*ZJ;+Q%9DB+6=YzH=wG zf1<2y%6IO>?VBhMdu5v6|JAv{krU=DH*$r_o=K-%v8Y#>UpBOpKWS@kxsmhcKcV$G z-sPK3_s{wGd}rixQ?{0#Cs&^pR8ODo`!6hTMlLsHYw5XVXs2+qgUkF5Y2on?&-2b6H)pw#D@@s1dNfa9@>8xbWozllmtXaVh9~8?-i^|ge`xGLxjbLG z+9x!2rX1UCqja@@Xxfo-+`b#78{eqqC+}WA$@iX{8#La0|3GDr@+R_&FRk0Vqu*wD zC;z@>TL;z$Hc?jcKlnGMX`c;ha|M$w=;DZJ?1S)%!ZGP(; z-{;!-Tb|U(Uvv5B!1}-@%8DP3xbzIKQT^%u8*kjR-1I`l&u{Zf@{N zMLs>&XV&aq6n={MdiRGnc=`0$w!SkQ6gFEr&+EJF4KJS_>jRr88?da^WAkgeL5c~}PnY*Nk zmrsxNnE^-c7<%Y`o__NmUOqjxtDFh|4k7K3FJ0{u8asU z<#N@H7IuAPp7&dWR(?J`)(19GHegw+$L7~`$zy#+ zd4}YfFWvf#+99MJ@};YNLStv~rF`jX|IoCf_)@-f>nGMX;49)k_yY>)noH(y5zAwqxwVg%$II`M(q&N4*Am6KB2L*_)@-fwLjZ1Zb$K@ zeCgIttZy7Vu91JvYjcCI??qo8$sT2!-}(mnJCE@TeGlu~;7gk*D}IRnRN@!jRr88?da^ zWAkgeSazI3%uXzVP$lrLTFADVU)U&@zm{lxkP#>yVY&xmQE z${uB#-}(l|TOP;H82hll+u%!^C@X%5@mvMR&lvjz)(7(Gv2Bg<;&P6k5%ax#dTd)` zJQ{HPj4=hrOdEX9>alH&v2VcfGsY|&Gi~ratH=7lCdvjZYxUUtnl5>)8JoBYn zpHcoH?T{~B?GqY1i!bF(kJ>Rb?I^ya?Xpq2^%LtGn5%o7zhg`ts_ap=`K@nYzUOiN zj=5K@{MH|Ae#|E;IDg07E3iIb_1LnutubF+&iOm$99}*>wyiNA4mf|uoQ89@4Zdgf z*tWK1F%J(om&g2x^ZyNctPj|-nm=HETh`{ceq!^h{*XLv9-D4`M)`-dL%wviPiX8c zzLYOr?H{rotl-$Y^^NBm?C;IO`tzaJO$t@^DBH5uudv?aas3c$Keh5(f3W$n zo>js1L#+J-)(5N}Th_KU*2|W2{Sa#&UOqjxt+5^#aQzT#DqJ(#;Coh&ZEIT=>wp2* z60v^6^~Vi*Y`fdCnm=HETh`{c{$TT~{*XLv9-D4`M)`-dL%wviPiX8czLYOr?H{ro ztl-$Y^^G_CjJkwykYh?oV)E1MA1K7ZR7X z?QY9z{($*yS)1SbgUzqpLUOZtte@CCYKM?^uz75{+9#x)tku7WU{K;oF_=7F`r#u__9PV{-{|jr??+Td3<4}3C+V_81G zvU%Y1%i~y<&#!DAys9%J+`dcU*eQ4YkkA&vHoDoT7R%* zzixO#upH}$YrQd{${uB_$NG%TgP0h^V`-bm`i#wE(=irW9*?W7&*V$D{(vz+MLe#~ zmu~$5V+=1ISKD;!CpHhpFkU>Cwry?mYo2)gydl4BYg<FX-M=DmOLl|1v$(rE z{5ZiOxH|-g4epi=?he5v5Zo^i95R&*`pPeP{agnVRmBNztc%w!&vH zdr8Vu^v}=Z+z(P7?gxG>_XE#^u`Y~%QJ?hivfY7go`-v;p-%Q2^#%3R{fgW(QaSYn z^TwP38L6E5qI)ndhW>W$8L6CmhWcPTFfNAv ze5ss!hWdCr>TwOJoO_1)kUKFhhOr5LtsCmp;}^a4xo67j=5Y$1r{vGaa?h0W%HtGL zo}y3Pw~WtV_L7vR=wJ6O<1?PUB<10L;2x0jz$@?%jw{<8*yef4cJ@_6om`G_lzLp1 zdqygUZ|ZSX?is0^dj`I#$5o|r?iq|T)#IvCIrj{FQ;)0iYu!+%9zX4^&plIKH;5;SNqM**xCf*>_^x8}H?W<@&3PW~ znNpwE$$rB)NsNy@|hz&#-4!B`iYzl!ZVZ; z^Re7B<-GDdRVh!=r=DAg&tUeFl&9!l&n?7fJbOvX!~MWLAmu?{A)7ys?L2Rp=i#0y z^?9A_C5)rg^Xj>0q;ibY)br}OXQXoO8H@wf^XjE??iq|T)${75a_$+7Y1Q-U`L%AS zQ_r98t^Uh4BmYFP7~NZ1X(aGYxgJmoTP+aWU%W9>zT*m1CTyUf07tBb9T{U>vBd@xj`J zUN7--?iq|Tl{G$C`_StpUd}y(F|D%32kR{0jW(Z@I`vwf-um1#C4XM0!}IWCxo67z z&+BxgJVl>+Z3RAq*-KKMqCdu$>g$rdB<10L;2x0j@cL|f0QU*o7R$L$*!BRnJ&bJ+ z;67p7Sg+LUE4GbwPqk;To~zy#%b7Q@o~zeCY`dkLc?Rpbdi}tzbzMHLXX^3}j8`zv z)cLc2q&&yyXQr99j- z>^rDK%ESG@Js{=bb+{kccVC`QR_?1?yu|K{I=E-p{f}7Ay}|B(uuibPFT$Fy`W_qW zRyxXBuwmRYQaQWN>EWJ{%Gte5i%-~nOCIYg_tkYBe6Q8p9oS~~E%oc-{--_`_sn(u zd@Q?fsm}}dKf|OvMW5^$b`Mkf3=%?769aT|9r)$Ksj2g00n8P@;PA(eA)u>PM8shsum^l;Be<*c8lhkHgU zXMH=vxtCbK&G3dg*$=!v>$j<27yUnZtc&_2(Pvoa&&RTUoBF)62c$gQGetM_C1PC< z`c%>P*pi2PhV=o~I^)@Y0MEnyz&#-4;dQuASl?qO>wj+X5-;bTVg1h?QaSew>wm^N z!Ma}>Yrg6+4y;?L$1Li;vOGs#Drf!7J=`-=IqO?)@d@iU9^OzV`+@t4^&8i(i~i?4 z)thK+41Ga6hoI zk4`rJ)#4>y&OO7%zdEII?hQ8n)#4dm&c?awzWTgIM=EFITzUMmjDPh=<8{EHf~kFF2=v|SQq?5b?f~3ST=4|pI7#Pl!ssIq7TNuu&xK6FO0pm)u1YsIOyQv&HjBK4D|8ooxKQ&WYD)Dd(PH7wd z9+2|zI@~90?nh_Y#(i{)XLvdH44ePcDV1|?u=zhNp5f(eo=*?=j8x9%`LuXODra+h z>TBJBYt82E)Y~0&zf;%Ae&D`h^LFaj#r&W8Slmaq9LwhI)aR8wAm!nnDf(dkPdyI` zbI)4xaL=&$V4YGP?g#DxDG#s1{XlCpddj-6&a#bXuNE(HpYS?to?$1i(^CHb^9-@J ztDeh>b%OQ$!-u=!s`F$1VT+f_`^TKs`n<9ScpmO0?in@*73+F1r?)K+_Y9ji*eT`Ve&EM)Kkz)f zoO^)QX!MkIVVz|g>%v;R#QnhQuzAj%ybdqto?-K!TRg+d**xbS?is0^&2w(?3@>N% znOo{`U$HsN!+CwlS8U#LT_62Db$-l$Zt)eHw_KlB_5jbry~I7k=EGxM57rc5zI{s` zey!QO=IybfDWk;gd88jbq8ci_6SH5B!B2lXG< zb+R|Ouh{yFx_%Gpb3brTvUL+Z{8;V>ek}J)(Ff~vYJITYr`9KXiC=4eEL%f?zJBPO z^Kd`#W4RyrvAmpn0KavJ-$lf4m6h!dZ1XzY17&>>))ltY=XJOrXuDol*ujtGbugAw z)_nDFpYUTz^Lm|N?)Pu1KaOYWb%J?Zp{xtbV^sAv_Z7w`$~rIjq4!wHSG<0CZ&>qH z=g-^xSYD@`Z}x!XtD;Zs8R*kizvz?e@N3PF<#mewSXWqIU##2e*d`7rW=(A9-YwqC3(&w&TvkcGl`iJM?$I@rB zUTd8D{p&VI@)dpdd&=6bJg!i;Iouok*iyf4XL^t2KH*^2vw{l-Ek`#lZZ4>$UR?$ztxb!n;3 zJwx~W1In7O4xWb}OV3vI?`GgWu-8jc9(p#Zf3u~<4^kd_ZmNH?C66oA&t=>j+*hT3 ze(vVSa-Z;HdHwR<@-r8&&ppHI@bdEh^RpQDj8x9OQFPAF^-?+aL(w1Wdg|+&y~KUO z>oj;H|8^$#3H1Zy-$kT3u;}x_HrDCjdA!#r)F)8?{!fc%TIw^;P@h9bS@YE)<-zz( zS=)u@*ssOxtF9o)K@dStnI>cbg!4BJf(i!&ol0^ZNB35xtB`*+!w?> zBbAr;pZkKiXQXoOnW9hbR}{SVt^ zR=-v!UW@u9>)#)1Iu^e_hJLDE&rqLdM_KdL!M(@xP~UP-S=)tvuwE}oc`!D>`j&gW zB;}#L;^Ad&7y9vf{UGHj_3M7-agS~D6|c{|RPyJ(Xzm%QyuAP17tK8*m2=M&o%6Vc zRL;Fo^vAlM`ub)s@pA5&25T63RZe4-u)Dce}5)8ZMtURm>n-#WzaC}z*_`rI=Z zlPGJxI=E+e9*p0VwO#0k@AZ|h{GK!BWAu6k_giJn zSH3qYYY#hleeM~I)08z|1Ef3{zbR|GhH(!_c`zPO)^=gOM6Z{mJQ#l}YrFDyPwgcs zPpMze^BMQpHed1j+)E{YzGvs2k;=>a&vSveXQXoOjiPfsw+Elu>?K~#JyWhD*7ela zH+zYfbI&w*1HV7t;uAcNVf+jC;AI=@bTA*R*E4wDD{H=*j?MMCXYf2()_e_+@?adO zo~Oz^Amzb$Kv~;``C7eRlJa0Is-A<&y(Hx+_3L?t;~v}QD_);_spQYkh}<($d3pbN zE+Y4gRL;FobjG@#`gi-Ymv}k%M!Aky*Hd5L>?K~#J=5TgHlLtB2;*Pq11Q@a*yf%= ze^XiW)#5Q;pL+)VS!K=F04Wc~Z_3&(%){*Ul9UI1b7gH8=8N`vNy>vUiFyt^_mY&S z)UW3`k9%yJuXug#rIJ7QQE|^m<>me7K2h!&shoSG=v>c{#%DHriI;P4lo z<-yoMS=)uR54~QJ@?b2At*z+wgOsP#uh&_Odu*Gpczy1rl0T1`aL-8P<^AU|8SWXW zoO`3_oY(b8<=h+PI_CesNh;@_;ohMCx)T5Y;CTNw=^D|2IudtxcjvgoN)5_!iErud zm*W!O)ZIM*uP-s>E$_c(s$HE^=AqqtpM#LyjaiJ^P-I?W8-5tkUcBQ7!YuktHZUZ-Urx}#iT=#IF=(7(#t%+MWi ziJ?2Ucf=)z{#E{FhVF<<4BZiz82VTF(cIvCTKAzl z$|Z*Gh)Z0xKgf&rr=6iY$|Z*Gh&ORpX`9B!&>eA!p*!LdL;os&GedX8C5G;ZOANiM z{Aho0uC4pf9pw^3cf=*G+8^Xa`_syC5HZ0{$_^mh)WFJ5tkTxSNYNY;5=IQp*zYYhVF<<485zo z%?#ZUml(Pu-o!)mwNv!oa1EOox+5+zbVpob=wIb;X6TN%#LyjaiJ^CuAMFp$qjev; zqg-O>j=03ozslRp&>eA!p*!MDtkfb|_wg}wM_gj)j=03ozsldt&>eA!p*!LdL+>g- z+8>-x>ppZxxx~;Nafz$;26@r`v@>)^xx~;N@h0x-T9RUlUR!49j=03o9dU`Ff0e(P zp*!LdLwCd_hTc_vv_CkH)_v%Xa*3fk;u2Tw5Ave@X=mt;a*3fk;!QlXd%3Lt_!zn) zE-`dRTw>^7^5 z{)6s_NetZ)Z{n`5RVb$DwPl9xh)WFJ5tkVHSNWS6x+5+zbVpob=w0PU`-Agn-G}Zd zml(PuE-|#L@-{PcM_gj)j(8If?OrqMKR$-;h)WFJ5tkVHSNWS6x+5+zbVpob=w0PU z`-Ago-G}Zdml(PuE;014@-{PcM_gj)j(8I*wSLxrd<@+Yml(PuE;014@;5VdM_gj) zj=03oyULID2j|ne58Y8NF?2^xWv#M@g}ZbQyC5Hah z>ohZTM_gj)j=03oyULID2U@o7LwA%*jM(`8s`dwY2bR}qW$2FMC5G;ZH}TN!Ehw*| z_a-xRM_gj)j=03ozsldt&>eA!p*!LdL+>g-+8>-p>ppZxxx~;0afz$;2YJ!{v@>)^ zxx~;N@g`PkyR85C7`h`aF?2^yC9c{XU zcf=)z-c^3IKk$0%KFY@T2i*~uxN3KhcVKy)R)+34USjBucoQqNALUi_Co^^s zxWv%E%HPb;9dU`FJK_>U?yC5G-*-e!jGh)WFJ5pUwIu7fG2 z=(S~r?ubha-4T}<`d9gz8M-4bF?2^x>LQrh4Xdb`_LWxh4Xdb`?Q_o<1lo} z<{JMu#RcCK{C`9uG9u5^cf(7%=Gy=VQ$$Iu;diJ?2<5>qV4C5G-eUSjBu zxWp90=Nsoi|G=&L&>Q6vLvO?-hVE6~W`^#FOAOr+Z({m9Wc|m-mG8TY|J%9peRuJH zJJV~U{edoxT=~Ac_`jVi-**@Pw=?A>U*+>a`;+zO`<36TX9$#!yI=Vo_gMHIZs*eO zP~P1Bv~lHooOf=2+PLyPbj$5e3wL#mpnQtHdt`?Gh)WFp5tkUcSNWS6`Xeqe^haD` z=wIc>{U^?&bsu`8Tw>^sxWv%C%G=D)9dU`FJK{}D+S6xW(dR?vs@+i?5?Aex>W~=v zSNWT{YIjtJ#8tbaIwXeP<^2=kJX-gmJIW=7?ubiVwLi#<_NSepJIW=7?ua)r&5O(W zkB=+g_sROB-njdf@B3u^5g&IS`d9gzx$=FVtUv0FyI=XfPu3stardEjl^_1c`Lym= zzVDOuM||A<%J+S;{)mseU-=(-;s187e2??S=b)V{-$OTi4qBPMkF);cW9W^z#LydY ziJ^a$znP&o;u1q|#3hE_Ren5wRnHQ9A9`b7V(5*y#L&IU*UZozafzWj;!RAsv;N~_ z=#IF=&>eA!p?{UXnV~!45<_>yC5HZ0e)^PCy>a)UJIW=7?ubiFv68=;p*xP37`h|g z#Ppi^scoWlm%KDFwp*!LdLwCd_hW=IlW`^#FOAOr+ml%3i`E&ns)}Qawc8*I7 z-BDj+=wIb)X6TN%#Lyk_CWbcf|M(cXBQ7y?M_l46H(sat54s~JF?2^yn|NsVU^;h2*GJ~c_k)Z7+qv@n;Nt&w#%ovk zo4NA+;Nt&wu6#eZ_`jVgfBpXH`xocYx)0q^E^+1i!NvdWT=^e);s187e2??S=b)V{ z-$OTi4qCaZ>w>KR_!#;lE-~~+Tw>^7! z#L&IU+sx1%afzWj;!Uj7kgWgsxN3KXWc^WZ-2JNE8Itu!eB6ELU*&J+s@)k<+Mjl= z+MOY#{b^_DUEV)^lyN?-`_LWb5?AfckgPxIjk{m9Kgf&rr=6iY$|Z*Gh&M6ycVzv? z$Iu&biJ>>*5<~wge=}F@Pj_j5+PP|fx=Z`h&d|HOfAs%k{rNt0$G*hS8*z!Nb_aRU z{bf`UKR$-;h)WFJ5tkVHSNWT{YIp7}?N2*b?asZW{b^_DU*12p zKRBP(edvyIiJ?2<5<~YYZ!<%8#3hFAh&QoPk7oVH$Iu;diJ?2<5<~wge=}F@&!eUN zY3Hi_d9<`Y?F_xk`=|B?=hM0m-BB(vbVpp`s@*|ev_I_(-BB(vbVt02hju?tc@=#= zWQOjDOAOr+ml*n2`J1_Ff1WSxPdiub&-11IX=mtN-aoZJIFHtS=#FxUp*!LdSM3h+ zqWx)S=#FxUp*!MDO#Px+|M4+&M_gj)j=03ozsldtRr@odv_I`!wLc?D`_syC5G-*-e!jGh)WFJ5pQCpMrQrT$Iu;diJ?2<5<~wge=}F@&&bmL zv~$(|j4bU>J45gC{^_HP^J(3O?kJZSx+5-e)$SlK+MjlY?kJZSx+C7iL%YAByl8)9 zhVF<<4BZiz82VTFo4IO#zA5cbJ6G+`H>Le)XXsttKeazNkJf$Yj&g~iJK_>o?GEyy z{b^_Dj&g~iJK{~;)ipZnKR$-;h)WFJ5tkVHSNWT{YJWzT_NSez_Gffyf7%&(m-kQY z56-7`AG)JlV(5;z#L&IU+sx1%afzWj;!SMS;%aGS=r1UzmQ>3VF0Uq3NiC~72|LxK zY7*67tw^|{no3Qf2C7vFS5?!hK5AvP2H_fNMm4=!U9C;HwwhVZs@7HO6RxjjS97Wj z)y9MytGQKQwW->iaC0@U>Zi6;TN7@r7ElYRZPj9gi_r&hQMIGmm2g+Jlv+aVto9__ zQ!S^KQM;>s3HMbUYJl2H9YA=1T1l;-_EU!t9->xLtEhw2VT6aNwbYvGP<15Xk!l^a zo;q3$A{?YPP#dY^)Cq(qs4lgMI$51cc&ge=ZJ|z6XAqvDwo==uv(yfRJE%p}_Ub%! z5#dE@7qyeRKwU<7nc73`rY=!e5niSCQG2V))is3Ir~}phYKXdl@CNlib+Ecl-As71 zIzk<;Zc?`p-lC3D$Ee%X9fWtNW7YBME_Dy#J?cbtlDc0#Ncf;SMGaODt6_x0)amL> zHC&xbc&^$`oui&m&k#PNE>!2Mr_>9CFQ`k^#p*fr3gIj2N_B;LQN2$1y1G_ftzK1c z5x%8vRM)FF)w_i6s-db|y`w%L{6O8RZdV_vk%S}Fo$7A&srroYGj*@JPkpJrCj44G zpdM1+s_zNESC6P3^`m;6@NspvdQAPQ{viBAJ*}QpqtzI~G3t5stolohB^;|>Rxhc4 zl+iEI-y7;RrF77*si5ChBb3t<=n-lH{l0onB|WizPfe^pR3EEJ_2l|vHM#yojZ#zU zsr4u|wfo3&w`YZK~no-ZJzfm*m@6-=!R{aa%FX~bCvzk-SqkmTO=-<_E zYHmHh{!PuV|5ksh`Sim2PqncAPyMSF(2MDR)neLetryWt5iX^p_Ie4uEa9?xB0ZsA zM)xP|uP4!y=?*=RaG;(-Po-DXD-*7)`{-%(YI+UAHS~0P2ECSEhj1M|lb%Jdr{^G? zL;s{^*Bj|g_3ZT5SI?!p^p=EM>VA4&y}90&a9h2QUQlnPcOcwBFRmBW+v!~hchO7h zCG}2vcf#HE@_ISFo8F6XFFina>V5Qng!}0g^h){weGuV6dKJB@{+~XK@G!l)UQ-{T zk0LxuudUbB$LI|SH`KG~4fOH)WWtm6CVFFiqCSoAG`)r1OrNUHB0NiPqqo+l>vIXu z)jR6#_1XGD!VC4TdS`vUzJ%}+y{FzoU#u@Dyj<_C_tjVGA%sKp{`x?DjlPcXI(@J{ zMBk`yCcIf6st?yg^{s@r>Lc~h`gVOB;ceXPD)-%ohIK1rXT@6!(xKCB1pQ}ly+ zIN@-8ranVIq8}%GT%V`U(U0n<2%pjy=?nCe`Z>bq^kw=|{j7eG@I`%vzDmEOUnP81 zU#+jzuj@An-_+OZ8}!@yUBY+uO}bmZuRkLENZ+Dw(;w@*2=CH^^qqQ?{*v%ZeXqVp zf1$r6{8m4tAJAXx9|?cdJ$jh_PX9vqi+(~srhn3-2}kQ^^wat`{TJb1`UU;G{!{-$ z_>X>BzoP%u%Dh5!l_%%_B( z>O1r&dMY!m`9x1^KG&b=Y0Qk~Gd-jEMt`MeFteJk^sMFw{k@*a%x=EdvzuS_&w4g9 zxA|GmZT`@|>$%K)=65}x8KeK!^O^e$AdJ&_IHH(@h2$wM41hceR zj&M1X%!Fon(?Qr_CN`6pPBSIplxC!!!mMOgGgHuCA2YRC)vQIhmYLp6XVx_95w2%u zF*BQW%m#!Tm^sZHW_{B|*k$H1ea*&ZbHdHd{HCAT%xp!tm08FvY_>Mr5pHJ|GmD$; z&CY~7n>QZ;T~ogv#i_fPZ>2C&@ea(u5E1Jp83g$p_2;m`SWwVO;pE;cH zaI?Bu!yI9bB0S2hZPqnMn?Zzw%!XzobF4Xm@C37o+0>k9P9;3mY-zSIrE7&k>(h4o4JGV4s)D2-rQyGA-u<&WKK5sngUGgq58%v*$Snd{8;=56yX;k)K0({0{29}<3OZZWr;kIYEIk>*ZwxB1k3 zM);Yz&)jc5H(wKeZ5}ocnXkcyVC(URxhH#8| z-aKpmGGhtHnwQLr=0Ec~;p=9IdCges?Q6!{H_ZqW?F4p&nZUkd-ZK-~N$h)O68nMq z*i33Cw;!9y?I&iGnbJ;eN13VZ7v@Vdjh)_pX{NW|ns3Z>b{6}MnZ^ESelRoHIqVN+ z4*RS5+0179+Mi8d`-l0>%x&klznS^%-{wy_EbSb_zR{UD2*gxU%hIr?sovH3-+RGuj#K z>ULeib?vNnX1liCkZ?mgr=8udZ#N;_#Li>qvR!sd!Yyq-JFnf`ZcDhWUC1tAx3-HB zE@qWo)b40^CfwOBVVAPI+T96vx69b&?4EXS!o6*O+iCZ)`w{MESFkJD1MESB2iaBZ zYW5I&7~x@dExV>Y)E-TEv|Z1xV~@1Q5gunZvK!bz_9ViS?51{Od!jv!@HD%H-OQe9 z&mug_ZezEyXV@JGcd(1t?d^H?0>TUIPIec2k-dcQ61$t-!(L{uAiTovW%spL+98BP z?EdyZdyT!0@H%_2{hz(T-b{G2J;EMtZ?d-$-e!-nN7-BKU4(bpfo@1Y|PZ2(4&$k!aXY6x?&)JLZrS=8; z65&hsa(k71*}h8ns=eA?YhSl-6257#w>R3i?7M{T+M%}FzGFWk{K(#JZ?zxTPYFM@ zciTJdNc#oh7xsR8kNwz`boJaPQmqY;u#j z_w1zZWBZ|<*iGp^v{SlK_7gj~o5p=&r*U7}&ukwzqx;Ox=)SRE+3DS^?khX1`@w!^ zXLi33{$d}sKifIo-0o*PxBJchZs&3Hx!>)4?oa!-o!>3!{x+9XAKz9PTGOyW7Zhx!LJ&F4xy>>NY3b+|BFyxh>t+gj>4> z+`?`fw;kbjZc(?m+rjNbxRYDbE$w!3yA$s2mUqj!-P}He`?yXw!0qJ@AUwdW_qhiMA8@C-)7(Su5yD5@8SYFs+&xD4m^<5@>z;5=5kBS4cNe;6+zW&+ zxJ%u|?s@kL;VbS+ce#7Xy+QbfyT%Q1uerAg-*z{+>)o5~J;L|gPOOFH5Z>XAb$7c@+-HQJxqIFH?hE%7;aBcK_ptlMeMk768|Hf4kM3u}pWUPGardhm zO*q;;>7I6fxG{ud+;i?(_qQ8MIM%)FUUdID>tCe5*WIg5`{-YF(ZA(JIOiwyBiw}k zefO?Qep3Igo78{oK6DfNk%S}NU2c?{!cXl-xvBl{Zf8OzmwmCa1Xz{U)JyD_aWTJclrT-FF%lQ zpr6vOjXsF{zX58aEL#^U+Z7^~v=#NXlX@}vCcgrEC+{C)mQ|1IIS{z3nM|Hl7F_@nRfkNEHXuY|w) z$Ni)JXa5J`AO30ol>g2DP58He!9VB!^#2k5=U?$J`G5SYgs=K*{2N{e7vAtLjPP&! z5K?&Cr|_idMx{1<-OFk|?_<Y; zU-=ortl=v^Yxu!`=VuOchVT5G;TQjtpFPYIe)98#-~DJmSLhc;`+i}J|I5!C77Bm) zg~C|>uU{aj@UK_lb#KF>VToYr&xaV649gHM6D9}~h2=tj!v0~BFlp!vD-f;_CJ$4F zmBOlotA?q=G-0){7U5c9`Y>HsGpt9rUYI4!6xIzJ5pERb2(yI^!ls0qhQ49$uyNRe zaEma1m@jM=wkF&R4h~y}&BH0-48k+Qwqcuadf1L|yRcZ;F`N_5Cphd;xAg#U$C!b{=bVB<^l_gZ*0m>A=$ zA;uBm%@E>5@y#$%d^fxkCXAEDcfzFcgYaRPEKV6e3{%FD;gc{`>=Qo;ed6cg%P>ux zE`AxNi{FHA!}M{c_-&Xe{t$i)Gsm9@e+rL>U&HKi?)Yn%JN^-V4|BzS@%PX#jtPH< zdE-Ly@32rD8~zCk#>L}5VezP=ii^gj373vOy0}zao^bg%K}>PE*g@D4CytZE&bR{M z3UTr{MO-PaLbyttI!+r`jjI!`9%qO%#x>*GglorH;;eC)9mN5UQBVsVkUecY9B*SKU{BJL9RB-}GD8<&ZD z#C-_&iT&e%xNqE_aQ`?kt{4xD2NNC~SB|U2L*k)?hsHJHTJi9BB;k>9-MC&nDy~ns zew-t26pxK35uOw`jhn<1;$XtTam%=QJSCnDay&8K6CWacD4rHijSs{g!k&0mJUtGJPY^y4 z&y8ot$Ko@D&%_Jk`SGdv0^tksl6Y}^KE6cwQoKA~8DEL75xy3O#B1UkaRlLrcwM|P zz7^jgd?(%D%~qoG#6hzK*k`ALDm%<}_#eF3y>Li9f~J(>&>?I8XXL{ubv>^QYh9 z{OPawXY7|2On=4&(?9XQxNurD{TCNaDw(u+T9R^|UVGx@p!lQ(7l&M7U9!Bh8jJ zNShLFn);@>QdioNaLY7bnm28cwkF&~v$nli1F_D_cp9+Fl|tE7X{;e>~$wbB~t&~!B6(P_Q3 zb~-8@Pk4OVFs+}CO(zqcoHj`trxVj@gr}v=(`IRKI)m_xv{l+Bot4fZJST0Jc1Y)? z3kWYrJEdLIh3R6#i_`9D&va?Jobd9rciJ~ynf4>xFRhpkOjoBH2yaOLO9!XxQa53D zIwBpGZc4Wi-jErECVV)Znoda%rD24_(&_2U zG(0^<_*gnSotvIWPZ2(q&QBMmr_-~9&!$V#W$F3!BH@eaigZx*qr0)s8PmiRY^ke#&@aObsdOZD_MiY)sPo`(m@99s%KhtyRh4gp&hwz{DQhFu* zmtG}&HC>b5NLEGlMvCg~G$MI5ks6UEQtzjC(*$ZV^=_I>eVjf>6RRoJ2Wd+6X&RX( zSJSAGX&UuK`YcVYW>BA{8PwP5t2CXONqv=OQs1Q?(kyB=^+TFX{gi%5bEvu0FKI6I mTlyo-qvlh8r1{ieX-t}5EvUw%1=YW4Y+6`pH8yGWdip>0+k1@w literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb.import b/addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb.import new file mode 100644 index 00000000..dc954336 --- /dev/null +++ b/addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb.import @@ -0,0 +1,37 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://p26cj0m5amq0" +path="res://.godot/imported/gizmo_rotate.glb-2e5427bc458d00aede170e5b0ed6cee0.scn" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb" +dest_files=["res://.godot/imported/gizmo_rotate.glb-2e5427bc458d00aede170e5b0ed6cee0.scn"] + +[params] + +nodes/root_type="Node3D" +nodes/root_name="Scene Root" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=false +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +_subresources={} +gltf/naming_version=0 +gltf/embedded_image_handling=1 diff --git a/addons/cyclops_level_builder/art/gizmos/gizmo_rotate.obj.import b/addons/cyclops_level_builder/art/gizmos/gizmo_rotate.obj.import new file mode 100644 index 00000000..c200206b --- /dev/null +++ b/addons/cyclops_level_builder/art/gizmos/gizmo_rotate.obj.import @@ -0,0 +1,22 @@ +[remap] + +importer="wavefront_obj" +importer_version=1 +type="Mesh" +uid="uid://dc41qtx1s2lbw" +path="res://.godot/imported/gizmo_rotate.obj-083ea63ef4767449d33eb052210ae2e8.mesh" + +[deps] + +files=["res://.godot/imported/gizmo_rotate.obj-083ea63ef4767449d33eb052210ae2e8.mesh"] + +source_file="res://addons/cyclops_level_builder/art/gizmos/gizmo_rotate.obj" +dest_files=["res://.godot/imported/gizmo_rotate.obj-083ea63ef4767449d33eb052210ae2e8.mesh", "res://.godot/imported/gizmo_rotate.obj-083ea63ef4767449d33eb052210ae2e8.mesh"] + +[params] + +generate_tangents=true +scale_mesh=Vector3(1, 1, 1) +offset_mesh=Vector3(0, 0, 0) +optimize_mesh=true +force_disable_mesh_compression=false diff --git a/addons/cyclops_level_builder/art/gizmos/gizmo_scale.glb b/addons/cyclops_level_builder/art/gizmos/gizmo_scale.glb new file mode 100644 index 0000000000000000000000000000000000000000..e898f39eff6e8507a926123aa1633f848293c28a GIT binary patch literal 11160 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 DNwEOs literal 0 HcmV?d00001 diff --git a/addons/cyclops_level_builder/art/gizmos/gizmo_translate.glb.import b/addons/cyclops_level_builder/art/gizmos/gizmo_translate.glb.import new file mode 100644 index 00000000..2c728ffc --- /dev/null +++ b/addons/cyclops_level_builder/art/gizmos/gizmo_translate.glb.import @@ -0,0 +1,37 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://ujq3kes2sdfu" +path="res://.godot/imported/gizmo_translate.glb-b25182ebac6173efa72020211f0823b4.scn" + +[deps] + +source_file="res://addons/cyclops_level_builder/art/gizmos/gizmo_translate.glb" +dest_files=["res://.godot/imported/gizmo_translate.glb-b25182ebac6173efa72020211f0823b4.scn"] + +[params] + +nodes/root_type="Node3D" +nodes/root_name="Scene Root" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=false +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +_subresources={} +gltf/naming_version=0 +gltf/embedded_image_handling=1 diff --git a/addons/cyclops_level_builder/art/gizmos/gizmo_translate.obj.import b/addons/cyclops_level_builder/art/gizmos/gizmo_translate.obj.import new file mode 100644 index 00000000..25b2cec4 --- /dev/null +++ b/addons/cyclops_level_builder/art/gizmos/gizmo_translate.obj.import @@ -0,0 +1,22 @@ +[remap] + +importer="wavefront_obj" +importer_version=1 +type="Mesh" +uid="uid://cuuxumssbvx" +path="res://.godot/imported/gizmo_translate.obj-dfe1041d0008a76a601d3c2537af97e5.mesh" + +[deps] + +files=["res://.godot/imported/gizmo_translate.obj-dfe1041d0008a76a601d3c2537af97e5.mesh"] + +source_file="res://addons/cyclops_level_builder/art/gizmos/gizmo_translate.obj" +dest_files=["res://.godot/imported/gizmo_translate.obj-dfe1041d0008a76a601d3c2537af97e5.mesh", "res://.godot/imported/gizmo_translate.obj-dfe1041d0008a76a601d3c2537af97e5.mesh"] + +[params] + +generate_tangents=true +scale_mesh=Vector3(1, 1, 1) +offset_mesh=Vector3(0, 0, 0) +optimize_mesh=true +force_disable_mesh_compression=false diff --git a/addons/cyclops_level_builder/art/icons/arrow_down.svg b/addons/cyclops_level_builder/art/icons/arrow_down.svg new file mode 100644 index 00000000..4dc25caf --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/arrow_down.svg @@ -0,0 +1,67 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/arrow_down.svg.import b/addons/cyclops_level_builder/art/icons/arrow_down.svg.import new file mode 100644 index 00000000..9509dee6 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/arrow_down.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bor2x3t7fiqc2" +path="res://.godot/imported/arrow_down.svg-2e1ff08c057ea7461c9327204e454db0.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/arrow_down.svg" +dest_files=["res://.godot/imported/arrow_down.svg-2e1ff08c057ea7461c9327204e454db0.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/arrow_left.svg b/addons/cyclops_level_builder/art/icons/arrow_left.svg new file mode 100644 index 00000000..136187aa --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/arrow_left.svg @@ -0,0 +1,67 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/arrow_left.svg.import b/addons/cyclops_level_builder/art/icons/arrow_left.svg.import new file mode 100644 index 00000000..21652232 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/arrow_left.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ghfvfty2oswu" +path="res://.godot/imported/arrow_left.svg-014ed9bdeef2dfa2058baab18d11c5cd.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/arrow_left.svg" +dest_files=["res://.godot/imported/arrow_left.svg-014ed9bdeef2dfa2058baab18d11c5cd.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/arrow_right.svg b/addons/cyclops_level_builder/art/icons/arrow_right.svg new file mode 100644 index 00000000..5e3e3a99 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/arrow_right.svg @@ -0,0 +1,67 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/arrow_right.svg.import b/addons/cyclops_level_builder/art/icons/arrow_right.svg.import new file mode 100644 index 00000000..9eeb534e --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/arrow_right.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c7c2vg6lbhmfn" +path="res://.godot/imported/arrow_right.svg-487571a4e582c53960841d4b8d93eafd.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/arrow_right.svg" +dest_files=["res://.godot/imported/arrow_right.svg-487571a4e582c53960841d4b8d93eafd.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/arrow_up.svg b/addons/cyclops_level_builder/art/icons/arrow_up.svg new file mode 100644 index 00000000..1ab600c4 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/arrow_up.svg @@ -0,0 +1,67 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/arrow_up.svg.import b/addons/cyclops_level_builder/art/icons/arrow_up.svg.import new file mode 100644 index 00000000..a199ce99 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/arrow_up.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://gb1w6xbrq5q" +path="res://.godot/imported/arrow_up.svg-98c02f3791a0716945de0c384c85f807.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/arrow_up.svg" +dest_files=["res://.godot/imported/arrow_up.svg-98c02f3791a0716945de0c384c85f807.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/block.svg b/addons/cyclops_level_builder/art/icons/block.svg new file mode 100644 index 00000000..6d026118 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/block.svg @@ -0,0 +1,48 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/block.svg.import b/addons/cyclops_level_builder/art/icons/block.svg.import new file mode 100644 index 00000000..912a7c37 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/block.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bwasqbq4iqkn6" +path="res://.godot/imported/block.svg-764d2bd43d9fe0588da4c013aa3df07b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/block.svg" +dest_files=["res://.godot/imported/block.svg-764d2bd43d9fe0588da4c013aa3df07b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/create_cylinder.svg b/addons/cyclops_level_builder/art/icons/create_cylinder.svg new file mode 100644 index 00000000..70bf7804 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/create_cylinder.svg @@ -0,0 +1,50 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/create_cylinder.svg.import b/addons/cyclops_level_builder/art/icons/create_cylinder.svg.import new file mode 100644 index 00000000..fe69c4f8 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/create_cylinder.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://0vye3ue3ayvf" +path="res://.godot/imported/create_cylinder.svg-476a4bc6152ac152d747a20ef15c4e74.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/create_cylinder.svg" +dest_files=["res://.godot/imported/create_cylinder.svg-476a4bc6152ac152d747a20ef15c4e74.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/create_prism.svg b/addons/cyclops_level_builder/art/icons/create_prism.svg new file mode 100644 index 00000000..782f75c3 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/create_prism.svg @@ -0,0 +1,50 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/create_prism.svg.import b/addons/cyclops_level_builder/art/icons/create_prism.svg.import new file mode 100644 index 00000000..b68d4aaf --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/create_prism.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cbmwkjbju75er" +path="res://.godot/imported/create_prism.svg-c58e90aecfc90ad3bbb2700eb92eba47.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/create_prism.svg" +dest_files=["res://.godot/imported/create_prism.svg-c58e90aecfc90ad3bbb2700eb92eba47.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/create_stairs.svg b/addons/cyclops_level_builder/art/icons/create_stairs.svg new file mode 100644 index 00000000..e598319c --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/create_stairs.svg @@ -0,0 +1,59 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/create_stairs.svg.import b/addons/cyclops_level_builder/art/icons/create_stairs.svg.import new file mode 100644 index 00000000..53de7b92 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/create_stairs.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bwq4w4vf8um1f" +path="res://.godot/imported/create_stairs.svg-d5c3678feb9fe435beb3be7ad9e116de.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/create_stairs.svg" +dest_files=["res://.godot/imported/create_stairs.svg-d5c3678feb9fe435beb3be7ad9e116de.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/edit_clip.svg b/addons/cyclops_level_builder/art/icons/edit_clip.svg new file mode 100644 index 00000000..5f5fb580 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/edit_clip.svg @@ -0,0 +1,59 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/edit_clip.svg.import b/addons/cyclops_level_builder/art/icons/edit_clip.svg.import new file mode 100644 index 00000000..fc9b49fd --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/edit_clip.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bos2j51dp4j1s" +path="res://.godot/imported/edit_clip.svg-cb82adafad7dd137e6bfab5345612057.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/edit_clip.svg" +dest_files=["res://.godot/imported/edit_clip.svg-cb82adafad7dd137e6bfab5345612057.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/eye_closed.svg b/addons/cyclops_level_builder/art/icons/eye_closed.svg new file mode 100644 index 00000000..456f992d --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/eye_closed.svg @@ -0,0 +1,79 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/eye_closed.svg.import b/addons/cyclops_level_builder/art/icons/eye_closed.svg.import new file mode 100644 index 00000000..a5452b1d --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/eye_closed.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dlaqhkooso2ef" +path="res://.godot/imported/eye_closed.svg-dd0fa412d337f7ed88eb934f289592d2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/eye_closed.svg" +dest_files=["res://.godot/imported/eye_closed.svg-dd0fa412d337f7ed88eb934f289592d2.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/eye_open.svg b/addons/cyclops_level_builder/art/icons/eye_open.svg new file mode 100644 index 00000000..ad91ab0d --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/eye_open.svg @@ -0,0 +1,94 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/eye_open.svg.import b/addons/cyclops_level_builder/art/icons/eye_open.svg.import new file mode 100644 index 00000000..c2d8020b --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/eye_open.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dmu0ivr826rwb" +path="res://.godot/imported/eye_open.svg-c6da53c32ed6c8a148f0ba4dc1173f28.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/eye_open.svg" +dest_files=["res://.godot/imported/eye_open.svg-c6da53c32ed6c8a148f0ba4dc1173f28.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/material_brush.svg b/addons/cyclops_level_builder/art/icons/material_brush.svg new file mode 100644 index 00000000..7cefff0f --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/material_brush.svg @@ -0,0 +1,53 @@ + + + + + + + + + diff --git a/addons/cyclops_level_builder/art/icons/material_brush.svg.import b/addons/cyclops_level_builder/art/icons/material_brush.svg.import new file mode 100644 index 00000000..181a8a84 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/material_brush.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dw8s7hrmnu34j" +path="res://.godot/imported/material_brush.svg-d1bd5b1c19cc756ce31fd5eaeedcb121.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/material_brush.svg" +dest_files=["res://.godot/imported/material_brush.svg-d1bd5b1c19cc756ce31fd5eaeedcb121.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/move.svg b/addons/cyclops_level_builder/art/icons/move.svg new file mode 100644 index 00000000..a42b891a --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/move.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/addons/cyclops_level_builder/art/icons/move.svg.import b/addons/cyclops_level_builder/art/icons/move.svg.import new file mode 100644 index 00000000..4a42b418 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/move.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cqy2x1s41ypbt" +path.s3tc="res://.godot/imported/move.svg-ed763a44f715fed1ba9cd0ebb407610b.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/move.svg" +dest_files=["res://.godot/imported/move.svg-ed763a44f715fed1ba9cd0ebb407610b.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/rotate.svg b/addons/cyclops_level_builder/art/icons/rotate.svg new file mode 100644 index 00000000..e58de624 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/rotate.svg @@ -0,0 +1,47 @@ + + + + + + + + + diff --git a/addons/cyclops_level_builder/art/icons/rotate.svg.import b/addons/cyclops_level_builder/art/icons/rotate.svg.import new file mode 100644 index 00000000..dfb34442 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/rotate.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://1hu5mqwbm55w" +path="res://.godot/imported/rotate.svg-1a301defe8a7754cea1ea5ac0034fd8a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/rotate.svg" +dest_files=["res://.godot/imported/rotate.svg-1a301defe8a7754cea1ea5ac0034fd8a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/select_edge.svg b/addons/cyclops_level_builder/art/icons/select_edge.svg new file mode 100644 index 00000000..f7bf14bc --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/select_edge.svg @@ -0,0 +1,53 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/select_edge.svg.import b/addons/cyclops_level_builder/art/icons/select_edge.svg.import new file mode 100644 index 00000000..f2d0da5c --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/select_edge.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://d2da2j8ve48rt" +path="res://.godot/imported/select_edge.svg-740cff471ac1df58ecc957f9e83b9e91.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/select_edge.svg" +dest_files=["res://.godot/imported/select_edge.svg-740cff471ac1df58ecc957f9e83b9e91.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/select_face.svg b/addons/cyclops_level_builder/art/icons/select_face.svg new file mode 100644 index 00000000..af6128b5 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/select_face.svg @@ -0,0 +1,55 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/select_face.svg.import b/addons/cyclops_level_builder/art/icons/select_face.svg.import new file mode 100644 index 00000000..b39d9d8b --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/select_face.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bi27fw31w4ssi" +path="res://.godot/imported/select_face.svg-3dcc771c6179443bd23c42d8d78eed16.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/select_face.svg" +dest_files=["res://.godot/imported/select_face.svg-3dcc771c6179443bd23c42d8d78eed16.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/select_vertex.svg b/addons/cyclops_level_builder/art/icons/select_vertex.svg new file mode 100644 index 00000000..d1ec765b --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/select_vertex.svg @@ -0,0 +1,54 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/select_vertex.svg.import b/addons/cyclops_level_builder/art/icons/select_vertex.svg.import new file mode 100644 index 00000000..8c93226e --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/select_vertex.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cwn58lev5oopd" +path="res://.godot/imported/select_vertex.svg-d1eacdb77752f52ac8784bfc74ae896a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/select_vertex.svg" +dest_files=["res://.godot/imported/select_vertex.svg-d1eacdb77752f52ac8784bfc74ae896a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/snap.svg b/addons/cyclops_level_builder/art/icons/snap.svg new file mode 100644 index 00000000..feda5b57 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/snap.svg @@ -0,0 +1,54 @@ + + + + + + + + diff --git a/addons/cyclops_level_builder/art/icons/snap.svg.import b/addons/cyclops_level_builder/art/icons/snap.svg.import new file mode 100644 index 00000000..4f1d7bc6 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/snap.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dloyvoq8piwx0" +path="res://.godot/imported/snap.svg-39023523aa8158257ae64cb4fbbc5761.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/snap.svg" +dest_files=["res://.godot/imported/snap.svg-39023523aa8158257ae64cb4fbbc5761.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/snap_grid.svg b/addons/cyclops_level_builder/art/icons/snap_grid.svg new file mode 100644 index 00000000..2edf8a81 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/snap_grid.svg @@ -0,0 +1,54 @@ + + + + + + + + + diff --git a/addons/cyclops_level_builder/art/icons/snap_grid.svg.import b/addons/cyclops_level_builder/art/icons/snap_grid.svg.import new file mode 100644 index 00000000..36070ea7 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/snap_grid.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c6mucdu7wcbkm" +path.s3tc="res://.godot/imported/snap_grid.svg-12ab1553ba1ac0d6d8b56aa201eba887.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/snap_grid.svg" +dest_files=["res://.godot/imported/snap_grid.svg-12ab1553ba1ac0d6d8b56aa201eba887.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/snap_vertex.svg b/addons/cyclops_level_builder/art/icons/snap_vertex.svg new file mode 100644 index 00000000..0fe7426e --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/snap_vertex.svg @@ -0,0 +1,52 @@ + + + + + + + + diff --git a/addons/cyclops_level_builder/art/icons/snap_vertex.svg.import b/addons/cyclops_level_builder/art/icons/snap_vertex.svg.import new file mode 100644 index 00000000..ac9e235f --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/snap_vertex.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c0x011okomj8n" +path.s3tc="res://.godot/imported/snap_vertex.svg-0a9ae24d62bafce943c0c8ecb890f083.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/snap_vertex.svg" +dest_files=["res://.godot/imported/snap_vertex.svg-0a9ae24d62bafce943c0c8ecb890f083.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/uv_lock.svg b/addons/cyclops_level_builder/art/icons/uv_lock.svg new file mode 100644 index 00000000..80d93f1e --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/uv_lock.svg @@ -0,0 +1,62 @@ + + + + + + + + + + diff --git a/addons/cyclops_level_builder/art/icons/uv_lock.svg.import b/addons/cyclops_level_builder/art/icons/uv_lock.svg.import new file mode 100644 index 00000000..7eb9d42c --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/uv_lock.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cmj6dd7haiga4" +path="res://.godot/imported/uv_lock.svg-ce9938594c32c381355d5711b9169a38.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/uv_lock.svg" +dest_files=["res://.godot/imported/uv_lock.svg-ce9938594c32c381355d5711b9169a38.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/vertex_color_brush.svg b/addons/cyclops_level_builder/art/icons/vertex_color_brush.svg new file mode 100644 index 00000000..3a9c0757 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/vertex_color_brush.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + diff --git a/addons/cyclops_level_builder/art/icons/vertex_color_brush.svg.import b/addons/cyclops_level_builder/art/icons/vertex_color_brush.svg.import new file mode 100644 index 00000000..42b3b56d --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/vertex_color_brush.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://be3f2j6mnl1yb" +path="res://.godot/imported/vertex_color_brush.svg-654b161cf9f3eb1f136399d25f961329.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/vertex_color_brush.svg" +dest_files=["res://.godot/imported/vertex_color_brush.svg-654b161cf9f3eb1f136399d25f961329.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/icons/xray_normal.svg b/addons/cyclops_level_builder/art/icons/xray_normal.svg new file mode 100644 index 00000000..1bf36c78 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/xray_normal.svg @@ -0,0 +1,108 @@ + + + +image/svg+xml diff --git a/addons/cyclops_level_builder/art/icons/xray_normal.svg.import b/addons/cyclops_level_builder/art/icons/xray_normal.svg.import new file mode 100644 index 00000000..ad4e9c45 --- /dev/null +++ b/addons/cyclops_level_builder/art/icons/xray_normal.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bs54uhn80ykrr" +path="res://.godot/imported/xray_normal.svg-01f10482e0b64ab4c53e5074b26f3f91.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/art/icons/xray_normal.svg" +dest_files=["res://.godot/imported/xray_normal.svg-01f10482e0b64ab4c53e5074b26f3f91.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.5 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/art/materialTest.glb b/addons/cyclops_level_builder/art/materialTest.glb new file mode 100644 index 0000000000000000000000000000000000000000..8f993f0958deaf20248a25a3d17a0c219737ec74 GIT binary patch literal 3668 zcmc%~O>Y}Tbeg6~TWA~74AZ>xlS*>3HP zX^^Hoqm41`^N1%w7ALepzdA|cC{AmAFsVHo@TkX=+V*Fy+L>9m>XuJ6dd8D9j3ZDs z>Woe_ns&hfZLk7MY2$EAqhJU;+7>d6Msbg$fW4Z$no(mqmG7mqpv-VS@bM;lo(;^1Q%V7JhN#7;ZOF3*C&AnfkPqy9<6Q?MS>PLT3uJcyGQ zL08=JkkvgVmaE%_ZM&wcu{v{2!!TUk*GrGJ0P`n!|+VgunkSe%!(M&8{9jQ z;VyV}dot0+^!mK(jOh#J&X{Q#HZyETH+|Q$nGKm%FSJ;);$rEEc%+Nh6R!bvmbXA` zw-nlS;2vsdb57!w(4MtG=*qQq-6#d0SG7uT_+MBcdimnI!%D$T{GXdXfARFnd+UzJ z;8RxnWrdJu+k5cuoo^KTje<*_3Z-0yWgKa_H!krj^--qkUEqHoetQ0c|JTOPOFzAl z_#Z#!8)ba`lYjn1{=dKfdZAy&Q3w4 zn8(L=nJN_kedO>f@llF?%KXb>y^D_Yhq2_E=fCU|ZRY7;Jog<0Mxxksa3db3gb0=p(>Z`LO=S%v*Su5kHU-YX2MV|s) zhBe^jMIWmW`J1o__IF_?Y1BhG@+CZ1^pG!Ul%qbCyclopsBlock: + var block:CyclopsBlock = preload("res://addons/cyclops_level_builder/nodes/cyclops_block.gd").new() + blocks_root.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.name = GeneralUtil.find_unique_name(blocks_root, block_name_prefix) + block.global_transform = set_pivot_xform.affine_inverse() + block.collision_type = collision_type + block.collision_layer = collision_layers + block.collision_mask = collision_mask + + if mat: + block.materials.append(mat) + + return block + + +func do_it(): +# var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path) + var blocks_root:Node = builder.get_node(blocks_root_path) + + var material:Material + var material_id:int = -1 + if ResourceLoader.exists(material_path): + var mat = load(material_path) + if mat is Material: + material_id = 0 + material = mat + + var set_pivot_xform:Transform3D = Transform3D(Basis.IDENTITY, -origin) + + if tube: + var bounding_points_inner:PackedVector3Array = MathUtil.create_circle_points(origin, axis_normal, radius_inner, segments) + var bounding_points_outer:PackedVector3Array = MathUtil.create_circle_points(origin, axis_normal, radius_outer, segments) + + for p_idx0 in bounding_points_inner.size(): + var p_idx1:int = wrap(p_idx0 + 1, 0, bounding_points_inner.size()) + + var block:CyclopsBlock = create_block(blocks_root, set_pivot_xform, material) + + var mesh:ConvexVolume = ConvexVolume.new() + var base_points:PackedVector3Array = [bounding_points_inner[p_idx0], bounding_points_inner[p_idx1], bounding_points_outer[p_idx1], bounding_points_outer[p_idx0]] + + mesh.init_prism(base_points, axis_normal * height, uv_transform, material_id) + mesh.transform(set_pivot_xform) + +# block.block_data = mesh.to_convex_block_data() + block.mesh_vector_data = mesh.to_mesh_vector_data() + block_paths.append(block.get_path()) + + else: + var block:CyclopsBlock = create_block(blocks_root, set_pivot_xform, material) + + var bounding_points:PackedVector3Array = MathUtil.create_circle_points(origin, axis_normal, radius_outer, segments) + var mesh:ConvexVolume = ConvexVolume.new() + mesh.init_prism(bounding_points, axis_normal * height, uv_transform, material_id) + mesh.transform(set_pivot_xform) + + block.mesh_vector_data = mesh.to_mesh_vector_data() + block_paths.append(block.get_path()) + +func undo_it(): + for path in block_paths: + var block:CyclopsBlock = builder.get_node(path) + block.queue_free() diff --git a/addons/cyclops_level_builder/commands/cmd_add_cylinder.gd.uid b/addons/cyclops_level_builder/commands/cmd_add_cylinder.gd.uid new file mode 100644 index 00000000..041328a1 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_add_cylinder.gd.uid @@ -0,0 +1 @@ +uid://dy3cy7ot2rpwd diff --git a/addons/cyclops_level_builder/commands/cmd_add_prism.gd b/addons/cyclops_level_builder/commands/cmd_add_prism.gd new file mode 100644 index 00000000..0c6ca141 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_add_prism.gd @@ -0,0 +1,80 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandAddPrism +extends CyclopsCommand + +@export var blocks_root_path:NodePath +@export var block_name:String +@export var base_polygon:PackedVector3Array +@export var extrude:Vector3 +#var local_transform:Transform3D +@export var uv_transform:Transform2D +@export var material_path:String +@export var collision_type:Collision.Type = Collision.Type.STATIC +@export var collision_layers:int = 1 +@export var collision_mask:int = 1 + +#Private +var block_path:NodePath + +func _init(): + command_name = "Add prism" + +func do_it(): + var block:CyclopsBlock = preload("res://addons/cyclops_level_builder/nodes/cyclops_block.gd").new() + + var blocks_root:Node = builder.get_node(blocks_root_path) + blocks_root.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.name = block_name + #block.transform = local_transform + block.collision_type = collision_type + block.collision_layer = collision_layers + block.collision_mask = collision_mask + + var material_id:int = -1 + if ResourceLoader.exists(material_path): + var mat = load(material_path) + if mat is Material: + material_id = 0 + block.materials.append(mat) + + var set_pivot_xform:Transform3D = Transform3D(Basis.IDENTITY, -base_polygon[0]) + + var mesh:ConvexVolume = ConvexVolume.new() + mesh.init_prism(base_polygon, extrude, uv_transform, material_id) + mesh.transform(set_pivot_xform) + + block.mesh_vector_data = mesh.to_mesh_vector_data() + block_path = block.get_path() + + block.global_transform = set_pivot_xform.affine_inverse() +# print("AddBlockCommand do_it() %s %s" % [block_inst_id, bounds]) + +func undo_it(): + var block:CyclopsBlock = builder.get_node(block_path) + block.queue_free() + +# print("AddBlockCommand undo_it()") diff --git a/addons/cyclops_level_builder/commands/cmd_add_prism.gd.uid b/addons/cyclops_level_builder/commands/cmd_add_prism.gd.uid new file mode 100644 index 00000000..9569d8fd --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_add_prism.gd.uid @@ -0,0 +1 @@ +uid://cph6t2vxpldsj diff --git a/addons/cyclops_level_builder/commands/cmd_add_stairs.gd b/addons/cyclops_level_builder/commands/cmd_add_stairs.gd new file mode 100644 index 00000000..fdc0f2d9 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_add_stairs.gd @@ -0,0 +1,139 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandAddStairs +extends CyclopsCommand + +#var blocks_root_inst_id:int +var blocks_root_path:NodePath +var block_name_prefix:String +var floor_normal:Vector3 +var drag_origin:Vector3 +var base_drag_cur:Vector3 +var block_drag_cur:Vector3 +var step_height:float = .25 +var step_depth:float = .5 +var direction:int = 0 + +var uv_transform:Transform2D +var material_path:String +var collision_type:Collision.Type = Collision.Type.STATIC +var collision_layers:int = 1 +var collision_mask:int = 1 + +#Private data +var block_paths:Array[NodePath] + +func _init(): + command_name = "Add stairs" + +func create_block(blocks_root:Node, mat:Material)->CyclopsBlock: + var block:CyclopsBlock = preload("res://addons/cyclops_level_builder/nodes/cyclops_block.gd").new() + blocks_root.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.name = GeneralUtil.find_unique_name(blocks_root, block_name_prefix) + block.collision_type = collision_type + block.collision_layer = collision_layers + block.collision_mask = collision_mask + + if mat: + block.materials.append(mat) + + return block + + +func do_it(): + var blocks_root:Node = builder.get_node(blocks_root_path) + + var material:Material + var material_id:int = -1 + if ResourceLoader.exists(material_path): + var mat = load(material_path) + if mat is Material: + material_id = 0 + material = mat + + var tan_bi:Array[Vector3] = MathUtil.get_axis_aligned_tangent_and_binormal(floor_normal) + var u_normal:Vector3 = tan_bi[0] + var v_normal:Vector3 = tan_bi[1] + + #Rotate ccw by 90 degree increments + match direction: + 1: + var tmp:Vector3 = u_normal + u_normal = -v_normal + v_normal = tmp + 2: + u_normal = -u_normal + v_normal = -v_normal + 3: + var tmp:Vector3 = -u_normal + u_normal = v_normal + v_normal = tmp + + var u_span:Vector3 = (base_drag_cur - drag_origin).project(u_normal) + var v_span:Vector3 = (base_drag_cur - drag_origin).project(v_normal) + + var stairs_origin:Vector3 = drag_origin + if u_span.dot(u_normal) < 0: + stairs_origin += u_span + u_span = -u_span + if v_span.dot(v_normal) < 0: + stairs_origin += v_span + v_span = -v_span + + #Stairs should ascend along v axis + var height_offset = block_drag_cur - base_drag_cur + if height_offset.dot(floor_normal) < 0: + return + var num_steps:int = min(v_span.length() / step_depth, height_offset.length() / step_height) + + var max_height:float = floor(height_offset.length() / step_height) * step_height + + var step_span:Vector3 = v_normal * step_depth + for i in num_steps: + var base_points:PackedVector3Array = [stairs_origin + step_span * i, \ + stairs_origin + u_span + step_span * i, \ + stairs_origin + u_span + step_span * (i + 1), \ + stairs_origin + step_span * (i + 1)] + + var pivot_xform:Transform3D = Transform3D(Basis.IDENTITY, -base_points[0]) + + var mesh:ConvexVolume = ConvexVolume.new() + mesh.init_prism(base_points, \ + floor_normal * (max_height - step_height * i), \ + uv_transform, material_id) + mesh.transform(pivot_xform) + + var block:CyclopsBlock = create_block(blocks_root, material) + + block.mesh_vector_data = mesh.to_mesh_vector_data() + block.global_transform = pivot_xform.affine_inverse() + block_paths.append(block.get_path()) + + +func undo_it(): + for path in block_paths: + var block:CyclopsBlock = builder.get_node(path) + block.queue_free() diff --git a/addons/cyclops_level_builder/commands/cmd_add_stairs.gd.uid b/addons/cyclops_level_builder/commands/cmd_add_stairs.gd.uid new file mode 100644 index 00000000..66efab33 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_add_stairs.gd.uid @@ -0,0 +1 @@ +uid://qwu5f3ith7uh diff --git a/addons/cyclops_level_builder/commands/cmd_add_vertices.gd b/addons/cyclops_level_builder/commands/cmd_add_vertices.gd new file mode 100644 index 00000000..1f233693 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_add_vertices.gd @@ -0,0 +1,74 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandAddVertices +extends CyclopsCommand + + +#Public +var points_to_add:PackedVector3Array +var block_path:NodePath + +#Private +var tracked_block_data:MeshVectorData +var selected_points:PackedVector3Array + + +func _init(): + command_name = "Add vertices" + +func do_it(): + var block:CyclopsBlock = builder.get_node(block_path) + + if !tracked_block_data: + var tracked_vol:ConvexVolume = block.control_mesh + tracked_block_data = tracked_vol.to_mesh_vector_data() + + for v in tracked_vol.vertices: + if v.selected: + selected_points.append(v.point) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(tracked_block_data) + + var point_list:PackedVector3Array = vol.get_points() + var local_points = block.global_transform.affine_inverse() * points_to_add + point_list.append_array(local_points) + + var new_vol:ConvexVolume = ConvexVolume.new() + new_vol.init_from_points(point_list) + new_vol.copy_face_attributes(vol) + + + for v_idx in new_vol.vertices.size(): + var v:ConvexVolume.VertexInfo = new_vol.vertices[v_idx] + if selected_points.has(v.point): + v.selected = true + + block.mesh_vector_data = new_vol.to_mesh_vector_data() + + +func undo_it(): + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = tracked_block_data diff --git a/addons/cyclops_level_builder/commands/cmd_add_vertices.gd.uid b/addons/cyclops_level_builder/commands/cmd_add_vertices.gd.uid new file mode 100644 index 00000000..4fabd7cb --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_add_vertices.gd.uid @@ -0,0 +1 @@ +uid://b6bp1swuhk7hr diff --git a/addons/cyclops_level_builder/commands/cmd_clip_block.gd b/addons/cyclops_level_builder/commands/cmd_clip_block.gd new file mode 100644 index 00000000..65d5b49f --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_clip_block.gd @@ -0,0 +1,106 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandClipBlock +extends CyclopsCommand + +#Public data to set before activating command +var blocks_root_path:NodePath +var block_path:NodePath +var cut_plane:Plane +var uv_transform:Transform2D = Transform2D.IDENTITY +var material_path:String = "" + +#Private +var block_sibling_name:String +var old_block_data:MeshVectorData +var old_mat_list:Array[Material] +var block_sibling_path:NodePath + +func _init(): + command_name = "Clip block" + +func get_material_index(mat_list:Array[Material], path:String)->int: + if path.is_empty(): + return -1 + for i in mat_list.size(): + var mat:Material = mat_list[i] + if mat != null && mat.resource_path == path: + return i + return -1 + +func do_it(): + var blocks_root:Node = builder.get_node(blocks_root_path) + var block:CyclopsBlock = builder.get_node(block_path) + + old_block_data = block.mesh_vector_data.duplicate() + old_mat_list = block.materials.duplicate() + + var new_mat_list0:Array[Material] = old_mat_list.duplicate() + + var cut_mat_idx = get_material_index(old_mat_list, material_path) + if cut_mat_idx == -1: + var mat = load(material_path) + if mat is Material: + cut_mat_idx = new_mat_list0.size() + new_mat_list0.append(mat) + + + var new_mat_list1:Array[Material] = new_mat_list0.duplicate() + + #var cut_plane_reverse:Plane = Plane(-cut_plane.normal, cut_plane.get_center()) + + var w2l:Transform3D = block.global_transform.affine_inverse() + var cut_plane_local:Plane = w2l * cut_plane + + var vol0:ConvexVolume = block.control_mesh.cut_with_plane(cut_plane_local, uv_transform, cut_mat_idx) + var vol1:ConvexVolume = block.control_mesh.cut_with_plane(MathUtil.flip_plane(cut_plane_local), uv_transform, cut_mat_idx) + + #Set data of existing block + block.mesh_vector_data = vol0.to_mesh_vector_data() + block.materials = new_mat_list0 + + #Create second block + var block_sibling:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + + blocks_root.add_child(block_sibling) + block_sibling.owner = builder.get_editor_interface().get_edited_scene_root() + block_sibling.name = block_sibling_name + block_sibling.global_transform = block.global_transform + #block_sibling.selected = block.selected + block_sibling_path = block_sibling.get_path() + + block_sibling.mesh_vector_data = vol1.to_mesh_vector_data() + block_sibling.materials = new_mat_list1 + + +func undo_it(): + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = old_block_data + block.materials = old_mat_list.duplicate() + + var block_sibling:CyclopsBlock = builder.get_node(block_sibling_path) + block_sibling.queue_free() + + diff --git a/addons/cyclops_level_builder/commands/cmd_clip_block.gd.uid b/addons/cyclops_level_builder/commands/cmd_clip_block.gd.uid new file mode 100644 index 00000000..bb15ed1a --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_clip_block.gd.uid @@ -0,0 +1 @@ +uid://b85cikeycwo18 diff --git a/addons/cyclops_level_builder/commands/cmd_delete_blocks.gd b/addons/cyclops_level_builder/commands/cmd_delete_blocks.gd new file mode 100644 index 00000000..104aa350 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_delete_blocks.gd @@ -0,0 +1,82 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandDeleteBlocks +extends CyclopsCommand + +#Public +var block_paths:Array[NodePath] + +#Private +var tracked_blocks:Array[TrackedBlock] + +func _init(): + command_name = "Delete blocks" + +func will_change_anything(): + if !block_paths.is_empty(): + return true + + return false + + +func do_it(): + #print("Delete do_it") + + if tracked_blocks.is_empty(): + var points:PackedVector3Array + + for path in block_paths: + var block:CyclopsBlock = builder.get_node(path) + var tracker:TrackedBlock = TrackedBlock.new(block) + tracked_blocks.append(tracker) + + #Delete source blocks + for block_path in block_paths: + var del_block:CyclopsBlock = builder.get_node(block_path) + del_block.get_parent().remove_child(del_block) + del_block.queue_free() + + +func undo_it(): + #print("Delete undo_it") + for tracked in tracked_blocks: + var parent = builder.get_node(tracked.path_parent) + + var block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + block.mesh_vector_data = tracked.data + block.materials = tracked.materials + block.name = tracked.name + #block.selected = tracked.selected + block.collision_type = tracked.collision_type + block.collision_layer = tracked.collision_layers + block.collision_mask = tracked.collision_mask + + parent.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.global_transform = tracked.world_xform + + + + diff --git a/addons/cyclops_level_builder/commands/cmd_delete_blocks.gd.uid b/addons/cyclops_level_builder/commands/cmd_delete_blocks.gd.uid new file mode 100644 index 00000000..d2e8d956 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_delete_blocks.gd.uid @@ -0,0 +1 @@ +uid://l1u1cie4f2ue diff --git a/addons/cyclops_level_builder/commands/cmd_duplicate_blocks.gd b/addons/cyclops_level_builder/commands/cmd_duplicate_blocks.gd new file mode 100644 index 00000000..b4d15443 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_duplicate_blocks.gd @@ -0,0 +1,90 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandDuplicateBlocks +extends CyclopsCommand + +#Public +var blocks_root_path:NodePath +var blocks_to_duplicate:Array[NodePath] +var move_offset:Vector3 +var lock_uvs:bool + +#Private +class BlockInfo extends RefCounted: + var new_block:CyclopsBlock + var source_data:MeshVectorData + var source_global_transform:Transform3D + + func _init(new_block:CyclopsBlock, source_data:MeshVectorData, source_global_transform:Transform3D): + self.new_block = new_block + self.source_data = source_data + self.source_global_transform = source_global_transform + +var added_blocks:Array[BlockInfo] + +func will_change_anything(): + return !added_blocks.is_empty() + +func do_it(): + if added_blocks.is_empty(): + + #Create new blocks + for block_path in blocks_to_duplicate: + var new_block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + + var source_block:CyclopsBlock = builder.get_node(block_path) + + var blocks_root:Node = builder.get_node(blocks_root_path) + new_block.name = GeneralUtil.find_unique_name(blocks_root, source_block.name) + blocks_root.add_child(new_block) + new_block.owner = builder.get_editor_interface().get_edited_scene_root() + new_block.global_transform = source_block.global_transform + new_block.mesh_vector_data = source_block.mesh_vector_data.duplicate() + + var info:BlockInfo = BlockInfo.new(new_block, source_block.mesh_vector_data, source_block.global_transform) + new_block.materials = source_block.materials + #new_block.selected = true + + added_blocks.append(info) + + for path in blocks_to_duplicate: + var block:CyclopsBlock = builder.get_node(path) + #block.selected = false + + for info in added_blocks: + + var new_xform:Transform3D = info.source_global_transform.translated(move_offset) + info.new_block.global_transform = new_xform + + +func undo_it(): + for block in added_blocks: + block.new_block.queue_free() + added_blocks = [] + + for path in blocks_to_duplicate: + var block:CyclopsBlock = builder.get_node(path) + #block.selected = true + diff --git a/addons/cyclops_level_builder/commands/cmd_duplicate_blocks.gd.uid b/addons/cyclops_level_builder/commands/cmd_duplicate_blocks.gd.uid new file mode 100644 index 00000000..758d7c0c --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_duplicate_blocks.gd.uid @@ -0,0 +1 @@ +uid://d176apihtd6bt diff --git a/addons/cyclops_level_builder/commands/cmd_intersect_block.gd b/addons/cyclops_level_builder/commands/cmd_intersect_block.gd new file mode 100644 index 00000000..6aad74b5 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_intersect_block.gd @@ -0,0 +1,152 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandIntersectBlock +extends CyclopsCommand + +class NewBlockInfo extends RefCounted: + var data:MeshVectorData + var materials:Array[Material] + var path:NodePath + var xform:Transform3D + #var centroid:Vector3 + +#Public +var block_paths:Array[NodePath] +var main_block_path:NodePath +var block_name_prefix:String = "Block_" + +#Private +var start_blocks:Array[TrackedBlock] +var main_block_cache:TrackedBlock +#var added_blocks:Array[NewBlockInfo] +var added_block:NewBlockInfo + +func _init(): + command_name = "Intersect blocks" + +func restore_tracked_block(tracked:TrackedBlock)->CyclopsBlock: + var parent = builder.get_node(tracked.path_parent) + + var block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + block.mesh_vector_data = tracked.data + block.materials = tracked.materials + block.name = tracked.name + #block.selected = tracked.selected + block.global_transform = tracked.world_xform + block.collision_type = tracked.collision_type + block.collision_layer = tracked.collision_layers + block.collision_mask = tracked.collision_mask + + parent.add_child(block) + + block.owner = builder.get_editor_interface().get_edited_scene_root() + + if tracked.selected: + var selection:EditorSelection = builder.get_editor_interface().get_selection() + selection.add_node(block) + + return block + +func will_change_anything()->bool: + var main_block:CyclopsBlock = builder.get_node(main_block_path) + var main_vol:ConvexVolume = main_block.control_mesh + main_vol = main_vol.transformed(main_block.global_transform) + + if block_paths.is_empty(): + return false + + for minuend_path in block_paths: + var minuend_block:CyclopsBlock = builder.get_node(minuend_path) + var minuend_vol:ConvexVolume = minuend_block.control_mesh + minuend_vol = minuend_vol.transformed(minuend_block.global_transform) + + if minuend_vol.intersects_convex_volume(main_vol): + return true + + return false + +func do_it(): + var main_block:CyclopsBlock = builder.get_node(main_block_path) + var snap_to_grid_util:SnapToGridUtil = CyclopsAutoload.calc_snap_to_grid_util() + + if start_blocks.is_empty(): + var main_vol:ConvexVolume = main_block.control_mesh + main_block_cache = TrackedBlock.new(main_block) + main_vol = main_vol.transformed(main_block.global_transform) + + for path in block_paths: + var block:CyclopsBlock = builder.get_node(path) + + var minuend_vol:ConvexVolume = block.control_mesh + minuend_vol = minuend_vol.transformed(block.global_transform) + if !minuend_vol.intersects_convex_volume(main_vol): + continue + + var tracker:TrackedBlock = TrackedBlock.new(block) + start_blocks.append(tracker) + + main_vol = minuend_vol.intersect(main_vol) + + + var block_info:NewBlockInfo = NewBlockInfo.new() + block_info.materials = main_block.materials + var xform_inv:Transform3D = main_block.global_transform.affine_inverse() + main_vol = main_vol.transformed(xform_inv) + block_info.data = main_vol.to_mesh_vector_data() + block_info.xform = main_block.global_transform + added_block = block_info + + #Delete source blocks + for block_info in start_blocks: + var del_block:CyclopsBlock = builder.get_node(block_info.path) + del_block.queue_free() + + main_block.queue_free() + + #Create blocks + var block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + var parent:Node = builder.get_node(start_blocks[0].path_parent) + parent.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.name = GeneralUtil.find_unique_name(parent, block_name_prefix) + block.mesh_vector_data = added_block.data + block.materials = added_block.materials + block.global_transform = added_block.xform + + added_block.path = block.get_path() + + + +func undo_it(): + + #for info in added_blocks: + var added_block_node:CyclopsBlock = builder.get_node(added_block.path) + added_block_node.queue_free() + + restore_tracked_block(main_block_cache) + + for tracked in start_blocks: + restore_tracked_block(tracked) + diff --git a/addons/cyclops_level_builder/commands/cmd_intersect_block.gd.uid b/addons/cyclops_level_builder/commands/cmd_intersect_block.gd.uid new file mode 100644 index 00000000..c33d1d51 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_intersect_block.gd.uid @@ -0,0 +1 @@ +uid://dylmln5xvn57b diff --git a/addons/cyclops_level_builder/commands/cmd_merge_blocks.gd b/addons/cyclops_level_builder/commands/cmd_merge_blocks.gd new file mode 100644 index 00000000..842e7069 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_merge_blocks.gd @@ -0,0 +1,148 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandMergeBlocks +extends CyclopsCommand + +#Public +var block_paths:Array[NodePath] +var block_name_prefix:String = "Block_" + +#Private +var tracked_blocks:Array[TrackedBlock] +var merged_block_data:MeshVectorData +var merged_mat_list:Array[Material] +var merged_block_path:NodePath +var world_pivot:Vector3 + +func _init(): + command_name = "Merge blocks" + +func get_best_face(centroid:Vector3, ref_list:Array[NodePath])->Array: + var best_face:ConvexVolume.FaceInfo + var best_dist:float = INF + var best_block:CyclopsBlock + + for block_path in ref_list: + var block:CyclopsBlock = builder.get_node(block_path) + var vol:ConvexVolume = block.control_mesh + for f in vol.faces: + var face_center:Vector3 = f.get_centroid() + var offset:float = centroid.distance_squared_to(face_center) + if offset < best_dist: + best_dist = offset + best_face = f + best_block = block + + if best_face.material_id == -1: + return [best_face, null] + return [best_face, best_block.materials[best_face.material_id]] + +func copy_face_attributes(target:ConvexVolume, ref_list:Array[NodePath])->Array[Material]: + var mat_list:Array[Material] + + for f in target.faces: + var centroid:Vector3 = f.get_centroid() + var res:Array = get_best_face(centroid, ref_list) + var ref_face:ConvexVolume.FaceInfo = res[0] + var material:Material = res[1] + + var mat_idx:int = -1 + if material != null: + mat_idx = mat_list.find(material) + if mat_idx == -1: + mat_idx = mat_list.size() + mat_list.append(material) + + f.material_id = mat_idx + f.uv_transform = ref_face.uv_transform + f.selected = ref_face.selected + + return mat_list + +func do_it(): + + if tracked_blocks.is_empty(): + var points:PackedVector3Array + + var first_block:CyclopsBlock = builder.get_node(block_paths[0]) + world_pivot = first_block.global_transform.origin + + for path in block_paths: + var block:CyclopsBlock = builder.get_node(path) + var tracker:TrackedBlock = TrackedBlock.new(block) + tracked_blocks.append(tracker) + + var world_block:ConvexVolume = ConvexVolume.new() + world_block.init_from_mesh_vector_data(block.control_mesh.to_mesh_vector_data()) + world_block.transform(block.global_transform) + points.append_array(world_block.get_points()) + + var merged_vol:ConvexVolume = ConvexVolume.new() + merged_vol.init_from_points(points) + merged_mat_list = copy_face_attributes(merged_vol, block_paths) + merged_vol.translate(-world_pivot) + merged_block_data = merged_vol.to_mesh_vector_data() + + + + #Delete source blocks + for block_path in block_paths: + var del_block:CyclopsBlock = builder.get_node(block_path) + del_block.queue_free() + + #Create block + var block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + var parent:Node = builder.get_node(tracked_blocks[0].path_parent) + parent.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.name = GeneralUtil.find_unique_name(parent, block_name_prefix) + block.mesh_vector_data = merged_block_data + block.materials = merged_mat_list + block.global_transform = Transform3D.IDENTITY.translated(world_pivot) + #block.materials + + merged_block_path = block.get_path() + +func undo_it(): +# var blocks_root:CyclopsBlocks = builder.get_node(blocks_root_path) + var merged_block:CyclopsBlock = builder.get_node(merged_block_path) + merged_block.queue_free() + +# for i in blocks_to_merge.size(): + for tracked in tracked_blocks: + var parent = builder.get_node(tracked.path_parent) + + var block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + block.mesh_vector_data = tracked.data + block.materials = tracked.materials + block.name = tracked.name + #block.selected = tracked.selected + block.global_transform = tracked.world_xform + block.collision_type = tracked.collision_type + block.collision_layer = tracked.collision_layers + block.collision_mask = tracked.collision_mask + + parent.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() diff --git a/addons/cyclops_level_builder/commands/cmd_merge_blocks.gd.uid b/addons/cyclops_level_builder/commands/cmd_merge_blocks.gd.uid new file mode 100644 index 00000000..3346c0f5 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_merge_blocks.gd.uid @@ -0,0 +1 @@ +uid://dx21ct5440wfh diff --git a/addons/cyclops_level_builder/commands/cmd_merge_vertices.gd b/addons/cyclops_level_builder/commands/cmd_merge_vertices.gd new file mode 100644 index 00000000..676ae26c --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_merge_vertices.gd @@ -0,0 +1,142 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandMergeVertices +extends CyclopsCommand + + +class BlockVertexChanges extends RefCounted: + var block_path:NodePath + var vertex_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +#Private +var block_map:Dictionary = {} + +#Public +var merge_point:Vector3 + +enum MergeType { POINT, CENTER, FIRST, LAST } +var merge_type:MergeType = MergeType.CENTER + +func add_vertex(block_path:NodePath, index:int): + add_vertices(block_path, [index]) + +func add_vertices(block_path:NodePath, indices:Array[int]): +# print("adding vertex %s %s" % [block_path, indices]) + var changes:BlockVertexChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockVertexChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data.duplicate() + block_map[block_path] = changes + + for index in indices: + if !changes.vertex_indices.has(index): + changes.vertex_indices.append(index) + +func _init(): + command_name = "Move vertices" + + +func do_it(): +# print("move verts do_it") + for block_path in block_map.keys(): + + var block:CyclopsBlock = builder.get_node(block_path) + var w2l:Transform3D = block.global_transform.affine_inverse() + + var rec:BlockVertexChanges = block_map[block_path] + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + var selected_points:PackedVector3Array + var new_points:PackedVector3Array + for v_idx in vol.vertices.size(): + if !rec.vertex_indices.has(v_idx): + var p:Vector3 = vol.vertices[v_idx].point + new_points.append(p) + + var merge_point_local:Vector3 + match merge_type: + MergeType.POINT: + merge_point_local = w2l * merge_point + pass + MergeType.CENTER: + var centroid:Vector3 + var count:int = 0 + for v_idx in vol.vertices.size(): + if rec.vertex_indices.has(v_idx): + var p:Vector3 = vol.vertices[v_idx].point + centroid += p + count += 1 + centroid /= count + merge_point_local = centroid + MergeType.FIRST: + merge_point_local = vol.vertices[rec.vertex_indices[0]].point + MergeType.LAST: + merge_point_local = vol.vertices[rec.vertex_indices[-1]].point + + + new_points.append(merge_point_local) + selected_points.append(merge_point_local) + + var new_vol:ConvexVolume = ConvexVolume.new() + new_vol.init_from_points(new_points) + + new_vol.copy_face_attributes(vol) + + for v_idx in new_vol.vertices.size(): + var v:ConvexVolume.VertexInfo = new_vol.vertices[v_idx] +# print ("vol point %s " % v.point) + if selected_points.has(v.point): +# print("set sel") + v.selected = true + + block.mesh_vector_data = new_vol.to_mesh_vector_data() + +func undo_it(): +# print("move verts undo_it") + for block_path in block_map.keys(): + var rec:BlockVertexChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data + +func will_change_anything()->bool: + for path in block_map: + var rec:BlockVertexChanges = block_map[path] + match merge_type: + MergeType.POINT: + if rec.vertex_indices.size() >= 1: + return true + _: + if rec.vertex_indices.size() >= 2: + return true + + return false + diff --git a/addons/cyclops_level_builder/commands/cmd_merge_vertices.gd.uid b/addons/cyclops_level_builder/commands/cmd_merge_vertices.gd.uid new file mode 100644 index 00000000..b68c7090 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_merge_vertices.gd.uid @@ -0,0 +1 @@ +uid://bk2reor7mbhes diff --git a/addons/cyclops_level_builder/commands/cmd_move_edges.gd b/addons/cyclops_level_builder/commands/cmd_move_edges.gd new file mode 100644 index 00000000..84f044bd --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_move_edges.gd @@ -0,0 +1,150 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandMoveEdges +extends CyclopsCommand + + +class BlockEdgeChanges extends RefCounted: + var block_path:NodePath + var edge_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +#Public +var move_offset:Vector3 = Vector3.ZERO + +#Private +var block_map:Dictionary = {} + +func add_edge(block_path:NodePath, index:int): + add_edges(block_path, [index]) + +func add_edges(block_path:NodePath, indices:Array[int]): + var changes:BlockEdgeChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockEdgeChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data + block_map[block_path] = changes + + for index in indices: + if !changes.edge_indices.has(index): + changes.edge_indices.append(index) + +func _init(): + command_name = "Move edges" + + +func do_it(): +# print("cmd move edges- DO IT") + + for block_path in block_map.keys(): + +# print("%s" % block_path) + + var block:CyclopsBlock = builder.get_node(block_path) + var rec:BlockEdgeChanges = block_map[block_path] + +# print("rec %s" % rec) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + +# print("init done") + var w2l:Transform3D = block.global_transform.affine_inverse() + var move_offset_local = w2l.basis * move_offset + #print("move_offset ", move_offset) + #print("move_offset_local ", move_offset_local) + + var vert_indices:PackedInt32Array + for edge_index in rec.edge_indices: + var e:ConvexVolume.EdgeInfo = vol.edges[edge_index] + if !vert_indices.has(e.start_index): + vert_indices.append(e.start_index) + if !vert_indices.has(e.end_index): + vert_indices.append(e.end_index) + + for v_idx in vert_indices: + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + v.point += move_offset_local + + block.mesh_vector_data = vol.to_mesh_vector_data() +#### + #var moved_vert_indices:PackedInt32Array + #var new_points:PackedVector3Array + #var new_sel_centroids:PackedVector3Array + #var moved_indices:Array[int] = [] + #for edge_index in rec.edge_indices: + #var e:ConvexVolume.EdgeInfo = vol.edges[edge_index] + #var v0:ConvexVolume.VertexInfo = vol.vertices[e.start_index] + #var v1:ConvexVolume.VertexInfo = vol.vertices[e.end_index] + #if e.selected: + #new_sel_centroids.append((v0.point + v1.point) / 2 + move_offset_local) + # + #if !moved_indices.has(e.start_index): + #new_points.append(v0.point + move_offset_local) + #moved_indices.append(e.start_index) + #if !moved_indices.has(e.end_index): + #new_points.append(v1.point + move_offset_local) + #moved_indices.append(e.end_index) + #else: + #if !moved_indices.has(e.start_index): + #new_points.append(v0.point + move_offset_local) + #moved_indices.append(e.start_index) + #if !moved_indices.has(e.end_index): + #new_points.append(v1.point + move_offset_local) + #moved_indices.append(e.end_index) + # + #for v_idx in vol.vertices.size(): + #if !moved_indices.has(v_idx): + #new_points.append(vol.vertices[v_idx].point) + ##print("new points_ %s" % new_points) + # + #var new_vol:ConvexVolume = ConvexVolume.new() + #new_vol.init_from_points(new_points) +# + #new_vol.copy_face_attributes(vol) +# + ##print("new init done") + # + ##Copy selection data + #for e_idx in new_vol.edges.size(): + #var e_new:ConvexVolume.EdgeInfo = new_vol.edges[e_idx] + #var centroid:Vector3 = (new_vol.vertices[e_new.start_index].point + new_vol.vertices[e_new.end_index].point) / 2 +## print ("vol point %s " % v1.point) + #if new_sel_centroids.has(centroid): +## print("set sel") + #e_new.selected = true +# + #block.mesh_vector_data = new_vol.to_mesh_vector_data() + + +func undo_it(): + for block_path in block_map.keys(): + var rec:BlockEdgeChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data diff --git a/addons/cyclops_level_builder/commands/cmd_move_edges.gd.uid b/addons/cyclops_level_builder/commands/cmd_move_edges.gd.uid new file mode 100644 index 00000000..dcc67082 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_move_edges.gd.uid @@ -0,0 +1 @@ +uid://b26mehllrcii5 diff --git a/addons/cyclops_level_builder/commands/cmd_move_face_planar.gd b/addons/cyclops_level_builder/commands/cmd_move_face_planar.gd new file mode 100644 index 00000000..1db13325 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_move_face_planar.gd @@ -0,0 +1,102 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandMoveFacePlanar +extends CyclopsCommand + +#Public data to set before activating command +var blocks_root_path:NodePath +var block_path:NodePath +var move_dir_normal:Vector3 +var move_amount:float +var face_index:int +var lock_uvs:bool = false + + +#Private +var block_name:String +var block_selected:bool +var tracked_block_data:MeshVectorData + +var deleted:bool = false + + +func _init(): + command_name = "Move face planar" + +func move_to(offset:Vector3, intermediate:bool): +# print("move_to off %s faceindex %s amount %s movedir %s" % [offset, face_index, move_amount, move_dir_normal]) + if !tracked_block_data: + var block:CyclopsBlock = builder.get_node(block_path) + + block_name = block.name + block_selected = block.selected + tracked_block_data = block.mesh_vector_data + + var ctl_mesh:ConvexVolume = ConvexVolume.new() + ctl_mesh.init_from_mesh_vector_data(tracked_block_data) + var new_mesh:ConvexVolume = ctl_mesh.translate_face_plane(face_index, offset, lock_uvs) + + #print("offset %s" % offset) + #print("ctl_mesh %s" % ctl_mesh.get_points()) + + + var block:CyclopsBlock = builder.get_node(block_path) + + if new_mesh == null || new_mesh.is_empty(): + #print("new_mesh EMPTY") + block.block_data = null + if !intermediate: + block.queue_free() + deleted = true + return + + #print("new_mesh %s" % new_mesh.get_points()) + + var result_data:MeshVectorData = new_mesh.to_mesh_vector_data() + block.mesh_vector_data = result_data + + +func do_it_intermediate(): + move_to(move_dir_normal * move_amount, true) + +func do_it(): + move_to(move_dir_normal * move_amount, false) + +func undo_it(): + if deleted: + var block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + + var blocks_root:Node = builder.get_node(blocks_root_path) + blocks_root.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.mesh_vector_data = tracked_block_data + block.name = block_name + block.selected = block_selected + + deleted = false + return + + move_to(Vector3.ZERO, false) + diff --git a/addons/cyclops_level_builder/commands/cmd_move_face_planar.gd.uid b/addons/cyclops_level_builder/commands/cmd_move_face_planar.gd.uid new file mode 100644 index 00000000..bd5bdf68 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_move_face_planar.gd.uid @@ -0,0 +1 @@ +uid://dqb4leire88a5 diff --git a/addons/cyclops_level_builder/commands/cmd_move_faces.gd b/addons/cyclops_level_builder/commands/cmd_move_faces.gd new file mode 100644 index 00000000..75c93089 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_move_faces.gd @@ -0,0 +1,144 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandMoveFaces +extends CyclopsCommand + +class BlockFaceChanges extends RefCounted: + var block_path:NodePath + var face_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +#Public +var move_offset:Vector3 = Vector3.ZERO + +#Private +var block_map:Dictionary = {} + + +func add_face(block_path:NodePath, index:int): +# print("Adding face %s %s" % [block_path, index]) + add_faces(block_path, [index]) + +func add_faces(block_path:NodePath, indices:Array[int]): + var changes:BlockFaceChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockFaceChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data + block_map[block_path] = changes + + for index in indices: + if !changes.face_indices.has(index): + changes.face_indices.append(index) + + +func _init(): + command_name = "Move faces" + +func do_it(): +# print("cmd move edges- DO IT") + + for block_path in block_map.keys(): + +# print("%s" % block_path) + + var block:CyclopsBlock = builder.get_node(block_path) + var rec:BlockFaceChanges = block_map[block_path] + + var w2l:Transform3D = block.global_transform.affine_inverse() + var move_offset_local:Vector3 = w2l.basis * move_offset +# print("rec %s" % rec) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + var vert_indices:PackedInt32Array + for f_index in rec.face_indices: + var f:ConvexVolume.FaceInfo = vol.faces[f_index] + for v_idx in f.vertex_indices: + if !vert_indices.has(v_idx): + vert_indices.append(v_idx) + + for v_idx in vert_indices: + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + v.point += move_offset_local + + block.mesh_vector_data = vol.to_mesh_vector_data() + +#### +# print("init done") + + #var new_points:PackedVector3Array + #var new_sel_centroids:PackedVector3Array + #var moved_vert_indices:Array[int] = [] + #for face_index in rec.face_indices: + #var f:ConvexVolume.FaceInfo = vol.faces[face_index] + #var centroid:Vector3 = f.get_centroid() +## var v0:ConvexVolume.VertexInfo = vol.vertices[e.start_index] +## var v1:ConvexVolume.VertexInfo = vol.vertices[e.end_index] + #if f.selected: + #new_sel_centroids.append(centroid + move_offset_local) + # + #for v_idx in f.vertex_indices: + #if !moved_vert_indices.has(v_idx): + #new_points.append(vol.vertices[v_idx].point + move_offset_local) + #moved_vert_indices.append(v_idx) + #else: + #for v_idx in f.vertex_indices: + #if !moved_vert_indices.has(v_idx): + #new_points.append(vol.vertices[v_idx].point + move_offset_local) + #moved_vert_indices.append(v_idx) + # + #for v_idx in vol.vertices.size(): + #if !moved_vert_indices.has(v_idx): + #new_points.append(vol.vertices[v_idx].point) + ##print("new points_ %s" % new_points) + # + #var new_vol:ConvexVolume = ConvexVolume.new() + #new_vol.init_from_points(new_points) +# + #new_vol.copy_face_attributes(vol) + ##print("new init done") + # + ##Copy selection data + #for f_idx in new_vol.faces.size(): + #var f_new:ConvexVolume.FaceInfo = new_vol.faces[f_idx] + #var centroid:Vector3 = f_new.get_centroid() +## print ("vol point %s " % v1.point) + #if new_sel_centroids.has(centroid): +## print("set sel") + #f_new.selected = true +# + #block.mesh_vector_data = new_vol.to_mesh_vector_data() + + +func undo_it(): + for block_path in block_map.keys(): + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data diff --git a/addons/cyclops_level_builder/commands/cmd_move_faces.gd.uid b/addons/cyclops_level_builder/commands/cmd_move_faces.gd.uid new file mode 100644 index 00000000..4a8997dd --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_move_faces.gd.uid @@ -0,0 +1 @@ +uid://cyu7npkpwi0q2 diff --git a/addons/cyclops_level_builder/commands/cmd_move_vertices.gd b/addons/cyclops_level_builder/commands/cmd_move_vertices.gd new file mode 100644 index 00000000..b9f9d477 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_move_vertices.gd @@ -0,0 +1,117 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandMoveVertices +extends CyclopsCommand + +class BlockVertexChanges extends RefCounted: + var block_path:NodePath + var vertex_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +#Public +@export var move_offset:Vector3 = Vector3.ZERO +@export var triplanar_lock_uvs:bool = false + +#Private +var block_map:Dictionary = {} + + +func add_vertex(block_path:NodePath, index:int): + add_vertices(block_path, [index]) + +func add_vertices(block_path:NodePath, indices:Array[int]): +# print("adding vertex %s %s" % [block_path, indices]) + var changes:BlockVertexChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockVertexChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data.duplicate() + block_map[block_path] = changes + + for index in indices: + if !changes.vertex_indices.has(index): + changes.vertex_indices.append(index) + +func _init(): + command_name = "Move vertices" + +func do_it(): +# print("move verts do_it") + for block_path in block_map.keys(): + + var block:CyclopsBlock = builder.get_node(block_path) + var w2l:Transform3D = block.global_transform + w2l = w2l.affine_inverse() + var move_offset_local:Vector3 = w2l.basis * move_offset + + #print("move offset %s" % move_offset) + #print("move offset local %s" % move_offset_local) + + var rec:BlockVertexChanges = block_map[block_path] + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + for v_idx in vol.vertices.size(): + if rec.vertex_indices.has(v_idx): + vol.vertices[v_idx].point += move_offset_local + + block.mesh_vector_data = vol.to_mesh_vector_data() +##### + #var selected_points:PackedVector3Array + #var new_points:PackedVector3Array + #for v_idx in vol.vertices.size(): + #if rec.vertex_indices.has(v_idx): + #var p:Vector3 = vol.vertices[v_idx].point + move_offset_local + #new_points.append(p) + #selected_points.append(p) + #else: + #new_points.append(vol.vertices[v_idx].point) + # + # + #var new_vol:ConvexVolume = ConvexVolume.new() + #new_vol.init_from_points(new_points) + # + #new_vol.copy_face_attributes(vol) + # + #for v_idx in new_vol.vertices.size(): + #var v:ConvexVolume.VertexInfo = new_vol.vertices[v_idx] +## print ("vol point %s " % v.point) + #if selected_points.has(v.point): +## print("set sel") + #v.selected = true +# + #block.mesh_vector_data = new_vol.to_mesh_vector_data() + + +func undo_it(): +# print("move verts undo_it") + for block_path in block_map.keys(): + var rec:BlockVertexChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data diff --git a/addons/cyclops_level_builder/commands/cmd_move_vertices.gd.uid b/addons/cyclops_level_builder/commands/cmd_move_vertices.gd.uid new file mode 100644 index 00000000..36f61ba9 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_move_vertices.gd.uid @@ -0,0 +1 @@ +uid://dw6i1l4qvxpeh diff --git a/addons/cyclops_level_builder/commands/cmd_select_blocks.gd b/addons/cyclops_level_builder/commands/cmd_select_blocks.gd new file mode 100644 index 00000000..f605e0b7 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_select_blocks.gd @@ -0,0 +1,239 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSelectBlocks +extends CyclopsCommand + +#Public +var selection_type:Selection.Type = Selection.Type.REPLACE + +var block_paths:Array[NodePath] + +#Private +#var tracked_selected_blocks:Array[NodePath] +#var tracked_active_blocks:Array[NodePath] +var cached_selection:Array[NodePath] +var init:bool = false + +func _init(): + command_name = "Select blocks" + +#func will_change_anything()->bool: +# +# var active_path:NodePath +# if !block_paths.is_empty(): +# active_path = block_paths[0] +## print("will change active %s" % active_path) +# +# for child in builder.get_blocks(): +# if child is CyclopsBlock: +# var block:CyclopsBlock = child +# var path:NodePath = block.get_path() +# +# match selection_type: +# Selection.Type.REPLACE: +# if block.selected != block_paths.has(path): +# return true +# +# if block.active != (path == active_path): +# return true +# +# Selection.Type.ADD: +# if block_paths.has(path): +# if !block.selected: +# return true +# if block.active != (path == active_path): +# return true +# +# Selection.Type.SUBTRACT: +# if block_paths.has(path): +# if block.selected: +# return true +# +# Selection.Type.TOGGLE: +# if !block_paths.is_empty(): +# return true +# +## print("will chage anything false") +# return false + +func will_change_anything()->bool: + var selection:EditorSelection = builder.get_editor_interface().get_selection() + + var cur_node_list:Array[Node] = selection.get_selected_nodes() + if !init: + for node in cur_node_list: + cached_selection.append(node.get_path()) + init = true + + var cur_paths:Array[NodePath] + for node in selection.get_selected_nodes(): + cur_paths.append(node.get_path()) + + if selection_type == Selection.Type.REPLACE: + if cur_paths.size() != block_paths.size(): + return true + for i in cur_paths.size(): + if cur_paths[i] != block_paths[i]: + return true + return false + + + elif selection_type == Selection.Type.ADD: + for path in block_paths: + if !cur_paths.has(path): + return true + return false + + elif selection_type == Selection.Type.SUBTRACT: + for path in block_paths: + if cur_paths.has(path): + return true + return false + + elif selection_type == Selection.Type.TOGGLE: + if !block_paths.is_empty(): + return true + return false + + return false + +func do_it(): + var selection:EditorSelection = builder.get_editor_interface().get_selection() + + var cur_node_list:Array[Node] = selection.get_selected_nodes() + if !init: + cached_selection = cur_node_list.duplicate() + init = true + + var cur_paths:Array[NodePath] + for node in selection.get_selected_nodes(): + cur_paths.append(node.get_path()) + + if selection_type == Selection.Type.REPLACE: + selection.clear() + for path in block_paths: + var node:Node = builder.get_node(path) + selection.add_node(node) + + elif selection_type == Selection.Type.ADD: + for path in block_paths: + if !cur_paths.has(path): + var node:Node = builder.get_node(path) + selection.add_node(node) + + elif selection_type == Selection.Type.SUBTRACT: + for path in block_paths: + if cur_paths.has(path): + var node:Node = builder.get_node(path) + selection.remove_node(node) + + elif selection_type == Selection.Type.TOGGLE: + for path in block_paths: + var node:Node = builder.get_node(path) + + if cur_paths.has(path): + selection.remove_node(node) + else: + selection.add_node(node) + + +#func do_it_old(): +## print("sel verts do_it") +# +# #Cache state +# tracked_selected_blocks.clear() +# tracked_active_blocks.clear() +# +# +# var active_block:CyclopsBlock = builder.get_active_block() +# tracked_active_blocks.append(active_block.get_path()) +# +# for child in builder.get_selected_blocks(): +# var block:CyclopsBlock = child +# tracked_selected_blocks.append(block.get_path()) +# +# #Do selection +# var active_path:NodePath +# if !block_paths.is_empty(): +# active_path = block_paths[0] +# +# #print("do_it active %s" % active_path) +## print("Setting active %s" % active_path) +# for child in builder.get_blocks(): +# var block:CyclopsBlock = child +# var path:NodePath = block.get_path() +# +# match selection_type: +# Selection.Type.REPLACE: +# block.selected = block_paths.has(path) +# block.active = path == active_path +# Selection.Type.ADD: +# if block_paths.has(path): +# block.selected = true +# block.active = path == active_path +# Selection.Type.SUBTRACT: +# if block_paths.has(path): +# block.selected = false +# block.active = false +# Selection.Type.TOGGLE: +# #print("Check block %s" % path) +# #print("act %s sel %s" % [block.active, block.selected]) +# if path == active_path: +# #print("Match active") +# if !block.active: +# #print("Setting active %s" % block.name) +# block.active = true +# block.selected = true +# else: +# #print("Clearing active %s" % block.name) +# block.active = false +# block.selected = false +# else: +# if block_paths.has(path): +# #print("Setting sel") +# block.selected = !block.selected +# block.active = false +# +# builder.selection_changed.emit() + +func undo_it(): + var selection:EditorSelection = builder.get_editor_interface().get_selection() + selection.clear() + + for path in cached_selection: + var node:Node = builder.get_node(path) + selection.add_node(node) + +#func undo_it(): +# +# for child in builder.get_blocks(): +# if child is CyclopsBlock: +# var block:CyclopsBlock = child +# var path:NodePath = block.get_path() +# +# block.selected = tracked_selected_blocks.has(path) +# block.active = tracked_active_blocks.has(path) +# +# builder.selection_changed.emit() diff --git a/addons/cyclops_level_builder/commands/cmd_select_blocks.gd.uid b/addons/cyclops_level_builder/commands/cmd_select_blocks.gd.uid new file mode 100644 index 00000000..b1ffdcc1 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_select_blocks.gd.uid @@ -0,0 +1 @@ +uid://valdmtvvo1al diff --git a/addons/cyclops_level_builder/commands/cmd_select_edges.gd b/addons/cyclops_level_builder/commands/cmd_select_edges.gd new file mode 100644 index 00000000..6d4c7190 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_select_edges.gd @@ -0,0 +1,176 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSelectEdges +extends CyclopsCommand + +class BlockEdgeChanges extends RefCounted: + var block_path:NodePath + var edge_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +#Public +var selection_type:Selection.Type = Selection.Type.REPLACE + +#Private +var block_map:Dictionary = {} + + +func add_edge(block_path:NodePath, index:int): + add_edges(block_path, [index]) + +func add_edges(block_path:NodePath, indices:Array[int]): + var changes:BlockEdgeChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockEdgeChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data + block_map[block_path] = changes + + for index in indices: + if !changes.edge_indices.has(index): + changes.edge_indices.append(index) + + +func _init(): + command_name = "Select edges" + +func will_change_anything()->bool: + for block_path in block_map.keys(): + #print("path %s" % node_path) + + var rec:BlockEdgeChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + if !rec.edge_indices.is_empty(): + if vol.active_edge != rec.edge_indices[0]: + return true + + match selection_type: + Selection.Type.REPLACE: + for e_idx in vol.edges.size(): + var e:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if e.selected != rec.edge_indices.has(e_idx): + #print("will change SREP") + return true + Selection.Type.ADD: + for e_idx in rec.edge_indices: + var e:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if rec.edge_indices.has(e_idx): + if !e.selected: + #print("will change ADD") + return true + Selection.Type.SUBTRACT: + for e_idx in rec.edge_indices: + var e:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if rec.edge_indices.has(e_idx): + if e.selected: + #print("will change SUB") + return true + Selection.Type.TOGGLE: + #print("will change TOG") + return true + + return false + +func do_it(): +# print("sel edges do_it") + + for block_path in block_map.keys(): +# print("path %s" % block_path) + + var rec:BlockEdgeChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + if !rec.edge_indices.is_empty(): + var active_index:int = rec.edge_indices[0] + match selection_type: + Selection.Type.REPLACE: + vol.active_edge = active_index + Selection.Type.ADD: + vol.active_edge = active_index + Selection.Type.SUBTRACT: + if rec.edge_indices.has(vol.active_edge): + vol.active_edge = -1 + Selection.Type.TOGGLE: + if rec.edge_indices.has(vol.active_edge): + vol.active_edge = -1 + elif !vol.edges[active_index].selected: + vol.active_edge = active_index + + match selection_type: + Selection.Type.REPLACE: + for e_idx in vol.edges.size(): + var e:ConvexVolume.EdgeInfo = vol.edges[e_idx] + e.selected = rec.edge_indices.has(e_idx) + + Selection.Type.ADD: + for e_idx in vol.edges.size(): + var e:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if rec.edge_indices.has(e_idx): + e.selected = true + + Selection.Type.SUBTRACT: + for e_idx in vol.edges.size(): + var e:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if rec.edge_indices.has(e_idx): + e.selected = false + + Selection.Type.TOGGLE: + for e_idx in vol.edges.size(): + var e:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if rec.edge_indices.has(e_idx): + #print("flipping %s" % e.selected) + e.selected = !e.selected + + if vol.active_edge != -1: + if vol.active_edge >= vol.edges.size() || !vol.edges[vol.active_edge].selected: + vol.active_edge = -1 + + block.mesh_vector_data = vol.to_mesh_vector_data() + + builder.selection_changed.emit() + +func undo_it(): +# print("sel verts undo_it") + #print("sel vert undo_it()") + for block_path in block_map.keys(): + var rec:BlockEdgeChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data + + builder.selection_changed.emit() + + + + diff --git a/addons/cyclops_level_builder/commands/cmd_select_edges.gd.uid b/addons/cyclops_level_builder/commands/cmd_select_edges.gd.uid new file mode 100644 index 00000000..9b3a4094 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_select_edges.gd.uid @@ -0,0 +1 @@ +uid://ddmkhmc2w6krj diff --git a/addons/cyclops_level_builder/commands/cmd_select_faces.gd b/addons/cyclops_level_builder/commands/cmd_select_faces.gd new file mode 100644 index 00000000..8a6b296c --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_select_faces.gd @@ -0,0 +1,168 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSelectFaces +extends CyclopsCommand + +class BlockFaceChanges extends RefCounted: + var block_path:NodePath + var face_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +#Public +var selection_type:Selection.Type = Selection.Type.REPLACE + +#Private +var block_map:Dictionary = {} + +func add_face(block_path:NodePath, index:int): + add_faces(block_path, [index]) + +func add_faces(block_path:NodePath, indices:Array[int]): + var changes:BlockFaceChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockFaceChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data + block_map[block_path] = changes + + for index in indices: + if !changes.face_indices.has(index): + changes.face_indices.append(index) + + +func _init(): + command_name = "Select faces" + +func will_change_anything()->bool: + for block_path in block_map.keys(): + #print("path %s" % node_path) + + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + +# var active_idx:int = -1 + if !rec.face_indices.is_empty(): + if vol.active_face != rec.face_indices[0]: + return true + + match selection_type: + Selection.Type.REPLACE: + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if f.selected != rec.face_indices.has(f_idx): + return true + Selection.Type.ADD: + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if rec.face_indices.has(f_idx): + if !f.selected: + return true + Selection.Type.SUBTRACT: + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if rec.face_indices.has(f_idx): + if f.selected: + return true + Selection.Type.TOGGLE: + return true + + return false + +func do_it(): + #print("sel verts do_it") + #print("sel vert do_it()") + for block_path in block_map.keys(): +# print("path %s" % block_path) + + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + if !rec.face_indices.is_empty(): + var active_index:int = rec.face_indices[0] + match selection_type: + Selection.Type.REPLACE: + vol.active_face = active_index + Selection.Type.ADD: + vol.active_face = active_index + Selection.Type.SUBTRACT: + if rec.face_indices.has(vol.active_face): + vol.active_face = -1 + Selection.Type.TOGGLE: + if rec.face_indices.has(vol.active_face): + vol.active_face = -1 + elif !vol.faces[active_index].selected: + vol.active_face = active_index + + +# print("face active index %s" % active_idx) + + match selection_type: + Selection.Type.REPLACE: + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + f.selected = rec.face_indices.has(f_idx) + + Selection.Type.ADD: + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if rec.face_indices.has(f_idx): + f.selected = true + + Selection.Type.SUBTRACT: + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if rec.face_indices.has(f_idx): + f.selected = false + + Selection.Type.TOGGLE: + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if rec.face_indices.has(f_idx): + f.selected = !f.selected + + if vol.active_face != -1: + if vol.active_face >= vol.faces.size() || !vol.faces[vol.active_face].selected: + vol.active_face = -1 + + block.mesh_vector_data = vol.to_mesh_vector_data() + builder.selection_changed.emit() + +func undo_it(): +# print("undo_it() select faces") + for block_path in block_map.keys(): + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data + + builder.selection_changed.emit() + diff --git a/addons/cyclops_level_builder/commands/cmd_select_faces.gd.uid b/addons/cyclops_level_builder/commands/cmd_select_faces.gd.uid new file mode 100644 index 00000000..8d4a1544 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_select_faces.gd.uid @@ -0,0 +1 @@ +uid://cvpcbtsmlhwyl diff --git a/addons/cyclops_level_builder/commands/cmd_select_vertices.gd b/addons/cyclops_level_builder/commands/cmd_select_vertices.gd new file mode 100644 index 00000000..d128a920 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_select_vertices.gd @@ -0,0 +1,174 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSelectVertices +extends CyclopsCommand + +class BlockVertexChanges extends RefCounted: + var block_path:NodePath + var vertex_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +#Public +var selection_type:Selection.Type = Selection.Type.REPLACE + +#Private +var block_map:Dictionary = {} + + + + +func add_vertex(block_path:NodePath, index:int): + add_vertices(block_path, [index]) + +func add_vertices(block_path:NodePath, indices:Array[int]): + var changes:BlockVertexChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockVertexChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data + block_map[block_path] = changes + + for index in indices: + if !changes.vertex_indices.has(index): + changes.vertex_indices.append(index) + + +func _init(): + command_name = "Select vertices" + + +func will_change_anything()->bool: + for block_path in block_map.keys(): + #print("path %s" % node_path) + + var rec:BlockVertexChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + if !rec.vertex_indices.is_empty(): + if vol.active_vertex != rec.vertex_indices[0]: + return true + + match selection_type: + Selection.Type.REPLACE: + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if v.selected != rec.vertex_indices.has(v_idx): + return true + Selection.Type.ADD: + for v_idx in rec.vertex_indices: + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if rec.vertex_indices.has(v_idx): + if !v.selected: + return true + Selection.Type.SUBTRACT: + for v_idx in rec.vertex_indices: + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if rec.vertex_indices.has(v_idx): + if v.selected: + return true + Selection.Type.TOGGLE: + return true + + return false + + +func do_it(): +# print("sel verts do_it") + for block_path in block_map.keys(): + #print("path %s" % node_path) + + var rec:BlockVertexChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + if !rec.vertex_indices.is_empty(): + var active_index:int = rec.vertex_indices[0] + #print("active_index ", active_index) + + match selection_type: + Selection.Type.REPLACE: + vol.active_vertex = active_index + Selection.Type.ADD: + vol.active_vertex = active_index + Selection.Type.SUBTRACT: + if rec.vertex_indices.has(vol.active_vertex): + vol.active_vertex = -1 + Selection.Type.TOGGLE: + if rec.vertex_indices.has(vol.active_vertex): + vol.active_vertex = -1 + elif !vol.vertices[active_index].selected: + vol.active_vertex = active_index + else: + if selection_type == Selection.Type.REPLACE: + vol.active_vertex = -1 + + match selection_type: + Selection.Type.REPLACE: + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + v.selected = rec.vertex_indices.has(v_idx) + + Selection.Type.ADD: + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if rec.vertex_indices.has(v_idx): + v.selected = true + + Selection.Type.SUBTRACT: + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if rec.vertex_indices.has(v_idx): + v.selected = false + + Selection.Type.TOGGLE: + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if rec.vertex_indices.has(v_idx): + v.selected = !v.selected + + vol.update_edge_and_face_selection_from_vertices() + #print("vol.active_vertex ", vol.active_vertex) + block.mesh_vector_data = vol.to_mesh_vector_data() + #print("block.mesh_vector_data.active_vertex ", block.mesh_vector_data.active_vertex) + + builder.selection_changed.emit() + +func undo_it(): +# print("sel verts undo_it") + #print("sel vert undo_it()") + for block_path in block_map.keys(): + var rec:BlockVertexChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data + + builder.selection_changed.emit() diff --git a/addons/cyclops_level_builder/commands/cmd_select_vertices.gd.uid b/addons/cyclops_level_builder/commands/cmd_select_vertices.gd.uid new file mode 100644 index 00000000..12ec8f6b --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_select_vertices.gd.uid @@ -0,0 +1 @@ +uid://b1ccwyylslrxd diff --git a/addons/cyclops_level_builder/commands/cmd_set_face_color.gd b/addons/cyclops_level_builder/commands/cmd_set_face_color.gd new file mode 100644 index 00000000..140c086e --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_face_color.gd @@ -0,0 +1,112 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSetFaceColor +extends CyclopsCommand + + +class BlockFaceChanges extends RefCounted: + var block_path:NodePath + var face_indices:Array[int] + var tracked_block_data:MeshVectorData + +var color:Color = Color.WHITE + +#Private +var block_map:Dictionary = {} + +func add_face(block_path:NodePath, index:int): + add_faces(block_path, [index]) + +func add_faces(block_path:NodePath, indices:Array[int]): +# print("adding_face %s %s" % [block_path, indices]) + var changes:BlockFaceChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockFaceChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data + block_map[block_path] = changes + + for index in indices: + if !changes.face_indices.has(index): + changes.face_indices.append(index) + + +func _init(): + command_name = "Set Face Color" + +func will_change_anything()->bool: +# print("CommandSetUvTransform will_change_anything") + for block_path in block_map.keys(): + + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + for f_idx in vol.faces.size(): + if rec.face_indices.has(f_idx): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if f.color != color: + return true + + return false + + +func do_it(): + #print("sel verts do_it") +# print("sel uv_transform do_it()") + for block_path in block_map.keys(): +# print("path %s" % block_path) + + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + +# print("block_path %s" % block_path) + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + for f_idx in vol.faces.size(): + if rec.face_indices.has(f_idx): +# print("face_idx %s" % f_idx) + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + f.color = color + + block.mesh_vector_data = vol.to_mesh_vector_data() + builder.selection_changed.emit() + + +func undo_it(): +# print("undo_it() select faces") + for block_path in block_map.keys(): + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data + + builder.selection_changed.emit() + diff --git a/addons/cyclops_level_builder/commands/cmd_set_face_color.gd.uid b/addons/cyclops_level_builder/commands/cmd_set_face_color.gd.uid new file mode 100644 index 00000000..e4bf671e --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_face_color.gd.uid @@ -0,0 +1 @@ +uid://c6eh3an2l8dn7 diff --git a/addons/cyclops_level_builder/commands/cmd_set_face_uv_transform.gd b/addons/cyclops_level_builder/commands/cmd_set_face_uv_transform.gd new file mode 100644 index 00000000..3c63748a --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_face_uv_transform.gd @@ -0,0 +1,114 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSetFaceUvTransform +extends CyclopsCommand + + +class BlockFaceChanges extends RefCounted: + var block_path:NodePath + var face_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +var uv_transform:Transform2D = Transform2D.IDENTITY +var visible:bool = true +var color:Color = Color.WHITE + +#Private +var block_map:Dictionary = {} + +func add_face(block_path:NodePath, index:int): + add_faces(block_path, [index]) + +func add_faces(block_path:NodePath, indices:Array[int]): +# print("adding_face %s %s" % [block_path, indices]) + var changes:BlockFaceChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockFaceChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data + block_map[block_path] = changes + + for index in indices: + if !changes.face_indices.has(index): + changes.face_indices.append(index) + + +func _init(): + command_name = "Set Face Uv Transform" + +func will_change_anything()->bool: +# print("CommandSetUvTransform will_change_anything") + for block_path in block_map.keys(): + + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + for f_idx in vol.faces.size(): + if rec.face_indices.has(f_idx): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if f.uv_transform != uv_transform: + return true + + return false + + +func do_it(): + #print("sel verts do_it") +# print("sel uv_transform do_it()") + for block_path in block_map.keys(): +# print("path %s" % block_path) + + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + +# print("block_path %s" % block_path) + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + for f_idx in vol.faces.size(): + if rec.face_indices.has(f_idx): +# print("face_idx %s" % f_idx) + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + f.uv_transform = uv_transform + + block.mesh_vector_data = vol.to_mesh_vector_data() + builder.selection_changed.emit() + + +func undo_it(): +# print("undo_it() select faces") + for block_path in block_map.keys(): + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data + + builder.selection_changed.emit() + diff --git a/addons/cyclops_level_builder/commands/cmd_set_face_uv_transform.gd.uid b/addons/cyclops_level_builder/commands/cmd_set_face_uv_transform.gd.uid new file mode 100644 index 00000000..b906cc71 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_face_uv_transform.gd.uid @@ -0,0 +1 @@ +uid://g4coow8jvi0n diff --git a/addons/cyclops_level_builder/commands/cmd_set_face_vertex_color.gd b/addons/cyclops_level_builder/commands/cmd_set_face_vertex_color.gd new file mode 100644 index 00000000..1a99f68f --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_face_vertex_color.gd @@ -0,0 +1,121 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSetFaceVertexColor +extends CyclopsCommand + + +class BlockFaceVertexChanges extends RefCounted: + var block_path:NodePath + var face_vert_indices:Array[int] + var tracked_block_data:MeshVectorData + +var color:Color = Color.WHITE +var strength:float = 1 + +#Private +var block_map:Dictionary = {} + +#class StrokePoint: + #var position:Vector3 + #var pressure:float + # +#var stroke_points:Array[StrokePoint] + +func add_face_vertex(block_path:NodePath, index:int): + add_face_vertices(block_path, [index]) + +func add_face_vertices(block_path:NodePath, indices:Array[int]): +# print("adding_face %s %s" % [block_path, indices]) + var changes:BlockFaceVertexChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockFaceVertexChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vertex_data + block_map[block_path] = changes + + for index in indices: + if !changes.face_vert_indices.has(index): + changes.face_vert_indices.append(index) + + +func _init(): + command_name = "Set Face Vertex Color" + +func will_change_anything()->bool: + return block_map.size() > 0 +# print("CommandSetUvTransform will_change_anything") + #for block_path in block_map.keys(): +# + #var rec:BlockFaceVertexChanges = block_map[block_path] + #var block:CyclopsBlock = builder.get_node(block_path) + # + #var vol:ConvexVolume = ConvexVolume.new() + #vol.init_from_convex_block_data(rec.tracked_block_data) +# + #for f_idx in vol.faces.size(): + #if rec.face_indices.has(f_idx): + #var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + #if f.color != color: + #return true +# + #return false + + + +func do_it(): + #print("sel verts do_it") + #print("sel face vert color do_it()") + for block_path in block_map.keys(): +# print("path %s" % block_path) + + var rec:BlockFaceVertexChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + #print("block_path %s" % block_path) + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + for fv_idx in vol.face_vertices.size(): + if rec.face_vert_indices.has(fv_idx): + #print("face_v_idx %s" % fv_idx) + var fv:ConvexVolume.FaceVertexInfo = vol.face_vertices[fv_idx] + fv.color = MathUtil.blend_colors_ignore_alpha(color, fv.color, strength) + + block.mesh_vector_data = vol.to_mesh_vector_data() + builder.selection_changed.emit() + + +func undo_it(): +# print("undo_it() select faces") + for block_path in block_map.keys(): + var rec:BlockFaceVertexChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data + + builder.selection_changed.emit() + diff --git a/addons/cyclops_level_builder/commands/cmd_set_face_vertex_color.gd.uid b/addons/cyclops_level_builder/commands/cmd_set_face_vertex_color.gd.uid new file mode 100644 index 00000000..f694f5f4 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_face_vertex_color.gd.uid @@ -0,0 +1 @@ +uid://3oqofjxljsfu diff --git a/addons/cyclops_level_builder/commands/cmd_set_face_visible.gd b/addons/cyclops_level_builder/commands/cmd_set_face_visible.gd new file mode 100644 index 00000000..478298b9 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_face_visible.gd @@ -0,0 +1,112 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSetFaceVisible +extends CyclopsCommand + + +class BlockFaceChanges extends RefCounted: + var block_path:NodePath + var face_indices:Array[int] = [] + var tracked_block_data:MeshVectorData + +var visible:bool = true + +#Private +var block_map:Dictionary = {} + +func add_face(block_path:NodePath, index:int): + add_faces(block_path, [index]) + +func add_faces(block_path:NodePath, indices:Array[int]): +# print("adding_face %s %s" % [block_path, indices]) + var changes:BlockFaceChanges + if block_map.has(block_path): + changes = block_map[block_path] + else: + changes = BlockFaceChanges.new() + changes.block_path = block_path + var block:CyclopsBlock = builder.get_node(block_path) + changes.tracked_block_data = block.mesh_vector_data + block_map[block_path] = changes + + for index in indices: + if !changes.face_indices.has(index): + changes.face_indices.append(index) + + +func _init(): + command_name = "Set Face Properties" + +func will_change_anything()->bool: +# print("CommandSetUvTransform will_change_anything") + for block_path in block_map.keys(): + + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + for f_idx in vol.faces.size(): + if rec.face_indices.has(f_idx): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if f.visible != visible: + return true + + return false + + +func do_it(): + #print("sel verts do_it") +# print("sel uv_transform do_it()") + for block_path in block_map.keys(): +# print("path %s" % block_path) + + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + +# print("block_path %s" % block_path) + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(rec.tracked_block_data) + + for f_idx in vol.faces.size(): + if rec.face_indices.has(f_idx): +# print("face_idx %s" % f_idx) + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + f.visible = visible + + block.mesh_vector_data = vol.to_mesh_vector_data() + builder.selection_changed.emit() + + +func undo_it(): +# print("undo_it() select faces") + for block_path in block_map.keys(): + var rec:BlockFaceChanges = block_map[block_path] + var block:CyclopsBlock = builder.get_node(block_path) + block.mesh_vector_data = rec.tracked_block_data + + builder.selection_changed.emit() + diff --git a/addons/cyclops_level_builder/commands/cmd_set_face_visible.gd.uid b/addons/cyclops_level_builder/commands/cmd_set_face_visible.gd.uid new file mode 100644 index 00000000..3d2f35cb --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_face_visible.gd.uid @@ -0,0 +1 @@ +uid://i11qjgwn207e diff --git a/addons/cyclops_level_builder/commands/cmd_set_material.gd b/addons/cyclops_level_builder/commands/cmd_set_material.gd new file mode 100644 index 00000000..e3ad9e31 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_material.gd @@ -0,0 +1,158 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSetMaterial +extends CyclopsCommand + +class Target extends RefCounted: + var block_path:NodePath + var face_indices:PackedInt32Array + +class BlockCache extends RefCounted: + var path:NodePath + var data:MeshVectorData + var materials:Array[Material] + +#Public +var setting_material:bool = true +var material_path:String + +var setting_color:bool = false +var color:Color = Color.WHITE + +var setting_visibility:bool = false +var visibility:bool = true + +var painting_uv:bool = false +var uv_matrix:Transform2D = Transform2D.IDENTITY + +#Private +var target_list:Array[Target] = [] + +var cache_list:Array[BlockCache] = [] + +func add_target(block_path:NodePath, face_indices:PackedInt32Array): +# print("add target %s %s" % [block_path.get_name(block_path.get_name_count() - 1), face_indices]) + var target:Target = null + for t in target_list: + if t.block_path == block_path: + target = t + break + + if !target: + target = Target.new() + target.block_path = block_path + target_list.append(target) + + for f_idx in face_indices: + if !target.face_indices.has(f_idx): + target.face_indices.append(f_idx) + + +func make_cache(): + cache_list = [] + + for t in target_list: + var cache:BlockCache = BlockCache.new() + var block:CyclopsBlock = builder.get_node(t.block_path) + + cache.path = block.get_path() + cache.data = block.mesh_vector_data + cache.materials = block.materials.duplicate() + + cache_list.append(cache) + +func will_change_anything()->bool: + return !target_list.is_empty() + +func _init(): + command_name = "Set material" + +func do_it(): + make_cache() + + for tgt in target_list: + var block:CyclopsBlock = builder.get_node(tgt.block_path) + + var data:MeshVectorData = block.mesh_vector_data + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(data) + + if setting_material: + + var target_material:Material = null + if ResourceLoader.exists(material_path, "Material"): + #print("loading material ", material_path) + var mat = load(material_path) + target_material = mat if mat is Material else null + + var mat_reindex:Dictionary + var mat_list_reduced:Array[Material] + + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + + var mat_to_apply:Material + + if tgt.face_indices.has(f_idx): + mat_to_apply = target_material + else: + mat_to_apply = null if f.material_id == -1 else block.materials[f.material_id] + + if !mat_to_apply: + f.material_id = -1 + elif !mat_reindex.has(mat_to_apply): + var new_idx = mat_reindex.size() + mat_reindex[mat_to_apply] = new_idx + mat_list_reduced.append(mat_to_apply) + f.material_id = new_idx + else: + f.material_id = mat_reindex[mat_to_apply] + + block.materials = mat_list_reduced + + #Set other properties + for f_idx in vol.faces.size(): + if tgt.face_indices.has(f_idx): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if setting_color: + f.color = color + for v_idx in f.vertex_indices: + var fv:ConvexVolume.FaceVertexInfo = \ + vol.get_face_vertex(f_idx, v_idx) + fv.color = color + if setting_visibility: + f.visible = visibility + if painting_uv: + f.uv_transform = uv_matrix + + block.mesh_vector_data = vol.to_mesh_vector_data() + + +func undo_it(): + for cache in cache_list: + var block:CyclopsBlock = builder.get_node(cache.path) + block.materials = cache.materials.duplicate() + block.mesh_vector_data = cache.data + diff --git a/addons/cyclops_level_builder/commands/cmd_set_material.gd.uid b/addons/cyclops_level_builder/commands/cmd_set_material.gd.uid new file mode 100644 index 00000000..9a06df8a --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_set_material.gd.uid @@ -0,0 +1 @@ +uid://de42rcrulircb diff --git a/addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd b/addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd new file mode 100644 index 00000000..8d9a4589 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd @@ -0,0 +1,84 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSnapToGrid +extends CyclopsCommand + +class TrackedInfo extends RefCounted: + var data:MeshVectorData + + +#Private +var blocks_to_move:Array[NodePath] +var tracked_block_data:Array[TrackedInfo] + + +func _init(): + command_name = "Snap to grid" + + +#Add blocks to be moved here +func add_block(block_path:NodePath): + blocks_to_move.append(block_path) + + var block:CyclopsBlock = builder.get_node(block_path) + #tracked_blocks.append(block) + var info:TrackedInfo = TrackedInfo.new() + info.data = block.mesh_vector_data.duplicate() +# info.materials = block.materials + tracked_block_data.append(info) + + +func do_it(): + + for i in blocks_to_move.size(): + var block:CyclopsBlock = builder.get_node(blocks_to_move[i]) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(tracked_block_data[i].data) + + var points_new:PackedVector3Array + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + var p_snap:Vector3 = builder.get_snapping_manager().snap_point( + block.global_transform * v.point, SnappingQuery.new(null, [])) + points_new.append(p_snap) + + var new_vol:ConvexVolume = ConvexVolume.new() + new_vol.init_from_points(points_new) + new_vol.transform(block.global_transform.affine_inverse()) + + + new_vol.copy_face_attributes(vol) + + block.mesh_vector_data = new_vol.to_mesh_vector_data() + +func undo_it(): + for i in blocks_to_move.size(): + var block:CyclopsBlock = builder.get_node(blocks_to_move[i]) + + block.mesh_vector_data = tracked_block_data[i].data + + + diff --git a/addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd.uid b/addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd.uid new file mode 100644 index 00000000..cbc7fbaa --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_snap_to_grid.gd.uid @@ -0,0 +1 @@ +uid://lsi7txyl7cjp diff --git a/addons/cyclops_level_builder/commands/cmd_subtract_block.gd b/addons/cyclops_level_builder/commands/cmd_subtract_block.gd new file mode 100644 index 00000000..71b730ae --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_subtract_block.gd @@ -0,0 +1,158 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandSubtractBlock +extends CyclopsCommand + +class NewBlockInfo extends RefCounted: + var data:MeshVectorData + var materials:Array[Material] + var path:NodePath + #var centroid:Vector3 + var xform:Transform3D + +#Public +var block_paths:Array[NodePath] +var block_to_subtract_path:NodePath +var block_name_prefix:String = "Block_" + +#Private +var start_blocks:Array[TrackedBlock] +var subtracted_block_cache:TrackedBlock +var added_blocks:Array[NewBlockInfo] + +func _init(): + command_name = "Subtract blocks" + +func restore_tracked_block(tracked:TrackedBlock)->CyclopsBlock: + var parent = builder.get_node(tracked.path_parent) + + var block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + block.mesh_vector_data = tracked.data + block.materials = tracked.materials + block.name = tracked.name +# block.selected = tracked.selected + block.global_transform = tracked.world_xform + block.collision_type = tracked.collision_type + block.collision_layer = tracked.collision_layers + block.collision_mask = tracked.collision_mask + + parent.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + + if tracked.selected: + var selection:EditorSelection = builder.get_editor_interface().get_selection() + selection.add_node(block) + + return block + +func will_change_anything()->bool: + var subtrahend_block:CyclopsBlock = builder.get_node(block_to_subtract_path) + var subtrahend_vol:ConvexVolume = subtrahend_block.control_mesh + subtrahend_vol = subtrahend_vol.transformed(subtrahend_block.global_transform) + + if block_paths.is_empty(): + return false + + for minuend_path in block_paths: + var minuend_block:CyclopsBlock = builder.get_node(minuend_path) + var minuend_vol:ConvexVolume = minuend_block.control_mesh + minuend_vol = minuend_vol.transformed(minuend_block.global_transform) + + if minuend_vol.intersects_convex_volume(subtrahend_vol): + return true + + return false + +func do_it(): + var subtrahend_block:CyclopsBlock = builder.get_node(block_to_subtract_path) + var snap_to_grid_util:SnapToGridUtil = CyclopsAutoload.calc_snap_to_grid_util() + + if start_blocks.is_empty(): + var subtrahend_vol:ConvexVolume = subtrahend_block.control_mesh + subtracted_block_cache = TrackedBlock.new(subtrahend_block) + subtrahend_vol = subtrahend_vol.transformed(subtrahend_block.global_transform) + var subtra_xform_inv:Transform3D = subtrahend_block.global_transform.affine_inverse() + + for path in block_paths: + var block:CyclopsBlock = builder.get_node(path) + + var minuend_vol:ConvexVolume = block.control_mesh + minuend_vol = minuend_vol.transformed(block.global_transform) + if !minuend_vol.intersects_convex_volume(subtrahend_vol): + continue + + var tracker:TrackedBlock = TrackedBlock.new(block) + start_blocks.append(tracker) + + var fragments:Array[ConvexVolume] = minuend_vol.subtract(subtrahend_vol) + + for f in fragments: + f.copy_face_attributes(minuend_vol) + #var centroid:Vector3 = f.get_centroid() + #centroid = snap_to_grid_util.snap_point(centroid) + #f.translate(-centroid) + f = f.transformed(block.global_transform.affine_inverse()) + + var block_info:NewBlockInfo = NewBlockInfo.new() + block_info.data = f.to_mesh_vector_data() + block_info.materials = block.materials + block_info.xform = block.global_transform + #block_info.centroid = centroid + added_blocks.append(block_info) + + #Delete source blocks + for block_info in start_blocks: + var del_block:CyclopsBlock = builder.get_node(block_info.path) + del_block.queue_free() + + subtrahend_block.queue_free() + + #Create blocks + for info in added_blocks: + var block:CyclopsBlock = preload("../nodes/cyclops_block.gd").new() + var parent:Node = builder.get_node(start_blocks[0].path_parent) + parent.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.name = GeneralUtil.find_unique_name(parent, block_name_prefix) + block.mesh_vector_data = info.data + block.materials = info.materials +# block.global_transform = Transform3D.IDENTITY.translated(info.centroid) + block.global_transform = info.xform + + info.path = block.get_path() + + + +func undo_it(): + + for info in added_blocks: + var added_block:CyclopsBlock = builder.get_node(info.path) + added_block.queue_free() + + restore_tracked_block(subtracted_block_cache) + + for tracked in start_blocks: + restore_tracked_block(tracked) + diff --git a/addons/cyclops_level_builder/commands/cmd_subtract_block.gd.uid b/addons/cyclops_level_builder/commands/cmd_subtract_block.gd.uid new file mode 100644 index 00000000..aa64c4b2 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_subtract_block.gd.uid @@ -0,0 +1 @@ +uid://ea4l68pc7tw diff --git a/addons/cyclops_level_builder/commands/cmd_transform_blocks.gd b/addons/cyclops_level_builder/commands/cmd_transform_blocks.gd new file mode 100644 index 00000000..132fd7d8 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_transform_blocks.gd @@ -0,0 +1,76 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandTransformBlocks +extends CyclopsCommand + +#Public data to set before activating command +var transform:Transform3D +var lock_uvs:bool = false + +#Private +var tracked_blocks:Array[TrackedBlock] + +func _init(): + command_name = "Transform blocks" + +#Add blocks to be moved here +func add_block(block_path:NodePath): + + var block:CyclopsBlock = builder.get_node(block_path) + var tracked:TrackedBlock = TrackedBlock.new(block) + tracked_blocks.append(tracked) + +#Moves all blocks from the start position by this amount +func move_to(offset:Vector3): + for tracked in tracked_blocks: + var block:CyclopsBlock = builder.get_node(tracked.path) + var w_init_xform:Transform3D = tracked.world_xform + + var new_w_xform:Transform3D = w_init_xform.translated(offset) + block.global_transform = new_w_xform + + +func do_it(): + for tracked in tracked_blocks: + var block:CyclopsBlock = builder.get_node(tracked.path) + var w_init_xform:Transform3D = tracked.world_xform + + var new_w_xform:Transform3D = transform * w_init_xform + block.global_transform = new_w_xform + + if !lock_uvs: + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(tracked.data) + + var uv_xform:Transform3D = transform.affine_inverse() + vol.transform_uvs(uv_xform) + + block.mesh_vector_data = vol.to_mesh_vector_data() + +func undo_it(): + for tracked in tracked_blocks: + var block:CyclopsBlock = builder.get_node(tracked.path) + block.global_transform = tracked.world_xform + diff --git a/addons/cyclops_level_builder/commands/cmd_transform_blocks.gd.uid b/addons/cyclops_level_builder/commands/cmd_transform_blocks.gd.uid new file mode 100644 index 00000000..4963d054 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_transform_blocks.gd.uid @@ -0,0 +1 @@ +uid://clqpwpmapu32h diff --git a/addons/cyclops_level_builder/commands/cmd_transform_vertices.gd b/addons/cyclops_level_builder/commands/cmd_transform_vertices.gd new file mode 100644 index 00000000..c94510b1 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_transform_vertices.gd @@ -0,0 +1,73 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +#Applied trnasorm of points in local space + +@tool +class_name CommandTransformVertices +extends CyclopsCommand + +class TrackedInfo extends RefCounted: + var data:MeshVectorData +# var materials:Array[Material] + +#Local space transform of points +var transform:Transform3D +var lock_uvs:bool = false + +#Private +var blocks_to_move:Array[NodePath] +var tracked_block_data:Array[TrackedInfo] + +func _init(): + command_name = "Transform vertices" + +#Add blocks to be moved here +func add_block(block_path:NodePath): + blocks_to_move.append(block_path) + + var block:CyclopsBlock = builder.get_node(block_path) + #tracked_blocks.append(block) + var info:TrackedInfo = TrackedInfo.new() + info.data = block.mesh_vector_data.duplicate() +# info.materials = block.materials + tracked_block_data.append(info) + +#Moves all blocks from the start position by this amount +func apply_transform(xform:Transform3D): + for i in blocks_to_move.size(): + var block:CyclopsBlock = builder.get_node(blocks_to_move[i]) + + var ctl_mesh:ConvexVolume = ConvexVolume.new() + ctl_mesh.init_from_mesh_vector_data(tracked_block_data[i].data) + ctl_mesh.transform(xform, lock_uvs) + var result_data:MeshVectorData = ctl_mesh.to_mesh_vector_data() + block.mesh_vector_data = result_data + + +func do_it(): + apply_transform(transform) + +func undo_it(): + apply_transform(Transform3D.IDENTITY) + diff --git a/addons/cyclops_level_builder/commands/cmd_transform_vertices.gd.uid b/addons/cyclops_level_builder/commands/cmd_transform_vertices.gd.uid new file mode 100644 index 00000000..b992e860 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_transform_vertices.gd.uid @@ -0,0 +1 @@ +uid://bhpuiehrl1geb diff --git a/addons/cyclops_level_builder/commands/cmd_vertex_paint_stroke.gd b/addons/cyclops_level_builder/commands/cmd_vertex_paint_stroke.gd new file mode 100644 index 00000000..c00e2577 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_vertex_paint_stroke.gd @@ -0,0 +1,130 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandVertexPaintStroke +extends CyclopsCommand + +@export var color:Color = Color.WHITE +@export var strength:float = 1 +@export var radius:float = 1 +@export var falloff_curve:Curve + +enum MaskType { NONE, VERTICES, FACES } +@export var mask:MaskType = MaskType.NONE + +#Private +var block_map:Dictionary = {} +#var block_tgt_map:Dictionary = {} + + +var pen_stroke:PenStroke = PenStroke.new() + +func append_block(block_path:NodePath): + if block_map.has(block_path): + return + + var block:CyclopsBlock = builder.get_node(block_path) + + #print("stroing block faces ", block.block_data.face_vertex_face_index) + + block_map[block_path] = block.mesh_vector_data.duplicate(true) + #print("stroing block faces ", block.block_data.face_vertex_face_index) +# block_tgt_map[block_path] = block.block_data.duplicate(true) + +func append_stroke_point(position:Vector3, pressure:float = 1): + pen_stroke.append_stroke_point(position, pressure) + #print("--pen_stroke ", pen_stroke.stroke_points) + +func _init(): + command_name = "Paint Vertex Color Stroke" + +func will_change_anything()->bool: + return !(block_map.is_empty() || pen_stroke.is_empty()) + +func do_it(): + #print("sel verts do_it") +# print("sel uv_transform do_it()") + + #print("stroke pts ", str(pen_stroke.stroke_points)) + var stroke_resamp:PenStroke = pen_stroke.resample_points(radius * .1) + #print("stroke resamp pts ", str(stroke_resamp.stroke_points)) + + for block_path in block_map.keys(): + + var block:CyclopsBlock = builder.get_node(block_path) + var w2l:Transform3D = block.global_transform.affine_inverse() + #print("painting block ", block.name) + + var block_data:MeshVectorData = block_map[block_path] + #print("block_data raw faces ", block_data.face_vertex_face_index) + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(block_data) + + #Apply stroke + for stroke_pt in stroke_resamp.stroke_points: + var pos_local:Vector3 = w2l * stroke_pt.position + for fv in vol.face_vertices: + var v:ConvexVolume.VertexInfo = vol.vertices[fv.vertex_index] + var f:ConvexVolume.FaceInfo = vol.faces[fv.face_index] + + if mask == MaskType.FACES: + if !f.selected: + continue + elif mask == MaskType.VERTICES: + if !v.selected: + continue + + var dist:float = v.point.distance_to(pos_local) + + if dist > radius: + continue + + var falloff_frac:float = 1 - (dist / radius) + var falloff:float = falloff_curve.sample(falloff_frac) \ + if falloff_curve else 1 + + fv.color = MathUtil.blend_colors_ignore_alpha(\ + color, fv.color, strength * stroke_pt.pressure * falloff) + + #print("fv_idx ", fv.index) + #print("fv color ", fv.color) + + var new_block_data:MeshVectorData = vol.to_mesh_vector_data() + #print("new_block_data faces ", block.block_data.face_vertex_face_index) + block.mesh_vector_data = new_block_data + + builder.selection_changed.emit() + +func undo_it(): +# print("undo_it() select faces") + for block_path in block_map.keys(): + var block:CyclopsBlock = builder.get_node(block_path) + + var block_data:MeshVectorData = block_map[block_path] + + block.mesh_vector_data = block_data + + builder.selection_changed.emit() + diff --git a/addons/cyclops_level_builder/commands/cmd_vertex_paint_stroke.gd.uid b/addons/cyclops_level_builder/commands/cmd_vertex_paint_stroke.gd.uid new file mode 100644 index 00000000..93c1df68 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cmd_vertex_paint_stroke.gd.uid @@ -0,0 +1 @@ +uid://cweif1xolxe54 diff --git a/addons/cyclops_level_builder/commands/cyclops_command.gd b/addons/cyclops_level_builder/commands/cyclops_command.gd new file mode 100644 index 00000000..7d66a6f3 --- /dev/null +++ b/addons/cyclops_level_builder/commands/cyclops_command.gd @@ -0,0 +1,77 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CyclopsCommand +extends RefCounted + +var command_name:String = "" +var builder:CyclopsLevelBuilder + +class TrackedBlock extends RefCounted: + var path:NodePath + var path_parent:NodePath + var data:MeshVectorData + var world_xform:Transform3D + var materials:Array[Material] + var selected:bool + var name:String + var collision_type:Collision.Type + var collision_layers:int + var collision_mask:int + + func _init(block:CyclopsBlock): + path = block.get_path() + path_parent = block.get_parent().get_path() + name = block.name + data = block.mesh_vector_data.duplicate() + world_xform = block.global_transform + #selected = block.selected + materials = block.materials + collision_type = block.collision_type + collision_layers = block.collision_layer + collision_mask = block.collision_mask + +func add_to_undo_manager(undo_manager:EditorUndoRedoManager): + undo_manager.create_action(command_name, UndoRedo.MERGE_DISABLE) + undo_manager.add_do_method(self, "do_it") + undo_manager.add_undo_method(self, "undo_it") + + undo_manager.commit_action() + +func node_global_transform(node:Node)->Transform3D: + var node_parent:Node3D + while node: + if node is Node3D: + node_parent = node + break + node = node.get_parent() + + return node_parent.global_transform if node_parent else Transform3D.IDENTITY + +func do_it()->void: + pass + +func undo_it()->void: + pass + diff --git a/addons/cyclops_level_builder/commands/cyclops_command.gd.uid b/addons/cyclops_level_builder/commands/cyclops_command.gd.uid new file mode 100644 index 00000000..a7c328aa --- /dev/null +++ b/addons/cyclops_level_builder/commands/cyclops_command.gd.uid @@ -0,0 +1 @@ +uid://jrro31yqr3o1 diff --git a/addons/cyclops_level_builder/commands/io/cmd_import_cyclops_file.gd b/addons/cyclops_level_builder/commands/io/cmd_import_cyclops_file.gd new file mode 100644 index 00000000..3e95d623 --- /dev/null +++ b/addons/cyclops_level_builder/commands/io/cmd_import_cyclops_file.gd @@ -0,0 +1,87 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandImportCyclopsFile +extends CyclopsCommand + +@export var file_path:String +@export var target_parent:NodePath + +var added_blocks:Array[NodePath] + +func _init(): + command_name = "Import Cyclops File" + +func will_change_anything()->bool: + return FileAccess.file_exists(file_path) + +func do_it(): + if !FileAccess.file_exists(file_path): + push_error("No such file: ", file_path) + return + + var source:String = FileAccess.get_file_as_string(file_path) + var raw = JSON.parse_string(source) + if !(raw is Dictionary): + push_error("Invalid file format: ", file_path) + return + + load_file(raw) + + pass + + +func load_file(root:Dictionary): + var loader:CyclopsFileLoader = CyclopsFileLoader.new() + loader.load(root) + + var editor_scene_root:Node = builder.get_editor_interface().get_edited_scene_root() + + + for scene_id in loader.scene_map.keys(): + var root_node_id:int = loader.scene_map[scene_id] + var loaded_scene:Node3D = loader.node_map[root_node_id] + + editor_scene_root.add_child(loaded_scene) + set_owner_recursive(loaded_scene, editor_scene_root) + + added_blocks.append(loaded_scene.get_path()) + + +func undo_it(): + for block_path in added_blocks: + var block:Node3D = builder.get_node(block_path) + block.queue_free() + + added_blocks.clear() + +func set_owner_recursive(loaded_node:Node3D, owner_node:Node3D): + loaded_node.owner = owner_node + if loaded_node is CyclopsBlock: + #Do not set owner of hidden children + return + + for child in loaded_node.get_children(): + set_owner_recursive(child, owner_node) + diff --git a/addons/cyclops_level_builder/commands/io/cmd_import_cyclops_file.gd.uid b/addons/cyclops_level_builder/commands/io/cmd_import_cyclops_file.gd.uid new file mode 100644 index 00000000..925b6819 --- /dev/null +++ b/addons/cyclops_level_builder/commands/io/cmd_import_cyclops_file.gd.uid @@ -0,0 +1 @@ +uid://bgnhohepua1kd diff --git a/addons/cyclops_level_builder/commands/io/cmd_import_godot_meshes.gd b/addons/cyclops_level_builder/commands/io/cmd_import_godot_meshes.gd new file mode 100644 index 00000000..64a16d9d --- /dev/null +++ b/addons/cyclops_level_builder/commands/io/cmd_import_godot_meshes.gd @@ -0,0 +1,99 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandImportGodotMeshes +extends CyclopsCommand + +@export var source_nodes:Array[NodePath] +@export var target_parent:NodePath +@export var collision_type:Collision.Type = Collision.Type.STATIC +@export var collision_layers:int = 1 +@export var collision_mask:int = 1 + +var added_blocks:Array[NodePath] + +func _init(): + command_name = "Import Godot Meshes" + +func will_change_anything()->bool: + return !target_parent.is_empty() && !source_nodes.is_empty() + +func do_it(): + var tgt_parent_node:Node = builder.get_node(target_parent) + if !tgt_parent_node || !(tgt_parent_node is Node3D): + return + + for src_path in source_nodes: + var src_node:Node = builder.get_node(src_path) + if !src_node is MeshInstance3D: + continue + + var src_mesh_inst:MeshInstance3D = src_node + if !src_mesh_inst.mesh: + continue + + var block:CyclopsBlock = preload("res://addons/cyclops_level_builder/nodes/cyclops_block.gd").new() + + var blocks_root:Node3D = tgt_parent_node + blocks_root.add_child(block) + block.owner = builder.get_editor_interface().get_edited_scene_root() + block.name = src_node.name + block.global_transform = src_node.global_transform + block.collision_type = collision_type + block.collision_layer = collision_layers + block.collision_mask = collision_mask + + added_blocks.append(block.get_path()) + + var best_mat:Material + var points:PackedVector3Array + for i in src_mesh_inst.mesh.get_surface_count(): + var mat:Material = src_mesh_inst.mesh.surface_get_material(i) + if best_mat != null: + best_mat = mat + + var surface_arrs:Array = src_mesh_inst.mesh.surface_get_arrays(i) + + if surface_arrs[Mesh.ARRAY_INDEX].is_empty(): + for pt in surface_arrs[Mesh.ARRAY_VERTEX]: + points.append(pt) + else: + for idx in surface_arrs[Mesh.ARRAY_INDEX]: + points.append(surface_arrs[Mesh.ARRAY_VERTEX][idx]) + + if best_mat: + block.materials = [best_mat] + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_points(points, Transform2D.IDENTITY, 0 if best_mat else -1) + block.mesh_vector_data = vol.to_mesh_vector_data() + + +func undo_it(): + for block_path in added_blocks: + var block:CyclopsBlock = builder.get_node(block_path) + block.queue_free() + + added_blocks.clear() + diff --git a/addons/cyclops_level_builder/commands/io/cmd_import_godot_meshes.gd.uid b/addons/cyclops_level_builder/commands/io/cmd_import_godot_meshes.gd.uid new file mode 100644 index 00000000..d0398ee7 --- /dev/null +++ b/addons/cyclops_level_builder/commands/io/cmd_import_godot_meshes.gd.uid @@ -0,0 +1 @@ +uid://d0k1cnal346ru diff --git a/addons/cyclops_level_builder/controls/enum_line_edit.gd b/addons/cyclops_level_builder/controls/enum_line_edit.gd new file mode 100644 index 00000000..3bc5a267 --- /dev/null +++ b/addons/cyclops_level_builder/controls/enum_line_edit.gd @@ -0,0 +1,59 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends OptionButton +class_name EnumLineEdit + +signal option_selected(index:int) + +@export var item_list:PackedStringArray: + get: + return item_list + set(value): + item_list = value + dirty = true + +var dirty:bool = true + +# Called when the node enters the scene tree for the first time. +func _ready(): + + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + clear() + + for name in item_list: + add_item(name) + + dirty = false + + + +func _on_item_selected(index): + option_selected.emit(index) + diff --git a/addons/cyclops_level_builder/controls/enum_line_edit.gd.uid b/addons/cyclops_level_builder/controls/enum_line_edit.gd.uid new file mode 100644 index 00000000..f7e868e1 --- /dev/null +++ b/addons/cyclops_level_builder/controls/enum_line_edit.gd.uid @@ -0,0 +1 @@ +uid://yneoqjqd3xao diff --git a/addons/cyclops_level_builder/controls/enum_line_edit.tscn b/addons/cyclops_level_builder/controls/enum_line_edit.tscn new file mode 100644 index 00000000..38d378a9 --- /dev/null +++ b/addons/cyclops_level_builder/controls/enum_line_edit.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://7ur3lovebuua"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/enum_line_edit.gd" id="1_ltl6a"] + +[node name="EnumLineEdit" type="OptionButton"] +script = ExtResource("1_ltl6a") + +[connection signal="item_selected" from="." to="." method="_on_item_selected"] diff --git a/addons/cyclops_level_builder/controls/fold_out_panel.gd b/addons/cyclops_level_builder/controls/fold_out_panel.gd new file mode 100644 index 00000000..4236156b --- /dev/null +++ b/addons/cyclops_level_builder/controls/fold_out_panel.gd @@ -0,0 +1,51 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name FoldOutPanel + +@export var open:bool = true +@export var text:String = "" + +func get_content_area(): + return %ContentArea + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + %HeaderButton.text = text + if open: + %HeaderButton.icon = preload("res://addons/cyclops_level_builder/art/icons/arrow_down.svg") + %ContentArea.visible = true + else: + %HeaderButton.icon = preload("res://addons/cyclops_level_builder/art/icons/arrow_right.svg") + %ContentArea.visible = false + + +func _on_button_pressed(): + open = !open diff --git a/addons/cyclops_level_builder/controls/fold_out_panel.gd.uid b/addons/cyclops_level_builder/controls/fold_out_panel.gd.uid new file mode 100644 index 00000000..4d76c7aa --- /dev/null +++ b/addons/cyclops_level_builder/controls/fold_out_panel.gd.uid @@ -0,0 +1 @@ +uid://sj5hw3u3rnp0 diff --git a/addons/cyclops_level_builder/controls/fold_out_panel.tscn b/addons/cyclops_level_builder/controls/fold_out_panel.tscn new file mode 100644 index 00000000..cd5522a2 --- /dev/null +++ b/addons/cyclops_level_builder/controls/fold_out_panel.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=3 format=3 uid="uid://bk0eelj64x4fk"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/fold_out_panel.gd" id="1_n3mr0"] +[ext_resource type="Texture2D" uid="uid://c7c2vg6lbhmfn" path="res://addons/cyclops_level_builder/art/icons/arrow_right.svg" id="2_dwm1s"] + +[node name="FoldOutPanel" type="PanelContainer"] +offset_right = 245.0 +offset_bottom = 219.0 +script = ExtResource("1_n3mr0") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="HeaderButton" type="Button" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Fold Name" +icon = ExtResource("2_dwm1s") +alignment = 0 + +[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/PanelContainer"] +layout_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/PanelContainer/HBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 8 + +[node name="ContentArea" type="PanelContainer" parent="VBoxContainer/PanelContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[connection signal="pressed" from="VBoxContainer/HeaderButton" to="." method="_on_button_pressed"] diff --git a/addons/cyclops_level_builder/controls/numeric_line_edit.gd b/addons/cyclops_level_builder/controls/numeric_line_edit.gd new file mode 100644 index 00000000..f7eb7d45 --- /dev/null +++ b/addons/cyclops_level_builder/controls/numeric_line_edit.gd @@ -0,0 +1,139 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name NumbericLineEdit + +signal value_changed(value:float) + +@export var value:float: + get: + return value + set(v): + if value == v: + return + value = v + dirty = true + +@export var snap_size:float = 1 + +@export var disabled:bool = false + +var dirty:bool = true + +enum NumEditState{ IDLE, READY, DRAGGING, TEXT_EDIT } +var state:NumEditState = NumEditState.IDLE + +var mouse_down_pos:Vector2 +var drag_start_radius:float = 4 +var value_start_drag:float + +var line_input:LineEdit +var line_display:Label + +# Called when the node enters the scene tree for the first time. +func _ready(): + var foo = $HBoxContainer/line_display + var uuu = get_node("HBoxContainer/line_display") + + line_input = %line_input + line_display = %line_display + + if line_input: + line_input.visible = false + pass + +func _process(delta): + if dirty: +# print("---value " + str(value)) + if line_input: + line_input.text = format_number(value) + line_display.text = format_number(value) + + dirty = false + +func format_number(val:float)->String: + var text:String = "%.5f" % val + var idx:int = text.findn(".") + if idx != -1: + text = text.rstrip("0") + if text.right(1) == ".": + text = text.left(-1) + return text + + +func _gui_input(event): + if event is InputEventMouseButton: + var e:InputEventMouseButton = event + if e.is_pressed(): + if state == NumEditState.IDLE: + mouse_down_pos = e.position + state = NumEditState.READY + else: + if state == NumEditState.READY: + if line_input: + line_input.visible = true + line_display.visible = false + state = NumEditState.TEXT_EDIT + elif state == NumEditState.DRAGGING: + state = NumEditState.IDLE + + + accept_event() + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + if state == NumEditState.READY: + if e.position.distance_to(mouse_down_pos) >= drag_start_radius: + state = NumEditState.DRAGGING + value_start_drag = value + + elif state == NumEditState.DRAGGING: + var offset = e.position.x - mouse_down_pos.x + var new_value = value_start_drag + (offset * snap_size / 20.0) + #print("-new_value %s" % new_value) + new_value = ceil(new_value / snap_size) * snap_size + + #print("new_value %s" % new_value) + + if value != new_value: + value = new_value + value_changed.emit(value) + dirty = true + +func _on_line_edit_text_submitted(new_text): + var regex = RegEx.new() + regex.compile("^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$") + var result:RegExMatch = regex.search(new_text) + if result: +# print("found match") + value = float(new_text) + value_changed.emit(value) + + dirty = true + state = NumEditState.IDLE + if line_input: + line_input.visible = false + line_display.visible = true + diff --git a/addons/cyclops_level_builder/controls/numeric_line_edit.gd.uid b/addons/cyclops_level_builder/controls/numeric_line_edit.gd.uid new file mode 100644 index 00000000..e3121ade --- /dev/null +++ b/addons/cyclops_level_builder/controls/numeric_line_edit.gd.uid @@ -0,0 +1 @@ +uid://d2w140s6ts4p diff --git a/addons/cyclops_level_builder/controls/numeric_line_edit.tscn b/addons/cyclops_level_builder/controls/numeric_line_edit.tscn new file mode 100644 index 00000000..4f53e746 --- /dev/null +++ b/addons/cyclops_level_builder/controls/numeric_line_edit.tscn @@ -0,0 +1,44 @@ +[gd_scene load_steps=5 format=3 uid="uid://diibmlqy1mpqb"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.gd" id="1_u8bpo"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_o7f15"] +bg_color = Color(0.0627451, 0.0627451, 0.0627451, 1) + +[sub_resource type="Theme" id="Theme_cw2vs"] +Label/styles/normal = SubResource("StyleBoxFlat_o7f15") + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_8gfnv"] +content_margin_left = 4.0 +content_margin_top = 4.0 +content_margin_right = 4.0 +content_margin_bottom = 4.0 + +[node name="numeric_line_edit" type="PanelContainer"] +offset_right = 476.0 +offset_bottom = 23.0 +script = ExtResource("1_u8bpo") +snap_size = 0.125 + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="line_input" type="LineEdit" parent="HBoxContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_horizontal = 3 +text = "0" +alignment = 2 +select_all_on_focus = true + +[node name="line_display" type="Label" parent="HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +theme = SubResource("Theme_cw2vs") +theme_override_styles/normal = SubResource("StyleBoxEmpty_8gfnv") +text = "0" +horizontal_alignment = 2 + +[connection signal="text_submitted" from="HBoxContainer/line_input" to="." method="_on_line_edit_text_submitted"] diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd new file mode 100644 index 00000000..0fa74232 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd @@ -0,0 +1,66 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CheckBox +class_name LineEditorBool + +var resource:Resource: + get: + return resource + set(value): + resource = value + dirty = true + +var prop_name:String: + get: + return prop_name + set(value): + prop_name = value + dirty = true + +var dirty = true + +func update_from_resource(): + if resource: + var result = resource.get(prop_name) + if result != null: + button_pressed = result + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + update_from_resource() + dirty = false + + +func _on_toggled(button_pressed): + if resource: +# print("prop_name %s" % prop_name) +# print("button_pressed %s" % button_pressed) + resource.set(prop_name, button_pressed) diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd.uid b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd.uid new file mode 100644 index 00000000..4c595540 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd.uid @@ -0,0 +1 @@ +uid://bs5xkqkatxt2k diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.tscn b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.tscn new file mode 100644 index 00000000..9ece333c --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.tscn @@ -0,0 +1,10 @@ +[gd_scene load_steps=2 format=3 uid="uid://dpncabeqiv1xo"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.gd" id="1_sn3qq"] + +[node name="CheckBox" type="CheckBox"] +offset_right = 24.0 +offset_bottom = 24.0 +script = ExtResource("1_sn3qq") + +[connection signal="toggled" from="." to="." method="_on_toggled"] diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd new file mode 100644 index 00000000..c3eea2e1 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd @@ -0,0 +1,65 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends SpinBox +class_name LineEditorFloat + + +var resource:Resource: + get: + return resource + set(value): + resource = value + dirty = true + +var prop_name:String: + get: + return prop_name + set(value): + prop_name = value + dirty = true + +var dirty = true + +func update_from_resource(): + if resource: + var result = resource.get(prop_name) + if result != null: + value = result + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + update_from_resource() + dirty = false + + +func _on_value_changed(value): + if resource: + resource.set(prop_name, value) diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd.uid b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd.uid new file mode 100644 index 00000000..cc382b29 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd.uid @@ -0,0 +1 @@ +uid://b2lgdxnbhlihn diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.tscn b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.tscn new file mode 100644 index 00000000..2ce2af20 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.tscn @@ -0,0 +1,11 @@ +[gd_scene load_steps=2 format=3 uid="uid://dg45e7tw7ttu3"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.gd" id="1_o1hmb"] + +[node name="SpinBox" type="SpinBox"] +offset_right = 83.0625 +offset_bottom = 31.0 +step = 0.001 +script = ExtResource("1_o1hmb") + +[connection signal="value_changed" from="." to="." method="_on_value_changed"] diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd new file mode 100644 index 00000000..3ccd0a3e --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd @@ -0,0 +1,71 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends SpinBox +class_name LineEditorInt + +var resource:Resource: + get: + return resource + set(value): + resource = value + dirty = true + +var prop_name:String: + get: + return prop_name + set(value): + prop_name = value + dirty = true + +var dirty = true + +func update_from_resource(): + #print("update_from_resource()") + if resource: + #print("resource %s" % resource) + #print("prop_name %s" % prop_name) + var result = resource.get(prop_name) + #print("result %s" % result) + if result != null: + value = result + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + update_from_resource() + dirty = false + + +func _on_value_changed(value): +# print("_on_value_changed(value)") + if resource: +# print("prop_name %s" % prop_name) +# print("value %s" % value) + resource.set(prop_name, value) diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd.uid b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd.uid new file mode 100644 index 00000000..d55d91e8 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd.uid @@ -0,0 +1 @@ +uid://dbkxopo7d47lq diff --git a/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.tscn b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.tscn new file mode 100644 index 00000000..35e8ef94 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.tscn @@ -0,0 +1,10 @@ +[gd_scene load_steps=2 format=3 uid="uid://dh6frljlp7oqe"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.gd" id="1_ryygx"] + +[node name="SpinBox" type="SpinBox"] +offset_right = 83.0625 +offset_bottom = 40.0 +script = ExtResource("1_ryygx") + +[connection signal="value_changed" from="." to="." method="_on_value_changed"] diff --git a/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd b/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd new file mode 100644 index 00000000..16de2ba5 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd @@ -0,0 +1,86 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Control +class_name ResourceInspector + +@export var target:Resource: + get: + return target + set(value): + target = value + build() + +func add_label(name:String): + var label:Label = Label.new() + label.text = name + $GridContainer.add_child(label) + +func build(): + for child in $GridContainer.get_children(): + $GridContainer.remove_child(child) + + if !target: + return + + for prop_dict in target.get_property_list(): + var prop_name:String = prop_dict["name"] +# prop_dict["class_name"] + + var type:Variant.Type = prop_dict["type"] + match type: + TYPE_BOOL: + add_label(prop_name) + + var editor:LineEditorBool = preload("res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_bool.tscn").instantiate() + editor.resource = target + editor.prop_name = prop_name + $GridContainer.add_child(editor) + + TYPE_INT: + add_label(prop_name) + + var editor:LineEditorInt = preload("res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_int.tscn").instantiate() + editor.resource = target + editor.prop_name = prop_name + $GridContainer.add_child(editor) + + TYPE_FLOAT: + add_label(prop_name) + + var editor:LineEditorFloat = preload("res://addons/cyclops_level_builder/controls/resource_inspector/line_editor_float.tscn").instantiate() + editor.resource = target + editor.prop_name = prop_name + $GridContainer.add_child(editor) + + pass + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd.uid b/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd.uid new file mode 100644 index 00000000..d9d5205c --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd.uid @@ -0,0 +1 @@ +uid://khhux7nnmrxl diff --git a/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.tscn b/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.tscn new file mode 100644 index 00000000..043660b6 --- /dev/null +++ b/addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=2 format=3 uid="uid://c2484sv0ymy2e"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.gd" id="1_m3yhx"] + +[node name="object_inspector" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_m3yhx") + +[node name="GridContainer" type="GridContainer" parent="."] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 40.0 +columns = 2 diff --git a/addons/cyclops_level_builder/controls/test_line_edit.gd b/addons/cyclops_level_builder/controls/test_line_edit.gd new file mode 100644 index 00000000..1a065c35 --- /dev/null +++ b/addons/cyclops_level_builder/controls/test_line_edit.gd @@ -0,0 +1,16 @@ +@tool +extends Control +class_name TestLineEdit + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + #$Label.text = "Bar" + var lab:Label = get_node("Label") + print(lab.text) + pass diff --git a/addons/cyclops_level_builder/controls/test_line_edit.gd.uid b/addons/cyclops_level_builder/controls/test_line_edit.gd.uid new file mode 100644 index 00000000..42a834f8 --- /dev/null +++ b/addons/cyclops_level_builder/controls/test_line_edit.gd.uid @@ -0,0 +1 @@ +uid://bkt0348qxgi7u diff --git a/addons/cyclops_level_builder/controls/test_line_edit.tscn b/addons/cyclops_level_builder/controls/test_line_edit.tscn new file mode 100644 index 00000000..31c90f05 --- /dev/null +++ b/addons/cyclops_level_builder/controls/test_line_edit.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=2 format=3 uid="uid://boco8mwkm8bc3"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/test_line_edit.gd" id="1_i4c5n"] + +[node name="test_line_edit" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_i4c5n") + +[node name="Label" type="Label" parent="."] +layout_mode = 0 +offset_right = 40.0 +offset_bottom = 23.0 +text = "Foo" diff --git a/addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd b/addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd new file mode 100644 index 00000000..c4ccc577 --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd @@ -0,0 +1,18 @@ +@tool +extends PanelContainer +class_name TreeTextComponent + +@export var text:String +@export var edit_mode:bool = false + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + %Label.text = text + %Label.visible = !edit_mode + %LineEdit.visible = edit_mode + pass diff --git a/addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd.uid b/addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd.uid new file mode 100644 index 00000000..c20ce40c --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd.uid @@ -0,0 +1 @@ +uid://cbp0p4vrik6y8 diff --git a/addons/cyclops_level_builder/controls/tree/TreeTextComponent.tscn b/addons/cyclops_level_builder/controls/tree/TreeTextComponent.tscn new file mode 100644 index 00000000..0a6e097b --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/TreeTextComponent.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=2 format=3 uid="uid://7xg6fyk4dust"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/tree/TreeTextComponent.gd" id="1_eruho"] + +[node name="TreeTextLine" type="PanelContainer"] +offset_right = 216.0 +offset_bottom = 31.0 +script = ExtResource("1_eruho") + +[node name="Label" type="Label" parent="."] +unique_name_in_owner = true +layout_mode = 2 +text = "text label" + +[node name="LineEdit" type="LineEdit" parent="."] +unique_name_in_owner = true +layout_mode = 2 +text = "line edit" diff --git a/addons/cyclops_level_builder/controls/tree/abstract_cyclops_tree_model.gd b/addons/cyclops_level_builder/controls/tree/abstract_cyclops_tree_model.gd new file mode 100644 index 00000000..af8e62d8 --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/abstract_cyclops_tree_model.gd @@ -0,0 +1,32 @@ +@tool +class_name AbstractCyclopsTreeModel + +signal tree_nodes_inserted(parent_node:Object, child_nodes:Array[Object], child_node_indices:PackedInt32Array) +signal tree_nodes_removed(parent_node:Object, child_nodes:Array[Object], child_node_indices:PackedInt32Array) + +#Display data of node has changed, but no the child structore +signal value_for_node_changed(old_node:Object, new_node:Object) + +#Rebuild this ode and all children +signal tree_node_changed(node:Object) + +#Entire tree needs to be rebuilt +signal tree_structure_changed() + +class CyclopsTreePath: + var path:Array[Object] + +func get_child(parent:Object, index:int)->Object: + return null + +func get_child_count(parent:Object)->int: + return 0 + +func get_index_of_child(parent:Object, child:Object)->int: + return -1 + +func get_root()->Object: + return null + +func is_leaf(node:Object)->bool: + return true diff --git a/addons/cyclops_level_builder/controls/tree/abstract_cyclops_tree_model.gd.uid b/addons/cyclops_level_builder/controls/tree/abstract_cyclops_tree_model.gd.uid new file mode 100644 index 00000000..53bf6358 --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/abstract_cyclops_tree_model.gd.uid @@ -0,0 +1 @@ +uid://n7cg0v7k3cyb diff --git a/addons/cyclops_level_builder/controls/tree/cyclops_tree.gd b/addons/cyclops_level_builder/controls/tree/cyclops_tree.gd new file mode 100644 index 00000000..f3b12ed5 --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/cyclops_tree.gd @@ -0,0 +1,65 @@ +@tool +extends PanelContainer +class_name CyclopsTree + +@export var node_display_component:PackedScene + +var model:AbstractCyclopsTreeModel: + get: + return model + set(value): + if model == value: + return + + if model: + model.tree_nodes_inserted.disconnect(on_tree_nodes_inserted) + model.tree_nodes_removed.disconnect(on_tree_nodes_removed) + model.refresh_node.disconnect(on_refresh_node) + model.tree_node_changed.disconnect(on_tree_node_changed) + model.tree_structure_changed.disconnect(on_tree_structure_changed) + + model = value + + if model: + model.tree_nodes_inserted.connect(on_tree_nodes_inserted) + model.tree_nodes_removed.connect(on_tree_nodes_removed) + model.refresh_node.connect(on_refresh_node) + model.tree_node_changed.connect(on_tree_node_changed) + model.tree_structure_changed.connect(on_tree_structure_changed) + + rebuild_tree() + +func on_tree_nodes_inserted(parent_node:Object, child_nodes:Array[Object], child_node_indices:PackedInt32Array): + pass + +func on_tree_nodes_removed(parent_node:Object, child_nodes:Array[Object], child_node_indices:PackedInt32Array): + pass + +func on_refresh_node(old_node:Object, new_node:Object): + pass + +func on_tree_node_changed(node:Object): + pass + +func on_tree_structure_changed(): + rebuild_tree() + +func rebuild_tree(): + for child in get_children(): + remove_child(child) + child.queue_free() + + if !model: + return + + model.get_root() + pass + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/addons/cyclops_level_builder/controls/tree/cyclops_tree.gd.uid b/addons/cyclops_level_builder/controls/tree/cyclops_tree.gd.uid new file mode 100644 index 00000000..02e62e02 --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/cyclops_tree.gd.uid @@ -0,0 +1 @@ +uid://blygqcaoveq3j diff --git a/addons/cyclops_level_builder/controls/tree/cyclops_tree.tscn b/addons/cyclops_level_builder/controls/tree/cyclops_tree.tscn new file mode 100644 index 00000000..c6632064 --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/cyclops_tree.tscn @@ -0,0 +1,8 @@ +[gd_scene load_steps=2 format=3 uid="uid://cq6olx6nychug"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/tree/cyclops_tree.gd" id="1_5sunq"] + +[node name="CyclopsTree" type="PanelContainer"] +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("1_5sunq") diff --git a/addons/cyclops_level_builder/controls/tree/tree_tier_component.tscn b/addons/cyclops_level_builder/controls/tree/tree_tier_component.tscn new file mode 100644 index 00000000..7fe05108 --- /dev/null +++ b/addons/cyclops_level_builder/controls/tree/tree_tier_component.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=3 format=3 uid="uid://bd6lfhom4yxls"] + +[ext_resource type="Texture2D" uid="uid://c7c2vg6lbhmfn" path="res://addons/cyclops_level_builder/art/icons/arrow_right.svg" id="1_rpn77"] +[ext_resource type="Texture2D" uid="uid://bor2x3t7fiqc2" path="res://addons/cyclops_level_builder/art/icons/arrow_down.svg" id="2_58w4p"] + +[node name="PanelContainer" type="PanelContainer"] +offset_right = 230.0 +offset_bottom = 210.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="bn_expand" type="TextureButton" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +toggle_mode = true +texture_normal = ExtResource("1_rpn77") +texture_pressed = ExtResource("2_58w4p") + +[node name="NodeDisplayArea" type="PanelContainer" parent="VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="DropdownArea" type="HBoxContainer" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/DropdownArea"] +layout_mode = 2 +theme_override_constants/margin_left = 8 + +[node name="ChildArea" type="PanelContainer" parent="VBoxContainer/DropdownArea"] +unique_name_in_owner = true +layout_mode = 2 diff --git a/addons/cyclops_level_builder/controls/vector3_edit.gd b/addons/cyclops_level_builder/controls/vector3_edit.gd new file mode 100644 index 00000000..2ffcc4b6 --- /dev/null +++ b/addons/cyclops_level_builder/controls/vector3_edit.gd @@ -0,0 +1,44 @@ +@tool +extends HBoxContainer +class_name Vector3Edit + +signal value_changed(value:Vector3) + +@export var value:Vector3: + get: + return value + set(v): + if value == v: + return + + value = v + value_changed.emit(v) + dirty = true + +var dirty:bool = true + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + %edit_x.value = value.x + %edit_y.value = value.y + %edit_z.value = value.z + dirty = false + + + +func _on_edit_x_value_changed(v:float): + value = Vector3(v, value.y, value.z) + + +func _on_edit_y_value_changed(v:float): + value = Vector3(value.x, v, value.z) + + +func _on_edit_z_value_changed(v:float): + value = Vector3(value.x, value.y, v) diff --git a/addons/cyclops_level_builder/controls/vector3_edit.gd.uid b/addons/cyclops_level_builder/controls/vector3_edit.gd.uid new file mode 100644 index 00000000..f7ab718c --- /dev/null +++ b/addons/cyclops_level_builder/controls/vector3_edit.gd.uid @@ -0,0 +1 @@ +uid://blfg5y8ys5hbn diff --git a/addons/cyclops_level_builder/controls/vector3_edit.tscn b/addons/cyclops_level_builder/controls/vector3_edit.tscn new file mode 100644 index 00000000..528e60f9 --- /dev/null +++ b/addons/cyclops_level_builder/controls/vector3_edit.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=3 format=3 uid="uid://cphtpklx81l3w"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/vector3_edit.gd" id="1_lnptu"] +[ext_resource type="PackedScene" uid="uid://diibmlqy1mpqb" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.tscn" id="2_wjq53"] + +[node name="vector3_edit" type="HBoxContainer"] +offset_right = 237.0 +offset_bottom = 26.0 +script = ExtResource("1_lnptu") + +[node name="Label" type="Label" parent="."] +layout_mode = 2 +text = "X:" + +[node name="edit_x" parent="." instance=ExtResource("2_wjq53")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label2" type="Label" parent="."] +layout_mode = 2 +text = "Y:" + +[node name="edit_y" parent="." instance=ExtResource("2_wjq53")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label3" type="Label" parent="."] +layout_mode = 2 +text = "Z:" + +[node name="edit_z" parent="." instance=ExtResource("2_wjq53")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[connection signal="value_changed" from="edit_x" to="." method="_on_edit_x_value_changed"] +[connection signal="value_changed" from="edit_y" to="." method="_on_edit_y_value_changed"] +[connection signal="value_changed" from="edit_z" to="." method="_on_edit_z_value_changed"] diff --git a/addons/cyclops_level_builder/controls/vertex_billboard.gd b/addons/cyclops_level_builder/controls/vertex_billboard.gd new file mode 100644 index 00000000..3b7ee351 --- /dev/null +++ b/addons/cyclops_level_builder/controls/vertex_billboard.gd @@ -0,0 +1,56 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Node3D +class_name VertexBillboard + +@export var radius:float = 4: + get: + return radius + set(value): + radius = value + dirty = true + +@export var color:Color = Color.WHITE: + get: + return color + set(value): + color = value + dirty = true + +var dirty:bool = true + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + var mat:ShaderMaterial = $MeshInstance3D.get_active_material(0) + #print("active mat %s" % mat) + mat.set_shader_parameter("radius", radius) + mat.set_shader_parameter("emission", color) + dirty = false diff --git a/addons/cyclops_level_builder/controls/vertex_billboard.gd.uid b/addons/cyclops_level_builder/controls/vertex_billboard.gd.uid new file mode 100644 index 00000000..0735ea94 --- /dev/null +++ b/addons/cyclops_level_builder/controls/vertex_billboard.gd.uid @@ -0,0 +1 @@ +uid://bndxllx2b8smd diff --git a/addons/cyclops_level_builder/controls/vertex_billboard.tscn b/addons/cyclops_level_builder/controls/vertex_billboard.tscn new file mode 100644 index 00000000..e6e3d9f0 --- /dev/null +++ b/addons/cyclops_level_builder/controls/vertex_billboard.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=4 format=3 uid="uid://cuykufmlg2unb"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/controls/vertex_billboard.gd" id="1_cman8"] +[ext_resource type="Material" uid="uid://rtk56g3h03nt" path="res://addons/cyclops_level_builder/materials/vertex_active_material.tres" id="2_ov23w"] + +[sub_resource type="QuadMesh" id="QuadMesh_5jfb0"] + +[node name="vertex_billboard" type="Node3D"] +script = ExtResource("1_cman8") +color = Color(0, 1, 0, 1) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +material_override = ExtResource("2_ov23w") +mesh = SubResource("QuadMesh_5jfb0") diff --git a/addons/cyclops_level_builder/cyclops_global_scene.gd b/addons/cyclops_level_builder/cyclops_global_scene.gd new file mode 100644 index 00000000..c4cd2af4 --- /dev/null +++ b/addons/cyclops_level_builder/cyclops_global_scene.gd @@ -0,0 +1,365 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Node3D +class_name CyclopsGlobalScene + +@export var selection_color:Color = Color(1, .5, .5, 1) +@export var default_material:Material = preload("res://addons/cyclops_level_builder/materials/grid.tres") +@export var selection_rect_material:Material = preload("res://addons/cyclops_level_builder/materials/selection_rect_material.tres") +@export var tool_edit_active_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_active_material.tres") +@export var tool_edit_active_fill_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_active_fill_material.tres") +@export var tool_edit_selected_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_selected_material.tres") +@export var tool_edit_selected_fill_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_selected_fill_material.tres") +@export var tool_edit_unselected_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_edit_unselected_material.tres") +@export var tool_object_active_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_object_active_material.tres") +@export var tool_object_selected_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_object_selected_material.tres") +@export var vertex_unselected_material:Material = preload("res://addons/cyclops_level_builder/materials/vertex_unselected_material.tres") +@export var vertex_selected_material:Material = preload("res://addons/cyclops_level_builder/materials/vertex_selected_material.tres") +@export var vertex_active_material:Material = preload("res://addons/cyclops_level_builder/materials/vertex_active_material.tres") +@export var vertex_tool_material:Material = preload("res://addons/cyclops_level_builder/materials/vertex_tool_material.tres") +@export var vertex_radius:float = 8 + +@export var tool_material:Material = preload("res://addons/cyclops_level_builder/materials/tool_material.tres") +@export var outline_material:Material = preload("res://addons/cyclops_level_builder/materials/outline_material.tres") +var tool_mesh:ImmediateMesh + +@export var units_font:Font +@export var units_font_size:int = 16 + +#@export var grid_size:int = 0 +@export var drag_angle_limit:float = deg_to_rad(5) + +const SNAPPING_ENABLED:String = "snapping/enabled" +const SNAPPING_GRID_UNIT_SIZE:String = "snapping/grid/unit_size" +const SNAPPING_GRID_USE_SUBDIVISIONS:String = "snapping/grid/use_subdivisions" +const SNAPPING_GRID_SUBDIVISIONS:String = "snapping/grid/subdivisions" +const SNAPPING_GRID_POWER_OF_TWO_SCALE:String = "snapping/grid/power_of_two_scale" +const SNAPPING_GRID_TRANSFORM:String = "snapping/grid/transform" +const SNAPPING_GRID_ANGLE:String = "snapping/grid/angle" + +@export_file("*.config") var settings_file:String = "cyclops_settings.config" +var settings:CyclopsSettings = CyclopsSettings.new() + +signal xray_mode_changed(value:bool) + +@export var xray_mode:bool = false: + get: + return xray_mode + set(value): + if xray_mode != value: + xray_mode = value + xray_mode_changed.emit(value) + +var unit_sphere:GeometryMesh +var builder:CyclopsLevelBuilder + + +# Called when the node enters the scene tree for the first time. +func _ready(): + init_settings() + + unit_sphere = MathGeometry.unit_sphere() + + tool_mesh = ImmediateMesh.new() + $ToolInstance3D.mesh = tool_mesh + + if FileAccess.file_exists(settings_file): + settings.load_from_file(settings_file) + +func init_settings(): + settings.add_setting(SNAPPING_ENABLED, true, TYPE_BOOL) + settings.add_setting(SNAPPING_GRID_UNIT_SIZE, 1, TYPE_FLOAT) + settings.add_setting(SNAPPING_GRID_POWER_OF_TWO_SCALE, 0, TYPE_INT) + settings.add_setting(SNAPPING_GRID_USE_SUBDIVISIONS, false, TYPE_BOOL) + settings.add_setting(SNAPPING_GRID_SUBDIVISIONS, 10, TYPE_INT) + settings.add_setting(SNAPPING_GRID_TRANSFORM, Transform3D.IDENTITY, TYPE_TRANSFORM3D) + settings.add_setting(SNAPPING_GRID_ANGLE, 15, TYPE_FLOAT) + +func save_settings(): + #print("saving ", settings_file) + settings.save_to_file(settings_file) + +func calc_snap_to_grid_util(): + var snap_to_grid_util:SnapToGridUtil = SnapToGridUtil.new() + #print("calc_snap_to_grid_util") + snap_to_grid_util.unit_size = settings.get_property(SNAPPING_GRID_UNIT_SIZE) + #print("unit_size ", snap_to_grid_util.unit_size) + snap_to_grid_util.power_of_two_scale = settings.get_property(SNAPPING_GRID_POWER_OF_TWO_SCALE) + #print("power_of_two_scale ", snap_to_grid_util.power_of_two_scale) + snap_to_grid_util.use_subdivisions = settings.get_property(SNAPPING_GRID_USE_SUBDIVISIONS) + snap_to_grid_util.grid_subdivisions = settings.get_property(SNAPPING_GRID_SUBDIVISIONS) + snap_to_grid_util.grid_transform = settings.get_property(SNAPPING_GRID_TRANSFORM) + return snap_to_grid_util + +#Called by CyclopsLevelBuilder to draw 2D components +func draw_over_viewport(overlay:Control): + pass + +func draw_line(p0:Vector3, p1:Vector3, mat:Material): + + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINES, mat) + + tool_mesh.surface_add_vertex(p0) + tool_mesh.surface_add_vertex(p1) + + tool_mesh.surface_end() + +func draw_loop(points:PackedVector3Array, closed:bool = true, mat:Material = null): + if points.is_empty(): + return + + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat) + + for p in points: + tool_mesh.surface_add_vertex(p) + + if closed: + tool_mesh.surface_add_vertex(points[0]) + + tool_mesh.surface_end() + + +func draw_wireframe(points:PackedVector3Array, edges:PackedInt32Array, mat:Material = null, vertex_mat = null): + for p in points: + draw_vertex(p, vertex_mat) + + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat) + + for e_idx in edges: + tool_mesh.surface_add_vertex(points[e_idx]) + + tool_mesh.surface_end() + + +func draw_prism(points:PackedVector3Array, extrude:Vector3, mat:Material = null, vertex_mat = null): + for p in points: + draw_vertex(p, vertex_mat) + draw_vertex(p + extrude, vertex_mat) + + #Bottom loop + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat) + + for p in points: + tool_mesh.surface_add_vertex(p) + + tool_mesh.surface_add_vertex(points[0]) + + tool_mesh.surface_end() + + #Top loop + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat) + + for p in points: + tool_mesh.surface_add_vertex(p + extrude) + + tool_mesh.surface_add_vertex(points[0] + extrude) + + tool_mesh.surface_end() + + #Sides + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINES, mat) + + for p in points: + tool_mesh.surface_add_vertex(p) + tool_mesh.surface_add_vertex(p + extrude) + + tool_mesh.surface_end() + + +func draw_triangles(tri_points:PackedVector3Array, mat:Material = null): + tool_mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES, mat) + + for p in tri_points: + tool_mesh.surface_add_vertex(p) + + tool_mesh.surface_end() + +func draw_rect(start:Vector3, end:Vector3, mat:Material = null, vertex_mat:Material = null): + + var p0:Vector3 = start + var p2:Vector3 = end + var p1:Vector3 = Vector3(p0.x, p0.y, p2.z) + var p3:Vector3 = Vector3(p2.x, p0.y, p0.z) + + draw_vertex(p0, vertex_mat) + draw_vertex(p1, vertex_mat) + draw_vertex(p2, vertex_mat) + draw_vertex(p3, vertex_mat) + + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, mat) + + tool_mesh.surface_add_vertex(p0) + tool_mesh.surface_add_vertex(p1) + tool_mesh.surface_add_vertex(p2) + tool_mesh.surface_add_vertex(p3) + tool_mesh.surface_add_vertex(p0) + + tool_mesh.surface_end() + +func clear_tool_mesh(): + #tool_mesh = ImmediateMesh.new() + #$ToolInstance3D.mesh = tool_mesh + tool_mesh.clear_surfaces() + + for child in %VertexGroup.get_children(): + %VertexGroup.remove_child(child) + child.queue_free() + #print("clear") + %cyclops_overlay.clear() + +func draw_text(text:String, pos:Vector2, font:Font, font_size:float): + %cyclops_overlay.draw_text(text, pos, font, font_size) + +# Draws the bounding box for the points [p0, p1, p2] +func draw_cube(p0:Vector3, p1:Vector3, p2:Vector3, mat:Material = null, vertex_mat:Material = null): +# print ("draw_cube %s %s %s" % [p0, p1, p2]) + + var bounds:AABB = AABB(p0, Vector3.ZERO) + bounds = bounds.expand(p1) + bounds = bounds.expand(p2) + + var p000:Vector3 = bounds.position + var p111:Vector3 = bounds.end + var p001:Vector3 = Vector3(p000.x, p000.y, p111.z) + var p010:Vector3 = Vector3(p000.x, p111.y, p000.z) + var p011:Vector3 = Vector3(p000.x, p111.y, p111.z) + var p100:Vector3 = Vector3(p111.x, p000.y, p000.z) + var p101:Vector3 = Vector3(p111.x, p000.y, p111.z) + var p110:Vector3 = Vector3(p111.x, p111.y, p000.z) + + draw_vertex(p000, vertex_mat) + draw_vertex(p001, vertex_mat) + draw_vertex(p010, vertex_mat) + draw_vertex(p011, vertex_mat) + draw_vertex(p100, vertex_mat) + draw_vertex(p101, vertex_mat) + draw_vertex(p110, vertex_mat) + draw_vertex(p111, vertex_mat) + + + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINES, mat) + + tool_mesh.surface_add_vertex(p000) + tool_mesh.surface_add_vertex(p001) + tool_mesh.surface_add_vertex(p000) + tool_mesh.surface_add_vertex(p100) + tool_mesh.surface_add_vertex(p101) + tool_mesh.surface_add_vertex(p001) + tool_mesh.surface_add_vertex(p101) + tool_mesh.surface_add_vertex(p100) + + tool_mesh.surface_add_vertex(p010) + tool_mesh.surface_add_vertex(p011) + tool_mesh.surface_add_vertex(p010) + tool_mesh.surface_add_vertex(p110) + tool_mesh.surface_add_vertex(p111) + tool_mesh.surface_add_vertex(p011) + tool_mesh.surface_add_vertex(p111) + tool_mesh.surface_add_vertex(p110) + + tool_mesh.surface_add_vertex(p000) + tool_mesh.surface_add_vertex(p010) + tool_mesh.surface_add_vertex(p100) + tool_mesh.surface_add_vertex(p110) + tool_mesh.surface_add_vertex(p101) + tool_mesh.surface_add_vertex(p111) + tool_mesh.surface_add_vertex(p001) + tool_mesh.surface_add_vertex(p011) + + tool_mesh.surface_end() + + #$ToolInstance3D.mesh = mesh + +func draw_points(points:PackedVector3Array, vertex_mat:Material = null): + draw_vertices(points, vertex_mat) + +func draw_vertex(position:Vector3, mat:Material = null): + draw_vertices([position], mat) + +func draw_vertices(vertices:PackedVector3Array, mat:Material = null): + var arr_mesh = ArrayMesh.new() + var arrays = [] + arrays.resize(Mesh.ARRAY_MAX) + arrays[Mesh.ARRAY_VERTEX] = vertices + + arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_POINTS, arrays) + var mesh_inst = MeshInstance3D.new() + mesh_inst.mesh = arr_mesh + + mesh_inst.material_override = mat + + %VertexGroup.add_child(mesh_inst) + + + +func draw_sphere(xform:Transform3D = Transform3D.IDENTITY, material:Material = null, segs_lat:int = 6, segs_long:int = 8): + unit_sphere.append_to_immediate_mesh(tool_mesh, material, xform) + + +func draw_selected_blocks(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_node("/root/CyclopsAutoload") + + var blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + var active_block:CyclopsBlock = builder.get_active_block() + for block in blocks: + var active:bool = block == active_block + var mat:Material = global_scene.tool_object_active_material if active else global_scene.tool_object_selected_material + + #Selection highlight outline + block.append_mesh_outline(tool_mesh, viewport_camera, block.global_transform, mat) + + #block.draw_unit_labels(viewport_camera, block.global_transform) + + +func draw_screen_rect(viewport_camera:Camera3D, p00:Vector2, p11:Vector2, material:Material): + var global_scene:CyclopsGlobalScene = builder.get_node("/root/CyclopsAutoload") + + var p01:Vector2 = Vector2(p00.x, p11.y) + var p10:Vector2 = Vector2(p11.x, p00.y) + var z_pos:float = (viewport_camera.near + viewport_camera.far) / 2 + + tool_mesh.surface_begin(Mesh.PRIMITIVE_LINE_STRIP, material) + + for p in [p00, p01, p11, p10, p00]: + var p_proj:Vector3 = viewport_camera.project_position(p, z_pos) +# print("p_proj %s" % p_proj) + + tool_mesh.surface_add_vertex(p_proj) + + tool_mesh.surface_end() + +func set_custom_gizmo(gizmo:Node3D): + for child in %GizmoControl.get_children(): + %GizmoControl.remove_child(child) + + if gizmo: +# print("Setting gizmo") + %GizmoControl.add_child(gizmo) + + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/addons/cyclops_level_builder/cyclops_global_scene.gd.uid b/addons/cyclops_level_builder/cyclops_global_scene.gd.uid new file mode 100644 index 00000000..af24aeb8 --- /dev/null +++ b/addons/cyclops_level_builder/cyclops_global_scene.gd.uid @@ -0,0 +1 @@ +uid://djybn1iehyo7j diff --git a/addons/cyclops_level_builder/cyclops_global_scene.tscn b/addons/cyclops_level_builder/cyclops_global_scene.tscn new file mode 100644 index 00000000..b18ccea6 --- /dev/null +++ b/addons/cyclops_level_builder/cyclops_global_scene.tscn @@ -0,0 +1,34 @@ +[gd_scene load_steps=6 format=3 uid="uid://4siqre3jhe80"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/cyclops_global_scene.gd" id="1_nu1d3"] +[ext_resource type="FontFile" uid="uid://dejaio63tyi02" path="res://addons/cyclops_level_builder/art/fonts/Roboto/Roboto-Regular.ttf" id="2_savc6"] +[ext_resource type="Script" path="res://addons/cyclops_level_builder/cyclops_overlay.gd" id="3_uf260"] + +[sub_resource type="PlaneMesh" id="PlaneMesh_sl0cw"] + +[sub_resource type="ImmediateMesh" id="ImmediateMesh_7cfi3"] + +[node name="CyclopsGlobals" type="Node3D"] +script = ExtResource("1_nu1d3") +units_font = ExtResource("2_savc6") + +[node name="ControlMesh" type="MeshInstance3D" parent="."] +visible = false +mesh = SubResource("PlaneMesh_sl0cw") + +[node name="ToolInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("ImmediateMesh_7cfi3") + +[node name="VertexGroup" type="Node3D" parent="."] +unique_name_in_owner = true + +[node name="GizmoControl" type="Node3D" parent="."] +unique_name_in_owner = true + +[node name="cyclops_overlay" type="Control" parent="."] +unique_name_in_owner = true +layout_mode = 3 +anchors_preset = 0 +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("3_uf260") diff --git a/addons/cyclops_level_builder/cyclops_level_builder.gd b/addons/cyclops_level_builder/cyclops_level_builder.gd new file mode 100644 index 00000000..bbd4507d --- /dev/null +++ b/addons/cyclops_level_builder/cyclops_level_builder.gd @@ -0,0 +1,462 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends EditorPlugin +class_name CyclopsLevelBuilder + +signal active_node_changed +signal selection_changed +signal snapping_tool_changed + +const AUTOLOAD_NAME = "CyclopsAutoload" +const CYCLOPS_HUD_NAME = "CyclopsGlobalHud" + +var config:CyclopsConfig = preload("res://addons/cyclops_level_builder/data/configuration.tres") + +var logger:CyclopsLogger = CyclopsLogger.new() + +var material_dock:MaterialPaletteViewport +var convex_face_editor_dock:ConvexFaceEdtiorViewport +var tool_properties_dock:ToolPropertiesDock +var snapping_properties_dock:SnappingPropertiesDock +var cyclops_console_dock:CyclopsConsole +var main_toolbar:MainToolbar +var editor_toolbar:EditorToolbar +var upgrade_cyclops_blocks_toolbar:UpgradeCyclopsBlocksToolbar +var activated:bool = false + +var always_on:bool = false: + get: + return always_on + set(value): + always_on = value + #print("always_on %s" % always_on) + update_activation() + +var block_create_distance:float = 10 +var tool:CyclopsTool = null +var snapping_system:CyclopsSnappingSystem = null +var lock_uvs:bool = false +var tool_overlay_extrude:float = .01 + +var tool_uv_transform:Transform2D +var tool_material_path:String + +var handle_screen_radius:float = 6 + +var drag_start_radius:float = 6 + +enum Mode { OBJECT, EDIT } +var mode:Mode = Mode.OBJECT +enum EditMode { VERTEX, EDGE, FACE } +var edit_mode:CyclopsLevelBuilder.EditMode = CyclopsLevelBuilder.EditMode.VERTEX + +var display_mode:DisplayMode.Type = DisplayMode.Type.MATERIAL + +var cached_viewport_camera:Camera3D + +var editor_cache:Dictionary +var editor_cache_file:String = "user://cyclops_editor_cache.json" + +func get_snapping_manager()->SnappingManager: + var mgr:SnappingManager = SnappingManager.new() + mgr.snap_enabled = CyclopsAutoload.settings.get_property(CyclopsGlobalScene.SNAPPING_ENABLED) + mgr.snap_tool = snapping_system + + return mgr + +func _get_plugin_name()->String: + return "CyclopsLevelBuilder" + +func _get_plugin_icon()->Texture2D: + return preload("res://addons/cyclops_level_builder/art/cyclops.svg") + +func _enter_tree(): + if FileAccess.file_exists(editor_cache_file): + #print(">> _enter_tree") + var text:String = FileAccess.get_file_as_string(editor_cache_file) + #print("load text:", text) + editor_cache = JSON.parse_string(text) + + add_custom_type("CyclopsScene", "Node3D", preload("nodes/cyclops_scene.gd"), preload("nodes/cyclops_blocks_icon.png")) + + add_custom_type("CyclopsBlock", "Node3D", preload("nodes/cyclops_block.gd"), preload("nodes/cyclops_blocks_icon.png")) + add_custom_type("CyclopsBlocks", "Node3D", preload("nodes/cyclops_blocks.gd"), preload("nodes/cyclops_blocks_icon.png")) + add_custom_type("CyclopsConvexBlock", "Node", preload("nodes/cyclops_convex_block.gd"), preload("nodes/cyclops_blocks_icon.png")) + add_custom_type("CyclopsConvexBlockBody", "Node", preload("nodes/cyclops_convex_block_body.gd"), preload("nodes/cyclops_blocks_icon.png")) + + add_autoload_singleton(AUTOLOAD_NAME, "res://addons/cyclops_level_builder/cyclops_global_scene.tscn") + #add_autoload_singleton(CYCLOPS_HUD_NAME, "res://addons/cyclops_level_builder/cyclops_global_hud.tscn") + + material_dock = preload("res://addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.tscn").instantiate() + material_dock.builder = self + + convex_face_editor_dock = preload("res://addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.tscn").instantiate() + convex_face_editor_dock.builder = self + + tool_properties_dock = preload("res://addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.tscn").instantiate() + tool_properties_dock.builder = self + + snapping_properties_dock = preload("res://addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.tscn").instantiate() + snapping_properties_dock.builder = self + + cyclops_console_dock = preload("res://addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.tscn").instantiate() + cyclops_console_dock.editor_plugin = self + + main_toolbar = preload("menu/main_toolbar.tscn").instantiate() + main_toolbar.editor_plugin = self + + editor_toolbar = preload("menu/editor_toolbar.tscn").instantiate() + editor_toolbar.editor_plugin = self + + upgrade_cyclops_blocks_toolbar = preload("res://addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.tscn").instantiate() + upgrade_cyclops_blocks_toolbar.editor_plugin = self + + add_control_to_bottom_panel(cyclops_console_dock, "Cyclops") + + add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, main_toolbar) + + var editor:EditorInterface = get_editor_interface() + var selection:EditorSelection = editor.get_selection() + selection.selection_changed.connect(on_selection_changed) + + update_activation() + + + #Wait until everything is loaded + await get_tree().process_frame + + var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + global_scene.builder = self + + switch_to_snapping_system(SnappingSystemGrid.new()) + switch_to_tool(ToolBlock.new()) + + +func _exit_tree(): + var file:FileAccess = FileAccess.open(editor_cache_file, FileAccess.WRITE) + #var text:String = JSON.stringify(editor_cache, " ") + #print("saving cache:", text) + file.store_string(JSON.stringify(editor_cache, " ")) + file.close() + + # Clean-up of the plugin goes here. + remove_autoload_singleton(AUTOLOAD_NAME) + #remove_autoload_singleton(CYCLOPS_HUD_NAME) + + remove_custom_type("CyclopsScene") + + remove_custom_type("CyclopsBlock") + remove_custom_type("CyclopsBlocks") + remove_custom_type("CyclopsConvexBlock") + remove_custom_type("CyclopsConvexBlockBody") + + remove_control_from_bottom_panel(cyclops_console_dock) + remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, main_toolbar) + + if activated: + remove_control_from_docks(material_dock) + remove_control_from_docks(convex_face_editor_dock) + remove_control_from_docks(tool_properties_dock) + remove_control_from_docks(snapping_properties_dock) + remove_control_from_docks(cyclops_console_dock) + remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar) + + if upgrade_cyclops_blocks_toolbar.activated: + remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, upgrade_cyclops_blocks_toolbar) + + material_dock.queue_free() + convex_face_editor_dock.queue_free() + tool_properties_dock.queue_free() + snapping_properties_dock.queue_free() + cyclops_console_dock.queue_free() + main_toolbar.queue_free() + editor_toolbar.queue_free() + upgrade_cyclops_blocks_toolbar.queue_free() + +func log(message:String, level:CyclopsLogger.LogLevel = CyclopsLogger.LogLevel.ERROR): + logger.log(message, level) + +func get_blocks()->Array[CyclopsBlock]: + return get_blocks_recursive(get_editor_interface().get_edited_scene_root()) + +func get_blocks_recursive(node:Node)->Array[CyclopsBlock]: + var result:Array[CyclopsBlock] + + if node is CyclopsBlock: + result.append(node) + for child in node.get_children(): + result.append_array(get_blocks_recursive(child)) + return result + +func is_selected(node:Node)->bool: + var selection:EditorSelection = get_editor_interface().get_selection() + for n in selection.get_selected_nodes(): + if n == node: + return true + return false + + +func is_active_block(block:CyclopsBlock)->bool: + var selection:EditorSelection = get_editor_interface().get_selection() + var nodes:Array[Node] = selection.get_selected_nodes() + + return !nodes.is_empty() && nodes.back() == block + +func get_active_block()->CyclopsBlock: + var selection:EditorSelection = get_editor_interface().get_selection() + var nodes:Array[Node] = selection.get_selected_nodes() + + var back:Node = nodes.back() + if back is CyclopsBlock: + return back + return null + + +#Blocks listed in order of selection with last block being the most recent (ie, active) one +func get_selected_blocks()->Array[CyclopsBlock]: + var result:Array[CyclopsBlock] + + var selection:EditorSelection = get_editor_interface().get_selection() + for node in selection.get_selected_nodes(): + if node is CyclopsBlock: + result.append(node) + + return result + +func get_block_add_parent()->Node: + var selection:EditorSelection = get_editor_interface().get_selection() + var nodes:Array = selection.get_selected_nodes() + if nodes.is_empty(): + return get_editor_interface().get_edited_scene_root() + + if nodes[0] is CyclopsBlock: + #print("getting parent of ", nodes[0].name) + return nodes[0].get_parent() + return nodes[0] + +func update_activation(): + var editor:EditorInterface = get_editor_interface() + var selection:EditorSelection = editor.get_selection() + var nodes:Array[Node] = selection.get_selected_nodes() + + #Node list ordered in order of selection with most recently sdelected at end + var node:Node = null + if !nodes.is_empty(): + node = nodes[0] + + if node is CyclopsBlock || always_on: + #print("updarting activation") + if !activated: + add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar) + add_control_to_bottom_panel(material_dock, "Materials") + add_control_to_dock(DOCK_SLOT_RIGHT_BL, convex_face_editor_dock) + add_control_to_dock(DOCK_SLOT_RIGHT_BL, tool_properties_dock) + add_control_to_dock(DOCK_SLOT_RIGHT_BL, snapping_properties_dock) + activated = true + else: + if activated: + remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, editor_toolbar) + remove_control_from_bottom_panel(material_dock) + remove_control_from_docks(convex_face_editor_dock) + remove_control_from_docks(tool_properties_dock) + remove_control_from_docks(snapping_properties_dock) + activated = false + + if node is CyclopsBlocks: + if !upgrade_cyclops_blocks_toolbar.activated: + add_control_to_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, upgrade_cyclops_blocks_toolbar) + upgrade_cyclops_blocks_toolbar.activated = true + else: + if upgrade_cyclops_blocks_toolbar.activated: + remove_control_from_container(EditorPlugin.CONTAINER_SPATIAL_EDITOR_MENU, upgrade_cyclops_blocks_toolbar) + upgrade_cyclops_blocks_toolbar.activated = false + +func on_selection_changed(): + update_activation() + + if cached_viewport_camera: + tool._draw_tool(cached_viewport_camera) + +func _handles(object:Object): +# return object is CyclopsBlocks or object is CyclopsConvexBlock + return object is CyclopsBlock or object is CyclopsBlocks or always_on + +func _forward_3d_draw_over_viewport(viewport_control:Control): + var global_scene:CyclopsGlobalScene = get_global_scene() + global_scene.draw_over_viewport(viewport_control) + #Draw on top of viweport here + +func _forward_3d_gui_input(viewport_camera:Camera3D, event:InputEvent): + #print("plugin: " + event.as_text()) + cached_viewport_camera = viewport_camera + + if tool: + var result:bool = tool._gui_input(viewport_camera, event) + tool._draw_tool(viewport_camera) + return EditorPlugin.AFTER_GUI_INPUT_STOP if result else EditorPlugin.AFTER_GUI_INPUT_PASS + + return EditorPlugin.AFTER_GUI_INPUT_PASS + +func _get_state()->Dictionary: + var state:Dictionary = {} + + #print("ed cache ", str(editor_cache)) + #state["editor_cache"] = editor_cache.duplicate() + + material_dock.save_state(state) + convex_face_editor_dock.save_state(state) + tool_properties_dock.save_state(state) + snapping_properties_dock.save_state(state) + cyclops_console_dock.save_state(state) + + return state + +func _set_state(state): + #print("ed set_state ", str(state)) + + #editor_cache = state.get("editor_cache", {}).duplicate() + + material_dock.load_state(state) + convex_face_editor_dock.load_state(state) + tool_properties_dock.load_state(state) + snapping_properties_dock.load_state(state) + cyclops_console_dock.load_state(state) + + +func get_tool_cache(tool_id:String): + if !editor_cache.has("tool"): + return {} + + if !editor_cache.tool.has(tool_id): + return {} + + return editor_cache.tool[tool_id] + +func set_tool_cache(tool_id:String, cache:Dictionary): + if !editor_cache.has("tool"): + editor_cache["tool"] = {} + + editor_cache.tool[tool_id] = cache + +func get_snapping_cache(tool_id:String): + if !editor_cache.has("snapping"): + return {} + + if !editor_cache.snapping.has(tool_id): + return {} + + return editor_cache.snapping[tool_id] + +func set_snapping_cache(tool_id:String, cache:Dictionary): + if !editor_cache.has("snapping"): + editor_cache["snapping"] = {} + + editor_cache.snapping[tool_id] = cache + +func switch_to_tool(_tool:CyclopsTool): + #print(">> switch to tool") + + if tool: + tool._deactivate() + + tool = _tool + + if tool: + tool._activate(self) + var control:Control = tool._get_tool_properties_editor() + tool_properties_dock.set_editor(control) + +func switch_to_snapping_system(_snapping_system:CyclopsSnappingSystem): + if snapping_system: + snapping_system._deactivate() + + snapping_system = _snapping_system + + if snapping_system: + snapping_system._activate(self) + var control:Control = snapping_system._get_properties_editor() + snapping_properties_dock.set_editor(control) + + snapping_tool_changed.emit() + +func get_global_scene()->CyclopsGlobalScene: + var scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + return scene + + + +func intersect_ray_closest(origin:Vector3, dir:Vector3)->IntersectResults: + var best_result:IntersectResults + + var blocks:Array[CyclopsBlock] = get_blocks() + + for block in blocks: + if !block.is_visible_in_tree(): + continue + + var result:IntersectResults = block.intersect_ray_closest(origin, dir) +# print("isect %s %s" % [node.name, result]) + if result: + if !best_result or result.distance_squared < best_result.distance_squared: +# print("setting best result %s" % node.name) + best_result = result +# print("best_result %s" % ray_best_result) + +# print("returning best result %s" % ray_best_result) + return best_result + +func intersect_ray_closest_selected_only(origin:Vector3, dir:Vector3)->IntersectResults: + var best_result:IntersectResults + + var blocks:Array[CyclopsBlock] = get_selected_blocks() + for block in blocks: + var result:IntersectResults = block.intersect_ray_closest(origin, dir) + if result: + if !best_result or result.distance_squared < best_result.distance_squared: + best_result = result + + return best_result + + +func intersect_frustum_all(frustum:Array[Plane])->Array[CyclopsBlock]: + var result:Array[CyclopsBlock] = [] + + var blocks:Array[CyclopsBlock] = get_blocks() + for block in blocks: + var xform:Transform3D = block.global_transform.affine_inverse() + + var frustum_local:Array[Plane] + for p in frustum: + frustum_local.append(xform * p) + + #print("intersect_frustum_all block %s" % block.get_path()) + var vol:ConvexVolume = block.control_mesh +# if !vol: +# print("nil vol %s" % block.get_path()) + if vol && vol.intersects_frustum(frustum_local): + result.append(block) + + return result + diff --git a/addons/cyclops_level_builder/cyclops_level_builder.gd.uid b/addons/cyclops_level_builder/cyclops_level_builder.gd.uid new file mode 100644 index 00000000..4d093ae8 --- /dev/null +++ b/addons/cyclops_level_builder/cyclops_level_builder.gd.uid @@ -0,0 +1 @@ +uid://cu2dgom4dn1pw diff --git a/addons/cyclops_level_builder/cyclops_overlay.gd b/addons/cyclops_level_builder/cyclops_overlay.gd new file mode 100644 index 00000000..0c584567 --- /dev/null +++ b/addons/cyclops_level_builder/cyclops_overlay.gd @@ -0,0 +1,69 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Control +class_name CyclopsOverlay + + +class TextLabel extends Resource: + var text:String + var pos:Vector2 + var font:Font + var font_size:float + +var text_labels:Array[TextLabel] + +func draw_text(text:String, pos:Vector2, font:Font, font_size:float): + #print("draw_Text") + var label:TextLabel = TextLabel.new() + label.text = text + label.pos = pos + label.font = font + label.font_size = font_size + + text_labels.append(label) + queue_redraw() + +#func add_label(label:TextLabel): +# text_labels.append(label) +# queue_redraw() + +func clear(): + text_labels.clear() + queue_redraw() + +func _draw(): + for label in text_labels: + draw_string(label.font, label.pos, \ + label.text, HORIZONTAL_ALIGNMENT_CENTER, -1, \ + label.font_size) + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/addons/cyclops_level_builder/cyclops_overlay.gd.uid b/addons/cyclops_level_builder/cyclops_overlay.gd.uid new file mode 100644 index 00000000..bdebd6a5 --- /dev/null +++ b/addons/cyclops_level_builder/cyclops_overlay.gd.uid @@ -0,0 +1 @@ +uid://bu0iv5u8xrbof diff --git a/addons/cyclops_level_builder/data/configuration.tres b/addons/cyclops_level_builder/data/configuration.tres new file mode 100644 index 00000000..d499d898 --- /dev/null +++ b/addons/cyclops_level_builder/data/configuration.tres @@ -0,0 +1,22 @@ +[gd_resource type="Resource" script_class="CyclopsConfig" load_steps=16 format=3 uid="uid://b54ok0creqhnb"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/resources/cyclops_config.gd" id="1_jrivp"] +[ext_resource type="Resource" uid="uid://dwxpsgoxb60yp" path="res://addons/cyclops_level_builder/data/snapping_tags/snap_tag_grid.tres" id="2_8mhpe"] +[ext_resource type="Resource" uid="uid://rskdanqaqt1y" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_move.tres" id="2_mkeje"] +[ext_resource type="Resource" uid="uid://beqrq2vlgidpe" path="res://addons/cyclops_level_builder/data/snapping_tags/snap_tag_vertex.tres" id="3_bw3pn"] +[ext_resource type="Resource" uid="uid://c648hs1r46mat" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_create_block.tres" id="3_fxuvh"] +[ext_resource type="Resource" uid="uid://cihxgriu32oxb" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_create_prism.tres" id="4_utowl"] +[ext_resource type="Resource" uid="uid://p0ucaj6w232i" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_rotate.tres" id="5_lrya4"] +[ext_resource type="Resource" uid="uid://wm5lu7jdndym" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_create_cylinder.tres" id="5_yyi6p"] +[ext_resource type="Resource" uid="uid://16f1nwimgn0p" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_create_stairs.tres" id="6_pr2fs"] +[ext_resource type="Resource" uid="uid://buod6sdg7c12l" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_clip.tres" id="7_pbu8d"] +[ext_resource type="Resource" uid="uid://ctj35x0jfg7ej" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_vertex.tres" id="8_m71cc"] +[ext_resource type="Resource" uid="uid://dub6oyal5fxly" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_edge.tres" id="9_hqyx3"] +[ext_resource type="Resource" uid="uid://cmdgd8wmfdo4a" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_face.tres" id="10_j16ya"] +[ext_resource type="Resource" uid="uid://bjmuechy70058" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_material_brush.tres" id="11_ew3jv"] +[ext_resource type="Resource" uid="uid://b1a71dvqwi4h1" path="res://addons/cyclops_level_builder/data/tool_tags/tool_tag_vertex_color_brush.tres" id="15_u2xjc"] + +[resource] +script = ExtResource("1_jrivp") +tool_tags = Array[Resource("res://addons/cyclops_level_builder/resources/tool_tag.gd")]([ExtResource("2_mkeje"), ExtResource("5_lrya4"), ExtResource("3_fxuvh"), ExtResource("4_utowl"), ExtResource("5_yyi6p"), ExtResource("6_pr2fs"), ExtResource("7_pbu8d"), ExtResource("8_m71cc"), ExtResource("9_hqyx3"), ExtResource("10_j16ya"), ExtResource("11_ew3jv"), ExtResource("15_u2xjc")]) +snapping_tags = Array[Resource("res://addons/cyclops_level_builder/snapping/snapping_tag.gd")]([ExtResource("2_8mhpe"), ExtResource("3_bw3pn")]) diff --git a/addons/cyclops_level_builder/data/snapping_tags/snap_tag_grid.tres b/addons/cyclops_level_builder/data/snapping_tags/snap_tag_grid.tres new file mode 100644 index 00000000..5f366e46 --- /dev/null +++ b/addons/cyclops_level_builder/data/snapping_tags/snap_tag_grid.tres @@ -0,0 +1,12 @@ +[gd_resource type="Resource" script_class="SnappingTag" load_steps=4 format=3 uid="uid://dwxpsgoxb60yp"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/snapping/snapping_tag.gd" id="1_jbxkl"] +[ext_resource type="Texture2D" uid="uid://c6mucdu7wcbkm" path="res://addons/cyclops_level_builder/art/icons/snap_grid.svg" id="1_ngui8"] +[ext_resource type="Script" path="res://addons/cyclops_level_builder/snapping/snapping_system_grid.gd" id="2_thx8k"] + +[resource] +script = ExtResource("1_jbxkl") +name = "Grid" +icon = ExtResource("1_ngui8") +tooltip = "Snap to grid points" +snapping_script = ExtResource("2_thx8k") diff --git a/addons/cyclops_level_builder/data/snapping_tags/snap_tag_vertex.tres b/addons/cyclops_level_builder/data/snapping_tags/snap_tag_vertex.tres new file mode 100644 index 00000000..d3329c6a --- /dev/null +++ b/addons/cyclops_level_builder/data/snapping_tags/snap_tag_vertex.tres @@ -0,0 +1,12 @@ +[gd_resource type="Resource" script_class="SnappingTag" load_steps=4 format=3 uid="uid://beqrq2vlgidpe"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/snapping/snapping_tag.gd" id="1_jlotd"] +[ext_resource type="Texture2D" uid="uid://c0x011okomj8n" path="res://addons/cyclops_level_builder/art/icons/snap_vertex.svg" id="1_jmnf8"] +[ext_resource type="Script" path="res://addons/cyclops_level_builder/snapping/snapping_system_vertex.gd" id="2_c0g2w"] + +[resource] +script = ExtResource("1_jlotd") +name = "Vertex" +icon = ExtResource("1_jmnf8") +tooltip = "Snap to vertices" +snapping_script = ExtResource("2_c0g2w") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_clip.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_clip.tres new file mode 100644 index 00000000..af019bc6 --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_clip.tres @@ -0,0 +1,31 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://buod6sdg7c12l"] + +[ext_resource type="Texture2D" uid="uid://bos2j51dp4j1s" path="res://addons/cyclops_level_builder/art/icons/edit_clip.svg" id="1_oaury"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="2_4grct"] +[ext_resource type="Script" uid="uid://dn7yacvdlbtty" path="res://addons/cyclops_level_builder/tools/tool_clip.gd" id="3_xt387"] + +[sub_resource type="InputEventKey" id="InputEventKey_hd0cm"] +device = -1 +pressed = true +keycode = 67 +unicode = 99 + +[resource] +script = ExtResource("2_4grct") +id = "clip" +name = "Clip" +input_events = Array[InputEvent]([SubResource("InputEventKey_hd0cm")]) +input_events_override = false +tooltip = "Clip + +Click on surface of block to place first cutting point. + +Click again to place second cutting point. This will define the plane block will be cut along. + +If you press Enter at this point, the block will be cut. The cutting plane will be defined by the cutting line you've drawn and the normal of the plane it is on. + +You can optionally place a third cutting point. If you do, the three placed points will define the cutting plane when you press Enter. + +Press Backspace to delete the last cutting point you placed." +icon = ExtResource("1_oaury") +tool_script = ExtResource("3_xt387") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_block.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_block.tres new file mode 100644 index 00000000..53897910 --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_block.tres @@ -0,0 +1,33 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://c648hs1r46mat"] + +[ext_resource type="Texture2D" uid="uid://bwasqbq4iqkn6" path="res://addons/cyclops_level_builder/art/icons/block.svg" id="1_qojcl"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="1_vgbvo"] +[ext_resource type="Script" uid="uid://i2mhsltvr4v7" path="res://addons/cyclops_level_builder/tools/tool_block.gd" id="3_52q4h"] + +[sub_resource type="InputEventKey" id="InputEventKey_vdxf5"] +device = -1 +pressed = true +keycode = 82 +unicode = 114 + +[resource] +script = ExtResource("1_vgbvo") +id = "block" +name = "Block" +input_events = Array[InputEvent]([SubResource("InputEventKey_vdxf5")]) +input_events_override = true +tooltip = "Block + +Click and drag in empty space or on unselected block to create a new block. + +Click and drag on a selected block to move it in the XZ plane. Hold Alt to drag along the Y axis. + +Ctrl-click and drag on the face of a block to move the face along its normal. + +Escape or right click to cancel drawing the block. + +Click on block to select it. Shift-Click toggles, Ctrl-Click adds and Shift-Ctrl Click subtracts. + +Click in empty space to clear selection." +icon = ExtResource("1_qojcl") +tool_script = ExtResource("3_52q4h") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_cylinder.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_cylinder.tres new file mode 100644 index 00000000..2c758d5c --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_cylinder.tres @@ -0,0 +1,27 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://wm5lu7jdndym"] + +[ext_resource type="Texture2D" uid="uid://0vye3ue3ayvf" path="res://addons/cyclops_level_builder/art/icons/create_cylinder.svg" id="1_a3871"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="2_8mpiw"] +[ext_resource type="Script" uid="uid://b5sri8n3mrk7n" path="res://addons/cyclops_level_builder/tools/tool_cylinder.gd" id="3_2hl37"] + +[sub_resource type="InputEventKey" id="InputEventKey_qk3nx"] +device = -1 +shift_pressed = true +keycode = 67 +unicode = 67 + +[resource] +script = ExtResource("2_8mpiw") +id = "cylinder" +name = "Cylinder" +input_events = Array[InputEvent]([SubResource("InputEventKey_qk3nx")]) +input_events_override = false +tooltip = "Cylinder + +Click on surface of block or in empty space to begin creating base of a cylinder. + +Release the mouse to enter height drawing mode. If you have the tube option selected, you will draw the second ring instead. + +Use the mouse wheel to change the number of sides of the cylinder while drawing." +icon = ExtResource("1_a3871") +tool_script = ExtResource("3_2hl37") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_prism.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_prism.tres new file mode 100644 index 00000000..8d5fa8a9 --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_prism.tres @@ -0,0 +1,29 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://cihxgriu32oxb"] + +[ext_resource type="Texture2D" uid="uid://cbmwkjbju75er" path="res://addons/cyclops_level_builder/art/icons/create_prism.svg" id="1_gxivr"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="1_oalyb"] +[ext_resource type="Script" uid="uid://diwmb0d2f7o55" path="res://addons/cyclops_level_builder/tools/tool_prism.gd" id="3_oagna"] + +[sub_resource type="InputEventKey" id="InputEventKey_ral6n"] +device = -1 +shift_pressed = true +keycode = 84 +unicode = 84 + +[resource] +script = ExtResource("1_oalyb") +id = "prism" +name = "Prism" +input_events = Array[InputEvent]([SubResource("InputEventKey_ral6n")]) +input_events_override = false +tooltip = "Prism + +Click on surface of block or in empty space to begin creating base of a prism. + +Click to add new point. Backspace to remove the last point you added. You can also right click on a point to remove it. + +Press Enter to extrude base. + +Press Enter again to finish extruding and create block." +icon = ExtResource("1_gxivr") +tool_script = ExtResource("3_oagna") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_stairs.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_stairs.tres new file mode 100644 index 00000000..5c273341 --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_create_stairs.tres @@ -0,0 +1,26 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://16f1nwimgn0p"] + +[ext_resource type="Texture2D" uid="uid://bwq4w4vf8um1f" path="res://addons/cyclops_level_builder/art/icons/create_stairs.svg" id="1_4iod6"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="1_kdc1t"] +[ext_resource type="Script" uid="uid://40clodalq2g4" path="res://addons/cyclops_level_builder/tools/tool_stairs.gd" id="3_5ju43"] + +[sub_resource type="InputEventKey" id="InputEventKey_bydj5"] +device = -1 +shift_pressed = true +pressed = true +keycode = 69 +unicode = 69 + +[resource] +script = ExtResource("1_kdc1t") +id = "stairs" +name = "Stairs" +input_events = Array[InputEvent]([SubResource("InputEventKey_bydj5")]) +input_events_override = false +tooltip = "Click on surface of block or in empty space to begin creating base of a stair case. + +Release mouse button and drag upwards to adjust the height of the stairs. + +Use the mouse wheel to change the direction the stairs face. Ctrl-Wheel to change the height of each step, Ctrl-Shift-Wheel to change the depth of each step." +icon = ExtResource("1_4iod6") +tool_script = ExtResource("3_5ju43") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_duplicate.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_duplicate.tres new file mode 100644 index 00000000..24c991ba --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_duplicate.tres @@ -0,0 +1,11 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=3 format=3 uid="uid://ryja8b4fr8bb"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="1_cii1q"] +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_duplicate.gd" id="2_ml6st"] + +[resource] +script = ExtResource("1_cii1q") +id = "duplicate" +name = "Duplicate" +tooltip = "" +tool_script = ExtResource("2_ml6st") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_edge.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_edge.tres new file mode 100644 index 00000000..5664767d --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_edge.tres @@ -0,0 +1,27 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://dub6oyal5fxly"] + +[ext_resource type="Texture2D" uid="uid://d2da2j8ve48rt" path="res://addons/cyclops_level_builder/art/icons/select_edge.svg" id="1_6o0d8"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="1_w2hsk"] +[ext_resource type="Script" uid="uid://b0w83m8apvlal" path="res://addons/cyclops_level_builder/tools/tool_edit_edge.gd" id="3_6rili"] + +[sub_resource type="InputEventKey" id="InputEventKey_k6fuk"] +device = -1 +pressed = true +keycode = 50 +unicode = 50 + +[resource] +script = ExtResource("1_w2hsk") +id = "edit_edge" +name = "Edge" +input_events = Array[InputEvent]([SubResource("InputEventKey_k6fuk")]) +input_events_override = false +tooltip = "Edge + +Click on an edge to select it. Shift Click to toggle selecton, Ctrl Click to add to selection, Shift-Ctrl click to subtract from selection. + +Click and drag to move edge in XZ plane. Hold Alt to drag along Y axis. Click and drag on a selected edge to move all selected edges. + +Hover the mouse over a different block and press Alt-Q to switch to editing that block." +icon = ExtResource("1_6o0d8") +tool_script = ExtResource("3_6rili") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_face.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_face.tres new file mode 100644 index 00000000..609b9f9a --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_face.tres @@ -0,0 +1,31 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=6 format=3 uid="uid://cmdgd8wmfdo4a"] + +[ext_resource type="Texture2D" uid="uid://bi27fw31w4ssi" path="res://addons/cyclops_level_builder/art/icons/select_face.svg" id="1_s64xo"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="2_qfyqw"] +[ext_resource type="Script" uid="uid://c7gkfpce0w24u" path="res://addons/cyclops_level_builder/tools/tool_edit_face.gd" id="3_y22x5"] + +[sub_resource type="InputEventKey" id="InputEventKey_xxi5p"] +pressed = true +keycode = 51 + +[sub_resource type="InputEventKey" id="InputEventKey_1smmt"] +device = -1 +pressed = true +keycode = 52 +unicode = 52 + +[resource] +script = ExtResource("2_qfyqw") +id = "edit_face" +name = "Face" +input_events = Array[InputEvent]([SubResource("InputEventKey_xxi5p"), SubResource("InputEventKey_1smmt")]) +input_events_override = false +tooltip = "Face + +Click on a face to select it. Shift Click to toggle selecton, Ctrl Click to add to selection, Shift-Ctrl click to subtract from selection. + +Click and drag to move face in XZ plane. Hold Alt to drag along Y axis. Click and drag on a selected face to move all selected faces. + +Hover the mouse over a different block and press Alt-Q to switch to editing that block." +icon = ExtResource("1_s64xo") +tool_script = ExtResource("3_y22x5") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_vertex.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_vertex.tres new file mode 100644 index 00000000..1b5853bf --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_edit_vertex.tres @@ -0,0 +1,27 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://ctj35x0jfg7ej"] + +[ext_resource type="Texture2D" uid="uid://cwn58lev5oopd" path="res://addons/cyclops_level_builder/art/icons/select_vertex.svg" id="1_i5cb7"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="2_yi1sl"] +[ext_resource type="Script" uid="uid://c8bst4y8gdo2c" path="res://addons/cyclops_level_builder/tools/tool_edit_vertex.gd" id="3_3wsge"] + +[sub_resource type="InputEventKey" id="InputEventKey_11fdh"] +device = -1 +pressed = true +keycode = 49 +unicode = 49 + +[resource] +script = ExtResource("2_yi1sl") +id = "edit_vertex" +name = "Vertex" +input_events = Array[InputEvent]([SubResource("InputEventKey_11fdh")]) +input_events_override = false +tooltip = "Vertex + +Click on a vertex to select it. Shift Click to toggle selecton, Ctrl Click to add to selection, Shift-Ctrl click to subtract from selection. + +Click and drag to move vertex in XZ plane. Hold Alt to drag along Y axis. Click and drag on a selected vertex to move all selected vertices. + +Hover the mouse over a different block and press Alt-Q to switch to editing that block." +icon = ExtResource("1_i5cb7") +tool_script = ExtResource("3_3wsge") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_material_brush.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_material_brush.tres new file mode 100644 index 00000000..cf691c84 --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_material_brush.tres @@ -0,0 +1,24 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://bjmuechy70058"] + +[ext_resource type="Texture2D" uid="uid://dw8s7hrmnu34j" path="res://addons/cyclops_level_builder/art/icons/material_brush.svg" id="1_hjh4j"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="2_ooato"] +[ext_resource type="Script" uid="uid://b1eem6ioru7ft" path="res://addons/cyclops_level_builder/tools/tool_material_brush.gd" id="3_1e4l3"] + +[sub_resource type="InputEventKey" id="InputEventKey_enkb2"] +device = -1 +keycode = 66 +unicode = 98 + +[resource] +script = ExtResource("2_ooato") +id = "material_brush" +name = "Material Brush" +input_events = Array[InputEvent]([SubResource("InputEventKey_enkb2")]) +input_events_override = false +tooltip = "Material Brush + +Click and drag on surfaces to apply the currently selected material. + +Shift-X will sample the properties of the face under the brush cursor." +icon = ExtResource("1_hjh4j") +tool_script = ExtResource("3_1e4l3") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_move.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_move.tres new file mode 100644 index 00000000..e858b191 --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_move.tres @@ -0,0 +1,37 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=6 format=3 uid="uid://rskdanqaqt1y"] + +[ext_resource type="Texture2D" uid="uid://cqy2x1s41ypbt" path="res://addons/cyclops_level_builder/art/icons/move.svg" id="1_g0ofo"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="1_skypg"] +[ext_resource type="Script" uid="uid://c5gupwfnlexcn" path="res://addons/cyclops_level_builder/tools/tool_move.gd" id="2_16d6f"] + +[sub_resource type="InputEventKey" id="InputEventKey_0yb0p"] +device = -1 +pressed = true +keycode = 81 +unicode = 113 + +[sub_resource type="InputEventKey" id="InputEventKey_ygw0u"] +device = -1 +pressed = true +keycode = 87 +unicode = 119 + +[resource] +script = ExtResource("1_skypg") +id = "move" +name = "Move" +input_events = Array[InputEvent]([SubResource("InputEventKey_0yb0p"), SubResource("InputEventKey_ygw0u")]) +input_events_override = true +tooltip = "Move + +Click and drag on a selected block to move it in the XZ plane. Hold Alt to drag along the Y axis. + +Click and drag anywhere else to drag a rectangular selection region. + +Escape or right click to cancel movement. + +Click on a block to select it. Shift-Click toggles, Ctrl-Click adds and Shift-Ctrl Click subtracts. + +Click in empty space to clear selection." +icon = ExtResource("1_g0ofo") +tool_script = ExtResource("2_16d6f") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_rotate.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_rotate.tres new file mode 100644 index 00000000..61810969 --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_rotate.tres @@ -0,0 +1,23 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://p0ucaj6w232i"] + +[ext_resource type="Texture2D" uid="uid://1hu5mqwbm55w" path="res://addons/cyclops_level_builder/art/icons/rotate.svg" id="1_12a61"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="2_10xto"] +[ext_resource type="Script" uid="uid://dv6ybnhuukmeh" path="res://addons/cyclops_level_builder/tools/tool_rotate.gd" id="3_nykm1"] + +[sub_resource type="InputEventKey" id="InputEventKey_dvj1l"] +device = -1 +pressed = true +keycode = 69 +unicode = 101 + +[resource] +script = ExtResource("2_10xto") +id = "rotate" +name = "Rotate" +input_events = Array[InputEvent]([SubResource("InputEventKey_dvj1l")]) +input_events_override = true +tooltip = "Rotate + +Click and drag the circle gizmo to rotate around the plane the circle lies in." +icon = ExtResource("1_12a61") +tool_script = ExtResource("3_nykm1") diff --git a/addons/cyclops_level_builder/data/tool_tags/tool_tag_vertex_color_brush.tres b/addons/cyclops_level_builder/data/tool_tags/tool_tag_vertex_color_brush.tres new file mode 100644 index 00000000..0af7fa1f --- /dev/null +++ b/addons/cyclops_level_builder/data/tool_tags/tool_tag_vertex_color_brush.tres @@ -0,0 +1,24 @@ +[gd_resource type="Resource" script_class="ToolTag" load_steps=5 format=3 uid="uid://b1a71dvqwi4h1"] + +[ext_resource type="Texture2D" uid="uid://be3f2j6mnl1yb" path="res://addons/cyclops_level_builder/art/icons/vertex_color_brush.svg" id="1_e5tvl"] +[ext_resource type="Script" uid="uid://cewve1gm2ssbu" path="res://addons/cyclops_level_builder/resources/tool_tag.gd" id="2_pcbhj"] +[ext_resource type="Script" uid="uid://c80pcu50d2sfm" path="res://addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd" id="3_12f6u"] + +[sub_resource type="InputEventKey" id="InputEventKey_v56kt"] +device = -1 +keycode = 86 +unicode = 118 + +[resource] +script = ExtResource("2_pcbhj") +id = "vertex_color_brush" +name = "Vertex Color Brush" +input_events = Array[InputEvent]([SubResource("InputEventKey_v56kt")]) +input_events_override = false +tooltip = "Vertex Color Brush + +Click and drag on surfaces to adjust the vertex color. + +Shift-X will sample the color of the closest vertex." +icon = ExtResource("1_e5tvl") +tool_script = ExtResource("3_12f6u") diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd new file mode 100644 index 00000000..9bf82acf --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd @@ -0,0 +1,77 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends SubViewport +class_name ConvexFaceEditorPreview + + + +@export var target_material:Material: + get: + return target_material + set(value): + target_material = value + dirty = true + +@export var uv_transform:Transform2D = Transform2D.IDENTITY: + get: + return uv_transform + set(value): + if value == uv_transform: + return + uv_transform = value + dirty = true + +@export var color:Color = Color.WHITE: + get: + return color + set(value): + if value == color: + return + color = value + dirty = true + +var dirty:bool = true +#var points:PackedVector3Array = [Vector3(0, 0, 0), Vector3(1, 1, 0), Vector3(1, 0, 0), Vector3(0, 1, 0)] + +func take_snapshot()->ImageTexture: + #print ("pre-grabbing image %s" % target_material.resource_path) + await RenderingServer.frame_post_draw + #print ("grabbing image %s" % target_material.resource_path) + var image:Image = get_viewport().get_texture().get_image() + var tex:ImageTexture = ImageTexture.create_from_image(image) + return tex + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + +func _process(delta): + if dirty: + $UvPreviewStudio.target_material = target_material + $UvPreviewStudio.uv_transform = uv_transform + $UvPreviewStudio.color = color + dirty = false + + diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd.uid b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd.uid new file mode 100644 index 00000000..ff9a4bf5 --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd.uid @@ -0,0 +1 @@ +uid://bud3iu3nmifux diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.tscn b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.tscn new file mode 100644 index 00000000..3cfd6e68 --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=4 format=3 uid="uid://bbfgpupliiqnm"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.gd" id="1_bjhau"] +[ext_resource type="Material" uid="uid://rdhrhgrb78ls" path="res://addons/cyclops_level_builder/materials/grid.tres" id="2_t8xtu"] +[ext_resource type="PackedScene" uid="uid://716oipfa7f5l" path="res://addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.tscn" id="3_jtspd"] + +[node name="UvPreview" type="SubViewport"] +own_world_3d = true +size = Vector2i(256, 256) +render_target_update_mode = 4 +script = ExtResource("1_bjhau") +target_material = ExtResource("2_t8xtu") +color = null + +[node name="UvPreviewStudio" parent="." instance=ExtResource("3_jtspd")] +target_material = ExtResource("2_t8xtu") diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd new file mode 100644 index 00000000..28cabada --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd @@ -0,0 +1,77 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Node3D +class_name ConvexFaceEditorPreviewStudio + + +@export var target_material:Material: + get: + return target_material + set(value): + target_material = value + #$Node3D/MeshInstance3D.material_override = target_material + dirty = true + +@export var uv_transform:Transform2D = Transform2D.IDENTITY: + get: + return uv_transform + set(value): + if value == uv_transform: + return + uv_transform = value + dirty = true + +@export var color:Color = Color.WHITE: + get: + return color + set(value): + if value == color: + return + color = value + dirty = true + +var dirty:bool = true +var points:PackedVector3Array = [Vector3(-1, 1, 0), Vector3(1, 1, 0), Vector3(-1, -1, 0), Vector3(1, -1, 0)] + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): +# print("_process") + if dirty: + var mesh:ImmediateMesh = ImmediateMesh.new() + + mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP, target_material) + + mesh.surface_set_normal(Vector3(0, 0, 1)) + for p in points: + mesh.surface_set_uv(uv_transform * Vector2(p.x, -p.y)) + mesh.surface_set_color(color) + mesh.surface_add_vertex(p) + + mesh.surface_end() + +# print("Building preview mesh") + $MeshInstance3D.mesh = mesh + dirty = false diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd.uid b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd.uid new file mode 100644 index 00000000..e4ee8067 --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd.uid @@ -0,0 +1 @@ +uid://ds054a02v3lls diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.tscn b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.tscn new file mode 100644 index 00000000..3c87e917 --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://716oipfa7f5l"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview_studio.gd" id="1_38c8p"] + +[sub_resource type="ImmediateMesh" id="ImmediateMesh_lw55q"] + +[node name="Node3D" type="Node3D"] +script = ExtResource("1_38c8p") +color = null + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1) +projection = 1 + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("ImmediateMesh_lw55q") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0.0684279) diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd new file mode 100644 index 00000000..12f81ac2 --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd @@ -0,0 +1,241 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Control +class_name ConvexFaceEdtiorViewport + +var material_thumbnail_dirty:bool = true + +var target_material:Material +var empty_material:Material + +var uv_transform:Transform2D = Transform2D.IDENTITY +var color:Color = Color.WHITE + +var builder:CyclopsLevelBuilder: + get: + return builder + set(value): + if builder: + builder.selection_changed.disconnect(on_selection_changed) + + builder = value + + if builder: + builder.selection_changed.connect(on_selection_changed) + +var spin_offset_x:NumbericLineEdit +var spin_offset_y:NumbericLineEdit +var spin_scale_x:NumbericLineEdit +var spin_scale_y:NumbericLineEdit +var spin_rotation:NumbericLineEdit +var spin_skew:NumbericLineEdit + +#var test_slider:EditorSpinSlider + +# Called when the node enters the scene tree for the first time. +func _ready(): + empty_material = StandardMaterial3D.new() + empty_material.albedo_color = Color.BLACK + + spin_offset_x = $VBoxContainer/GridContainer2/HBoxContainer2/offset_x + spin_offset_y = $VBoxContainer/GridContainer2/HBoxContainer/offset_y + spin_scale_x = $VBoxContainer/GridContainer3/HBoxContainer2/scale_x + spin_scale_y = $VBoxContainer/GridContainer3/HBoxContainer/scale_y + spin_rotation = $VBoxContainer/GridContainer4/HBoxContainer2/rotation + spin_skew = $VBoxContainer/GridContainer4/HBoxContainer/skew + +# test_slider = EditorSpinSlider.new() +# test_slider.size_flags_horizontal = Control.SIZE_EXPAND +# $VBoxContainer.add_child(test_slider) + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + + if material_thumbnail_dirty: + material_thumbnail_dirty = false + + $UvPreview.target_material = target_material + $UvPreview.uv_transform = uv_transform + $UvPreview.color = color + + var tex:ImageTexture = await $UvPreview.take_snapshot() + $VBoxContainer/Preview.texture = tex + pass + +func on_selection_changed(): + material_thumbnail_dirty = true + target_material = empty_material + + + var block:CyclopsBlock = builder.get_active_block() + if block: + var vol:ConvexVolume = block.control_mesh + var face_idx = vol.active_face if vol.active_face != -1 else 0 + + var f:ConvexVolume.FaceInfo = vol.get_face(face_idx) + + + spin_offset_x.value = f.uv_transform.origin.x + spin_offset_y.value = f.uv_transform.origin.y + spin_scale_x.value = f.uv_transform.get_scale().x + spin_scale_y.value = f.uv_transform.get_scale().y + spin_rotation.value = rad_to_deg(f.uv_transform.get_rotation()) + spin_skew.value = rad_to_deg(f.uv_transform.get_skew()) + %check_face_visible.button_pressed = f.visible + %color_picker_face.color = f.color + + if f.material_id != -1: + var mat:Material = block.materials[f.material_id] + target_material = mat + else: + target_material = null + + uv_transform = f.uv_transform + + + +func save_state(state:Dictionary): + var substate:Dictionary = {} + state["uv_editor_dock"] = substate + +# substate["materials"] = material_list.duplicate() + +func load_state(state:Dictionary): + if state == null || !state.has("uv_editor_dock"): + return + + var substate:Dictionary = state["uv_editor_dock"] + + +func apply_uv_transform(): + var xform:Transform2D = Transform2D(deg_to_rad(spin_rotation.value), \ + Vector2(spin_scale_x.value, spin_scale_y.value), \ + deg_to_rad(spin_skew.value), \ + Vector2(spin_offset_x.value, spin_offset_y.value)) + + uv_transform = xform + #print("apply_uv_transform ", uv_transform) + + var cmd:CommandSetFaceUvTransform = CommandSetFaceUvTransform.new() + cmd.builder = builder + cmd.uv_transform = xform + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: +# print("sel block %s" % block.name) + + var vol:ConvexVolume = block.control_mesh + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if f.selected: + cmd.add_face(block.get_path(), f_idx) + + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + +func apply_visible(): + var face_visible:bool = %check_face_visible.button_pressed + + #print("apply_uv_transform ", uv_transform) + + var cmd:CommandSetFaceVisible = CommandSetFaceVisible.new() + cmd.builder = builder + cmd.visible = face_visible + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: +# print("sel block %s" % block.name) + + var vol:ConvexVolume = block.control_mesh + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if f.selected: + cmd.add_face(block.get_path(), f_idx) + + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + +func apply_color(): + var face_color:Color = %color_picker_face.color + color = face_color + + #print("apply_uv_transform ", uv_transform) + + var cmd:CommandSetFaceColor = CommandSetFaceColor.new() + cmd.builder = builder + cmd.color = face_color + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: +# print("sel block %s" % block.name) + + var vol:ConvexVolume = block.control_mesh + for f_idx in vol.faces.size(): + var f:ConvexVolume.FaceInfo = vol.faces[f_idx] + if f.selected: + cmd.add_face(block.get_path(), f_idx) + + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + +func _on_offset_x_value_changed(value): + apply_uv_transform() + + +func _on_offset_y_value_changed(value): + apply_uv_transform() + + +func _on_scale_x_value_changed(value): + apply_uv_transform() + + +func _on_scale_y_value_changed(value): + apply_uv_transform() + + +func _on_rotation_value_changed(value): + apply_uv_transform() + + +func _on_skew_value_changed(value): + apply_uv_transform() + + + + +func _on_color_picker_face_color_changed(color): + apply_color() + + +func _on_check_face_visible_toggled(button_pressed): + apply_visible() diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd.uid b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd.uid new file mode 100644 index 00000000..526df022 --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd.uid @@ -0,0 +1 @@ +uid://doawkp5336h1s diff --git a/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.tscn b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.tscn new file mode 100644 index 00000000..84359874 --- /dev/null +++ b/addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.tscn @@ -0,0 +1,163 @@ +[gd_scene load_steps=6 format=3 uid="uid://bxcewugh0vbee"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_viewport.gd" id="1_rk116"] +[ext_resource type="PackedScene" uid="uid://diibmlqy1mpqb" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.tscn" id="2_cekit"] +[ext_resource type="PackedScene" uid="uid://bbfgpupliiqnm" path="res://addons/cyclops_level_builder/docks/convex_face_editor/convex_face_editor_preview.tscn" id="2_kpj7h"] + +[sub_resource type="Image" id="Image_a1rps"] +data = { +"data": PackedByteArray(203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 205, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203, 203), +"format": "RGB8", +"height": 128, +"mipmaps": false, +"width": 128 +} + +[sub_resource type="ImageTexture" id="ImageTexture_lr775"] +image = SubResource("Image_a1rps") + +[node name="Face Properties" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -697.0 +offset_bottom = -285.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_rk116") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +metadata/_edit_lock_ = true + +[node name="Preview" type="TextureRect" parent="VBoxContainer"] +layout_mode = 2 +texture = SubResource("ImageTexture_lr775") +stretch_mode = 3 + +[node name="GridContainer2" type="GridContainer" parent="VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer/GridContainer2"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="VBoxContainer/GridContainer2/HBoxContainer2"] +layout_mode = 2 +text = "Offset X +" + +[node name="offset_x" parent="VBoxContainer/GridContainer2/HBoxContainer2" instance=ExtResource("2_cekit")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/GridContainer2"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label2" type="Label" parent="VBoxContainer/GridContainer2/HBoxContainer"] +layout_mode = 2 +text = "Offset Y +" + +[node name="offset_y" parent="VBoxContainer/GridContainer2/HBoxContainer" instance=ExtResource("2_cekit")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="GridContainer3" type="GridContainer" parent="VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer/GridContainer3"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="VBoxContainer/GridContainer3/HBoxContainer2"] +layout_mode = 2 +text = "Scale X +" + +[node name="scale_x" parent="VBoxContainer/GridContainer3/HBoxContainer2" instance=ExtResource("2_cekit")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/GridContainer3"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label2" type="Label" parent="VBoxContainer/GridContainer3/HBoxContainer"] +layout_mode = 2 +text = "Scale Y" + +[node name="scale_y" parent="VBoxContainer/GridContainer3/HBoxContainer" instance=ExtResource("2_cekit")] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="GridContainer4" type="GridContainer" parent="VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer/GridContainer4"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="VBoxContainer/GridContainer4/HBoxContainer2"] +layout_mode = 2 +text = "Rotation" + +[node name="rotation" parent="VBoxContainer/GridContainer4/HBoxContainer2" instance=ExtResource("2_cekit")] +layout_mode = 2 +size_flags_horizontal = 3 +snap_size = 15.0 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/GridContainer4"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label2" type="Label" parent="VBoxContainer/GridContainer4/HBoxContainer"] +layout_mode = 2 +text = "Skew +" + +[node name="skew" parent="VBoxContainer/GridContainer4/HBoxContainer" instance=ExtResource("2_cekit")] +layout_mode = 2 +size_flags_horizontal = 3 +snap_size = 15.0 + +[node name="check_face_visible" type="CheckBox" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Visible" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Color" + +[node name="color_picker_face" type="ColorPickerButton" parent="VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="UvPreview" parent="." instance=ExtResource("2_kpj7h")] +size = Vector2i(128, 128) +target_material = null +color = Color(1, 1, 1, 1) + +[connection signal="value_changed" from="VBoxContainer/GridContainer2/HBoxContainer2/offset_x" to="." method="_on_offset_x_value_changed"] +[connection signal="value_changed" from="VBoxContainer/GridContainer2/HBoxContainer/offset_y" to="." method="_on_offset_y_value_changed"] +[connection signal="value_changed" from="VBoxContainer/GridContainer3/HBoxContainer2/scale_x" to="." method="_on_scale_x_value_changed"] +[connection signal="value_changed" from="VBoxContainer/GridContainer3/HBoxContainer/scale_y" to="." method="_on_scale_y_value_changed"] +[connection signal="value_changed" from="VBoxContainer/GridContainer4/HBoxContainer2/rotation" to="." method="_on_rotation_value_changed"] +[connection signal="value_changed" from="VBoxContainer/GridContainer4/HBoxContainer/skew" to="." method="_on_skew_value_changed"] +[connection signal="toggled" from="VBoxContainer/check_face_visible" to="." method="_on_check_face_visible_toggled"] +[connection signal="color_changed" from="VBoxContainer/HBoxContainer/color_picker_face" to="." method="_on_color_picker_face_color_changed"] diff --git a/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd b/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd new file mode 100644 index 00000000..f7169463 --- /dev/null +++ b/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd @@ -0,0 +1,67 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Control +class_name CyclopsConsole + +var editor_plugin:CyclopsLevelBuilder + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func save_state(state:Dictionary): + var substate:Dictionary = {} + state["cyclops_console"] = substate + + +func load_state(state:Dictionary): + if state == null || !state.has("cyclops_console"): + return + + var substate:Dictionary = state["cyclops_console"] + +func _on_enable_cyclops_toggled(button_pressed): + editor_plugin.always_on = button_pressed + + +func _on_bn_create_block_pressed(): + var cmd:CommandAddBlock = CommandAddBlock.new() + cmd.builder = editor_plugin + + var bounds:AABB = AABB(%block_position.value, %block_size.value) + cmd.bounds = bounds + var scene_root = editor_plugin.get_editor_interface().get_edited_scene_root() + cmd.blocks_root_path = scene_root.get_path() + cmd.block_name = GeneralUtil.find_unique_name(scene_root, "block") + + var undo:EditorUndoRedoManager = editor_plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) + diff --git a/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd.uid b/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd.uid new file mode 100644 index 00000000..258e8e09 --- /dev/null +++ b/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd.uid @@ -0,0 +1 @@ +uid://ny44o05tmfm6 diff --git a/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.tscn b/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.tscn new file mode 100644 index 00000000..bcf69c0c --- /dev/null +++ b/addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.tscn @@ -0,0 +1,58 @@ +[gd_scene load_steps=3 format=3 uid="uid://cbo80g1hbom2"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/cyclops_console/cyclops_console.gd" id="1_f4kro"] +[ext_resource type="PackedScene" uid="uid://cphtpklx81l3w" path="res://addons/cyclops_level_builder/controls/vector3_edit.tscn" id="2_qpx41"] + +[node name="PanelContainer" type="PanelContainer"] +offset_right = 469.0 +offset_bottom = 322.0 +script = ExtResource("1_f4kro") + +[node name="enable_cyclops" type="CheckBox" parent="."] +visible = false +layout_mode = 2 +text = "Enable Cyclops" + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/HBoxContainer/PanelContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/PanelContainer/VBoxContainer"] +layout_mode = 2 +text = "Create Block" + +[node name="GridContainer" type="GridContainer" parent="VBoxContainer/HBoxContainer/PanelContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer/PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Position" + +[node name="block_position" parent="VBoxContainer/HBoxContainer/PanelContainer/VBoxContainer/GridContainer" instance=ExtResource("2_qpx41")] +unique_name_in_owner = true +layout_mode = 2 + +[node name="Label2" type="Label" parent="VBoxContainer/HBoxContainer/PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Size" + +[node name="block_size" parent="VBoxContainer/HBoxContainer/PanelContainer/VBoxContainer/GridContainer" instance=ExtResource("2_qpx41")] +unique_name_in_owner = true +layout_mode = 2 +value = Vector3(1, 1, 1) + +[node name="bn_create_block" type="Button" parent="VBoxContainer/HBoxContainer/PanelContainer/VBoxContainer"] +layout_mode = 2 +text = "Create Block" + +[connection signal="toggled" from="enable_cyclops" to="." method="_on_enable_cyclops_toggled"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/PanelContainer/VBoxContainer/bn_create_block" to="." method="_on_bn_create_block_pressed"] diff --git a/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_add_materials.gd b/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_add_materials.gd new file mode 100644 index 00000000..513cb10a --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_add_materials.gd @@ -0,0 +1,56 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandMaterialDockAddMaterials +extends CyclopsCommand + +#Public +var res_path_list:Array[String] + +#Private +var old_res_path_list:Array[String] + + +func _init(): + command_name = "Add materials" + +func do_it(): +# print("Add Materials do_it") + var mat_dock:MaterialPaletteViewport = builder.material_dock + old_res_path_list = mat_dock.material_list.duplicate() + +# print("old mat list %s" % str(old_res_path_list)) + + var new_list:Array[String] = old_res_path_list.duplicate() + for mat in res_path_list: + if !new_list.has(mat): + new_list.append(mat) + +# print("new mat list %s" % str(new_list)) + + mat_dock.set_materials(new_list) + +func undo_it(): + var mat_dock:MaterialPaletteViewport = builder.material_dock + mat_dock.set_materials(old_res_path_list) diff --git a/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_add_materials.gd.uid b/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_add_materials.gd.uid new file mode 100644 index 00000000..cb80e010 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_add_materials.gd.uid @@ -0,0 +1 @@ +uid://dkdi728y44mmo diff --git a/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_remove_materials.gd b/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_remove_materials.gd new file mode 100644 index 00000000..771906cd --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_remove_materials.gd @@ -0,0 +1,52 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CommandMaterialDockRemoveMaterials +extends CyclopsCommand + +#Public +var res_path_list:Array[String] + +#Private +var old_res_path_list:Array[String] + + +func _init(): + command_name = "Remove materials" + +func do_it(): +# print("Remove Materials do_it") + + var mat_dock:MaterialPaletteViewport = builder.material_dock + old_res_path_list = mat_dock.material_list.duplicate() + + var new_list:Array[String] = old_res_path_list.duplicate() + for mat in res_path_list: + var idx:int = new_list.find(mat) + new_list.remove_at(idx) + mat_dock.set_materials(new_list) + +func undo_it(): + var mat_dock:MaterialPaletteViewport = builder.material_dock + mat_dock.set_materials(old_res_path_list) diff --git a/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_remove_materials.gd.uid b/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_remove_materials.gd.uid new file mode 100644 index 00000000..b1cbf39c --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/commands/cmd_mat_dock_remove_materials.gd.uid @@ -0,0 +1 @@ +uid://bnar8qdxeko0x diff --git a/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd b/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd new file mode 100644 index 00000000..040fa49d --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd @@ -0,0 +1,242 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Control +class_name MaterialPaletteViewport + +#@export var material_list:Array[String] = [] + +#@export var thumbnail_group:ThumbnailGroup + +var builder:CyclopsLevelBuilder: + get: + return builder + set(value): + if builder == value: + return + + builder = value + + var mv:MaterialViewer = %MaterialViewer + if mv: + mv.builder = builder + + #call_deferred("update_plugin") + #update_plugin() + +#var undo_manager:UndoRedo + +#var has_mouse_focus:bool = false + +#var drag_pressed:bool = false +#var drag_start_pos:Vector2 +#var drag_start_scroll_value_y:float + +#func update_plugin(): + #var mv:MaterialViewer = %MaterialViewer + #if mv: + #mv.builder = builder + + +# Called when the node enters the scene tree for the first time. +func _ready(): +# print("MaterialPaletteViewport") + #undo_manager = UndoRedo.new() + + #update_thumbnails() + + #%MaterialViewer.builder = builder + pass + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + +#func _can_drop_data(at_position:Vector2, data:Variant): +## print("_can_drop_data %s" % data) + #return typeof(data) == TYPE_DICTIONARY and data.has("type") and data["type"] == "files" +# +#func _gui_input(event): + #if event is InputEventMouseButton: + #var e:InputEventMouseButton = event + # + #if e.button_index == MOUSE_BUTTON_MIDDLE: + #var v_scroll:VScrollBar = %ScrollContainer.get_v_scroll_bar() + # + #drag_pressed = e.pressed + #drag_start_pos = e.position + #drag_start_scroll_value_y = v_scroll.value +# + #elif event is InputEventMouseMotion: + #if drag_pressed: + #var e:InputEventMouseMotion = event + #var offset:Vector2 = e.position - drag_start_pos + # + #var win_size:Vector2 = %ScrollContainer.size + # + #var v_scroll:VScrollBar = %ScrollContainer.get_v_scroll_bar() + #v_scroll.value = clamp(drag_start_scroll_value_y - (offset.y / win_size.y) * v_scroll.max_value, v_scroll.min_value, v_scroll.max_value) +## print("v min max %s %s" % [v_scroll.min_value, v_scroll.max_value]) + + + +#func _unhandled_input(event): + #if !has_mouse_focus: + #return + # + #if event is InputEventKey: + ##print("key event %s" % str(event)) + #var e:InputEventKey = event +## if e.keycode == KEY_DELETE: + #if e.keycode == KEY_X: + #if e.pressed: +## print("mat pal X") + #remove_selected_material() +# + #accept_event() +# +#func remove_selected_material(): + #var cmd:CommandMaterialDockRemoveMaterials = CommandMaterialDockRemoveMaterials.new() + #cmd.builder = builder + # + #for child in %HFlowContainer.get_children(): + #if child.selected: + #cmd.res_path_list.append(child.material_path) +# + #var undo_manager:EditorUndoRedoManager = builder.get_undo_redo() + #cmd.add_to_undo_manager(undo_manager) + +#func set_materials(res_path_list:Array[String]): + #material_list = res_path_list +## print("set mat list %s" % str(material_list)) + #update_thumbnails() + # +# +func save_state(state:Dictionary): + var substate:Dictionary = {} + state["material_palette"] = substate + #substate["materials"] = material_list.duplicate() + +func load_state(state:Dictionary): + if state == null || !state.has("material_palette"): + return + + var substate:Dictionary = state["material_palette"] +# +## print("load_state()") + #material_list = [] + #if substate.has("materials"): + #for mat_path in substate["materials"]: + #if ResourceLoader.exists(mat_path): + #material_list.append(mat_path) + # + #update_thumbnails() +# +#func _drop_data(at_position, data): + #var files = data["files"] + ##print("--drop") + #var add_list:Array[String] + #for f in files: +## print("Dropping %s" % f) + #var res:Resource = load(f) + #if res is Material: + #if !material_list.has(f): + #add_list.append(f) + # + # + #var cmd:CommandMaterialDockAddMaterials = CommandMaterialDockAddMaterials.new() + #cmd.builder = builder + # + #cmd.res_path_list = add_list +# + #var undo_manager:EditorUndoRedoManager = builder.get_undo_redo() + #cmd.add_to_undo_manager(undo_manager) + # + ##print("drop data clear") + ##material_list.clear() + +#func update_thumbnails(): +## print("update_thumbnails()") + #var cur_sel:String + # + #for child in %HFlowContainer.get_children(): + #if child.selected: + #cur_sel = child.material_path + #break +# + #for child in %HFlowContainer.get_children(): + ##print("removing %s" % child.get_class()) + #child.group = null + #%HFlowContainer.remove_child(child) + #child.queue_free() +# + #for path in material_list: + #var res:Resource = preload("res://addons/cyclops_level_builder/docks/material_palette/material_thumbnail.tscn") + #var thumbnail:MaterialThumbnail = res.instantiate() + #thumbnail.builder = builder + #thumbnail.material_path = path + #thumbnail.group = thumbnail_group +## print("adding mat %s" % path) + # + # + #%HFlowContainer.add_child(thumbnail) + #thumbnail.owner = self + # + #if cur_sel: + #for child in %HFlowContainer.get_children(): + #if child.material_path == cur_sel: + #child.selected = true + #break + + +#func _on_visibility_changed(): + ##Control freezes for some reason when hidden and then shown, so just regenereate it + #if visible: + #update_thumbnails() + + + +#func _on_remove_all_materials_pressed(): + #var cmd:CommandMaterialDockRemoveMaterials = CommandMaterialDockRemoveMaterials.new() + #cmd.builder = builder + # + #cmd.res_path_list = material_list.duplicate() +# + #var undo_manager:EditorUndoRedoManager = builder.get_undo_redo() + #cmd.add_to_undo_manager(undo_manager) + + + +#func _on_remove_sel_pressed(): + #remove_selected_material() +# +# +#func _on_h_flow_container_mouse_entered(): + #has_mouse_focus = true +## print("_on_h_flow_container_mouse_entered()") +# +# +#func _on_h_flow_container_mouse_exited(): + #has_mouse_focus = false +## print("_on_h_flow_container_mouse_exited()") diff --git a/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd.uid new file mode 100644 index 00000000..52862a23 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd.uid @@ -0,0 +1 @@ +uid://b8wl6pyk2d4wu diff --git a/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.tscn b/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.tscn new file mode 100644 index 00000000..31ed4f31 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.tscn @@ -0,0 +1,27 @@ +[gd_scene load_steps=3 format=3 uid="uid://o1efx0qxc4n3"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_palette_viewport.gd" id="1_xyxg3"] +[ext_resource type="PackedScene" uid="uid://denc7grw42qsu" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.tscn" id="3_bks23"] + +[node name="Materials" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_xyxg3") +metadata/_edit_lock_ = true + +[node name="MaterialViewer" parent="." instance=ExtResource("3_bks23")] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = 0.0 +offset_bottom = 0.0 +grow_horizontal = 2 +grow_vertical = 2 + +[connection signal="visibility_changed" from="." to="." method="_on_visibility_changed"] diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd b/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd new file mode 100644 index 00000000..17d025e1 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd @@ -0,0 +1,124 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Window +class_name CreateMaterialDialog + +signal create_material(params:Dictionary) + +var texture_list:Array[Texture2D] +var parent_dir_path:String + +var plugin:CyclopsLevelBuilder: + get: + return plugin + set(value): + if value == plugin: + return + + plugin = value + #print("CreateMaterialDialog setting plugin") + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_bn_okay_pressed(): + var mat_type:String = "standard" if %radio_stdMat.is_pressed() else "shader" + var tgt_param:String = "albedo_texture" + + + create_material.emit({ + "name": %line_material_name.text, + "material_type" : mat_type, + "shader_res_path" : %line_shader_path.text, + "texture_parameter" : %target_slot.get_item_text(%target_slot.selected), + "uv_parameter" : %uv_slot.get_item_text(%uv_slot.selected), + "uv_type" : "1x1" if %radio_uv_1x1.is_pressed() else "pix_per_game_unit", + "pix_per_game_unit" : %line_pix_per_game_unit.text.to_int(), + "parent_dir" : parent_dir_path, + "textures" : texture_list + #material_type: "" + }) + + hide() + + +func _on_bn_cancel_pressed(): + hide() + + +func _on_bn_browse_shader_pressed(): + %FileDialog.popup_centered() + + +func _on_about_to_popup(): + #print("CreateMaterialDialog about to popup") + + var ed_iface:EditorInterface = plugin.get_editor_interface() + var efs:EditorFileSystem = ed_iface.get_resource_filesystem() + + var root_dir:EditorFileSystemDirectory = efs.get_filesystem() + + if !texture_list.is_empty(): + %line_material_name.text = texture_list[0].resource_path.get_file().get_basename() + + +func _on_file_dialog_file_selected(path:String): + var shader:Shader = ResourceLoader.load(path, "Shader") + if !shader: + return + + %line_shader_path.text = path + update_shader_slot_list() + +func update_shader_slot_list(): + var path:String = %line_shader_path.text + var shader:Shader = ResourceLoader.load(path, "Shader") + %target_slot.clear() + %uv_slot.clear() + + #TYPE_VECTOR2 + if shader: + #Array of dictionaries + var params:Array = shader.get_shader_uniform_list() + + for p in params: + #print("shader param ", str(p)) + if p["hint_string"] == "Texture2D": + %target_slot.add_item(p["name"]) + if p["type"] == TYPE_VECTOR2 || p["type"] == TYPE_VECTOR3: + %uv_slot.add_item(p["name"]) + + + + +func _on_line_shader_path_text_changed(new_text): + update_shader_slot_list() diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd.uid new file mode 100644 index 00000000..1add1567 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd.uid @@ -0,0 +1 @@ +uid://b5h34kf7s1cx1 diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.tscn b/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.tscn new file mode 100644 index 00000000..639526dd --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.tscn @@ -0,0 +1,182 @@ +[gd_scene load_steps=6 format=3 uid="uid://b510d4yme5xtx"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.gd" id="1_ysdvw"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_7cu3j"] +bg_color = Color(0.309804, 0.309804, 0.309804, 0) +border_width_left = 2 +border_width_top = 2 +border_width_right = 2 +border_width_bottom = 2 + +[sub_resource type="Theme" id="Theme_u2063"] +PanelContainer/styles/panel = SubResource("StyleBoxFlat_7cu3j") + +[sub_resource type="ButtonGroup" id="ButtonGroup_hlttb"] + +[sub_resource type="ButtonGroup" id="ButtonGroup_rde8s"] + +[node name="CreateMaterialDialog" type="Window"] +title = "Create Material" +position = Vector2i(0, 36) +size = Vector2i(600, 400) +script = ExtResource("1_ysdvw") + +[node name="PanelContainer" type="PanelContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"] +layout_mode = 2 + +[node name="HBoxContainer2" type="HBoxContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Material Name:" + +[node name="line_material_name" type="LineEdit" parent="PanelContainer/VBoxContainer/HBoxContainer2"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="PanelContainer2" type="PanelContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +theme = SubResource("Theme_u2063") + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2"] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer"] +layout_mode = 2 +text = "Material Type" + +[node name="radio_stdMat" type="CheckBox" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +button_pressed = true +button_group = SubResource("ButtonGroup_hlttb") +text = "StandardMaterial3D" + +[node name="radio_shaderMat" type="CheckBox" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +button_group = SubResource("ButtonGroup_hlttb") +text = "ShaderMaterial" + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 64 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Shader:" + +[node name="line_shader_path" type="LineEdit" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="bn_browse_shader" type="Button" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Pick shader to use for material" +text = "..." + +[node name="HBoxContainer2" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Texture Parameter:" + +[node name="target_slot" type="OptionButton" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer2"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="HBoxContainer3" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer3"] +layout_mode = 2 +text = "UV Parameter:" + +[node name="uv_slot" type="OptionButton" parent="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer3"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="PanelContainer" type="PanelContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +theme = SubResource("Theme_u2063") + +[node name="VBoxContainer2" type="VBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2"] +layout_mode = 2 +text = "UVs" + +[node name="radio_uv_1x1" type="CheckBox" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2"] +unique_name_in_owner = true +layout_mode = 2 +button_group = SubResource("ButtonGroup_rde8s") +text = "1 x 1" + +[node name="radio_uv_scale_to_pix" type="CheckBox" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2"] +unique_name_in_owner = true +layout_mode = 2 +button_pressed = true +button_group = SubResource("ButtonGroup_rde8s") +text = "Scale to pixel size" + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2"] +layout_mode = 2 +theme_override_constants/margin_left = 64 + +[node name="HBoxContainer2" type="HBoxContainer" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2/MarginContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2/MarginContainer/HBoxContainer2"] +layout_mode = 2 +text = "Pixels per game unit" + +[node name="line_pix_per_game_unit" type="LineEdit" parent="PanelContainer/VBoxContainer/PanelContainer/VBoxContainer2/MarginContainer/HBoxContainer2"] +unique_name_in_owner = true +layout_mode = 2 +text = "32" + +[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +alignment = 1 + +[node name="bn_okay" type="Button" parent="PanelContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Okay" + +[node name="bn_cancel" type="Button" parent="PanelContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Cancel +" + +[node name="FileDialog" type="FileDialog" parent="."] +unique_name_in_owner = true +title = "Open a File" +size = Vector2i(600, 400) +ok_button_text = "Open" +file_mode = 0 + +[connection signal="about_to_popup" from="." to="." method="_on_about_to_popup"] +[connection signal="text_changed" from="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer/line_shader_path" to="." method="_on_line_shader_path_text_changed"] +[connection signal="pressed" from="PanelContainer/VBoxContainer/PanelContainer2/VBoxContainer/MarginContainer/VBoxContainer/HBoxContainer/bn_browse_shader" to="." method="_on_bn_browse_shader_pressed"] +[connection signal="pressed" from="PanelContainer/VBoxContainer/HBoxContainer/bn_okay" to="." method="_on_bn_okay_pressed"] +[connection signal="pressed" from="PanelContainer/VBoxContainer/HBoxContainer/bn_cancel" to="." method="_on_bn_cancel_pressed"] +[connection signal="file_selected" from="FileDialog" to="." method="_on_file_dialog_file_selected"] diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd b/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd new file mode 100644 index 00000000..aeaa37b2 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd @@ -0,0 +1,69 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +@tool +extends PopupPanel +class_name LineInput + +@export var text:String: + get: + return text + set(value): + text = value + title = value + #%Label.text = text + +@export var edit_text:String: + get: + return edit_text + set(value): + edit_text = value + %LineEdit.text = text + +signal text_chosen(text:String) + +# Called when the node enters the scene tree for the first time. +func _ready(): + #%Label.text = text + #%LineEdit.text = edit_text + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_line_edit_text_submitted(new_text): + text_chosen.emit(%LineEdit.text) + hide() + + +func _on_bn_accept_pressed(): + text_chosen.emit(%LineEdit.text) + hide() + + +func _on_bn_cancel_pressed(): + hide() diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd.uid new file mode 100644 index 00000000..11bc8cac --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd.uid @@ -0,0 +1 @@ +uid://bufnqqwg2a64h diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.tscn b/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.tscn new file mode 100644 index 00000000..b3e09d0b --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=2 format=3 uid="uid://tkp4i7e1fs5"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/line_input.gd" id="1_5x46h"] + +[node name="LineInput" type="PopupPanel"] +title = "Input" +size = Vector2i(200, 74) +visible = true +unresizable = false +borderless = false +always_on_top = true +script = ExtResource("1_5x46h") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +offset_left = 4.0 +offset_top = 4.0 +offset_right = 196.0 +offset_bottom = 70.0 + +[node name="LineEdit" type="LineEdit" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/CenterContainer"] +layout_mode = 2 + +[node name="bn_accept" type="Button" parent="VBoxContainer/CenterContainer/HBoxContainer"] +layout_mode = 2 +text = "Okay" + +[node name="bn_cancel" type="Button" parent="VBoxContainer/CenterContainer/HBoxContainer"] +layout_mode = 2 +text = "Cancel" + +[connection signal="text_submitted" from="VBoxContainer/LineEdit" to="." method="_on_line_edit_text_submitted"] +[connection signal="pressed" from="VBoxContainer/CenterContainer/HBoxContainer/bn_accept" to="." method="_on_bn_accept_pressed"] +[connection signal="pressed" from="VBoxContainer/CenterContainer/HBoxContainer/bn_cancel" to="." method="_on_bn_cancel_pressed"] diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_active_theme.tres b/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_active_theme.tres new file mode 100644 index 00000000..6068bac9 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_active_theme.tres @@ -0,0 +1,16 @@ +[gd_resource type="Theme" load_steps=2 format=3 uid="uid://eajwlh2rlu3a"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_amf1g"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 4 +border_width_top = 4 +border_width_right = 4 +border_width_bottom = 4 +border_color = Color(1, 0.890196, 0.729412, 1) +corner_radius_top_left = 4 +corner_radius_top_right = 4 +corner_radius_bottom_right = 4 +corner_radius_bottom_left = 4 + +[resource] +PanelContainer/styles/panel = SubResource("StyleBoxFlat_amf1g") diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_normal_theme.tres b/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_normal_theme.tres new file mode 100644 index 00000000..6446863d --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_normal_theme.tres @@ -0,0 +1,17 @@ +[gd_resource type="Theme" load_steps=2 format=3 uid="uid://di7ydnvl4n54r"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_amf1g"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 4 +border_width_top = 4 +border_width_right = 4 +border_width_bottom = 4 +border_color = Color(0, 0, 0, 1) +border_blend = true +corner_radius_top_left = 4 +corner_radius_top_right = 4 +corner_radius_bottom_right = 4 +corner_radius_bottom_left = 4 + +[resource] +PanelContainer/styles/panel = SubResource("StyleBoxFlat_amf1g") diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_selected_theme.tres b/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_selected_theme.tres new file mode 100644 index 00000000..06cc9e53 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_selected_theme.tres @@ -0,0 +1,16 @@ +[gd_resource type="Theme" load_steps=2 format=3 uid="uid://8ufqa1nourhn"] + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_amf1g"] +bg_color = Color(0, 0, 0, 1) +border_width_left = 4 +border_width_top = 4 +border_width_right = 4 +border_width_bottom = 4 +border_color = Color(1, 0.533333, 0, 1) +corner_radius_top_left = 4 +corner_radius_top_right = 4 +corner_radius_bottom_right = 4 +corner_radius_bottom_left = 4 + +[resource] +PanelContainer/styles/panel = SubResource("StyleBoxFlat_amf1g") diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd new file mode 100644 index 00000000..f1fcd0c4 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd @@ -0,0 +1,154 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name MaterialButton + +signal apply_material(mat_bn:MaterialButton) +signal select_material(mat_bn:MaterialButton, selection_type:SelectionList.Type) + +@export var selected:bool = false: + get: + return selected + set(value): + if selected == value: + return + selected = value + update_border() + +@export var active:bool = false: + get: + return active + set(value): + if active == value: + return + active = value + update_border() + +@export_file("*.tres") var material_path:String: + get: + return material_path + set(value): + if material_path == value: + return + + material_path = value + + dirty = true + + +@export var group:RadioButtonGroup: + get: + return group + set(value): + if group == value: + return + + if group != null: + group.remove_button(self) + + group = value + + if group != null: + group.add_button(self) + +@export var theme_normal:Theme = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_normal_theme.tres") +@export var theme_selected:Theme = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_selected_theme.tres") +@export var theme_active:Theme = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_active_theme.tres") + +var plugin:CyclopsLevelBuilder: + get: + return plugin + set(value): + if value == plugin: + return + + plugin = value + + dirty = true + +var dirty:bool = true + +var material_local:Material + +func rebuild_thumbnail(): + if !plugin: + return + + var rp:EditorResourcePreview = plugin.get_editor_interface().get_resource_previewer() + rp.queue_resource_preview(material_path, self, "resource_preview_callback", null) + + material_local = ResourceLoader.load(material_path, "Material") +# material_local = load(material_path) + %MaterialName.text = GeneralUtil.calc_resource_name(material_local) + tooltip_text = material_path + +func resource_preview_callback(path:String, preview:Texture2D, thumbnail_preview:Texture2D, userdata:Variant): + #print("Set bn tex ", path) + %TextureRect.texture = preview + + +func _gui_input(event:InputEvent): + if event is InputEventMouseButton: + var e:InputEventMouseButton = event + + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.pressed: + if e.double_click: + #apply_material_to_selected() + apply_material.emit(self) + else: + #if group: + #group.select_thumbnail(self) + #else: + #selected = true + + # builder.tool_material_path = material_path + + select_material.emit(self, SelectionList.choose_type(e.shift_pressed, e.ctrl_pressed)) + + get_viewport().set_input_as_handled() + +func update_border(): + if active: + theme = theme_active + elif selected: + theme = theme_selected + else: + theme = theme_normal + + +# Called when the node enters the scene tree for the first time. +func _ready(): + update_border() + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + rebuild_thumbnail() + dirty = false + pass diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd.uid new file mode 100644 index 00000000..8a634961 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd.uid @@ -0,0 +1 @@ +uid://bxfx35ug3n5d8 diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.tscn b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.tscn new file mode 100644 index 00000000..cd99104d --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.tscn @@ -0,0 +1,38 @@ +[gd_scene load_steps=5 format=3 uid="uid://dj3p6dratmybd"] + +[ext_resource type="Theme" uid="uid://di7ydnvl4n54r" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/mat_bn_normal_theme.tres" id="1_t260s"] +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.gd" id="1_vd4oe"] + +[sub_resource type="Image" id="Image_cy15a"] +data = { +"data": PackedByteArray(158, 156, 158, 163, 159, 163, 158, 156, 158, 163, 159, 163, 158, 156, 158, 163, 159, 163, 158, 156, 158, 163, 159, 163, 158, 156, 158, 163, 159, 163, 158, 156, 158, 163, 160, 163, 158, 156, 158, 163, 160, 163, 158, 156, 158, 163, 160, 163, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 159, 157, 159, 164, 160, 164, 159, 157, 159, 164, 160, 164, 159, 156, 159, 164, 160, 164, 159, 156, 159, 164, 160, 164, 159, 156, 159, 164, 160, 164, 159, 156, 159, 164, 160, 164, 159, 156, 159, 163, 160, 163, 159, 156, 159, 163, 160, 163, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 127, 132, 127, 131, 135, 131, 126, 132, 126, 131, 134, 131, 126, 132, 126, 131, 134, 131, 163, 159, 163, 163, 159, 163, 169, 163, 169, 164, 160, 164, 166, 162, 166, 164, 160, 164, 169, 163, 169, 164, 160, 164, 166, 163, 166, 164, 160, 164, 169, 164, 169, 165, 161, 165, 167, 163, 167, 165, 161, 165, 170, 164, 170, 165, 161, 165, 136, 140, 136, 135, 138, 135, 139, 141, 139, 135, 139, 135, 137, 141, 137, 135, 139, 135, 140, 142, 140, 136, 139, 136, 137, 141, 137, 136, 139, 136, 140, 142, 140, 136, 139, 136, 137, 141, 137, 136, 139, 136, 140, 142, 140, 136, 139, 136, 169, 165, 169, 166, 162, 166, 171, 165, 171, 166, 162, 166, 168, 165, 168, 166, 162, 166, 171, 165, 171, 166, 162, 166, 168, 164, 168, 166, 162, 166, 171, 165, 171, 166, 162, 166, 168, 164, 168, 165, 162, 165, 170, 165, 170, 165, 162, 165, 136, 140, 136, 134, 138, 134, 139, 141, 139, 134, 137, 134, 135, 139, 135, 134, 137, 134, 138, 140, 138, 133, 137, 133, 135, 138, 135, 133, 136, 133, 137, 139, 137, 133, 136, 133, 134, 138, 134, 132, 136, 132, 137, 138, 137, 129, 133, 129, 158, 156, 158, 165, 162, 165, 161, 159, 161, 166, 162, 166, 162, 159, 162, 166, 162, 166, 162, 160, 162, 167, 163, 167, 162, 160, 162, 167, 163, 167, 162, 160, 162, 167, 164, 167, 163, 161, 163, 168, 164, 168, 163, 161, 163, 168, 164, 168, 133, 138, 133, 138, 141, 138, 134, 139, 134, 138, 142, 138, 134, 139, 134, 138, 142, 138, 134, 140, 134, 139, 143, 139, 135, 140, 135, 139, 143, 139, 135, 140, 135, 139, 143, 139, 135, 140, 135, 139, 143, 139, 135, 141, 135, 139, 143, 139, 165, 163, 165, 170, 166, 170, 165, 163, 165, 170, 166, 170, 165, 163, 165, 170, 166, 170, 165, 163, 165, 169, 166, 169, 165, 163, 165, 169, 165, 169, 164, 162, 164, 169, 165, 169, 164, 162, 164, 169, 165, 169, 164, 162, 164, 168, 164, 168, 133, 138, 133, 137, 141, 137, 132, 138, 132, 136, 140, 136, 132, 137, 132, 136, 140, 136, 131, 137, 131, 135, 139, 135, 131, 136, 131, 135, 139, 135, 130, 136, 130, 135, 138, 135, 130, 135, 130, 134, 138, 134, 130, 135, 130, 131, 134, 131, 166, 160, 166, 165, 162, 165, 169, 163, 169, 164, 160, 164, 169, 163, 169, 166, 163, 166, 169, 164, 169, 165, 161, 165, 170, 164, 170, 167, 164, 167, 170, 164, 170, 165, 162, 165, 170, 165, 170, 168, 164, 168, 171, 165, 171, 166, 163, 166, 141, 143, 141, 138, 142, 138, 141, 143, 141, 137, 140, 137, 142, 144, 142, 139, 143, 139, 142, 144, 142, 138, 141, 138, 142, 144, 142, 140, 143, 140, 143, 145, 143, 138, 142, 138, 143, 145, 143, 140, 144, 140, 143, 145, 143, 138, 142, 138, 173, 167, 173, 170, 167, 170, 173, 167, 173, 168, 164, 168, 173, 167, 173, 170, 166, 170, 173, 167, 173, 168, 164, 168, 173, 167, 173, 170, 166, 170, 172, 167, 172, 167, 164, 167, 172, 166, 172, 169, 165, 169, 172, 166, 172, 167, 163, 167, 141, 142, 141, 137, 141, 137, 140, 142, 140, 135, 139, 135, 139, 141, 139, 136, 140, 136, 139, 141, 139, 134, 138, 134, 138, 140, 138, 135, 139, 135, 138, 140, 138, 133, 137, 133, 137, 139, 137, 134, 138, 134, 137, 139, 137, 129, 133, 129, 158, 156, 158, 166, 162, 166, 162, 159, 162, 166, 162, 166, 162, 160, 162, 167, 163, 167, 162, 160, 162, 167, 163, 167, 163, 160, 163, 167, 164, 167, 163, 161, 163, 168, 164, 168, 164, 162, 164, 168, 165, 168, 164, 162, 164, 169, 165, 169, 134, 139, 134, 139, 142, 139, 135, 140, 135, 139, 143, 139, 135, 140, 135, 140, 143, 140, 136, 141, 136, 140, 144, 140, 136, 141, 136, 140, 144, 140, 136, 141, 136, 141, 144, 141, 136, 142, 136, 141, 144, 141, 137, 142, 137, 141, 145, 141, 166, 164, 166, 171, 167, 171, 166, 164, 166, 171, 167, 171, 166, 164, 166, 170, 167, 170, 166, 164, 166, 170, 167, 170, 165, 164, 165, 170, 166, 170, 165, 163, 165, 170, 166, 170, 165, 163, 165, 169, 165, 169, 165, 162, 165, 169, 165, 169, 134, 139, 134, 138, 142, 138, 133, 139, 133, 137, 141, 137, 133, 138, 133, 137, 140, 137, 132, 137, 132, 136, 140, 136, 132, 137, 132, 136, 139, 136, 131, 136, 131, 135, 139, 135, 130, 136, 130, 135, 138, 135, 130, 135, 130, 131, 135, 131, 163, 159, 163, 164, 160, 164, 169, 163, 169, 164, 160, 164, 167, 163, 167, 165, 161, 165, 170, 164, 170, 165, 162, 165, 167, 164, 167, 165, 162, 165, 171, 165, 171, 166, 162, 166, 169, 165, 169, 167, 163, 167, 172, 166, 172, 167, 163, 167, 139, 143, 139, 137, 141, 137, 142, 144, 142, 138, 141, 138, 140, 144, 140, 138, 142, 138, 143, 145, 143, 139, 142, 139, 141, 144, 141, 139, 143, 139, 144, 145, 144, 140, 143, 140, 141, 145, 141, 140, 143, 140, 144, 146, 144, 140, 143, 140, 171, 168, 171, 169, 165, 169, 174, 169, 174, 169, 165, 169, 171, 167, 171, 169, 165, 169, 174, 168, 174, 169, 165, 169, 170, 167, 170, 169, 165, 169, 173, 167, 173, 168, 164, 168, 170, 166, 170, 168, 164, 168, 172, 167, 172, 167, 164, 167, 138, 142, 138, 137, 140, 137, 141, 143, 141, 136, 139, 136, 137, 141, 137, 135, 139, 135, 140, 142, 140, 135, 138, 135, 136, 140, 136, 134, 138, 134, 138, 140, 138, 134, 137, 134, 135, 139, 135, 133, 137, 133, 137, 139, 137, 129, 133, 129, 158, 156, 158, 166, 162, 166, 162, 160, 162, 167, 163, 167, 162, 160, 162, 167, 163, 167, 163, 160, 163, 167, 164, 167, 163, 161, 163, 168, 164, 168, 164, 162, 164, 169, 165, 169, 164, 162, 164, 169, 165, 169, 165, 163, 165, 169, 166, 169, 135, 140, 135, 140, 143, 140, 136, 141, 136, 140, 144, 140, 136, 142, 136, 141, 144, 141, 137, 142, 137, 141, 145, 141, 137, 142, 137, 142, 145, 142, 137, 143, 137, 142, 145, 142, 138, 143, 138, 142, 145, 142, 138, 143, 138, 142, 145, 142, 167, 165, 167, 172, 168, 172, 167, 165, 167, 172, 168, 172, 167, 165, 167, 172, 168, 172, 167, 165, 167, 171, 168, 171, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 167, 170, 166, 164, 166, 170, 167, 170, 165, 163, 165, 170, 166, 170, 135, 140, 135, 139, 142, 139, 134, 139, 134, 138, 142, 138, 133, 139, 133, 137, 141, 137, 133, 138, 133, 137, 140, 137, 132, 137, 132, 136, 140, 136, 132, 137, 132, 136, 139, 136, 131, 136, 131, 135, 139, 135, 130, 136, 130, 131, 135, 131, 166, 160, 166, 166, 162, 166, 169, 164, 169, 165, 161, 165, 170, 164, 170, 167, 164, 167, 170, 165, 170, 166, 162, 166, 171, 165, 171, 168, 165, 168, 171, 165, 171, 167, 163, 167, 172, 166, 172, 169, 165, 169, 172, 167, 172, 168, 164, 168, 143, 145, 143, 140, 144, 140, 143, 145, 143, 139, 143, 139, 144, 145, 144, 141, 145, 141, 145, 146, 145, 140, 144, 140, 145, 146, 145, 142, 146, 142, 145, 147, 145, 141, 144, 141, 145, 147, 145, 143, 146, 143, 145, 147, 145, 141, 145, 141, 175, 170, 175, 172, 169, 172, 175, 170, 175, 170, 167, 170, 175, 169, 175, 172, 169, 172, 174, 169, 174, 170, 166, 170, 174, 169, 174, 172, 168, 172, 174, 169, 174, 169, 165, 169, 173, 168, 173, 170, 167, 170, 173, 167, 173, 168, 164, 168, 142, 144, 142, 139, 143, 139, 142, 144, 142, 137, 140, 137, 141, 143, 141, 138, 142, 138, 140, 142, 140, 136, 139, 136, 140, 142, 140, 136, 140, 136, 139, 141, 139, 134, 138, 134, 138, 140, 138, 135, 139, 135, 138, 140, 138, 129, 133, 129, 158, 156, 158, 166, 163, 166, 162, 160, 162, 167, 163, 167, 163, 160, 163, 167, 164, 167, 163, 161, 163, 168, 164, 168, 164, 162, 164, 169, 165, 169, 164, 162, 164, 169, 165, 169, 165, 163, 165, 170, 166, 170, 165, 163, 165, 170, 167, 170, 136, 141, 136, 141, 144, 141, 137, 142, 137, 141, 145, 141, 137, 143, 137, 142, 145, 142, 138, 143, 138, 143, 146, 143, 138, 144, 138, 143, 146, 143, 139, 144, 139, 143, 147, 143, 139, 145, 139, 144, 147, 144, 139, 145, 139, 144, 147, 144, 169, 167, 169, 173, 169, 173, 169, 166, 169, 173, 169, 173, 168, 166, 168, 173, 169, 173, 168, 166, 168, 172, 169, 172, 168, 165, 168, 172, 168, 172, 167, 165, 167, 172, 168, 172, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 167, 170, 136, 141, 136, 140, 143, 140, 135, 140, 135, 139, 143, 139, 134, 140, 134, 138, 142, 138, 134, 139, 134, 137, 141, 137, 133, 138, 133, 137, 140, 137, 132, 137, 132, 136, 140, 136, 132, 137, 132, 135, 139, 135, 131, 136, 131, 131, 135, 131, 163, 159, 163, 164, 160, 164, 170, 164, 170, 165, 161, 165, 167, 164, 167, 165, 162, 165, 171, 165, 171, 166, 162, 166, 169, 165, 169, 167, 163, 167, 172, 166, 172, 167, 164, 167, 170, 166, 170, 168, 164, 168, 173, 167, 173, 169, 165, 169, 141, 145, 141, 140, 143, 140, 145, 146, 145, 140, 144, 140, 142, 146, 142, 141, 145, 141, 145, 147, 145, 142, 145, 142, 144, 147, 144, 142, 145, 142, 146, 148, 146, 143, 146, 143, 144, 148, 144, 143, 146, 143, 147, 149, 147, 143, 146, 143, 173, 170, 173, 172, 168, 172, 176, 171, 176, 172, 168, 172, 173, 170, 173, 171, 167, 171, 176, 170, 176, 171, 167, 171, 173, 169, 173, 170, 167, 170, 175, 169, 175, 170, 166, 170, 172, 168, 172, 169, 166, 169, 174, 168, 174, 169, 165, 169, 140, 144, 140, 138, 142, 138, 143, 145, 143, 138, 141, 138, 139, 143, 139, 137, 140, 137, 141, 143, 141, 136, 140, 136, 137, 141, 137, 135, 139, 135, 140, 142, 140, 135, 138, 135, 136, 140, 136, 134, 138, 134, 138, 140, 138, 129, 133, 129, 158, 156, 158, 167, 163, 167, 162, 160, 162, 167, 164, 167, 163, 161, 163, 168, 164, 168, 164, 162, 164, 169, 165, 169, 164, 162, 164, 169, 165, 169, 165, 163, 165, 170, 166, 170, 165, 164, 165, 170, 167, 170, 166, 164, 166, 171, 167, 171, 137, 143, 137, 142, 145, 142, 138, 143, 138, 143, 146, 143, 139, 144, 139, 143, 147, 143, 139, 145, 139, 144, 147, 144, 140, 145, 140, 145, 148, 145, 140, 145, 140, 145, 148, 145, 141, 146, 141, 145, 148, 145, 141, 146, 141, 145, 149, 145, 170, 168, 170, 174, 170, 174, 170, 168, 170, 174, 170, 174, 169, 167, 169, 174, 170, 174, 169, 167, 169, 173, 170, 173, 169, 167, 169, 173, 169, 173, 168, 166, 168, 172, 169, 172, 168, 165, 168, 172, 168, 172, 167, 165, 167, 171, 168, 171, 137, 142, 137, 141, 144, 141, 136, 141, 136, 140, 144, 140, 135, 140, 135, 139, 143, 139, 134, 140, 134, 138, 142, 138, 134, 139, 134, 137, 141, 137, 133, 138, 133, 137, 140, 137, 132, 137, 132, 136, 140, 136, 131, 136, 131, 131, 135, 131, 166, 160, 166, 167, 163, 167, 170, 164, 170, 165, 162, 165, 171, 165, 171, 168, 164, 168, 171, 165, 171, 167, 163, 167, 172, 166, 172, 169, 166, 169, 173, 167, 173, 168, 164, 168, 173, 167, 173, 171, 167, 171, 174, 168, 174, 169, 166, 169, 145, 146, 145, 142, 146, 142, 145, 147, 145, 142, 145, 142, 146, 148, 146, 144, 147, 144, 147, 149, 147, 143, 146, 143, 148, 149, 148, 145, 149, 145, 148, 150, 148, 144, 147, 144, 148, 150, 148, 146, 149, 146, 149, 150, 149, 145, 148, 145, 177, 172, 177, 175, 171, 175, 177, 172, 177, 173, 169, 173, 177, 172, 177, 174, 171, 174, 177, 172, 177, 172, 168, 172, 176, 171, 176, 173, 170, 173, 176, 170, 176, 171, 167, 171, 175, 170, 175, 172, 169, 172, 175, 169, 175, 170, 166, 170, 145, 146, 145, 141, 145, 141, 144, 145, 144, 139, 142, 139, 143, 145, 143, 139, 143, 139, 142, 144, 142, 137, 140, 137, 141, 143, 141, 138, 141, 138, 140, 142, 140, 135, 139, 135, 139, 141, 139, 136, 140, 136, 138, 140, 138, 129, 133, 129, 158, 156, 158, 167, 163, 167, 163, 161, 163, 168, 164, 168, 164, 162, 164, 169, 165, 169, 164, 162, 164, 169, 165, 169, 165, 163, 165, 170, 166, 170, 165, 164, 165, 170, 167, 170, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 168, 172, 138, 144, 138, 143, 146, 143, 139, 145, 139, 144, 147, 144, 140, 145, 140, 145, 148, 145, 141, 146, 141, 145, 149, 145, 142, 146, 142, 146, 149, 146, 142, 147, 142, 146, 150, 146, 143, 147, 143, 146, 150, 146, 143, 148, 143, 147, 150, 147, 171, 169, 171, 175, 172, 175, 171, 169, 171, 175, 172, 175, 171, 169, 171, 175, 172, 175, 170, 169, 170, 174, 171, 174, 170, 168, 170, 174, 170, 174, 169, 167, 169, 173, 170, 173, 169, 167, 169, 173, 169, 173, 168, 166, 168, 172, 169, 172, 138, 143, 138, 142, 145, 142, 137, 142, 137, 141, 144, 141, 136, 141, 136, 140, 144, 140, 135, 140, 135, 139, 143, 139, 134, 140, 134, 138, 142, 138, 133, 139, 133, 137, 141, 137, 133, 138, 133, 136, 140, 136, 131, 137, 131, 131, 135, 131, 163, 160, 163, 165, 161, 165, 170, 165, 170, 166, 162, 166, 168, 165, 168, 167, 163, 167, 172, 166, 172, 167, 164, 167, 170, 166, 170, 168, 164, 168, 173, 167, 173, 169, 165, 169, 171, 167, 171, 169, 166, 169, 174, 169, 174, 170, 167, 170, 143, 146, 143, 142, 145, 142, 147, 148, 147, 143, 146, 143, 145, 148, 145, 144, 147, 144, 148, 150, 148, 145, 148, 145, 146, 150, 146, 145, 148, 145, 150, 151, 150, 145, 149, 145, 147, 150, 147, 146, 149, 146, 150, 152, 150, 146, 149, 146, 176, 173, 176, 174, 170, 174, 179, 173, 179, 174, 170, 174, 176, 172, 176, 174, 170, 174, 178, 173, 178, 173, 170, 173, 175, 171, 175, 173, 169, 173, 177, 172, 177, 172, 169, 172, 174, 170, 174, 171, 168, 171, 176, 170, 176, 170, 167, 170, 143, 146, 143, 141, 144, 141, 145, 146, 145, 140, 143, 140, 141, 144, 141, 139, 142, 139, 143, 145, 143, 138, 141, 138, 139, 143, 139, 137, 140, 137, 141, 143, 141, 136, 139, 136, 137, 141, 137, 135, 139, 135, 139, 141, 139, 129, 133, 129, 158, 156, 158, 167, 164, 167, 163, 161, 163, 168, 164, 168, 164, 162, 164, 169, 165, 169, 165, 163, 165, 170, 166, 170, 165, 163, 165, 170, 167, 170, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 168, 172, 168, 166, 168, 173, 169, 173, 139, 145, 139, 144, 148, 144, 141, 145, 141, 145, 149, 145, 142, 146, 142, 146, 150, 146, 142, 147, 142, 147, 150, 147, 143, 148, 143, 147, 151, 147, 144, 149, 144, 148, 151, 148, 144, 149, 144, 148, 152, 148, 145, 149, 145, 148, 152, 148, 172, 170, 172, 177, 173, 177, 172, 170, 172, 177, 173, 177, 172, 170, 172, 176, 173, 176, 172, 170, 172, 176, 172, 176, 171, 169, 171, 175, 172, 175, 170, 169, 170, 174, 171, 174, 170, 168, 170, 174, 170, 174, 169, 167, 169, 173, 169, 173, 139, 144, 139, 143, 146, 143, 138, 143, 138, 142, 145, 142, 137, 142, 137, 141, 144, 141, 136, 141, 136, 140, 143, 140, 135, 140, 135, 139, 142, 139, 134, 139, 134, 138, 142, 138, 133, 138, 133, 137, 141, 137, 132, 137, 132, 131, 135, 131, 166, 160, 166, 167, 164, 167, 171, 165, 171, 166, 163, 166, 172, 166, 172, 169, 165, 169, 172, 167, 172, 168, 164, 168, 173, 167, 173, 170, 167, 170, 174, 168, 174, 169, 166, 169, 174, 169, 174, 172, 169, 172, 175, 170, 175, 171, 167, 171, 147, 149, 147, 145, 148, 145, 148, 150, 148, 144, 147, 144, 149, 150, 149, 147, 150, 147, 150, 151, 150, 146, 149, 146, 150, 152, 150, 148, 151, 148, 151, 153, 151, 147, 150, 147, 151, 153, 151, 149, 152, 149, 152, 153, 152, 148, 151, 148, 180, 175, 180, 177, 174, 177, 180, 174, 180, 175, 172, 175, 180, 174, 180, 177, 173, 177, 179, 174, 179, 174, 171, 174, 179, 173, 179, 176, 172, 176, 178, 173, 178, 173, 169, 173, 177, 172, 177, 174, 171, 174, 177, 171, 177, 172, 168, 172, 146, 148, 146, 143, 147, 143, 145, 147, 145, 141, 144, 141, 145, 146, 145, 141, 145, 141, 143, 145, 143, 138, 142, 138, 142, 144, 142, 139, 143, 139, 141, 143, 141, 136, 140, 136, 141, 142, 141, 137, 141, 137, 139, 141, 139, 129, 133, 129, 127, 132, 127, 136, 140, 136, 133, 138, 133, 138, 142, 138, 134, 139, 134, 139, 143, 139, 135, 140, 135, 140, 144, 140, 136, 141, 136, 141, 145, 141, 137, 143, 137, 142, 145, 142, 138, 144, 138, 143, 146, 143, 139, 145, 139, 144, 148, 144, 170, 167, 170, 174, 171, 174, 170, 169, 170, 175, 172, 175, 171, 169, 171, 176, 172, 176, 172, 170, 172, 177, 173, 177, 173, 171, 173, 177, 174, 177, 173, 171, 173, 178, 174, 178, 174, 172, 174, 178, 174, 178, 174, 172, 174, 178, 174, 178, 146, 151, 146, 150, 153, 150, 146, 151, 146, 150, 153, 150, 145, 150, 145, 149, 153, 149, 145, 150, 145, 149, 152, 149, 144, 149, 144, 148, 151, 148, 144, 148, 144, 147, 150, 147, 142, 147, 142, 146, 149, 146, 141, 146, 141, 145, 148, 145, 169, 167, 169, 173, 169, 173, 168, 166, 168, 172, 169, 172, 167, 165, 167, 171, 168, 171, 166, 164, 166, 170, 167, 170, 165, 164, 165, 170, 166, 170, 165, 163, 165, 169, 165, 169, 164, 162, 164, 168, 164, 168, 163, 161, 163, 163, 160, 163, 131, 135, 131, 135, 138, 135, 141, 142, 141, 137, 140, 137, 139, 142, 139, 137, 141, 137, 143, 144, 143, 139, 142, 139, 141, 144, 141, 140, 143, 140, 145, 146, 145, 141, 144, 141, 143, 146, 143, 142, 145, 142, 147, 149, 147, 143, 146, 143, 174, 171, 174, 173, 169, 173, 178, 173, 178, 174, 170, 174, 176, 173, 176, 174, 171, 174, 179, 174, 179, 175, 172, 175, 178, 174, 178, 176, 172, 176, 181, 176, 181, 176, 173, 176, 178, 175, 178, 177, 173, 177, 181, 176, 181, 177, 173, 177, 151, 154, 151, 150, 153, 150, 153, 155, 153, 149, 152, 149, 150, 153, 150, 149, 152, 149, 152, 154, 152, 148, 151, 148, 149, 152, 149, 147, 150, 147, 151, 152, 151, 146, 149, 146, 147, 150, 147, 145, 148, 145, 149, 150, 149, 144, 147, 144, 174, 170, 174, 172, 168, 172, 176, 170, 176, 170, 167, 170, 172, 169, 172, 170, 166, 170, 174, 168, 174, 169, 165, 169, 170, 167, 170, 168, 164, 168, 172, 167, 172, 167, 164, 167, 169, 165, 169, 166, 163, 166, 170, 165, 170, 161, 157, 161, 127, 132, 127, 137, 140, 137, 134, 139, 134, 138, 142, 138, 135, 140, 135, 139, 143, 139, 136, 141, 136, 140, 144, 140, 137, 142, 137, 142, 145, 142, 138, 143, 138, 143, 146, 143, 139, 145, 139, 144, 147, 144, 141, 145, 141, 145, 149, 145, 170, 169, 170, 175, 172, 175, 172, 169, 172, 176, 173, 176, 172, 170, 172, 177, 173, 177, 173, 171, 173, 178, 174, 178, 174, 172, 174, 178, 175, 178, 174, 173, 174, 179, 176, 179, 175, 173, 175, 179, 176, 179, 175, 173, 175, 179, 176, 179, 148, 153, 148, 152, 155, 152, 148, 153, 148, 151, 155, 151, 147, 152, 147, 151, 154, 151, 147, 151, 147, 150, 153, 150, 146, 150, 146, 149, 153, 149, 145, 150, 145, 148, 151, 148, 144, 149, 144, 147, 150, 147, 143, 147, 143, 146, 149, 146, 170, 168, 170, 174, 170, 174, 169, 167, 169, 173, 169, 173, 168, 166, 168, 172, 168, 172, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 167, 170, 165, 163, 165, 169, 165, 169, 164, 162, 164, 169, 165, 169, 163, 161, 163, 163, 160, 163, 134, 136, 134, 137, 140, 137, 141, 143, 141, 137, 140, 137, 142, 144, 142, 140, 143, 140, 143, 145, 143, 139, 143, 139, 144, 146, 144, 142, 145, 142, 145, 147, 145, 142, 145, 142, 146, 148, 146, 145, 148, 145, 148, 150, 148, 144, 147, 144, 178, 172, 178, 176, 172, 176, 179, 173, 179, 175, 171, 175, 180, 174, 180, 178, 174, 178, 180, 175, 180, 176, 173, 176, 181, 176, 181, 179, 176, 179, 182, 177, 182, 178, 174, 178, 182, 177, 182, 180, 177, 180, 183, 177, 183, 178, 175, 178, 155, 157, 155, 153, 156, 153, 155, 156, 155, 151, 154, 151, 154, 156, 154, 152, 155, 152, 154, 156, 154, 150, 153, 150, 153, 155, 153, 150, 153, 150, 152, 153, 152, 147, 150, 147, 151, 153, 151, 148, 151, 148, 150, 151, 150, 145, 148, 145, 177, 172, 177, 174, 170, 174, 176, 171, 176, 171, 167, 171, 175, 170, 175, 172, 169, 172, 174, 169, 174, 169, 165, 169, 173, 168, 173, 170, 167, 170, 173, 167, 173, 167, 164, 167, 172, 166, 172, 169, 165, 169, 170, 165, 170, 161, 157, 161, 127, 132, 127, 137, 141, 137, 134, 139, 134, 139, 143, 139, 135, 140, 135, 140, 144, 140, 136, 142, 136, 141, 145, 141, 137, 143, 137, 142, 146, 142, 139, 144, 139, 144, 147, 144, 140, 145, 140, 145, 148, 145, 142, 146, 142, 146, 150, 146, 171, 169, 171, 176, 173, 176, 172, 170, 172, 177, 174, 177, 173, 171, 173, 178, 174, 178, 174, 172, 174, 179, 176, 179, 175, 173, 175, 180, 176, 180, 176, 174, 176, 180, 177, 180, 176, 174, 176, 180, 177, 180, 177, 174, 177, 181, 177, 181, 150, 154, 150, 153, 156, 153, 150, 154, 150, 153, 156, 153, 149, 153, 149, 152, 156, 152, 148, 153, 148, 152, 155, 152, 147, 152, 147, 150, 154, 150, 146, 151, 146, 150, 153, 150, 145, 150, 145, 148, 151, 148, 144, 149, 144, 147, 150, 147, 171, 169, 171, 174, 171, 174, 170, 167, 170, 173, 170, 173, 169, 167, 169, 172, 169, 172, 167, 165, 167, 172, 168, 172, 167, 164, 167, 170, 167, 170, 165, 164, 165, 170, 166, 170, 165, 163, 165, 169, 165, 169, 163, 161, 163, 164, 160, 164, 131, 135, 131, 135, 139, 135, 141, 143, 141, 137, 141, 137, 140, 143, 140, 138, 142, 138, 144, 145, 144, 140, 143, 140, 142, 145, 142, 141, 145, 141, 146, 148, 146, 142, 145, 142, 145, 148, 145, 144, 147, 144, 149, 150, 149, 145, 148, 145, 176, 172, 176, 174, 171, 174, 180, 174, 180, 176, 172, 176, 178, 174, 178, 177, 173, 177, 182, 176, 182, 178, 174, 178, 180, 176, 180, 178, 175, 178, 183, 178, 183, 179, 176, 179, 181, 178, 181, 179, 176, 179, 184, 179, 184, 179, 176, 179, 154, 157, 154, 153, 156, 153, 156, 158, 156, 152, 155, 152, 153, 156, 153, 152, 155, 152, 155, 157, 155, 151, 154, 151, 152, 155, 152, 150, 153, 150, 153, 155, 153, 149, 152, 149, 150, 153, 150, 147, 150, 147, 151, 152, 151, 146, 149, 146, 175, 172, 175, 173, 169, 173, 177, 172, 177, 172, 168, 172, 173, 170, 173, 171, 167, 171, 175, 169, 175, 170, 166, 170, 171, 167, 171, 169, 165, 169, 173, 167, 173, 168, 164, 168, 169, 166, 169, 167, 163, 167, 171, 165, 171, 161, 158, 161, 127, 132, 127, 137, 141, 137, 134, 140, 134, 139, 143, 139, 136, 141, 136, 140, 144, 140, 137, 142, 137, 142, 145, 142, 138, 143, 138, 143, 146, 143, 139, 145, 139, 144, 148, 144, 141, 146, 141, 145, 149, 145, 142, 147, 142, 147, 150, 147, 172, 170, 172, 177, 173, 177, 173, 171, 173, 178, 174, 178, 174, 172, 174, 179, 176, 179, 175, 173, 175, 180, 177, 180, 176, 174, 176, 181, 177, 181, 177, 175, 177, 181, 178, 181, 177, 176, 177, 182, 178, 182, 178, 176, 178, 182, 179, 182, 151, 156, 151, 155, 158, 155, 151, 156, 151, 154, 158, 154, 150, 155, 150, 154, 157, 154, 150, 154, 150, 153, 156, 153, 149, 153, 149, 152, 155, 152, 147, 152, 147, 150, 154, 150, 146, 151, 146, 149, 153, 149, 145, 150, 145, 148, 151, 148, 172, 169, 172, 175, 172, 175, 170, 168, 170, 174, 170, 174, 169, 167, 169, 173, 169, 173, 168, 166, 168, 172, 168, 172, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 166, 170, 165, 163, 165, 169, 165, 169, 164, 161, 164, 164, 160, 164, 134, 136, 134, 137, 141, 137, 142, 144, 142, 138, 141, 138, 143, 145, 143, 141, 144, 141, 144, 146, 144, 140, 144, 140, 145, 147, 145, 143, 147, 143, 146, 148, 146, 143, 146, 143, 148, 150, 148, 146, 150, 146, 150, 151, 150, 146, 149, 146, 179, 174, 179, 177, 174, 177, 180, 175, 180, 176, 173, 176, 182, 176, 182, 179, 176, 179, 183, 177, 183, 178, 175, 178, 184, 178, 184, 181, 178, 181, 184, 179, 184, 180, 177, 180, 185, 179, 185, 182, 179, 182, 185, 180, 185, 180, 177, 180, 158, 160, 158, 156, 158, 156, 158, 159, 158, 154, 157, 154, 157, 159, 157, 154, 158, 154, 156, 158, 156, 152, 155, 152, 156, 157, 156, 152, 156, 152, 154, 156, 154, 150, 153, 150, 153, 155, 153, 150, 153, 150, 152, 153, 152, 147, 150, 147, 179, 173, 179, 176, 172, 176, 178, 172, 178, 172, 169, 172, 176, 171, 176, 173, 170, 173, 175, 170, 175, 170, 166, 170, 174, 169, 174, 171, 167, 171, 173, 168, 173, 168, 164, 168, 173, 167, 173, 169, 165, 169, 171, 165, 171, 161, 158, 161, 127, 132, 127, 137, 141, 137, 135, 140, 135, 140, 143, 140, 136, 141, 136, 141, 144, 141, 137, 142, 137, 142, 145, 142, 138, 144, 138, 144, 147, 144, 140, 145, 140, 145, 148, 145, 142, 146, 142, 146, 150, 146, 143, 148, 143, 148, 151, 148, 173, 171, 173, 178, 174, 178, 174, 172, 174, 179, 175, 179, 175, 173, 175, 180, 176, 180, 176, 174, 176, 181, 177, 181, 177, 175, 177, 182, 178, 182, 178, 176, 178, 182, 179, 182, 178, 177, 178, 183, 179, 183, 179, 177, 179, 183, 180, 183, 153, 157, 153, 156, 159, 156, 152, 157, 152, 156, 159, 156, 152, 156, 152, 155, 158, 155, 151, 156, 151, 154, 157, 154, 150, 154, 150, 153, 156, 153, 149, 153, 149, 152, 155, 152, 147, 152, 147, 150, 153, 150, 145, 150, 145, 149, 152, 149, 172, 170, 172, 176, 172, 176, 171, 169, 171, 174, 171, 174, 170, 167, 170, 173, 170, 173, 169, 166, 169, 172, 169, 172, 167, 165, 167, 171, 168, 171, 166, 164, 166, 170, 167, 170, 165, 163, 165, 169, 166, 169, 164, 162, 164, 164, 160, 164, 131, 135, 131, 136, 139, 136, 142, 144, 142, 138, 142, 138, 140, 144, 140, 139, 143, 139, 145, 146, 145, 141, 144, 141, 143, 146, 143, 142, 145, 142, 147, 149, 147, 144, 147, 144, 146, 149, 146, 145, 148, 145, 150, 152, 150, 147, 150, 147, 177, 174, 177, 176, 172, 176, 181, 176, 181, 177, 174, 177, 179, 176, 179, 178, 175, 178, 183, 178, 183, 179, 176, 179, 182, 178, 182, 180, 177, 180, 185, 180, 185, 181, 178, 181, 183, 180, 183, 182, 178, 182, 186, 181, 186, 182, 178, 182, 157, 160, 157, 155, 158, 155, 159, 160, 159, 155, 158, 155, 156, 159, 156, 154, 157, 154, 158, 159, 158, 153, 156, 153, 154, 157, 154, 152, 155, 152, 155, 157, 155, 150, 153, 150, 151, 154, 151, 149, 152, 149, 152, 154, 152, 147, 150, 147, 177, 173, 177, 174, 170, 174, 178, 173, 178, 173, 169, 173, 174, 170, 174, 172, 168, 172, 176, 170, 176, 170, 167, 170, 172, 168, 172, 169, 166, 169, 174, 168, 174, 169, 165, 169, 170, 166, 170, 167, 164, 167, 171, 165, 171, 161, 158, 161, 127, 132, 127, 137, 141, 137, 135, 140, 135, 140, 144, 140, 136, 141, 136, 141, 145, 141, 137, 143, 137, 142, 146, 142, 139, 144, 139, 144, 147, 144, 140, 145, 140, 145, 149, 145, 142, 147, 142, 147, 150, 147, 144, 149, 144, 149, 152, 149, 173, 171, 173, 178, 174, 178, 174, 173, 174, 179, 176, 179, 176, 174, 176, 180, 177, 180, 177, 175, 177, 182, 178, 182, 178, 176, 178, 183, 179, 183, 179, 177, 179, 183, 180, 183, 179, 178, 179, 184, 180, 184, 180, 178, 180, 184, 180, 184, 153, 158, 153, 157, 160, 157, 153, 158, 153, 157, 160, 157, 153, 157, 153, 156, 159, 156, 152, 156, 152, 155, 158, 155, 151, 155, 151, 154, 157, 154, 150, 154, 150, 152, 156, 152, 148, 153, 148, 151, 154, 151, 146, 151, 146, 149, 153, 149, 173, 170, 173, 176, 173, 176, 171, 169, 171, 175, 172, 175, 170, 168, 170, 174, 170, 174, 169, 167, 169, 173, 169, 173, 168, 165, 168, 172, 168, 172, 167, 164, 167, 170, 167, 170, 165, 164, 165, 170, 166, 170, 164, 162, 164, 164, 160, 164, 134, 136, 134, 137, 141, 137, 142, 144, 142, 138, 142, 138, 143, 145, 143, 141, 145, 141, 145, 146, 145, 141, 144, 141, 146, 148, 146, 144, 147, 144, 147, 149, 147, 144, 147, 144, 149, 150, 149, 147, 150, 147, 150, 152, 150, 147, 150, 147, 180, 175, 180, 178, 175, 178, 182, 176, 182, 178, 174, 178, 183, 178, 183, 181, 177, 181, 184, 179, 184, 180, 177, 180, 185, 180, 185, 183, 179, 183, 186, 180, 186, 182, 178, 182, 186, 181, 186, 184, 181, 184, 187, 182, 187, 183, 179, 183, 160, 162, 160, 158, 160, 158, 160, 161, 160, 156, 159, 156, 159, 161, 159, 156, 160, 156, 158, 160, 158, 154, 157, 154, 157, 159, 157, 154, 157, 154, 156, 158, 156, 151, 154, 151, 154, 156, 154, 151, 154, 151, 153, 154, 153, 148, 151, 148, 180, 174, 180, 176, 173, 176, 178, 173, 178, 173, 170, 173, 177, 172, 177, 174, 170, 174, 176, 170, 176, 171, 167, 171, 175, 169, 175, 172, 168, 172, 174, 168, 174, 169, 165, 169, 173, 167, 173, 170, 166, 170, 171, 165, 171, 161, 158, 161, 127, 132, 127, 137, 141, 137, 135, 140, 135, 140, 144, 140, 136, 142, 136, 141, 145, 141, 138, 143, 138, 143, 146, 143, 139, 145, 139, 144, 148, 144, 141, 146, 141, 145, 149, 145, 143, 147, 143, 147, 150, 147, 144, 149, 144, 149, 152, 149, 174, 172, 174, 178, 175, 178, 175, 173, 175, 180, 176, 180, 176, 174, 176, 181, 178, 181, 177, 176, 177, 182, 179, 182, 178, 177, 178, 183, 180, 183, 179, 178, 179, 184, 180, 184, 180, 178, 180, 184, 181, 184, 180, 178, 180, 185, 181, 185, 154, 159, 154, 158, 161, 158, 154, 158, 154, 158, 160, 158, 153, 158, 153, 157, 160, 157, 153, 157, 153, 156, 159, 156, 151, 156, 151, 154, 158, 154, 150, 155, 150, 153, 156, 153, 148, 153, 148, 151, 155, 151, 147, 151, 147, 150, 153, 150, 173, 171, 173, 177, 173, 177, 172, 170, 172, 175, 172, 175, 170, 168, 170, 174, 170, 174, 169, 167, 169, 173, 169, 173, 168, 166, 168, 172, 168, 172, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 166, 170, 164, 162, 164, 164, 160, 164, 131, 135, 131, 136, 139, 136, 142, 144, 142, 138, 142, 138, 141, 144, 141, 140, 143, 140, 145, 146, 145, 141, 145, 141, 144, 147, 144, 143, 146, 143, 148, 150, 148, 144, 147, 144, 146, 150, 146, 146, 149, 146, 151, 153, 151, 148, 151, 148, 178, 174, 178, 177, 173, 177, 182, 177, 182, 178, 174, 178, 180, 177, 180, 179, 176, 179, 184, 179, 184, 180, 177, 180, 183, 179, 183, 182, 178, 182, 186, 181, 186, 182, 179, 182, 184, 181, 184, 183, 179, 183, 187, 182, 187, 183, 179, 183, 158, 161, 158, 157, 160, 157, 160, 162, 160, 156, 159, 156, 157, 160, 157, 156, 158, 156, 159, 160, 159, 155, 158, 155, 155, 158, 155, 153, 156, 153, 156, 158, 156, 152, 155, 152, 152, 156, 152, 150, 153, 150, 153, 155, 153, 149, 152, 149, 177, 174, 177, 175, 171, 175, 179, 173, 179, 173, 170, 173, 175, 171, 175, 172, 169, 172, 176, 171, 176, 171, 167, 171, 172, 169, 172, 170, 166, 170, 174, 169, 174, 169, 165, 169, 170, 167, 170, 168, 164, 168, 171, 165, 171, 161, 158, 161, 127, 132, 127, 138, 141, 138, 135, 141, 135, 140, 144, 140, 137, 142, 137, 141, 145, 141, 138, 143, 138, 143, 146, 143, 139, 145, 139, 144, 148, 144, 141, 146, 141, 146, 149, 146, 143, 148, 143, 147, 151, 147, 145, 149, 145, 149, 153, 149, 174, 172, 174, 179, 175, 179, 175, 173, 175, 180, 177, 180, 177, 174, 177, 181, 178, 181, 178, 176, 178, 183, 179, 183, 179, 177, 179, 183, 180, 183, 180, 178, 180, 184, 181, 184, 180, 178, 180, 185, 182, 185, 181, 179, 181, 185, 182, 185, 155, 159, 155, 158, 161, 158, 155, 159, 155, 158, 161, 158, 154, 158, 154, 157, 160, 157, 153, 158, 153, 156, 159, 156, 152, 156, 152, 155, 158, 155, 150, 155, 150, 153, 156, 153, 149, 153, 149, 152, 155, 152, 147, 152, 147, 150, 153, 150, 173, 171, 173, 177, 173, 177, 172, 170, 172, 175, 172, 175, 170, 169, 170, 174, 170, 174, 169, 167, 169, 173, 169, 173, 168, 166, 168, 172, 168, 172, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 166, 170, 164, 162, 164, 164, 160, 164, 134, 136, 134, 138, 141, 138, 142, 144, 142, 138, 142, 138, 144, 145, 144, 141, 145, 141, 145, 146, 145, 141, 145, 141, 146, 148, 146, 144, 148, 144, 148, 150, 148, 145, 148, 145, 150, 151, 150, 148, 151, 148, 151, 153, 151, 148, 151, 148, 181, 176, 181, 179, 175, 179, 182, 177, 182, 178, 175, 178, 183, 178, 183, 181, 178, 181, 185, 179, 185, 180, 177, 180, 186, 180, 186, 184, 180, 184, 186, 181, 186, 183, 179, 183, 187, 182, 187, 185, 182, 185, 187, 182, 187, 183, 180, 183, 161, 162, 161, 158, 162, 158, 160, 162, 160, 157, 160, 157, 160, 162, 160, 157, 160, 157, 159, 160, 159, 155, 158, 155, 158, 160, 158, 155, 158, 155, 156, 158, 156, 152, 155, 152, 155, 157, 155, 152, 155, 152, 153, 155, 153, 149, 152, 149, 180, 175, 180, 177, 173, 177, 179, 173, 179, 173, 170, 173, 177, 172, 177, 174, 170, 174, 176, 171, 176, 171, 167, 171, 175, 170, 175, 172, 168, 172, 174, 169, 174, 169, 165, 169, 173, 167, 173, 170, 166, 170, 171, 165, 171, 161, 158, 161, 159, 157, 159, 169, 165, 169, 165, 163, 165, 170, 167, 170, 166, 164, 166, 171, 168, 171, 167, 165, 167, 172, 169, 172, 169, 167, 169, 173, 170, 173, 170, 168, 170, 175, 171, 175, 171, 169, 171, 176, 173, 176, 172, 170, 172, 177, 174, 177, 146, 151, 146, 151, 154, 151, 148, 153, 148, 153, 156, 153, 150, 154, 150, 154, 157, 154, 151, 156, 151, 156, 158, 156, 153, 157, 153, 157, 160, 157, 153, 158, 153, 158, 161, 158, 154, 159, 154, 158, 161, 158, 155, 159, 155, 158, 162, 158, 181, 179, 181, 185, 182, 185, 181, 179, 181, 185, 181, 185, 180, 178, 180, 184, 180, 184, 179, 178, 179, 183, 180, 183, 178, 177, 178, 182, 179, 182, 177, 175, 177, 181, 177, 181, 176, 174, 176, 179, 176, 179, 174, 173, 174, 178, 174, 178, 145, 150, 145, 148, 152, 148, 144, 149, 144, 147, 150, 147, 142, 147, 142, 145, 149, 145, 140, 145, 140, 144, 147, 144, 139, 144, 139, 142, 145, 142, 137, 143, 137, 141, 145, 141, 136, 141, 136, 139, 143, 139, 133, 139, 133, 131, 135, 131, 164, 160, 164, 166, 162, 166, 173, 167, 173, 168, 165, 168, 171, 167, 171, 169, 165, 169, 174, 169, 174, 170, 167, 170, 173, 169, 173, 172, 168, 172, 177, 171, 177, 173, 169, 173, 175, 172, 175, 174, 170, 174, 179, 174, 179, 176, 172, 176, 150, 153, 150, 150, 153, 150, 154, 156, 154, 151, 154, 151, 153, 156, 153, 153, 156, 153, 157, 159, 157, 154, 157, 154, 156, 159, 156, 155, 158, 155, 160, 161, 160, 156, 159, 156, 158, 161, 158, 157, 160, 157, 161, 162, 161, 157, 160, 157, 185, 182, 185, 183, 180, 183, 187, 182, 187, 183, 179, 183, 184, 181, 184, 182, 179, 182, 186, 181, 186, 181, 178, 181, 183, 179, 183, 180, 177, 180, 184, 179, 184, 179, 175, 179, 180, 177, 180, 177, 174, 177, 181, 176, 181, 176, 173, 176, 149, 153, 149, 147, 150, 147, 150, 152, 150, 145, 148, 145, 146, 149, 146, 144, 147, 144, 147, 149, 147, 142, 145, 142, 143, 146, 143, 141, 144, 141, 144, 146, 144, 139, 143, 139, 140, 144, 140, 138, 141, 138, 140, 142, 140, 130, 133, 130, 159, 157, 159, 168, 165, 168, 165, 163, 165, 170, 167, 170, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 169, 172, 169, 166, 169, 173, 170, 173, 170, 168, 170, 175, 171, 175, 171, 169, 171, 176, 172, 176, 172, 170, 172, 177, 174, 177, 146, 151, 146, 151, 154, 151, 148, 153, 148, 152, 156, 152, 150, 154, 150, 154, 157, 154, 151, 156, 151, 155, 158, 155, 152, 157, 152, 156, 160, 156, 153, 158, 153, 157, 160, 157, 154, 158, 154, 158, 161, 158, 155, 159, 155, 158, 161, 158, 181, 179, 181, 185, 182, 185, 180, 179, 180, 184, 181, 184, 180, 178, 180, 184, 180, 184, 179, 177, 179, 183, 179, 183, 178, 176, 178, 182, 178, 182, 177, 175, 177, 180, 177, 180, 176, 174, 176, 179, 176, 179, 174, 172, 174, 178, 174, 178, 145, 150, 145, 148, 152, 148, 144, 148, 144, 146, 150, 146, 142, 147, 142, 145, 148, 145, 140, 145, 140, 144, 147, 144, 139, 144, 139, 142, 145, 142, 137, 142, 137, 141, 144, 141, 136, 141, 136, 139, 143, 139, 133, 139, 133, 131, 135, 131, 166, 160, 166, 168, 165, 168, 173, 167, 173, 168, 164, 168, 173, 168, 173, 171, 167, 171, 174, 169, 174, 170, 167, 170, 176, 170, 176, 173, 170, 173, 177, 171, 177, 173, 169, 173, 178, 173, 178, 176, 172, 176, 179, 174, 179, 175, 172, 175, 152, 154, 152, 150, 154, 150, 154, 156, 154, 151, 154, 151, 156, 157, 156, 154, 157, 154, 157, 158, 157, 154, 157, 154, 158, 160, 158, 156, 159, 156, 159, 160, 159, 156, 159, 156, 160, 161, 160, 158, 161, 158, 160, 162, 160, 157, 160, 157, 187, 182, 187, 185, 181, 185, 187, 182, 187, 182, 179, 182, 186, 181, 186, 184, 180, 184, 186, 180, 186, 181, 177, 181, 185, 179, 185, 182, 178, 182, 184, 178, 184, 178, 175, 178, 182, 177, 182, 179, 176, 179, 181, 176, 181, 176, 172, 176, 151, 153, 151, 148, 151, 148, 150, 152, 150, 145, 148, 145, 148, 150, 148, 145, 148, 145, 147, 149, 147, 142, 145, 142, 145, 147, 145, 142, 145, 142, 144, 146, 144, 139, 142, 139, 143, 145, 143, 139, 143, 139, 140, 142, 140, 130, 133, 130, 159, 156, 159, 168, 165, 168, 165, 163, 165, 170, 167, 170, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 169, 172, 168, 166, 168, 173, 170, 173, 169, 167, 169, 174, 171, 174, 171, 169, 171, 176, 172, 176, 172, 170, 172, 177, 173, 177, 145, 150, 145, 150, 153, 150, 147, 152, 147, 152, 155, 152, 149, 153, 149, 153, 156, 153, 150, 155, 150, 155, 158, 155, 152, 156, 152, 156, 159, 156, 153, 157, 153, 157, 160, 157, 153, 158, 153, 157, 160, 157, 154, 158, 154, 158, 161, 158, 180, 178, 180, 184, 181, 184, 180, 178, 180, 184, 180, 184, 179, 178, 179, 183, 180, 183, 179, 177, 179, 182, 179, 182, 178, 176, 178, 181, 178, 181, 177, 175, 177, 180, 177, 180, 176, 173, 176, 179, 176, 179, 174, 172, 174, 178, 174, 178, 145, 150, 145, 148, 151, 148, 143, 148, 143, 146, 150, 146, 141, 146, 141, 145, 148, 145, 140, 145, 140, 143, 147, 143, 138, 144, 138, 142, 145, 142, 137, 142, 137, 141, 144, 141, 136, 141, 136, 139, 143, 139, 133, 139, 133, 131, 135, 131, 164, 160, 164, 166, 162, 166, 172, 167, 172, 168, 164, 168, 170, 167, 170, 169, 165, 169, 174, 169, 174, 170, 166, 170, 173, 169, 173, 171, 167, 171, 176, 171, 176, 172, 169, 172, 175, 172, 175, 174, 170, 174, 179, 173, 179, 175, 171, 175, 149, 153, 149, 149, 152, 149, 153, 155, 153, 150, 153, 150, 152, 156, 152, 152, 155, 152, 156, 158, 156, 153, 156, 153, 155, 158, 155, 154, 157, 154, 158, 160, 158, 155, 158, 155, 157, 160, 157, 156, 158, 156, 160, 161, 160, 156, 159, 156, 184, 180, 184, 182, 179, 182, 186, 181, 186, 182, 178, 182, 183, 180, 183, 181, 178, 181, 185, 180, 185, 180, 177, 180, 182, 178, 182, 179, 176, 179, 183, 178, 183, 178, 174, 178, 179, 176, 179, 177, 173, 177, 181, 176, 181, 176, 172, 176, 149, 152, 149, 146, 150, 146, 150, 151, 150, 145, 148, 145, 145, 149, 145, 143, 146, 143, 146, 148, 146, 142, 145, 142, 142, 146, 142, 140, 144, 140, 144, 145, 144, 139, 142, 139, 140, 144, 140, 138, 141, 138, 140, 142, 140, 130, 133, 130, 159, 156, 159, 168, 164, 168, 165, 163, 165, 170, 166, 170, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 168, 172, 168, 166, 168, 173, 169, 173, 169, 167, 169, 174, 170, 174, 170, 169, 170, 175, 172, 175, 172, 170, 172, 177, 173, 177, 145, 150, 145, 150, 153, 150, 147, 151, 147, 151, 154, 151, 148, 153, 148, 153, 156, 153, 150, 154, 150, 154, 157, 154, 151, 156, 151, 155, 158, 155, 152, 156, 152, 156, 159, 156, 153, 157, 153, 156, 160, 156, 153, 158, 153, 157, 160, 157, 179, 178, 179, 183, 180, 183, 179, 177, 179, 183, 180, 183, 179, 177, 179, 183, 179, 183, 178, 176, 178, 182, 178, 182, 177, 175, 177, 181, 177, 181, 176, 174, 176, 180, 176, 180, 175, 173, 175, 178, 175, 178, 174, 172, 174, 177, 174, 177, 144, 149, 144, 147, 151, 147, 143, 148, 143, 146, 149, 146, 141, 146, 141, 145, 148, 145, 139, 145, 139, 143, 146, 143, 138, 143, 138, 142, 145, 142, 137, 142, 137, 140, 144, 140, 135, 141, 135, 139, 143, 139, 133, 138, 133, 131, 135, 131, 166, 160, 166, 168, 164, 168, 172, 167, 172, 168, 164, 168, 173, 167, 173, 171, 167, 171, 174, 169, 174, 170, 166, 170, 175, 169, 175, 173, 169, 173, 176, 170, 176, 172, 168, 172, 177, 172, 177, 175, 172, 175, 178, 173, 178, 174, 171, 174, 151, 153, 151, 150, 153, 150, 153, 154, 153, 150, 153, 150, 154, 156, 154, 152, 156, 152, 156, 157, 156, 152, 155, 152, 156, 158, 156, 155, 158, 155, 158, 159, 158, 154, 157, 154, 158, 160, 158, 156, 159, 156, 158, 160, 158, 155, 158, 155, 186, 180, 186, 183, 179, 183, 185, 180, 185, 181, 177, 181, 185, 180, 185, 182, 179, 182, 184, 179, 184, 179, 176, 179, 184, 178, 184, 180, 177, 180, 183, 177, 183, 177, 174, 177, 181, 176, 181, 178, 175, 178, 180, 175, 180, 175, 172, 175, 150, 152, 150, 147, 150, 147, 149, 151, 149, 144, 147, 144, 148, 149, 148, 144, 148, 144, 146, 148, 146, 141, 145, 141, 145, 146, 145, 141, 145, 141, 144, 145, 144, 138, 142, 138, 142, 144, 142, 139, 143, 139, 140, 142, 140, 130, 133, 130, 159, 156, 159, 168, 164, 168, 165, 163, 165, 170, 166, 170, 165, 164, 165, 170, 167, 170, 167, 165, 167, 172, 168, 172, 168, 165, 168, 173, 169, 173, 169, 167, 169, 174, 170, 174, 170, 168, 170, 175, 171, 175, 171, 169, 171, 176, 173, 176, 144, 149, 144, 149, 152, 149, 146, 150, 146, 150, 153, 150, 147, 152, 147, 152, 155, 152, 149, 153, 149, 153, 156, 153, 150, 154, 150, 154, 157, 154, 151, 155, 151, 155, 158, 155, 151, 156, 151, 155, 158, 155, 152, 156, 152, 156, 158, 156, 178, 177, 178, 183, 179, 183, 178, 176, 178, 182, 179, 182, 178, 176, 178, 182, 178, 182, 177, 175, 177, 181, 177, 181, 176, 174, 176, 180, 177, 180, 175, 173, 175, 179, 176, 179, 174, 172, 174, 178, 174, 178, 173, 171, 173, 177, 173, 177, 144, 149, 144, 147, 150, 147, 142, 147, 142, 145, 149, 145, 140, 145, 140, 144, 147, 144, 139, 144, 139, 143, 146, 143, 138, 143, 138, 141, 145, 141, 136, 142, 136, 140, 144, 140, 135, 140, 135, 139, 143, 139, 133, 138, 133, 131, 135, 131, 164, 160, 164, 166, 162, 166, 172, 166, 172, 167, 164, 167, 170, 166, 170, 169, 165, 169, 174, 168, 174, 169, 166, 169, 172, 168, 172, 170, 167, 170, 176, 170, 176, 172, 168, 172, 174, 170, 174, 173, 169, 173, 178, 172, 178, 174, 170, 174, 148, 151, 148, 147, 150, 147, 152, 153, 152, 149, 152, 149, 150, 154, 150, 150, 153, 150, 154, 156, 154, 151, 154, 151, 153, 156, 153, 152, 155, 152, 156, 158, 156, 153, 156, 153, 154, 158, 154, 153, 156, 153, 157, 159, 157, 153, 156, 153, 182, 179, 182, 180, 177, 180, 184, 179, 184, 180, 176, 180, 181, 178, 181, 179, 176, 179, 183, 178, 183, 178, 175, 178, 180, 177, 180, 178, 174, 178, 182, 176, 182, 177, 173, 177, 178, 174, 178, 176, 172, 176, 179, 174, 179, 174, 171, 174, 147, 150, 147, 145, 148, 145, 148, 150, 148, 144, 147, 144, 144, 148, 144, 142, 145, 142, 145, 147, 145, 141, 144, 141, 142, 145, 142, 139, 143, 139, 143, 145, 143, 138, 142, 138, 139, 143, 139, 137, 140, 137, 140, 142, 140, 130, 133, 130, 159, 156, 159, 168, 164, 168, 164, 162, 164, 169, 166, 169, 165, 163, 165, 170, 167, 170, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 169, 172, 168, 166, 168, 173, 170, 173, 169, 167, 169, 174, 171, 174, 170, 169, 170, 175, 172, 175, 144, 148, 144, 148, 151, 148, 145, 150, 145, 150, 153, 150, 146, 151, 146, 150, 154, 150, 147, 152, 147, 152, 155, 152, 149, 153, 149, 153, 156, 153, 150, 154, 150, 153, 156, 153, 150, 155, 150, 154, 157, 154, 150, 155, 150, 154, 157, 154, 177, 175, 177, 181, 178, 181, 177, 175, 177, 181, 178, 181, 177, 175, 177, 180, 177, 180, 176, 174, 176, 180, 176, 180, 175, 173, 175, 179, 176, 179, 174, 172, 174, 178, 174, 178, 173, 171, 173, 177, 173, 177, 172, 170, 172, 176, 172, 176, 143, 148, 143, 146, 150, 146, 141, 146, 141, 145, 148, 145, 140, 145, 140, 143, 147, 143, 138, 144, 138, 142, 145, 142, 137, 142, 137, 141, 144, 141, 136, 141, 136, 140, 143, 140, 135, 140, 135, 138, 142, 138, 133, 138, 133, 131, 135, 131, 166, 160, 166, 168, 164, 168, 172, 166, 172, 167, 164, 167, 173, 167, 173, 170, 166, 170, 173, 168, 173, 169, 165, 169, 174, 169, 174, 172, 168, 172, 175, 170, 175, 171, 167, 171, 176, 171, 176, 174, 170, 174, 177, 172, 177, 173, 169, 173, 150, 151, 150, 147, 151, 147, 151, 153, 151, 147, 150, 147, 152, 153, 152, 150, 153, 150, 153, 155, 153, 150, 153, 150, 154, 156, 154, 152, 155, 152, 155, 156, 155, 151, 154, 151, 156, 157, 156, 153, 156, 153, 156, 157, 156, 152, 155, 152, 183, 178, 183, 181, 177, 181, 183, 178, 183, 178, 175, 178, 183, 178, 183, 180, 177, 180, 182, 177, 182, 177, 174, 177, 182, 176, 182, 178, 175, 178, 180, 175, 180, 176, 172, 176, 180, 174, 180, 177, 173, 177, 179, 173, 179, 174, 170, 174, 149, 150, 149, 145, 149, 145, 148, 149, 148, 143, 146, 143, 146, 148, 146, 143, 146, 143, 145, 147, 145, 140, 144, 140, 144, 145, 144, 140, 144, 140, 143, 145, 143, 138, 141, 138, 142, 144, 142, 138, 142, 138, 140, 142, 140, 130, 133, 130, 159, 156, 159, 168, 164, 168, 164, 162, 164, 169, 165, 169, 165, 163, 165, 170, 166, 170, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 168, 172, 168, 165, 168, 173, 169, 173, 169, 167, 169, 174, 170, 174, 170, 168, 170, 174, 171, 174, 142, 147, 142, 147, 150, 147, 144, 149, 144, 148, 152, 148, 145, 150, 145, 150, 153, 150, 146, 151, 146, 150, 153, 150, 147, 152, 147, 151, 154, 151, 148, 153, 148, 152, 155, 152, 148, 153, 148, 152, 156, 152, 149, 153, 149, 153, 156, 153, 176, 174, 176, 180, 177, 180, 176, 174, 176, 180, 176, 180, 176, 173, 176, 179, 176, 179, 175, 173, 175, 179, 175, 179, 174, 172, 174, 178, 174, 178, 173, 171, 173, 177, 174, 177, 172, 170, 172, 176, 173, 176, 171, 169, 171, 175, 172, 175, 142, 147, 142, 145, 149, 145, 140, 145, 140, 144, 147, 144, 139, 144, 139, 143, 146, 143, 138, 143, 138, 141, 145, 141, 137, 142, 137, 140, 144, 140, 135, 141, 135, 139, 143, 139, 134, 140, 134, 138, 142, 138, 132, 138, 132, 131, 135, 131, 163, 160, 163, 165, 162, 165, 172, 166, 172, 167, 163, 167, 169, 165, 169, 168, 164, 168, 173, 167, 173, 169, 165, 169, 171, 167, 171, 169, 166, 169, 174, 169, 174, 170, 167, 170, 173, 169, 173, 171, 168, 171, 177, 171, 177, 172, 169, 172, 146, 149, 146, 145, 148, 145, 150, 151, 150, 146, 149, 146, 148, 151, 148, 147, 150, 147, 152, 153, 152, 148, 151, 148, 150, 153, 150, 149, 152, 149, 153, 155, 153, 150, 153, 150, 151, 155, 151, 150, 153, 150, 154, 156, 154, 150, 153, 150, 179, 176, 179, 177, 174, 177, 182, 177, 182, 177, 174, 177, 179, 176, 179, 177, 173, 177, 181, 176, 181, 176, 173, 176, 178, 174, 178, 176, 172, 176, 180, 174, 180, 174, 171, 174, 176, 173, 176, 174, 170, 174, 178, 173, 178, 173, 169, 173, 145, 149, 145, 143, 146, 143, 147, 148, 147, 142, 145, 142, 143, 146, 143, 141, 144, 141, 145, 146, 145, 139, 143, 139, 140, 144, 140, 138, 142, 138, 142, 144, 142, 137, 141, 137, 138, 142, 138, 136, 140, 136, 139, 141, 139, 129, 133, 129, 159, 156, 159, 167, 164, 167, 164, 162, 164, 169, 165, 169, 165, 162, 165, 170, 166, 170, 165, 163, 165, 170, 167, 170, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 169, 172, 168, 166, 168, 173, 169, 173, 169, 167, 169, 174, 170, 174, 141, 146, 141, 146, 149, 146, 143, 147, 143, 147, 150, 147, 144, 149, 144, 148, 151, 148, 145, 150, 145, 149, 152, 149, 145, 150, 145, 150, 153, 150, 146, 151, 146, 150, 153, 150, 147, 151, 147, 151, 154, 151, 147, 152, 147, 151, 154, 151, 174, 173, 174, 179, 175, 179, 174, 172, 174, 178, 175, 178, 174, 172, 174, 178, 174, 178, 174, 172, 174, 178, 174, 178, 173, 171, 173, 177, 173, 177, 172, 170, 172, 176, 173, 176, 171, 169, 171, 175, 172, 175, 170, 169, 170, 174, 171, 174, 141, 146, 141, 144, 148, 144, 139, 145, 139, 143, 146, 143, 138, 144, 138, 142, 145, 142, 137, 142, 137, 141, 144, 141, 136, 141, 136, 140, 143, 140, 135, 140, 135, 139, 142, 139, 134, 139, 134, 138, 141, 138, 132, 137, 132, 131, 135, 131, 166, 160, 166, 167, 164, 167, 171, 165, 171, 167, 163, 167, 172, 166, 172, 169, 165, 169, 172, 167, 172, 168, 164, 168, 173, 168, 173, 171, 167, 171, 174, 169, 174, 170, 166, 170, 175, 169, 175, 173, 169, 173, 176, 170, 176, 172, 168, 172, 147, 149, 147, 145, 149, 145, 149, 150, 149, 145, 148, 145, 150, 151, 150, 147, 151, 147, 150, 152, 150, 147, 150, 147, 151, 153, 151, 149, 152, 149, 152, 153, 152, 148, 151, 148, 152, 154, 152, 150, 153, 150, 153, 154, 153, 149, 152, 149, 181, 176, 181, 178, 174, 178, 180, 175, 180, 176, 172, 176, 180, 175, 180, 177, 174, 177, 180, 174, 180, 175, 172, 175, 179, 174, 179, 176, 173, 176, 179, 173, 179, 174, 170, 174, 178, 172, 178, 175, 171, 175, 177, 172, 177, 172, 168, 172, 147, 149, 147, 144, 147, 144, 146, 148, 146, 141, 144, 141, 145, 146, 145, 141, 145, 141, 144, 145, 144, 139, 142, 139, 143, 145, 143, 139, 143, 139, 142, 144, 142, 137, 140, 137, 141, 143, 141, 137, 141, 137, 139, 141, 139, 129, 133, 129, 127, 132, 127, 136, 140, 136, 133, 138, 133, 138, 141, 138, 134, 139, 134, 138, 142, 138, 135, 140, 135, 139, 143, 139, 136, 141, 136, 140, 144, 140, 137, 142, 137, 142, 145, 142, 138, 143, 138, 143, 146, 143, 139, 144, 139, 144, 147, 144, 169, 167, 169, 174, 170, 174, 170, 168, 170, 174, 171, 174, 171, 169, 171, 175, 172, 175, 172, 169, 172, 176, 173, 176, 172, 170, 172, 177, 173, 177, 173, 170, 173, 177, 173, 177, 173, 171, 173, 177, 174, 177, 173, 171, 173, 177, 174, 177, 145, 150, 145, 149, 153, 149, 145, 150, 145, 149, 152, 149, 145, 150, 145, 149, 152, 149, 144, 149, 144, 148, 151, 148, 144, 149, 144, 147, 150, 147, 143, 148, 143, 146, 150, 146, 142, 147, 142, 145, 149, 145, 141, 146, 141, 144, 148, 144, 169, 167, 169, 173, 169, 173, 168, 166, 168, 172, 168, 172, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 167, 170, 165, 163, 165, 169, 166, 169, 165, 162, 165, 169, 165, 169, 164, 162, 164, 168, 164, 168, 163, 160, 163, 163, 160, 163, 131, 135, 131, 134, 138, 134, 140, 142, 140, 136, 139, 136, 138, 141, 138, 137, 140, 137, 142, 143, 142, 138, 141, 138, 140, 143, 140, 138, 142, 138, 144, 145, 144, 140, 143, 140, 142, 145, 142, 141, 144, 141, 145, 147, 145, 142, 145, 142, 173, 169, 173, 172, 168, 172, 177, 171, 177, 172, 169, 172, 174, 171, 174, 173, 169, 173, 178, 172, 178, 173, 170, 173, 176, 172, 176, 174, 170, 174, 179, 173, 179, 174, 171, 174, 177, 173, 177, 175, 171, 175, 179, 174, 179, 175, 171, 175, 148, 152, 148, 147, 150, 147, 151, 153, 151, 147, 150, 147, 148, 151, 148, 146, 150, 146, 150, 152, 150, 145, 149, 145, 147, 150, 147, 145, 148, 145, 149, 150, 149, 144, 147, 144, 145, 149, 145, 143, 146, 143, 147, 149, 147, 142, 145, 142, 173, 169, 173, 170, 167, 170, 174, 169, 174, 169, 166, 169, 171, 167, 171, 169, 165, 169, 173, 167, 173, 168, 164, 168, 170, 166, 170, 167, 164, 167, 172, 166, 172, 167, 163, 167, 168, 164, 168, 166, 162, 166, 170, 164, 170, 161, 157, 161, 127, 132, 127, 136, 139, 136, 132, 138, 132, 137, 141, 137, 133, 139, 133, 138, 142, 138, 134, 139, 134, 139, 143, 139, 135, 140, 135, 140, 143, 140, 136, 141, 136, 141, 144, 141, 137, 142, 137, 142, 145, 142, 138, 143, 138, 143, 146, 143, 168, 166, 168, 173, 169, 173, 169, 167, 169, 174, 170, 174, 170, 167, 170, 174, 171, 174, 170, 168, 170, 175, 171, 175, 171, 169, 171, 175, 172, 175, 171, 169, 171, 176, 172, 176, 172, 170, 172, 176, 172, 176, 172, 170, 172, 176, 173, 176, 144, 149, 144, 147, 151, 147, 144, 148, 144, 147, 150, 147, 143, 148, 143, 147, 150, 147, 143, 148, 143, 146, 150, 146, 142, 147, 142, 145, 149, 145, 141, 146, 141, 145, 148, 145, 140, 145, 140, 144, 147, 144, 139, 145, 139, 143, 146, 143, 168, 166, 168, 172, 168, 172, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 167, 170, 165, 164, 165, 170, 166, 170, 165, 163, 165, 169, 165, 169, 164, 162, 164, 168, 165, 168, 164, 161, 164, 168, 164, 168, 162, 160, 162, 163, 160, 163, 134, 136, 134, 136, 139, 136, 139, 141, 139, 135, 139, 135, 140, 142, 140, 138, 141, 138, 141, 143, 141, 137, 140, 137, 142, 144, 142, 139, 143, 139, 143, 145, 143, 139, 142, 139, 144, 145, 144, 141, 145, 141, 145, 146, 145, 141, 144, 141, 175, 169, 175, 173, 169, 173, 176, 170, 176, 171, 167, 171, 176, 171, 176, 174, 170, 174, 177, 171, 177, 172, 169, 172, 177, 172, 177, 175, 171, 175, 178, 172, 178, 173, 170, 173, 178, 173, 178, 175, 172, 175, 178, 173, 178, 173, 170, 173, 150, 151, 150, 147, 150, 147, 149, 151, 149, 145, 148, 145, 149, 150, 149, 146, 150, 146, 149, 150, 149, 144, 147, 144, 148, 150, 148, 145, 148, 145, 147, 149, 147, 143, 146, 143, 146, 148, 146, 144, 147, 144, 146, 147, 146, 141, 144, 141, 174, 169, 174, 172, 168, 172, 174, 168, 174, 169, 165, 169, 173, 167, 173, 170, 166, 170, 173, 167, 173, 167, 164, 167, 172, 166, 172, 169, 165, 169, 171, 165, 171, 166, 162, 166, 170, 165, 170, 167, 164, 167, 170, 164, 170, 161, 157, 161, 127, 132, 127, 135, 139, 135, 132, 137, 132, 137, 140, 137, 133, 138, 133, 137, 141, 137, 133, 139, 133, 138, 142, 138, 134, 140, 134, 139, 143, 139, 135, 140, 135, 140, 144, 140, 136, 141, 136, 141, 144, 141, 137, 142, 137, 142, 145, 142, 167, 165, 167, 172, 169, 172, 168, 166, 168, 173, 169, 173, 169, 167, 169, 173, 170, 173, 169, 167, 169, 174, 170, 174, 170, 167, 170, 174, 170, 174, 170, 168, 170, 174, 171, 174, 170, 168, 170, 175, 171, 175, 170, 169, 170, 175, 171, 175, 142, 147, 142, 146, 149, 146, 142, 147, 142, 145, 149, 145, 141, 146, 141, 145, 149, 145, 141, 146, 141, 145, 148, 145, 140, 145, 140, 144, 148, 144, 140, 145, 140, 144, 147, 144, 139, 144, 139, 143, 146, 143, 138, 144, 138, 142, 145, 142, 167, 165, 167, 171, 167, 171, 166, 164, 166, 170, 167, 170, 165, 164, 165, 170, 166, 170, 165, 163, 165, 169, 165, 169, 164, 162, 164, 169, 165, 169, 164, 162, 164, 168, 164, 168, 163, 161, 163, 167, 164, 167, 162, 160, 162, 163, 160, 163, 131, 135, 131, 134, 137, 134, 139, 141, 139, 135, 138, 135, 137, 140, 137, 135, 139, 135, 140, 142, 140, 136, 140, 136, 138, 142, 138, 137, 140, 137, 142, 144, 142, 138, 141, 138, 140, 144, 140, 139, 142, 139, 144, 145, 144, 139, 143, 139, 171, 168, 171, 170, 166, 170, 174, 169, 174, 170, 167, 170, 172, 169, 172, 171, 167, 171, 176, 170, 176, 171, 167, 171, 173, 170, 173, 172, 168, 172, 176, 171, 176, 172, 168, 172, 174, 170, 174, 172, 169, 172, 177, 171, 177, 172, 169, 172, 145, 149, 145, 144, 147, 144, 148, 150, 148, 143, 146, 143, 145, 148, 145, 143, 146, 143, 147, 149, 147, 143, 146, 143, 144, 147, 144, 142, 145, 142, 146, 148, 146, 141, 145, 141, 143, 146, 143, 141, 144, 141, 145, 146, 145, 140, 143, 140, 171, 167, 171, 169, 165, 169, 173, 167, 173, 168, 164, 168, 170, 166, 170, 167, 164, 167, 172, 166, 172, 167, 163, 167, 169, 165, 169, 166, 162, 166, 171, 165, 171, 165, 162, 165, 167, 164, 167, 165, 161, 165, 169, 164, 169, 161, 157, 161, 127, 132, 127, 135, 139, 135, 131, 137, 131, 136, 140, 136, 132, 137, 132, 137, 140, 137, 133, 138, 133, 137, 141, 137, 134, 139, 134, 138, 142, 138, 134, 140, 134, 139, 143, 139, 135, 140, 135, 140, 143, 140, 136, 141, 136, 140, 144, 140, 166, 164, 166, 171, 167, 171, 167, 165, 167, 172, 168, 172, 167, 165, 167, 172, 169, 172, 168, 166, 168, 173, 169, 173, 169, 166, 169, 173, 169, 173, 169, 167, 169, 173, 170, 173, 169, 167, 169, 173, 170, 173, 169, 167, 169, 173, 170, 173, 140, 145, 140, 144, 148, 144, 140, 145, 140, 144, 148, 144, 140, 145, 140, 144, 147, 144, 139, 145, 139, 144, 147, 144, 139, 144, 139, 143, 146, 143, 138, 144, 138, 142, 146, 142, 138, 143, 138, 142, 145, 142, 137, 142, 137, 141, 145, 141, 166, 164, 166, 170, 167, 170, 165, 164, 165, 170, 166, 170, 165, 163, 165, 169, 165, 169, 164, 162, 164, 169, 165, 169, 164, 162, 164, 168, 164, 168, 163, 161, 163, 167, 164, 167, 163, 160, 163, 167, 163, 167, 162, 160, 162, 163, 159, 163, 134, 136, 134, 135, 139, 135, 138, 140, 138, 134, 138, 134, 139, 141, 139, 136, 140, 136, 140, 142, 140, 136, 139, 136, 140, 142, 140, 138, 142, 138, 141, 143, 141, 137, 140, 137, 142, 144, 142, 139, 143, 139, 143, 144, 143, 138, 142, 138, 173, 168, 173, 171, 167, 171, 174, 168, 174, 169, 165, 169, 174, 169, 174, 172, 168, 172, 174, 169, 174, 170, 166, 170, 175, 169, 175, 172, 169, 172, 175, 170, 175, 171, 167, 171, 176, 170, 176, 173, 169, 173, 176, 170, 176, 171, 167, 171, 146, 148, 146, 144, 147, 144, 146, 148, 146, 142, 145, 142, 146, 148, 146, 143, 146, 143, 145, 147, 145, 141, 145, 141, 145, 147, 145, 142, 146, 142, 145, 146, 145, 140, 144, 140, 144, 146, 144, 141, 145, 141, 144, 145, 144, 139, 142, 139, 173, 167, 173, 170, 166, 170, 172, 167, 172, 167, 164, 167, 172, 166, 172, 169, 165, 169, 171, 165, 171, 166, 162, 166, 171, 165, 171, 168, 164, 168, 170, 165, 170, 165, 161, 165, 170, 164, 170, 167, 163, 167, 169, 164, 169, 161, 157, 161, 127, 132, 127, 135, 138, 135, 131, 136, 131, 136, 139, 136, 132, 137, 132, 136, 140, 136, 132, 137, 132, 137, 140, 137, 133, 138, 133, 137, 141, 137, 134, 139, 134, 138, 142, 138, 134, 140, 134, 139, 143, 139, 135, 140, 135, 139, 143, 139, 165, 164, 165, 170, 167, 170, 166, 164, 166, 171, 167, 171, 167, 164, 167, 171, 167, 171, 167, 165, 167, 172, 168, 172, 167, 165, 167, 172, 168, 172, 167, 165, 167, 172, 169, 172, 168, 166, 168, 172, 169, 172, 168, 166, 168, 172, 169, 172, 139, 144, 139, 143, 146, 143, 139, 144, 139, 143, 146, 143, 138, 144, 138, 142, 146, 142, 138, 143, 138, 142, 145, 142, 138, 143, 138, 142, 145, 142, 137, 142, 137, 141, 145, 141, 137, 142, 137, 140, 144, 140, 136, 141, 136, 140, 144, 140, 165, 163, 165, 170, 166, 170, 165, 163, 165, 169, 165, 169, 164, 162, 164, 169, 165, 169, 164, 162, 164, 168, 164, 168, 163, 161, 163, 167, 164, 167, 163, 160, 163, 167, 163, 167, 162, 160, 162, 167, 163, 167, 162, 160, 162, 163, 159, 163, 131, 135, 131, 133, 136, 133, 138, 140, 138, 134, 137, 134, 136, 139, 136, 134, 138, 134, 139, 141, 139, 135, 138, 135, 137, 140, 137, 135, 139, 135, 140, 142, 140, 136, 140, 136, 138, 142, 138, 137, 140, 137, 142, 143, 142, 137, 141, 137, 170, 166, 170, 168, 164, 168, 173, 167, 173, 168, 165, 168, 170, 167, 170, 169, 165, 169, 174, 168, 174, 169, 165, 169, 171, 168, 171, 169, 166, 169, 174, 169, 174, 170, 166, 170, 172, 168, 172, 170, 166, 170, 174, 169, 174, 170, 166, 170, 142, 145, 142, 141, 144, 141, 145, 146, 145, 140, 144, 140, 142, 145, 142, 140, 144, 140, 145, 146, 145, 140, 143, 140, 141, 145, 141, 139, 143, 139, 144, 145, 144, 139, 142, 139, 140, 144, 140, 138, 142, 138, 143, 144, 143, 138, 141, 138, 169, 166, 169, 167, 164, 167, 172, 166, 172, 167, 163, 167, 169, 165, 169, 166, 162, 166, 171, 165, 171, 165, 162, 165, 167, 164, 167, 165, 162, 165, 170, 164, 170, 165, 161, 165, 167, 163, 167, 164, 160, 164, 169, 163, 169, 161, 157, 161, 127, 132, 127, 134, 138, 134, 130, 136, 130, 135, 139, 135, 131, 136, 131, 136, 139, 136, 132, 137, 132, 136, 140, 136, 132, 137, 132, 137, 140, 137, 133, 138, 133, 137, 141, 137, 133, 139, 133, 138, 142, 138, 134, 139, 134, 138, 142, 138, 165, 163, 165, 170, 166, 170, 165, 163, 165, 170, 166, 170, 165, 164, 165, 170, 167, 170, 166, 164, 166, 170, 167, 170, 166, 164, 166, 171, 167, 171, 167, 164, 167, 171, 167, 171, 167, 165, 167, 171, 167, 171, 167, 165, 167, 171, 168, 171, 137, 143, 137, 141, 145, 141, 137, 142, 137, 141, 145, 141, 137, 142, 137, 141, 145, 141, 137, 142, 137, 141, 144, 141, 136, 142, 136, 140, 144, 140, 136, 141, 136, 140, 144, 140, 135, 141, 135, 139, 143, 139, 135, 140, 135, 139, 143, 139, 165, 162, 165, 169, 165, 169, 164, 162, 164, 169, 165, 169, 164, 162, 164, 168, 164, 168, 163, 161, 163, 167, 164, 167, 163, 160, 163, 167, 163, 167, 162, 160, 162, 167, 163, 167, 162, 160, 162, 166, 162, 166, 161, 159, 161, 163, 159, 163, 134, 136, 134, 134, 138, 134, 137, 139, 137, 133, 137, 133, 138, 140, 138, 135, 139, 135, 138, 140, 138, 134, 138, 134, 139, 141, 139, 136, 140, 136, 140, 141, 140, 135, 139, 135, 140, 142, 140, 137, 141, 137, 141, 143, 141, 136, 140, 136, 172, 166, 172, 169, 165, 169, 172, 167, 172, 167, 164, 167, 173, 167, 173, 170, 166, 170, 173, 167, 173, 168, 164, 168, 173, 167, 173, 170, 167, 170, 173, 168, 173, 169, 165, 169, 173, 168, 173, 171, 167, 171, 173, 168, 173, 169, 165, 169, 144, 145, 144, 141, 144, 141, 144, 145, 144, 139, 142, 139, 143, 145, 143, 140, 144, 140, 143, 145, 143, 138, 142, 138, 143, 145, 143, 140, 143, 140, 142, 144, 142, 138, 141, 138, 142, 144, 142, 139, 143, 139, 142, 143, 142, 137, 140, 137, 172, 166, 172, 169, 165, 169, 171, 165, 171, 166, 162, 166, 171, 165, 171, 168, 164, 168, 170, 165, 170, 165, 161, 165, 170, 164, 170, 167, 163, 167, 169, 164, 169, 164, 160, 164, 169, 163, 169, 166, 162, 166, 169, 163, 169, 161, 157, 161, 126, 132, 126, 134, 138, 134, 130, 135, 130, 135, 138, 135, 130, 136, 130, 135, 139, 135, 131, 136, 131, 136, 139, 136, 131, 137, 131, 136, 140, 136, 132, 137, 132, 137, 140, 137, 133, 138, 133, 137, 141, 137, 133, 138, 133, 138, 141, 138, 164, 162, 164, 169, 165, 169, 164, 162, 164, 169, 165, 169, 165, 163, 165, 169, 166, 169, 165, 163, 165, 170, 166, 170, 165, 163, 165, 170, 166, 170, 165, 164, 165, 170, 167, 170, 166, 164, 166, 170, 167, 170, 166, 164, 166, 170, 167, 170, 136, 141, 136, 140, 144, 140, 136, 141, 136, 140, 144, 140, 136, 141, 136, 140, 144, 140, 135, 141, 135, 140, 143, 140, 135, 140, 135, 139, 143, 139, 135, 140, 135, 139, 143, 139, 134, 140, 134, 138, 142, 138, 134, 139, 134, 138, 142, 138, 164, 162, 164, 168, 164, 168, 164, 161, 164, 168, 164, 168, 163, 161, 163, 167, 164, 167, 163, 160, 163, 167, 163, 167, 162, 160, 162, 167, 163, 167, 162, 160, 162, 166, 162, 166, 162, 159, 162, 166, 162, 166, 161, 159, 161, 163, 159, 163, 131, 134, 131, 132, 136, 132, 137, 139, 137, 133, 136, 133, 135, 138, 135, 133, 137, 133, 138, 140, 138, 134, 137, 134, 135, 139, 135, 134, 138, 134, 139, 141, 139, 135, 138, 135, 136, 140, 136, 135, 139, 135, 140, 142, 140, 136, 139, 136, 168, 164, 168, 166, 163, 166, 172, 166, 172, 167, 163, 167, 169, 165, 169, 167, 163, 167, 172, 166, 172, 167, 164, 167, 169, 166, 169, 167, 164, 167, 172, 167, 172, 168, 164, 168, 170, 166, 170, 168, 164, 168, 173, 167, 173, 168, 164, 168, 139, 143, 139, 138, 141, 138, 142, 144, 142, 138, 141, 138, 139, 143, 139, 138, 141, 138, 142, 144, 142, 137, 141, 137, 139, 143, 139, 137, 140, 137, 141, 143, 141, 137, 140, 137, 138, 142, 138, 136, 140, 136, 141, 142, 141, 136, 139, 136, 168, 164, 168, 166, 162, 166, 170, 165, 170, 165, 162, 165, 167, 164, 167, 165, 161, 165, 170, 164, 170, 165, 161, 165, 167, 163, 167, 164, 160, 164, 169, 163, 169, 164, 160, 164, 166, 162, 166, 164, 160, 164, 169, 163, 169, 161, 157, 161, 126, 132, 126, 134, 137, 134, 130, 135, 130, 134, 138, 134, 130, 135, 130, 134, 138, 134, 130, 136, 130, 135, 138, 135, 131, 136, 131, 135, 139, 135, 131, 136, 131, 135, 139, 135, 131, 137, 131, 136, 139, 136, 132, 137, 132, 136, 140, 136, 163, 161, 163, 167, 164, 167, 163, 161, 163, 168, 164, 168, 163, 161, 163, 168, 164, 168, 164, 161, 164, 168, 164, 168, 164, 162, 164, 168, 164, 168, 164, 162, 164, 168, 165, 168, 164, 162, 164, 168, 165, 168, 164, 162, 164, 169, 165, 169, 133, 139, 133, 138, 141, 138, 133, 139, 133, 137, 141, 137, 133, 139, 133, 137, 141, 137, 133, 138, 133, 137, 141, 137, 133, 138, 133, 137, 141, 137, 133, 138, 133, 137, 141, 137, 132, 138, 132, 137, 140, 137, 132, 137, 132, 136, 140, 136, 163, 160, 163, 167, 164, 167, 162, 160, 162, 167, 163, 167, 162, 160, 162, 167, 163, 167, 162, 160, 162, 166, 163, 166, 162, 160, 162, 166, 162, 166, 161, 159, 161, 166, 162, 166, 161, 159, 161, 165, 162, 165, 161, 158, 161, 163, 159, 163, 134, 136, 134, 131, 134, 131, 134, 136, 134, 129, 133, 129, 134, 136, 134, 131, 135, 131, 134, 136, 134, 129, 133, 129, 134, 136, 134, 131, 135, 131, 134, 136, 134, 129, 133, 129, 134, 136, 134, 131, 135, 131, 134, 136, 134, 129, 133, 129, 166, 160, 166, 163, 160, 163, 166, 160, 166, 161, 157, 161, 166, 160, 166, 164, 160, 164, 166, 160, 166, 161, 158, 161, 166, 160, 166, 164, 160, 164, 166, 160, 166, 161, 158, 161, 166, 160, 166, 164, 160, 164, 166, 160, 166, 161, 158, 161, 134, 136, 134, 131, 135, 131, 134, 136, 134, 130, 133, 130, 134, 136, 134, 131, 135, 131, 134, 136, 134, 130, 133, 130, 134, 136, 134, 131, 135, 131, 134, 136, 134, 130, 133, 130, 134, 136, 134, 131, 135, 131, 134, 136, 134, 129, 133, 129, 166, 160, 166, 163, 160, 163, 166, 160, 166, 161, 157, 161, 166, 160, 166, 163, 159, 163, 166, 160, 166, 161, 157, 161, 166, 160, 166, 163, 159, 163, 166, 160, 166, 161, 157, 161, 166, 160, 166, 163, 159, 163, 166, 160, 166, 161, 157, 161), +"format": "RGB8", +"height": 64, +"mipmaps": false, +"width": 64 +} + +[sub_resource type="ImageTexture" id="ImageTexture_7h7sd"] +image = SubResource("Image_cy15a") + +[node name="MaterialButton" type="PanelContainer"] +offset_right = 89.0 +offset_bottom = 91.0 +mouse_filter = 1 +theme = ExtResource("1_t260s") +script = ExtResource("1_vd4oe") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 +metadata/_edit_lock_ = true + +[node name="TextureRect" type="TextureRect" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +texture = SubResource("ImageTexture_7h7sd") +stretch_mode = 3 + +[node name="MaterialName" type="Label" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +clip_text = true diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_group.gd b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_group.gd new file mode 100644 index 00000000..57751e33 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_group.gd @@ -0,0 +1,58 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name MaterialGroup + +class Tier: + var name:String + var children:Array[MaterialGroup] + + func _init(name:String = ""): + self.name = name + + func create_child_with_name(name:String)->Tier: + var child:Tier = Tier.new(name) + children.append(child) + return child + + func get_child_with_name(name:String): + for child in children: + if child.name == name: + return child + return null + + func get_child_index_with_name(name:String)->int: + for i in children.size(): + if children[i].name == name: + return i + return -1 + + func remove_child_with_name(name:String): + var idx:int = get_child_index_with_name(name) + if idx > -1: + children.remove_at(idx) + +var root:Tier = Tier.new("Any") + diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_group.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_group.gd.uid new file mode 100644 index 00000000..44248794 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_group.gd.uid @@ -0,0 +1 @@ +uid://b5okehwnewkbc diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd new file mode 100644 index 00000000..e28138b8 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd @@ -0,0 +1,321 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Tree +class_name MaterialGroupsTree + +signal visiblity_changed + +enum ButtonType { VISIBLE } + +const bn_vis_off = preload("res://addons/cyclops_level_builder/art/icons/eye_closed.svg") +const bn_vis_on = preload("res://addons/cyclops_level_builder/art/icons/eye_open.svg") + +@export var show_unused_dirs:bool = true: + get: + return show_unused_dirs + set(value): + if value == show_unused_dirs: + return + show_unused_dirs = value + + reload_materials() + +var plugin:CyclopsLevelBuilder: + get: + return plugin + set(value): + if value == plugin: + return + + if plugin: + var ed_iface:EditorInterface = plugin.get_editor_interface() + var efs:EditorFileSystem = ed_iface.get_resource_filesystem() + efs.filesystem_changed.disconnect(on_filesystem_changed) + efs.resources_reimported.disconnect(on_resources_reimported) + efs.resources_reload.disconnect(on_resources_reload) + + plugin = value + %CreateMaterialDialog.plugin = plugin + + if plugin: + var ed_iface:EditorInterface = plugin.get_editor_interface() + var efs:EditorFileSystem = ed_iface.get_resource_filesystem() + efs.filesystem_changed.connect(on_filesystem_changed) + efs.resources_reimported.connect(on_resources_reimported) + efs.resources_reload.connect(on_resources_reload) + + reload_materials() + +var tree_item_to_path_map:Dictionary +var path_to_tree_item_map:Dictionary + + +func reload_materials(): + #print("reload_materials") + clear() + tree_item_to_path_map.clear() + path_to_tree_item_map.clear() + + if !plugin: + return + + var ed_iface:EditorInterface = plugin.get_editor_interface() + var efs:EditorFileSystem = ed_iface.get_resource_filesystem() + + var root_dir:EditorFileSystemDirectory = efs.get_filesystem() + + var root_tree_item:TreeItem = create_item() + root_tree_item.set_text(0, root_dir.get_name()) + root_tree_item.set_checked(1, true) + root_tree_item.set_editable(1, true) + + tree_item_to_path_map[root_tree_item] = root_dir.get_path() + path_to_tree_item_map[root_dir.get_path()] = root_tree_item + + build_tree_recursive(root_dir, root_tree_item) + + collapse_unused_dirs() + + +func build_tree_recursive(parent_dir:EditorFileSystemDirectory, tree_item_parent:TreeItem): + #print("par_dir count ", parent_dir.get_path(), parent_dir.get_subdir_count()) + + for i in parent_dir.get_subdir_count(): + var child_dir:EditorFileSystemDirectory = parent_dir.get_subdir(i) + #print("add child ", child_dir.get_path()) + + if !show_unused_dirs && !dir_has_materials_recursive(child_dir): + continue + + var item:TreeItem = create_item(tree_item_parent) + item.set_text(0, child_dir.get_name()) + item.set_checked(1, true) + #item.set_editable(1, true) + item.add_button(1, bn_vis_on, ButtonType.VISIBLE, false, "Visible") + + tree_item_to_path_map[item] = child_dir.get_path() + path_to_tree_item_map[child_dir.get_path()] = item + #print("path ", child_dir.get_path()) + + build_tree_recursive(child_dir, item) + + +func on_filesystem_changed(): + reload_materials() + pass + +func on_resources_reimported(resources: PackedStringArray): + pass + +func on_resources_reload(resources: PackedStringArray): + pass + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + +func create_new_group(): + pass + +func delete_selected_group(): + pass + +func rename_selected_group(): + pass + +func _on_item_selected(): + var item:TreeItem = get_selected() + item.get_index() + pass # Replace with function body. + + +func _on_item_edited(): + var item:TreeItem = get_edited() + pass # Replace with function body. + + +func _on_popup_menu_id_pressed(id:int): + match id: + 0: + create_new_group() + 1: + delete_selected_group() + 2: + rename_selected_group() + + + +func _on_button_clicked(item:TreeItem, column:int, id:int, mouse_button_index:int): + var checked:bool = !item.is_checked(1) + item.set_checked(1, checked) + item.set_button(1, ButtonType.VISIBLE, bn_vis_on if checked else bn_vis_off) + visiblity_changed.emit() + +func is_path_visible(path:String)->bool: + if !path_to_tree_item_map.has(path): + return false + + var item:TreeItem = path_to_tree_item_map[path] + return item.is_checked(1) + + +func get_hidden_directories()->Array[String]: + var ret_paths:Array[String] + + for path in path_to_tree_item_map.keys(): + var item:TreeItem = path_to_tree_item_map[path] + if !item.is_checked(1): + ret_paths.append(path) + + return ret_paths + +func dir_has_materials(dir:EditorFileSystemDirectory)->bool: + for i in dir.get_file_count(): + var file_type:StringName = dir.get_file_type(i) + + if file_type == "StandardMaterial3D" || file_type == "ORMMaterial3D" || file_type == "ShaderMaterial": + return true + + return false + +func dir_has_materials_recursive(dir:EditorFileSystemDirectory)->bool: + if dir_has_materials(dir): + return true + + for i in dir.get_subdir_count(): + var child_dir:EditorFileSystemDirectory = dir.get_subdir(i) + if dir_has_materials_recursive(child_dir): + return true + + return false + +func collapse_unused_dirs(): + if !plugin: + return + + var ed_iface:EditorInterface = plugin.get_editor_interface() + var efs:EditorFileSystem = ed_iface.get_resource_filesystem() + + var root_dir:EditorFileSystemDirectory = efs.get_filesystem() + collapse_unused_dirs_recursive(root_dir) + + +func collapse_unused_dirs_recursive(dir:EditorFileSystemDirectory)->bool: + #print("path ", dir.get_path()) + if !path_to_tree_item_map.has(dir.get_path()): + return false + + var item:TreeItem = path_to_tree_item_map[dir.get_path()] + #print("item ", item.get_text(0)) + var expanded:bool = dir_has_materials(dir) +# item.collapsed = !dir_has_materials(dir) + # + for i in dir.get_subdir_count(): + var child_dir:EditorFileSystemDirectory = dir.get_subdir(i) + var result:bool = collapse_unused_dirs_recursive(child_dir) + if result: + expanded = true + + item.collapsed = !expanded + + return expanded + +func _can_drop_data(at_position:Vector2, data:Variant): +# print("_can_drop_data %s" % data) + return typeof(data) == TYPE_DICTIONARY and data.has("type") and data["type"] == "files" + + +func _drop_data(at_position:Vector2, data:Variant): + var item:TreeItem = get_item_at_position(at_position) + if !item: + return + + var files = data["files"] + #print("--drop") + var texture_list:Array[Texture2D] + for f in files: +# print("Dropping %s" % f) + var res:Resource = load(f) + if res is Texture2D: + #print("Dropping %s" % res.resource_path) + + texture_list.append(res) + + if texture_list.is_empty(): + return + + var parent_dir_path:String = tree_item_to_path_map[item] + + %CreateMaterialDialog.parent_dir_path = parent_dir_path + %CreateMaterialDialog.texture_list = texture_list + %CreateMaterialDialog.popup_centered() + #%CreateMaterialDialog.popup_on_parent() + +func _on_create_material_dialog_create_material(params:Dictionary): + + #Prepare texture + var target_texture:Texture2D + + var tex_list:Array = params["textures"] + if tex_list.size() == 1: + target_texture = tex_list[0] + elif tex_list.size() > 1: + var anim_tex:AnimatedTexture = AnimatedTexture.new() + anim_tex.frames = tex_list.size() + for i in tex_list.size(): + anim_tex.set_frame_texture(i, tex_list[i]) + + target_texture = anim_tex + + #Create material + if params["material_type"] == "standard": + var new_mat:StandardMaterial3D = StandardMaterial3D.new() + new_mat.albedo_texture = target_texture + + if params["uv_type"] == "pix_per_game_unit": + var ppgu:int = params["pix_per_game_unit"] + new_mat.uv1_scale = Vector3(tex_list[0].get_width() / ppgu, tex_list[0].get_height() / ppgu, 1) + + ResourceSaver.save(new_mat, params["parent_dir"] + "/" + params["name"] + ".tres") + + elif params["material_type"] == "shader": + var new_mat:ShaderMaterial = ShaderMaterial.new() + new_mat.shader = ResourceLoader.load(params["shader_res_path"], "Shader") + + #print("tex param ", params["texture_parameter"]) + new_mat.set_shader_parameter(params["texture_parameter"], target_texture) + + if params["uv_type"] == "pix_per_game_unit": + var ppgu:float = params["pix_per_game_unit"] + new_mat.set_shader_parameter(params["uv_parameter"], Vector3(tex_list[0].get_width() / ppgu, tex_list[0].get_height() / ppgu, 1)) + + ResourceSaver.save(new_mat, params["parent_dir"] + "/" + params["name"] + ".tres") + + pass # Replace with function body. diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd.uid new file mode 100644 index 00000000..b80ac205 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd.uid @@ -0,0 +1 @@ +uid://diecdj66oa1fd diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.tscn b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.tscn new file mode 100644 index 00000000..89c92651 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.tscn @@ -0,0 +1,29 @@ +[gd_scene load_steps=3 format=3 uid="uid://cchlfqbh0djdn"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.gd" id="1_u4dlj"] +[ext_resource type="PackedScene" uid="uid://b510d4yme5xtx" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/create_material_dialog.tscn" id="2_adfk6"] + +[node name="MatGroupTree" type="Tree"] +unique_name_in_owner = true +columns = 2 +script = ExtResource("1_u4dlj") + +[node name="PopupMenu" type="PopupMenu" parent="."] +unique_name_in_owner = true +item_count = 3 +item_0/text = "New Group" +item_0/id = 0 +item_1/text = "Delete Group" +item_1/id = 1 +item_2/text = "Rename" +item_2/id = 2 + +[node name="CreateMaterialDialog" parent="." instance=ExtResource("2_adfk6")] +unique_name_in_owner = true +visible = false + +[connection signal="button_clicked" from="." to="." method="_on_button_clicked"] +[connection signal="item_edited" from="." to="." method="_on_item_edited"] +[connection signal="item_selected" from="." to="." method="_on_item_selected"] +[connection signal="id_pressed" from="PopupMenu" to="." method="_on_popup_menu_id_pressed"] +[connection signal="create_material" from="CreateMaterialDialog" to="." method="_on_create_material_dialog_create_material"] diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd new file mode 100644 index 00000000..4e2573e7 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd @@ -0,0 +1,240 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name MaterialViewer + +#var button_group:RadioButtonGroup = RadioButtonGroup.new() + +var builder:CyclopsLevelBuilder: + get: + return builder + set(value): + if value == builder: + return + + if builder: + var ed_iface:EditorInterface = builder.get_editor_interface() + var efs:EditorFileSystem = ed_iface.get_resource_filesystem() + efs.filesystem_changed.disconnect(on_filesystem_changed) + efs.resources_reimported.disconnect(on_resources_reimported) + efs.resources_reload.disconnect(on_resources_reload) + + builder = value + %MatGroupTree.plugin = builder + + if builder: + var ed_iface:EditorInterface = builder.get_editor_interface() + var efs:EditorFileSystem = ed_iface.get_resource_filesystem() + efs.filesystem_changed.connect(on_filesystem_changed) + efs.resources_reimported.connect(on_resources_reimported) + efs.resources_reload.connect(on_resources_reload) + + reload_materials() + + +var material_groups:MaterialGroup + +var selected_material_paths:Array[String] +var material_viewer_state:MaterialViewerState = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state_res.tres") + +func on_filesystem_changed(): + #print("on_filesystem_changed") + reload_materials() + pass + +func on_resources_reimported(resources:PackedStringArray): + #print("on_resources_reimported ", resources) + pass + +func on_resources_reload(resources:PackedStringArray): + #print("on_resources_reload ", resources) + pass + +func reload_materials(): + #return + + for child in %ButtonArea.get_children(): + %ButtonArea.remove_child(child) + child.queue_free() + + if !builder: + return + + var ed_iface:EditorInterface = builder.get_editor_interface() + var efs:EditorFileSystem = ed_iface.get_resource_filesystem() + + var efsd:EditorFileSystemDirectory = efs.get_filesystem() + reload_materials_recursive(efsd) + pass + +func reload_materials_recursive(dir:EditorFileSystemDirectory): + var mat_name_filter:String = %lineEd_filter.text + + if !%MatGroupTree.is_path_visible(dir.get_path()): + return + #var vis = %MatGroupTree.is_path_visible(dir.get_path()) + #print("reload check path ", dir.get_path(), " vis ", vis) + #get_hidden_directories() + + var ed_iface:EditorInterface = builder.get_editor_interface() + var res_prev:EditorResourcePreview = ed_iface.get_resource_previewer() + + for i in dir.get_file_count(): +# dir.get_file(i) + var type:String = dir.get_file_type(i) + #"StandardMaterial3D" + if type == "StandardMaterial3D" || type == "ShaderMaterial" || type == "ORMMaterial3D": + var path:String = dir.get_file_path(i) + + if !mat_name_filter.is_empty() && !path.contains(mat_name_filter): + continue + + #print("path %s type %s" % [path, type]) + + #res_prev.queue_resource_preview(path, self, "resource_preview_callback", null) + + var bn:MaterialButton = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_button.tscn").instantiate() + bn.material_path = path + bn.plugin = builder + bn.selected = selected_material_paths.has(path) + bn.active = !selected_material_paths.is_empty() && path == selected_material_paths[-1] + #button_group.add_button(bn) + bn.apply_material.connect(func(mat_bn:MaterialButton): apply_material(mat_bn)) + bn.select_material.connect(func(mat_bn:MaterialButton, type:SelectionList.Type): select_material(mat_bn, type)) + + %ButtonArea.add_child(bn) + pass + + for i in dir.get_subdir_count(): + reload_materials_recursive(dir.get_subdir(i)) + +func apply_material(mat_bn:MaterialButton): + var cmd:CommandSetMaterial = CommandSetMaterial.new() + cmd.builder = builder + cmd.material_path = mat_bn.material_path + + var is_obj_mode:bool = builder.mode == CyclopsLevelBuilder.Mode.OBJECT + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + if is_obj_mode: + cmd.add_target(block.get_path(), block.control_mesh.get_face_indices()) + else: + var face_indices:PackedInt32Array = block.control_mesh.get_face_indices(true) + if !face_indices.is_empty(): + cmd.add_target(block.get_path(), face_indices) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + +func is_active_material(path:String): + return !selected_material_paths.is_empty() && path == selected_material_paths[-1] + +func select_material(mat_bn:MaterialButton, sel_type:SelectionList.Type): + match sel_type: + SelectionList.Type.REPLACE: + selected_material_paths = [mat_bn.material_path] + SelectionList.Type.TOGGLE: + var idx:int = selected_material_paths.find(mat_bn.material_path) + if idx >= 0: + selected_material_paths.remove_at(idx) + else: + selected_material_paths.append(mat_bn.material_path) + SelectionList.Type.RANGE: + var bn_list = %ButtonArea.get_children() + var range_from_idx:int = -1 + var range_to_idx:int = -1 + for i in bn_list.size(): + if bn_list[i] == mat_bn: + range_to_idx = i + if is_active_material(bn_list[i].material_path): + range_from_idx = i + + for i in range(range_from_idx, range_to_idx + (1 if range_from_idx < range_to_idx else -1), 1 if range_from_idx < range_to_idx else -1): + var path = bn_list[i].material_path + if selected_material_paths.has(path): + selected_material_paths.erase(path) + selected_material_paths.append(path) + + material_viewer_state.active_material_path = \ + "" if selected_material_paths.is_empty() else selected_material_paths[-1] + + #print("set sel mat: ", material_viewer_state.active_material_path) + #print("sel mat list: ", selected_material_paths) + + for bn in %ButtonArea.get_children(): + var mat_idx:int = selected_material_paths.find(bn.material_path) + if mat_idx >= 0: + if mat_idx == selected_material_paths.size() - 1: + bn.active = true + else: + bn.active = false + + bn.selected = true + + else: + bn.active = false + bn.selected = false + + + +#func resource_preview_callback(path:String, preview:Texture2D, userdata:Variant): + #pass + +# Called when the node enters the scene tree for the first time. +func _ready(): + #material_groups = MaterialGroup.new("All") + # + #reload_materials() + + + #var root:TreeItem = %Tree.create_item() + #var child1:TreeItem = %Tree.create_item(root) + #var child2:TreeItem = %Tree.create_item(root) + #var subchild1:TreeItem = %Tree.create_item(child1) + #subchild1.set_text(0, "Subchild1") + + pass + + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_line_ed_filter_text_changed(new_text): + reload_materials() + + +func _on_mat_group_tree_visiblity_changed(): + reload_materials() + + + +func _on_bn_show_unused_dirs_toggled(toggled_on): + %MatGroupTree.show_unused_dirs = toggled_on diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd.uid new file mode 100644 index 00000000..0405bcb0 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd.uid @@ -0,0 +1 @@ +uid://db31qfrjt3vdx diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.tscn b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.tscn new file mode 100644 index 00000000..8c9df53c --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.tscn @@ -0,0 +1,66 @@ +[gd_scene load_steps=3 format=3 uid="uid://denc7grw42qsu"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer.gd" id="1_nrjye"] +[ext_resource type="PackedScene" uid="uid://cchlfqbh0djdn" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_groups_tree.tscn" id="2_8hnut"] + +[node name="MaterialViewer" type="PanelContainer"] +offset_right = 523.0 +offset_bottom = 350.0 +size_flags_horizontal = 3 +size_flags_vertical = 3 +script = ExtResource("1_nrjye") + +[node name="HSplitContainer" type="HSplitContainer" parent="."] +layout_mode = 2 +split_offset = 240 + +[node name="VBoxContainer2" type="VBoxContainer" parent="HSplitContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="HSplitContainer/VBoxContainer2"] +layout_mode = 2 + +[node name="bn_show_unused_dirs" type="Button" parent="HSplitContainer/VBoxContainer2/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Show unused directories" +toggle_mode = true +button_pressed = true +text = "Show unused" + +[node name="MatGroupTree" parent="HSplitContainer/VBoxContainer2" instance=ExtResource("2_8hnut")] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="VBoxContainer" type="VBoxContainer" parent="HSplitContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="HSplitContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="HSplitContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Filter:" + +[node name="lineEd_filter" type="LineEdit" parent="HSplitContainer/VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +tooltip_text = "Filter materials" + +[node name="PanelContainer" type="PanelContainer" parent="HSplitContainer/VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="ScrollContainer" type="ScrollContainer" parent="HSplitContainer/VBoxContainer/PanelContainer"] +layout_mode = 2 + +[node name="ButtonArea" type="HFlowContainer" parent="HSplitContainer/VBoxContainer/PanelContainer/ScrollContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 + +[connection signal="toggled" from="HSplitContainer/VBoxContainer2/HBoxContainer/bn_show_unused_dirs" to="." method="_on_bn_show_unused_dirs_toggled"] +[connection signal="visiblity_changed" from="HSplitContainer/VBoxContainer2/MatGroupTree" to="." method="_on_mat_group_tree_visiblity_changed"] +[connection signal="text_changed" from="HSplitContainer/VBoxContainer/HBoxContainer/lineEd_filter" to="." method="_on_line_ed_filter_text_changed"] diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd new file mode 100644 index 00000000..116cb7b4 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd @@ -0,0 +1,32 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name MaterialViewerState + +@export var active_material_path:String: + set(value): + if active_material_path != value: + active_material_path = value + emit_changed() diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd.uid new file mode 100644 index 00000000..12e43326 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd.uid @@ -0,0 +1 @@ +uid://bg1usi17d0se7 diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state_res.tres b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state_res.tres new file mode 100644 index 00000000..79f7112b --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state_res.tres @@ -0,0 +1,7 @@ +[gd_resource type="Resource" script_class="MaterialViewerState" load_steps=2 format=3 uid="uid://cwq6b2p7f631n"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state.gd" id="1_3sifp"] + +[resource] +script = ExtResource("1_3sifp") +active_material_path = "res://materials/tiles/groundcover_green.tres" diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/radio_button_group.gd b/addons/cyclops_level_builder/docks/material_palette/material_viewer/radio_button_group.gd new file mode 100644 index 00000000..d74161d8 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/radio_button_group.gd @@ -0,0 +1,40 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name RadioButtonGroup + +var buttons:Array + +func select_button(button): + for t in buttons: + t.selected = t == button + +func add_button(button): + buttons.append(button) + +func remove_button(button): + buttons.remove_at(buttons.find(button)) + + diff --git a/addons/cyclops_level_builder/docks/material_palette/material_viewer/radio_button_group.gd.uid b/addons/cyclops_level_builder/docks/material_palette/material_viewer/radio_button_group.gd.uid new file mode 100644 index 00000000..72ea6270 --- /dev/null +++ b/addons/cyclops_level_builder/docks/material_palette/material_viewer/radio_button_group.gd.uid @@ -0,0 +1 @@ +uid://h71rx0tecec8 diff --git a/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd b/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd new file mode 100644 index 00000000..ee254c0d --- /dev/null +++ b/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd @@ -0,0 +1,93 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Control +class_name SnappingPropertiesDock + + +var builder:CyclopsLevelBuilder: + get: + return builder + set(value): + if builder == value: + return + + if builder: + builder.snapping_tool_changed.disconnect(on_snapping_tool_changed) + + builder = value + + if builder: + builder.snapping_tool_changed.connect(on_snapping_tool_changed) + +func on_snapping_tool_changed(): + update_ui() + +func update_ui(): + if builder: + var snap_tool:CyclopsSnappingSystem = builder.snapping_system + + var ed = snap_tool._get_properties_editor() + + #print("Clearing editor") + + for child in %ScrollContainer.get_children(): + %ScrollContainer.remove_child(child) + child.queue_free() + + #print("Setting editor") + if ed: + %ScrollContainer.add_child(ed) + pass + +# Called when the node enters the scene tree for the first time. +func _ready(): + update_ui() + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func set_editor(control:Control): + + for child in $ScrollContainer.get_children(): + $ScrollContainer.remove_child(child) + + if control: + $ScrollContainer.add_child(control) + +func save_state(state:Dictionary): + var substate:Dictionary = {} + state["snapping_properties"] = substate + + #substate["materials"] = material_list.duplicate() + +func load_state(state:Dictionary): + if state == null || !state.has("snapping_properties"): + return + + var substate:Dictionary = state["snapping_properties"] diff --git a/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd.uid b/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd.uid new file mode 100644 index 00000000..15e29fed --- /dev/null +++ b/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd.uid @@ -0,0 +1 @@ +uid://kp1awueycx2m diff --git a/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.tscn b/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.tscn new file mode 100644 index 00000000..a36927b5 --- /dev/null +++ b/addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=2 format=3 uid="uid://cu2hyc0pa1nh3"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/snapping_properties/snapping_properties_dock.gd" id="1_rymgk"] + +[node name="Snapping" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_rymgk") + +[node name="ScrollContainer" type="ScrollContainer" parent="."] +unique_name_in_owner = true +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd b/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd new file mode 100644 index 00000000..dfa856a9 --- /dev/null +++ b/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd @@ -0,0 +1,56 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Control +class_name ToolPropertiesDock + +var builder:CyclopsLevelBuilder + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + +func set_editor(control:Control): + for child in $ScrollContainer.get_children(): + $ScrollContainer.remove_child(child) + + if control: + $ScrollContainer.add_child(control) + +func save_state(state:Dictionary): + var substate:Dictionary = {} + state["tool_properties_dock"] = substate + + +func load_state(state:Dictionary): + if state == null || !state.has("tool_properties_dock"): + return + + var substate:Dictionary = state["tool_properties_dock"] diff --git a/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd.uid b/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd.uid new file mode 100644 index 00000000..0b4bdf64 --- /dev/null +++ b/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd.uid @@ -0,0 +1 @@ +uid://b4nq5w38a3njj diff --git a/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.tscn b/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.tscn new file mode 100644 index 00000000..3c2a250d --- /dev/null +++ b/addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=2 format=3 uid="uid://caoy37s0y5a8y"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/docks/tool_properties/tool_properties_dock.gd" id="1_7262j"] + +[node name="Tool Properties" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_7262j") + +[node name="ScrollContainer" type="ScrollContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/addons/cyclops_level_builder/handles/handle_edge.gd b/addons/cyclops_level_builder/handles/handle_edge.gd new file mode 100644 index 00000000..86da2e85 --- /dev/null +++ b/addons/cyclops_level_builder/handles/handle_edge.gd @@ -0,0 +1,40 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name HandleEdge + +var edge_index:int +#var p0:Vector3 +#var p1:Vector3 +#var p0_init:Vector3 +#var p1_init:Vector3 +#var p_ref:Vector3 #Centroid +#var p_ref_init:Vector3 +var block_path:NodePath + + +func _to_string(): +# return "%s init pos %s %s pos %s %s" % [block_path, initial_p0, initial_p1, p0, p1] + return "edge %s e_idx:%s " % [block_path, edge_index] diff --git a/addons/cyclops_level_builder/handles/handle_edge.gd.uid b/addons/cyclops_level_builder/handles/handle_edge.gd.uid new file mode 100644 index 00000000..cd5af785 --- /dev/null +++ b/addons/cyclops_level_builder/handles/handle_edge.gd.uid @@ -0,0 +1 @@ +uid://s1ct3qab32ok diff --git a/addons/cyclops_level_builder/handles/handle_face.gd b/addons/cyclops_level_builder/handles/handle_face.gd new file mode 100644 index 00000000..f6f0ae9b --- /dev/null +++ b/addons/cyclops_level_builder/handles/handle_face.gd @@ -0,0 +1,38 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name HandleFace + +var face_index:int +#var face_id:int +#var p_ref:Vector3 #Centroid +#var p_ref_init:Vector3 +var p_center:Vector3 +var block_path:NodePath + + +func _to_string(): +# return "%s init pos %s %s pos %s %s" % [block_path, initial_p0, initial_p1, p0, p1] + return "face %s idx:%s center %s" % [block_path.get_name(block_path.get_name_count() - 1), face_index, p_center] diff --git a/addons/cyclops_level_builder/handles/handle_face.gd.uid b/addons/cyclops_level_builder/handles/handle_face.gd.uid new file mode 100644 index 00000000..a1535b73 --- /dev/null +++ b/addons/cyclops_level_builder/handles/handle_face.gd.uid @@ -0,0 +1 @@ +uid://dae51i8wbm8y8 diff --git a/addons/cyclops_level_builder/handles/handle_vertex.gd b/addons/cyclops_level_builder/handles/handle_vertex.gd new file mode 100644 index 00000000..af89b775 --- /dev/null +++ b/addons/cyclops_level_builder/handles/handle_vertex.gd @@ -0,0 +1,36 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name HandleVertex + +var vertex_index:int +var position:Vector3 +#var id:int #Label to link this vertex back to whatever is being tracked +var initial_position:Vector3 +var block_path:NodePath + + +func _to_string(): + return "%s init pos %s pos %s" % [block_path, initial_position, position] diff --git a/addons/cyclops_level_builder/handles/handle_vertex.gd.uid b/addons/cyclops_level_builder/handles/handle_vertex.gd.uid new file mode 100644 index 00000000..f734217f --- /dev/null +++ b/addons/cyclops_level_builder/handles/handle_vertex.gd.uid @@ -0,0 +1 @@ +uid://bi43v6lhg8q8i diff --git a/addons/cyclops_level_builder/io/cyclops_io/buffer_archive.gd b/addons/cyclops_level_builder/io/cyclops_io/buffer_archive.gd new file mode 100644 index 00000000..41c7a1d1 --- /dev/null +++ b/addons/cyclops_level_builder/io/cyclops_io/buffer_archive.gd @@ -0,0 +1,82 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends ResourceInspector +class_name BufferArchive + +class BufferRegion extends Resource: + var builder:BufferArchive + #var index:int + var start_byte:int + var length:int + + func get_buffer()->PackedByteArray: + return builder.buffer.slice(start_byte, start_byte + length) + +var buffer:PackedByteArray +#var region_list:Array[BufferRegion] + +func store_buffer(buf:PackedByteArray)->BufferRegion: + var region:BufferRegion = BufferRegion.new() + + region.builder = self + #region.index = region_list.size() + region.start_byte = buffer.size() + region.length = buf.size() + + buffer.append_array(buf) +# buffer.resize(buffer.size() + byte_len) + + #region_list.append(region) + + return region + + +#func allocate_buffer(byte_len:int)->BufferRegion: + #var region:BufferRegion = BufferRegion.new() +# + #region.builder = self + #region.index = region_list.size() + #region.start_byte = buffer.size() + #region.length = byte_len + #buffer.resize(buffer.size() + byte_len) + # + #region_list.append(region) + # + #return region + +func to_dictionary()->Dictionary: + var result:Dictionary + + #result["regions"] = [] + #for region in region_list: + #result.region.append({ + ##"index": region.index, + #"start": region.start_byte, + #"length": region.length + #}) + + result["buffer"] = Marshalls.raw_to_base64(buffer.compress()) + + return result diff --git a/addons/cyclops_level_builder/io/cyclops_io/buffer_archive.gd.uid b/addons/cyclops_level_builder/io/cyclops_io/buffer_archive.gd.uid new file mode 100644 index 00000000..9de8b2bb --- /dev/null +++ b/addons/cyclops_level_builder/io/cyclops_io/buffer_archive.gd.uid @@ -0,0 +1 @@ +uid://doti22yi4ot1e diff --git a/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_builder.gd b/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_builder.gd new file mode 100644 index 00000000..51e44ff1 --- /dev/null +++ b/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_builder.gd @@ -0,0 +1,199 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CyclopsFileBuilder +extends RefCounted + + +var plugin:CyclopsLevelBuilder +var buffer_archive:BufferArchive = BufferArchive.new() + +var document:Dictionary +var node_indexer:ItemIndexer = ItemIndexer.new() +var object_indexer:ItemIndexer = ItemIndexer.new() +var buffer_region_indexer:ItemIndexer = ItemIndexer.new() + +var buffer_region_map:Dictionary + + +func _init(plugin:CyclopsLevelBuilder): + self.plugin = plugin + +func should_include_branch(node:Node3D)->bool: + if node is CyclopsBlock: + return true + + for child in node.get_children(): + if child is Node3D && should_include_branch(child): + return true + + return false + +func build_file(): + + var root:Node = plugin.get_editor_interface().get_edited_scene_root() + + document = { + "header": { + "exporter": "Cyclops Level Builder " + plugin.get_plugin_version(), + "version": "1.0.0" + }, + "scenes": [], + "nodes": [], + "objects": [], + "buffer_regions": [], + "buffers": [] + } + + export_scene_recursive(root) + + #var build_scene:Dictionary + #build_scene["root"] = root.name + document.scenes.append({ + "id": 0, + "root": node_indexer.get_or_create_id(root) + }) + + for id in buffer_region_map.keys(): + var region:BufferArchive.BufferRegion = buffer_region_map[id] + document.buffer_regions.append({ + "id": id, + "start": region.start_byte, + "length": region.length, + "buffer_id": 0 + }) + + document.buffers.append({ + "id": 0, + "byte_length": buffer_archive.buffer.size(), + "data_buffer": Marshalls.raw_to_base64(buffer_archive.buffer.compress()) + }) + + +func export_scene_recursive(cur_node:Node3D): + #print(str(cur_node.get_path()) + "\n") + if !should_include_branch(cur_node): + return + + var build_node:Dictionary + build_node["id"] = node_indexer.get_or_create_id(cur_node) + build_node["name"] = cur_node.name + document.nodes.append(build_node) + + if !cur_node.visible: + build_node["visible"] = cur_node.visible + if !cur_node.position.is_equal_approx(Vector3.ZERO): + build_node["translate"] = [cur_node.position.x, cur_node.position.y, cur_node.position.z] + if !cur_node.transform.basis.is_equal_approx(Basis.IDENTITY): + build_node["basis"] = [ + cur_node.basis.x.x, cur_node.basis.x.y, cur_node.basis.x.z, + cur_node.basis.y.x, cur_node.basis.y.y, cur_node.basis.y.z, + cur_node.basis.z.x, cur_node.basis.z.y, cur_node.basis.z.z + ] + + + + if cur_node is CyclopsBlock: + var obj_id:int = object_indexer.get_or_create_id(cur_node) + build_node["object"] = obj_id + + var dict:Dictionary = cur_node.export_to_cyclops_file(self) + + document.objects.append( + { + "id": obj_id, + "type": "convex_block", + "body": dict + } + ) + #export_mesh_node(cur_node) + else: +# print("children of ", cur_node.name) + + var child_ids:Array[int] + var exp_children:Array[Node3D] + for local_child in cur_node.get_children(): + if local_child is Node3D && should_include_branch(local_child): + child_ids.append(node_indexer.get_or_create_id(local_child)) + exp_children.append(local_child) + + if !child_ids.is_empty(): + build_node["children"] = child_ids + + for local_child in exp_children: + export_scene_recursive(local_child) + +func export_mesh_node(cur_node:CyclopsBlock): + if !cur_node.mesh_vector_data: + return + + var build_mesh:Dictionary + document.objects.append(build_mesh) + + build_mesh["id"] = object_indexer.get_or_create_id(cur_node) + + build_mesh["collision_type"] = Collision.Type.keys()[cur_node.collision_type] + build_mesh["collision_layer"] = cur_node.collision_layer + build_mesh["collision_mask"] = cur_node.collision_mask + + var mat_res_paths:PackedStringArray + for mat in cur_node.materials: + if mat: + mat_res_paths.append(mat.resource_path) + else: + mat_res_paths.append("") + build_mesh["materials"] = mat_res_paths + + build_mesh["mesh"] = cur_node.mesh_vector_data.to_dictionary(self) + #build_mesh["mesh"] = cur_node.mesh_vector_data.to_dictionary(self) + + +func export_byte_array(byte_data:PackedByteArray)->int: + var result:Dictionary + + var region:BufferArchive.BufferRegion = buffer_archive.store_buffer(byte_data) + var buf_id:int = buffer_region_indexer.get_or_create_id(region) + buffer_region_map[buf_id] = region +# result["data_buffer"] = region.index + return buf_id + + +func export_vector(vec:DataVector)->Dictionary: + var result:Dictionary + + result["name"] = vec.name + result["data_type"] = DataVector.DataType.keys()[vec.data_type] + #if vec.stride != 1: + #result["stride"] = vec.stride + if !vec.category.is_empty(): + result["category"] = vec.category + + var region:BufferArchive.BufferRegion = buffer_archive.store_buffer(vec.get_buffer_byte_data()) + var buf_id:int = buffer_region_indexer.get_or_create_id(region) + buffer_region_map[buf_id] = region +# result["data_buffer"] = region.index + result["data_buffer"] = buf_id + + return result + diff --git a/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_builder.gd.uid b/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_builder.gd.uid new file mode 100644 index 00000000..c2e9a712 --- /dev/null +++ b/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_builder.gd.uid @@ -0,0 +1 @@ +uid://f7wvs0nk2kj6 diff --git a/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_loader.gd b/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_loader.gd new file mode 100644 index 00000000..f89ffc27 --- /dev/null +++ b/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_loader.gd @@ -0,0 +1,209 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name CyclopsFileLoader +extends RefCounted + +class BufferRegion: + var start:int + var length:int + var buffer_id:int + +var buffer_archive:BufferArchive = BufferArchive.new() + +var buffer_map:Dictionary +var buffer_region_map:Dictionary +var object_map:Dictionary +var node_map:Dictionary +var scene_map:Dictionary + +var plugin:CyclopsLevelBuilder + +func load(root:Dictionary): + for buf_dict in root["buffers"]: + var buf_id:int = buf_dict["id"] + var buf_size:int = buf_dict["byte_length"] + var text:String = buf_dict["data_buffer"] + var zip_buf:PackedByteArray = Marshalls.base64_to_raw(text) + var buf:PackedByteArray = zip_buf.decompress(buf_size) + + var ba:BufferArchive = BufferArchive.new() + ba.buffer = buf + buffer_map[buf_id] = ba + + for reg_dict in root["buffer_regions"]: + var reg:BufferRegion = BufferRegion.new() + var id:int = reg_dict["id"] + reg.start = reg_dict["start"] + reg.length = reg_dict["length"] + reg.buffer_id = reg_dict["buffer_id"] + + buffer_region_map[id] = reg + + for obj_dict in root["objects"]: + var id:int = obj_dict["id"] + var type:String = obj_dict["type"] + var body:Dictionary = obj_dict["body"] + + var object_node + match type: + "convex_block": + object_node = load_convex_block(body) + + if object_node: + object_map[id] = object_node + + for node_dict in root["nodes"]: + var id:int = node_dict["id"] + var node:Node3D + if node_dict.has("object"): + var obj_id:int = node_dict["object"] + node = object_map[obj_id] + else: + node = Node3D.new() + + node_map[id] = node + + if node_dict.has("name"): + node.name = node_dict["name"] + + if node_dict.has("visible"): + node.visible = node_dict["visible"] + if node_dict.has("basis"): + var a:Array = node_dict["basis"] + var basis:Basis = Basis(Vector3(a[0], a[1], a[2]), Vector3(a[3], a[4], a[5]), Vector3(a[6], a[7], a[8])) + node.basis = basis + if node_dict.has("translate"): + var a:Array = node_dict["translate"] + node.position = Vector3(a[0], a[1], a[2]) + + for node_dict in root["nodes"]: + var id:int = node_dict["id"] + var node:Node3D = node_map[id] + + if node_dict.has("children"): + for child_idx in node_dict["children"]: + + var child_node:Node3D = node_map[int(child_idx)] + node.add_child(child_node) + + for scene_dict in root["scenes"]: + var id:int = scene_dict["id"] + var root_id:int = scene_dict["root"] + scene_map[id] = root_id + + +func load_convex_block(body_dict:Dictionary)->CyclopsBlock: + var block:CyclopsBlock = preload("res://addons/cyclops_level_builder/nodes/cyclops_block.gd").new() + #blocks_root.add_child(block) + #block.owner = builder.get_editor_interface().get_edited_scene_root() + #block.name = GeneralUtil.find_unique_name(blocks_root, block_name_prefix) + + block.collision_type = Collision.Type.get(body_dict["collision_type"]) + block.collision_layer = body_dict["collision_layer"] + block.collision_mask = body_dict["collision_mask"] + + for mat_res_path in body_dict["materials"]: + var res = ResourceLoader.load(mat_res_path) + block.materials.append(res) + + if body_dict.has("mesh"): + var mesh_dict:Dictionary = body_dict["mesh"] + var mesh:MeshVectorData = MeshVectorData.new() + mesh.num_vertices = mesh_dict["num_vertices"] + mesh.num_edges = mesh_dict["num_edges"] + mesh.num_faces = mesh_dict["num_faces"] + mesh.num_face_vertices = mesh_dict["num_face_vertices"] + mesh.active_vertex = mesh_dict["active_vertex"] + mesh.active_edge = mesh_dict["active_edge"] + mesh.active_face = mesh_dict["active_face"] + mesh.active_face_vertex = mesh_dict["active_face_vertex"] + + mesh.edge_vertex_indices = load_buffer(mesh_dict["edge_vertex_index_buffer"]).to_int32_array() + mesh.edge_face_indices = load_buffer(mesh_dict["edge_face_index_buffer"]).to_int32_array() + mesh.face_vertex_count = load_buffer(mesh_dict["face_vertex_count_buffer"]).to_int32_array() + mesh.face_vertex_indices = load_buffer(mesh_dict["face_vertex_index_buffer"]).to_int32_array() + + for vec_dict in mesh_dict["vectors"]["vertices"]: + var vec:DataVector = load_data_vector(vec_dict) + mesh.vertex_data[vec.name] = vec + + for vec_dict in mesh_dict["vectors"]["edges"]: + var vec:DataVector = load_data_vector(vec_dict) + mesh.edge_data[vec.name] = vec + + for vec_dict in mesh_dict["vectors"]["faces"]: + var vec:DataVector = load_data_vector(vec_dict) + mesh.face_data[vec.name] = vec + + for vec_dict in mesh_dict["vectors"]["face_vertices"]: + var vec:DataVector = load_data_vector(vec_dict) + mesh.face_vertex_data[vec.name] = vec + + block.mesh_vector_data = mesh + + return block + +#enum DataType { BOOL, INT, FLOAT, STRING, COLOR, VECTOR2, VECTOR3, VECTOR4, TRANSFORM_2D, TRANSFORM_3D } + +func load_data_vector(vec_dict)->DataVector: + match vec_dict["data_type"]: + "BOOL": + var buf:PackedByteArray = load_buffer(vec_dict["data_buffer"]) + return DataVectorByte.new(vec_dict["name"], buf, DataVector.DataType.BOOL) + "INT": + var buf:PackedInt32Array = load_buffer(vec_dict["data_buffer"]).to_int32_array() + return DataVectorInt.new(vec_dict["name"], buf, DataVector.DataType.INT) + "FLOAT": + var buf:PackedFloat32Array = load_buffer(vec_dict["data_buffer"]).to_float32_array() + return DataVectorFloat.new(vec_dict["name"], buf, DataVector.DataType.FLOAT) + "STRING": + var buf:PackedStringArray = bytes_to_var(load_buffer(vec_dict["data_buffer"])) + return DataVectorString.new(vec_dict["name"], buf, DataVector.DataType.STRING) + "COLOR": + var buf:PackedFloat32Array = load_buffer(vec_dict["data_buffer"]).to_float32_array() + return DataVectorFloat.new(vec_dict["name"], buf, DataVector.DataType.COLOR) + "TRANSFORM_2D": + var buf:PackedFloat32Array = load_buffer(vec_dict["data_buffer"]).to_float32_array() + return DataVectorFloat.new(vec_dict["name"], buf, DataVector.DataType.TRANSFORM_2D) + "TRANSFORM_3D": + var buf:PackedFloat32Array = load_buffer(vec_dict["data_buffer"]).to_float32_array() + return DataVectorFloat.new(vec_dict["name"], buf, DataVector.DataType.TRANSFORM_3D) + "VECTOR2": + var buf:PackedFloat32Array = load_buffer(vec_dict["data_buffer"]).to_float32_array() + return DataVectorFloat.new(vec_dict["name"], buf, DataVector.DataType.VECTOR2) + "VECTOR3": + var buf:PackedFloat32Array = load_buffer(vec_dict["data_buffer"]).to_float32_array() + return DataVectorFloat.new(vec_dict["name"], buf, DataVector.DataType.VECTOR3) + "VECTOR4": + var buf:PackedFloat32Array = load_buffer(vec_dict["data_buffer"]).to_float32_array() + return DataVectorFloat.new(vec_dict["name"], buf, DataVector.DataType.VECTOR4) + _: + return null + + +func load_buffer(buf_id:int)->PackedByteArray: + var buf_reg:BufferRegion = buffer_region_map[buf_id] + var buf_src:BufferArchive = buffer_map[buf_reg.buffer_id] + return buf_src.buffer.slice(buf_reg["start"], buf_reg["start"] + buf_reg["length"]) diff --git a/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_loader.gd.uid b/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_loader.gd.uid new file mode 100644 index 00000000..a0c378d2 --- /dev/null +++ b/addons/cyclops_level_builder/io/cyclops_io/cyclops_file_loader.gd.uid @@ -0,0 +1 @@ +uid://pidpyykaq8o3 diff --git a/addons/cyclops_level_builder/io/cyclops_io/item_indexer.gd b/addons/cyclops_level_builder/io/cyclops_io/item_indexer.gd new file mode 100644 index 00000000..715ac0c7 --- /dev/null +++ b/addons/cyclops_level_builder/io/cyclops_io/item_indexer.gd @@ -0,0 +1,36 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name ItemIndexer +extends RefCounted + +var dict:Dictionary + +func get_or_create_id(node:Variant)->int: + if dict.has(node): + return dict[node] + + var id:int = dict.size() + dict[node] = id + return id diff --git a/addons/cyclops_level_builder/io/cyclops_io/item_indexer.gd.uid b/addons/cyclops_level_builder/io/cyclops_io/item_indexer.gd.uid new file mode 100644 index 00000000..eb4e0c5d --- /dev/null +++ b/addons/cyclops_level_builder/io/cyclops_io/item_indexer.gd.uid @@ -0,0 +1 @@ +uid://bval324hhu4qq diff --git a/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd b/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd new file mode 100644 index 00000000..de2fcd02 --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd @@ -0,0 +1,85 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Window +class_name ExporterCyclopsWizard + +var file_dialog:FileDialog +var save_path:String + +var plugin:CyclopsLevelBuilder + +# Called when the node enters the scene tree for the first time. +func _ready(): + file_dialog = FileDialog.new() + add_child(file_dialog) + file_dialog.size = Vector2(600, 400) + file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE + file_dialog.set_access(FileDialog.ACCESS_RESOURCES) + file_dialog.title = "Save file..." + file_dialog.filters = PackedStringArray(["*.cyclops; Cyclops files"]) + file_dialog.current_file = save_path + file_dialog.file_selected.connect(on_save_file) + + %lineEdit_path.text = save_path + #_text_path = %lineEdit_path + #_text_path.text = save_path + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func on_save_file(path:String): + save_path = path + %lineEdit_path.text = path + +func _on_bn_browse_pressed(): + file_dialog.popup_centered() + + +func _on_bn_cancel_pressed(): + hide() + + +func _on_close_requested(): + hide() + + +func _on_bn_okay_pressed(): + var path:String = save_path + if !save_path.to_lower().ends_with(".cyclops"): + path = save_path + ".cyclops" + + var cyclops_file_builder:CyclopsFileBuilder = CyclopsFileBuilder.new(plugin) + + cyclops_file_builder.build_file() + + var text = JSON.stringify(cyclops_file_builder.document, " ", false) + + var file:FileAccess = FileAccess.open(path, FileAccess.WRITE) + file.store_string(text) + + hide() diff --git a/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd.uid b/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd.uid new file mode 100644 index 00000000..fe8a4e88 --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd.uid @@ -0,0 +1 @@ +uid://chwbqveh3d6kn diff --git a/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.tscn b/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.tscn new file mode 100644 index 00000000..018342b2 --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.tscn @@ -0,0 +1,60 @@ +[gd_scene load_steps=3 format=3 uid="uid://bxmmf4lvpqtvr"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/io/exporter/exporter_cyclops_wizard.gd" id="1_107gl"] + +[sub_resource type="Theme" id="Theme_5yuos"] +MarginContainer/constants/margin_bottom = 10 +MarginContainer/constants/margin_left = 10 +MarginContainer/constants/margin_right = 10 +MarginContainer/constants/margin_top = 10 + +[node name="Window" type="Window"] +position = Vector2i(0, 36) +size = Vector2i(600, 100) +script = ExtResource("1_107gl") + +[node name="MarginContainer" type="MarginContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = SubResource("Theme_5yuos") + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Path +" + +[node name="lineEdit_path" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="bn_browse" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Browse" +text = "..." + +[node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 + +[node name="bn_okay" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Okay" + +[node name="bn_cancel" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Cancel" + +[connection signal="close_requested" from="." to="." method="_on_close_requested"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer/bn_browse" to="." method="_on_bn_browse_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/bn_okay" to="." method="_on_bn_okay_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/bn_cancel" to="." method="_on_bn_cancel_pressed"] diff --git a/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd b/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd new file mode 100644 index 00000000..95ccca59 --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd @@ -0,0 +1,167 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Window +class_name ExporterGltfWizard + +#@onready var _text_path:LineEdit = $VBoxContainer/HBoxContainer/text_path +#var _text_path:LineEdit + +var file_dialog:FileDialog +var save_path:String + +var plugin:CyclopsLevelBuilder + + + +# Called when the node enters the scene tree for the first time. +func _ready(): + + file_dialog = FileDialog.new() + add_child(file_dialog) + file_dialog.size = Vector2(600, 400) + file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE + file_dialog.set_access(FileDialog.ACCESS_FILESYSTEM) + file_dialog.title = "Export scene..." + file_dialog.filters = PackedStringArray(["*.gltf; glTF files"]) + file_dialog.current_file = save_path + file_dialog.file_selected.connect(on_save_file) + +# _text_path = $VBoxContainer/HBoxContainer/lineEdit_path + #var hh = get_node("VBoxContainer") + #var children = get_children() + + +# _text_path = get_node("VBoxContainer/HBoxContainer/lineEdit_path") + %lineEdit_path.text = save_path + #_text_path = %lineEdit_path + #_text_path.text = save_path + + +func on_save_file(path:String): + save_path = path + %lineEdit_path.text = path + +func _on_bn_browse_pressed(): + file_dialog.popup_centered() + +func branch_is_valid(node:Node)->bool: + if node is CyclopsBlock || (%check_markers.button_pressed && node is Marker3D): + return true + + for child in node.get_children(): + if child is Node3D and branch_is_valid(child): + return true + + return false + + +func clean_branch(node:Node3D)->Node3D: + if node is CyclopsBlock: + var block:CyclopsBlock = node + var new_mesh_node:MeshInstance3D = block.mesh_instance.duplicate() + new_mesh_node.name = block.mesh_instance.name + + var new_node:Node3D = Node3D.new() + new_node.name = node.name + new_node.transform = node.transform + new_node.add_child(new_mesh_node) + return new_node + + elif node is Marker3D: + var new_node:Marker3D = node.duplicate() + return new_node + + else: + var new_node:Node3D = Node3D.new() + new_node.transform = node.transform + new_node.name = node.name + for child in node.get_children(): + if branch_is_valid(child): + new_node.add_child(clean_branch(child)) + return new_node + + +func search_nodes_flat(node:Node, root:Node3D): +# print("searching %s" % node.name) + + if node is CyclopsBlock: + #print("exporting block %s" % node.name) + var block:CyclopsBlock = node + var new_mesh_node:MeshInstance3D = block.mesh_instance.duplicate() + new_mesh_node.name = block.name + + root.add_child(new_mesh_node) + new_mesh_node.global_transform = block.mesh_instance.global_transform + + elif node is Marker3D: + if %check_markers.button_pressed: + var new_node:Marker3D = Marker3D.new() + new_node.name = node.name + + root.add_child(new_node) + new_node.global_transform = node.global_transform + + + for child in node.get_children(): + search_nodes_flat(child, root) + + + +func clean_flat(node:Node3D)->Node3D: + #print("clean_flat") + var root:Node3D = Node3D.new() + root.name = "CyclopsScene" + + for child in node.get_children(): + #print("rpt chjild %s" % child.name) + search_nodes_flat(child, root) + + return root + + +func _on_bn_okay_pressed(): + + var path:String = save_path + if !save_path.to_lower().ends_with(".gltf") && !save_path.to_lower().ends_with(".glb"): + path = save_path + ".gltf" + + + var doc:GLTFDocument = GLTFDocument.new() + var state:GLTFState = GLTFState.new() + var root:Node = plugin.get_editor_interface().get_edited_scene_root() + var root_clean:Node3D = clean_flat(root) if %check_flatten.button_pressed else clean_branch(root) + + doc.append_from_scene(root_clean, state) + doc.write_to_filesystem(state, path) + + hide() + + +func _on_bn_cancel_pressed(): + hide() + + +func _on_close_requested(): + hide() diff --git a/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd.uid b/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd.uid new file mode 100644 index 00000000..86972125 --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd.uid @@ -0,0 +1 @@ +uid://dwo5sdvcmfutq diff --git a/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.tscn b/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.tscn new file mode 100644 index 00000000..7577b9d5 --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.tscn @@ -0,0 +1,75 @@ +[gd_scene load_steps=3 format=3 uid="uid://ct2mftn2hge7k"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/io/exporter/exporter_gltf_wizard.gd" id="1_asb2l"] + +[sub_resource type="Theme" id="Theme_pvimd"] +MarginContainer/constants/margin_bottom = 10 +MarginContainer/constants/margin_left = 10 +MarginContainer/constants/margin_right = 10 +MarginContainer/constants/margin_top = 10 + +[node name="Window" type="Window"] +title = "Gltf Wizard" +position = Vector2i(0, 36) +size = Vector2i(400, 150) +script = ExtResource("1_asb2l") + +[node name="MarginContainer" type="MarginContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = SubResource("Theme_pvimd") + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="check_flatten" type="CheckBox" parent="MarginContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "If unchecked, the scene heierarchy will be refelected in the exported nodes. Otherwise all nodes will be children of the root." +button_pressed = true +text = "Flatten" + +[node name="check_markers" type="CheckBox" parent="MarginContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Include Marker3Ds in export." +button_pressed = true +text = "Markers" + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Path +" + +[node name="lineEdit_path" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="bn_browse" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Browse" +text = "..." + +[node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 + +[node name="bn_okay" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Okay" + +[node name="bn_cancel" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Cancel" + +[connection signal="close_requested" from="." to="." method="_on_close_requested"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer/bn_browse" to="." method="_on_bn_browse_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/bn_okay" to="." method="_on_bn_okay_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/bn_cancel" to="." method="_on_bn_cancel_pressed"] diff --git a/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd b/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd new file mode 100644 index 00000000..45fa5701 --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd @@ -0,0 +1,155 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Window +class_name ExporterGodotSceneWizard + +#var _text_path:LineEdit +var default_material:Material = preload("res://addons/cyclops_level_builder/materials/grid.tres") + +var file_dialog:FileDialog +var save_path:String + +var plugin:CyclopsLevelBuilder + +# Called when the node enters the scene tree for the first time. +func _ready(): + file_dialog = FileDialog.new() + add_child(file_dialog) + file_dialog.size = Vector2(600, 400) + file_dialog.file_mode = FileDialog.FILE_MODE_SAVE_FILE + file_dialog.set_access(FileDialog.ACCESS_RESOURCES) + file_dialog.title = "Export scene..." + file_dialog.filters = PackedStringArray(["*.tscn; tscn files"]) + file_dialog.current_file = save_path + file_dialog.file_selected.connect(on_save_file) + + %lineEdit_path.text = save_path + #_text_path = %lineEdit_path + #_text_path.text = save_path + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func on_save_file(path:String): + save_path = path + %lineEdit_path.text = path + +func _on_bn_browse_pressed(): + file_dialog.popup_centered() + + +func _on_bn_cancel_pressed(): + hide() + + +func _on_close_requested(): + hide() + + +func _on_bn_okay_pressed(): + var path:String = save_path + if !save_path.to_lower().ends_with(".tscn") && !save_path.to_lower().ends_with(".tscn"): + path = save_path + ".tscn" + + var root:Node = plugin.get_editor_interface().get_edited_scene_root() + #var dup_node:Node = copy_scene_recursive(root) + var dup_node:Node = root.duplicate() + await get_tree().process_frame + + replace_blocks_recursive(dup_node, dup_node) + #dup_node.name = "aaaaaaa" + + var dup_scene:PackedScene = PackedScene.new() + dup_scene.pack(dup_node) + ResourceSaver.save(dup_scene, path) + + hide() + +func replace_blocks_recursive(node:Node, root:Node): + + for child in node.get_children(): + #print("child.name ", child.name) + + if child is CyclopsBlock: + var child_block:CyclopsBlock = child + + var new_child:Node3D = Node3D.new() + child.add_sibling(new_child) + new_child.owner = root + new_child.transform = child_block.transform + new_child.set_display_folded(true) + + #Mesh + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(child_block.mesh_vector_data) + + var mesh:ArrayMesh = vol.create_mesh(child_block.materials, default_material) + + var mesh_instance:MeshInstance3D = MeshInstance3D.new() + new_child.add_child(mesh_instance) + mesh_instance.owner = root + mesh_instance.mesh = mesh + mesh_instance.name = "mesh_instance" + + #Collision + var collision_body:PhysicsBody3D + + match child_block.collision_type: + Collision.Type.STATIC: + collision_body = StaticBody3D.new() + Collision.Type.KINEMATIC: + collision_body = CharacterBody3D.new() + Collision.Type.RIGID: + collision_body = RigidBody3D.new() + + if collision_body: + collision_body.collision_layer = child_block.collision_layer + collision_body.collision_mask = child_block.collision_mask + new_child.add_child(collision_body) + collision_body.owner = root + collision_body.name = "collision_body" + + var collision_shape:CollisionShape3D = CollisionShape3D.new() + collision_body.add_child(collision_shape) + collision_shape.owner = root + + var shape:ConvexPolygonShape3D = ConvexPolygonShape3D.new() + shape.points = vol.get_points() + collision_shape.shape = shape + collision_shape.name = "collision_shape" + + var child_name:String = child.name + node.remove_child(child) + child.queue_free() + new_child.name = child_name + + else: + replace_blocks_recursive(child, root) + + + diff --git a/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd.uid b/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd.uid new file mode 100644 index 00000000..8c00854e --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd.uid @@ -0,0 +1 @@ +uid://bo4eisoyofjlr diff --git a/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.tscn b/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.tscn new file mode 100644 index 00000000..d1863e12 --- /dev/null +++ b/addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.tscn @@ -0,0 +1,61 @@ +[gd_scene load_steps=3 format=3 uid="uid://bqmvfbarjmc7c"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/io/exporter/exporter_godot_scene_wizard.gd" id="1_khuso"] + +[sub_resource type="Theme" id="Theme_3em6s"] +MarginContainer/constants/margin_bottom = 10 +MarginContainer/constants/margin_left = 10 +MarginContainer/constants/margin_right = 10 +MarginContainer/constants/margin_top = 10 + +[node name="Window" type="Window"] +title = "Export as Scene" +position = Vector2i(0, 36) +size = Vector2i(600, 100) +script = ExtResource("1_khuso") + +[node name="MarginContainer" type="MarginContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = SubResource("Theme_3em6s") + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Path +" + +[node name="lineEdit_path" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="bn_browse" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Browse" +text = "..." + +[node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 + +[node name="bn_okay" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Okay" + +[node name="bn_cancel" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Cancel" + +[connection signal="close_requested" from="." to="." method="_on_close_requested"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer/bn_browse" to="." method="_on_bn_browse_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/bn_okay" to="." method="_on_bn_okay_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/bn_cancel" to="." method="_on_bn_cancel_pressed"] diff --git a/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd b/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd new file mode 100644 index 00000000..47a669a6 --- /dev/null +++ b/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd @@ -0,0 +1,82 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Window +class_name ImporterCyclopsFileWizard + +#var _text_path:LineEdit +var default_material:Material = preload("res://addons/cyclops_level_builder/materials/grid.tres") + +var file_dialog:FileDialog +var file_path:String + +var plugin:CyclopsLevelBuilder + +# Called when the node enters the scene tree for the first time. +func _ready(): + file_dialog = FileDialog.new() + add_child(file_dialog) + file_dialog.size = Vector2(600, 400) + file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE + file_dialog.set_access(FileDialog.ACCESS_RESOURCES) + file_dialog.title = "Import scene..." + file_dialog.filters = PackedStringArray(["*.cyclops; Cyclops files"]) + file_dialog.current_file = file_path + file_dialog.file_selected.connect(on_open_file) + + %lineEdit_path.text = file_path + +func on_open_file(path:String): + file_path = path + %lineEdit_path.text = path + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_bn_browse_pressed(): + file_dialog.popup_centered() + + +func _on_close_requested(): + hide() + + +func _on_bn_cancel_pressed(): + hide() + +func _on_bn_okay_pressed(): + var editor_scene_root:Node = plugin.get_editor_interface().get_edited_scene_root() + + var cmd:CommandImportCyclopsFile = CommandImportCyclopsFile.new() + cmd.builder = plugin + cmd.file_path = file_path + cmd.target_parent = editor_scene_root.get_path() + + var undo:EditorUndoRedoManager = plugin.get_undo_redo() + cmd.add_to_undo_manager(undo) + + + hide() diff --git a/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd.uid b/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd.uid new file mode 100644 index 00000000..e3727f42 --- /dev/null +++ b/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd.uid @@ -0,0 +1 @@ +uid://ca7qet6nfg6m0 diff --git a/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.tscn b/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.tscn new file mode 100644 index 00000000..f49b29ef --- /dev/null +++ b/addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.tscn @@ -0,0 +1,59 @@ +[gd_scene load_steps=3 format=3 uid="uid://bl2ohfqvxwjke"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/io/importer/importer_cyclops_file_wizard.gd" id="1_sehb5"] + +[sub_resource type="Theme" id="Theme_jvbwn"] +MarginContainer/constants/margin_bottom = 10 +MarginContainer/constants/margin_left = 10 +MarginContainer/constants/margin_right = 10 +MarginContainer/constants/margin_top = 10 + +[node name="ImporterCyclopsFileWizard" type="Window"] +size = Vector2i(600, 100) +script = ExtResource("1_sehb5") + +[node name="MarginContainer" type="MarginContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme = SubResource("Theme_jvbwn") + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Path +" + +[node name="lineEdit_path" type="LineEdit" parent="MarginContainer/VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="bn_browse" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer"] +layout_mode = 2 +tooltip_text = "Browse" +text = "..." + +[node name="HBoxContainer2" type="HBoxContainer" parent="MarginContainer/VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 + +[node name="bn_okay" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Okay" + +[node name="bn_cancel" type="Button" parent="MarginContainer/VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Cancel" + +[connection signal="close_requested" from="." to="." method="_on_close_requested"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer/bn_browse" to="." method="_on_bn_browse_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/bn_okay" to="." method="_on_bn_okay_pressed"] +[connection signal="pressed" from="MarginContainer/VBoxContainer/HBoxContainer2/bn_cancel" to="." method="_on_bn_cancel_pressed"] diff --git a/addons/cyclops_level_builder/materials/gizmo_axis_selected_material.tres b/addons/cyclops_level_builder/materials/gizmo_axis_selected_material.tres new file mode 100644 index 00000000..eb18fbe3 --- /dev/null +++ b/addons/cyclops_level_builder/materials/gizmo_axis_selected_material.tres @@ -0,0 +1,6 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://cfcmrftwleii6"] + +[resource] +no_depth_test = true +shading_mode = 0 +albedo_color = Color(1, 1, 0, 1) diff --git a/addons/cyclops_level_builder/materials/gizmo_axis_special_material.tres b/addons/cyclops_level_builder/materials/gizmo_axis_special_material.tres new file mode 100644 index 00000000..000ee8b0 --- /dev/null +++ b/addons/cyclops_level_builder/materials/gizmo_axis_special_material.tres @@ -0,0 +1,7 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://cqvh1j2n71fej"] + +[resource] +cull_mode = 2 +no_depth_test = true +shading_mode = 0 +fixed_size = true diff --git a/addons/cyclops_level_builder/materials/gizmo_axis_x_material.tres b/addons/cyclops_level_builder/materials/gizmo_axis_x_material.tres new file mode 100644 index 00000000..5508439d --- /dev/null +++ b/addons/cyclops_level_builder/materials/gizmo_axis_x_material.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://drodm0wf41vin"] + +[resource] +cull_mode = 2 +no_depth_test = true +shading_mode = 0 +albedo_color = Color(1, 0, 0, 1) +fixed_size = true diff --git a/addons/cyclops_level_builder/materials/gizmo_axis_y_material.tres b/addons/cyclops_level_builder/materials/gizmo_axis_y_material.tres new file mode 100644 index 00000000..7ea359d8 --- /dev/null +++ b/addons/cyclops_level_builder/materials/gizmo_axis_y_material.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://bv4k8o22vl6ub"] + +[resource] +cull_mode = 2 +no_depth_test = true +shading_mode = 0 +albedo_color = Color(0, 1, 0, 1) +fixed_size = true diff --git a/addons/cyclops_level_builder/materials/gizmo_axis_z_material.tres b/addons/cyclops_level_builder/materials/gizmo_axis_z_material.tres new file mode 100644 index 00000000..13229935 --- /dev/null +++ b/addons/cyclops_level_builder/materials/gizmo_axis_z_material.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://divsg4lq712rw"] + +[resource] +cull_mode = 2 +no_depth_test = true +shading_mode = 0 +albedo_color = Color(0, 0, 1, 1) +fixed_size = true diff --git a/addons/cyclops_level_builder/materials/grid.tres b/addons/cyclops_level_builder/materials/grid.tres new file mode 100644 index 00000000..ee804922 --- /dev/null +++ b/addons/cyclops_level_builder/materials/grid.tres @@ -0,0 +1,10 @@ +[gd_resource type="StandardMaterial3D" load_steps=3 format=3 uid="uid://rdhrhgrb78ls"] + +[ext_resource type="Texture2D" uid="uid://bnlqi20ay4vs1" path="res://addons/cyclops_level_builder/art/textures/grid_cell2.png" id="1_17wu6"] +[ext_resource type="Texture2D" uid="uid://b78mg60xhic6n" path="res://addons/cyclops_level_builder/art/textures/checkerboard.png" id="1_ldry2"] + +[resource] +vertex_color_use_as_albedo = true +albedo_texture = ExtResource("1_ldry2") +roughness_texture = ExtResource("1_17wu6") +texture_filter = 5 diff --git a/addons/cyclops_level_builder/materials/outline_material.tres b/addons/cyclops_level_builder/materials/outline_material.tres new file mode 100644 index 00000000..fc4196a8 --- /dev/null +++ b/addons/cyclops_level_builder/materials/outline_material.tres @@ -0,0 +1,8 @@ +[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://kw5ymmorwkvp"] + +[ext_resource type="Shader" uid="uid://cc5tovf48xmg1" path="res://addons/cyclops_level_builder/shaders/outline_shader.tres" id="1_i1fkq"] + +[resource] +render_priority = 0 +shader = ExtResource("1_i1fkq") +shader_parameter/ColorParameter = Color(0, 0, 0, 1) diff --git a/addons/cyclops_level_builder/materials/selection_rect_material.tres b/addons/cyclops_level_builder/materials/selection_rect_material.tres new file mode 100644 index 00000000..301ae098 --- /dev/null +++ b/addons/cyclops_level_builder/materials/selection_rect_material.tres @@ -0,0 +1,9 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://c4vils431vd0v"] + +[resource] +cull_mode = 2 +depth_draw_mode = 2 +no_depth_test = true +albedo_color = Color(0, 0, 0, 1) +emission_enabled = true +emission = Color(0.380392, 0.764706, 0.87451, 1) diff --git a/addons/cyclops_level_builder/materials/test_materials.tscn b/addons/cyclops_level_builder/materials/test_materials.tscn new file mode 100644 index 00000000..0efea494 --- /dev/null +++ b/addons/cyclops_level_builder/materials/test_materials.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=4 format=3 uid="uid://4ak07b64jmrq"] + +[sub_resource type="BoxMesh" id="BoxMesh_5fbgh"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_0nsw5"] +no_depth_test = true +albedo_color = Color(1, 0.141176, 1, 1) + +[sub_resource type="BoxMesh" id="BoxMesh_8rhcf"] +material = SubResource("StandardMaterial3D_0nsw5") + +[node name="Node3D" type="Node3D"] + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +mesh = SubResource("BoxMesh_5fbgh") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1.03827, 0, 1.15165) +mesh = SubResource("BoxMesh_8rhcf") diff --git a/addons/cyclops_level_builder/materials/tool_edit_active_fill_material.tres b/addons/cyclops_level_builder/materials/tool_edit_active_fill_material.tres new file mode 100644 index 00000000..aa77626f --- /dev/null +++ b/addons/cyclops_level_builder/materials/tool_edit_active_fill_material.tres @@ -0,0 +1,9 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://dv5gwbhe5pg64"] + +[resource] +render_priority = 1 +transparency = 1 +albedo_color = Color(0, 0, 0, 0.0627451) +emission_enabled = true +emission = Color(1, 1, 1, 1) +grow_amount = 0.1 diff --git a/addons/cyclops_level_builder/materials/tool_edit_active_material.tres b/addons/cyclops_level_builder/materials/tool_edit_active_material.tres new file mode 100644 index 00000000..2472241e --- /dev/null +++ b/addons/cyclops_level_builder/materials/tool_edit_active_material.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://dneusleqxicge"] + +[resource] +render_priority = 1 +albedo_color = Color(0, 0, 0, 1) +emission_enabled = true +emission = Color(1, 1, 1, 1) +grow_amount = 0.1 diff --git a/addons/cyclops_level_builder/materials/tool_edit_selected_fill_material.tres b/addons/cyclops_level_builder/materials/tool_edit_selected_fill_material.tres new file mode 100644 index 00000000..cc823090 --- /dev/null +++ b/addons/cyclops_level_builder/materials/tool_edit_selected_fill_material.tres @@ -0,0 +1,9 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://b20sku4kdojbr"] + +[resource] +render_priority = 1 +transparency = 1 +albedo_color = Color(0, 0, 0, 0.0627451) +emission_enabled = true +emission = Color(1, 0.466667, 0.109804, 1) +grow_amount = 0.1 diff --git a/addons/cyclops_level_builder/materials/tool_edit_selected_material.tres b/addons/cyclops_level_builder/materials/tool_edit_selected_material.tres new file mode 100644 index 00000000..d634b72e --- /dev/null +++ b/addons/cyclops_level_builder/materials/tool_edit_selected_material.tres @@ -0,0 +1,9 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://cmr7csndcasyp"] + +[resource] +render_priority = 1 +transparency = 4 +albedo_color = Color(0, 0, 0, 1) +emission_enabled = true +emission = Color(1, 0.466667, 0.109804, 1) +grow_amount = 0.1 diff --git a/addons/cyclops_level_builder/materials/tool_edit_unselected_material.tres b/addons/cyclops_level_builder/materials/tool_edit_unselected_material.tres new file mode 100644 index 00000000..ffaca441 --- /dev/null +++ b/addons/cyclops_level_builder/materials/tool_edit_unselected_material.tres @@ -0,0 +1,8 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://ff2cjjfaaqfb"] + +[resource] +render_priority = 1 +transparency = 4 +albedo_color = Color(0, 0, 0, 1) +emission_enabled = true +grow_amount = 0.1 diff --git a/addons/cyclops_level_builder/materials/tool_material.tres b/addons/cyclops_level_builder/materials/tool_material.tres new file mode 100644 index 00000000..48dfa0c5 --- /dev/null +++ b/addons/cyclops_level_builder/materials/tool_material.tres @@ -0,0 +1,9 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://bm85lvfgttrlj"] + +[resource] +render_priority = 1 +transparency = 4 +albedo_color = Color(0, 0, 0, 1) +emission_enabled = true +emission = Color(1, 1, 0, 1) +grow_amount = 0.1 diff --git a/addons/cyclops_level_builder/materials/tool_object_active_material.tres b/addons/cyclops_level_builder/materials/tool_object_active_material.tres new file mode 100644 index 00000000..6f666b96 --- /dev/null +++ b/addons/cyclops_level_builder/materials/tool_object_active_material.tres @@ -0,0 +1,10 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://dcr6mnkfw7mvh"] + +[resource] +render_priority = 1 +transparency = 4 +no_depth_test = true +albedo_color = Color(0, 0, 0, 1) +emission_enabled = true +emission = Color(1, 0.717647, 0.529412, 1) +grow_amount = 0.1 diff --git a/addons/cyclops_level_builder/materials/tool_object_selected_material.tres b/addons/cyclops_level_builder/materials/tool_object_selected_material.tres new file mode 100644 index 00000000..e08c7653 --- /dev/null +++ b/addons/cyclops_level_builder/materials/tool_object_selected_material.tres @@ -0,0 +1,10 @@ +[gd_resource type="StandardMaterial3D" format=3 uid="uid://bscbhmr84pnpx"] + +[resource] +render_priority = 1 +transparency = 4 +no_depth_test = true +albedo_color = Color(0, 0, 0, 1) +emission_enabled = true +emission = Color(1, 0.494118, 0.160784, 1) +grow_amount = 0.1 diff --git a/addons/cyclops_level_builder/materials/vertex_active_material.tres b/addons/cyclops_level_builder/materials/vertex_active_material.tres new file mode 100644 index 00000000..6ed5da9b --- /dev/null +++ b/addons/cyclops_level_builder/materials/vertex_active_material.tres @@ -0,0 +1,12 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://rtk56g3h03nt"] + +[ext_resource type="Texture2D" uid="uid://dsvcm4kvcqlru" path="res://addons/cyclops_level_builder/art/textures/vertex.png" id="1_ondel"] + +[resource] +transparency = 2 +alpha_scissor_threshold = 0.5 +alpha_antialiasing_mode = 0 +shading_mode = 0 +albedo_texture = ExtResource("1_ondel") +use_point_size = true +point_size = 8.0 diff --git a/addons/cyclops_level_builder/materials/vertex_selected_material.tres b/addons/cyclops_level_builder/materials/vertex_selected_material.tres new file mode 100644 index 00000000..30e4982b --- /dev/null +++ b/addons/cyclops_level_builder/materials/vertex_selected_material.tres @@ -0,0 +1,13 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://ba8rrvb78dmln"] + +[ext_resource type="Texture2D" uid="uid://dsvcm4kvcqlru" path="res://addons/cyclops_level_builder/art/textures/vertex.png" id="1_p0377"] + +[resource] +transparency = 2 +alpha_scissor_threshold = 0.5 +alpha_antialiasing_mode = 0 +shading_mode = 0 +albedo_color = Color(1, 0.560784, 0.341176, 1) +albedo_texture = ExtResource("1_p0377") +use_point_size = true +point_size = 8.0 diff --git a/addons/cyclops_level_builder/materials/vertex_tool_material.tres b/addons/cyclops_level_builder/materials/vertex_tool_material.tres new file mode 100644 index 00000000..39f9f308 --- /dev/null +++ b/addons/cyclops_level_builder/materials/vertex_tool_material.tres @@ -0,0 +1,13 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://slp88hyjpj6v"] + +[ext_resource type="Texture2D" uid="uid://dsvcm4kvcqlru" path="res://addons/cyclops_level_builder/art/textures/vertex.png" id="1_m6fsr"] + +[resource] +transparency = 2 +alpha_scissor_threshold = 0.5 +alpha_antialiasing_mode = 0 +shading_mode = 0 +albedo_color = Color(1, 1, 0, 1) +albedo_texture = ExtResource("1_m6fsr") +use_point_size = true +point_size = 8.0 diff --git a/addons/cyclops_level_builder/materials/vertex_unselected_material.tres b/addons/cyclops_level_builder/materials/vertex_unselected_material.tres new file mode 100644 index 00000000..068ed14f --- /dev/null +++ b/addons/cyclops_level_builder/materials/vertex_unselected_material.tres @@ -0,0 +1,13 @@ +[gd_resource type="StandardMaterial3D" load_steps=2 format=3 uid="uid://dqwtka7ltyekm"] + +[ext_resource type="Texture2D" uid="uid://dsvcm4kvcqlru" path="res://addons/cyclops_level_builder/art/textures/vertex.png" id="1_a8v6v"] + +[resource] +transparency = 2 +alpha_scissor_threshold = 0.5 +alpha_antialiasing_mode = 0 +shading_mode = 0 +albedo_color = Color(0, 0, 0, 1) +albedo_texture = ExtResource("1_a8v6v") +use_point_size = true +point_size = 8.0 diff --git a/addons/cyclops_level_builder/math/clip_poly_result.gd b/addons/cyclops_level_builder/math/clip_poly_result.gd new file mode 100644 index 00000000..4e135a09 --- /dev/null +++ b/addons/cyclops_level_builder/math/clip_poly_result.gd @@ -0,0 +1,33 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name ClipPolyResult + +var polygons:Array[PackedVector3Array] +var cut_segments:Array[Segment3] + +func _init(polygons:Array[PackedVector3Array] = [], cut_segments:Array[Segment3] = []): + self.polygons = polygons + self.cut_segments = cut_segments diff --git a/addons/cyclops_level_builder/math/clip_poly_result.gd.uid b/addons/cyclops_level_builder/math/clip_poly_result.gd.uid new file mode 100644 index 00000000..04fb9a43 --- /dev/null +++ b/addons/cyclops_level_builder/math/clip_poly_result.gd.uid @@ -0,0 +1 @@ +uid://qwnwpk13hjfl diff --git a/addons/cyclops_level_builder/math/convex_volume.gd b/addons/cyclops_level_builder/math/convex_volume.gd new file mode 100644 index 00000000..0239c3ad --- /dev/null +++ b/addons/cyclops_level_builder/math/convex_volume.gd @@ -0,0 +1,1447 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name ConvexVolume + + +class VertexInfo extends RefCounted: + var index:int + var mesh:ConvexVolume + var point:Vector3 + var normal:Vector3 + var edge_indices:Array[int] = [] + var selected:bool + + func _init(mesh:ConvexVolume, point:Vector3 = Vector3.ZERO): + self.mesh = mesh + self.point = point + + func _to_string(): + var s:String = "%s [" % [point] + for i in edge_indices: + s += "%s " % i + s += "]" + + return s + +class EdgeInfo extends RefCounted: + var index:int + var mesh:ConvexVolume + var start_index:int + var end_index:int + var face_indices:Array[int] = [] + var selected:bool + + func _init(mesh:ConvexVolume, start:int = 0, end:int = 0): + self.mesh = mesh + start_index = start + end_index = end + + func get_midpoint()->Vector3: + var p0:Vector3 = mesh.vertices[start_index].point + var p1:Vector3 = mesh.vertices[end_index].point + return (p0 + p1) / 2 + + func _to_string(): + var s:String = "%s %s [" % [start_index, end_index] + for i in face_indices: + s += "%s " % i + s += "]" + return s + + +class FaceInfo extends RefCounted: + var index:int + var mesh:ConvexVolume + #@deprecated + #var id:int + var normal:Vector3 #Face normal points in direction of interior + var material_id:int + var uv_transform:Transform2D + var color:Color + var visible:bool + var selected:bool + var vertex_indices:Array[int] + var face_vertex_indices:Array[int] + var triangulation_indices:Array[int] + var lightmap_uvs:PackedVector2Array + + func _init(mesh:ConvexVolume, normal:Vector3, uv_transform:Transform2D = Transform2D.IDENTITY, material_id:int = 0, visible:bool = true, color:Color = Color.WHITE, selected:bool = false): + self.mesh = mesh + #self.id = id + self.normal = normal + self.material_id = material_id + self.uv_transform = uv_transform + self.selected = selected + self.visible = visible + self.color = color + + func get_plane()->Plane: + return Plane(normal, mesh.vertices[vertex_indices[0]].point) + + func get_points()->PackedVector3Array: + var result:PackedVector3Array + for i in vertex_indices: + result.append(mesh.vertices[i].point) + return result + + func get_centroid()->Vector3: + var points:PackedVector3Array = get_points() + var center:Vector3 + for p in points: + center += p + center /= points.size() + return center + + ##Returns vector with magnitude equal to twice the area of the face and + ## pointing along the face normal + func get_area_vector_x2()->Vector3: + var points:PackedVector3Array = get_points() + return MathUtil.face_area_x2(points) + + func get_triangulation()->Array[int]: + if triangulation_indices.is_empty(): + var points:PackedVector3Array + for v_idx in vertex_indices: + points.append(mesh.vertices[v_idx].point) + +# print("start points %s" % points) + + var normal:Vector3 = MathUtil.face_area_x2(points).normalized() +# print("normal %s" % normal) + triangulation_indices = MathUtil.trianglate_face_vertex_indices(points, normal) +# print("triangulation %s" % str(triangulation_indices)) + + return triangulation_indices + + func get_trianges()->PackedVector3Array: + var indices:Array[int] = get_triangulation() + var result:PackedVector3Array + + for fv_idx in indices: + var v_idx:int = vertex_indices[fv_idx] + result.append(mesh.vertices[v_idx].point) + +# print("triangules %s" % result) + + return result + + func reverse(): + normal = -normal + vertex_indices.reverse() + triangulation_indices.clear() + + #Vertex on face closest to given point + func get_closest_vertex(point:Vector3)->int: + var best_dist:float = -1 + var best_idx:int = -1 + for v_idx in vertex_indices: + var v:VertexInfo = mesh.vertices[v_idx] + var dist:float = v.point.distance_to(point) + if best_idx == -1 || dist < best_dist: + best_idx = v_idx + best_dist = dist + + return best_idx + + + +class FaceVertexInfo extends RefCounted: + var index:int + var mesh:ConvexVolume + var face_index:int + var vertex_index:int + var vertex_local_index:int #Position of vertex within this face loop - eg, if this face has 5 verts, the local vert numbers are in order [0, 1, 2, 3, 4] + var color:Color = Color.WHITE + var normal:Vector3 + + +var vertices:Array[VertexInfo] = [] +var edges:Array[EdgeInfo] = [] +var faces:Array[FaceInfo] = [] +var face_vertices:Array[FaceVertexInfo] = [] +var face_vertex_coord_map:Dictionary + +var bounds:AABB + +var lightmap_uvs_dirty = true + +var active_vertex:int = -1 +var active_edge:int = -1 +var active_face:int = -1 +var active_face_vertex:int = -1 + +func _to_string()->String: + var result:String = "" + for v in vertices: + result += str(v.point) + ", " + return result + + +func init_block(block_bounds:AABB, uv_transform:Transform2D = Transform2D.IDENTITY, material_id:int = -1, visible:bool = true, color:Color = Color.WHITE): + var p000:Vector3 = block_bounds.position + var p111:Vector3 = block_bounds.end + var p001:Vector3 = Vector3(p000.x, p000.y, p111.z) + var p010:Vector3 = Vector3(p000.x, p111.y, p000.z) + var p011:Vector3 = Vector3(p000.x, p111.y, p111.z) + var p100:Vector3 = Vector3(p111.x, p000.y, p000.z) + var p101:Vector3 = Vector3(p111.x, p000.y, p111.z) + var p110:Vector3 = Vector3(p111.x, p111.y, p000.z) + + init_prism([p000, p001, p011, p010], p100 - p000, uv_transform, material_id, visible, color) + + +func init_prism(base_points:Array[Vector3], extrude_dir:Vector3, uv_transform:Transform2D = Transform2D.IDENTITY, material_id:int = -1, visible:bool = true, color:Color = Color.WHITE): + vertices = [] + edges = [] + faces = [] + face_vertices = [] + face_vertex_coord_map.clear() + + var base_normal = -extrude_dir.normalized() + + var face_area_x2:Vector3 = MathUtil.face_area_x2(base_points) + if face_area_x2.dot(extrude_dir) > 0: + base_points.reverse() + + for p in base_points: + var v:VertexInfo = VertexInfo.new(self, p) + v.index = vertices.size() + vertices.append(v) + for p in base_points: + var v:VertexInfo = VertexInfo.new(self, p + extrude_dir) + v.index = vertices.size() + vertices.append(v) + + var f0:FaceInfo = FaceInfo.new(self, base_normal, uv_transform, material_id, visible, color) + f0.index = faces.size() + f0.vertex_indices = [] + f0.vertex_indices.append_array(range(base_points.size())) + faces.append(f0) + var f1:FaceInfo = FaceInfo.new(self, -base_normal, uv_transform, material_id, visible, color) + f1.index = faces.size() + f1.vertex_indices = [] + f1.vertex_indices.append_array(range(base_points.size(), base_points.size() * 2)) + f1.vertex_indices.reverse() + faces.append(f1) + + + for i in base_points.size(): + var p_idx0:int = i + var p_idx1:int = wrap(i + 1, 0, base_points.size()) + + var v0:VertexInfo = vertices[p_idx0] + var v1:VertexInfo = vertices[p_idx1] + + var normal = base_normal.cross(v1.point - v0.point).normalized() + var f:FaceInfo = FaceInfo.new(self, normal, uv_transform, material_id, visible, color) + f.index = faces.size() + f.vertex_indices = [p_idx1, p_idx0, p_idx0 + base_points.size(), p_idx1 + base_points.size()] + faces.append(f) + + build_edges() + build_face_vertices() + calc_vertex_normals() + + bounds = calc_bounds() + calc_lightmap_uvs() + +func init_from_convex_block_data(data:ConvexBlockData): + #print("init_from_convex_block_data") + #print(var_to_str(data)) + + vertices = [] + edges = [] + faces = [] + face_vertices = [] + face_vertex_coord_map.clear() + + if !data: + return + #data.validate_arrays() + + active_vertex = data.active_vertex + active_edge = data.active_edge + active_face = data.active_face + + for i in data.vertex_points.size(): + var v:VertexInfo = VertexInfo.new(self, data.vertex_points[i]) + v.index = vertices.size() + vertices.append(v) + v.selected = data.vertex_selected[i] + + var num_edges:int = data.edge_vertex_indices.size() / 2 + for i in num_edges: + var edge:EdgeInfo = EdgeInfo.new(self, data.edge_vertex_indices[i * 2], data.edge_vertex_indices[i * 2 + 1]) + edge.index = edges.size() + edges.append(edge) + edge.face_indices.append(data.edge_face_indices[i * 2]) + edge.face_indices.append(data.edge_face_indices[i * 2 + 1]) + edge.selected = data.edge_selected[i] + #edge.active = data.edge_active[i] + + #print("data.face_vertex_count ", data.face_vertex_count) + var face_vertex_count:int = 0 + for face_idx in data.face_vertex_count.size(): + var num_verts:int = data.face_vertex_count[face_idx] + var vert_indices:Array[int] + var vert_points:PackedVector3Array + for i in num_verts: + var vert_idx:int = data.face_vertex_indices[face_vertex_count] + vert_indices.append(vert_idx) + vert_points.append(vertices[vert_idx].point) + face_vertex_count += 1 + + var normal = MathUtil.face_area_x2(vert_points).normalized() + + var face_uv_transform:Transform2D = data.face_uv_transform[face_idx] + var face_mat_index:int = data.face_material_indices[face_idx] + var face_visible:int = data.face_visible[face_idx] + var face_color:Color = data.face_color[face_idx] + var f:FaceInfo = FaceInfo.new(self, normal, face_uv_transform, face_mat_index, face_visible, face_color) + f.index = faces.size() + f.selected = data.face_selected[face_idx] + #f.active = data.face_active[face_idx] + f.vertex_indices = vert_indices + + faces.append(f) + + #print("faces buit ", faces.size()) + + bounds = calc_bounds() + calc_lightmap_uvs() + + #Rebuild face verticies if input data is erronious + var all_zero:bool = true + for f_idx in data.face_vertex_face_index: + if f_idx != 0: + all_zero = false + break + + if data.face_vertex_face_index.size() == 0 || all_zero: + #print("<<0>>") + #Face vertices not initialized - generate new ones + build_face_vertices() + else: + #print("<<1>>") + for fv_idx in data.face_vertex_face_index.size(): + var f_idx:int = data.face_vertex_face_index[fv_idx] + var v_idx:int = data.face_vertex_vertex_index[fv_idx] + var fv:FaceVertexInfo = FaceVertexInfo.new() + face_vertices.append(fv) + #faces[f_idx].face_vertex_indices.append(fv_idx) + + fv.face_index = f_idx + fv.vertex_index = v_idx + var coord:Vector2i = Vector2i(f_idx, v_idx) + face_vertex_coord_map[coord] = fv + + var f:FaceInfo = faces[f_idx] + fv.normal = data.face_vertex_normal[fv_idx] if data.face_vertex_normal.size() > fv_idx else f.normal + fv.color = data.face_vertex_color[fv_idx] if data.face_vertex_color.size() > fv_idx else Color(1, 1, 1, 1) + #print("init_from_convex_block_data face_vertex_coord_map ", face_vertex_coord_map) + for f_idx in faces.size(): + var face:FaceInfo = faces[f_idx] + for v_idx in face.vertex_indices: + face.face_vertex_indices.append(face_vertex_coord_map[Vector2i(f_idx, v_idx)].index) + + + calc_vertex_normals() + + #print("init_from_convex_block_data %s" % format_faces_string()) + +func init_from_mesh_vector_data(mvd:MeshVectorData): + #print("init_from_mesh_vector_data") + var block_data:ConvexBlockData = ConvexBlockData.new() + block_data.init_from_mesh_vector_data(mvd) + init_from_convex_block_data(block_data) + + +#Calc convex hull bouding points +func init_from_points(points:PackedVector3Array, uv_transform:Transform2D = Transform2D.IDENTITY, material_id:int = -1, visible:bool = true, color:Color = Color.WHITE): + vertices = [] + edges = [] + faces = [] + face_vertices = [] + face_vertex_coord_map.clear() + + #print("init_from_points %s" % points) + var hull:QuickHull.Hull = QuickHull.quickhull(points) + #print("hull %s" % hull.format_points()) + + var hull_points:Array[Vector3] = hull.get_points() + + for p in hull_points: + var v:VertexInfo = VertexInfo.new(self, p) + v.index = vertices.size() + vertices.append(v) + + for facet in hull.facets: + var plane:Plane = facet.plane + var vert_indices:Array[int] = [] + + for p in facet.points: + var vert_idx:int = hull_points.find(p) + vert_indices.append(vert_idx) + + var f:FaceInfo = FaceInfo.new(self, plane.normal, uv_transform, material_id, visible, color) + f.index = faces.size() + f.vertex_indices = vert_indices + faces.append(f) + + + build_edges() + build_face_vertices() + calc_vertex_normals() + + bounds = calc_bounds() + calc_lightmap_uvs() + +func calc_vertex_normals(smooth:bool = false): + #print("calc_vertex_normals ", _to_string()) + #print("calc_vertex_normals face_vertex_coord_map ", face_vertex_coord_map) + + for v_idx in vertices.size(): + var v:VertexInfo = vertices[v_idx] + var weighted_normal:Vector3 + + for face in faces: + if face.vertex_indices.has(v_idx): + weighted_normal += MathUtil.face_area_x2(face.get_points()) + + v.normal = weighted_normal.normalized() + + #Calc face vertices + for f_idx in faces.size(): + var face:FaceInfo = faces[f_idx] + if face.vertex_indices.has(v_idx): + var fv:FaceVertexInfo = face_vertex_coord_map[Vector2i(f_idx, v_idx)] + fv.normal = v.normal if smooth else face.normal + +func get_vertices_in_sphere(center:Vector3, radius:float)->Array[VertexInfo]: + var result:Array[VertexInfo] + for v in vertices: + var dist2 = v.point.distance_squared_to(center) + if dist2 <= radius * radius: + result.append(v) + + return result + +func get_edge(vert_idx0:int, vert_idx1:int)->EdgeInfo: + for e in edges: + if e.start_index == vert_idx0 && e.end_index == vert_idx1: + return e + if e.start_index == vert_idx1 && e.end_index == vert_idx0: + return e + return null + +func get_face_vertex(face_idx:int, vertex_idx:int)->FaceVertexInfo: + var coord:Vector2i = Vector2i(face_idx, vertex_idx) + return face_vertex_coord_map[coord] + +func build_face_vertices(): + #print("build_face_vertices") + for f_idx in faces.size(): + var face:FaceInfo = faces[f_idx] + for v_local_idx in face.vertex_indices.size(): + var v_idx = face.vertex_indices[v_local_idx] + var vert:VertexInfo = vertices[v_idx] + + var fv:FaceVertexInfo = FaceVertexInfo.new() + var fv_idx:int = face_vertices.size() + face_vertices.append(fv) + var coord:Vector2i = Vector2i(f_idx, v_idx) + #print("Storing fv ", coord) + face_vertex_coord_map[coord] = fv + fv.index = fv_idx + fv.mesh = self + fv.face_index = f_idx + fv.vertex_index = v_idx + fv.vertex_local_index = v_local_idx + fv.color = face.color + + face.face_vertex_indices.append(fv_idx) + +func build_edges(): + + #Calculate edges + for face in faces: + var num_corners = face.vertex_indices.size() + for i0 in num_corners: + var i1:int = wrap(i0 + 1, 0, num_corners) + var v0_idx:int = face.vertex_indices[i0] + var v1_idx:int = face.vertex_indices[i1] + + var edge:EdgeInfo = get_edge(v0_idx, v1_idx) + if !edge: + var edge_idx = edges.size() + edge = EdgeInfo.new(self, v0_idx, v1_idx) + edge.index = edges.size() + edges.append(edge) + + var v0:VertexInfo = vertices[v0_idx] + v0.edge_indices.append(edge_idx) + + var v1:VertexInfo = vertices[v1_idx] + v1.edge_indices.append(edge_idx) + +# edge.face_indices.append(face.id) + edge.face_indices.append(face.index) + +func get_face_coincident_with_plane(plane:Plane)->FaceInfo: + for f in faces: + var p:Plane = f.get_plane() + if p.is_equal_approx(plane): + return f + return null + +func get_face_indices(selected_only:bool = false)->PackedInt32Array: + var result:PackedInt32Array + for f_idx in faces.size(): + var f:FaceInfo = faces[f_idx] + if !selected_only || f.selected: + result.append(f_idx) + return result + +func get_trimesh_indices()->PackedInt32Array: + var result:PackedInt32Array + + for f in faces: + for fv_idx in f.get_triangulation(): + var v_idx:int = f.vertex_indices[fv_idx] + result.append(v_idx) + + return result + +func get_face_most_similar_to_plane(plane:Plane)->FaceInfo: + var best_dot:float = -1 + var best_face:FaceInfo + + for f in faces: + var p:Plane = f.get_plane() + var dot = p.normal.dot(plane.normal) + if dot >= best_dot: + best_dot = dot + best_face = f + return best_face + +func get_vertex_at_position(point:Vector3)->VertexInfo: + for v in vertices: + if v.point.is_equal_approx(point): + return v + return null + +func get_edge_at_position(point:Vector3)->EdgeInfo: + for e in edges: + if e.get_midpoint().is_equal_approx(point): + return e + return null + +func get_face_at_position(point:Vector3)->FaceInfo: + for f in faces: + if f.get_centroid().is_equal_approx(point): + return f + return null + +func copy_vertex_attributes(ref_vol:ConvexVolume): + for v_idx in vertices.size(): + var v:VertexInfo = vertices[v_idx] + var ref_v:VertexInfo = ref_vol.get_vertex_at_position(v.point) + if ref_v: + v.selected = ref_v.selected + +func copy_face_attributes(ref_vol:ConvexVolume): + for f_idx in faces.size(): + var f:FaceInfo = faces[f_idx] + var ref_face:FaceInfo = ref_vol.get_face_most_similar_to_plane(f.get_plane()) + + f.material_id = ref_face.material_id + f.uv_transform = ref_face.uv_transform + f.visible = ref_face.visible + f.color = ref_face.color + f.selected = ref_face.selected + + #Copy face vertex values + for v_local_idx in f.vertex_indices.size(): + var v_idx:int = f.vertex_indices[v_local_idx] + var v:VertexInfo = vertices[v_idx] + var fv:FaceVertexInfo = face_vertex_coord_map[Vector2i(f_idx, v_idx)] + + var v_idx_ref:int = ref_face.get_closest_vertex(v.point) + + var fv_ref:FaceVertexInfo = ref_vol.face_vertex_coord_map[Vector2i(ref_face.index, v_idx_ref)] + + fv.normal = fv_ref.normal + fv.color = fv_ref.color + +func to_convex_block_data()->ConvexBlockData: + var result:ConvexBlockData = ConvexBlockData.new() + + result.active_vertex = active_vertex + result.active_edge = active_edge + result.active_face = active_face + result.active_face_vertex = active_face_vertex + + for v in vertices: + result.vertex_points.append(v.point) + result.vertex_selected.append(v.selected) + #result.vertex_active.append(v.active) + + for e in edges: + result.edge_vertex_indices.append_array([e.start_index, e.end_index]) + result.edge_face_indices.append_array([e.face_indices[0], e.face_indices[1]]) + result.edge_selected.append(e.selected) + #result.edge_active.append(e.active) + + for face in faces: + var num_verts:int = face.vertex_indices.size() + result.face_vertex_count.append(num_verts) + result.face_vertex_indices.append_array(face.vertex_indices) + #result.face_ids.append(face.id) + result.face_selected.append(face.selected) + #result.face_active.append(face.active) + result.face_material_indices.append(face.material_id) + result.face_uv_transform.append(face.uv_transform) + result.face_visible.append(face.visible) + result.face_color.append(face.color) + + for fv_idx in face_vertices.size(): + var fv:FaceVertexInfo = face_vertices[fv_idx] + #print("to_convex_block_data fv ", fv.face_index, " ", fv.vertex_index) + result.face_vertex_face_index.append(fv.face_index) + result.face_vertex_vertex_index.append(fv.vertex_index) + result.face_vertex_normal.append(fv.normal) + result.face_vertex_color.append(fv.color) + + return result + +func to_mesh_vector_data()->MeshVectorData: + var mvd:MeshVectorData = MeshVectorData.new() + var block_data:ConvexBlockData = to_convex_block_data() + mvd.create_from_convex_block(block_data) + return mvd + +func get_face(face_index:int)->FaceInfo: + return faces[face_index] + +func get_centroid()->Vector3: + var points:PackedVector3Array = get_points() + var sum:Vector3 + for p in points: + sum += p + return sum / points.size() + +# Creates a new volume that is equal to the portion of this volume on the top +# side of the passed plane. Does not modify the geometry of this volume. +func cut_with_plane(plane:Plane, uv_transform:Transform2D = Transform2D.IDENTITY, material_id:int = 0)->ConvexVolume: +# + var planes:Array[Plane] + for f in faces: + #Top of planr should point toward interior + planes.append(MathUtil.flip_plane(f.get_plane())) + planes.append(plane) + + #print("planes %s" % GeneralUtil.format_planes_string(planes)) + + var hull_points:Array[Vector3] = MathUtil.get_convex_hull_points_from_planes(planes) + if hull_points.is_empty(): + return null + + var new_vol:ConvexVolume = ConvexVolume.new() + new_vol.init_from_points(hull_points) + + new_vol.copy_face_attributes(self) + + for f in new_vol.faces: + var f_plane:Plane = MathUtil.flip_plane(f.get_plane()) + if f_plane.is_equal_approx(plane): + f.uv_transform = uv_transform + f.material_id = material_id + break + + return new_vol + +func is_empty(): + return bounds.size.is_zero_approx() + +# Returns a new ConvexVolume equal to this volume after the plane of the +# indicated face has been translated the given offset. Does not modify the +# geometry of this volume. +func translate_face_plane(face_index:int, offset:Vector3, lock_uvs:bool = false)->ConvexVolume: + var xform:Transform3D = Transform3D(Basis.IDENTITY, -offset) + + var source_face:FaceInfo + var transformed_plane:Plane + + var planes:Array[Plane] = [] + for f in faces: + if f.index == face_index: + transformed_plane = MathUtil.flip_plane(f.get_plane()) * xform + planes.append(transformed_plane) + source_face = f + else: + planes.append(MathUtil.flip_plane(f.get_plane())) + + #print("planes %s" % str(planes)) + var hull_points:Array[Vector3] = MathUtil.get_convex_hull_points_from_planes(planes) + if hull_points.is_empty(): + return null + + var new_vol:ConvexVolume = ConvexVolume.new() + new_vol.init_from_points(hull_points) + new_vol.copy_face_attributes(self) + + return new_vol + +func translated(offset:Vector3, lock_uvs:bool = false)->ConvexVolume: + return transformed(Transform3D(Basis.IDENTITY, offset), lock_uvs) + +func translate(offset:Vector3, lock_uvs:bool = false): + transform(Transform3D(Basis.IDENTITY, offset), lock_uvs) + +func transformed(xform:Transform3D, lock_uvs:bool = false)->ConvexVolume: + var new_vol:ConvexVolume = ConvexVolume.new() + new_vol.init_from_convex_block_data(to_convex_block_data()) + new_vol.transform(xform) + return new_vol + + +func transform_uvs(xform:Transform3D): +# var xform:Transform3D = obj_xform.affine_inverse() + + for f in faces: + var axis:MathUtil.Axis = MathUtil.get_longest_axis(f.normal) + + match axis: + MathUtil.Axis.X: + var orig_p:Vector3 = xform.origin + var u_p:Vector3 = xform * Vector3(0, 0, 1) - orig_p + var v_p:Vector3 = xform * Vector3(0, 1, 0) - orig_p + var move_xform:Transform2D = Transform2D(Vector2(u_p.z, u_p.y), \ + Vector2(v_p.z, v_p.y), \ + Vector2(orig_p.z, orig_p.y)) + + f.uv_transform = f.uv_transform * move_xform + + MathUtil.Axis.Y: + var orig_p:Vector3 = xform.origin + var u_p:Vector3 = xform * Vector3(1, 0, 0) - orig_p + var v_p:Vector3 = xform * Vector3(0, 0, 1) - orig_p + var move_xform:Transform2D = Transform2D(Vector2(u_p.x, u_p.z), \ + Vector2(v_p.x, v_p.z), \ + Vector2(orig_p.x, orig_p.z)) + + f.uv_transform = f.uv_transform * move_xform + + MathUtil.Axis.Z: + #var xform_inv = xform.affine_inverse() + var orig_p:Vector3 = xform.origin + var u_p:Vector3 = xform * Vector3(1, 0, 0) - orig_p + var v_p:Vector3 = xform * Vector3(0, 1, 0) - orig_p + var move_xform:Transform2D = Transform2D(Vector2(u_p.x, u_p.y), \ + Vector2(v_p.x, v_p.y), \ + Vector2(orig_p.x, orig_p.y)) + + f.uv_transform = f.uv_transform * move_xform + + +func transform(xform:Transform3D, lock_uvs:bool = false): + for v in vertices: + v.point = xform * v.point + + if xform.basis.determinant() < 0: + for f in faces: + f.reverse() + + if lock_uvs: + + for f in faces: + var axis:MathUtil.Axis = MathUtil.get_longest_axis(f.normal) + + match axis: + MathUtil.Axis.X: + var orig_p:Vector3 = xform.origin + var u_p:Vector3 = xform * Vector3(0, 0, 1) - orig_p + var v_p:Vector3 = xform * Vector3(0, 1, 0) - orig_p + var move_xform:Transform2D = Transform2D(Vector2(u_p.z, u_p.y), \ + Vector2(v_p.z, v_p.y), \ + Vector2(orig_p.z, orig_p.y)) + + f.uv_transform = f.uv_transform * move_xform + + MathUtil.Axis.Y: + var orig_p:Vector3 = xform.origin + var u_p:Vector3 = xform * Vector3(1, 0, 0) - orig_p + var v_p:Vector3 = xform * Vector3(0, 0, 1) - orig_p + var move_xform:Transform2D = Transform2D(Vector2(u_p.x, u_p.z), \ + Vector2(v_p.x, v_p.z), \ + Vector2(orig_p.x, orig_p.z)) + + f.uv_transform = f.uv_transform * move_xform + + MathUtil.Axis.Z: + #var xform_inv = xform.affine_inverse() + var orig_p:Vector3 = xform.origin + var u_p:Vector3 = xform * Vector3(1, 0, 0) - orig_p + var v_p:Vector3 = xform * Vector3(0, 1, 0) - orig_p + var move_xform:Transform2D = Transform2D(Vector2(u_p.x, u_p.y), \ + Vector2(v_p.x, v_p.y), \ + Vector2(orig_p.x, orig_p.y)) + + f.uv_transform = f.uv_transform * move_xform + + #calc_lightmap_uvs() + +#@deprecated +#func unused_face_id()->int: + #var idx = 0 + #for p in faces: + #idx = max(idx, p.id) + #return idx + 1 + +func contains_point(point:Vector3)->bool: + for f in faces: + var plane:Plane = f.get_plane() + if !plane.has_point(point) && !plane.is_point_over(point): + return false + return true + + +func get_points()->PackedVector3Array: + var points:PackedVector3Array + + for v in vertices: + points.append(v.point) + + return points + +func calc_bounds()->AABB: + if vertices.is_empty(): + return AABB() + + var result:AABB = AABB(vertices[0].point, Vector3.ZERO) + + for v_idx in range(1, vertices.size()): + result = result.expand(vertices[v_idx].point) + + return result + +func calc_bounds_xform(xform:Transform3D)->AABB: + if vertices.is_empty(): + return AABB() + + var result:AABB = AABB(xform * vertices[0].point, Vector3.ZERO) + + for v_idx in range(1, vertices.size()): + result = result.expand(xform * vertices[v_idx].point) + + return result + + +func tristrip_vertex_range(num_verts:int)->PackedInt32Array: + var result:PackedInt32Array + + result.append(0) + result.append(1) + for i in range(2, num_verts): + if (i & 1) == 0: + result.append(num_verts - (i >> 1)) + else: + result.append((i >> 1) + 1) + + return result + +func tristrip_vertex_range_reverse(num_verts:int)->PackedInt32Array: + var result:PackedInt32Array + + result.append(1) + result.append(0) + for i in range(2, num_verts): + if (i & 1) == 0: + result.append((i >> 1) + 1) + else: + result.append(num_verts - (i >> 1)) + + return result + +func calc_lightmap_uvs(): + var packer:FacePacker = FacePacker.new() + var max_dim:float = max(bounds.size.x, bounds.size.y, bounds.size.z) + var tree:FacePacker.FaceTree = packer.build_faces(self, max_dim * .1) + + var xform:Transform2D = Transform2D.IDENTITY + xform = xform.scaled(tree.bounds.size) + if is_zero_approx(xform.determinant()): + return + var xform_inv = xform.affine_inverse() + + for ft in tree.face_list: + var face:FaceInfo = faces[ft.face_index] + face.lightmap_uvs = xform_inv * ft.points + +func create_mesh(material_list:Array[Material], default_material:Material, override_with_default_material:bool = false)->ArrayMesh: + + var mesh:ArrayMesh = ArrayMesh.new() + mesh.blend_shape_mode = Mesh.BLEND_SHAPE_MODE_NORMALIZED + mesh.lightmap_size_hint = Vector2(1000, 1000) + + var shadow_mesh:ArrayMesh = ArrayMesh.new() + shadow_mesh.blend_shape_mode = Mesh.BLEND_SHAPE_MODE_NORMALIZED + + #print("create_mesh") + #print("faces.size() ", faces.size()) + + var face_dict:Dictionary = {} + for f_idx in faces.size(): +# print("check F_idx %s" % f_idx) + var face:FaceInfo = faces[f_idx] + if face_dict.has(face.material_id): + var arr = face_dict[face.material_id] + arr.append(f_idx) +# print("arr %s" % [arr]) + face_dict[face.material_id] = arr +# print("append %s to %s" % [f_idx, face.material_id]) + else: + face_dict[face.material_id] = [f_idx] +# print("starting %s to %s" % [f_idx, face.material_id]) + + var surface_idx:int = 0 + for mat_id in face_dict.keys(): +# print("surface mat grp %s" % mat_id) + + var points:PackedVector3Array + var normals:PackedVector3Array + var tangents:PackedFloat32Array + var colors:PackedColorArray + var uv1s:PackedVector2Array + var uv2s:PackedVector2Array + + var material = default_material + if !override_with_default_material: + if mat_id >= 0 && mat_id < material_list.size(): + material = material_list[mat_id] + + for f_idx in face_dict[mat_id]: +# print("f_idx %s" % f_idx) + + var face:FaceInfo = faces[f_idx] + if !face.visible: + continue + + var axis:MathUtil.Axis = MathUtil.get_longest_axis(face.normal) + + var fv_trianglation:Array[int] = face.get_triangulation() + + for v_local_idx in fv_trianglation: + + var v_idx:int = face.vertex_indices[v_local_idx] +# var fv_idx:int = face.face_vertex_indices[v_local_idx] +# var fv_idx:int = face_vertex_coord_map[Vector2i(f_idx, v_idx)].index + var fv:FaceVertexInfo = face_vertex_coord_map[Vector2i(f_idx, v_idx)] + #var fv:ConvexVolume.FaceVertexInfo = face + #vol.get_face_vertex(f_idx, v_idx) + + var p:Vector3 = vertices[v_idx].point + + var uv:Vector2 + if axis == MathUtil.Axis.X: + uv = Vector2(-p.z, -p.y) + elif axis == MathUtil.Axis.Y: + uv = Vector2(-p.x, -p.z) + elif axis == MathUtil.Axis.Z: + uv = Vector2(-p.x, -p.y) + + uv = face.uv_transform * uv + uv1s.append(uv) + uv2s.append(face.lightmap_uvs[v_local_idx]) + +# normals.append(face.normal) + normals.append(fv.normal) +# colors.append(face.color) +# colors.append(face_vertices[fv_idx].color) + colors.append(fv.color) + + points.append(p) + + #Calculate tangents + #http://foundationsofgameenginedev.com/FGED2-sample.pdf + for i in range(0, points.size(), 3): + var p0:Vector3 = points[i] + var p1:Vector3 = points[i + 1] + var p2:Vector3 = points[i + 2] + + var uv0:Vector2 = uv1s[i] + var uv1:Vector2 = uv1s[i + 1] + var uv2:Vector2 = uv1s[i + 2] + + var n:Vector3 = normals[i] + + var e1:Vector3 = p1 - p0 + var e2:Vector3 = p2 - p0 + + var duv1:Vector2 = uv1 - uv0 + var duv2:Vector2 = uv2 - uv0 + + var r:float = 1.0 / (duv1.x * duv2.y - duv2.x * duv1.y) + var t:Vector3 = (e1 * duv2.y - e2 * duv1.y) * r + var b:Vector3 = (e2 * duv1.x - e1 * duv2.x) * r + + t = t.normalized() + + for j in 3: + tangents.append(t.x) + tangents.append(t.y) + tangents.append(t.z) + tangents.append(-1.0 if t.cross(b).dot(n) > 0 else 1.0) + + var arrays:Array = create_indexed_vertex_array(points, normals, tangents, colors, uv1s, uv2s) + + mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays) + mesh.surface_set_material(surface_idx, material) + + var shadow_arrays:Array = [] + shadow_arrays.resize(Mesh.ARRAY_MAX) + shadow_arrays[Mesh.ARRAY_VERTEX] = points + + shadow_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, shadow_arrays) + shadow_mesh.surface_set_material(surface_idx, material) + + surface_idx += 1 + + mesh.shadow_mesh = shadow_mesh +# var err = mesh.lightmap_unwrap(Transform3D.IDENTITY, 10) +# print("Lightmap unwrap Error: %s" % err) + return mesh + + + +func create_indexed_vertex_array(points:PackedVector3Array, normals:PackedVector3Array, tangents:PackedFloat32Array, colors:PackedColorArray, uv1s:PackedVector2Array, uv2s:PackedVector2Array)->Array: + var vert_idx_map:Dictionary + var indices:PackedInt32Array + var points_indexed:PackedVector3Array + var normals_indexed:PackedVector3Array + var tangents_indexed:PackedFloat32Array + var colors_indexed:PackedColorArray + var uv1s_indexed:PackedVector2Array + var uv2s_indexed:PackedVector2Array + + for v_idx in points.size(): + var vertex:PackedFloat32Array + vertex.append(points[v_idx].x) + vertex.append(points[v_idx].y) + vertex.append(points[v_idx].z) + + vertex.append(normals[v_idx].x) + vertex.append(normals[v_idx].y) + vertex.append(normals[v_idx].z) + + vertex.append(tangents[v_idx * 4]) + vertex.append(tangents[v_idx * 4 + 1]) + vertex.append(tangents[v_idx * 4 + 2]) + vertex.append(tangents[v_idx * 4 + 3]) + + vertex.append(colors[v_idx].r) + vertex.append(colors[v_idx].g) + vertex.append(colors[v_idx].b) + vertex.append(colors[v_idx].a) + + vertex.append(uv1s[v_idx].x) + vertex.append(uv1s[v_idx].y) + + vertex.append(uv2s[v_idx].x) + vertex.append(uv2s[v_idx].y) + + var new_index:int + if !vert_idx_map.has(vertex): + #print("alloc vtx ", vertex) + + new_index = vert_idx_map.size() + vert_idx_map[vertex] = new_index + points_indexed.append(points[v_idx]) + normals_indexed.append(normals[v_idx]) + tangents_indexed.append(tangents[v_idx * 4]) + tangents_indexed.append(tangents[v_idx * 4 + 1]) + tangents_indexed.append(tangents[v_idx * 4 + 2]) + tangents_indexed.append(tangents[v_idx * 4 + 3]) + colors_indexed.append(colors[v_idx]) + uv1s_indexed.append(uv1s[v_idx]) + uv2s_indexed.append(uv2s[v_idx]) + else: + new_index = vert_idx_map[vertex] + + #print("index ", new_index) + indices.append(new_index) + + #print("indices ", indices) + + var arrays:Array = [] + arrays.resize(Mesh.ARRAY_MAX) + arrays[Mesh.ARRAY_VERTEX] = points_indexed + arrays[Mesh.ARRAY_NORMAL] = normals_indexed + arrays[Mesh.ARRAY_TANGENT] = tangents_indexed + arrays[Mesh.ARRAY_TEX_UV] = uv1s_indexed + arrays[Mesh.ARRAY_TEX_UV2] = uv2s_indexed + arrays[Mesh.ARRAY_COLOR] = colors_indexed + arrays[Mesh.ARRAY_INDEX] = indices + + return arrays + + +func append_mesh_backfacing(mesh:ImmediateMesh, material:Material, offset:float = .2): +# if Engine.is_editor_hint(): +# return + + for face in faces: + + mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP, material) +# print("face %s" % face.index) + + mesh.surface_set_normal(face.normal) + +# for i in tristrip_vertex_range_reverse(face.vertex_indices.size()): + for i in tristrip_vertex_range_reverse(face.vertex_indices.size()): + var v_idx:int = face.vertex_indices[i] + var v:VertexInfo = vertices[v_idx] + var p:Vector3 = v.point + v.normal * offset + #var p:Vector3 = v.point + Vector3(.1, .1, .1) + + mesh.surface_add_vertex(p) + + mesh.surface_end() + +func append_mesh_outline(mesh:ImmediateMesh, viewport_camera:Camera3D, local_to_world:Transform3D, material:Material, thickness:float = 4): + var cam_orig:Vector3 = viewport_camera.global_transform.origin + + var segments:PackedVector2Array + + #print("--append_mesh_outline") + #var view_plane:Plane = Plane(-viewport_camera.global_basis.z, + #viewport_camera.global_position + #- viewport_camera.global_basis.z * viewport_camera.near * 1) + + var frustum:Array[Plane] = viewport_camera.get_frustum() + + for edge in edges: + var v0:VertexInfo = vertices[edge.start_index] + var v1:VertexInfo = vertices[edge.end_index] + var p0_world:Vector3 = local_to_world * v0.point + var p1_world:Vector3 = local_to_world * v1.point + + var frustum_culled:bool = false + for p in frustum: + var p_flip:Plane = MathUtil.flip_plane(p) + var result:PackedVector3Array = MathUtil.clip_segment_to_plane_3d(p_flip, p0_world, p1_world) + if result.is_empty(): + frustum_culled = true + break + p0_world = result[0] + p1_world = result[1] + + if frustum_culled: + continue + + var has_front:bool = false + var has_back:bool = false + + for f_idx in edge.face_indices: + var face = faces[f_idx] + + var plane = face.get_plane() + plane = local_to_world * plane + + if plane.is_point_over(cam_orig): + has_front = true + else: + has_back = true + + #print("front %s back %s" % [has_front, has_back]) + + if has_front && has_back: + #Draw edge + var p0_screen:Vector2 = viewport_camera.unproject_position(p0_world) + var p1_screen:Vector2 = viewport_camera.unproject_position(p1_world) + segments.append(p0_screen) + segments.append(p1_screen) + #print("seg %s %s" % [p0_screen, p1_screen]) + + #print("segments ", segments) + + var loops:Array[Loop2D] = MathUtil.get_loops_from_segments_2d(segments) + for loop in loops: + var out_dirs:PackedVector2Array + + #print("loop ", loop) + for v_idx in loop.points.size(): + var p0_screen:Vector2 = loop.points[wrap(v_idx - 1, 0, loop.points.size())] + var p1_screen:Vector2 = loop.points[v_idx] + var p2_screen:Vector2 = loop.points[wrap(v_idx + + 1, 0, loop.points.size())] + #var span:Vector2 = p2_screen - p1_screen + + var norm01:Vector2 = (p1_screen - p0_screen).normalized() + var norm12:Vector2 = (p2_screen - p1_screen).normalized() + + var out_dir1:Vector2 = (-norm01 + norm12).normalized() + var perp:Vector2 = out_dir1 - out_dir1.project(norm12) + #Check winding + if perp.x * norm12.y - perp.y * norm12.x < 0: + out_dir1 = -out_dir1 + + out_dirs.append(out_dir1) + + + mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP, material) + for v_idx in loop.points.size() + (1 if loop.closed else 0): + var p_screen:Vector2 = loop.points[wrap(v_idx, 0, loop.points.size())] + var p_out_dir:Vector2 = out_dirs[wrap(v_idx, 0, loop.points.size())] + + var z_pos:float = (viewport_camera.near + viewport_camera.far) / 2 + var p0:Vector3 = viewport_camera.project_position(p_screen, z_pos) + var p1:Vector3 = viewport_camera.project_position(p_screen + p_out_dir * thickness, z_pos) + + mesh.surface_add_vertex(p0) + mesh.surface_add_vertex(p1) + + mesh.surface_end() + + + +func create_mesh_wire(material:Material)->ImmediateMesh: +# if Engine.is_editor_hint(): +# return + var mesh:ImmediateMesh = ImmediateMesh.new() + + mesh.surface_begin(Mesh.PRIMITIVE_LINES, material) + + for e in edges: + var v0:VertexInfo = vertices[e.start_index] + var v1:VertexInfo = vertices[e.end_index] + + mesh.surface_add_vertex(v0.point) + mesh.surface_add_vertex(v1.point) + + mesh.surface_end() + + return mesh + + +func intersect_ray_closest(origin:Vector3, dir:Vector3)->IntersectResults: + if bounds.intersects_ray(origin, dir) == null: + return null + + var best_result:IntersectResults + + for f_idx in faces.size(): + var face:FaceInfo = faces[f_idx] +# var tris:PackedVector3Array = MathUtil.trianglate_face(face.get_points(), face.normal) + var tris:PackedVector3Array = face.get_trianges() + for i in range(0, tris.size(), 3): + var p0:Vector3 = tris[i] + var p1:Vector3 = tris[i + 1] + var p2:Vector3 = tris[i + 2] + + #Godot uses clockwise winding + var tri_area_x2:Vector3 = MathUtil.triangle_area_x2(p0, p1, p2) + + var p_hit:Vector3 = MathUtil.intersect_plane(origin, dir, p0, tri_area_x2) + if !p_hit.is_finite(): + continue + + if MathUtil.triangle_area_x2(p_hit, p0, p1).dot(tri_area_x2) < 0: + continue + if MathUtil.triangle_area_x2(p_hit, p1, p2).dot(tri_area_x2) < 0: + continue + if MathUtil.triangle_area_x2(p_hit, p2, p0).dot(tri_area_x2) < 0: + continue + + #Intersection + var dist_sq:float = (origin - p_hit).length_squared() + if !best_result || best_result.distance_squared > dist_sq: + + var result:IntersectResults = IntersectResults.new() + #result.face_id = face.id + result.face_index = f_idx + result.normal = face.normal + result.position = p_hit + result.distance_squared = dist_sq + + best_result = result + + return best_result + +func format_faces_string()->String: + var s:String = "" + for f in faces: + s = s + "[" + for v_idx in f.vertex_indices: + s += "%s, " % vertices[v_idx].point + s = s + "],\n" + return s + +func update_edge_and_face_selection_from_vertices(): + for e in edges: + e.selected = vertices[e.start_index].selected && vertices[e.end_index].selected + + for f in faces: + var all_sel:bool = true + for v_idx in f.vertex_indices: + if !vertices[v_idx].selected: + all_sel = false + break + f.selected = all_sel + + +func intersects_plane(plane:Plane)->bool: + + var is_over:bool = false + var is_under:bool = false + + for v in vertices: + var p:Vector3 = v.point + + if plane.has_point(p): + continue + + if plane.is_point_over(p): + is_over = true + else: + is_under = true + + if is_over && is_under: + return true + + return false + +func subtract(subtrahend:ConvexVolume)->Array[ConvexVolume]: + var result_list:Array[ConvexVolume] + + var split_vol:ConvexVolume = self + + for face in subtrahend.faces: + var p:Plane = face.get_plane() + + if !split_vol.intersects_plane(p): + continue + + var vol_over:ConvexVolume = split_vol.cut_with_plane(p) + var vol_under:ConvexVolume = split_vol.cut_with_plane(MathUtil.flip_plane(p)) + + result_list.append(vol_over) + split_vol = vol_under + +# result_list.append(split_vol) + + return result_list + + +func intersect(subtrahend:ConvexVolume)->ConvexVolume: + var result_list:Array[ConvexVolume] + + var split_vol:ConvexVolume = self + + for face in subtrahend.faces: + var p:Plane = face.get_plane() + + if !split_vol.intersects_plane(p): + continue + + var vol_over:ConvexVolume = split_vol.cut_with_plane(p) + var vol_under:ConvexVolume = split_vol.cut_with_plane(MathUtil.flip_plane(p)) + + result_list.append(vol_over) + split_vol = vol_under + + return split_vol + + +func is_over_or_on_plane(plane:Plane)->bool: + for v in vertices: + if !plane.is_point_over(v.point) && !plane.has_point(v.point): + return false + + return true + +func intersects_convex_volume(vol:ConvexVolume)->bool: + #Look for plane of separtion between two volumes + for f in vol.faces: + var p:Plane = f.get_plane() + if is_over_or_on_plane(p): + return false + + return true + + +func intersects_frustum(frustum:Array[Plane])->bool: + + for face in faces: + var points:PackedVector3Array = face.get_points() + if MathUtil.polygon_intersects_frustum(points, frustum): + return true + + return false + +func make_convex(): + var selected_points:PackedVector3Array + var new_points:PackedVector3Array + + for v in vertices: + new_points.append(v.point) + + var new_vol:ConvexVolume = ConvexVolume.new() + new_vol.init_from_points(new_points) + + new_vol.copy_vertex_attributes(self) + new_vol.copy_face_attributes(self) + + if active_vertex != -1: + var v:VertexInfo = vertices[active_vertex] + var new_v:VertexInfo = new_vol.get_vertex_at_position(v.point) + if new_v: + new_vol.active_vertex = new_v.index + + if active_edge != -1: + var e:EdgeInfo = edges[active_edge] + var mp:Vector3 = e.get_midpoint() + var new_e:EdgeInfo = new_vol.get_edge_at_position(mp) + if new_e: + new_vol.active_edge = new_e.index + + if active_face != -1: + var f:FaceInfo = faces[active_face] + var centroid:Vector3 = f.get_centroid() + var new_f:FaceInfo = new_vol.get_face_at_position(centroid) + if new_f: + new_vol.active_face = new_f.index + + + #for v_idx in new_vol.vertices.size(): + #var v:ConvexVolume.VertexInfo = new_vol.vertices[v_idx] +## print ("vol point %s " % v.point) + #if selected_points.has(v.point): +## print("set sel") + #v.selected = true +# + #block.mesh_vector_data = new_vol.to_mesh_vector_data() + + diff --git a/addons/cyclops_level_builder/math/convex_volume.gd.uid b/addons/cyclops_level_builder/math/convex_volume.gd.uid new file mode 100644 index 00000000..4bda58af --- /dev/null +++ b/addons/cyclops_level_builder/math/convex_volume.gd.uid @@ -0,0 +1 @@ +uid://dymbwvld1tb5n diff --git a/addons/cyclops_level_builder/math/face_packer.gd b/addons/cyclops_level_builder/math/face_packer.gd new file mode 100644 index 00000000..9a811abe --- /dev/null +++ b/addons/cyclops_level_builder/math/face_packer.gd @@ -0,0 +1,253 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name FacePacker + +class SpawnResult extends RefCounted: + var point:Vector2 + var flip:bool + + func _init(point:Vector2, flip:bool): + self.point = point + self.flip = flip + +class FaceTree extends RefCounted: +# var root:FaceTreeNode + var size:Vector2 + var spawn_points:PackedVector2Array = [Vector2.ZERO] + var face_list:Array[FaceTracker] + var bounds:Rect2 + + func _to_string()->String: + var res:String = "" + for face in face_list: + res += "%s,\n" % str(face) + return res + + func is_collision(rect:Rect2)->bool: + for face in face_list: + if face.bounds.intersects(rect): + return true + return false + + func max_vec_dim(v:Vector2): + return max(v.x, v.y) + + func get_best_spawn_point(face:FaceTracker)->SpawnResult: + var started:bool = false + var best_spawn_point:Vector2 = Vector2.INF + var best_bounds:Rect2 + var best_flip:bool + + for s_idx in spawn_points.size(): + var spawn_point:Vector2 = spawn_points[s_idx] + + var placed_bounds:Rect2 = face.bounds + placed_bounds.position += spawn_point + + if !is_collision(placed_bounds): + var new_bounds:Rect2 = bounds.merge(placed_bounds) + + if new_bounds.is_equal_approx(bounds): + return SpawnResult.new(spawn_point, false) + else: + if !started || max_vec_dim(best_bounds.size) > max_vec_dim(new_bounds.size): + best_bounds = new_bounds + best_flip = false + best_spawn_point = spawn_point + started = true + + var placed_bounds_flipped:Rect2 = face.bounds + placed_bounds_flipped.size = Vector2(placed_bounds_flipped.size.y, placed_bounds_flipped.size.x) + placed_bounds_flipped.position += spawn_point + + if !is_collision(placed_bounds_flipped): + var new_bounds_flipped:Rect2 = bounds.merge(placed_bounds_flipped) + + if new_bounds_flipped.is_equal_approx(bounds): + return SpawnResult.new(spawn_point, true) + else: + if !started || max_vec_dim(best_bounds.size) > max_vec_dim(new_bounds_flipped.size): + best_bounds = new_bounds_flipped + best_flip = true + best_spawn_point = spawn_point + started = true + + return SpawnResult.new(best_spawn_point, best_flip) + + func add_face(face:FaceTracker): + var spawn:SpawnResult = get_best_spawn_point(face) + + var idx = spawn_points.find(spawn.point) + spawn_points.remove_at(idx) + + if spawn.flip: + face.reflect_diagonal() + + face.translate(spawn.point) + face_list.append(face) + bounds = bounds.merge(face.bounds) + + var sp_0:Vector2 = face.bounds.position + Vector2(face.bounds.size.x, 0) + var sp_1:Vector2 = face.bounds.position + Vector2(0, face.bounds.size.y) + if !spawn_points.has(sp_0): + spawn_points.append(sp_0) + if !spawn_points.has(sp_1): + spawn_points.append(sp_1) + + + +class FaceTracker extends RefCounted: + var points:PackedVector2Array + var indices:PackedInt32Array + var bounds:Rect2 + var face_index:int + + func _to_string()->String: + var res:String = "[" + for p in points: + res += "%s, " % str(p) + res += "]" + return res + + func max_dim()->float: + return max(bounds.size.x, bounds.size.y) + + func reflect_diagonal(): + for p_idx in points.size(): + var p:Vector2 = points[p_idx] + points[p_idx] = Vector2(p.y, p.x) + bounds.size = Vector2(bounds.size.y, bounds.size.x) + + func translate(offset:Vector2): + for p_idx in points.size(): + points[p_idx] += offset + bounds.position += offset + + func fit_initial_rect(): + bounds = Rect2(points[0], Vector2.ZERO) + for i in range(1, points.size()): + bounds = bounds.expand(points[i]) + + #Move so corner of bounds is at (0, 0) + for i in points.size(): + points[i] -= bounds.position + bounds.position = Vector2.ZERO + + func get_best_base_index()->int: + var best_index:int = -1 + var best_height:float = INF + + for i0 in points.size(): + var i1:int = wrap(i0 + 1, 0, points.size()) + + var base_dir:Vector2 = points[i1] - points[i0] + var base_origin:Vector2 = points[i0] + var base_dir_perp:Vector2 = Vector2(-base_dir.y, base_dir.x) + + var max_height:float = 0 + + for j in range(2, points.size()): + var p_idx:int = wrap(j + i0, 0, points.size()) + var p:Vector2 = points[p_idx] + var offset:Vector2 = p - base_origin + var offset_proj:Vector2 = offset.project(base_dir_perp) + + max_height = max(max_height, offset_proj.length_squared()) + + if max_height < best_height: + best_height = max_height + best_index = i0 + + return best_index + + func rotate_to_best_fit(): + var i0:int = get_best_base_index() + var i1:int = wrap(i0 + 1, 0, points.size()) + + var base_dir:Vector2 = (points[i1] - points[i0]).normalized() + var base_dir_perp:Vector2 = Vector2(-base_dir.y, base_dir.x) + + var xform:Transform2D = Transform2D(base_dir, base_dir_perp, Vector2.ZERO) + var xform_inv:Transform2D = xform.affine_inverse() + + for p_idx in points.size(): + var p:Vector2 = xform_inv * points[p_idx] + points[p_idx] = p + + +func pack_faces(faces:Array[FaceTracker])->FaceTree: + faces.sort_custom(func (a:FaceTracker, b:FaceTracker): return a.max_dim() > b.max_dim()) + + var tree:FaceTree = FaceTree.new() + for f in faces: + tree.add_face(f) + + #print(tree) + return tree + +func build_faces(vol:ConvexVolume, margin:float)->FaceTree: + var faces:Array[FaceTracker] + + for f_idx in vol.faces.size(): + var face:ConvexVolume.FaceInfo = vol.faces[f_idx] + var axis:MathUtil.Axis = MathUtil.get_longest_axis(face.normal) + + var cross_vec:Vector3 + if axis == MathUtil.Axis.Y: + cross_vec = Vector3.FORWARD + else: + cross_vec = Vector3.UP + + var u_axis:Vector3 = face.normal.cross(cross_vec) + var v_axis:Vector3 = u_axis.cross(face.normal) + var basis:Basis = Basis(u_axis, face.normal, v_axis) + + var xform:Transform3D = Transform3D(basis, face.get_centroid()) + var xz_xform:Transform3D = xform.affine_inverse() + + var tracker:FaceTracker = FaceTracker.new() + tracker.face_index = f_idx + faces.append(tracker) + + for v_idx in face.vertex_indices: + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + var proj:Vector3 = xz_xform * v.point + tracker.points.append(Vector2(proj.x, proj.z)) + tracker.indices.append(v_idx) + + #print("face init points %s" % tracker.points) + + tracker.rotate_to_best_fit() + #print("after rot %s" % tracker.points) + tracker.fit_initial_rect() + #print("after fit %s" % tracker.points) + for p_idx in tracker.points.size(): + tracker.points[p_idx] += Vector2(margin, margin) + tracker.bounds.size += Vector2(margin, margin) * 2 + + return pack_faces(faces) + + diff --git a/addons/cyclops_level_builder/math/face_packer.gd.uid b/addons/cyclops_level_builder/math/face_packer.gd.uid new file mode 100644 index 00000000..9ebf2a3e --- /dev/null +++ b/addons/cyclops_level_builder/math/face_packer.gd.uid @@ -0,0 +1 @@ +uid://bhmrfl7c6lyos diff --git a/addons/cyclops_level_builder/math/general_mesh.gd b/addons/cyclops_level_builder/math/general_mesh.gd new file mode 100644 index 00000000..85d8ef17 --- /dev/null +++ b/addons/cyclops_level_builder/math/general_mesh.gd @@ -0,0 +1,446 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +#@deprecated +@tool +extends RefCounted +class_name GeneralMesh + + +class VertexInfo extends RefCounted: + var index:int + var point:Vector3 + var edge_indices:Array[int] = [] + var selected:bool + + func _init(_index:int, _point:Vector3 = Vector3.ZERO): + index = _index + point = _point + + func _to_string(): + var s:String = "%s %s [" % [index, point] + for i in edge_indices: + s += "%s " % i + s += "]" + + return s + +class EdgeInfo extends RefCounted: + var index:int + var start_index:int + var end_index:int + var face_indices:Array[int] = [] + var selected:bool + + func _init(_index:int, _start:int = 0, _end:int = 0): + index = _index + start_index = _start + end_index = _end + + func _to_string(): + var s:String = "%s %s %s [" % [index, start_index, end_index] + for i in face_indices: + s += "%s " % i + s += "]" + return s + +class FaceInfo extends RefCounted: + var index:int + var normal:Vector3 +# var vertex_indices:Array[int] + var face_corner_indices:Array[int] + var material_index:int + var selected:bool + + func _init(_index:int, _face_corner_indices:Array[int] = [], _mat_index:int = 0): + index = _index + face_corner_indices = _face_corner_indices + material_index = _mat_index + + func _to_string(): + var s:String = "%s %s %s [" % [index, normal, material_index] + for i in face_corner_indices: + s += "%s " % i + s += "]" + return s + +class FaceCornerInfo extends RefCounted: + var index:int + var uv:Vector2 + var vertex_index:int + var face_index:int + var selected:bool + + func _init(_index:int, _vertex_index:int, _face_index:int): + vertex_index = _vertex_index + face_index = _face_index + + func _to_string(): + var s:String = "%s %s %s %s" % [index, uv, vertex_index, face_index] + return s + + + +var vertices:Array[VertexInfo] = [] +var edges:Array[EdgeInfo] = [] +var faces:Array[FaceInfo] = [] +var face_corners:Array[FaceCornerInfo] = [] +var bounds:AABB + +#var points:PackedVector3Array + +func _init(): + pass + +func get_face_indices()->PackedInt32Array: + var result:PackedInt32Array + for f in faces: + result.append(f.index) + return result + +func clear_lists(): + vertices = [] + edges = [] + faces = [] + face_corners = [] + bounds = AABB() + +func init_block(block_bounds:AABB): + var p000:Vector3 = block_bounds.position + var p111:Vector3 = block_bounds.end + var p001:Vector3 = Vector3(p000.x, p000.y, p111.z) + var p010:Vector3 = Vector3(p000.x, p111.y, p000.z) + var p011:Vector3 = Vector3(p000.x, p111.y, p111.z) + var p100:Vector3 = Vector3(p111.x, p000.y, p000.z) + var p101:Vector3 = Vector3(p111.x, p000.y, p111.z) + var p110:Vector3 = Vector3(p111.x, p111.y, p000.z) + + init_prism([p000, p001, p011, p010], p100 - p000) + + +func init_prism(base_points:Array[Vector3], extrude_dir:Vector3): + + var verts:PackedVector3Array + for p in base_points: + verts.append(p) + for p in base_points: + verts.append(p + extrude_dir) + + var index_list:PackedInt32Array + var face_len_list:PackedInt32Array + + var num_points:int = base_points.size() + for i0 in num_points: + var i1:int = wrap(i0 + 1, 0, num_points) + + index_list.append(i0) + index_list.append(i1) + index_list.append(i1 + num_points) + index_list.append(i0 + num_points) + face_len_list.append(4) + + for i0 in num_points: +# index_list.append(i0) + index_list.append(num_points - i0 - 1) + face_len_list.append(num_points) + + for i0 in num_points: + index_list.append(i0 + num_points) +# index_list.append(num_points * 2 - i0 - 1) + face_len_list.append(num_points) + + init_from_face_lists(verts, index_list, face_len_list) + + +func init_from_face_lists(verts:PackedVector3Array, index_list:PackedInt32Array, face_len_list:PackedInt32Array): + clear_lists() + + for i in verts.size(): + var v:VertexInfo = VertexInfo.new(i, verts[i]) + vertices.append(v) + + if i == 0: + bounds = AABB(verts[0], Vector3.ZERO) + else: + bounds = bounds.expand(verts[i]) + + var vertex_index_offset:int = 0 + for face_index in face_len_list.size(): + var num_face_verts = face_len_list[face_index] +# if num_face_verts < 3: +# continue + + var face_corners_local:Array[int] = [] + for i in num_face_verts: + var face_corner_index:int = face_corners.size() + var face_corner:FaceCornerInfo = FaceCornerInfo.new(face_corner_index, index_list[vertex_index_offset], face_index) + face_corners.append(face_corner) + face_corners_local.append(face_corner_index) + vertex_index_offset += 1 + + var face:FaceInfo = FaceInfo.new(face_index, face_corners_local) + faces.append(face) + + #Calc normal + var fc0:FaceCornerInfo = face_corners[face_corners_local[0]] +# var vidx0 = fc0.vertex_index + var p0:Vector3 = vertices[fc0.vertex_index].point +# + var weighted_normal:Vector3 + for i in range(1, num_face_verts - 1): + var fc1:FaceCornerInfo = face_corners[face_corners_local[i]] + var fc2:FaceCornerInfo = face_corners[face_corners_local[i + 1]] +# var vidx1 = fc1.vertex_index +# var vidx2 = fc2.vertex_index + var p1:Vector3 = vertices[fc1.vertex_index].point + var p2:Vector3 = vertices[fc2.vertex_index].point + + var v1:Vector3 = p1 - p0 + var v2:Vector3 = p2 - p0 + weighted_normal += v2.cross(v1) + + face.normal = weighted_normal.normalized() + + #Calculate edges + for face in faces: + var num_corners = face.face_corner_indices.size() + for i0 in num_corners: + var i1:int = wrap(i0 + 1, 0, num_corners) + var fc0:FaceCornerInfo = face_corners[face.face_corner_indices[i0]] + var fc1:FaceCornerInfo = face_corners[face.face_corner_indices[i1]] + + var edge:EdgeInfo = get_edge(fc0.vertex_index, fc1.vertex_index) + if !edge: + var edge_idx = edges.size() + edge = EdgeInfo.new(edge_idx, fc0.vertex_index, fc1.vertex_index) + edges.append(edge) + + var v0:VertexInfo = vertices[fc0.vertex_index] + v0.edge_indices.append(edge_idx) + + var v1:VertexInfo = vertices[fc1.vertex_index] + v1.edge_indices.append(edge_idx) + + edge.face_indices.append(face.index) + + +func get_edge(vert_idx0:int, vert_idx1:int)->EdgeInfo: + for e in edges: + if e.start_index == vert_idx0 && e.end_index == vert_idx1: + return e + if e.start_index == vert_idx1 && e.end_index == vert_idx0: + return e + return null + + +func init_block_data(block:BlockData): + clear_lists() + + for i in block.points.size(): + var v:VertexInfo = VertexInfo.new(i, block.points[i]) + vertices.append(v) + + if i == 0: + bounds = AABB(v.point, Vector3.ZERO) + else: + bounds = bounds.expand(v.point) + + var corner_index_offset:int = 0 + for face_index in block.face_vertex_count.size(): + var num_face_verts = block.face_vertex_count[face_index] + + var face_corners_local:Array[int] = [] + for i in num_face_verts: + var vertex_index = block.face_vertex_indices[corner_index_offset] + + var face_corner:FaceCornerInfo = FaceCornerInfo.new(corner_index_offset, vertex_index, face_index) + face_corner.uv = block.uvs[corner_index_offset] + face_corners.append(face_corner) + face_corners_local.append(corner_index_offset) + corner_index_offset += 1 + + var face:FaceInfo = FaceInfo.new(face_index, face_corners_local) + face.material_index = block.face_material_indices[face_index] + faces.append(face) + + #Calc normal + var fc0:FaceCornerInfo = face_corners[face_corners_local[0]] + var p0:Vector3 = vertices[fc0.vertex_index].point +# + var weighted_normal:Vector3 + for i in range(1, num_face_verts - 1): + var fc1:FaceCornerInfo = face_corners[face_corners_local[i]] + var fc2:FaceCornerInfo = face_corners[face_corners_local[i + 1]] + var p1:Vector3 = vertices[fc1.vertex_index].point + var p2:Vector3 = vertices[fc2.vertex_index].point + + var v1:Vector3 = p1 - p0 + var v2:Vector3 = p2 - p0 + weighted_normal += v2.cross(v1) + + face.normal = weighted_normal.normalized() + + #Calculate edges + for face in faces: + var num_corners = face.face_corner_indices.size() + for i0 in num_corners: + var i1:int = wrap(i0 + 1, 0, num_corners) + var fc0:FaceCornerInfo = face_corners[face.face_corner_indices[i0]] + var fc1:FaceCornerInfo = face_corners[face.face_corner_indices[i1]] + + var edge:EdgeInfo = get_edge(fc0.vertex_index, fc1.vertex_index) + if !edge: + var edge_idx = edges.size() + edge = EdgeInfo.new(edge_idx, fc0.vertex_index, fc1.vertex_index) + edges.append(edge) + + var v0:VertexInfo = vertices[fc0.vertex_index] + v0.edge_indices.append(edge_idx) + + var v1:VertexInfo = vertices[fc1.vertex_index] + v1.edge_indices.append(edge_idx) + + edge.face_indices.append(face.index) + + +func to_block_data()->BlockData: + var block:BlockData = preload("res://addons/cyclops_level_builder/resources/block_data.gd").new() +# var block:BlockData = BlockData.new() + + for v in vertices: + block.points.append(v.point) + + for f in faces: + block.face_vertex_count.append(f.face_corner_indices.size()) + block.face_material_indices.append(f.material_index) + + for fc_idx in f.face_corner_indices: + var fc:FaceCornerInfo = face_corners[fc_idx] + block.face_vertex_indices.append(fc.vertex_index) + block.uvs.append(fc.uv) + + return block + +func append_mesh(mesh:ImmediateMesh, material:Material, color:Color = Color.WHITE): + + for face in faces: + mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLE_STRIP, material) +# print("face %s" % face.index) + + mesh.surface_set_normal(face.normal) + + var num_corners:int = face.face_corner_indices.size() + for i in num_corners: + var idx = (i + 1) / 2 if i & 1 else wrap(num_corners - (i / 2), 0, num_corners) + var fc:FaceCornerInfo = face_corners[face.face_corner_indices[idx]] + + mesh.surface_set_color(color) + mesh.surface_set_uv(fc.uv) + mesh.surface_add_vertex(vertices[fc.vertex_index].point) +# print ("%s %s %s" % [idx, fc.vertex_index, control_mesh.vertices[fc.vertex_index].point]) + + mesh.surface_end() + +func triplanar_unwrap(scale:float = 1): + for fc in face_corners: + var v:VertexInfo = vertices[fc.vertex_index] + var f:FaceInfo = faces[fc.face_index] + + if abs(f.normal.x) > abs(f.normal.y) && abs(f.normal.x) > abs(f.normal.z): + fc.uv = Vector2(v.point.y, v.point.z) * scale + elif abs(f.normal.y) > abs(f.normal.z): + fc.uv = Vector2(v.point.x, v.point.z) * scale + else: + fc.uv = Vector2(v.point.x, v.point.y) * scale + + +func get_face_points(face:FaceInfo)->PackedVector3Array: + var points:PackedVector3Array + for fc_idx in face.face_corner_indices: + var fc:FaceCornerInfo = face_corners[fc_idx] + points.append(vertices[fc.vertex_index].point) + return points + +func triangulate_face(face:FaceInfo)->PackedVector3Array: + var points:PackedVector3Array = get_face_points(face) + return MathUtil.trianglate_face(points, face.normal) + + +func intersect_ray_closest(origin:Vector3, dir:Vector3)->IntersectResults: + if bounds.intersects_ray(origin, dir) == null: + return null + + var best_result:IntersectResults + + for f in faces: + var tris:PackedVector3Array = triangulate_face(f) + for i in range(0, tris.size(), 3): + var p0:Vector3 = tris[i] + var p1:Vector3 = tris[i + 1] + var p2:Vector3 = tris[i + 2] + + #Godot uses clockwise winding + var tri_area_x2:Vector3 = MathUtil.triangle_area_x2(p0, p1, p2) + + var p_hit:Vector3 = MathUtil.intersect_plane(origin, dir, p0, tri_area_x2) + if !p_hit.is_finite(): + continue + + if MathUtil.triangle_area_x2(p_hit, p0, p1).dot(tri_area_x2) < 0: + continue + if MathUtil.triangle_area_x2(p_hit, p1, p2).dot(tri_area_x2) < 0: + continue + if MathUtil.triangle_area_x2(p_hit, p2, p0).dot(tri_area_x2) < 0: + continue + + #Intersection + var dist_sq:float = (origin - p_hit).length_squared() + if !best_result || best_result.distance_squared > dist_sq: + + var result:IntersectResults = IntersectResults.new() + result.face_index = f.index + result.normal = f.normal + result.position = p_hit + result.distance_squared = dist_sq + + best_result = result + + return best_result + +func translate(offset:Vector3): + for v in vertices: + v.point += offset + +func dump(): + print ("Verts") + for v in vertices: + print(v.to_string()) + print ("Edges") + for e in edges: + print(e.to_string()) + print ("Faces") + for f in faces: + print(f.to_string()) + print ("Face Corners") + for f in face_corners: + print(f.to_string()) diff --git a/addons/cyclops_level_builder/math/general_mesh.gd.uid b/addons/cyclops_level_builder/math/general_mesh.gd.uid new file mode 100644 index 00000000..532012ee --- /dev/null +++ b/addons/cyclops_level_builder/math/general_mesh.gd.uid @@ -0,0 +1 @@ +uid://ci08jp0465ucu diff --git a/addons/cyclops_level_builder/math/geometry_mesh.gd b/addons/cyclops_level_builder/math/geometry_mesh.gd new file mode 100644 index 00000000..7d96ffe9 --- /dev/null +++ b/addons/cyclops_level_builder/math/geometry_mesh.gd @@ -0,0 +1,63 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +#extends RefCounted +class_name GeometryMesh + +var coords:PackedVector3Array +var normals:PackedVector3Array +var uvs:PackedVector2Array + +func transform(xform:Transform3D)->GeometryMesh: + var result:GeometryMesh = GeometryMesh.new() + + var basis:Basis = xform.basis + basis = basis.inverse() + basis = basis.transposed() + + for i in coords.size(): + result.coords.append(xform * coords[i]) + result.uvs.append(uvs[i]) + result.normals.append(basis * normals[i]) + + return result + +func append_to_immediate_mesh(mesh:ImmediateMesh, material:Material, xform:Transform3D = Transform3D.IDENTITY): + mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES, material) + + var basis:Basis = xform.basis + basis = basis.inverse() + basis = basis.transposed() + + for i in coords.size(): + var normal:Vector3 = basis * normals[i] + var coord:Vector3 = xform * coords[i] + var uv:Vector2 = uvs[i] + + mesh.surface_set_normal(normal) + mesh.surface_set_uv(uv) + mesh.surface_add_vertex(coord) + + mesh.surface_end() + diff --git a/addons/cyclops_level_builder/math/geometry_mesh.gd.uid b/addons/cyclops_level_builder/math/geometry_mesh.gd.uid new file mode 100644 index 00000000..491c54fc --- /dev/null +++ b/addons/cyclops_level_builder/math/geometry_mesh.gd.uid @@ -0,0 +1 @@ +uid://dym54klg4qk8u diff --git a/addons/cyclops_level_builder/math/loop_2d.gd b/addons/cyclops_level_builder/math/loop_2d.gd new file mode 100644 index 00000000..179f9098 --- /dev/null +++ b/addons/cyclops_level_builder/math/loop_2d.gd @@ -0,0 +1,36 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name Loop2D + +var points:PackedVector2Array +var closed:bool + +func reverse(): + points.reverse() + +func _to_string(): + return "Loop2D(%s, %s)" % [closed, str(points)] + diff --git a/addons/cyclops_level_builder/math/loop_2d.gd.uid b/addons/cyclops_level_builder/math/loop_2d.gd.uid new file mode 100644 index 00000000..579b5d12 --- /dev/null +++ b/addons/cyclops_level_builder/math/loop_2d.gd.uid @@ -0,0 +1 @@ +uid://baipex8u0cuyv diff --git a/addons/cyclops_level_builder/math/math_geometry.gd b/addons/cyclops_level_builder/math/math_geometry.gd new file mode 100644 index 00000000..e8536ec1 --- /dev/null +++ b/addons/cyclops_level_builder/math/math_geometry.gd @@ -0,0 +1,182 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +#extends RefCounted +class_name MathGeometry + +#static func circle_points(radius:float = 1, segs:int = 16, u_axis:Vector3 = Vector3.RIGHT, v_axis:Vector3 = Vector3.BACK)->PackedVector3Array: + #var result:PackedVector3Array + # + #for i in (segs + 1): + #result.append(u_axis * cos(i / float(segs)) + v_axis * sin(i / float(segs))) +# + #return result + # +#static func circle(radius:float = 1, segs:int = 16, u_axis:Vector3 = Vector3.RIGHT, v_axis:Vector3 = Vector3.BACK)->GeometryMesh: + #var mesh:GeometryMesh = GeometryMesh.new() + # + #for i in (segs + 1): + #mesh.coords.append(u_axis * cos(i / float(segs)) + v_axis * sin(i / float(segs))) + #mesh.uvs.append(Vector2(i / float(segs), 0)) + #mesh.normals.append(mesh.coords[-1].normalized()) + # + #return mesh + +static func unit_cylinder(segs:int = 16, radius0:float = 1, radius1:float = 1, top_height:float = 1, bottom_height:float = -1, bottom_cap:bool = false, top_cap:bool = false)->GeometryMesh: + var mesh:GeometryMesh = GeometryMesh.new() + + var vc0:Vector3 = Vector3(0, 0, -1) + var vc1:Vector3 = Vector3(0, 0, 1) + var uvc:Vector2 = Vector2(.5, .5) + + for s in range(segs): + + var sin0:float = sin(deg_to_rad(360 * s / segs)) + var cos0:float = cos(deg_to_rad(360 * s / segs)) + var sin1:float = sin(deg_to_rad(360 * (s + 1) / segs)) + var cos1:float = cos(deg_to_rad(360 * (s + 1) / segs)) + + var v00:Vector3 = Vector3(sin0 * radius0, cos0 * radius0, bottom_height) + var v10:Vector3 = Vector3(sin1 * radius0, cos1 * radius0, bottom_height) + var v01:Vector3 = Vector3(sin0 * radius1, cos0 * radius1, top_height) + var v11:Vector3 = Vector3(sin1 * radius1, cos1 * radius1, top_height) + + var tan0:Vector3 = Vector3(cos0, sin0, 0) + var n00:Vector3 = (v01 - v00).cross(tan0) + n00 = n00.normalized() + var n01:Vector3 = n00 + var tan1:Vector3 = Vector3(cos1, sin1, 0) + var n10:Vector3 = (v11 - v10).cross(tan1) + n10 = n10.normalized() + var n11 = n10 + + var uv00:Vector2 = Vector2(s / segs, 0) + var uv10:Vector2 = Vector2((s + 1) / segs, 0) + var uv01:Vector2 = Vector2(s / segs, 1) + var uv11:Vector2 = Vector2((s + 1) / segs, 1) + + if radius0 != 0: + mesh.coords.append(v00) + mesh.coords.append(v10) + mesh.coords.append(v11) + + mesh.normals.append(n00) + mesh.normals.append(n10) + mesh.normals.append(n11) + + mesh.uvs.append(uv00) + mesh.uvs.append(uv10) + mesh.uvs.append(uv11) + + if radius1 != 0: + mesh.coords.append(v00) + mesh.coords.append(v11) + mesh.coords.append(v01) + + mesh.normals.append(n00) + mesh.normals.append(n11) + mesh.normals.append(n01) + + mesh.uvs.append(uv00) + mesh.uvs.append(uv11) + mesh.uvs.append(uv01) + + if top_cap and radius1 != 0: + mesh.coords.append(v01) + mesh.coords.append(v11) + mesh.coords.append(vc1) + + mesh.normals.append(Vector3(0, 0, 1)) + mesh.normals.append(Vector3(0, 0, 1)) + mesh.normals.append(Vector3(0, 0, 1)) + + mesh.uvs.append(Vector2(sin0, cos0)) + mesh.uvs.append(Vector2(sin1, cos1)) + mesh.uvs.append(uvc) + + if bottom_cap and radius0 != 0: + mesh.coords.append(v00) + mesh.coords.append(v10) + mesh.coords.append(vc0) + + mesh.normals.append(-Vector3(0, 0, 1)) + mesh.normals.append(-Vector3(0, 0, 1)) + mesh.normals.append(-Vector3(0, 0, 1)) + + mesh.uvs.append(Vector2(sin0, cos0)) + mesh.uvs.append(Vector2(sin1, cos1)) + mesh.uvs.append(uvc) + + + return mesh + +static func unit_sphere(segs_lat:int = 6, segs_long:int = 8)->GeometryMesh: + var mesh:GeometryMesh = GeometryMesh.new() + + for la in range(segs_lat): + + var z0:float = cos(deg_to_rad(180 * la / segs_lat)) + var z1:float = cos(deg_to_rad(180 * (la + 1) / segs_lat)) + var r0:float = sin(deg_to_rad(180 * la / segs_lat)) + var r1:float = sin(deg_to_rad(180 * (la + 1) / segs_lat)) + + for lo in range(segs_long): + var cx0:float = sin(deg_to_rad(360 * lo / segs_long)) + var cx1:float = sin(deg_to_rad(360 * (lo + 1) / segs_long)) + var cy0:float = cos(deg_to_rad(360 * lo / segs_long)) + var cy1:float = cos(deg_to_rad(360 * (lo + 1) / segs_long)) + + var v00:Vector3 = Vector3(cx0 * r0, cy0 * r0, z0) + var v10:Vector3 = Vector3(cx1 * r0, cy1 * r0, z0) + var v01:Vector3 = Vector3(cx0 * r1, cy0 * r1, z1) + var v11:Vector3 = Vector3(cx1 * r1, cy1 * r1, z1) + + if la != 0: + mesh.coords.append(v00) + mesh.coords.append(v11) + mesh.coords.append(v10) + + mesh.normals.append(v00) + mesh.normals.append(v10) + mesh.normals.append(v10) + + mesh.uvs.append(Vector2(lo / segs_long, la / segs_lat)) + mesh.uvs.append(Vector2((lo + 1) / segs_long, la / segs_lat)) + mesh.uvs.append(Vector2((lo + 1) / segs_long, (la + 1) / segs_lat)) + + if la != segs_lat - 1: + mesh.coords.append(v00) + mesh.coords.append(v01) + mesh.coords.append(v11) + + mesh.normals.append(v00) + mesh.normals.append(v01) + mesh.normals.append(v11) + + mesh.uvs.append(Vector2(lo / segs_long, la / segs_lat)) + mesh.uvs.append(Vector2((lo + 1) / segs_long, (la + 1) / segs_lat)) + mesh.uvs.append(Vector2(lo / segs_long, (la + 1) / segs_lat)) + + return mesh + diff --git a/addons/cyclops_level_builder/math/math_geometry.gd.uid b/addons/cyclops_level_builder/math/math_geometry.gd.uid new file mode 100644 index 00000000..308be49f --- /dev/null +++ b/addons/cyclops_level_builder/math/math_geometry.gd.uid @@ -0,0 +1 @@ +uid://cgy7gcqup47t0 diff --git a/addons/cyclops_level_builder/math/math_util.gd b/addons/cyclops_level_builder/math/math_util.gd new file mode 100644 index 00000000..545df223 --- /dev/null +++ b/addons/cyclops_level_builder/math/math_util.gd @@ -0,0 +1,934 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name MathUtil + +enum Axis { X, Y, Z } + +static func square(value:float)->float: + return value * value + +static func snap_to_grid(pos:Vector3, cell_size:float)->Vector3: +# return floor(pos / cell_size) * cell_size + return floor((pos + Vector3(cell_size, cell_size, cell_size) / 2) / cell_size) * cell_size + + +#Returns intersection of line with point. +# plane_perp_dir points in direction of plane's normal and does not need to be normalized +static func intersect_plane(ray_origin:Vector3, ray_dir:Vector3, plane_origin:Vector3, plane_perp_dir:Vector3)->Vector3: + var s:float = (plane_origin - ray_origin).dot(plane_perp_dir) / ray_dir.dot(plane_perp_dir) + return ray_origin + ray_dir * s + +static func intersects_triangle(ray_origin:Vector3, ray_dir:Vector3, p0:Vector3, p1:Vector3, p2:Vector3)->bool: + #Godot uses clockwise winding + var tri_area_x2:Vector3 = MathUtil.triangle_area_x2(p0, p1, p2) + + var p_hit:Vector3 = MathUtil.intersect_plane(ray_origin, ray_dir, p0, tri_area_x2) + if !p_hit.is_finite(): + return false + + if MathUtil.triangle_area_x2(p_hit, p0, p1).dot(tri_area_x2) < 0: + return false + if MathUtil.triangle_area_x2(p_hit, p1, p2).dot(tri_area_x2) < 0: + return false + if MathUtil.triangle_area_x2(p_hit, p2, p0).dot(tri_area_x2) < 0: + return false + + return true + +class IntersectTriangleResult: + var position:Vector3 + var normal:Vector3 + +static func intersect_triangle(ray_origin:Vector3, ray_dir:Vector3, p0:Vector3, p1:Vector3, p2:Vector3)->IntersectTriangleResult: + #Godot uses clockwise winding + var tri_area_x2:Vector3 = MathUtil.triangle_area_x2(p0, p1, p2) + + var p_hit:Vector3 = MathUtil.intersect_plane(ray_origin, ray_dir, p0, tri_area_x2) + if !p_hit.is_finite(): + return null + + if MathUtil.triangle_area_x2(p_hit, p0, p1).dot(tri_area_x2) < 0: + return null + if MathUtil.triangle_area_x2(p_hit, p1, p2).dot(tri_area_x2) < 0: + return null + if MathUtil.triangle_area_x2(p_hit, p2, p0).dot(tri_area_x2) < 0: + return null + + var result:IntersectTriangleResult = IntersectTriangleResult.new() + result.position = p_hit + result.normal = tri_area_x2.normalized() + return result + +#Returns the closest point on the line to the ray +static func closest_point_on_line(ray_origin:Vector3, ray_dir:Vector3, line_origin:Vector3, line_dir:Vector3)->Vector3: + var a:Vector3 = ray_dir.cross(line_dir) + var w_perp:Vector3 = ray_dir.cross(a) + return intersect_plane(line_origin, line_dir, ray_origin, w_perp) + +static func closest_point_on_plane(point:Vector3, plane_origin:Vector3, plane_dir:Vector3)->Vector3: + return point - (point - plane_origin).project(plane_dir) + +static func closest_point_on_segment(ray_origin:Vector3, ray_dir:Vector3, seg_start:Vector3, seg_end:Vector3)->Vector3: + var seg_span:Vector3 = seg_end - seg_start + var p:Vector3 = closest_point_on_line(ray_origin, ray_dir, seg_start, seg_span) + var offset:Vector3 = p - seg_start + if offset.dot(seg_span) < 0: + return seg_start + if offset.length_squared() > seg_span.length_squared(): + return seg_end + return p + +#Shortest distance from point to given ray. Returns NAN if point is behind origin of ray. +static func distance_to_ray(ray_origin:Vector3, ray_dir:Vector3, point:Vector3): + var offset = point - ray_origin + var parallel:Vector3 = offset.project(ray_dir) + if parallel.dot(ray_dir) < 0: + return NAN + + var perp:Vector3 = offset - parallel + return perp.length() + + +static func trianglate_face(points:PackedVector3Array, normal:Vector3)->PackedVector3Array: + var result:PackedVector3Array + + while (points.size() >= 3): + var num_points:int = points.size() + for i in range(0, num_points): + var p0:Vector3 = points[i] + var p1:Vector3 = points[wrap(i + 1, 0, num_points)] + var p2:Vector3 = points[wrap(i + 2, 0, num_points)] + + #Godot uses clockwise winding + var tri_norm_dir:Vector3 = (p2 - p0).cross(p1 - p0) + if tri_norm_dir.dot(normal) > 0: + result.append(p0) + result.append(p1) + result.append(p2) + + points.remove_at(i + 1) + break + + return result + +static func trianglate_face_indices(points:PackedVector3Array, indices:Array[int], normal:Vector3)->Array[int]: + var result:Array[int] = [] + +# print("trianglate_face_indices %s" % points) + + while (points.size() >= 3): + var num_points:int = points.size() + var added_point:bool = false + + for i in range(0, num_points): + var idx0:int = i + var idx1:int = wrap(i + 1, 0, num_points) + var idx2:int = wrap(i + 2, 0, num_points) + var p0:Vector3 = points[idx0] + var p1:Vector3 = points[idx1] + var p2:Vector3 = points[idx2] + + #Godot uses clockwise winding + var tri_norm_dir:Vector3 = (p2 - p0).cross(p1 - p0) + if tri_norm_dir.dot(normal) > 0: + result.append(indices[idx0]) + result.append(indices[idx1]) + result.append(indices[idx2]) + +# print("adding indices %s %s %s" % [indices[idx0], indices[idx1], indices[idx2]]) + + points.remove_at(idx1) + indices.remove_at(idx1) + added_point = true + break + + assert(added_point, "failed to add point in triangulation") +# print("tri_done %s" % str(result)) + + return result + +static func trianglate_face_vertex_indices(points:PackedVector3Array, normal:Vector3)->Array[int]: + var result:Array[int] = [] + var fv_indices:Array = range(0, points.size()) +# print("trianglate_face_indices %s" % points) + + while (points.size() >= 3): + var num_points:int = points.size() + var added_point:bool = false + + for i in range(0, num_points): + var idx0:int = i + var idx1:int = wrap(i + 1, 0, num_points) + var idx2:int = wrap(i + 2, 0, num_points) + var p0:Vector3 = points[idx0] + var p1:Vector3 = points[idx1] + var p2:Vector3 = points[idx2] + + #Godot uses clockwise winding + var tri_norm_dir:Vector3 = (p2 - p0).cross(p1 - p0) + if tri_norm_dir.dot(normal) > 0: + result.append(fv_indices[idx0]) + result.append(fv_indices[idx1]) + result.append(fv_indices[idx2]) + +# print("adding indices %s %s %s" % [indices[idx0], indices[idx1], indices[idx2]]) + + points.remove_at(idx1) + fv_indices.remove_at(idx1) + added_point = true + break + + assert(added_point, "failed to add point in triangulation") +# print("tri_done %s" % str(result)) + + return result + +static func flip_plane(plane:Plane)->Plane: + return Plane(-plane.normal, plane.get_center()) + +#Returns a vector pointing along the normal in the clockwise winding direction with a length equal to twice the area of the triangle +static func triangle_area_x2(p0:Vector3, p1:Vector3, p2:Vector3)->Vector3: + return (p2 - p0).cross(p1 - p0) + +#Returns a vector pointing along the normal in the clockwise winding direction with a lengh equal to twice the area of the face +static func face_area_x2(points:PackedVector3Array)->Vector3: + if points.size() <= 1: + return Vector3.ZERO + + var result:Vector3 + var p0:Vector3 = points[0] + + for i in range(1, points.size() - 1): + var p1:Vector3 = points[i] + var p2:Vector3 = points[i + 1] + + result += (p2 - p0).cross(p1 - p0) + + return result + +static func face_area_x2_2d(points:PackedVector2Array)->float: + if points.size() <= 1: + return 0 + + var result:float + var p0:Vector2 = points[0] + + for i in range(1, points.size() - 1): + var p1:Vector2 = points[i] + var p2:Vector2 = points[i + 1] + + result += triange_area_2x_2d(p1 - p0, p2 - p0) + + return result + +static func fit_plane(points:PackedVector3Array)->Plane: + var normal:Vector3 = face_area_x2(points).normalized() + return Plane(normal, points[0]) + +static func snap_to_best_axis_normal(vector:Vector3)->Vector3: + if abs(vector.x) > abs(vector.y) and abs(vector.x) > abs(vector.z): + return Vector3(1, 0, 0) if vector.x > 0 else Vector3(-1, 0, 0) + elif abs(vector.y) > abs(vector.z): + return Vector3(0, 1, 0) if vector.y > 0 else Vector3(0, -1, 0) + else: + return Vector3(0, 0, 1) if vector.z > 0 else Vector3(0, 0, -1) + +static func get_longest_axis(vector:Vector3)->Axis: + if abs(vector.x) > abs(vector.y) and abs(vector.x) > abs(vector.z): + return Axis.X + elif abs(vector.y) > abs(vector.z): + return Axis.Y + else: + return Axis.Z + +static func calc_bounds(points:PackedVector3Array)->AABB: + if points.is_empty(): + return AABB(Vector3.ZERO, Vector3.ZERO) + + var result:AABB = AABB(points[0], Vector3.ZERO) + for i in range(1, points.size()): + result = result.expand(points[i]) + return result + +#Returns value equal to twise the area between the two vectors. Clockwise windings have negative area +static func triange_area_2x_2d(a:Vector2, b:Vector2)->float: + return a.x * b.y - a.y * b.x + +#Finds the bouding polygons of this set of points with a clockwise winding +static func bounding_polygon_2d(base_points:PackedVector2Array)->PackedVector2Array: + if base_points.size() <= 2: + return base_points + + + #Start with leftmost vertex, topmost if more than one + var p_init:Vector2 = base_points[0] + for p in base_points: + if p.x < p_init.x or (p.x == p_init.x and p.y > p_init.y): + p_init = p + + + var p_cur:Vector2 = p_init + var last_segment_dir = Vector2(0, 1) + + var polygon:PackedVector2Array + + while true: + var best_point:Vector2 + var best_dir:Vector2 + var best_angle:float = 0 + + for p in base_points: + if p.is_equal_approx(p_cur): + continue + + var point_dir:Vector2 = (p - p_cur).normalized() + var angle:float = acos(-last_segment_dir.dot(point_dir)) + + if angle > best_angle or (angle == best_angle and p_cur.distance_squared_to(p) > p_cur.distance_squared_to(best_point)): + best_point = p + best_dir = point_dir + best_angle = angle + + p_cur = best_point + last_segment_dir = best_dir + polygon.append(best_point) + + if best_point.is_equal_approx(p_init): + break + + return polygon + +#static func bounding_polygon(base_points:PackedVector3Array, plane:Plane)->PackedVector3Array: +static func bounding_polygon_3d(base_points:PackedVector3Array, normal:Vector3)->PackedVector3Array: + if base_points.size() <= 2: + return base_points + + var quat:Quaternion = Quaternion(normal, Vector3.FORWARD) + +# var xform:Transform3D = Transform3D(Basis(quat), -base_points[0]) + var xform:Transform3D = Transform3D(Basis(quat)) + xform = xform.translated_local(-base_points[0]) + var xform_inv = xform.inverse() + + #print("xform %s" % xform) + + var points_local:PackedVector2Array + + for p in base_points: + var p_local = xform * p + points_local.append(Vector2(p_local.x, p_local.y)) + + var points_bounds:PackedVector2Array = bounding_polygon_2d(points_local) + + var result:PackedVector3Array + for p in points_bounds: + var p_result = xform_inv * Vector3(p.x, p.y, 0) + result.append(p_result) + + return result + +static func points_are_colinear(points:PackedVector3Array)->bool: + if points.size() <= 2: + return true + + var p0:Vector3 = points[0] + var p1:Vector3 = p0 + var index:int = 0 + for i in range(1, points.size()): + if !points[i].is_equal_approx(p0): + p1 = points[i] + index = i + break + + if index == 0: + return true + + var v10:Vector3 = p1 - p0 + for i in range(index + 1, points.size()): + if !triangle_area_x2(p0, p1, points[i]).is_zero_approx(): + return false + + return true + + +static func furthest_point_from_line(line_origin:Vector3, line_dir:Vector3, points:PackedVector3Array)->Vector3: + var best_point:Vector3 + var best_dist:float = 0 + + for p in points: + var offset:Vector3 = p - line_origin + var along:Vector3 = offset.project(line_dir) + var perp:Vector3 = offset - along + var dist:float = perp.length_squared() + if dist > best_dist: + best_dist = dist + best_point = p + + return best_point + +static func furthest_point_from_plane(plane:Plane, points:PackedVector3Array)->Vector3: + var best_point:Vector3 + var best_distance:float = 0 + + for p in points: + var dist = abs(plane.distance_to(p)) + if dist > best_distance: + best_point = p + best_distance = dist + + return best_point + +static func planar_volume_contains_point(planes:Array[Plane], point:Vector3)->bool: +# print("candidate %s" % point) + + for p in planes: + var is_over:bool = p.is_point_over(point) + var is_on:bool = p.has_point(point) + if !is_over && !is_on: +# print("reject by %s" % p) + return false +# print("passed %s" % point) + return true + +static func get_convex_hull_points_from_planes(planes:Array[Plane])->Array[Vector3]: + #Check for overlapping planes + for i0 in range(0, planes.size()): + for i1 in range(i0 + 1, planes.size()): + var p0:Plane = planes[i0] + var p1:Plane = flip_plane(planes[i1]) + if p0.is_equal_approx(p1): + return [] + + var points:Array[Vector3] + + for i0 in range(0, planes.size()): + for i1 in range(i0 + 1, planes.size()): + for i2 in range(i1 + 1, planes.size()): + var result = planes[i0].intersect_3(planes[i1], planes[i2]) + + if result == null: + continue + #print("candidate %s" % result) + if !planar_volume_contains_point(planes, result): + continue + if points.any(func(p):return p.is_equal_approx(result)): + continue + #print("adding %s" % result) + points.append(result) + + return points + +static func dist_to_segment_squared_2d(point:Vector2, seg_start:Vector2, seg_end:Vector2)->float: + if seg_start.is_equal_approx(seg_end): + return point.distance_squared_to(seg_start) + + var dist_sq_p0:float = point.distance_squared_to(seg_start) + var dist_sq_p1:float = point.distance_squared_to(seg_end) + var seg_span:Vector2 = seg_end - seg_start + + var offset:Vector2 = point - seg_start + var offset_proj:Vector2 = offset.project(seg_span) + var perp_dist_sq:float = (offset - offset_proj).length_squared() + + if seg_span.dot(offset) < 0: + return dist_sq_p0 + elif offset_proj.length_squared() > seg_span.length_squared(): + return dist_sq_p1 + return perp_dist_sq + +class Segment2d extends RefCounted: + var p0:Vector2 + var p1:Vector2 + + func _init(p0:Vector2, p1:Vector2): + self.p0 = p0 + self.p1 = p1 + + func reverse()->Segment2d: + return Segment2d.new(p1, p0) + + func _to_string(): + return "[%s %s]" % [p0, p1] + +static func extract_loop_2d(seg_stack:Array[Segment2d])->Loop2D: + var segs_sorted:Array[Segment2d] = [] + var seg_tail = seg_stack.pop_back() + segs_sorted.append(seg_tail) + var seg_head = seg_tail + + while !seg_stack.is_empty(): + var found_seg:bool = false + for s_idx in seg_stack.size(): + var cur_seg:Segment2d = seg_stack[s_idx] + + if cur_seg.p0.is_equal_approx(seg_tail.p1): + #print("matching %s with %s" % [seg_tail, cur_seg]) + segs_sorted.append(cur_seg) + seg_stack.remove_at(s_idx) + seg_tail = cur_seg + found_seg = true + break + elif cur_seg.p1.is_equal_approx(seg_tail.p1): + #print("matching %s with %s" % [seg_tail, cur_seg]) + cur_seg = cur_seg.reverse() + segs_sorted.append(cur_seg) + seg_stack.remove_at(s_idx) + seg_tail = cur_seg + found_seg = true + break + elif cur_seg.p1.is_equal_approx(seg_head.p0): + #print("matching %s with %s" % [seg_head, cur_seg]) + segs_sorted.insert(0, cur_seg) + seg_stack.remove_at(s_idx) + seg_head = cur_seg + found_seg = true + break + elif cur_seg.p0.is_equal_approx(seg_head.p0): + #print("matching %s with %s" % [seg_head, cur_seg]) + cur_seg = cur_seg.reverse() + segs_sorted.insert(0, cur_seg) + seg_stack.remove_at(s_idx) + seg_head = cur_seg + found_seg = true + break + + if !found_seg: +# push_warning("loop not continuous") + break + + #print("segs_sorted %s" % str(segs_sorted)) + + var result:Loop2D = Loop2D.new() + result.closed = true + for s in segs_sorted: + result.points.append(s.p0) + + if seg_head.p0 != seg_tail.p1: + result.points.append(seg_tail.p1) + result.closed = false + + if face_area_x2_2d(result.points) < 0: + result.reverse() + + #print("loop %s" % str(result)) + + return result + +static func get_loops_from_segments_2d(segments:PackedVector2Array)->Array[Loop2D]: + #print("segments %s" % segments) + var loops:Array[Loop2D] = [] + + var seg_stack:Array[Segment2d] = [] + for i in range(0, segments.size(), 2): + seg_stack.append(Segment2d.new(segments[i], segments[i + 1])) + +# print("segs %s" % str(seg_stack)) + + while !seg_stack.is_empty(): + var loop:Loop2D = extract_loop_2d(seg_stack) + loops.append(loop) + + #print("result %s" % str(loops)) + return loops + +static func create_transform(translation:Vector3, rotation_axis:Vector3, rotation_angle:float, scale:Vector3, pivot:Vector3)->Transform3D: + var xform:Transform3D = Transform3D.IDENTITY + + xform = xform.translated_local(pivot + translation) + xform = xform.rotated_local(rotation_axis, rotation_angle) + xform = xform.scaled_local(scale) + xform = xform.translated_local(-pivot) + + return xform + +static func create_circle_points(center:Vector3, normal:Vector3, radius:float, num_segments:int)->PackedVector3Array: + var result:PackedVector3Array + + var axis:Axis = get_longest_axis(normal) + var perp_normal:Vector3 + match axis: + Axis.X: + perp_normal = normal.cross(Vector3.UP) + Axis.Y: + perp_normal = normal.cross(Vector3.FORWARD) + Axis.Z: + perp_normal = normal.cross(Vector3.UP) + + var angle_incrment = (PI * 2 / num_segments) + for i in num_segments: + var offset:Vector3 = perp_normal.rotated(normal, i * angle_incrment) + result.append(offset * radius + center) + + return result + +static func get_axis_aligned_tangent_and_binormal(normal:Vector3)->Array[Vector3]: + var axis:MathUtil.Axis = MathUtil.get_longest_axis(normal) + #calc tangent and binormal + var u_normal:Vector3 + var v_normal:Vector3 + match axis: + MathUtil.Axis.Y: + u_normal = normal.cross(Vector3.FORWARD) + v_normal = u_normal.cross(normal) + return [u_normal, v_normal] + MathUtil.Axis.X: + u_normal = normal.cross(Vector3.UP) + v_normal = u_normal.cross(normal) + return [u_normal, v_normal] + MathUtil.Axis.Z: + u_normal = normal.cross(Vector3.UP) + v_normal = u_normal.cross(normal) + return [u_normal, v_normal] + + return [] + +#Returns the planes of a frustum for the rectangular region on the camera's near +# plane with all planes pointing toward the interior of the frustum +static func calc_frustum_camera_rect(cam:Camera3D, p0:Vector2, p1:Vector2)->Array[Plane]: + + var x0 = min(p0.x, p1.x) + var x1 = max(p0.x, p1.x) + var y0 = min(p0.y, p1.y) + var y1 = max(p0.y, p1.y) + + var p00:Vector2 = Vector2(x0, y0) + var p01:Vector2 = Vector2(x0, y1) + var p10:Vector2 = Vector2(x1, y0) + var p11:Vector2 = Vector2(x1, y1) + +# print("cam rect %s" % str([p00, p11])) + + #Cam project_position does not work if we set distance to far plane, so back off a bit + var far_scalar:float = .95 + + var p000:Vector3 = cam.project_position(p00, cam.near) + var p100:Vector3 = cam.project_position(p10, cam.near) + var p010:Vector3 = cam.project_position(p01, cam.near) + var p110:Vector3 = cam.project_position(p11, cam.near) + var p001:Vector3 = cam.project_position(p00, cam.far * far_scalar) + var p101:Vector3 = cam.project_position(p10, cam.far * far_scalar) + var p011:Vector3 = cam.project_position(p01, cam.far * far_scalar) + var p111:Vector3 = cam.project_position(p11, cam.far * far_scalar) + +# print("points %s" % str([p000, p100, p010, p110, p001, p101, p011, p111, ])) + + var plane_left:Plane = Plane(p001, p011, p010) + var plane_right:Plane = Plane(p101, p110, p111) + var plane_top:Plane = Plane(p011, p111, p110) + var plane_bottom:Plane = Plane(p001, p100, p101) + var plane_near:Plane = Plane(p000, p110, p100) + var plane_far:Plane = Plane(p001, p111, p011) + + return [plane_left, plane_right, plane_top, plane_bottom, plane_near, plane_far] + +static func clip_polygon(points:PackedVector3Array, plane:Plane)->PackedVector3Array: + var result:PackedVector3Array + + #Cut at planr intersection + var points_on_or_over:PackedVector3Array + + for p_idx0 in points.size(): + var p_idx1:int = wrap(p_idx0 + 1, 0, points.size()) + + var p0:Vector3 = points[p_idx0] + var p1:Vector3 = points[p_idx1] + + var on0:bool = plane.has_point(p0) + var over0:bool = plane.is_point_over(p0) + var under0:bool = !on0 && !over0 + var on1:bool = plane.has_point(p1) + var over1:bool = plane.is_point_over(p1) + var under1:bool = !on1 && !over1 + + if on0 || over0: + points_on_or_over.append(p0) + + if (under0 && over1) || (over0 && under1): + points_on_or_over.append(plane.intersects_segment(p0, p1)) + + return points_on_or_over + + +#Snaps point to a point appearing in the list if distance to it is <= radius. Otherwise appends +# point to point list +static func snap_point_to_point_list_or_append(point:Vector3, list:PackedVector3Array, radius:float = .005): + for p in list: + if p.distance_squared_to(point) < radius * radius: + return p + list.append(point) + return point + + +static func create_loop_from_directed_segments(segs:Array[Segment3], snap_radius:float = .005)->PackedVector3Array: + var snap_list:PackedVector3Array + for seg in segs: + seg.p0 = snap_point_to_point_list_or_append(seg.p0, snap_list, snap_radius) + seg.p1 = snap_point_to_point_list_or_append(seg.p1, snap_list, snap_radius) + + + var seg_stack:Array[Segment3] + var sorted_segs:Array[Segment3] + + for s in segs: + if !is_zero_approx(s.length_squared()): + seg_stack.append(s) + + + sorted_segs.append(seg_stack.pop_back()) + while !seg_stack.is_empty(): + var found_seg:bool = false + var min_dist:float = 10000 + for i in seg_stack.size(): + var s:Segment3 = seg_stack[i] + +# if s.p0.is_equal_approx(sorted_segs.back().p1): + var dist:float = s.p0.distance_to(sorted_segs.back().p1) + min_dist = min(min_dist, dist) + + if dist < .005: +# if s.p0.is_equal_approx(sorted_segs.back().p1): + sorted_segs.append(s) + seg_stack.remove_at(i) + found_seg = true + break +# if s.p1.is_equal_approx(sorted_segs.back().p1): +# sorted_segs.append(s.reversed()) +# seg_stack.remove_at(i) +# found_seg = true +# break + + if !found_seg: + print("Error: could not form loop") + return [] + + var result:PackedVector3Array + for s in sorted_segs: + result.append(s.p0) + + return result + +static func clip_polygon_separate(points:PackedVector3Array, plane:Plane)->ClipPolyResult: + + #Clip points to plane. + var clipped_points:PackedVector3Array = clip_polygon(points, plane) + + #Every point should now be on or above the plane + var is_over:Array[bool] + var all_over:bool = true + var none_over:bool = true + for p in clipped_points: + var is_on:bool = plane.has_point(p) + if is_on: + all_over = false + else: + none_over = false + + is_over.append(!is_on) + + if all_over: + return ClipPolyResult.new([clipped_points]) + + if none_over: + return ClipPolyResult.new() + + var start_idx:int = -1 + for p_idx0 in clipped_points.size(): + var p_idx1:int = wrap(p_idx0 + 1, 0, clipped_points.size()) + + var over0:bool = is_over[p_idx0] + var over1:bool = is_over[p_idx1] + + if !over0 && over1: + start_idx = p_idx0 + break + + #If you think of the clipped_points as a string where every point on the plane is + # represented by the character 'n' and every point over the plane is the character + # 'v', then every sub polygon will be a string that can be represented by the + # regular expression "(nv+n)" + var results:Array[PackedVector3Array]= [] + var cut_segments:Array[Segment3] + + var writing_shape:bool = true + var sub_poly:PackedVector3Array + for i in clipped_points.size(): + var p_idx0:int = wrap(i + start_idx, 0, clipped_points.size()) + var p_idx1:int = wrap(i + start_idx + 1, 0, clipped_points.size()) + + if is_over[p_idx1]: + sub_poly.append(clipped_points[p_idx0]) + + elif is_over[p_idx0]: + sub_poly.append(clipped_points[p_idx0]) + sub_poly.append(clipped_points[p_idx1]) + + cut_segments.append(Segment3.new(sub_poly[sub_poly.size() - 1], sub_poly[0])) + results.append(sub_poly.duplicate()) + sub_poly.clear() + + return ClipPolyResult.new(results, cut_segments) + + + +static func polygon_intersects_frustum(points:PackedVector3Array, frustum:Array[Plane])->bool: + var points_i:PackedVector3Array = points + + for plane in frustum: + points_i = clip_polygon(points_i, plane) + if points_i.is_empty(): + return false + + return true + + +static func frustum_contians_point(planes:Array[Plane], point:Vector3)->bool: + for plane in planes: + if !plane.is_point_over(point) && !plane.has_point(point): + return false + return true + +static func frustum_intersects_sphere(planes:Array[Plane], center:Vector3, radius:float)->bool: + for plane in planes: + var dist:float = plane.distance_to(center) + + if dist < -radius: + return false + + return true + + +func plane_intesects_point_cloud(points:PackedVector3Array, plane:Plane)->bool: + + var is_over:bool = false + var is_under:bool = false + for p in points: + if plane.has_point(p): + continue + + if plane.is_point_over(p): + is_over = true + else: + is_under = true + if is_over && is_under: + return true + + return false + +#Returns vector with [R, Q] where R is the orthogonal basis +# and Q is a triangular matrix such that basis = R * Q +static func gram_schmidt_decomposition(basis:Basis)->Array[Basis]: + #https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process + var v0:Vector3 = basis.x + var v1:Vector3 = basis.y + var v2:Vector3 = basis.z + + var u0:Vector3 = v0 + var u1:Vector3 = v1 - v1.project(u0) + var u2:Vector3 = v2 - v2.project(u0) - v2.project(u1) + + var R:Basis = Basis(u0.normalized(), u1.normalized(), u2.normalized()) + var R_inv:Basis = R.inverse() + var Q:Basis = R_inv * basis + + return [R, Q] + +#Decomposes matrix into translate, rotate, scale and shear vectors where +# M = T * R * Sh * S +# where: +# T - translate matrix +# R - rotate matrix +# Sh - shear matrix +# S - scale matrix +# +# Shear matrix for vector (x, y, z) is +# [1 x y] +# [0 1 z] +# [0 0 1] +static func decompose_matrix_3d(m:Transform3D, order:EulerOrder = EULER_ORDER_YXZ)->Dictionary: + + if is_zero_approx(m.basis.determinant()): + return {"valid": false} + + var basis:Basis = m.basis + var gram_schmidt = gram_schmidt_decomposition(basis) + var rot_mtx = gram_schmidt[0] + var euler:Vector3 = rot_mtx.get_euler(order) + + var scale_shear = gram_schmidt[1] + var scale:Vector3 = Vector3(scale_shear.x.x, scale_shear.y.y, scale_shear.z.z) + var scale_mat:Basis = Basis.from_scale(scale) + var shear:Basis = scale_shear * scale_mat.inverse() + + #print(shear) + + return { + "valid": true, + "translate": m.origin, + "rotate": euler, + "scale": scale, + "shear": Vector3(shear.y.x, shear.z.x, shear.z.y) + } + +static func compose_matrix_3d(translate:Vector3, rotate:Vector3 = Vector3.ZERO, order:EulerOrder = EULER_ORDER_YXZ, shear:Vector3 = Vector3.ZERO, scale:Vector3 = Vector3.ONE)->Transform3D: + var scale_mat:Basis = Basis.from_scale(scale) + var shear_mat:Basis = Basis( + Vector3(1, 0, 0), + Vector3(shear.x, 1, 0), + Vector3(shear.y, shear.z, 1)) + var rot_mat:Basis = Basis.from_euler(rotate, order) + var basis:Basis = rot_mat * shear_mat * scale_mat + + return Transform3D(basis, translate) + +static func clip_segment_to_plane_3d(p:Plane, v0:Vector3, v1:Vector3)->PackedVector3Array: + var clip_v0:bool = !p.is_point_over(v0) + var clip_v1:bool = !p.is_point_over(v1) + if clip_v0 && clip_v1: + return [] + + if clip_v0: + v0 = p.intersects_segment(v0, v1) + elif clip_v1: + v1 = p.intersects_segment(v0, v1) + + return [v0, v1] + + +static func blend_over_with_alpha(src:Color, dest:Color): + #https://en.wikipedia.org/wiki/Alpha_compositing + var a0:float = src.a + dest.a * (1 - src.a) + var r0:float = (src.r * src.a + dest.r * dest.a * (1 - src.a)) / a0 + var g0:float = (src.g * src.a + dest.g * dest.a * (1 - src.a)) / a0 + var b0:float = (src.b * src.a + dest.b * dest.a * (1 - src.a)) / a0 + return Color(r0, g0, b0, a0) + +static func blend_colors_with_alpha(src:Color, dest:Color, weight:float)->Color: + var col:Color = blend_over_with_alpha(src, dest) + col.a *= weight + return blend_over_with_alpha(col, dest) + +static func blend_colors_ignore_alpha(src:Color, dest:Color, weight:float)->Color: + return weight * src + (1 - weight) * dest + diff --git a/addons/cyclops_level_builder/math/math_util.gd.uid b/addons/cyclops_level_builder/math/math_util.gd.uid new file mode 100644 index 00000000..54a9f234 --- /dev/null +++ b/addons/cyclops_level_builder/math/math_util.gd.uid @@ -0,0 +1 @@ +uid://dihlkkrul6uii diff --git a/addons/cyclops_level_builder/math/pen_stroke.gd b/addons/cyclops_level_builder/math/pen_stroke.gd new file mode 100644 index 00000000..1bdf658c --- /dev/null +++ b/addons/cyclops_level_builder/math/pen_stroke.gd @@ -0,0 +1,94 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name PenStroke +extends Resource + +class StrokePoint extends Resource: + @export var position:Vector3 + @export var pressure:float + + #func _init(position:Vector3 = Vector3.ZERO, pressure:float = 1): + #print("ppp ", position) + #self.position = position + #self.pressure = pressure + + func _to_string()->String: + return "%s %f" % [str(position), pressure] + + func lerp(p:StrokePoint, weight:float): + var r:StrokePoint = StrokePoint.new() + r.position = lerp(position, p.position, weight) + r.pressure = lerp(pressure, p.pressure, weight) + return r + +var stroke_points:Array[StrokePoint] + +func clear(): + stroke_points.clear() + +func is_empty()->bool: + return stroke_points.is_empty() + +func append_stroke_point(position:Vector3, pressure:float = 1): + var p:StrokePoint = StrokePoint.new() + p.position = position + p.pressure = pressure + stroke_points.append(p) + +func resample_points(resample_dist:float)->PenStroke: + if stroke_points.is_empty(): + return null + + var result:PenStroke = PenStroke.new() + + #var p_start:StrokePoint = stroke_points[0] + #var p_start1:StrokePoint = p_start.duplicate(true) + #print("p_start ", p_start) + #print("p_start1 ", p_start1) + #print("stroke_points[0] ", stroke_points[0].position) + result.stroke_points.append(stroke_points[0].duplicate()) + #print("--stroke_points[0] ", stroke_points[0].position) + + var seg_dist_covered:float = 0 + var last_pos_plotted:float = 0 + + for src_p_idx in stroke_points.size() - 1: + var p0:StrokePoint = stroke_points[src_p_idx] + var p1:StrokePoint = stroke_points[src_p_idx + 1] + var seg_len:float = p0.position.distance_to(p1.position) + + while last_pos_plotted + resample_dist <= seg_dist_covered + seg_len: + var pn:StrokePoint = p0.lerp(p1, \ + (last_pos_plotted + resample_dist - seg_dist_covered) / seg_len) + result.stroke_points.append(pn) + last_pos_plotted += resample_dist + + seg_dist_covered += seg_len + + #print("stroke points res ", str(result.stroke_points)) + + return result + + diff --git a/addons/cyclops_level_builder/math/pen_stroke.gd.uid b/addons/cyclops_level_builder/math/pen_stroke.gd.uid new file mode 100644 index 00000000..3f3c7e23 --- /dev/null +++ b/addons/cyclops_level_builder/math/pen_stroke.gd.uid @@ -0,0 +1 @@ +uid://wir082psotj5 diff --git a/addons/cyclops_level_builder/math/quick_hull.gd b/addons/cyclops_level_builder/math/quick_hull.gd new file mode 100644 index 00000000..fc08316c --- /dev/null +++ b/addons/cyclops_level_builder/math/quick_hull.gd @@ -0,0 +1,360 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name QuickHull + +class DirectedEdge extends RefCounted: + var p0:Vector3 + var p1:Vector3 + + func _init(p0:Vector3, p1:Vector3): + self.p0 = p0 + self.p1 = p1 + + func _to_string()->String: + return "%s %s" % [p0, p1] + + func reverse()->DirectedEdge: + return DirectedEdge.new(p1, p0) + + func equals(e:DirectedEdge)->bool: + return p0 == e.p0 && p1 == e.p1 + +class Facet extends RefCounted: + var plane:Plane + var points:PackedVector3Array #Clockwise winding faces out + var over_points:PackedVector3Array + + func _to_string(): + var result:String = "plane %s\ncentroid %s\npoints %s\nover %s" % [plane, (points[0] + points[1] + points[2])/3, points, over_points] + + return result + + func has_edge(e:DirectedEdge)->bool: + return (points[0] == e.p0 && points[1] == e.p1) || \ + (points[1] == e.p0 && points[2] == e.p1) || \ + (points[2] == e.p0 && points[0] == e.p1) + + func get_edges()->Array[DirectedEdge]: + var result:Array[DirectedEdge] = [] + + result.append(DirectedEdge.new(points[0], points[1])) + result.append(DirectedEdge.new(points[1], points[2])) + result.append(DirectedEdge.new(points[2], points[0])) + return result + + func init_from_points(p0:Vector3, p1:Vector3, p2:Vector3): + #Facet normal points to outside + plane = Plane(p0, p1, p2) + points = [p0, p1, p2] + + #Create a facet with vertices at p0, p1, p2 and winding such that under_ref + # is on the under side of the plane + func init_from_points_under(p0:Vector3, p1:Vector3, p2:Vector3, under_ref:Vector3): + #Facet normal points to outside + plane = Plane(p0, p1, p2) + if plane.is_point_over(under_ref): + plane = Plane(p0, p2, p1) + points = [p0, p2, p1] + else: + points = [p0, p1, p2] + + func get_furthest_point()->Vector3: + var best_point:Vector3 + var best_distance:float = 0 + + for p in over_points: + var dist = abs(plane.distance_to(p)) + if dist > best_distance: + best_point = p + best_distance = dist + + return best_point + +class Hull extends RefCounted: + var facets:Array[Facet] = [] + + func get_non_empty_facet()->Facet: + for f in facets: + if !f.over_points.is_empty(): + return f + return null + + func get_facet_with_edge(e:DirectedEdge)->Facet: + for f in facets: + if f.has_edge(e): + return f + return null + + func _to_string(): + var result:String = "" + for f in facets: + result += "%s\n" % f + return result + + + func get_points()->Array[Vector3]: + var result:Array[Vector3] + + for f in facets: + for p in f.points: + if !result.any(func(pl):return pl.is_equal_approx(p)): + result.append(p) + + return result + + func format_points()->String: + var result:String = "" + for f in facets: + result += "%s,\n" % f.points + return result + + +static func form_loop(edges:Array[DirectedEdge])->PackedVector3Array: + var sorted:Array[DirectedEdge] = [] + + var cur_edge:DirectedEdge = edges.pop_back() + sorted.append(cur_edge) + + while !edges.is_empty(): + var found_edge:bool = false + for i in edges.size(): + var e:DirectedEdge = edges[i] + if e.p0.is_equal_approx(cur_edge.p1): + edges.remove_at(i) + cur_edge = e + sorted.append(e) + found_edge = true + break + + if !found_edge: + assert(found_edge, "Unable to complete loop") + pass +# if !found_edge: +# assert(false, "Unable to complete loop") +# return PackedVector3Array() + + var result:PackedVector3Array + for e in sorted: + result.append(e.p0) + return result + +static func merge_coplanar_facets(hull:Hull)->Hull: +# print("hull %s " % hull) + #print("hull %s " % hull.format_points()) + + var new_hull:Hull = Hull.new() + var already_seen:Array[Facet] = [] + + for facet_idx in hull.facets.size(): + var facet:Facet = hull.facets[facet_idx] + if already_seen.has(facet): + continue + already_seen.append(facet) + + #print("merging facet %s" % facet) + + var neighbor_set:Array[Facet] = [] + neighbor_set.append(facet) + var boundary:Array[DirectedEdge] = [] + + while !neighbor_set.is_empty(): + var cur_facet:Facet = neighbor_set.pop_back() + var edges:Array[DirectedEdge] = cur_facet.get_edges() + + for e in edges: + var neighbor:Facet = hull.get_facet_with_edge(e.reverse()) + if neighbor.plane.is_equal_approx(facet.plane): + if !already_seen.has(neighbor): + already_seen.append(neighbor) + neighbor_set.append(neighbor) + else: + boundary.append(e) + + + var points:PackedVector3Array = form_loop(boundary) + + var nf:Facet = Facet.new() + nf.plane = facet.plane + nf.points = points + new_hull.facets.append(nf) + + return new_hull + + +static func create_initial_simplex(points:PackedVector3Array)->Hull: + if points.size() < 4: + return null + + #For first two points, pick furthest apart along one of the axes + var max_x:Vector3 = points[0] + var min_x:Vector3 = points[0] + var max_y:Vector3 = points[0] + var min_y:Vector3 = points[0] + var max_z:Vector3 = points[0] + var min_z:Vector3 = points[0] + + for idx in range(1, points.size()): + var p:Vector3 = points[idx] + if p.x > max_x.x: + max_x = p + if p.x < min_x.x: + min_x = p + if p.y > max_y.y: + max_y = p + if p.y < min_y.y: + min_y = p + if p.z > max_z.z: + max_z = p + if p.z < min_z.z: + min_z = p + + var p0:Vector3 + var p1:Vector3 + var dx:float = max_x.distance_squared_to(min_x) + var dy:float = max_y.distance_squared_to(min_y) + var dz:float = max_z.distance_squared_to(min_z) + + if dx > dy and dx > dz: + p0 = max_x + p1 = min_x + elif dy > dz: + p0 = max_y + p1 = min_y + else: + p0 = max_z + p1 = min_z + + #Find furthest point from line for second point + var p2:Vector3 = MathUtil.furthest_point_from_line(p0, p1 - p0, points) + var p3:Vector3 = MathUtil.furthest_point_from_plane(Plane(p0, p1, p2), points) + + #Make simplex + var hull:Hull = Hull.new() + + var f0:Facet = Facet.new() + f0.init_from_points_under(p1, p2, p3, p0) + var f1:Facet = Facet.new() + f1.init_from_points_under(p2, p3, p0, p1) + var f2:Facet = Facet.new() + f2.init_from_points_under(p3, p0, p1, p2) + var f3:Facet = Facet.new() + f3.init_from_points_under(p0, p1, p2, p3) + + hull.facets.append(f0) + hull.facets.append(f1) + hull.facets.append(f2) + hull.facets.append(f3) + + for p in points: + for f in hull.facets: + if f.plane.is_point_over(p) && !f.plane.has_point(p): + f.over_points.append(p) + + return hull + + +static func quickhull(points:PackedVector3Array)->Hull: + if points.size() < 4: + return null + + var hull:Hull = create_initial_simplex(points) + if !hull: + return null + + #print("initial points %s" % points) + #print("initial simplex %s" % hull.format_points()) + + while true: + var facet:Facet = hull.get_non_empty_facet() + if facet == null: + break + + #print("-facet %s" % facet) + + var p_over:Vector3 = facet.get_furthest_point() + #print("over point %s" % p_over) + + #print("hull %s" % hull.format_points()) + + var visibile_faces:Array[Facet] = [facet] + var edges:Array[DirectedEdge] = facet.get_edges() + var visited_edges:Array[DirectedEdge] = [] + var boundary_edges:Array[DirectedEdge] = [] + +# for e in edges: +# print("init edge search set %s" % e) + + + #Find set of edges that form the boundary of faces visible to point + # being added. We're basically flood filling from central facet until + # we hit faces pointing away from reference point. + while !edges.is_empty(): + var edge:DirectedEdge = edges.pop_back() + visited_edges.append(edge) + var edge_inv:DirectedEdge = edge.reverse() + + var neighbor_facet:Facet = hull.get_facet_with_edge(edge_inv) + if neighbor_facet.plane.is_point_over(p_over): + visibile_faces.append(neighbor_facet) + visited_edges.append(edge_inv) + var neighbor_edges:Array[DirectedEdge] = neighbor_facet.get_edges() + for e in neighbor_edges: + if !visited_edges.any(func(edge): return edge.equals(e)): + #print("adding edge to search set %s" % e) + edges.append(e) + else: + boundary_edges.append(edge) + #print("adding edge to boundary set %s" % edge) + + var remaining_over_points:PackedVector3Array + for f in visibile_faces: + for pf in f.over_points: + if pf == p_over: + continue + if !remaining_over_points.has(pf): + remaining_over_points.append(pf) + #print("over point for test %s" % pf) + + hull.facets.remove_at(hull.facets.find(f)) + + for e in boundary_edges: + var f:Facet = Facet.new() + f.init_from_points(e.p0, e.p1, p_over) + hull.facets.append(f) + + #print("adding facet %s" % f) + + for p in remaining_over_points: + if f.plane.is_point_over(p) && !f.plane.has_point(p): + f.over_points.append(p) + + #print("hull %s" % hull.format_points()) + + hull = merge_coplanar_facets(hull) + return hull + + + diff --git a/addons/cyclops_level_builder/math/quick_hull.gd.uid b/addons/cyclops_level_builder/math/quick_hull.gd.uid new file mode 100644 index 00000000..b043349f --- /dev/null +++ b/addons/cyclops_level_builder/math/quick_hull.gd.uid @@ -0,0 +1 @@ +uid://bgdb08gme3jxm diff --git a/addons/cyclops_level_builder/math/segent_3.gd b/addons/cyclops_level_builder/math/segent_3.gd new file mode 100644 index 00000000..1b217a8c --- /dev/null +++ b/addons/cyclops_level_builder/math/segent_3.gd @@ -0,0 +1,43 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name Segment3 + +var p0:Vector3 +var p1:Vector3 + +func _init(p0:Vector3 = Vector3.ZERO, p1:Vector3 = Vector3.ZERO): + self.p0 = p0 + self.p1 = p1 + +func reversed()->Segment3: + return Segment3.new(p1, p0) + +func length_squared()->float: + return p0.distance_squared_to(p1) + + +func _to_string(): + return "[%s, %s]" % [str(p0), str(p1)] diff --git a/addons/cyclops_level_builder/math/segent_3.gd.uid b/addons/cyclops_level_builder/math/segent_3.gd.uid new file mode 100644 index 00000000..a00687fb --- /dev/null +++ b/addons/cyclops_level_builder/math/segent_3.gd.uid @@ -0,0 +1 @@ +uid://enm8i0y4nrs0 diff --git a/addons/cyclops_level_builder/menu/action_popup_menu.gd b/addons/cyclops_level_builder/menu/action_popup_menu.gd new file mode 100644 index 00000000..4ac8a734 --- /dev/null +++ b/addons/cyclops_level_builder/menu/action_popup_menu.gd @@ -0,0 +1,46 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PopupMenu +class_name ActionPopupMenu + +var action_map:Dictionary = {} + +func _ready(): + id_pressed.connect(on_id_pressed) + +func add_action_item(action:CyclopsAction): +# var id:int = action_map.size() + var id:int = action_map.size() + 1000 + add_item(action.name, id, action.accellerator) + action_map[id] = action + +#func add_separator(label:String, id:int = -1): +# pass + +func on_id_pressed(id:int): + var action:CyclopsAction = action_map[id] + action._execute() + + diff --git a/addons/cyclops_level_builder/menu/action_popup_menu.gd.uid b/addons/cyclops_level_builder/menu/action_popup_menu.gd.uid new file mode 100644 index 00000000..74da5699 --- /dev/null +++ b/addons/cyclops_level_builder/menu/action_popup_menu.gd.uid @@ -0,0 +1 @@ +uid://be3xbg17bp750 diff --git a/addons/cyclops_level_builder/menu/editor_toolbar.gd b/addons/cyclops_level_builder/menu/editor_toolbar.gd new file mode 100644 index 00000000..c9b65748 --- /dev/null +++ b/addons/cyclops_level_builder/menu/editor_toolbar.gd @@ -0,0 +1,231 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name EditorToolbar + +var editor_plugin:CyclopsLevelBuilder: + get: + return editor_plugin + set(value): + editor_plugin = value + editor_plugin.active_node_changed.connect(on_active_node_changed) + + build_ui() + + +var tool_button_group = ButtonGroup.new() +var override_shortcuts: Dictionary = {} #Dictionary[InputEvent, String] +var currently_in_3d := false + +func on_active_node_changed(): + update_grid() + + +# Called when the node enters the scene tree for the first time. +func _ready(): + + %Menu.clear() + %Menu.add_action_item(ActionToolDuplicate.new(editor_plugin)) + %Menu.add_action_item(ActionMergeSelectedBlocks.new(editor_plugin)) + %Menu.add_action_item(ActionSubtractBlock.new(editor_plugin)) + %Menu.add_action_item(ActionIntersectBlock.new(editor_plugin)) + %Menu.add_action_item(ActionDeleteSelectedBlocks.new(editor_plugin)) + %Menu.add_action_item(ActionSnapToGrid.new(editor_plugin)) + %Menu.add_action_item(ActionMergeVerticesCenter.new(editor_plugin)) + %Menu.add_separator() + %Menu.add_action_item(ActionConvertToMesh.new(editor_plugin)) + %Menu.add_action_item(ActionExportAsGltf.new(editor_plugin)) + %Menu.add_action_item(ActionExportAsGodotScene.new(editor_plugin)) + %Menu.add_action_item(ActionExportAsCyclops.new(editor_plugin)) + %Menu.add_separator() + %Menu.add_action_item(ActionRotateX90Ccw.new(editor_plugin)) + %Menu.add_action_item(ActionRotateX90Cw.new(editor_plugin)) + %Menu.add_action_item(ActionRotateX180.new(editor_plugin)) + %Menu.add_action_item(ActionMirrorSelectionX2.new(editor_plugin)) + %Menu.add_separator() + %Menu.add_action_item(ActionRotateY90Ccw.new(editor_plugin)) + %Menu.add_action_item(ActionRotateY90Cw.new(editor_plugin)) + %Menu.add_action_item(ActionRotateY180.new(editor_plugin)) + %Menu.add_action_item(ActionMirrorSelectionY2.new(editor_plugin)) + %Menu.add_separator() + %Menu.add_action_item(ActionRotateZ90Ccw.new(editor_plugin)) + %Menu.add_action_item(ActionRotateZ90Cw.new(editor_plugin)) + %Menu.add_action_item(ActionRotateZ180.new(editor_plugin)) + %Menu.add_action_item(ActionMirrorSelectionZ.new(editor_plugin)) + + var global_scene = get_node("/root/CyclopsAutoload") + + global_scene.xray_mode_changed.connect(on_xray_mode_changed) + %bn_xray.button_pressed = global_scene.xray_mode + + update_grid() + + + + +var prev_button_pressed: Button = null +func _press_button_line(button: Button) -> void: + if prev_button_pressed != null: + var line := prev_button_pressed.get_node_or_null('line') + if line != null: + prev_button_pressed.remove_child(line) + line.queue_free() + prev_button_pressed = null + + var new_line := ColorRect.new() + new_line.anchor_left = 0.05 + new_line.anchor_top = 0.9 + new_line.anchor_right = 0.95 + new_line.anchor_bottom = 0.94 + button.add_child(new_line) + new_line.name = 'line' + prev_button_pressed = button + + +func build_ui(): + #Tools + for child in %ToolButtonContainer.get_children(): + %ToolButtonContainer.remove_child(child) + + %snap_options.clear() + + if !editor_plugin: + return + + editor_plugin.main_screen_changed.connect(_on_main_screen_changed) + set_process_input(true) + + + var config:CyclopsConfig = editor_plugin.config + for tag: ToolTag in config.tool_tags: +# print("adding tag %s" % tag.name) + var bn:Button = Button.new() + if tag.icon: + bn.icon = tag.icon + else: + bn.text = tag.name + + bn.name = tag.name + + if !tag.input_events.is_empty(): #InputEvent + if tag.input_events_override: #bool + for v: InputEvent in tag.input_events: + override_shortcuts[v] = tag.name #for _input function + else: + bn.shortcut = Shortcut.new() + for v: InputEvent in tag.input_events: + bn.shortcut.events.append(v) + + bn.tooltip_text = tag.tooltip + bn.pressed.connect(func(): + _press_button_line(bn) + tag._activate(editor_plugin) + ) +# print("adding bn %s" % tag.name) + + %ToolButtonContainer.add_child(bn) + + %display_mode.select(editor_plugin.display_mode) + + #Snapping + for tag in config.snapping_tags: + if tag.icon: + %snap_options.add_icon_item(tag.icon, tag.name) + else: + %snap_options.add_item(tag.name) + +func update_grid(): + if !editor_plugin: + return + + #var size:int = editor_plugin.get_global_scene().grid_size + #$HBoxContainer/grid_size.select(size + 4) + + $HBoxContainer/display_mode.select(editor_plugin.display_mode) + + + +func _on_main_screen_changed(screen_name: String): + currently_in_3d = (screen_name == '3D') + +func _input(event: InputEvent) -> void: + if !currently_in_3d: return + + for v: InputEvent in override_shortcuts: + if event.is_match(v, true) and event.is_pressed() and not event.is_echo(): + var button := %ToolButtonContainer.get_node_or_null(override_shortcuts[v] as String) as Button + if button: + button.pressed.emit() #simulate press + break + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +#func _on_grid_size_item_selected(index): + #editor_plugin.get_global_scene().grid_size = index - 4 + + + +func _on_check_lock_uvs_toggled(button_pressed): + editor_plugin.lock_uvs = button_pressed + + + +func _on_display_mode_item_selected(index:int): + editor_plugin.display_mode = index + + +func on_xray_mode_changed(value:bool): + %bn_xray.button_pressed = value + +func _on_bn_xray_toggled(button_pressed:bool): + if !editor_plugin: + return + + var global_scene:CyclopsGlobalScene = editor_plugin.get_global_scene() + global_scene.xray_mode = button_pressed + +# +#func _on_bn_snap_settings_pressed(): +## var rect:Rect2 = %bn_snap_settings.get_rect() + # + #var rect:Rect2 = %bn_snap_settings.get_global_rect() + #var new_rect:Rect2 = Rect2(rect.position.x, rect.position.y + rect.size.y, 200, 100) + #%snap_settings_popup.popup_on_parent(new_rect) + ##print("snap popup2 ", rect) + + +func _on_snap_options_item_selected(index:int): + var tag:SnappingTag = editor_plugin.config.snapping_tags[index] + tag._activate(editor_plugin) + + + +func _on_bn_snap_toggled(toggled_on): + CyclopsAutoload.settings.set_property(CyclopsGlobalScene.SNAPPING_ENABLED, toggled_on) + pass # Replace with function body. diff --git a/addons/cyclops_level_builder/menu/editor_toolbar.gd.uid b/addons/cyclops_level_builder/menu/editor_toolbar.gd.uid new file mode 100644 index 00000000..f7e9c833 --- /dev/null +++ b/addons/cyclops_level_builder/menu/editor_toolbar.gd.uid @@ -0,0 +1 @@ +uid://hc6d52dbyik3 diff --git a/addons/cyclops_level_builder/menu/editor_toolbar.tscn b/addons/cyclops_level_builder/menu/editor_toolbar.tscn new file mode 100644 index 00000000..c6807255 --- /dev/null +++ b/addons/cyclops_level_builder/menu/editor_toolbar.tscn @@ -0,0 +1,129 @@ +[gd_scene load_steps=7 format=3 uid="uid://c3cl77r65dexu"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/menu/editor_toolbar.gd" id="1_o71fd"] +[ext_resource type="Script" path="res://addons/cyclops_level_builder/menu/action_popup_menu.gd" id="2_ni0c8"] +[ext_resource type="Texture2D" uid="uid://bs54uhn80ykrr" path="res://addons/cyclops_level_builder/art/icons/xray_normal.svg" id="3_ldp0l"] +[ext_resource type="Texture2D" uid="uid://dloyvoq8piwx0" path="res://addons/cyclops_level_builder/art/icons/snap.svg" id="4_begwr"] + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_o7kxq"] + +[sub_resource type="Theme" id="Theme_0hxey"] +PanelContainer/styles/panel = SubResource("StyleBoxEmpty_o7kxq") + +[node name="PanelContainer" type="PanelContainer"] +offset_right = 739.0 +offset_bottom = 31.0 +size_flags_horizontal = 3 +theme = SubResource("Theme_0hxey") +script = ExtResource("1_o71fd") + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="ToolButtonContainer" type="HBoxContainer" parent="HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="MenuBar" type="MenuBar" parent="HBoxContainer"] +layout_mode = 2 +prefer_global_menu = false + +[node name="Menu" type="PopupMenu" parent="HBoxContainer/MenuBar"] +unique_name_in_owner = true +item_count = 27 +item_0/text = "Duplicate Selected Blocks" +item_0/id = 1000 +item_1/text = "Merge Selected Blocks" +item_1/id = 1001 +item_2/text = "Subtract Block" +item_2/id = 1002 +item_3/text = "Intersect Blocks" +item_3/id = 1003 +item_4/text = "Delete Selected Blocks" +item_4/id = 1004 +item_5/text = "Snap to grid" +item_5/id = 1005 +item_6/text = "Merge Vertices Center" +item_6/id = 1006 +item_7/text = "" +item_7/id = -1 +item_7/separator = true +item_8/text = "Convert To Godot Mesh" +item_8/id = 1007 +item_9/text = "Export As Gltf..." +item_9/id = 1008 +item_10/text = "Export As Godot Scene..." +item_10/id = 1009 +item_11/text = "Export As Cyclops File..." +item_11/id = 1010 +item_12/text = "" +item_12/id = -1 +item_12/separator = true +item_13/text = "Rotate 90 Ccw X" +item_13/id = 1011 +item_14/text = "Rotate 90 Cw X" +item_14/id = 1012 +item_15/text = "Rotate 180 X" +item_15/id = 1013 +item_16/text = "Mirror Selection X" +item_16/id = 1014 +item_17/text = "" +item_17/id = -1 +item_17/separator = true +item_18/text = "Rotate 90 Ccw Y" +item_18/id = 1015 +item_19/text = "Rotate 90 Cw Y" +item_19/id = 1016 +item_20/text = "Rotate 180 Y" +item_20/id = 1017 +item_21/text = "Mirror Selection Y" +item_21/id = 1018 +item_22/text = "" +item_22/id = -1 +item_22/separator = true +item_23/text = "Rotate 90 Ccw Z" +item_23/id = 1019 +item_24/text = "Rotate 90 Cw Z" +item_24/id = 1020 +item_25/text = "Rotate 180 Z" +item_25/id = 1021 +item_26/text = "Mirror Selection Z" +item_26/id = 1022 +script = ExtResource("2_ni0c8") + +[node name="bn_snap" type="Button" parent="HBoxContainer"] +layout_mode = 2 +tooltip_text = "Snapping on/off" +toggle_mode = true +button_pressed = true +icon = ExtResource("4_begwr") + +[node name="snap_options" type="OptionButton" parent="HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Snapping system" + +[node name="display_mode" type="OptionButton" parent="HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "How the mesh is shown in the viewport." +item_count = 3 +selected = 1 +popup/item_0/text = "Wireframe" +popup/item_0/id = 0 +popup/item_1/text = "Mesh" +popup/item_1/id = 1 +popup/item_2/text = "Materials" +popup/item_2/id = 2 + +[node name="bn_xray" type="Button" parent="HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Xray" +toggle_mode = true +icon = ExtResource("3_ldp0l") + +[connection signal="toggled" from="HBoxContainer/bn_snap" to="." method="_on_bn_snap_toggled"] +[connection signal="item_selected" from="HBoxContainer/snap_options" to="." method="_on_snap_options_item_selected"] +[connection signal="item_selected" from="HBoxContainer/display_mode" to="." method="_on_display_mode_item_selected"] +[connection signal="toggled" from="HBoxContainer/bn_xray" to="." method="_on_bn_xray_toggled"] diff --git a/addons/cyclops_level_builder/menu/main_toolbar.gd b/addons/cyclops_level_builder/menu/main_toolbar.gd new file mode 100644 index 00000000..41a520fc --- /dev/null +++ b/addons/cyclops_level_builder/menu/main_toolbar.gd @@ -0,0 +1,39 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name MainToolbar + +var editor_plugin:CyclopsLevelBuilder + +# Called when the node enters the scene tree for the first time. +func _ready(): + %Cyclops.clear() + %Cyclops.add_action_item(ActionImportMeshInstance.new(editor_plugin)) + %Cyclops.add_action_item(ActionImportCyclopsFile.new(editor_plugin)) + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/addons/cyclops_level_builder/menu/main_toolbar.gd.uid b/addons/cyclops_level_builder/menu/main_toolbar.gd.uid new file mode 100644 index 00000000..09443399 --- /dev/null +++ b/addons/cyclops_level_builder/menu/main_toolbar.gd.uid @@ -0,0 +1 @@ +uid://dd7e0k6gr0sid diff --git a/addons/cyclops_level_builder/menu/main_toolbar.tscn b/addons/cyclops_level_builder/menu/main_toolbar.tscn new file mode 100644 index 00000000..d969248a --- /dev/null +++ b/addons/cyclops_level_builder/menu/main_toolbar.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://bm17ky7j4lwqc"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/menu/main_toolbar.gd" id="1_7i5xc"] +[ext_resource type="Script" path="res://addons/cyclops_level_builder/menu/action_popup_menu.gd" id="2_8w58b"] + +[node name="MainToolbar" type="PanelContainer"] +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("1_7i5xc") + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +layout_mode = 2 + +[node name="MenuBar" type="MenuBar" parent="HBoxContainer"] +layout_mode = 2 + +[node name="Cyclops" type="PopupMenu" parent="HBoxContainer/MenuBar"] +unique_name_in_owner = true +script = ExtResource("2_8w58b") diff --git a/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd b/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd new file mode 100644 index 00000000..493ad8ed --- /dev/null +++ b/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd @@ -0,0 +1,84 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name UpgradeCyclopsBlocksToolbar + +var editor_plugin:CyclopsLevelBuilder + +var activated:bool = false + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_bn_upgrade_pressed(): + var ed_iface:EditorInterface = editor_plugin.get_editor_interface() + var nodes:Array = ed_iface.get_selection().get_selected_nodes() + + if nodes.is_empty(): + return + + if !(nodes[0] is CyclopsBlocks): + return + + + var root:CyclopsBlocks = nodes[0] + var parent:Node = root.get_parent() + var index:int = root.get_index() + + var new_root:Node3D = Node3D.new() + root.add_sibling(new_root) + new_root.name = root.name + "_upgraded" + new_root.owner = ed_iface.get_edited_scene_root() + + root.visible = false + + #var grid_step_size:float = pow(2, editor_plugin.get_global_scene().grid_size) + + for child in root.get_children(): + if child is CyclopsConvexBlock: + var old_block:CyclopsConvexBlock = child + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(old_block.mesh_vector_data) + var centroid:Vector3 = vol.get_centroid() + #centroid = MathUtil.snap_to_grid(centroid, grid_step_size) + vol.translate(-centroid) + + var new_block:CyclopsBlock = CyclopsBlock.new() + new_root.add_child(new_block) + new_block.owner = ed_iface.get_edited_scene_root() + + new_block.name = old_block.name + new_block.materials = old_block.materials + new_block.mesh_vector_data = vol.to_mesh_vector_data() + new_block.global_transform = Transform3D.IDENTITY.translated(centroid) + diff --git a/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd.uid b/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd.uid new file mode 100644 index 00000000..30ce8181 --- /dev/null +++ b/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd.uid @@ -0,0 +1 @@ +uid://b155buk8rdjp2 diff --git a/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.tscn b/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.tscn new file mode 100644 index 00000000..2f4075da --- /dev/null +++ b/addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=2 format=3 uid="uid://u52a8gflbktl"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/menu/upgrade_cyclops_blocks_toolbar.gd" id="1_pbwhi"] + +[node name="PanelContainer" type="PanelContainer"] +offset_right = 40.0 +offset_bottom = 40.0 +script = ExtResource("1_pbwhi") + +[node name="bn_upgrade" type="Button" parent="."] +layout_mode = 2 +text = "Upgrade CyclopsBlocks" + +[connection signal="pressed" from="bn_upgrade" to="." method="_on_bn_upgrade_pressed"] diff --git a/addons/cyclops_level_builder/nodes/cyclops_block.gd b/addons/cyclops_level_builder/nodes/cyclops_block.gd new file mode 100644 index 00000000..66a387d9 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_block.gd @@ -0,0 +1,293 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Node3D +class_name CyclopsBlock + +signal mesh_changed + +var mesh_instance:MeshInstance3D +var mesh_wire:MeshInstance3D +var collision_body:PhysicsBody3D +var collision_shape:CollisionShape3D +var active:bool + +var dirty:bool = true + +var control_mesh:ConvexVolume + +@export var block_data:ConvexBlockData: + get: + return block_data + + set(value): + if block_data != value: + block_data = value + control_mesh = ConvexVolume.new() + control_mesh.init_from_convex_block_data(block_data) + + #Convert to mesh vector data + var mvd:MeshVectorData = MeshVectorData.new() + mvd.create_from_convex_block(block_data) + mesh_vector_data = mvd + + #dirty = true + #mesh_changed.emit() + +@export var mesh_vector_data:MeshVectorData: + set(value): + if mesh_vector_data != value: + mesh_vector_data = value + + control_mesh = ConvexVolume.new() + control_mesh.init_from_mesh_vector_data(mesh_vector_data) + + dirty = true + mesh_changed.emit() + +@export var materials:Array[Material] + +var default_material:Material = preload("res://addons/cyclops_level_builder/materials/grid.tres") +var display_mode:DisplayMode.Type = DisplayMode.Type.MATERIAL + +@export var collision_type:Collision.Type = Collision.Type.STATIC: + get: + return collision_type + set(value): + collision_type = value + update_physics_body() + +@export_flags_3d_physics var collision_layer:int = 1: + get: + return collision_layer + set(value): + collision_layer = value + if collision_body: + collision_body.collision_layer = collision_layer + +@export_flags_3d_physics var collision_mask:int = 1: + get: + return collision_mask + set(value): + collision_mask = value + if collision_body: + collision_body.collision_mask = collision_mask + +# Called when the node enters the scene tree for the first time. +func _ready(): + mesh_instance = MeshInstance3D.new() + add_child(mesh_instance) + mesh_instance.gi_mode = GeometryInstance3D.GI_MODE_STATIC + + #print("block owner path %s" % owner.get_path()) + + if Engine.is_editor_hint(): + mesh_wire = MeshInstance3D.new() + add_child(mesh_wire) + + collision_shape = CollisionShape3D.new() + + #occluder = OccluderInstance3D.new() + #add_child(occluder) + + build_from_block() + update_physics_body() + +func update_physics_body(): + + if collision_body: + collision_body.remove_child(collision_shape) + collision_body.queue_free() + collision_body = null + + match collision_type: + Collision.Type.STATIC: + collision_body = StaticBody3D.new() + Collision.Type.KINEMATIC: + collision_body = CharacterBody3D.new() + Collision.Type.RIGID: + collision_body = RigidBody3D.new() + + if collision_body: + collision_body.collision_layer = collision_layer + collision_body.collision_mask = collision_mask + add_child(collision_body) + + collision_body.add_child(collision_shape) + + +func build_from_block(): + #print("build_from_block") + + dirty = false + + mesh_instance.mesh = null + collision_shape.shape = null + + if Engine.is_editor_hint(): +# var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + var global_scene = get_node("/root/CyclopsAutoload") + display_mode = global_scene.builder.display_mode + +# print("block_data %s" % block_data) +# print("vert points %s" % block_data.vertex_points) + #if !block_data: + #return + if !mesh_vector_data: + return + +# print("got block data") + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(mesh_vector_data) + #vol.init_from_convex_block_data(block_data) + + #print("volume %s" % vol) + + var mesh:ArrayMesh + + if Engine.is_editor_hint(): + var global_scene = get_node("/root/CyclopsAutoload") + mesh_wire.mesh = vol.create_mesh_wire(global_scene.outline_material) + #print ("added wireframe") + + #print("rebuilding mesh") + if display_mode == DisplayMode.Type.MATERIAL: + mesh = vol.create_mesh(materials, default_material) + if display_mode == DisplayMode.Type.MESH: + mesh = vol.create_mesh(materials, default_material, true) + #print ("added faces") + else: + mesh = vol.create_mesh(materials, default_material) + + mesh_instance.mesh = mesh + + var shape:ConvexPolygonShape3D = ConvexPolygonShape3D.new() + shape.points = vol.get_points() + collision_shape.shape = shape + + #if !Engine.is_editor_hint(): + ##Disabling this in the editor for now since this is causing slowdown + #var occluder_object:ArrayOccluder3D = ArrayOccluder3D.new() + #occluder_object.vertices = vol.get_points() + #occluder_object.indices = vol.get_trimesh_indices() + #occluder.occluder = occluder_object + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + + build_from_block() + + if Engine.is_editor_hint(): +# var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + var global_scene = get_node("/root/CyclopsAutoload") + + if display_mode != global_scene.builder.display_mode: + dirty = true + return + +func draw_unit_labels(viewport_camera:Camera3D, local_to_world:Transform3D): + var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + + var font:Font = global_scene.units_font + var font_size:float = global_scene.units_font_size + var descent:float = font.get_descent(font_size) + var text_offset:Vector2 = Vector2(0, -global_scene.vertex_radius - descent) + + if control_mesh: + for e_idx in control_mesh.edges.size(): + var e:ConvexVolume.EdgeInfo = control_mesh.edges[e_idx] + var focus:Vector3 = local_to_world * e.get_midpoint() + if !viewport_camera.is_position_behind(focus): + var focus_2d:Vector2 = viewport_camera.unproject_position(focus) + + var v0:ConvexVolume.VertexInfo = control_mesh.vertices[e.start_index] + var v1:ConvexVolume.VertexInfo = control_mesh.vertices[e.end_index] + var distance:Vector3 = v1.point - v0.point + global_scene.draw_text("%.3f" % distance.length(), focus_2d, font, font_size) + + + +func append_mesh_outline(mesh:ImmediateMesh, viewport_camera:Camera3D, local_to_world:Transform3D, mat:Material): + #var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + + if control_mesh: + control_mesh.append_mesh_outline(mesh, viewport_camera, local_to_world, mat) + +func append_mesh_wire(mesh:ImmediateMesh): + var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + + var mat:Material = global_scene.outline_material + control_mesh.append_mesh_wire(mesh, mat) + + +func intersect_ray_closest(origin:Vector3, dir:Vector3)->IntersectResults: + if !mesh_vector_data: + return null + + var xform:Transform3D = global_transform.affine_inverse() + var origin_local:Vector3 = xform * origin + var dir_local:Vector3 = xform.basis * dir + + var result:IntersectResults = control_mesh.intersect_ray_closest(origin_local, dir_local) + if result: + result.object = self + + return result + + +func select_face(face_idx:int, select_type:Selection.Type = Selection.Type.REPLACE): + if select_type == Selection.Type.REPLACE: + for f in control_mesh.faces: + f.selected = f.index == face_idx + elif select_type == Selection.Type.ADD: + control_mesh.faces[face_idx].selected = true + elif select_type == Selection.Type.SUBTRACT: + control_mesh.faces[face_idx].selected = true + elif select_type == Selection.Type.TOGGLE: + control_mesh.faces[face_idx].selected = !control_mesh.faces[face_idx].selected + + mesh_changed.emit() + +func export_to_cyclops_file(file_builder:CyclopsFileBuilder)->Dictionary: + var result:Dictionary + + result["collision_type"] = Collision.Type.keys()[collision_type] + result["collision_layer"] = collision_layer + result["collision_mask"] = collision_mask + + var mat_res_paths:PackedStringArray + for mat in materials: + if mat: + mat_res_paths.append(mat.resource_path) + else: + mat_res_paths.append("") + result["materials"] = mat_res_paths + + if mesh_vector_data: + result["mesh"] = mesh_vector_data.to_dictionary(file_builder) + #build_mesh["mesh"] = cur_node.mesh_vector_data.to_dictionary(self) + return result + diff --git a/addons/cyclops_level_builder/nodes/cyclops_block.gd.uid b/addons/cyclops_level_builder/nodes/cyclops_block.gd.uid new file mode 100644 index 00000000..a80953b1 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_block.gd.uid @@ -0,0 +1 @@ +uid://cvisn0b641od4 diff --git a/addons/cyclops_level_builder/nodes/cyclops_blocks.gd b/addons/cyclops_level_builder/nodes/cyclops_blocks.gd new file mode 100644 index 00000000..d57beee8 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_blocks.gd @@ -0,0 +1,155 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Node3D +class_name CyclopsBlocks + +signal blocks_changed + +@export var occluder_vertex_offset:float = 0: + get: + return occluder_vertex_offset + set(value): + occluder_vertex_offset = value + dirty = true + +var dirty:bool = true + +var block_bodies:Node3D + +# Called when the node enters the scene tree for the first time. +func _ready(): + + child_entered_tree.connect(on_child_entered_tree) + child_exiting_tree.connect(on_child_exiting_tree) + + block_bodies = Node3D.new() + block_bodies.name = "block_bodies" + add_child(block_bodies) + + for node in get_children(): + if node is CyclopsConvexBlock: + var block:CyclopsConvexBlock = node + block.mesh_changed.connect(on_child_mesh_changed) + + + +func on_child_mesh_changed(): + dirty = true + blocks_changed.emit() + + +func on_child_entered_tree(node:Node): + if node is CyclopsConvexBlock: + var block:CyclopsConvexBlock = node + block.mesh_changed.connect(on_child_mesh_changed) + +# print("on_child_entered_tree %s" % node.name) + dirty = true + +func on_child_exiting_tree(node:Node): + if node is CyclopsConvexBlock: + var block:CyclopsConvexBlock = node + block.mesh_changed.disconnect(on_child_mesh_changed) + +# print("on_child_exited_tree %s" % node.name) + + dirty = true + +func has_selected_blocks()->bool: + for child in get_children(): + if child is CyclopsConvexBlock and child.selected: + return true + return false + + +func rebuild_mesh(): + for child in block_bodies.get_children(): + child.queue_free() + + for child in get_children(): + if child is CyclopsConvexBlock: + var block:CyclopsConvexBlock = child + +# var block_body:CyclopsConvexBlockBody = preload("res://addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd").instantiate() + var block_body:CyclopsConvexBlockBody = CyclopsConvexBlockBody.new() + block_body.materials = block.materials + block_body.block_data = block.block_data + block_bodies.add_child(block_body) + + + dirty = false + +func get_active_block()->CyclopsConvexBlock: + for child in get_children(): + if child is CyclopsConvexBlock: + var block:CyclopsConvexBlock = child + if block.active: + return block + return null + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + rebuild_mesh() + +func _input(event): + if Engine.is_editor_hint(): + pass + + #print(event.as_text()) + pass + +func intersect_ray_closest(origin:Vector3, dir:Vector3)->IntersectResults: + return intersect_ray_closest_filtered(origin, dir, func(block:CyclopsConvexBlock): return true) + +func intersect_ray_closest_selected_only(origin:Vector3, dir:Vector3)->IntersectResults: + return intersect_ray_closest_filtered(origin, dir, func(block:CyclopsConvexBlock): return block.selected) + +func intersect_ray_closest_filtered(origin:Vector3, dir:Vector3, filter:Callable)->IntersectResults: + var best_result:IntersectResults + + for child in get_children(): + if child is CyclopsConvexBlock: + var result:IntersectResults = child.intersect_ray_closest(origin, dir) + if result: + if !filter.call(result.object): + continue + + if !best_result or result.distance_squared < best_result.distance_squared: + best_result = result + + return best_result + +func intersect_frustum_all(frustum:Array[Plane])->Array[CyclopsConvexBlock]: + var result:Array[CyclopsConvexBlock] = [] + + for child in get_children(): + if child is CyclopsConvexBlock: + var block:CyclopsConvexBlock = child + var vol:ConvexVolume = block.control_mesh + if vol.intersects_frustum(frustum): + result.append(block) + + return result diff --git a/addons/cyclops_level_builder/nodes/cyclops_blocks.gd.uid b/addons/cyclops_level_builder/nodes/cyclops_blocks.gd.uid new file mode 100644 index 00000000..1e487add --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_blocks.gd.uid @@ -0,0 +1 @@ +uid://5e28c5ocyuws diff --git a/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png b/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png new file mode 100644 index 00000000..36922d79 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5f632146c885b8faafb10d0ce69adebde97b6cebc3f069402713e0f343fca374 +size 631 diff --git a/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png.import b/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png.import new file mode 100644 index 00000000..d1622bce --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bdmaqfi82aq41" +path="res://.godot/imported/cyclops_blocks_icon.png-24c4441d9ebe4c1c02b0cf9fcbf537f3.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/nodes/cyclops_blocks_icon.png" +dest_files=["res://.godot/imported/cyclops_blocks_icon.png-24c4441d9ebe4c1c02b0cf9fcbf537f3.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg b/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg new file mode 100644 index 00000000..9d6e2406 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + diff --git a/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg.import b/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg.import new file mode 100644 index 00000000..1c1ce7d3 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://chuwp6awho53q" +path="res://.godot/imported/cyclops_blocks_icon.svg-5e216ef2489ff1d30c472c6b8748fdf1.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/cyclops_level_builder/nodes/cyclops_blocks_icon.svg" +dest_files=["res://.godot/imported/cyclops_blocks_icon.svg-5e216ef2489ff1d30c472c6b8748fdf1.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/cyclops_level_builder/nodes/cyclops_convex_block.gd b/addons/cyclops_level_builder/nodes/cyclops_convex_block.gd new file mode 100644 index 00000000..7c71e0f7 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_convex_block.gd @@ -0,0 +1,124 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Node +class_name CyclopsConvexBlock + +signal mesh_changed + +@export var materials:Array[Material] + +var control_mesh:ConvexVolume + +var selected:bool = false: + get: + return selected + set(value): + if value == selected: + return + selected = value + mesh_changed.emit() + +var active:bool: + get: + return active + set(value): + if value == active: + return + active = value + mesh_changed.emit() + + +var default_material:Material = preload("res://addons/cyclops_level_builder/materials/grid.tres") + +@export var block_data:ConvexBlockData: + get: + return block_data + set(value): + if block_data != value: + block_data = value + control_mesh = ConvexVolume.new() + control_mesh.init_from_convex_block_data(block_data) + + mesh_changed.emit() + + +func intersect_ray_closest(origin:Vector3, dir:Vector3)->IntersectResults: + if !block_data: + return null + + var result:IntersectResults = control_mesh.intersect_ray_closest(origin, dir) + if result: +# result.object = self + result.object = null + + return result + + +func select_face(face_idx:int, select_type:Selection.Type = Selection.Type.REPLACE): + if select_type == Selection.Type.REPLACE: + for f in control_mesh.faces: + f.selected = f.index == face_idx + elif select_type == Selection.Type.ADD: + control_mesh.faces[face_idx].selected = true + elif select_type == Selection.Type.SUBTRACT: + control_mesh.faces[face_idx].selected = true + elif select_type == Selection.Type.TOGGLE: + control_mesh.faces[face_idx].selected = !control_mesh.faces[face_idx].selected + + mesh_changed.emit() + +func append_mesh(mesh:ImmediateMesh): +# print("adding block mesh %s" % name) + #var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + + control_mesh.append_mesh(mesh, materials, default_material) + +func append_mesh_wire(mesh:ImmediateMesh): + var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + + var mat:Material = global_scene.outline_material + control_mesh.append_mesh_wire(mesh, mat) + +func append_mesh_backfacing(mesh:ImmediateMesh): + var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + + var mat:Material = global_scene.tool_object_selected_material + control_mesh.append_mesh_backfacing(mesh, mat) + +func append_mesh_outline(mesh:ImmediateMesh, viewport_camera:Camera3D, local_to_world:Transform3D): + var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + + var mat:Material = global_scene.tool_object_active_material if active else global_scene.tool_object_selected_material + control_mesh.append_mesh_outline(mesh, viewport_camera, local_to_world, mat) + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + diff --git a/addons/cyclops_level_builder/nodes/cyclops_convex_block.gd.uid b/addons/cyclops_level_builder/nodes/cyclops_convex_block.gd.uid new file mode 100644 index 00000000..e484d919 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_convex_block.gd.uid @@ -0,0 +1 @@ +uid://dxktkpb8foag6 diff --git a/addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd b/addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd new file mode 100644 index 00000000..f660d2ab --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd @@ -0,0 +1,142 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Node3D +class_name CyclopsConvexBlockBody + +var mesh_instance:MeshInstance3D +var mesh_wire:MeshInstance3D +var collision_body:StaticBody3D +var collision_shape:CollisionShape3D +var occluder:OccluderInstance3D + +var dirty:bool = true + +@export var block_data:ConvexBlockData: + get: + return block_data + set(value): + block_data = value + dirty = true + + +@export var materials:Array[Material] + +var default_material:Material = preload("res://addons/cyclops_level_builder/materials/grid.tres") +var display_mode:DisplayMode.Type = DisplayMode.Type.MATERIAL + +# Called when the node enters the scene tree for the first time. +func _ready(): + mesh_instance = MeshInstance3D.new() + add_child(mesh_instance) + mesh_instance.gi_mode = GeometryInstance3D.GI_MODE_STATIC + + if Engine.is_editor_hint(): + mesh_wire = MeshInstance3D.new() + add_child(mesh_wire) + + collision_body = StaticBody3D.new() + add_child(collision_body) + collision_shape = CollisionShape3D.new() + collision_body.add_child(collision_shape) + + occluder = OccluderInstance3D.new() + add_child(occluder) + + build_from_block() + + +func build_from_block(): + + dirty = false + + mesh_instance.mesh = null + collision_shape.shape = null + + if Engine.is_editor_hint(): +# var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + var global_scene = get_node("/root/CyclopsAutoload") + display_mode = global_scene.builder.display_mode + +# print("block_data %s" % block_data) +# print("vert points %s" % block_data.vertex_points) + if !block_data: + return + +# print("got block data") + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_convex_block_data(block_data) + + #print("volume %s" % vol) + +# var mesh:ImmediateMesh = ImmediateMesh.new() + var mesh:ArrayMesh + + if Engine.is_editor_hint(): +# var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + var global_scene = get_node("/root/CyclopsAutoload") + mesh_wire.mesh = vol.create_mesh_wire(global_scene.outline_material) + + if display_mode == DisplayMode.Type.MATERIAL: + mesh = vol.create_mesh(materials, default_material) + elif display_mode == DisplayMode.Type.MESH: + mesh = vol.create_mesh(materials, default_material, true) + #print ("added faces") + else: + mesh = vol.create_mesh(materials, default_material) +# vol.append_mesh(mesh, materials, default_material) + + mesh_instance.mesh = mesh + +# print("===============") +# GeneralUtil.dump_properties(mesh_instance) +# print("---------------") +# GeneralUtil.dump_properties(mesh_instance.mesh) + + var shape:ConvexPolygonShape3D = ConvexPolygonShape3D.new() + shape.points = vol.get_points() + collision_shape.shape = shape + + if !Engine.is_editor_hint(): + #Disabling this in the editor for now since this is causing slowdown + var occluder_object:ArrayOccluder3D = ArrayOccluder3D.new() + occluder_object.vertices = vol.get_points() + occluder_object.indices = vol.get_trimesh_indices() + occluder.occluder = occluder_object + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + if dirty: + build_from_block() + + + if Engine.is_editor_hint(): +# var global_scene:CyclopsGlobalScene = get_node("/root/CyclopsAutoload") + var global_scene = get_node("/root/CyclopsAutoload") + + if display_mode != global_scene.builder.display_mode: + dirty = true + return + diff --git a/addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd.uid b/addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd.uid new file mode 100644 index 00000000..1cf92392 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_convex_block_body.gd.uid @@ -0,0 +1 @@ +uid://b2turnshb4e4j diff --git a/addons/cyclops_level_builder/nodes/cyclops_scene.gd b/addons/cyclops_level_builder/nodes/cyclops_scene.gd new file mode 100644 index 00000000..969b255c --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_scene.gd @@ -0,0 +1,35 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Node3D +class_name CyclopsScene + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/addons/cyclops_level_builder/nodes/cyclops_scene.gd.uid b/addons/cyclops_level_builder/nodes/cyclops_scene.gd.uid new file mode 100644 index 00000000..e19354ed --- /dev/null +++ b/addons/cyclops_level_builder/nodes/cyclops_scene.gd.uid @@ -0,0 +1 @@ +uid://tgbf30c787dj diff --git a/addons/cyclops_level_builder/nodes/intersect_results.gd b/addons/cyclops_level_builder/nodes/intersect_results.gd new file mode 100644 index 00000000..9d9a7dd7 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/intersect_results.gd @@ -0,0 +1,44 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name IntersectResults + +var object:CyclopsBlock +#var face_id:int +var face_index:int +var position:Vector3 #local space of block +var normal:Vector3 +var distance_squared:float + +func get_world_position()->Vector3: + return object.global_transform * position + +func get_world_normal()->Vector3: + var basis:Basis = object.global_transform.basis + var basis_normals:Basis = basis.inverse().transposed() + return basis_normals * normal + +func _to_string(): + return "object:%s face_idx:%s pos:%s norm:%s dist_sq:%s" % [object, face_index, position, normal, distance_squared] diff --git a/addons/cyclops_level_builder/nodes/intersect_results.gd.uid b/addons/cyclops_level_builder/nodes/intersect_results.gd.uid new file mode 100644 index 00000000..2df9eb17 --- /dev/null +++ b/addons/cyclops_level_builder/nodes/intersect_results.gd.uid @@ -0,0 +1 @@ +uid://bbqnhakrw3sg0 diff --git a/addons/cyclops_level_builder/plugin.cfg b/addons/cyclops_level_builder/plugin.cfg new file mode 100644 index 00000000..fb1e042c --- /dev/null +++ b/addons/cyclops_level_builder/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="Cyclops Level Builder" +description="Tools for rapidly blocking in levels." +author="Mark McKay" +version="1.0.4" +script="cyclops_level_builder.gd" diff --git a/addons/cyclops_level_builder/resources/block_data.gd b/addons/cyclops_level_builder/resources/block_data.gd new file mode 100644 index 00000000..eb4a10df --- /dev/null +++ b/addons/cyclops_level_builder/resources/block_data.gd @@ -0,0 +1,32 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name BlockData + +@export var points:PackedVector3Array #Per vertex +@export var uvs:PackedVector2Array #Per face corner uv info +@export var face_vertex_indices:PackedInt32Array #Vertex index per face +@export var face_vertex_count:PackedInt32Array #Number of verts in each face +@export var face_material_indices:PackedInt32Array #Material index for each face diff --git a/addons/cyclops_level_builder/resources/block_data.gd.uid b/addons/cyclops_level_builder/resources/block_data.gd.uid new file mode 100644 index 00000000..4ff536d1 --- /dev/null +++ b/addons/cyclops_level_builder/resources/block_data.gd.uid @@ -0,0 +1 @@ +uid://chncijcwrpqyg diff --git a/addons/cyclops_level_builder/resources/convex_block_data.gd b/addons/cyclops_level_builder/resources/convex_block_data.gd new file mode 100644 index 00000000..524b5b62 --- /dev/null +++ b/addons/cyclops_level_builder/resources/convex_block_data.gd @@ -0,0 +1,137 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ConvexBlockData + +@export var selected:bool = false +@export var active:bool = false +@export var collision:bool = true +@export_flags_3d_physics var physics_layer:int +@export_flags_3d_physics var physics_mask:int + +@export var vertex_points:PackedVector3Array #Per vertex +@export var vertex_selected:PackedByteArray #Per vertex + +@export var edge_selected:PackedByteArray + +@export var face_material_indices:PackedInt32Array #Material index for each face +@export var face_uv_transform:Array[Transform2D] +@export var face_visible:PackedByteArray +@export var face_color:PackedColorArray +@export var face_selected:PackedByteArray #Per face + +@export var face_vertex_face_index:PackedInt32Array #Face index of this face-vertex +@export var face_vertex_vertex_index:PackedInt32Array #Vertex index of this face-vertex +@export var face_vertex_normal:PackedVector3Array #Per face-vertex +@export var face_vertex_color:PackedColorArray #Per face-vertex + + +@export var edge_vertex_indices:PackedInt32Array +@export var edge_face_indices:PackedInt32Array + +@export var face_vertex_count:PackedInt32Array #Number of verts in each face +@export var face_vertex_indices:PackedInt32Array #Vertex indices encountered as you iterate over mesh one face at a time and each vertex per face + +@export var active_vertex:int +@export var active_edge:int +@export var active_face:int +@export var active_face_vertex:int + + +#Validate arrays to make sure they're the right size +#@deprecated +func validate_arrays(): + #print("deprecated validate_arrays") + var num_faces:int = face_vertex_count.size() + + if face_visible.size() < num_faces: + var arr:PackedByteArray + arr.resize(num_faces - face_visible.size()) + arr.fill(true) + face_visible.append_array(arr) + + + if face_color.size() < num_faces: + var arr:PackedColorArray + arr.resize(num_faces - face_color.size()) + arr.fill(Color.WHITE) + face_color.append_array(arr) + +func init_from_mesh_vector_data(mvd:MeshVectorData): + + active_vertex = mvd.active_vertex + active_edge = mvd.active_edge + active_face = mvd.active_face + active_face_vertex = mvd.active_face_vertex + + #selected = mvd.selected + #active = mvd.active + #collision = mvd.collision + #physics_layer = mvd.physics_layer + #physics_mask = mvd.physics_mask + + var v_pos:DataVectorFloat = mvd.get_vertex_data(MeshVectorData.V_POSITION) + vertex_points = v_pos.to_vec3_array() + + var v_sel:DataVectorByte = mvd.get_vertex_data(MeshVectorData.V_SELECTED) + vertex_selected = v_sel.data + + var e_sel:DataVectorByte = mvd.get_edge_data(MeshVectorData.E_SELECTED) + edge_selected = e_sel.data + + var f_mat:DataVectorInt = mvd.get_face_data(MeshVectorData.F_MATERIAL_INDEX) + face_material_indices = f_mat.data + +# print("+build convex_block_data") + var f_uv_xform:DataVectorFloat = mvd.get_face_data(MeshVectorData.F_UV_XFORM) + face_uv_transform = f_uv_xform.to_transform2d_array() +# print("-build convex_block_data") + + var f_vis:DataVectorByte = mvd.get_face_data(MeshVectorData.F_VISIBLE) + face_visible = f_vis.data + + var f_col:DataVectorFloat = mvd.get_face_data(MeshVectorData.F_COLOR) + face_color = f_col.to_color_array() + + var f_sel:DataVectorByte = mvd.get_face_data(MeshVectorData.F_SELECTED) + face_selected = f_sel.data + + var fv_fidx:DataVectorInt = mvd.get_face_vertex_data(MeshVectorData.FV_FACE_INDEX) + face_vertex_face_index = fv_fidx.data + + var fv_vidx:DataVectorInt = mvd.get_face_vertex_data(MeshVectorData.FV_VERTEX_INDEX) + face_vertex_vertex_index = fv_vidx.data + + var fv_norm:DataVectorFloat = mvd.get_face_vertex_data(MeshVectorData.FV_NORMAL) + face_vertex_normal = fv_norm.to_vec3_array() + + var fv_col:DataVectorFloat = mvd.get_face_vertex_data(MeshVectorData.FV_COLOR) + face_vertex_color = fv_col.to_color_array() + + edge_vertex_indices = mvd.edge_vertex_indices + edge_face_indices = mvd.edge_face_indices + face_vertex_count = mvd.face_vertex_count + face_vertex_indices = mvd.face_vertex_indices + diff --git a/addons/cyclops_level_builder/resources/convex_block_data.gd.uid b/addons/cyclops_level_builder/resources/convex_block_data.gd.uid new file mode 100644 index 00000000..36d9cba7 --- /dev/null +++ b/addons/cyclops_level_builder/resources/convex_block_data.gd.uid @@ -0,0 +1 @@ +uid://8vx604meg2mc diff --git a/addons/cyclops_level_builder/resources/cyclops_config.gd b/addons/cyclops_level_builder/resources/cyclops_config.gd new file mode 100644 index 00000000..5a97368a --- /dev/null +++ b/addons/cyclops_level_builder/resources/cyclops_config.gd @@ -0,0 +1,30 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name CyclopsConfig + +@export var tool_tags:Array[ToolTag] +@export var snapping_tags:Array[SnappingTag] + diff --git a/addons/cyclops_level_builder/resources/cyclops_config.gd.uid b/addons/cyclops_level_builder/resources/cyclops_config.gd.uid new file mode 100644 index 00000000..cbf95c05 --- /dev/null +++ b/addons/cyclops_level_builder/resources/cyclops_config.gd.uid @@ -0,0 +1 @@ +uid://ddqn8pj8hqmcv diff --git a/addons/cyclops_level_builder/resources/data_vector.gd b/addons/cyclops_level_builder/resources/data_vector.gd new file mode 100644 index 00000000..dbf84a6f --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector.gd @@ -0,0 +1,84 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name DataVector + +enum DataFormatType { BYTE, INT32, FLOAT32, STRING } +enum DataType { BOOL, INT, FLOAT, STRING, COLOR, VECTOR2, VECTOR3, VECTOR4, TRANSFORM_2D, TRANSFORM_3D } + +@export var name:StringName +@export var category:String #uv, color, weights, etc. +@export var data_type:DataType +@export var stride:int = 1 + +func get_data_format_type()->DataFormatType: + return DataFormatType.BYTE + +func size()->int: + return 0 + +func num_components()->int: + return size() / stride + +func get_buffer_byte_data()->PackedByteArray: + return [] + +#func to_dictionary(buffer_ar:BufferArchive)->Dictionary: + #var result:Dictionary + # + #result["name"] = name + #result["data_type"] = DataType.values()[data_type] + #if stride != 1: + #result["stride"] = stride + #if !category.is_empty(): + #result["category"] = category + # + #return result + +static func data_type_num_components(type:DataType)->int: + match type: + DataType.BOOL: + return 1 + DataType.INT: + return 1 + DataType.FLOAT: + return 1 + DataType.STRING: + return 1 + DataType.COLOR: + return 4 + DataType.VECTOR2: + return 2 + DataType.VECTOR3: + return 3 + DataType.VECTOR4: + return 4 + DataType.TRANSFORM_2D: + return 6 + DataType.TRANSFORM_3D: + return 12 + _: + push_error("Invalid data type") + return 1 diff --git a/addons/cyclops_level_builder/resources/data_vector.gd.uid b/addons/cyclops_level_builder/resources/data_vector.gd.uid new file mode 100644 index 00000000..853d3a4e --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector.gd.uid @@ -0,0 +1 @@ +uid://c1agkwubreosr diff --git a/addons/cyclops_level_builder/resources/data_vector_byte.gd b/addons/cyclops_level_builder/resources/data_vector_byte.gd new file mode 100644 index 00000000..19b0157e --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector_byte.gd @@ -0,0 +1,62 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends DataVector +class_name DataVectorByte + +@export var data:PackedByteArray + +func _init(name:StringName = "", data:PackedByteArray = [], data_type:DataType = DataType.BOOL): + self.name = name + self.data = data + self.data_type = data_type + self.stride = data_type_num_components(data_type) + + +func get_buffer_byte_data()->PackedByteArray: + return data + +#func to_dictionary(buffer_ar:BufferArchive)->Dictionary: + #var result:Dictionary = super(buffer_ar) + #var region:BufferArchive.BufferRegion = buffer_ar.store_buffer(data) + # +## result["data"] = Marshalls.raw_to_base64(data.compress()) + #result["data_buffer"] = region.index + # + #return result + +func get_data_format_type()->DataFormatType: + return DataFormatType.BYTE + +func size()->int: + return data.size() + +func resize(size:int): + data.resize(size * stride) + +func get_value(index:int)->int: + return data[index] + +func set_value(value:int, index:int): + data[index] = value diff --git a/addons/cyclops_level_builder/resources/data_vector_byte.gd.uid b/addons/cyclops_level_builder/resources/data_vector_byte.gd.uid new file mode 100644 index 00000000..5252534c --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector_byte.gd.uid @@ -0,0 +1 @@ +uid://djeq3sxhsep3c diff --git a/addons/cyclops_level_builder/resources/data_vector_float.gd b/addons/cyclops_level_builder/resources/data_vector_float.gd new file mode 100644 index 00000000..5eea45f1 --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector_float.gd @@ -0,0 +1,140 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends DataVector +class_name DataVectorFloat + +@export var data:PackedFloat32Array + +func _init(name:StringName = "", data:PackedFloat32Array = [], data_type:DataType = DataType.FLOAT): + self.name = name + self.data = data + self.data_type = data_type + self.stride = data_type_num_components(data_type) + +func get_data_format_type()->DataFormatType: + return DataFormatType.FLOAT32 + +func size()->int: + return data.size() + +func resize(size:int): + data.resize(size * stride) + +func get_value(index:int)->float: + return data[index] + +func to_vec2_array()->PackedVector2Array: + var result:PackedVector2Array + for i in num_components(): + result.append(get_value_vec2(i)) + return result + +func to_vec3_array()->PackedVector3Array: + var result:PackedVector3Array + for i in num_components(): + result.append(get_value_vec3(i)) + return result + +func to_vec4_array()->Array[Vector4]: + var result:Array[Vector4] + for i in num_components(): + result.append(get_value_vec4(i)) + return result + +func to_color_array()->PackedColorArray: + var result:PackedColorArray + for i in num_components(): + result.append(get_value_color(i)) + return result + +func to_transform2d_array()->Array[Transform2D]: + #print("to_transform2d_array num_components() ", num_components()) + var result:Array[Transform2D] + for i in num_components(): + result.append(get_value_transform2d(i)) + return result + +func get_value_vec2(index:int)->Vector2: + return Vector2(data[index * stride], data[index * stride + 1]) + +func get_value_vec3(index:int)->Vector3: + return Vector3(data[index * stride], data[index * stride + 1], data[index * stride + 2]) + +func get_value_vec4(index:int)->Vector4: + return Vector4(data[index * stride], data[index * stride + 1], data[index * stride + 2], data[index * stride + 3]) + +func get_value_color(index:int)->Color: + return Color(data[index * stride], data[index * stride + 1], data[index * stride + 2], data[index * stride + 3]) + +func get_value_transform2d(index:int)->Transform2D: + return Transform2D( + Vector2(data[index * stride], data[index * stride + 1]), + Vector2(data[index * stride + 2], data[index * stride + 3]), + Vector2(data[index * stride + 4], data[index * stride + 5]) + ) + +func get_value_transform3d(index:int)->Transform3D: + return Transform3D( + Vector3(data[index * stride], data[index * stride + 1], data[index * stride + 2]), + Vector3(data[index * stride + 3], data[index * stride + 4], data[index * stride + 5]), + Vector3(data[index * stride + 6], data[index * stride + 7], data[index * stride + 8]), + Vector3(data[index * stride + 9], data[index * stride + 10], data[index * stride + 11]) + ) + + +func set_value(value:int, index:int): + data[index] = value + +func set_value_vec2(value:Vector2, index:int): + data[index * stride] = value.x + data[index * stride + 1] = value.y + +func set_value_vec3(value:Vector3, index:int): + data[index * stride] = value.x + data[index * stride + 1] = value.y + data[index * stride + 2] = value.z + +func set_value_vec4(value:Vector4, index:int): + data[index * stride] = value.x + data[index * stride + 1] = value.y + data[index * stride + 2] = value.z + data[index * stride + 3] = value.w + +func set_value_color(value:Color, index:int): + data[index * stride] = value.r + data[index * stride + 1] = value.g + data[index * stride + 2] = value.b + data[index * stride + 3] = value.a + +func get_buffer_byte_data()->PackedByteArray: + return data.to_byte_array() + +#func to_dictionary(buffer_ar:BufferArchive)->Dictionary: + #var result:Dictionary = super(buffer_ar) + #var region:BufferArchive.BufferRegion = buffer_ar.store_buffer(data.to_byte_array()) + # + #result["data_buffer"] = region.index + # + #return result diff --git a/addons/cyclops_level_builder/resources/data_vector_float.gd.uid b/addons/cyclops_level_builder/resources/data_vector_float.gd.uid new file mode 100644 index 00000000..214a9655 --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector_float.gd.uid @@ -0,0 +1 @@ +uid://db41w3h28c2la diff --git a/addons/cyclops_level_builder/resources/data_vector_int.gd b/addons/cyclops_level_builder/resources/data_vector_int.gd new file mode 100644 index 00000000..a990a820 --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector_int.gd @@ -0,0 +1,85 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends DataVector +class_name DataVectorInt + +@export var data:PackedInt32Array + +func _init(name:StringName = "", data:PackedInt32Array = [], data_type:DataType = DataType.INT): + self.name = name + self.data = data + self.data_type = data_type + self.stride = data_type_num_components(data_type) + +func get_data_format_type()->DataFormatType: + return DataFormatType.INT32 + +func size()->int: + return data.size() + +func resize(size:int): + data.resize(size * stride) + +func get_value(index:int)->int: + return data[index] + +func get_value_ivec2(index:int)->Vector2i: + return Vector2i(data[index * stride], data[index * stride + 1]) + +func get_value_ivec3(index:int)->Vector3i: + return Vector3i(data[index * stride], data[index * stride + 1], data[index * stride + 2]) + +func get_value_ivec4(index:int)->Vector4i: + return Vector4i(data[index * stride], data[index * stride + 1], data[index * stride + 2], data[index * stride + 3]) + + +func set_value(value:int, index:int): + data[index] = value + +func set_value_ivec2(value:Vector2i, index:int): + data[index * stride] = value.x + data[index * stride + 1] = value.y + +func set_value_ivec3(value:Vector3i, index:int): + data[index * stride] = value.x + data[index * stride + 1] = value.y + data[index * stride + 2] = value.z + +func set_value_ivec4(value:Vector4i, index:int): + data[index * stride] = value.x + data[index * stride + 1] = value.y + data[index * stride + 2] = value.z + data[index * stride + 3] = value.w + +func get_buffer_byte_data()->PackedByteArray: + return data.to_byte_array() + +#func to_dictionary(buffer_ar:BufferArchive)->Dictionary: + #var result:Dictionary = super(buffer_ar) + #var region:BufferArchive.BufferRegion = buffer_ar.store_buffer(data.to_byte_array()) + # + #result["data_buffer"] = region.index + # + #return result diff --git a/addons/cyclops_level_builder/resources/data_vector_int.gd.uid b/addons/cyclops_level_builder/resources/data_vector_int.gd.uid new file mode 100644 index 00000000..9ebee7ca --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector_int.gd.uid @@ -0,0 +1 @@ +uid://civ3w78ahacnu diff --git a/addons/cyclops_level_builder/resources/data_vector_string.gd b/addons/cyclops_level_builder/resources/data_vector_string.gd new file mode 100644 index 00000000..fcff4a40 --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector_string.gd @@ -0,0 +1,61 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends DataVector +class_name DataVectorString + +@export var data:PackedStringArray + +func _init(name:StringName = "", data:PackedStringArray = [], data_type:DataType = DataType.STRING): + self.name = name + self.data = data + self.data_type = data_type + self.stride = data_type_num_components(data_type) + +func get_data_format_type()->DataFormatType: + return DataFormatType.STRING + +func size()->int: + return data.size() + +func resize(size:int): + data.resize(size * stride) + +func get_value(index:int)->String: + return data[index] + +func set_value(value:String, index:int): + data[index] = value + +func get_buffer_byte_data()->PackedByteArray: + return var_to_bytes(data) +# return data.to_byte_array() + +#func to_dictionary(buffer_ar:BufferArchive)->Dictionary: + #var result:Dictionary = super(buffer_ar) + #var region:BufferArchive.BufferRegion = buffer_ar.store_buffer(data.to_byte_array()) + # + #result["data_buffer"] = region.index + # + #return result diff --git a/addons/cyclops_level_builder/resources/data_vector_string.gd.uid b/addons/cyclops_level_builder/resources/data_vector_string.gd.uid new file mode 100644 index 00000000..d6005f3b --- /dev/null +++ b/addons/cyclops_level_builder/resources/data_vector_string.gd.uid @@ -0,0 +1 @@ +uid://bwk5jj2yko7nn diff --git a/addons/cyclops_level_builder/resources/mesh_vector_data.gd b/addons/cyclops_level_builder/resources/mesh_vector_data.gd new file mode 100644 index 00000000..a501e5aa --- /dev/null +++ b/addons/cyclops_level_builder/resources/mesh_vector_data.gd @@ -0,0 +1,369 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name MeshVectorData + + +#@export var selected:bool = false +#@export var active:bool = false +#@export var collision:bool = true +#@export_flags_3d_physics var physics_layer:int +#@export_flags_3d_physics var physics_mask:int + +@export var num_vertices:int +@export var num_edges:int +@export var num_faces:int +@export var num_face_vertices:int + +@export var active_vertex:int +@export var active_edge:int +@export var active_face:int +@export var active_face_vertex:int + + +@export var edge_vertex_indices:PackedInt32Array +@export var edge_face_indices:PackedInt32Array + +@export var face_vertex_count:PackedInt32Array #Number of verts in each face +@export var face_vertex_indices:PackedInt32Array #Vertex index per face + +@export var vertex_data:Dictionary +@export var edge_data:Dictionary +@export var face_data:Dictionary +@export var face_vertex_data:Dictionary + +const V_POSITION: StringName = "position" +const V_SELECTED: StringName = "selected" +const V_COLOR: StringName = "color" + +const E_SELECTED: StringName = "selected" + +const F_MATERIAL_INDEX: StringName = "material_index" +const F_UV_XFORM: StringName = "uv_transform" +const F_VISIBLE: StringName = "visible" +const F_COLOR: StringName = "color" +const F_SELECTED: StringName = "selected" + +const FV_VERTEX_INDEX: StringName = "vertex_index" +const FV_FACE_INDEX: StringName = "face_index" +const FV_VERTEX_LOCAL_INDEX: StringName = "vertex_local_index" +const FV_SELECTED: StringName = "selected" +const FV_COLOR: StringName = "color" +const FV_NORMAL: StringName = "normal" +const FV_UV1: StringName = "uv1" +const FV_UV2: StringName = "uv2" + + +func create_from_convex_block(block_data:ConvexBlockData): + + #selected = block_data.selected + #active = block_data.active + #collision = block_data.collision + #physics_layer = block_data.physics_layer + #physics_mask = block_data.physics_mask + + active_vertex = block_data.active_vertex + active_edge = block_data.active_edge + active_face = block_data.active_face + active_face_vertex = block_data.active_face_vertex + + num_vertices = block_data.vertex_points.size() + num_edges = block_data.edge_vertex_indices.size() / 2 + num_faces = block_data.face_vertex_count.size() + + set_vertex_data(DataVectorFloat.new(V_POSITION, + block_data.vertex_points.to_byte_array().to_float32_array(), + DataVector.DataType.VECTOR3)) + + set_vertex_data(DataVectorByte.new(V_SELECTED, + block_data.vertex_selected, + DataVector.DataType.BOOL)) + + set_edge_data(DataVectorByte.new(E_SELECTED, + block_data.edge_selected, + DataVector.DataType.BOOL)) + + set_face_data(DataVectorInt.new(F_MATERIAL_INDEX, + block_data.face_material_indices, + DataVector.DataType.INT)) + + set_face_data(DataVectorByte.new(F_VISIBLE, + block_data.face_visible, + DataVector.DataType.BOOL)) + + set_face_data(DataVectorFloat.new(F_COLOR, + block_data.face_color.to_byte_array().to_float32_array(), + DataVector.DataType.COLOR)) + + var f_uv_xform:PackedFloat32Array + for t in block_data.face_uv_transform: + f_uv_xform.append_array([t.x.x, t.x.y, t.y.x, t.y.y, t.origin.x, t.origin.y]) + set_face_data(DataVectorFloat.new(F_UV_XFORM, + f_uv_xform, + DataVector.DataType.TRANSFORM_2D)) + + + set_face_data(DataVectorByte.new(F_SELECTED, + block_data.face_selected, + DataVector.DataType.BOOL)) + + set_face_data(DataVectorFloat.new(F_COLOR, + block_data.face_color.to_byte_array().to_float32_array(), + DataVector.DataType.COLOR)) + + + #Create face-vertex data + edge_vertex_indices = block_data.edge_vertex_indices + edge_face_indices = block_data.edge_face_indices + face_vertex_count = block_data.face_vertex_count + face_vertex_indices = block_data.face_vertex_indices + + num_face_vertices = 0 + for n in block_data.face_vertex_count: + num_face_vertices += n + + var fv_array_offset:int = 0 + var next_fv_idx:int = 0 + var face_indices:PackedInt32Array + var vert_indices:PackedInt32Array + + for f_idx in block_data.face_vertex_count.size(): + var num_verts_in_face:int = block_data.face_vertex_count[f_idx] + for fv_local_idx in num_verts_in_face: + var v_idx:int = block_data.face_vertex_indices[fv_array_offset + fv_local_idx] + + face_indices.append(f_idx) + vert_indices.append(v_idx) + + fv_array_offset += num_verts_in_face + + + set_face_vertex_data(DataVectorInt.new(FV_FACE_INDEX, + face_indices, + DataVector.DataType.INT)) + + set_face_vertex_data(DataVectorInt.new(FV_VERTEX_INDEX, + vert_indices, + DataVector.DataType.INT)) + + #set_face_vertex_data(DataVectorInt.new(FV_VERTEX_LOCAL_INDEX, + #fv_local_indices, + #DataVector.DataType.INT)) + + if block_data.face_vertex_color.is_empty(): + #Construct face vertex colors from old face colors system + var col_fv_data:PackedColorArray + for fv_idx in num_face_vertices: + var f_idx:int = face_indices[fv_idx] + var v_idx:int = vert_indices[fv_idx] + col_fv_data.append(block_data.face_color[f_idx]) + + + set_face_vertex_data(DataVectorFloat.new(FV_COLOR, + col_fv_data.to_byte_array().to_float32_array(), + DataVector.DataType.COLOR)) + else: + #Copy face vertex colors + set_face_vertex_data(DataVectorFloat.new(FV_COLOR, + block_data.face_vertex_color.to_byte_array().to_float32_array(), + DataVector.DataType.COLOR)) + + set_face_vertex_data(DataVectorFloat.new(FV_NORMAL, + block_data.face_vertex_normal.to_byte_array().to_float32_array(), + DataVector.DataType.VECTOR3)) + + +func get_vertex_data(vector_name:String)->DataVector: + return vertex_data[vector_name] + +func get_edge_data(vector_name:String)->DataVector: + return edge_data[vector_name] + +func get_face_data(vector_name:String)->DataVector: + return face_data[vector_name] + +func get_face_vertex_data(vector_name:String)->DataVector: + return face_vertex_data[vector_name] + +func set_vertex_data(data_vector:DataVector): + vertex_data[data_vector.name] = data_vector + +func set_edge_data(data_vector:DataVector): + edge_data[data_vector.name] = data_vector + +func set_face_data(data_vector:DataVector): + face_data[data_vector.name] = data_vector + +func set_face_vertex_data(data_vector:DataVector): + face_vertex_data[data_vector.name] = data_vector + +func validate()->bool: + return true + + +func create_vector_xml_node(name:String, type:String, value:String)->XMLElement: + var evi_ele:XMLElement = XMLElement.new("vector") + evi_ele.set_attribute("name", name) + evi_ele.set_attribute("type", type) + evi_ele.set_attribute("value", value) + return evi_ele + +func section_to_xml(type:String, vertex_data:Dictionary)->XMLElement: + var sec_vertex_ele:XMLElement = XMLElement.new("section") + sec_vertex_ele.set_attribute("type", type) + + for vec_name in vertex_data.keys(): + var v:DataVector = vertex_data[vec_name] + match v.data_type: + DataVector.DataType.BOOL: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "bool", var_to_str(v.data))) + DataVector.DataType.INT: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "int", var_to_str(v.data))) + DataVector.DataType.FLOAT: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "float", var_to_str(v.data))) + DataVector.DataType.STRING: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "string", var_to_str(v.data))) + DataVector.DataType.COLOR: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "color", var_to_str(v.data))) + DataVector.DataType.VECTOR2: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "vector2", var_to_str(v.data))) + DataVector.DataType.VECTOR3: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "vector3", var_to_str(v.data))) + DataVector.DataType.VECTOR4: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "vector4", var_to_str(v.data))) + DataVector.DataType.TRANSFORM_2D: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "transform2D", var_to_str(v.data))) + DataVector.DataType.TRANSFORM_3D: + sec_vertex_ele.add_child(create_vector_xml_node(v.name, "transform3D", var_to_str(v.data))) + + return sec_vertex_ele + +func to_xml()->XMLElement: + var rec_ele:XMLElement = XMLElement.new("record") + rec_ele.set_attribute("type", "mesh") + + #rec_ele.set_attribute("selected", str(selected)) + #rec_ele.set_attribute("active", str(active)) + #rec_ele.set_attribute("collision", str(collision)) + #rec_ele.set_attribute("physics_layer", str(physics_layer)) + #rec_ele.set_attribute("physics_mask", str(physics_mask)) + + rec_ele.set_attribute("num_vertices", str(num_vertices)) + rec_ele.set_attribute("num_edges", str(num_edges)) + rec_ele.set_attribute("num_faces", str(num_faces)) + rec_ele.set_attribute("num_face_vertices", str(num_face_vertices)) + + + rec_ele.add_child(create_vector_xml_node("edge_vertex_indices", "int", var_to_str(edge_vertex_indices))) + rec_ele.add_child(create_vector_xml_node("edge_face_indices", "int", var_to_str(edge_face_indices))) + rec_ele.add_child(create_vector_xml_node("face_vertex_count", "int", var_to_str(face_vertex_count))) + rec_ele.add_child(create_vector_xml_node("face_vertex_indices", "int", var_to_str(face_vertex_indices))) + + rec_ele.set_attribute("active_vertex", str(active_vertex)) + rec_ele.set_attribute("active_edge", str(active_edge)) + rec_ele.set_attribute("active_face", str(active_face)) + rec_ele.set_attribute("active_face_vertex", str(active_face_vertex)) + + var sec_vertex_ele:XMLElement = XMLElement.new("data") + sec_vertex_ele.set_attribute("type", "vertex") + rec_ele.add_child(sec_vertex_ele) + + rec_ele.add_child(section_to_xml("vertex", vertex_data)) + rec_ele.add_child(section_to_xml("edge", edge_data)) + rec_ele.add_child(section_to_xml("face", face_data)) + rec_ele.add_child(section_to_xml("faceVertex", face_vertex_data)) + + + return rec_ele + +func to_dictionary(file_builder:CyclopsFileBuilder)->Dictionary: + var result:Dictionary + + result["num_vertices"] = num_vertices + result["num_edges"] = num_edges + result["num_faces"] = num_faces + result["num_face_vertices"] = num_face_vertices + + result["active_vertex"] = active_vertex + result["active_edge"] = active_edge + result["active_face"] = active_face + result["active_face_vertex"] = active_face_vertex + +# vectors["face_vertices"].append(file_builder.export_vector(data_vec)) + result["edge_vertex_index_buffer"] = file_builder.export_byte_array(edge_vertex_indices.to_byte_array()) + result["edge_face_index_buffer"] = file_builder.export_byte_array(edge_face_indices.to_byte_array()) + result["face_vertex_count_buffer"] = file_builder.export_byte_array(face_vertex_count.to_byte_array()) + result["face_vertex_index_buffer"] = file_builder.export_byte_array(face_vertex_indices.to_byte_array()) + #result["edge_vertex_indices"] = edge_vertex_indices + #result["edge_face_indices"] = edge_face_indices + # + #result["face_vertex_count"] = face_vertex_count + #result["face_vertex_indices"] = face_vertex_indices + + var vectors:Dictionary = { + "vertices": [], + "edges": [], + "faces": [], + "face_vertices": [] + } + result["vectors"] = vectors + + for key in vertex_data.keys(): + var data_vec:DataVector = vertex_data[key] +# vectors["vertices"].append(data_vec.to_dictionary(buf_ar)) + vectors["vertices"].append(file_builder.export_vector(data_vec)) + + for key in edge_data.keys(): + var data_vec:DataVector = edge_data[key] +# vectors["edges"].append(data_vec.to_dictionary(buf_ar)) + vectors["edges"].append(file_builder.export_vector(data_vec)) + + for key in face_data.keys(): + var data_vec:DataVector = face_data[key] +# vectors["faces"].append(data_vec.to_dictionary(buf_ar)) + vectors["faces"].append(file_builder.export_vector(data_vec)) + + for key in face_vertex_data.keys(): + var data_vec:DataVector = face_vertex_data[key] +# vectors["face_vertices"].append(data_vec.to_dictionary(buf_ar)) + vectors["face_vertices"].append(file_builder.export_vector(data_vec)) + + return result + +#func export_vector(vec:DataVector, file_builder:CyclopsFileBuilder)->Dictionary: + #var result:Dictionary + # + #result["name"] = vec.name + #result["data_type"] = DataVector.DataType.values()[vec.data_type] + #if vec.stride != 1: + #result["stride"] = vec.stride + #if !vec.category.is_empty(): + #result["category"] = vec.category + # + #var region:BufferArchive.BufferRegion = file_builder.buf_ar.store_buffer(vec.get_buffer_byte_data()) + #result["data_buffer"] = region.index + # + #return result + diff --git a/addons/cyclops_level_builder/resources/mesh_vector_data.gd.uid b/addons/cyclops_level_builder/resources/mesh_vector_data.gd.uid new file mode 100644 index 00000000..21bda348 --- /dev/null +++ b/addons/cyclops_level_builder/resources/mesh_vector_data.gd.uid @@ -0,0 +1 @@ +uid://c43o57os2lmc3 diff --git a/addons/cyclops_level_builder/resources/tool_tag.gd b/addons/cyclops_level_builder/resources/tool_tag.gd new file mode 100644 index 00000000..5d1799d5 --- /dev/null +++ b/addons/cyclops_level_builder/resources/tool_tag.gd @@ -0,0 +1,50 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolTag + +@export var id:String +@export var name:String +@export var input_events: Array[InputEvent] = [] +@export var input_events_override := false +@export_multiline var tooltip:String +@export var icon:Texture2D +@export var tool_script:Script + +var tool:CyclopsTool + +func _activate(plugin:CyclopsLevelBuilder): + if !tool_script: + return + + if !tool: + tool = tool_script.new() + + +# print("Activating %s" % tool_script.resource_path) +# print("tool id %s" % tool._get_tool_id()) + +# print("Activating %s" % name) + plugin.switch_to_tool(tool) diff --git a/addons/cyclops_level_builder/resources/tool_tag.gd.uid b/addons/cyclops_level_builder/resources/tool_tag.gd.uid new file mode 100644 index 00000000..d074aec2 --- /dev/null +++ b/addons/cyclops_level_builder/resources/tool_tag.gd.uid @@ -0,0 +1 @@ +uid://cewve1gm2ssbu diff --git a/addons/cyclops_level_builder/shaders/outline_shader.tres b/addons/cyclops_level_builder/shaders/outline_shader.tres new file mode 100644 index 00000000..f39feff7 --- /dev/null +++ b/addons/cyclops_level_builder/shaders/outline_shader.tres @@ -0,0 +1,67 @@ +[gd_resource type="VisualShader" load_steps=5 format=3 uid="uid://cc5tovf48xmg1"] + +[sub_resource type="VisualShaderNodeColorConstant" id="VisualShaderNodeColorConstant_mqcg1"] +constant = Color(0, 0, 0, 1) + +[sub_resource type="VisualShaderNodeColorParameter" id="VisualShaderNodeColorParameter_kvn47"] +parameter_name = "ColorParameter" +default_value_enabled = true +default_value = Color(0, 0, 0, 1) + +[sub_resource type="VisualShaderNodeLinearSceneDepth" id="VisualShaderNodeLinearSceneDepth_d3ao7"] + +[sub_resource type="VisualShaderNodeFloatOp" id="VisualShaderNodeFloatOp_pyrux"] +default_input_values = [0, 0.0, 1, 1.0] + +[resource] +code = "shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx; + +uniform vec4 ColorParameter : source_color = vec4(0.000000, 0.000000, 0.000000, 1.000000); +uniform sampler2D depth_tex_frg_4 : hint_depth_texture; + + + +void fragment() { +// ColorConstant:2 + vec4 n_out2p0 = vec4(0.000000, 0.000000, 0.000000, 1.000000); + + +// ColorParameter:3 + vec4 n_out3p0 = ColorParameter; + + + float n_out4p0; +// LinearSceneDepth:4 + { + float __log_depth = textureLod(depth_tex_frg_4, SCREEN_UV, 0.0).x; + vec4 __depth_view = INV_PROJECTION_MATRIX * vec4(vec3(SCREEN_UV, __log_depth) * 2.0 - 1.0, 1.0); + __depth_view.xyz /= __depth_view.w; + n_out4p0 = -__depth_view.z; + } + + +// FloatOp:5 + float n_in5p1 = 1.00000; + float n_out5p0 = n_out4p0 + n_in5p1; + + +// Output:0 + ALBEDO = vec3(n_out2p0.xyz); + EMISSION = vec3(n_out3p0.xyz); + NORMAL_MAP_DEPTH = n_out5p0; + + +} +" +graph_offset = Vector2(-10.4364, 103.709) +nodes/fragment/0/position = Vector2(480, 140) +nodes/fragment/2/node = SubResource("VisualShaderNodeColorConstant_mqcg1") +nodes/fragment/2/position = Vector2(227.319, 156.469) +nodes/fragment/3/node = SubResource("VisualShaderNodeColorParameter_kvn47") +nodes/fragment/3/position = Vector2(80, 280) +nodes/fragment/4/node = SubResource("VisualShaderNodeLinearSceneDepth_d3ao7") +nodes/fragment/4/position = Vector2(0, 560) +nodes/fragment/5/node = SubResource("VisualShaderNodeFloatOp_pyrux") +nodes/fragment/5/position = Vector2(260, 520) +nodes/fragment/connections = PackedInt32Array(2, 0, 0, 0, 3, 0, 0, 5, 4, 0, 5, 0, 5, 0, 0, 10) diff --git a/addons/cyclops_level_builder/shaders/tool_outline_shader.tres b/addons/cyclops_level_builder/shaders/tool_outline_shader.tres new file mode 100644 index 00000000..ad3d116b --- /dev/null +++ b/addons/cyclops_level_builder/shaders/tool_outline_shader.tres @@ -0,0 +1,38 @@ +[gd_resource type="VisualShader" load_steps=3 format=3 uid="uid://c33k8fbmgw46b"] + +[sub_resource type="VisualShaderNodeColorConstant" id="VisualShaderNodeColorConstant_mqcg1"] +constant = Color(0, 0, 0, 1) + +[sub_resource type="VisualShaderNodeColorParameter" id="VisualShaderNodeColorParameter_kvn47"] +parameter_name = "ColorParameter" +default_value_enabled = true +default_value = Color(1, 1, 0, 1) + +[resource] +code = "shader_type spatial; +uniform vec4 ColorParameter : source_color = vec4(1.000000, 1.000000, 0.000000, 1.000000); + + + +void fragment() { +// ColorConstant:2 + vec4 n_out2p0 = vec4(0.000000, 0.000000, 0.000000, 1.000000); + + +// ColorParameter:3 + vec4 n_out3p0 = ColorParameter; + + +// Output:0 + ALBEDO = vec3(n_out2p0.xyz); + EMISSION = vec3(n_out3p0.xyz); + + +} +" +nodes/fragment/0/position = Vector2(480, 140) +nodes/fragment/2/node = SubResource("VisualShaderNodeColorConstant_mqcg1") +nodes/fragment/2/position = Vector2(227.319, 156.469) +nodes/fragment/3/node = SubResource("VisualShaderNodeColorParameter_kvn47") +nodes/fragment/3/position = Vector2(80, 280) +nodes/fragment/connections = PackedInt32Array(2, 0, 0, 0, 3, 0, 0, 5) diff --git a/addons/cyclops_level_builder/shaders/vertex_shader.tres b/addons/cyclops_level_builder/shaders/vertex_shader.tres new file mode 100644 index 00000000..5ee3ea99 --- /dev/null +++ b/addons/cyclops_level_builder/shaders/vertex_shader.tres @@ -0,0 +1,60 @@ +[gd_resource type="Shader" format=3 uid="uid://dewb6ohh2wxv0"] + +[resource] +code = "// NOTE: Shader automatically converted from Godot Engine 4.0.2.stable's StandardMaterial3D. + +shader_type spatial; +render_mode blend_mix,depth_draw_never,cull_disabled,diffuse_burley,specular_schlick_ggx,ambient_light_disabled,alpha_to_coverage; +uniform float radius = 4; + +uniform sampler2D texture_emission : source_color, hint_default_black,filter_linear_mipmap,repeat_enable; +uniform vec4 emission : source_color; +uniform float emission_energy; + +uniform float alpha_scissor_threshold; +uniform float alpha_antialiasing_edge; + +void vertex() { + //UV=UV*uv1_scale.xy+uv1_offset.xy; + + vec4 model_pos_world = MODEL_MATRIX[3]; +// vec4 cam_origin_world = INV_VIEW_MATRIX[3]; + vec4 model_origin_cam_space = VIEW_MATRIX * model_pos_world; + vec4 model_origin_proj_space = PROJECTION_MATRIX * VIEW_MATRIX * model_pos_world; + model_origin_proj_space /= model_origin_proj_space.w; + vec4 offset_proj_space = model_origin_proj_space + vec4(0.0, radius / VIEWPORT_SIZE.y, 0.0, 0.0); + vec4 offset_cam_space = INV_PROJECTION_MATRIX * offset_proj_space; + offset_cam_space /= offset_cam_space.w; + + vec4 radius_offset_cam_space = offset_cam_space - model_origin_cam_space; + +// float scale = length(model_origin_cam_space.xyz) * radius * 5.0 / VIEWPORT_SIZE.y; + float scale = length(radius_offset_cam_space.xy) * 10.0; + + mat4 SCALE = mat4(vec4(scale, 0.0, 0.0, 0.0), + vec4(0.0, scale, 0.0, 0.0), + vec4(0.0, 0.0, scale, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); + + MODELVIEW_MATRIX = VIEW_MATRIX * mat4(INV_VIEW_MATRIX[0], INV_VIEW_MATRIX[1], INV_VIEW_MATRIX[2], MODEL_MATRIX[3]) * SCALE; + + MODELVIEW_NORMAL_MATRIX = mat3(MODELVIEW_MATRIX); +} + + + +void fragment() { + vec2 base_uv = UV; + vec4 emission_tex = texture(texture_emission, base_uv); + emission_tex *= COLOR * emission; + + ALBEDO = vec3(0.0, 0.0, 0.0); + EMISSION = emission_tex.xyz; + + ALPHA = emission_tex.a; + ALPHA_SCISSOR_THRESHOLD = alpha_scissor_threshold; + ALPHA_ANTIALIASING_EDGE = alpha_antialiasing_edge; + ALPHA_TEXTURE_COORDINATE = UV; +} + +" diff --git a/addons/cyclops_level_builder/snapping/cyclops_snapping_system.gd b/addons/cyclops_level_builder/snapping/cyclops_snapping_system.gd new file mode 100644 index 00000000..c8115415 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/cyclops_snapping_system.gd @@ -0,0 +1,67 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool + +extends Resource +class_name CyclopsSnappingSystem + +var move_constraint:MoveConstraint.Type = MoveConstraint.Type.NONE + +var plugin:CyclopsLevelBuilder + +func _activate(plugin:CyclopsLevelBuilder): + self.plugin = plugin + +func _deactivate(): + pass + +func _snap_point(point:Vector3, query:SnappingQuery)->Vector3: + return point + +func _snap_angle(angle:float, query:SnappingQuery)->float: + return angle + +func _get_properties_editor()->Control: + return null + +func constrain_point(point:Vector3, target_point:Vector3, move_constraint:MoveConstraint.Type = MoveConstraint.Type.NONE)->Vector3: + match move_constraint: + MoveConstraint.Type.NONE: + return target_point + MoveConstraint.Type.AXIS_X: + return Vector3(target_point.x, point.y, point.z) + MoveConstraint.Type.AXIS_Y: + return Vector3(point.x, target_point.y, point.z) + MoveConstraint.Type.AXIS_Z: + return Vector3(point.x, point.y, target_point.z) + MoveConstraint.Type.PLANE_XY: + return Vector3(target_point.x, target_point.y, point.z) + MoveConstraint.Type.PLANE_XZ: + return Vector3(target_point.x, point.y, target_point.z) + MoveConstraint.Type.PLANE_YZ: + return Vector3(point.x, target_point.y, target_point.z) + _: + return point + + diff --git a/addons/cyclops_level_builder/snapping/cyclops_snapping_system.gd.uid b/addons/cyclops_level_builder/snapping/cyclops_snapping_system.gd.uid new file mode 100644 index 00000000..cccad3bf --- /dev/null +++ b/addons/cyclops_level_builder/snapping/cyclops_snapping_system.gd.uid @@ -0,0 +1 @@ +uid://cstrpukb5136q diff --git a/addons/cyclops_level_builder/snapping/move_constraint.gd b/addons/cyclops_level_builder/snapping/move_constraint.gd new file mode 100644 index 00000000..e2a44171 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/move_constraint.gd @@ -0,0 +1,28 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name MoveConstraint + +enum Type { NONE, AXIS_X, AXIS_Y, AXIS_Z, PLANE_XY, PLANE_XZ, PLANE_YZ, PLANE_VIEWPORT } + diff --git a/addons/cyclops_level_builder/snapping/move_constraint.gd.uid b/addons/cyclops_level_builder/snapping/move_constraint.gd.uid new file mode 100644 index 00000000..fec8b228 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/move_constraint.gd.uid @@ -0,0 +1 @@ +uid://bh6ce1mgmqnd6 diff --git a/addons/cyclops_level_builder/snapping/snap_to_grid_util.gd b/addons/cyclops_level_builder/snapping/snap_to_grid_util.gd new file mode 100644 index 00000000..3c0e1f5b --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snap_to_grid_util.gd @@ -0,0 +1,92 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name SnapToGridUtil + +#const feet_per_meter:float = 3.28084 + +@export var unit_size:float = 1 + +@export var use_subdivisions:bool = false +@export var grid_subdivisions:int = 10 + +@export var power_of_two_scale:int = 0 #Scaling 2^n + +#local transform matrix for grid +@export var grid_transform:Transform3D = Transform3D.IDENTITY: + get: + return grid_transform + set(value): + grid_transform = value + grid_transform_inv = grid_transform.affine_inverse() + +var grid_transform_inv:Transform3D = Transform3D.IDENTITY + +func load_from_cache(cache:Dictionary): + unit_size = cache.get("unit_size", 1) + use_subdivisions = cache.get("use_subdivisions", false) + grid_subdivisions = cache.get("grid_subdivisions", 10) + power_of_two_scale = cache.get("power_of_two_scale", 0) + #print("load grid_transform before") + grid_transform = SerialUtil.load_cache_transform_3d(cache.get("grid_transform", ""), Transform3D.IDENTITY) + #print("load grid_transform after ") + + if is_zero_approx(grid_transform.basis.determinant()): + #print("replace") + grid_transform = Transform3D.IDENTITY + #grid_transform = cache.get("grid_transform", Transform3D.IDENTITY) + +func save_to_cache(): + #print("save SnapToGridUtil") + return { + "unit_size": unit_size, + "use_subdivisions": use_subdivisions, + "grid_subdivisions": grid_subdivisions, + "power_of_two_scale": power_of_two_scale, + "grid_transform": SerialUtil.save_cache_transform_3d(grid_transform), + } + +#Point is in world space +func snap_point(point:Vector3)->Vector3: + + var p_local:Vector3 = grid_transform_inv * point + + #print("unit_size %s pow 2 %s" % [unit_size, pow(2, power_of_two_scale)]) + var scale:Vector3 = Vector3.ONE * unit_size * pow(2, power_of_two_scale) + if use_subdivisions: + scale /= float(grid_subdivisions) + + p_local = floor(p_local / scale + Vector3(.5, .5, .5)) * scale + + var target_point:Vector3 = grid_transform * p_local + + #print("point %s target_point %s scale %s" % [point, target_point, scale]) + return target_point + +func _to_string(): + return "unit_size %s use_subdiv %s subdiv %s pot %s xform %s" \ + % [unit_size, use_subdivisions, grid_subdivisions, power_of_two_scale, grid_transform] + + diff --git a/addons/cyclops_level_builder/snapping/snap_to_grid_util.gd.uid b/addons/cyclops_level_builder/snapping/snap_to_grid_util.gd.uid new file mode 100644 index 00000000..6594eece --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snap_to_grid_util.gd.uid @@ -0,0 +1 @@ +uid://d1wpfgb8saaxn diff --git a/addons/cyclops_level_builder/snapping/snapping_manager.gd b/addons/cyclops_level_builder/snapping/snapping_manager.gd new file mode 100644 index 00000000..d35723ee --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_manager.gd @@ -0,0 +1,45 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name SnappingManager + +var snap_enabled:bool +var snap_tool:CyclopsSnappingSystem + +func snap_point(point:Vector3, query:SnappingQuery)->Vector3: + if !snap_enabled || !snap_tool: + return point + + return snap_tool._snap_point(point, query) + +func snap_angle(angle:float, query:SnappingQuery)->float: + if !snap_enabled || !snap_tool: + return angle + + return snap_tool._snap_angle(angle, query) + + + + diff --git a/addons/cyclops_level_builder/snapping/snapping_manager.gd.uid b/addons/cyclops_level_builder/snapping/snapping_manager.gd.uid new file mode 100644 index 00000000..f4469ce2 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_manager.gd.uid @@ -0,0 +1 @@ +uid://b4sgei5n74bvj diff --git a/addons/cyclops_level_builder/snapping/snapping_query.gd b/addons/cyclops_level_builder/snapping/snapping_query.gd new file mode 100644 index 00000000..f6e1422d --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_query.gd @@ -0,0 +1,35 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name SnappingQuery + + +var viewport_camera:Camera3D +var exclude_blocks:Array[NodePath] + + +func _init(viewport_camera:Camera3D = null, exclude_blocks:Array[NodePath] = []): + self.viewport_camera = viewport_camera + self.exclude_blocks = exclude_blocks diff --git a/addons/cyclops_level_builder/snapping/snapping_query.gd.uid b/addons/cyclops_level_builder/snapping/snapping_query.gd.uid new file mode 100644 index 00000000..f8784b4b --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_query.gd.uid @@ -0,0 +1 @@ +uid://dd21sktn1c7ah diff --git a/addons/cyclops_level_builder/snapping/snapping_system_grid.gd b/addons/cyclops_level_builder/snapping/snapping_system_grid.gd new file mode 100644 index 00000000..1593f1ac --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_grid.gd @@ -0,0 +1,68 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool + +extends CyclopsSnappingSystem +class_name SnappingSystemGrid + +const SNAPPING_TOOL_ID:String = "grid" + +var snap_to_grid_util:SnapToGridUtil = SnapToGridUtil.new() + +func _activate(plugin:CyclopsLevelBuilder): + super._activate(plugin) + + snap_to_grid_util = plugin.get_global_scene().calc_snap_to_grid_util() + + var cache:Dictionary = plugin.get_snapping_cache(SNAPPING_TOOL_ID) + snap_to_grid_util.load_from_cache(cache) + +func _deactivate(): + super._deactivate() + + flush_cache() + +func flush_cache(): + var cache:Dictionary = snap_to_grid_util.save_to_cache() + plugin.set_snapping_cache(SNAPPING_TOOL_ID, cache) + +#Point is in world space +func _snap_point(point:Vector3, query:SnappingQuery)->Vector3: + + var target_point = snap_to_grid_util.snap_point(point) + return target_point + +func _snap_angle(angle:float, query:SnappingQuery)->float: + var snap_angle:float = plugin.get_global_scene().settings.get_property(CyclopsGlobalScene.SNAPPING_GRID_ANGLE) + return floor(angle / snap_angle) * snap_angle + + +func _get_properties_editor()->Control: + var ed:SnappingSystemGridPropertiesEditor = preload("res://addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.tscn").instantiate() + ed.tool = self + + return ed + + + diff --git a/addons/cyclops_level_builder/snapping/snapping_system_grid.gd.uid b/addons/cyclops_level_builder/snapping/snapping_system_grid.gd.uid new file mode 100644 index 00000000..91ef4346 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_grid.gd.uid @@ -0,0 +1 @@ +uid://dfkqwre15kie2 diff --git a/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd b/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd new file mode 100644 index 00000000..21e8d16e --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd @@ -0,0 +1,204 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name SnappingSystemGridPropertiesEditor + +const meters_per_yard:float = 0.9144 +const meters_per_feet:float = 0.3048 + +var tool:SnappingSystemGrid: + get: + return tool + set(value): + #print("setting SnappingSystemGridPropertiesEditor props") + if value == tool: + return + tool = value + update_ui_from_props() + +func update_ui_from_props(): + #print("setting SnappingSystemGridPropertiesEditor props") + + if !tool: + return + + var properties:SnapToGridUtil = tool.snap_to_grid_util + %spin_power_of_two.value = properties.power_of_two_scale + %ed_unit_size.value = properties.unit_size + %check_use_subdiv.button_pressed = properties.use_subdivisions + %spin_subdiv.value = properties.grid_subdivisions + + var parts:Dictionary = MathUtil.decompose_matrix_3d(properties.grid_transform) + + %xform_translate.value = parts.translate + %xform_rotate.value = parts.rotate + %xform_shear.value = parts.shear + %xform_scale.value = parts.scale + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_spin_power_of_two_value_changed(value:float): + if !tool: + return + + tool.snap_to_grid_util.power_of_two_scale = value + tool.flush_cache() + CyclopsAutoload.settings.set_property(CyclopsGlobalScene.SNAPPING_GRID_POWER_OF_TWO_SCALE, int(value)) + CyclopsAutoload.save_settings() + +func _on_ed_unit_size_value_changed(value:float): + if !tool: + return + + tool.snap_to_grid_util.unit_size = value + tool.flush_cache() + CyclopsAutoload.settings.set_property(CyclopsGlobalScene.SNAPPING_GRID_UNIT_SIZE, value) + CyclopsAutoload.save_settings() + +func _on_check_use_subdiv_toggled(toggled_on:bool): + if !tool: + return + + tool.snap_to_grid_util.use_subdivisions = toggled_on + tool.flush_cache() + CyclopsAutoload.settings.set_property(CyclopsGlobalScene.SNAPPING_GRID_USE_SUBDIVISIONS, toggled_on) + CyclopsAutoload.save_settings() + +func _on_spin_subdiv_value_changed(value): + if !tool: + return + + tool.snap_to_grid_util.grid_subdivisions = value + tool.flush_cache() + CyclopsAutoload.settings.set_property(CyclopsGlobalScene.SNAPPING_GRID_SUBDIVISIONS, int(value)) + CyclopsAutoload.save_settings() + +func _on_xform_translate_value_changed(value): + if !tool: + return + + set_grid_transform_from_ui() + +func _on_xform_rotate_value_changed(value): + if !tool: + return + + set_grid_transform_from_ui() + +func _on_xform_scale_value_changed(value): + if !tool: + return + + set_grid_transform_from_ui() + +func _on_xform_shear_value_changed(value): + if !tool: + return + + set_grid_transform_from_ui() + +func set_grid_transform_from_ui(): + var xform:Transform3D = MathUtil.compose_matrix_3d(%xform_translate.value, + %xform_rotate.value, + EULER_ORDER_YXZ, + %xform_shear.value, + %xform_scale.value) + tool.snap_to_grid_util.grid_transform = xform + tool.flush_cache() + + CyclopsAutoload.save_settings() + +func _on_popup_presets_index_pressed(index): + #print("Preset ", index) + var unit_size:float + var subdiv:int + match index: + 0: + unit_size = 1 + subdiv = 10 + 1: + unit_size = meters_per_yard + subdiv = 3 + 2: + unit_size = meters_per_feet + subdiv = 12 + _: + return + + %ed_unit_size.value = unit_size + %spin_subdiv.value = subdiv + + tool.snap_to_grid_util.unit_size = unit_size + CyclopsAutoload.settings.set_property(CyclopsGlobalScene.SNAPPING_GRID_UNIT_SIZE, unit_size) + + tool.snap_to_grid_util.grid_subdivisions = subdiv + tool.flush_cache() + + CyclopsAutoload.settings.set_property(CyclopsGlobalScene.SNAPPING_GRID_SUBDIVISIONS, int(subdiv)) + + CyclopsAutoload.save_settings() + + +func _on_bn_presets_pressed(): + var rect:Rect2 = %bn_presets.get_global_rect() + %popup_presets.popup_on_parent(Rect2i(rect.position.x, rect.position.y + rect.size.y, 0, 0)) + + +func _on_bn_presets_transform_pressed(): + var rect:Rect2 = %bn_presets_transform.get_global_rect() + %popup_transform_presets.popup_on_parent(Rect2i(rect.position.x, rect.position.y + rect.size.y, 0, 0)) + + +func _on_popup_transform_presets_index_pressed(index): + var xform:Transform3D + match index: + 0: + xform = Transform3D.IDENTITY + 1: + var x:Vector3 = Vector3(1, 0, 0) + var y:Vector3 = Vector3(0, 1, 0) + var angle:float = deg_to_rad(60) + + var z:Vector3 = Vector3(cos(angle), 0, sin(angle)) + xform = Transform3D(Basis(x, y, z), Vector3.ZERO) + _: + return + + + tool.snap_to_grid_util.grid_transform = xform + tool.flush_cache() + + CyclopsAutoload.settings.set_property(CyclopsGlobalScene.SNAPPING_GRID_TRANSFORM, xform) + + CyclopsAutoload.save_settings() + update_ui_from_props() diff --git a/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd.uid b/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd.uid new file mode 100644 index 00000000..6b8cde77 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd.uid @@ -0,0 +1 @@ +uid://7600hmhfsi30 diff --git a/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.tscn b/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.tscn new file mode 100644 index 00000000..afb71a17 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.tscn @@ -0,0 +1,153 @@ +[gd_scene load_steps=4 format=3 uid="uid://c165arqp73p1k"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/snapping/snapping_system_grid_properties_editor.gd" id="1_jva1e"] +[ext_resource type="PackedScene" uid="uid://diibmlqy1mpqb" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.tscn" id="2_3bhn6"] +[ext_resource type="PackedScene" uid="uid://cphtpklx81l3w" path="res://addons/cyclops_level_builder/controls/vector3_edit.tscn" id="2_beo4d"] + +[node name="snapping_system_grid_properties" type="PanelContainer"] +offset_right = 400.0 +offset_bottom = 337.0 +script = ExtResource("1_jva1e") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2"] +layout_mode = 2 +text = "Power of 2 Scale" + +[node name="spin_power_of_two" type="SpinBox" parent="VBoxContainer/HBoxContainer2"] +unique_name_in_owner = true +layout_mode = 2 +min_value = -16.0 +max_value = 16.0 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="HBoxContainer3" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer3"] +layout_mode = 2 +text = "Unit size:" + +[node name="ed_unit_size" parent="VBoxContainer/HBoxContainer3" instance=ExtResource("2_3bhn6")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="bn_presets" type="Button" parent="VBoxContainer/HBoxContainer3"] +unique_name_in_owner = true +layout_mode = 2 +text = "Presets" + +[node name="check_use_subdiv" type="CheckBox" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Use Subdivisions" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +text = "Subdivisions" + +[node name="spin_subdiv" type="SpinBox" parent="VBoxContainer/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +min_value = 1.0 +max_value = 16.0 +value = 10.0 +rounded = true +allow_greater = true + +[node name="VBoxContainer2" type="VBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/VBoxContainer2"] +layout_mode = 2 +text = "Transform:" + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/VBoxContainer2"] +layout_mode = 2 + +[node name="bn_presets_transform" type="Button" parent="VBoxContainer/VBoxContainer2/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Transform Presets" + +[node name="GridContainer" type="GridContainer" parent="VBoxContainer/VBoxContainer2"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="VBoxContainer/VBoxContainer2/GridContainer"] +layout_mode = 2 +text = "Translate" + +[node name="xform_translate" parent="VBoxContainer/VBoxContainer2/GridContainer" instance=ExtResource("2_beo4d")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label2" type="Label" parent="VBoxContainer/VBoxContainer2/GridContainer"] +layout_mode = 2 +text = "Rotate" + +[node name="xform_rotate" parent="VBoxContainer/VBoxContainer2/GridContainer" instance=ExtResource("2_beo4d")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label3" type="Label" parent="VBoxContainer/VBoxContainer2/GridContainer"] +layout_mode = 2 +text = "Scale" + +[node name="xform_scale" parent="VBoxContainer/VBoxContainer2/GridContainer" instance=ExtResource("2_beo4d")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label4" type="Label" parent="VBoxContainer/VBoxContainer2/GridContainer"] +layout_mode = 2 +text = "Shear" + +[node name="xform_shear" parent="VBoxContainer/VBoxContainer2/GridContainer" instance=ExtResource("2_beo4d")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="popup_presets" type="PopupMenu" parent="."] +unique_name_in_owner = true +item_count = 3 +item_0/text = "Meters" +item_0/id = 0 +item_1/text = "Yards" +item_1/id = 1 +item_2/text = "Feet" +item_2/id = 2 + +[node name="popup_transform_presets" type="PopupMenu" parent="."] +unique_name_in_owner = true +item_count = 2 +item_0/text = "Cube Grid" +item_0/id = 0 +item_1/text = "Equilateral Triangles XZ" +item_1/id = 1 + +[connection signal="value_changed" from="VBoxContainer/HBoxContainer2/spin_power_of_two" to="." method="_on_spin_power_of_two_value_changed"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer3/ed_unit_size" to="." method="_on_ed_unit_size_value_changed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer3/bn_presets" to="." method="_on_bn_presets_pressed"] +[connection signal="toggled" from="VBoxContainer/check_use_subdiv" to="." method="_on_check_use_subdiv_toggled"] +[connection signal="value_changed" from="VBoxContainer/HBoxContainer/spin_subdiv" to="." method="_on_spin_subdiv_value_changed"] +[connection signal="pressed" from="VBoxContainer/VBoxContainer2/HBoxContainer/bn_presets_transform" to="." method="_on_bn_presets_transform_pressed"] +[connection signal="value_changed" from="VBoxContainer/VBoxContainer2/GridContainer/xform_translate" to="." method="_on_xform_translate_value_changed"] +[connection signal="value_changed" from="VBoxContainer/VBoxContainer2/GridContainer/xform_rotate" to="." method="_on_xform_rotate_value_changed"] +[connection signal="value_changed" from="VBoxContainer/VBoxContainer2/GridContainer/xform_scale" to="." method="_on_xform_scale_value_changed"] +[connection signal="value_changed" from="VBoxContainer/VBoxContainer2/GridContainer/xform_shear" to="." method="_on_xform_shear_value_changed"] +[connection signal="index_pressed" from="popup_presets" to="." method="_on_popup_presets_index_pressed"] +[connection signal="index_pressed" from="popup_transform_presets" to="." method="_on_popup_transform_presets_index_pressed"] diff --git a/addons/cyclops_level_builder/snapping/snapping_system_vertex.gd b/addons/cyclops_level_builder/snapping/snapping_system_vertex.gd new file mode 100644 index 00000000..a73590fc --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_vertex.gd @@ -0,0 +1,117 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsSnappingSystem +class_name SnappingSystemVertex + +@export var max_radius:float = .2 + +const SNAPPING_TOOL_ID:String = "vertex" + +#var snap_to_grid_util:SnapToGridUtil = SnapToGridUtil.new() + +var settings:SnappingSystemVertexSettings = SnappingSystemVertexSettings.new() + +func _activate(plugin:CyclopsLevelBuilder): + super._activate(plugin) + + var cache:Dictionary = plugin.get_snapping_cache(SNAPPING_TOOL_ID) + settings.load_from_cache(cache) + +func _deactivate(): + super._deactivate() + + flush_cache() + +func flush_cache(): + var cache:Dictionary = settings.save_to_cache() + plugin.set_snapping_cache(SNAPPING_TOOL_ID, cache) + + +#Point is in world space +func _snap_point(point:Vector3, query:SnappingQuery)->Vector3: + + var screen_point:Vector2 = query.viewport_camera.unproject_position(point) + + var blocks:Array[CyclopsBlock] = plugin.get_blocks() + + var best_vertex:Vector3 = Vector3.INF + var best_dist:float = INF + + #print("Exclude blocks ", query.exclude_blocks) + for block in blocks: + if query.exclude_blocks.has(block.get_path()): + continue + + #print("check block ", block.name) + var ctrl_mesh:ConvexVolume = block.control_mesh + var bounds_local:AABB = ctrl_mesh.bounds + + var obj_center:Vector3 = block.global_transform * bounds_local.get_center() + var obj_corner:Vector3 = block.global_transform * bounds_local.position + var radius:float = obj_corner.distance_to(obj_center) + var obj_offset:Vector3 = obj_center + query.viewport_camera.global_basis.x * radius + + var screen_obj_center:Vector2 = query.viewport_camera.unproject_position(obj_center) + var screen_obj_offset:Vector2 = query.viewport_camera.unproject_position(obj_offset) + + #print("screen_point ", screen_point) + #print("screen_obj_center ", screen_obj_center) + #print("screen_obj_offset ", screen_obj_offset) + #print("screen_point.distance_to(screen_obj_center) ", screen_point.distance_to(screen_obj_center)) + #print("screen_obj_center.distance_to(screen_obj_offset) ", screen_obj_center.distance_to(screen_obj_offset)) + if screen_point.distance_to(screen_obj_center) > \ + screen_obj_center.distance_to(screen_obj_offset) + settings.snap_radius: + #Skip if bounding box text fails + continue + + + #print("snap block ", block.name) + for v_idx in ctrl_mesh.vertices.size(): + var v:ConvexVolume.VertexInfo = ctrl_mesh.vertices[v_idx] + var v_point_world:Vector3 = block.global_transform * v.point + var v_point_screen:Vector2 = query.viewport_camera.unproject_position(v_point_world) + + var dist:float = v_point_screen.distance_to(screen_point) + #print("dist ", dist, " settings.snap_radius ", settings.snap_radius) + if dist > settings.snap_radius: + continue + + #print("try vertex ", v_point_world) + if dist < best_dist: +# if dist < best_dist: + best_vertex = v_point_world + best_dist = dist + + + return best_vertex if is_finite(best_dist) else point + + +func _get_properties_editor()->Control: + var ed:SnappingSystemVertexPropertiesEditor = preload("res://addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.tscn").instantiate() + ed.snap_tool = self + + return ed + + diff --git a/addons/cyclops_level_builder/snapping/snapping_system_vertex.gd.uid b/addons/cyclops_level_builder/snapping/snapping_system_vertex.gd.uid new file mode 100644 index 00000000..675f3a36 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_vertex.gd.uid @@ -0,0 +1 @@ +uid://bu5iqmnw00mty diff --git a/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd b/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd new file mode 100644 index 00000000..81606364 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd @@ -0,0 +1,62 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name SnappingSystemVertexPropertiesEditor + +var snap_tool:SnappingSystemVertex: + get: + return snap_tool + set(value): + #print("setting SnappingSystemGridPropertiesEditor props") + if value == snap_tool: + return + snap_tool = value + update_ui_from_props() + +#var settings:SnappingSystemVertexSettings: + #get: + #return settings + #set(value): + ##print("setting SnappingSystemGridPropertiesEditor props") + #if value == settings: + #return + #settings = value + #update_ui_from_props() + +func update_ui_from_props(): + if !snap_tool: + return + + var settings = snap_tool.settings + + %snap_radius.value = settings.snap_radius + +func _on_snap_radius_value_changed(value): + if !snap_tool: + return + + snap_tool.settings.snap_radius = value + snap_tool.flush_cache() + diff --git a/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd.uid b/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd.uid new file mode 100644 index 00000000..3187e648 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd.uid @@ -0,0 +1 @@ +uid://b30y2jmb8hdwr diff --git a/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.tscn b/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.tscn new file mode 100644 index 00000000..c52e3e52 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=3 format=3 uid="uid://cbucsqmj5g1i1"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/snapping/snapping_system_vertex_properties_editor.gd" id="1_tibga"] +[ext_resource type="PackedScene" uid="uid://diibmlqy1mpqb" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.tscn" id="2_hl6or"] + +[node name="SnappingSystemVertexPropertiesEditor" type="PanelContainer"] +offset_right = 319.0 +offset_bottom = 210.0 +script = ExtResource("1_tibga") + +[node name="GridContainer" type="GridContainer" parent="."] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Snap Radius +" + +[node name="snap_radius" parent="GridContainer" instance=ExtResource("2_hl6or")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[connection signal="value_changed" from="GridContainer/snap_radius" to="." method="_on_snap_radius_value_changed"] diff --git a/addons/cyclops_level_builder/snapping/snapping_system_vertex_settings.gd b/addons/cyclops_level_builder/snapping/snapping_system_vertex_settings.gd new file mode 100644 index 00000000..4380b975 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_vertex_settings.gd @@ -0,0 +1,37 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name SnappingSystemVertexSettings + +#Snapping redous in viewport pixels +@export var snap_radius:float = 6 + +func load_from_cache(cache:Dictionary): + snap_radius = cache.get("snap_radius", 6.0) + +func save_to_cache()->Dictionary: + return { + "snap_radius": snap_radius + } diff --git a/addons/cyclops_level_builder/snapping/snapping_system_vertex_settings.gd.uid b/addons/cyclops_level_builder/snapping/snapping_system_vertex_settings.gd.uid new file mode 100644 index 00000000..29adeea8 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_system_vertex_settings.gd.uid @@ -0,0 +1 @@ +uid://dtk5lob0jn54d diff --git a/addons/cyclops_level_builder/snapping/snapping_tag.gd b/addons/cyclops_level_builder/snapping/snapping_tag.gd new file mode 100644 index 00000000..190f14dd --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_tag.gd @@ -0,0 +1,45 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name SnappingTag + +@export var name:String +@export var icon:Texture2D +@export_multiline var tooltip:String +@export var snapping_script:Script + + +var snapping_system:CyclopsSnappingSystem + +func _activate(plugin:CyclopsLevelBuilder): + if !snapping_script: + return + + if !snapping_system: + snapping_system = snapping_script.new() + + plugin.switch_to_snapping_system(snapping_system) + + diff --git a/addons/cyclops_level_builder/snapping/snapping_tag.gd.uid b/addons/cyclops_level_builder/snapping/snapping_tag.gd.uid new file mode 100644 index 00000000..442a7c20 --- /dev/null +++ b/addons/cyclops_level_builder/snapping/snapping_tag.gd.uid @@ -0,0 +1 @@ +uid://5l6u2ql5tu47 diff --git a/addons/cyclops_level_builder/tools/block_alignment.gd b/addons/cyclops_level_builder/tools/block_alignment.gd new file mode 100644 index 00000000..d0679975 --- /dev/null +++ b/addons/cyclops_level_builder/tools/block_alignment.gd @@ -0,0 +1,39 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name BlockAlignment + +enum Type { ALIGN_TO_SURFACE, XY_PLANE, XZ_PLANE, YZ_PLANE } + +static func get_plane_normal(type:Type)->Vector3: + match type: + BlockAlignment.Type.XY_PLANE: + return Vector3(0, 0, 1) + BlockAlignment.Type.XZ_PLANE: + return Vector3(0, 1, 0) + BlockAlignment.Type.YZ_PLANE: + return Vector3(1, 0, 0) + _: + return Vector3(0, 1, 0) + diff --git a/addons/cyclops_level_builder/tools/block_alignment.gd.uid b/addons/cyclops_level_builder/tools/block_alignment.gd.uid new file mode 100644 index 00000000..48c71500 --- /dev/null +++ b/addons/cyclops_level_builder/tools/block_alignment.gd.uid @@ -0,0 +1 @@ +uid://qokmq3xaarwu diff --git a/addons/cyclops_level_builder/tools/cyclops_tool.gd b/addons/cyclops_level_builder/tools/cyclops_tool.gd new file mode 100644 index 00000000..d9da0581 --- /dev/null +++ b/addons/cyclops_level_builder/tools/cyclops_tool.gd @@ -0,0 +1,189 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name CyclopsTool + +var builder:CyclopsLevelBuilder + +#func _init(_editorPlugin:EditorPlugin): +# editorPlugin = _editorPlugin + +func _activate(builder:CyclopsLevelBuilder): + self.builder = builder + +func _deactivate(): + pass + +func _get_tool_id()->String: + return "" + +func _draw_tool(viewport_camera:Camera3D): + pass + +func _get_tool_properties_editor()->Control: + return null + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_X: + if e.is_pressed(): + #print("cyc tool X") + var action:ActionDeleteSelectedBlocks = ActionDeleteSelectedBlocks.new(builder) + action._execute() + + return true + + if e.keycode == KEY_D: + if e.is_pressed(): + if e.shift_pressed && !Input.is_mouse_button_pressed(MOUSE_BUTTON_RIGHT): + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + builder.switch_to_tool(ToolDuplicate.new()) + + return true + + if event is InputEventMouseButton: + var e:InputEventMouseButton = event + + if e.button_index == MOUSE_BUTTON_MIDDLE: + if e.alt_pressed: + if e.is_pressed(): + if builder.get_active_block(): + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + +# var start_pos:Vector3 = origin + builder.block_create_distance * dir +# var w2l = builder.active_node.global_transform.inverse() +# var origin_local:Vector3 = w2l * origin +# var dir_local:Vector3 = w2l.basis * dir + + var result:IntersectResults = builder.active_node.intersect_ray_closest(origin, dir) + if result: + var ed_iface:EditorInterface = builder.get_editor_interface() + var base_control:Control = ed_iface.get_base_control() + + #viewport_camera + var new_cam_origin:Vector3 = result.position + \ + viewport_camera.global_transform.basis.z * builder.block_create_distance + viewport_camera.global_transform.origin = new_cam_origin + return true + + return false + + + +func to_local(point:Vector3, world_to_local:Transform3D, grid_step_size:float)->Vector3: + var p_local:Vector3 = world_to_local * point + + return MathUtil.snap_to_grid(p_local, grid_step_size) + + +func calc_empty_space_draw_plane_origin(viewport_camera:Camera3D, draw_plane_point:Vector3 = Vector3.ZERO, draw_plane_normal:Vector3 = Vector3.UP): + var active_block:CyclopsBlock = builder.get_active_block() + var block_xfrom:Transform3D = active_block.global_transform + if active_block: + var vol:ConvexVolume = active_block.control_mesh + var bounds:AABB = vol.calc_bounds_xform(block_xfrom) + var plane:Plane = Plane(draw_plane_normal, bounds.get_center()) + + var p0:Vector3 = bounds.position + var p1:Vector3 = bounds.position + bounds.size + if plane.is_point_over(viewport_camera.global_transform.origin): + if plane.is_point_over(p0): + draw_plane_point = p1 + else: + draw_plane_point = p0 + else: + if plane.is_point_over(p0): + draw_plane_point = p0 + else: + draw_plane_point = p1 + + return draw_plane_point + +func calc_hit_point_empty_space(origin:Vector3, dir:Vector3, viewport_camera:Camera3D = null, base_plane_origin:Vector3 = Vector3.ZERO, drag_floor_normal:Vector3 = Vector3.UP): + #print("Miss") + var drag_angle_limit:float = builder.get_global_scene().drag_angle_limit + + var angle_y_axis:float = acos(dir.dot(Vector3.UP)) + if angle_y_axis > PI / 2 - drag_angle_limit && angle_y_axis < PI / 2 + drag_angle_limit: + #Nearly parallel with ground plane + if abs(dir.z) > abs(dir.x): + drag_floor_normal = Vector3.FORWARD + else: + drag_floor_normal = Vector3.LEFT + + #print("base_plane_normal ", base_plane_normal) + + var hit_base:Vector3 = MathUtil.intersect_plane(origin, dir, base_plane_origin, drag_floor_normal) + #print("hit_base 1 ", hit_base) + + if (hit_base - origin).dot(dir) < 0: + #Hit point is behind camera + var plane_offset:Vector3 = origin.project(drag_floor_normal) + base_plane_origin += plane_offset * 2 + hit_base = MathUtil.intersect_plane(origin, dir, base_plane_origin, drag_floor_normal) + + #print("base_plane_origin ", base_plane_origin) + #print("hit_base ", hit_base) + + var block_drag_p0:Vector3 = builder.get_snapping_manager().snap_point(hit_base, SnappingQuery.new(viewport_camera)) + + return [block_drag_p0, drag_floor_normal] + +func calc_active_block_orthogonal_height(plane_origin:Vector3, drag_floor_normal:Vector3)->float: + var active_block:CyclopsBlock = builder.get_active_block() + var block_bounds:AABB = active_block.control_mesh.calc_bounds_xform(active_block.global_transform) + var plane:Plane = Plane(drag_floor_normal, block_bounds.get_center()) + var p0_over:bool = plane.is_point_over(plane_origin) + + var height:float = abs(block_bounds.size.dot(drag_floor_normal)) + if p0_over: + height = -height + + return height + +func select_block_under_cursor(viewport_camera:Camera3D, mouse_pos:Vector2): + var origin:Vector3 = viewport_camera.project_ray_origin(mouse_pos) + var dir:Vector3 = viewport_camera.project_ray_normal(mouse_pos) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + if result: + var cmd:CommandSelectBlocks = CommandSelectBlocks.new() + cmd.builder = builder + cmd.block_paths.append(result.object.get_path()) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + _deactivate() + _activate(builder) + diff --git a/addons/cyclops_level_builder/tools/cyclops_tool.gd.uid b/addons/cyclops_level_builder/tools/cyclops_tool.gd.uid new file mode 100644 index 00000000..7f178a24 --- /dev/null +++ b/addons/cyclops_level_builder/tools/cyclops_tool.gd.uid @@ -0,0 +1 @@ +uid://ce3p7ldqxt1w3 diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_base.gd b/addons/cyclops_level_builder/tools/gizmos/gizmo_base.gd new file mode 100644 index 00000000..0b7d28f2 --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_base.gd @@ -0,0 +1,92 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +@tool +extends Node3D +class_name GizmoBase + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func intersect_part(ray_origin:Vector3, ray_dir:Vector3, viewport_camera:Camera3D, mesh_inst:MeshInstance3D)->MathUtil.IntersectTriangleResult: + var proj:Projection = viewport_camera.get_camera_projection() + + #Calc modelview matrix + var view_inv_matrix:Transform3D = viewport_camera.global_transform.affine_inverse() + var mv:Projection = Projection(view_inv_matrix * mesh_inst.global_transform) + #Static size adjustment + if proj[3][3] != 0: + var h:float = abs(1 / (2 * proj[1][1])) + var sc = h * 2 + mv[0] *= sc + mv[1] *= sc + mv[2] *= sc + else: + var sc:float = -mv[3].z + mv[0] *= sc + mv[1] *= sc + mv[2] *= sc + + var model_mtx:Projection = Projection(viewport_camera.global_transform) * mv + + var mesh:Mesh = mesh_inst.mesh + var tris:PackedVector3Array = mesh.get_faces() + for i in range(0, tris.size(), 3): + var p0:Vector3 = tris[i] + var p1:Vector3 = tris[i + 1] + var p2:Vector3 = tris[i + 2] + + var p0_t:Vector3 = proj_mul_point(model_mtx, p0) + var p1_t:Vector3 = proj_mul_point(model_mtx, p1) + var p2_t:Vector3 = proj_mul_point(model_mtx, p2) + + #print("tri world %s %s %s" % [p0_t, p1_t, p2_t]) + var res = MathUtil.intersect_triangle(ray_origin, ray_dir, p0_t, p1_t, p2_t) + + if res: + return res + + return null + + +func proj_mul_point(m:Projection, p:Vector3)->Vector3: + var p4:Vector4 = Vector4(p.x, p.y, p.z, 1) + var p4_t = m * p4 + p4_t /= p4_t.w + return Vector3(p4_t.x, p4_t.y, p4_t.z) + + +func proj_mul_vec(m:Projection, p:Vector3)->Vector3: + var p4:Vector4 = Vector4(p.x, p.y, p.z, 0) + var p4_t = m * p4 + p4_t /= p4_t.w + return Vector3(p4_t.x, p4_t.y, p4_t.z) diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_base.gd.uid b/addons/cyclops_level_builder/tools/gizmos/gizmo_base.gd.uid new file mode 100644 index 00000000..ab60b486 --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_base.gd.uid @@ -0,0 +1 @@ +uid://csmlrcfhociek diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd b/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd new file mode 100644 index 00000000..4ee039ca --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd @@ -0,0 +1,72 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +@tool +extends GizmoBase +class_name GizmoRotate + +enum Part { NONE, PLANE_XY, PLANE_XZ, PLANE_YZ, VIEWPORT, TRACKBALL } + + +class IntersectResult: + var part:Part + var pos_world:Vector3 + + +# Called when the node enters the scene tree for the first time. +func _ready(): + $gizmo_rotate/rot_axis_viewport.visible = false + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + get_viewport() + pass + + +func intersect(ray_origin:Vector3, ray_dir:Vector3, viewport_camera:Camera3D)->IntersectResult: + var result:IntersectResult = IntersectResult.new() + result.part = Part.NONE + + for child in $gizmo_rotate.get_children(): + var part_res:MathUtil.IntersectTriangleResult = intersect_part(ray_origin, ray_dir, viewport_camera, child) + + if part_res: + result.pos_world = part_res.position + match child.name: + "rot_axis_x": + result.part = Part.PLANE_YZ + "rot_axis_y": + result.part = Part.PLANE_XZ + "rot_axis_z": + result.part = Part.PLANE_XY + + return result +# print("hit " + child.name) +# return + + return null + + diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd.uid b/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd.uid new file mode 100644 index 00000000..94f9c2f5 --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd.uid @@ -0,0 +1 @@ +uid://ccmb62cspcnvr diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.tscn b/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.tscn new file mode 100644 index 00000000..e56cbad7 --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=7 format=3 uid="uid://cyi4s4loi2i15"] + +[ext_resource type="PackedScene" uid="uid://p26cj0m5amq0" path="res://addons/cyclops_level_builder/art/gizmos/gizmo_rotate.glb" id="1_knqem"] +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.gd" id="1_vhpbh"] +[ext_resource type="Material" uid="uid://bv4k8o22vl6ub" path="res://addons/cyclops_level_builder/materials/gizmo_axis_y_material.tres" id="2_538x0"] +[ext_resource type="Material" uid="uid://drodm0wf41vin" path="res://addons/cyclops_level_builder/materials/gizmo_axis_x_material.tres" id="3_7q6t6"] +[ext_resource type="Material" uid="uid://divsg4lq712rw" path="res://addons/cyclops_level_builder/materials/gizmo_axis_z_material.tres" id="4_eibo1"] +[ext_resource type="Material" uid="uid://cqvh1j2n71fej" path="res://addons/cyclops_level_builder/materials/gizmo_axis_special_material.tres" id="5_ib271"] + +[node name="GizmoRotate" type="Node3D"] +script = ExtResource("1_vhpbh") + +[node name="gizmo_rotate" parent="." instance=ExtResource("1_knqem")] +transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) + +[node name="rot_axis_y" parent="gizmo_rotate" index="0"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("2_538x0") + +[node name="rot_axis_x" parent="gizmo_rotate" index="1"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("3_7q6t6") + +[node name="rot_axis_z" parent="gizmo_rotate" index="2"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("4_eibo1") + +[node name="rot_axis_viewport" parent="gizmo_rotate" index="3"] +visible = false +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("5_ib271") + +[editable path="gizmo_rotate"] diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd b/addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd new file mode 100644 index 00000000..5685a288 --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd @@ -0,0 +1,23 @@ +extends Node3D + +func _input(event): + if event is InputEventMouseButton: + var e:InputEventMouseButton = event + + if e.is_pressed(): + + var cam:Camera3D = %Camera3D + var ray_norm:Vector3 = cam.project_ray_normal(e.position) + var ray_orig:Vector3 = cam.project_ray_origin(e.position) + %gizmo_translate.intersect(ray_orig, ray_norm, cam) + + pass + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd.uid b/addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd.uid new file mode 100644 index 00000000..066b4513 --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd.uid @@ -0,0 +1 @@ +uid://co4koa8l4ta3f diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_test.tscn b/addons/cyclops_level_builder/tools/gizmos/gizmo_test.tscn new file mode 100644 index 00000000..b98711a1 --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_test.tscn @@ -0,0 +1,37 @@ +[gd_scene load_steps=4 format=3 uid="uid://bykffnaq3h1ar"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/gizmos/gizmo_test.gd" id="1_0e45b"] +[ext_resource type="PackedScene" uid="uid://2pi622xycrd6" path="res://addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn" id="2_2n1ok"] + +[sub_resource type="SphereMesh" id="SphereMesh_off5f"] +radius = 0.02 +height = 0.04 + +[node name="gizmo_test" type="Node3D"] +script = ExtResource("1_0e45b") + +[node name="gizmo_translate" parent="." instance=ExtResource("2_2n1ok")] +unique_name_in_owner = true + +[node name="Camera3D" type="Camera3D" parent="."] +unique_name_in_owner = true +transform = Transform3D(0.930759, 0.202432, -0.30448, -0.0272565, 0.868848, 0.494329, 0.364615, -0.451802, 0.814206, -0.279477, 1.02398, 1.38375) + +[node name="MeshInstance3D" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.126, 0, 0.266) +mesh = SubResource("SphereMesh_off5f") + +[node name="MeshInstance3D2" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.266, 0, 0.126) +mesh = SubResource("SphereMesh_off5f") + +[node name="MeshInstance3D3" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.266, 0, 0.266) +mesh = SubResource("SphereMesh_off5f") + +[node name="MeshInstance3D4" type="MeshInstance3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.126, 0, 0.126) +mesh = SubResource("SphereMesh_off5f") + +[editable path="gizmo_translate"] +[editable path="gizmo_translate/gizmo_translate"] diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd b/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd new file mode 100644 index 00000000..9c3f248e --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd @@ -0,0 +1,73 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +@tool +extends GizmoBase +class_name GizmoTranslate + +enum Part { NONE, AXIS_X, AXIS_Y, AXIS_Z, PLANE_XY, PLANE_XZ, PLANE_YZ } + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + +class IntersectResult: + var part:Part + var pos_world:Vector3 + +func intersect(ray_origin:Vector3, ray_dir:Vector3, viewport_camera:Camera3D)->IntersectResult: + var result:IntersectResult = IntersectResult.new() + result.part = Part.NONE +# if intersect_part(ray_origin, ray_dir, viewport_camera, $gizmo_translate/axis_y): + for child in $gizmo_translate.get_children(): + var part_res:MathUtil.IntersectTriangleResult = intersect_part(ray_origin, ray_dir, viewport_camera, child) + + if part_res: + result.pos_world = part_res.position + match child.name: + "axis_x": + result.part = Part.AXIS_X + "axis_y": + result.part = Part.AXIS_Y + "axis_z": + result.part = Part.AXIS_Z + "plane_xy": + result.part = Part.PLANE_XY + "plane_xz": + result.part = Part.PLANE_XZ + "plane_yz": + result.part = Part.PLANE_YZ + + return result +# print("hit " + child.name) +# return + + return null + + diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd.uid b/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd.uid new file mode 100644 index 00000000..cada6f6e --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd.uid @@ -0,0 +1 @@ +uid://dx88eguy6bpi6 diff --git a/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn b/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn new file mode 100644 index 00000000..ebed020a --- /dev/null +++ b/addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn @@ -0,0 +1,45 @@ +[gd_scene load_steps=6 format=3 uid="uid://2pi622xycrd6"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/gizmos/gizmo_translate.gd" id="1_fyqe0"] +[ext_resource type="PackedScene" uid="uid://ujq3kes2sdfu" path="res://addons/cyclops_level_builder/art/gizmos/gizmo_translate.glb" id="1_ljs46"] +[ext_resource type="Material" uid="uid://bv4k8o22vl6ub" path="res://addons/cyclops_level_builder/materials/gizmo_axis_y_material.tres" id="3_tsii4"] +[ext_resource type="Material" uid="uid://divsg4lq712rw" path="res://addons/cyclops_level_builder/materials/gizmo_axis_z_material.tres" id="4_0qd8v"] +[ext_resource type="Material" uid="uid://drodm0wf41vin" path="res://addons/cyclops_level_builder/materials/gizmo_axis_x_material.tres" id="5_xvd3e"] + +[node name="gizmo_translate" type="Node3D"] +script = ExtResource("1_fyqe0") + +[node name="gizmo_translate" parent="." instance=ExtResource("1_ljs46")] +transform = Transform3D(0.2, 0, 0, 0, 0.2, 0, 0, 0, 0.2, 0, 0, 0) + +[node name="axis_y" parent="gizmo_translate" index="0"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("3_tsii4") + +[node name="axis_z" parent="gizmo_translate" index="1"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("4_0qd8v") + +[node name="axis_x" parent="gizmo_translate" index="2"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("5_xvd3e") + +[node name="plane_xz" parent="gizmo_translate" index="3"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("3_tsii4") + +[node name="plane_yz" parent="gizmo_translate" index="4"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("5_xvd3e") + +[node name="plane_xy" parent="gizmo_translate" index="5"] +lod_bias = 128.0 +ignore_occlusion_culling = true +surface_material_override/0 = ExtResource("4_0qd8v") + +[editable path="gizmo_translate"] diff --git a/addons/cyclops_level_builder/tools/tool_block.gd b/addons/cyclops_level_builder/tools/tool_block.gd new file mode 100644 index 00000000..342ddc24 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_block.gd @@ -0,0 +1,360 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolBlock + +const TOOL_ID:String = "block" + +enum ToolState { NONE, READY, BLOCK_BASE, BLOCK_HEIGHT, MOVE_FACE } +var tool_state:ToolState = ToolState.NONE + +#enum BlockAlign { ALIGN_TO_SURFACE, XY_PLANE, XZ_PLANE, YZ_PLANE } + +#var drag_angle_limit:float = deg_to_rad(5) + +var viewport_camera_start:Camera3D +var event_start:InputEventMouseButton + +var block_drag_cur:Vector3 +var block_drag_p0:Vector3 +var block_drag_p1:Vector3 +var block_drag_p2:Vector3 + +var drag_floor_normal:Vector3 + +var settings:ToolBlockSettings = ToolBlockSettings.new() + +#Keep a copy of move command here while we are building it +var cmd_move_face:CommandMoveFacePlanar +var move_face_origin:Vector3 #Kep track of the origin when moving a face + +var base_points:PackedVector3Array + +var mouse_hover_pos:Vector2 + +func _get_tool_id()->String: + return TOOL_ID + +func _get_tool_properties_editor()->Control: + var ed:ToolBlockSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_block_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func start_block_drag(viewport_camera:Camera3D, event:InputEvent): + var blocks_root:Node = builder.get_block_add_parent() + var e:InputEventMouseButton = event + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + #print("origin %s dir %s" % [origin, dir]) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + #print("result %s" % result) + + if result && settings.block_alignment == BlockAlignment.Type.ALIGN_TO_SURFACE: + #print("Hit! %s" % result) + drag_floor_normal = MathUtil.snap_to_best_axis_normal(result.get_world_normal()) + + var start_pos:Vector3 = result.get_world_position() + + #var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + #block_drag_p0 = MathUtil.snap_to_grid(start_pos, grid_step_size) + + block_drag_p0 = builder.get_snapping_manager().snap_point(start_pos, SnappingQuery.new(viewport_camera)) + + + if e.ctrl_pressed: + tool_state = ToolState.MOVE_FACE + + cmd_move_face = CommandMoveFacePlanar.new() + cmd_move_face.builder = builder + cmd_move_face.blocks_root_path = builder.get_block_add_parent().get_path() + cmd_move_face.block_path = result.object.get_path() + cmd_move_face.face_index = result.face_index + cmd_move_face.lock_uvs = builder.lock_uvs + cmd_move_face.move_dir_normal = result.object.control_mesh.faces[result.face_id].normal + + move_face_origin = result.object.global_transform * result.position + #print("moving face move_face_origin %s" % move_face_origin) + + else: + tool_state = ToolState.BLOCK_BASE + + + else: + #print("Miss") + var draw_plane_point:Vector3 = Vector3.ZERO + var draw_plane_normal:Vector3 = BlockAlignment.get_plane_normal(settings.block_alignment) + + if settings.match_selected_block: + draw_plane_point = calc_empty_space_draw_plane_origin(viewport_camera, draw_plane_point, draw_plane_normal) + + var hit_result = calc_hit_point_empty_space(origin, dir, viewport_camera, draw_plane_point, draw_plane_normal) + block_drag_p0 = hit_result[0] + drag_floor_normal = hit_result[1] + + tool_state = ToolState.BLOCK_BASE + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + + if tool_state == ToolState.BLOCK_BASE: + global_scene.draw_loop(base_points, true, global_scene.tool_material) + global_scene.draw_points(base_points, global_scene.vertex_tool_material) + + if tool_state == ToolState.BLOCK_HEIGHT: + global_scene.draw_cube(block_drag_p0, block_drag_p1, block_drag_cur, global_scene.tool_material, global_scene.vertex_tool_material) + + +func create_block(): + block_drag_p2 = block_drag_cur +# print("Adding block %s %s %s" % [block_drag_p0, block_drag_p1, block_drag_p2]) + + var bounds:AABB = AABB(block_drag_p0, Vector3.ZERO) + bounds = bounds.expand(block_drag_p1) + bounds = bounds.expand(block_drag_p2) + + if bounds.has_volume(): + var blocks_root:Node = builder.get_block_add_parent() + + var command:CommandAddBlock = CommandAddBlock.new() + + command.builder = builder + command.blocks_root_path = blocks_root.get_path() + command.block_name = GeneralUtil.find_unique_name(blocks_root, "Block_") + command.bounds = bounds +# command.origin = block_drag_p0 + command.uv_transform = builder.tool_uv_transform + command.material_path = builder.tool_material_path + command.collision_type = settings.collision_type + command.collision_layers = settings.collision_layer + command.collision_mask = settings.collision_mask + + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + command.add_to_undo_manager(undo) + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + #print("tool_block gui_input %s" % event) + + var blocks_root:Node = builder.get_block_add_parent() + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ESCAPE: + if e.is_pressed(): + tool_state = ToolState.NONE + return true + + if e.keycode == KEY_Q && e.alt_pressed: + if e.is_pressed(): + select_block_under_cursor(viewport_camera, mouse_hover_pos) + #var origin:Vector3 = viewport_camera.project_ray_origin(mouse_hover_pos) + #var dir:Vector3 = viewport_camera.project_ray_normal(mouse_hover_pos) + # + #var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + #if result: + #var cmd:CommandSelectBlocks = CommandSelectBlocks.new() + #cmd.builder = builder + #cmd.block_paths.append(result.object.get_path()) + # + #if cmd.will_change_anything(): + #var undo:EditorUndoRedoManager = builder.get_undo_redo() + #cmd.add_to_undo_manager(undo) + # + #_deactivate() + #_activate(builder) + + return true + + elif event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + if tool_state == ToolState.NONE: + event_start = event + viewport_camera_start = viewport_camera + + tool_state = ToolState.READY + + else: + if tool_state == ToolState.READY: + + tool_state = ToolState.NONE + + elif tool_state == ToolState.BLOCK_BASE: + block_drag_p1 = block_drag_cur + + var camera_dir:Vector3 = viewport_camera.project_ray_normal(e.position) + var angle_with_base:float = acos(drag_floor_normal.dot(camera_dir)) + + var drag_angle_limit:float = builder.get_global_scene().drag_angle_limit + + if angle_with_base < drag_angle_limit || angle_with_base > PI - drag_angle_limit: + var height = settings.default_block_height + if settings.match_selected_block: + height = calc_active_block_orthogonal_height(block_drag_p0, drag_floor_normal) + + block_drag_cur = block_drag_p1 + drag_floor_normal * height + + create_block() + + tool_state = ToolState.NONE + else: + + tool_state = ToolState.BLOCK_HEIGHT + + elif tool_state == ToolState.BLOCK_HEIGHT: + create_block() + + tool_state = ToolState.NONE + + + elif tool_state == ToolState.MOVE_FACE: + + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd_move_face.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + return true + + #elif e.button_index == MOUSE_BUTTON_RIGHT: + #if tool_state == ToolState.BLOCK_BASE || tool_state == ToolState.BLOCK_HEIGHT: + #if e.is_pressed(): + #tool_state = ToolState.NONE + #return true + + + elif event is InputEventMouseMotion: + + var e:InputEventMouseMotion = event + + mouse_hover_pos = e.position + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var start_pos:Vector3 = origin + builder.block_create_distance * dir + + #print("tool_state %s" % tool_state) + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return super._gui_input(viewport_camera, event) + + if tool_state == ToolState.NONE: + if e.ctrl_pressed: + #block_drag_cur = MathUtil.intersect_plane(origin_local, dir_local, block_drag_p0_local, drag_floor_normal) + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + #print("picked result %s" % result) + if result: + var block:CyclopsBlock = result.object + var convex_mesh:ConvexVolume = block.control_mesh + base_points = convex_mesh.get_face(result.face_index).get_points() + return true + + return false + + elif tool_state == ToolState.READY: + var offset:Vector2 = e.position - event_start.position + if offset.length_squared() > MathUtil.square(builder.drag_start_radius): + start_block_drag(viewport_camera_start, event_start) + + return true + + elif tool_state == ToolState.BLOCK_BASE: + + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, drag_floor_normal) + + #print("block_drag_cur %s" % block_drag_cur) + + block_drag_cur = builder.get_snapping_manager().snap_point(block_drag_cur, SnappingQuery.new(viewport_camera)) + + #print("block_drag_cur snapped %s" % block_drag_cur) + + #Draw tool + var p01:Vector3 + var p10:Vector3 + if abs(drag_floor_normal.x) > abs(drag_floor_normal.y) and abs(drag_floor_normal.x) > abs(drag_floor_normal.z): + p01 = Vector3(block_drag_p0.x, block_drag_p0.y, block_drag_cur.z) + p10 = Vector3(block_drag_p0.x, block_drag_cur.y, block_drag_p0.z) + elif abs(drag_floor_normal.y) > abs(drag_floor_normal.z): + p01 = Vector3(block_drag_p0.x, block_drag_p0.y, block_drag_cur.z) + p10 = Vector3(block_drag_cur.x, block_drag_p0.y, block_drag_p0.z) + else: + p01 = Vector3(block_drag_p0.x, block_drag_cur.y, block_drag_p0.z) + p10 = Vector3(block_drag_cur.x, block_drag_p0.y, block_drag_p0.z) + + base_points = [block_drag_p0, p01, block_drag_cur, p10] + + return true + + elif tool_state == ToolState.BLOCK_HEIGHT: + block_drag_cur = MathUtil.closest_point_on_line(origin, dir, block_drag_p1, drag_floor_normal) + + block_drag_cur = builder.get_snapping_manager().snap_point(block_drag_cur, SnappingQuery.new(viewport_camera)) + + return true + + elif tool_state == ToolState.MOVE_FACE: + var drag_to:Vector3 = MathUtil.closest_point_on_line(origin, dir, move_face_origin, cmd_move_face.move_dir_normal) + #print("move_face_origin %s norm %s" % [move_face_origin, cmd_move_face.move_dir_normal]) + + drag_to = builder.get_snapping_manager().snap_point(drag_to, SnappingQuery.new(viewport_camera)) + + #print("move_face drag_to %s" % [drag_to]) + cmd_move_face.move_amount = (drag_to - move_face_origin).dot(cmd_move_face.move_dir_normal) + #print("move by %s" % [drag_to - move_face_origin]) + + cmd_move_face.do_it_intermediate() + + return true + + return super._gui_input(viewport_camera, event) + + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.OBJECT + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + var cache:Dictionary = builder.get_tool_cache(TOOL_ID) + #print("loaded cache ", str(cache)) + settings.load_from_cache(cache) + +func _deactivate(): + var cache:Dictionary = settings.save_to_cache() + builder.set_tool_cache(TOOL_ID, cache) + diff --git a/addons/cyclops_level_builder/tools/tool_block.gd.uid b/addons/cyclops_level_builder/tools/tool_block.gd.uid new file mode 100644 index 00000000..969c6395 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_block.gd.uid @@ -0,0 +1 @@ +uid://i2mhsltvr4v7 diff --git a/addons/cyclops_level_builder/tools/tool_block_settings.gd b/addons/cyclops_level_builder/tools/tool_block_settings.gd new file mode 100644 index 00000000..57d468bb --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_block_settings.gd @@ -0,0 +1,54 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolBlockSettings + +@export var block_alignment:BlockAlignment.Type = BlockAlignment.Type.ALIGN_TO_SURFACE +@export var match_selected_block:bool = true +@export var default_block_elevation:float = 0 +@export var default_block_height:float = 1 +@export var collision_type:Collision.Type = Collision.Type.STATIC +@export_flags_3d_physics var collision_layer:int = 1 +@export_flags_3d_physics var collision_mask:int = 1 + +func load_from_cache(cache:Dictionary): + block_alignment = cache.get("block_alignment", BlockAlignment.Type.ALIGN_TO_SURFACE) + match_selected_block = cache.get("match_selected_block", true) + default_block_elevation = cache.get("default_block_elevation", 0) + default_block_height = cache.get("default_block_height", 1) + collision_type = cache.get("collision_type", Collision.Type.STATIC) + collision_layer = cache.get("collision_layer", 1) + collision_mask = cache.get("collision_mask", 1) + +func save_to_cache(): + return { + "block_alignment": block_alignment, + "match_selected_block": match_selected_block, + "default_block_elevation": default_block_elevation, + "default_block_height": default_block_height, + "collision_type": collision_type, + "collision_layer": collision_layer, + "collision_mask": collision_mask, + } diff --git a/addons/cyclops_level_builder/tools/tool_block_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_block_settings.gd.uid new file mode 100644 index 00000000..282a08a8 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_block_settings.gd.uid @@ -0,0 +1 @@ +uid://3dmybeh0fsp1 diff --git a/addons/cyclops_level_builder/tools/tool_block_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_block_settings_editor.gd new file mode 100644 index 00000000..55e0c213 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_block_settings_editor.gd @@ -0,0 +1,92 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolBlockSettingsEditor + +var settings:ToolBlockSettings: + get: + return settings + set(value): + settings = value + dirty = true + +var dirty:bool = true + +func _ready(): + %collision_type.clear() + for text in Collision.Type.keys(): + %collision_type.add_item(text) + +func _process(delta): + if dirty: + update() + dirty = false + +func update(): + if !settings: + %check_match_selected_block.disabled = true + %default_block_elevation.disabled = true + %default_block_height.disabled = true + return + + %check_match_selected_block.disabled = false + %check_match_selected_block.button_pressed = settings.match_selected_block + %default_block_elevation.disabled = false + %default_block_elevation.value = settings.default_block_elevation + %default_block_height.disabled = false + %default_block_height.value = settings.default_block_height + + %alignment_type.selected = settings.block_alignment + + %collision_type.selected = settings.collision_type + %collision_layers.value = settings.collision_layer + %collision_mask.value = settings.collision_mask + + +func _on_default_block_height_value_changed(value:float): + settings.default_block_height = value + + +func _on_default_block_elevation_value_changed(value:float): + settings.default_block_elevation = value + + +func _on_check_match_selected_block_toggled(value:bool): + settings.match_selected_block = value + + +func _on_collision_layers_value_changed(value): + settings.collision_layer = value + + +func _on_collision_mask_value_changed(value): + settings.collision_mask = value + +func _on_collision_type_item_selected(index): + settings.collision_type = index + + +func _on_alignment_type_item_selected(index): + settings.block_alignment = index diff --git a/addons/cyclops_level_builder/tools/tool_block_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_block_settings_editor.gd.uid new file mode 100644 index 00000000..e42008a8 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_block_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://cc3wgmyr66ec diff --git a/addons/cyclops_level_builder/tools/tool_block_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_block_settings_editor.tscn new file mode 100644 index 00000000..081b7300 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_block_settings_editor.tscn @@ -0,0 +1,132 @@ +[gd_scene load_steps=3 format=3 uid="uid://baccfnd0b5yqv"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_block_settings_editor.gd" id="1_nvmrk"] +[ext_resource type="PackedScene" uid="uid://diibmlqy1mpqb" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.tscn" id="2_1r7f8"] + +[node name="ToolBlockSettings" type="PanelContainer"] +offset_right = 413.0 +offset_bottom = 232.0 +script = ExtResource("1_nvmrk") + +[node name="PanelContainer" type="PanelContainer" parent="."] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"] +layout_mode = 2 + +[node name="GridContainer" type="GridContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Type" + +[node name="collision_type" type="OptionButton" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 4 +selected = 0 +popup/item_0/text = "NONE" +popup/item_0/id = 0 +popup/item_1/text = "STATIC" +popup/item_1/id = 1 +popup/item_2/text = "KINEMATIC" +popup/item_2/id = 2 +popup/item_3/text = "RIGID" +popup/item_3/id = 3 + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Layers" + +[node name="collision_layers" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label3" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Mask" + +[node name="collision_mask" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label5" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Alignment" + +[node name="alignment_type" type="OptionButton" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 4 +selected = 0 +popup/item_0/text = "Align to surface" +popup/item_0/id = 0 +popup/item_1/text = "XY Plane" +popup/item_1/id = 1 +popup/item_2/text = "XZ Plane" +popup/item_2/id = 2 +popup/item_3/text = "YZ Plane" +popup/item_3/id = 3 + +[node name="Label4" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Match Active Block" + +[node name="check_match_selected_block" type="CheckBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "When drawing in empty space, copy elevation and height properties from currently selected block." +disabled = true +text = "On" + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +text = "Orthogonal Viewport:" + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 16 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/MarginContainer"] +layout_mode = 2 + +[node name="GridContainer" type="GridContainer" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Default Block Elevation" + +[node name="default_block_elevation" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer" instance=ExtResource("2_1r7f8")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +disabled = true + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Default Block Height" + +[node name="default_block_height" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer" instance=ExtResource("2_1r7f8")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +disabled = true + +[connection signal="item_selected" from="PanelContainer/VBoxContainer/GridContainer/collision_type" to="." method="_on_collision_type_item_selected"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/collision_layers" to="." method="_on_collision_layers_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/collision_mask" to="." method="_on_collision_mask_value_changed"] +[connection signal="item_selected" from="PanelContainer/VBoxContainer/GridContainer/alignment_type" to="." method="_on_alignment_type_item_selected"] +[connection signal="toggled" from="PanelContainer/VBoxContainer/GridContainer/check_match_selected_block" to="." method="_on_check_match_selected_block_toggled"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer/default_block_elevation" to="." method="_on_default_block_elevation_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer/default_block_height" to="." method="_on_default_block_height_value_changed"] diff --git a/addons/cyclops_level_builder/tools/tool_clip.gd b/addons/cyclops_level_builder/tools/tool_clip.gd new file mode 100644 index 00000000..a10a80a0 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_clip.gd @@ -0,0 +1,170 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolClip + +const TOOL_ID:String = "clip" + +enum ToolState { READY, PICK_POINTS, PICK_SIDE } +var tool_state:ToolState = ToolState.READY + +var clip_points:PackedVector3Array +var clip_normals:PackedVector3Array +var clip_block:CyclopsBlock + +func _get_tool_id()->String: + return TOOL_ID + +func has_clip_point(point:Vector3)->bool: + for p in clip_points: + if p.is_equal_approx(point): + return true + return false + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + + if !clip_points.is_empty(): + global_scene.draw_points(clip_points, global_scene.vertex_tool_material) + + if clip_points.size() >= 2: + global_scene.draw_loop(clip_points, false, global_scene.tool_material) + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + var blocks_root:Node = builder.get_block_add_parent() + #var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_BACKSPACE: + if e.is_pressed(): + if !clip_points.is_empty(): + var count:int = clip_points.size() + clip_points.remove_at(count - 1) + clip_normals.remove_at(count - 1) + if clip_points.is_empty(): + clip_block = null + + return true + + elif e.keycode == KEY_ESCAPE: + clip_points.clear() + clip_normals.clear() + clip_block = null +# _draw_tool(viewport_camera) + return true + + elif e.keycode == KEY_ENTER: + #Cut at plane + var cut_plane:Plane + + #for p in clip_points: + #print("clip ", p) + + if clip_points.size() == 3: + cut_plane = Plane(clip_points[0], clip_points[1], clip_points[2]) + elif clip_points.size() == 2: + var dir:Vector3 = clip_points[1] - clip_points[0] + var face_dir:Vector3 = clip_normals[0].cross(dir) + cut_plane = Plane(face_dir.normalized(), clip_points[0]) + else: + #Cannot cut with fewer than 2 points + return true + + var cmd:CommandClipBlock = CommandClipBlock.new() + cmd.builder = builder + cmd.blocks_root_path = blocks_root.get_path() + cmd.block_path = clip_block.get_path() + cmd.block_sibling_name = GeneralUtil.find_unique_name(blocks_root, "Block_") + cmd.cut_plane = cut_plane + cmd.material_path = builder.tool_material_path + cmd.uv_transform = builder.tool_uv_transform + + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + #Clean up + clip_points.clear() + clip_normals.clear() + clip_block = null + +# _draw_tool(viewport_camera) + + return true + + if event is InputEventMouseButton: + + var e:InputEventMouseButton = event + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return false + + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + if result: + #var p:Vector3 = to_local(result.position, blocks_root.global_transform.inverse(), grid_step_size) +# var p:Vector3 = MathUtil.snap_to_grid(result.get_world_position(), grid_step_size) + var p_hit:Vector3 = result.get_world_position() + var p_norm:Vector3 = result.get_world_normal() + var p:Vector3 = builder.get_snapping_manager().snap_point(p_hit, SnappingQuery.new(viewport_camera)) + p = MathUtil.closest_point_on_plane(p, p_hit, p_norm) + + if !has_clip_point(p): + if clip_points.is_empty(): + clip_block = result.object + + if clip_points.size() < 3: + clip_points.append(p) + clip_normals.append(p_norm) + else: + clip_points[2] = p + clip_normals[2] = p_norm + +# _draw_tool(viewport_camera) + + return true + + return false + + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.OBJECT + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() diff --git a/addons/cyclops_level_builder/tools/tool_clip.gd.uid b/addons/cyclops_level_builder/tools/tool_clip.gd.uid new file mode 100644 index 00000000..566022d5 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_clip.gd.uid @@ -0,0 +1 @@ +uid://dn7yacvdlbtty diff --git a/addons/cyclops_level_builder/tools/tool_cylinder.gd b/addons/cyclops_level_builder/tools/tool_cylinder.gd new file mode 100644 index 00000000..129c31a9 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_cylinder.gd @@ -0,0 +1,297 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolCylinder + +const TOOL_ID:String = "cylinder" + +enum ToolState { READY, FIRST_RING, SECOND_RING, DRAG_HEIGHT } +var tool_state:ToolState = ToolState.READY + +#@export var segments:int = 16 +#@export var tube:bool = false +var settings:ToolCylinderSettings = ToolCylinderSettings.new() + +var floor_normal:Vector3 +var base_center:Vector3 +var block_drag_cur:Vector3 +var drag_offset:Vector3 +var first_ring_radius:float +var second_ring_radius:float + + + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.OBJECT + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + var cache:Dictionary = builder.get_tool_cache(TOOL_ID) + settings.load_from_cache(cache) + +func _deactivate(): + var cache:Dictionary = settings.save_to_cache() + builder.set_tool_cache(TOOL_ID, cache) + + +func _get_tool_properties_editor()->Control: +# var res_insp:ResourceInspector = preload("res://addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.tscn").instantiate() + var ed:ToolCylinderSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + + if tool_state == ToolState.FIRST_RING: + var bounding_points:PackedVector3Array = MathUtil.create_circle_points(base_center, floor_normal, first_ring_radius, settings.segments) + global_scene.draw_loop(bounding_points, true, global_scene.tool_material) + global_scene.draw_points(bounding_points, global_scene.vertex_tool_material) + + elif tool_state == ToolState.SECOND_RING: + for radius in [first_ring_radius, second_ring_radius]: + var bounding_points:PackedVector3Array = MathUtil.create_circle_points(base_center, floor_normal, radius, settings.segments) + global_scene.draw_loop(bounding_points, true, global_scene.tool_material) + global_scene.draw_points(bounding_points, global_scene.vertex_tool_material) + + elif tool_state == ToolState.DRAG_HEIGHT: + var bounding_points:PackedVector3Array = MathUtil.create_circle_points(base_center, floor_normal, first_ring_radius, settings.segments) + global_scene.draw_prism(bounding_points, drag_offset, global_scene.tool_material, global_scene.vertex_tool_material) + + if settings.tube: + bounding_points = MathUtil.create_circle_points(base_center, floor_normal, second_ring_radius, settings.segments) + global_scene.draw_prism(bounding_points, drag_offset, global_scene.tool_material, global_scene.vertex_tool_material) + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + var blocks_root:Node = builder.get_block_add_parent() + #var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ESCAPE: + if e.is_pressed(): + tool_state = ToolState.READY + return true + + elif event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + + if tool_state == ToolState.READY: + tool_state = ToolState.FIRST_RING + + first_ring_radius = 0 + second_ring_radius = 0 + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + if result && settings.block_alignment == BlockAlignment.Type.ALIGN_TO_SURFACE: + #print("init base point block") +# floor_normal = result.normal + floor_normal = result.get_world_normal() + +# var p:Vector3 = to_local(result.position, blocks_root.global_transform.inverse(), grid_step_size) + var p:Vector3 = builder.get_snapping_manager().snap_point(result.get_world_position(), SnappingQuery.new(viewport_camera)) + base_center = p + + return true + + else: + #print("init base point empty space") + var draw_plane_point:Vector3 = Vector3.ZERO + var draw_plane_normal:Vector3 = BlockAlignment.get_plane_normal(settings.block_alignment) + if settings.match_selected_block: + draw_plane_point = calc_empty_space_draw_plane_origin(viewport_camera, draw_plane_point, draw_plane_normal) + + var hit_result = calc_hit_point_empty_space(origin, dir, viewport_camera, draw_plane_point, draw_plane_normal) + var start_pos:Vector3 = hit_result[0] + floor_normal = hit_result[1] + + var p:Vector3 = builder.get_snapping_manager().snap_point(start_pos, SnappingQuery.new(viewport_camera)) + base_center = p + + return true + else: + if tool_state == ToolState.FIRST_RING: + if settings.tube: + tool_state = ToolState.SECOND_RING + else: + var camera_dir:Vector3 = viewport_camera.project_ray_normal(e.position) + var angle_with_base:float = acos(floor_normal.dot(camera_dir)) + var drag_angle_limit:float = builder.get_global_scene().drag_angle_limit + if angle_with_base < drag_angle_limit || angle_with_base > PI - drag_angle_limit: + #block_drag_cur = base_center + floor_normal + var height = settings.default_block_height + + if settings.match_selected_block: + height = calc_active_block_orthogonal_height(base_center, floor_normal) + + block_drag_cur = base_center + floor_normal * height + drag_offset = block_drag_cur - base_center + + create_block() + + tool_state = ToolState.READY + else: + tool_state = ToolState.DRAG_HEIGHT + return true + + elif tool_state == ToolState.SECOND_RING: + var camera_dir:Vector3 = viewport_camera.project_ray_normal(e.position) + var angle_with_base:float = acos(floor_normal.dot(camera_dir)) + var drag_angle_limit:float = builder.get_global_scene().drag_angle_limit + if angle_with_base < drag_angle_limit || angle_with_base > PI - drag_angle_limit: + #block_drag_cur = base_center + floor_normal + var height = settings.default_block_height + if settings.match_selected_block: + height = calc_active_block_orthogonal_height(base_center, floor_normal) + + block_drag_cur = base_center + floor_normal * height + drag_offset = block_drag_cur - base_center + + create_block() + + tool_state = ToolState.READY + else: + + tool_state = ToolState.DRAG_HEIGHT + return true + + elif tool_state == ToolState.DRAG_HEIGHT: + + create_block() + + tool_state = ToolState.READY + return true + + #elif e.button_index == MOUSE_BUTTON_RIGHT: + #if tool_state == ToolState.FIRST_RING || tool_state == ToolState.SECOND_RING || tool_state == ToolState.DRAG_HEIGHT: + #if e.is_pressed(): + #tool_state = ToolState.READY + #return true + + elif e.button_index == MOUSE_BUTTON_WHEEL_UP: + if tool_state == ToolState.FIRST_RING || tool_state == ToolState.SECOND_RING || tool_state == ToolState.DRAG_HEIGHT: + if e.pressed: + settings.segments += 1 + return true + + elif e.button_index == MOUSE_BUTTON_WHEEL_DOWN: + if tool_state == ToolState.FIRST_RING || tool_state == ToolState.SECOND_RING || tool_state == ToolState.DRAG_HEIGHT: + if e.pressed: + settings.segments = max(settings.segments - 1, 3) + return true + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return false + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var start_pos:Vector3 = origin + builder.block_create_distance * dir +# var w2l = blocks_root.global_transform.inverse() +# var origin_local:Vector3 = w2l * origin +# var dir_local:Vector3 = w2l.basis * dir + + if tool_state == ToolState.FIRST_RING: + var p_isect:Vector3 = MathUtil.intersect_plane(origin, dir, base_center, floor_normal) + #var p_snapped = to_local(p_isect, blocks_root.global_transform.inverse(), grid_step_size) + #var p_snapped = MathUtil.snap_to_grid(p_isect, grid_step_size) + var p_snapped:Vector3 = builder.get_snapping_manager().snap_point(p_isect, SnappingQuery.new(viewport_camera)) + first_ring_radius = (p_snapped - base_center).length() + + return true + + elif tool_state == ToolState.SECOND_RING: + var p_isect:Vector3 = MathUtil.intersect_plane(origin, dir, base_center, floor_normal) + #var p_snapped = to_local(p_isect, blocks_root.global_transform.inverse(), grid_step_size) +# var p_snapped = MathUtil.snap_to_grid(p_isect, grid_step_size) + var p_snapped:Vector3 = builder.get_snapping_manager().snap_point(p_isect, SnappingQuery.new(viewport_camera)) + second_ring_radius = (p_snapped - base_center).length() + + return true + + elif tool_state == ToolState.DRAG_HEIGHT: + block_drag_cur = MathUtil.closest_point_on_line(origin, dir, base_center, floor_normal) + + block_drag_cur = builder.get_snapping_manager().snap_point(block_drag_cur, SnappingQuery.new(viewport_camera)) + + drag_offset = block_drag_cur - base_center +# var bounding_points:PackedVector3Array = MathUtil.bounding_polygon_3d(base_points, floor_normal) + +# global_scene.clear_tool_mesh() +# global_scene.draw_prism(bounding_points, drag_offset, global_scene.tool_material) + + return true + + return super._gui_input(viewport_camera, event) + +func create_block(): + var blocks_root:Node = builder.get_block_add_parent() + + var cmd:CommandAddCylinder = CommandAddCylinder.new() + cmd.builder = builder + cmd.block_name_prefix = "Block_" + cmd.blocks_root_path = blocks_root.get_path() + cmd.tube = settings.tube + cmd.origin = base_center + cmd.axis_normal = floor_normal + var height:float = drag_offset.length() if drag_offset.dot(floor_normal) > 0 else - drag_offset.length() + cmd.height = height + cmd.collision_type = settings.collision_type + cmd.collision_layers = settings.collision_layer + cmd.collision_mask = settings.collision_mask + + if settings.tube: + cmd.radius_inner = min(first_ring_radius, second_ring_radius) + cmd.radius_outer = max(first_ring_radius, second_ring_radius) + else: + cmd.radius_inner = first_ring_radius + cmd.radius_outer = first_ring_radius + cmd.segments = settings.segments + cmd.uv_transform = builder.tool_uv_transform + cmd.material_path = builder.tool_material_path + + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/tools/tool_cylinder.gd.uid b/addons/cyclops_level_builder/tools/tool_cylinder.gd.uid new file mode 100644 index 00000000..9461cffd --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_cylinder.gd.uid @@ -0,0 +1 @@ +uid://b5sri8n3mrk7n diff --git a/addons/cyclops_level_builder/tools/tool_cylinder_settings.gd b/addons/cyclops_level_builder/tools/tool_cylinder_settings.gd new file mode 100644 index 00000000..93fd993f --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_cylinder_settings.gd @@ -0,0 +1,62 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolCylinderSettings + +@export var block_alignment:BlockAlignment.Type = BlockAlignment.Type.ALIGN_TO_SURFACE +@export var match_selected_block:bool = true +@export var default_block_elevation:float = 0 +@export var default_block_height:float = 1 +@export var collision_type:Collision.Type = Collision.Type.STATIC +@export_flags_3d_physics var collision_layer:int = 1 +@export_flags_3d_physics var collision_mask:int = 1 + +@export var segments:int = 16 +@export var tube:bool = false + +func load_from_cache(cache:Dictionary): + block_alignment = cache.get("block_alignment", BlockAlignment.Type.ALIGN_TO_SURFACE) + match_selected_block = cache.get("match_selected_block", true) + default_block_elevation = cache.get("default_block_elevation", 0) + default_block_height = cache.get("default_block_height", 1) + collision_type = cache.get("collision_type", Collision.Type.STATIC) + collision_layer = cache.get("collision_layer", 1) + collision_mask = cache.get("collision_mask", 1) + + segments = cache.get("segments", 16) + tube = cache.get("tube", false) + +func save_to_cache(): + return { + "block_alignment": block_alignment, + "match_selected_block": match_selected_block, + "default_block_elevation": default_block_elevation, + "default_block_height": default_block_height, + "collision_type": collision_type, + "collision_layer": collision_layer, + "collision_mask": collision_mask, + "segments": segments, + "tube": tube, + } diff --git a/addons/cyclops_level_builder/tools/tool_cylinder_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_cylinder_settings.gd.uid new file mode 100644 index 00000000..5e331a57 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_cylinder_settings.gd.uid @@ -0,0 +1 @@ +uid://dp8ryhvwvxwk8 diff --git a/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd new file mode 100644 index 00000000..de7fe39b --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd @@ -0,0 +1,104 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolCylinderSettingsEditor + + +var settings:ToolCylinderSettings: + get: + return settings + set(value): + settings = value + dirty = true + +var dirty:bool = true + +func _ready(): + %collision_type.clear() + for text in Collision.Type.keys(): + %collision_type.add_item(text) + +func _process(delta): + if dirty: + update() + dirty = false + + +func update(): + if !settings: + %check_tube.disabled = true + %check_match_selected_block.disabled = true + %default_block_elevation.disabled = true + %default_block_height.disabled = true + return + + %spin_segments.value = settings.segments + %check_tube.disabled = false + %check_tube.button_pressed = settings.match_selected_block + %check_match_selected_block.disabled = false + %check_match_selected_block.button_pressed = settings.match_selected_block + %default_block_elevation.disabled = false + %default_block_elevation.value = settings.default_block_elevation + %default_block_height.disabled = false + %default_block_height.value = settings.default_block_height + + %alignment_type.selected = settings.block_alignment + + %collision_type.selected = settings.collision_type + %collision_layers.value = settings.collision_layer + %collision_mask.value = settings.collision_mask + +func _on_check_match_selected_block_toggled(value): + settings.match_selected_block = value + + +func _on_default_block_elevation_value_changed(value): + settings.default_block_elevation = value + + +func _on_default_block_height_value_changed(value): + settings.default_block_height = value + + +func _on_check_tube_toggled(value): + settings.tube = value + + +func _on_spin_segments_value_changed(value): + settings.segments = value + +func _on_collision_layers_value_changed(value): + settings.collision_layer = value + + +func _on_collision_mask_value_changed(value): + settings.collision_mask = value + +func _on_collision_type_item_selected(index): + settings.collision_type = index + + +func _on_alignment_type_item_selected(index): + settings.block_alignment = index diff --git a/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd.uid new file mode 100644 index 00000000..49ce73b6 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://c6botn5punjjv diff --git a/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.tscn new file mode 100644 index 00000000..044d69d5 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.tscn @@ -0,0 +1,157 @@ +[gd_scene load_steps=3 format=3 uid="uid://dx804lkvek177"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_cylinder_settings_editor.gd" id="1_oyugv"] +[ext_resource type="PackedScene" uid="uid://diibmlqy1mpqb" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.tscn" id="2_wm7rv"] + +[node name="ToolCylinderSettings" type="PanelContainer"] +offset_right = 413.0 +offset_bottom = 232.0 +script = ExtResource("1_oyugv") + +[node name="PanelContainer" type="PanelContainer" parent="."] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"] +layout_mode = 2 + +[node name="GridContainer" type="GridContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label4" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Type" + +[node name="collision_type" type="OptionButton" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 4 +selected = 0 +popup/item_0/text = "NONE" +popup/item_0/id = 0 +popup/item_1/text = "STATIC" +popup/item_1/id = 1 +popup/item_2/text = "KINEMATIC" +popup/item_2/id = 2 +popup/item_3/text = "RIGID" +popup/item_3/id = 3 + +[node name="Label5" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Layers" + +[node name="collision_layers" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label6" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Mask" + +[node name="collision_mask" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Segments" + +[node name="spin_segments" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +min_value = 3.0 +max_value = 20.0 +value = 3.0 +rounded = true +allow_greater = true + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Tube" + +[node name="check_tube" type="CheckBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +disabled = true +text = "On" + +[node name="Label7" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Alignment" + +[node name="alignment_type" type="OptionButton" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 4 +selected = 0 +popup/item_0/text = "Align to surface" +popup/item_0/id = 0 +popup/item_1/text = "XY Plane" +popup/item_1/id = 1 +popup/item_2/text = "XZ Plane" +popup/item_2/id = 2 +popup/item_3/text = "YZ Plane" +popup/item_3/id = 3 + +[node name="Label3" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Match selected block" + +[node name="check_match_selected_block" type="CheckBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "When drawing in empty space, copy elevation and height properties from currently selected block." +disabled = true +text = "On" + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +text = "Orthogonal Viewport:" + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 16 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/MarginContainer"] +layout_mode = 2 + +[node name="GridContainer" type="GridContainer" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Default Block Elevation" + +[node name="default_block_elevation" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer" instance=ExtResource("2_wm7rv")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +disabled = true + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Default Block Height" + +[node name="default_block_height" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer" instance=ExtResource("2_wm7rv")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +disabled = true + +[connection signal="item_selected" from="PanelContainer/VBoxContainer/GridContainer/collision_type" to="." method="_on_collision_type_item_selected"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/collision_layers" to="." method="_on_collision_layers_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/collision_mask" to="." method="_on_collision_mask_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/spin_segments" to="." method="_on_spin_segments_value_changed"] +[connection signal="toggled" from="PanelContainer/VBoxContainer/GridContainer/check_tube" to="." method="_on_check_tube_toggled"] +[connection signal="item_selected" from="PanelContainer/VBoxContainer/GridContainer/alignment_type" to="." method="_on_alignment_type_item_selected"] +[connection signal="toggled" from="PanelContainer/VBoxContainer/GridContainer/check_match_selected_block" to="." method="_on_check_match_selected_block_toggled"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer/default_block_elevation" to="." method="_on_default_block_elevation_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer/default_block_height" to="." method="_on_default_block_height_value_changed"] diff --git a/addons/cyclops_level_builder/tools/tool_duplicate.gd b/addons/cyclops_level_builder/tools/tool_duplicate.gd new file mode 100644 index 00000000..6873ef7c --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_duplicate.gd @@ -0,0 +1,124 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolDuplicate + +const TOOL_ID:String = "duplicate" + +var drag_start_point:Vector3 +var cmd_duplicate:CommandDuplicateBlocks + +enum ToolState { READY, DRAGGING, DONE } +var tool_state:ToolState = ToolState.READY + +func _get_tool_id()->String: + return TOOL_ID + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + if event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if !e.is_pressed(): + if tool_state == ToolState.DRAGGING: + #print("committing duplicate") + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + if cmd_duplicate.will_change_anything(): + cmd_duplicate.add_to_undo_manager(undo) + + tool_state = ToolState.DONE + builder.switch_to_tool(ToolBlock.new()) + + return true + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return super._gui_input(viewport_camera, event) + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + if tool_state == ToolState.DRAGGING: + var drag_to:Vector3 + if e.alt_pressed: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_start_point, Vector3.UP) + else: + drag_to = MathUtil.intersect_plane(origin, dir, drag_start_point, Vector3.UP) + + var offset:Vector3 = drag_to - drag_start_point + offset = builder.get_snapping_manager().snap_point(offset, SnappingQuery.new(viewport_camera)) + #print("drag offset %s" % offset) + + #print("duplicate drag by %s" % offset) + + cmd_duplicate.move_offset = offset + cmd_duplicate.do_it() + + return true + + + return false + + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + #Invoke command immediately + cmd_duplicate = CommandDuplicateBlocks.new() + cmd_duplicate.builder = builder + var blocks_root:Node = builder.get_block_add_parent() + cmd_duplicate.blocks_root_path = blocks_root.get_path() + var centroid:Vector3 + var count:int = 0 + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + cmd_duplicate.blocks_to_duplicate.append(block.get_path()) + centroid += block.global_transform * block.control_mesh.bounds.get_center() + count += 1 + + cmd_duplicate.lock_uvs = builder.lock_uvs + + centroid /= count + drag_start_point = centroid + tool_state = ToolState.DRAGGING + + cmd_duplicate.do_it() + + + diff --git a/addons/cyclops_level_builder/tools/tool_duplicate.gd.uid b/addons/cyclops_level_builder/tools/tool_duplicate.gd.uid new file mode 100644 index 00000000..618d55f9 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_duplicate.gd.uid @@ -0,0 +1 @@ +uid://07htn8rqg4qj diff --git a/addons/cyclops_level_builder/tools/tool_edit_base.gd b/addons/cyclops_level_builder/tools/tool_edit_base.gd new file mode 100644 index 00000000..1600b43b --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_base.gd @@ -0,0 +1,100 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolEditBase + +var mouse_hover_pos:Vector2 + +var drag_select_start_pos:Vector2 +var drag_select_to_pos:Vector2 + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_Q && e.alt_pressed: + select_block_under_cursor(viewport_camera, mouse_hover_pos) + + return true + + + elif event is InputEventMouseButton: + var e:InputEventMouseButton = event + mouse_hover_pos = e.position + return false + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + mouse_hover_pos = e.position + return false + + return false + +func pick_material(global_scene:CyclopsGlobalScene, selected:bool = false, active = false)->Material: + if active: + return global_scene.tool_edit_active_material + if selected: + return global_scene.tool_edit_selected_material + return global_scene.tool_edit_unselected_material + +func pick_vertex_material(global_scene:CyclopsGlobalScene, selected:bool = false, active = false)->Material: + if active: + return global_scene.vertex_active_material + if selected: + return global_scene.vertex_selected_material + return global_scene.vertex_unselected_material + + +func calc_gizmo_basis(average_normal:Vector3, active_block:Node3D, viewport_camera:Camera3D, orientation:TransformSpace.Type)->Basis: + var result:Basis + + match orientation: + TransformSpace.Type.GLOBAL: + result = Basis.IDENTITY + TransformSpace.Type.LOCAL: + result = active_block.global_basis + + #var xform:Transform3D = active_block.global_transform + #gizmo_translate.global_transform = xform + #gizmo_translate.global_position = origin + TransformSpace.Type.NORMAL: + var up:Vector3 = Vector3.UP + var x:Vector3 = up.cross(average_normal).normalized() + var y:Vector3 = average_normal.cross(x) + #gizmo_translate.global_basis = Basis(x, y, average_normal) + #gizmo_translate.global_position = origin + result = Basis(x, y, average_normal) + TransformSpace.Type.VIEW: + #gizmo_translate.global_basis = viewport_camera.global_basis + #gizmo_translate.global_position = origin + + result = viewport_camera.global_basis + TransformSpace.Type.PARENT: + result = active_block.get_parent_node_3d().global_basis + #var xform:Transform3D = active_block.get_parent_node_3d().global_transform + #gizmo_translate.global_transform = xform + + return result diff --git a/addons/cyclops_level_builder/tools/tool_edit_base.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_base.gd.uid new file mode 100644 index 00000000..956ef484 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_base.gd.uid @@ -0,0 +1 @@ +uid://cf7gnuvlibc4r diff --git a/addons/cyclops_level_builder/tools/tool_edit_edge.gd b/addons/cyclops_level_builder/tools/tool_edit_edge.gd new file mode 100644 index 00000000..67e332cd --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_edge.gd @@ -0,0 +1,646 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends ToolEditBase +class_name ToolEditEdge + +const TOOL_ID:String = "edit_edge" + +var handles:Array[HandleEdge] = [] + +enum ToolState { NONE, READY, DRAGGING, MOVE_HANDLES_CLICK, DRAG_SELECTION } +var tool_state:ToolState = ToolState.NONE + +#var drag_handle:HandleEdge +var drag_mouse_start_pos:Vector2 +var drag_handle_start_pos:Vector3 + +#enum MoveConstraint { NONE, AXIS_X, AXIS_Y, AXIS_Z, PLANE_XY, PLANE_XZ, PLANE_YZ, PLANE_VIEWPORT } +var move_constraint:MoveConstraint.Type = MoveConstraint.Type.NONE + +var gizmo_translate:Node3D + +var cmd_move_edge:CommandMoveEdges + + +class PickHandleResult extends RefCounted: + var handle:HandleEdge + var position:Vector3 + + +var settings:ToolEditEdgeSettings = ToolEditEdgeSettings.new() + +var average_normal:Vector3 = Vector3.UP + +func _get_tool_id()->String: + return TOOL_ID + +func _get_tool_properties_editor()->Control: + var ed:ToolEditEdgeSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func draw_gizmo(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + if !gizmo_translate: + gizmo_translate = preload("res://addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn").instantiate() + + var origin:Vector3 + var count:int = 0 + for h in handles: + var block:CyclopsBlock = builder.get_node(h.block_path) + var l2w:Transform3D = block.global_transform + + if h.edge_index >= block.control_mesh.edges.size(): + continue + var e:ConvexVolume.EdgeInfo = block.control_mesh.edges[h.edge_index] + if e.selected: +# print("adding midpoint ", e.get_midpoint()) + origin += l2w * e.get_midpoint() + count += 1 + + if count == 0: + global_scene.set_custom_gizmo(null) + else: + origin /= count + global_scene.set_custom_gizmo(gizmo_translate) +# gizmo_translate.global_transform.origin = origin + var active_block:Node3D = builder.get_active_block() + + gizmo_translate.global_basis = calc_gizmo_basis(average_normal, active_block, viewport_camera, settings.transform_space) + gizmo_translate.global_position = origin + + #match settings.transform_space: + #TransformSpace.Type.GLOBAL: + #var xform:Transform3D = Transform3D.IDENTITY + #xform.origin = origin + #gizmo_translate.global_transform = xform + #TransformSpace.Type.LOCAL: + #var xform:Transform3D = active_block.global_transform + #gizmo_translate.global_transform = xform + #gizmo_translate.global_position = origin + #TransformSpace.Type.NORMAL: + #var up:Vector3 = Vector3.UP + #var x:Vector3 = up.cross(average_normal).normalized() + #var y:Vector3 = average_normal.cross(x) + #gizmo_translate.global_basis = Basis(x, y, average_normal) + #gizmo_translate.global_position = origin + #TransformSpace.Type.VIEW: + #gizmo_translate.global_basis = viewport_camera.global_basis + #gizmo_translate.global_position = origin + #TransformSpace.Type.PARENT: + #var xform:Transform3D = active_block.get_parent_node_3d().global_transform + #gizmo_translate.global_transform = xform +# + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + if tool_state == ToolState.DRAG_SELECTION: + global_scene.draw_screen_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos, global_scene.selection_rect_material) + + for h in handles: + var block:CyclopsBlock = builder.get_node(h.block_path) + if h.edge_index >= block.control_mesh.edges.size(): + #TODO: Sometimes we are retaining handles that do not corepond to the correct edges after an undo operation. + continue + var e:ConvexVolume.EdgeInfo = block.control_mesh.edges[h.edge_index] + var p0:Vector3 = block.global_transform * block.control_mesh.vertices[e.start_index].point + var p1:Vector3 = block.global_transform * block.control_mesh.vertices[e.end_index].point + + var active:bool = block.control_mesh.active_edge == h.edge_index + global_scene.draw_vertex((p0 + p1) / 2, pick_vertex_material(global_scene, e.selected, active)) + global_scene.draw_line(p0, p1, pick_material(global_scene, e.selected, active)) + + draw_gizmo(viewport_camera) + +func setup_tool(): + handles = [] + + average_normal = Vector3.ZERO + #print("setup_tool") + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + var l2w:Transform3D = block.global_transform + + var l2w_normal:Basis = l2w.basis.transposed().inverse() + + for e_idx in block.control_mesh.edges.size(): + var ctl_mesh:ConvexVolume = block.control_mesh + var e:ConvexVolume.EdgeInfo = ctl_mesh.edges[e_idx] + + var handle:HandleEdge = HandleEdge.new() + handle.edge_index = e_idx + handle.block_path = block.get_path() + handles.append(handle) + + if e.selected: + var edge_normal:Vector3 = Vector3.ZERO + for f_idx in e.face_indices: + #print("f_idx ", f_idx) + var f:ConvexVolume.FaceInfo = ctl_mesh.faces[f_idx] + #print("f.normal ", f.normal) + edge_normal += f.get_area_vector_x2().normalized() + + average_normal += l2w_normal * edge_normal.normalized() + #print("average_normal ", average_normal) + + average_normal = average_normal.normalized() + #print("setup_tool handles.size() ", handles.size()) + +func pick_closest_handle(viewport_camera:Camera3D, position:Vector2, radius:float)->PickHandleResult: + var best_dist:float = INF + var best_handle:HandleEdge = null + var best_pick_position:Vector3 + + var pick_origin:Vector3 = viewport_camera.project_ray_origin(position) + var pick_dir:Vector3 = viewport_camera.project_ray_normal(position) + + #print("pick_closest_handle") + for h in handles: + #print("<<0>>") + #print("h ", h) + var block:CyclopsBlock = builder.get_node(h.block_path) + #print("<<0.1>>") + var ctl_mesh:ConvexVolume = block.control_mesh + #print("<<0.2>>") + if ctl_mesh.edges.size() <= h.edge_index: + continue + var edge:ConvexVolume.EdgeInfo = ctl_mesh.edges[h.edge_index] + #print("<<1>>") + + var p0 = ctl_mesh.vertices[edge.start_index].point + var p1 = ctl_mesh.vertices[edge.end_index].point + var p0_world:Vector3 = block.global_transform * p0 + var p1_world:Vector3 = block.global_transform * p1 + + var p0_screen:Vector2 = viewport_camera.unproject_position(p0_world) + var p1_screen:Vector2 = viewport_camera.unproject_position(p1_world) + + var dist_to_seg_2d_sq = MathUtil.dist_to_segment_squared_2d(position, p0_screen, p1_screen) + + #print("<<2>>") + if dist_to_seg_2d_sq > radius * radius: + #print("<<2.5>>") + #Failed handle radius test + continue + #print("<<3>>") + + var point_on_seg:Vector3 = MathUtil.closest_point_on_segment(pick_origin, pick_dir, p0_world, p1_world) + #print("dist_to_seg_2d_sq ", dist_to_seg_2d_sq) + + var offset:Vector3 = point_on_seg - pick_origin + var parallel:Vector3 = offset.project(pick_dir) + var dist = parallel.dot(pick_dir) + #print("offset ", offset) + #print("parallel ", parallel) + #print("dist ", dist) + #print("<<4>>") + if dist <= 0: + #Behind camera + continue + + #print("<<5>>") + #print("best_dist ", best_dist) + #print("h pos %s ray orig %s ray dir %s offset %s para %s dist %s" % [str(h.position), pick_origin, pick_dir, offset, parallel, dist]) + if dist >= best_dist: + continue + + #print("<<6>>") + best_pick_position = point_on_seg + best_dist = dist + best_handle = h + #print("best_handle ", best_handle) + #print("<<7>>") + + #print("bar") + if !best_handle: + return null + + #print("foo") + var result:PickHandleResult = PickHandleResult.new() + result.handle = best_handle + result.position = best_pick_position + #print("result ", result) + return result + +func active_node_changed(): + setup_tool() + +func active_node_updated(): + setup_tool() + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.EDIT + builder.edit_mode = CyclopsLevelBuilder.EditMode.EDGE + builder.active_node_changed.connect(active_node_changed) + + setup_tool() + + +func _deactivate(): + super._deactivate() + builder.active_node_changed.disconnect(active_node_changed) + + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.set_custom_gizmo(null) + + +func start_drag(viewport_camera:Camera3D, event:InputEvent): + var e:InputEventMouseMotion = event + move_constraint = MoveConstraint.Type.NONE + + if gizmo_translate: + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var part_res:GizmoTranslate.IntersectResult = gizmo_translate.intersect(origin, dir, viewport_camera) + if part_res: + #print("Gizmo hit ", part_res.part) + match part_res.part: + GizmoTranslate.Part.AXIS_X: + move_constraint = MoveConstraint.Type.AXIS_X + GizmoTranslate.Part.AXIS_Y: + move_constraint = MoveConstraint.Type.AXIS_Y + GizmoTranslate.Part.AXIS_Z: + move_constraint = MoveConstraint.Type.AXIS_Z + GizmoTranslate.Part.PLANE_XY: + move_constraint = MoveConstraint.Type.PLANE_XY + GizmoTranslate.Part.PLANE_XZ: + move_constraint = MoveConstraint.Type.PLANE_XZ + GizmoTranslate.Part.PLANE_YZ: + move_constraint = MoveConstraint.Type.PLANE_YZ + + drag_handle_start_pos = part_res.pos_world +# drag_handle_start_pos = gizmo_translate.global_position + #var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + #drag_handle_start_pos = MathUtil.snap_to_grid(start_pos, grid_step_size) + #drag_handle_start_pos = builder.get_snapping_manager().snap_point(start_pos, SnappingQuery.new(viewport_camera)) + + # print("res obj %s" % result.object.get_path()) + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + tool_state = ToolState.DRAGGING + #print("Move block") + + cmd_move_edge = CommandMoveEdges.new() + cmd_move_edge.builder = builder + + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for e_idx in vol.edges.size(): + var edge:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if edge.selected: + cmd_move_edge.add_edge(block.get_path(), e_idx) + + return + + + if e.alt_pressed: + move_constraint = MoveConstraint.Type.AXIS_Y + else: + move_constraint = MoveConstraint.Type.PLANE_XZ + + var res:PickHandleResult = pick_closest_handle(viewport_camera, drag_mouse_start_pos, builder.handle_screen_radius) + + if res: + var handle:HandleEdge = res.handle +# drag_handle = handle +# drag_handle_start_pos = handle.p_ref + drag_handle_start_pos = res.position + tool_state = ToolState.DRAGGING + #print("drag habdle start pos ", drag_handle_start_pos) + + cmd_move_edge = CommandMoveEdges.new() + cmd_move_edge.builder = builder + + var handle_block:CyclopsBlock = builder.get_node(handle.block_path) + if handle_block.control_mesh.edges[handle.edge_index].selected: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for e_idx in vol.edges.size(): + var edge:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if edge.selected: + cmd_move_edge.add_edge(block.get_path(), e_idx) + else: + cmd_move_edge.add_edge(handle.block_path, handle.edge_index) + + return + + #Drag selectio rectangle + tool_state = ToolState.DRAG_SELECTION + drag_select_start_pos = e.position + drag_select_to_pos = e.position + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + var gui_result = super._gui_input(viewport_camera, event) + if gui_result: + return true + +# var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ESCAPE: + if e.is_pressed(): + if cmd_move_edge: + cmd_move_edge.undo_it() + cmd_move_edge = null + tool_state = ToolState.NONE + + setup_tool() + + return true + + elif e.keycode == KEY_A: + + if e.is_pressed(): + var cmd:CommandSelectEdges = CommandSelectEdges.new() + cmd.builder = builder + + if e.alt_pressed: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + cmd.add_edges(block.get_path(), []) + + else: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + for e_idx in block.control_mesh.edges.size(): + cmd.add_edge(block.get_path(), e_idx) + + cmd.selection_type = Selection.Type.REPLACE + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) + + elif e.keycode == KEY_G: + + if e.is_pressed() && tool_state == ToolState.NONE: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + tool_state = ToolState.MOVE_HANDLES_CLICK + move_constraint = MoveConstraint.Type.PLANE_VIEWPORT + + drag_handle_start_pos = Vector3.INF + + cmd_move_edge = CommandMoveEdges.new() + cmd_move_edge.builder = builder + + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for e_idx in vol.edges.size(): + var edge:ConvexVolume.EdgeInfo = vol.edges[e_idx] + if edge.selected: + cmd_move_edge.add_edge(block.get_path(), e_idx) + + return true + + elif e.keycode == KEY_X: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_YZ + else: + move_constraint = MoveConstraint.Type.AXIS_X + return true + + elif e.keycode == KEY_Y: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_XZ + else: + move_constraint = MoveConstraint.Type.AXIS_Y + return true + + elif e.keycode == KEY_Z: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_XY + else: + move_constraint = MoveConstraint.Type.AXIS_Z + return true + + if event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + if tool_state == ToolState.NONE: + drag_mouse_start_pos = e.position + tool_state = ToolState.READY + + return true + else: +# print("bn up: state %s" % tool_state) + if tool_state == ToolState.READY: + #print("cmd select") + var cmd:CommandSelectEdges = CommandSelectEdges.new() + cmd.builder = builder + + var sel_blocks:Array[CyclopsBlock] + for block in sel_blocks: + cmd.add_edges(block.get_path(), []) + + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + #print("handles.size() ", handles.size()) + var res:PickHandleResult = pick_closest_handle(viewport_camera, e.position, builder.handle_screen_radius) + if res: + var handle:HandleEdge = res.handle + + #print("handle %s" % handle) + + cmd.add_edge(handle.block_path, handle.edge_index) + #print("selectibg %s" % handle.vertex_index) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + setup_tool() + + elif tool_state == ToolState.DRAGGING: + #Finish drag + #print("cmd finish drag") + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd_move_edge.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + cmd_move_edge = null + + elif tool_state == ToolState.MOVE_HANDLES_CLICK: + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd_move_edge.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + cmd_move_edge = null + + elif tool_state == ToolState.DRAG_SELECTION: + + var frustum:Array[Plane] = MathUtil.calc_frustum_camera_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos) + + var cmd:CommandSelectEdges = CommandSelectEdges.new() + cmd.builder = builder + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + + for e_idx in block.control_mesh.edges.size(): + var edge:ConvexVolume.EdgeInfo = block.control_mesh.edges[e_idx] + var point_w:Vector3 = block.global_transform * edge.get_midpoint() + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) +# var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + + #Obstruction check + if !global_scene.xray_mode && builder.display_mode != DisplayMode.Type.WIRE: + var result:IntersectResults = builder.intersect_ray_closest(origin, point_w - origin) + if result: + var res_point_w:Vector3 = result.get_world_position() + if !res_point_w.is_equal_approx(point_w): + continue + + if MathUtil.frustum_contians_point(frustum, point_w): + cmd.add_edge(block.get_path(), e_idx) + + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + #setup_tool() + + return true + + elif e.button_index == MOUSE_BUTTON_RIGHT: + if e.is_pressed(): + #Right click cancel + if cmd_move_edge: + cmd_move_edge.undo_it() + cmd_move_edge = null + tool_state = ToolState.NONE + + setup_tool() + return true + + return false + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return false + + if tool_state == ToolState.READY: + if e.position.distance_squared_to(drag_mouse_start_pos) > MathUtil.square(builder.drag_start_radius): + start_drag(viewport_camera, event) + + return true + + elif tool_state == ToolState.DRAGGING || tool_state == ToolState.MOVE_HANDLES_CLICK: + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + if !drag_handle_start_pos.is_finite(): + #If start point set to infinite, replace with point along view ray + drag_handle_start_pos = origin + dir * 20 + + var active_block:Node3D = builder.get_active_block() + var xform_basis:Basis = calc_gizmo_basis(average_normal, active_block, viewport_camera, settings.transform_space) + + #match settings.transform_space: + #TransformSpace.Type.GLOBAL: + #xform_basis = Basis.IDENTITY + #TransformSpace.Type.LOCAL: + #var active_block:Node3D = builder.get_active_block() + #xform_basis = active_block.basis + #TransformSpace.Type.NORMAL: + #var up:Vector3 = Vector3.UP + #var x:Vector3 = up.cross(average_normal).normalized() + #var y:Vector3 = average_normal.cross(x) + #xform_basis = Basis(x, y, average_normal) + #TransformSpace.Type.VIEW: + #xform_basis = viewport_camera.global_basis + #TransformSpace.Type.PARENT: + #var active_block:Node3D = builder.get_active_block().get_parent_node_3d() + #xform_basis = active_block.basis + + var drag_to:Vector3 + match move_constraint: + MoveConstraint.Type.AXIS_X: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.x) + MoveConstraint.Type.AXIS_Y: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.y) + MoveConstraint.Type.AXIS_Z: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.z) + MoveConstraint.Type.PLANE_XY: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.z) + MoveConstraint.Type.PLANE_XZ: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.y) + MoveConstraint.Type.PLANE_YZ: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.x) + MoveConstraint.Type.PLANE_VIEWPORT: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, viewport_camera.global_transform.basis.z) + + var offset:Vector3 = drag_to - drag_handle_start_pos + offset = builder.get_snapping_manager().snap_point(offset, SnappingQuery.new(viewport_camera)) + #drag_to = drag_handle_start_pos + offset + + cmd_move_edge.move_offset = offset + cmd_move_edge.do_it() + + setup_tool() +# draw_tool() + return true + + elif tool_state == ToolState.DRAG_SELECTION: + drag_select_to_pos = e.position + return true + + return false diff --git a/addons/cyclops_level_builder/tools/tool_edit_edge.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_edge.gd.uid new file mode 100644 index 00000000..03629fff --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_edge.gd.uid @@ -0,0 +1 @@ +uid://b0w83m8apvlal diff --git a/addons/cyclops_level_builder/tools/tool_edit_edge_settings.gd b/addons/cyclops_level_builder/tools/tool_edit_edge_settings.gd new file mode 100644 index 00000000..01589683 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_edge_settings.gd @@ -0,0 +1,39 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolEditEdgeSettings + +@export var transform_space:TransformSpace.Type = TransformSpace.Type.GLOBAL +@export var triplanar_lock_uvs:bool = true + +func load_from_cache(cache:Dictionary): + transform_space = cache.get("transform_space", TransformSpace.Type.GLOBAL) + triplanar_lock_uvs = cache.get("triplanar_lock_uvs", true) + +func save_to_cache(): + return { + "transform_space": transform_space, + "triplanar_lock_uvs": triplanar_lock_uvs, + } diff --git a/addons/cyclops_level_builder/tools/tool_edit_edge_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_edge_settings.gd.uid new file mode 100644 index 00000000..1b234798 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_edge_settings.gd.uid @@ -0,0 +1 @@ +uid://c2a524axb7kwn diff --git a/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd new file mode 100644 index 00000000..9ee0bb9c --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd @@ -0,0 +1,60 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolEditEdgeSettingsEditor + +var settings:ToolEditEdgeSettings: + get: + return settings + set(value): + settings = value + dirty = true + +var dirty:bool = true + + +func _ready(): + %transform_space.clear() + for text in TransformSpace.Type.keys(): + %transform_space.add_item(text) + +func _process(delta): + if dirty: + update() + dirty = false + +func update(): + %transform_space.selected = settings.transform_space + %check_correct_uvs.button_pressed = settings.triplanar_lock_uvs + + pass + + +func _on_transform_space_item_selected(index): + settings.transform_space = index + + +func _on_check_correct_uvs_toggled(toggled_on): + settings.triplanar_lock_uvs = toggled_on diff --git a/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd.uid new file mode 100644 index 00000000..b8efee64 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://klg2h1rpn6nt diff --git a/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.tscn new file mode 100644 index 00000000..05222508 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=2 format=3 uid="uid://d3hfpe2pe0ml2"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_edit_edge_settings_editor.gd" id="1_a1oyt"] + +[node name="ToolMoveSettingsEditor" type="PanelContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -929.0 +offset_bottom = -415.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_a1oyt") + +[node name="GridContainer" type="GridContainer" parent="."] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Transform space" + +[node name="transform_space" type="OptionButton" parent="GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 5 +selected = 0 +popup/item_0/text = "GLOBAL" +popup/item_0/id = 0 +popup/item_1/text = "LOCAL" +popup/item_1/id = 1 +popup/item_2/text = "NORMAL" +popup/item_2/id = 2 +popup/item_3/text = "VIEW" +popup/item_3/id = 3 +popup/item_4/text = "PARENT" +popup/item_4/id = 4 + +[node name="Label2" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Triplanar lock UVs" + +[node name="check_correct_uvs" type="CheckBox" parent="GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "On" + +[connection signal="item_selected" from="GridContainer/transform_space" to="." method="_on_transform_space_item_selected"] +[connection signal="toggled" from="GridContainer/check_correct_uvs" to="." method="_on_check_correct_uvs_toggled"] diff --git a/addons/cyclops_level_builder/tools/tool_edit_face.gd b/addons/cyclops_level_builder/tools/tool_edit_face.gd new file mode 100644 index 00000000..cab14b53 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_face.gd @@ -0,0 +1,642 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends ToolEditBase +class_name ToolEditFace + +const TOOL_ID:String = "edit_face" + +var handles:Array[HandleFace] = [] + +enum ToolState { NONE, READY, DRAGGING, MOVE_HANDLES_CLICK, DRAG_SELECTION } +var tool_state:ToolState = ToolState.NONE + +#var drag_handle:HandleFace +var drag_mouse_start_pos:Vector2 +var drag_handle_start_pos:Vector3 + +#enum MoveConstraint { NONE, AXIS_X, AXIS_Y, AXIS_Z, PLANE_XY, PLANE_XZ, PLANE_YZ, PLANE_VIEWPORT } +var move_constraint:MoveConstraint.Type = MoveConstraint.Type.NONE + +var gizmo_translate:Node3D + +var cmd_move_face:CommandMoveFaces + + +class PickHandleResult extends RefCounted: + var handle:HandleFace + var position:Vector3 + +var settings:ToolEditFaceSettings = ToolEditFaceSettings.new() + +var average_normal:Vector3 = Vector3.UP + +func _get_tool_id()->String: + return TOOL_ID + +func _get_tool_properties_editor()->Control: + var ed:ToolEditFaceSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func draw_gizmo(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + if !gizmo_translate: + gizmo_translate = preload("res://addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn").instantiate() + + var origin:Vector3 + var count:int = 0 + for h in handles: + var block:CyclopsBlock = builder.get_node(h.block_path) + if !block: + continue + var l2w:Transform3D = block.global_transform + + var f:ConvexVolume.FaceInfo = block.control_mesh.faces[h.face_index] + if f.selected: +# print("adding midpoint ", e.get_midpoint()) + origin += l2w * f.get_centroid() + count += 1 + + if count == 0: + global_scene.set_custom_gizmo(null) + else: + origin /= count + global_scene.set_custom_gizmo(gizmo_translate) +# gizmo_translate.global_transform.origin = origin + var active_block:Node3D = builder.get_active_block() + + gizmo_translate.global_basis = calc_gizmo_basis(average_normal, active_block, viewport_camera, settings.transform_space) + gizmo_translate.global_position = origin + #match settings.transform_space: + #TransformSpace.Type.GLOBAL: + #var xform:Transform3D = Transform3D.IDENTITY + #xform.origin = origin + #gizmo_translate.global_transform = xform + #TransformSpace.Type.LOCAL: + #var xform:Transform3D = active_block.global_transform + #gizmo_translate.global_transform = xform + #gizmo_translate.global_position = origin + #TransformSpace.Type.NORMAL: + #var up:Vector3 = Vector3.UP + #var x:Vector3 = up.cross(average_normal).normalized() + #var y:Vector3 = average_normal.cross(x) + #gizmo_translate.global_basis = Basis(x, y, average_normal) + #gizmo_translate.global_position = origin + #TransformSpace.Type.VIEW: + #gizmo_translate.global_basis = viewport_camera.global_basis + #gizmo_translate.global_position = origin + #TransformSpace.Type.PARENT: + #var xform:Transform3D = active_block.get_parent_node_3d().global_transform + #gizmo_translate.global_transform = xform + + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + if tool_state == ToolState.DRAG_SELECTION: + global_scene.draw_screen_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos, global_scene.selection_rect_material) + + #var blocks_root:CyclopsBlocks = builder.active_node + for h in handles: +# print("draw face %s" % h) + if Engine.is_editor_hint() && !builder.has_node(h.block_path): + continue + + var block:CyclopsBlock = builder.get_node(h.block_path) + var f:ConvexVolume.FaceInfo = block.control_mesh.faces[h.face_index] + + var active:bool = block.control_mesh.active_face == h.face_index + global_scene.draw_vertex(h.p_center, pick_vertex_material(global_scene, f.selected, active)) + + var l2w:Transform3D = block.global_transform + #var w2l:Transform3D = block.global_transform.affine_inverse() + + if f.selected: + var edge_loop:PackedVector3Array = f.get_points() + for p_idx in edge_loop.size(): + edge_loop[p_idx] += f.normal * builder.tool_overlay_extrude + global_scene.draw_loop(l2w * edge_loop, true, pick_material(global_scene, f.selected, active)) + + var tris:PackedVector3Array = f.get_trianges() + for p_idx in tris.size(): + tris[p_idx] += f.normal * builder.tool_overlay_extrude + +# print("draw face %s %s %s" % [h.face_index, f.selected, f.active]) + var mat:Material = global_scene.tool_edit_active_fill_material if active else global_scene.tool_edit_selected_fill_material + global_scene.draw_triangles(l2w * tris, mat) + + draw_gizmo(viewport_camera) + +func setup_tool(): + handles = [] + #print("setup_tool") + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + average_normal = Vector3.ZERO + + for block in sel_blocks: + var l2w:Transform3D = block.global_transform + + var l2w_normal:Basis = l2w.basis.transposed().inverse() + + for f_idx in block.control_mesh.faces.size(): + + var ctl_mesh:ConvexVolume = block.control_mesh + var face:ConvexVolume.FaceInfo = ctl_mesh.faces[f_idx] + + var handle:HandleFace = HandleFace.new() + + var p_start:Vector3 = l2w * face.get_centroid() + #print("p_start %s" % p_start) + + handle.p_center = p_start + + handle.face_index = f_idx + handle.block_path = block.get_path() + handles.append(handle) + + if face.selected: + average_normal += l2w_normal * face.get_area_vector_x2() + + average_normal = average_normal.normalized() + +func pick_closest_handle(viewport_camera:Camera3D, position:Vector2, radius:float)->PickHandleResult: + + var pick_origin:Vector3 = viewport_camera.project_ray_origin(position) + var pick_dir:Vector3 = viewport_camera.project_ray_normal(position) + + if builder.display_mode == DisplayMode.Type.MATERIAL || builder.display_mode == DisplayMode.Type.MESH: + var result:IntersectResults = builder.intersect_ray_closest_selected_only(pick_origin, pick_dir) + if result: + for h in handles: + if h.block_path == result.object.get_path() && h.face_index == result.face_index: + var ret:PickHandleResult = PickHandleResult.new() + ret.handle = h + ret.position = result.get_world_position() + return ret + + elif builder.display_mode == DisplayMode.Type.WIRE: + var best_dist:float = INF + var best_handle:HandleFace = null + var best_position:Vector3 + + + for h in handles: +# var h_world_pos:Vector3 = blocks_root.global_transform * h.p_ref + var h_world_pos:Vector3 = h.p_center + var h_screen_pos:Vector2 = viewport_camera.unproject_position(h_world_pos) + if position.distance_squared_to(h_screen_pos) > radius * radius: + #Failed handle radius test + continue + + var offset:Vector3 = h_world_pos - pick_origin + var parallel:Vector3 = offset.project(pick_dir) + var dist = parallel.dot(pick_dir) + if dist <= 0: + #Behind camera + continue + + #print("h pos %s ray orig %s ray dir %s offset %s para %s dist %s perp %s" % [h.position, ray_origin, ray_dir, offset, parallel, dist, perp]) + if dist >= best_dist: + continue + + best_dist = dist + best_handle = h + best_position = h_world_pos + + var result:PickHandleResult = PickHandleResult.new() + result.handle = best_handle + result.position = best_position + return result + + return null + + + +func active_node_changed(): + setup_tool() + + +func active_node_updated(): + setup_tool() + #draw_tool() + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.EDIT + builder.edit_mode = CyclopsLevelBuilder.EditMode.FACE + builder.active_node_changed.connect(active_node_changed) + + setup_tool() + + +func _deactivate(): + super._deactivate() + builder.active_node_changed.disconnect(active_node_changed) + + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.set_custom_gizmo(null) + + +func start_drag(viewport_camera:Camera3D, event:InputEvent): + var e:InputEventMouseMotion = event + move_constraint = MoveConstraint.Type.NONE + + if gizmo_translate: + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var part_res:GizmoTranslate.IntersectResult = gizmo_translate.intersect(origin, dir, viewport_camera) + if part_res: + #print("Gizmo hit ", part_res.part) + match part_res.part: + GizmoTranslate.Part.AXIS_X: + move_constraint = MoveConstraint.Type.AXIS_X + GizmoTranslate.Part.AXIS_Y: + move_constraint = MoveConstraint.Type.AXIS_Y + GizmoTranslate.Part.AXIS_Z: + move_constraint = MoveConstraint.Type.AXIS_Z + GizmoTranslate.Part.PLANE_XY: + move_constraint = MoveConstraint.Type.PLANE_XY + GizmoTranslate.Part.PLANE_XZ: + move_constraint = MoveConstraint.Type.PLANE_XZ + GizmoTranslate.Part.PLANE_YZ: + move_constraint = MoveConstraint.Type.PLANE_YZ + + var start_pos:Vector3 = part_res.pos_world + + drag_handle_start_pos = start_pos + + # print("res obj %s" % result.object.get_path()) + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + tool_state = ToolState.DRAGGING + #print("Move block") + + cmd_move_face = CommandMoveFaces.new() + cmd_move_face.builder = builder + + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for f_idx in vol.faces.size(): + var face:ConvexVolume.FaceInfo = vol.faces[f_idx] + if face.selected: + cmd_move_face.add_face(block.get_path(), f_idx) + + return + + + if e.alt_pressed: + move_constraint = MoveConstraint.Type.AXIS_Y + else: + move_constraint = MoveConstraint.Type.PLANE_XZ + + + var res:PickHandleResult = pick_closest_handle(viewport_camera, drag_mouse_start_pos, builder.handle_screen_radius) + + if res && res.handle: + #print("pick handle %s" % res.handle) + + var handle:HandleFace = res.handle + #drag_handle = handle + drag_handle_start_pos = res.position + #print("drag_handle_start_pos %s" % drag_handle_start_pos) + tool_state = ToolState.DRAGGING + + cmd_move_face = CommandMoveFaces.new() + cmd_move_face.builder = builder + + var handle_block:CyclopsBlock = builder.get_node(handle.block_path) + if handle_block.control_mesh.faces[handle.face_index].selected: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for f_idx in vol.faces.size(): + var face:ConvexVolume.FaceInfo = vol.faces[f_idx] + if face.selected: + cmd_move_face.add_face(block.get_path(), f_idx) + + else: + cmd_move_face.add_face(handle.block_path, handle.face_index) + + return + + + #Drag selectio rectangle + tool_state = ToolState.DRAG_SELECTION + drag_select_start_pos = e.position + drag_select_to_pos = e.position + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + var gui_result = super._gui_input(viewport_camera, event) + if gui_result: + return true + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ESCAPE: + if e.is_pressed(): + if cmd_move_face: + cmd_move_face.undo_it() + cmd_move_face = null + tool_state = ToolState.NONE + + setup_tool() + + return true + + elif e.keycode == KEY_A: + + if e.is_pressed(): + var cmd:CommandSelectFaces = CommandSelectFaces.new() + cmd.builder = builder + + if e.alt_pressed: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + cmd.add_faces(block.get_path(), []) + + else: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + for f_idx in block.control_mesh.faces.size(): + cmd.add_face(block.get_path(), f_idx) + + cmd.selection_type = Selection.Type.REPLACE + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) + + elif e.keycode == KEY_G: + + if e.is_pressed() && tool_state == ToolState.NONE: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + tool_state = ToolState.MOVE_HANDLES_CLICK + move_constraint = MoveConstraint.Type.PLANE_VIEWPORT + + drag_handle_start_pos = Vector3.INF + + cmd_move_face = CommandMoveFaces.new() + cmd_move_face.builder = builder + + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for f_idx in vol.faces.size(): + var face:ConvexVolume.FaceInfo = vol.faces[f_idx] + if face.selected: + cmd_move_face.add_face(block.get_path(), f_idx) + + return true + + elif e.keycode == KEY_X: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_YZ + else: + move_constraint = MoveConstraint.Type.AXIS_X + return true + + elif e.keycode == KEY_Y: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_XZ + else: + move_constraint = MoveConstraint.Type.AXIS_Y + return true + + elif e.keycode == KEY_Z: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_XY + else: + move_constraint = MoveConstraint.Type.AXIS_Z + return true + + if event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + if tool_state == ToolState.NONE: + drag_mouse_start_pos = e.position + tool_state = ToolState.READY + + return true + else: +# print("bn up: state %s" % tool_state) + if tool_state == ToolState.READY: + #print("cmd select") + + var cmd:CommandSelectFaces = CommandSelectFaces.new() + cmd.builder = builder + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + cmd.add_faces(block.get_path(), []) + + var res:PickHandleResult = pick_closest_handle(viewport_camera, e.position, builder.handle_screen_radius) + if res: + var handle:HandleFace = res.handle + #print("pick handle %s" % handle) + + cmd.add_face(handle.block_path, handle.face_index) + #print("selecting %s" % handle.face_index) + + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + + tool_state = ToolState.NONE + setup_tool() + + elif tool_state == ToolState.DRAGGING: + #Finish drag + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd_move_face.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + cmd_move_face = null + setup_tool() + + + elif tool_state == ToolState.MOVE_HANDLES_CLICK: + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd_move_face.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + cmd_move_face = null + + elif tool_state == ToolState.DRAG_SELECTION: + + var frustum:Array[Plane] = MathUtil.calc_frustum_camera_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos) + + var cmd:CommandSelectFaces = CommandSelectFaces.new() + cmd.builder = builder + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + #print("block ", block.name) + + for f_idx in block.control_mesh.faces.size(): + var face:ConvexVolume.FaceInfo = block.control_mesh.faces[f_idx] + var point_w:Vector3 = block.global_transform * face.get_centroid() + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + + #print("precheck") + #Obstruction check + if !global_scene.xray_mode && builder.display_mode != DisplayMode.Type.WIRE: + var result:IntersectResults = builder.intersect_ray_closest(origin, point_w - origin) + if result: + var res_point_w:Vector3 = result.get_world_position() + if !res_point_w.is_equal_approx(point_w): + continue + + #print("frustum check ", point_w) + if MathUtil.frustum_contians_point(frustum, point_w): + #print("frustim hit ", point_w) + cmd.add_face(block.get_path(), f_idx) + + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + return true + + elif e.button_index == MOUSE_BUTTON_RIGHT: + if e.is_pressed(): + #Right click cancel + if cmd_move_face: + cmd_move_face.undo_it() + cmd_move_face = null + tool_state = ToolState.NONE + + setup_tool() + return true + + return false + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return false + + if tool_state == ToolState.READY: + if e.position.distance_squared_to(drag_mouse_start_pos) > MathUtil.square(builder.drag_start_radius): + start_drag(viewport_camera, event) + return true + + + elif tool_state == ToolState.DRAGGING || tool_state == ToolState.MOVE_HANDLES_CLICK: + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + + if !drag_handle_start_pos.is_finite(): + #If start point set to infinite, replace with point along view ray + drag_handle_start_pos = origin + dir * 20 + + var active_block:Node3D = builder.get_active_block() + var xform_basis:Basis = calc_gizmo_basis(average_normal, active_block, viewport_camera, settings.transform_space) + + #match settings.transform_space: + #TransformSpace.Type.GLOBAL: + #xform_basis = Basis.IDENTITY + #TransformSpace.Type.LOCAL: + #var active_block:Node3D = builder.get_active_block() + #xform_basis = active_block.basis + #TransformSpace.Type.NORMAL: + #var up:Vector3 = Vector3.UP + #var x:Vector3 = up.cross(average_normal).normalized() + #var y:Vector3 = average_normal.cross(x) + #xform_basis = Basis(x, y, average_normal) + #TransformSpace.Type.VIEW: + #xform_basis = viewport_camera.global_basis + #TransformSpace.Type.PARENT: + #var active_block:Node3D = builder.get_active_block().get_parent_node_3d() + #xform_basis = active_block.basis + + var drag_to:Vector3 + match move_constraint: + MoveConstraint.Type.AXIS_X: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.x) + MoveConstraint.Type.AXIS_Y: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.y) + MoveConstraint.Type.AXIS_Z: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.z) + MoveConstraint.Type.PLANE_XY: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.z) + MoveConstraint.Type.PLANE_XZ: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.y) + MoveConstraint.Type.PLANE_YZ: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.x) + MoveConstraint.Type.PLANE_VIEWPORT: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, viewport_camera.global_transform.basis.z) + + + var offset = drag_to - drag_handle_start_pos +# offset = MathUtil.snap_to_grid(offset, grid_step_size) + offset = builder.get_snapping_manager().snap_point(offset, SnappingQuery.new(viewport_camera)) + + #print("offset %s" % offset) + + cmd_move_face.move_offset = offset + cmd_move_face.do_it() + + setup_tool() + return true + + elif tool_state == ToolState.DRAG_SELECTION: + drag_select_to_pos = e.position + return true + + return false + diff --git a/addons/cyclops_level_builder/tools/tool_edit_face.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_face.gd.uid new file mode 100644 index 00000000..615ecc98 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_face.gd.uid @@ -0,0 +1 @@ +uid://c7gkfpce0w24u diff --git a/addons/cyclops_level_builder/tools/tool_edit_face_settings.gd b/addons/cyclops_level_builder/tools/tool_edit_face_settings.gd new file mode 100644 index 00000000..6535e82c --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_face_settings.gd @@ -0,0 +1,39 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolEditFaceSettings + +@export var transform_space:TransformSpace.Type = TransformSpace.Type.GLOBAL +@export var triplanar_lock_uvs:bool = true + +func load_from_cache(cache:Dictionary): + transform_space = cache.get("transform_space", TransformSpace.Type.GLOBAL) + triplanar_lock_uvs = cache.get("triplanar_lock_uvs", true) + +func save_to_cache(): + return { + "transform_space": transform_space, + "triplanar_lock_uvs": triplanar_lock_uvs, + } diff --git a/addons/cyclops_level_builder/tools/tool_edit_face_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_face_settings.gd.uid new file mode 100644 index 00000000..3a6eb344 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_face_settings.gd.uid @@ -0,0 +1 @@ +uid://bvc1x2ix8d3q4 diff --git a/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd new file mode 100644 index 00000000..8b20375b --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd @@ -0,0 +1,60 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolEditFaceSettingsEditor + +var settings:ToolEditFaceSettings: + get: + return settings + set(value): + settings = value + dirty = true + +var dirty:bool = true + + +func _ready(): + %transform_space.clear() + for text in TransformSpace.Type.keys(): + %transform_space.add_item(text) + +func _process(delta): + if dirty: + update() + dirty = false + +func update(): + %transform_space.selected = settings.transform_space + %check_correct_uvs.button_pressed = settings.triplanar_lock_uvs + + pass + + +func _on_transform_space_item_selected(index): + settings.transform_space = index + + +func _on_check_correct_uvs_toggled(toggled_on): + settings.triplanar_lock_uvs = toggled_on diff --git a/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd.uid new file mode 100644 index 00000000..7a145383 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://b018xts28o0gw diff --git a/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.tscn new file mode 100644 index 00000000..940d9c54 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=2 format=3 uid="uid://bxy3qukjatj4l"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_edit_face_settings_editor.gd" id="1_i7hy2"] + +[node name="ToolMoveSettingsEditor" type="PanelContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -929.0 +offset_bottom = -415.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_i7hy2") + +[node name="GridContainer" type="GridContainer" parent="."] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Transform space" + +[node name="transform_space" type="OptionButton" parent="GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 5 +selected = 0 +popup/item_0/text = "GLOBAL" +popup/item_0/id = 0 +popup/item_1/text = "LOCAL" +popup/item_1/id = 1 +popup/item_2/text = "NORMAL" +popup/item_2/id = 2 +popup/item_3/text = "VIEW" +popup/item_3/id = 3 +popup/item_4/text = "PARENT" +popup/item_4/id = 4 + +[node name="Label2" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Triplanar lock UVs" + +[node name="check_correct_uvs" type="CheckBox" parent="GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "On" + +[connection signal="item_selected" from="GridContainer/transform_space" to="." method="_on_transform_space_item_selected"] +[connection signal="toggled" from="GridContainer/check_correct_uvs" to="." method="_on_check_correct_uvs_toggled"] diff --git a/addons/cyclops_level_builder/tools/tool_edit_vertex.gd b/addons/cyclops_level_builder/tools/tool_edit_vertex.gd new file mode 100644 index 00000000..e3f5e091 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_vertex.gd @@ -0,0 +1,632 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends ToolEditBase +class_name ToolEditVertex + +const TOOL_ID:String = "edit_vertex" + +var handles:Array[HandleVertex] = [] + +enum ToolState { NONE, READY, DRAGGING, DRAGGING_ADD, MOVE_HANDLES_CLICK, DRAG_SELECTION } +var tool_state:ToolState = ToolState.NONE + +#enum MoveConstraint { NONE, AXIS_X, AXIS_Y, AXIS_Z, PLANE_XY, PLANE_XZ, PLANE_YZ, PLANE_VIEWPORT } +var move_constraint:MoveConstraint.Type = MoveConstraint.Type.NONE + +#var mouse_hover_pos:Vector2 + +#var drag_handle:HandleVertex +var drag_mouse_start_pos:Vector2 +var drag_handle_start_pos:Vector3 +var drag_home_block:NodePath +var added_point_pos:Vector3 + +var cmd_move_vertex:CommandMoveVertices +var cmd_add_vertex:CommandAddVertices + +var gizmo_translate:Node3D + +var watched_blocks:Array[CyclopsBlock] + +var settings:ToolEditVertexSettings = ToolEditVertexSettings.new() + +var average_normal:Vector3 = Vector3.UP + +func _get_tool_id()->String: + return TOOL_ID + +func _get_tool_properties_editor()->Control: + var ed:ToolEditVertexSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func draw_gizmo(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + if !gizmo_translate: + gizmo_translate = preload("res://addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn").instantiate() + + var origin:Vector3 + var count:int = 0 + for h in handles: + var block:CyclopsBlock = builder.get_node(h.block_path) + var v:ConvexVolume.VertexInfo = block.control_mesh.vertices[h.vertex_index] + if v.selected: + origin += h.position + count += 1 + + if count == 0: + global_scene.set_custom_gizmo(null) + else: + origin /= count + #print("gizmo origin ", origin) + global_scene.set_custom_gizmo(gizmo_translate) + var active_block:Node3D = builder.get_active_block() + + gizmo_translate.global_basis = calc_gizmo_basis(average_normal, active_block, viewport_camera, settings.transform_space) + gizmo_translate.global_position = origin + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + if tool_state == ToolState.DRAG_SELECTION: + global_scene.draw_screen_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos, global_scene.selection_rect_material) + + for h in handles: + var block:CyclopsBlock = builder.get_node(h.block_path) + var v:ConvexVolume.VertexInfo = block.control_mesh.vertices[h.vertex_index] + + var active:bool = block.control_mesh.active_vertex == h.vertex_index + #print("draw vert idx:%s sel:%s active:%s" % [h.vertex_index, v.selected, active]) + global_scene.draw_vertex(h.position, pick_vertex_material(global_scene, v.selected, active)) + + draw_gizmo(viewport_camera) + +func on_block_changed(): + setup_tool() + +func setup_tool(): + handles = [] + #print("setup_tool") + + for block in watched_blocks: + block.mesh_changed.disconnect(on_block_changed) + watched_blocks.clear() + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + average_normal = Vector3.ZERO + + for block in sel_blocks: +# print("block sel %s" % block.block_data.vertex_selected) + var l2w:Transform3D = block.global_transform + block.mesh_changed.connect(on_block_changed) + watched_blocks.append(block) + + var l2w_normal:Basis = l2w.basis.transposed().inverse() + + for v_idx in block.control_mesh.vertices.size(): + var v:ConvexVolume.VertexInfo = block.control_mesh.vertices[v_idx] + var handle:HandleVertex = HandleVertex.new() + handle.position = l2w * v.point + handle.initial_position = handle.position + handle.vertex_index = v_idx + handle.block_path = block.get_path() + handles.append(handle) + + if v.selected: + #print("v.normal ", l2w_normal * v.normal) + average_normal += l2w_normal * v.normal + + #print("adding handle %s" % handle) + average_normal = average_normal.normalized() + + +func pick_closest_handle(viewport_camera:Camera3D, position:Vector2, radius:float)->HandleVertex: +# print("pick radius ", radius) + var best_dist:float = INF + var best_handle:HandleVertex = null + + var origin:Vector3 = viewport_camera.project_ray_origin(position) + var dir:Vector3 = viewport_camera.project_ray_normal(position) + + for h in handles: +# var h_world_pos:Vector3 = blocks_root.global_transform * h.position + var h_world_pos:Vector3 = h.position + var h_screen_pos:Vector2 = viewport_camera.unproject_position(h_world_pos) + if position.distance_squared_to(h_screen_pos) > radius * radius: + #Failed handle radius test + continue + + var offset:Vector3 = h_world_pos - origin + var parallel:Vector3 = offset.project(dir) + var dist = parallel.dot(dir) + if dist <= 0: + #Behind camera + continue + + #print("h pos %s ray orig %s ray dir %s offset %s para %s dist %s perp %s" % [h.position, ray_origin, ray_dir, offset, parallel, dist, perp]) + if dist >= best_dist: + continue + + best_dist = dist + best_handle = h + + return best_handle + +func active_node_changed(): + setup_tool() + + +func active_node_updated(): + setup_tool() + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.EDIT + builder.edit_mode = CyclopsLevelBuilder.EditMode.VERTEX + builder.active_node_changed.connect(active_node_changed) + + setup_tool() + + +func _deactivate(): + super._deactivate() + builder.active_node_changed.disconnect(active_node_changed) + + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.set_custom_gizmo(null) + +func start_drag(viewport_camera:Camera3D, event:InputEvent): + var e:InputEventMouseMotion = event + move_constraint = MoveConstraint.Type.NONE + + if gizmo_translate: + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var part_res:GizmoTranslate.IntersectResult = gizmo_translate.intersect(origin, dir, viewport_camera) + if part_res: +# print("Gizmo hit ", part_res.part) + match part_res.part: + GizmoTranslate.Part.AXIS_X: + move_constraint = MoveConstraint.Type.AXIS_X + GizmoTranslate.Part.AXIS_Y: + move_constraint = MoveConstraint.Type.AXIS_Y + GizmoTranslate.Part.AXIS_Z: + move_constraint = MoveConstraint.Type.AXIS_Z + GizmoTranslate.Part.PLANE_XY: + move_constraint = MoveConstraint.Type.PLANE_XY + GizmoTranslate.Part.PLANE_XZ: + move_constraint = MoveConstraint.Type.PLANE_XZ + GizmoTranslate.Part.PLANE_YZ: + move_constraint = MoveConstraint.Type.PLANE_YZ + + drag_handle_start_pos = gizmo_translate.global_position + #print("drag_handle_start_pos ", drag_handle_start_pos) +# var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + # print("res obj %s" % result.object.get_path()) + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + tool_state = ToolState.DRAGGING + #print("Move block") + + cmd_move_vertex = CommandMoveVertices.new() + cmd_move_vertex.builder = builder + + cmd_move_vertex.triplanar_lock_uvs = settings.triplanar_lock_uvs + + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if v.selected: + cmd_move_vertex.add_vertex(block.get_path(), v_idx) + if vol.active_vertex == v_idx: + #drag_handle_start_pos = block.global_transform * v.point + drag_home_block = block.get_path() + + return + + if e.alt_pressed: + move_constraint = MoveConstraint.Type.AXIS_Y + else: + move_constraint = MoveConstraint.Type.PLANE_XZ + + var handle:HandleVertex = pick_closest_handle(viewport_camera, drag_mouse_start_pos, builder.handle_screen_radius) + + if handle: + #drag_handle = handle + drag_handle_start_pos = handle.position + drag_home_block = handle.block_path + tool_state = ToolState.DRAGGING + + cmd_move_vertex = CommandMoveVertices.new() + cmd_move_vertex.builder = builder + + var handle_block:CyclopsBlock = builder.get_node(handle.block_path) + if handle_block.control_mesh.vertices[handle.vertex_index].selected: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if v.selected: + cmd_move_vertex.add_vertex(block.get_path(), v_idx) + else: + cmd_move_vertex.add_vertex(handle.block_path, handle.vertex_index) + + return true + + else: + if e.ctrl_pressed: + #Add vertex under cursor + var pick_origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var pick_dir:Vector3 = viewport_camera.project_ray_normal(e.position) + var result:IntersectResults = builder.intersect_ray_closest_selected_only(pick_origin, pick_dir) + if result: + #print("start drag add") + drag_handle_start_pos = result.get_world_position() + added_point_pos = result.get_world_position() + tool_state = ToolState.DRAGGING_ADD + + cmd_add_vertex = CommandAddVertices.new() + cmd_add_vertex.builder = builder + + cmd_add_vertex.block_path = result.object.get_path() + cmd_add_vertex.points_to_add = [added_point_pos] + #print("init point %s" % added_point_pos) + + return true + + #Drag selection rectangle + tool_state = ToolState.DRAG_SELECTION + drag_select_start_pos = e.position + drag_select_to_pos = e.position + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + var gui_result = super._gui_input(viewport_camera, event) + if gui_result: + return true + +# var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ESCAPE: + if e.is_pressed(): + if cmd_move_vertex: + cmd_move_vertex.undo_it() + cmd_move_vertex = null + tool_state = ToolState.NONE + + setup_tool() + + if cmd_add_vertex: + cmd_add_vertex.undo_it() + cmd_add_vertex = null + tool_state = ToolState.NONE + + setup_tool() + + return true + + elif e.keycode == KEY_A: + + if e.is_pressed(): + var cmd:CommandSelectVertices = CommandSelectVertices.new() + cmd.builder = builder + + if e.alt_pressed: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + cmd.add_vertices(block.get_path(), []) + + else: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + for v_idx in block.control_mesh.vertices.size(): + cmd.add_vertex(block.get_path(), v_idx) + + cmd.selection_type = Selection.Type.REPLACE + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) + + elif e.keycode == KEY_G: + + if e.is_pressed() && tool_state == ToolState.NONE: + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + tool_state = ToolState.MOVE_HANDLES_CLICK + move_constraint = MoveConstraint.Type.PLANE_VIEWPORT + + drag_handle_start_pos = Vector3.INF + + cmd_move_vertex = CommandMoveVertices.new() + cmd_move_vertex.builder = builder + + for block in sel_blocks: + var vol:ConvexVolume = block.control_mesh + for v_idx in vol.vertices.size(): + var v:ConvexVolume.VertexInfo = vol.vertices[v_idx] + if v.selected: + cmd_move_vertex.add_vertex(block.get_path(), v_idx) + + return true + + elif e.keycode == KEY_X: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_YZ + else: + move_constraint = MoveConstraint.Type.AXIS_X + return true + + elif e.keycode == KEY_Y: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_XZ + else: + move_constraint = MoveConstraint.Type.AXIS_Y + return true + + elif e.keycode == KEY_Z: + if tool_state == ToolState.MOVE_HANDLES_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_XY + else: + move_constraint = MoveConstraint.Type.AXIS_Z + return true + + + + if event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + if tool_state == ToolState.NONE: + drag_mouse_start_pos = e.position + tool_state = ToolState.READY + #print("Start READY") + + return true + else: + if tool_state == ToolState.READY: + #print("cmd select") + var handle:HandleVertex = pick_closest_handle(viewport_camera, drag_mouse_start_pos, builder.handle_screen_radius) + + var cmd:CommandSelectVertices = CommandSelectVertices.new() + cmd.builder = builder + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + cmd.add_vertices(block.get_path(), []) + + + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + if handle: + cmd.add_vertex(handle.block_path, handle.vertex_index) + #print("selectibg %s" % handle.vertex_index) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) + + + tool_state = ToolState.NONE + cmd_move_vertex = null + + elif tool_state == ToolState.DRAGGING: + #Finish drag + + #print("cmd finish drag") + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd_move_vertex.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + cmd_move_vertex = null + + elif tool_state == ToolState.DRAGGING_ADD: + #Finish drag + #print("cmd finish drag add") + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd_add_vertex.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + cmd_add_vertex = null + + elif tool_state == ToolState.MOVE_HANDLES_CLICK: + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd_move_vertex.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + cmd_add_vertex = null + + + elif tool_state == ToolState.DRAG_SELECTION: + + var frustum:Array[Plane] = MathUtil.calc_frustum_camera_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos) + + var cmd:CommandSelectVertices = CommandSelectVertices.new() + cmd.builder = builder + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + for block in sel_blocks: + + for v_idx in block.control_mesh.vertices.size(): + var v:ConvexVolume.VertexInfo = block.control_mesh.vertices[v_idx] + var point_w:Vector3 = block.global_transform * v.point + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) +# var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + + #Obstruction check + if !global_scene.xray_mode && builder.display_mode != DisplayMode.Type.WIRE: + var result:IntersectResults = builder.intersect_ray_closest(origin, point_w - origin) + if result: + var res_point_w:Vector3 = result.get_world_position() + if !res_point_w.is_equal_approx(point_w): + continue + + if MathUtil.frustum_contians_point(frustum, point_w): + cmd.add_vertex(block.get_path(), v_idx) + + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + return true + + elif e.button_index == MOUSE_BUTTON_RIGHT: + if e.is_pressed(): + #Right click cancel + if cmd_move_vertex: + cmd_move_vertex.undo_it() + cmd_move_vertex = null + tool_state = ToolState.NONE + + setup_tool() + return true + + if cmd_add_vertex: + cmd_add_vertex.undo_it() + cmd_add_vertex = null + tool_state = ToolState.NONE + + setup_tool() + return true + + return false + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + #mouse_hover_pos = e.position + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return false + + if tool_state == ToolState.READY: + if e.position.distance_squared_to(drag_mouse_start_pos) > MathUtil.square(builder.drag_start_radius): + start_drag(viewport_camera, event) + + return true + + elif tool_state == ToolState.DRAGGING || tool_state == ToolState.MOVE_HANDLES_CLICK: + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + if !drag_handle_start_pos.is_finite(): + #If start point set to infinite, replace with point along view ray + drag_handle_start_pos = origin + dir * 20 + + var active_block:Node3D = builder.get_active_block() +# var gizmo_global_xform:Transform3D = calc_gizmo_transform(origin, average_normal, active_block, viewport_camera, settings.transform_space) + var xform_basis:Basis = calc_gizmo_basis(average_normal, active_block, viewport_camera, settings.transform_space) + + #print("drag_handle_start_pos ", drag_handle_start_pos) + #print("basis ", xform_basis) + var drag_to:Vector3 + match move_constraint: + MoveConstraint.Type.AXIS_X: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.x) + MoveConstraint.Type.AXIS_Y: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.y) + MoveConstraint.Type.AXIS_Z: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, xform_basis.z) + MoveConstraint.Type.PLANE_XY: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.z) + MoveConstraint.Type.PLANE_XZ: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.y) + MoveConstraint.Type.PLANE_YZ: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, xform_basis.x) + MoveConstraint.Type.PLANE_VIEWPORT: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, viewport_camera.global_transform.basis.z) + + + #print("send snap bock-2- ", drag_home_block) + drag_to = builder.get_snapping_manager().snap_point(drag_to, SnappingQuery.new(viewport_camera, [drag_home_block])) + #print("drag_to snapped ", drag_to) + + cmd_move_vertex.move_offset = drag_to - drag_handle_start_pos + #print("cmd_move_vertex.move_offset ", cmd_move_vertex.move_offset) + cmd_move_vertex.do_it() + + setup_tool() + return true + + elif tool_state == ToolState.DRAGGING_ADD: + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var drag_to:Vector3 + if e.alt_pressed: + drag_to = MathUtil.closest_point_on_line(origin, dir, drag_handle_start_pos, Vector3.UP) + else: + drag_to = MathUtil.intersect_plane(origin, dir, drag_handle_start_pos, Vector3.UP) + + #drag_to = MathUtil.snap_to_grid(drag_to, grid_step_size) + #print("send snap bock ", drag_home_block) + drag_to = builder.get_snapping_manager().snap_point(drag_to, SnappingQuery.new(viewport_camera, [drag_home_block])) + + added_point_pos = drag_to + #print("drag point to %s" % drag_to) + + cmd_add_vertex.points_to_add = [drag_to] + cmd_add_vertex.do_it() + + setup_tool() + + elif tool_state == ToolState.DRAG_SELECTION: + drag_select_to_pos = e.position + return true + + return false + diff --git a/addons/cyclops_level_builder/tools/tool_edit_vertex.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_vertex.gd.uid new file mode 100644 index 00000000..00b54ff1 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_vertex.gd.uid @@ -0,0 +1 @@ +uid://c8bst4y8gdo2c diff --git a/addons/cyclops_level_builder/tools/tool_edit_vertex_settings.gd b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings.gd new file mode 100644 index 00000000..c751523e --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings.gd @@ -0,0 +1,39 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolEditVertexSettings + +@export var transform_space:TransformSpace.Type = TransformSpace.Type.GLOBAL +@export var triplanar_lock_uvs:bool = true + +func load_from_cache(cache:Dictionary): + transform_space = cache.get("transform_space", TransformSpace.Type.GLOBAL) + triplanar_lock_uvs = cache.get("triplanar_lock_uvs", true) + +func save_to_cache(): + return { + "transform_space": transform_space, + "triplanar_lock_uvs": triplanar_lock_uvs, + } diff --git a/addons/cyclops_level_builder/tools/tool_edit_vertex_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings.gd.uid new file mode 100644 index 00000000..a58c7bce --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings.gd.uid @@ -0,0 +1 @@ +uid://bsdjto60ni2x3 diff --git a/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd new file mode 100644 index 00000000..fab7200c --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd @@ -0,0 +1,60 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolEditVertexSettingsEditor + +var settings:ToolEditVertexSettings: + get: + return settings + set(value): + settings = value + dirty = true + +var dirty:bool = true + + +func _ready(): + %transform_space.clear() + for text in TransformSpace.Type.keys(): + %transform_space.add_item(text) + +func _process(delta): + if dirty: + update() + dirty = false + +func update(): + %transform_space.selected = settings.transform_space + %check_correct_uvs.button_pressed = settings.triplanar_lock_uvs + + pass + + +func _on_transform_space_item_selected(index): + settings.transform_space = index + + +func _on_check_correct_uvs_toggled(toggled_on): + settings.triplanar_lock_uvs = toggled_on diff --git a/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd.uid new file mode 100644 index 00000000..ec3eefb4 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://cbbm5c605d655 diff --git a/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.tscn new file mode 100644 index 00000000..7811bb04 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=2 format=3 uid="uid://s8gaqniiv1on"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_edit_vertex_settings_editor.gd" id="1_6qkra"] + +[node name="ToolMoveSettingsEditor" type="PanelContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -929.0 +offset_bottom = -415.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_6qkra") + +[node name="GridContainer" type="GridContainer" parent="."] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Transform space" + +[node name="transform_space" type="OptionButton" parent="GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 5 +selected = 0 +popup/item_0/text = "GLOBAL" +popup/item_0/id = 0 +popup/item_1/text = "LOCAL" +popup/item_1/id = 1 +popup/item_2/text = "NORMAL" +popup/item_2/id = 2 +popup/item_3/text = "VIEW" +popup/item_3/id = 3 +popup/item_4/text = "PARENT" +popup/item_4/id = 4 + +[node name="Label2" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Triplanar lock UVs" + +[node name="check_correct_uvs" type="CheckBox" parent="GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "On" + +[connection signal="item_selected" from="GridContainer/transform_space" to="." method="_on_transform_space_item_selected"] +[connection signal="toggled" from="GridContainer/check_correct_uvs" to="." method="_on_check_correct_uvs_toggled"] diff --git a/addons/cyclops_level_builder/tools/tool_material_brush.gd b/addons/cyclops_level_builder/tools/tool_material_brush.gd new file mode 100644 index 00000000..71a0bd75 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_material_brush.gd @@ -0,0 +1,209 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolMaterialBrush + +enum ToolState { READY, PAINTING } +var tool_state:ToolState = ToolState.READY + +const TOOL_ID:String = "material_brush" + +var cmd:CommandSetMaterial + +var settings:ToolMaterialBrushSettings = ToolMaterialBrushSettings.new() +var material_viewer_state:MaterialViewerState = preload("res://addons/cyclops_level_builder/docks/material_palette/material_viewer/material_viewer_state_res.tres") + +var last_mouse_pos:Vector2 + +func _get_tool_id()->String: + return TOOL_ID + +func _draw_tool(viewport_camera:Camera3D): + super._draw_tool(viewport_camera) + + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + +func _get_tool_properties_editor()->Control: + var ed:ToolMaterialBrushSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_X: + if e.shift_pressed: + if e.is_pressed(): + var origin:Vector3 = viewport_camera.project_ray_origin(last_mouse_pos) + var dir:Vector3 = viewport_camera.project_ray_normal(last_mouse_pos) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + if result: + var block:CyclopsBlock = result.object + result.face_index + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(block.mesh_vector_data) + + var face:ConvexVolume.FaceInfo = vol.faces[result.face_index] + + #Sample under cursor + if settings.paint_materials: + if face.material_id != -1: + #Pick this material + #print("face.material_id ", face.material_id) + var mat:Material = block.materials[face.material_id] \ + if face.material_id >= 0 && face.material_id < block.materials.size() \ + else null + settings.material_path = mat.resource_path if mat else NodePath() + #print("settings.material_path ", settings.material_path) + + + if settings.paint_color: + settings.color = face.color + + if settings.paint_visibility: + settings.visibility = face.visible + + if settings.paint_uv: + settings.uv_matrix = face.uv_transform + + return true + + elif event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + if tool_state == ToolState.READY: + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + if result: + cmd = CommandSetMaterial.new() + cmd.builder = builder + + #print("settings.paint_materials ", settings.paint_materials) + cmd.setting_material = settings.paint_materials + + cmd.material_path = settings.material_path \ + if !settings.erase_material else "" + + cmd.setting_color = settings.paint_color + cmd.color = settings.color + + cmd.setting_visibility = settings.paint_visibility + cmd.visibility = settings.visibility + + cmd.painting_uv = settings.paint_uv + cmd.uv_matrix = settings.uv_matrix + + var block:CyclopsBlock = result.object + + if settings.individual_faces: + cmd.add_target(block.get_path(), [result.face_index]) + + else: + cmd.add_target(block.get_path(), block.control_mesh.get_face_indices()) + + tool_state = ToolState.PAINTING + + else: + + if tool_state == ToolState.PAINTING: + cmd.undo_it() + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.READY + + return true + + + elif event is InputEventMouseMotion: + + var e:InputEventMouseMotion = event + + last_mouse_pos = e.position + + if tool_state == ToolState.PAINTING: + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + if result: + #print ("hit ", result.object.name) + cmd.undo_it() + var block:CyclopsBlock = result.object + if settings.individual_faces: + cmd.add_target(block.get_path(), [result.face_index]) + + else: + cmd.add_target(block.get_path(), block.control_mesh.get_face_indices()) + cmd.do_it() + + return true + + return false + + +func on_material_viewer_state_changed(): + #print("mat changed to ", material_viewer_state.active_material_path) + settings.material_path = material_viewer_state.active_material_path + + +func _init(): + material_viewer_state.changed.connect(on_material_viewer_state_changed) + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + var cache:Dictionary = builder.get_tool_cache(TOOL_ID) + settings.load_from_cache(cache) + settings.material_path = material_viewer_state.active_material_path + +# material_viewer_state.changed.connect(on_material_viewer_state_changed) + +func _deactivate(): +# material_viewer_state.changed.disconnect(on_material_viewer_state_changed) + + var cache:Dictionary = settings.save_to_cache() + builder.set_tool_cache(TOOL_ID, cache) + + + diff --git a/addons/cyclops_level_builder/tools/tool_material_brush.gd.uid b/addons/cyclops_level_builder/tools/tool_material_brush.gd.uid new file mode 100644 index 00000000..a7c9728d --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_material_brush.gd.uid @@ -0,0 +1 @@ +uid://b1eem6ioru7ft diff --git a/addons/cyclops_level_builder/tools/tool_material_brush_settings.gd b/addons/cyclops_level_builder/tools/tool_material_brush_settings.gd new file mode 100644 index 00000000..2854bb94 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_material_brush_settings.gd @@ -0,0 +1,91 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolMaterialBrushSettings + +@export var paint_materials:bool = true +@export var paint_color:bool = false +@export var paint_visibility:bool = false +@export var paint_uv:bool = false +@export var uv_matrix:Transform2D = Transform2D.IDENTITY: + set(value): + if value != uv_matrix: + uv_matrix = value + emit_changed() + +#@export var component_type:GeometryComponentType.Type = GeometryComponentType.Type.OBJECT +@export var individual_faces:bool = false +@export var erase_material:bool = false + +@export var color:Color = Color.WHITE: + set(value): + if value != color: + color = value + emit_changed() + +@export var material_path:NodePath: + set(value): + if value != material_path: + material_path = value + emit_changed() + +@export var visibility:bool = true: + set(value): + if value != visibility: + visibility = value + emit_changed() + +func load_from_cache(cache:Dictionary): + paint_materials = cache.get("paint_materials", true) + paint_color = cache.get("paint_color", false) + paint_visibility = cache.get("paint_visibility", false) + individual_faces = cache.get("individual_faces", false) + #component_type = cache.get("component_type", GeometryComponentType.Type.OBJECT) + erase_material = cache.get("erase_material", false) + material_path = str_to_var(cache.get("material_path", NodePath())) + color = str_to_var(cache.get("color", var_to_str(Color.WHITE))) + visibility = cache.get("visibility", false) + paint_uv = cache.get("paint_uv", false) + uv_matrix = str_to_var(cache.get("uv_matrix", var_to_str(Transform2D.IDENTITY))) + +func save_to_cache(): + return { + "paint_materials": paint_materials, + "paint_color": paint_color, + "paint_visibility": paint_visibility, + "individual_faces": individual_faces, + #"component_type": component_type, + "erase_material": erase_material, + "material_path": var_to_str(material_path), + "color": var_to_str(color), + "visibility": visibility, + "paint_uv": paint_uv, + "uv_matrix": var_to_str(uv_matrix) + } + + + + + diff --git a/addons/cyclops_level_builder/tools/tool_material_brush_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_material_brush_settings.gd.uid new file mode 100644 index 00000000..0beee509 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_material_brush_settings.gd.uid @@ -0,0 +1 @@ +uid://ig2s0j4lipd0 diff --git a/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd new file mode 100644 index 00000000..cb01a867 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd @@ -0,0 +1,142 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolMaterialBrushSettingsEditor + +@export var settings:ToolMaterialBrushSettings: + get: + return settings + + set(value): + if settings == value: + return + + if settings: + settings.changed.disconnect(on_settings_changed) + + settings = value + + if settings: + settings.changed.connect(on_settings_changed) + + update() + +func on_settings_changed(): + update() + +func update(): + if !settings: + %check_paint_material.disabled = true + %check_individual_faces.disabled = true + %check_erase_material.disabled = true + + %check_paint_color.disabled = true + %color_button.disabled = true + + %check_paint_visibility.disabled = true + %check_visibility.disabled = true + + %check_paint_uv.disabled = true + + return + + %check_paint_material.disabled = false + %check_paint_color.disabled = false + %check_paint_visibility.disabled = false + %check_individual_faces.disabled = false + + %check_individual_faces.button_pressed = settings.individual_faces + #%opbn_geom_component.selected = settings.component_type + + %check_paint_material.button_pressed = settings.paint_materials + %check_erase_material.button_pressed = settings.erase_material + %check_erase_material.disabled = !settings.paint_materials + + %check_paint_color.button_pressed = settings.paint_color + %color_button.color = settings.color + %color_button.disabled = !settings.paint_color + + %check_paint_visibility.button_pressed = settings.paint_visibility + %check_visibility.button_pressed = settings.visibility + %check_visibility.disabled = !settings.paint_visibility + + %check_paint_uv.button_pressed = settings.paint_uv + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_check_paint_material_toggled(button_pressed:bool): + #print("_on_check_paint_material_toggled ", button_pressed) + settings.paint_materials = button_pressed + %check_erase_material.disabled = !settings.paint_materials + + + +func _on_check_erase_material_toggled(button_pressed:bool): + settings.erase_material = button_pressed + + +func _on_check_paint_color_toggled(button_pressed:bool): + settings.paint_color = button_pressed + %color_button.disabled = !settings.paint_color + + +func _on_color_button_color_changed(color:Color): + settings.color = color + + +func _on_check_paint_visibility_toggled(button_pressed:bool): + settings.paint_visibility = button_pressed + %check_visibility.disabled = !settings.paint_visibility + + +func _on_check_visibility_toggled(button_pressed:bool): + settings.visibility = button_pressed + + +func _on_check_paint_uv_toggled(button_pressed:bool): + settings.paint_uv = button_pressed + + +func _on_check_individual_faces_toggled(button_pressed:bool): + settings.individual_faces = button_pressed + +#func _on_opbn_geom_component_item_selected(index): + #match index: + #0: + #settings.component_type = GeometryComponentType.Type.OBJECT + #1: + #settings.component_type = GeometryComponentType.Type.VERTEX + #2: + #settings.component_type = GeometryComponentType.Type.FACE + #3: + #settings.component_type = GeometryComponentType.Type.FACE_VERTEX diff --git a/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd.uid new file mode 100644 index 00000000..36fc73a6 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://lhf8eypo8qdx diff --git a/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.tscn new file mode 100644 index 00000000..8914f836 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.tscn @@ -0,0 +1,83 @@ +[gd_scene load_steps=2 format=3 uid="uid://dugi0xh84150p"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_material_brush_settings_editor.gd" id="1_q0hdg"] + +[node name="PanelContainer" type="PanelContainer"] +offset_right = 317.0 +offset_bottom = 269.0 +script = ExtResource("1_q0hdg") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 + +[node name="check_individual_faces" type="CheckBox" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Individual faces" + +[node name="check_paint_material" type="CheckBox" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Paint materials" + +[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 16 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/MarginContainer"] +layout_mode = 2 + +[node name="check_erase_material" type="CheckBox" parent="VBoxContainer/MarginContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Erase materials" + +[node name="check_paint_color" type="CheckBox" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Paint color" + +[node name="MarginContainer2" type="MarginContainer" parent="VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 16 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/MarginContainer2"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/MarginContainer2/HBoxContainer"] +layout_mode = 2 +text = "Color" + +[node name="color_button" type="ColorPickerButton" parent="VBoxContainer/MarginContainer2/HBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="check_paint_visibility" type="CheckBox" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Paint visibility" + +[node name="MarginContainer3" type="MarginContainer" parent="VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 16 + +[node name="check_visibility" type="CheckBox" parent="VBoxContainer/MarginContainer3"] +unique_name_in_owner = true +layout_mode = 2 +text = "Visible" + +[node name="check_paint_uv" type="CheckBox" parent="VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "Set the face's UV transform to the identity matrix." +text = "Paint UV" + +[connection signal="toggled" from="VBoxContainer/check_individual_faces" to="." method="_on_check_individual_faces_toggled"] +[connection signal="toggled" from="VBoxContainer/check_paint_material" to="." method="_on_check_paint_material_toggled"] +[connection signal="toggled" from="VBoxContainer/MarginContainer/VBoxContainer/check_erase_material" to="." method="_on_check_erase_material_toggled"] +[connection signal="toggled" from="VBoxContainer/check_paint_color" to="." method="_on_check_paint_color_toggled"] +[connection signal="color_changed" from="VBoxContainer/MarginContainer2/HBoxContainer/color_button" to="." method="_on_color_button_color_changed"] +[connection signal="toggled" from="VBoxContainer/check_paint_visibility" to="." method="_on_check_paint_visibility_toggled"] +[connection signal="toggled" from="VBoxContainer/MarginContainer3/check_visibility" to="." method="_on_check_visibility_toggled"] +[connection signal="toggled" from="VBoxContainer/check_paint_uv" to="." method="_on_check_paint_uv_toggled"] diff --git a/addons/cyclops_level_builder/tools/tool_move.gd b/addons/cyclops_level_builder/tools/tool_move.gd new file mode 100644 index 00000000..7506cd71 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_move.gd @@ -0,0 +1,451 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolMove + +const TOOL_ID:String = "move" + + +enum ToolState { NONE, READY, MOVE_BLOCK, MOVE_BLOCK_CLICK, DRAG_SELECTION } +var tool_state:ToolState = ToolState.NONE + +#enum MoveConstraint { NONE, AXIS_X, AXIS_Y, AXIS_Z, PLANE_XY, PLANE_XZ, PLANE_YZ, PLANE_VIEWPORT } +var move_constraint:MoveConstraint.Type = MoveConstraint.Type.NONE + +#var viewport_camera_start:Camera3D +var event_start:InputEventMouseButton + +var block_drag_cur:Vector3 +var block_drag_p0:Vector3 + +var drag_select_start_pos:Vector2 +var drag_select_to_pos:Vector2 + +var mouse_hover_pos:Vector2 + +#Keep a copy of move command here while we are building it +#var cmd_move_blocks:CommandMoveBlocks +var cmd_xform_blocks:CommandTransformBlocks + +var base_points:PackedVector3Array + +var gizmo_translate:GizmoTranslate + +var settings:ToolMoveSettings = ToolMoveSettings.new() + +func _get_tool_properties_editor()->Control: + var ed:ToolMoveSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_move_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func _get_tool_id()->String: + return TOOL_ID + +func draw_gizmo(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + if !gizmo_translate: + gizmo_translate = preload("res://addons/cyclops_level_builder/tools/gizmos/gizmo_translate.tscn").instantiate() + + var blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + var active_block:Node3D = builder.get_active_block() + + if blocks.is_empty(): + global_scene.set_custom_gizmo(null) + else: + var origin:Vector3 + for block in blocks: + origin += block.global_transform.origin + origin /= blocks.size() + global_scene.set_custom_gizmo(gizmo_translate) + + match settings.transform_space: + TransformSpace.Type.GLOBAL: + var xform:Transform3D = Transform3D.IDENTITY + xform.origin = origin + gizmo_translate.global_transform = xform + TransformSpace.Type.LOCAL: + var xform:Transform3D = active_block.global_transform + gizmo_translate.global_transform = xform + TransformSpace.Type.NORMAL: + var xform:Transform3D = active_block.global_transform + gizmo_translate.global_transform = xform + TransformSpace.Type.VIEW: + gizmo_translate.global_basis = viewport_camera.global_basis + gizmo_translate.global_position = origin + TransformSpace.Type.PARENT: + var xform:Transform3D = active_block.get_parent_node_3d().global_transform + gizmo_translate.global_transform = xform + + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + + if tool_state == ToolState.DRAG_SELECTION: + #print("draw sel %s " % drag_select_to_pos) + global_scene.draw_screen_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos, global_scene.selection_rect_material) + + draw_gizmo(viewport_camera) + + + +func start_drag(viewport_camera:Camera3D, event:InputEvent): + var blocks_root:Node = builder.get_block_add_parent() + var e:InputEventMouseButton = event + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + move_constraint = MoveConstraint.Type.NONE + + if gizmo_translate: + var part_res:GizmoTranslate.IntersectResult = gizmo_translate.intersect(origin, dir, viewport_camera) + if part_res: + #print("Gizmo hit ", part_res.part) + match part_res.part: + GizmoTranslate.Part.AXIS_X: + move_constraint = MoveConstraint.Type.AXIS_X + GizmoTranslate.Part.AXIS_Y: + move_constraint = MoveConstraint.Type.AXIS_Y + GizmoTranslate.Part.AXIS_Z: + move_constraint = MoveConstraint.Type.AXIS_Z + GizmoTranslate.Part.PLANE_XY: + move_constraint = MoveConstraint.Type.PLANE_XY + GizmoTranslate.Part.PLANE_XZ: + move_constraint = MoveConstraint.Type.PLANE_XZ + GizmoTranslate.Part.PLANE_YZ: + move_constraint = MoveConstraint.Type.PLANE_YZ + + var start_pos:Vector3 = part_res.pos_world +# var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + #block_drag_p0 = MathUtil.snap_to_grid(start_pos, grid_step_size) + block_drag_p0 = builder.get_snapping_manager().snap_point(start_pos, SnappingQuery.new(viewport_camera)) + + # print("res obj %s" % result.object.get_path()) + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + tool_state = ToolState.MOVE_BLOCK + #print("Move block") + + cmd_xform_blocks = CommandTransformBlocks.new() + cmd_xform_blocks.builder = builder + cmd_xform_blocks.lock_uvs = settings.correct_uvs + for child in sel_blocks: + cmd_xform_blocks.add_block(child.get_path()) + + return + + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) +# print("result %s" % result) + + if result: + + if e.alt_pressed: + move_constraint = MoveConstraint.Type.AXIS_Y + else: + move_constraint = MoveConstraint.Type.PLANE_XZ + + var start_pos:Vector3 = result.get_world_position() + #var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + #block_drag_p0 = MathUtil.snap_to_grid(start_pos, grid_step_size) + block_drag_p0 = builder.get_snapping_manager().snap_point(start_pos, SnappingQuery.new(viewport_camera)) + + #print("block_drag_p0 %s" % block_drag_p0) + +# print("res obj %s" % result.object.get_path()) + if builder.is_selected(result.object): + + tool_state = ToolState.MOVE_BLOCK + + cmd_xform_blocks = CommandTransformBlocks.new() + cmd_xform_blocks.builder = builder + cmd_xform_blocks.lock_uvs = settings.correct_uvs + for child in builder.get_selected_blocks(): + cmd_xform_blocks.add_block(child.get_path()) + + return + + tool_state = ToolState.DRAG_SELECTION + drag_select_start_pos = e.position + drag_select_to_pos = e.position + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ESCAPE: + if e.is_pressed(): + tool_state = ToolState.NONE + if cmd_xform_blocks: + cmd_xform_blocks.undo_it() + cmd_xform_blocks = null + + return true + + elif e.keycode == KEY_G: + if e.is_pressed() && tool_state == ToolState.NONE: + tool_state = ToolState.MOVE_BLOCK_CLICK + move_constraint = MoveConstraint.Type.PLANE_VIEWPORT +# block_drag_p0 = MathUtil.intersect_plane(origin, dir, block_drag_p0, viewport_camera.global_transform.basis.z) +# block_drag_p0 = origin + dir * 20 + block_drag_p0 = Vector3.INF + + cmd_xform_blocks = CommandTransformBlocks.new() + cmd_xform_blocks.builder = builder + cmd_xform_blocks.lock_uvs = settings.correct_uvs + for child in builder.get_selected_blocks(): + cmd_xform_blocks.add_block(child.get_path()) + + return true + + elif e.keycode == KEY_X: + if tool_state == ToolState.MOVE_BLOCK_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_YZ + else: + move_constraint = MoveConstraint.Type.AXIS_X + return true + + elif e.keycode == KEY_Y: + if tool_state == ToolState.MOVE_BLOCK_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_XZ + else: + move_constraint = MoveConstraint.Type.AXIS_Y + return true + + elif e.keycode == KEY_Z: + if tool_state == ToolState.MOVE_BLOCK_CLICK: + if e.shift_pressed: + move_constraint = MoveConstraint.Type.PLANE_XY + else: + move_constraint = MoveConstraint.Type.AXIS_Z + return true + + if e.keycode == KEY_Q && e.alt_pressed: + if e.is_pressed(): + var origin:Vector3 = viewport_camera.project_ray_origin(mouse_hover_pos) + var dir:Vector3 = viewport_camera.project_ray_normal(mouse_hover_pos) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + if result: + var cmd:CommandSelectBlocks = CommandSelectBlocks.new() + cmd.builder = builder + cmd.block_paths.append(result.object.get_path()) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + _deactivate() + _activate(builder) + + return true + + elif event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + if tool_state == ToolState.NONE: + event_start = event + + tool_state = ToolState.READY + + elif tool_state == ToolState.MOVE_BLOCK_CLICK: + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd_xform_blocks.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + else: + if tool_state == ToolState.READY: + + #We just clicked with the mouse + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + #print("Invokke select %s" % result) + var cmd:CommandSelectBlocks = CommandSelectBlocks.new() + cmd.builder = builder + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + if result: + cmd.block_paths.append(result.object.get_path()) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + elif tool_state == ToolState.MOVE_BLOCK: + + #Finish moving blocks + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd_xform_blocks.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + elif tool_state == ToolState.DRAG_SELECTION: + + var frustum:Array[Plane] = MathUtil.calc_frustum_camera_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos) + + var result:Array[CyclopsBlock] = builder.intersect_frustum_all(frustum) + + if !result.is_empty(): + + var cmd:CommandSelectBlocks = CommandSelectBlocks.new() + cmd.builder = builder + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + for r in result: + cmd.block_paths.append(r.get_path()) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + return true + + elif e.button_index == MOUSE_BUTTON_RIGHT: + if e.is_pressed(): + #Right click cancel + if tool_state == ToolState.MOVE_BLOCK || tool_state == ToolState.MOVE_BLOCK_CLICK: + tool_state = ToolState.NONE + if cmd_xform_blocks: + cmd_xform_blocks.undo_it() + cmd_xform_blocks = null + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + + mouse_hover_pos = e.position + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return super._gui_input(viewport_camera, event) + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + #print("tool_state %s" % tool_state) + + if tool_state == ToolState.READY: + var offset:Vector2 = e.position - event_start.position + if offset.length_squared() > MathUtil.square(builder.drag_start_radius): + start_drag(viewport_camera, event_start) + + return true + + elif tool_state == ToolState.MOVE_BLOCK || tool_state == ToolState.MOVE_BLOCK_CLICK: + if !block_drag_p0.is_finite(): + block_drag_p0 = origin + dir * 20 + + var xform_basis:Basis + + match settings.transform_space: + TransformSpace.Type.GLOBAL: + xform_basis = Basis.IDENTITY + TransformSpace.Type.LOCAL: + var active_block:Node3D = builder.get_active_block() + xform_basis = active_block.basis + TransformSpace.Type.NORMAL: + var active_block:Node3D = builder.get_active_block() + xform_basis = active_block.basis + TransformSpace.Type.VIEW: + xform_basis = viewport_camera.global_basis + TransformSpace.Type.PARENT: + var active_block:Node3D = builder.get_active_block().get_parent_node_3d() + xform_basis = active_block.basis + + + match move_constraint: + MoveConstraint.Type.AXIS_X: + block_drag_cur = MathUtil.closest_point_on_line(origin, dir, block_drag_p0, xform_basis.x) + MoveConstraint.Type.AXIS_Y: + block_drag_cur = MathUtil.closest_point_on_line(origin, dir, block_drag_p0, xform_basis.y) + MoveConstraint.Type.AXIS_Z: + block_drag_cur = MathUtil.closest_point_on_line(origin, dir, block_drag_p0, xform_basis.z) + MoveConstraint.Type.PLANE_XY: + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, xform_basis.z) + MoveConstraint.Type.PLANE_XZ: + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, xform_basis.y) + MoveConstraint.Type.PLANE_YZ: + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, xform_basis.x) + MoveConstraint.Type.PLANE_VIEWPORT: + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, viewport_camera.global_transform.basis.z) + + #print("dragging move_constraint %s block_drag_cur %s" % [move_constraint, block_drag_cur]) + + #var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + #block_drag_cur = MathUtil.snap_to_grid(block_drag_cur, grid_step_size) + block_drag_cur = builder.get_snapping_manager().snap_point(block_drag_cur, SnappingQuery.new(viewport_camera)) + + #cmd_move_blocks.move_offset = block_drag_cur - block_drag_p0 + cmd_xform_blocks.transform = Transform3D(Basis.IDENTITY, block_drag_cur - block_drag_p0) + #print("cmd_move_blocks.move_offset %s" % cmd_move_blocks.move_offset) + cmd_xform_blocks.do_it() + + return true + + elif tool_state == ToolState.DRAG_SELECTION: + drag_select_to_pos = e.position + return true + + + return super._gui_input(viewport_camera, event) + + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.OBJECT + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + var cache:Dictionary = builder.get_tool_cache(TOOL_ID) + settings.load_from_cache(cache) + +func _deactivate(): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.set_custom_gizmo(null) + + var cache:Dictionary = settings.save_to_cache() + builder.set_tool_cache(TOOL_ID, cache) + diff --git a/addons/cyclops_level_builder/tools/tool_move.gd.uid b/addons/cyclops_level_builder/tools/tool_move.gd.uid new file mode 100644 index 00000000..9943ad97 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_move.gd.uid @@ -0,0 +1 @@ +uid://c5gupwfnlexcn diff --git a/addons/cyclops_level_builder/tools/tool_move_settings.gd b/addons/cyclops_level_builder/tools/tool_move_settings.gd new file mode 100644 index 00000000..69db0a3c --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_move_settings.gd @@ -0,0 +1,39 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolMoveSettings + +@export var transform_space:TransformSpace.Type = TransformSpace.Type.GLOBAL +@export var correct_uvs:bool = true + +func load_from_cache(cache:Dictionary): + transform_space = cache.get("transform_space", TransformSpace.Type.GLOBAL) + correct_uvs = cache.get("correct_uvs", true) + +func save_to_cache(): + return { + "transform_space": transform_space, + "correct_uvs": correct_uvs, + } diff --git a/addons/cyclops_level_builder/tools/tool_move_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_move_settings.gd.uid new file mode 100644 index 00000000..4b31f0c6 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_move_settings.gd.uid @@ -0,0 +1 @@ +uid://b0ha6uo7lxtgl diff --git a/addons/cyclops_level_builder/tools/tool_move_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_move_settings_editor.gd new file mode 100644 index 00000000..4c2e51a5 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_move_settings_editor.gd @@ -0,0 +1,60 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolMoveSettingsEditor + +var settings:ToolMoveSettings: + get: + return settings + set(value): + settings = value + dirty = true + +var dirty:bool = true + + +func _ready(): + %transform_space.clear() + for text in TransformSpace.Type.keys(): + %transform_space.add_item(text) + +func _process(delta): + if dirty: + update() + dirty = false + +func update(): + %transform_space.selected = settings.transform_space + %check_correct_uvs.button_pressed = settings.correct_uvs + + pass + + +func _on_transform_space_item_selected(index): + settings.transform_space = index + + +func _on_check_correct_uvs_toggled(toggled_on): + settings.correct_uvs = toggled_on diff --git a/addons/cyclops_level_builder/tools/tool_move_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_move_settings_editor.gd.uid new file mode 100644 index 00000000..ee5407fa --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_move_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://hh5pj2nsclxx diff --git a/addons/cyclops_level_builder/tools/tool_move_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_move_settings_editor.tscn new file mode 100644 index 00000000..37b14596 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_move_settings_editor.tscn @@ -0,0 +1,49 @@ +[gd_scene load_steps=2 format=3 uid="uid://c83wthlpyd7dm"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_move_settings_editor.gd" id="1_w2n7n"] + +[node name="ToolMoveSettingsEditor" type="PanelContainer"] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_right = -929.0 +offset_bottom = -415.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_w2n7n") + +[node name="GridContainer" type="GridContainer" parent="."] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Transform space" + +[node name="transform_space" type="OptionButton" parent="GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 5 +selected = 0 +popup/item_0/text = "GLOBAL" +popup/item_0/id = 0 +popup/item_1/text = "LOCAL" +popup/item_1/id = 1 +popup/item_2/text = "NORMAL" +popup/item_2/id = 2 +popup/item_3/text = "VIEW" +popup/item_3/id = 3 +popup/item_4/text = "PARENT" +popup/item_4/id = 4 + +[node name="Label2" type="Label" parent="GridContainer"] +layout_mode = 2 +text = "Triplanar Lock UVs" + +[node name="check_correct_uvs" type="CheckBox" parent="GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "On" + +[connection signal="item_selected" from="GridContainer/transform_space" to="." method="_on_transform_space_item_selected"] +[connection signal="toggled" from="GridContainer/check_correct_uvs" to="." method="_on_check_correct_uvs_toggled"] diff --git a/addons/cyclops_level_builder/tools/tool_prism.gd b/addons/cyclops_level_builder/tools/tool_prism.gd new file mode 100644 index 00000000..6d7ffcaf --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_prism.gd @@ -0,0 +1,265 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolPrism + +const TOOL_ID:String = "prism" + +enum ToolState { READY, BASE_POINTS, DRAG_HEIGHT } +var tool_state:ToolState = ToolState.READY + +var floor_normal:Vector3 +var base_points:PackedVector3Array +var block_drag_cur:Vector3 +var drag_offset:Vector3 +var preview_point:Vector3 + +var settings:ToolPrismSettings = ToolPrismSettings.new() + +func _get_tool_properties_editor()->Control: + var ed:ToolPrismSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_prism_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.OBJECT + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + var cache:Dictionary = builder.get_tool_cache(TOOL_ID) + settings.load_from_cache(cache) + +func _deactivate(): + var cache:Dictionary = settings.save_to_cache() + builder.set_tool_cache(TOOL_ID, cache) + + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + + if tool_state == ToolState.BASE_POINTS: + var bounding_points:PackedVector3Array = MathUtil.bounding_polygon_3d(base_points, floor_normal) + global_scene.draw_loop(bounding_points, true, global_scene.tool_material) + global_scene.draw_points(bounding_points, global_scene.vertex_tool_material) + + global_scene.draw_vertex(preview_point, global_scene.vertex_tool_material) + + if tool_state == ToolState.DRAG_HEIGHT: + var bounding_points:PackedVector3Array = MathUtil.bounding_polygon_3d(base_points, floor_normal) + global_scene.draw_prism(bounding_points, drag_offset, global_scene.tool_material, global_scene.vertex_tool_material) + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + var blocks_root:Node = builder.get_block_add_parent() + #var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ENTER: + if e.is_pressed(): + if tool_state == ToolState.BASE_POINTS: + var camera_dir:Vector3 = viewport_camera.global_transform.basis.z + var angle_with_base:float = acos(floor_normal.dot(camera_dir)) + var drag_angle_limit:float = builder.get_global_scene().drag_angle_limit + if angle_with_base < drag_angle_limit || angle_with_base > PI - drag_angle_limit: + var height = settings.default_block_height + + if settings.match_selected_block: + height = calc_active_block_orthogonal_height(base_points[0], floor_normal) + + drag_offset = floor_normal * height + block_drag_cur = base_points[0] + drag_offset + + create_block() + + tool_state = ToolState.READY + else: + + drag_offset = Vector3.ZERO + tool_state = ToolState.DRAG_HEIGHT + return true + + elif e.keycode == KEY_BACKSPACE: + if e.is_pressed(): + base_points.remove_at(base_points.size() - 1) + return true + + elif e.keycode == KEY_ESCAPE: + if e.is_pressed(): + tool_state = ToolState.READY + return true + + elif event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + if tool_state == ToolState.READY: + base_points.clear() + tool_state = ToolState.BASE_POINTS + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + if result && settings.block_alignment == BlockAlignment.Type.ALIGN_TO_SURFACE: + floor_normal = result.get_world_normal() + + var p:Vector3 = builder.get_snapping_manager().snap_point(result.get_world_position(), SnappingQuery.new(viewport_camera)) + + base_points.append(p) + preview_point = p + + return true + + else: + #print("init base point empty space") + var draw_plane_point:Vector3 = Vector3.ZERO + var draw_plane_normal:Vector3 = BlockAlignment.get_plane_normal(settings.block_alignment) + if settings.match_selected_block: + draw_plane_point = calc_empty_space_draw_plane_origin(viewport_camera, draw_plane_point, draw_plane_normal) + + var hit_result = calc_hit_point_empty_space(origin, dir, viewport_camera, draw_plane_point, draw_plane_normal) + var start_pos:Vector3 = hit_result[0] + floor_normal = hit_result[1] + + +# var p:Vector3 = MathUtil.snap_to_grid(start_pos, grid_step_size) + var p:Vector3 = builder.get_snapping_manager().snap_point(start_pos, SnappingQuery.new(viewport_camera)) + base_points.append(p) + + return true + + elif tool_state == ToolState.BASE_POINTS: + #print("add base point") + if e.double_click: + if e.is_pressed(): + var camera_dir:Vector3 = viewport_camera.global_transform.basis.z + var angle_with_base:float = acos(floor_normal.dot(camera_dir)) + var drag_angle_limit:float = builder.get_global_scene().drag_angle_limit + if angle_with_base < drag_angle_limit || angle_with_base > PI - drag_angle_limit: + var height = settings.default_block_height + + if settings.match_selected_block: + height = calc_active_block_orthogonal_height(base_points[0], floor_normal) + + drag_offset = floor_normal * height + block_drag_cur = base_points[0] + drag_offset + + create_block() + + tool_state = ToolState.READY + else: + drag_offset = Vector3.ZERO + tool_state = ToolState.DRAG_HEIGHT + return true + + var p_isect:Vector3 = MathUtil.intersect_plane(origin, dir, base_points[0], floor_normal) + var p:Vector3 = builder.get_snapping_manager().snap_point(p_isect, SnappingQuery.new(viewport_camera)) + base_points.append(p) + + var bounding_points:PackedVector3Array = MathUtil.bounding_polygon_3d(base_points, floor_normal) + return true + + elif tool_state == ToolState.DRAG_HEIGHT: + create_block() + + tool_state = ToolState.READY + return true + + if e.button_index == MOUSE_BUTTON_RIGHT: + + if tool_state == ToolState.BASE_POINTS: + if e.is_pressed(): + for p_idx in base_points.size(): + var screen_pos:Vector2 = viewport_camera.unproject_position(base_points[p_idx]) + if screen_pos.distance_to(e.position) < builder.handle_screen_radius: + base_points.remove_at(p_idx) + break + return true + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return false + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var start_pos:Vector3 = origin + builder.block_create_distance * dir + var w2l = blocks_root.global_transform.inverse() + var origin_local:Vector3 = w2l * origin + var dir_local:Vector3 = w2l.basis * dir + + if tool_state == ToolState.BASE_POINTS: + var p_isect:Vector3 = MathUtil.intersect_plane(origin, dir, base_points[0], floor_normal) + preview_point = builder.get_snapping_manager().snap_point(p_isect, SnappingQuery.new(viewport_camera)) + + + elif tool_state == ToolState.DRAG_HEIGHT: + block_drag_cur = MathUtil.closest_point_on_line(origin_local, dir_local, base_points[0], floor_normal) + + block_drag_cur = builder.get_snapping_manager().snap_point(block_drag_cur, SnappingQuery.new(viewport_camera)) + + drag_offset = block_drag_cur - base_points[0] + var bounding_points:PackedVector3Array = MathUtil.bounding_polygon_3d(base_points, floor_normal) + + return true + + return super._gui_input(viewport_camera, event) + +func create_block(): + var blocks_root:Node = builder.get_block_add_parent() + + var bounding_points:PackedVector3Array = MathUtil.bounding_polygon_3d(base_points, floor_normal) + drag_offset = block_drag_cur - base_points[0] + + var cmd:CommandAddPrism = CommandAddPrism.new() + cmd.builder = builder + cmd.block_name = GeneralUtil.find_unique_name(blocks_root, "Block_") + cmd.blocks_root_path = blocks_root.get_path() + cmd.base_polygon = bounding_points + #cmd.local_transform = local_xform + cmd.extrude = drag_offset + cmd.uv_transform = builder.tool_uv_transform + cmd.material_path = builder.tool_material_path + cmd.collision_type = settings.collision_type + cmd.collision_layers = settings.collision_layer + cmd.collision_mask = settings.collision_mask + + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/tools/tool_prism.gd.uid b/addons/cyclops_level_builder/tools/tool_prism.gd.uid new file mode 100644 index 00000000..30a0555e --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_prism.gd.uid @@ -0,0 +1 @@ +uid://diwmb0d2f7o55 diff --git a/addons/cyclops_level_builder/tools/tool_prism_settings.gd b/addons/cyclops_level_builder/tools/tool_prism_settings.gd new file mode 100644 index 00000000..a935c094 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_prism_settings.gd @@ -0,0 +1,56 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolPrismSettings + + +@export var block_alignment:BlockAlignment.Type = BlockAlignment.Type.ALIGN_TO_SURFACE +@export var match_selected_block:bool = true +@export var default_block_elevation:float = 0 +@export var default_block_height:float = 1 +@export var collision_type:Collision.Type = Collision.Type.STATIC +@export_flags_3d_physics var collision_layer:int = 1 +@export_flags_3d_physics var collision_mask:int = 1 + +func load_from_cache(cache:Dictionary): + block_alignment = cache.get("block_alignment", BlockAlignment.Type.ALIGN_TO_SURFACE) + match_selected_block = cache.get("match_selected_block", true) + default_block_elevation = cache.get("default_block_elevation", 0) + default_block_height = cache.get("default_block_height", 1) + collision_type = cache.get("collision_type", Collision.Type.STATIC) + collision_layer = cache.get("collision_layer", 1) + collision_mask = cache.get("collision_mask", 1) + +func save_to_cache(): + return { + "block_alignment": block_alignment, + "match_selected_block": match_selected_block, + "default_block_elevation": default_block_elevation, + "default_block_height": default_block_height, + "collision_type": collision_type, + "collision_layer": collision_layer, + "collision_mask": collision_mask, + } + diff --git a/addons/cyclops_level_builder/tools/tool_prism_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_prism_settings.gd.uid new file mode 100644 index 00000000..005865d7 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_prism_settings.gd.uid @@ -0,0 +1 @@ +uid://chypghk1bibcv diff --git a/addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd new file mode 100644 index 00000000..1679ff7f --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd @@ -0,0 +1,90 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolPrismSettingsEditor + +var settings:ToolPrismSettings: + get: + return settings + set(value): + settings = value + dirty = true + +var dirty:bool = true + +func _ready(): + %collision_type.clear() + for text in Collision.Type.keys(): + %collision_type.add_item(text) + +func _process(delta): + if dirty: + update() + dirty = false + +func update(): + if !settings: + %check_match_selected_block.disabled = true + %default_block_elevation.disabled = true + %default_block_height.disabled = true + return + + %check_match_selected_block.disabled = false + %check_match_selected_block.button_pressed = settings.match_selected_block + %default_block_elevation.disabled = false + %default_block_elevation.value = settings.default_block_elevation + %default_block_height.disabled = false + %default_block_height.value = settings.default_block_height + + %alignment_type.selected = settings.block_alignment + + %collision_type.selected = settings.collision_type + %collision_layers.value = settings.collision_layer + %collision_mask.value = settings.collision_mask + +func _on_default_block_height_value_changed(value:float): + settings.default_block_height = value + + +func _on_default_block_elevation_value_changed(value:float): + settings.default_block_elevation = value + + +func _on_check_match_selected_block_toggled(value:bool): + settings.match_selected_block = value + +func _on_collision_layers_value_changed(value): + settings.collision_layer = value + + +func _on_collision_mask_value_changed(value): + settings.collision_mask = value + +func _on_collision_type_item_selected(index): + settings.collision_type = index + + +func _on_alignment_type_item_selected(index): + settings.block_alignment = index diff --git a/addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd.uid new file mode 100644 index 00000000..ffd8b461 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://qlvyr4jqql0t diff --git a/addons/cyclops_level_builder/tools/tool_prism_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_prism_settings_editor.tscn new file mode 100644 index 00000000..544a2a74 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_prism_settings_editor.tscn @@ -0,0 +1,132 @@ +[gd_scene load_steps=3 format=3 uid="uid://b7vyy46r72h0d"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_prism_settings_editor.gd" id="1_rbt26"] +[ext_resource type="PackedScene" uid="uid://diibmlqy1mpqb" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.tscn" id="2_aysnj"] + +[node name="ToolPrismSettings" type="PanelContainer"] +offset_right = 315.0 +offset_bottom = 70.0 +script = ExtResource("1_rbt26") + +[node name="PanelContainer" type="PanelContainer" parent="."] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"] +layout_mode = 2 + +[node name="GridContainer" type="GridContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Type" + +[node name="collision_type" type="OptionButton" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 4 +selected = 0 +popup/item_0/text = "NONE" +popup/item_0/id = 0 +popup/item_1/text = "STATIC" +popup/item_1/id = 1 +popup/item_2/text = "KINEMATIC" +popup/item_2/id = 2 +popup/item_3/text = "RIGID" +popup/item_3/id = 3 + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Layers" + +[node name="collision_layers" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label3" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Mask" + +[node name="collision_mask" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label5" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Alignment" + +[node name="alignment_type" type="OptionButton" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 4 +selected = 0 +popup/item_0/text = "Align to surface" +popup/item_0/id = 0 +popup/item_1/text = "XY Plane" +popup/item_1/id = 1 +popup/item_2/text = "XZ Plane" +popup/item_2/id = 2 +popup/item_3/text = "YZ Plane" +popup/item_3/id = 3 + +[node name="Label4" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Match Active Block" + +[node name="check_match_selected_block" type="CheckBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "When drawing in empty space, copy elevation and height properties from currently selected block." +disabled = true +text = "Match selected block" + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +text = "Orthogonal Viewport:" + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 16 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/MarginContainer"] +layout_mode = 2 + +[node name="GridContainer" type="GridContainer" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Default Block Elevation" + +[node name="default_block_elevation" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer" instance=ExtResource("2_aysnj")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +disabled = true + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Default Block Height" + +[node name="default_block_height" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer" instance=ExtResource("2_aysnj")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +disabled = true + +[connection signal="item_selected" from="PanelContainer/VBoxContainer/GridContainer/collision_type" to="." method="_on_collision_type_item_selected"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/collision_layers" to="." method="_on_collision_layers_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/collision_mask" to="." method="_on_collision_mask_value_changed"] +[connection signal="item_selected" from="PanelContainer/VBoxContainer/GridContainer/alignment_type" to="." method="_on_alignment_type_item_selected"] +[connection signal="toggled" from="PanelContainer/VBoxContainer/GridContainer/check_match_selected_block" to="." method="_on_check_match_selected_block_toggled"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer/default_block_elevation" to="." method="_on_default_block_elevation_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer/default_block_height" to="." method="_on_default_block_height_value_changed"] diff --git a/addons/cyclops_level_builder/tools/tool_rotate.gd b/addons/cyclops_level_builder/tools/tool_rotate.gd new file mode 100644 index 00000000..fb0e3824 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_rotate.gd @@ -0,0 +1,336 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolRotate + +const TOOL_ID:String = "rotate" + + +enum ToolState { NONE, READY, ROTATE_BLOCK, DRAG_SELECTION } +var tool_state:ToolState = ToolState.NONE + +#enum MoveConstraint { NONE, AXIS_X, AXIS_Y, AXIS_Z, PLANE_XY, PLANE_XZ, PLANE_YZ, PLANE_VIEWPORT } +var move_constraint:MoveConstraint.Type = MoveConstraint.Type.NONE + +#var viewport_camera_start:Camera3D +var event_start:InputEventMouseButton + +var drag_select_start_pos:Vector2 +var drag_select_to_pos:Vector2 + +var block_drag_cur:Vector3 +var block_drag_p0:Vector3 +var block_drag_origin:Vector3 + +var gizmo_rotate:GizmoRotate + +var mouse_hover_pos:Vector2 + +#Keep a copy of move command here while we are building it +var cmd_transform_blocks:CommandTransformBlocks + +func _get_tool_id()->String: + return TOOL_ID + +func draw_gizmo(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + if !gizmo_rotate: + gizmo_rotate = preload("res://addons/cyclops_level_builder/tools/gizmos/gizmo_rotate.tscn").instantiate() + + var blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if blocks.is_empty(): + global_scene.set_custom_gizmo(null) + else: + var origin:Vector3 + for block in blocks: + origin += block.global_transform.origin + origin /= blocks.size() + global_scene.set_custom_gizmo(gizmo_rotate) + gizmo_rotate.global_transform.origin = origin + + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + + if tool_state == ToolState.DRAG_SELECTION: + #print("draw sel %s " % drag_select_to_pos) + global_scene.draw_screen_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos, global_scene.selection_rect_material) + + draw_gizmo(viewport_camera) + + + +func start_drag(viewport_camera:Camera3D, event:InputEvent): + var blocks_root:Node = builder.get_block_add_parent() + var e:InputEventMouseButton = event + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + move_constraint = MoveConstraint.Type.NONE + + if gizmo_rotate: + var part_res:GizmoRotate.IntersectResult = gizmo_rotate.intersect(origin, dir, viewport_camera) + if part_res: + #print("Gizmo hit ", part_res.part) + match part_res.part: + GizmoRotate.Part.PLANE_XY: + move_constraint = MoveConstraint.Type.PLANE_XY + GizmoRotate.Part.PLANE_XZ: + move_constraint = MoveConstraint.Type.PLANE_XZ + GizmoRotate.Part.PLANE_YZ: + move_constraint = MoveConstraint.Type.PLANE_YZ + + var start_pos:Vector3 = part_res.pos_world +# var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + #block_drag_p0 = MathUtil.snap_to_grid(start_pos, grid_step_size) + block_drag_p0 = start_pos + + var blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + #var blocks_origin:Vector3 + block_drag_origin = Vector3.ZERO + for block in blocks: + block_drag_origin += block.global_transform.origin + block_drag_origin /= blocks.size() + + # print("res obj %s" % result.object.get_path()) + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() + if !sel_blocks.is_empty(): + + tool_state = ToolState.ROTATE_BLOCK + #print("Move block") + + cmd_transform_blocks = CommandTransformBlocks.new() + cmd_transform_blocks.builder = builder + cmd_transform_blocks.lock_uvs = builder.lock_uvs + for child in sel_blocks: + cmd_transform_blocks.add_block(child.get_path()) + + return + + + tool_state = ToolState.DRAG_SELECTION + drag_select_start_pos = e.position + drag_select_to_pos = e.position + + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ESCAPE: + if e.is_pressed(): + tool_state = ToolState.NONE + if cmd_transform_blocks: + cmd_transform_blocks.undo_it() + cmd_transform_blocks = null + + return true + + + if e.keycode == KEY_Q && e.alt_pressed: + if e.is_pressed(): + var origin:Vector3 = viewport_camera.project_ray_origin(mouse_hover_pos) + var dir:Vector3 = viewport_camera.project_ray_normal(mouse_hover_pos) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + if result: + var cmd:CommandSelectBlocks = CommandSelectBlocks.new() + cmd.builder = builder + cmd.block_paths.append(result.object.get_path()) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + _deactivate() + _activate(builder) + + return true + + elif event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + if tool_state == ToolState.NONE: + event_start = event + + tool_state = ToolState.READY + + else: + if tool_state == ToolState.READY: + + #We just clicked with the mouse + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + #print("Invoke select %s" % result) + var cmd:CommandSelectBlocks = CommandSelectBlocks.new() + cmd.builder = builder + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + if result: + cmd.block_paths.append(result.object.get_path()) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + elif tool_state == ToolState.ROTATE_BLOCK: + + #Finish moving blocks + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd_transform_blocks.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + elif tool_state == ToolState.DRAG_SELECTION: + + var frustum:Array[Plane] = MathUtil.calc_frustum_camera_rect(viewport_camera, drag_select_start_pos, drag_select_to_pos) + + var result:Array[CyclopsBlock] = builder.intersect_frustum_all(frustum) + + if !result.is_empty(): + + var cmd:CommandSelectBlocks = CommandSelectBlocks.new() + cmd.builder = builder + cmd.selection_type = Selection.choose_type(e.shift_pressed, e.ctrl_pressed) + + for r in result: + cmd.block_paths.append(r.get_path()) + + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.NONE + + return true + + elif e.button_index == MOUSE_BUTTON_RIGHT: + if e.is_pressed(): + #Right click cancel + if tool_state == ToolState.ROTATE_BLOCK: + tool_state = ToolState.NONE + if cmd_transform_blocks: + cmd_transform_blocks.undo_it() + cmd_transform_blocks = null + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + + mouse_hover_pos = e.position + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return super._gui_input(viewport_camera, event) + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + #print("tool_state %s" % tool_state) + + if tool_state == ToolState.READY: + var offset:Vector2 = e.position - event_start.position + if offset.length_squared() > MathUtil.square(builder.drag_start_radius): + start_drag(viewport_camera, event_start) + + return true + + elif tool_state == ToolState.ROTATE_BLOCK: + if !block_drag_p0.is_finite(): + block_drag_p0 = origin + dir * 20 + + var rot_axis:Vector3 + match move_constraint: + MoveConstraint.Type.PLANE_XY: + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, Vector3.BACK) + rot_axis = Vector3.BACK + MoveConstraint.Type.PLANE_XZ: + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, Vector3.UP) + rot_axis = Vector3.UP + MoveConstraint.Type.PLANE_YZ: + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, Vector3.RIGHT) + rot_axis = Vector3.RIGHT + MoveConstraint.Type.PLANE_VIEWPORT: + block_drag_cur = MathUtil.intersect_plane(origin, dir, block_drag_p0, viewport_camera.global_transform.basis.z) + rot_axis = viewport_camera.global_transform.basis.z + + #print("dragging move_constraint %s block_drag_cur %s" % [move_constraint, block_drag_cur]) + + var v0:Vector3 = (block_drag_p0 - block_drag_origin).normalized() + var v1:Vector3 = (block_drag_cur - block_drag_origin).normalized() + var binorm:Vector3 = v0.cross(rot_axis) + + var angle:float = atan2(v1.dot(binorm), v1.dot(v0)) + var snapped_angle = builder.get_snapping_manager().snap_angle(rad_to_deg(angle), SnappingQuery.new(viewport_camera)) + angle = deg_to_rad(snapped_angle) + + var xform:Transform3D = Transform3D.IDENTITY + xform = xform.translated_local(block_drag_origin) + xform = xform.rotated_local(rot_axis, -angle) + xform = xform.translated_local(-block_drag_origin) + #var rot_basis:Basis + #rot_basis = rot_basis.rotated(rot_axis, angle) + + + + block_drag_cur = builder.get_snapping_manager().snap_point(block_drag_cur, SnappingQuery.new(viewport_camera)) + + cmd_transform_blocks.transform = xform + #print("cmd_move_blocks.move_offset %s" % cmd_move_blocks.move_offset) + cmd_transform_blocks.do_it() + + return true + + elif tool_state == ToolState.DRAG_SELECTION: + drag_select_to_pos = e.position + return true + + + return super._gui_input(viewport_camera, event) + + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.OBJECT + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + +func _deactivate(): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.set_custom_gizmo(null) + diff --git a/addons/cyclops_level_builder/tools/tool_rotate.gd.uid b/addons/cyclops_level_builder/tools/tool_rotate.gd.uid new file mode 100644 index 00000000..875f15fb --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_rotate.gd.uid @@ -0,0 +1 @@ +uid://dv6ybnhuukmeh diff --git a/addons/cyclops_level_builder/tools/tool_stairs.gd b/addons/cyclops_level_builder/tools/tool_stairs.gd new file mode 100644 index 00000000..17fc3a84 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_stairs.gd @@ -0,0 +1,319 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolStairs + +const TOOL_ID:String = "stairs" + +enum ToolState { READY, DRAG_BASE, DRAG_HEIGHT } +var tool_state:ToolState = ToolState.READY + +var settings:ToolStairsSettings = ToolStairsSettings.new() + +var floor_normal:Vector3 +var drag_origin:Vector3 +var base_drag_cur:Vector3 +var block_drag_cur:Vector3 + + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + builder.mode = CyclopsLevelBuilder.Mode.OBJECT + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + + var cache:Dictionary = builder.get_tool_cache(TOOL_ID) + settings.load_from_cache(cache) + +func _deactivate(): + var cache:Dictionary = settings.save_to_cache() + builder.set_tool_cache(TOOL_ID, cache) + +func _get_tool_properties_editor()->Control: + #var res_insp:ResourceInspector = preload("res://addons/cyclops_level_builder/controls/resource_inspector/resource_inspector.tscn").instantiate() + # + #res_insp.target = settings + # + #return res_insp + var ed:ToolStairsSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_stairs_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + + + if tool_state == ToolState.DRAG_BASE: + var p01:Vector3 + var p10:Vector3 + var axis:MathUtil.Axis = MathUtil.get_longest_axis(floor_normal) + match axis: + MathUtil.Axis.X: + p01 = Vector3(drag_origin.x, drag_origin.y, base_drag_cur.z) + p10 = Vector3(drag_origin.x, base_drag_cur.y, drag_origin.z) + MathUtil.Axis.Y: + p01 = Vector3(drag_origin.x, drag_origin.y, base_drag_cur.z) + p10 = Vector3(base_drag_cur.x, drag_origin.y, drag_origin.z) + MathUtil.Axis.Z: + p01 = Vector3(drag_origin.x, base_drag_cur.y, drag_origin.z) + p10 = Vector3(base_drag_cur.x, drag_origin.y, drag_origin.z) + + var base_points:PackedVector3Array = [drag_origin, p01, base_drag_cur, p10] + + global_scene.draw_loop(base_points, true, global_scene.tool_material) + global_scene.draw_points(base_points, global_scene.vertex_tool_material) + + if tool_state == ToolState.DRAG_HEIGHT: + var tan_bi:Array[Vector3] = MathUtil.get_axis_aligned_tangent_and_binormal(floor_normal) + var u_normal:Vector3 = tan_bi[0] + var v_normal:Vector3 = tan_bi[1] + + #Rotate ccw by 90 degree increments + match settings.direction: + 1: + var tmp:Vector3 = u_normal + u_normal = -v_normal + v_normal = tmp + 2: + u_normal = -u_normal + v_normal = -v_normal + 3: + var tmp:Vector3 = -u_normal + u_normal = v_normal + v_normal = tmp + + var u_span:Vector3 = (base_drag_cur - drag_origin).project(u_normal) + var v_span:Vector3 = (base_drag_cur - drag_origin).project(v_normal) + + var stairs_origin:Vector3 = drag_origin + if u_span.dot(u_normal) < 0: + stairs_origin += u_span + u_span = -u_span + if v_span.dot(v_normal) < 0: + stairs_origin += v_span + v_span = -v_span + + #Stairs should ascend along v axis + global_scene.draw_cube(drag_origin, base_drag_cur, block_drag_cur, global_scene.tool_material, global_scene.vertex_tool_material) + + var height_offset = block_drag_cur - base_drag_cur + if height_offset.dot(floor_normal) < 0: + return + var num_steps:int = min(v_span.length() / settings.step_depth, height_offset.length() / settings.step_height) + + var max_height:float = floor(height_offset.length() / settings.step_height) * settings.step_height + + var step_span:Vector3 = v_normal * settings.step_depth + for i in num_steps: + var base_points:PackedVector3Array = [stairs_origin + step_span * i, \ + stairs_origin + u_span + step_span * i, \ + stairs_origin + u_span + step_span * (i + 1), \ + stairs_origin + step_span * (i + 1)] + global_scene.draw_prism(base_points, \ + floor_normal * (max_height - settings.step_height * i), \ + global_scene.tool_material, \ + global_scene.vertex_tool_material) + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + var blocks_root:Node = builder.get_block_add_parent() + #var grid_step_size:float = pow(2, builder.get_global_scene().grid_size) + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_ESCAPE: + if e.is_pressed(): + tool_state = ToolState.READY + return true + + elif event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + if tool_state == ToolState.READY: + tool_state = ToolState.DRAG_BASE + + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + if result && settings.block_alignment == BlockAlignment.Type.ALIGN_TO_SURFACE: + #print("init base point block") + floor_normal = result.get_world_normal() + +# var p:Vector3 = MathUtil.snap_to_grid(result.get_world_position(), grid_step_size) + var p:Vector3 = builder.get_snapping_manager().snap_point(result.get_world_position(), SnappingQuery.new(viewport_camera)) + drag_origin = p + base_drag_cur = p + + return true + + else: + #print("init base point empty space") + var draw_plane_point:Vector3 = Vector3.ZERO + var draw_plane_normal:Vector3 = BlockAlignment.get_plane_normal(settings.block_alignment) + if settings.match_selected_block: + draw_plane_point = calc_empty_space_draw_plane_origin(viewport_camera, draw_plane_point, draw_plane_normal) + + var hit_result = calc_hit_point_empty_space(origin, dir, viewport_camera, draw_plane_point, draw_plane_normal) + var start_pos:Vector3 = hit_result[0] + floor_normal = hit_result[1] + + #var p:Vector3 = MathUtil.snap_to_grid(start_pos, grid_step_size) + var p:Vector3 = builder.get_snapping_manager().snap_point(start_pos, SnappingQuery.new(viewport_camera)) + drag_origin = p + base_drag_cur = p + + return true + + else: + if tool_state == ToolState.DRAG_BASE: + var camera_dir:Vector3 = viewport_camera.project_ray_normal(e.position) + var angle_with_base:float = acos(floor_normal.dot(camera_dir)) + var drag_angle_limit:float = builder.get_global_scene().drag_angle_limit + if angle_with_base < drag_angle_limit || angle_with_base > PI - drag_angle_limit: + var height = settings.default_block_height + if settings.match_selected_block: + height = calc_active_block_orthogonal_height(base_drag_cur, floor_normal) + + block_drag_cur = base_drag_cur + floor_normal * height + + create_block() + + tool_state = ToolState.READY + else: + tool_state = ToolState.DRAG_HEIGHT + block_drag_cur = base_drag_cur + return true + + elif tool_state == ToolState.DRAG_HEIGHT: + #Create shape + create_block() + + tool_state = ToolState.READY + return true + + #elif e.button_index == MOUSE_BUTTON_RIGHT: + #if tool_state == ToolState.DRAG_BASE || tool_state == ToolState.DRAG_HEIGHT: + #if e.is_pressed(): + #tool_state = ToolState.READY + #return true + + elif e.button_index == MOUSE_BUTTON_WHEEL_UP: + if tool_state == ToolState.DRAG_BASE || tool_state == ToolState.DRAG_HEIGHT: + if e.pressed: + if e.ctrl_pressed: + if e.shift_pressed: + var size = log(settings.step_depth) / log(2) + settings.step_depth = pow(2, size + 1) + else: + var size = log(settings.step_height) / log(2) + settings.step_height = pow(2, size + 1) + else: + settings.direction = wrap(settings.direction + 1, 0, 4) + return true + + elif e.button_index == MOUSE_BUTTON_WHEEL_DOWN: + if tool_state == ToolState.DRAG_BASE || tool_state == ToolState.DRAG_HEIGHT: + if e.pressed: + if e.ctrl_pressed: + if e.shift_pressed: + var size = log(settings.step_depth) / log(2) + settings.step_depth = pow(2, size - 1) + else: + var size = log(settings.step_height) / log(2) + settings.step_height = pow(2, size - 1) + else: + settings.direction = wrap(settings.direction - 1, 0, 4) + return true + + + elif event is InputEventMouseMotion: + var e:InputEventMouseMotion = event + + if (e.button_mask & MOUSE_BUTTON_MASK_MIDDLE): + return false + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var start_pos:Vector3 = origin + builder.block_create_distance * dir +# var w2l = blocks_root.global_transform.inverse() +# var origin_local:Vector3 = w2l * origin +# var dir_local:Vector3 = w2l.basis * dir + + if tool_state == ToolState.DRAG_BASE: + var p_isect:Vector3 = MathUtil.intersect_plane(origin, dir, drag_origin, floor_normal) + #var p_snapped = to_local(p_isect, blocks_root.global_transform.inverse(), grid_step_size) +# var p_snapped:Vector3 = MathUtil.snap_to_grid(p_isect, grid_step_size) + var p_snapped:Vector3 = builder.get_snapping_manager().snap_point(p_isect, SnappingQuery.new(viewport_camera)) + base_drag_cur = p_snapped + + return true + + elif tool_state == ToolState.DRAG_HEIGHT: + block_drag_cur = MathUtil.closest_point_on_line(origin, dir, base_drag_cur, floor_normal) + + #block_drag_cur = to_local(block_drag_cur, blocks_root.global_transform.inverse(), grid_step_size) + block_drag_cur = builder.get_snapping_manager().snap_point(block_drag_cur, SnappingQuery.new(viewport_camera)) + + return true + + return super._gui_input(viewport_camera, event) + +func create_block(): + var blocks_root:Node = builder.get_block_add_parent() + + var cmd:CommandAddStairs = CommandAddStairs.new() + cmd.builder = builder + cmd.blocks_root_path = blocks_root.get_path() + cmd.block_name_prefix = "Block_" + cmd.floor_normal = floor_normal + cmd.drag_origin = drag_origin + cmd.base_drag_cur = base_drag_cur + cmd.block_drag_cur = block_drag_cur + cmd.step_height = settings.step_height + cmd.step_depth = settings.step_depth + cmd.direction = settings.direction + cmd.uv_transform = builder.tool_uv_transform + cmd.material_path = builder.tool_material_path + cmd.collision_type = settings.collision_type + cmd.collision_layers = settings.collision_layer + cmd.collision_mask = settings.collision_mask + + var undo:EditorUndoRedoManager = builder.get_undo_redo() + + cmd.add_to_undo_manager(undo) diff --git a/addons/cyclops_level_builder/tools/tool_stairs.gd.uid b/addons/cyclops_level_builder/tools/tool_stairs.gd.uid new file mode 100644 index 00000000..04da654c --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_stairs.gd.uid @@ -0,0 +1 @@ +uid://40clodalq2g4 diff --git a/addons/cyclops_level_builder/tools/tool_stairs_settings.gd b/addons/cyclops_level_builder/tools/tool_stairs_settings.gd new file mode 100644 index 00000000..34f2c9e4 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_stairs_settings.gd @@ -0,0 +1,66 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolStairsSettings + +@export var block_alignment:BlockAlignment.Type = BlockAlignment.Type.ALIGN_TO_SURFACE +@export var match_selected_block:bool = true +@export var default_block_elevation:float = 0 +@export var default_block_height:float = 1 +@export var collision_type:Collision.Type = Collision.Type.STATIC +@export_flags_3d_physics var collision_layer:int = 1 +@export_flags_3d_physics var collision_mask:int = 1 + +@export var step_height:float = .25 +@export var step_depth:float = .5 +@export var direction:int = 0 + +func load_from_cache(cache:Dictionary): + block_alignment = cache.get("block_alignment", BlockAlignment.Type.ALIGN_TO_SURFACE) + match_selected_block = cache.get("match_selected_block", true) + default_block_elevation = cache.get("default_block_elevation", 0) + default_block_height = cache.get("default_block_height", 1) + collision_type = cache.get("collision_type", Collision.Type.STATIC) + collision_layer = cache.get("collision_layer", 1) + collision_mask = cache.get("collision_mask", 1) + + step_height = cache.get("step_height", .25) + step_depth = cache.get("step_depth", .5) + direction = cache.get("direction", 0) + +func save_to_cache(): + return { + "block_alignment": block_alignment, + "match_selected_block": match_selected_block, + "default_block_elevation": default_block_elevation, + "default_block_height": default_block_height, + "collision_type": collision_type, + "collision_layer": collision_layer, + "collision_mask": collision_mask, + "step_height": step_height, + "step_depth": step_depth, + "direction": direction, + } + diff --git a/addons/cyclops_level_builder/tools/tool_stairs_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_stairs_settings.gd.uid new file mode 100644 index 00000000..95652b8b --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_stairs_settings.gd.uid @@ -0,0 +1 @@ +uid://2pwn13fdtjoj diff --git a/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd new file mode 100644 index 00000000..44a6b55d --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd @@ -0,0 +1,116 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolStairsSettingsEditor + + +var settings:ToolStairsSettings: + get: + return settings + set(value): + settings = value + dirty = true + +var dirty:bool = true + +func _ready(): + %collision_type.clear() + for text in Collision.Type.keys(): + %collision_type.add_item(text) + +func _process(delta): + if dirty: + update() + dirty = false + + +func update(): + if !settings: + #%default_block_height.value = 0 +# %step_height.disabled = true +# %step_depth.disabled = true + %spin_direction.disabled = true + %check_match_selected_block.disabled = true + %default_block_elevation.disabled = true + %default_block_height.disabled = true + return + +# %step_height.disabled = false + %step_height.value = settings.step_height +# %step_depth.disabled = false + %step_depth.value = settings.step_depth + #%spin_direction.disabled = false + %spin_direction.value = settings.direction + %check_match_selected_block.disabled = false + %check_match_selected_block.button_pressed = settings.match_selected_block + %default_block_elevation.disabled = false + %default_block_elevation.value = settings.default_block_elevation + %default_block_height.disabled = false + %default_block_height.value = settings.default_block_height + + %alignment_type.selected = settings.block_alignment + + %collision_type.selected = settings.collision_type + %collision_layers.value = settings.collision_layer + %collision_mask.value = settings.collision_mask + + +func _on_check_match_selected_block_toggled(value): + settings.match_selected_block = value + + +func _on_default_block_elevation_value_changed(value): + settings.default_block_elevation = value + + +func _on_default_block_height_value_changed(value): + settings.default_block_height = value + + + +func _on_step_height_value_changed(value): + settings.step_height + + +func _on_step_depth_value_changed(value): + settings.step_depth + + +func _on_spin_direction_value_changed(value): + settings.direction + +func _on_collision_layers_value_changed(value): + settings.collision_layer = value + + +func _on_collision_mask_value_changed(value): + settings.collision_mask = value + +func _on_collision_type_item_selected(index): + settings.collision_type = index + + +func _on_alignment_type_item_selected(index): + settings.block_alignment = index diff --git a/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd.uid new file mode 100644 index 00000000..ed334c96 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://ce2rnwfrv6s2k diff --git a/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.tscn new file mode 100644 index 00000000..5dc96c8b --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_stairs_settings_editor.tscn @@ -0,0 +1,163 @@ +[gd_scene load_steps=3 format=3 uid="uid://bhbo7hbko5myp"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_stairs_settings_editor.gd" id="1_flcpk"] +[ext_resource type="PackedScene" uid="uid://diibmlqy1mpqb" path="res://addons/cyclops_level_builder/controls/numeric_line_edit.tscn" id="2_hqkby"] + +[node name="ToolStairsSettings" type="PanelContainer"] +offset_right = 413.0 +offset_bottom = 232.0 +script = ExtResource("1_flcpk") + +[node name="PanelContainer" type="PanelContainer" parent="."] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer"] +layout_mode = 2 + +[node name="GridContainer" type="GridContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label5" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Type" + +[node name="collision_type" type="OptionButton" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 4 +selected = 0 +popup/item_0/text = "NONE" +popup/item_0/id = 0 +popup/item_1/text = "STATIC" +popup/item_1/id = 1 +popup/item_2/text = "KINEMATIC" +popup/item_2/id = 2 +popup/item_3/text = "RIGID" +popup/item_3/id = 3 + +[node name="Label6" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Layers" + +[node name="collision_layers" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label7" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Collision Mask" + +[node name="collision_mask" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Step Height" + +[node name="step_height" parent="PanelContainer/VBoxContainer/GridContainer" instance=ExtResource("2_hqkby")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label4" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Step Depth" + +[node name="step_depth" parent="PanelContainer/VBoxContainer/GridContainer" instance=ExtResource("2_hqkby")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Direction" + +[node name="spin_direction" type="SpinBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +max_value = 3.0 +value = 3.0 +rounded = true +allow_greater = true +allow_lesser = true + +[node name="Label8" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Alignment" + +[node name="alignment_type" type="OptionButton" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 4 +selected = 0 +popup/item_0/text = "Align to surface" +popup/item_0/id = 0 +popup/item_1/text = "XY Plane" +popup/item_1/id = 1 +popup/item_2/text = "XZ Plane" +popup/item_2/id = 2 +popup/item_3/text = "YZ Plane" +popup/item_3/id = 3 + +[node name="Label3" type="Label" parent="PanelContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Match selected block" + +[node name="check_match_selected_block" type="CheckBox" parent="PanelContainer/VBoxContainer/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +tooltip_text = "When drawing in empty space, copy elevation and height properties from currently selected block." +text = "On" + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +text = "Orthogonal Viewport:" + +[node name="MarginContainer" type="MarginContainer" parent="PanelContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/margin_left = 16 + +[node name="VBoxContainer" type="VBoxContainer" parent="PanelContainer/VBoxContainer/MarginContainer"] +layout_mode = 2 + +[node name="GridContainer" type="GridContainer" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer"] +layout_mode = 2 +columns = 2 + +[node name="Label" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Default Block Elevation" + +[node name="default_block_elevation" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer" instance=ExtResource("2_hqkby")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label2" type="Label" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer"] +layout_mode = 2 +text = "Default Block Height" + +[node name="default_block_height" parent="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer" instance=ExtResource("2_hqkby")] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[connection signal="item_selected" from="PanelContainer/VBoxContainer/GridContainer/collision_type" to="." method="_on_collision_type_item_selected"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/collision_layers" to="." method="_on_collision_layers_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/collision_mask" to="." method="_on_collision_mask_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/step_height" to="." method="_on_step_height_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/step_depth" to="." method="_on_step_depth_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/GridContainer/spin_direction" to="." method="_on_spin_direction_value_changed"] +[connection signal="item_selected" from="PanelContainer/VBoxContainer/GridContainer/alignment_type" to="." method="_on_alignment_type_item_selected"] +[connection signal="toggled" from="PanelContainer/VBoxContainer/GridContainer/check_match_selected_block" to="." method="_on_check_match_selected_block_toggled"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer/default_block_elevation" to="." method="_on_default_block_elevation_value_changed"] +[connection signal="value_changed" from="PanelContainer/VBoxContainer/MarginContainer/VBoxContainer/GridContainer/default_block_height" to="." method="_on_default_block_height_value_changed"] diff --git a/addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd b/addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd new file mode 100644 index 00000000..1c71ade6 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd @@ -0,0 +1,198 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends CyclopsTool +class_name ToolVertexColorBrush + +enum ToolState { READY, PAINTING } +var tool_state:ToolState = ToolState.READY + +const TOOL_ID:String = "vertex_color_brush" + +var cmd:CommandVertexPaintStroke + +var settings:ToolVertexColorBrushSettings = ToolVertexColorBrushSettings.new() + +var last_mouse_pos:Vector2 + +var brush_over_mesh:bool = false +var last_hit_pos:Vector3 + +func _get_tool_id()->String: + return TOOL_ID + +func _draw_tool(viewport_camera:Camera3D): + var global_scene:CyclopsGlobalScene = builder.get_global_scene() + global_scene.clear_tool_mesh() + global_scene.draw_selected_blocks(viewport_camera) + + #super._draw_tool(viewport_camera) + + if brush_over_mesh: + var view_dir:Vector3 = viewport_camera.global_transform.basis.z + var bounding_points:PackedVector3Array = \ + MathUtil.create_circle_points(last_hit_pos, view_dir.normalized(), settings.radius, 16) + global_scene.draw_loop(bounding_points, true, global_scene.tool_material) + + +func _get_tool_properties_editor()->Control: + var ed:ToolVertexColorBrushSettingsEditor = preload("res://addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.tscn").instantiate() + + ed.settings = settings + + return ed + + +func _gui_input(viewport_camera:Camera3D, event:InputEvent)->bool: + + if event is InputEventKey: + var e:InputEventKey = event + + if e.keycode == KEY_X: + if e.shift_pressed: + if e.is_pressed(): + #Pick closest vertex color + var origin:Vector3 = viewport_camera.project_ray_origin(last_mouse_pos) + var dir:Vector3 = viewport_camera.project_ray_normal(last_mouse_pos) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + if result: + var block:CyclopsBlock = result.object + result.face_index + + var vol:ConvexVolume = ConvexVolume.new() + vol.init_from_mesh_vector_data(block.mesh_vector_data) + + var face:ConvexVolume.FaceInfo = vol.faces[result.face_index] + var v_idx:int = face.get_closest_vertex(result.position) + var vert:ConvexVolume.VertexInfo = vol.vertices[v_idx] + + var fv:ConvexVolume.FaceVertexInfo = vol.get_face_vertex(result.face_index, v_idx) + #print("sample color ", fv.color) + + settings.color = fv.color + + return true + + + elif e.keycode == KEY_Q: + + if e.is_pressed(): + select_block_under_cursor(viewport_camera, last_mouse_pos) + + return true + + elif event is InputEventMouseButton: + + var e:InputEventMouseButton = event + if e.button_index == MOUSE_BUTTON_LEFT: + + if e.is_pressed(): + + if tool_state == ToolState.READY: + #print("vertex color brush bn down") + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + var sel_blocks:Array[CyclopsBlock] = builder.get_selected_blocks() +# if result && result.object == builder.get_active_block(): + if result && sel_blocks.has(result.object): + #print("starting paint") + cmd = CommandVertexPaintStroke.new() + cmd.builder = builder + + cmd.append_block(result.object.get_path()) + cmd.color = settings.color + cmd.strength = settings.strength + cmd.radius = settings.radius + cmd.falloff_curve = settings.falloff_curve.duplicate() + cmd.mask = settings.mask_type + + var pos:Vector3 = result.get_world_position() + #print("pos ", pos) + cmd.append_stroke_point(pos, 1) + + + cmd.do_it() + tool_state = ToolState.PAINTING + + else: + + if tool_state == ToolState.PAINTING: + cmd.undo_it() + if cmd.will_change_anything(): + var undo:EditorUndoRedoManager = builder.get_undo_redo() + cmd.add_to_undo_manager(undo) + + tool_state = ToolState.READY + + return true + + + elif event is InputEventMouseMotion: + + var e:InputEventMouseMotion = event + + last_mouse_pos = e.position + + var origin:Vector3 = viewport_camera.project_ray_origin(e.position) + var dir:Vector3 = viewport_camera.project_ray_normal(e.position) + + var result:IntersectResults = builder.intersect_ray_closest(origin, dir) + + if result: + brush_over_mesh = true + last_hit_pos = result.object.global_transform * result.position + else: + brush_over_mesh = false + + if tool_state == ToolState.PAINTING: + + if result: + #print ("hit ", result.object.name) + cmd.undo_it() + + cmd.append_stroke_point(result.get_world_position(), \ + e.pressure if settings.pen_pressure_strength else 1) + + cmd.do_it() + + return true + + return false + + +func _activate(builder:CyclopsLevelBuilder): + super._activate(builder) + + var cache:Dictionary = builder.get_tool_cache(TOOL_ID) + settings.load_from_cache(cache) + +func _deactivate(): + var cache:Dictionary = settings.save_to_cache() + builder.set_tool_cache(TOOL_ID, cache) diff --git a/addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd.uid b/addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd.uid new file mode 100644 index 00000000..88e5dd4b --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_vertex_color_brush.gd.uid @@ -0,0 +1 @@ +uid://c80pcu50d2sfm diff --git a/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings.gd b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings.gd new file mode 100644 index 00000000..d27fa833 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings.gd @@ -0,0 +1,94 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name ToolVertexColorBrushSettings + + +@export var component_type:GeometryComponentType.Type = GeometryComponentType.Type.OBJECT + +@export var mask_type:CommandVertexPaintStroke.MaskType = CommandVertexPaintStroke.MaskType.NONE: + set(value): + if value != mask_type: + mask_type = value + emit_changed() + +@export var color:Color = Color.WHITE: + set(value): + if value != color: + color = value + emit_changed() + +@export var radius:float: + set(value): + if value != radius: + radius = value + emit_changed() + +@export var strength:float: + set(value): + if value != strength: + strength = value + emit_changed() + +@export var pen_pressure_strength:bool: + set(value): + if value != pen_pressure_strength: + pen_pressure_strength = value + emit_changed() + +@export var falloff_curve:Curve: + set(value): + if value != falloff_curve: + falloff_curve = value + emit_changed() + +func load_from_cache(cache:Dictionary): + component_type = cache.get("component_type", GeometryComponentType.Type.OBJECT) + color = str_to_var(cache.get("color", var_to_str(Color.WHITE))) + radius = cache.get("radius", 1) + strength = cache.get("strength", 1) + pen_pressure_strength = cache.get("pen_pressure_strength", false) + + if cache.has("falloff_curve"): + falloff_curve = str_to_var(cache.get("falloff_curve")) + else: + falloff_curve = Curve.new() + falloff_curve.add_point(Vector2(0, 0)) + falloff_curve.add_point(Vector2(1, 1)) + +func save_to_cache(): + return { + "component_type": component_type, + "color": var_to_str(color), + "radius": radius, + "strength": strength, + "pen_pressure_strength": pen_pressure_strength, + "falloff_curve": var_to_str(falloff_curve) + } + + + + + diff --git a/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings.gd.uid b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings.gd.uid new file mode 100644 index 00000000..79d7808b --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings.gd.uid @@ -0,0 +1 @@ +uid://c7kr4gfi07uji diff --git a/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd new file mode 100644 index 00000000..5facaaee --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd @@ -0,0 +1,104 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends PanelContainer +class_name ToolVertexColorBrushSettingsEditor + +@export var settings:ToolVertexColorBrushSettings: + get: + return settings + + set(value): + if settings == value: + return + + if settings: + settings.changed.disconnect(on_settings_changed) + + settings = value + + if settings: + settings.changed.connect(on_settings_changed) + + update() + +func on_settings_changed(): + update() + +func update(): + + %opbn_mask_type.selected = settings.mask_type + + %color_button.color = settings.color + %spin_strength.value = settings.strength + %spin_radius.value = settings.radius + %check_pen_pressure_str.button_pressed = settings.pen_pressure_strength + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + pass + + +func _on_color_button_color_changed(color:Color): + settings.color = color + + +#func _on_opbn_geom_component_item_selected(index): + #match index: + #0: + #settings.component_type = GeometryComponentType.Type.OBJECT + #1: + #settings.component_type = GeometryComponentType.Type.VERTEX + #2: + #settings.component_type = GeometryComponentType.Type.FACE + #3: + #settings.component_type = GeometryComponentType.Type.FACE_VERTEX + + +func _on_spin_strength_value_changed(value): + settings.strength = value + + +func _on_check_pen_pressure_str_toggled(toggled_on): + settings.pen_pressure_strength = toggled_on + + +func _on_spin_radius_value_changed(value): + settings.radius = value + + +func _on_opbn_mask_type_item_selected(index): + match index: + 0: + settings.mask_type = CommandVertexPaintStroke.MaskType.NONE + 1: + settings.mask_type = CommandVertexPaintStroke.MaskType.VERTICES + 2: + settings.mask_type = CommandVertexPaintStroke.MaskType.FACES diff --git a/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd.uid b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd.uid new file mode 100644 index 00000000..01b4395f --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd.uid @@ -0,0 +1 @@ +uid://dd3r1yiwew2ma diff --git a/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.tscn b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.tscn new file mode 100644 index 00000000..6f046501 --- /dev/null +++ b/addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.tscn @@ -0,0 +1,80 @@ +[gd_scene load_steps=2 format=3 uid="uid://djlowj2pi405u"] + +[ext_resource type="Script" path="res://addons/cyclops_level_builder/tools/tool_vertex_color_brush_settings_editor.gd" id="1_1a32u"] + +[node name="PanelContainer" type="PanelContainer"] +offset_right = 317.0 +offset_bottom = 269.0 +script = ExtResource("1_1a32u") + +[node name="MarginContainer2" type="MarginContainer" parent="."] +layout_mode = 2 +theme_override_constants/margin_left = 16 + +[node name="GridContainer" type="GridContainer" parent="MarginContainer2"] +layout_mode = 2 +columns = 2 + +[node name="Label3" type="Label" parent="MarginContainer2/GridContainer"] +layout_mode = 2 +text = "Component type" + +[node name="opbn_mask_type" type="OptionButton" parent="MarginContainer2/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +item_count = 3 +selected = 0 +popup/item_0/text = "None" +popup/item_0/id = 0 +popup/item_1/text = "Vertex" +popup/item_1/id = 1 +popup/item_2/text = "Face" +popup/item_2/id = 2 + +[node name="Label" type="Label" parent="MarginContainer2/GridContainer"] +layout_mode = 2 +text = "Color" + +[node name="color_button" type="ColorPickerButton" parent="MarginContainer2/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="Label5" type="Label" parent="MarginContainer2/GridContainer"] +layout_mode = 2 +text = "Radius" + +[node name="spin_radius" type="SpinBox" parent="MarginContainer2/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +max_value = 1.0 +step = 0.1 +value = 1.0 +allow_greater = true + +[node name="Label2" type="Label" parent="MarginContainer2/GridContainer"] +layout_mode = 2 +text = "Strength" + +[node name="spin_strength" type="SpinBox" parent="MarginContainer2/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +max_value = 1.0 +step = 0.1 +value = 1.0 +allow_greater = true + +[node name="Label4" type="Label" parent="MarginContainer2/GridContainer"] +layout_mode = 2 +text = "Pen Pressure" + +[node name="check_pen_pressure_str" type="CheckBox" parent="MarginContainer2/GridContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "On" + +[connection signal="item_selected" from="MarginContainer2/GridContainer/opbn_mask_type" to="." method="_on_opbn_mask_type_item_selected"] +[connection signal="color_changed" from="MarginContainer2/GridContainer/color_button" to="." method="_on_color_button_color_changed"] +[connection signal="value_changed" from="MarginContainer2/GridContainer/spin_radius" to="." method="_on_spin_radius_value_changed"] +[connection signal="value_changed" from="MarginContainer2/GridContainer/spin_strength" to="." method="_on_spin_strength_value_changed"] +[connection signal="toggled" from="MarginContainer2/GridContainer/check_pen_pressure_str" to="." method="_on_check_pen_pressure_str_toggled"] diff --git a/addons/cyclops_level_builder/util/collision.gd b/addons/cyclops_level_builder/util/collision.gd new file mode 100644 index 00000000..cb172e9e --- /dev/null +++ b/addons/cyclops_level_builder/util/collision.gd @@ -0,0 +1,27 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name Collision + +enum Type { NONE, STATIC, KINEMATIC, RIGID } diff --git a/addons/cyclops_level_builder/util/collision.gd.uid b/addons/cyclops_level_builder/util/collision.gd.uid new file mode 100644 index 00000000..7bb80c99 --- /dev/null +++ b/addons/cyclops_level_builder/util/collision.gd.uid @@ -0,0 +1 @@ +uid://d2guqvm33k2p8 diff --git a/addons/cyclops_level_builder/util/cyclops_logger.gd b/addons/cyclops_level_builder/util/cyclops_logger.gd new file mode 100644 index 00000000..5eb670b4 --- /dev/null +++ b/addons/cyclops_level_builder/util/cyclops_logger.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name CyclopsLogger + +enum LogLevel { ERROR, WARNING, INFO } + +func log(message:String, level:LogLevel = LogLevel.ERROR): + print(message) diff --git a/addons/cyclops_level_builder/util/cyclops_logger.gd.uid b/addons/cyclops_level_builder/util/cyclops_logger.gd.uid new file mode 100644 index 00000000..16f97b07 --- /dev/null +++ b/addons/cyclops_level_builder/util/cyclops_logger.gd.uid @@ -0,0 +1 @@ +uid://b25abnsx4400p diff --git a/addons/cyclops_level_builder/util/cyclops_settings.gd b/addons/cyclops_level_builder/util/cyclops_settings.gd new file mode 100644 index 00000000..128a8922 --- /dev/null +++ b/addons/cyclops_level_builder/util/cyclops_settings.gd @@ -0,0 +1,228 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name CyclopsSettings + +@export var definition_map:Dictionary +@export var lookup:Dictionary + +var float_regex_strn:String = "[+-]?([0-9]*[.])?[0-9]+" +var regex_int = RegEx.create_from_string("[0-9]+") +var regex_float = RegEx.create_from_string(float_regex_strn) +var regex_color = RegEx.create_from_string("color\\(" + float_regex_strn + "\\)") + +class SettingDef: + var name:String + var default_value + var type:Variant.Type + var hint:PropertyHint + var hint_string:String + + +func value_to_text(value, type:int)->String: + match type: + TYPE_BOOL: + return "true" if value else "false" + + TYPE_COLOR: + return JSON.stringify([value.r, value.g, value.b, value.a]) + + TYPE_FLOAT: + return str(value) + + TYPE_INT: + return str(value) + + TYPE_NODE_PATH: + return str(value) + + TYPE_STRING: + return "\"" + value + "\"" + + TYPE_TRANSFORM2D: + var a:Transform2D = value + return JSON.stringify({"x": [a.x.x, a.x.y], + "y": [a.y.x, a.y.y], + "o": [a.origin.x, a.origin.y], + }) + + TYPE_TRANSFORM3D: + var a:Transform3D = value + return JSON.stringify({"x": [a.basis.x.x, a.basis.x.y, a.basis.x.z], + "y": [a.basis.y.x, a.basis.y.y, a.basis.y.z], + "z": [a.basis.z.x, a.basis.z.y, a.basis.z.z], + "o": [a.origin.x, a.origin.y, a.origin.z], + }) + + TYPE_VECTOR2: + var a:Vector2 = value + return JSON.stringify([a.x, a.y]) + + TYPE_VECTOR3: + var a:Vector3 = value + return JSON.stringify([a.x, a.y, a.z]) + + TYPE_VECTOR4: + var a:Vector4 = value + return JSON.stringify([a.x, a.y, a.z, a.w]) + + _: + return "" + +func text_to_value(text:String, type:int): + text = text.lstrip(" ").rstrip(" ") + + match type: + TYPE_BOOL: + return text.to_lower() == "true" + + TYPE_COLOR: + var a:Array = JSON.parse_string(text) + return Color(a[0], a[1], a[2], a[3]) + + TYPE_FLOAT: + return float(text) + + TYPE_INT: + return int(text) + + TYPE_NODE_PATH: + return NodePath(text) + + TYPE_STRING: + #Trim starting and ending quotes + return text.substr(1, text.length() - 2) + + TYPE_TRANSFORM2D: + var a:Dictionary = JSON.parse_string(text) + return Transform2D(Vector2(a["x"][0], a["x"][1]), + Vector2(a["y"][0], a["y"][1]), + Vector2(a["o"][0], a["o"][1])) + + TYPE_TRANSFORM3D: + var a:Dictionary = JSON.parse_string(text) + return Transform3D(Vector3(a["x"][0], a["x"][1], a["x"][2]), + Vector3(a["y"][0], a["y"][1], a["y"][2]), + Vector3(a["z"][0], a["z"][1], a["z"][2]), + Vector3(a["o"][0], a["o"][1], a["o"][2])) + + TYPE_VECTOR2: + var a:Array = JSON.parse_string(text) + return Vector2(a[0], a[1]) + + TYPE_VECTOR3: + var a:Array = JSON.parse_string(text) + return Vector3(a[0], a[1], a[2]) + + TYPE_VECTOR4: + var a:Array = JSON.parse_string(text) + return Vector4(a[0], a[1], a[2], a[3]) + + _: + return null + + +func save_to_file(path:String): + var keys:Array = lookup.keys() + keys.sort() + + var f:FileAccess = FileAccess.open(path, FileAccess.WRITE) + if !f: + return + + for key in keys: + var def:SettingDef = definition_map[key] + f.store_line("%s=%s" % [key, value_to_text(lookup[key], def.type)]) + + f.close() + +func load_from_file(path:String): + lookup.clear() + + var f:FileAccess = FileAccess.open(path, FileAccess.READ) + + while !f.eof_reached(): + var line:String = f.get_line() + line = line.lstrip(" ") + if line.is_empty() || line[0] == "#": + continue + + var idx = line.find("=") + if idx == -1: + continue + + var name:String = line.substr(0, idx) + var value_text:String = line.substr(idx + 1) + + if !definition_map.has(name): + continue + + var def:SettingDef = definition_map[name] + set_property(name, text_to_value(value_text, def.type)) + + + +func add_setting(name:String, default_value, type:Variant.Type, hint:PropertyHint = PROPERTY_HINT_NONE, hint_string:String = ""): + var def:SettingDef = SettingDef.new() + def.name = name + def.default_value = default_value + def.type = type + def.hint = hint + def.hint_string = hint_string + + definition_map[name] = def + + +func set_property(name:String, value): + if !definition_map.has(name): + push_error("Unknown setting name " + name) + return + + var def:SettingDef = definition_map[name] + var var_type:int = typeof(value) + if var_type != def.type: + push_error("Settings error: Bad setting type. Needed %s but got %s" % [def.type, var_type]) + return + + lookup[name] = value + + +func has_property(name:String)->bool: + return definition_map.has(name) + +func get_property(name:String): + #print("lookup ", name) + if !definition_map.has(name): + push_error("Unknown setting name " + name) + return null + + #print("is defined ", name) + if lookup.has(name): + return lookup[name] + + #print("returning default ", name) + var def:SettingDef = definition_map[name] + return def.default_value + diff --git a/addons/cyclops_level_builder/util/cyclops_settings.gd.uid b/addons/cyclops_level_builder/util/cyclops_settings.gd.uid new file mode 100644 index 00000000..382577f4 --- /dev/null +++ b/addons/cyclops_level_builder/util/cyclops_settings.gd.uid @@ -0,0 +1 @@ +uid://y4pr06uuvdgh diff --git a/addons/cyclops_level_builder/util/display_mode.gd b/addons/cyclops_level_builder/util/display_mode.gd new file mode 100644 index 00000000..69d26162 --- /dev/null +++ b/addons/cyclops_level_builder/util/display_mode.gd @@ -0,0 +1,28 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name DisplayMode + +enum Type { WIRE, MESH, MATERIAL } + diff --git a/addons/cyclops_level_builder/util/display_mode.gd.uid b/addons/cyclops_level_builder/util/display_mode.gd.uid new file mode 100644 index 00000000..87f541f4 --- /dev/null +++ b/addons/cyclops_level_builder/util/display_mode.gd.uid @@ -0,0 +1 @@ +uid://bark23jva82cu diff --git a/addons/cyclops_level_builder/util/general_util.gd b/addons/cyclops_level_builder/util/general_util.gd new file mode 100644 index 00000000..24095000 --- /dev/null +++ b/addons/cyclops_level_builder/util/general_util.gd @@ -0,0 +1,71 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name GeneralUtil + +static func find_unique_name(parent:Node, base_name:String)->String: + #Check if numeric suffix already exists + var regex = RegEx.new() + regex.compile("(\\d+)") + var match_res:RegExMatch = regex.search(base_name) + + var name_idx:int = 0 + + if match_res: + var suffix:String = match_res.get_string(1) + name_idx = int(suffix) + 1 + base_name = base_name.substr(0, base_name.length() - suffix.length()) + + #Search for free index + while true: + var name = base_name + str(name_idx) + if !parent.find_child(name, false): + return name + + name_idx += 1 + + return "" + +static func calc_resource_name(res:Resource)->String: + var name:String = res.resource_name + + if name.is_empty(): + name = res.resource_path.get_file() + var idx:int = name.rfind(".") + if idx != -1: + name = name.substr(0, idx) + + return name + +static func format_planes_string(planes:Array[Plane])->String: + var result:String = "" + for p in planes: + result = result + "(%s, %s, %s, %s)," % [p.x, p.y, p.z, p.d] + return result + + +static func dump_properties(obj): + for prop in obj.get_property_list(): + var name:String = prop["name"] + print ("%s: %s" % [name, str(obj.get(name))]) diff --git a/addons/cyclops_level_builder/util/general_util.gd.uid b/addons/cyclops_level_builder/util/general_util.gd.uid new file mode 100644 index 00000000..45734269 --- /dev/null +++ b/addons/cyclops_level_builder/util/general_util.gd.uid @@ -0,0 +1 @@ +uid://docmprng1ingo diff --git a/addons/cyclops_level_builder/util/geometry_component_type.gd b/addons/cyclops_level_builder/util/geometry_component_type.gd new file mode 100644 index 00000000..0429c90e --- /dev/null +++ b/addons/cyclops_level_builder/util/geometry_component_type.gd @@ -0,0 +1,28 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name GeometryComponentType + +enum Type { OBJECT, VERTEX, FACE, FACE_VERTEX } + diff --git a/addons/cyclops_level_builder/util/geometry_component_type.gd.uid b/addons/cyclops_level_builder/util/geometry_component_type.gd.uid new file mode 100644 index 00000000..3105aed1 --- /dev/null +++ b/addons/cyclops_level_builder/util/geometry_component_type.gd.uid @@ -0,0 +1 @@ +uid://c66n3yvrhvaev diff --git a/addons/cyclops_level_builder/util/selection.gd b/addons/cyclops_level_builder/util/selection.gd new file mode 100644 index 00000000..46e40e3c --- /dev/null +++ b/addons/cyclops_level_builder/util/selection.gd @@ -0,0 +1,37 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name Selection + +enum Type { REPLACE, ADD, SUBTRACT, TOGGLE } + +static func choose_type(shift_pressed:bool, ctrl_pressed)->Type: + if !shift_pressed and !ctrl_pressed: + return Type.REPLACE + elif shift_pressed and !ctrl_pressed: + return Type.TOGGLE + elif !shift_pressed and ctrl_pressed: + return Type.ADD + else: + return Type.SUBTRACT diff --git a/addons/cyclops_level_builder/util/selection.gd.uid b/addons/cyclops_level_builder/util/selection.gd.uid new file mode 100644 index 00000000..151973e4 --- /dev/null +++ b/addons/cyclops_level_builder/util/selection.gd.uid @@ -0,0 +1 @@ +uid://b3dqr815jtdp0 diff --git a/addons/cyclops_level_builder/util/selection_list.gd b/addons/cyclops_level_builder/util/selection_list.gd new file mode 100644 index 00000000..453a4dc9 --- /dev/null +++ b/addons/cyclops_level_builder/util/selection_list.gd @@ -0,0 +1,37 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name SelectionList + +enum Type { REPLACE, RANGE, TOGGLE } + +static func choose_type(shift_pressed:bool, ctrl_pressed)->Type: + if !shift_pressed and !ctrl_pressed: + return Type.REPLACE + elif shift_pressed and !ctrl_pressed: + return Type.RANGE + elif !shift_pressed and ctrl_pressed: + return Type.TOGGLE + else: + return Type.REPLACE diff --git a/addons/cyclops_level_builder/util/selection_list.gd.uid b/addons/cyclops_level_builder/util/selection_list.gd.uid new file mode 100644 index 00000000..353e890c --- /dev/null +++ b/addons/cyclops_level_builder/util/selection_list.gd.uid @@ -0,0 +1 @@ +uid://eop5a6ixvy45 diff --git a/addons/cyclops_level_builder/util/serial_util.gd b/addons/cyclops_level_builder/util/serial_util.gd new file mode 100644 index 00000000..ed8a6f76 --- /dev/null +++ b/addons/cyclops_level_builder/util/serial_util.gd @@ -0,0 +1,72 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name SerialUtil + +static func save_cache_vector3(value:Vector3)->Dictionary: + return { + "value": [value.x, value.y, value.z] + } + +static func load_cache_vector3(cache:Dictionary, default_value:Vector3 = Vector3.ZERO)->Vector3: + if !cache: + return default_value + + return Vector3(cache.value[0], cache.value[1], cache.value[2]) + +static func save_cache_color(value:Color)->Dictionary: + return { + "color": [value.r, value.g, value.b, value.a] + } + +static func load_cache_color(cache:Dictionary, default_value:Color = Color.BLACK)->Color: + if !cache: + return default_value + + return Color(cache.color[0], cache.color[1], cache.color[2], cache.color[3]) + +static func save_cache_transform_3d(t:Transform3D)->String: + return var_to_str(t) + #var dict:Dictionary = { + #"x": [t.basis.x.x, t.basis.x.y, t.basis.x.z], + #"y": [t.basis.y.x, t.basis.y.y, t.basis.y.z], + #"z": [t.basis.z.x, t.basis.z.y, t.basis.z.z], + #"o": [t.origin.x, t.origin.y, t.origin.z], + #} + #return JSON.stringify(dict) + +static func load_cache_transform_3d(text:String, default_value:Transform3D = Transform3D.IDENTITY)->Transform3D: + if text.is_empty(): + return default_value + + return str_to_var(text) + + #var cache:Dictionary = JSON.parse_string(text) + #var x:Vector3 = Vector3(cache.x[0], cache.x[1], cache.x[2]) + #var y:Vector3 = Vector3(cache.y[0], cache.y[1], cache.y[2]) + #var z:Vector3 = Vector3(cache.z[0], cache.z[1], cache.z[2]) + #var o:Vector3 = Vector3(cache.o[0], cache.o[1], cache.o[2]) + # + #return Transform3D(x, y, z, o) + diff --git a/addons/cyclops_level_builder/util/serial_util.gd.uid b/addons/cyclops_level_builder/util/serial_util.gd.uid new file mode 100644 index 00000000..2ade6896 --- /dev/null +++ b/addons/cyclops_level_builder/util/serial_util.gd.uid @@ -0,0 +1 @@ +uid://brkbfky5n3m10 diff --git a/addons/cyclops_level_builder/util/transform_space.gd b/addons/cyclops_level_builder/util/transform_space.gd new file mode 100644 index 00000000..b3bbd681 --- /dev/null +++ b/addons/cyclops_level_builder/util/transform_space.gd @@ -0,0 +1,29 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +@tool + +class_name TransformSpace + +enum Type { GLOBAL, LOCAL, NORMAL, VIEW, PARENT } diff --git a/addons/cyclops_level_builder/util/transform_space.gd.uid b/addons/cyclops_level_builder/util/transform_space.gd.uid new file mode 100644 index 00000000..031edcbf --- /dev/null +++ b/addons/cyclops_level_builder/util/transform_space.gd.uid @@ -0,0 +1 @@ +uid://dbroe6ylut6wq diff --git a/addons/cyclops_level_builder/util/tree_vistor.gd b/addons/cyclops_level_builder/util/tree_vistor.gd new file mode 100644 index 00000000..598e6047 --- /dev/null +++ b/addons/cyclops_level_builder/util/tree_vistor.gd @@ -0,0 +1,35 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends RefCounted +class_name TreeVisitor + +static func visit(root:Node, callback:Callable): + visit_recursive(root, callback) + +static func visit_recursive(node:Node, callback:Callable): + callback.call(node) + + for child in node.get_children(): + visit_recursive(child, callback) diff --git a/addons/cyclops_level_builder/util/tree_vistor.gd.uid b/addons/cyclops_level_builder/util/tree_vistor.gd.uid new file mode 100644 index 00000000..a2598e6c --- /dev/null +++ b/addons/cyclops_level_builder/util/tree_vistor.gd.uid @@ -0,0 +1 @@ +uid://dbsaewwcw45d7 diff --git a/addons/cyclops_level_builder/util/unit_system.gd b/addons/cyclops_level_builder/util/unit_system.gd new file mode 100644 index 00000000..de44a13c --- /dev/null +++ b/addons/cyclops_level_builder/util/unit_system.gd @@ -0,0 +1,28 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +class_name UnitSystem + +enum Type { NONE, METRIC, IMPERIAL } + diff --git a/addons/cyclops_level_builder/util/unit_system.gd.uid b/addons/cyclops_level_builder/util/unit_system.gd.uid new file mode 100644 index 00000000..61628d16 --- /dev/null +++ b/addons/cyclops_level_builder/util/unit_system.gd.uid @@ -0,0 +1 @@ +uid://blbv7n4rmosqd diff --git a/addons/cyclops_level_builder/util/xml/XML_attribute.gd b/addons/cyclops_level_builder/util/xml/XML_attribute.gd new file mode 100644 index 00000000..42c9569f --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_attribute.gd @@ -0,0 +1,33 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends XMLNode +class_name XMLAttribute + +@export var name:String +@export var value:String + +func _init(name:String = "", value:String = ""): + self.name = name + self.value = value diff --git a/addons/cyclops_level_builder/util/xml/XML_attribute.gd.uid b/addons/cyclops_level_builder/util/xml/XML_attribute.gd.uid new file mode 100644 index 00000000..00dc6e02 --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_attribute.gd.uid @@ -0,0 +1 @@ +uid://d1gwo0f6j0e4e diff --git a/addons/cyclops_level_builder/util/xml/XML_document.gd b/addons/cyclops_level_builder/util/xml/XML_document.gd new file mode 100644 index 00000000..376f05f1 --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_document.gd @@ -0,0 +1,35 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends XMLNode +class_name XMLDocument + +@export var root:XMLElement + +func format_document(indent:String = "")->String: + return root.format_document_recursive("", indent) if root else "" + +func format_document_recursive(cur_indent:String = "", indent_increment:String = "")->String: + assert(false, "Call to_string()") + return "" diff --git a/addons/cyclops_level_builder/util/xml/XML_document.gd.uid b/addons/cyclops_level_builder/util/xml/XML_document.gd.uid new file mode 100644 index 00000000..9ef5dd11 --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_document.gd.uid @@ -0,0 +1 @@ +uid://b8mum3t57vc7p diff --git a/addons/cyclops_level_builder/util/xml/XML_element.gd b/addons/cyclops_level_builder/util/xml/XML_element.gd new file mode 100644 index 00000000..b2bce20a --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_element.gd @@ -0,0 +1,82 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends XMLNode +class_name XMLElement + +@export var name:String +@export var attributes:Array[XMLAttribute] +@export var children:Array[XMLNode] + +func _init(name:String = ""): + self.name = name + + +func format_document_recursive(cur_indent:String = "", indent_increment:String = " ")->String: + var result = cur_indent + "<" + name + for attr in attributes: + result += " " + attr.name + "=\"" + attr.value + "\"" + if children.is_empty(): + result += "/>" + else: + result += ">" + for child in children: + result += child.to_string_recursive(cur_indent + indent_increment, indent_increment) + result += "" + return result + + +func add_child(node:XMLNode): + children.append(node) + +func get_attribute(name:String)->XMLAttribute: + for attr in attributes: + if attr.name == name: + return attr + return null + +func get_attribute_value(name:String, default_value:String = "")->String: + for attr in attributes: + if attr.name == name: + return attr.value + return default_value + +func get_attribute_index(nane:String)->int: + for attr_idx in attributes.size(): + if attributes[attr_idx].name == name: + return attr_idx + return -1 + +func set_attribute(name:String, value:String): + var idx = get_attribute_index(name) + if idx != -1: + attributes[idx].value = value + else: + attributes.append(XMLAttribute.new(name, value)) + +#func set_attribute_bool(name:String, value:bool): + #set_attribute(name, str(value)) +# +#func set_attribute_int(name:String, value:int): + #set_attribute(name, str(value)) diff --git a/addons/cyclops_level_builder/util/xml/XML_element.gd.uid b/addons/cyclops_level_builder/util/xml/XML_element.gd.uid new file mode 100644 index 00000000..2646d1f4 --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_element.gd.uid @@ -0,0 +1 @@ +uid://jilooaouu8hb diff --git a/addons/cyclops_level_builder/util/xml/XML_node.gd b/addons/cyclops_level_builder/util/xml/XML_node.gd new file mode 100644 index 00000000..8f4ec170 --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_node.gd @@ -0,0 +1,29 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends Resource +class_name XMLNode + +func format_document_recursive(cur_indent:String = "", indent_increment:String = " ")->String: + return "" diff --git a/addons/cyclops_level_builder/util/xml/XML_node.gd.uid b/addons/cyclops_level_builder/util/xml/XML_node.gd.uid new file mode 100644 index 00000000..2b9e6684 --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_node.gd.uid @@ -0,0 +1 @@ +uid://dx1xvxg4slx3c diff --git a/addons/cyclops_level_builder/util/xml/XML_text.gd b/addons/cyclops_level_builder/util/xml/XML_text.gd new file mode 100644 index 00000000..1e2f1bb9 --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_text.gd @@ -0,0 +1,31 @@ +# MIT License +# +# Copyright (c) 2023 Mark McKay +# https://github.com/blackears/cyclopsLevelBuilder +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +@tool +extends XMLNode +class_name XMLText + +@export var value:String + +func format_document_recursive(cur_indent:String = "", indent_increment:String = " ")->String: + return value diff --git a/addons/cyclops_level_builder/util/xml/XML_text.gd.uid b/addons/cyclops_level_builder/util/xml/XML_text.gd.uid new file mode 100644 index 00000000..e6f2996a --- /dev/null +++ b/addons/cyclops_level_builder/util/xml/XML_text.gd.uid @@ -0,0 +1 @@ +uid://cwijh5w6genx3 diff --git a/project.godot b/project.godot index 784f657e..93e25332 100644 --- a/project.godot +++ b/project.godot @@ -48,6 +48,7 @@ DebugStats="res://Scenes/debug_stats.tscn" Dialogic="*res://addons/dialogic/Core/DialogicGameHandler.gd" GlobalState="*res://Scripts/GlobalState.cs" GodotGTweensContextNode="*res://GTweensGodot/Godot/Source/Contexts/GodotGTweensContextNode.cs" +CyclopsAutoload="*res://addons/cyclops_level_builder/cyclops_global_scene.tscn" [dialogic] @@ -155,7 +156,7 @@ movie_writer/movie_file="D:/Maddo/Recordings/Capture.avi" [editor_plugins] -enabled=PackedStringArray("res://addons/dialogic/plugin.cfg", "res://addons/godot_test_scene/plugin.cfg", "res://addons/resources_spreadsheet_view/plugin.cfg", "res://addons/scene_palette/plugin.cfg", "res://addons/smoothing/plugin.cfg") +enabled=PackedStringArray("res://addons/cyclops_level_builder/plugin.cfg", "res://addons/dialogic/plugin.cfg", "res://addons/godot_test_scene/plugin.cfg", "res://addons/resources_spreadsheet_view/plugin.cfg", "res://addons/scene_palette/plugin.cfg", "res://addons/smoothing/plugin.cfg") [global_group]