Browse Source

Fill out some more core-export stuff

pull/1/head
Adam Johnson 13 years ago
parent
commit
f4f39e2d2f
  1. 101
      korman/exporter.py
  2. 14
      korman/operators/op_export.py
  3. 8
      korman/properties/prop_object.py
  4. 37
      korman/properties/prop_world.py
  5. 4
      korman/ui/ui_object.py
  6. 32
      korman/ui/ui_world.py

101
korman/exporter.py

@ -28,9 +28,26 @@ class Exporter:
self._op = op # Blender operator self._op = op # Blender operator
# This stuff doesn't need to be static # This stuff doesn't need to be static
self._nodes = {}
self._objects = [] self._objects = []
self._pages = {} self._pages = {}
self.texture_page = True
def add_object(self, pl, bl=None, loc=None):
"""Automates adding a converted Blender object to our Plasma Resource Manager"""
assert (bl or loc)
if loc:
location = loc
else:
location = self._pages[bl.plasma_object.page]
self.mgr.AddObject(location, pl)
node = self._nodes[location]
if node: # All objects must be in the scene node
if isinstance(pl, plSceneObject):
f = node.addSceneObject
else:
f = node.addPoolObject
f(pl.key)
@property @property
def age_name(self): def age_name(self):
@ -56,7 +73,10 @@ class Exporter:
node = plSceneNode("%s_District_%s" % (self.age_name, name)) node = plSceneNode("%s_District_%s" % (self.age_name, name))
else: else:
node = plSceneNode("%s_%s" % (self.age_name, name)) node = plSceneNode("%s_%s" % (self.age_name, name))
self._nodes[location] = node
self.mgr.AddObject(location, node) self.mgr.AddObject(location, node)
else:
self._nodes[location] = None
return location return location
def get_textures_page(self, obj): def get_textures_page(self, obj):
@ -87,37 +107,37 @@ class Exporter:
self._sanity_check_pages() self._sanity_check_pages()
self._generate_builtins() # Creates BuiltIn and Textures self._generate_builtins() # Creates BuiltIn and Textures
# ... todo ... # Step 3: Export all the things!
self._export_scene_objects()
# ... And finally... Write it all out! # Step 4: FINALLY. Let's write the PRPs and crap.
self.mgr.WriteAge(self._op.filepath, self._age_info) self.mgr.WriteAge(self._op.filepath, self._age_info)
dir = os.path.split(self._op.filepath)[0] self._write_fni()
for name, loc in self._pages.items(): self._write_pages()
page = self.mgr.FindPage(loc) # not cached because it's C++ owned
# I know that plAgeInfo has its own way of doing this, but we'd have
# to do some looping and stuff. This is easier.
if self.version <= pvMoul:
chapter = "_District_"
else:
chapter = "_"
f = os.path.join(dir, "%s%s%s.prp" % (self.age_name, chapter, name))
self.mgr.WritePage(f, page)
def _collect_objects(self): def _collect_objects(self):
for obj in bpy.data.objects: for obj in bpy.data.objects:
if obj.plasma_object.export: if obj.plasma_object.enabled:
self._objects.append(obj) self._objects.append(obj)
def _grab_age_info(self): def _grab_age_info(self):
self._age_info = bpy.context.scene.world.plasma_age.export() age = bpy.context.scene.world.plasma_age
self._age_info = plAgeInfo()
self._age_info.dayLength = age.day_length
self._age_info.lingerTime = 180 # this is fairly standard
self._age_info.name = self.age_name self._age_info.name = self.age_name
self._age_info.seqPrefix = age.seq_prefix
self._age_info.startDateTime = age.start_time
self.mgr.AddAge(self._age_info) self.mgr.AddAge(self._age_info)
def _sanity_check_pages(self): def _sanity_check_pages(self):
"""Ensure all objects are in valid pages and create the Default page if used""" """Ensure all objects are in valid pages and create the Default page if used"""
for obj in self._objects: for obj in self._objects:
page = obj.plasma_object.page page = obj.plasma_object.page
if not page in self._pages and page == "": if page in self._pages:
# good. keep trying.
continue
elif page == "":
# This object is in the default page... Init that. # This object is in the default page... Init that.
for loc in self._pages.values(): for loc in self._pages.values():
if not loc.page: if not loc.page:
@ -143,11 +163,11 @@ class Exporter:
_s -= 1 _s -= 1
# Grunt work... # Grunt work...
if self.version <= pvMoul: if self.version <= pvMoul and self._op.save_state:
builtin = self._create_page("BuiltIn", suffixes[1], True) builtin = self._create_page("BuiltIn", suffixes[1], True)
pfm = plPythonFileMod("VeryVerySpecialPythonFileMod") pfm = plPythonFileMod("VeryVerySpecialPythonFileMod")
pfm.filename = self.age_name pfm.filename = self.age_name
self.mgr.AddObject(builtin, pfm) self.mgr.AddObject(builtin, pfm) # add_object has lots of overhead
sdlhook = plSceneObject("AgeSDLHook") sdlhook = plSceneObject("AgeSDLHook")
sdlhook.addModifier(pfm.key) sdlhook.addModifier(pfm.key)
self.mgr.AddObject(builtin, sdlhook) self.mgr.AddObject(builtin, sdlhook)
@ -158,3 +178,46 @@ class Exporter:
self._pages["Textures"] = textures self._pages["Textures"] = textures
else: else:
self._pages["Textures"] = None # probably easier than looping to find it self._pages["Textures"] = None # probably easier than looping to find it
def _export_scene_objects(self):
for bl_obj in self._objects:
# Normally, we'd pass off to the property for export logic, but we need to
# do meshes here, so let's stay local until it's modifier time
so = plSceneObject(bl_obj.name)
self.add_object(pl=so, bl=bl_obj)
# TODO: export mesh
# TODO: export plasma modifiers
def _write_fni(self):
if self.version <= pvMoul:
enc = plEncryptedStream.kEncXtea
else:
enc = plEncryptedStream.kEncAES
fname = os.path.join(os.path.split(self._op.filepath)[0], "%s.fni" % self.age_name)
stream = plEncryptedStream()
stream.open(fname, fmWrite, enc)
# Write out some stuff
fni = bpy.context.scene.world.plasma_fni
stream.writeLine("Graphics.Renderer.Fog.SetClearColor %f %f %f" % tuple(fni.clear_color))
if fni.fog_method != "none":
stream.writeLine("Graphics.Renderer.Fog.SetDefColor %f %f %f" % tuple(fni.fog_color))
if fni.fog_method == "linear":
stream.writeLine("Graphics.Renderer.Fog.SetDefLinear %f %f %f" % (fni.fog_start, fni.fog_end, fni.fog_density))
elif fni.fog_method == "exp2":
stream.writeLine("Graphics.Renderer.Fog.SetDefExp2 %f %f" % (fni.fog_end, fni.fog_density))
stream.writeLine("Graphics.Renderer.Setyon %f" % fni.yon)
stream.close()
def _write_pages(self):
dir = os.path.split(self._op.filepath)[0]
for name, loc in self._pages.items():
page = self.mgr.FindPage(loc) # not cached because it's C++ owned
# I know that plAgeInfo has its own way of doing this, but we'd have
# to do some looping and stuff. This is easier.
if self.version <= pvMoul:
chapter = "_District_"
else:
chapter = "_"
f = os.path.join(dir, "%s%s%s.prp" % (self.age_name, chapter, name))
self.mgr.WritePage(f, page)

14
korman/operators/op_export.py

@ -38,15 +38,17 @@ class ExportOperator(bpy.types.Operator):
) )
optimize = bpy.props.BoolProperty(name="Optimize Age", optimize = bpy.props.BoolProperty(name="Optimize Age",
description="Optimizes your age to run faster. This slows down export.") description="Optimizes your age to run faster. This slows down export.")
save_state = bpy.props.BoolProperty(name="Save State",
description="Saves your age's state to the server for subsequent link ins.",
default=True)
use_texture_page = bpy.props.BoolProperty(name="Use Texture Page", use_texture_page = bpy.props.BoolProperty(name="Use Texture Page",
description="Exports all textures to a dedicated Textures page", description="Exports all textures to a dedicated Textures page",
default=True) default=True)
filepath = bpy.props.StringProperty(subtype="FILE_PATH") filepath = bpy.props.StringProperty(subtype="FILE_PATH")
def _set_error(self, value): @property
self.has_reports = True def has_reports(self):
self.report = ({"ERROR"}, value) return hasattr(self.report)
error = property(fset=_set_error) # Can't use decorators here :(
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
@ -64,7 +66,7 @@ class ExportOperator(bpy.types.Operator):
try: try:
os.mkdirs(dir) os.mkdirs(dir)
except os.error: except os.error:
self.error = "Failed to create export directory" self.report({"ERROR"}, "Failed to create export directory")
return {"CANCELLED"} return {"CANCELLED"}
# Separate blender operator and actual export logic for my sanity # Separate blender operator and actual export logic for my sanity
@ -72,7 +74,7 @@ class ExportOperator(bpy.types.Operator):
try: try:
e.run() e.run()
except exporter.ExportError as error: except exporter.ExportError as error:
self.error = str(error) self.report({"ERROR"}, str(error))
return {"CANCELLED"} return {"CANCELLED"}
else: else:
return {"FINISHED"} return {"FINISHED"}

8
korman/properties/prop_object.py

@ -17,7 +17,7 @@ import bpy
from bpy.props import * from bpy.props import *
class PlasmaObject(bpy.types.PropertyGroup): class PlasmaObject(bpy.types.PropertyGroup):
def _export_changed(self, context): def _enabled(self, context):
# This makes me sad # This makes me sad
if not self.is_inited: if not self.is_inited:
self._init(context) self._init(context)
@ -34,14 +34,14 @@ class PlasmaObject(bpy.types.PropertyGroup):
for page in age.pages: for page in age.pages:
if page.seq_suffix > num_layers: if page.seq_suffix > num_layers:
continue continue
if o.layers[page.seq_suffix-1]: if o.layers[page.seq_suffix - 1]:
o.plasma_object.page = page.name o.plasma_object.page = page.name
break break
export = BoolProperty(name="Export", enabled = BoolProperty(name="Export",
description="Export this as a discrete object", description="Export this as a discrete object",
default=False, default=False,
update=_export_changed) update=_enabled)
page = StringProperty(name="Page", page = StringProperty(name="Page",
description="Page this object will be exported to") description="Page this object will be exported to")

37
korman/properties/prop_world.py

@ -22,8 +22,24 @@ class PlasmaFni(bpy.types.PropertyGroup):
fog_color = FloatVectorProperty(name="Fog Color", fog_color = FloatVectorProperty(name="Fog Color",
description="The default fog color used in your age", description="The default fog color used in your age",
default=(0.3, 0.2, 0.05), default=(0.4, 0.3, 0.1),
subtype="COLOR") subtype="COLOR")
fog_method = EnumProperty(name="Fog Type",
items=[
("linear", "Linear", "Linear Fog"),
("exp2", "Exponential", "Exponential Fog"),
("none", "None", "Use fog from the previous age")
])
fog_start = FloatProperty(name="Start",
description="",
default= -1500.0)
fog_end = FloatProperty(name="End",
description="",
default=20000.0)
fog_density = FloatProperty(name="Density",
description="",
default=1.0,
min=0.0)
clear_color = FloatVectorProperty(name="Clear Color", clear_color = FloatVectorProperty(name="Clear Color",
description="The default background color rendered in your age", description="The default background color rendered in your age",
subtype="COLOR") subtype="COLOR")
@ -32,7 +48,6 @@ class PlasmaFni(bpy.types.PropertyGroup):
default=100000, default=100000,
soft_min=100, soft_min=100,
min=1) min=1)
# TODO: density
class PlasmaPage(bpy.types.PropertyGroup): class PlasmaPage(bpy.types.PropertyGroup):
def _check_suffix(self, context): def _check_suffix(self, context):
@ -86,6 +101,9 @@ class PlasmaPage(bpy.types.PropertyGroup):
auto_load = BoolProperty(name="Auto Load", auto_load = BoolProperty(name="Auto Load",
description="Load this page on link-in", description="Load this page on link-in",
default=True) default=True)
local_only = BoolProperty(name="Local Only",
description="This page should not synchronize with the server",
default=False)
# Implementation details... # Implementation details...
last_name = StringProperty(description="INTERNAL: Cached page name", last_name = StringProperty(description="INTERNAL: Cached page name",
@ -100,9 +118,14 @@ class PlasmaPage(bpy.types.PropertyGroup):
class PlasmaAge(bpy.types.PropertyGroup): class PlasmaAge(bpy.types.PropertyGroup):
day_length = FloatProperty(name="Day Length", day_length = FloatProperty(name="Day Length",
description="Length of a day (in hours) on this age", description="Length of a day (in hours) on this age",
default=24.0, default=30.230000,
soft_min=0.1, soft_min=0.1,
min=0.0) min=0.0)
start_time = IntProperty(name="Start Time",
description="Seconds from 1/1/1970 until the first day on this age",
subtype="UNSIGNED",
default=672211080,
min=0)
seq_prefix = IntProperty(name="Sequence Prefix", seq_prefix = IntProperty(name="Sequence Prefix",
description="A unique numerical ID for this age", description="A unique numerical ID for this age",
soft_min=0, # Negative indicates global--advanced users only soft_min=0, # Negative indicates global--advanced users only
@ -113,11 +136,3 @@ class PlasmaAge(bpy.types.PropertyGroup):
# Implementation details # Implementation details
active_page_index = IntProperty(name="Active Page Index") active_page_index = IntProperty(name="Active Page Index")
def export(self):
age = plAgeInfo()
age.dayLength = self.day_length
age.seqPrefix = self.seq_prefix
# Pages are added to the ResManager in the main exporter
return age

4
korman/ui/ui_object.py

@ -29,12 +29,12 @@ class PlasmaObjectPanel(ObjectButtonsPanel, bpy.types.Panel):
bl_label = "Plasma Object" bl_label = "Plasma Object"
def draw_header(self, context): def draw_header(self, context):
self.layout.prop(context.object.plasma_object, "export", text="") self.layout.prop(context.object.plasma_object, "enabled", text="")
def draw(self, context): def draw(self, context):
layout = self.layout layout = self.layout
pl_obj = context.object.plasma_object pl_obj = context.object.plasma_object
pl_age = context.scene.world.plasma_age pl_age = context.scene.world.plasma_age
layout.active = pl_obj.export layout.active = pl_obj.enabled
layout.prop_search(pl_obj, "page", pl_age, "pages", icon="BOOKMARKS") layout.prop_search(pl_obj, "page", pl_age, "pages", icon="BOOKMARKS")

32
korman/ui/ui_world.py

@ -32,9 +32,6 @@ class PlasmaAgePanel(AgeButtonsPanel, bpy.types.Panel):
layout = self.layout layout = self.layout
age = context.world.plasma_age age = context.world.plasma_age
# Core age settings
# ...
# We want a list of pages and an editor below that # We want a list of pages and an editor below that
row = layout.row() row = layout.row()
row.template_list(age, "pages", age, "active_page_index", rows=2) row.template_list(age, "pages", age, "active_page_index", rows=2)
@ -42,14 +39,23 @@ class PlasmaAgePanel(AgeButtonsPanel, bpy.types.Panel):
col.operator("world.plasma_page_add", icon="ZOOMIN", text="") col.operator("world.plasma_page_add", icon="ZOOMIN", text="")
col.operator("world.plasma_page_remove", icon="ZOOMOUT", text="") col.operator("world.plasma_page_remove", icon="ZOOMOUT", text="")
# name/id editor for current selection # Page Properties
if age.active_page_index < len(age.pages): if age.active_page_index < len(age.pages):
active_page = age.pages[age.active_page_index] active_page = age.pages[age.active_page_index]
split = layout.split(percentage=0.65) split = layout.box().split()
col = split.column() col = split.column()
col.prop(active_page, "name") col.prop(active_page, "name", text="")
col.prop(active_page, "auto_load")
col = split.column() col = split.column()
col.prop(active_page, "seq_suffix") col.prop(active_page, "seq_suffix")
col.prop(active_page, "local_only")
# Core settings
row = layout.row()
row.prop(age, "day_length")
row.prop(age, "seq_prefix", text="ID")
layout.prop(age, "start_time")
class PlasmaEnvironmentPanel(AgeButtonsPanel, bpy.types.Panel): class PlasmaEnvironmentPanel(AgeButtonsPanel, bpy.types.Panel):
@ -59,11 +65,23 @@ class PlasmaEnvironmentPanel(AgeButtonsPanel, bpy.types.Panel):
layout = self.layout layout = self.layout
fni = context.world.plasma_fni fni = context.world.plasma_fni
# Column-ize the colors # basic colors
split = layout.split() split = layout.split()
col = split.column() col = split.column()
col.prop(fni, "fog_color") col.prop(fni, "fog_color")
col = split.column() col = split.column()
col.prop(fni, "clear_color") col.prop(fni, "clear_color")
# fog box
split = layout.box()
row = split.row().split(percentage=0.50)
row.column().prop_menu_enum(fni, "fog_method")
if fni.fog_method == "linear":
row.column().prop(fni, "fog_start")
if fni.fog_method != "none":
row = split.row()
row.prop(fni, "fog_density")
row.prop(fni, "fog_end")
# tacked on: draw distance
layout.prop(fni, "yon") layout.prop(fni, "yon")

Loading…
Cancel
Save