Berikut ini hasil belajar membuat add-ons untuk Blender 3D. Add-ons ini untuk mengonversi obyek yang sedang aktif di Blender ke kode Python. Mungkin ini memudahkan ketika kita membuat add-ons atau otomatisasi obyek agar dapat bekerja lebih efektif dan efisien.
Untuk menambahkan add-ons ini sila unduh dari sini file phyton atau salin langsung dari kotak kode di bawah, perhatikan letak file hasil unduhan. Kemudian buka Aplikasi Blender (dianjurkan versi 4.3.0 atau lebih tinggi) > klik menu Edit > Preferences > Add-ons, klik tanda
di bawah tanda x > Install from disk... Arahkan ke folder hasil unduhan.
Untuk mengaksesnya, buka aplikasi Blender 3D > Export > Object to Python. Silakan simpan file dengan ekstensi dot py. Untuk mencoba sila buka Aktive Work Space bagian Scripting (biasa ada di tab paling kanan) > klik New dan salin hasil konversi dot py tadi di bagian layar kerja Scripting > klik tombol Run Script atau tekan Alt P.
Jika hasilnya sama persis dengan obyek sebelumnya artinya hasil konversi berhasil.
import bpy
import bmesh
import os
from bpy.types import Operator, Menu
from bpy_extras.io_utils import ExportHelper
from bpy.props import StringProperty, BoolProperty
import uuid
bl_info = {
"name": "Blender Object to Python Converter",
"author": "Rukim",
"version": (1, 0, 2),
"blender": (4, 3, 0),
"location": "File > Export > Object to Python",
"description": "Exports the active mesh object to a Python script that recreates the mesh, including transforms and optional UV maps",
"category": "Export",
"warning": "Requires Blender 4.3 or higher.",
"doc_url": "https://www.urip.info/2025/07/konversi-obyek-blender-to-python.html",
}
class OBJECT_OT_export_to_python(Operator, ExportHelper):
"""Export active mesh object to Python script"""
bl_idname = "export.object_to_python"
bl_label = "Object to Python"
bl_options = {'REGISTER', 'UNDO'}
# File picker properties
filename_ext = ".py"
filter_glob: StringProperty(
default="*.py",
options={'HIDDEN'},
maxlen=255,
)
# Export options
include_material: BoolProperty(
name="Include Material",
description="Include material properties in the Python script",
default=True,
)
include_uv: BoolProperty(
name="Include UV Map",
description="Include UV map data in the Python script",
default=False,
)
use_original_name: BoolProperty(
name="Use Original Object Name",
description="Use the original object name instead of a random UUID",
default=False,
)
def execute(self, context):
try:
output_path = self.filepath
# Cek kalau ada objek aktif
obj = context.active_object
if not obj or obj.type != 'MESH':
self.report({'ERROR'}, "No active mesh object selected")
return {'CANCELLED'}
# Cek kalau mesh punya data
mesh = obj.data
if len(mesh.vertices) == 0:
self.report({'ERROR'}, "Mesh has no vertices")
return {'CANCELLED'}
# Cek kalau path file valid
if not output_path.endswith('.py'):
output_path += '.py'
if not os.path.isdir(os.path.dirname(output_path)):
self.report({'ERROR'}, "Invalid output directory")
return {'CANCELLED'}
# Ambil data mesh
bm = bmesh.new()
bm.from_mesh(mesh)
vertices = [(v.co.x, v.co.y, v.co.z) for v in bm.verts]
edges = [(e.verts[0].index, e.verts[1].index) for e in bm.edges]
faces = [[v.index for v in f.verts] for f in bm.faces]
# Ambil UV map kalau dicentang
uv_data = None
if self.include_uv and mesh.uv_layers:
uv_layer = mesh.uv_layers.active
if uv_layer:
uv_data = []
for poly in mesh.polygons:
poly_uvs = []
for loop_index in poly.loop_indices:
uv = mesh.uv_layers.active.data[loop_index].uv
poly_uvs.append((uv.x, uv.y))
uv_data.append(poly_uvs)
bm.free()
# Ambil transformasi
location = obj.location[:]
rotation = obj.rotation_euler[:]
scale = obj.scale[:]
# Ambil material kalau dicentang
material_data = None
if self.include_material and mesh.materials:
mat = mesh.materials[0] # Ambil material pertama
if mat and mat.node_tree and mat.node_tree.nodes.get("Principled BSDF"):
bsdf = mat.node_tree.nodes["Principled BSDF"]
base_color = bsdf.inputs["Base Color"].default_value[:]
alpha = bsdf.inputs["Alpha"].default_value
material_data = {
'name': mat.name,
'base_color': base_color,
'alpha': alpha,
'blend_method': mat.blend_method
}
# Nama objek
obj_name = obj.name if self.use_original_name else f"Mesh_{str(uuid.uuid4())[:8]}"
# Buat kode Python
code = [
"import bpy",
"import bmesh",
"",
f"def create_mesh_{obj_name}():",
f" # Buat mesh baru",
f" mesh = bpy.data.meshes.new('{obj_name}_Mesh')",
f" obj = bpy.data.objects.new('{obj_name}', mesh)",
f" bpy.context.collection.objects.link(obj)",
"",
f" # Set transformasi",
f" obj.location = {location}",
f" obj.rotation_euler = {rotation}",
f" obj.scale = {scale}",
"",
f" # Setup bmesh",
f" bm = bmesh.new()",
"",
f" # Tambah vertices",
]
for i, vert in enumerate(vertices):
code.append(f" bm.verts.new({vert})")
code.append(" bm.verts.ensure_lookup_table()")
code.append("")
# Tambah edges
if edges:
code.append(f" # Tambah edges")
for edge in edges:
code.append(f" bm.edges.new((bm.verts[{edge[0]}], bm.verts[{edge[1]}]))")
code.append("")
# Tambah faces
if faces:
code.append(f" # Tambah faces")
for face in faces:
code.append(f" bm.faces.new([bm.verts[i] for i in {face}])")
code.append("")
# Tambah UV map kalau ada
if uv_data:
code.append(f" # Tambah UV map")
code.append(f" uv_layer = mesh.uv_layers.new(name='UVMap')")
for i, poly_uvs in enumerate(uv_data):
code.append(f" for j, uv in enumerate({poly_uvs}):")
code.append(f" uv_layer.data[mesh.polygons[{i}].loop_start + j].uv = uv")
code.append("")
code.append(f" # Update mesh")
code.append(f" bm.to_mesh(mesh)")
code.append(f" bm.free()")
code.append("")
# Tambah material kalau ada
if material_data:
code.append(f" # Tambah material")
code.append(f" mat = bpy.data.materials.new(name='{material_data['name']}')")
code.append(f" mat.use_nodes = True")
code.append(f" nodes = mat.node_tree.nodes")
code.append(f" nodes.clear()")
code.append(f" bsdf = nodes.new('ShaderNodeBsdfPrincipled')")
code.append(f" bsdf.inputs['Base Color'].default_value = {material_data['base_color']}")
code.append(f" bsdf.inputs['Alpha'].default_value = {material_data['alpha']}")
code.append(f" output = nodes.new('ShaderNodeOutputMaterial')")
code.append(f" mat.node_tree.links.new(bsdf.outputs['BSDF'], output.inputs['Surface'])")
code.append(f" mat.blend_method = '{material_data['blend_method']}'")
code.append(f" mesh.materials.append(mat)")
code.append("")
code.append(f" # Set shade smooth")
code.append(f" for f in mesh.polygons:")
code.append(f" f.use_smooth = True")
code.append("")
code.append(f"if __name__ == '__main__':")
code.append(f" create_mesh_{obj_name}()")
# Tulis ke file
with open(output_path, 'w', encoding='utf-8') as f:
f.write('\n'.join(code))
self.report({'INFO'}, f"Object '{obj.name}' exported to Python script: {output_path}")
return {'FINISHED'}
except Exception as e:
self.report({'ERROR'}, f"Failed to export object: {str(e)}")
return {'CANCELLED'}
def menu_func_export(self, context):
self.layout.operator(OBJECT_OT_export_to_python.bl_idname, text="Object to Python")
def register():
try:
bpy.utils.register_class(OBJECT_OT_export_to_python)
bpy.types.TOPBAR_MT_file_export.append(menu_func_export)
except Exception as e:
print(f"Failed to register addon: {str(e)}")
def unregister():
try:
bpy.utils.unregister_class(OBJECT_OT_export_to_python)
bpy.types.TOPBAR_MT_file_export.remove(menu_func_export)
except Exception as e:
print(f"Failed to unregister addon: {str(e)}")
if __name__ == "__main__":
register()
Gunakan secara bijak, jangan disebarkan untuk komersialisasi.
Tidak ada komentar:
Posting Komentar