├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── addons └── quick_place │ ├── plugin.cfg │ ├── plugin.gd │ └── plugin.gd.uid ├── demo ├── materials │ ├── mat_demo_grounds.tres │ └── mat_demo_object.tres ├── models │ ├── demo_grounds.blend │ ├── demo_grounds.glb │ ├── demo_grounds.glb.import │ ├── demo_grounds.tscn │ ├── demo_object_chair.blend │ ├── demo_object_chair.glb │ ├── demo_object_chair.glb.import │ ├── demo_object_chair.tscn │ ├── demo_object_cube.blend │ ├── demo_object_cube.glb │ ├── demo_object_cube.glb.import │ ├── demo_object_cube.tscn │ ├── demo_object_multishape.blend │ ├── demo_object_multishape.blend1 │ ├── demo_object_multishape.glb │ ├── demo_object_multishape.glb.import │ ├── demo_object_multishape.tscn │ ├── demo_object_sphere.blend │ ├── demo_object_sphere.glb │ ├── demo_object_sphere.glb.import │ ├── demo_object_sphere.tscn │ ├── demo_object_tree.blend │ ├── demo_object_tree.blend1 │ ├── demo_object_tree.glb │ ├── demo_object_tree.glb.import │ └── demo_object_tree.tscn └── world.tscn ├── docs ├── demo.webm ├── icon.png ├── icon.png.import ├── icon.svg ├── icon.svg.import ├── screenshot.png └── screenshot.png.import ├── icon.svg ├── icon.svg.import └── project.godot /.gitattributes: -------------------------------------------------------------------------------- 1 | # Normalize EOL for all files that Git considers text files. 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Godot 4+ specific ignores 2 | .godot/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Laura Sofia Heimann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QuickPlace 2 | Quickly place packed scenes and optionally rotate towards faces and randomize its position 3 | 4 | ![Screenshot](docs/screenshot.png) 5 | 6 | ## Features 7 | - **Quickly place PackedScene's** 8 | - Start placement mode and select a Node3D to be used as a parent, then click in your 3D viewport to quickly place your PackedScene. 9 | - **Randomize rotation** 10 | - Randomize the rotation on all axis to quickly scatter objects like rocks 11 | - **Align to Face** 12 | - Align the bottom of the PackedScene to the normal of the face you clicked 13 | - **Random Aligned to Face** 14 | - First, align the bottom of the PackedScene to the normal of the face you clicked. Then, randomize the (local) Y-rotation. 15 | 16 | ## Installation 17 | 1. Download the latest release 18 | 2. Place the ``quick_place`` folder into your ``addons`` folder 19 | 3. Activate the addon 20 | 21 | ## Support 22 | Any version from 4.0 onwards should be compatible. The addon was created and tested with 4.2.2. 23 | 24 | ## Donations 25 | If you would like to support my open source projects, feel free to [drop me a coffee (or rather, an energy drink)](https://ko-fi.com/laurasofiaheimann) or check out my [release games](https://indiegesindel.itch.io) on itch. 26 | 27 | ## License 28 | This project is licensed under the MIT License. For more information, check out the included [LICENSE](LICENSE) file. -------------------------------------------------------------------------------- /addons/quick_place/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="QuickPlace" 4 | description="Quickly place packed scenes and optionally rotate towards faces and randomize its position" 5 | author="Laura Sofia Heimann" 6 | version="1.0.0" 7 | script="plugin.gd" 8 | -------------------------------------------------------------------------------- /addons/quick_place/plugin.gd: -------------------------------------------------------------------------------- 1 | @tool 2 | extends EditorPlugin 3 | 4 | var dock:Control 5 | var undo_redo:EditorUndoRedoManager = get_undo_redo() 6 | 7 | var setting_scene:PackedScene 8 | var setting_rotation:RotationType 9 | var setting_active:bool 10 | 11 | var start_stop_button:Button 12 | 13 | enum RotationType { 14 | ORIGINAL, 15 | RANDOM, 16 | ALIGNED_TO_FACE, 17 | RANDOM_ALIGNED_TO_FACE, 18 | } 19 | 20 | func _enter_tree()->void: 21 | # Add dock 22 | dock = create_settings_dock() 23 | add_control_to_dock(DOCK_SLOT_RIGHT_BL, dock) 24 | 25 | func _exit_tree()->void: 26 | # Remove dock 27 | remove_control_from_docks(dock) 28 | dock.free() 29 | 30 | func _handles(object:Object)->bool: 31 | return object is Node3D 32 | 33 | func _forward_3d_gui_input(viewport_camera:Camera3D, event:InputEvent)->int: 34 | if not (setting_active and setting_scene != null): 35 | return EditorPlugin.AFTER_GUI_INPUT_PASS 36 | if not (event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and event.pressed): 37 | return EditorPlugin.AFTER_GUI_INPUT_PASS 38 | 39 | # Raycast mouse 40 | var position_in_node:Vector2 = event.position 41 | var ray_space_state:PhysicsDirectSpaceState3D = viewport_camera.get_world_3d().direct_space_state 42 | var ray_origin:Vector3 = viewport_camera.project_ray_origin(position_in_node) 43 | var ray_end:Vector3 = ray_origin + viewport_camera.project_ray_normal(position_in_node) * 5000.0 44 | var ray_query := PhysicsRayQueryParameters3D.create(ray_origin, ray_end) 45 | ray_query.collide_with_areas = false 46 | var ray_result:Dictionary = ray_space_state.intersect_ray(ray_query) 47 | if not ray_result.has("position"): 48 | return EditorPlugin.AFTER_GUI_INPUT_PASS 49 | 50 | # Instantiate prefab 51 | var parent:Node = get_editor_interface().get_selection().get_selected_nodes()[0] 52 | var prefab:Node3D = setting_scene.instantiate() 53 | prefab.name = str(prefab.name, " #", parent.get_child_count()) 54 | 55 | # Place / Unplace 56 | undo_redo.create_action(str("Place ", setting_scene.resource_path)) 57 | undo_redo.add_do_method(self, &"place", prefab, parent, ray_result) 58 | undo_redo.add_undo_method(self, &"unplace", prefab, parent) 59 | undo_redo.add_do_reference(prefab) 60 | undo_redo.commit_action() 61 | 62 | return EditorPlugin.AFTER_GUI_INPUT_STOP 63 | 64 | func create_settings_dock()->PanelContainer: 65 | var root := PanelContainer.new() 66 | root.name = "QuickPlace Settings" 67 | 68 | var settings_list := VBoxContainer.new() 69 | settings_list.set_anchors_preset(Control.PRESET_FULL_RECT) 70 | root.add_child(settings_list) 71 | 72 | # SCENE 73 | var scene_picker := EditorResourcePicker.new() 74 | scene_picker.base_type = "PackedScene" 75 | var settings_item_scene:PanelContainer = create_settings_item("Scene", scene_picker) 76 | settings_list.add_child(settings_item_scene) 77 | scene_picker.connect("resource_changed", func(new_resource:PackedScene)->void: 78 | setting_scene = new_resource 79 | start_stop_button.disabled = new_resource == null) 80 | 81 | # ROTATION 82 | var rotation_select := OptionButton.new() 83 | for rotation_type in RotationType: 84 | rotation_select.add_item(rotation_type.capitalize(), RotationType.get(rotation_type)) 85 | rotation_select.connect("item_selected", func(index:int)->void: 86 | setting_rotation = index) 87 | var settings_item_rotation_select:PanelContainer = create_settings_item("Rotation", rotation_select) 88 | settings_list.add_child(settings_item_rotation_select) 89 | 90 | # START/STOP BUTTON 91 | start_stop_button = Button.new() 92 | start_stop_button.disabled = true 93 | start_stop_button.text = "Start" 94 | start_stop_button.toggle_mode = true 95 | settings_list.add_child(start_stop_button) 96 | start_stop_button.connect("toggled", func(is_active:bool)->void: 97 | setting_active = is_active 98 | start_stop_button.text = "Stop" if is_active else "Start") 99 | 100 | return root 101 | 102 | func create_settings_item(label:String, control:Control)->PanelContainer: 103 | var new_item_panel := PanelContainer.new() 104 | 105 | var new_item := HBoxContainer.new() 106 | new_item.set_anchors_preset(Control.PRESET_VCENTER_WIDE) 107 | new_item.size_flags_horizontal = Control.SIZE_EXPAND_FILL 108 | new_item_panel.add_child(new_item) 109 | 110 | var new_label := Label.new() 111 | new_label.text = label 112 | new_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL 113 | new_item.add_child(new_label) 114 | 115 | control.set_anchors_preset(Control.PRESET_VCENTER_WIDE) 116 | control.size_flags_horizontal = Control.SIZE_EXPAND_FILL 117 | new_item.add_child(control) 118 | 119 | return new_item_panel 120 | 121 | # https://www.reddit.com/r/godot/comments/f2fowu/comment/fhdkxz5/ 122 | # Adjusted to support 90° side angles 123 | func align_up(node_basis:Basis, normal:Vector3)->Basis: 124 | var result := Basis() 125 | var scale:Vector3 = node_basis.get_scale() 126 | 127 | # Check if normal is parallel to node_basis.z 128 | if abs(normal.dot(node_basis.z)) > 0.999: 129 | # Choose a different axis to avoid zero vector 130 | if abs(normal.dot(Vector3(1, 0, 0))) < 0.999: 131 | result.x = normal.cross(Vector3(1, 0, 0)) 132 | else: 133 | result.x = normal.cross(Vector3(0, 1, 0)) 134 | else: 135 | result.x = normal.cross(node_basis.z) 136 | 137 | result.y = normal 138 | result.z = result.x.cross(normal) 139 | 140 | result = result.orthonormalized() 141 | result.x *= scale.x 142 | result.y *= scale.y 143 | result.z *= scale.z 144 | 145 | return result 146 | 147 | func place(prefab:Node3D, parent:Node, ray_result:Dictionary)->void: 148 | # Spawn 149 | parent.add_child(prefab) 150 | prefab.set_owner(parent.get_tree().edited_scene_root) 151 | prefab.global_position = ray_result.position 152 | 153 | # Rotate 154 | match setting_rotation: 155 | RotationType.ALIGNED_TO_FACE, RotationType.RANDOM_ALIGNED_TO_FACE when ray_result.normal != null: 156 | # Align To Face 157 | prefab.global_transform.basis = align_up(prefab.global_transform.basis, ray_result.normal.normalized()) 158 | 159 | # Random Aligned To Face 160 | if setting_rotation == RotationType.RANDOM_ALIGNED_TO_FACE: 161 | var random_rotation:float = randf_range(0.0, 360.0) 162 | prefab.global_transform = prefab.global_transform.rotated_local(Vector3.UP, random_rotation) 163 | RotationType.RANDOM: 164 | # Random 165 | var random_rotation_x:float = randf_range(0, TAU) 166 | var random_rotation_y:float = randf_range(0, TAU) 167 | var random_rotation_z:float = randf_range(0, TAU) 168 | prefab.rotation = Vector3(random_rotation_x, random_rotation_y, random_rotation_z) 169 | 170 | func unplace(prefab:Node3D, parent:Node)->void: 171 | parent.remove_child(prefab) 172 | -------------------------------------------------------------------------------- /addons/quick_place/plugin.gd.uid: -------------------------------------------------------------------------------- 1 | uid://c0ykuu8m3cxlq 2 | -------------------------------------------------------------------------------- /demo/materials/mat_demo_grounds.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StandardMaterial3D" format=3 uid="uid://wg2oxm2b06wh"] 2 | 3 | [resource] 4 | resource_name = "Demo" 5 | cull_mode = 2 6 | albedo_color = Color(0.392043, 0.392043, 0.392043, 1) 7 | roughness = 0.5 8 | -------------------------------------------------------------------------------- /demo/materials/mat_demo_object.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="StandardMaterial3D" format=3 uid="uid://2qmywwner0js"] 2 | 3 | [resource] 4 | resource_name = "Material" 5 | cull_mode = 2 6 | albedo_color = Color(0.906332, 0.906332, 0.906332, 1) 7 | roughness = 0.5 8 | -------------------------------------------------------------------------------- /demo/models/demo_grounds.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_grounds.blend -------------------------------------------------------------------------------- /demo/models/demo_grounds.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_grounds.glb -------------------------------------------------------------------------------- /demo/models/demo_grounds.glb.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="scene" 4 | importer_version=1 5 | type="PackedScene" 6 | uid="uid://bmu86cnwby5sn" 7 | path="res://.godot/imported/demo_grounds.glb-8344d339b9b3679137553f6d22f6e619.scn" 8 | 9 | [deps] 10 | 11 | source_file="res://demo/models/demo_grounds.glb" 12 | dest_files=["res://.godot/imported/demo_grounds.glb-8344d339b9b3679137553f6d22f6e619.scn"] 13 | 14 | [params] 15 | 16 | nodes/root_type="" 17 | nodes/root_name="" 18 | nodes/apply_root_scale=true 19 | nodes/root_scale=5.0 20 | meshes/ensure_tangents=true 21 | meshes/generate_lods=true 22 | meshes/create_shadow_meshes=true 23 | meshes/light_baking=1 24 | meshes/lightmap_texel_size=0.2 25 | meshes/force_disable_compression=false 26 | skins/use_named_skins=true 27 | animation/import=true 28 | animation/fps=30 29 | animation/trimming=false 30 | animation/remove_immutable_tracks=true 31 | import_script/path="" 32 | _subresources={ 33 | "materials": { 34 | "Demo": { 35 | "use_external/enabled": true, 36 | "use_external/path": "res://demo/materials/mat_demo_grounds.tres" 37 | } 38 | }, 39 | "nodes": { 40 | "PATH:Elevation": { 41 | "generate/physics": true, 42 | "physics/shape_type": 2 43 | }, 44 | "PATH:Roundness": { 45 | "generate/physics": true, 46 | "physics/shape_type": 2 47 | }, 48 | "PATH:Slanted": { 49 | "generate/physics": true, 50 | "physics/shape_type": 2 51 | }, 52 | "PATH:Sphere": { 53 | "generate/physics": true, 54 | "physics/shape_type": 2 55 | }, 56 | "PATH:Uneven": { 57 | "generate/physics": true, 58 | "physics/shape_type": 2 59 | } 60 | } 61 | } 62 | gltf/naming_version=1 63 | gltf/embedded_image_handling=1 64 | -------------------------------------------------------------------------------- /demo/models/demo_grounds.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://ctr7sx5otsygk"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://bmu86cnwby5sn" path="res://demo/models/demo_grounds.glb" id="1_cepfi"] 4 | 5 | [node name="demo_grounds" instance=ExtResource("1_cepfi")] 6 | -------------------------------------------------------------------------------- /demo/models/demo_object_chair.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_chair.blend -------------------------------------------------------------------------------- /demo/models/demo_object_chair.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_chair.glb -------------------------------------------------------------------------------- /demo/models/demo_object_chair.glb.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="scene" 4 | importer_version=1 5 | type="PackedScene" 6 | uid="uid://bkhne30y0sddp" 7 | path="res://.godot/imported/demo_object_chair.glb-4626464ef1b8423c41b8f59297c58659.scn" 8 | 9 | [deps] 10 | 11 | source_file="res://demo/models/demo_object_chair.glb" 12 | dest_files=["res://.godot/imported/demo_object_chair.glb-4626464ef1b8423c41b8f59297c58659.scn"] 13 | 14 | [params] 15 | 16 | nodes/root_type="" 17 | nodes/root_name="" 18 | nodes/apply_root_scale=true 19 | nodes/root_scale=1.0 20 | meshes/ensure_tangents=true 21 | meshes/generate_lods=true 22 | meshes/create_shadow_meshes=true 23 | meshes/light_baking=1 24 | meshes/lightmap_texel_size=0.2 25 | meshes/force_disable_compression=false 26 | skins/use_named_skins=true 27 | animation/import=true 28 | animation/fps=30 29 | animation/trimming=false 30 | animation/remove_immutable_tracks=true 31 | import_script/path="" 32 | _subresources={ 33 | "materials": { 34 | "Material": { 35 | "use_external/enabled": true, 36 | "use_external/path": "res://demo/materials/mat_demo_object.tres" 37 | } 38 | }, 39 | "nodes": { 40 | "PATH:Cube": { 41 | "generate/physics": true, 42 | "physics/shape_type": 2 43 | } 44 | } 45 | } 46 | gltf/naming_version=1 47 | gltf/embedded_image_handling=1 48 | -------------------------------------------------------------------------------- /demo/models/demo_object_chair.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dt3acfy2hqtyx"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://bkhne30y0sddp" path="res://demo/models/demo_object_chair.glb" id="1_m5rw3"] 4 | 5 | [node name="demo_object_chair" instance=ExtResource("1_m5rw3")] 6 | -------------------------------------------------------------------------------- /demo/models/demo_object_cube.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_cube.blend -------------------------------------------------------------------------------- /demo/models/demo_object_cube.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_cube.glb -------------------------------------------------------------------------------- /demo/models/demo_object_cube.glb.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="scene" 4 | importer_version=1 5 | type="PackedScene" 6 | uid="uid://d6tpeqscuckp" 7 | path="res://.godot/imported/demo_object_cube.glb-f2cd5312a936712aedb37a6d05243866.scn" 8 | 9 | [deps] 10 | 11 | source_file="res://demo/models/demo_object_cube.glb" 12 | dest_files=["res://.godot/imported/demo_object_cube.glb-f2cd5312a936712aedb37a6d05243866.scn"] 13 | 14 | [params] 15 | 16 | nodes/root_type="" 17 | nodes/root_name="" 18 | nodes/apply_root_scale=true 19 | nodes/root_scale=1.0 20 | meshes/ensure_tangents=true 21 | meshes/generate_lods=true 22 | meshes/create_shadow_meshes=true 23 | meshes/light_baking=1 24 | meshes/lightmap_texel_size=0.2 25 | meshes/force_disable_compression=false 26 | skins/use_named_skins=true 27 | animation/import=true 28 | animation/fps=30 29 | animation/trimming=false 30 | animation/remove_immutable_tracks=true 31 | import_script/path="" 32 | _subresources={ 33 | "materials": { 34 | "Material": { 35 | "use_external/enabled": true, 36 | "use_external/path": "res://demo/materials/mat_demo_object.tres" 37 | } 38 | }, 39 | "nodes": { 40 | "PATH:Cube": { 41 | "generate/physics": true, 42 | "physics/shape_type": 2 43 | } 44 | } 45 | } 46 | gltf/naming_version=1 47 | gltf/embedded_image_handling=1 48 | -------------------------------------------------------------------------------- /demo/models/demo_object_cube.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://dtpp8mcwggdbl"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://d6tpeqscuckp" path="res://demo/models/demo_object_cube.glb" id="1_7gunh"] 4 | 5 | [node name="demo_object_cube" instance=ExtResource("1_7gunh")] 6 | -------------------------------------------------------------------------------- /demo/models/demo_object_multishape.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_multishape.blend -------------------------------------------------------------------------------- /demo/models/demo_object_multishape.blend1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_multishape.blend1 -------------------------------------------------------------------------------- /demo/models/demo_object_multishape.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_multishape.glb -------------------------------------------------------------------------------- /demo/models/demo_object_multishape.glb.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="scene" 4 | importer_version=1 5 | type="PackedScene" 6 | uid="uid://1mm5ctl4alef" 7 | path="res://.godot/imported/demo_object_multishape.glb-8cbabae5752d9b4e6295cbfd3184aed6.scn" 8 | 9 | [deps] 10 | 11 | source_file="res://demo/models/demo_object_multishape.glb" 12 | dest_files=["res://.godot/imported/demo_object_multishape.glb-8cbabae5752d9b4e6295cbfd3184aed6.scn"] 13 | 14 | [params] 15 | 16 | nodes/root_type="" 17 | nodes/root_name="" 18 | nodes/apply_root_scale=true 19 | nodes/root_scale=1.0 20 | meshes/ensure_tangents=true 21 | meshes/generate_lods=true 22 | meshes/create_shadow_meshes=true 23 | meshes/light_baking=1 24 | meshes/lightmap_texel_size=0.2 25 | meshes/force_disable_compression=false 26 | skins/use_named_skins=true 27 | animation/import=true 28 | animation/fps=30 29 | animation/trimming=false 30 | animation/remove_immutable_tracks=true 31 | import_script/path="" 32 | _subresources={ 33 | "materials": { 34 | "Material": { 35 | "use_external/enabled": true, 36 | "use_external/path": "res://demo/materials/mat_demo_object.tres" 37 | } 38 | }, 39 | "nodes": { 40 | "PATH:Cube": { 41 | "generate/physics": true, 42 | "physics/shape_type": 2 43 | }, 44 | "PATH:Cube_001": { 45 | "generate/physics": true, 46 | "physics/shape_type": 2 47 | }, 48 | "PATH:Cube_002": { 49 | "generate/physics": true, 50 | "physics/shape_type": 2 51 | } 52 | } 53 | } 54 | gltf/naming_version=1 55 | gltf/embedded_image_handling=1 56 | -------------------------------------------------------------------------------- /demo/models/demo_object_multishape.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://ltprdponfikg"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://1mm5ctl4alef" path="res://demo/models/demo_object_multishape.glb" id="1_0ofw7"] 4 | 5 | [node name="demo_object_multishape" instance=ExtResource("1_0ofw7")] 6 | -------------------------------------------------------------------------------- /demo/models/demo_object_sphere.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_sphere.blend -------------------------------------------------------------------------------- /demo/models/demo_object_sphere.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_sphere.glb -------------------------------------------------------------------------------- /demo/models/demo_object_sphere.glb.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="scene" 4 | importer_version=1 5 | type="PackedScene" 6 | uid="uid://da0hc6x1x7i23" 7 | path="res://.godot/imported/demo_object_sphere.glb-baad5c6c2dd3cd7b6c1976d756271531.scn" 8 | 9 | [deps] 10 | 11 | source_file="res://demo/models/demo_object_sphere.glb" 12 | dest_files=["res://.godot/imported/demo_object_sphere.glb-baad5c6c2dd3cd7b6c1976d756271531.scn"] 13 | 14 | [params] 15 | 16 | nodes/root_type="" 17 | nodes/root_name="" 18 | nodes/apply_root_scale=true 19 | nodes/root_scale=1.0 20 | meshes/ensure_tangents=true 21 | meshes/generate_lods=true 22 | meshes/create_shadow_meshes=true 23 | meshes/light_baking=1 24 | meshes/lightmap_texel_size=0.2 25 | meshes/force_disable_compression=false 26 | skins/use_named_skins=true 27 | animation/import=true 28 | animation/fps=30 29 | animation/trimming=false 30 | animation/remove_immutable_tracks=true 31 | import_script/path="" 32 | _subresources={ 33 | "materials": { 34 | "Material": { 35 | "use_external/enabled": true, 36 | "use_external/path": "res://demo/materials/mat_demo_object.tres" 37 | } 38 | }, 39 | "nodes": { 40 | "PATH:Sphere": { 41 | "generate/physics": true, 42 | "physics/shape_type": 2 43 | } 44 | } 45 | } 46 | gltf/naming_version=1 47 | gltf/embedded_image_handling=1 48 | -------------------------------------------------------------------------------- /demo/models/demo_object_sphere.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://duxki0x0s8jd2"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://da0hc6x1x7i23" path="res://demo/models/demo_object_sphere.glb" id="1_ljudk"] 4 | 5 | [node name="demo_object_sphere" instance=ExtResource("1_ljudk")] 6 | -------------------------------------------------------------------------------- /demo/models/demo_object_tree.blend: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_tree.blend -------------------------------------------------------------------------------- /demo/models/demo_object_tree.blend1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_tree.blend1 -------------------------------------------------------------------------------- /demo/models/demo_object_tree.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/demo/models/demo_object_tree.glb -------------------------------------------------------------------------------- /demo/models/demo_object_tree.glb.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="scene" 4 | importer_version=1 5 | type="PackedScene" 6 | uid="uid://bqsgn5ky4qi1y" 7 | path="res://.godot/imported/demo_object_tree.glb-f7bf2b10e8ed14415851040601ebd42b.scn" 8 | 9 | [deps] 10 | 11 | source_file="res://demo/models/demo_object_tree.glb" 12 | dest_files=["res://.godot/imported/demo_object_tree.glb-f7bf2b10e8ed14415851040601ebd42b.scn"] 13 | 14 | [params] 15 | 16 | nodes/root_type="" 17 | nodes/root_name="" 18 | nodes/apply_root_scale=true 19 | nodes/root_scale=1.0 20 | meshes/ensure_tangents=true 21 | meshes/generate_lods=true 22 | meshes/create_shadow_meshes=true 23 | meshes/light_baking=1 24 | meshes/lightmap_texel_size=0.2 25 | meshes/force_disable_compression=false 26 | skins/use_named_skins=true 27 | animation/import=true 28 | animation/fps=30 29 | animation/trimming=false 30 | animation/remove_immutable_tracks=true 31 | import_script/path="" 32 | _subresources={ 33 | "materials": { 34 | "Material": { 35 | "use_external/enabled": true, 36 | "use_external/path": "res://demo/materials/mat_demo_object.tres" 37 | } 38 | }, 39 | "nodes": { 40 | "PATH:Cylinder": { 41 | "generate/physics": true, 42 | "physics/shape_type": 2 43 | } 44 | } 45 | } 46 | gltf/naming_version=1 47 | gltf/embedded_image_handling=1 48 | -------------------------------------------------------------------------------- /demo/models/demo_object_tree.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=3 uid="uid://ctih8b88r2jb8"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://bqsgn5ky4qi1y" path="res://demo/models/demo_object_tree.glb" id="1_p82h6"] 4 | 5 | [node name="demo_object_tree" instance=ExtResource("1_p82h6")] 6 | -------------------------------------------------------------------------------- /demo/world.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=3 uid="uid://cjpigp1c7y5c7"] 2 | 3 | [ext_resource type="PackedScene" uid="uid://ctr7sx5otsygk" path="res://demo/models/demo_grounds.tscn" id="1_50jbj"] 4 | 5 | [sub_resource type="Environment" id="Environment_titps"] 6 | background_mode = 1 7 | background_color = Color(0.817521, 0.817521, 0.817521, 1) 8 | 9 | [node name="World" type="Node3D"] 10 | 11 | [node name="WorldEnvironment" type="WorldEnvironment" parent="."] 12 | environment = SubResource("Environment_titps") 13 | 14 | [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] 15 | transform = Transform3D(0.258819, -0.683013, 0.683013, 0, 0.707107, 0.707107, -0.965926, -0.183013, 0.183013, 0, 23, 0) 16 | shadow_enabled = true 17 | 18 | [node name="Camera3D" type="Camera3D" parent="."] 19 | transform = Transform3D(0.939693, -0.116978, 0.321394, 0, 0.939693, 0.34202, -0.34202, -0.321394, 0.883022, 15.51, 13.84, 21.585) 20 | current = true 21 | 22 | [node name="demo_grounds" parent="." instance=ExtResource("1_50jbj")] 23 | 24 | [node name="objects" type="Node3D" parent="."] 25 | -------------------------------------------------------------------------------- /docs/demo.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/docs/demo.webm -------------------------------------------------------------------------------- /docs/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/docs/icon.png -------------------------------------------------------------------------------- /docs/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://dwof00pti2owc" 6 | path="res://.godot/imported/icon.png-be38bcc53a5f19f28a8c043cf1cbb790.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://docs/icon.png" 14 | dest_files=["res://.godot/imported/icon.png-be38bcc53a5f19f28a8c043cf1cbb790.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /docs/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /docs/icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://cdadamvd8khln" 6 | path="res://.godot/imported/icon.svg-d74203da674a59f31ae118bcc76df45e.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://docs/icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-d74203da674a59f31ae118bcc76df45e.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /docs/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LauraWebdev/Godot4-QuickPlace/4944ddc6f0943d7ed5304cd80f7c9af493f7a16d/docs/screenshot.png -------------------------------------------------------------------------------- /docs/screenshot.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://bakifnp77uta5" 6 | path="res://.godot/imported/screenshot.png-5c854034f77817cfff9777cb4fcabae4.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://docs/screenshot.png" 14 | dest_files=["res://.godot/imported/screenshot.png-5c854034f77817cfff9777cb4fcabae4.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | -------------------------------------------------------------------------------- /icon.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="CompressedTexture2D" 5 | uid="uid://xxig72v206oh" 6 | path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" 7 | metadata={ 8 | "vram_texture": false 9 | } 10 | 11 | [deps] 12 | 13 | source_file="res://icon.svg" 14 | dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] 15 | 16 | [params] 17 | 18 | compress/mode=0 19 | compress/high_quality=false 20 | compress/lossy_quality=0.7 21 | compress/hdr_compression=1 22 | compress/normal_map=0 23 | compress/channel_pack=0 24 | mipmaps/generate=false 25 | mipmaps/limit=-1 26 | roughness/mode=0 27 | roughness/src_normal="" 28 | process/fix_alpha_border=true 29 | process/premult_alpha=false 30 | process/normal_map_invert_y=false 31 | process/hdr_as_srgb=false 32 | process/hdr_clamp_exposure=false 33 | process/size_limit=0 34 | detect_3d/compress_to=1 35 | svg/scale=1.0 36 | editor/scale_with_editor_scale=false 37 | editor/convert_colors_with_editor_theme=false 38 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=5 10 | 11 | [application] 12 | 13 | config/name="Addon_QuickPlace" 14 | run/main_scene="res://demo/world.tscn" 15 | config/features=PackedStringArray("4.2", "Forward Plus") 16 | config/icon="res://icon.svg" 17 | 18 | [dotnet] 19 | 20 | project/assembly_name="Addon_QuickPlace" 21 | 22 | [editor_plugins] 23 | 24 | enabled=PackedStringArray("res://addons/quick_place/plugin.cfg") 25 | --------------------------------------------------------------------------------