1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
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;
}
|