2025-07-01
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
"""
|
||||
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: props/common.py
|
||||
# brief: Common Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
import bpy
|
||||
|
||||
from ..common import RESOLUTIONS_DICT
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarPhysicalSize(bpy.types.PropertyGroup):
|
||||
x: bpy.props.FloatProperty(
|
||||
name="x",
|
||||
default=1.0,
|
||||
description="The X physical size to be used") # noqa
|
||||
y: bpy.props.FloatProperty(
|
||||
name="y",
|
||||
default=1.0,
|
||||
description="The Y physical size to be used") # noqa
|
||||
z: bpy.props.FloatProperty(
|
||||
name="z",
|
||||
default=1.0,
|
||||
description="The Z physical size to be used") # noqa
|
||||
|
||||
def init(self, value):
|
||||
self.x = value[0]
|
||||
self.y = value[1]
|
||||
self.z = value[2]
|
||||
|
||||
def get(self):
|
||||
return [self.x, self.y, self.z]
|
||||
|
||||
|
||||
def on_linked_tiling_changed(self, context):
|
||||
if self.linked:
|
||||
self.y = self.x
|
||||
self.z = self.x
|
||||
else:
|
||||
on_tiling_changed(self, context)
|
||||
|
||||
|
||||
def on_tiling_changed(self, context):
|
||||
pass
|
||||
|
||||
|
||||
class SUBSTANCE_PG_Tiling(bpy.types.PropertyGroup):
|
||||
x: bpy.props.FloatProperty(
|
||||
name="x",
|
||||
default=2.0,
|
||||
description="The X tiling to be used", # noqa
|
||||
update=on_linked_tiling_changed)
|
||||
y: bpy.props.FloatProperty(
|
||||
name="y",
|
||||
default=2.0,
|
||||
description="The Y tiling to be used", # noqa
|
||||
update=on_tiling_changed)
|
||||
z: bpy.props.FloatProperty(
|
||||
name="z",
|
||||
default=2.0,
|
||||
description="The Z tiling to be used", # noqa
|
||||
update=on_tiling_changed)
|
||||
linked: bpy.props.BoolProperty(
|
||||
name="linked",
|
||||
default=True,
|
||||
description='Lock/Unlock the tiling', # noqa
|
||||
update=on_linked_tiling_changed)
|
||||
|
||||
def init(self, value):
|
||||
self.x = value[0]
|
||||
self.y = value[1]
|
||||
self.z = value[2]
|
||||
|
||||
def get(self):
|
||||
return [self.x, self.y, self.z]
|
||||
|
||||
|
||||
def on_update_resolution(self, context):
|
||||
if self.linked:
|
||||
self.height = self.width
|
||||
|
||||
|
||||
class SUBSTANCE_PG_Resolution(bpy.types.PropertyGroup):
|
||||
width: bpy.props.EnumProperty(
|
||||
name="width",
|
||||
default="10",
|
||||
description="The width of the exported map", # noqa
|
||||
items=RESOLUTIONS_DICT,
|
||||
update=on_update_resolution)
|
||||
height: bpy.props.EnumProperty(
|
||||
name="height",
|
||||
default="10",
|
||||
description="The height of the exported map", # noqa
|
||||
items=RESOLUTIONS_DICT)
|
||||
linked: bpy.props.BoolProperty(
|
||||
name="linked",
|
||||
default=True,
|
||||
description='Lock/Unlock the resolution', # noqa
|
||||
update=on_update_resolution)
|
||||
|
||||
def init(self, value):
|
||||
self.width = value[0]
|
||||
self.height = value[1]
|
||||
|
||||
def get(self):
|
||||
return [int(self.width), int(self.height)]
|
||||
@@ -0,0 +1,135 @@
|
||||
"""
|
||||
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: props/sbsar.py
|
||||
# brief: Substance Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
import bpy
|
||||
from .sbsar_graph import SUBSTANCE_PG_SbsarGraph
|
||||
|
||||
from ..common import (
|
||||
Code_SbsarLoadSuffix,
|
||||
ADDON_PACKAGE
|
||||
)
|
||||
|
||||
|
||||
def get_graph_items(self, context):
|
||||
_graphs = []
|
||||
for _idx, _graph in enumerate(self.graphs):
|
||||
_item = (_graph.index, _graph.label, "{}:{}:{}".format(_graph.index, _graph.label, _graph.uid))
|
||||
_graphs.append(_item)
|
||||
if len(_graphs) == 0:
|
||||
return [("0", "NONE", "NONE:NONE:NONE")]
|
||||
return _graphs
|
||||
|
||||
|
||||
def on_graph_update(self, context):
|
||||
pass
|
||||
|
||||
|
||||
def on_suffix_update(self, context):
|
||||
if self.suffix == Code_SbsarLoadSuffix.success.value[0]:
|
||||
self.loading = Code_SbsarLoadSuffix.success.value[1]
|
||||
self.load_success = True
|
||||
elif self.suffix == Code_SbsarLoadSuffix.error.value[0]:
|
||||
self.loading = Code_SbsarLoadSuffix.error.value[1]
|
||||
self.load_success = False
|
||||
|
||||
|
||||
class SUBSTANCE_PG_Sbsar(bpy.types.PropertyGroup):
|
||||
uuid: bpy.props.StringProperty(
|
||||
name="uuid",
|
||||
description="The ID of the Substance 3D *.sbsar file") # noqa
|
||||
version: bpy.props.IntProperty(
|
||||
name="version",
|
||||
description="The Version of the Substance Engine used by the .sbsar file") # noqa
|
||||
name: bpy.props.StringProperty(
|
||||
name="name",
|
||||
description="The name of the Substance *.sbsar file") # noqa
|
||||
filename: bpy.props.StringProperty(
|
||||
name='filename',
|
||||
description='The name of the *.sbsar file') # noqa
|
||||
filepath: bpy.props.StringProperty(
|
||||
name='filepath',
|
||||
description='The path to the *.sbsar file') # noqa
|
||||
|
||||
graphs: bpy.props.CollectionProperty(type=SUBSTANCE_PG_SbsarGraph)
|
||||
graphs_list: bpy.props.EnumProperty(
|
||||
name="graphs",
|
||||
description="The available graphs of the Substance 3D material", # noqa
|
||||
items=get_graph_items,
|
||||
update=on_graph_update)
|
||||
|
||||
suffix: bpy.props.StringProperty(
|
||||
name="suffix",
|
||||
default=Code_SbsarLoadSuffix.loading.value[0],
|
||||
update=on_suffix_update)
|
||||
icon: bpy.props.StringProperty(
|
||||
name="icon",
|
||||
default=Code_SbsarLoadSuffix.loading.value[1],
|
||||
update=on_suffix_update)
|
||||
|
||||
loading: bpy.props.StringProperty(name="loading", default="TEMP") # noqa
|
||||
load_success: bpy.props.BoolProperty(default=False)
|
||||
|
||||
def init(self, sbsar):
|
||||
self.uuid = sbsar.uuid
|
||||
self.version = sbsar.version
|
||||
self.name = sbsar.name
|
||||
self.filename = sbsar.filename
|
||||
self.filepath = sbsar.filepath
|
||||
|
||||
_addon_prefs = bpy.context.preferences.addons[ADDON_PACKAGE].preferences
|
||||
for _graph in sbsar.graphs:
|
||||
_new_graph = self.graphs.add()
|
||||
_new_graph.init(_graph, _addon_prefs)
|
||||
|
||||
def init_shader(self, shader_idx, shader, default_output):
|
||||
for _graph in self.graphs:
|
||||
_graph.init_shader(shader_idx, shader, default_output)
|
||||
|
||||
def init_tiling(self, sbsar):
|
||||
for _idx, _graph in enumerate(self.graphs):
|
||||
_graph.init_tiling(sbsar.graphs[_idx].tiling.get(), sbsar.graphs[_idx].tiling.linked)
|
||||
|
||||
def init_shader_duplicate(self, sbsar):
|
||||
for _idx, _graph in enumerate(self.graphs):
|
||||
_graph.init_shader_duplicate(sbsar.graphs[_idx].shaders_list)
|
||||
|
||||
def init_outputs(self, sbsar):
|
||||
for _idx, _graph in enumerate(self.graphs):
|
||||
_graph.init_outputs(sbsar.graphs[_idx].outputs)
|
||||
|
||||
def init_presets(self, sbsar):
|
||||
for _idx, _graph in enumerate(self.graphs):
|
||||
_graph.init_preset(sbsar.graphs[_idx].presets_list)
|
||||
|
||||
def get(self):
|
||||
_obj = {
|
||||
"uuid": self.uuid,
|
||||
"version": self.version,
|
||||
"name": self.name,
|
||||
"filename": self.filename,
|
||||
"filepath": self.filepath,
|
||||
"graphs": []
|
||||
}
|
||||
for _graph in self.graphs:
|
||||
_obj["graphs"].append(_graph.get())
|
||||
|
||||
return _obj
|
||||
@@ -0,0 +1,361 @@
|
||||
"""
|
||||
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: props/sbsar_graph.py
|
||||
# brief: Substance Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
import os
|
||||
import bpy
|
||||
from .utils import get_shaders
|
||||
from ..sbsar.async_ops import _render_sbsar, _set_input_visibility
|
||||
from ..api import SUBSTANCE_Api
|
||||
from ..thread_ops import SUBSTANCE_Threads
|
||||
from ..material.manager import SUBSTANCE_MaterialManager
|
||||
from ..utils import SUBSTANCE_Utils
|
||||
from .common import SUBSTANCE_PG_SbsarPhysicalSize
|
||||
from .sbsar_input import SUBSTANCE_PG_SbsarInput, SUBSTANCE_PG_SbsarInputGroup
|
||||
from .sbsar_output import SUBSTANCE_PG_SbsarOutput
|
||||
from .sbsar_preset import SUBSTANCE_PG_SbsarPreset
|
||||
from ..common import OUTPUTS_FILTER_DICT, Code_InputIdentifier, Code_Response
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarMaterial(bpy.types.PropertyGroup):
|
||||
name: bpy.props.StringProperty(name="name", description="The ID of the Substance 3D shader material") # noqa
|
||||
shader: bpy.props.StringProperty(name="shader", default="") # noqa
|
||||
|
||||
|
||||
def on_linked_tiling_changed(self, context):
|
||||
if self.linked:
|
||||
self.y = self.x
|
||||
self.z = self.x
|
||||
else:
|
||||
on_tiling_changed(self, context)
|
||||
|
||||
|
||||
def on_tiling_changed(self, context):
|
||||
if not self.callback:
|
||||
return
|
||||
_sbsar = context.scene.loaded_sbsars[context.scene.sbsar_index]
|
||||
_graph = _sbsar.graphs[int(_sbsar.graphs_list)]
|
||||
_addons_prefs, _selected_shader_idx, _selected_shader_preset = SUBSTANCE_Utils.get_selected_shader(
|
||||
context,
|
||||
int(_graph.shaders_list))
|
||||
_shader_filepath = SUBSTANCE_Utils.get_shader_file(_selected_shader_preset.filename)
|
||||
_shader_graph = SUBSTANCE_Utils.get_json(_shader_filepath)
|
||||
_material = SUBSTANCE_MaterialManager.get_existing_material(_graph.material.name)
|
||||
|
||||
if _material is None:
|
||||
return
|
||||
|
||||
for _property in _shader_graph["properties"]:
|
||||
if _property["type"] == "tiling":
|
||||
_node_name = None
|
||||
for _node in _shader_graph["nodes"]:
|
||||
if _node["id"] == _property["id"]:
|
||||
_node_name = _node["name"]
|
||||
break
|
||||
if _node_name is None:
|
||||
continue
|
||||
if _node_name in _material.node_tree.nodes:
|
||||
_node = _material.node_tree.nodes[_node_name]
|
||||
_value = self.get()
|
||||
if "input" in _property:
|
||||
setattr(_node.inputs[_property["input"]], _property["name"], _value)
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarTiling(bpy.types.PropertyGroup):
|
||||
x: bpy.props.FloatProperty(
|
||||
name="x",
|
||||
default=2.0,
|
||||
description="The X tiling to be used", # noqa
|
||||
update=on_linked_tiling_changed)
|
||||
y: bpy.props.FloatProperty(
|
||||
name="y",
|
||||
default=2.0,
|
||||
description="The Y tiling to be used", # noqa
|
||||
update=on_tiling_changed)
|
||||
z: bpy.props.FloatProperty(
|
||||
name="z",
|
||||
default=2.0,
|
||||
description="The Z tiling to be used", # noqa
|
||||
update=on_tiling_changed)
|
||||
linked: bpy.props.BoolProperty(
|
||||
name="linked",
|
||||
default=True,
|
||||
description='Lock/Unlock the tiling', # noqa
|
||||
update=on_linked_tiling_changed)
|
||||
callback: bpy.props.BoolProperty(default=True)
|
||||
|
||||
def init(self, value):
|
||||
self.callback = False
|
||||
self.x = value[0]
|
||||
self.y = value[1]
|
||||
self.z = value[2]
|
||||
self.callback = True
|
||||
|
||||
def set(self, value, linked):
|
||||
self.callback = False
|
||||
self.x = value[0]
|
||||
self.y = value[1]
|
||||
self.z = value[2]
|
||||
self.linked = linked
|
||||
self.callback = True
|
||||
|
||||
def get(self):
|
||||
return [self.x, self.y, self.z]
|
||||
|
||||
|
||||
def on_shader_update(self, context):
|
||||
if not self.shader_callback:
|
||||
return
|
||||
|
||||
_sbsar = context.scene.loaded_sbsars[context.scene.sbsar_index]
|
||||
_graph_idx = int(_sbsar.graphs_list)
|
||||
|
||||
_addons_prefs, _selected_shader_idx, _selected_shader = SUBSTANCE_Utils.get_selected_shader(
|
||||
context,
|
||||
int(self.shaders_list))
|
||||
|
||||
for _output in self.outputs:
|
||||
_output.shader_callback_enabled = False
|
||||
if _output.name in _selected_shader.outputs:
|
||||
_shader_output = _selected_shader.outputs[_output.name]
|
||||
_output.shader_enabled = _shader_output.enabled
|
||||
_output.shader_format = _shader_output.format
|
||||
_output.shader_bitdepth = _shader_output.bitdepth
|
||||
else:
|
||||
_output.shader_enabled = _addons_prefs.output_default_enabled
|
||||
_output.shader_format = _addons_prefs.output_default_format
|
||||
_output.shader_bitdepth = _addons_prefs.output_default_bitdepth
|
||||
_output.shader_callback_enabled = True
|
||||
|
||||
SUBSTANCE_Threads.alt_thread_run(_render_sbsar, (context, _sbsar, _graph_idx))
|
||||
|
||||
|
||||
def on_preset_update(self, context):
|
||||
if not self.preset_callback:
|
||||
return
|
||||
_sbsar = context.scene.loaded_sbsars[context.scene.sbsar_index]
|
||||
_preset_idx = int(self.presets_list)
|
||||
_preset = self.presets[_preset_idx]
|
||||
|
||||
_result = SUBSTANCE_Api.sbsar_preset_load(
|
||||
_sbsar,
|
||||
self,
|
||||
_preset.value)
|
||||
|
||||
if _result[0] != Code_Response.success:
|
||||
return
|
||||
|
||||
_data = _result[1]["data"]["inputs"]
|
||||
SUBSTANCE_Threads.alt_thread_run(_set_input_visibility, (
|
||||
_sbsar,
|
||||
self,
|
||||
_data))
|
||||
|
||||
SUBSTANCE_Threads.alt_thread_run(_render_sbsar, (
|
||||
context,
|
||||
_sbsar,
|
||||
int(self.index)))
|
||||
|
||||
_input_class = getattr(context.scene, self.inputs_class_name)
|
||||
_input_class.callback["enabled"] = False
|
||||
_input_class.from_json(self.inputs, _data)
|
||||
_input_class.callback["enabled"] = True
|
||||
|
||||
|
||||
def get_preset_items(self, context):
|
||||
_presets = []
|
||||
for _preset in self.presets:
|
||||
_item = (
|
||||
_preset.index,
|
||||
_preset.label,
|
||||
"{}:{}".format(_preset.index, _preset.label),
|
||||
int(_preset.index)
|
||||
)
|
||||
_presets.append(_item)
|
||||
return _presets
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarGraph(bpy.types.PropertyGroup):
|
||||
index: bpy.props.StringProperty(
|
||||
name="index",
|
||||
description="The index of the graph in the Substance 3D material") # noqa
|
||||
uid: bpy.props.StringProperty(
|
||||
name="uid",
|
||||
description="The ID of the Substance 3D graph") # noqa
|
||||
name: bpy.props.StringProperty(name="name")
|
||||
label: bpy.props.StringProperty(
|
||||
name="label",
|
||||
description="The name of the Substance 3D graph") # noqa
|
||||
identifier: bpy.props.StringProperty(
|
||||
name="identifier",
|
||||
description="The identifier of the Substance 3D graph") # noqa
|
||||
packageUrl: bpy.props.StringProperty(
|
||||
name="packageUrl",
|
||||
description="The package URL of the Substance 3D graph") # noqa
|
||||
material: bpy.props.PointerProperty(type=SUBSTANCE_PG_SbsarMaterial)
|
||||
tiling: bpy.props.PointerProperty(
|
||||
name="tiling",
|
||||
description="The default tiling to be used in the shader network", # noqa
|
||||
type=SUBSTANCE_PG_SbsarTiling)
|
||||
physical_size: bpy.props.PointerProperty(
|
||||
name="physical_size",
|
||||
description="The physical size of the material", # noqa
|
||||
type=SUBSTANCE_PG_SbsarPhysicalSize)
|
||||
|
||||
presets: bpy.props.CollectionProperty(type=SUBSTANCE_PG_SbsarPreset)
|
||||
presets_list: bpy.props.EnumProperty(
|
||||
name="presets",
|
||||
description="The available presets on ths SBSAR file", # noqa
|
||||
items=get_preset_items,
|
||||
update=on_preset_update)
|
||||
preset_callback: bpy.props.BoolProperty(name="preset_callback", default=True)
|
||||
|
||||
outputs_filter: bpy.props.EnumProperty(
|
||||
name="outputs_filter",
|
||||
description="Filter the outputs displayed", # noqa
|
||||
items=OUTPUTS_FILTER_DICT)
|
||||
|
||||
inputs_class_name: bpy.props.StringProperty(name="inputs_class_name")
|
||||
input_groups: bpy.props.CollectionProperty(type=SUBSTANCE_PG_SbsarInputGroup)
|
||||
inputs: bpy.props.CollectionProperty(type=SUBSTANCE_PG_SbsarInput)
|
||||
|
||||
outputs: bpy.props.CollectionProperty(type=SUBSTANCE_PG_SbsarOutput)
|
||||
|
||||
outputsize_exists: bpy.props.BoolProperty(
|
||||
name="outputsize_exists",
|
||||
default=False)
|
||||
randomseed_exists: bpy.props.BoolProperty(
|
||||
name="randomseed_exists",
|
||||
default=False)
|
||||
|
||||
shaders_list: bpy.props.EnumProperty(
|
||||
name="shaders_list",
|
||||
description="The available shader network presets", # noqa
|
||||
items=get_shaders,
|
||||
update=on_shader_update)
|
||||
shader_callback: bpy.props.BoolProperty(name="shader_callback", default=True)
|
||||
update_tx_only: bpy.props.BoolProperty(name="update_tx_only", default=False)
|
||||
|
||||
thumbnail: bpy.props.StringProperty(name="thumbnail")
|
||||
|
||||
def init(self, graph, addon_prefs):
|
||||
self.index = graph.index
|
||||
self.uid = graph.uid
|
||||
self.name = graph.identifier
|
||||
self.identifier = graph.identifier
|
||||
self.packageUrl = graph.packageUrl
|
||||
self.label = graph.label
|
||||
self.material.name = graph.material
|
||||
self.physical_size.init(graph.physicalSize)
|
||||
self.tiling.init(graph.tiling)
|
||||
self.inputs_class_name = graph.inputs_class_name
|
||||
|
||||
self.update_tx_only = addon_prefs.default_tx_update
|
||||
|
||||
for _preset in graph.presets:
|
||||
_new_preset = self.presets.add()
|
||||
_new_preset.init(_preset)
|
||||
|
||||
for _idx, _group in enumerate(graph.inputs_groups):
|
||||
new_group = self.input_groups.add()
|
||||
new_group.init(_idx, _group, addon_prefs)
|
||||
|
||||
for _key, _input in graph.inputs.items():
|
||||
_new_input = self.inputs.add()
|
||||
_new_input.init(_input)
|
||||
if _input.identifier == Code_InputIdentifier.outputsize.value:
|
||||
self.outputsize_exists = True
|
||||
if _input.identifier == Code_InputIdentifier.randomseed.value:
|
||||
self.randomseed_exists = True
|
||||
|
||||
for _key, _outputs in graph.outputs.items():
|
||||
_new_output = self.outputs.add()
|
||||
_new_output.init(_outputs)
|
||||
|
||||
def init_shader(self, shader_idx, shader, default_output):
|
||||
self.shader_callback = False
|
||||
self.shaders_list = shader_idx
|
||||
self.shader_callback = True
|
||||
for _output in self.outputs:
|
||||
_output.init_shader(shader, default_output)
|
||||
|
||||
def init_shader_duplicate(self, shader_index):
|
||||
_shader_idx = int(shader_index)
|
||||
_addon_prefs, _selected_shader_idx, _selected_shader_preset = SUBSTANCE_Utils.get_selected_shader(
|
||||
bpy.context, _shader_idx)
|
||||
self.shader_callback = False
|
||||
self.shaders_list = _selected_shader_idx
|
||||
self.shader_callback = True
|
||||
for _output in self.outputs:
|
||||
_output.init_shader(_selected_shader_preset, _addon_prefs.get_default_output())
|
||||
|
||||
def init_tiling(self, value, linked):
|
||||
self.tiling.set(value, linked)
|
||||
|
||||
def init_outputs(self, outputs):
|
||||
for _output in self.outputs:
|
||||
if _output.name in outputs:
|
||||
_output.init_output(outputs[_output.name])
|
||||
|
||||
def init_preset(self, preset_value):
|
||||
self.preset_callback = False
|
||||
self.presets_list = preset_value
|
||||
self.preset_callback = True
|
||||
|
||||
def set_thumbnail(self, data):
|
||||
if "graph_thumb" not in data:
|
||||
return
|
||||
|
||||
_file = data["graph_thumb"]
|
||||
if os.path.exists(_file):
|
||||
_thumbnail_img = bpy.data.images.load(_file, check_existing=True)
|
||||
_thumbnail_txt = bpy.data.textures.new(name=_thumbnail_img.name, type="IMAGE")
|
||||
_thumbnail_txt.image = _thumbnail_img
|
||||
_thumbnail_txt.extension = "EXTEND"
|
||||
self.thumbnail = _thumbnail_img.name
|
||||
else:
|
||||
self.thumbnail = ""
|
||||
|
||||
def get(self):
|
||||
_obj = {
|
||||
"index": self.index,
|
||||
"uid": self.uid,
|
||||
"identifier": self.identifier,
|
||||
"packagrUrl": self.packageUrl,
|
||||
"label": self.label,
|
||||
"physical_size": self.physical_size.get(),
|
||||
"tiling": self.tiling.get(),
|
||||
"presets": [],
|
||||
"inputs": [],
|
||||
"outputs": [],
|
||||
"thumbnail": self.thumbnail
|
||||
}
|
||||
|
||||
for _preset in self.presets:
|
||||
_obj["presets"].append(_preset.get())
|
||||
|
||||
for _input in self.inputs:
|
||||
_obj["inputs"].append(_input.get())
|
||||
|
||||
for _output in self.outputs:
|
||||
_obj["outputs"].append(_output.get())
|
||||
|
||||
return _obj
|
||||
@@ -0,0 +1,95 @@
|
||||
"""
|
||||
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: props/sbsar_input.py
|
||||
# brief: Substance Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarInput(bpy.types.PropertyGroup):
|
||||
id: bpy.props.StringProperty(name="id")
|
||||
name: bpy.props.StringProperty(name="name")
|
||||
graphID: bpy.props.StringProperty(name="graphID")
|
||||
identifier: bpy.props.StringProperty(name="identifier")
|
||||
label: bpy.props.StringProperty(name="label")
|
||||
guiDescription: bpy.props.StringProperty(name="label")
|
||||
guiGroup: bpy.props.StringProperty(name="guiGroup")
|
||||
guiVisibleIf: bpy.props.StringProperty(name="guiVisibleIf")
|
||||
userTag: bpy.props.StringProperty(name="userTag")
|
||||
type: bpy.props.StringProperty(name="type")
|
||||
guiWidget: bpy.props.StringProperty(name="guiWidget")
|
||||
showAsPin: bpy.props.BoolProperty(name="showAsPin", default=False)
|
||||
useCache: bpy.props.BoolProperty(name="useCache", default=False)
|
||||
visibleIf: bpy.props.BoolProperty(name="visibleIf", default=False)
|
||||
isHeavyDuty: bpy.props.BoolProperty(name="isHeavyDuty", default=False)
|
||||
|
||||
def init(self, input):
|
||||
self.id = str(input.id)
|
||||
self.name = input.identifier
|
||||
self.graphID = str(input.graphID)
|
||||
self.identifier = input.identifier
|
||||
self.label = input.label
|
||||
self.guiDescription = input.guiDescription
|
||||
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
|
||||
|
||||
def get(self):
|
||||
_obj = {
|
||||
"id": int(self.id),
|
||||
"graphID": int(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
|
||||
}
|
||||
return _obj
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarInputGroup(bpy.types.PropertyGroup):
|
||||
index: bpy.props.IntProperty(name="index")
|
||||
label: bpy.props.StringProperty(name="label")
|
||||
collapsed: bpy.props.BoolProperty(default=False)
|
||||
|
||||
def init(self, index, value, addon_prefs):
|
||||
self.index = index
|
||||
self.label = value
|
||||
self.collapsed = addon_prefs.default_group_collapse
|
||||
|
||||
def get(self):
|
||||
_obj = {
|
||||
"label": self.label,
|
||||
"collapsed": self.collapsed
|
||||
}
|
||||
return _obj
|
||||
@@ -0,0 +1,169 @@
|
||||
"""
|
||||
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: props/sbsar_output.py
|
||||
# brief: Substance Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
import bpy
|
||||
|
||||
from ..thread_ops import SUBSTANCE_Threads
|
||||
from ..sbsar.async_ops import _render_sbsar
|
||||
from ..utils import SUBSTANCE_Utils
|
||||
from ..common import (
|
||||
IMAGE_FORMAT_DICT,
|
||||
IMAGE_BITDEPTH_DICT
|
||||
)
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarOutputChannelUse(bpy.types.PropertyGroup):
|
||||
value: bpy.props.StringProperty(name="value")
|
||||
|
||||
|
||||
def on_output_update(self, context):
|
||||
if not self.shader_callback_enabled:
|
||||
return
|
||||
|
||||
_sbsar = context.scene.loaded_sbsars[context.scene.sbsar_index]
|
||||
_graph = SUBSTANCE_Utils.get_selected_graph(context)
|
||||
|
||||
SUBSTANCE_Threads.alt_thread_run(_render_sbsar, (context, _sbsar, int(_graph.index)))
|
||||
|
||||
|
||||
def get_colorspace_dict(self, context):
|
||||
return SUBSTANCE_Utils.get_colorspaces()
|
||||
|
||||
|
||||
def get_bitdepths(self, context):
|
||||
return IMAGE_BITDEPTH_DICT[self.shader_format]
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarOutput(bpy.types.PropertyGroup):
|
||||
id: bpy.props.StringProperty(name="id")
|
||||
index: bpy.props.IntProperty(name="index")
|
||||
name: bpy.props.StringProperty(name="name")
|
||||
graphID: bpy.props.StringProperty(name="graphID")
|
||||
format: bpy.props.IntProperty(name="format")
|
||||
mipmaps: bpy.props.IntProperty(name="mipmaps")
|
||||
identifier: bpy.props.StringProperty(name="identifier")
|
||||
label: bpy.props.StringProperty(name="label")
|
||||
guiDescription: bpy.props.StringProperty(name="guiDescription")
|
||||
group: bpy.props.StringProperty(name="group")
|
||||
guiVisibleIf: bpy.props.StringProperty(name="guiVisibleIf")
|
||||
userTag: bpy.props.StringProperty(name="userTag")
|
||||
type: bpy.props.StringProperty(name="type")
|
||||
guiType: bpy.props.StringProperty(name="guiType")
|
||||
defaultChannelUse: bpy.props.StringProperty(name="defaultChannelUse")
|
||||
enabled: bpy.props.BoolProperty(name="enabled")
|
||||
channelUseSpecified: bpy.props.BoolProperty(name="channelUseSpecified")
|
||||
channelUse: bpy.props.CollectionProperty(type=SUBSTANCE_PG_SbsarOutputChannelUse)
|
||||
|
||||
shader_callback_enabled: bpy.props.BoolProperty(name="shader_callback_enabled", default=False)
|
||||
shader_enabled: bpy.props.BoolProperty(
|
||||
name="shader_enabled",
|
||||
default=False,
|
||||
update=on_output_update)
|
||||
shader_colorspace: bpy.props.EnumProperty(
|
||||
name="shader_colorspace",
|
||||
description="The available colorspaces to be applied to this map", # noqa
|
||||
items=get_colorspace_dict,
|
||||
update=on_output_update)
|
||||
shader_format: bpy.props.EnumProperty(
|
||||
name="shader_format",
|
||||
description="The available colorspaces to be applied to this map", # noqa
|
||||
items=IMAGE_FORMAT_DICT,
|
||||
update=on_output_update)
|
||||
shader_bitdepth: bpy.props.EnumProperty(
|
||||
name="shader_bitdepth",
|
||||
description="The available colorspaces to be applied to this map", # noqa
|
||||
items=get_bitdepths,
|
||||
update=on_output_update)
|
||||
|
||||
filepath: bpy.props.StringProperty(name="filepath", default="") # noqa
|
||||
filename: bpy.props.StringProperty(name="filename", default="") # noqa
|
||||
|
||||
def init(self, output):
|
||||
self.id = str(output.id)
|
||||
self.index = output.index
|
||||
self.name = output.defaultChannelUse if output.defaultChannelUse != "UNKNOWN" else output.identifier
|
||||
self.graphID = str(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
|
||||
|
||||
for _use in output.channelUse:
|
||||
_new_use = self.channelUse.add()
|
||||
_new_use.value = _use
|
||||
|
||||
def init_shader(self, shader, default_output):
|
||||
if self.name not in shader.outputs:
|
||||
self.shader_enabled = default_output["enabled"]
|
||||
self.shader_format = default_output["format"]
|
||||
self.shader_bitdepth = default_output["bitdepth"]
|
||||
else:
|
||||
for _output in shader.outputs:
|
||||
if _output.id == self.name:
|
||||
self.shader_enabled = _output.enabled
|
||||
self.shader_format = _output.format
|
||||
self.shader_bitdepth = _output.bitdepth
|
||||
self.shader_callback_enabled = True
|
||||
|
||||
def init_output(self, default_output):
|
||||
self.shader_callback_enabled = False
|
||||
self.shader_enabled = default_output.shader_enabled
|
||||
self.shader_format = default_output.shader_format
|
||||
self.shader_bitdepth = default_output.shader_bitdepth
|
||||
self.shader_callback_enabled = True
|
||||
|
||||
def get(self):
|
||||
_obj = {
|
||||
"id": int(self.id),
|
||||
"graphID": int(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": [],
|
||||
"shader_enabled": self.shader_enabled,
|
||||
"shader_colorspace": self.shader_colorspace,
|
||||
"shader_format": self.shader_format,
|
||||
"shader_bitdepth": self.shader_bitdepth
|
||||
}
|
||||
|
||||
for _use in self.channelUse:
|
||||
_obj["channelUse"].append(_use.value)
|
||||
return _obj
|
||||
@@ -0,0 +1,59 @@
|
||||
"""
|
||||
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: props/sbsar_preset.py
|
||||
# brief: Substance Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
class SUBSTANCE_PG_SbsarPreset(bpy.types.PropertyGroup):
|
||||
name: bpy.props.StringProperty(name="name")
|
||||
index: bpy.props.StringProperty(
|
||||
name="index",
|
||||
description="The index of the preset in the Substance 3D graph") # noqa
|
||||
label: bpy.props.StringProperty(
|
||||
name="label",
|
||||
description="The preset name of the Substance 3D graph") # noqa
|
||||
value: bpy.props.StringProperty(
|
||||
name="value",
|
||||
description="The preset value of the Substance 3D graph") # noqa
|
||||
icon: bpy.props.StringProperty(
|
||||
name="icon",
|
||||
description="The preset icon that shows if a preset is editable") # noqa
|
||||
embedded: bpy.props.BoolProperty(
|
||||
name="embedded",
|
||||
description="The preset origin") # noqa
|
||||
|
||||
def init(self, preset):
|
||||
self.name = preset.label
|
||||
self.index = preset.index
|
||||
self.label = preset.label
|
||||
self.value = preset.value
|
||||
self.icon = preset.icon
|
||||
self.embedded = preset.embedded
|
||||
|
||||
def get(self):
|
||||
return {
|
||||
"index": self.index,
|
||||
"label": self.label,
|
||||
"value": self.value,
|
||||
"icon": self.icon,
|
||||
"embedded": self.embedded
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
"""
|
||||
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: props/shader.py
|
||||
# brief: Shader Preset Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
import bpy
|
||||
from ..shader.callbacks import SUBSTANCE_ShaderCallbacks
|
||||
from ..common import IMAGE_FORMAT_DICT, IMAGE_BITDEPTH_DICT
|
||||
from ..utils import SUBSTANCE_Utils
|
||||
|
||||
|
||||
class SUBSTANCE_PG_ShaderInput(bpy.types.PropertyGroup):
|
||||
id: bpy.props.StringProperty(name="id")
|
||||
label: bpy.props.StringProperty(name="label")
|
||||
type: bpy.props.StringProperty(name="type")
|
||||
|
||||
def init(self, input):
|
||||
self.id = input.id
|
||||
self.label = input.label
|
||||
self.type = input.type
|
||||
|
||||
|
||||
def on_enabled_update(self, context):
|
||||
if not self.callback_enabled:
|
||||
return
|
||||
SUBSTANCE_ShaderCallbacks.on_output_changed(self, context)
|
||||
|
||||
|
||||
def on_shader_colorspace_update(self, context):
|
||||
if not self.callback_enabled:
|
||||
return
|
||||
SUBSTANCE_ShaderCallbacks.on_output_changed(self, context)
|
||||
|
||||
|
||||
def on_shader_format_update(self, context):
|
||||
if not self.callback_enabled:
|
||||
return
|
||||
|
||||
_callback_enabled = self.callback_enabled
|
||||
self.callback_enabled = False
|
||||
self.bitdepth = IMAGE_BITDEPTH_DICT[self.format][0][0]
|
||||
self.callback_enabled = _callback_enabled
|
||||
SUBSTANCE_ShaderCallbacks.on_output_changed(self, context)
|
||||
|
||||
|
||||
def on_shader_bitdepth_update(self, context):
|
||||
if not self.callback_enabled:
|
||||
return
|
||||
SUBSTANCE_ShaderCallbacks.on_output_changed(self, context)
|
||||
|
||||
|
||||
def get_colorspace_dict(self, context):
|
||||
return SUBSTANCE_Utils.get_colorspaces()
|
||||
|
||||
|
||||
def get_shader_bitdepths(self, context):
|
||||
return IMAGE_BITDEPTH_DICT[self.format]
|
||||
|
||||
|
||||
class SUBSTANCE_PG_ShaderOutput(bpy.types.PropertyGroup):
|
||||
id: bpy.props.StringProperty(name="id")
|
||||
name: bpy.props.StringProperty(name="name")
|
||||
label: bpy.props.StringProperty(name="label")
|
||||
optional: bpy.props.BoolProperty(name="optional")
|
||||
enabled: bpy.props.BoolProperty(
|
||||
name="enabled",
|
||||
update=on_enabled_update)
|
||||
colorspace: bpy.props.EnumProperty(
|
||||
name="colorspace",
|
||||
description="The default colorspace to be used when creating the shader network", # noqa
|
||||
items=get_colorspace_dict,
|
||||
update=on_shader_colorspace_update)
|
||||
format: bpy.props.EnumProperty(
|
||||
name="format",
|
||||
description="The default format to be used when exporting this maps", # noqa
|
||||
items=IMAGE_FORMAT_DICT,
|
||||
update=on_shader_format_update)
|
||||
bitdepth: bpy.props.EnumProperty(
|
||||
name="bitdepth",
|
||||
description="The default bitdepth to be applied to this map", # noqa
|
||||
items=get_shader_bitdepths,
|
||||
update=on_shader_bitdepth_update)
|
||||
normal: bpy.props.BoolProperty(name="normal", default=False)
|
||||
callback_enabled: bpy.props.BoolProperty(name="callback_enabled", default=False)
|
||||
|
||||
def init(self, output):
|
||||
self.id = output.id
|
||||
self.name = output.id
|
||||
self.label = output.label
|
||||
self.enabled = output.enabled
|
||||
self.optional = output.optional
|
||||
self.format = output.format
|
||||
self.bitdepth = output.bitdepth
|
||||
self.normal = output.normal
|
||||
self.callback_enabled = True
|
||||
self.colorspace = output.colorspace
|
||||
|
||||
def to_json(self):
|
||||
_object = {
|
||||
"id": self.id,
|
||||
"label": self.label,
|
||||
"enabled": self.enabled,
|
||||
"optional": self.optional,
|
||||
"colorspace": self.colorspace,
|
||||
"format": self.format,
|
||||
"bitdepth": self.bitdepth,
|
||||
}
|
||||
|
||||
if self.normal:
|
||||
_object["normal"] = self.normal
|
||||
return _object
|
||||
|
||||
|
||||
class SUBSTANCE_PG_ShaderPreset(bpy.types.PropertyGroup):
|
||||
filename: bpy.props.StringProperty(name="filename")
|
||||
name: bpy.props.StringProperty(name="name")
|
||||
label: bpy.props.StringProperty(name="label")
|
||||
modified: bpy.props.BoolProperty(name="modified", default=False)
|
||||
|
||||
inputs: bpy.props.CollectionProperty(type=SUBSTANCE_PG_ShaderInput)
|
||||
outputs: bpy.props.CollectionProperty(type=SUBSTANCE_PG_ShaderOutput)
|
||||
|
||||
inputs_class_name: bpy.props.StringProperty(name="inputs_class_name")
|
||||
|
||||
def init(self, shader):
|
||||
self.filename = shader.filename
|
||||
self.name = shader.name
|
||||
self.label = shader.label
|
||||
self.inputs_class_name = shader.inputs_class_name
|
||||
|
||||
for _key, _input in shader.inputs.items():
|
||||
_parm_item = self.inputs.add()
|
||||
_parm_item.init(_input)
|
||||
|
||||
for _key, _output in shader.outputs.items():
|
||||
_output_item = self.outputs.add()
|
||||
_output_item.init(_output)
|
||||
|
||||
def to_json(self):
|
||||
_data = []
|
||||
for _output in self.outputs:
|
||||
_data.append(_output.to_json())
|
||||
return _data
|
||||
@@ -0,0 +1,54 @@
|
||||
"""
|
||||
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: props/shortcuts.py
|
||||
# brief: Shortcuts Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
import bpy
|
||||
|
||||
|
||||
def _on_shortcut_update(self, context):
|
||||
_ctrl = "Ctrl+" if self.menu_ctrl else ""
|
||||
_shift = "Shift+" if self.menu_shift else ""
|
||||
_alt = "Alt+" if self.menu_alt else ""
|
||||
self.menu_label = _ctrl + _shift + _alt + self.menu_key
|
||||
|
||||
|
||||
class SUBSTANCE_PG_Shortcuts(bpy.types.PropertyGroup):
|
||||
# Floating Menu
|
||||
menu_name: bpy.props.StringProperty(default="Floating Menu") # noqa
|
||||
menu_ctrl: bpy.props.BoolProperty(default=True, update=_on_shortcut_update)
|
||||
menu_shift: bpy.props.BoolProperty(default=True, update=_on_shortcut_update)
|
||||
menu_alt: bpy.props.BoolProperty(default=False, update=_on_shortcut_update)
|
||||
menu_key: bpy.props.StringProperty(default='U', update=_on_shortcut_update) # noqa
|
||||
menu_label: bpy.props.StringProperty(default="Ctrl+Shift+U") # noqa
|
||||
|
||||
# Load SBSAR
|
||||
load_name: bpy.props.StringProperty(default="Load SBSAR") # noqa
|
||||
load_ctrl: bpy.props.BoolProperty(default=True)
|
||||
load_shift: bpy.props.BoolProperty(default=True)
|
||||
load_alt: bpy.props.BoolProperty(default=False)
|
||||
load_key: bpy.props.StringProperty(default='L') # noqa
|
||||
|
||||
# Apply Material
|
||||
apply_name: bpy.props.StringProperty(default="Apply Current Material") # noqa
|
||||
apply_ctrl: bpy.props.BoolProperty(default=True)
|
||||
apply_shift: bpy.props.BoolProperty(default=True)
|
||||
apply_alt: bpy.props.BoolProperty(default=False)
|
||||
apply_key: bpy.props.StringProperty(default='M') # noqa
|
||||
@@ -0,0 +1,33 @@
|
||||
"""
|
||||
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: props/utils.py
|
||||
# brief: Auxiliary functions for Property Groups
|
||||
# author Adobe - 3D & Immersive
|
||||
# copyright 2023 Adobe Inc. All rights reserved.
|
||||
|
||||
|
||||
from ..common import ADDON_PACKAGE
|
||||
|
||||
|
||||
def get_shaders(self, context):
|
||||
_shader_presets = []
|
||||
_addon_prefs = context.preferences.addons[ADDON_PACKAGE].preferences
|
||||
for _idx, _shader_preset in enumerate(_addon_prefs.shaders):
|
||||
_shader_presets.append(
|
||||
(str(_idx), _shader_preset.label, _shader_preset.filename)
|
||||
)
|
||||
return _shader_presets
|
||||
Reference in New Issue
Block a user