From 39a3a88bb828f7e14ecc2a3039c285ddbe86688c Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 6 Jan 2021 10:27:28 -0500 Subject: [PATCH 1/2] Ensure PFM-related lights are marked animated. --- korman/exporter/manager.py | 8 ++++++ korman/nodes/node_python.py | 52 +++++++++++++++++++++++++------------ 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/korman/exporter/manager.py b/korman/exporter/manager.py index f62672c..859420a 100644 --- a/korman/exporter/manager.py +++ b/korman/exporter/manager.py @@ -16,6 +16,7 @@ import bpy from pathlib import Path from PyHSPlasma import * +from typing import Iterable import weakref from . import explosions @@ -190,6 +191,13 @@ class ExportManager: else: return plEncryptedStream.kEncXtea + def find_interfaces(self, pClass, so : plSceneObject) -> Iterable[plObjInterface]: + assert issubclass(pClass, plObjInterface) + + for i in (i.object for i in so.interfaces): + if isinstance(i, pClass): + yield i + def find_create_key(self, pClass, bl=None, name=None, so=None): key = self.find_key(pClass, bl, name, so) if key is None: diff --git a/korman/nodes/node_python.py b/korman/nodes/node_python.py index 9b9dcbc..c758b3e 100644 --- a/korman/nodes/node_python.py +++ b/korman/nodes/node_python.py @@ -256,6 +256,10 @@ class PlasmaPythonFileNode(PlasmaVersionedNode, bpy.types.Node): def export(self, exporter, bo, so): pfm = self.get_key(exporter, so).object + # Special PFM-SO handling ahoy - be sure to do it for all objects this PFM is attached to. + # Otherwise, you get non-determinant behavior. + self._export_ancillary_sceneobject(exporter, so) + # No need to continue if the PFM was already generated. if pfm.filename: return @@ -276,7 +280,6 @@ class PlasmaPythonFileNode(PlasmaVersionedNode, bpy.types.Node): # Handle exporting the Python Parameters attrib_sockets = (i for i in self.inputs if i.is_linked) for socket in attrib_sockets: - attrib = socket.attribute_type from_node = socket.links[0].from_node value = from_node.value if socket.is_simple_value else from_node.get_key(exporter, so) @@ -285,27 +288,42 @@ class PlasmaPythonFileNode(PlasmaVersionedNode, bpy.types.Node): for i in value: param = plPythonParameter() param.id = socket.attribute_id - param.valueType = _attrib2param[attrib] + param.valueType = _attrib2param[socket.attribute_type] param.value = i - # Key type sanity checking... Because I trust no user. if not socket.is_simple_value: - if i is None: - msg = "'{}' Node '{}' didn't return a key and therefore will be unavailable to Python".format( - self.id_data.name, from_node.name) - exporter.report.warn(msg, indent=3) - else: - key_type = _attrib_key_types[attrib] - if isinstance(key_type, tuple): - good_key = i.type in key_type - else: - good_key = i.type == key_type - if not good_key: - msg = "'{}' Node '{}' returned an unexpected key type '{}'".format( - self.id_data.name, from_node.name, plFactory.ClassName(i.type)) - exporter.report.warn(msg, indent=3) + self._export_key_attrib(exporter, bo, so, i, socket) pfm.addParameter(param) + def _export_ancillary_sceneobject(self, exporter, so : plSceneObject) -> None: + # Danger: Special case evil ahoy... + # If the key is an object that represents a lamp, we have to assume that the reason it's + # being passed to Python is so it can be turned on/off at will. That means it's technically + # an animated lamp. + for light in exporter.mgr.find_interfaces(plLightInfo, so): + exporter.report.msg("Marking RT light '{}' as animated due to usage in a Python File node", + so.key.name, indent=3) + light.setProperty(plLightInfo.kLPMovable, True) + + def _export_key_attrib(self, exporter, bo, so : plSceneObject, key : plKey, socket) -> None: + if key is None: + exporter.report.warn("Attribute '{}' didn't return a key and therefore will be unavailable to Python", + self.id_data.name, socket.links[0].name, indent=3) + return + + key_type = _attrib_key_types[socket.attribute_type] + if isinstance(key_type, tuple): + good_key = key.type in key_type + else: + good_key = key.type == key_type + if not good_key: + exporter.report.warn("'{}' Node '{}' returned an unexpected key type '{}'", + self.id_data.name, socket.links[0].from_node.name, + plFactory.ClassName(key.type), indent=3) + + if isinstance(key.object, plSceneObject): + self._export_ancillary_sceneobject(exporter, key.object) + def _get_attrib_sockets(self, idx): for i in self.inputs: if i.attribute_id == idx: From 172d8083aa81470c47dd0bc8249889a088c2d045 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Wed, 6 Jan 2021 16:53:47 -0500 Subject: [PATCH 2/2] Only set runtime colors to black if we are not preshading. Otherwise, what we wind up doing is making it pretty much impossible for RT lights to affect objects with kLiteMaterial. --- korman/exporter/material.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/korman/exporter/material.py b/korman/exporter/material.py index d2a2ba9..3013ea6 100644 --- a/korman/exporter/material.py +++ b/korman/exporter/material.py @@ -1184,7 +1184,7 @@ class MaterialConverter: return utils.color(color) def get_material_runtime(self, bo, bm, color=None) -> hsColorRGBA: - if not bo.plasma_modifiers.lighting.rt_lights: + if not bo.plasma_modifiers.lighting.preshade: return hsColorRGBA.kBlack if color is None: color = bm.diffuse_color