diff options
Diffstat (limited to 'mayaPlug/shaveCheckObjectVisibility.cpp')
| -rw-r--r-- | mayaPlug/shaveCheckObjectVisibility.cpp | 250 |
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; +} |