diff --git a/mel/AETemplates/AEmmImagePlaneShapeTemplate.mel b/mel/AETemplates/AEmmImagePlaneShapeTemplate.mel
index 075ba7ff..73dbd9dc 100644
--- a/mel/AETemplates/AEmmImagePlaneShapeTemplate.mel
+++ b/mel/AETemplates/AEmmImagePlaneShapeTemplate.mel
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2022 David Cattermole.
+// Copyright (C) 2022, 2024 David Cattermole.
//
// This file is part of mmSolver.
//
@@ -97,11 +97,14 @@ global proc AEmmImagePlaneShape_browser(
string $cmd = "";
$cmd = $cmd + "import mmSolver.tools.createimageplane.tool as tool;\n";
$cmd = $cmd + "import mmSolver.tools.createimageplane.lib as lib;\n";
+ $cmd = $cmd + "\n";
$cmd = $cmd + "image_seq = tool.prompt_user_for_image_sequence();\n";
+ $cmd = $cmd + "\n";
+ $cmd = $cmd + "mm_ip_shp = \"" + $image_plane_shp + "\";\n";
+ $cmd = $cmd + "attr_name = \"" + $attr_name + "\";\n";
+ $cmd = $cmd + "current_slot_attr = \"" + $slot_attr_name + "\";\n";
+ $cmd = $cmd + "\n";
$cmd = $cmd + "if image_seq:\n";
- $cmd = $cmd + " mm_ip_shp = \"" + $image_plane_shp + "\";\n";
- $cmd = $cmd + " attr_name = \"" + $attr_name + "\";\n";
- $cmd = $cmd + " current_slot_attr = \"" + $slot_attr_name + "\";\n";
$cmd = $cmd + " if attr_name == current_slot_attr:\n";
$cmd = $cmd + " lib.set_image_sequence(\n";
$cmd = $cmd + " mm_ip_shp,\n";
@@ -132,16 +135,18 @@ global proc AEmmImagePlaneShape_sequenceSlotChanged(
AEmmImagePlaneShape_setSlotValue($image_plane_shp, $slot_attr_value);
string $cmd = "";
- $cmd = $cmd + "import os.path;\n";
$cmd = $cmd + "import mmSolver.tools.createimageplane.tool as tool;\n";
$cmd = $cmd + "import mmSolver.tools.createimageplane.lib as lib;\n";
+ $cmd = $cmd + "\n";
$cmd = $cmd + "mm_ip_shp = \"" + $image_plane_shp + "\";\n";
$cmd = $cmd + "attr_name = \"" + $attr_name + "\";\n";
$cmd = $cmd + "current_slot_attr = \"" + $slot_attr_name + "\";\n";
+ $cmd = $cmd + "\n";
$cmd = $cmd + "image_seq = maya.cmds.getAttr(\n";
$cmd = $cmd + " mm_ip_shp + '.' + current_slot_attr) or ''\n";
- $cmd = $cmd + "if len(image_seq) == 0 or not os.path.isfile(image_seq):\n";
+ $cmd = $cmd + "if len(image_seq) == 0:\n";
$cmd = $cmd + " image_seq = lib.get_default_image_path();\n";
+ $cmd = $cmd + "\n";
$cmd = $cmd + "lib.set_image_sequence(\n";
$cmd = $cmd + " mm_ip_shp,\n";
$cmd = $cmd + " image_seq,\n";
@@ -233,12 +238,15 @@ global proc AEmmImagePlaneShapeTemplate(string $nodeName)
editorTemplate -beginLayout "Display" -collapse 0;
editorTemplate -addControl "visibleToCameraOnly";
editorTemplate -addSeparator;
- editorTemplate -addControl "exposure";
- editorTemplate -addControl "gamma";
editorTemplate -addControl "colorGain";
+ editorTemplate -addControl "colorExposure";
+ editorTemplate -addControl "colorGamma";
+ editorTemplate -addControl "colorSaturation";
+ editorTemplate -addControl "colorSoftClip";
editorTemplate -addControl "alphaGain";
- // editorTemplate -addSeparator;
- // editorTemplate -addControl "colorSpace"; // Might not be possible.
+ editorTemplate -addSeparator;
+ editorTemplate -addControl "imageIgnoreAlpha";
+ editorTemplate -addControl "displayChannel";
editorTemplate -endLayout;
editorTemplate -beginLayout "Image Sequence" -collapse 0;
@@ -270,6 +278,18 @@ global proc AEmmImagePlaneShapeTemplate(string $nodeName)
"AEmmImagePlaneShape_imageSequenceReplace"
"imageSequenceAlternate3";
+ editorTemplate -addSeparator;
+ editorTemplate -addControl "imageWidth";
+ editorTemplate -addControl "imageHeight";
+ editorTemplate -addControl "imagePixelAspect";
+ editorTemplate -addSeparator;
+ editorTemplate -addControl "imageSequenceStartFrame";
+ editorTemplate -addControl "imageSequenceEndFrame";
+ editorTemplate -addSeparator;
+ // TODO: Use mmColorIO results to allow users to manually give the
+ // inputColorSpace.
+ editorTemplate -addControl "inputColorSpace";
+ editorTemplate -addSeparator;
// TODO: Add radio button to choose what will connect to the
// 'imageSequenceFrame' value? Options are:
// - Scene Time (time1)
@@ -279,15 +299,8 @@ global proc AEmmImagePlaneShapeTemplate(string $nodeName)
editorTemplate -addControl "imageSequenceFirstFrame";
editorTemplate -addControl "imageSequenceFrameOutput";
editorTemplate -addSeparator;
- editorTemplate -addControl "imageLoadEnable";
- editorTemplate -addControl "imageUseAlphaChannel";
- editorTemplate -addSeparator;
- editorTemplate -addControl "imageWidth";
- editorTemplate -addControl "imageHeight";
- editorTemplate -addControl "imagePixelAspect";
- editorTemplate -addSeparator;
- editorTemplate -addControl "imageSequenceStartFrame";
- editorTemplate -addControl "imageSequenceEndFrame";
+ editorTemplate -addControl "imageFlip";
+ editorTemplate -addControl "imageFlop";
editorTemplate -endLayout;
editorTemplate -beginLayout "HUD" -collapse 0;
@@ -298,24 +311,31 @@ global proc AEmmImagePlaneShapeTemplate(string $nodeName)
// TODO: Add 'hudTextColor' - control the HUD text color.
editorTemplate -endLayout;
+ // editorTemplate -beginLayout "Image Cache" -collapse 1;
+ // // TODO: Add controls to view and edit the image cache.
+ // editorTemplate -endLayout;
+
editorTemplate -beginLayout "Miscellaneous" -collapse 1;
editorTemplate -addControl "meshResolution";
editorTemplate -addControl "imageDefaultColor"; // Cannot be textured.
+ editorTemplate -addControl "shaderIsTransparent";
editorTemplate -endLayout;
editorTemplate -beginLayout "Nodes" -collapse 1;
- editorTemplate -addControl "shaderNode";
- editorTemplate -addControl "shaderFileNode";
editorTemplate -addControl "geometryNode";
editorTemplate -addControl "cameraNode";
editorTemplate -addControl "imagePlaneShapeNode";
editorTemplate -endLayout;
- editorTemplate -suppress "imageSequencePadding";
- editorTemplate -suppress "cameraWidthInch";
- editorTemplate -suppress "cameraHeightInch";
- editorTemplate -suppress "lensHashCurrent";
- editorTemplate -suppress "lensHashPrevious";
+ // // Internals that we don't want the user to see.
+ // editorTemplate -suppress "imageSequencePadding";
+ // editorTemplate -suppress "cameraWidthInch";
+ // editorTemplate -suppress "cameraHeightInch";
+ // editorTemplate -suppress "lensHashCurrent";
+ // editorTemplate -suppress "lensHashPrevious";
+ // editorTemplate -suppress "imageFilePath";
+ // editorTemplate -suppress "inputColorSpace";
+ // editorTemplate -suppress "outputColorSpace";
AEmmNodeShapeTemplateCommonEnd($nodeName);
}
diff --git a/python/mmSolver/tools/createimageplane/_lib/constant.py b/python/mmSolver/tools/createimageplane/_lib/constant.py
index c8fa6d3b..20761606 100644
--- a/python/mmSolver/tools/createimageplane/_lib/constant.py
+++ b/python/mmSolver/tools/createimageplane/_lib/constant.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 David Cattermole.
+# Copyright (C) 2022, 2024 David Cattermole.
#
# This file is part of mmSolver.
#
@@ -17,3 +17,20 @@
#
DEFAULT_IMAGE_SEQUENCE_ATTR_NAME = 'imageSequenceMain'
+ALT_1_IMAGE_SEQUENCE_ATTR_NAME = 'imageSequenceAlternate1'
+ALT_2_IMAGE_SEQUENCE_ATTR_NAME = 'imageSequenceAlternate2'
+ALT_3_IMAGE_SEQUENCE_ATTR_NAME = 'imageSequenceAlternate3'
+
+VALID_INPUT_IMAGE_SEQUENCE_ATTR_NAMES = [
+ DEFAULT_IMAGE_SEQUENCE_ATTR_NAME,
+ ALT_1_IMAGE_SEQUENCE_ATTR_NAME,
+ ALT_2_IMAGE_SEQUENCE_ATTR_NAME,
+ ALT_3_IMAGE_SEQUENCE_ATTR_NAME,
+]
+
+SHADER_FILE_PATH_ATTR_NAME = 'imageFilePath'
+INPUT_COLOR_SPACE_ATTR_NAME = 'inputColorSpace'
+OUTPUT_COLOR_SPACE_ATTR_NAME = 'outputColorSpace'
+
+SCENE_LINEAR_FILE_EXTENSIONS = ['exr', 'sxr']
+SRGB_FILE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'tif', 'tiff', 'tga', 'iff']
diff --git a/python/mmSolver/tools/createimageplane/_lib/main.py b/python/mmSolver/tools/createimageplane/_lib/main.py
index 18a8a555..8f272dd3 100644
--- a/python/mmSolver/tools/createimageplane/_lib/main.py
+++ b/python/mmSolver/tools/createimageplane/_lib/main.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2020, 2022 David Cattermole.
+# Copyright (C) 2020, 2022, 2024 David Cattermole.
#
# This file is part of mmSolver.
#
@@ -25,12 +25,13 @@
import mmSolver.logger
import mmSolver.api as mmapi
import mmSolver.utils.camera as camera_utils
+import mmSolver.utils.constant as const_utils
+import mmSolver.utils.imageseq as imageseq_utils
import mmSolver.utils.python_compat as pycompat
import mmSolver.tools.createimageplane.constant as const
import mmSolver.tools.createimageplane._lib.constant as lib_const
import mmSolver.tools.createimageplane._lib.utilities as lib_utils
-import mmSolver.tools.createimageplane._lib.shader as lib_shader
import mmSolver.tools.createimageplane._lib.mmimageplane as lib_mmimageplane
import mmSolver.tools.createimageplane._lib.polyplane as lib_polyplane
import mmSolver.tools.createimageplane._lib.nativeimageplane as lib_nativeimageplane
@@ -56,20 +57,18 @@ def create_image_plane_on_camera(cam, name=None):
poly_plane_name, mm_ip_tfm, cam_shp
)
- name_shade = name + 'Shader'
- shader_network = lib_shader.create_network(name_shade, mm_ip_tfm)
-
name_img_shp = name + 'Shape'
mm_ip_shp = lib_mmimageplane.create_shape_node(
- name_img_shp, mm_ip_tfm, cam_shp, poly_plane_network, shader_network
- )
-
- # Shortcut connections to nodes.
- lib_utils.force_connect_attr(
- shader_network.file_node + '.message', mm_ip_tfm + '.shaderFileNode'
+ name_img_shp,
+ mm_ip_tfm,
+ cam_shp,
+ poly_plane_network,
)
# Logic to calculate the frame number.
+ #
+ # TODO: Move this expression into a Maya node, because expressions
+ # are buggy and not flexible.
frame_expr = const.FRAME_EXPRESSION.format(node=mm_ip_shp)
frame_expr = frame_expr.replace('{{', '{')
frame_expr = frame_expr.replace('}}', '}')
@@ -79,17 +78,6 @@ def create_image_plane_on_camera(cam, name=None):
shp_node_attr = mm_ip_shp + '.imageSequenceFrameOutput'
maya.cmds.setAttr(shp_node_attr, lock=True)
- # Set useFrameExtension temporarily. Setting useFrameExtension to
- # False causes frameOffset to be locked (but we need to edit it).
- is_seq = maya.cmds.getAttr(shader_network.file_node + '.useFrameExtension')
- maya.cmds.setAttr(shader_network.file_node + '.useFrameExtension', True)
-
- file_node_attr = shader_network.file_node + '.frameExtension'
- lib_utils.force_connect_attr(shp_node_attr, file_node_attr)
- maya.cmds.setAttr(file_node_attr, lock=True)
-
- maya.cmds.setAttr(shader_network.file_node + '.useFrameExtension', is_seq)
-
# Image sequence.
image_sequence_path = lib_utils.get_default_image_path()
set_image_sequence(mm_ip_tfm, image_sequence_path)
@@ -120,12 +108,12 @@ def convert_image_planes_on_camera(cam):
lib_nativeimageplane.copy_depth_value(mm_ip_tfm, native_ip_shp)
- name_shader = name + 'Shader'
- shader_network = lib_shader.create_network(name_shader, mm_ip_tfm)
-
name_img_shp = name + 'Shape'
mm_ip_shp = lib_mmimageplane.create_shape_node(
- name_img_shp, mm_ip_tfm, cam_shp, poly_plane_network, shader_network
+ name_img_shp,
+ mm_ip_tfm,
+ cam_shp,
+ poly_plane_network,
)
# Disable/hide the Maya image plane.
@@ -138,20 +126,65 @@ def convert_image_planes_on_camera(cam):
return ip_node_pairs
+def _guess_color_space(file_path):
+ file_extension = file_path.lower().split('.')[-1]
+ if file_extension in lib_const.SCENE_LINEAR_FILE_EXTENSIONS:
+ color_space = maya.cmds.mmColorIO(roleSceneLinear=True)
+ elif file_extension in lib_const.SRGB_FILE_EXTENSIONS:
+ color_space = maya.cmds.mmColorIO(roleColorPicking=True)
+ else:
+ color_space = maya.cmds.mmColorIO(guessColorSpaceFromFile=file_path)
+
+ if not color_space:
+ color_space = maya.cmds.mmColorIO(roleData=True)
+ if not color_space:
+ color_space = maya.cmds.mmColorIO(roleDefault=True)
+
+ exists = maya.cmds.mmColorIO(colorSpaceExists=color_space)
+ if exists is False:
+ color_space = None
+
+ return color_space
+
+
def set_image_sequence(mm_image_plane_node, image_sequence_path, attr_name=None):
if attr_name is None:
attr_name = lib_const.DEFAULT_IMAGE_SEQUENCE_ATTR_NAME
+ assert isinstance(attr_name, str)
+ assert attr_name in lib_const.VALID_INPUT_IMAGE_SEQUENCE_ATTR_NAMES
tfm, shp = lib_mmimageplane.get_image_plane_node_pair(mm_image_plane_node)
if tfm is None or shp is None:
LOG.warn('mmImagePlane transform/shape could not be found.')
- file_node = lib_mmimageplane.get_file_node(tfm)
- if file_node is None:
- LOG.warn('mmImagePlane shader file node is invalid.')
-
if shp is not None:
lib_mmimageplane.set_image_sequence(shp, image_sequence_path, attr_name)
- if file_node is not None:
- lib_shader.set_file_path(file_node, image_sequence_path)
+ lib_mmimageplane.set_image_sequence(
+ shp, image_sequence_path, lib_const.SHADER_FILE_PATH_ATTR_NAME
+ )
+
+ format_style = const_utils.IMAGE_SEQ_FORMAT_STYLE_FIRST_FRAME
+ (
+ file_pattern,
+ _,
+ _,
+ _,
+ _,
+ ) = imageseq_utils.expand_image_sequence_path(image_sequence_path, format_style)
+ first_frame_file_seq = file_pattern.replace('\\', '/')
+
+ input_color_space = _guess_color_space(first_frame_file_seq)
+ output_color_space = maya.cmds.mmColorIO(roleSceneLinear=True)
+
+ maya.cmds.setAttr(
+ shp + '.' + lib_const.INPUT_COLOR_SPACE_ATTR_NAME,
+ input_color_space,
+ type='string',
+ )
+ maya.cmds.setAttr(
+ shp + '.' + lib_const.OUTPUT_COLOR_SPACE_ATTR_NAME,
+ output_color_space,
+ type='string',
+ )
+
return
diff --git a/python/mmSolver/tools/createimageplane/_lib/mmimageplane.py b/python/mmSolver/tools/createimageplane/_lib/mmimageplane.py
index 93040e4b..121109ee 100644
--- a/python/mmSolver/tools/createimageplane/_lib/mmimageplane.py
+++ b/python/mmSolver/tools/createimageplane/_lib/mmimageplane.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2020, 2022 David Cattermole.
+# Copyright (C) 2020, 2022, 2024 David Cattermole.
#
# This file is part of mmSolver.
#
@@ -121,68 +121,6 @@ def _create_transform_attrs(image_plane_tfm):
def _create_image_plane_shape_attrs(image_plane_shp):
- # Exposure attribute
- attr = 'exposure'
- maya.cmds.addAttr(
- image_plane_shp,
- longName=attr,
- attributeType='double',
- softMinValue=-5.0,
- softMaxValue=5.0,
- defaultValue=0.0,
- )
- node_attr = image_plane_shp + '.' + attr
- maya.cmds.setAttr(node_attr, keyable=True)
-
- # Gamma attribute
- attr = 'gamma'
- maya.cmds.addAttr(
- image_plane_shp,
- longName=attr,
- attributeType='double',
- minValue=0.0,
- softMaxValue=3.0,
- defaultValue=1.0,
- )
- node_attr = image_plane_shp + '.' + attr
- maya.cmds.setAttr(node_attr, keyable=True)
-
- # Color Gain attribute
- attr = 'colorGain'
- default_value = 1.0
- lib_utils.add_attr_float3_color(image_plane_shp, attr, default_value)
-
- # Alpha Gain attribute
- attr = 'alphaGain'
- maya.cmds.addAttr(
- image_plane_shp,
- longName=attr,
- attributeType='double',
- minValue=0.0,
- softMaxValue=1.0,
- defaultValue=1.0,
- )
- node_attr = image_plane_shp + '.' + attr
- maya.cmds.setAttr(node_attr, keyable=True)
-
- # Use Image Alpha Channel attribute
- attr = 'imageUseAlphaChannel'
- maya.cmds.addAttr(
- image_plane_shp, longName=attr, attributeType='bool', defaultValue=0
- )
- node_attr = image_plane_shp + '.' + attr
- maya.cmds.setAttr(node_attr, keyable=True)
-
- # Default Image Color attribute, display a dark-red color when an
- # image is not found.
- attr = 'imageDefaultColor'
- default_value = 0.0
- lib_utils.add_attr_float3_color(image_plane_shp, attr, default_value)
- node_attr = image_plane_shp + '.' + attr
- maya.cmds.setAttr(node_attr + 'R', 0.3)
- maya.cmds.setAttr(node_attr + 'G', 0.0)
- maya.cmds.setAttr(node_attr + 'B', 0.0)
-
# Image Load Enable attribute
attr = 'imageLoadEnable'
maya.cmds.addAttr(
@@ -248,6 +186,8 @@ def _create_image_plane_shape_attrs(image_plane_shp):
)
node_attr = image_plane_shp + '.' + attr
maya.cmds.setAttr(node_attr, keyable=True)
+ dst_node_attr = image_plane_shp + '.imageFrameNumber'
+ lib_utils.force_connect_attr(node_attr, dst_node_attr)
# Image Sequence details.
maya.cmds.addAttr(
@@ -320,7 +260,10 @@ def create_transform_node(name_tfm, cam_tfm, cam_shp):
def create_shape_node(
- name_img_shp, tfm, cam_shp, poly_plane_node_network, shader_node_network
+ name_img_shp,
+ tfm,
+ cam_shp,
+ poly_plane_node_network,
):
"""
Convert mesh to a mmImagePlaneShape.
@@ -331,13 +274,6 @@ def create_shape_node(
img_plane_poly_shp_original = poly_plane_node_network.mesh_shape_original
poly_creator = poly_plane_node_network.plane_creator
- shd_node = shader_node_network.shd_node
- file_node = shader_node_network.file_node
- color_gamma_node = shader_node_network.color_gamma_node
- alpha_channel_blend_node = shader_node_network.alpha_channel_blend_node
- image_load_invert_boolean_node = shader_node_network.image_load_invert_boolean_node
- alpha_channel_reverse_node = shader_node_network.alpha_channel_reverse_node
-
mmapi.load_plugin()
shp = maya.cmds.createNode('mmImagePlaneShape', name=name_img_shp, parent=tfm)
@@ -365,45 +301,11 @@ def create_shape_node(
# Nodes to drive the image plane shape.
lib_utils.force_connect_attr(img_plane_poly_shp + '.outMesh', shp + '.geometryNode')
- lib_utils.force_connect_attr(shd_node + '.outColor', shp + '.shaderNode')
lib_utils.force_connect_attr(cam_shp + '.message', shp + '.cameraNode')
# The image drives the pixel aspect ratio of the image plane.
lib_utils.force_connect_attr(shp + '.imagePixelAspect', tfm + '.pixelAspect')
- # Use the image alpha channel, or not
- lib_utils.force_connect_attr(
- shp + '.imageUseAlphaChannel', alpha_channel_blend_node + '.blender'
- )
-
- # Allow user to load the image, or not.
- lib_utils.force_connect_attr(
- shp + '.imageLoadEnable', image_load_invert_boolean_node + '.inputX'
- )
-
- # Color Exposure control.
- lib_utils.force_connect_attr(shp + '.exposure', file_node + '.exposure')
-
- # Color Gamma control.
- lib_utils.force_connect_attr(shp + '.gamma', color_gamma_node + '.gammaX')
- lib_utils.force_connect_attr(shp + '.gamma', color_gamma_node + '.gammaY')
- lib_utils.force_connect_attr(shp + '.gamma', color_gamma_node + '.gammaZ')
-
- # Control file color multiplier
- lib_utils.force_connect_attr(shp + '.colorGain', file_node + '.colorGain')
-
- # Control the alpha gain when 'imageUseAlphaChannel' is disabled.
- lib_utils.force_connect_attr(shp + '.alphaGain', file_node + '.alphaGain')
- lib_utils.force_connect_attr(
- shp + '.alphaGain', alpha_channel_reverse_node + '.inputX'
- )
- lib_utils.force_connect_attr(
- shp + '.alphaGain', alpha_channel_reverse_node + '.inputY'
- )
- lib_utils.force_connect_attr(
- shp + '.alphaGain', alpha_channel_reverse_node + '.inputZ'
- )
-
# Set the camera size of the image plane shape HUD.
lib_utils.force_connect_attr(
tfm + '.horizontalFilmAperture', shp + '.cameraWidthInch'
@@ -412,11 +314,6 @@ def create_shape_node(
tfm + '.verticalFilmAperture', shp + '.cameraHeightInch'
)
- # Default color for the image plane, when nothing is loaded.
- lib_utils.force_connect_attr(
- shp + '.imageDefaultColor', file_node + '.defaultColor'
- )
-
# Mesh Resolution attr drives the plane sub-divisions.
node_attr = shp + '.meshResolution'
lib_utils.force_connect_attr(node_attr, poly_creator + '.subdivisionsWidth')
@@ -427,7 +324,6 @@ def create_shape_node(
maya.cmds.setAttr(img_plane_poly_shp + '.intermediateObject', 1)
# Add extra message attributes for finding nodes during callbacks.
- maya.cmds.addAttr(shp, longName='shaderFileNode', attributeType='message')
maya.cmds.addAttr(shp, longName='imagePlaneShapeNode', attributeType='message')
return shp
@@ -439,16 +335,15 @@ def set_image_sequence(shp, image_sequence_path, attr_name):
format_style = const_utils.IMAGE_SEQ_FORMAT_STYLE_FIRST_FRAME
(
file_pattern,
- start_frame,
- end_frame,
- pad_num,
- is_seq,
+ _,
+ _,
+ _,
+ _,
) = imageseq_utils.expand_image_sequence_path(image_sequence_path, format_style)
- first_frame_file_seq = file_pattern
+ first_frame_file_seq = file_pattern.replace('\\', '/')
mmapi.load_plugin()
try:
- first_frame_file_seq = first_frame_file_seq.replace('\\', '/')
image_width_height = maya.cmds.mmReadImage(
first_frame_file_seq, query=True, widthHeight=True
)
@@ -471,6 +366,15 @@ def set_image_sequence(shp, image_sequence_path, attr_name):
maya.cmds.setAttr(shp + '.imageWidth', lock=True)
maya.cmds.setAttr(shp + '.imageHeight', lock=True)
+ format_style = const_utils.IMAGE_SEQ_FORMAT_STYLE_HASH_PADDED
+ (
+ file_pattern,
+ start_frame,
+ end_frame,
+ pad_num,
+ is_seq,
+ ) = imageseq_utils.expand_image_sequence_path(image_sequence_path, format_style)
+
maya.cmds.setAttr(shp + '.' + attr_name, file_pattern, type='string')
if not node_utils.node_is_referenced(shp):
@@ -530,20 +434,3 @@ def get_image_plane_node_pair(node):
tfm = get_transform_node(node)
shp = node
return tfm, shp
-
-
-def get_file_node(image_plane_tfm):
- file_node = None
- conns = (
- maya.cmds.listConnections(
- image_plane_tfm + '.shaderFileNode',
- destination=False,
- source=True,
- plugs=False,
- type='file',
- )
- or []
- )
- if len(conns) > 0:
- file_node = conns[0]
- return file_node
diff --git a/python/mmSolver/tools/createimageplane/constant.py b/python/mmSolver/tools/createimageplane/constant.py
index 14982842..ea0aa28e 100644
--- a/python/mmSolver/tools/createimageplane/constant.py
+++ b/python/mmSolver/tools/createimageplane/constant.py
@@ -16,6 +16,8 @@
# along with mmSolver. If not, see .
#
+# NOTE: '{{' and '}}' is used in place of real '{' and '}' characters,
+# to allow Python's 'str.format()' to work.
DISPLAY_MODE_EXPRESSION = '''
if ({image_plane_tfm}.displayMode == 0)
{{
@@ -27,9 +29,25 @@
}}
'''
+# NOTE: '{{' and '}}' is used in place of real '{' and '}' characters,
+# to allow Python's 'str.format()' to work.
FRAME_EXPRESSION = '''
int $start_frame = {node}.imageSequenceStartFrame;
+int $end_frame = {node}.imageSequenceEndFrame;
int $first_frame = {node}.imageSequenceFirstFrame;
-int $user_frame = {node}.imageSequenceFrame;
-{node}.imageSequenceFrameOutput = ($start_frame - $first_frame) + $user_frame;
+int $input_frame = {node}.imageSequenceFrame;
+
+int $result = ($start_frame - $first_frame) + $input_frame;
+
+// // Clamp to start and end frames.
+// if ($result < $start_frame)
+// {{
+// $result = $start_frame;
+// }}
+// else if ($result > $end_frame)
+// {{
+// $result = $end_frame;
+// }}
+
+{node}.imageSequenceFrameOutput = $result;
'''
diff --git a/python/mmSolver/utils/imageseq.py b/python/mmSolver/utils/imageseq.py
index 696d0d79..290888e4 100644
--- a/python/mmSolver/utils/imageseq.py
+++ b/python/mmSolver/utils/imageseq.py
@@ -91,6 +91,19 @@ def _get_image_sequence_start_end_frames(base_dir, file_name, file_extension):
def expand_image_sequence_path(image_sequence_path, format_style):
+ """
+ Expand a given image sequence path into tokens.
+
+ The tokens are:
+ - file_pattern: str, the pattern of the file path.
+ - start_frame: int, first frame of the image sequence.
+ - end_frame: int, last frame of the image sequence.
+ - padding_num: int, number of padding digits for the frame number.
+ - is_seq: bool, is this a sequence? Otherwise it's a single frame.
+
+ :returns:
+ Tuple of (file_pattern, start_frame, end_frame, padding_num, is_seq)
+ """
image_sequence_path = os.path.abspath(image_sequence_path)
(
diff --git a/share/shader/mmImagePlane.ogsfx b/share/shader/mmImagePlane.ogsfx
index 5c8cca55..faa3b8b2 100644
--- a/share/shader/mmImagePlane.ogsfx
+++ b/share/shader/mmImagePlane.ogsfx
@@ -22,20 +22,37 @@
// Global variables provided by Maya.
uniform mat4 gWVPXf : WorldViewProjection;
-// The solid color uniform, its default value and several extra
-// parameters
-uniform vec4 gSolidColor : DIFFUSE = {1, 1, 1, 1};
-uniform float gColorGain = 1.0f;
-uniform float gAlphaGain = 1.0f;
+// Color and alpha modifications.
+uniform vec4 gColorGain : DIFFUSE = {1, 1, 1, 1};
+uniform float gColorExposure = 0.0f;
uniform float gColorGamma = 1.0f;
+uniform float gColorSoftClip = 1.0f;
+uniform float gAlphaGain = 1.0f;
+uniform float4x4 gColorSaturationMatrix < string UIWidget = "None"; >;
+
+// Should we use the alpha channel from the image?
uniform bool gIgnoreAlpha = false;
+
+// Flip or flop the image.
uniform bool gFlip = false;
uniform bool gFlop = false;
-uniform bool gShowChannelRed = false;
-uniform bool gShowChannelGreen = false;
-uniform bool gShowChannelBlue = false;
-uniform bool gShowChannelAlpha = false;
+
+// What type of channels to display to the user.
+//
+// NOTE: Matches the mmsolver::ImageDisplayChannel enum class.
+#define DISPLAY_CHANNEL_RGBA (0)
+#define DISPLAY_CHANNEL_RGB (1)
+#define DISPLAY_CHANNEL_RED (2)
+#define DISPLAY_CHANNEL_GREEN (3)
+#define DISPLAY_CHANNEL_BLUE (4)
+#define DISPLAY_CHANNEL_ALPHA (5)
+#define DISPLAY_CHANNEL_LUMINANCE (6)
+uniform int gDisplayChannel = 0;
+
+// When the image is not found the fallback color should be shown.
+uniform bool gImageNotFound = false;
+uniform vec4 gFallbackColor : DIFFUSE = {0.3f, 0.0f, 0.0f, 1};
// The main image texture displaying RGBA values to the user.
uniform texture2D gImageTexture
@@ -90,11 +107,38 @@ GLSLShader VS_mmImagePlane {
// Pixel Shader Outputs
attribute PIXEL_DATA {
- vec4 colorOut : COLOR0;
+ vec4 color_out : COLOR0;
}
GLSLShader PS_mmImagePlane_Main {
+ // Simple Reinhard tone-mapping operator.
+ //
+ // blend_value is a blend between no adjustment and the full
+ // tone-mapping (0.0 to 1.0).
+ vec3 apply_soft_clip(vec3 in_color, float blend_value) {
+ vec3 adjusted = in_color / (1.0 + in_color);
+ return mix(in_color, adjusted, blend_value);
+ }
+
+ vec4 convert_to_luminance_only(vec4 in_color) {
+ // Luminance weights
+ //
+ // From Mozilla:
+ // https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_Colors_and_Luminance
+ float r_weight = 0.2126f; // Luminance Red
+ float g_weight = 0.7152f; // Luminance Green
+ float b_weight = 0.0722f; // Luminance Blue
+
+ mat4 matrix;
+ matrix[0] = vec4(r_weight, g_weight, b_weight, 0.0);
+ matrix[1] = vec4(r_weight, g_weight, b_weight, 0.0);
+ matrix[2] = vec4(r_weight, g_weight, b_weight, 0.0);
+ matrix[3] = vec4(0.0, 0.0, 0.0, 1.0);
+
+ return in_color * matrix;
+ }
+
// The OCIO function will be replaced and injected at runtime into
// this line. This function is used as a stand-in.
vec4 OCIODisplay(vec4 passthrough) { return passthrough; }
@@ -105,13 +149,15 @@ GLSLShader PS_mmImagePlane_Main {
texture_color.a = 1.0f;
}
- vec3 gamma = vec3(gColorGamma, gColorGamma, gColorGamma);
+ vec3 gamma = 1.0f / vec3(gColorGamma, gColorGamma, gColorGamma);
+
+ texture_color.rgb *= gColorGain.rgb;
+ texture_color.rgb *= pow(2.0, gColorExposure);
texture_color.rgb = max(vec3(0.0f, 0.0f, 0.0f), texture_color.rgb);
- texture_color.rgb = pow(texture_color.rgb, (1.0f / gamma));
+ texture_color.rgb = pow(texture_color.rgb, gamma);
+ texture_color *= gColorSaturationMatrix;
+ texture_color.rgb = apply_soft_clip(texture_color.rgb, gColorSoftClip);
- texture_color.r *= gColorGain;
- texture_color.g *= gColorGain;
- texture_color.b *= gColorGain;
texture_color.a *= gAlphaGain;
if (texture_color.a > 1.0f) {
@@ -120,15 +166,19 @@ GLSLShader PS_mmImagePlane_Main {
texture_color.a = 0.0f;
}
- colorOut = gSolidColor * texture_color;
- if (gShowChannelRed) {
- colorOut = vec4(colorOut.r, colorOut.r, colorOut.r, 1.0f);
- } else if (gShowChannelGreen) {
- colorOut = vec4(colorOut.g, colorOut.g, colorOut.g, 1.0f);
- } else if (gShowChannelBlue) {
- colorOut = vec4(colorOut.b, colorOut.b, colorOut.b, 1.0f);
- } else if (gShowChannelAlpha) {
- colorOut = vec4(colorOut.a, colorOut.a, colorOut.a, 1.0f);
+ color_out = texture_color;
+ if (gDisplayChannel == DISPLAY_CHANNEL_RGB) {
+ color_out = vec4(color_out.rgb, 1.0f);
+ } else if (gDisplayChannel == DISPLAY_CHANNEL_RED) {
+ color_out = vec4(color_out.rrr, 1.0f);
+ } else if (gDisplayChannel == DISPLAY_CHANNEL_GREEN) {
+ color_out = vec4(color_out.ggg, 1.0f);
+ } else if (gDisplayChannel == DISPLAY_CHANNEL_BLUE) {
+ color_out = vec4(color_out.bbb, 1.0f);
+ } else if (gDisplayChannel == DISPLAY_CHANNEL_ALPHA) {
+ color_out = vec4(color_out.aaa, 1.0f);
+ } else if (gDisplayChannel == DISPLAY_CHANNEL_LUMINANCE) {
+ color_out = convert_to_luminance_only(color_out);
}
}
}
diff --git a/src/mmSolver/shape/ImagePlaneGeometryOverride.cpp b/src/mmSolver/shape/ImagePlaneGeometryOverride.cpp
index 777c7944..59470bcf 100644
--- a/src/mmSolver/shape/ImagePlaneGeometryOverride.cpp
+++ b/src/mmSolver/shape/ImagePlaneGeometryOverride.cpp
@@ -74,10 +74,14 @@ ImagePlaneGeometryOverride::ImagePlaneGeometryOverride(const MObject &obj)
, m_draw_image_size(false)
, m_draw_camera_size(false)
, m_geometry_node_type(MFn::kInvalid)
- , m_use_color_plug(false)
, m_image_display_channel(ImageDisplayChannel::kAll)
- , m_color_gain(1.0f)
+ , m_color_gain(1.0, 1.0, 1.0, 1.0)
+ , m_color_exposure(0.0f)
+ , m_color_gamma(1.0f)
+ , m_color_saturation(1.0f)
+ , m_color_soft_clip(0.0f)
, m_alpha_gain(1.0f)
+ , m_default_color(0.3, 0.0, 0.0, 1.0)
, m_ignore_alpha(false)
, m_flip(false)
, m_flop(false)
@@ -280,12 +284,13 @@ void ImagePlaneGeometryOverride::query_node_attributes(
bool &out_visible_to_camera_only, bool &out_is_under_camera,
bool &out_draw_hud, bool &out_draw_image_size, MString &out_image_size,
bool &out_draw_camera_size, MString &out_camera_size,
- bool &out_use_color_plug, ImageDisplayChannel &out_image_display_channel,
- float &out_color_gain, float &out_alpha_gain, bool &out_ignore_alpha,
+ ImageDisplayChannel &out_image_display_channel, MColor &out_color_gain,
+ float &out_color_exposure, float &out_color_gamma,
+ float &out_color_saturation, float &out_color_soft_clip,
+ float &out_alpha_gain, MColor &out_default_color, bool &out_ignore_alpha,
bool &out_flip, bool &out_flop, bool &out_is_transparent,
mmcore::FrameValue &out_frame, MString &out_file_path,
- MString &out_input_color_space_name, MString &out_output_color_space_name,
- MPlug &out_color_plug) {
+ MString &out_input_color_space_name, MString &out_output_color_space_name) {
const bool verbose = false;
MDagPath objPath;
@@ -339,62 +344,68 @@ void ImagePlaneGeometryOverride::query_node_attributes(
calculate_node_camera_size_string(objPath, double_precision,
out_draw_camera_size, out_camera_size);
- // Shader attributes.
- {
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_use_color_plug,
- out_use_color_plug);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_color_gain,
+ out_color_gain);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_color_gain,
- out_color_gain);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_color_exposure,
+ out_color_exposure);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_alpha_gain,
- out_alpha_gain);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_color_gamma,
+ out_color_gamma);
+ CHECK_MSTATUS(status);
- short image_display_channel_value = 0;
- status =
- getNodeAttr(objPath, ImagePlaneShapeNode::m_image_display_channel,
- image_display_channel_value);
- CHECK_MSTATUS(status);
- out_image_display_channel =
- static_cast(image_display_channel_value);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_color_saturation,
+ out_color_saturation);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_ignore_alpha,
- out_ignore_alpha);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_color_soft_clip,
+ out_color_soft_clip);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_flip, out_flip);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_alpha_gain,
+ out_alpha_gain);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_flop, out_flop);
- CHECK_MSTATUS(status);
+ short image_display_channel_value = 0;
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_display_channel,
+ image_display_channel_value);
+ CHECK_MSTATUS(status);
+ out_image_display_channel =
+ static_cast(image_display_channel_value);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_is_transparent,
- out_is_transparent);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_ignore_alpha,
+ out_ignore_alpha);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_frame_number,
- out_frame);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_flip, out_flip);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_file_path,
- out_file_path);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_flop, out_flop);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_input_color_space,
- out_input_color_space_name);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_shader_is_transparent,
+ out_is_transparent);
+ CHECK_MSTATUS(status);
- status = getNodeAttr(objPath, ImagePlaneShapeNode::m_output_color_space,
- out_output_color_space_name);
- CHECK_MSTATUS(status);
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_frame_number,
+ out_frame);
+ CHECK_MSTATUS(status);
- status = getNodeAttrPlug(objPath, ImagePlaneShapeNode::m_color,
- out_color_plug);
- CHECK_MSTATUS(status);
- }
+ status = getNodeAttr(objPath, ImagePlaneShapeNode::m_image_file_path,
+ out_file_path);
+ CHECK_MSTATUS(status);
+
+ status =
+ getNodeAttr(objPath, ImagePlaneShapeNode::m_image_input_color_space,
+ out_input_color_space_name);
+ CHECK_MSTATUS(status);
+
+ status =
+ getNodeAttr(objPath, ImagePlaneShapeNode::m_image_output_color_space,
+ out_output_color_space_name);
+ CHECK_MSTATUS(status);
// Find the input/output file color spaces.
//
@@ -422,61 +433,28 @@ void find_geometry_node_path(MObject &node, MString &attr_name,
MPlugArray connections;
bool ok = getUpstreamNodeFromConnection(node, attr_name, connections);
-
- if (ok) {
- for (uint32_t i = 0; i < connections.length(); ++i) {
- MObject node = connections[i].node();
-
- if (node.hasFn(MFn::kMesh)) {
- MDagPath path;
- MDagPath::getAPathTo(node, path);
- out_geometry_node_path = path;
- out_geometry_node_type = path.apiType();
- MMSOLVER_MAYA_VRB(
- "Validated geometry node: "
- << " path="
- << out_geometry_node_path.fullPathName().asChar()
- << " type=" << node.apiTypeStr());
- break;
- } else {
- MMSOLVER_MAYA_WRN(
- "Geometry node is not correct type:"
- << " path="
- << out_geometry_node_path.fullPathName().asChar()
- << " type=" << node.apiTypeStr());
- }
- }
+ if (!ok) {
+ return;
}
-}
-
-void find_shader_node(MObject &node, MString &attr_name,
- MObject &out_shader_node,
- MFn::Type &out_shader_node_type) {
- const auto verbose = false;
- MPlugArray connections;
- bool ok = getUpstreamNodeFromConnection(node, attr_name, connections);
-
- if (ok) {
- for (uint32_t i = 0; i < connections.length(); ++i) {
- MObject node = connections[i].node();
-
- MFnDependencyNode mfn_depend_node(node);
- if (node.hasFn(MFn::kSurfaceShader) ||
- node.hasFn(MFn::kHwShaderNode) ||
- node.hasFn(MFn::kPluginHardwareShader) ||
- node.hasFn(MFn::kPluginHwShaderNode)) {
- out_shader_node = node;
- out_shader_node_type = node.apiType();
- MMSOLVER_MAYA_VRB("Validated shader node:"
- << " name=" << mfn_depend_node.name().asChar()
- << " type=" << node.apiTypeStr());
- break;
- } else {
- MMSOLVER_MAYA_WRN("Shader node is not correct type: "
- << " name=" << mfn_depend_node.name().asChar()
- << " type=" << node.apiTypeStr());
- }
+ for (uint32_t i = 0; i < connections.length(); ++i) {
+ MObject node = connections[i].node();
+
+ if (node.hasFn(MFn::kMesh)) {
+ MDagPath path;
+ MDagPath::getAPathTo(node, path);
+ out_geometry_node_path = path;
+ out_geometry_node_type = path.apiType();
+ MMSOLVER_MAYA_VRB("Validated geometry node: "
+ << " path="
+ << out_geometry_node_path.fullPathName().asChar()
+ << " type=" << node.apiTypeStr());
+ break;
+ } else {
+ MMSOLVER_MAYA_WRN("Geometry node is not correct type:"
+ << " path="
+ << out_geometry_node_path.fullPathName().asChar()
+ << " type=" << node.apiTypeStr());
}
}
}
@@ -488,27 +466,28 @@ void find_camera_node_path(MObject &node, MString &attr_name,
MPlugArray connections;
bool ok = getUpstreamNodeFromConnection(node, attr_name, connections);
+ if (!ok) {
+ return;
+ }
- if (ok) {
- for (uint32_t i = 0; i < connections.length(); ++i) {
- MObject node = connections[i].node();
-
- if (node.hasFn(MFn::kCamera)) {
- MDagPath path;
- MDagPath::getAPathTo(node, path);
- out_camera_node_path = path;
- out_camera_node_type = path.apiType();
- MMSOLVER_MAYA_VRB(
- "Validated camera node: "
- << " path=" << out_camera_node_path.fullPathName().asChar()
- << " type=" << node.apiTypeStr());
- break;
- } else {
- MMSOLVER_MAYA_WRN(
- "Camera node is not correct type:"
- << " path=" << out_camera_node_path.fullPathName().asChar()
- << " type=" << node.apiTypeStr());
- }
+ for (uint32_t i = 0; i < connections.length(); ++i) {
+ MObject node = connections[i].node();
+
+ if (node.hasFn(MFn::kCamera)) {
+ MDagPath path;
+ MDagPath::getAPathTo(node, path);
+ out_camera_node_path = path;
+ out_camera_node_type = path.apiType();
+ MMSOLVER_MAYA_VRB("Validated camera node: "
+ << " path="
+ << out_camera_node_path.fullPathName().asChar()
+ << " type=" << node.apiTypeStr());
+ break;
+ } else {
+ MMSOLVER_MAYA_WRN("Camera node is not correct type:"
+ << " path="
+ << out_camera_node_path.fullPathName().asChar()
+ << " type=" << node.apiTypeStr());
}
}
}
@@ -520,12 +499,6 @@ void ImagePlaneGeometryOverride::updateDG() {
m_geometry_node_type);
}
- if (m_shader_node.isNull()) {
- MString attr_name = "shaderNode";
- find_shader_node(m_this_node, attr_name, m_shader_node,
- m_shader_node_type);
- }
-
if (!m_camera_node_path.isValid()) {
MString attr_name = "cameraNode";
find_camera_node_path(m_this_node, attr_name, m_camera_node_path,
@@ -538,11 +511,12 @@ void ImagePlaneGeometryOverride::updateDG() {
ImagePlaneGeometryOverride::query_node_attributes(
m_this_node, m_camera_node_path, m_visible, m_visible_to_camera_only,
m_is_under_camera, m_draw_hud, m_draw_image_size, m_image_size,
- m_draw_camera_size, m_camera_size, m_use_color_plug,
- m_image_display_channel, m_color_gain, m_alpha_gain, m_ignore_alpha,
+ m_draw_camera_size, m_camera_size, m_image_display_channel,
+ m_color_gain, m_color_exposure, m_color_gamma, m_color_saturation,
+ m_color_soft_clip, m_alpha_gain, m_default_color, m_ignore_alpha,
m_flip, m_flop, m_is_transparent, m_frame, m_file_path,
- temp_input_color_space_name, temp_output_color_space_name,
- m_color_plug);
+ temp_input_color_space_name, temp_output_color_space_name);
+
if ((m_input_color_space_name.asChar() !=
temp_input_color_space_name.asChar()) ||
(m_input_color_space_name.asChar() !=
@@ -553,83 +527,104 @@ void ImagePlaneGeometryOverride::updateDG() {
}
}
-MTexture *create_color_bars_texture(
- MHWRender::MTextureManager *textureManager) {
- MHWRender::MTextureDescription texture_desc;
- texture_desc.setToDefault2DTexture();
- texture_desc.fWidth = COLOR_BARS_F32_4X4_PIXEL_WIDTH;
- texture_desc.fHeight = COLOR_BARS_F32_4X4_PIXEL_HEIGHT;
- texture_desc.fDepth = 1;
- texture_desc.fBytesPerSlice =
- COLOR_BARS_F32_4X4_PIXEL_COUNT * COLOR_BARS_F32_4X4_PIXEL_BYTE_COUNT;
- texture_desc.fBytesPerRow =
- COLOR_BARS_F32_4X4_PIXEL_WIDTH * COLOR_BARS_F32_4X4_PIXEL_BYTE_COUNT;
- texture_desc.fMipmaps = 1;
- texture_desc.fArraySlices = 1;
- texture_desc.fTextureType = MHWRender::kImage2D;
- texture_desc.fFormat = MHWRender::kR32G32B32A32_FLOAT;
-
- const bool generate_mip_maps = false;
- return textureManager->acquireTexture(
- "", texture_desc, &(COLOR_BARS_F32_4X4[0]), generate_mip_maps);
-}
-
-MTexture *create_plug_texture(MHWRender::MTextureManager *textureManager,
- MPlug &texture_plug) {
- MObject texture_node;
- MStatus status = get_connected_node(texture_plug, texture_node);
- CHECK_MSTATUS(status);
- if (status != MS::kSuccess) {
- return nullptr;
- }
-
- if (texture_node.isNull()) {
- // For when the plug is just a color value, but doesn't have
- // any input texture.
- const bool generate_mip_maps = false;
- const int width = 2;
- const int height = 2;
- return textureManager->acquireTexture("", texture_plug, width, height,
- generate_mip_maps);
- }
-
- const bool allowBackgroundLoad = false;
- return textureManager->acquireTexture(texture_node, allowBackgroundLoad);
+inline MFloatMatrix create_saturation_matrix(const float saturation) {
+ // Luminance weights
+ //
+ // From Mozilla:
+ // https://developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_Colors_and_Luminance
+ const float kLuminanceRed = 0.2126f;
+ const float kLuminanceGreen = 0.7152f;
+ const float kLuminanceBlue = 0.0722f;
+
+ const float r_weight = kLuminanceRed;
+ const float g_weight = kLuminanceGreen;
+ const float b_weight = kLuminanceBlue;
+
+ const float r1 = (1.0 - saturation) * r_weight + saturation;
+ const float r2 = (1.0 - saturation) * r_weight;
+ const float r3 = (1.0 - saturation) * r_weight;
+
+ const float g1 = (1.0 - saturation) * g_weight;
+ const float g2 = (1.0 - saturation) * g_weight + saturation;
+ const float g3 = (1.0 - saturation) * g_weight;
+
+ const float b1 = (1.0 - saturation) * b_weight;
+ const float b2 = (1.0 - saturation) * b_weight;
+ const float b3 = (1.0 - saturation) * b_weight + saturation;
+
+ const float saturation_matrix_values[4][4] = {
+ // Column 0
+ {r1, g1, b1, 0.0},
+ // Column 1
+ {r2, g2, b2, 0.0},
+ // Column 2
+ {r3, g3, b3, 0.0},
+ // Column 3
+ {0.0, 0.0, 0.0, 1.0},
+ };
+
+ return MFloatMatrix(saturation_matrix_values);
}
void ImagePlaneGeometryOverride::set_shader_instance_parameters(
MShaderInstance *shader, MHWRender::MTextureManager *textureManager,
- const float color_gain, const float alpha_gain, const bool ignore_alpha,
- const bool flip, const bool flop, const bool is_transparent,
+ const MColor &color_gain, const float color_exposure,
+ const float color_gamma, const float color_saturation,
+ const float color_soft_clip, const float alpha_gain,
+ const MColor &default_color, const bool ignore_alpha, const bool flip,
+ const bool flop, const bool is_transparent,
const ImageDisplayChannel image_display_channel,
const mmcore::FrameValue frame, const MString &file_path,
const MString &input_color_space_name,
const MString &output_color_space_name,
MHWRender::MTexture *out_color_texture,
- const MHWRender::MSamplerState *out_texture_sampler,
- const bool use_color_plug, MPlug &out_color_plug) {
+ const MHWRender::MSamplerState *out_texture_sampler) {
+ MStatus status = MStatus::kSuccess;
const bool verbose = false;
MMSOLVER_MAYA_VRB("mmImagePlaneShape: set_shader_instance_parameters.");
- static const float color[] = {1.0f, 1.0f, 1.0f, 1.0f};
- shader->setParameter("gSolidColor", color);
- shader->setParameter("gColorGain", color_gain);
- shader->setParameter("gAlphaGain", alpha_gain);
- shader->setParameter("gFlip", flip);
- shader->setParameter("gFlop", flop);
- shader->setParameter("gIgnoreAlpha", m_ignore_alpha);
- shader->setParameter("gShowChannelRed",
- image_display_channel == ImageDisplayChannel::kRed);
- shader->setParameter("gShowChannelGreen",
- image_display_channel == ImageDisplayChannel::kGreen);
- shader->setParameter("gShowChannelBlue",
- image_display_channel == ImageDisplayChannel::kBlue);
- shader->setParameter("gShowChannelAlpha",
- image_display_channel == ImageDisplayChannel::kAlpha);
-
- shader->setIsTransparent(is_transparent);
+ const float color[] = {color_gain[0], color_gain[1], color_gain[2], 1.0f};
+ status = shader->setParameter("gColorGain", color);
+ CHECK_MSTATUS(status);
+
+ status = shader->setParameter("gColorExposure", color_exposure);
+ CHECK_MSTATUS(status);
+
+ status = shader->setParameter("gColorGamma", color_gamma);
+ CHECK_MSTATUS(status);
+
+ MFloatMatrix saturation_matrix = create_saturation_matrix(color_saturation);
+ status = shader->setParameter("gColorSaturationMatrix", saturation_matrix);
+ CHECK_MSTATUS(status);
+
+ status = shader->setParameter("gColorSoftClip", color_soft_clip);
+ CHECK_MSTATUS(status);
+
+ status = shader->setParameter("gAlphaGain", alpha_gain);
+ CHECK_MSTATUS(status);
+
+ const float temp_default_color[] = {default_color[0], default_color[1],
+ default_color[2], 1.0f};
+ status = shader->setParameter("gFallbackColor", temp_default_color);
+ CHECK_MSTATUS(status);
+
+ status = shader->setParameter("gFlip", flip);
+ CHECK_MSTATUS(status);
+
+ status = shader->setParameter("gFlop", flop);
+ CHECK_MSTATUS(status);
+
+ status = shader->setParameter("gIgnoreAlpha", m_ignore_alpha);
+ CHECK_MSTATUS(status);
+
+ status = shader->setParameter("gDisplayChannel",
+ static_cast(image_display_channel));
+ CHECK_MSTATUS(status);
+
+ status = shader->setIsTransparent(is_transparent);
MMSOLVER_MAYA_VRB("mmImagePlaneShape: shader->isTransparent()="
<< shader->isTransparent());
+ CHECK_MSTATUS(status);
MMSOLVER_MAYA_VRB("mmImagePlaneShape: file_path=" << file_path.asChar());
@@ -641,35 +636,21 @@ void ImagePlaneGeometryOverride::set_shader_instance_parameters(
MMSOLVER_MAYA_VRB("mmImagePlaneShape: expanded_file_path="
<< expanded_file_path.asChar());
- MMSOLVER_MAYA_VRB(
- "mmImagePlaneShape: start use_color_plug=" << use_color_plug);
MMSOLVER_MAYA_VRB(
"mmImagePlaneShape: start out_color_texture=" << out_color_texture);
if (!out_color_texture) {
- if (!use_color_plug) {
- MMSOLVER_MAYA_VRB("mmImagePlaneShape: use image read");
- const MImage::MPixelType pixel_type = MImage::MPixelType::kByte;
-
- // // TODO: using kFloat crashes.
- // const MImage::MPixelType pixel_type = MImage::MPixelType::kFloat;
+ MMSOLVER_MAYA_VRB("mmImagePlaneShape: use image read");
+ const MImage::MPixelType pixel_type = MImage::MPixelType::kByte;
- const bool do_texture_update = false;
- ImageCache &image_cache = ImageCache::getInstance();
- out_color_texture = read_image_file(
- textureManager, image_cache, m_temp_image, expanded_file_path,
- pixel_type, do_texture_update);
+ // // TODO: using kFloat crashes.
+ // const MImage::MPixelType pixel_type = MImage::MPixelType::kFloat;
- } else {
- if (!out_color_plug.isNull()) {
- MMSOLVER_MAYA_VRB("mmImagePlaneShape: use color plug texture");
- out_color_texture =
- create_plug_texture(textureManager, out_color_plug);
- } else {
- MMSOLVER_MAYA_VRB("mmImagePlaneShape: use color bars");
- out_color_texture = create_color_bars_texture(textureManager);
- }
- }
+ const bool do_texture_update = false;
+ ImageCache &image_cache = ImageCache::getInstance();
+ out_color_texture =
+ read_image_file(textureManager, image_cache, m_temp_image,
+ expanded_file_path, pixel_type, do_texture_update);
if (out_color_texture) {
MMSOLVER_MAYA_VRB("mmImagePlaneShape: texture->name()="
@@ -731,7 +712,9 @@ void ImagePlaneGeometryOverride::set_shader_instance_parameters(
}
if (out_texture_sampler) {
- shader->setParameter("gImageTextureSampler", *out_texture_sampler);
+ status =
+ shader->setParameter("gImageTextureSampler", *out_texture_sampler);
+ CHECK_MSTATUS(status);
} else {
MMSOLVER_MAYA_WRN("mmImagePlaneShape: Could not get texture sampler."
<< " out_texture_sampler=" << out_texture_sampler);
@@ -740,7 +723,9 @@ void ImagePlaneGeometryOverride::set_shader_instance_parameters(
if (out_color_texture) {
MHWRender::MTextureAssignment texture_assignment;
texture_assignment.texture = out_color_texture;
- shader->setParameter("gImageTexture", texture_assignment);
+ status = shader->setParameter("gImageTexture", texture_assignment);
+ CHECK_MSTATUS(status);
+
out_color_texture = nullptr;
} else {
MMSOLVER_MAYA_VRB(
@@ -834,7 +819,8 @@ void ImagePlaneGeometryOverride::updateRenderItems(const MDagPath &path,
shaderManager->getStockShader(MShaderManager::k3dSolidShader);
if (shader) {
static const float color[] = {1.0f, 0.0f, 0.0f, 1.0f};
- shader->setParameter("solidColor", color);
+ MStatus status = shader->setParameter("solidColor", color);
+ CHECK_MSTATUS(status);
wireframeItem->setShader(shader);
shaderManager->releaseShader(shader);
}
@@ -921,12 +907,12 @@ void ImagePlaneGeometryOverride::updateRenderItems(const MDagPath &path,
}
set_shader_instance_parameters(
- m_shader, textureManager, m_color_gain, m_alpha_gain,
- m_ignore_alpha, m_flip, m_flop, m_is_transparent,
- m_image_display_channel, m_frame, m_file_path,
+ m_shader, textureManager, m_color_gain, m_color_exposure,
+ m_color_gamma, m_color_saturation, m_color_soft_clip,
+ m_alpha_gain, m_default_color, m_ignore_alpha, m_flip, m_flop,
+ m_is_transparent, m_image_display_channel, m_frame, m_file_path,
m_input_color_space_name, m_output_color_space_name,
- m_color_texture, m_texture_sampler, m_use_color_plug,
- m_color_plug);
+ m_color_texture, m_texture_sampler);
shadedItem->setShader(m_shader);
}
@@ -1048,7 +1034,7 @@ void ImagePlaneGeometryOverride::cleanUp() {}
#if MAYA_API_VERSION >= 20190000
bool ImagePlaneGeometryOverride::requiresGeometryUpdate() const {
const bool verbose = false;
- if (m_geometry_node_path.isValid() && !m_shader_node.isNull()) {
+ if (m_geometry_node_path.isValid()) {
MMSOLVER_MAYA_VRB(
"ImagePlaneGeometryOverride::requiresGeometryUpdate: false");
return false;
diff --git a/src/mmSolver/shape/ImagePlaneGeometryOverride.h b/src/mmSolver/shape/ImagePlaneGeometryOverride.h
index cbaa8713..1c752e11 100644
--- a/src/mmSolver/shape/ImagePlaneGeometryOverride.h
+++ b/src/mmSolver/shape/ImagePlaneGeometryOverride.h
@@ -113,32 +113,34 @@ class ImagePlaneGeometryOverride : public MPxGeometryOverride {
bool &out_visible_to_camera_only, bool &out_is_under_camera,
bool &out_draw_hud, bool &out_draw_image_size, MString &out_image_size,
bool &out_draw_camera_size, MString &out_camera_size,
- bool &out_use_color_plug,
- ImageDisplayChannel &out_image_display_channel, float &out_color_gain,
- float &out_alpha_gain, bool &out_ignore_alpha, bool &out_flip,
- bool &out_flop, bool &out_is_transparent, mmcore::FrameValue &out_frame,
+ ImageDisplayChannel &out_image_display_channel, MColor &out_color_gain,
+ float &out_color_exposure, float &out_color_gamma,
+ float &out_color_saturation, float &out_color_soft_clip,
+ float &out_alpha_gain, MColor &out_default_color,
+ bool &out_ignore_alpha, bool &out_flip, bool &out_flop,
+ bool &out_is_transparent, mmcore::FrameValue &out_frame,
MString &out_file_path, MString &out_input_color_space_name,
- MString &out_output_color_space_name, MPlug &out_color_plug);
+ MString &out_output_color_space_name);
void set_shader_instance_parameters(
MShaderInstance *shader, MHWRender::MTextureManager *textureManager,
- const float color_gain, const float alpha_gain, const bool ignore_alpha,
- const bool flip, const bool flop, const bool is_transparent,
+ const MColor &color_gain, const float color_exposure,
+ const float color_gamma, const float color_saturation,
+ const float color_soft_clip, const float alpha_gain,
+ const MColor &default_color, const bool ignore_alpha, const bool flip,
+ const bool flop, const bool is_transparent,
const ImageDisplayChannel image_display_channel,
const mmcore::FrameValue frame, const MString &file_path,
const MString &input_color_space_name,
const MString &output_color_space_name,
MHWRender::MTexture *out_color_texture,
- const MHWRender::MSamplerState *out_texture_sampler,
- const bool use_color_plug, MPlug &out_color_plug);
+ const MHWRender::MSamplerState *out_texture_sampler);
MObject m_this_node;
MDagPath m_geometry_node_path;
MDagPath m_camera_node_path;
MFn::Type m_geometry_node_type;
- MFn::Type m_shader_node_type;
MFn::Type m_camera_node_type;
- MObject m_shader_node;
bool m_visible;
bool m_visible_to_camera_only;
@@ -151,13 +153,16 @@ class ImagePlaneGeometryOverride : public MPxGeometryOverride {
MString m_camera_size;
MCallbackId m_model_editor_changed_callback_id;
- bool m_use_color_plug;
-
// Shader attributes.
MShaderInstance *m_shader;
ImageDisplayChannel m_image_display_channel;
- float m_color_gain;
+ MColor m_color_gain;
float m_alpha_gain;
+ float m_color_exposure;
+ float m_color_gamma;
+ float m_color_saturation;
+ float m_color_soft_clip;
+ MColor m_default_color;
bool m_ignore_alpha;
bool m_flip;
bool m_flop;
@@ -166,7 +171,6 @@ class ImagePlaneGeometryOverride : public MPxGeometryOverride {
MString m_file_path;
MString m_input_color_space_name;
MString m_output_color_space_name;
- MPlug m_color_plug;
// Texture caching
MImage m_temp_image;
diff --git a/src/mmSolver/shape/ImagePlaneShapeNode.cpp b/src/mmSolver/shape/ImagePlaneShapeNode.cpp
index 81d92396..35a1d4ce 100644
--- a/src/mmSolver/shape/ImagePlaneShapeNode.cpp
+++ b/src/mmSolver/shape/ImagePlaneShapeNode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 David Cattermole.
+ * Copyright (C) 2022, 2024 David Cattermole.
*
* This file is part of mmSolver.
*
@@ -77,23 +77,25 @@ MObject ImagePlaneShapeNode::m_camera_height_inch;
MObject ImagePlaneShapeNode::m_lens_hash_current;
MObject ImagePlaneShapeNode::m_lens_hash_previous;
MObject ImagePlaneShapeNode::m_geometry_node;
-MObject ImagePlaneShapeNode::m_shader_node;
MObject ImagePlaneShapeNode::m_camera_node;
-// Shader Attributes
-MObject ImagePlaneShapeNode::m_use_color_plug;
+// Image Attributes
MObject ImagePlaneShapeNode::m_image_display_channel;
-MObject ImagePlaneShapeNode::m_color_gain;
-MObject ImagePlaneShapeNode::m_alpha_gain;
-MObject ImagePlaneShapeNode::m_ignore_alpha;
-MObject ImagePlaneShapeNode::m_flip;
-MObject ImagePlaneShapeNode::m_flop;
-MObject ImagePlaneShapeNode::m_is_transparent;
-MObject ImagePlaneShapeNode::m_frame_number;
-MObject ImagePlaneShapeNode::m_file_path;
-MObject ImagePlaneShapeNode::m_input_color_space;
-MObject ImagePlaneShapeNode::m_output_color_space;
-MObject ImagePlaneShapeNode::m_color;
+MObject ImagePlaneShapeNode::m_image_color_gain;
+MObject ImagePlaneShapeNode::m_image_color_exposure;
+MObject ImagePlaneShapeNode::m_image_color_gamma;
+MObject ImagePlaneShapeNode::m_image_color_saturation;
+MObject ImagePlaneShapeNode::m_image_color_soft_clip;
+MObject ImagePlaneShapeNode::m_image_alpha_gain;
+MObject ImagePlaneShapeNode::m_image_default_color;
+MObject ImagePlaneShapeNode::m_image_ignore_alpha;
+MObject ImagePlaneShapeNode::m_image_flip;
+MObject ImagePlaneShapeNode::m_image_flop;
+MObject ImagePlaneShapeNode::m_image_frame_number;
+MObject ImagePlaneShapeNode::m_image_file_path;
+MObject ImagePlaneShapeNode::m_image_input_color_space;
+MObject ImagePlaneShapeNode::m_image_output_color_space;
+MObject ImagePlaneShapeNode::m_shader_is_transparent;
ImagePlaneShapeNode::ImagePlaneShapeNode() {}
@@ -260,13 +262,6 @@ MStatus ImagePlaneShapeNode::initialize() {
CHECK_MSTATUS(msgAttr.setKeyable(false));
CHECK_MSTATUS(addAttribute(m_geometry_node));
- m_shader_node = msgAttr.create("shaderNode", "shdnd", &status);
- CHECK_MSTATUS(status);
- CHECK_MSTATUS(msgAttr.setStorable(true));
- CHECK_MSTATUS(msgAttr.setConnectable(true));
- CHECK_MSTATUS(msgAttr.setKeyable(false));
- CHECK_MSTATUS(addAttribute(m_shader_node));
-
m_camera_node = msgAttr.create("cameraNode", "camnd", &status);
CHECK_MSTATUS(status);
CHECK_MSTATUS(msgAttr.setStorable(true));
@@ -274,120 +269,176 @@ MStatus ImagePlaneShapeNode::initialize() {
CHECK_MSTATUS(msgAttr.setKeyable(false));
CHECK_MSTATUS(addAttribute(m_camera_node));
- m_use_color_plug = nAttr.create("useColorPlug", "useclrplg",
- MFnNumericData::kBoolean, true);
+ m_image_color_gain = nAttr.createColor("colorGain", "colgn");
+ CHECK_MSTATUS(nAttr.setKeyable(true));
+ CHECK_MSTATUS(nAttr.setStorable(true));
+ CHECK_MSTATUS(nAttr.setReadable(true));
+ CHECK_MSTATUS(nAttr.setWritable(true));
+ CHECK_MSTATUS(nAttr.setDefault(1.0f, 1.0f, 1.0f));
+ CHECK_MSTATUS(addAttribute(m_image_color_gain));
+
+ const float exposure_soft_min = -9.0f;
+ const float exposure_soft_max = +9.0f;
+ const float exposure_default = 0.0f;
+ m_image_color_exposure = nAttr.create(
+ "colorExposure", "colexpsr", MFnNumericData::kFloat, exposure_default);
+ CHECK_MSTATUS(nAttr.setStorable(true));
+ CHECK_MSTATUS(nAttr.setKeyable(true));
+ CHECK_MSTATUS(nAttr.setSoftMin(exposure_soft_min));
+ CHECK_MSTATUS(nAttr.setSoftMax(exposure_soft_max));
+ CHECK_MSTATUS(addAttribute(m_image_color_exposure));
+
+ const float gamma_min = 0.0f;
+ const float gamma_soft_max = +2.0f;
+ const float gamma_default = 1.0f;
+ m_image_color_gamma = nAttr.create("colorGamma", "colgmma",
+ MFnNumericData::kFloat, gamma_default);
+ CHECK_MSTATUS(nAttr.setStorable(true));
+ CHECK_MSTATUS(nAttr.setKeyable(true));
+ CHECK_MSTATUS(nAttr.setMin(gamma_min));
+ CHECK_MSTATUS(nAttr.setSoftMax(gamma_soft_max));
+ CHECK_MSTATUS(addAttribute(m_image_color_gamma));
+
+ const float saturation_min = 0.0f;
+ const float saturation_soft_max = 2.0f;
+ const float saturation_default = 1.0f;
+ m_image_color_saturation =
+ nAttr.create("colorSaturation", "colstrtn", MFnNumericData::kFloat,
+ saturation_default);
+ CHECK_MSTATUS(nAttr.setStorable(true));
+ CHECK_MSTATUS(nAttr.setKeyable(true));
+ CHECK_MSTATUS(nAttr.setMin(saturation_min));
+ CHECK_MSTATUS(nAttr.setSoftMax(saturation_soft_max));
+ CHECK_MSTATUS(addAttribute(m_image_color_saturation));
+
+ const float soft_clip_min = 0.0f;
+ const float soft_clip_max = 1.0f;
+ const float soft_clip_default = 0.0f;
+ m_image_color_soft_clip =
+ nAttr.create("colorSoftClip", "colsftclp", MFnNumericData::kFloat,
+ soft_clip_default);
+ CHECK_MSTATUS(nAttr.setStorable(true));
+ CHECK_MSTATUS(nAttr.setKeyable(true));
+ CHECK_MSTATUS(nAttr.setMin(soft_clip_min));
+ CHECK_MSTATUS(nAttr.setMax(soft_clip_max));
+ CHECK_MSTATUS(addAttribute(m_image_color_soft_clip));
+
+ const double alpha_min = 0.0;
+ const double alpha_max = 1.0;
+ const double alpha_default = 1.0;
+ m_image_alpha_gain = nAttr.create("alphaGain", "alpgn",
+ MFnNumericData::kDouble, alpha_default);
CHECK_MSTATUS(nAttr.setStorable(true));
CHECK_MSTATUS(nAttr.setConnectable(true));
CHECK_MSTATUS(nAttr.setKeyable(true));
- CHECK_MSTATUS(addAttribute(m_use_color_plug));
+ CHECK_MSTATUS(nAttr.setMin(alpha_min));
+ CHECK_MSTATUS(nAttr.setMax(alpha_max));
+ CHECK_MSTATUS(addAttribute(m_image_alpha_gain));
// Which channel of the image should be displayed?
- short value_all = static_cast(ImageDisplayChannel::kAll);
- short value_red = static_cast(ImageDisplayChannel::kRed);
- short value_green = static_cast(ImageDisplayChannel::kGreen);
- short value_blue = static_cast(ImageDisplayChannel::kBlue);
- short value_alpha = static_cast(ImageDisplayChannel::kAlpha);
- m_image_display_channel = eAttr.create("shaderImageDisplayChannel",
- "shdimgdspchan", value_all, &status);
+ const short value_all = static_cast(ImageDisplayChannel::kAll);
+ const short value_rgb = static_cast(ImageDisplayChannel::kRGB);
+ const short value_red = static_cast(ImageDisplayChannel::kRed);
+ const short value_green = static_cast(ImageDisplayChannel::kGreen);
+ const short value_blue = static_cast(ImageDisplayChannel::kBlue);
+ const short value_alpha = static_cast(ImageDisplayChannel::kAlpha);
+ const short value_luminance =
+ static_cast(ImageDisplayChannel::kLuminance);
+ m_image_display_channel =
+ eAttr.create("displayChannel", "dspchan", value_all, &status);
CHECK_MSTATUS(status);
CHECK_MSTATUS(eAttr.addField("RGBA", value_all));
+ CHECK_MSTATUS(eAttr.addField("RGB", value_rgb));
CHECK_MSTATUS(eAttr.addField("Red", value_red));
CHECK_MSTATUS(eAttr.addField("Green", value_green));
CHECK_MSTATUS(eAttr.addField("Blue", value_blue));
CHECK_MSTATUS(eAttr.addField("Alpha", value_alpha));
+ CHECK_MSTATUS(eAttr.addField("Luminance", value_luminance));
CHECK_MSTATUS(eAttr.setStorable(true));
CHECK_MSTATUS(eAttr.setKeyable(true));
CHECK_MSTATUS(addAttribute(m_image_display_channel));
- m_color_gain = nAttr.create("shaderColorGain", "shdclgn",
- MFnNumericData::kDouble, 1.0);
- CHECK_MSTATUS(nAttr.setStorable(true));
- CHECK_MSTATUS(nAttr.setConnectable(true));
- CHECK_MSTATUS(nAttr.setKeyable(false));
- CHECK_MSTATUS(nAttr.setMin(0.0));
- CHECK_MSTATUS(nAttr.setNiceNameOverride(MString("Color Gain (Shader)")));
- CHECK_MSTATUS(addAttribute(m_color_gain));
-
- m_alpha_gain = nAttr.create("shaderAlphaGain", "shdalpgn",
- MFnNumericData::kDouble, 1.0);
- CHECK_MSTATUS(nAttr.setStorable(true));
- CHECK_MSTATUS(nAttr.setConnectable(true));
- CHECK_MSTATUS(nAttr.setKeyable(false));
- CHECK_MSTATUS(nAttr.setMin(0.0));
- CHECK_MSTATUS(nAttr.setMax(1.0));
- CHECK_MSTATUS(nAttr.setNiceNameOverride(MString("Alpha Gain (Shader)")));
- CHECK_MSTATUS(addAttribute(m_alpha_gain));
-
- m_ignore_alpha = nAttr.create("shaderIgnoreAlpha", "shdignalp",
- MFnNumericData::kBoolean, false);
+ m_image_ignore_alpha = nAttr.create("imageIgnoreAlpha", "imgignalp",
+ MFnNumericData::kBoolean, false);
CHECK_MSTATUS(nAttr.setStorable(true));
CHECK_MSTATUS(nAttr.setConnectable(true));
CHECK_MSTATUS(nAttr.setKeyable(true));
- CHECK_MSTATUS(nAttr.setNiceNameOverride(MString("Ignore Alpha (Shader)")));
- CHECK_MSTATUS(addAttribute(m_ignore_alpha));
+ CHECK_MSTATUS(addAttribute(m_image_ignore_alpha));
- m_flip =
- nAttr.create("shaderFlip", "shdflip", MFnNumericData::kBoolean, false);
+ m_image_flip =
+ nAttr.create("imageFlip", "imgflip", MFnNumericData::kBoolean, false);
CHECK_MSTATUS(nAttr.setStorable(true));
CHECK_MSTATUS(nAttr.setConnectable(true));
CHECK_MSTATUS(nAttr.setKeyable(true));
- CHECK_MSTATUS(nAttr.setNiceNameOverride(MString("Flip (Shader)")));
- CHECK_MSTATUS(addAttribute(m_flip));
+ CHECK_MSTATUS(nAttr.setNiceNameOverride(MString("Image Flip (Vertical)")));
+ CHECK_MSTATUS(addAttribute(m_image_flip));
- m_flop =
- nAttr.create("shaderFlop", "shdflop", MFnNumericData::kBoolean, false);
+ m_image_flop =
+ nAttr.create("imageFlop", "imgflop", MFnNumericData::kBoolean, false);
CHECK_MSTATUS(nAttr.setStorable(true));
CHECK_MSTATUS(nAttr.setConnectable(true));
CHECK_MSTATUS(nAttr.setKeyable(true));
- CHECK_MSTATUS(nAttr.setNiceNameOverride(MString("Flop (Shader)")));
- CHECK_MSTATUS(addAttribute(m_flop));
+ CHECK_MSTATUS(
+ nAttr.setNiceNameOverride(MString("Image Flop (Horizontal)")));
+ CHECK_MSTATUS(addAttribute(m_image_flop));
- m_is_transparent = nAttr.create("shaderIsTransparent", "shdistrnsp",
- MFnNumericData::kBoolean, false);
+ m_shader_is_transparent = nAttr.create("shaderIsTransparent", "shdistrnsp",
+ MFnNumericData::kBoolean, false);
CHECK_MSTATUS(nAttr.setStorable(true));
CHECK_MSTATUS(nAttr.setConnectable(true));
CHECK_MSTATUS(nAttr.setKeyable(true));
CHECK_MSTATUS(
- nAttr.setNiceNameOverride(MString("Is Transparent (Shader)")));
- CHECK_MSTATUS(addAttribute(m_is_transparent));
+ nAttr.setNiceNameOverride(MString("Shader Is Transparent (Debug)")));
+ CHECK_MSTATUS(addAttribute(m_shader_is_transparent));
- m_frame_number =
- nAttr.create("frameNumber", "frmnmb", MFnNumericData::kInt, 1);
+ m_image_default_color = nAttr.createColor("imageDefaultColor", "imgdefcol");
+ CHECK_MSTATUS(nAttr.setKeyable(true));
+ CHECK_MSTATUS(nAttr.setStorable(true));
+ CHECK_MSTATUS(nAttr.setReadable(true));
+ CHECK_MSTATUS(nAttr.setWritable(true));
+ CHECK_MSTATUS(nAttr.setDefault(1.0f, 1.0f, 1.0f));
+ CHECK_MSTATUS(addAttribute(m_image_default_color));
+
+ m_image_frame_number =
+ nAttr.create("imageFrameNumber", "imgfrmnmb", MFnNumericData::kInt, 1);
CHECK_MSTATUS(nAttr.setStorable(true));
CHECK_MSTATUS(nAttr.setKeyable(true));
- CHECK_MSTATUS(addAttribute(m_frame_number));
+ CHECK_MSTATUS(addAttribute(m_image_frame_number));
+
+ // // Pixel Data Type
+ // m_cache_pixel_data_type = eAttr.create(
+ // "cachePixelDataType", "cchpxldtyp",
+ // kDataTypeUnknown);
+ // CHECK_MSTATUS(eAttr.addField("auto", kDataTypeUnknown));
+ // CHECK_MSTATUS(eAttr.addField("uint8", kDataTypeUInt8));
+ // CHECK_MSTATUS(eAttr.addField("uint16", kDataTypeUInt16));
+ // CHECK_MSTATUS(eAttr.addField("half16", kDataTypeHalf16));
+ // CHECK_MSTATUS(eAttr.addField("float32", kDataTypeFloat32));
+ // CHECK_MSTATUS(eAttr.setStorable(true));
// Create empty string data to be used as attribute default
// (string) value.
MFnStringData empty_string_data;
MObject empty_string_data_obj = empty_string_data.create("");
- m_file_path = tAttr.create("shaderFilePath", "shdflpth", MFnData::kString,
- empty_string_data_obj);
+ m_image_file_path = tAttr.create("imageFilePath", "imgflpth",
+ MFnData::kString, empty_string_data_obj);
CHECK_MSTATUS(tAttr.setStorable(true));
CHECK_MSTATUS(tAttr.setUsedAsFilename(true));
- CHECK_MSTATUS(addAttribute(m_file_path));
+ CHECK_MSTATUS(addAttribute(m_image_file_path));
- m_input_color_space = tAttr.create("inputColorSpace", "incolspc",
- MFnData::kString, empty_string_data_obj);
+ m_image_input_color_space = tAttr.create(
+ "inputColorSpace", "incolspc", MFnData::kString, empty_string_data_obj);
CHECK_MSTATUS(tAttr.setStorable(true));
CHECK_MSTATUS(tAttr.setUsedAsFilename(false));
- CHECK_MSTATUS(addAttribute(m_input_color_space));
+ CHECK_MSTATUS(addAttribute(m_image_input_color_space));
- m_output_color_space =
+ m_image_output_color_space =
tAttr.create("outputColorSpace", "outcolspc", MFnData::kString,
empty_string_data_obj);
CHECK_MSTATUS(tAttr.setStorable(true));
CHECK_MSTATUS(tAttr.setUsedAsFilename(false));
- CHECK_MSTATUS(addAttribute(m_output_color_space));
-
- m_color = nAttr.createColor("shaderColor", "shdcl");
- CHECK_MSTATUS(nAttr.setDefault(0.0f, 0.58824f, 0.644f));
- CHECK_MSTATUS(nAttr.setStorable(true));
- CHECK_MSTATUS(nAttr.setConnectable(true));
- CHECK_MSTATUS(nAttr.setKeyable(false));
- CHECK_MSTATUS(nAttr.setNiceNameOverride(MString("Color (Shader)")));
- CHECK_MSTATUS(addAttribute(m_color));
+ CHECK_MSTATUS(addAttribute(m_image_output_color_space));
return MS::kSuccess;
}
diff --git a/src/mmSolver/shape/ImagePlaneShapeNode.h b/src/mmSolver/shape/ImagePlaneShapeNode.h
index d03b6279..7f2977cd 100644
--- a/src/mmSolver/shape/ImagePlaneShapeNode.h
+++ b/src/mmSolver/shape/ImagePlaneShapeNode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2022 David Cattermole.
+ * Copyright (C) 2022, 2024 David Cattermole.
*
* This file is part of mmSolver.
*
@@ -44,7 +44,15 @@
namespace mmsolver {
-enum class ImageDisplayChannel { kAll = 0, kRed, kGreen, kBlue, kAlpha };
+enum class ImageDisplayChannel {
+ kAll = 0,
+ kRGB,
+ kRed,
+ kGreen,
+ kBlue,
+ kAlpha,
+ kLuminance
+};
class ImagePlaneShapeNode : public MPxLocatorNode {
public:
@@ -99,23 +107,25 @@ class ImagePlaneShapeNode : public MPxLocatorNode {
static MObject m_lens_hash_current;
static MObject m_lens_hash_previous;
static MObject m_geometry_node;
- static MObject m_shader_node;
static MObject m_camera_node;
+ static MObject m_shader_is_transparent;
- // Shader Attributes
- static MObject m_use_color_plug;
+ // Image Attributes
static MObject m_image_display_channel;
- static MObject m_color_gain;
- static MObject m_alpha_gain;
- static MObject m_ignore_alpha;
- static MObject m_flip;
- static MObject m_flop;
- static MObject m_is_transparent;
- static MObject m_frame_number;
- static MObject m_file_path;
- static MObject m_input_color_space;
- static MObject m_output_color_space;
- static MObject m_color;
+ static MObject m_image_color_gain;
+ static MObject m_image_color_exposure;
+ static MObject m_image_color_gamma;
+ static MObject m_image_color_saturation;
+ static MObject m_image_color_soft_clip;
+ static MObject m_image_alpha_gain;
+ static MObject m_image_default_color;
+ static MObject m_image_ignore_alpha;
+ static MObject m_image_flip;
+ static MObject m_image_flop;
+ static MObject m_image_file_path;
+ static MObject m_image_frame_number;
+ static MObject m_image_input_color_space;
+ static MObject m_image_output_color_space;
};
} // namespace mmsolver