Create a Blender Add-on for your Simplygon pipeline
Written by Jesper Tingvall, Product Expert, Simplygon
Disclaimer: The code in this post is written using version 9.1.36100 of Simplygon and Blender 2.93.5. If you encounter this post at a later stage, some of the API calls might have changed. However, the core concepts should still remain valid.
Introduction
In this post we will take the script created in A simple reduction script in Blender and turn it into a simple Blender Add-on with a basic user interface. That allows us to easily share it and makes it easy to use for non-programmers.
Prerequisites
This example will use the Simplygon integration in Blender, but the same concepts can be applied to all other integrations of the Simplygon API.
Solution
The solution is to create a Python script which adds a new operator to Blender - reduce and export.
Reduce mesh
The reduction part of the script is straight from A simple reduction script in Blender. It reduces the selected object to specified triangle ratio.
def reduce_selection(self, sg, ratio):
file_path = 'c:/Temp/_intermediate.glb'
bpy.ops.export_scene.gltf(filepath = file_path, use_selection=True)
pipeline = sg.CreateReductionPipeline()
pipeline.GetReductionSettings().SetReductionTargetTriangleRatio(ratio)
pipeline.RunSceneFromFile(file_path, file_path, Simplygon.EPipelineRunMode_RunInThisProcess)
bpy.ops.import_scene.gltf(filepath=file_path)
os.remove(file_path)
Export from Blender
After reducing it is time to export our mesh. This will be done via Blenders export_scene function. Export settings depends on which engine that is targeted.
def export_to_path(self, export_path):
# Export result from Blender. Settings for Unity.
bpy.ops.export_scene.fbx(filepath=export_path, check_existing=False,
use_selection=True,
object_types={'ARMATURE', 'EMPTY', 'MESH', 'OTHER'},
apply_unit_scale=True, apply_scale_options='FBX_SCALE_ALL',
path_mode='COPY', embed_textures=False, axis_forward='-Y', axis_up='Z')
# Clean up optimized objects from Blender
bpy.ops.object.delete(use_global=False, confirm=False)
Operator
We can capsulate the reduction and export function into a Blender operator. That allows us to showcase a popup box where the user can specify settings. In our example we just have two; export path and how much it should be reduced.
The execute
method contains the code which does the processing.
class ReduceAndExport(bpy.types.Operator):
"""Simplygon reduce and export selected objects as fbx"""
bl_idname = "object.reduce_and_export"
bl_label = "Reduce and export"
bl_options = {'REGISTER'}
reduction: bpy.props.FloatProperty(default=50, max=100, min=0,subtype='PERCENTAGE')
path: bpy.props.StringProperty(default="C:\\Temp\\Exported.fbx")
@classmethod
def poll(cls, context):
return True
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
row = self.layout
row.label(text="Simplygon reduce selected meshes and export.")
row.prop(self, "path", text="Export path")
row.prop(self, "reduction", text="Reduction")
def execute(self, context):
reduce = self.reduction/100
self.report({'INFO'}, 'Reduction of %f' % reduce)
sg = simplygon_loader.init_simplygon()
self.reduce_selection(sg, reduce)
self.export_to_path(self.path)
sg = None
return {'FINISHED'}
We also need a function to show the operator popup window.
def show_reduce_and_export_popup(self, context):
self.layout.operator(ReduceAndExport.bl_idname)
Add-on
Make the script easy to share we are going to package our script as a Blender Add-on. First we need to add meta information.
bl_info = {
"name": "Simplygon reduce and export",
"description": "Simplygon reduce and export selected objects as fbx.",
"version": (1, 0),
"location": "View3D > Object",
"blender": (2, 93, 0),
"category": "Import-Export",
}
We also need to register, and unregister, our new operation as well as adding it to the Object menu.
def register():
bpy.utils.register_class(ReduceAndExport)
bpy.types.VIEW3D_MT_object.append(show_reduce_and_export_popup)
def unregister():
bpy.utils.unregister_class(ReduceAndExport)
bpy.types.VIEW3D_MT_object.remove(show_reduce_and_export_popup)
After that been added the add-on can be installed as a Blender Add-on.
Result
The result is a Blender add-on running a simple mesh reduction. The functionality is accessible via Blenders user interface and it can easily be shared around and installed.
The script could be very easy extended with more options and stop conditions. It would also be possible to change the pipeline into something else, for example remeshing.
Complete script
The resulting script can be found below.
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT license.
bl_info = {
"name": "Simplygon reduce and export",
"description": "Simplygon reduce and export selected objects as fbx.",
"version": (1, 0),
"location": "View3D > Object",
"blender": (2, 93, 0),
"category": "Import-Export",
}
import os
import bpy
from simplygon import simplygon_loader
from simplygon import Simplygon
class ReduceAndExport(bpy.types.Operator):
"""Simplygon reduce and export selected objects as fbx"""
bl_idname = "object.reduce_and_export"
bl_label = "Reduce and export"
bl_options = {'REGISTER'}
reduction: bpy.props.FloatProperty(default=50, max=100, min=0,subtype='PERCENTAGE')
path: bpy.props.StringProperty(default="C:\\Temp\\Exported.fbx")
@classmethod
def poll(cls, context):
return True
def invoke(self, context, event):
return context.window_manager.invoke_props_dialog(self)
def draw(self, context):
row = self.layout
row.label(text="Simplygon reduce selected meshes and export.")
row.prop(self, "path", text="Export path")
row.prop(self, "reduction", text="Reduction")
def execute(self, context):
reduce = self.reduction/100
self.report({'INFO'}, 'Reduction of %f' % reduce)
sg = simplygon_loader.init_simplygon()
self.reduce_selection(sg, reduce)
self.export_to_path(self.path)
sg = None
return {'FINISHED'}
def reduce_selection(self, sg, ratio):
file_path = 'c:/Temp/_intermediate.glb'
bpy.ops.export_scene.gltf(filepath = file_path, use_selection=True)
pipeline = sg.CreateReductionPipeline()
pipeline.GetReductionSettings().SetReductionTargetTriangleRatio(ratio)
pipeline.RunSceneFromFile(file_path, file_path, Simplygon.EPipelineRunMode_RunInThisProcess)
bpy.ops.import_scene.gltf(filepath=file_path)
os.remove(file_path)
def export_to_path(self, export_path):
# Export result from Blender. Settings for Unity.
bpy.ops.export_scene.fbx(filepath=export_path, check_existing=False,
use_selection=True,
object_types={'ARMATURE', 'EMPTY', 'MESH', 'OTHER'},
apply_unit_scale=True, apply_scale_options='FBX_SCALE_ALL',
path_mode='COPY', embed_textures=False, axis_forward='-Y', axis_up='Z')
# Clean up optimized objects from Blender
bpy.ops.object.delete(use_global=False, confirm=False)
def show_reduce_and_export_popup(self, context):
self.layout.operator(ReduceAndExport.bl_idname)
def register():
bpy.utils.register_class(ReduceAndExport)
bpy.types.VIEW3D_MT_object.append(show_reduce_and_export_popup) # Adds the new operator to an existing menu.
def unregister():
bpy.utils.unregister_class(ReduceAndExport)
bpy.types.VIEW3D_MT_object.remove(show_reduce_and_export_popup)
if __name__ == "__main__":
register()