Skip to content

Commit

Permalink
big roy's comment - code tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
moonyuet committed Dec 6, 2024
1 parent 206ffe6 commit b31c5e1
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ def process(self, instance):
texture_sets_by_map_identifier[map_identifier].extend(outputs)
for map_identifier, outputs in texture_sets_by_map_identifier.items():
self.log.info(f"Processing {map_identifier}")
self.create_image_instance_by_map_filtering(
instance, outputs, task_entity, map_identifier)
self.create_image_instance(instance, template, outputs,
task_entity=task_entity,
texture_set_name=texture_set_name,
stack_name=stack_name)

else:
for (texture_set_name, stack_name), template_maps in maps.items():
Expand All @@ -79,9 +81,22 @@ def create_image_instance(self, instance, template, outputs,

context = instance.context
first_filepath = outputs[0]["filepath"]
is_single_output = instance.data["creator_attributes"].get(
"exportTextureSetsAsOneOutput", False)
fnames = [os.path.basename(output["filepath"]) for output in outputs]
ext = os.path.splitext(first_filepath)[1]
assert ext.lstrip("."), f"No extension: {ext}"
if is_single_output:
# Function to remove textureSet from filepath
def remove_texture_set_token(filepath, texture_set):
return filepath.replace(texture_set, "")

fnames = [
remove_texture_set_token(
output["output"], output["textureSet"]
)
for output in outputs
]

always_include_texture_set_name = False # todo: make this configurable
all_texture_sets = substance_painter.textureset.all_texture_sets()
Expand All @@ -92,12 +107,13 @@ def create_image_instance(self, instance, template, outputs,
# Define the suffix we want to give this particular texture
# set and set up a remapped product naming for it.
suffix = ""
if always_include_texture_set_name or len(all_texture_sets) > 1:
# More than one texture set, include texture set name
suffix += f".{texture_set_name}"
if texture_set.is_layered_material() and stack_name:
# More than one stack, include stack name
suffix += f".{stack_name}"
if not is_single_output:
if always_include_texture_set_name or len(all_texture_sets) > 1:
# More than one texture set, include texture set name
suffix += f".{texture_set_name}"
if texture_set.is_layered_material() and stack_name:
# More than one stack, include stack name
suffix += f".{stack_name}"

# Always include the map identifier
map_identifier = strip_template(template)
Expand Down Expand Up @@ -162,6 +178,10 @@ def create_image_instance(self, instance, template, outputs,
image_instance.data["families"] = [product_type, "textures"]
if instance.data["creator_attributes"].get("review"):
image_instance.data["families"].append("review")
if is_single_output:
image_instance.data["image_outputs"] = [
os.path.basename(output["filepath"]) for output in outputs
]

image_instance.data["representations"] = [representation]

Expand All @@ -172,110 +192,6 @@ def create_image_instance(self, instance, template, outputs,
image_instance.data["textureSetName"] = texture_set_name
image_instance.data["textureStackName"] = stack_name

# Store color space with the instance
# Note: The extractor will assign it to the representation
colorspace = outputs[0].get("colorSpace")
if colorspace:
self.log.debug(f"{image_product_name} colorspace: {colorspace}")
image_instance.data["colorspace"] = colorspace

# Store the instance in the original instance as a member
instance.append(image_instance)

def create_image_instance_by_map_filtering(self, instance, outputs,
task_entity, map_identifier):
"""Create a new instance per image based on map filtering.
The new instances will be of product type `image`.
**Only used for exporting multiple texture sets as one texture output
"""

context = instance.context
first_filepath = outputs[0]["filepath"]
fnames = [os.path.basename(output["filepath"]) for output in outputs]
ext = os.path.splitext(first_filepath)[1]
assert ext.lstrip("."), f"No extension: {ext}"
# Function to remove textureSet from filepath
def remove_texture_set_token(filepath, texture_set):
return filepath.replace(texture_set, '')

fnames_without_textureSet = [
remove_texture_set_token(output["output"], output["textureSet"])
for output in outputs
]

task_name = task_type = None
if task_entity:
task_name = task_entity["name"]
task_type = task_entity["taskType"]

# TODO: The product type actually isn't 'texture' currently but
# for now this is only done so the product name starts with
# 'texture'
image_product_name = get_product_name(
context.data["projectName"],
task_name,
task_type,
context.data["hostName"],
product_type="texture",
variant=instance.data["variant"] + f".{map_identifier}",
project_settings=context.data["project_settings"]
)
image_product_group_name = get_product_name(
context.data["projectName"],
task_name,
task_type,
context.data["hostName"],
product_type="texture",
variant=instance.data["variant"],
project_settings=context.data["project_settings"]
)

# Prepare representation
representation = {
"name": ext.lstrip("."),
"ext": ext.lstrip("."),
#TODO: strip the texture_sets.
"files": (
fnames_without_textureSet
if len(fnames_without_textureSet) > 1
else fnames_without_textureSet[0]
),
}

# Mark as UDIM explicitly if it has UDIM tiles.
if bool(outputs[0].get("udim")):
# The representation for a UDIM sequence should have a `udim` key
# that is a list of all udim tiles (str) like: ["1001", "1002"]
# strings. See CollectTextures plug-in and Integrators.
representation["udim"] = [output["udim"] for output in outputs]

# Set up the representation for thumbnail generation
# TODO: Simplify this once thumbnail extraction is refactored
staging_dir = os.path.dirname(first_filepath)
representation["tags"] = ["review"]
representation["stagingDir"] = staging_dir
# Clone the instance
product_type = "image"
image_instance = context.create_instance(image_product_name)
image_instance[:] = instance[:]
image_instance.data.update(copy.deepcopy(dict(instance.data)))
image_instance.data["name"] = image_product_name
image_instance.data["label"] = image_product_name
image_instance.data["productName"] = image_product_name
image_instance.data["productType"] = product_type
image_instance.data["family"] = product_type
image_instance.data["families"] = [product_type, "textures"]
if instance.data["creator_attributes"].get("review"):
image_instance.data["families"].append("review")
image_instance.data["image_outputs"] = fnames
image_instance.data["representations"] = [representation]

# Group the textures together in the loader
image_instance.data["productGroup"] = image_product_group_name


# Store color space with the instance
# Note: The extractor will assign it to the representation
colorspace = outputs[0].get("colorSpace")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,18 @@
)


def convert_texture_maps_for_udim_export(staging_dir, image_outputs, has_udim=False):
def get_texture_outputs(staging_dir, image_outputs, has_udim=False):
"""Getting the expected texture output(s) with/without udim sequence
before merging them with oiio tools.
Args:
staging_dir (str): staging dir
image_outputs (list): source image outputs
has_udim (bool, optional): Is with UDIM. Defaults to False.
Returns:
list: Texture outputs which are used for merging.
"""
if has_udim:
collections, remainder = clique.assemble(image_outputs, minimum_items=1)
return [
Expand All @@ -29,9 +40,9 @@ def convert_texture_maps_as_single_output(staging_dir, source_image_outputs,
log=None):
oiio_tool_args = get_oiio_tool_args("oiiotool")

source_maps = convert_texture_maps_for_udim_export(
source_maps = get_texture_outputs(
staging_dir, source_image_outputs, has_udim=has_udim)
dest_map = next(convert_texture_maps_for_udim_export(
dest_map = next(get_texture_outputs(
staging_dir, dest_image_outputs, has_udim=has_udim
), None)

Expand All @@ -44,13 +55,11 @@ def convert_texture_maps_as_single_output(staging_dir, source_image_outputs,
subprocess_args = " ".join(oiio_cmd)

env = os.environ.copy()
env.pop("OCIO", None)
log.info(" ".join(subprocess_args))

try:
run_subprocess(subprocess_args, env=env)
except Exception:
log.error("Texture maketx conversion failed", exc_info=True)
raise
except Exception as exc:
raise RuntimeError("Flattening texture stack to single output image failed") from exc


class ExtractTexturesAsSingleOutput(publish.Extractor):
Expand All @@ -69,25 +78,28 @@ class ExtractTexturesAsSingleOutput(publish.Extractor):
order = publish.Extractor.order - 0.099

def process(self, instance):
if "exportTextureSetsAsOneOutput" not in instance.data["creator_attributes"]:
if not instance.data.get("creator_attributes", {}).get(
"exportTextureSetsAsOneOutput", False):
self.log.debug(
"Skipping to export texture sets as single texture output.."
)
return

representations: "list[dict]" = instance.data["representations"]
repre = representations[0]

staging_dir = instance.data["stagingDir"]
source_image_outputs = instance.data["image_outputs"]
has_udim = False
dest_image_outputs = []
for representation in list(representations):
dest_files = representation["files"]
is_sequence = isinstance(dest_files, (list, tuple))
if not is_sequence:
dest_image_outputs = [dest_image_outputs]
if "udim" in representation:
has_udim = True
dest_files = repre["files"]
is_sequence = isinstance(dest_files, (list, tuple))
if not is_sequence:
dest_image_outputs = [dest_image_outputs]
else:
dest_image_outputs = dest_files
if "udim" in repre:
has_udim = True

convert_texture_maps_as_single_output(
staging_dir, source_image_outputs,
Expand Down

0 comments on commit b31c5e1

Please sign in to comment.