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/actors/image-actor-impl.h>
22 #include <cstring> // for strcmp
25 #include <dali/public-api/animation/constraints.h> // for EqualToConstraint
26 #include <dali/public-api/object/type-registry.h>
27 #include <dali/devel-api/scripting/scripting.h>
28 #include <dali/internal/event/animation/constraint-impl.h>
29 #include <dali/internal/event/common/property-helper.h>
30 #include <dali/internal/event/effects/shader-effect-impl.h>
31 #include <dali/internal/event/images/image-connector.h>
32 #include <dali/internal/event/images/nine-patch-image-impl.h>
45 // Name Type writable animatable constraint-input enum for index-checking
46 DALI_PROPERTY_TABLE_BEGIN
47 DALI_PROPERTY( "pixelArea", RECTANGLE, true, false, true, Dali::ImageActor::Property::PIXEL_AREA )
48 DALI_PROPERTY( "style", STRING, true, false, true, Dali::ImageActor::Property::STYLE )
49 DALI_PROPERTY( "border", VECTOR4, true, false, true, Dali::ImageActor::Property::BORDER )
50 DALI_PROPERTY( "image", MAP, true, false, false, Dali::ImageActor::Property::IMAGE )
51 DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
55 return Dali::ImageActor::New();
58 TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::Actor ), Create );
63 Vector2 mTextureCoord;
66 GeometryPtr CreateQuadGeometry( const Vector2& size, int imageWidth, int imageHeight, const Dali::ImageActor::PixelArea& pixelArea )
68 const float halfWidth = size.width * 0.5f;
69 const float halfHeight = size.height * 0.5f;
70 GridVertex quadVertexData[4] =
72 { Vector3( -halfWidth, -halfHeight, 0.f ), Vector2( ( pixelArea.x ) / (float)imageWidth, ( pixelArea.y ) / (float)imageHeight ) },
73 { Vector3( -halfWidth, halfHeight, 0.f ), Vector2( ( pixelArea.x ) / (float)imageWidth, ( pixelArea.y + pixelArea.height ) / (float)imageHeight ) },
74 { Vector3( halfWidth, -halfHeight, 0.f ), Vector2( ( pixelArea.x + pixelArea.width ) / (float)imageWidth, ( pixelArea.y ) / (float)imageHeight ) },
75 { Vector3( halfWidth, halfHeight, 0.f ), Vector2( ( pixelArea.x + pixelArea.width ) / (float)imageWidth, ( pixelArea.y + pixelArea.height ) / (float)imageHeight ) }
78 Property::Map quadVertexFormat;
79 quadVertexFormat["aPosition"] = Property::VECTOR3;
80 quadVertexFormat["aTexCoord"] = Property::VECTOR2;
81 PropertyBufferPtr quadVertices = PropertyBuffer::New();
82 quadVertices->SetFormat( quadVertexFormat );
83 quadVertices->SetSize( 4 );
84 quadVertices->SetData(quadVertexData);
86 // Create the geometry object
87 GeometryPtr geometry = Geometry::New();
88 geometry->AddVertexBuffer( *quadVertices );
89 geometry->SetGeometryType( Dali::Geometry::TRIANGLE_STRIP );
94 GeometryPtr CreateGridGeometry( const Vector2& size, unsigned int gridWidth, unsigned int gridHeight, int imageWidth, int imageHeight, const Dali::ImageActor::PixelArea& pixelArea )
97 std::vector< GridVertex > vertices;
98 vertices.reserve( ( gridWidth + 1 ) * ( gridHeight + 1 ) );
100 for( unsigned int y = 0u; y < gridHeight + 1; ++y )
102 float yPos = (float)y / gridHeight;
103 for( unsigned int x = 0u; x < gridWidth + 1; ++x )
105 float xPos = (float)x / gridWidth;
106 GridVertex vertex = {
107 Vector3( size.width * ( xPos - 0.5f ), size.height * ( yPos - 0.5f ), 0.0f ),
108 Vector2( ( pixelArea.x + pixelArea.width * xPos ) / (float)imageWidth,
109 ( pixelArea.y + pixelArea.height * yPos ) / (float)imageHeight )
111 vertices.push_back( vertex );
116 Vector< unsigned int > indices;
117 indices.Reserve( ( gridWidth + 2 ) * gridHeight * 2 - 2);
119 for( unsigned int row = 0u; row < gridHeight; ++row )
121 unsigned int rowStartIndex = row*(gridWidth+1u);
122 unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u;
124 if( row != 0u ) // degenerate index on non-first row
126 indices.PushBack( rowStartIndex );
129 for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip
131 indices.PushBack( rowStartIndex + column);
132 indices.PushBack( nextRowStartIndex + column);
135 if( row != gridHeight-1u ) // degenerate index on non-last row
137 indices.PushBack( nextRowStartIndex + gridWidth );
142 Property::Map vertexFormat;
143 vertexFormat[ "aPosition" ] = Property::VECTOR3;
144 vertexFormat[ "aTexCoord" ] = Property::VECTOR2;
145 PropertyBufferPtr vertexPropertyBuffer = PropertyBuffer::New();
146 vertexPropertyBuffer->SetFormat( vertexFormat );
147 vertexPropertyBuffer->SetSize( vertices.size() );
148 if( vertices.size() > 0 )
150 vertexPropertyBuffer->SetData( &vertices[ 0 ] );
153 Property::Map indexFormat;
154 indexFormat[ "indices" ] = Property::INTEGER;
155 PropertyBufferPtr indexPropertyBuffer = PropertyBuffer::New();
156 indexPropertyBuffer->SetFormat( indexFormat );
157 indexPropertyBuffer->SetSize( indices.Size() );
158 if( indices.Size() > 0 )
160 indexPropertyBuffer->SetData( &indices[ 0 ] );
163 // Create the geometry object
164 GeometryPtr geometry = Geometry::New();
165 geometry->AddVertexBuffer( *vertexPropertyBuffer );
166 geometry->SetIndexBuffer( *indexPropertyBuffer );
167 geometry->SetGeometryType( Dali::Geometry::TRIANGLE_STRIP );
174 template< typename T>
175 ConstraintBase* CreateEqualConstraint(Object& target, Property::Index index, Internal::SourceContainer& sources )
177 typedef typename Dali::Internal::PropertyConstraintPtr< T >::Type PropertyConstraintPtrType;
179 CallbackBase* callback = new Dali::Constraint::Function< T >( EqualToConstraint() );
180 PropertyConstraintPtrType funcPtr( new Internal::PropertyConstraint< T >( reinterpret_cast< Dali::Constraint::Function< T >* >( callback ) ) );
182 return Internal::Constraint< T >::New( target, index, sources, funcPtr );
185 const char* VERTEX_SHADER = DALI_COMPOSE_SHADER(
186 attribute mediump vec3 aPosition;\n
187 attribute mediump vec2 aTexCoord;\n
188 varying mediump vec2 vTexCoord;\n
189 uniform mediump mat4 uMvpMatrix;\n
190 uniform mediump vec3 uSize;\n
191 uniform mediump vec4 uTextureRect;\n
195 mediump vec4 vertexPosition = vec4(aPosition, 1.0);\n
196 vertexPosition = uMvpMatrix * vertexPosition;\n
198 vTexCoord = aTexCoord;\n
199 gl_Position = vertexPosition;\n
203 const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER(
204 varying mediump vec2 vTexCoord;\n
205 uniform sampler2D sTexture;\n
206 uniform lowp vec4 uColor;\n
210 gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
214 const size_t INVALID_TEXTURE_ID = (size_t)-1;
215 const int INVALID_RENDERER_ID = -1;
216 const unsigned int MAXIMUM_GRID_SIZE = 2048;
219 ImageActorPtr ImageActor::New()
221 ImageActorPtr actor( new ImageActor );
223 // Second-phase construction of base class
226 //Create the renderer
227 actor->mRenderer = Renderer::New();
229 GeometryPtr quad = CreateQuadGeometry( Vector2::ONE, 1, 1, PixelArea() );
230 actor->mRenderer->SetGeometry( *quad );
232 ShaderPtr shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, Dali::Shader::HINT_NONE );
233 MaterialPtr material = Material::New();
234 material->SetShader( *shader );
235 actor->mRenderer->SetMaterial( *material );
240 void ImageActor::OnInitialize()
242 // TODO: Remove this, at the moment its needed for size negotiation to work
243 SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
246 void ImageActor::SetImage( ImagePtr& image )
250 if( mRendererIndex != INVALID_RENDERER_ID )
252 RemoveRenderer( mRendererIndex );
253 mRendererIndex = INVALID_RENDERER_ID;
258 SamplerPtr sampler = Sampler::New();
259 sampler->SetFilterMode( mMinFilter, mMagFilter );
261 mTextureIndex = mRenderer->GetMaterial()->AddTexture( image, "sTexture", sampler );
263 if( mRendererIndex == INVALID_RENDERER_ID )
265 mRendererIndex = AddRenderer( *mRenderer );
268 if( !mIsPixelAreaSet )
270 mPixelArea = PixelArea( 0, 0, image->GetWidth(), image->GetHeight() );
277 ImagePtr ImageActor::GetImage() const
279 return mRenderer->GetMaterial()->GetTexture( mTextureIndex );
282 void ImageActor::SetPixelArea( const PixelArea& pixelArea )
284 mPixelArea = pixelArea;
285 mIsPixelAreaSet = true;
290 const ImageActor::PixelArea& ImageActor::GetPixelArea() const
295 bool ImageActor::IsPixelAreaSet() const
297 return mIsPixelAreaSet;
300 void ImageActor::ClearPixelArea()
302 mIsPixelAreaSet = false;
306 ImagePtr image = GetImage();
309 imageWidth = image->GetWidth();
310 imageHeight = image->GetHeight();
313 mPixelArea = PixelArea( 0, 0, imageWidth, imageHeight );
318 ImageActor::ImageActor()
319 : Actor( Actor::BASIC ),
320 mRendererIndex( INVALID_RENDERER_ID ),
321 mTextureIndex( INVALID_TEXTURE_ID ),
322 mEffectTextureIndex( INVALID_TEXTURE_ID ),
323 mMinFilter( FilterMode::DEFAULT ),
324 mMagFilter( FilterMode::DEFAULT ),
325 mIsPixelAreaSet( false )
329 ImageActor::~ImageActor()
333 Vector3 ImageActor::GetNaturalSize() const
335 Vector2 naturalSize( CalculateNaturalSize() );
336 return Vector3( naturalSize.width, naturalSize.height, 0.f );
339 Vector2 ImageActor::CalculateNaturalSize() const
341 // if no image then natural size is 0
342 Vector2 size( 0.0f, 0.0f );
344 ImagePtr image = GetImage();
347 if( IsPixelAreaSet() )
349 PixelArea area(GetPixelArea());
350 size.width = area.width;
351 size.height = area.height;
355 size = image->GetNaturalSize();
362 void ImageActor::OnRelayout( const Vector2& size, RelayoutContainer& container )
367 ImagePtr image = GetImage();
371 imageWidth = image->GetWidth();
372 imageHeight = image->GetHeight();
375 unsigned int gridWidth = 1;
376 unsigned int gridHeight = 1;
379 Dali::ShaderEffect::GeometryHints hints = mShaderEffect->GetGeometryHints();
380 Property::Value gridDensityValue = mShaderEffect->GetDefaultProperty( Dali::ShaderEffect::Property::GRID_DENSITY );
381 int gridDensity = Dali::ShaderEffect::DEFAULT_GRID_DENSITY;
382 gridDensityValue.Get( gridDensity );
384 if( ( hints & Dali::ShaderEffect::HINT_GRID_X ) )
386 gridWidth = size.width / gridDensity;
388 if( ( hints & Dali::ShaderEffect::HINT_GRID_Y ) )
390 gridHeight = size.height / gridDensity;
393 //limit the grid size
394 gridWidth = std::min( MAXIMUM_GRID_SIZE, gridWidth );
395 gridHeight = std::min( MAXIMUM_GRID_SIZE, gridHeight );
398 GeometryPtr quad = gridWidth <= 1 && gridHeight <= 1 ?
399 CreateQuadGeometry( size, imageWidth, imageHeight, mPixelArea ) :
400 CreateGridGeometry( size, gridWidth, gridHeight, imageWidth, imageHeight, mPixelArea );
402 mRenderer->SetGeometry( *quad );
404 Vector4 textureRect( 0.f, 0.f, 1.f, 1.f );
405 if( mIsPixelAreaSet )
407 ImagePtr image = GetImage();
410 int imageWidth = image->GetWidth();
411 int imageHeight = image->GetHeight();;
413 const float uScale = 1.0f / float(imageWidth);
414 const float vScale = 1.0f / float(imageHeight);
415 const float x = uScale * float(mPixelArea.x);
416 const float y = vScale * float(mPixelArea.y);
417 const float width = uScale * float(mPixelArea.width);
418 const float height = vScale * float(mPixelArea.height);
425 textureRect.z = x + width;
426 textureRect.w = y + height;
430 Material* material = mRenderer->GetMaterial();
431 Property::Index index = material->GetPropertyIndex( "sTextureRect" );
432 if( index != Property::INVALID_INDEX )
434 material->SetProperty( index, textureRect );
438 material->RegisterProperty( "sTextureRect", textureRect );
442 unsigned int ImageActor::GetDefaultPropertyCount() const
444 return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
447 void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
449 Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
451 indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
453 int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
454 for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
456 indices.PushBack( index );
460 bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
462 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
464 return Actor::IsDefaultPropertyWritable(index);
467 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
468 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
470 return DEFAULT_PROPERTY_DETAILS[ index ].writable;
476 bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
478 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
480 return Actor::IsDefaultPropertyAnimatable( index );
483 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
484 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
486 return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
492 bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
494 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
496 return Actor::IsDefaultPropertyAConstraintInput( index );
499 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
500 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
502 return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
508 Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
510 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
512 return Actor::GetDefaultPropertyType( index );
515 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
516 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
518 return DEFAULT_PROPERTY_DETAILS[index].type;
521 // index out-of-bounds
522 return Property::NONE;
525 const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
527 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
529 return Actor::GetDefaultPropertyName(index);
532 index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
533 if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
535 return DEFAULT_PROPERTY_DETAILS[index].name;
538 // index out-of-bounds
542 Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
544 Property::Index index = Property::INVALID_INDEX;
546 // Look for name in default properties
547 for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
549 const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
550 if( 0 == strcmp( name.c_str(), property->name ) ) // Don't want to convert rhs to string
552 index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
557 // If not found, check in base class
558 if( Property::INVALID_INDEX == index )
560 index = Actor::GetDefaultPropertyIndex( name );
565 void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
567 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
569 Actor::SetDefaultProperty( index, propertyValue );
575 case Dali::ImageActor::Property::PIXEL_AREA:
577 SetPixelArea(propertyValue.Get<Rect<int> >());
580 case Dali::ImageActor::Property::STYLE:
585 case Dali::ImageActor::Property::BORDER:
590 case Dali::ImageActor::Property::IMAGE:
592 Dali::Image img = Scripting::NewImage( propertyValue );
595 ImagePtr image( &GetImplementation(img) );
600 DALI_LOG_WARNING("Cannot create image from property value\n");
606 DALI_LOG_WARNING("Unknown property (%d)\n", index);
614 Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
617 if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
619 ret = Actor::GetDefaultProperty( index );
625 case Dali::ImageActor::Property::PIXEL_AREA:
627 Rect<int> r = GetPixelArea();
631 case Dali::ImageActor::Property::STYLE:
636 case Dali::ImageActor::Property::BORDER:
641 case Dali::ImageActor::Property::IMAGE:
644 Scripting::CreatePropertyMap( Dali::Image( GetImage().Get() ), map );
645 ret = Property::Value( map );
650 DALI_LOG_WARNING( "Unknown property (%d)\n", index );
659 void ImageActor::SetSortModifier(float modifier)
661 mRenderer->SetDepthIndex( modifier );
664 float ImageActor::GetSortModifier() const
666 return mRenderer->GetDepthIndex();
669 void ImageActor::SetCullFace(CullFaceMode mode)
671 mRenderer->GetMaterial()->SetFaceCullingMode( static_cast< Dali::Material::FaceCullingMode >( mode ) );
674 CullFaceMode ImageActor::GetCullFace() const
676 return static_cast< CullFaceMode >( mRenderer->GetMaterial()->GetFaceCullingMode() );
679 void ImageActor::SetBlendMode( BlendingMode::Type mode )
681 mRenderer->GetMaterial()->SetBlendMode( mode );
684 BlendingMode::Type ImageActor::GetBlendMode() const
686 return mRenderer->GetMaterial()->GetBlendMode();
689 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba )
691 mRenderer->GetMaterial()->SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
694 void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb,
695 BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
697 mRenderer->GetMaterial()->SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
700 void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb, BlendingFactor::Type& destFactorRgb,
701 BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
703 mRenderer->GetMaterial()->GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
706 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
708 mRenderer->GetMaterial()->SetBlendEquation( equationRgba, equationRgba );
711 void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
713 mRenderer->GetMaterial()->SetBlendEquation( equationRgb, equationAlpha );
716 void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
718 mRenderer->GetMaterial()->GetBlendEquation( equationRgb, equationAlpha );
721 void ImageActor::SetBlendColor( const Vector4& color )
724 mRenderer->GetMaterial()->SetBlendColor( mBlendColor );
727 const Vector4& ImageActor::GetBlendColor() const
732 void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
734 mMinFilter = minFilter;
735 mMagFilter = magFilter;
737 if( mTextureIndex != INVALID_TEXTURE_ID )
739 SamplerPtr sampler = Sampler::New();
740 sampler->SetFilterMode( minFilter, magFilter );
742 mRenderer->GetMaterial()->SetTextureSampler( mTextureIndex, sampler.Get() );
746 void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
748 minFilter = mMinFilter;
749 magFilter = mMagFilter;
752 void ImageActor::SetShaderEffect( ShaderEffect& effect )
756 mShaderEffect->Disconnect( this );
759 mShaderEffect = ShaderEffectPtr( &effect );
760 effect.Connect( this );
762 Dali::ShaderEffect::GeometryHints hints = effect.GetGeometryHints();
764 int shaderHints = Dali::Shader::HINT_NONE;
766 if( hints & Dali::ShaderEffect::HINT_DEPTH_BUFFER )
768 shaderHints |= Dali::Shader::HINT_REQUIRES_SELF_DEPTH_TEST;
770 if( hints & Dali::ShaderEffect::HINT_BLENDING )
772 shaderHints |= Dali::Shader::HINT_OUTPUT_IS_TRANSPARENT;
774 if( !(hints & Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY) )
776 shaderHints |= Dali::Shader::HINT_MODIFIES_GEOMETRY;
779 ShaderPtr shader = Shader::New( effect.GetVertexShader(), effect.GetFragmentShader(), static_cast< Dali::Shader::ShaderHints >( shaderHints ) );
780 mRenderer->GetMaterial()->SetShader( *shader );
782 //get the uniforms and apply them to the renderer
783 const ShaderEffect::UniformArray& uniforms = mShaderEffect->GetUniforms();
784 for( ShaderEffect::UniformArray::const_iterator it = uniforms.begin(); it != uniforms.end(); ++it )
786 const ShaderEffect::Uniform& uniform = *it;
787 EffectUniformUpdated( uniform );
790 if( mShaderEffect->GetEffectImage() )
792 EffectImageUpdated();
796 void ImageActor::EffectUniformUpdated( const ShaderEffect::Uniform& uniform )
803 Shader* shader = mRenderer->GetMaterial()->GetShader();
805 Property::Index index = shader->GetPropertyIndex( uniform.mName );
806 if( index == Property::INVALID_INDEX )
808 index = shader->RegisterProperty( uniform.mName, uniform.mValue );
810 //Constrain the shader's uniform properties to the ShaderEffect properties
811 Internal::ConstraintBase* constraint = NULL;
812 Internal::SourceContainer sources;
814 switch( uniform.mValue.GetType() )
816 case Property::INTEGER:
817 case Property::FLOAT:
819 constraint = CreateEqualConstraint< float >(*shader, index, sources );
822 case Property::VECTOR2:
824 constraint = CreateEqualConstraint< Vector2 >(*shader, index, sources );
827 case Property::VECTOR3:
829 constraint = CreateEqualConstraint< Vector3 >(*shader, index, sources );
832 case Property::VECTOR4:
834 constraint = CreateEqualConstraint< Vector4 >(*shader, index, sources );
837 case Property::MATRIX3:
839 constraint = CreateEqualConstraint< Matrix3 >(*shader, index, sources );
842 case Property::MATRIX:
844 constraint = CreateEqualConstraint< Matrix >(*shader, index, sources );
847 case Property::BOOLEAN:
848 case Property::ARRAY:
849 case Property::ROTATION:
850 case Property::STRING:
851 case Property::RECTANGLE:
858 //constrain the renderers property to the ShaderEffect
862 source.sourceType = OBJECT_PROPERTY;
863 source.propertyIndex = uniform.mIndex;
864 source.object = mShaderEffect.Get();
866 constraint->AddSource( source );
872 shader->SetProperty( index, uniform.mValue );
876 ShaderEffectPtr ImageActor::GetShaderEffect() const
878 return mShaderEffect;
881 void ImageActor::RemoveShaderEffect()
883 //if we previously had a subdivided grid then we need to reset the geometry as well
886 mShaderEffect->Disconnect( this );
888 Dali::ShaderEffect::GeometryHints hints = mShaderEffect->GetGeometryHints();
889 if( ( hints & Dali::ShaderEffect::HINT_GRID_X ) ||
890 ( hints & Dali::ShaderEffect::HINT_GRID_Y ) )
896 ShaderPtr shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, Dali::Shader::HINT_NONE );
897 mRenderer->GetMaterial()->SetShader( *shader );
898 mShaderEffect.Reset();
901 void ImageActor::EffectImageUpdated()
905 Dali::Image effectImage = mShaderEffect->GetEffectImage();
908 Image& effectImageImpl = GetImplementation( effectImage );
910 if( mEffectTextureIndex == INVALID_TEXTURE_ID )
912 mEffectTextureIndex = mRenderer->GetMaterial()->AddTexture( &effectImageImpl, "sEffect", NULL );
916 mRenderer->GetMaterial()->SetTextureImage( mEffectTextureIndex, &effectImageImpl );
921 if( mEffectTextureIndex != INVALID_TEXTURE_ID )
923 mRenderer->GetMaterial()->RemoveTexture( mEffectTextureIndex );
925 mEffectTextureIndex = INVALID_TEXTURE_ID;
928 //ensure that the sEffectRect uniform is set
929 Shader* shader = mRenderer->GetMaterial()->GetShader();
930 Property::Index index = shader->GetPropertyIndex( "sEffectRect" );
931 if( index == Property::INVALID_INDEX )
933 shader->RegisterProperty( "sEffectRect", Vector4( 0.f, 0.f, 1.f, 1.f) );
938 } // namespace Internal