|
|
|
# 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 PyHSPlasma import *
|
|
|
|
|
|
|
|
from .node_core import PlasmaNodeBase, PlasmaNodeSocketBase, PlasmaTreeOutputNodeBase
|
|
|
|
from .. import idprops
|
|
|
|
|
|
|
|
class PlasmaSoftVolumeOutputNode(PlasmaTreeOutputNodeBase, bpy.types.Node):
|
|
|
|
bl_category = "SV"
|
|
|
|
bl_idname = "PlasmaSoftVolumeOutputNode"
|
|
|
|
bl_label = "Soft Volume Output"
|
|
|
|
|
|
|
|
input_sockets: dict[str, dict[str, str]] = {
|
|
|
|
"input": {
|
|
|
|
"text": "Final Volume",
|
|
|
|
"type": "PlasmaSoftVolumeNodeSocket",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
def get_key(self, exporter, so):
|
|
|
|
svNode = self.find_input("input")
|
|
|
|
if svNode is not None:
|
|
|
|
return svNode.get_key(exporter, so)
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
class PlasmaSoftVolumeNodeSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket):
|
|
|
|
bl_color = (0.133, 0.094, 0.345, 1.0)
|
|
|
|
class PlasmaSoftVolumePropertiesNodeSocket(PlasmaNodeSocketBase, bpy.types.NodeSocket):
|
|
|
|
bl_color = (0.067, 0.40, 0.067, 1.0)
|
|
|
|
|
|
|
|
|
|
|
|
class PlasmaSoftVolumePropertiesNode(PlasmaNodeBase, bpy.types.Node):
|
|
|
|
bl_category = "SV"
|
|
|
|
bl_idname = "PlasmaSoftVolumePropertiesNode"
|
|
|
|
bl_label = "Soft Volume Properties"
|
|
|
|
|
|
|
|
output_sockets: dict[str, dict[str, str]] = {
|
|
|
|
"target": {
|
|
|
|
"text": "Volume",
|
|
|
|
"type": "PlasmaSoftVolumePropertiesNodeSocket"
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
inside_strength = IntProperty(name="Inside", description="Strength inside the region",
|
|
|
|
subtype="PERCENTAGE", default=100, min=0, max=100)
|
|
|
|
outside_strength = IntProperty(name="Outside", description="Strength outside the region",
|
|
|
|
subtype="PERCENTAGE", default=0, min=0, max=100)
|
|
|
|
|
|
|
|
def draw_buttons(self, context, layout):
|
|
|
|
layout.prop(self, "inside_strength")
|
|
|
|
layout.prop(self, "outside_strength")
|
|
|
|
|
|
|
|
def propagate(self, softvolume):
|
|
|
|
softvolume.insideStrength = self.inside_strength / 100
|
|
|
|
softvolume.outsideStrength = self.outside_strength / 100
|
|
|
|
|
|
|
|
|
|
|
|
class PlasmaSoftVolumeReferenceNode(idprops.IDPropObjectMixin, PlasmaNodeBase, bpy.types.Node):
|
|
|
|
bl_category = "SV"
|
|
|
|
bl_idname = "PlasmaSoftVolumeReferenceNode"
|
|
|
|
bl_label = "Soft Region"
|
|
|
|
bl_width_default = 150
|
|
|
|
|
|
|
|
output_sockets: dict[str, dict[str, str]] = {
|
|
|
|
"output": {
|
|
|
|
"text": "Volume",
|
|
|
|
"type": "PlasmaSoftVolumeNodeSocket"
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
soft_volume = PointerProperty(name="Soft Volume",
|
|
|
|
description="Object whose Soft Volume modifier we should use",
|
|
|
|
type=bpy.types.Object,
|
|
|
|
poll=idprops.poll_softvolume_objects)
|
|
|
|
|
|
|
|
def draw_buttons(self, context, layout):
|
|
|
|
layout.prop(self, "soft_volume", text="")
|
|
|
|
|
|
|
|
def get_key(self, exporter, so):
|
|
|
|
if self.soft_volume is None:
|
|
|
|
self.raise_error("Invalid SoftVolume object reference")
|
|
|
|
# Don't use SO here because that's the tree owner's SO. This soft region will find or create
|
|
|
|
# its own SceneObject. Yay!
|
|
|
|
return self.soft_volume.plasma_modifiers.softvolume.get_key(exporter)
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def _idprop_mapping(cls):
|
|
|
|
return {"soft_volume": "soft_object"}
|
|
|
|
|
|
|
|
|
|
|
|
class PlasmaSoftVolumeInvertNode(PlasmaNodeBase, bpy.types.Node):
|
|
|
|
bl_category = "SV"
|
|
|
|
bl_idname = "PlasmaSoftVolumeInvertNode"
|
|
|
|
bl_label = "Soft Volume Invert"
|
|
|
|
|
|
|
|
# The only difference between this and PlasmaSoftVolumeLinkNode is this can only have ONE input
|
|
|
|
input_sockets: dict[str, dict[str, str]] = {
|
|
|
|
"properties": {
|
|
|
|
"text": "Properties",
|
|
|
|
"type": "PlasmaSoftVolumePropertiesNodeSocket",
|
|
|
|
},
|
|
|
|
"input": {
|
|
|
|
"text": "Input Volume",
|
|
|
|
"type": "PlasmaSoftVolumeNodeSocket",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
output_sockets: dict[str, dict[str, str]] = {
|
|
|
|
"output": {
|
|
|
|
"text": "Volume",
|
|
|
|
"type": "PlasmaSoftVolumeNodeSocket"
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
def get_key(self, exporter, so):
|
|
|
|
return self._find_create_key(plSoftVolumeInvert, exporter, so=so)
|
|
|
|
|
|
|
|
def export(self, exporter, bo, so):
|
|
|
|
parent = self.find_input("input")
|
|
|
|
if parent is None:
|
|
|
|
self.raise_error("SoftVolume Invert requires an input volume!")
|
|
|
|
|
|
|
|
sv = self.get_key(exporter, so).object
|
|
|
|
sv.addSubVolume(parent.get_key(exporter, so))
|
|
|
|
|
|
|
|
props = self.find_input("properties")
|
|
|
|
if props is not None:
|
|
|
|
props.propagate(sv)
|
|
|
|
else:
|
|
|
|
sv.insideStrength = 1.0
|
|
|
|
sv.outsideStrength = 0.0
|
|
|
|
|
|
|
|
@property
|
|
|
|
def export_once(self):
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
class PlasmaSoftVolumeLinkNode(PlasmaNodeBase):
|
|
|
|
input_sockets: dict[str, any] = {
|
|
|
|
"properties": {
|
|
|
|
"text": "Properties",
|
|
|
|
"type": "PlasmaSoftVolumePropertiesNodeSocket",
|
|
|
|
},
|
|
|
|
"input": {
|
|
|
|
"text": "Input Volume",
|
|
|
|
"type": "PlasmaSoftVolumeNodeSocket",
|
|
|
|
"spawn_empty": True,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
output_sockets: dict[str, dict[str, str]] = {
|
|
|
|
"output": {
|
|
|
|
"text": "Volume",
|
|
|
|
"type": "PlasmaSoftVolumeNodeSocket"
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
def export(self, exporter, bo, so):
|
|
|
|
sv = self.get_key(exporter, so).object
|
|
|
|
for node in self.find_inputs("input"):
|
|
|
|
sv.addSubVolume(node.get_key(exporter, so))
|
|
|
|
|
|
|
|
props = self.find_input("properties")
|
|
|
|
if props is not None:
|
|
|
|
props.propagate(sv)
|
|
|
|
else:
|
|
|
|
sv.insideStrength = 1.0
|
|
|
|
sv.outsideStrength = 0.0
|
|
|
|
|
|
|
|
@property
|
|
|
|
def export_once(self):
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
class PlasmaSoftVolumeIntersectNode(PlasmaSoftVolumeLinkNode, bpy.types.Node):
|
|
|
|
bl_category = "SV"
|
|
|
|
bl_idname = "PlasmaSoftVolumeIntersectNode"
|
|
|
|
bl_label = "Soft Volume Intersect"
|
|
|
|
|
|
|
|
def get_key(self, exporter, so):
|
|
|
|
## FIXME: SoftVolumeIntersect should not be listed as an interface
|
|
|
|
return self._find_create_key(plSoftVolumeIntersect, exporter, so=so)
|
|
|
|
|
|
|
|
|
|
|
|
class PlasmaSoftVolumeUnionNode(PlasmaSoftVolumeLinkNode, bpy.types.Node):
|
|
|
|
bl_category = "SV"
|
|
|
|
bl_idname = "PlasmaSoftVolumeUnionNode"
|
|
|
|
bl_label = "Soft Volume Union"
|
|
|
|
|
|
|
|
def get_key(self, exporter, so):
|
|
|
|
## FIXME: SoftVolumeUnion should not be listed as an interface
|
|
|
|
return self._find_create_key(plSoftVolumeUnion, exporter, so=so)
|