|
|
|
# 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 bpy.props import *
|
|
|
|
from . import korlib
|
|
|
|
|
|
|
|
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 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())
|
|
|
|
|
|
|
|
player = StringProperty(name="Player",
|
|
|
|
description="Name of the player to use when launching the game",
|
|
|
|
options=set())
|
|
|
|
ki = IntProperty(name="KI",
|
|
|
|
description="KI Number of the player to use when launching the game",
|
|
|
|
options=set(), min=0)
|
|
|
|
serverini = StringProperty(name="Server INI",
|
|
|
|
description="Name of the server configuation to use when launching the game",
|
|
|
|
options=set())
|
|
|
|
|
|
|
|
@property
|
|
|
|
def can_launch(self):
|
|
|
|
if self.version == "pvMoul":
|
|
|
|
return self.is_property_set("ki") and self.ki
|
|
|
|
else:
|
|
|
|
return self.is_property_set("player") and bool(self.player.strip())
|
|
|
|
|
|
|
|
|
|
|
|
class KormanAddonPreferences(bpy.types.AddonPreferences):
|
|
|
|
bl_idname = __package__
|
|
|
|
|
|
|
|
games = CollectionProperty(type=PlasmaGame)
|
|
|
|
active_game_index = IntProperty(options={"SKIP_SAVE"})
|
|
|
|
|
|
|
|
def _check_py22_exe(self, context):
|
|
|
|
if self._ensure_abspath((2, 2)):
|
|
|
|
self._check_python((2, 2))
|
|
|
|
def _check_py23_exe(self, context):
|
|
|
|
if self._ensure_abspath((2, 3)):
|
|
|
|
self._check_python((2, 3))
|
|
|
|
def _check_py27_exe(self, context):
|
|
|
|
if self._ensure_abspath((2, 7)):
|
|
|
|
self._check_python((2, 7))
|
|
|
|
|
|
|
|
python22_executable = StringProperty(name="Python 2.2",
|
|
|
|
description="Path to the Python 2.2 executable",
|
|
|
|
options=set(),
|
|
|
|
subtype="FILE_PATH",
|
|
|
|
update=_check_py22_exe)
|
|
|
|
python23_executable = StringProperty(name="Python 2.3",
|
|
|
|
description="Path to the Python 2.3 executable",
|
|
|
|
options=set(),
|
|
|
|
subtype="FILE_PATH",
|
|
|
|
update=_check_py23_exe)
|
|
|
|
python27_executable = StringProperty(name="Python 2.7",
|
|
|
|
description="Path to the Python 2.7 executable",
|
|
|
|
options=set(),
|
|
|
|
subtype="FILE_PATH",
|
|
|
|
update=_check_py27_exe)
|
|
|
|
|
|
|
|
def _validate_py_exes(self):
|
|
|
|
if not self.is_property_set("python22_valid"):
|
|
|
|
self._check_python((2, 2))
|
|
|
|
if not self.is_property_set("python23_valid"):
|
|
|
|
self._check_python((2, 3))
|
|
|
|
if not self.is_property_set("python27_valid"):
|
|
|
|
self._check_python((2, 7))
|
|
|
|
return True
|
|
|
|
|
|
|
|
# Internal error states
|
|
|
|
python22_valid = BoolProperty(options={"HIDDEN", "SKIP_SAVE"})
|
|
|
|
python23_valid = BoolProperty(options={"HIDDEN", "SKIP_SAVE"})
|
|
|
|
python27_valid = BoolProperty(options={"HIDDEN", "SKIP_SAVE"})
|
|
|
|
python_validated = BoolProperty(get=_validate_py_exes, options={"HIDDEN", "SKIP_SAVE"})
|
|
|
|
|
|
|
|
def _check_python(self, py_version):
|
|
|
|
py_exe = getattr(self, "python{}{}_executable".format(*py_version))
|
|
|
|
if py_exe:
|
|
|
|
valid = korlib.verify_python(py_version, py_exe)
|
|
|
|
else:
|
|
|
|
valid = True
|
|
|
|
setattr(self, "python{}{}_valid".format(*py_version), valid)
|
|
|
|
|
|
|
|
def _ensure_abspath(self, py_version):
|
|
|
|
attr = "python{}{}_executable".format(*py_version)
|
|
|
|
path = getattr(self, attr)
|
|
|
|
if path.startswith("//"):
|
|
|
|
setattr(self, attr, bpy.path.abspath(path))
|
|
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
|
|
def draw(self, context):
|
|
|
|
layout = self.layout
|
|
|
|
split = layout.split()
|
|
|
|
main_col = split.column()
|
|
|
|
|
|
|
|
main_col.label("Plasma Games:")
|
|
|
|
row = main_col.row()
|
|
|
|
row.template_list("PlasmaGameListRW", "games", self, "games", self,
|
|
|
|
"active_game_index", rows=3)
|
|
|
|
col = row.column(align=True)
|
|
|
|
col.operator("world.plasma_game_add", icon="ZOOMIN", text="")
|
|
|
|
col.operator("world.plasma_game_remove", icon="ZOOMOUT", text="")
|
|
|
|
col.operator("world.plasma_game_convert", icon="IMPORT", text="")
|
|
|
|
|
|
|
|
# Game Properties
|
|
|
|
active_game_index = self.active_game_index
|
|
|
|
if bool(self.games) and active_game_index < len(self.games):
|
|
|
|
active_game = self.games[active_game_index]
|
|
|
|
|
|
|
|
col = split.column()
|
|
|
|
col.label("Game Configuration:")
|
|
|
|
box = col.box().column()
|
|
|
|
|
|
|
|
row = box.row(align=True)
|
|
|
|
row.prop(active_game, "path")
|
|
|
|
op = row.operator("world.plasma_game_add", icon="FILE_FOLDER", text="")
|
|
|
|
op.filepath = active_game.path
|
|
|
|
op.game_index = active_game_index
|
|
|
|
box.prop(active_game, "version")
|
|
|
|
|
|
|
|
box.separator()
|
|
|
|
box.separator()
|
|
|
|
if active_game.version == "pvMoul":
|
|
|
|
box.alert = not active_game.is_property_set("ki")
|
|
|
|
box.prop(active_game, "ki", slider=False)
|
|
|
|
box.alert = False
|
|
|
|
box.prop(active_game, "serverini")
|
|
|
|
else:
|
|
|
|
box.alert = not active_game.is_property_set("player")
|
|
|
|
box.prop(active_game, "player")
|
|
|
|
|
|
|
|
# Python Installs
|
|
|
|
assert self.python_validated
|
|
|
|
col = layout.column()
|
|
|
|
col.label("Python Executables:")
|
|
|
|
col.alert = not self.python22_valid
|
|
|
|
col.prop(self, "python22_executable")
|
|
|
|
col.alert = not self.python23_valid
|
|
|
|
col.prop(self, "python23_executable")
|
|
|
|
col.alert = not self.python27_valid
|
|
|
|
col.prop(self, "python27_executable")
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def register(cls):
|
|
|
|
# Register the old-timey per-world Plasma Games for use in the conversion
|
|
|
|
# operator. What fun. I guess....
|
|
|
|
from .properties.prop_world import PlasmaGames
|
|
|
|
PlasmaGames.games = CollectionProperty(type=PlasmaGame)
|