diff --git a/.gitignore b/.gitignore
index f24cd99..45c9785 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
*.py[co]
+__pycache__
# Packages
*.egg
diff --git a/korman/__init__.py b/korman/__init__.py
index 8476085..170c467 100644
--- a/korman/__init__.py
+++ b/korman/__init__.py
@@ -15,6 +15,7 @@
import bpy
from . import exporter, render
+from . import operators, properties, ui
bl_info = {
"name": "Korman",
@@ -31,9 +32,12 @@ def register():
"""Registers all Blender operators and GUI items in Korman"""
# This will auto-magically register all blender classes for us
- # We will define a lot of them, methinks...
bpy.utils.register_module(__name__)
+ # We have to setup pointer props to our custom property groups ourselves,
+ # so let's go ahead and do that now.
+ properties.register()
+
def unregister():
"""Unregisters all Blender operators and GUI items"""
bpy.utils.unregister_module(__name__)
diff --git a/korman/exporter.py b/korman/exporter.py
index dfdc21f..0203a7b 100644
--- a/korman/exporter.py
+++ b/korman/exporter.py
@@ -37,7 +37,8 @@ class PlasmaExporter(bpy.types.Operator):
@classmethod
def poll(cls, context):
- return context.object is not None
+ if context.object is not None:
+ return context.scene.render.engine == "PLASMA_GAME"
def execute(self, context):
# TODO
@@ -54,4 +55,5 @@ class PlasmaExporter(bpy.types.Operator):
def menu_cb(self, context):
self.layout.operator_context = "INVOKE_DEFAULT"
self.layout.operator(PlasmaExporter.bl_idname, text="Plasma Age (.age)")
-bpy.types.INFO_MT_file_export.append(menu_cb)
+def register():
+ bpy.types.INFO_MT_file_export.append(menu_cb)
diff --git a/korman/operators/__init__.py b/korman/operators/__init__.py
new file mode 100644
index 0000000..d44002a
--- /dev/null
+++ b/korman/operators/__init__.py
@@ -0,0 +1,16 @@
+# 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 .
+
+from .op_world import *
diff --git a/korman/operators/op_world.py b/korman/operators/op_world.py
new file mode 100644
index 0000000..19415a6
--- /dev/null
+++ b/korman/operators/op_world.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 .
+
+import bpy
+
+class AgeOperator:
+ @classmethod
+ def poll(cls, context):
+ return context.scene.render.engine == "PLASMA_GAME"
+
+class PlasmaPageAddOperator(AgeOperator, bpy.types.Operator):
+ bl_idname = "world.plasma_page_add"
+ bl_label = "Add Page"
+ bl_description = "Adds a new Plasma Registry Page"
+
+ def execute(self, context):
+ w = context.world
+ if w:
+ age = w.plasma_age
+ page = age.pages.add()
+
+ # Find the first non-zero ID and suggest that.
+ suffixes = []
+ for p in age.pages:
+ # Filter out pages with no-id or
+ if p.seq_suffix:
+ suffixes.append(p.seq_suffix)
+ if len(suffixes):
+ suffixes.sort()
+ test = set(range(suffixes[0], suffixes[-1]))
+ missing = test - set(suffixes)
+ try:
+ suffix = missing.pop()
+ except KeyError:
+ suffix = suffixes[-1] + 1
+ page.make_default_name(suffix)
+ else:
+ # Page 0 is a magic "catch-all" page. The user *may* define it
+ # if he wants. If he doesn't, we'll defer it until export time
+ page.make_default_name(1)
+
+ # Finally, select the new page
+ age.active_page_index = len(age.pages) - 1
+ return {"FINISHED"}
+ else:
+ return {"CANCELLED"}
+
+
+class PlasmaPageRemoveOperator(AgeOperator, bpy.types.Operator):
+ bl_idname = "world.plasma_page_remove"
+ bl_label = "Remove Page"
+ bl_description = "Removes the selected Plasma Registry Page"
+
+ def execute(self, context):
+ w = context.world
+ if w:
+ # ...
+ return {"FINISHED"}
+ else:
+ return {"CANCELLED"}
diff --git a/korman/properties/__init__.py b/korman/properties/__init__.py
new file mode 100644
index 0000000..6164589
--- /dev/null
+++ b/korman/properties/__init__.py
@@ -0,0 +1,24 @@
+# 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 .
+
+import bpy
+
+from .prop_object import *
+from .prop_world import *
+
+def register():
+ bpy.types.Object.plasma_object = PointerProperty(type=PlasmaObject)
+ bpy.types.World.plasma_age = PointerProperty(type=PlasmaAge)
+ bpy.types.World.plasma_fni = PointerProperty(type=PlasmaFni)
diff --git a/korman/properties/prop_object.py b/korman/properties/prop_object.py
new file mode 100644
index 0000000..17b1caf
--- /dev/null
+++ b/korman/properties/prop_object.py
@@ -0,0 +1,51 @@
+# 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 .
+
+import bpy
+from bpy.props import *
+
+class PlasmaObject(bpy.types.PropertyGroup):
+ def _export_changed(self, context):
+ # This makes me sad
+ if not self.is_inited:
+ self._init(context)
+ self.is_inited = True
+
+ def _init(self, context):
+ o = context.object
+ age = context.scene.world.plasma_age
+
+ # We want to encourage the pages = layers paradigm.
+ # So, let's see which layers we're on and check for a page whose
+ # suffix matches our layers. We'll take the first match.
+ num_layers = len(o.layers)
+ for page in age.pages:
+ if page.seq_suffix > num_layers:
+ continue
+ if o.layers[page.seq_suffix-1]:
+ o.plasma_object.page = page.name
+ break
+
+ export = BoolProperty(name="Export",
+ description="Export this as a discrete object",
+ default=False,
+ update=_export_changed)
+ page = StringProperty(name="Page",
+ description="Page this object will be exported to")
+
+ # Implementation Details
+ is_inited = BoolProperty(description="INTERNAL: Init proc complete",
+ default=False,
+ options={"HIDDEN"})
diff --git a/korman/properties/prop_world.py b/korman/properties/prop_world.py
new file mode 100644
index 0000000..011cecd
--- /dev/null
+++ b/korman/properties/prop_world.py
@@ -0,0 +1,114 @@
+# 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 .
+
+import bpy
+from bpy.props import *
+
+class PlasmaFni(bpy.types.PropertyGroup):
+ bl_idname = "world.plasma_fni"
+
+ fog_color = FloatVectorProperty(name="Fog Color",
+ description="The default fog color used in your age",
+ default=(0.3, 0.2, 0.05),
+ subtype="COLOR")
+ clear_color = FloatVectorProperty(name="Clear Color",
+ description="The default background color rendered in your age",
+ subtype="COLOR")
+ yon = IntProperty(name="Draw Distance",
+ description="The distance (in feet) Plasma will draw",
+ default=100000,
+ soft_min=100,
+ min=1)
+ # TODO: density
+
+class PlasmaPage(bpy.types.PropertyGroup):
+ def _check_suffix(self, context):
+ """Verifies that a suffix change does not conflict"""
+ old = self.last_seq_suffix
+ self.last_seq_suffix = self.seq_suffix
+ if not self.check_suffixes:
+ return None
+
+ for page in context.world.plasma_age.pages:
+ if page.seq_suffix == self.seq_suffix:
+ # Need to supress checking while we override the suffix
+ page.check_suffixes = False
+ page.seq_suffix = old
+ page.check_suffixes = True
+ break
+ return None
+
+ def _rename_page(self, context):
+ # Need to init?
+ if self.last_name == "" and self.name:
+ self.last_name = self.name
+ return None
+
+ # Empty page names not allowed!
+ if self.name == "":
+ self.make_default_name(self.seq_suffix)
+ return None
+
+ # Since many objects will have page names attached to them, we'll be
+ # very nice and handle renames for the user.
+ for obj in bpy.data.objects:
+ if obj.plasma_object.page == self.last_name:
+ obj.plasma_object.page = self.name
+ self.last_name = self.name
+ return None
+
+ def make_default_name(self, suffix):
+ self.seq_suffix = suffix
+ self.name = "Page%02i" % suffix
+ self.check_suffixes = True
+
+ name = StringProperty(name="Name",
+ description="Name of the specified page",
+ update=_rename_page)
+ seq_suffix = IntProperty(name="ID",
+ description="A numerical ID for this page",
+ soft_min=0, # Negatives indicate global--advanced users only
+ default=0, # The add operator will autogen a default
+ update=_check_suffix)
+ auto_load = BoolProperty(name="Auto Load",
+ description="Load this page on link-in",
+ default=True)
+
+ # Implementation details...
+ last_name = StringProperty(description="INTERNAL: Cached page name",
+ options={"HIDDEN"})
+ last_seq_suffix = IntProperty(description="INTERNAL: Cached sequence suffix",
+ options={"HIDDEN"})
+ check_suffixes = BoolProperty(description="INTERNAL: Should we sanity-check suffixes?",
+ options={"HIDDEN"},
+ default=False)
+
+
+class PlasmaAge(bpy.types.PropertyGroup):
+ day_length = FloatProperty(name="Day Length",
+ description="Length of a day (in hours) on this age",
+ default=24.0,
+ soft_min=0.1,
+ min=0.0)
+ seq_prefix = IntProperty(name="Sequence Prefix",
+ description="A unique numerical ID for this age",
+ soft_min=0, # Negative indicates global--advanced users only
+ default=100)
+ pages = CollectionProperty(name="Pages",
+ description="Registry pages for this age",
+ type=PlasmaPage)
+
+ # Implementation details
+ active_page_index = IntProperty(name="Active Page Index")
\ No newline at end of file
diff --git a/korman/ui/__init__.py b/korman/ui/__init__.py
new file mode 100644
index 0000000..00688be
--- /dev/null
+++ b/korman/ui/__init__.py
@@ -0,0 +1,17 @@
+# 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 .
+
+from .ui_object import *
+from .ui_world import *
diff --git a/korman/ui/ui_object.py b/korman/ui/ui_object.py
new file mode 100644
index 0000000..895d201
--- /dev/null
+++ b/korman/ui/ui_object.py
@@ -0,0 +1,40 @@
+# 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 .
+
+import bpy
+
+class ObjectButtonsPanel:
+ bl_space_type = "PROPERTIES"
+ bl_region_type = "WINDOW"
+ bl_context = "object"
+
+ @classmethod
+ def poll(cls, context):
+ return context.object and context.scene.render.engine == "PLASMA_GAME"
+
+
+class PlasmaObjectPanel(ObjectButtonsPanel, bpy.types.Panel):
+ bl_label = "Plasma Object"
+
+ def draw_header(self, context):
+ self.layout.prop(context.object.plasma_object, "export", text="")
+
+ def draw(self, context):
+ layout = self.layout
+ pl_obj = context.object.plasma_object
+ pl_age = context.scene.world.plasma_age
+ layout.active = pl_obj.export
+
+ layout.prop_search(pl_obj, "page", pl_age, "pages", icon="BOOKMARKS")
diff --git a/korman/ui/ui_world.py b/korman/ui/ui_world.py
new file mode 100644
index 0000000..6af9b1f
--- /dev/null
+++ b/korman/ui/ui_world.py
@@ -0,0 +1,69 @@
+# 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 .
+
+import bpy
+
+class AgeButtonsPanel:
+ bl_space_type = "PROPERTIES"
+ bl_region_type = "WINDOW"
+ bl_context = "world"
+
+ @classmethod
+ def poll(cls, context):
+ return context.world and context.scene.render.engine == "PLASMA_GAME"
+
+
+class PlasmaAgePanel(AgeButtonsPanel, bpy.types.Panel):
+ bl_label = "Plasma Age"
+
+ def draw(self, context):
+ layout = self.layout
+ age = context.world.plasma_age
+
+ # Core age settings
+ # ...
+
+ # We want a list of pages and an editor below that
+ row = layout.row()
+ row.template_list(age, "pages", age, "active_page_index", rows=2)
+ col = row.column(align=True)
+ col.operator("world.plasma_page_add", icon="ZOOMIN", text="")
+ col.operator("world.plasma_page_remove", icon="ZOOMOUT", text="")
+
+ # name/id editor for current selection
+ if age.active_page_index < len(age.pages):
+ active_page = age.pages[age.active_page_index]
+ split = layout.split(percentage=0.65)
+ col = split.column()
+ col.prop(active_page, "name")
+ col = split.column()
+ col.prop(active_page, "seq_suffix")
+
+
+class PlasmaEnvironmentPanel(AgeButtonsPanel, bpy.types.Panel):
+ bl_label = "Plasma Environment"
+
+ def draw(self, context):
+ layout = self.layout
+ fni = context.world.plasma_fni
+
+ # Column-ize the colors
+ split = layout.split()
+ col = split.column()
+ col.prop(fni, "fog_color")
+ col = split.column()
+ col.prop(fni, "clear_color")
+
+ layout.prop(fni, "yon")