mirror of
https://github.com/H-uru/korman.git
synced 2025-07-14 22:36:52 +00:00
Move exporter logic out of prop_object...
... And commence more work on the exporter. We now export CoordinateInterfaces! Go us.
This commit is contained in:
@ -18,7 +18,10 @@ import os.path
|
||||
from PyHSPlasma import *
|
||||
|
||||
from . import explosions
|
||||
from . import logger
|
||||
from . import manager
|
||||
from . import mesh
|
||||
from . import utils
|
||||
|
||||
class Exporter:
|
||||
# These are objects that we need to export as plSceneObjects
|
||||
@ -32,26 +35,34 @@ class Exporter:
|
||||
return os.path.splitext(os.path.split(self._op.filepath)[1])[0]
|
||||
|
||||
def run(self):
|
||||
# Step 0: Init export resmgr and stuff
|
||||
self.mgr = manager.ExportManager(globals()[self._op.version])
|
||||
with logger.ExportLogger("{}_export.log".format(self.age_name)) as _log:
|
||||
# Step 0: Init export resmgr and stuff
|
||||
self.mgr = manager.ExportManager(globals()[self._op.version])
|
||||
self.mesh = mesh.MeshConverter()
|
||||
self.report = logger.ExportAnalysis()
|
||||
|
||||
# Step 1: Gather a list of objects that we need to export
|
||||
# We should do this first so we can sanity check
|
||||
# and give accurate progress reports
|
||||
self._collect_objects()
|
||||
# Step 1: Gather a list of objects that we need to export
|
||||
# We should do this first so we can sanity check
|
||||
# and give accurate progress reports
|
||||
self._collect_objects()
|
||||
|
||||
# Step 2: Create the age info and the pages
|
||||
self._export_age_info()
|
||||
# Step 2: Create the age info and the pages
|
||||
self._export_age_info()
|
||||
|
||||
# Step 2.9: Ensure that all Plasma Objects are in a valid page
|
||||
# This creates the default page if it is used
|
||||
self.mgr.sanity_check_object_pages(self.age_name, self._objects)
|
||||
# Step 2.9: Ensure that all Plasma Objects are in a valid page
|
||||
# This creates the default page if it is used
|
||||
self.mgr.sanity_check_object_pages(self.age_name, self._objects)
|
||||
|
||||
# Step 3: Export all the things!
|
||||
self._export_scene_objects()
|
||||
# Step 3: Export all the things!
|
||||
self._export_scene_objects()
|
||||
|
||||
# Step 4: FINALLY. Let's write the PRPs and crap.
|
||||
self.mgr.save_age(self._op.filepath)
|
||||
# Step 4: FINALLY. Let's write the PRPs and crap.
|
||||
self.mgr.save_age(self._op.filepath)
|
||||
|
||||
# Step 4.1: Save out the export report.
|
||||
# If the export fails and this doesn't save, we have bigger problems than
|
||||
# these little warnings and notices.
|
||||
self.report.save()
|
||||
|
||||
def _collect_objects(self):
|
||||
for obj in bpy.data.objects:
|
||||
@ -72,9 +83,75 @@ class Exporter:
|
||||
mgr.create_page(age_name, page.name, page.seq_suffix)
|
||||
mgr.create_builtins(age_name, self._op.use_texture_page)
|
||||
|
||||
def _export_actor(self, so, bo):
|
||||
"""Exports a Coordinate Interface if we need one"""
|
||||
empty = bo.type in {"CAMERA", "EMPTY", "LAMP"}
|
||||
childobj = bo.parent is not None
|
||||
|
||||
if empty or childobj:
|
||||
self._export_coordinate_interface(so, bo)
|
||||
|
||||
# If this object has a parent, then we will need to go upstream and add ourselves to the
|
||||
# parent's CoordinateInterface... Because life just has to be backwards.
|
||||
if childobj:
|
||||
parent = bo.parent
|
||||
if parent.plasma_object.enabled:
|
||||
print("\tAttaching to parent SceneObject '{}'".format(parent.name))
|
||||
|
||||
# Instead of exporting a skeleton now, we'll just make an orphaned CI.
|
||||
# The bl_obj export will make this work.
|
||||
parent_ci = self.mgr.find_create_key(parent, plCoordinateInterface).object
|
||||
parent_ci.addChild(so.key)
|
||||
else:
|
||||
self.report.warn("oversight",
|
||||
"You have parented Plasma Object '{}' to '{}', which has not been marked for export. \
|
||||
The object may not appear in the correct location or animate properly.".format(
|
||||
bo.name, parent.name))
|
||||
|
||||
def _export_coordinate_interface(self, so, bo):
|
||||
"""Ensures that the SceneObject has a CoordinateInterface"""
|
||||
if not so.coord:
|
||||
ci = self.mgr.find_create_key(bo, plCoordinateInterface)
|
||||
so.coord = ci
|
||||
ci = ci.object
|
||||
ci.owner = so.key
|
||||
|
||||
# Now we have the "fun" work of filling in the CI
|
||||
ci.worldToLocal = utils.matrix44(bo.matrix_basis)
|
||||
ci.localToWorld = ci.worldToLocal.inverse()
|
||||
ci.parentToLocal = utils.matrix44(bo.matrix_local)
|
||||
ci.localToParent = ci.parentToLocal.inverse()
|
||||
|
||||
def _export_scene_objects(self):
|
||||
for bl_obj in self._objects:
|
||||
# Naive export all Plasma Objects. They will be responsible for calling back into the
|
||||
# exporter to find/create drawable meshes, materials, etc. Not sure if this design will
|
||||
# work well, but we're going to go with it for now.
|
||||
bl_obj.plasma_object.export(self, bl_obj)
|
||||
print("=== Exporting plSceneObject ===")
|
||||
|
||||
# First pass: do things specific to this object type.
|
||||
# note the function calls: to export a MESH, it's _export_mesh_blobj
|
||||
export_fn = "_export_{}_blobj".format(bl_obj.type.lower())
|
||||
try:
|
||||
export_fn = getattr(self, export_fn)
|
||||
except AttributeError:
|
||||
print("WARNING: '{}' is a Plasma Object of Blender type '{}'".format(bl_obj.name, bl_obj.type))
|
||||
print("... And I have NO IDEA what to do with that! Tossing.")
|
||||
continue
|
||||
print("\tBlender Object '{}' of type '{}'".format(bl_obj.name, bl_obj.type))
|
||||
|
||||
# Create a sceneobject if one does not exist.
|
||||
# Before we call the export_fn, we need to determine if this object is an actor of any
|
||||
# sort, and barf out a CI.
|
||||
sceneobject = self.mgr.find_create_key(bl_obj, plSceneObject).object
|
||||
self._export_actor(sceneobject, bl_obj)
|
||||
export_fn(sceneobject, bl_obj)
|
||||
|
||||
# :(
|
||||
print()
|
||||
|
||||
def _export_empty_blobj(self, so, bo):
|
||||
# We don't need to do anything here. This function just makes sure we don't error out
|
||||
# or add a silly special case :(
|
||||
pass
|
||||
|
||||
def _export_mesh_blobj(self, so, bo):
|
||||
# TODO
|
||||
pass
|
72
korman/exporter/logger.py
Normal file
72
korman/exporter/logger.py
Normal file
@ -0,0 +1,72 @@
|
||||
# This file is part of Korman.
|
||||
#
|
||||
# Korman is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Korman is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys
|
||||
|
||||
class ExportAnalysis:
|
||||
"""This is used to collect artist action items from the export process. You can warn about
|
||||
portability issues, possible oversights, etc. The benefit here is that the user doesn't have
|
||||
to look through all of the gobbledygook in the export log.
|
||||
"""
|
||||
|
||||
_notices = {}
|
||||
_warnings = {}
|
||||
|
||||
def save(self):
|
||||
# TODO
|
||||
pass
|
||||
|
||||
def _stash(self, _d, category, message):
|
||||
if category not in _d:
|
||||
_d[category] = [message,]
|
||||
else:
|
||||
_d[category].append(message)
|
||||
|
||||
def note(self, category, message):
|
||||
self._stash(self._notices, category, message)
|
||||
print("NOTICE {}: {}".format(category, message))
|
||||
|
||||
def warn(self, category, message):
|
||||
self._stash(self._warnings, category, message)
|
||||
print("WARNING {}: {}".format(category, message))
|
||||
|
||||
|
||||
class ExportLogger:
|
||||
"""Yet Another Logger(TM)"""
|
||||
|
||||
def __init__(self, fn):
|
||||
self._stdout = sys.stdout
|
||||
self._stderr = sys.stderr
|
||||
self._file = open(fn, "w")
|
||||
|
||||
for i in dir(self._file):
|
||||
if not hasattr(self, i):
|
||||
setattr(self, i, getattr(self._file, i))
|
||||
|
||||
def __enter__(self):
|
||||
sys.stdout = self._file
|
||||
sys.stderr = self._file
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
sys.stdout = self._stdout
|
||||
sys.stderr = self._stderr
|
||||
|
||||
def write(self, str):
|
||||
self._file.write(str)
|
||||
self._stdout.write(str)
|
||||
|
||||
def writelines(self, seq):
|
||||
self._file.writelines(seq)
|
||||
self._stdout.writelines(seq)
|
@ -109,12 +109,17 @@ class ExportManager:
|
||||
self._nodes[location] = None
|
||||
return location
|
||||
|
||||
def find_key(self, bl_obj, index):
|
||||
"""Given a blender Object and a pCre index, find an exported plKey"""
|
||||
def find_create_key(self, bl_obj, pClass):
|
||||
key = self.find_key(bl_obj, pClass)
|
||||
if key is None:
|
||||
key = self.add_object(pl=pClass, bl=bl_obj).key
|
||||
return key
|
||||
|
||||
def find_key(self, bl_obj, pClass):
|
||||
"""Given a blender Object and a Plasma class, find (or create) an exported plKey"""
|
||||
location = self._pages[bl_obj.plasma_object.page]
|
||||
|
||||
# NOTE: may need to replace with a python side dict for faster lookups
|
||||
# evaluate when exporter has been fleshed out
|
||||
index = plFactory.ClassIndex(pClass.__name__)
|
||||
for key in self.mgr.getKeys(location, index):
|
||||
if bl_obj.name == key.name:
|
||||
return key
|
||||
|
21
korman/exporter/mesh.py
Normal file
21
korman/exporter/mesh.py
Normal file
@ -0,0 +1,21 @@
|
||||
# This file is part of Korman.
|
||||
#
|
||||
# Korman is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Korman is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from PyHSPlasma import *
|
||||
|
||||
class MeshConverter:
|
||||
# TODO
|
||||
pass
|
26
korman/exporter/utils.py
Normal file
26
korman/exporter/utils.py
Normal file
@ -0,0 +1,26 @@
|
||||
# This file is part of Korman.
|
||||
#
|
||||
# Korman is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Korman is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Korman. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from PyHSPlasma import *
|
||||
|
||||
def matrix44(blmat):
|
||||
"""Converts a mathutils.Matrix to an hsMatrix44"""
|
||||
hsmat = hsMatrix44()
|
||||
for i in range(4):
|
||||
hsmat[0, i] = blmat[i][0]
|
||||
hsmat[1, i] = blmat[i][1]
|
||||
hsmat[2, i] = blmat[i][2]
|
||||
hsmat[3, i] = blmat[i][3]
|
||||
return hsmat
|
@ -51,14 +51,6 @@ class PlasmaObject(bpy.types.PropertyGroup):
|
||||
o.plasma_object.page = page.name
|
||||
break
|
||||
|
||||
def export(self, exporter, bl_obj):
|
||||
"""Plasma Object Export"""
|
||||
|
||||
# This is where the magic happens...
|
||||
if self.enabled:
|
||||
# TODO: Something more useful than a blank object.
|
||||
exporter.mgr.add_object(plSceneObject, bl=bl_obj)
|
||||
|
||||
|
||||
enabled = BoolProperty(name="Export",
|
||||
description="Export this as a discrete object",
|
||||
|
Reference in New Issue
Block a user