Skip to content

Commit

Permalink
structured folders for more ordered code
Browse files Browse the repository at this point in the history
  • Loading branch information
marco-ambrosio committed Apr 8, 2023
1 parent d007ce0 commit e66f5d2
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 168 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*.zip

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
23 changes: 23 additions & 0 deletions ExportGazeboModel/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
bl_info = {
"name": "Export Gazebo Model",
"version": (0, 1, 0),
"blender": (3, 3, 0),
"category": "Import-Export",
}

import bpy
from .export_gazebo_model_addon import ExportGazeboModel

def menu_func_export(self, context):
self.layout.operator(
ExportGazeboModel.bl_idname, text="Gazebo Model (.sdf, .obj)"
)

def register():
bpy.utils.register_class(ExportGazeboModel)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)


def unregister():
bpy.utils.unregister_class(ExportGazeboModel)
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
250 changes: 82 additions & 168 deletions ExportGazeboModel/export_gazebo_model_addon.py
Original file line number Diff line number Diff line change
@@ -1,223 +1,137 @@
bl_info = {
"name": "Export Gazebo Model",
"blender": (3, 3, 0),
"category": "Import-Export",
}


import os
import shutil
from glob import glob
from string import Template
import string

import bpy
from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
from bpy.types import Operator

from .templates.sdf_template import SdfTemplate
from .templates.config_template import ConfigTemplate

class ConfigTemplate:

template = Template(
'''\
<?xml version="1.0" ?>
<model>
<name>${model_name}</name>
<version>1.0</version>
<sdf version="1.6">model.sdf</sdf>
<author>
<name>${author_name}</name>
<email>${author_email}</email>
</author>
<description></description>
</model>\
''')


class SdfTemplate:

template = Template(
'''\
<?xml version='1.0'?>
<sdf version="1.6">
<model name="${model_name}">
<link name='link'>
<pose>0 0 0 0 0 0</pose>
<gravity>1</gravity>
<self_collide>0</self_collide>
<kinematic>0</kinematic>
<enable_wind>0</enable_wind>
<visual name='visual'>
<pose>0 0 0 0 0 0</pose>
<geometry>
<mesh>
<uri>${mesh_path}</uri>
</mesh>
</geometry>
<transparency>0</transparency>
<cast_shadows>1</cast_shadows>
</visual>
<collision name='collision'>
<laser_retro>0</laser_retro>
<max_contacts>10</max_contacts>
<pose>0 0 0 0 0 0</pose>
<geometry>
<mesh>
<uri>${mesh_path}</uri>
<scale>1 1 1</scale>
</mesh>
</geometry>
</collision>
</link>
<static>1</static>
<allow_auto_disable>1</allow_auto_disable>
</model>
</sdf>\
''')

class GazeboModel:

def export(self, export_name, overwrite):
''' Execute all the operations to export a model for Gazebo 11 '''

self.base_path = bpy.path.abspath('//')

class ExportGazeboModel(Operator, ExportHelper):
bl_idname = "export_gazebo_model.data"
bl_label = "Export Gazebo Model"

filename_ext = ""

filter_glob: StringProperty(
default="*",
options={"HIDDEN"},
maxlen=255,
)



def execute(self, context):
"""Execute all the operations to export a model for Gazebo 11"""

self.base_path = bpy.path.abspath("//")
self.model_name = bpy.path.basename(bpy.context.blend_data.filepath)[:-6]
self.export_name = bpy.path.basename(export_name)
if not overwrite:
''' do something to avoid overwriting an already exported model '''
self.export_name = bpy.path.basename(self.filepath)

if self.check_existing:
"""do something to avoid overwriting an already exported model"""
pass

self.create_folders()
self.export_meshes()
self.create_sdf()
return {'FINISHED'}

return {"FINISHED"}



def create_folders(self):
''' Create the folder structure and save paths into class variables '''

self.export_folder = os.path.join(
self.base_path, self.export_name)

self.meshes_folder = os.path.join(
self.export_folder, 'meshes')

"""Create the folder structure and save paths into class variables"""

self.export_folder = os.path.join(self.base_path, self.export_name)

self.meshes_folder = os.path.join(self.export_folder, "meshes")

os.makedirs(self.meshes_folder, exist_ok=True)



def export_meshes(self):
''' Export obj and textures '''

filepath = os.path.join(
self.meshes_folder, self.model_name + '.obj')

"""Export obj and textures"""

filepath = os.path.join(self.meshes_folder, self.model_name + ".obj")

# Export mesh as OBJ
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
bpy.ops.object.origin_set(type="ORIGIN_CURSOR")
bpy.ops.export_scene.obj(
filepath=filepath,
check_existing=True,
use_mesh_modifiers=True,
use_normals=True,
use_uvs=True,
use_materials=True,
path_mode='STRIP',
axis_forward='X',
axis_up='Z')

path_mode="STRIP",
axis_forward="X",
axis_up="Z",
)

# Export textures files
unpacked = False
for img in bpy.data.images:
if img.source == 'FILE':
name = img.name.rstrip(string.digits + '.')
if img.source == "FILE":
name = img.name.rstrip(string.digits + ".")
# if texture files are packed into the blend file
# unpack them temporarily and pack them again
if img.packed_file is not None:
unpacked = True
img.unpack()
img.pack()

shutil.copy2(
os.path.join(bpy.path.abspath('//textures'), name),
os.path.join(self.meshes_folder, name))
os.path.join(bpy.path.abspath("//textures"), name),
os.path.join(self.meshes_folder, name),
)
else:
shutil.copy2(
bpy.path.abspath(img.filepath),
os.path.join(self.meshes_folder, name))
os.path.join(self.meshes_folder, name),
)

# clean unpacked textures
if unpacked:
shutil.rmtree(bpy.path.abspath('//textures'), ignore_errors=False)

shutil.rmtree(bpy.path.abspath("//textures"), ignore_errors=False)



def create_sdf(self):

with open(os.path.join(
self.export_folder, 'model.sdf'), 'w') as f:

f.write(SdfTemplate().template.substitute({
"model_name": self.model_name,
"mesh_path": f"model://{self.export_name}/meshes/{self.model_name+'.obj'}",
}))


with open(os.path.join(
self.export_folder, 'model.config'), 'w') as f:

f.write(ConfigTemplate().template.substitute({
"model_name": self.model_name,
"author_name": "TODO",
"author_email": "TODO@TODO.now"
}))


class ExportGazeboModel(Operator, ExportHelper):

bl_idname = 'export_gazebo_model.data'
bl_label = "Export Gazebo Model"

filename_ext = ''

filter_glob: StringProperty(
default='*',
options={'HIDDEN'},
maxlen=255,
)

overwrite: BoolProperty(
name="Overwrite Existing",
description="Overwrite an existing model with the same name",
default=True,
)

def execute(self, context):
gazebo_model = GazeboModel()
return gazebo_model.export(self.filepath, self.overwrite)


def create_sdf(self):
''' Write the SDF and config files '''

with open(os.path.join(self.export_folder, "model.sdf"), "w") as f:
f.write(
SdfTemplate().template.substitute(
{
"model_name": self.model_name,
"mesh_path": f"model://{self.export_name}/meshes/{self.model_name+'.obj'}",
}
)
)

with open(os.path.join(self.export_folder, "model.config"), "w") as f:
f.write(
ConfigTemplate().template.substitute(
{
"model_name": self.model_name,
"author_name": "TODO",
"author_email": "TODO@TODO.now",
}
)
)

def menu_func_export(self, context):
self.layout.operator(ExportGazeboModel.bl_idname, text="Export Gazebo Model (.sdf, .obj)")


def register():
bpy.utils.register_class(ExportGazeboModel)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)


def unregister():
bpy.utils.unregister_class(ExportGazeboModel)
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)



if __name__ == "__main__":
register()

# register()
pass

# test call
# bpy.ops.export_gazebo_model.data('INVOKE_DEFAULT')

Empty file.
18 changes: 18 additions & 0 deletions ExportGazeboModel/templates/config_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from string import Template

class ConfigTemplate:
template = Template(
"""\
<?xml version="1.0" ?>
<model>
<name>${model_name}</name>
<version>1.0</version>
<sdf version="1.6">model.sdf</sdf>
<author>
<name>${author_name}</name>
<email>${author_email}</email>
</author>
<description></description>
</model>\
"""
)
Loading

0 comments on commit e66f5d2

Please sign in to comment.