You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

177 lines
6.8 KiB

# 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 pathlib import Path
from PyHSPlasma import *
from .explosions import ExportError
from . import logger
from .. import korlib
from ..plasma_magic import plasma_python_glue, very_very_special_python
class PythonPackageExporter:
def __init__(self, filepath, version):
self._filepath = filepath
self._modules = {}
self._pfms = {}
self._version = version
def _compyle(self, report):
report.progress_advance()
report.progress_range = len(self._modules) + len(self._pfms)
inc_progress = report.progress_increment
age = bpy.context.scene.world.plasma_age
Text = bpy.types.Text
if self._version <= pvPots:
py_version = (2, 2)
else:
py_version = (2, 3)
py_code = []
for filename, source in self._pfms.items():
if isinstance(source, Text):
if not source.plasma_text.package and age.python_method != "all":
inc_progress()
continue
code = source.as_string()
else:
code = source
code = "{}\n\n{}\n".format(code, plasma_python_glue)
success, result = korlib.compyle(filename, code, py_version, report)
if not success:
raise ExportError("Failed to compyle '{}':\n{}".format(filename, result))
py_code.append((filename, result))
inc_progress()
for filename, source in self._modules.items():
if isinstance(source, Text):
if not source.plasma_text.package and age.python_method != "all":
inc_progress()
continue
code = source.as_string()
else:
code = source
# no glue needed here, ma!
success, result = korlib.compyle(filename, code, py_version, report)
if not success:
raise ExportError("Failed to compyle '{}':\n{}".format(filename, result))
py_code.append((filename, result))
inc_progress()
# man that was ugly...
return py_code
def _ensure_age_sdl_hook(self, report):
age_props = bpy.context.scene.world.plasma_age
if age_props.age_sdl:
fixed_agename = korlib.replace_python2_identifier(age_props.age_name)
py_filename = "{}.py".format(fixed_agename)
age_py = self._modules.get(py_filename)
if age_py is not None:
del self._modules[py_filename]
if age_py.plasma_text.package or age.python_method == "all":
self._pfms[py_filename] = age_py
else:
report.warn("AgeSDL Python Script provided, but not requested for packing... Using default Python.")
self._pfms[py_filename] = very_very_special_python.format(age_name=fixed_agename)
else:
report.msg("Packing default AgeSDL Python")
very_very_special_python.format(age_name=age_props.age_name)
self._pfms[py_filename] = very_very_special_python.format(age_name=fixed_agename)
def _harvest_pfms(self, report):
objects = bpy.context.scene.objects
report.progress_advance()
report.progress_range = len(objects)
inc_progress = report.progress_increment
for i in objects:
logic = i.plasma_modifiers.advanced_logic
if i.plasma_object.enabled and logic.enabled:
for j in logic.logic_groups:
tree_versions = (globals()[version] for version in j.version)
if self._version in tree_versions:
self._harvest_tree(j.node_tree)
inc_progress()
def _harvest_modules(self, report):
texts = bpy.data.texts
report.progress_advance()
report.progress_range = len(texts)
inc_progress = report.progress_increment
for i in texts:
if i.name.endswith(".py") and i.name not in self._pfms:
self._modules.setdefault(i.name, i)
inc_progress()
def _harvest_tree(self, tree):
# Search the node tree for any python file nodes. Any that we find are PFMs
for i in tree.nodes:
if i.bl_idname == "PlasmaPythonFileNode":
if i.filename and i.text_id:
self._pfms.setdefault(i.filename, i.text_id)
def run(self):
"""Runs a stripped-down version of the Exporter that only handles Python files"""
age_props = bpy.context.scene.world.plasma_age
log = logger.ExportVerboseLogger if age_props.verbose else logger.ExportProgressLogger
with korlib.ConsoleToggler(age_props.show_console), log(self._filepath) as report:
report.progress_add_step("Harvesting Plasma PythonFileMods")
report.progress_add_step("Harvesting Helper Python Modules")
report.progress_add_step("Compyling Python Code")
report.progress_add_step("Packing Compyled Code")
report.progress_start("PACKING PYTHON")
# Harvest the Python code
self._harvest_pfms(report)
self._harvest_modules(report)
self._ensure_age_sdl_hook(report)
# Compyle and package the Python
self._package_python(report)
# DONE
report.progress_end()
report.raise_errors()
def _package_python(self, report):
py_code = self._compyle(report)
if not py_code:
report.error("No Python files were packaged.")
self._write_python_pak(py_code, report)
def _write_python_pak(self, py_code, report):
report.progress_advance()
if self._version == pvEoa:
enc = plEncryptedStream.kEncAes
elif self._version == pvMoul:
enc = None
else:
enc = plEncryptedStream.kEncXtea
if enc is None:
stream = hsFileStream(self._version).open(self._filepath, fmCreate)
else:
stream = plEncryptedStream(self._version).open(self._filepath, fmCreate, enc)
try:
korlib.package_python(stream, py_code)
finally:
stream.close()