From 3606f312b0f671404cea584dfdca2d9af749e18c Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 31 Oct 2023 16:33:06 +0800 Subject: [PATCH 1/9] fix the wrong aspect ratio and viewport doesn't maximize to 1 during context --- openpype/hosts/max/api/preview_animation.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index 1bf99b86d0..bef5741343 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -23,8 +23,8 @@ def play_preview_when_done(has_autoplay): @contextlib.contextmanager -def viewport_camera(camera): - """Set viewport camera during context +def viewport_layout_and_camera(camera): + """Set viewport layout and camera during context ***For 3dsMax 2024+ Args: camera (str): viewport camera @@ -36,9 +36,12 @@ def viewport_camera(camera): original = rt.getNodeByName(camera) review_camera = rt.getNodeByName(camera) try: + if rt.viewport.getLayout() != rt.Name("layout_1"): + rt.viewport.setLayout(rt.Name("layout_1")) rt.viewport.setCamera(review_camera) yield finally: + rt.viewport.ResetAllViews() rt.viewport.setCamera(original) @@ -162,6 +165,7 @@ def _render_preview_animation_max_pre_2024( Returns: list: Created filepaths """ + # get the screenshot percent = percentSize / 100.0 res_width = int(round(rt.renderWidth * percent)) @@ -190,7 +194,7 @@ def _render_preview_animation_max_pre_2024( widthCrop = dib_height * renderRatio leftEdge = int((dib_width - widthCrop) / 2.0) tempImage_bmp = rt.bitmap(widthCrop, dib_height) - src_box_value = rt.Box2(0, leftEdge, dib_width, dib_height) + src_box_value = rt.Box2(0, leftEdge, widthCrop, 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) @@ -243,7 +247,7 @@ def render_preview_animation( if viewport_options is None: viewport_options = viewport_options_for_preview_animation() with play_preview_when_done(False): - with viewport_camera(camera): + with viewport_layout_and_camera(camera): with render_resolution(width, height): if int(get_max_version()) < 2024: with viewport_preference_setting( From e120b55fa47d7b716aa71122f4ecc3aa93ff6a06 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 31 Oct 2023 17:13:24 +0800 Subject: [PATCH 2/9] setLayout in regards to original layout --- openpype/hosts/max/api/preview_animation.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index bef5741343..22de298175 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -29,11 +29,12 @@ def viewport_layout_and_camera(camera): Args: camera (str): viewport camera """ - original = rt.viewport.getCamera() - if not original: + original_camera = rt.viewport.getCamera() + original_layout = rt.viewport.getLayout() + if not original_camera: # if there is no original camera # use the current camera as original - original = rt.getNodeByName(camera) + original_camera = rt.getNodeByName(camera) review_camera = rt.getNodeByName(camera) try: if rt.viewport.getLayout() != rt.Name("layout_1"): @@ -41,8 +42,8 @@ def viewport_layout_and_camera(camera): rt.viewport.setCamera(review_camera) yield finally: - rt.viewport.ResetAllViews() - rt.viewport.setCamera(original) + rt.viewport.setLayout(original_layout) + rt.viewport.setCamera(original_camera) @contextlib.contextmanager From dadd258cf1f1938ef609ecec689d08bb19815198 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Tue, 31 Oct 2023 17:26:25 +0800 Subject: [PATCH 3/9] make the viewport_layout_and_camera reuseable --- openpype/hosts/max/api/preview_animation.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index 22de298175..dcf243d31e 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -23,11 +23,13 @@ def play_preview_when_done(has_autoplay): @contextlib.contextmanager -def viewport_layout_and_camera(camera): +def viewport_layout_and_camera(camera, layout="layout_1"): """Set viewport layout and camera during context ***For 3dsMax 2024+ Args: camera (str): viewport camera + layout (str): layout to use in viewport, defaults to `layout_1` + Use None to not change viewport layout during context. """ original_camera = rt.viewport.getCamera() original_layout = rt.viewport.getLayout() @@ -37,8 +39,10 @@ def viewport_layout_and_camera(camera): original_camera = rt.getNodeByName(camera) review_camera = rt.getNodeByName(camera) try: - if rt.viewport.getLayout() != rt.Name("layout_1"): - rt.viewport.setLayout(rt.Name("layout_1")) + if layout is not None: + layout = rt.Name(layout) + if rt.viewport.getLayout() != layout: + rt.viewport.setLayout(layout) rt.viewport.setCamera(review_camera) yield finally: From 026aae1d0d9ebc6409acedc545c9d20950b5365a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 2 Nov 2023 21:35:18 +0800 Subject: [PATCH 4/9] add AA quality setting options & add the correct aspect ratio --- openpype/hosts/max/api/preview_animation.py | 4 +++- openpype/hosts/max/plugins/create/create_review.py | 8 +++++++- openpype/hosts/max/plugins/publish/collect_review.py | 1 + openpype/plugins/publish/extract_review.py | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index dcf243d31e..5f36b12edb 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -189,7 +189,8 @@ def _render_preview_animation_max_pre_2024( dib = rt.gw.getViewportDib() dib_width = float(dib.width) dib_height = float(dib.height) - renderRatio = float(dib_width / dib_height) + # aspect ratio + renderRatio = rt.getRendImageAspect() if viewportRatio <= renderRatio: heightCrop = (dib_width / renderRatio) topEdge = int((dib_height - heightCrop) / 2.0) @@ -311,6 +312,7 @@ def viewport_options_for_preview_animation(): viewport_options["nitrous_viewport"] = { "VisualStyleMode": "defaultshading", "ViewportPreset": "highquality", + "AntialiasingQuality": "None", "UseTextureEnabled": False } viewport_options["vp_btn_mgr"] = { diff --git a/openpype/hosts/max/plugins/create/create_review.py b/openpype/hosts/max/plugins/create/create_review.py index 8052b74f06..331d2f30ea 100644 --- a/openpype/hosts/max/plugins/create/create_review.py +++ b/openpype/hosts/max/plugins/create/create_review.py @@ -23,6 +23,7 @@ class CreateReview(plugin.MaxCreator): "percentSize", "visualStyleMode", "viewportPreset", + "antialiasingQuality", "vpTexture"]: if key in pre_create_data: creator_attributes[key] = pre_create_data[key] @@ -33,7 +34,7 @@ class CreateReview(plugin.MaxCreator): pre_create_data) def get_instance_attr_defs(self): - image_format_enum = ["exr", "jpg", "png"] + image_format_enum = ["exr", "jpg", "png", "tga"] visual_style_preset_enum = [ "Realistic", "Shaded", "Facets", @@ -45,6 +46,7 @@ class CreateReview(plugin.MaxCreator): preview_preset_enum = [ "Quality", "Standard", "Performance", "DXMode", "Customize"] + anti_aliasing_enum = ["None", "2X", "4X", "8X"] return [ NumberDef("review_width", @@ -77,6 +79,10 @@ class CreateReview(plugin.MaxCreator): preview_preset_enum, default="Quality", label="Pre-View Preset"), + EnumDef("antialiasingQuality", + anti_aliasing_enum, + default="None", + label="Anti-aliasing Quality"), BoolDef("vpTexture", label="Viewport Texture", default=False) diff --git a/openpype/hosts/max/plugins/publish/collect_review.py b/openpype/hosts/max/plugins/publish/collect_review.py index b1d9c2d25e..a579b3f4b0 100644 --- a/openpype/hosts/max/plugins/publish/collect_review.py +++ b/openpype/hosts/max/plugins/publish/collect_review.py @@ -93,6 +93,7 @@ class CollectReview(pyblish.api.InstancePlugin, nitrous_viewport = { "VisualStyleMode": creator_attrs["visualStyleMode"], "ViewportPreset": creator_attrs["viewportPreset"], + "AntialiasingQuality": creator_attrs["antialiasingQuality"], "UseTextureEnabled": creator_attrs["vpTexture"] } preview_data = { diff --git a/openpype/plugins/publish/extract_review.py b/openpype/plugins/publish/extract_review.py index 0ae941511c..db8a030dfa 100644 --- a/openpype/plugins/publish/extract_review.py +++ b/openpype/plugins/publish/extract_review.py @@ -68,7 +68,7 @@ class ExtractReview(pyblish.api.InstancePlugin): ] # Supported extensions - image_exts = ["exr", "jpg", "jpeg", "png", "dpx"] + image_exts = ["exr", "jpg", "jpeg", "png", "dpx", "tga"] video_exts = ["mov", "mp4"] supported_exts = image_exts + video_exts From 487d8dfde72a9af0b2964a15d4b57a07954ce767 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Thu, 2 Nov 2023 22:34:20 +0800 Subject: [PATCH 5/9] make sure the code doesn't break the extractor --- openpype/hosts/max/api/preview_animation.py | 14 +++++++++++++- .../hosts/max/plugins/publish/collect_review.py | 5 ++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index 5f36b12edb..0754fa61c4 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -52,6 +52,7 @@ def viewport_layout_and_camera(camera, layout="layout_1"): @contextlib.contextmanager def viewport_preference_setting(general_viewport, + nitrous_manager, nitrous_viewport, vp_button_mgr): """Function to set viewport setting during context @@ -59,6 +60,7 @@ def viewport_preference_setting(general_viewport, Args: camera (str): Viewport camera for review render general_viewport (dict): General viewport setting + nitrous_manager (dict): Nitrous graphic manager nitrous_viewport (dict): Nitrous setting for preview animation vp_button_mgr (dict): Viewport button manager Setting @@ -72,6 +74,9 @@ def viewport_preference_setting(general_viewport, vp_button_mgr_original = { key: getattr(rt.ViewportButtonMgr, key) for key in vp_button_mgr } + nitrous_manager_original = { + key: getattr(nitrousGraphicMgr, key) for key in nitrous_manager + } nitrous_viewport_original = { key: getattr(viewport_setting, key) for key in nitrous_viewport } @@ -81,6 +86,8 @@ def viewport_preference_setting(general_viewport, rt.viewport.EnableSolidBackgroundColorMode(general_viewport["dspBkg"]) for key, value in vp_button_mgr.items(): setattr(rt.ViewportButtonMgr, key, value) + for key, value in nitrous_manager.items(): + setattr(nitrousGraphicMgr, key, value) for key, value in nitrous_viewport.items(): if nitrous_viewport[key] != nitrous_viewport_original[key]: setattr(viewport_setting, key, value) @@ -91,6 +98,8 @@ def viewport_preference_setting(general_viewport, rt.viewport.EnableSolidBackgroundColorMode(orig_vp_bkg) for key, value in vp_button_mgr_original.items(): setattr(rt.ViewportButtonMgr, key, value) + for key, value in nitrous_manager_original.items(): + setattr(nitrousGraphicMgr, key, value) for key, value in nitrous_viewport_original.items(): setattr(viewport_setting, key, value) @@ -258,6 +267,7 @@ def render_preview_animation( if int(get_max_version()) < 2024: with viewport_preference_setting( viewport_options["general_viewport"], + viewport_options["nitrous_manager"], viewport_options["nitrous_viewport"], viewport_options["vp_btn_mgr"] ): @@ -309,10 +319,12 @@ def viewport_options_for_preview_animation(): "dspBkg": True, "dspGrid": False } + viewport_options["nitrous_manager"] = { + "AntialiasingQuality": "None" + } viewport_options["nitrous_viewport"] = { "VisualStyleMode": "defaultshading", "ViewportPreset": "highquality", - "AntialiasingQuality": "None", "UseTextureEnabled": False } viewport_options["vp_btn_mgr"] = { diff --git a/openpype/hosts/max/plugins/publish/collect_review.py b/openpype/hosts/max/plugins/publish/collect_review.py index a579b3f4b0..e7e957e6f1 100644 --- a/openpype/hosts/max/plugins/publish/collect_review.py +++ b/openpype/hosts/max/plugins/publish/collect_review.py @@ -90,14 +90,17 @@ class CollectReview(pyblish.api.InstancePlugin, "dspBkg": attr_values.get("dspBkg"), "dspGrid": attr_values.get("dspGrid") } + nitrous_manager = { + "AntialiasingQuality": creator_attrs["antialiasingQuality"], + } nitrous_viewport = { "VisualStyleMode": creator_attrs["visualStyleMode"], "ViewportPreset": creator_attrs["viewportPreset"], - "AntialiasingQuality": creator_attrs["antialiasingQuality"], "UseTextureEnabled": creator_attrs["vpTexture"] } preview_data = { "general_viewport": general_viewport, + "nitrous_manager": nitrous_manager, "nitrous_viewport": nitrous_viewport, "vp_btn_mgr": {"EnableButtons": False} } From 44a0b0e6284a73180dccdef244fe92c5761caaf0 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 3 Nov 2023 22:42:44 +0800 Subject: [PATCH 6/9] make sure the aspect ratio correct --- openpype/hosts/max/api/preview_animation.py | 51 +++++++++++---------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index 0754fa61c4..d6becd499e 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -166,13 +166,16 @@ def _render_preview_animation_max_2024( def _render_preview_animation_max_pre_2024( - filepath, startFrame, endFrame, percentSize, ext): + filepath, startFrame, endFrame, + width, height, percentSize, ext): """Render viewport animation by creating bitmaps ***For 3dsMax Version <2024 Args: filepath (str): filepath without frame numbers and extension startFrame (int): start frame endFrame (int): end frame + width (int): render resolution width + height (int): render resolution height percentSize (float): render resolution multiplier by 100 e.g. 100.0 is 1x, 50.0 is 0.5x, 150.0 is 1.5x ext (str): image extension @@ -182,9 +185,8 @@ def _render_preview_animation_max_pre_2024( # get the screenshot percent = percentSize / 100.0 - res_width = int(round(rt.renderWidth * percent)) - res_height = int(round(rt.renderHeight * percent)) - viewportRatio = float(res_width / res_height) + res_width = int(round(width * percent)) + res_height = int(round(height * percent)) frame_template = "{}.{{:04}}.{}".format(filepath, ext) frame_template.replace("\\", "/") files = [] @@ -196,10 +198,11 @@ def _render_preview_animation_max_pre_2024( res_width, res_height, filename=filepath ) dib = rt.gw.getViewportDib() - dib_width = float(dib.width) - dib_height = float(dib.height) + dib_width = rt.renderWidth + dib_height = rt.renderHeight # aspect ratio - renderRatio = rt.getRendImageAspect() + viewportRatio = dib_width /dib_height + renderRatio = float(res_width / res_height) if viewportRatio <= renderRatio: heightCrop = (dib_width / renderRatio) topEdge = int((dib_height - heightCrop) / 2.0) @@ -263,22 +266,24 @@ def render_preview_animation( viewport_options = viewport_options_for_preview_animation() with play_preview_when_done(False): with viewport_layout_and_camera(camera): - with render_resolution(width, height): - if int(get_max_version()) < 2024: - with viewport_preference_setting( - viewport_options["general_viewport"], - viewport_options["nitrous_manager"], - viewport_options["nitrous_viewport"], - viewport_options["vp_btn_mgr"] - ): - return _render_preview_animation_max_pre_2024( - filepath, - start_frame, - end_frame, - percentSize, - ext - ) - else: + if int(get_max_version()) < 2024: + with viewport_preference_setting( + viewport_options["general_viewport"], + viewport_options["nitrous_manager"], + viewport_options["nitrous_viewport"], + viewport_options["vp_btn_mgr"] + ): + return _render_preview_animation_max_pre_2024( + filepath, + start_frame, + end_frame, + width, + height, + percentSize, + ext + ) + else: + with render_resolution(width, height): return _render_preview_animation_max_2024( filepath, start_frame, From 01c965eb9cb701eee833cb735dcec0daf4f6f61a Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 3 Nov 2023 22:43:34 +0800 Subject: [PATCH 7/9] hound --- openpype/hosts/max/api/preview_animation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index d6becd499e..bd0fee3658 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -201,7 +201,7 @@ def _render_preview_animation_max_pre_2024( dib_width = rt.renderWidth dib_height = rt.renderHeight # aspect ratio - viewportRatio = dib_width /dib_height + viewportRatio = dib_width / dib_height renderRatio = float(res_width / res_height) if viewportRatio <= renderRatio: heightCrop = (dib_width / renderRatio) From 026fa6567680e4079c20158f16edad466b777999 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Mon, 6 Nov 2023 21:19:30 +0800 Subject: [PATCH 8/9] value tweaks on aspect ratio --- openpype/hosts/max/api/preview_animation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index bd0fee3658..bbf05f4ca9 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -185,8 +185,8 @@ def _render_preview_animation_max_pre_2024( # get the screenshot percent = percentSize / 100.0 - res_width = int(round(width * percent)) - res_height = int(round(height * percent)) + res_width = width * percent + res_height = height * percent frame_template = "{}.{{:04}}.{}".format(filepath, ext) frame_template.replace("\\", "/") files = [] @@ -212,7 +212,7 @@ def _render_preview_animation_max_pre_2024( widthCrop = dib_height * renderRatio leftEdge = int((dib_width - widthCrop) / 2.0) tempImage_bmp = rt.bitmap(widthCrop, dib_height) - src_box_value = rt.Box2(0, leftEdge, widthCrop, dib_height) + src_box_value = rt.Box2(leftEdge, 0, widthCrop, 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) From ae4bb7dacfba6d0326aea7cc904128e8440da4d6 Mon Sep 17 00:00:00 2001 From: Kayla Man Date: Fri, 10 Nov 2023 16:38:21 +0800 Subject: [PATCH 9/9] make sure if the aspect ratio is 16:9 and follows the render aspect ratio, the render sequences wont be cropped --- openpype/hosts/max/api/preview_animation.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/openpype/hosts/max/api/preview_animation.py b/openpype/hosts/max/api/preview_animation.py index bbf05f4ca9..6c7b8eaa80 100644 --- a/openpype/hosts/max/api/preview_animation.py +++ b/openpype/hosts/max/api/preview_animation.py @@ -203,20 +203,24 @@ def _render_preview_animation_max_pre_2024( # aspect ratio viewportRatio = dib_width / dib_height renderRatio = float(res_width / res_height) - if viewportRatio <= renderRatio: + if viewportRatio < renderRatio: heightCrop = (dib_width / renderRatio) topEdge = int((dib_height - heightCrop) / 2.0) tempImage_bmp = rt.bitmap(dib_width, heightCrop) src_box_value = rt.Box2(0, topEdge, dib_width, heightCrop) - else: + rt.pasteBitmap(dib, tempImage_bmp, src_box_value, rt.Point2(0, 0)) + rt.copy(tempImage_bmp, preview_res) + rt.close(tempImage_bmp) + elif viewportRatio > renderRatio: widthCrop = dib_height * renderRatio leftEdge = int((dib_width - widthCrop) / 2.0) tempImage_bmp = rt.bitmap(widthCrop, dib_height) src_box_value = rt.Box2(leftEdge, 0, widthCrop, 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.pasteBitmap(dib, tempImage_bmp, src_box_value, rt.Point2(0, 0)) + rt.copy(tempImage_bmp, preview_res) + rt.close(tempImage_bmp) + else: + rt.copy(dib, preview_res) rt.save(preview_res) rt.close(preview_res) rt.close(dib)