aboutsummaryrefslogtreecommitdiff
path: root/mayaPlug/shaveCheckObjectVisibility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mayaPlug/shaveCheckObjectVisibility.cpp')
-rw-r--r--mayaPlug/shaveCheckObjectVisibility.cpp250
1 files changed, 250 insertions, 0 deletions
diff --git a/mayaPlug/shaveCheckObjectVisibility.cpp b/mayaPlug/shaveCheckObjectVisibility.cpp
new file mode 100644
index 0000000..6f725e7
--- /dev/null
+++ b/mayaPlug/shaveCheckObjectVisibility.cpp
@@ -0,0 +1,250 @@
+// Shave and a Haircut
+// (c) 2019 Epic Games
+// US Patent 6720962
+
+#include <maya/MDagPath.h>
+#include <maya/MFnDagNode.h>
+#include <maya/MFnDependencyNode.h>
+#include <maya/MPlug.h>
+#include <maya/MPlugArray.h>
+
+#include "shaveCheckObjectVisibility.h"
+#include "shaveIO.h"
+#include "shaveUtil.h"
+
+
+bool isObjectVisible(
+ const MDagPath& path,
+ bool andNotTemplated,
+ bool ignorePrimaryVisibility,
+ bool ignoreTransparency,
+ bool ignoreOverrideTemplating,
+ bool& overridesEnabled
+)
+//
+// Description:
+// Check if the given object is visible
+//
+{
+ MStatus status;
+ MFnDagNode fnDN(path);
+ MPlug plug;
+
+ //
+ // Are layer overrides enabled?
+ //
+ plug = fnDN.findPlug("overrideEnabled");
+ plug.getValue(overridesEnabled);
+
+ //
+ // If the object isn't visible, then it's not visible. :-)
+ //
+ bool isSet;
+
+ plug = fnDN.findPlug("visibility");
+ plug.getValue(isSet);
+
+ if (!isSet) return false;
+
+ if (!ignorePrimaryVisibility)
+ {
+ plug = fnDN.findPlug("primaryVisibility");
+ plug.getValue(isSet);
+
+ if (!isSet) return false;
+ }
+
+ //
+ // If any part of the object is being shaded by a shader with non-zero
+ // transparency, or whose transparency is driven by a connection, then
+ // we will consider the object to be transparent and return false.
+ //
+ if (!ignoreTransparency)
+ {
+ //
+ // Get all of the shading groups to which this instance of this
+ // object, or any of its components, is assigned.
+ //
+ MObjectArray shadingGroups;
+
+ shaveUtil::getShadingGroups(path, shadingGroups);
+
+ //
+ // Step through each shading group and see if its associated
+ // shader has non-zero transparency.
+ //
+ float transparency;
+ unsigned int i;
+ unsigned int j;
+ unsigned int k;
+ unsigned int numShadingGroups = shadingGroups.length();
+ MPlugArray conns;
+ char* plugNames[] = { "surfaceShader", "volumeShader" };
+
+ char* transpNames[] = {
+ "transparency",
+ "transparencyR",
+ "transparencyG",
+ "transparencyB"
+ };
+
+
+ for (i = 0; i < numShadingGroups; i++)
+ {
+ MFnDependencyNode groupFn(shadingGroups[i]);
+
+ for (j = 0; j < 2; j++)
+ {
+ plug = groupFn.findPlug(plugNames[j], &status);
+
+ if (status)
+ {
+ //
+ // If this port on the shading group has a shader
+ // connected to it, then we need to check the shader's
+ // transparency.
+ //
+ // Unless this is a layered shader, then we ignore
+ // transparency because layered shaders *always* have
+ // transparency but are rarely transparent overall.
+ //
+ plug.connectedTo(conns, true, false);
+
+ if ((conns.length() > 0)
+ && !conns[0].node().hasFn(MFn::kLayeredShader))
+ {
+ MFnDependencyNode shaderFn(conns[0].node());
+
+ //
+ // Does the shader have a transparency attribute?
+ //
+ for (k = 0; k < 4; k++)
+ {
+ plug = shaderFn.findPlug(transpNames[k], &status);
+
+ if (status)
+ {
+ //
+ // If the transparency attribute has an
+ // incoming connection, then the
+ // transparency value may change during the
+ // course of a render. So we treat the
+ // shader as being transparent and return
+ // true.
+ //
+ plug.connectedTo(conns, true, false);
+
+ if (conns.length() > 0) return false;
+
+ //
+ // If the shader's transparency is anything
+ // other than zero, we treat it as
+ // transparent and return true.
+ //
+ plug.getValue(transparency);
+
+ if (transparency > 0.0f) return false;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // If the object is an intermediate object (e.g. in the middle of a
+ // chaini of deformations) then it's not visible.
+ //
+ plug = fnDN.findPlug("intermediateObject");
+ plug.getValue(isSet);
+
+ if (isSet) return false;
+
+ //
+ // Are we treating templated objects as if they're invisible?
+ //
+ if (andNotTemplated)
+ {
+ plug = fnDN.findPlug("template");
+ plug.getValue(isSet);
+
+ if (isSet) return false;
+ }
+
+ if (overridesEnabled)
+ {
+ //
+ // Now we do the same checks, but this time for the layer
+ // overrides.
+ //
+ // First, visibility.
+ //
+ plug = fnDN.findPlug("overrideVisibility");
+ plug.getValue(isSet);
+
+ if (!isSet) return false;
+
+ //
+ // Templating.
+ //
+ if (andNotTemplated && !ignoreOverrideTemplating)
+ {
+ int displayMode;
+
+ plug = fnDN.findPlug("overrideDisplayType");
+ plug.getValue(displayMode);
+
+ if (displayMode == 1) return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool areObjectAndParentsVisible(
+ const MDagPath& path,
+ bool andNotTemplated,
+ bool ignorePrimaryVisibility,
+ bool ignoreTransparency
+)
+//
+// Description:
+// Check if this object and all of its parents are visible. In Maya,
+// visibility is determined by heirarchy. So, if one of a node's
+// parents is invisible, then so is the node.
+//
+{
+ bool ignoreOverrideTemplating = false;
+ bool isVisible = true;
+ bool overridesEnabled;
+ MDagPath searchPath(path);
+
+ while (isVisible)
+ {
+ isVisible = isObjectVisible(
+ searchPath,
+ andNotTemplated,
+ ignorePrimaryVisibility,
+ ignoreTransparency,
+ ignoreOverrideTemplating,
+ overridesEnabled
+ );
+
+ if (searchPath.length() == 1) break;
+
+ //
+ // One exception to the hierarchical rule is override templating.
+ // That's handled by the lowest node which has overrides enabled.
+ // So once we've hit a node which has overrides enabled, then we
+ // must ignore override templating in any nodes above that in the
+ // hierarchy.
+ //
+ if (overridesEnabled) ignoreOverrideTemplating = true;
+
+ searchPath.pop();
+ }
+
+ return isVisible;
+}