345 lines
12 KiB
Python
345 lines
12 KiB
Python
"""
|
|
Copyright (C) 2023 Adobe.
|
|
This program 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.
|
|
|
|
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
"""
|
|
|
|
# file: sbsar/sbsar.py
|
|
# brief: Substance class object definition
|
|
# author Adobe - 3D & Immersive
|
|
# copyright 2023 Adobe Inc. All rights reserved.
|
|
|
|
|
|
from ..utils import SUBSTANCE_Utils
|
|
from ..common import (
|
|
Code_InputType,
|
|
Code_InputWidget,
|
|
INPUT_DEFAULT_GROUP,
|
|
INPUT_IMAGE_DEFAULT_GROUP,
|
|
PRESET_CUSTOM,
|
|
CLASS_GRAPH_INPUTS
|
|
)
|
|
|
|
|
|
class SBS_EnumValue():
|
|
def __init__(self, enum):
|
|
self.first = enum["first"]
|
|
self.second = enum["second"]
|
|
|
|
def to_json(self):
|
|
_obj = {
|
|
"first": self.first,
|
|
"second": self.second,
|
|
}
|
|
return _obj
|
|
|
|
|
|
class SBS_Input():
|
|
def __init__(self, index, input):
|
|
if "index" in input:
|
|
self.index = input["index"]
|
|
else:
|
|
self.index = index
|
|
|
|
self.id = input["id"]
|
|
self.graphID = input["graphID"]
|
|
self.identifier = input["identifier"]
|
|
self.label = input["label"]
|
|
self.guiDescription = input["guiDescription"]
|
|
|
|
if input["type"] == Code_InputType.image.name:
|
|
self.guiGroup = INPUT_IMAGE_DEFAULT_GROUP
|
|
elif len(input["guiGroup"]) == 0:
|
|
self.guiGroup = INPUT_DEFAULT_GROUP
|
|
else:
|
|
self.guiGroup = input["guiGroup"]
|
|
|
|
self.guiVisibleIf = input["guiVisibleIf"]
|
|
self.userTag = input["userTag"]
|
|
self.type = input["type"]
|
|
self.guiWidget = input["guiWidget"]
|
|
self.showAsPin = input["showAsPin"]
|
|
self.useCache = input["useCache"]
|
|
self.visibleIf = input["visibleIf"]
|
|
self.isHeavyDuty = input["isHeavyDuty"]
|
|
self.enumValues = []
|
|
|
|
if "labelFalse" in input:
|
|
self.labelFalse = input["labelFalse"]
|
|
if "labelTrue" in input:
|
|
self.labelTrue = input["labelTrue"]
|
|
if "sliderClamp" in input:
|
|
self.sliderClamp = input["sliderClamp"]
|
|
if "sliderStep" in input:
|
|
self.sliderStep = input["sliderStep"]
|
|
|
|
if "maxValue" in input:
|
|
self.maxValue = input["maxValue"]
|
|
if "minValue" in input:
|
|
self.minValue = input["minValue"]
|
|
if "defaultValue" in input:
|
|
self.defaultValue = input["defaultValue"]
|
|
if "value" in input:
|
|
self.value = input["value"]
|
|
if "channelUse" in input:
|
|
self.channelUse = input["channelUse"]
|
|
|
|
if "enumValues" in input:
|
|
for _enum in input["enumValues"]:
|
|
_new_enum = SBS_EnumValue(_enum)
|
|
self.enumValues.append(_new_enum)
|
|
|
|
def to_json(self):
|
|
_obj = {
|
|
"id": self.id,
|
|
"graphID": self.graphID,
|
|
"identifier": self.identifier,
|
|
"label": self.label,
|
|
"guiDescription": self.guiDescription,
|
|
"guiGroup": self.guiGroup,
|
|
"guiVisibleIf": self.guiVisibleIf,
|
|
"userTag": self.userTag,
|
|
"type": self.type,
|
|
"guiWidget": self.guiWidget,
|
|
"showAsPin": self.showAsPin,
|
|
"useCache": self.useCache,
|
|
"visibleIf": self.visibleIf,
|
|
"isHeavyDuty": self.isHeavyDuty
|
|
}
|
|
|
|
if hasattr(self, "labelFalse"):
|
|
_obj["labelFalse"] = self.labelFalse
|
|
if hasattr(self, "labelTrue"):
|
|
_obj["labelTrue"] = self.labelTrue
|
|
if hasattr(self, "sliderClamp"):
|
|
_obj["sliderClamp"] = self.sliderClamp
|
|
if hasattr(self, "sliderStep"):
|
|
_obj["sliderStep"] = self.sliderStep
|
|
|
|
if hasattr(self, "maxValue"):
|
|
_obj["maxValue"] = self.maxValue
|
|
if hasattr(self, "minValue"):
|
|
_obj["minValue"] = self.minValue
|
|
if hasattr(self, "defaultValue"):
|
|
_obj["defaultValue"] = self.defaultValue
|
|
if hasattr(self, "value"):
|
|
_obj["value"] = self.value
|
|
if hasattr(self, "channelUse"):
|
|
_obj["channelUse"] = self.channelUse
|
|
if hasattr(self, "enumValues"):
|
|
_obj["enumValues"] = self.enumValues
|
|
|
|
return _obj
|
|
|
|
|
|
class SBS_Output():
|
|
def __init__(self, output, index):
|
|
self.id = output["id"]
|
|
self.index = index
|
|
self.graphID = output["graphID"]
|
|
self.format = output["format"]
|
|
self.mipmaps = output["mipmaps"]
|
|
self.identifier = output["identifier"]
|
|
self.label = output["label"]
|
|
self.guiDescription = output["guiDescription"]
|
|
self.group = output["group"]
|
|
self.guiVisibleIf = output["guiVisibleIf"]
|
|
self.userTag = output["userTag"]
|
|
self.type = output["type"]
|
|
self.guiType = output["guiType"]
|
|
self.defaultChannelUse = output["defaultChannelUse"]
|
|
self.enabled = output["enabled"]
|
|
self.channelUseSpecified = output["channelUseSpecified"]
|
|
self.channelUse = output["channelUse"]
|
|
|
|
def to_json(self):
|
|
_obj = {
|
|
"id": self.id,
|
|
"graphID": self.graphID,
|
|
"format": self.format,
|
|
"mipmaps": self.mipmaps,
|
|
"identifier": self.identifier,
|
|
"label": self.label,
|
|
"guiDescription": self.guiDescription,
|
|
"group": self.group,
|
|
"guiVisibleIf": self.guiVisibleIf,
|
|
"userTag": self.userTag,
|
|
"type": self.type,
|
|
"guiType": self.guiType,
|
|
"defaultChannelUse": self.defaultChannelUse,
|
|
"enabled": self.enabled,
|
|
"channelUseSpecified": self.channelUseSpecified,
|
|
"channelUse": self.channelUse
|
|
}
|
|
return _obj
|
|
|
|
|
|
class SBS_Preset():
|
|
def __init__(self, preset, addon_prefs=None, inputs=None):
|
|
self.index = str(preset["index"])
|
|
self.label = preset["label"]
|
|
self.value = preset["value"]
|
|
|
|
if "icon" in preset:
|
|
self.icon = preset["icon"]
|
|
else:
|
|
self.icon = "LOCKED" if self.label != PRESET_CUSTOM else "UNLOCKED"
|
|
if "embedded" in preset:
|
|
self.embedded = preset["embedded"]
|
|
else:
|
|
self.embedded = True if self.label != PRESET_CUSTOM else False
|
|
|
|
if addon_prefs is not None and inputs is not None:
|
|
if "$outputsize" in inputs:
|
|
self.value = SUBSTANCE_Utils.update_preset_outputsize(
|
|
self.value,
|
|
inputs["$outputsize"],
|
|
Code_InputType.integer2.value,
|
|
addon_prefs.default_resolution.get())
|
|
if "normal_format" in inputs:
|
|
self.value = SUBSTANCE_Utils.update_preset_outputsize(
|
|
self.value,
|
|
inputs["normal_format"],
|
|
Code_InputType.integer.value,
|
|
0 if addon_prefs.default_normal_format == "DirectX" else 1)
|
|
|
|
def to_json(self):
|
|
_obj = {
|
|
"index": int(self.index),
|
|
"label": self.label,
|
|
"value": self.value,
|
|
"icon": self.icon,
|
|
"embedded": self.embedded
|
|
}
|
|
return _obj
|
|
|
|
|
|
class SBS_Graph():
|
|
def __init__(self, unique_name, uuid, index, graph, multi_graph, addon_prefs=None):
|
|
self.index = str(index)
|
|
self.uid = str(graph["uid"])
|
|
self.label = graph["label"]
|
|
self.identifier = graph["packageUrl"].replace("pkg://", "")
|
|
self.packageUrl = graph["packageUrl"]
|
|
if graph["physicalSize"][0] == 0 or graph["physicalSize"][1] == 0:
|
|
self.physicalSize = (1/100, 1/100, 1/100)
|
|
else:
|
|
self.physicalSize = (graph["physicalSize"][0]/100,
|
|
graph["physicalSize"][1]/100,
|
|
graph["physicalSize"][2]/100)
|
|
self.tiling = addon_prefs.default_tiling.get()
|
|
self.inputs = {}
|
|
self.inputs_groups = {}
|
|
self.outputs = {}
|
|
self.presets = []
|
|
|
|
if multi_graph:
|
|
_material_name = "{}-{}".format(unique_name, graph["label"]).replace(" ", "_")
|
|
_class_name = "{}-{}".format(uuid, self.uid)
|
|
else:
|
|
_material_name = "{}".format(unique_name).replace(" ", "_")
|
|
_class_name = "{}".format(uuid)
|
|
|
|
self.material = _material_name
|
|
self.inputs_class_name = CLASS_GRAPH_INPUTS.format(_class_name)
|
|
|
|
if len(graph["inputs"]) > 0 and "index" in graph["inputs"][0]:
|
|
_sorted_inputs = sorted(graph["inputs"], key=lambda d: d['index'])
|
|
else:
|
|
_sorted_inputs = graph["inputs"]
|
|
|
|
_input_index = 0
|
|
for _input in _sorted_inputs:
|
|
if _input["guiWidget"] != Code_InputWidget.nowidget.value or _input["type"] != Code_InputType.string.name:
|
|
if _input["type"] == Code_InputType.image.name:
|
|
_group = INPUT_IMAGE_DEFAULT_GROUP
|
|
else:
|
|
_group = _input["guiGroup"] if len(_input["guiGroup"]) > 0 else INPUT_DEFAULT_GROUP
|
|
|
|
if _group not in self.inputs_groups:
|
|
self.inputs_groups[_group] = [_input["identifier"]]
|
|
else:
|
|
self.inputs_groups[_group].append(_input["identifier"])
|
|
|
|
_new_input = SBS_Input(_input_index, _input)
|
|
_input_index += 1
|
|
self.inputs[_input["identifier"]] = _new_input
|
|
|
|
for _idx, _output in enumerate(graph["outputs"]):
|
|
_new_output = SBS_Output(_output, _idx)
|
|
self.outputs[_output["identifier"]] = _new_output
|
|
|
|
_pre_sort_presets = []
|
|
for _preset in graph["presets"]:
|
|
_new_preset = SBS_Preset(_preset, addon_prefs, self.inputs)
|
|
_pre_sort_presets.append(_new_preset)
|
|
self.presets = sorted(_pre_sort_presets, key=lambda _preset: _preset.index, reverse=False)
|
|
|
|
def to_json(self):
|
|
_obj = {
|
|
"uid": self.uid,
|
|
"label": self.label,
|
|
"physicalSize": self.physicalSize,
|
|
"inputs": [],
|
|
"outputs": [],
|
|
"presets": []
|
|
}
|
|
|
|
for _preset in self.presets:
|
|
_obj["presets"].append(_preset.to_json())
|
|
|
|
for _key, _output in self.outputs.items():
|
|
_obj["outputs"].append(_output.to_json())
|
|
|
|
for _key, _input in self.inputs.items():
|
|
_obj["inputs"].append(_input.to_json())
|
|
|
|
return _obj
|
|
|
|
def reset_presets(self, presets):
|
|
self.presets = []
|
|
_pre_sort_presets = []
|
|
for _preset in presets:
|
|
_new_preset = SBS_Preset(_preset)
|
|
_pre_sort_presets.append(_new_preset)
|
|
self.presets = sorted(_pre_sort_presets, key=lambda _preset: _preset.index, reverse=False)
|
|
|
|
|
|
class SBSAR():
|
|
def __init__(self, unique_name, filename, data, addon_prefs=None):
|
|
self.uuid = data["uuid"]
|
|
self.version = data["version"]
|
|
self.name = unique_name
|
|
self.filename = filename
|
|
self.filepath = data["filename"]
|
|
self.graphs = []
|
|
|
|
_multi_graph = len(data["graphs"]) > 1
|
|
|
|
for _idx, _graph in enumerate(data["graphs"]):
|
|
_new_graph = SBS_Graph(unique_name, self.uuid, _idx, _graph, _multi_graph, addon_prefs)
|
|
self.graphs.append(_new_graph)
|
|
|
|
def to_json(self):
|
|
_obj = {
|
|
"uuid": self.uuid,
|
|
"name": self.name,
|
|
"filename": self.filename,
|
|
"filepath": self.filepath,
|
|
"graphs": []
|
|
}
|
|
|
|
for _graph in self.graphs:
|
|
_obj["graphs"].append(_graph.to_json())
|
|
return _obj
|