clean up code for preview animation

This commit is contained in:
Kayla Man 2023-10-20 00:30:24 +08:00
parent 71e9d6cc13
commit e24140715b
2 changed files with 90 additions and 93 deletions

View file

@ -92,96 +92,92 @@ def viewport_preference_setting(general_viewport,
setattr(viewport_setting, key, value)
def publish_review_animation(instance, staging_dir, start,
end, ext, fps, viewport_options):
def _render_preview_animation_max_2024(
filepath, start, end, ext, viewport_options):
"""Function to set up preview arguments in MaxScript.
****For 3dsMax 2024+
Args:
instance (str): instance
filepath (str): output of the preview animation
filepath (str): filepath for render output without frame number and
extension, for example: /path/to/file
start (int): startFrame
end (int): endFrame
fps (float): fps value
viewport_options (dict): viewport setting options
viewport_options (dict): viewport setting options, e.g.
{"vpStyle": "defaultshading", "vpPreset": "highquality"}
Returns:
list: job arguments
list: Created files
"""
job_args = list()
filename = "{0}..{1}".format(instance.name, ext)
filepath = os.path.join(staging_dir, filename)
filepath = filepath.replace("\\", "/")
filepath = f"{filepath}..{ext}"
frame_template = f"{filepath}.{{:04d}}.{ext}"
job_args = list()
default_option = f'CreatePreview filename:"{filepath}"'
job_args.append(default_option)
frame_option = f"outputAVI:false start:{start} end:{end} fps:{fps}" # noqa
frame_option = f"outputAVI:false start:{start} end:{end}"
job_args.append(frame_option)
for key, value in viewport_options.items():
if isinstance(value, bool):
if value:
job_args.append(f"{key}:{value}")
elif isinstance(value, str):
if key == "vpStyle":
if viewport_options[key] == "Realistic":
if value == "Realistic":
value = "defaultshading"
elif viewport_options[key] == "Shaded":
elif value == "Shaded":
log.warning(
"'Shaded' Mode not supported in "
"preview animation in Max 2024..\n"
"Using 'defaultshading' instead")
"preview animation in Max 2024.\n"
"Using 'defaultshading' instead.")
value = "defaultshading"
elif viewport_options[key] == "ConsistentColors":
elif value == "ConsistentColors":
value = "flatcolor"
else:
value = value.lower()
elif key == "vpPreset":
if viewport_options[key] == "Quality":
if value == "Quality":
value = "highquality"
elif viewport_options[key] == "Customize":
elif value == "Customize":
value = "userdefined"
else:
value = value.lower()
job_args.append(f"{key}: #{value}")
auto_play_option = "autoPlay:false"
job_args.append(auto_play_option)
job_str = " ".join(job_args)
log.debug(job_str)
return job_str
rt.completeRedraw()
rt.execute(job_str)
# Return the created files
return [frame_template.format(frame) for frame in range(start, end + 1)]
def publish_preview_sequences(staging_dir, filename,
startFrame, endFrame,
percentSize, ext):
"""publish preview animation by creating bitmaps
def _render_preview_animation_max_pre_2024(
filepath, startFrame, endFrame, percentSize, ext):
"""Render viewport animation by creating bitmaps
***For 3dsMax Version <2024
Args:
staging_dir (str): staging directory
filename (str): filename
filepath (str): filepath without frame numbers and extension
startFrame (int): start frame
endFrame (int): end frame
percentSize (int): percentage of the resolution
ext (str): image extension
Returns:
list: Created filepaths
"""
# get the screenshot
resolution_percentage = float(percentSize) / 100
res_width = rt.renderWidth * resolution_percentage
res_height = rt.renderHeight * resolution_percentage
viewportRatio = float(res_width / res_height)
for i in range(startFrame, endFrame + 1):
rt.sliderTime = i
fname = "{}.{:04}.{}".format(filename, i, ext)
filepath = os.path.join(staging_dir, fname)
filepath = filepath.replace("\\", "/")
frame_template = "{}.{{:04}}.{}".format(filepath, ext)
frame_template.replace("\\", "/")
files = []
user_cancelled = False
for frame in range(startFrame, endFrame + 1):
rt.sliderTime = frame
filepath = frame_template.format(frame)
preview_res = rt.bitmap(
res_width, res_height, filename=filepath)
res_width, res_height, filename=filepath
)
dib = rt.gw.getViewportDib()
dib_width = float(dib.width)
dib_height = float(dib.height)
@ -197,71 +193,78 @@ def publish_preview_sequences(staging_dir, filename,
tempImage_bmp = rt.bitmap(widthCrop, dib_height)
src_box_value = rt.Box2(0, leftEdge, dib_width, dib_height)
rt.pasteBitmap(dib, tempImage_bmp, src_box_value, rt.Point2(0, 0))
# copy the bitmap and close it
rt.copy(tempImage_bmp, preview_res)
rt.close(tempImage_bmp)
rt.save(preview_res)
rt.close(preview_res)
rt.close(dib)
if rt.keyboard.escPressed:
rt.exit()
files.append(filepath)
# clean up the cache
if rt.keyboard.escPressed:
user_cancelled = True
break
rt.gc(delayed=True)
if user_cancelled:
raise RuntimeError("User cancelled rendering of viewport animation.")
return files
def render_preview_animation(
instance, staging_dir,
ext, review_camera,
startFrame=None, endFrame=None,
resolution=None,
filepath,
ext,
review_camera,
start_frame=None,
end_frame=None,
width=1920,
height=1080,
viewport_options=None):
"""Render camera review animation
Args:
instance (pyblish.api.instance): Instance
filepath (str): filepath
filepath (str): filepath to render to, without frame number and
extension
ext (str): output file extension
review_camera (str): viewport camera for preview render
startFrame (int): start frame
endFrame (int): end frame
start_frame (int): start frame
end_frame (int): end frame
width (int): render resolution width
height (int): render resolution height
viewport_options (dict): viewport setting options
Returns:
list: Rendered output files
"""
if start_frame is None:
start_frame = int(rt.animationRange.start)
if end_frame is None:
end_frame = int(rt.animationRange.end)
if startFrame is None:
startFrame = int(rt.animationRange.start)
if endFrame is None:
endFrame = int(rt.animationRange.end)
if viewport_options is None:
viewport_options = viewport_options_for_preview_animation()
if resolution is None:
resolution = (1920, 1080)
with play_preview_when_done(False):
with viewport_camera(review_camera):
width, height = resolution
with render_resolution(width, height):
if int(get_max_version()) < 2024:
with viewport_preference_setting(
viewport_options["general_viewport"],
viewport_options["nitrous_viewport"],
viewport_options["vp_btn_mgr"]):
viewport_options["vp_btn_mgr"]
):
percentSize = viewport_options.get("percentSize", 100)
publish_preview_sequences(
staging_dir, instance.name,
startFrame, endFrame, percentSize, ext)
return _render_preview_animation_max_pre_2024(
filepath,
start_frame,
end_frame,
percentSize,
ext
)
else:
fps = instance.data["fps"]
rt.completeRedraw()
preview_arg = publish_review_animation(
instance, staging_dir,
startFrame, endFrame,
ext, fps, viewport_options)
rt.execute(preview_arg)
rt.completeRedraw()
return _render_preview_animation_max_2024(
filepath,
start_frame,
end_frame,
ext,
viewport_options
)
def viewport_options_for_preview_animation():

View file

@ -24,8 +24,6 @@ class ExtractReviewAnimation(publish.Extractor):
end = int(instance.data["frameEnd"])
filepath = os.path.join(staging_dir, filename)
filepath = filepath.replace("\\", "/")
filenames = self.get_files(
instance.name, start, end, ext)
self.log.debug(
"Writing Review Animation to"
@ -34,13 +32,18 @@ class ExtractReviewAnimation(publish.Extractor):
review_camera = instance.data["review_camera"]
viewport_options = instance.data.get("viewport_options", {})
resolution = instance.data.get("resolution", ())
render_preview_animation(
instance, staging_dir,
ext, review_camera,
startFrame=start, endFrame=end,
resolution=resolution,
files = render_preview_animation(
os.path.join(staging_dir, instance.name),
ext,
review_camera,
start,
end,
width=resolution[0],
height=resolution[1],
viewport_options=viewport_options)
filenames = [os.path.basename(path) for path in files]
tags = ["review"]
if not instance.data.get("keepImages"):
tags.append("delete")
@ -63,12 +66,3 @@ class ExtractReviewAnimation(publish.Extractor):
if "representations" not in instance.data:
instance.data["representations"] = []
instance.data["representations"].append(representation)
def get_files(self, filename, start, end, ext):
file_list = []
for frame in range(int(start), int(end) + 1):
actual_name = "{}.{:04}.{}".format(
filename, frame, ext)
file_list.append(actual_name)
return file_list