diff --git a/korman/operators/op_export.py b/korman/operators/op_export.py
index d65ee5c..49029c3 100644
--- a/korman/operators/op_export.py
+++ b/korman/operators/op_export.py
@@ -20,8 +20,7 @@ from pathlib import Path
import pstats
from .. import exporter
-from ..properties.prop_world import PlasmaAge
-from ..properties.modifiers.logic import game_versions
+from ..properties.prop_world import PlasmaAge, game_versions
from ..korlib import ConsoleToggler
class ExportOperator(bpy.types.Operator):
@@ -84,8 +83,7 @@ class ExportOperator(bpy.types.Operator):
@classmethod
def poll(cls, context):
- if context.object is not None:
- return context.scene.render.engine == "PLASMA_GAME"
+ return context.scene.render.engine == "PLASMA_GAME"
def execute(self, context):
# Before we begin, do some basic sanity checking...
@@ -133,7 +131,7 @@ class ExportOperator(bpy.types.Operator):
if not self.filepath:
blend_filepath = context.blend_data.filepath
if not blend_filepath:
- blend_filepath = "Korman"
+ blend_filepath = context.scene.world.plasma_age.age_name
self.filepath = str(Path(blend_filepath).with_suffix(".age"))
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
diff --git a/korman/operators/op_world.py b/korman/operators/op_world.py
index 93b79d2..7affe66 100644
--- a/korman/operators/op_world.py
+++ b/korman/operators/op_world.py
@@ -14,7 +14,8 @@
# along with Korman. If not, see .
import bpy
-
+from bpy.props import *
+from pathlib import Path
class AgeOperator:
@classmethod
@@ -22,6 +23,70 @@ class AgeOperator:
return context.scene.render.engine == "PLASMA_GAME"
+class GameAddOperator(AgeOperator, bpy.types.Operator):
+ bl_idname = "world.plasma_game_add"
+ bl_label = "Add Plasma Game"
+
+ filepath = StringProperty(subtype="DIR_PATH")
+ directory = BoolProperty(default=True, options={"HIDDEN"})
+ game_index = IntProperty(default=-1, options={"HIDDEN"})
+
+ def execute(self, context):
+ w = context.world
+ if w:
+ # First, verify this is a valid Uru directory...
+ path = Path(self.filepath)
+
+ # Blendsucks likes to tack filenames onto our doggone directories...
+ if not path.is_dir():
+ path = path.parent
+ if not ((path / "UruExplorer.exe").is_file() or (path / "plClient.exe").is_file()):
+ self.report({"ERROR"}, "The selected directory is not a copy of URU.")
+ return {"CANCELLED"}
+
+ # New game?
+ games = w.plasma_games
+ new_game = self.game_index == -1
+ if new_game:
+ games.active_game_index = len(games.games)
+ game = games.games.add()
+ else:
+ game = games.games[self.game_index]
+
+ # Setup game...
+ game.path = str(path)
+ if (path / "cypython22.dll").is_file():
+ game.version = "pvPots"
+ else:
+ game.version = "pvMoul"
+ game.name = path.name
+
+ return {"FINISHED"}
+ else:
+ return {"CANCELLED"}
+
+
+ def invoke(self, context, event):
+ context.window_manager.fileselect_add(self)
+ return {"RUNNING_MODAL"}
+
+
+class GameRemoveOperator(AgeOperator, bpy.types.Operator):
+ bl_idname = "world.plasma_game_remove"
+ bl_label = "Remove Plasma Game"
+
+ def execute(self, context):
+ w = context.world
+ if w:
+ games = w.plasma_games
+ if games.active_game_index >= len(games.games):
+ return {"CANCELLED"}
+ games.games.remove(games.active_game_index)
+ return {"FINISHED"}
+ else:
+ return {"CANCELLED"}
+
+
class PageAddOperator(AgeOperator, bpy.types.Operator):
bl_idname = "world.plasma_page_add"
bl_label = "Add Page"
diff --git a/korman/properties/__init__.py b/korman/properties/__init__.py
index b24bb8e..dc98a70 100644
--- a/korman/properties/__init__.py
+++ b/korman/properties/__init__.py
@@ -29,3 +29,4 @@ def register():
bpy.types.Texture.plasma_layer = bpy.props.PointerProperty(type=PlasmaLayer)
bpy.types.World.plasma_age = bpy.props.PointerProperty(type=PlasmaAge)
bpy.types.World.plasma_fni = bpy.props.PointerProperty(type=PlasmaFni)
+ bpy.types.World.plasma_games = bpy.props.PointerProperty(type=PlasmaGames)
diff --git a/korman/properties/modifiers/logic.py b/korman/properties/modifiers/logic.py
index 339fd9e..2dea10e 100644
--- a/korman/properties/modifiers/logic.py
+++ b/korman/properties/modifiers/logic.py
@@ -18,13 +18,10 @@ from bpy.props import *
from PyHSPlasma import *
from .base import PlasmaModifierProperties
+from ..prop_world import game_versions
from ...exporter import ExportError
from ... import idprops
-game_versions = [("pvPrime", "Ages Beyond Myst (63.11)", "Targets the original Uru (Live) game"),
- ("pvPots", "Path of the Shell (63.12)", "Targets the most recent offline expansion pack"),
- ("pvMoul", "Myst Online: Uru Live (70)", "Targets the most recent online game")]
-
class PlasmaVersionedNodeTree(idprops.IDPropMixin, bpy.types.PropertyGroup):
name = StringProperty(name="Name")
version = EnumProperty(name="Version",
diff --git a/korman/properties/prop_world.py b/korman/properties/prop_world.py
index badba65..5e4308d 100644
--- a/korman/properties/prop_world.py
+++ b/korman/properties/prop_world.py
@@ -17,6 +17,9 @@ import bpy
from bpy.props import *
from PyHSPlasma import *
+game_versions = [("pvPrime", "Ages Beyond Myst (63.11)", "Targets the original Uru (Live) game"),
+ ("pvPots", "Path of the Shell (63.12)", "Targets the most recent offline expansion pack"),
+ ("pvMoul", "Myst Online: Uru Live (70)", "Targets the most recent online game")]
class PlasmaFni(bpy.types.PropertyGroup):
bl_idname = "world.plasma_fni"
@@ -55,6 +58,36 @@ class PlasmaFni(bpy.types.PropertyGroup):
min=1)
+class PlasmaGame(bpy.types.PropertyGroup):
+ name = StringProperty(name="Name",
+ description="Name of the Plasma Game",
+ options=set())
+ path = StringProperty(name="Path",
+ description="Path to this Plasma Game",
+ options=set())
+ version = EnumProperty(name="Version",
+ description="Plasma version of this game",
+ items=game_versions,
+ options=set())
+
+
+class PlasmaGames(bpy.types.PropertyGroup):
+ bl_idname = "world.plasma_games"
+
+ games = CollectionProperty(type=PlasmaGame)
+ active_game_index = IntProperty(options={"HIDDEN"})
+
+ @property
+ def active_game(self):
+ if len(self.games) > self.active_game_index and self.active_game_index != -1:
+ return self.games[self.active_game_index]
+ return None
+
+ @property
+ def is_game_active(self):
+ return len(self.games) > 0 and self.active_game_index != -1
+
+
class PlasmaPage(bpy.types.PropertyGroup):
def _check_suffix(self, context):
"""Verifies that a suffix change does not conflict"""
@@ -158,6 +191,9 @@ class PlasmaAge(bpy.types.PropertyGroup):
use_texture_page = BoolProperty(name="Use Textures Page",
description="Exports all textures to a dedicated Textures page",
default=True)
+ age_name = StringProperty(name="Age Name",
+ description="Name of the Age to be used for data files",
+ options=set())
# Implementation details
active_page_index = IntProperty(name="Active Page Index")
diff --git a/korman/ui/ui_world.py b/korman/ui/ui_world.py
index 3b51392..6452855 100644
--- a/korman/ui/ui_world.py
+++ b/korman/ui/ui_world.py
@@ -14,6 +14,9 @@
# along with Korman. If not, see .
import bpy
+from pathlib import Path
+
+from ..korlib import ConsoleToggler
class AgeButtonsPanel:
@@ -26,6 +29,49 @@ class AgeButtonsPanel:
return context.world and context.scene.render.engine == "PLASMA_GAME"
+class PlasmaGamePanel(AgeButtonsPanel, bpy.types.Panel):
+ bl_label = "Plasma Games"
+
+ def draw(self, context):
+ layout = self.layout
+ games = context.world.plasma_games
+ age = context.world.plasma_age
+
+ row = layout.row()
+ row.template_list("PlasmaGameList", "games", games, "games", games,
+ "active_game_index", rows=2)
+ col = row.column(align=True)
+ col.operator("world.plasma_game_add", icon="ZOOMIN", text="")
+ col.operator("world.plasma_game_remove", icon="ZOOMOUT", text="")
+
+ # Game Properties
+ active_game_index = games.active_game_index
+ if active_game_index < len(games.games):
+ active_game = games.games[active_game_index]
+
+ layout.separator()
+ box = layout.box()
+
+ box.prop(active_game, "path", emboss=False)
+ box.prop(active_game, "version")
+ box.separator()
+
+ row = box.row(align=True)
+ op = row.operator("world.plasma_game_add", icon="FILE_FOLDER", text="Change Path")
+ op.filepath = active_game.path
+ op.game_index = active_game_index
+ row = row.row(align=True)
+ row.operator_context = "EXEC_DEFAULT"
+ row.enabled = bool(age.age_name.strip())
+ op = row.operator("export.plasma_age", icon="EXPORT")
+ op.filepath = str((Path(active_game.path) / "dat" / age.age_name).with_suffix(".age"))
+
+
+class PlasmaGameList(bpy.types.UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
+ layout.prop(item, "name", text="", emboss=False, icon="BOOKMARKS")
+
+
class PlasmaPageList(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_property, index=0, flt_flag=0):
layout.prop(item, "name", text="", emboss=False, icon="BOOKMARKS")
@@ -77,10 +123,27 @@ class PlasmaAgePanel(AgeButtonsPanel, bpy.types.Panel):
col = split.column()
col.label("Age Settings:")
col.prop(age, "seq_prefix", text="ID")
+ col.alert = not age.age_name.strip()
+ col.prop(age, "age_name", text="")
+
+ layout.separator()
+ split = layout.split()
+
+ col = split.column()
+ col.label("Export Settings:")
+ col.prop(age, "bake_lighting")
+ cons_ui = col.column()
+ cons_ui.enabled = ConsoleToggler.is_platform_supported()
+ cons_ui.prop(age, "verbose")
+ cons_ui.prop(age, "show_console")
+
+ col = split.column()
+ col.label("Plasma Settings:")
col.prop(age, "age_sdl")
col.prop(age, "use_texture_page")
+
class PlasmaEnvironmentPanel(AgeButtonsPanel, bpy.types.Panel):
bl_label = "Plasma Environment"