Skip to content

Instantly share code, notes, and snippets.

@VojtaStruhar
Created July 21, 2022 16:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VojtaStruhar/6eca6c89d8b1197e4af9f2938dfaf35d to your computer and use it in GitHub Desktop.
Save VojtaStruhar/6eca6c89d8b1197e4af9f2938dfaf35d to your computer and use it in GitHub Desktop.
@tool
extends Node3D
# ------------------------------------------------------------------------------
# Script that turns a folder with meshes into MeshInstances in a scene.
# You can then export the scene into a MeshLibrary or further customize the
# meshes. You may want to add colliders :)
# Good for testing / prototyping / quick layout purposes.
# Written and tested in Godot 4 alpha 12
# ------------------------------------------------------------------------------
## Click to create MeshInstances from the folder contents.
@export var generate_mesh_library := false:
get: return generate_mesh_library
set(v): button_press()
## Click to delete all children from scene root.
@export var delete_all_chidren := false:
get: return delete_all_chidren
set(v): delete_children()
## Directory in which to look for meshes
@export_dir var mesh_directory
## Scale all meshes in a uniform way
@export_range(0.5, 5.0) var model_scale := 1.0
## Spacing between all the spawned MeshInstances. Purely for preview purposes,
## does not affect the final export.
@export var model_spacing := 2
## How many MeshInstances are in a row. Purely for preview purposes.
@export var per_row := 5
## Extension of the file in which to look for meshes.
@export_enum(".glb", ".gltf") var file_extension = 0
const suffixes = [".glb", ".gltf"]
func delete_children():
for child in get_children():
child.free()
func button_press():
create_mesh_library()
func create_mesh_library():
if mesh_directory == null:
return
delete_children()
var dir = Directory.new()
dir.open(mesh_directory)
dir.list_dir_begin()
var nodes_placed := 0
var ending = suffixes[file_extension]
while true:
var filename = dir.get_next()
if filename.is_empty():
return
if filename.ends_with(ending):
var packed = load(mesh_directory + "/" + filename)
var node = MeshInstance3D.new()
# This setup is kinda dependant on the way Kenney exports his stuff (.glb)
var imported_mesh = packed.instantiate().get_child(0).get_child(0).mesh.duplicate()
node.mesh = imported_mesh
# Construct a nice node name from a filename
node.name = filename.replace(ending, "").replace("_", " ").capitalize()
node.editor_description = "Instanced via ML_Factory.gd from '" + filename + "'"
_add_node(node)
if (per_row == 0):
node.position = Vector3i(nodes_placed * model_spacing, 0, 0)
else:
node.position = Vector3i((nodes_placed % per_row), 0, floor(nodes_placed / per_row)) * model_spacing
node.scale = Vector3(model_scale, model_scale, model_scale)
nodes_placed += 1
func _add_node(adding: Node) -> void:
var scene_root = get_tree().get_edited_scene_root()
if scene_root == null:
printerr("Failed to add node: No scene open")
return
scene_root.add_child(adding)
adding.set_owner(scene_root)
@VojtaStruhar
Copy link
Author

VojtaStruhar commented Jul 21, 2022

The checkboxes are "hacky" buttons, they just perform an action.

Option What it does
Generate Mesh Library Takes specified meshes and puts them into the scene as MeshInstance3Ds.
Delete All Children Removes all children nodes from the scene root
Mesh Directory Directory to take the meshes from
Model Spacing Space the models apart, doesn't affect later Mesh Library generation. Preview purposes.
Model Scale Scale all mesh instances by a uniform value
Per Row If >0, arranges mesh instances into a grid instead of a straight line. Preview purposes.
File Extension Which file extension to take as the mesh. Ignores .import files. Only supports GLTF and GLB since they are the best for Godot right now and you should use them.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment