2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/event/effects/shader-effect-impl.h>
25 #include <dali/public-api/math/vector2.h>
26 #include <dali/public-api/math/matrix.h>
27 #include <dali/public-api/math/matrix3.h>
28 #include <dali/public-api/shader-effects/shader-effect.h>
29 #include <dali/public-api/object/type-registry.h>
30 #include <dali/public-api/scripting/scripting.h>
31 #include "dali-shaders.h"
32 #include <dali/internal/event/effects/shader-declarations.h>
33 #include <dali/internal/event/effects/shader-factory.h>
34 #include <dali/internal/event/images/image-impl.h>
35 #include <dali/internal/update/common/animatable-property.h>
36 #include <dali/internal/update/manager/update-manager.h>
37 #include <dali/internal/event/common/stage-impl.h>
38 #include <dali/internal/event/common/thread-local-storage.h>
39 #include <dali/internal/render/shaders/shader.h>
40 #include <dali/internal/update/common/property-owner-messages.h>
41 #include <dali/internal/update/animation/scene-graph-constraint-base.h>
43 using Dali::Internal::SceneGraph::UpdateManager;
44 using Dali::Internal::SceneGraph::UniformMeta;
45 using Dali::Internal::SceneGraph::Shader;
46 using Dali::Internal::SceneGraph::AnimatableProperty;
47 using Dali::Internal::SceneGraph::PropertyBase;
48 using Dali::Internal::SceneGraph::PropertyBase;
49 using Dali::Internal::SceneGraph::RenderQueue;
54 const Property::Index ShaderEffect::GRID_DENSITY = 0;
55 const Property::Index ShaderEffect::IMAGE = 1;
56 const Property::Index ShaderEffect::PROGRAM = 2;
57 const Property::Index ShaderEffect::GEOMETRY_HINTS = 3;
62 ShaderEffect::DefaultPropertyLookup* ShaderEffect::mDefaultPropertyLookup = NULL;
69 Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New( );
71 ShaderFactory::LoadTextSubtypeShaders(internal);
73 return Dali::ShaderEffect(internal.Get());
76 TypeRegistration mType( typeid(Dali::ShaderEffect), typeid(Dali::Handle), Create );
78 const std::string DEFAULT_PROPERTY_NAMES[] =
85 const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
87 const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
89 Property::FLOAT, // "grid-density",
90 Property::MAP, // "image",
91 Property::MAP, // "program",
92 Property::INTEGER, // "geometry-hints",
95 void SetShaderProgram( const std::string& imageVertexSnippet, const std::string& imageFragmentSnippet,
96 const std::string& textVertexSnippet, const std::string& textFragmentSnippet,
97 const std::string& texturedMeshVertexSnippet, const std::string& texturedMeshFragmentSnippet,
98 const std::string& meshVertexSnippet, const std::string& meshFragmentSnippet,
99 const std::string& vertexShaderPrefix, const std::string& fragmentShaderPrefix,
100 ShaderEffectPtr shaderEffect )
102 DALI_ASSERT_DEBUG(shaderEffect);
104 // create complete shader program strings for GEOMETRY_TYPE_IMAGE
105 std::string vertexSource = vertexShaderPrefix + CustomImagePrefixVertex;
106 std::string fragmentSource = fragmentShaderPrefix + CustomImagePrefixFragment;
108 // Append the custom vertex shader code if supplied, otherwise append the default
109 if ( imageVertexSnippet.length() > 0 )
111 vertexSource.append( imageVertexSnippet );
115 vertexSource.append( CustomImagePostfixVertex );
118 // Append the custom fragment shader code if supplied, otherwise append the default
119 if ( imageFragmentSnippet.length() > 0 )
121 fragmentSource.append( imageFragmentSnippet );
125 fragmentSource.append( CustomImagePostfixFragment );
129 shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
132 // create complete shader program strings for GEOMETRY_TYPE_TEXT
133 vertexSource = CustomFontPrefixVertex;
134 fragmentSource = CustomFontPrefixFragment;
136 // Append the custom vertex shader code if supplied, otherwise append the default
137 if ( textVertexSnippet.length() > 0 )
139 vertexSource.append( textVertexSnippet );
143 vertexSource.append( CustomFontPostfixVertex );
146 // Append the custom fragment shader code if supplied, otherwise append the default
147 if ( textFragmentSnippet.length() > 0 )
149 fragmentSource.append( textFragmentSnippet );
153 fragmentSource.append( CustomFontPostfixFragment );
156 // Add Program. Note, we only change the default program here, and leave the other sub-types as-is
157 shaderEffect->SetProgram(GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, vertexSource, fragmentSource);
159 // create complete shader program strings for GEOMETRY_TYPE_TEXTURED_MESH
160 if( texturedMeshVertexSnippet.length() > 0 )
162 vertexSource = CustomMeshPrefixVertex;
163 vertexSource.append( texturedMeshVertexSnippet );
167 vertexSource = MeshVertex;
170 if( texturedMeshFragmentSnippet.length() > 0 )
172 fragmentSource = CustomMeshPrefixFragment;
173 fragmentSource.append( texturedMeshFragmentSnippet );
177 fragmentSource = MeshFragment;
181 shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
183 // create complete shader program strings for GEOMETRY_TYPE_MESH
184 if( meshVertexSnippet.length() > 0 )
186 vertexSource = CustomMeshPrefixVertex;
187 vertexSource.append( meshVertexSnippet );
191 vertexSource = MeshVertex;
194 if( meshFragmentSnippet.length() > 0 )
196 fragmentSource = CustomMeshPrefixFragment;
197 fragmentSource.append( meshFragmentSnippet );
201 fragmentSource = MeshFragment;
205 shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
208 void SetShaderProgram( const std::string& vertexShaderPrefix, const std::string& vertexShader,
209 const std::string& fragmentShaderPrefix, const std::string& fragmentShader,
210 GeometryType geometryTypes,
211 ShaderEffectPtr shaderEffect )
213 DALI_ASSERT_DEBUG(shaderEffect);
215 if( geometryTypes & GEOMETRY_TYPE_IMAGE )
217 shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL,
218 vertexShaderPrefix + CustomImagePrefixVertex + ( !vertexShader.empty() ? vertexShader : CustomImagePostfixVertex ),
219 fragmentShaderPrefix + CustomImagePrefixFragment + ( !fragmentShader.empty() ? fragmentShader : CustomImagePostfixFragment ) );
223 shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL,
224 CustomImagePrefixVertex + CustomImagePostfixVertex,
225 CustomImagePrefixFragment + CustomImagePostfixFragment );
228 if( geometryTypes & GEOMETRY_TYPE_TEXT )
230 shaderEffect->SetProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT,
231 vertexShaderPrefix + CustomFontPrefixVertex + ( !vertexShader.empty() ? vertexShader : CustomFontPostfixVertex ),
232 fragmentShaderPrefix + CustomFontPrefixFragment + ( !fragmentShader.empty() ? fragmentShader : CustomFontPostfixFragment ) );
236 shaderEffect->SetProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT,
237 CustomFontPrefixVertex + CustomFontPostfixVertex,
238 CustomFontPrefixFragment + CustomFontPostfixFragment );
241 if( geometryTypes & GEOMETRY_TYPE_TEXTURED_MESH )
243 shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL,
244 vertexShaderPrefix + ( !vertexShader.empty() ? CustomMeshPrefixVertex + vertexShader : MeshVertex ),
245 fragmentShaderPrefix + ( !fragmentShader.empty() ? CustomMeshPrefixFragment + fragmentShader : MeshFragment ) );
249 shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, MeshVertex, MeshFragment );
252 if( geometryTypes & GEOMETRY_TYPE_MESH )
254 shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL,
255 vertexShaderPrefix + ( !vertexShader.empty() ? CustomMeshPrefixVertex + vertexShader : MeshColorNoTextureVertex ),
256 fragmentShaderPrefix + ( !fragmentShader.empty() ? CustomMeshPrefixFragment + fragmentShader : MeshColorNoTextureFragment ) );
260 shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, MeshColorNoTextureVertex, MeshColorNoTextureFragment );
264 std::string GetFileContents( const std::string& filename )
266 std::ifstream input( filename.c_str() );
267 return std::string( std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>() );
270 std::string GetShader(const std::string& field, const Property::Value& property)
272 if( property.HasKey(field) )
274 DALI_ASSERT_ALWAYS(property.GetValue(field).GetType() == Property::STRING && "Shader property is not a string" );
276 // we could also check here for an array of strings as convenience for json not having multi line strings
277 return property.GetValue(field).Get<std::string>();
281 // convention of shader field appended with -filename signifies a file
282 std::string filenameKey(std::string(field) + std::string("-filename"));
284 if( property.HasKey( filenameKey ) )
286 DALI_ASSERT_ALWAYS(property.GetValue(filenameKey).GetType() == Property::STRING && "Shader filename property is not a string" );
287 // this should eventually be done by an adaptor interface
288 return GetFileContents( property.GetValue(filenameKey).Get<std::string>() );
293 return std::string();
299 ShaderEffectPtr ShaderEffect::New( Dali::ShaderEffect::GeometryHints hints )
301 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
302 UpdateManager& updateManager = tls.GetUpdateManager();
303 ShaderFactory& shaderFactory = tls.GetShaderFactory();
305 // Create a new scene-object, temporarily owned
306 Shader* sceneObject = new Shader( hints );
307 DALI_ASSERT_DEBUG( NULL != sceneObject );
309 ShaderEffectPtr shaderEffect( new ShaderEffect( updateManager, shaderFactory, *sceneObject ) );
310 shaderEffect->RegisterObject();
315 ShaderEffectPtr ShaderEffect::New( const std::string& vertexShader,
316 const std::string& fragmentShader,
317 GeometryType geometryType,
318 Dali::ShaderEffect::GeometryHints hints )
320 return NewWithPrefix( "", vertexShader, "", fragmentShader, geometryType, hints);
323 ShaderEffectPtr ShaderEffect::NewWithPrefix( const std::string& vertexShaderPrefix,
324 const std::string& vertexShader,
325 const std::string& fragmentShaderPrefix,
326 const std::string& fragmentShader,
327 GeometryType geometryTypes,
328 Dali::ShaderEffect::GeometryHints hints )
330 ShaderEffectPtr shaderEffect( New(hints) );
332 ShaderFactory::LoadTextSubtypeShaders(shaderEffect);
334 SetShaderProgram( vertexShaderPrefix, vertexShader,
335 fragmentShaderPrefix, fragmentShader,
342 ShaderEffectPtr ShaderEffect::New( const std::string& imageVertexShader,
343 const std::string& imageFragmentShader,
344 const std::string& textVertexShader,
345 const std::string& textFragmentShader,
346 const std::string& texturedMeshVertexShader,
347 const std::string& texturedMeshFragmentShader,
348 const std::string& meshVertexShader,
349 const std::string& meshFragmentShader,
350 Dali::ShaderEffect::GeometryHints hints )
352 ShaderEffectPtr shaderEffect( New(hints) );
354 ShaderFactory::LoadTextSubtypeShaders(shaderEffect);
356 SetShaderProgram( imageVertexShader, imageFragmentShader,
357 textVertexShader, textFragmentShader,
358 texturedMeshVertexShader, texturedMeshFragmentShader,
359 meshVertexShader, meshFragmentShader,
366 ShaderEffect::~ShaderEffect()
368 DALI_ASSERT_DEBUG( mSceneObject != NULL );
370 // Guard to allow handle destruction after Core has been destroyed
371 if ( Stage::IsInstalled() )
373 // Remove scene-object using a message to the UpdateManager
374 RemoveShaderMessage( mUpdateManager, *mSceneObject );
380 ShaderEffect::ShaderEffect( UpdateManager& updateManager, ShaderFactory& shaderFactory, Shader& sceneObject )
381 : mUpdateManager( updateManager ),
382 mShaderFactory( shaderFactory ),
383 mSceneObject( &sceneObject ),
386 // Transfer shader ownership to a scene message
387 AddShaderMessage( mUpdateManager, *mSceneObject );
390 void ShaderEffect::SetEffectImage( Dali::Image image )
392 // if images are the same, do nothing
398 if (mImage && mConnectionCount > 0)
400 // unset previous image
401 GetImplementation(mImage).Disconnect();
404 // in case image is empty this will reset our image handle
409 // mSceneShader can be in a separate thread; queue a setter message
410 SetTextureIdMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, 0 );
414 // tell image that we're using it
415 if (mConnectionCount > 0)
417 GetImplementation(mImage).Connect();
419 // mSceneShader can be in a separate thread; queue a setter message
420 SetTextureIdMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, GetImplementation(mImage).GetResourceId() );
424 void ShaderEffect::SetUniform( const std::string& name, Property::Value value, UniformCoordinateType uniformCoordinateType )
426 // Register the property if it does not exist
427 Property::Index index = GetPropertyIndex( name );
428 if ( Property::INVALID_INDEX == index )
430 index = RegisterProperty( name, value );
433 SetProperty( index, value );
435 SetCoordinateTypeMessage( mUpdateManager.GetEventToUpdate(), *mCustomMetadata[index], uniformCoordinateType );
438 void ShaderEffect::AttachExtension( Dali::ShaderEffect::Extension *extension )
440 DALI_ASSERT_ALWAYS( extension != NULL && "Attaching uninitialized extension" );
441 mExtension = IntrusivePtr<Dali::ShaderEffect::Extension>( extension );
444 Dali::ShaderEffect::Extension& ShaderEffect::GetExtension()
446 DALI_ASSERT_ALWAYS( mExtension && "Getting uninitialized extension" );
450 const Dali::ShaderEffect::Extension& ShaderEffect::GetExtension() const
452 DALI_ASSERT_ALWAYS( mExtension && "Getting uninitialized extension" );
456 void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType,
457 const std::string& vertexSource, const std::string& fragmentSource,
458 ShaderEffect::FixedVertexShader fixedShader )
460 // Load done asynchronously in update thread. SetProgram message below must be processed afterwards.
461 // Therefore, resource manager cannot farm out the loading to the adaptor resource threads,
462 // but must instead use synchronous loading via PlatformAbstraction::LoadFile()
464 ResourceTicketPtr ticket( mShaderFactory.Load(vertexSource, fragmentSource, shaderHash) );
466 DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "ShaderEffect: SetProgram(geometryType %d subType:%d ticket.id:%d)\n", geometryType, subType, ticket->GetId() );
468 bool areVerticesFixed = (fixedShader == ShaderEffect::FIXED);
469 // Add shader program to scene-object using a message to the UpdateManager
470 SetShaderProgramMessage( mUpdateManager, *mSceneObject, geometryType, subType, ticket->GetId(), shaderHash, areVerticesFixed );
472 mTickets.push_back(ticket); // add ticket to collection to keep it alive.
476 void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType,
477 const std::string& vertexPrefix, const std::string& fragmentPrefix,
478 const std::string& vertexSource, const std::string& fragmentSource,
479 ShaderEffect::FixedVertexShader fixedShader )
481 const std::string vertex( vertexPrefix + vertexSource );
482 const std::string fragment( fragmentPrefix + fragmentSource );
483 SetProgram( geometryType, subType, vertex, fragment, fixedShader );
486 void ShaderEffect::Connect()
490 if (mImage && mConnectionCount == 1)
492 GetImplementation(mImage).Connect();
494 // Image may have changed resource due to load/release policy. Ensure correct texture ID is set on scene graph object
495 SetTextureIdMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, GetImplementation(mImage).GetResourceId() );
499 void ShaderEffect::Disconnect()
501 DALI_ASSERT_DEBUG(mConnectionCount > 0);
504 if (mImage && mConnectionCount == 0)
506 GetImplementation(mImage).Disconnect();
510 bool ShaderEffect::IsSceneObjectRemovable() const
512 return false; // The Shader is not removed during this proxy's lifetime
515 unsigned int ShaderEffect::GetDefaultPropertyCount() const
517 return DEFAULT_PROPERTY_COUNT;
520 void ShaderEffect::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
522 indices.reserve( DEFAULT_PROPERTY_COUNT );
524 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
526 indices.push_back( i );
530 const std::string& ShaderEffect::GetDefaultPropertyName(Property::Index index) const
532 if( index < DEFAULT_PROPERTY_COUNT )
534 return DEFAULT_PROPERTY_NAMES[index];
538 // index out of range..return empty string
539 static const std::string INVALID_PROPERTY_NAME;
540 return INVALID_PROPERTY_NAME;
544 Property::Index ShaderEffect::GetDefaultPropertyIndex(const std::string& name) const
546 Property::Index index = Property::INVALID_INDEX;
548 // Lazy initialization of static mDefaultPropertyLookup
549 if (!mDefaultPropertyLookup)
551 mDefaultPropertyLookup = new DefaultPropertyLookup();
553 for (int i=0; i<DEFAULT_PROPERTY_COUNT; ++i)
555 (*mDefaultPropertyLookup)[DEFAULT_PROPERTY_NAMES[i]] = i;
558 DALI_ASSERT_DEBUG( NULL != mDefaultPropertyLookup );
560 // Look for name in default properties
561 DefaultPropertyLookup::const_iterator result = mDefaultPropertyLookup->find( name );
562 if ( mDefaultPropertyLookup->end() != result )
564 index = result->second;
570 bool ShaderEffect::IsDefaultPropertyWritable(Property::Index index) const
575 bool ShaderEffect::IsDefaultPropertyAnimatable(Property::Index index) const
580 bool ShaderEffect::IsDefaultPropertyAConstraintInput( Property::Index index ) const
585 Property::Type ShaderEffect::GetDefaultPropertyType(Property::Index index) const
587 if( index < DEFAULT_PROPERTY_COUNT )
589 return DEFAULT_PROPERTY_TYPES[index];
593 // index out of range...return Property::NONE
594 return Property::NONE;
598 void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
602 case Dali::ShaderEffect::GRID_DENSITY:
604 SetGridDensityMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, propertyValue.Get<float>() );
608 case Dali::ShaderEffect::IMAGE:
610 Dali::Image img(Scripting::NewImage( propertyValue ));
613 SetEffectImage( img );
617 DALI_LOG_WARNING("Cannot create image from property value for ShaderEffect image\n");
622 case Dali::ShaderEffect::PROGRAM:
624 std::string vertexPrefix = GetShader("vertex-prefix", propertyValue);
625 std::string fragmentPrefix = GetShader("fragment-prefix", propertyValue);
626 std::string vertex = GetShader("vertex", propertyValue);
627 std::string fragment = GetShader("fragment", propertyValue);
629 GeometryType geometryType = GEOMETRY_TYPE_IMAGE;
631 if( propertyValue.HasKey("geometry-type") )
633 Property::Value geometryValue = propertyValue.GetValue("geometry-type");
634 DALI_ASSERT_ALWAYS(geometryValue.GetType() == Property::STRING && "Geometry type is not a string" );
636 std::string s = geometryValue.Get<std::string>();
637 if(s == "GEOMETRY_TYPE_IMAGE")
639 geometryType = GEOMETRY_TYPE_IMAGE;
641 else if (s == "GEOMETRY_TYPE_TEXT")
643 geometryType = GEOMETRY_TYPE_TEXT;
645 else if( s == "GEOMETRY_TYPE_MESH")
647 geometryType = GEOMETRY_TYPE_MESH;
649 else if( s == "GEOMETRY_TYPE_TEXTURED_MESH")
651 geometryType = GEOMETRY_TYPE_TEXTURED_MESH;
655 DALI_ASSERT_ALWAYS(!"Geometry type unknown" );
658 SetShaderProgram( vertexPrefix, vertex, fragmentPrefix, fragment, geometryType, ShaderEffectPtr(this) );
662 case Dali::ShaderEffect::GEOMETRY_HINTS:
664 Dali::ShaderEffect::GeometryHints hint = Dali::ShaderEffect::HINT_NONE;
665 Property::Value geometryHintsValue = propertyValue.GetValue("geometry-hints");
667 std::string s = geometryHintsValue.Get<std::string>();
670 hint = Dali::ShaderEffect::HINT_NONE;
672 else if(s == "HINT_GRID_X")
674 hint = Dali::ShaderEffect::HINT_GRID_X;
676 else if(s == "HINT_GRID_Y")
678 hint = Dali::ShaderEffect::HINT_GRID_Y;
680 else if(s == "HINT_GRID")
682 hint = Dali::ShaderEffect::HINT_GRID;
684 else if(s == "HINT_DEPTH_BUFFER")
686 hint = Dali::ShaderEffect::HINT_DEPTH_BUFFER;
688 else if(s == "HINT_BLENDING")
690 hint = Dali::ShaderEffect::HINT_BLENDING;
694 DALI_ASSERT_ALWAYS(!"Geometry hint unknown" );
697 SetHintsMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, hint );
704 DALI_ASSERT_ALWAYS(false && "ShaderEffect property enumeration out of range"); // should not come here
710 Property::Value ShaderEffect::GetDefaultProperty(Property::Index /*index*/) const
712 // none of our properties are readable so return empty
713 return Property::Value();
716 void ShaderEffect::InstallSceneObjectProperty( PropertyBase& newProperty, const std::string& name, unsigned int index )
718 // Warning - the property is added to the Shader object in the Update thread and the meta-data is added in the Render thread (through a secondary message)
720 // mSceneObject is being used in a separate thread; queue a message to add the property
721 InstallCustomPropertyMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, newProperty ); // Message takes ownership
723 // mSceneObject requires metadata for each custom property (uniform)
724 UniformMeta* meta = UniformMeta::New( name, newProperty, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
725 // mSceneObject is being used in a separate thread; queue a message to add the property
726 InstallUniformMetaMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, *meta ); // Message takes ownership
728 // Add entry to the metadata lookup
729 mCustomMetadata[index] = meta;
732 const SceneGraph::PropertyOwner* ShaderEffect::GetSceneObject() const
737 const PropertyBase* ShaderEffect::GetSceneObjectAnimatableProperty( Property::Index index ) const
739 CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
741 DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "Property index is invalid" );
743 DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "shader effect has only animatable properties" );
745 return dynamic_cast<const PropertyBase*>( entry->second.GetSceneGraphProperty() );
748 const PropertyInputImpl* ShaderEffect::GetSceneObjectInputProperty( Property::Index index ) const
750 CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
752 DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "Property index is invalid" );
754 DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "shader effect has only animatable properties" );
756 return entry->second.GetSceneGraphProperty();
759 } // namespace Internal