I am trying to learn how to use the Python API for Blender, and have been wanting to see if I can make some kind of gpencil to mesh convert tool to see if i can make it do consistent conversions through a specific camera view.
I was able to come up with this so far based on what I could find across various searches:
import bpy
def get_3d_view_custom_context():
"""creates a 3d view custom context
Args:
None
Returns:
custom_context (dict): the dictionary creating a custom context
"""
my_camera = bpy.context.scene.cameraComboBox
print('my_camera', my_camera)
if my_camera == 'no_items':
return
custom_context = bpy.context.copy()
for area in bpy.context.screen.areas:
if area.type == "VIEW_3D":
for region in area.regions:
if region.type == "WINDOW":
custom_context["area"] = area
# view_3d = area.spaces.active
# area.spaces.active.local_view = bpy.context.scene.objects[my_camera]
# view_3d.camera_to_view()
custom_context["region"] = region
break
break
# bpy.context.scene.camera = bpy.data.objects[my_camera]
# areas3d = [area for area in bpy.context.window.screen.areas if area.type == 'VIEW_3D']
# bpy.ops.view3d.camera_to_view({'area':areas3d[0]})
print("Custom context use with VIEW_3D area and WINDOW region.")
custom_context['scene'].camera = bpy.context.scene.objects[my_camera]
# bpy.ops.view_3d.camera_to_view()
custom_context['space_data'].region_3d.view_perspective == 'CAMERA'
return custom_context
class ConvertToMeshFunc(bpy.types.Operator):
"""Convert gpencil to geo"""
bl_idname = "gpencil.blendlines_meshify"
bl_label = "Convert to Poly"
bl_context = "gpencil"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
obj = context.object
override = get_3d_view_custom_context()
bpy.ops.object.gpencil_modifier_apply(modifier="Noise")
obj_world_scale = obj.matrix_world.to_scale()
depth = 0.005 * obj.data.pixel_factor * min(obj_world_scale)
resolution = 12
bpy.ops.gpencil.convert(type="POLY",use_timing_data=False)
bpy.ops.object.convert(target="MESH")
active = context.view_layer.objects.active
selected = context.view_layer.objects.selected
# objs = [item for item in selected if item != active]
# converted = objs[0]
# print("{} converted to {}.".format(obj.name, converted.name))
return {"FINISHED"}
@classmethod
def poll(cls, context):
return context.mode in {"OBJECT"}
class GPencilToMesh(bpy.types.Operator):
"""Convert gpencil to mesh, cap the ends, cut out gpmask, add material/stroke attributes"""
bl_idname = "object.mesh_check"
bl_label = "GPencil to Mesh"
bl_context = "object"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
bpy.ops.gpencil.blendlines_meshify()
return {"FINISHED"}
@classmethod
def poll(cls, context):
return context.mode in {"OBJECT"}
class UpdateCamerasList(bpy.types.Operator):
bl_idname = "object.greasepencil_camsrefresh"
bl_label = "Refresh Cameras"
bl_context = "object"
bl_options = {"REGISTER", "UNDO"}
def execute(self, context):
cams_list = [ob for ob in bpy.context.scene.objects if ob.type == 'CAMERA']
cams_combo_items = []
if cams_list:
for idx, cam in enumerate(cams_list):
cams_combo_items.append((cam.name, cam.name, "", idx+1))
self.updateCameraDropdown(cams_combo_items)
print('cams_combo_items:', cams_combo_items)
return {'FINISHED'}
@classmethod
def updateCameraDropdown(cls, cItems=None):
if not cItems:
cItems = [
("no_items", "No items", "", 1),
]
# cItems = [(bpy.data.objects['Camera'], 'Camera', '', 1)]
default_selection = "no_items"
else:
default_selection = bpy.data.scenes["Scene"].camera.name
bpy.types.Scene.cameraComboBox = bpy.props.EnumProperty(
items=cItems,
name="Cameras",
description="Camera",
default=default_selection,
)
# print('get_3d_view_custom_context():', get_3d_view_custom_context())
# my_camera = bpy.context.scene.cameraComboBox
# bpy.context.scene.camera = bpy.data.objects[my_camera]
# areas3d = [area for area in bpy.context.window.screen.areas if area.type == 'VIEW_3D']
# bpy.ops.view3d.camera_to_view({'area':areas3d[0]})
get_3d_view_custom_context()
class VIEW3D_PT_greasepencil_mesh_test(bpy.types.Panel):
"""BlendLines Export UI Panel"""
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
bl_idname = "VIEW3D_PT_greasepencil_mesh_test"
bl_category = "GREASEPENCILTEST"
bl_label = "testing meshify for greasepencil"
def draw(self, context):
layout = self.layout
scene = bpy.context.scene
box = layout.box()
row = box.row()
row.operator(
"object.mesh_check",
text="Mesh Check",
icon="MESH_ICOSPHERE",
)
box1 = layout.box()
row1 = box1.row()
row1.label(text="Set Camera:")
row2 = box1.row()
row2.prop(scene, "cameraComboBox", text="")
row3 = box1.row()
row3.operator(
"object.greasepencil_camsrefresh",
text="Refresh Cameras",
)
# Registration
# =========================================================================
classes = (
ConvertToMeshFunc,
GPencilToMesh,
UpdateCamerasList,
VIEW3D_PT_greasepencil_mesh_test,
)
def register():
UpdateCamerasList.updateCameraDropdown()
for cls in classes:
bpy.utils.register_class(cls)
def unregister():
for cls in reversed(classes):
if cls.is_registered:
bpy.utils.unregister_class(cls)
del bpy.types.Scene.cameraComboBox
if __name__ == "__main__":
register()
this seems to just create a mesh based on the current viewport I am looking through which is great, but what I really want to do is pass a view from a specific camera somewhere in bpy.ops.gpencil.convert(type="POLY",use_timing_data=False)
, but when I pass the result of get_3d_view_custom_context()
this errors out.
I am still having troubles understanding what this “context” stuff is so I am pretty stuck as of now. Would someone be able to provide some insight as to how to make sure this mesh conversion ONLY WORKS from a specific camera view…?