Hi all, here’s a rather blunt script I’ve made to automatically generate files needed to go from throwing a .dae into a folder in your project, to being able to instantiate that model in your game with Lua.
Basic usage is like this: create a folder in your project main named objects. This will contain the script. Run the script once (I use python 3) and it will create the necessary folders. Otherwise within objects create a folder called data, and within that three folders called daes, gameobjects, and collections.
Export with your 3D editor the models for your game into the daes folder.
When you run the script again, it will generate the necessary .go, .collection, and .collectionfactory files. It will also generate text for a game object called factories containing all collection factories that you can paste into your main.collection, output to objects/all-factories.txt.
In your code, factories are then accessed via “factories#f.modelname”.
Note that it’s a very naive script and will only generate missing files, ie for new models you’ve added to the project, and it assumes the same material and texture for all of them. It would be easy enough to build a dictionary of models in your project and associate the materials and textures you want them to have, then generate the rest of the text files based on that. In theory that’s a purpose the “Model” type in defold could serve, but I found it was unnecessary as .go embeds all data.
If you start using 3D models you might run into two problems that bug me personally, working with Blender. The world position of your model on export either gets baked into the model, or imported from scene data by defold, so you need to clear transforms (or apply them) in order to control the correct origin on your object in defold. You also need to ensure your model only has one material applied, otherwise you’ll have missing faces if you only intend on applying one material in defold. This seems reasonable but if there’s a discrepancy between your model in your editor – for example, multi-material for baking textures, but only needing one textured material on export to engine – you’ll have to assign everything to the first material slot before export.
These two problems could be automated with a blender export script, which I’ll surely eventually write for myself to speed up iteration on my own projects, but for now just keep them in mind.
Here’s the simple file-generating script.
import os
material = "/main/materials/3d.material"
texture = "/main/images/ENVIRON.jpg"
gotext = '''
embedded_components {{
id: "model"
type: "model"
data: "mesh: \\"/main/objects/data/daes/{0}.dae\\"\\nmaterial: \\"{1}\\"\\ntextures: \\"{2}\\"\\n"
position {{
x: 0.0
y: 0.0
z: 0.0
}}
rotation {{
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}}
}}
'''
colltext = '''
name: "{0}"
instances {{
id: "{0}"
prototype: "/main/objects/data/gameobjects/{0}.go"
scale3 {{
x: 1.0
y: 1.0
z: 1.0
}}
}}
'''
facttext = '''
prototype: "/main/objects/data/collections/{0}.collection"
'''
facts_comp = '''
components {{
id: \\"f.{0}\\"
component: \\"/main/objects/{0}.collectionfactory\\"
position {{
x: 0.0
y: 0.0
z: 0.0
}}
rotation {{
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}}
}}
'''
facts_gotext = '''
embedded_instances {{
id: "factories"
data: "{0}"
scale3 {{
x: 1.0
y: 1.0
z: 1.0
}}
}}
'''
directories = ["./data", "./data/daes", "./data/gameobjects", "./data/collections"]
for directory in directories:
if not os.path.exists(directory):
os.makedirs(directory)
for f in os.listdir("./data/daes/"):
if f.endswith(".dae"):
fname = f.split(".")[0]
gopath = "./data/gameobjects/%s.go"%fname
collpath = "./data/collections/%s.collection"%fname
factpath = "./%s.collectionfactory"%fname
if not os.path.exists(gopath):
with open(gopath, 'w') as f:
text = gotext.format(fname, material, texture)
f.write(text)
if not os.path.exists(collpath):
with open(collpath, 'w') as f:
text = colltext.format(fname)
f.write(text)
if not os.path.exists(factpath):
with open(factpath, 'w') as f:
text = facttext.format(fname)
f.write(text)
all_factories_string = ""
for f in os.listdir("./"):
if f.endswith(".collectionfactory"):
fname = f.split(".")[0]
all_factories_string += facts_comp.format(fname).replace("\n", "\\n")
with open("./all_factories.txt", 'w') as f:
f.write(facts_gotext.format(all_factories_string))
Happy iterating!