1 //-*****************************************************************************
2 //
3 // Copyright (c) 2009-2012,
4 // Sony Pictures Imageworks Inc. and
5 // Industrial Light & Magic, a division of Lucasfilm Entertainment Company Ltd.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are
11 // met:
12 // * Redistributions of source code must retain the above copyright
13 // notice, this list of conditions and the following disclaimer.
14 // * Redistributions in binary form must reproduce the above
15 // copyright notice, this list of conditions and the following disclaimer
16 // in the documentation and/or other materials provided with the
17 // distribution.
18 // * Neither the name of Sony Pictures Imageworks, nor
19 // Industrial Light & Magic, nor the names of their contributors may be used
20 // to endorse or promote products derived from this software without specific
21 // prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 //
35 //-*****************************************************************************
36
37
38 #include <Alembic/AbcMaterial/IMaterial.h>
39 #include "InternalUtil.h"
40
41 #include <set>
42
43 namespace Alembic {
44 namespace AbcMaterial {
45 namespace ALEMBIC_VERSION_NS {
46
init()47 void IMaterialSchema::init()
48 {
49 ALEMBIC_ABC_SAFE_CALL_BEGIN( "IMaterialSchema::init()" );
50
51 AbcCoreAbstract::CompoundPropertyReaderPtr _this = this->getPtr();
52
53 if ( this->getPropertyHeader( ".nodes" ) != NULL )
54 {
55 m_node = Abc::ICompoundProperty( _this, ".nodes" );
56 }
57
58 if ( this->getPropertyHeader( ".interfaceParams" ) != NULL )
59 {
60 m_interfaceParams = Abc::ICompoundProperty( _this, ".interfaceParams" );
61 }
62
63 if ( this->getPropertyHeader( ".terminals" ) != NULL )
64 {
65 Abc::IStringArrayProperty termProp( _this, ".terminals" );
66 Abc::StringArraySamplePtr samp;
67 termProp.get( samp );
68
69 size_t numTerms = samp->size() / 2;
70 for( size_t i = 0; i < numTerms; ++i )
71 {
72 m_terminals[( *samp )[2 * i]] = ( *samp )[2 * i + 1];
73 }
74 }
75
76 if ( this->getPropertyHeader( ".shaderNames" ) != NULL )
77 {
78 Abc::IStringArrayProperty shaderProp( _this, ".shaderNames" );
79 Abc::StringArraySamplePtr samp;
80 shaderProp.get( samp );
81
82 size_t numShaders = samp->size() / 2;
83 for( size_t i = 0; i < numShaders; ++i )
84 {
85 m_shaderNames[( *samp )[2 * i]] = ( *samp )[2 * i + 1];
86 }
87 }
88
89 if ( this->getPropertyHeader( ".interface" ) != NULL )
90 {
91 Abc::IStringArrayProperty interfaceProp( _this, ".interface" );
92 Abc::StringArraySamplePtr samp;
93 interfaceProp.get( samp );
94
95 size_t numInterface = samp->size() / 2;
96 m_interface.reserve( numInterface );
97 for( size_t i = 0; i < numInterface; ++i )
98 {
99 m_interfaceMap[( *samp )[2 * i]] = ( *samp )[2 * i + 1];
100 m_interface.push_back( ( *samp )[2 * i] );
101 }
102 }
103 ALEMBIC_ABC_SAFE_CALL_END_RESET();
104 }
105
getTargetNames(std::vector<std::string> & oTargetNames)106 void IMaterialSchema::getTargetNames( std::vector<std::string> & oTargetNames )
107 {
108 ALEMBIC_ABC_SAFE_CALL_BEGIN( "IMaterial::getTargetNames" );
109 std::set<std::string> uniqueNames;
110
111 std::vector<std::string> tokens;
112
113 std::map<std::string, std::string>::iterator i;
114 for ( i = m_shaderNames.begin(); i != m_shaderNames.end(); ++i )
115 {
116 Util::split_tokens( i->first, tokens );
117
118 // target.shaderType
119 if ( tokens.size() == 2 )
120 {
121 uniqueNames.insert( tokens[0] );
122 }
123 }
124
125 oTargetNames.clear();
126 oTargetNames.reserve( uniqueNames.size() );
127 oTargetNames.insert( oTargetNames.end(), uniqueNames.begin(),
128 uniqueNames.end() );
129
130 ALEMBIC_ABC_SAFE_CALL_END_RESET();
131 }
132
133
getShaderTypesForTarget(const std::string & iTargetName,std::vector<std::string> & oShaderTypeNames)134 void IMaterialSchema::getShaderTypesForTarget( const std::string & iTargetName,
135 std::vector<std::string> & oShaderTypeNames )
136 {
137 ALEMBIC_ABC_SAFE_CALL_BEGIN( "IMaterialSchema::getShaderTypesForTarget" );
138 std::set<std::string> uniqueNames;
139
140 std::vector<std::string> tokens;
141
142 std::map<std::string, std::string>::iterator i;
143 for ( i = m_shaderNames.begin(); i != m_shaderNames.end(); ++i )
144 {
145 Util::split_tokens( i->first, tokens );
146
147 if ( tokens.size() == 2 )
148 {
149 if ( tokens[0] == iTargetName )
150 {
151 uniqueNames.insert( tokens[1] );
152 }
153 }
154 }
155
156 oShaderTypeNames.clear();
157 oShaderTypeNames.reserve( uniqueNames.size() );
158 oShaderTypeNames.insert( oShaderTypeNames.end(),
159 uniqueNames.begin(), uniqueNames.end() );
160 ALEMBIC_ABC_SAFE_CALL_END_RESET();
161 }
162
getShader(const std::string & iTarget,const std::string & iShaderType,std::string & oResult)163 bool IMaterialSchema::getShader( const std::string & iTarget,
164 const std::string & iShaderType,
165 std::string & oResult )
166 {
167 ALEMBIC_ABC_SAFE_CALL_BEGIN( "IMaterialSchema::getShader" );
168 std::string propName = Util::buildTargetName( iTarget, iShaderType, "" );
169
170 std::map<std::string, std::string>::iterator i =
171 m_shaderNames.find( propName );
172
173 if ( i != m_shaderNames.end() )
174 {
175 oResult = i->second;
176 return true;
177 }
178
179 ALEMBIC_ABC_SAFE_CALL_END_RESET();
180 return false;
181 }
182
183
getShaderParameters(const std::string & iTarget,const std::string & iShaderType)184 Abc::ICompoundProperty IMaterialSchema::getShaderParameters(
185 const std::string & iTarget,
186 const std::string & iShaderType )
187 {
188 Abc::ICompoundProperty result;
189
190 ALEMBIC_ABC_SAFE_CALL_BEGIN( "IMaterialSchema::getShaderParameters" );
191 std::string propName = Util::buildTargetName( iTarget, iShaderType,
192 "params" );
193
194 if (const AbcCoreAbstract::PropertyHeader * header =
195 getPropertyHeader( propName ) )
196 {
197 if ( header->isCompound() )
198 {
199 result = Abc::ICompoundProperty( *this, propName );
200 }
201 }
202 ALEMBIC_ABC_SAFE_CALL_END_RESET();
203
204 return result;
205 }
206
getNumNetworkNodes()207 size_t IMaterialSchema::getNumNetworkNodes()
208 {
209 ALEMBIC_ABC_SAFE_CALL_BEGIN( "IMaterialSchema::getNumNetworkNodes" );
210 if ( m_node.valid() )
211 {
212 return m_node.getNumProperties();
213 }
214 ALEMBIC_ABC_SAFE_CALL_END_RESET();
215
216 return 0;
217 }
218
getNetworkNodeNames(std::vector<std::string> & oNames)219 void IMaterialSchema::getNetworkNodeNames( std::vector<std::string> & oNames )
220 {
221 ALEMBIC_ABC_SAFE_CALL_BEGIN( "IMateriaSchema::getNetworkNodeNames" );
222 oNames.clear();
223
224 if ( !m_node.valid() )
225 {
226 return;
227 }
228
229 oNames.reserve( m_node.getNumProperties() );
230
231 for ( size_t i = 0, e = m_node.getNumProperties(); i < e; ++i )
232 {
233 const AbcCoreAbstract::PropertyHeader &header =
234 m_node.getPropertyHeader( i );
235
236 if ( header.isCompound() )
237 {
238 oNames.push_back( header.getName() );
239 }
240 }
241 ALEMBIC_ABC_SAFE_CALL_END_RESET();
242 }
243
getNetworkNode(size_t iIndex)244 IMaterialSchema::NetworkNode IMaterialSchema::getNetworkNode( size_t iIndex )
245 {
246 ALEMBIC_ABC_SAFE_CALL_BEGIN( "IMateriaSchema::getNetworkNode" );
247 if ( !m_node.valid() || iIndex >= m_node.getNumProperties() )
248 {
249 return NetworkNode();
250 }
251
252 const AbcCoreAbstract::PropertyHeader &header =
253 m_node.getPropertyHeader( iIndex );
254
255 if ( !header.isCompound() )
256 {
257 return NetworkNode();
258 }
259
260 return NetworkNode(
261 Abc::ICompoundProperty( m_node, header.getName() ) );
262 ALEMBIC_ABC_SAFE_CALL_END_RESET();
263
264 return NetworkNode();
265 }
266
267
getNetworkNode(const std::string & iNodeName)268 IMaterialSchema::NetworkNode IMaterialSchema::getNetworkNode(
269 const std::string & iNodeName )
270 {
271 return NetworkNode( m_node, iNodeName );
272 }
273
274
getNetworkTerminalTargetNames(std::vector<std::string> & oTargetNames)275 void IMaterialSchema::getNetworkTerminalTargetNames(
276 std::vector<std::string> & oTargetNames )
277 {
278 ALEMBIC_ABC_SAFE_CALL_BEGIN(
279 "IMateriaSchema::getNetworkTerminalTargetNames" );
280 oTargetNames.clear();
281
282 std::set<std::string> uniqueNames;
283
284 std::vector<std::string> tokens;
285 std::map<std::string, std::string>::iterator i;
286 for ( i = m_terminals.begin(); i != m_terminals.end(); ++i )
287 {
288 Util::split_tokens( i->first, tokens );
289
290 // target.shaderType
291 if ( tokens.size() == 2 )
292 {
293 uniqueNames.insert( tokens[0] );
294 }
295 }
296
297 oTargetNames.reserve( uniqueNames.size() );
298 oTargetNames.insert( oTargetNames.end(),
299 uniqueNames.begin(), uniqueNames.end() );
300 ALEMBIC_ABC_SAFE_CALL_END_RESET();
301 }
302
getNetworkTerminalShaderTypesForTarget(const std::string & iTargetName,std::vector<std::string> & oShaderTypeNames)303 void IMaterialSchema::getNetworkTerminalShaderTypesForTarget(
304 const std::string & iTargetName,
305 std::vector<std::string> & oShaderTypeNames)
306 {
307 ALEMBIC_ABC_SAFE_CALL_BEGIN(
308 "IMateriaSchema::getNetworkTerminalShaderTypesForTarget" );
309
310 oShaderTypeNames.clear();
311
312 std::set<std::string> uniqueNames;
313
314 std::vector<std::string> tokens;
315 std::map<std::string, std::string>::iterator i;
316 for ( i = m_terminals.begin(); i != m_terminals.end(); ++i )
317 {
318 Util::split_tokens( i->first, tokens );
319
320 if ( tokens.size() == 2 )
321 {
322 if ( tokens[0] == iTargetName )
323 {
324 uniqueNames.insert( tokens[1] );
325 }
326 }
327 }
328
329 oShaderTypeNames.reserve( uniqueNames.size() );
330 oShaderTypeNames.insert( oShaderTypeNames.end(),
331 uniqueNames.begin(), uniqueNames.end() );
332
333 ALEMBIC_ABC_SAFE_CALL_END_RESET();
334 }
335
getNetworkTerminal(const std::string & iTarget,const std::string & iShaderType,std::string & oNodeName,std::string & oOutputName)336 bool IMaterialSchema::getNetworkTerminal(
337 const std::string & iTarget,
338 const std::string & iShaderType,
339 std::string & oNodeName,
340 std::string & oOutputName)
341 {
342 ALEMBIC_ABC_SAFE_CALL_BEGIN(
343 "IMateriaSchema::getNetworkTerminal" );
344
345 std::string propName = iTarget + "." + iShaderType;
346
347 std::map<std::string, std::string>::iterator i =
348 m_terminals.find( propName );
349
350 if ( i == m_terminals.end() )
351 {
352 return false;
353 }
354
355 std::vector<std::string> tokens;
356 Util::split_tokens( i->second, tokens, 1 );
357
358 oNodeName = tokens[0];
359 oOutputName = tokens.size() > 1 ? tokens[1] : "";
360
361 return true;
362 ALEMBIC_ABC_SAFE_CALL_END_RESET();
363
364 return false;
365 }
366
getNumNetworkInterfaceParameterMappings()367 size_t IMaterialSchema::getNumNetworkInterfaceParameterMappings()
368 {
369 return m_interface.size();
370 }
371
372
getNetworkInterfaceParameterMapping(size_t iIndex,std::string & oInterfaceParamName,std::string & oMapToNodeName,std::string & oMapToParamName)373 bool IMaterialSchema::getNetworkInterfaceParameterMapping( size_t iIndex,
374 std::string & oInterfaceParamName, std::string & oMapToNodeName,
375 std::string & oMapToParamName )
376 {
377 ALEMBIC_ABC_SAFE_CALL_BEGIN(
378 "IMateriaSchema::getNetworkInterfaceParameterMapping(size_t,...)" );
379
380 if ( iIndex >= m_interface.size() )
381 {
382 return false;
383 }
384
385 oInterfaceParamName = m_interface[iIndex];
386
387 return getNetworkInterfaceParameterMapping( oInterfaceParamName,
388 oMapToNodeName,
389 oMapToParamName );
390 ALEMBIC_ABC_SAFE_CALL_END_RESET();
391
392 return false;
393 }
394
395
396
397
getNetworkInterfaceParameterMappingNames(std::vector<std::string> & oNames)398 void IMaterialSchema::getNetworkInterfaceParameterMappingNames(
399 std::vector<std::string> & oNames )
400 {
401 oNames = m_interface;
402 }
403
404
getNetworkInterfaceParameterMapping(const std::string & iInterfaceParamName,std::string & oMapToNodeName,std::string & oMapToParamName)405 bool IMaterialSchema::getNetworkInterfaceParameterMapping(
406 const std::string & iInterfaceParamName,
407 std::string & oMapToNodeName,
408 std::string & oMapToParamName )
409 {
410 ALEMBIC_ABC_SAFE_CALL_BEGIN(
411 "IMateriaSchema::getNetworkInterfaceParameterMapping" );
412
413 std::map<std::string, std::string>::iterator i =
414 m_interfaceMap.find( iInterfaceParamName );
415
416 if ( i == m_interfaceMap.end() )
417 {
418 return false;
419 }
420
421 std::vector<std::string> tokens;
422
423 Util::split_tokens( i->second, tokens, 1 );
424
425 oMapToNodeName = tokens[0];
426 oMapToParamName = tokens.size() > 1 ? tokens[1] : "";
427
428 return true;
429 ALEMBIC_ABC_SAFE_CALL_END_RESET();
430
431 return false;
432 }
433
getNetworkInterfaceParameters()434 Abc::ICompoundProperty IMaterialSchema::getNetworkInterfaceParameters()
435 {
436 return m_interfaceParams;
437 }
438
439
440 ///////////////////////////////////////////////////////////////////////////////
441
NetworkNode()442 IMaterialSchema::NetworkNode::NetworkNode()
443 : m_connectionsChecked( false )
444 {
445 }
446
447
NetworkNode(Abc::ICompoundProperty iCompound)448 IMaterialSchema::NetworkNode::NetworkNode( Abc::ICompoundProperty iCompound )
449 : m_compound( iCompound )
450 , m_connectionsChecked( false )
451 {
452 }
453
454
NetworkNode(Abc::ICompoundProperty iParent,const std::string & iNodeName)455 IMaterialSchema::NetworkNode::NetworkNode( Abc::ICompoundProperty iParent,
456 const std::string & iNodeName )
457 : m_connectionsChecked( false )
458 {
459 if ( iParent.valid() )
460 {
461 if ( const AbcCoreAbstract::PropertyHeader * header =
462 iParent.getPropertyHeader( iNodeName ) )
463 {
464 if ( header->isCompound() )
465 {
466 m_compound = Abc::ICompoundProperty( iParent, iNodeName );
467 }
468 }
469 }
470 }
471
valid()472 bool IMaterialSchema::NetworkNode::valid()
473 {
474 return m_compound.valid();
475 }
476
477
getName()478 std::string IMaterialSchema::NetworkNode::getName()
479 {
480 if ( valid() )
481 {
482 return m_compound.getName();
483 }
484
485 return "";
486 }
487
488
getTarget(std::string & oResult)489 bool IMaterialSchema::NetworkNode::getTarget( std::string & oResult )
490 {
491 if ( !valid() )
492 {
493 return false;
494 }
495
496 if ( const AbcCoreAbstract::PropertyHeader * header =
497 m_compound.getPropertyHeader( "target" ) )
498 {
499 if ( header->isScalar() && Abc::IStringProperty::matches( *header) )
500 {
501 Abc::IStringProperty prop( m_compound, header->getName() );
502
503 oResult = prop.getValue();
504 return true;
505 }
506 }
507
508 return false;
509 }
510
getNodeType(std::string & oResult)511 bool IMaterialSchema::NetworkNode::getNodeType( std::string & oResult )
512 {
513 if ( !valid() )
514 {
515 return false;
516 }
517
518 if ( const AbcCoreAbstract::PropertyHeader * header =
519 m_compound.getPropertyHeader( "type" ) )
520 {
521 if ( header->isScalar() && Abc::IStringProperty::matches( *header ) )
522 {
523 Abc::IStringProperty prop( m_compound, header->getName() );
524
525 oResult = prop.getValue();
526 return true;
527 }
528 }
529
530 return false;
531 }
532
getParameters()533 Abc::ICompoundProperty IMaterialSchema::NetworkNode::getParameters()
534 {
535 Abc::ICompoundProperty result;
536 if ( !valid() )
537 {
538 return result;
539 }
540
541 if (const AbcCoreAbstract::PropertyHeader * header =
542 m_compound.getPropertyHeader( "params" ) )
543 {
544 if ( header->isCompound() )
545 {
546 result = Abc::ICompoundProperty( m_compound, "params" );
547 }
548 }
549
550 return result;
551 }
552
getNumConnections()553 size_t IMaterialSchema::NetworkNode::getNumConnections()
554 {
555 if ( ! m_connectionsChecked )
556 {
557 if ( m_compound.getPropertyHeader( ".connections" ) != NULL )
558 {
559 Abc::IStringArrayProperty connectProp( m_compound, ".connections" );
560 Abc::StringArraySamplePtr samp;
561 connectProp.get( samp );
562
563 size_t numConnect = samp->size() / 2;
564 m_connections.reserve( numConnect );
565 for( size_t i = 0; i < numConnect; ++i )
566 {
567 m_connectionsMap[( *samp )[2 * i]] = ( *samp )[2 * i + 1];
568 m_connections.push_back( ( *samp )[2 * i] );
569 }
570 }
571 m_connectionsChecked = true;
572 }
573
574 return m_connections.size();
575
576 }
577
splitConnectionValue(const std::string & v,std::string & a,std::string & b)578 void IMaterialSchema::NetworkNode::splitConnectionValue( const std::string & v,
579 std::string & a, std::string & b )
580 {
581 std::vector<std::string> tokens;
582
583 Util::split_tokens(v, tokens, 1);
584
585 a = tokens[0];
586 b = tokens.size() > 1 ? tokens[1] : "";
587 }
588
getConnection(size_t iIndex,std::string & oInputName,std::string & oConnectedNodeName,std::string & oConnectedOutputName)589 bool IMaterialSchema::NetworkNode::getConnection(
590 size_t iIndex,
591 std::string & oInputName,
592 std::string & oConnectedNodeName,
593 std::string & oConnectedOutputName )
594 {
595 if ( iIndex >= getNumConnections() )
596 {
597 return false;
598 }
599
600 oInputName = m_connections[iIndex];
601 return getConnection( oInputName, oConnectedNodeName,
602 oConnectedOutputName );
603 }
604
getConnection(const std::string & iInputName,std::string & oConnectedNodeName,std::string & oConnectedOutputName)605 bool IMaterialSchema::NetworkNode::getConnection(
606 const std::string & iInputName,
607 std::string & oConnectedNodeName,
608 std::string & oConnectedOutputName )
609 {
610 // loads the connections if it hasn't already
611 getNumConnections();
612
613 std::map< std::string, std::string >::iterator i =
614 m_connectionsMap.find( iInputName );
615
616 if ( i == m_connectionsMap.end() )
617 {
618 return false;
619 }
620
621 std::string value = i->second;
622 splitConnectionValue( value, oConnectedNodeName, oConnectedOutputName );
623
624 return true;
625 }
626
627 } // End namespace ALEMBIC_VERSION_NS
628 } // End namespace AbcMaterial
629 } // End namespace Alembic
630
631