mirror of
https://gitlab.com/ProcyonLotor/vrchat-template.git
synced 2026-08-25 18:53:53 +05:00
Future-proof implementation 2.0
This commit is contained in:
@@ -2,10 +2,13 @@ import os
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.props import StringProperty, BoolProperty, PointerProperty, IntProperty
|
_FUTURE = bpy.app.version >= (2, 80, 0)
|
||||||
from bpy.types import UIList, Operator, Panel, PropertyGroup, Context
|
from bpy.props import EnumProperty, StringProperty, BoolProperty, PointerProperty, IntProperty
|
||||||
|
from bpy.types import UIList, Operator, Panel, PropertyGroup, Context, Scene
|
||||||
from io_scene_fbx import ExportFBX
|
if _FUTURE:
|
||||||
|
from bpy.types import Collection as Group
|
||||||
|
else:
|
||||||
|
from bpy.types import Group as Group
|
||||||
|
|
||||||
|
|
||||||
def message_box(message: str, title: str = "Message", icon: str = 'INFO') -> None:
|
def message_box(message: str, title: str = "Message", icon: str = 'INFO') -> None:
|
||||||
@@ -18,7 +21,7 @@ def message_box(message: str, title: str = "Message", icon: str = 'INFO') -> Non
|
|||||||
def draw(self, context):
|
def draw(self, context):
|
||||||
col = self.layout.column(align=True)
|
col = self.layout.column(align=True)
|
||||||
for line in message.strip().split("\n"):
|
for line in message.strip().split("\n"):
|
||||||
col.label(line)
|
col.label(text=line)
|
||||||
bpy.context.window_manager.popup_menu(draw, title=title, icon=icon)
|
bpy.context.window_manager.popup_menu(draw, title=title, icon=icon)
|
||||||
|
|
||||||
|
|
||||||
@@ -37,9 +40,10 @@ def fbx_export(context: Context) -> None:
|
|||||||
"""
|
"""
|
||||||
print("[%s] Batch FBX export begin" % datetime.now())
|
print("[%s] Batch FBX export begin" % datetime.now())
|
||||||
|
|
||||||
rootpath = os.path.normpath(bpy.path.abspath(context.scene.fbx_export.export_dir))
|
rootpath = os.path.normpath(bpy.path.abspath(context.scene.fbx_export_dir))
|
||||||
|
groups = bpy.data.collections if _FUTURE else bpy.data.groups
|
||||||
|
|
||||||
for group in [g for g in bpy.data.groups if g.fbx_exportable]:
|
for group in [g for g in groups if g.fbx_exportable]:
|
||||||
filepath = os.path.join(rootpath, name_as_path(group.name))
|
filepath = os.path.join(rootpath, name_as_path(group.name))
|
||||||
basepath = os.path.dirname(filepath)
|
basepath = os.path.dirname(filepath)
|
||||||
|
|
||||||
@@ -60,7 +64,7 @@ def fbx_export(context: Context) -> None:
|
|||||||
global_scale=1.0,
|
global_scale=1.0,
|
||||||
axis_forward='-Z',
|
axis_forward='-Z',
|
||||||
axis_up='Y',
|
axis_up='Y',
|
||||||
object_types=context.scene.fbx_export.object_types,
|
object_types=context.scene.fbx_object_types,
|
||||||
use_mesh_modifiers=True,
|
use_mesh_modifiers=True,
|
||||||
mesh_smooth_type='OFF',
|
mesh_smooth_type='OFF',
|
||||||
use_mesh_edges=False,
|
use_mesh_edges=False,
|
||||||
@@ -81,22 +85,6 @@ def fbx_export(context: Context) -> None:
|
|||||||
print("\n[%s] Batch FBX export end." % datetime.now())
|
print("\n[%s] Batch FBX export end." % datetime.now())
|
||||||
|
|
||||||
|
|
||||||
class FBXExportProps(PropertyGroup):
|
|
||||||
export_dir = StringProperty(
|
|
||||||
name="FBX Export Dir",
|
|
||||||
description="FBX Export Directory",
|
|
||||||
subtype="DIR_PATH",
|
|
||||||
default="//../fbx/",
|
|
||||||
)
|
|
||||||
on_save = BoolProperty(
|
|
||||||
name="Export on save",
|
|
||||||
description="Export FBX on Blender file save",
|
|
||||||
default=False
|
|
||||||
)
|
|
||||||
object_types = ExportFBX.object_types
|
|
||||||
group_index = IntProperty(default=0)
|
|
||||||
|
|
||||||
|
|
||||||
class FBX_OT_ManualExport(Operator):
|
class FBX_OT_ManualExport(Operator):
|
||||||
bl_idname = "fbx.manual_export"
|
bl_idname = "fbx.manual_export"
|
||||||
bl_label = "Manual Export"
|
bl_label = "Manual Export"
|
||||||
@@ -133,29 +121,29 @@ class SCENE_PT_fbx_autoexport(Panel):
|
|||||||
col = layout.column()
|
col = layout.column()
|
||||||
|
|
||||||
sub = col.column(align=True)
|
sub = col.column(align=True)
|
||||||
sub.prop(scene.fbx_export, "on_save", icon='LOAD_FACTORY')
|
sub.prop(scene, "fbx_on_save", icon='FILE_REFRESH')
|
||||||
sub.operator(FBX_OT_ManualExport.bl_idname, icon="PASTEDOWN")
|
sub.operator(FBX_OT_ManualExport.bl_idname, icon="PASTEDOWN")
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
split = col.split()
|
split = col.split()
|
||||||
sub = split.column()
|
sub = split.column()
|
||||||
sub.label("Filter groups:")
|
sub.label(text="Filter groups:")
|
||||||
sub.template_list("FBX_UL_ExportItems", "", bpy.data, "groups", scene.fbx_export, "group_index", rows=5)
|
sub.template_list("FBX_UL_ExportItems", "", bpy.data, "collections" if _FUTURE else "groups", scene, "fbx_group_index", rows=5)
|
||||||
sub = split.column()
|
sub = split.column()
|
||||||
sub.label("Filter object types:")
|
sub.label(text="Filter object types:")
|
||||||
sub.prop(scene.fbx_export, "object_types")
|
sub.prop(scene, "fbx_object_types")
|
||||||
|
|
||||||
col.separator()
|
col.separator()
|
||||||
|
|
||||||
col.prop(scene.fbx_export, "export_dir")
|
col.prop(scene, "fbx_export_dir")
|
||||||
|
|
||||||
|
|
||||||
def on_save(*args, **kwargs) -> None:
|
def on_save(*args, **kwargs) -> None:
|
||||||
"""
|
"""
|
||||||
Runs when Blender file is being saved
|
Runs when Blender file is being saved
|
||||||
"""
|
"""
|
||||||
if not bpy.context.scene.fbx_export.on_save:
|
if not bpy.context.scene.fbx_on_save:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -165,7 +153,6 @@ def on_save(*args, **kwargs) -> None:
|
|||||||
|
|
||||||
|
|
||||||
classes = [
|
classes = [
|
||||||
FBXExportProps,
|
|
||||||
FBX_OT_ManualExport,
|
FBX_OT_ManualExport,
|
||||||
FBX_UL_ExportItems,
|
FBX_UL_ExportItems,
|
||||||
SCENE_PT_fbx_autoexport,
|
SCENE_PT_fbx_autoexport,
|
||||||
@@ -175,8 +162,33 @@ classes = [
|
|||||||
def register() -> None:
|
def register() -> None:
|
||||||
for cls in classes:
|
for cls in classes:
|
||||||
bpy.utils.register_class(cls)
|
bpy.utils.register_class(cls)
|
||||||
bpy.types.Scene.fbx_export = PointerProperty(type=FBXExportProps)
|
Scene.fbx_export_dir = StringProperty(
|
||||||
bpy.types.Group.fbx_exportable = BoolProperty(
|
name="FBX Export Dir",
|
||||||
|
description="FBX Export Directory",
|
||||||
|
subtype="DIR_PATH",
|
||||||
|
default="//../fbx/",
|
||||||
|
)
|
||||||
|
Scene.fbx_on_save = BoolProperty(
|
||||||
|
name="Export on save",
|
||||||
|
description="Export FBX on Blender file save",
|
||||||
|
default=False
|
||||||
|
)
|
||||||
|
Scene.fbx_object_types = EnumProperty(
|
||||||
|
name="Object Types",
|
||||||
|
options={'ENUM_FLAG'},
|
||||||
|
items=(
|
||||||
|
('EMPTY', "Empty", ""),
|
||||||
|
('CAMERA', "Camera", ""),
|
||||||
|
('LAMP', "Lamp", ""),
|
||||||
|
('ARMATURE', "Armature", "WARNING: not supported in dupli/group instances"),
|
||||||
|
('MESH', "Mesh", ""),
|
||||||
|
('OTHER', "Other", "Other geometry types, like curve, metaball, etc. (converted to meshes)"),
|
||||||
|
),
|
||||||
|
description="Which kind of object to export",
|
||||||
|
default={'EMPTY', 'CAMERA', 'LAMP', 'ARMATURE', 'MESH', 'OTHER'},
|
||||||
|
)
|
||||||
|
Scene.fbx_group_index = IntProperty(default=0)
|
||||||
|
Group.fbx_exportable = BoolProperty(
|
||||||
name="Export Group",
|
name="Export Group",
|
||||||
description="Mark group as FBX exportable",
|
description="Mark group as FBX exportable",
|
||||||
default=False
|
default=False
|
||||||
@@ -186,8 +198,11 @@ def register() -> None:
|
|||||||
|
|
||||||
def unregister() -> None:
|
def unregister() -> None:
|
||||||
bpy.app.handlers.save_pre.remove(on_save)
|
bpy.app.handlers.save_pre.remove(on_save)
|
||||||
del bpy.types.Group.fbx_exportable
|
del Group.fbx_exportable
|
||||||
del bpy.types.Scene.fbx_export
|
del Scene.fbx_group_index
|
||||||
|
del Scene.fbx_object_types
|
||||||
|
del Scene.fbx_on_save
|
||||||
|
del Scene.fbx_export_dir
|
||||||
for cls in reversed(classes):
|
for cls in reversed(classes):
|
||||||
bpy.utils.unregister_class(cls)
|
bpy.utils.unregister_class(cls)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user