Browse Source

Move exporter logic out of prop_object...

... And commence more work on the exporter. We now export
CoordinateInterfaces! Go us.
pull/6/head
Adam Johnson 11 years ago
parent
commit
242ed01afb
  1. 115
      korman/exporter/convert.py
  2. 72
      korman/exporter/logger.py
  3. 13
      korman/exporter/manager.py
  4. 21
      korman/exporter/mesh.py
  5. 26
      korman/exporter/utils.py
  6. 8
      korman/properties/prop_object.py

115
korman/exporter/convert.py

@ -18,7 +18,10 @@ import os.path
from PyHSPlasma import * from PyHSPlasma import *
from . import explosions from . import explosions
from . import logger
from . import manager from . import manager
from . import mesh
from . import utils
class Exporter: class Exporter:
# These are objects that we need to export as plSceneObjects # 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] return os.path.splitext(os.path.split(self._op.filepath)[1])[0]
def run(self): def run(self):
# Step 0: Init export resmgr and stuff with logger.ExportLogger("{}_export.log".format(self.age_name)) as _log:
self.mgr = manager.ExportManager(globals()[self._op.version]) # 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 # Step 1: Gather a list of objects that we need to export
# We should do this first so we can sanity check # We should do this first so we can sanity check
# and give accurate progress reports # and give accurate progress reports
self._collect_objects() self._collect_objects()
# Step 2: Create the age info and the pages # Step 2: Create the age info and the pages
self._export_age_info() self._export_age_info()
# Step 2.9: Ensure that all Plasma Objects are in a valid page # Step 2.9: Ensure that all Plasma Objects are in a valid page
# This creates the default page if it is used # This creates the default page if it is used
self.mgr.sanity_check_object_pages(self.age_name, self._objects) self.mgr.sanity_check_object_pages(self.age_name, self._objects)
# Step 3: Export all the things! # Step 3: Export all the things!
self._export_scene_objects() self._export_scene_objects()
# Step 4: FINALLY. Let's write the PRPs and crap. # Step 4: FINALLY. Let's write the PRPs and crap.
self.mgr.save_age(self._op.filepath) 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): def _collect_objects(self):
for obj in bpy.data.objects: for obj in bpy.data.objects:
@ -72,9 +83,75 @@ class Exporter:
mgr.create_page(age_name, page.name, page.seq_suffix) mgr.create_page(age_name, page.name, page.seq_suffix)
mgr.create_builtins(age_name, self._op.use_texture_page) 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): def _export_scene_objects(self):
for bl_obj in self._objects: for bl_obj in self._objects:
# Naive export all Plasma Objects. They will be responsible for calling back into the print("=== Exporting plSceneObject ===")
# 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. # First pass: do things specific to this object type.
bl_obj.plasma_object.export(self, bl_obj) # 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

@ -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)

13
korman/exporter/manager.py

@ -109,12 +109,17 @@ class ExportManager:
self._nodes[location] = None self._nodes[location] = None
return location return location
def find_key(self, bl_obj, index): def find_create_key(self, bl_obj, pClass):
"""Given a blender Object and a pCre index, find an exported plKey""" 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] location = self._pages[bl_obj.plasma_object.page]
# NOTE: may need to replace with a python side dict for faster lookups index = plFactory.ClassIndex(pClass.__name__)
# evaluate when exporter has been fleshed out
for key in self.mgr.getKeys(location, index): for key in self.mgr.getKeys(location, index):
if bl_obj.name == key.name: if bl_obj.name == key.name:
return key return key

21
korman/exporter/mesh.py

@ -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

@ -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

8
korman/properties/prop_object.py

@ -51,14 +51,6 @@ class PlasmaObject(bpy.types.PropertyGroup):
o.plasma_object.page = page.name o.plasma_object.page = page.name
break 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", enabled = BoolProperty(name="Export",
description="Export this as a discrete object", description="Export this as a discrete object",

Loading…
Cancel
Save