#include <sstream>
#include <dali-toolkit-test-suite-utils.h>
#include <dali/integration-api/events/pan-gesture-event.h>
+#include <dali/public-api/images/buffer-image.h>
#include <dali-toolkit/public-api/controls/page-turn-view/page-factory.h>
#include <dali-toolkit/public-api/controls/page-turn-view/page-turn-landscape-view.h>
#include <dali-toolkit/public-api/controls/page-turn-view/page-turn-portrait-view.h>
TestPageFactory(ToolkitTestApplication& application)
: mApplication( application )
{
- mSourceActors.resize(TOTAL_PAGE_NUMBER);
mTotalPageNumber = TOTAL_PAGE_NUMBER;
}
}
/**
- * Create an image actor to represent a page.
+ * Create an image to represent a page content.
* @param[in] pageId The ID of the page to create.
- * @return An image actor, or an uninitialized pointer if the ID is out of range.
+ * @return An image, or an empty handle if the ID is out of range.
*/
- virtual Actor NewPage( unsigned int pageId )
+ virtual Image NewPage( unsigned int pageId )
{
- if(!mSourceActors[pageId])
- {
- Actor actor = CreateSolidColorImageActor(mApplication, Color::BLUE,IMAGE_WIDTH,IMAGE_HEIGHT);
- actor.SetName( static_cast<std::ostringstream*>( &(std::ostringstream() << pageId) )->str() );
-
- actor.SetParentOrigin( ParentOrigin::CENTER );
- actor.SetAnchorPoint( AnchorPoint::CENTER );
-
- ImageActor backPageActor = CreateSolidColorImageActor(mApplication, Color::BLUE,IMAGE_WIDTH,IMAGE_HEIGHT);
- backPageActor.SetParentOrigin( ParentOrigin::CENTER );
- backPageActor.SetAnchorPoint( AnchorPoint::CENTER );
- actor.Add( backPageActor );
-
- mSourceActors[pageId] = actor;
- }
-
- return mSourceActors[pageId];
- }
-
- void DeletePage( unsigned int pageId )
- {
- mSourceActors.erase( mSourceActors.begin() + pageId );
- mTotalPageNumber--;
+ return BufferImage::WHITE();
}
private:
ToolkitTestApplication& mApplication;
- std::vector<Actor> mSourceActors;
unsigned int mTotalPageNumber;
};
DALI_TEST_EQUALS( landscapeView.GetProperty(PageTurnView::Property::CURRENT_PAGE_ID).Get<int>(), 0, TEST_LOCATION );
END_TEST;
}
+
+int UtcDaliPageImageFactoryGetExtention(void)
+{
+ ToolkitTestApplication application;
+ TestPageFactory factory(application);
+ DALI_TEST_CHECK( factory.GetExtension() == NULL );
+ END_TEST;
+}
*
*/
-// EXTERNAL INCLUDES
-#include <dali/public-api/shader-effects/shader-effect.h>
+#define DALI_COMPOSE_SHADER(STR) #STR
namespace Dali
{
*
* Animatable/Constrainable uniforms:
* "uSpineShadowParameter" - The two parameters are the major&minor radius (in pixels) to form an ellipse shape. The top-left
- * quarter of this ellipse is used to calculate spine normal for simulating shadow
- * "uIsBackImageVisible" - Set whether the current page is with its backside visible. Need to pass the parameter as true for
- * the page which is turned over but still visible in Landscape
- * "uPageWidth" - The page width of the PageTurnBookSpineEffect
+ * quarter of this ellipse is used to calculate spine normal for simulating shadow *
+ * "uTextureWidth" - 1.0 for single sided page,
+ * 2.0 for double sided image which has left half part as page front side and right half part as page back side.
*
- * @return A handle to a newly allocated ShaderEffect
+ * @return The newly created Property::Map with the page turn book spine effect
**/
-inline ShaderEffect CreatePageTurnBookSpineEffect()
+inline Property::Map CreatePageTurnBookSpineEffect()
{
+ const char* vertexSource = DALI_COMPOSE_SHADER(
+ precision mediump float;\n
+ attribute mediump vec2 aPosition;\n
+ uniform mediump mat4 uMvpMatrix;\n
+ uniform vec3 uSize;\n
+ uniform float uTextureWidth;\n
+ varying vec2 vTexCoord;\n
+ void main()\n
+ {\n
+ mediump vec4 vertexPosition = vec4(aPosition*uSize.xy, 0.0, 1.0);\n
+ gl_Position = uMvpMatrix * vertexPosition;\n
+ vTexCoord = aPosition + vec2(0.5);\n
+ vTexCoord.x /= uTextureWidth;
+ }\n);
+
// the simplified version of the fragment shader of page turn effect
- std::string fragmentSource = DALI_COMPOSE_SHADER(
+ const char* fragmentSource = DALI_COMPOSE_SHADER(
precision mediump float;\n
- uniform float uIsBackImageVisible;\n
- uniform float uPageWidth;\n
+ varying mediump vec2 vTexCoord;\n
+ uniform vec3 uSize;\n
uniform vec2 uSpineShadowParameter;\n
+ uniform sampler2D sTexture;\n
+ uniform lowp vec4 uColor;\n
+
void main()\n
{\n
- // flip the image horizontally by changing the x component of the texture coordinate
- if( uIsBackImageVisible == 1.0 )\n
- gl_FragColor = texture2D( sTexture, vec2( sTextureRect.p+sTextureRect.s-vTexCoord.x, vTexCoord.y ) ) * uColor; \n
- else\n
- gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
- // display book spine, a stripe of shadowed texture
- float pixelPos = (vTexCoord.x-sTextureRect.s)*uPageWidth; \n
- if(pixelPos < uSpineShadowParameter.x) \n
+ if( gl_FrontFacing )\n // display front side
+ {\n
+ gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n
+ }\n
+ else\n // display back side, flip the image horizontally by changing the x component of the texture coordinate
+ {\n
+ gl_FragColor = texture2D( sTexture, vec2( 1.0 - vTexCoord.x, vTexCoord.y ) ) * uColor;\n
+ }\n
+ // display book spine, a stripe of shadowed texture
+ float pixelPos = vTexCoord.x * uSize.x;\n
+ if( pixelPos < uSpineShadowParameter.x )\n
{\n
float x = pixelPos - uSpineShadowParameter.x;\n
float y = sqrt( uSpineShadowParameter.x*uSpineShadowParameter.x - x*x );\n
vec2 spineNormal = normalize(vec2(uSpineShadowParameter.y*x/uSpineShadowParameter.x, y));\n
gl_FragColor.rgb *= spineNormal.y; \n
- }
+ }\n
} );
- const Vector2 DEFAULT_SPINE_SHADOW_PARAMETER(50.0f, 20.0f);
-
- ShaderEffect shaderEffect = ShaderEffect::New( "", fragmentSource );
+ Property::Map map;
- shaderEffect.SetUniform( "uIsBackImageVisible", -1.f );
- shaderEffect.SetUniform( "uSpineShadowParameter", DEFAULT_SPINE_SHADOW_PARAMETER );
+ Property::Map customShader;
- float defaultPageWidth = Dali::Stage::GetCurrent().GetSize().x;
- shaderEffect.SetUniform( "uPageWidth", defaultPageWidth );
+ customShader[ "vertexShader" ] = vertexSource;
+ customShader[ "fragmentShader" ] = fragmentSource;
- return shaderEffect;
+ map[ "shader" ] = customShader;
+ return map;
}
} //namespace Internal
*
*/
+//EXTERNAL INCLUDES
+#include <string.h>
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/object/property-map.h>
+
+//INTERNAL INCLUDES
#include <dali-toolkit/internal/controls/page-turn-view/page-turn-effect.h>
-#include <dali/public-api/math/matrix.h>
using namespace Dali;
using namespace Dali::Toolkit;
-void CommonParametersConstraint( Dali::Matrix& current, const PropertyInputContainer& inputs )
+namespace
{
- const Vector2& originalCenter = inputs[0]->GetVector2();
- Vector2 currentCenter = inputs[1]->GetVector2();
- const Vector2& pageSize = inputs[2]->GetVector2();
+#define DALI_COMPOSE_SHADER(STR) #STR
+const char * const PROPERTY_COMMON_PARAMETERS( "uCommonParameters" );
+const char * const PROPERTY_ORIGINAL_CENTER( "originalCenter" );
+const char * const PROPERTY_CURRENT_CENTER( "currentCenter" );
+}
- // calculate the curve direction and the vanishing point
- // here, the vanishing point is the intersection of spine with the line passing through original center and vertical to curve direction
- Vector2 curveDirection( currentCenter - originalCenter );
- curveDirection.Normalize();
- if( fabs(curveDirection.y) < 0.01f) // eliminate the possibility of division by zero in the next step
- {
- curveDirection.y = 0.01f;
- }
- float vanishingPointY = originalCenter.y + curveDirection.x * originalCenter.x / curveDirection.y;
+/**
+ * This constraint updates the common parameter values used by every vertex.
+ * By using constraint, they are calculate once in CPU then pass into the vertex shader as uniforms
+ */
+struct CommonParametersConstraint
+{
+ CommonParametersConstraint( float pageHeight )
+ : mPageHeight( pageHeight )
+ {}
- float curveEndY, cosTheta ,sinTheta ,translateX, translateY;
- // when the vanishing point is very far away, make it infinitely, in this case, the page bent horizontally
- const float THRESHOLD(20.0);
- if( fabs(vanishingPointY-pageSize.y*0.5f) >= pageSize.y*THRESHOLD )
+ void operator()( Dali::Matrix& current, const PropertyInputContainer& inputs )
{
- curveDirection = Vector2(-1.f,0.f);
- currentCenter.y = originalCenter.y;
+ const Vector2& originalCenter = inputs[0]->GetVector2();
+ Vector2 currentCenter = inputs[1]->GetVector2();
- curveEndY = originalCenter.y;
- cosTheta = 1.f;
- sinTheta = 0.f;
- translateX = currentCenter.x - originalCenter.x;
- translateY = vanishingPointY;
- }
- else
- {
- curveEndY = currentCenter.y - curveDirection.y * (currentCenter.x/curveDirection.x) ;
- Vector2 v1( currentCenter.x, currentCenter.y - vanishingPointY );
- v1.Normalize();
- Vector2 v2( originalCenter.x, originalCenter.y - vanishingPointY );
- v2.Normalize();
- cosTheta = v1.x*v2.x + v1.y*v2.y;
- sinTheta = ( vanishingPointY > pageSize.y*0.5f ) ? sqrt(1.0-cosTheta*cosTheta) : -sqrt(1.0-cosTheta*cosTheta);
- translateX = currentCenter.x - cosTheta*originalCenter.x - sinTheta*( originalCenter.y-vanishingPointY );
- translateY = currentCenter.y + sinTheta*originalCenter.x - cosTheta*( originalCenter.y-vanishingPointY );
- }
+ // calculate the curve direction and the vanishing point
+ // here, the vanishing point is the intersection of spine with the line passing through original center and vertical to curve direction
+ Vector2 curveDirection( currentCenter - originalCenter );
+ curveDirection.Normalize();
+ if( fabs(curveDirection.y) < 0.01f) // eliminate the possibility of division by zero in the next step
+ {
+ curveDirection.y = 0.01f;
+ }
+ float vanishingPointY = originalCenter.y + curveDirection.x * originalCenter.x / curveDirection.y;
- float originalLength = fabs(originalCenter.x/curveDirection.x);
- float currentLength = fabs(currentCenter.x/curveDirection.x);
- float curveHeight = 0.45f*sqrt(originalLength*originalLength - currentLength*currentLength);
+ float curveEndY, cosTheta ,sinTheta ,translateX, translateY;
+ // when the vanishing point is very far away, make it infinitely, in this case, the page bent horizontally
+ const float THRESHOLD(20.0);
+ if( fabs(vanishingPointY-mPageHeight*0.5f) >= mPageHeight*THRESHOLD )
+ {
+ curveDirection = Vector2(-1.f,0.f);
+ currentCenter.y = originalCenter.y;
- float* parameterArray = current.AsFloat();
- parameterArray[0] = cosTheta;
- parameterArray[1] = -sinTheta;
- parameterArray[2] = originalCenter.x;
- parameterArray[3] = originalCenter.y;
- parameterArray[4] = sinTheta;
- parameterArray[5] = cosTheta;
- parameterArray[6] = currentCenter.x;
- parameterArray[7] = currentCenter.y;
- parameterArray[8] = translateX;
- parameterArray[9] = translateY;
- parameterArray[10] = vanishingPointY;
- parameterArray[11] = curveEndY;
- parameterArray[12] = curveDirection.x;
- parameterArray[13] = curveDirection.y;
- parameterArray[14] = curveHeight;
- parameterArray[15] = currentLength;
-}
+ curveEndY = originalCenter.y;
+ cosTheta = 1.f;
+ sinTheta = 0.f;
+ translateX = currentCenter.x - originalCenter.x;
+ translateY = vanishingPointY;
+ }
+ else
+ {
+ curveEndY = currentCenter.y - curveDirection.y * (currentCenter.x/curveDirection.x) ;
+ Vector2 v1( currentCenter.x, currentCenter.y - vanishingPointY );
+ v1.Normalize();
+ Vector2 v2( originalCenter.x, originalCenter.y - vanishingPointY );
+ v2.Normalize();
+ cosTheta = v1.x*v2.x + v1.y*v2.y;
+ sinTheta = ( vanishingPointY > mPageHeight*0.5f ) ? sqrt(1.0-cosTheta*cosTheta) : -sqrt(1.0-cosTheta*cosTheta);
+ translateX = currentCenter.x - cosTheta*originalCenter.x - sinTheta*( originalCenter.y-vanishingPointY );
+ translateY = currentCenter.y + sinTheta*originalCenter.x - cosTheta*( originalCenter.y-vanishingPointY );
+ }
+
+ float originalLength = fabs(originalCenter.x/curveDirection.x);
+ float currentLength = fabs(currentCenter.x/curveDirection.x);
+ float curveHeight = 0.45f*sqrt(originalLength*originalLength - currentLength*currentLength);
+
+ float* parameterArray = current.AsFloat();
+ parameterArray[0] = cosTheta;
+ parameterArray[1] = -sinTheta;
+ parameterArray[2] = originalCenter.x;
+ parameterArray[3] = originalCenter.y;
+ parameterArray[4] = sinTheta;
+ parameterArray[5] = cosTheta;
+ parameterArray[6] = currentCenter.x;
+ parameterArray[7] = currentCenter.y;
+ parameterArray[8] = translateX;
+ parameterArray[9] = translateY;
+ parameterArray[10] = vanishingPointY;
+ parameterArray[11] = curveEndY;
+ parameterArray[12] = curveDirection.x;
+ parameterArray[13] = curveDirection.y;
+ parameterArray[14] = curveHeight;
+ parameterArray[15] = currentLength;
+ }
+
+ float mPageHeight;
+};
-void Dali::Toolkit::Internal::PageTurnApplyInternalConstraint( ShaderEffect& shaderEffect)
+void Dali::Toolkit::Internal::PageTurnApplyInternalConstraint( Actor& actor, float pageHeight )
{
- Constraint constraint = Constraint::New<Dali::Matrix>( shaderEffect, shaderEffect.GetPropertyIndex( "uCommonParameters" ), CommonParametersConstraint );
- constraint.AddSource( LocalSource( shaderEffect.GetPropertyIndex( "uOriginalCenter" ) ) );
- constraint.AddSource( LocalSource( shaderEffect.GetPropertyIndex( "uCurrentCenter" ) ) );
- constraint.AddSource( LocalSource( shaderEffect.GetPropertyIndex( "uPageSize" ) ) );
+ Constraint constraint = Constraint::New<Dali::Matrix>( actor, actor.GetPropertyIndex( PROPERTY_COMMON_PARAMETERS ) , CommonParametersConstraint( pageHeight ) );
+ constraint.AddSource( LocalSource( actor.GetPropertyIndex( PROPERTY_ORIGINAL_CENTER ) ) );
+ constraint.AddSource( LocalSource( actor.GetPropertyIndex( PROPERTY_CURRENT_CENTER ) ) );
constraint.Apply();
}
-ShaderEffect Dali::Toolkit::Internal::CreatePageTurnEffect()
+Property::Map Dali::Toolkit::Internal::CreatePageTurnEffect()
{
- std::string vertexShader = DALI_COMPOSE_SHADER(
+ const char* vertexShader = DALI_COMPOSE_SHADER(
/*
* The common parameters for all the vertices, calculate in CPU then pass into the shader as uniforms
*
* ([3][3]) float currentLength: The length from the current center to the curveEnd.
*/
precision mediump float;\n
+ \n
+ attribute mediump vec2 aPosition;\n
+ \n
+ uniform mediump mat4 uMvpMatrix;\n
+ uniform mediump mat3 uNormalMatrix;\n
+ uniform mediump mat4 uModelView;\n
+ \n
uniform mat4 uCommonParameters;\n
\n
- uniform vec2 uPageSize;\n
+ uniform vec3 uSize;\n
uniform float uIsTurningBack;\n
+ uniform float uTextureWidth;\n
varying vec3 vNormal;\n
varying vec4 vPosition;\n
- varying float vEdgeShadow;\n
+ varying mediump vec2 vTexCoord;\n
\n
void main()\n
{\n
- vec4 position = vec4( aPosition, 1.0);\n
+ vec4 position = vec4( aPosition*uSize.xy, 0.0, 1.0);\n
vec2 currentCenter = vec2( uCommonParameters[1][2], uCommonParameters[1][3]);\n
vec2 originalCenter = vec2( uCommonParameters[0][2], uCommonParameters[0][3]);\n
vec3 normal = vec3(0.0,0.0,1.0);\n
if(currentCenter.x < originalCenter.x)\n
{\n
// change the coordinate origin from the center of the page to its top-left
- position.xy += uPageSize * 0.5;\n
+ position.xy += uSize.xy * 0.5;\n
vec2 curveDirection = vec2( uCommonParameters[3]);\n
vec3 vanishingPoint = vec3(0.0, uCommonParameters[2][2], 0.0);\n
// first part of the page, (outside the the line passing through original center and vertical to curve direction)
}\n
\n
// define the control points of hermite curve, composed with two segments
- // calulation is carried out on the 2D plane which is passing through both current and original center and vertical to the image plane
+ // calculation is carried out on the 2D plane which is passing through both current and original center and vertical to the image plane
float currentLength = uCommonParameters[3][3];\n
float originalLength = abs(originalCenter.x/curveDirection.x);\n
float height = uCommonParameters[3][2];\n
vec2 SegmentTwoTangentVector0 = SegmentOneTangentVector1;\n
vec2 SegmentTwoTangentVector1 = SegmentOneTangentVector1;\n
\n
- // calulate the corresponding curve point position and its tangent vector
+ // calculate the corresponding curve point position and its tangent vector
// it is a linear mapping onto nonlinear curves, might cause some unwanted deformation
// but as there are no analytical method to calculate the curve length on arbitrary segment
// no efficient way to solve this nonlinear mapping, Numerical approximation would cost too much computation in shader
// a trick to eliminate some optical illusion caused by the gradient matter of normal in per-fragment shading
// which is caused by linear interpolation of normal vs. nonlinear lighting
// will notice some artifact in the areas with dramatically normal changes, so compress the normal differences here
- tangent.y *= min(1.0, length(position.xyz - vanishingPoint) / uPageSize.y ); \n
+ tangent.y *= min(1.0, length(position.xyz - vanishingPoint) / uSize.y ); \n
}\n
vec3 curvePoint = vec3(curveEnd - curvePoint2D.x*curveDirection,max(0.0,curvePoint2D.y));\n
vec3 tangentVector = vec3(-tangent.x*curveDirection,tangent.y);\n
normal.xy *= -uIsTurningBack;\n
}\n
// change the coordinate origin from the top-left of the page to its center
- position.xy -= uPageSize * 0.5; \n
+ position.xy -= uSize.xy * 0.5; \n
}\n
- gl_Position = uMvpMatrix * position;\n
+ vNormal = uNormalMatrix * normal;\n
+ gl_Position = uMvpMatrix * position;
// varying parameters for fragment shader
- vTexCoord = mix( sTextureRect.xy, sTextureRect.zw, aTexCoord );\n;
- vNormal = uNormalMatrix*normal;\n
+ vTexCoord = aPosition + vec2(0.5);\n
+ vTexCoord.x /= uTextureWidth;
vPosition = uModelView * position;\n
}\n
);
- std::string fragmentShader = DALI_COMPOSE_SHADER(
+ const char* fragmentShader = DALI_COMPOSE_SHADER(
precision mediump float;\n
- uniform vec2 uPageSize;\n
+ \n
+ varying mediump vec2 vTexCoord;\n
+ \n
+ uniform sampler2D sTexture;\n
+ uniform lowp vec4 uColor;\n
+ uniform vec3 uSize;\n
uniform vec2 uSpineShadowParameter;\n
varying vec3 vNormal;\n
varying vec4 vPosition;\n
- varying float vEdgeShadow;\n
\n
void main()\n
{\n
// need to re-normalize the interpolated normal
- vec3 normal = normalize(vNormal);\n
- vec4 texel;\n
- float spineShadowCoef = 1.0; \n
+ vec3 normal = normalize( vNormal );\n
// display page content
+ vec4 texel;
// display back image of the page, flip the texture
- if( dot(vPosition.xyz, normal) > 0.0 ) texel = texture2D( sTexture, vec2( sTextureRect.p+sTextureRect.s-vTexCoord.x, vTexCoord.y ) );\n
+ if( dot(vPosition.xyz, normal) > 0.0 ) texel = texture2D( sTexture, vec2( 1.0 - vTexCoord.x, vTexCoord.y ) );\n
// display front image of the page
else texel = texture2D( sTexture, vTexCoord );\n
+
// display book spine, a stripe of shadowed texture
- float pixelPos = (vTexCoord.x-sTextureRect.s)*uPageSize.x; \n
- if(pixelPos < uSpineShadowParameter.x) \n
+ float pixelPos = vTexCoord.x * uSize.x; \n
+ float spineShadowCoef = 1.0; \n
+ if( pixelPos < uSpineShadowParameter.x ) \n
{\n
float x = pixelPos - uSpineShadowParameter.x;\n
- float y = sqrt( uSpineShadowParameter.x*uSpineShadowParameter.x - x*x);\n
+ float y = sqrt( uSpineShadowParameter.x*uSpineShadowParameter.x - x*x );\n
spineShadowCoef = normalize( vec2( uSpineShadowParameter.y*x/uSpineShadowParameter.x, y ) ).y;\n
}\n
// calculate the lighting
// set the ambient color as vec3(0.4);
float lightColor = abs( normal.z ) * 0.6 + 0.4;\n
- gl_FragColor = vec4( ( spineShadowCoef* lightColor)* texel.rgb , texel.a ) * uColor;\n
+ gl_FragColor = vec4( ( spineShadowCoef * lightColor ) * texel.rgb , texel.a ) * uColor;\n
}
);
- // Create the implementation, temporarily owned on stack,
- Dali::ShaderEffect shaderEffectCustom = Dali::ShaderEffect::New( vertexShader, fragmentShader,ShaderEffect::HINT_GRID );
-
- static const Vector2 DEFAULT_SPINE_SHADOW_PARAMETER(50.0f, 20.0f);
-
- Vector2 defaultPageSize = Dali::Stage::GetCurrent().GetSize();
- Dali::Matrix zeroMatrix(true);
- shaderEffectCustom.SetUniform( "uCommonParameters", zeroMatrix );
- shaderEffectCustom.SetUniform( "uPageSize", defaultPageSize );
- shaderEffectCustom.SetUniform( "uSpineShadowParameter", DEFAULT_SPINE_SHADOW_PARAMETER );
+ Property::Map map;
- shaderEffectCustom.RegisterProperty( "uOriginalCenter", Vector2( defaultPageSize[0], defaultPageSize[1]*0.5f ) );
- shaderEffectCustom.RegisterProperty( "uCurrentCenter", Vector2( defaultPageSize[0], defaultPageSize[1]*0.5f ) );
+ Property::Map customShader;
- PageTurnApplyInternalConstraint(shaderEffectCustom);
+ customShader[ "vertexShader" ] = vertexShader;
+ customShader[ "fragmentShader" ] = fragmentShader;
+ customShader[ "subdivideGridX" ] = 20;
+ customShader[ "subdivideGridY" ] = 20;
- // setting isTurningBack to -1.0f here means turning page forward
- shaderEffectCustom.SetUniform( "uIsTurningBack", -1.0f );
+ map[ "shader" ] = customShader;
+ return map;
- return shaderEffectCustom;
}
*/
// EXTERNAL INCLUDES
-#include <dali/public-api/animation/constraint.h>
-#include <dali/public-api/common/stage.h>
-#include <dali/public-api/object/property-input.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
-#include <sstream>
namespace Dali
{
/**
* @brief Re-applies PageTurnEffect internal constraints
- * The internal constraint uses the OriginalCenter property and the CurrentCenter Property
+ * The internal constraint uses the OriginalCenter property and the CURRENT_CENTER Property
* to update the variety of common parameters which are with the same value for all the vertices.
* Note: For each actor, the constraints are applied in the same order as the calls to Actor::ApplyConstraint().
- * So if there are other contraints applied to the OriginalCenter or CurrentCenter while when using this effect,
+ * So if there are other contraints applied to the ORIGINAL_CENTER or CURRENT_CENTER while when using this effect,
* call this method to get the internal constraints and re-apply it afterwards.
*
- * @param[in] shaderEffect The page turn effect to which internal constraints should be re-applied
+ * @param[in] actor The page turn actor to which internal constraints should be re-applied
+ * @param[in] pageHeight The page height.
*/
-void PageTurnApplyInternalConstraint( ShaderEffect& shaderEffect);
+void PageTurnApplyInternalConstraint( Actor& actor, float pageHeight );
/**
* @brief Create a new PageTurnEffect
* Usage example:-
*
* // create shader used for doing page-turn effect\n
- * ShaderEffect pageTurnEffect = CreatePageTurnEffect();
+ * Property::Map pageTurnEffect = CreatePageTurnEffect();
*
- * // set image actor shader to the page-turn one\n
+ * // set image view custom shader to the page-turn one\n
* // for portrait view, one image actor for each page\n
* // for landscape view, the page turned over is still visible, so back image is needed \n
* // in this case, create another image Actor using the back image and added to the page actor \n
- * ImageActor pageActor = ImageActor::New(....); \n
- * ImageActor backImageActor = ImageActor::New(....); \n
- * pageActor.Add(backPageActor);\n
- * pageActor.SetShaderEffect ( pageTurnEffect ); \n
+ * ImageView page = ImageView::New(....); \n
+ * page.SetProperty ( ImageView::Property::IMAGE, pageTurnEffect ); \n
*
* //set initial values
- * pageTurnEffect.SetUniform("uPageSize", Vector2);\n
- * pageTurnEffect.SetUniform("uOriginalCenter", Vector2);\n
- * pageTurnEffect.SetUniform("uIsTurningBack", bool);\n
- * pageTurnEffect.SetUniform("uCurrentCenter",Vector2);\n
+ * page.SetProperty( page.GetPropertyIndex("uIsTurningBack",) bool );\n
+ * page.SetProperty( page.GetPropertyIndex("uSpineShadowParameter",) Vector2 );\n
+ * page.SetProperty( page.GetPropertyIndex("ORIGINAL_CENTER"), Vector2 );\n
+ * page.SetProperty( page.GetPropertyIndex("CURRENT_CENTER"), Vector2 );\n
+ * page.SetProperty( page.GetPropertyIndex("uCommonParameters"), Matrix );\n
+ * page.SetProperty( page.GetPropertyIndex("uTextureWidth"), float ); // Set to 1.0 for single-sided or 2.0 for double-sided \n
+ * PageTurnApplyInternalConstraint( page );\n
*
* //Animate it with the current center property\n
- * Animation animation[mAnimationIndex] = Animation::New( ... );\n
- * animation.AnimateTo(Property( pageTurnEffect, "uCurrentCenter" ),
- * currentCenter,
- * AlphaFunction::...);\n
- * animation[mAnimationIndex].Play(); \n
+ * Animation animation = Animation::New( ... );\n
+ * animation.AnimateTo(Property( page, "CURRENT_CENTER" ),
+ * currentCenter,
+ * AlphaFunction::...);\n
+ * animation.Play(); \n
*
- * Animatable/Constrainable uniforms:
*/
-ShaderEffect CreatePageTurnEffect();
+Property::Map CreatePageTurnEffect();
} // namespace Internal
namespace
{
-using namespace Dali;
DALI_TYPE_REGISTRATION_BEGIN( Toolkit::PageTurnLandscapeView, Toolkit::PageTurnView, NULL )
DALI_TYPE_REGISTRATION_END()
void PageTurnLandscapeView::OnPageTurnViewInitialize()
{
+ mTurnEffectShader.RegisterProperty(PROPERTY_TEXTURE_WIDTH, 2.f );
+ mSpineEffectShader.RegisterProperty(PROPERTY_TEXTURE_WIDTH, 2.f );
+
mControlSize = Vector2( mPageSize.width * 2.f, mPageSize.height );
Self().SetSize( mControlSize );
mTurningPageLayer.SetParentOrigin( ParentOrigin::CENTER );
}
-void PageTurnLandscapeView::OnAddPage( ImageActor newPage, bool isLeftSide )
+void PageTurnLandscapeView::OnAddPage( Actor newPage, bool isLeftSide )
{
newPage.SetParentOrigin( ParentOrigin::CENTER );
- SetCullFace( newPage, CullBack );
-
- if( 0 < newPage.GetChildCount() )
- {
- ImageActor backImage = ImageActor::DownCast( newPage.GetChildAt( 0 ) );
- backImage.SetParentOrigin( ParentOrigin::CENTER );
- backImage.SetSize( mPageSize );
- SetCullFace( backImage, CullFront );
- backImage.SetZ( 0.25f * STATIC_PAGE_INTERVAL_DISTANCE );
- }
- if( isLeftSide )
- {
- SetShaderEffect( newPage, mSpineEffectBack );
- }
}
Vector2 PageTurnLandscapeView::SetPanPosition( const Vector2& gesturePosition )
{
- if( mIsTurnBack[mPanActor] )
+ if( mPages[mIndex].isTurnBack )
{
return Vector2( mPageSize.width - gesturePosition.x, gesturePosition.y );
}
void PageTurnLandscapeView::SetPanActor( const Vector2& panPosition )
{
- if( panPosition.x > mPageSize.width && mCurrentPageIndex < mTotalPageCount-1 )
+ if( panPosition.x > mPageSize.width && mCurrentPageIndex < mTotalPageCount )
{
- mPanActor = mPageActors[mCurrentPageIndex%NUMBER_OF_CACHED_PAGES]; // right side page
mTurningPageIndex = mCurrentPageIndex;
}
else if( panPosition.x <= mPageSize.width && mCurrentPageIndex > 0 )
{
- mPanActor = mPageActors[ (mCurrentPageIndex-1)%NUMBER_OF_CACHED_PAGES ]; // left side page
mTurningPageIndex = mCurrentPageIndex - 1;
}
else
{
- mPanActor.Reset();
- }
-}
-
-void PageTurnLandscapeView::SetSpineEffect(ImageActor actor, bool isLeftSide)
-{
- if(isLeftSide)
- {
- SetShaderEffect( actor, mSpineEffectBack );
- }
- else
- {
- SetShaderEffect( actor, mSpineEffectFront );
+ mTurningPageIndex = -1;
}
}
public:
/**
- * Create a new PageTurnLandscapeView
- * @return A handle to the newly allocated PageTurnLandscapeView
+ * @copydoc Toolkit::PageTurnLandscapeView::New( PageFactory&, const Vector2& )
*/
static Toolkit::PageTurnLandscapeView New( PageFactory& pageFactory, const Vector2& pageSize );
protected:
/**
* Constructor.
- * It initializes the PageTurnLandscapeView members
+ * It initializes the PageTurnPortraitView members
+ * @param[in] pageFactory The factory which provides image actors to PageTurnView as the page content.
+ * @param[in] pageSize The size of the page
*/
PageTurnLandscapeView( PageFactory& pageFactory, const Vector2& pageSize );
/**
* @copydoc PageTurnView::OnAddPage
*/
- virtual void OnAddPage( ImageActor newPage, bool isLeftSide );
+ virtual void OnAddPage( Actor newPage, bool isLeftSide );
/**
* @copydoc PageTurnView::SetPanPosition
*/
virtual void SetPanActor( const Vector2& panPosition );
- /**
- * @copydoc PageTurnView::SetSpineEffect
- */
- virtual void SetSpineEffect(ImageActor actor, bool isLeftSide);
-
private:
//Undefined
namespace
{
-using namespace Dali;
-
DALI_TYPE_REGISTRATION_BEGIN( Toolkit::PageTurnPortraitView, Toolkit::PageTurnView, NULL )
DALI_TYPE_REGISTRATION_END()
PageTurnPortraitView::PageTurnPortraitView( PageFactory& pageFactory, const Vector2& pageSize )
: PageTurnView( pageFactory, pageSize )
{
-
}
PageTurnPortraitView::~PageTurnPortraitView()
void PageTurnPortraitView::OnPageTurnViewInitialize()
{
+ mTurnEffectShader.RegisterProperty(PROPERTY_TEXTURE_WIDTH, 1.f );
+ mSpineEffectShader.RegisterProperty(PROPERTY_TEXTURE_WIDTH, 1.f );
+
mControlSize = mPageSize;
Self().SetSize( mPageSize );
mTurningPageLayer.SetParentOrigin( ParentOrigin::CENTER_LEFT );
{
if( mCurrentPageIndex < mTotalPageCount )
{
- mPanActor = mPageActors[mCurrentPageIndex%NUMBER_OF_CACHED_PAGES];
mTurningPageIndex = mCurrentPageIndex;
}
else
{
- mPanActor.Reset();
- }
-}
-
-void PageTurnPortraitView::SetSpineEffect(ImageActor actor, bool isLeftSide)
-{
- if(isLeftSide)
- {
- actor.RemoveShaderEffect();
- }
- else
- {
- actor.SetShaderEffect( mSpineEffectFront );
+ mTurningPageIndex = -1;
}
}
// There is previous page and an outwards flick is detected
if( mCurrentPageIndex > 0 && gestureSpeed > GESTURE_SPEED_THRESHOLD && offset.x > fabs( offset.y ))
{
- ImageActor actor = mPageActors[ (mCurrentPageIndex-1) % NUMBER_OF_CACHED_PAGES ];
+ int actorIndex = (mCurrentPageIndex-1) % NUMBER_OF_CACHED_PAGES;
+ Actor actor = mPages[ actorIndex ].actor;
if(actor.GetParent() != Self())
{
return;
RemovePage( mCurrentPageIndex+NUMBER_OF_CACHED_PAGES_EACH_SIDE );
AddPage( mCurrentPageIndex-NUMBER_OF_CACHED_PAGES_EACH_SIDE );
OrganizePageDepth();
+ mPageUpdated = true;
- mPageActors[mTurningPageIndex%NUMBER_OF_CACHED_PAGES].SetVisible(true);
+ actor.SetVisible(true);
// Add the page to tuning page layer and set up PageTurnEffect
mShadowView.Add( actor );
- actor.SetShaderEffect( mTurnEffect[mIndex] );
- PageTurnApplyInternalConstraint(mTurnEffect[mIndex]);
- mIsAnimating[mIndex] = true;
- mTurnEffect[mIndex].SetUniform("uIsTurningBack", 1.f );
+ mPages[actorIndex].UseEffect( mTurnEffectShader );
+ mAnimatingCount++;
Vector2 originalCenter( mPageSize.width*1.5f, 0.5f*mPageSize.height );
- mTurnEffect[mIndex].SetUniform("uOriginalCenter", originalCenter );
- mTurnEffect[mIndex].SetUniform("uCurrentCenter", Vector2( mPageSize.width*0.5f, mPageSize.height*0.5f ) );
+ mPages[actorIndex].SetOriginalCenter( originalCenter );
+ mPages[actorIndex].SetCurrentCenter( Vector2( mPageSize.width*0.5f, mPageSize.height*0.5f ) );
+ PageTurnApplyInternalConstraint(actor, mPageSize.height);
// Start an animation to turn the previous page back
Animation animation = Animation::New( PAGE_TURN_OVER_ANIMATION_DURATION );
mAnimationPageIdPair[animation] = mCurrentPageIndex;
- mAnimationIndexPair[animation] = mIndex;
- animation.AnimateTo( Property( mTurnEffect[mIndex], "uCurrentCenter" ),
+ animation.AnimateTo( Property( actor, mPages[actorIndex].propertyCurrentCenter ),
originalCenter,
AlphaFunction::EASE_OUT, TimePeriod(PAGE_TURN_OVER_ANIMATION_DURATION*0.75f) );
animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), AngleAxis( Degree( 180.0f ), Vector3::YAXIS ) ,AlphaFunction::EASE_OUT );
animation.Play();
- ImageActor imageActor = ImageActor::DownCast(actor);
- if( imageActor )
- {
- SetCullFace( imageActor, CullBack );
- }
animation.FinishedSignal().Connect( this, &PageTurnPortraitView::TurnedOverBackwards );
}
}
-void PageTurnPortraitView::OnTurnedOver( ImageActor actor, bool isLeftSide )
+void PageTurnPortraitView::OnTurnedOver( Actor actor, bool isLeftSide )
{
if( isLeftSide )
{
void PageTurnPortraitView::TurnedOverBackwards( Animation& animation )
{
- ImageActor imageActor = mPageActors[mAnimationPageIdPair[animation] % NUMBER_OF_CACHED_PAGES];
- if( imageActor )
- {
- SetCullFace( imageActor, CullNone );
- }
TurnedOver( animation );
}
public:
/**
- * Create a new PageTurnPortraitView
- * @return A handle to the newly allocated PageTurnPortraitView
+ * @copydoc Toolkit::PageTurnPortraitView::New( PageFactory&, const Vector2& )
*/
static Toolkit::PageTurnPortraitView New( PageFactory& pageFactory, const Vector2& pageSize );
/**
* Constructor.
* It initializes the PageTurnPortraitView members
+ * @param[in] pageFactory The factory which provides image actors to PageTurnView as the page content.
+ * @param[in] pageSize The size of the page
*/
PageTurnPortraitView( PageFactory& pageFactory, const Vector2& pageSize );
virtual void SetPanActor( const Vector2& panPosition );
/**
- * @copydoc PageTurnView::SetSpineEffect
- */
- virtual void SetSpineEffect(ImageActor actor, bool isLeftSide);
-
- /**
* @copydoc PageTurnView::OnPossibleOutwardsFlick
*/
virtual void OnPossibleOutwardsFlick( const Vector2& panPosition, float gestureSpeed );
- virtual void OnTurnedOver( ImageActor actor, bool isLeftSide );
+ /**
+ * @copydoc PageTurnView::OnTurnedOver
+ */
+ virtual void OnTurnedOver( Actor actor, bool isLeftSide );
private:
#include <cstring> // for strcmp
#include <dali/public-api/animation/animation.h>
#include <dali/public-api/animation/constraint.h>
-#include <dali/devel-api/events/hit-test-algorithm.h>
+#include <dali/public-api/images/resource-image.h>
#include <dali/public-api/object/type-registry.h>
#include <dali/devel-api/object/type-registry-helper.h>
-#include <dali/public-api/render-tasks/render-task-list.h>
-#include <dali/devel-api/rendering/cull-face.h>
+#include <dali/integration-api/debug.h>
// INTERNAL INCLUDES
#include <dali-toolkit/internal/controls/page-turn-view/page-turn-effect.h>
#include <dali-toolkit/internal/controls/page-turn-view/page-turn-book-spine-effect.h>
+#include <dali-toolkit/internal/controls/renderers/renderer-factory-cache.h>
+
+// headers needed for backward compatibility of PageFactory::NewPage(pageId) API
+#include <dali/public-api/actors/image-actor.h>
using namespace Dali;
namespace //Unnamed namespace
{
-// default grid density for page turn effect, 10 pixels by 10 pixels
-const float DEFAULT_GRID_DENSITY(10.0f);
+// broken image is loaded if there is no valid image provided for the page
+const char * const BROKEN_IMAGE_URL( DALI_IMAGE_DIR "broken.png");
+
+// names of shader property map
+const char * const CUSTOM_SHADER( "shader" );
+const char * const CUSTOM_VERTEX_SHADER( "vertexShader" );
+const char * const CUSTOM_FRAGMENT_SHADER( "fragmentShader" );
+
+// name of the texture in material
+const char * const TEXTURE_NAME( "sTexture" );
+
+// properties set on shader, these properties have the constant value in regardless of the page status
+const char * const PROPERTY_SPINE_SHADOW ( "uSpineShadowParameter" ); // uniform for both spine and turn effect
+
+// properties set on actor, the value of these properties varies depending on the page status
+// properties used in turn effect
+const char * const PROPERTY_TURN_DIRECTION( "uIsTurningBack" ); // uniform
+const char * const PROPERTY_COMMON_PARAMETERS( "uCommonParameters" ); //uniform
+
+const char * const PROPERTY_PAN_DISPLACEMENT( "panDisplacement" );// property used to constrain the uniforms
+const char * const PROPERTY_PAN_CENTER( "panCenter" );// property used to constrain the uniforms
+
+// default grid density for page turn effect, 20 pixels by 20 pixels
+const float DEFAULT_GRID_DENSITY(20.0f);
// to bent the page, the minimal horizontal pan start position is pageSize.x * MINIMUM_START_POSITION_RATIO
const float MINIMUM_START_POSITION_RATIO(0.6f);
const Vector2& centerOrigin = inputs[1]->GetVector2();
Vector2 direction = centerOrigin - Vector2(mThres, centerPosition.y);
float coef = 1.f+(centerPosition.x*2.f / mPageWidth);
- // Todo: when coef <= 0, the page is flat, slow down the last moment of the page stretch by 10 times to avoid a small bounce
+ // when coef <= 0, the page is flat, slow down the last moment of the page stretch by 10 times to avoid a small bounce
if(coef < 0.025f)
{
coef = (coef+0.225f)/10.0f;
}
// these several constants are also used in the derived classes
+const char * const PageTurnView::PROPERTY_TEXTURE_WIDTH( "uTextureWidth" ); // uniform name
+const char * const PageTurnView::PROPERTY_ORIGINAL_CENTER( "originalCenter" ); // property used to constrain the uniform
+const char * const PageTurnView::PROPERTY_CURRENT_CENTER( "currentCenter" );// property used to constrain the uniform
const int PageTurnView::MAXIMUM_TURNING_NUM = 4;
const int PageTurnView::NUMBER_OF_CACHED_PAGES_EACH_SIDE = MAXIMUM_TURNING_NUM + 1;
const int PageTurnView::NUMBER_OF_CACHED_PAGES = NUMBER_OF_CACHED_PAGES_EACH_SIDE*2;
const float PageTurnView::STATIC_PAGE_INTERVAL_DISTANCE = 1.0f;
+PageTurnView::Page::Page()
+: isTurnBack( false )
+{
+ actor = Actor::New();
+ actor.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
+ actor.SetParentOrigin( ParentOrigin::CENTER_LEFT );
+ actor.SetVisible( false );
+
+ propertyPanDisplacement = actor.RegisterProperty( PROPERTY_PAN_DISPLACEMENT, 0.f );
+ propertyPanCenter = actor.RegisterProperty(PROPERTY_PAN_CENTER, Vector2::ZERO);
+
+ propertyOriginalCenter = actor.RegisterProperty(PROPERTY_ORIGINAL_CENTER, Vector2::ZERO);
+ propertyCurrentCenter = actor.RegisterProperty(PROPERTY_CURRENT_CENTER, Vector2::ZERO);
+ Matrix zeroMatrix(true);
+ actor.RegisterProperty(PROPERTY_COMMON_PARAMETERS, zeroMatrix);
+ propertyTurnDirection = actor.RegisterProperty(PROPERTY_TURN_DIRECTION, -1.f);
+}
+
+void PageTurnView::Page::SetImage( Image image )
+{
+ if( material.GetNumberOfTextures() > 0 )
+ {
+ material.SetTextureImage( 0u, image );
+ }
+ else
+ {
+ material.AddTexture(image, TEXTURE_NAME);
+ }
+}
+
+void PageTurnView::Page::UseEffect(Shader shader)
+{
+ if( material )
+ {
+ material.SetShader( shader );
+ }
+ else
+ {
+ material = Material::New( shader );
+ }
+}
+
+void PageTurnView::Page::UseEffect(Shader shader, Geometry geometry)
+{
+ UseEffect( shader );
+
+ if( !renderer )
+ {
+ renderer = Renderer::New( geometry, material );
+ actor.AddRenderer( renderer );
+ }
+}
+
+void PageTurnView::Page::ChangeTurnDirection()
+{
+ isTurnBack = !isTurnBack;
+ actor.SetProperty( propertyTurnDirection, isTurnBack ? 1.f : -1.f );
+}
+
+void PageTurnView::Page::SetPanDisplacement(float value)
+{
+ actor.SetProperty( propertyPanDisplacement, value );
+}
+
+void PageTurnView::Page::SetPanCenter( const Vector2& value )
+{
+ actor.SetProperty( propertyPanCenter, value );
+}
+
+void PageTurnView::Page::SetOriginalCenter( const Vector2& value )
+{
+ actor.SetProperty( propertyOriginalCenter, value );
+}
+
+void PageTurnView::Page::SetCurrentCenter( const Vector2& value )
+{
+ actor.SetProperty( propertyCurrentCenter, value );
+}
+
PageTurnView::PageTurnView( PageFactory& pageFactory, const Vector2& pageSize )
: Control( ControlBehaviour( REQUIRES_TOUCH_EVENTS ) ),
- mPageFactory( pageFactory ),
+ mPageFactory( &pageFactory ),
mPageSize( pageSize ),
- mTotalPageCount( 0 ),
- mPanning( false ),
mSpineShadowParameter( DEFAULT_SPINE_SHADOW_PARAMETER ),
+ mDistanceUpCorner( 0.f ),
+ mDistanceBottomCorner( 0.f ),
+ mPanDisplacement( 0.f ),
+ mTotalPageCount( 0 ),
mCurrentPageIndex( 0 ),
mTurningPageIndex( 0 ),
mIndex( 0 ),
+ mSlidingCount( 0 ),
+ mAnimatingCount( 0 ),
+ mConstraints( false ),
mPress( false ),
mPageUpdated( true ),
- mDistanceUpCorner( 0.f ),
- mDistanceBottomCorner( 0.f ),
- mPanDisplacement( 0.f ),
- mConstraints( false ),
mPageTurnStartedSignal(),
mPageTurnFinishedSignal(),
mPagePanStartedSignal(),
mPagePanFinishedSignal()
{
- mPageActors.resize( NUMBER_OF_CACHED_PAGES );
- mIsAnimating.resize( MAXIMUM_TURNING_NUM );
- mIsSliding.resize( MAXIMUM_TURNING_NUM );
- mTurnEffect.resize( MAXIMUM_TURNING_NUM );
- mPropertyPanDisplacement.resize( MAXIMUM_TURNING_NUM );
- mPropertyCurrentCenter.resize( MAXIMUM_TURNING_NUM );
}
PageTurnView::~PageTurnView()
void PageTurnView::OnInitialize()
{
- // create the two book spine effect for static images, left and right side pages respectively
- mSpineEffectFront = CreatePageTurnBookSpineEffect();
- mSpineEffectFront.SetUniform("uIsBackImageVisible", -1.f );
- mSpineEffectFront.SetUniform("uPageWidth", mPageSize.width );
- mSpineEffectFront.SetUniform("uShadowWidth", 0.f );
- mSpineEffectFront.SetUniform("uSpineShadowParameter", mSpineShadowParameter );
-
- mSpineEffectBack = CreatePageTurnBookSpineEffect();
- mSpineEffectBack.SetUniform("uIsBackImageVisible", 1.f );
- mSpineEffectBack.SetUniform("uPageWidth", mPageSize.width );
- mSpineEffectBack.SetUniform("uShadowWidth", 0.f );
- mSpineEffectBack.SetUniform("uSpineShadowParameter", mSpineShadowParameter );
-
- // create the page turn effect objects
- for( int i = 0; i < MAXIMUM_TURNING_NUM; i++ )
+ // create the book spine effect for static pages
+ Property::Map spineEffectMap = CreatePageTurnBookSpineEffect();
+ mSpineEffectShader = CreateShader( spineEffectMap );
+ mSpineEffectShader.RegisterProperty(PROPERTY_SPINE_SHADOW, mSpineShadowParameter );
+ // create the turn effect for turning pages
+ Property::Map turnEffectMap = CreatePageTurnEffect();
+ mTurnEffectShader = CreateShader( turnEffectMap );
+ mTurnEffectShader.RegisterProperty(PROPERTY_SPINE_SHADOW, mSpineShadowParameter );
+
+ // create the grid geometry for pages
+ uint16_t width = static_cast<uint16_t>(mPageSize.width / DEFAULT_GRID_DENSITY + 0.5f);
+ uint16_t height = static_cast<uint16_t>(mPageSize.height / DEFAULT_GRID_DENSITY + 0.5f);
+ mGeometry = RendererFactoryCache::CreateGridGeometry( Uint16Pair( width, height ) );
+ mGeometry.SetRequiresDepthTesting( true );
+
+ mPages.reserve( NUMBER_OF_CACHED_PAGES );
+ for( int i = 0; i < NUMBER_OF_CACHED_PAGES; i++ )
{
- mTurnEffect[i] = CreatePageTurnEffect();
- mTurnEffect[i].SetProperty( ShaderEffect::Property::GRID_DENSITY, Property::Value( DEFAULT_GRID_DENSITY ) );
- mTurnEffect[i].SetUniform( "uPageSize", mPageSize );
- mTurnEffect[i].SetUniform( "uShadowWidth", 0.f);
- mTurnEffect[i].SetUniform( "uSpineShadowParameter", mSpineShadowParameter );
- mIsAnimating[i] = false;
- mIsSliding[i] = false;
- mPropertyPanDisplacement[i] = Self().RegisterProperty("PAN_DISPLACEMENT_PROPERTY_"+i, 0.0f);
- mPropertyCurrentCenter[i] = Self().RegisterProperty("CURRENT_CENTER_PROPERTY_"+i, Vector2(0.0f,0.0f));
+ mPages.push_back( Page() );
+ mPages[i].actor.SetSize( mPageSize );
+ Self().Add( mPages[i].actor );
}
+ // create the layer for turning images
mTurningPageLayer = Layer::New();
mTurningPageLayer.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
mTurningPageLayer.SetBehavior(Layer::LAYER_3D);
+ mTurningPageLayer.Raise();
// Set control size and the parent origin of page layers
OnPageTurnViewInitialize();
Self().Add(mTurningPageLayer);
- mTotalPageCount = static_cast<int>( mPageFactory.GetNumberOfPages() );
+ mTotalPageCount = static_cast<int>( mPageFactory->GetNumberOfPages() );
// add pages to the scene, and set depth for the stacked pages
for( int i = 0; i < NUMBER_OF_CACHED_PAGES_EACH_SIDE; i++ )
{
AddPage( i );
- if(mPageActors[i])
- {
- mPageActors[i].SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
- }
+ mPages[i].actor.SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
}
- mPageActors[0].SetVisible(true);
+ mPages[0].actor.SetVisible(true);
// enable the pan gesture which is attached to the control
EnableGestureDetection(Gesture::Type(Gesture::Pan));
}
+Shader PageTurnView::CreateShader( const Property::Map& shaderMap )
+{
+ Shader shader;
+ Property::Value* shaderValue = shaderMap.Find( CUSTOM_SHADER );
+ Property::Map shaderSource;
+ if( shaderValue && shaderValue->Get( shaderSource ) )
+ {
+ std::string vertexShader;
+ Property::Value* vertexShaderValue = shaderSource.Find( CUSTOM_VERTEX_SHADER );
+ if( !vertexShaderValue || !vertexShaderValue->Get( vertexShader ) )
+ {
+ DALI_LOG_ERROR("PageTurnView::CreateShader failed: vertex shader source is not available.\n");
+ }
+ std::string fragmentShader;
+ Property::Value* fragmentShaderValue = shaderSource.Find( CUSTOM_FRAGMENT_SHADER );
+ if( !fragmentShaderValue || !fragmentShaderValue->Get( fragmentShader ) )
+ {
+ DALI_LOG_ERROR("PageTurnView::CreateShader failed: fragment shader source is not available.\n");
+ }
+ shader = Shader::New( vertexShader, fragmentShader );
+ }
+ else
+ {
+ DALI_LOG_ERROR("PageTurnView::CreateShader failed: shader source is not available.\n");
+ }
+
+ return shader;
+}
+
void PageTurnView::SetupShadowView()
{
mShadowView = Toolkit::ShadowView::New( 0.25f, 0.25f );
Control::OnStageConnection( depth );
SetupShadowView();
- mTurningPageLayer.Raise();
}
void PageTurnView::OnStageDisconnection()
{
if(mShadowView)
{
+ mShadowView.RemoveConstraints();
mPointLight.Unparent();
mShadowPlaneBackground.Unparent();
mShadowView.Unparent();
}
// make sure the status of the control is updated correctly when the pan gesture is interrupted
- if(mPanning)
- {
- mPanning = false;
-
- Self().Add(mPanActor);
- mIsAnimating[mIndex] = false;
- mPanActor.RemoveConstraints();
- mTurnEffect[mIndex].RemoveConstraints();
- mPageUpdated = true;
-
- SetSpineEffect( mPanActor, mIsTurnBack[mPanActor] );
- }
+ StopTurning();
Control::OnStageDisconnection();
}
void PageTurnView::SetPageSize( const Vector2& pageSize )
{
mPageSize = pageSize;
- mSpineEffectFront.SetUniform("uPageWidth", mPageSize.width );
- mSpineEffectBack.SetUniform("uPageWidth", mPageSize.width );
- for( int i = 0; i < MAXIMUM_TURNING_NUM; i++ )
- {
- mTurnEffect[i].SetUniform( "uPageSize", mPageSize );
- }
if( mPointLight )
{
mPointLight.SetPosition( 0.f, 0.f, mPageSize.width*POINT_LIGHT_HEIGHT_RATIO );
}
- for( size_t i=0; i<mPageActors.size(); i++ )
+ for( size_t i=0; i<mPages.size(); i++ )
{
- if( mPageActors[i] )
- {
- mPageActors[i].SetSize( mPageSize );
- if( mPageActors[i].GetChildCount()>0 )
- {
- mPageActors[i].GetChildAt(0).SetSize( mPageSize );
- }
- }
+ mPages[i].actor.SetSize( mPageSize );
}
OnPageTurnViewInitialize();
mSpineShadowParameter = spineShadowParameter;
// set spine shadow parameter to all the shader effects
- mSpineEffectFront.SetUniform("uSpineShadowParameter", mSpineShadowParameter );
- mSpineEffectBack.SetUniform("uSpineShadowParameter", mSpineShadowParameter );
- for( int i = 0; i < MAXIMUM_TURNING_NUM; i++ )
- {
- mTurnEffect[i].SetUniform("uSpineShadowParameter", mSpineShadowParameter );
- }
+ mSpineEffectShader.RegisterProperty(PROPERTY_SPINE_SHADOW, mSpineShadowParameter );
+ mTurnEffectShader.RegisterProperty(PROPERTY_SPINE_SHADOW, mSpineShadowParameter );
}
Vector2 PageTurnView::GetSpineShadowParameter()
return;
}
+ // if any animation ongoing, stop it.
+ StopTurning();
+
// record the new current page index
mCurrentPageIndex = pageIdx;
- // clear the old pages
- for(int i = 0; i < NUMBER_OF_CACHED_PAGES; i++ )
- {
- if( mPageActors[i] )
- {
- mPageActors[i].Unparent();
- mPageActors[i].Reset();
- }
- }
// add the current page and the pages right before and after it
for( int i = pageIdx - NUMBER_OF_CACHED_PAGES_EACH_SIDE; i < pageIdx + NUMBER_OF_CACHED_PAGES_EACH_SIDE; i++ )
AddPage( i );
}
- mPageActors[pageId%NUMBER_OF_CACHED_PAGES].SetVisible(true);
+ mPages[pageId%NUMBER_OF_CACHED_PAGES].actor.SetVisible(true);
if( pageId > 0 )
{
- mPageActors[(pageId-1)%NUMBER_OF_CACHED_PAGES].SetVisible(true);
+ mPages[(pageId-1)%NUMBER_OF_CACHED_PAGES].actor.SetVisible(true);
}
// set ordered depth to the stacked pages
OrganizePageDepth();
if(pageIndex > -1 && pageIndex < mTotalPageCount) // whether the page is available from the page factory
{
int index = pageIndex % NUMBER_OF_CACHED_PAGES;
- ImageActor newPage= ImageActor::DownCast( mPageFactory.NewPage( pageIndex ) );
- DALI_ASSERT_ALWAYS( newPage );
- newPage.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
- newPage.SetParentOrigin( ParentOrigin::CENTER_LEFT );
- newPage.SetSize( mPageSize );
- Self().Add( newPage );
- mPageActors[index] = newPage;
+ Image newPageImage;
+ newPageImage = mPageFactory->NewPage( pageIndex );
- bool isLeftSide = ( pageIndex < mCurrentPageIndex );
- mIsTurnBack[ newPage ] = isLeftSide;
- if( isLeftSide )
+ if( !newPageImage ) // load the broken image
{
- // new page is added to the left side, so need to rotate it 180 degrees
- newPage.RotateBy( Degree(-180.0f ), Vector3::YAXIS );
+ newPageImage = ResourceImage::New( BROKEN_IMAGE_URL );
}
- else
+
+ bool isLeftSide = ( pageIndex < mCurrentPageIndex );
+ if( mPages[index].isTurnBack != isLeftSide )
{
- newPage.SetShaderEffect(mSpineEffectFront);
+ mPages[index].ChangeTurnDirection();
}
- newPage.SetVisible( false );
+ float degree = isLeftSide ? 180.f :0.f;
+ mPages[index].actor.SetOrientation( Degree( degree ), Vector3::YAXIS );
+ mPages[index].actor.SetVisible( false );
+ mPages[index].UseEffect( mSpineEffectShader, mGeometry );
+ mPages[index].SetImage( newPageImage );
// For Portrait, nothing to do
- // For Landscape, set spineEffectBack to the new effect if it is in the left side, and set properties to the back image actor if it exists
- OnAddPage( newPage, isLeftSide );
+ // For Landscape, set the parent origin to CENTER
+ OnAddPage( mPages[index].actor, isLeftSide );
}
}
if( pageIndex > -1 && pageIndex < mTotalPageCount)
{
int index = pageIndex % NUMBER_OF_CACHED_PAGES;
- mPageActors[index].Unparent();
- mIsTurnBack.erase( mPageActors[index] );
- mPageActors[index].Reset();
+ mPages[index].actor.SetVisible(false);
}
}
{
case Gesture::Started:
{
- mPanning = true;
- // to find out whether the undergoing turning page number already reaches the maximum allowed
- // and get one idle index when it is animatable
- bool animatable = false;
- for( int i = 0; i < MAXIMUM_TURNING_NUM; i++ )
- {
- if( !mIsAnimating[mIndex] )
- {
- animatable = true;
- break;
- }
- if( mIsSliding[mIndex] )
- {
- animatable = false;
- break;
- }
- mIndex++;
- mIndex = mIndex % MAXIMUM_TURNING_NUM;
- }
-
- if( mPageUpdated && animatable )
+ // check whether the undergoing turning page number already reaches the maximum allowed
+ if( mPageUpdated && mAnimatingCount< MAXIMUM_TURNING_NUM && mSlidingCount < 1 )
{
SetPanActor( gesture.position ); // determine which page actor is panned
- if(mPanActor && mPanActor.GetParent() != Self()) // if the page is added to turning layer,it is undergoing an animation currently
+ if( mTurningPageIndex != -1 && mPages[mTurningPageIndex % NUMBER_OF_CACHED_PAGES].actor.GetParent() != Self()) // if the page is added to turning layer,it is undergoing an animation currently
{
- mPanActor.Reset();
+ mTurningPageIndex = -1;
}
PanStarted( SetPanPosition( gesture.position ) ); // pass in the pan position in the local page coordinate
}
else
{
- mPanActor.Reset();
+ mTurningPageIndex = -1;
}
break;
}
case Gesture::Finished:
case Gesture::Cancelled:
{
- mPanning = false;
PanFinished( SetPanPosition( gesture.position ), gesture.GetSpeed() );
break;
}
{
mPressDownPosition = gesturePosition;
- if( !mPanActor )
+ if( mTurningPageIndex == -1 )
{
return;
}
+ mIndex = mTurningPageIndex % NUMBER_OF_CACHED_PAGES;
+
mOriginalCenter = gesturePosition;
- mTurnEffect[mIndex].SetUniform("uIsTurningBack", mIsTurnBack[ mPanActor] ? 1.f : -1.f);
mPress = false;
mPageUpdated = false;
void PageTurnView::PanContinuing( const Vector2& gesturePosition )
{
- if( !mPanActor )
+ if( mTurningPageIndex == -1 )
{
return;
}
{
mDistanceUpCorner = mOriginalCenter.Length();
mDistanceBottomCorner = ( mOriginalCenter - Vector2( 0.0f, mPageSize.height ) ).Length();
- mShadowView.Add( mPanActor );
- SetShaderEffect( mPanActor, mTurnEffect[mIndex] );
- mTurnEffect[mIndex].SetUniform("uOriginalCenter", mOriginalCenter );
+ mShadowView.Add( mPages[mIndex].actor );
+ mPages[mIndex].UseEffect( mTurnEffectShader );
+ mPages[mIndex].SetOriginalCenter( mOriginalCenter );
mCurrentCenter = mOriginalCenter;
- mTurnEffect[mIndex].SetUniform("uCurrentCenter", mCurrentCenter );
+ mPages[mIndex].SetCurrentCenter( mCurrentCenter );
mPanDisplacement = 0.f;
- mConstraints = true;
+ mConstraints = false;
mPress = true;
- mIsAnimating[mIndex] = true;
+ mAnimatingCount++;
- mPageTurnStartedSignal.Emit( handle, static_cast<unsigned int>(mTurningPageIndex), !mIsTurnBack[mPanActor] );
- int id = mTurningPageIndex + (mIsTurnBack[mPanActor]? -1 : 1);
+ mPageTurnStartedSignal.Emit( handle, static_cast<unsigned int>(mTurningPageIndex), !mPages[mIndex].isTurnBack );
+ int id = mTurningPageIndex + (mPages[mIndex].isTurnBack ? -1 : 1);
if( id >=0 && id < mTotalPageCount )
{
- mPageActors[id%NUMBER_OF_CACHED_PAGES].SetVisible(true);
+ mPages[id%NUMBER_OF_CACHED_PAGES].actor.SetVisible(true);
}
mShadowView.RemoveConstraints();
Actor self = Self();
- self.SetProperty( mPropertyPanDisplacement[mIndex], 0.f );
+ mPages[mIndex].SetPanDisplacement( 0.f );
Constraint shadowBlurStrengthConstraint = Constraint::New<float>( mShadowView, mShadowView.GetBlurStrengthPropertyIndex(), ShadowBlurStrengthConstraint( mPageSize.width*PAGE_TURN_OVER_THRESHOLD_RATIO ) );
- shadowBlurStrengthConstraint.AddSource( Source(mTurnEffect[mIndex], mTurnEffect[mIndex].GetPropertyIndex("uCurrentCenter")) );
- shadowBlurStrengthConstraint.AddSource( Source(mTurnEffect[mIndex], mTurnEffect[mIndex].GetPropertyIndex("uOriginalCenter")) );
- shadowBlurStrengthConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) );
+ shadowBlurStrengthConstraint.AddSource( Source(mPages[mIndex].actor, mPages[mIndex].propertyCurrentCenter) );
+ shadowBlurStrengthConstraint.AddSource( Source(mPages[mIndex].actor, mPages[mIndex].propertyOriginalCenter) );
+ shadowBlurStrengthConstraint.AddSource( Source(mPages[mIndex].actor, mPages[mIndex].propertyPanDisplacement) );
shadowBlurStrengthConstraint.Apply();
}
}
{
// set the property values used by the constraints
mPanDisplacement = mPageSize.width*PAGE_TURN_OVER_THRESHOLD_RATIO - currentCenter.x;
- Self().SetProperty( mPropertyPanDisplacement[mIndex], mPanDisplacement );
- Self().SetProperty( mPropertyCurrentCenter[mIndex], currentCenter );
+ mPages[mIndex].SetPanDisplacement( mPanDisplacement );
+ mPages[mIndex].SetPanCenter( currentCenter );
// set up the OriginalCenterConstraint and CurrentCebterConstraint to the PageTurnEdffect
// also set up the RotationConstraint to the page actor
- if( mConstraints )
+ if( !mConstraints )
{
Vector2 corner;
// the corner position need to be a little far away from the page edge to ensure the whole page is lift up
offset *= k;
Actor self = Self();
- Property::Index shaderOriginalCenterPropertyIndex = mTurnEffect[mIndex].GetPropertyIndex("uOriginalCenter");
- Constraint originalCenterConstraint = Constraint::New<Vector2>( mTurnEffect[mIndex], shaderOriginalCenterPropertyIndex, OriginalCenterConstraint( mOriginalCenter, offset ));
- originalCenterConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) );
+ Constraint originalCenterConstraint = Constraint::New<Vector2>( mPages[mIndex].actor, mPages[mIndex].propertyOriginalCenter, OriginalCenterConstraint( mOriginalCenter, offset ));
+ originalCenterConstraint.AddSource( Source( mPages[mIndex].actor, mPages[mIndex].propertyPanDisplacement ) );
originalCenterConstraint.Apply();
- Property::Index shaderCurrentCenterPropertyIndex = mTurnEffect[mIndex].GetPropertyIndex("uCurrentCenter");
- Constraint currentCenterConstraint = Constraint::New<Vector2>( mTurnEffect[mIndex], shaderCurrentCenterPropertyIndex, CurrentCenterConstraint(mPageSize.width));
- currentCenterConstraint.AddSource( Source(self, mPropertyCurrentCenter[mIndex]) );
- currentCenterConstraint.AddSource( Source(mTurnEffect[mIndex], shaderOriginalCenterPropertyIndex) );
+ Constraint currentCenterConstraint = Constraint::New<Vector2>( mPages[mIndex].actor, mPages[mIndex].propertyCurrentCenter, CurrentCenterConstraint(mPageSize.width));
+ currentCenterConstraint.AddSource( Source( mPages[mIndex].actor, mPages[mIndex].propertyPanCenter ) );
+ currentCenterConstraint.AddSource( Source( mPages[mIndex].actor, mPages[mIndex].propertyOriginalCenter ) );
currentCenterConstraint.Apply();
- PageTurnApplyInternalConstraint(mTurnEffect[mIndex]);
+ PageTurnApplyInternalConstraint( mPages[mIndex].actor, mPageSize.height );
float distance = offset.Length();
- Constraint rotationConstraint = Constraint::New<Quaternion>( mPanActor, Actor::Property::ORIENTATION, RotationConstraint(distance, mPageSize.width, mIsTurnBack[mPanActor]));
- rotationConstraint.AddSource( Source( self, mPropertyPanDisplacement[mIndex] ) );
+ Constraint rotationConstraint = Constraint::New<Quaternion>( mPages[mIndex].actor, Actor::Property::ORIENTATION, RotationConstraint(distance, mPageSize.width, mPages[mIndex].isTurnBack));
+ rotationConstraint.AddSource( Source( mPages[mIndex].actor, mPages[mIndex].propertyPanDisplacement ) );
rotationConstraint.Apply();
- mConstraints = false;
+ mConstraints = true;
}
}
else
{
- if(!mConstraints) // remove the constraint is the pan position move back to far away from the spine
+ if(mConstraints) // remove the constraint is the pan position move back to far away from the spine
{
- mPanActor.RemoveConstraints();
- mTurnEffect[mIndex].RemoveConstraints();
- mTurnEffect[mIndex].SetUniform("uOriginalCenter",mOriginalCenter );
- mConstraints = true;
+ mPages[mIndex].actor.RemoveConstraints();
+ mPages[mIndex].SetOriginalCenter(mOriginalCenter );
+ mConstraints = false;
mPanDisplacement = 0.f;
}
- mTurnEffect[mIndex].SetUniform("uCurrentCenter", currentCenter );
+ mPages[mIndex].SetCurrentCenter( currentCenter );
mCurrentCenter = currentCenter;
- PageTurnApplyInternalConstraint(mTurnEffect[mIndex]);
+ PageTurnApplyInternalConstraint(mPages[mIndex].actor, mPageSize.height );
}
}
}
// Guard against destruction during signal emission
Toolkit::PageTurnView handle( GetOwner() );
- if( !mPanActor )
+ if( mTurningPageIndex == -1 )
{
- if(!mIsAnimating[mIndex])
+ if( mAnimatingCount< MAXIMUM_TURNING_NUM && mSlidingCount < 1)
{
OnPossibleOutwardsFlick( gesturePosition, gestureSpeed );
}
+
return;
}
mPagePanFinishedSignal.Emit( handle );
- ImageActor actor = mPanActor;
if(mPress)
{
- if(!mConstraints) // if with constraints, the pan finished position is near spine, set up an animation to turn the page over
+ if(mConstraints) // if with constraints, the pan finished position is near spine, set up an animation to turn the page over
{
// update the pages here instead of in the TurnedOver callback function
// as new page is allowed to respond to the pan gesture before other pages finishing animation
- if(mIsTurnBack[actor])
+ if(mPages[mIndex].isTurnBack)
{
mCurrentPageIndex--;
RemovePage( mCurrentPageIndex+NUMBER_OF_CACHED_PAGES_EACH_SIDE );
OrganizePageDepth();
// set up an animation to turn the page over
- Actor self = Self();
float width = mPageSize.width*(1.f+PAGE_TURN_OVER_THRESHOLD_RATIO);
Animation animation = Animation::New( std::max(0.1f,PAGE_TURN_OVER_ANIMATION_DURATION * (1.0f - mPanDisplacement / width)) );
- animation.AnimateTo( Property(self, mPropertyPanDisplacement[mIndex]),
+ animation.AnimateTo( Property(mPages[mIndex].actor, mPages[mIndex].propertyPanDisplacement),
width,AlphaFunction::EASE_OUT_SINE);
- animation.AnimateTo( Property(self, mPropertyCurrentCenter[mIndex]),
+ animation.AnimateTo( Property(mPages[mIndex].actor, mPages[mIndex].propertyPanCenter),
Vector2(-mPageSize.width*1.1f, 0.5f*mPageSize.height), AlphaFunction::EASE_OUT_SINE);
mAnimationPageIdPair[animation] = mTurningPageIndex;
- mAnimationIndexPair[animation] = mIndex;
animation.Play();
animation.FinishedSignal().Connect( this, &PageTurnView::TurnedOver );
}
else // the pan finished position is far away from the spine, set up an animation to slide the page back instead of turning over
{
Animation animation= Animation::New( PAGE_SLIDE_BACK_ANIMATION_DURATION * (mOriginalCenter.x - mCurrentCenter.x) / mPageSize.width / PAGE_TURN_OVER_THRESHOLD_RATIO );
- animation.AnimateTo( Property( mTurnEffect[mIndex], "uCurrentCenter" ),
+ animation.AnimateTo( Property( mPages[mIndex].actor, mPages[mIndex].propertyCurrentCenter ),
mOriginalCenter, AlphaFunction::LINEAR );
mAnimationPageIdPair[animation] = mTurningPageIndex;
- mAnimationIndexPair[animation] = mIndex;
animation.Play();
- mIsSliding[mIndex] = true;
+ mSlidingCount++;
animation.FinishedSignal().Connect( this, &PageTurnView::SliddenBack );
- mPageTurnStartedSignal.Emit( handle, static_cast<unsigned int>(mTurningPageIndex), mIsTurnBack[actor] );
+ mPageTurnStartedSignal.Emit( handle, static_cast<unsigned int>(mTurningPageIndex), mPages[mIndex].isTurnBack );
}
}
else
// In landscape view, nothing to do
OnPossibleOutwardsFlick( gesturePosition, gestureSpeed );
}
-
mPageUpdated = true;
}
void PageTurnView::TurnedOver( Animation& animation )
{
int pageId = mAnimationPageIdPair[animation];
- ImageActor actor = mPageActors[pageId % NUMBER_OF_CACHED_PAGES];
- mIsTurnBack[actor] = !mIsTurnBack[actor];
- actor.RemoveConstraints();
- Self().Add(actor);
- int index = mAnimationIndexPair[animation];
- mIsAnimating[index] = false;
- mTurnEffect[index].RemoveConstraints();
- mAnimationIndexPair.erase( animation );
+ int index = pageId%NUMBER_OF_CACHED_PAGES;
+
+ mPages[index].ChangeTurnDirection();
+ mPages[index].actor.RemoveConstraints();
+ Self().Add(mPages[index].actor);
+ mAnimatingCount--;
mAnimationPageIdPair.erase( animation );
- SetSpineEffect( actor, mIsTurnBack[actor] );
+ float degree = mPages[index].isTurnBack ? 180.f : 0.f;
+ mPages[index].actor.SetOrientation( Degree(degree), Vector3::YAXIS );
+ mPages[index].UseEffect( mSpineEffectShader );
- int id = pageId + (mIsTurnBack[actor]? -1 : 1);
+ int id = pageId + (mPages[index].isTurnBack ? -1 : 1);
if( id >=0 && id < mTotalPageCount )
{
- mPageActors[id%NUMBER_OF_CACHED_PAGES].SetVisible(false);
+ mPages[id%NUMBER_OF_CACHED_PAGES].actor.SetVisible(false);
}
- OnTurnedOver( actor, mIsTurnBack[actor] );
+ OnTurnedOver( mPages[index].actor, mPages[index].isTurnBack );
// Guard against destruction during signal emission
Toolkit::PageTurnView handle( GetOwner() );
- mPageTurnFinishedSignal.Emit( handle, static_cast<unsigned int>(pageId), mIsTurnBack[actor] );
+ mPageTurnFinishedSignal.Emit( handle, static_cast<unsigned int>(pageId), mPages[index].isTurnBack );
}
void PageTurnView::SliddenBack( Animation& animation )
{
int pageId = mAnimationPageIdPair[animation];
- ImageActor actor = mPageActors[pageId % NUMBER_OF_CACHED_PAGES];
- Self().Add(actor);
- int index = mAnimationIndexPair[animation];
- mIsSliding[index] = false;
- mIsAnimating[index] = false;
- mAnimationIndexPair.erase( animation );
+ int index = pageId%NUMBER_OF_CACHED_PAGES;
+ Self().Add(mPages[index].actor);
+ mSlidingCount--;
+ mAnimatingCount--;
mAnimationPageIdPair.erase( animation );
- SetSpineEffect( actor, mIsTurnBack[actor] );
+ mPages[index].UseEffect( mSpineEffectShader );
- int id = pageId + (mIsTurnBack[actor]? -1 : 1);
+ int id = pageId + (mPages[index].isTurnBack ? -1 : 1);
if( id >=0 && id < mTotalPageCount )
{
- mPageActors[id%NUMBER_OF_CACHED_PAGES].SetVisible(false);
+ mPages[id%NUMBER_OF_CACHED_PAGES].actor.SetVisible(false);
}
// Guard against destruction during signal emission
Toolkit::PageTurnView handle( GetOwner() );
- mPageTurnFinishedSignal.Emit( handle, static_cast<unsigned int>(pageId), mIsTurnBack[actor] );
+ mPageTurnFinishedSignal.Emit( handle, static_cast<unsigned int>(pageId), mPages[index].isTurnBack );
}
void PageTurnView::OrganizePageDepth()
{
if(mCurrentPageIndex+i < mTotalPageCount)
{
- mPageActors[( mCurrentPageIndex+i )%NUMBER_OF_CACHED_PAGES].SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
+ mPages[( mCurrentPageIndex+i )%NUMBER_OF_CACHED_PAGES].actor.SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
}
if( mCurrentPageIndex >= i + 1 )
{
- mPageActors[( mCurrentPageIndex-i-1 )%NUMBER_OF_CACHED_PAGES].SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
+ mPages[( mCurrentPageIndex-i-1 )%NUMBER_OF_CACHED_PAGES].actor.SetZ( -static_cast<float>( i )*STATIC_PAGE_INTERVAL_DISTANCE );
}
}
}
-void PageTurnView::SetShaderEffect( ImageActor actor, ShaderEffect shaderEffect )
+void PageTurnView::StopTurning()
{
- SetShaderEffectRecursively( actor, shaderEffect );
+ mAnimatingCount = 0;
+ mSlidingCount = 0;
+
+ if( !mPageUpdated )
+ {
+ int index = mTurningPageIndex % NUMBER_OF_CACHED_PAGES;
+ Self().Add( mPages[ index ].actor );
+ mPages[ index ].actor.RemoveConstraints();
+ mPages[ index ].UseEffect( mSpineEffectShader );
+ float degree = mTurningPageIndex==mCurrentPageIndex ? 0.f :180.f;
+ mPages[index].actor.SetOrientation( Degree(degree), Vector3::YAXIS );
+ mPageUpdated = true;
+ }
+
+ if( !mAnimationPageIdPair.empty() )
+ {
+ for (std::map<Animation,int>::iterator it=mAnimationPageIdPair.begin(); it!=mAnimationPageIdPair.end(); ++it)
+ {
+ static_cast<Animation>(it->first).SetCurrentProgress( 1.f );
+ }
+ }
}
Toolkit::PageTurnView::PageTurnSignal& PageTurnView::PageTurnStartedSignal()
// EXTERNAL INCLUDES
#include <dali/devel-api/common/map-wrapper.h>
#include <dali/public-api/actors/layer.h>
-#include <dali/public-api/actors/camera-actor.h>
-#include <dali/public-api/actors/image-actor.h>
-#include <dali/public-api/images/frame-buffer-image.h>
-#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/devel-api/rendering/renderer.h>
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
protected:
/**
+ * The book page class
+ */
+ struct Page
+ {
+ /**
+ * Constructor
+ */
+ Page();
+ /**
+ * Destructor
+ */
+ ~Page(){};
+
+ /**
+ * Set the page image content
+ * @param[in] image The content of the page.
+ */
+ void SetImage( Image image );
+
+ /**
+ * Apply an effect onto the page actor.
+ * @param[in] shader The shader for rendering effect.
+ */
+ void UseEffect(Shader shader);
+
+ /**
+ * Apply an effect onto the page actor.
+ * @param[in] shader The shader for rendering effect.
+ * @param[in] geometry The geometry for rendering effect.
+ */
+ void UseEffect(Shader shader, Geometry geometry);
+
+ /**
+ * Change the page turning direction.
+ */
+ void ChangeTurnDirection();
+
+ /**
+ * Set the pan displacement property
+ * @param[in] value The property value
+ */
+ void SetPanDisplacement(float value);
+
+ /**
+ * Set the pan center property
+ * @param[in] value The property value
+ */
+ void SetPanCenter( const Vector2& value );
+
+ /**
+ * Set the original center property to be used by shader
+ * @param[in] value The property value
+ */
+ void SetOriginalCenter( const Vector2& value );
+
+ /**
+ * Set the current center property to be used by shader
+ * @param[in] value The property value
+ */
+ void SetCurrentCenter( const Vector2& value );
+
+ Actor actor; ///< The page actor
+ Material material; ///< The material of the actor
+ Renderer renderer; ///< The renderer of the actor
+ bool isTurnBack; ///< The turning direction
+ Property::Index propertyPanDisplacement; ///< The horizontal displacement of the pan
+ Property::Index propertyPanCenter; ///< The current pan position
+ Property::Index propertyOriginalCenter; ///< The original center to be used by the shader
+ Property::Index propertyCurrentCenter; ///< The current center to be used by the shader
+ Property::Index propertyTurnDirection; ///< The turning direction property
+ };
+
+
+protected:
+
+ /**
* Constructor.
* It initializes the PageTurnView members
*/
*/
void OrganizePageDepth();
+private:
+
/**
- * Set shader Effect to the actor.
- * If the actor has children, the shader effect is also applied to its first child
- * @param[in] actor The actor which the shader effect would be applied onto
- * @param[in] shaderEffect The shader effect to be set to the actor
+ * Create shader from a property map.
+ * @param[in] shaderMap The shader property map;
+ * @return The created shader.
*/
- void SetShaderEffect( ImageActor actor, ShaderEffect shaderEffect );
-
-private:
+ Shader CreateShader( const Property::Map& shaderMap );
/**
* Set up the shadow view control to cast shadow
*/
void SliddenBack( Animation& animation );
+ /**
+ * Stop the page turning animation and contraint.
+ * This method should be called when taking off stage or jump to a specified page.
+ */
+ void StopTurning();
private: // from Control
* @param[in] newPage The added page actor
* @param[in] isLeftSide Which side the new page is added to
*/
- virtual void OnAddPage( ImageActor newPage, bool isLeftSide ) { }
+ virtual void OnAddPage( Actor newPage, bool isLeftSide ) { }
/**
* This method is called when pan started or continuing
virtual void SetPanActor( const Vector2& panPosition ) = 0;
/**
- * This method is called when a page is turned over or slidden back
- * Remove PageTurnEffect and use a proper PageTurnBookSpineEffect
- * Implemented in subclasses to provide specific behaviour.
- * @param[in] actor The current page actor
- * @param[in] isLeftSide Which side the current page is located
- */
- virtual void SetSpineEffect(ImageActor actor, bool isLeftSide) = 0;
-
- /**
* This method is called when pan finished to detect outwards flick
* In portrait view, start an animation of turning previous page back when outwards flick is detected
* In landscape view, nothing to do
* @param[in] actor The page actor
* @param[in] isLeftSide Which side the page is turned to
*/
- virtual void OnTurnedOver( ImageActor actor, bool isLeftSide ) { }
+ virtual void OnTurnedOver( Actor actor, bool isLeftSide ) { }
public: //signal and property
protected:
- Vector2 mControlSize; ///< The size of the control, it is decided by the page size, the SetSize from application can not change it
Layer mTurningPageLayer; ///< The layer for the turning page, to avoid possible depth conflict
Toolkit::ShadowView mShadowView; ///< The shadow view control for shadow casting
Actor mShadowPlaneBackground; ///< The plane for the shadow to cast on
Actor mPointLight; ///< The point light used for shadow casting
- PageFactory& mPageFactory; ///< The page factory which provides the page actors
- Vector2 mPageSize; ///< The page size
- int mTotalPageCount; ///< The total number of pages provided by the page factory
+ PageFactory* const mPageFactory; ///< The factory which provides the page actors
+ Shader mTurnEffectShader; ///< The group of PageTurnEffects
+ Shader mSpineEffectShader; ///< The book spine shader effect
+ Geometry mGeometry; ///< The grid geometry for pages
- bool mPanning; ///< The boolean to indicate whether the pan gesture is continuing
+ std::vector<Page> mPages; ///< The vector of pages on stage
+ std::map<Animation,int> mAnimationPageIdPair; ///< The map to keep track which page actor is the animation act on
- std::vector<ShaderEffect> mTurnEffect; ///< The group of PageTurnEffects
- ShaderEffect mSpineEffectFront; ///< The book spine shader effect without flipping image content
- ShaderEffect mSpineEffectBack; ///< The book spine shader effect with image content flipped
+ Vector2 mPageSize; ///< The page size
+ Vector2 mControlSize; ///< The size of the control, it is decided by the page size, the SetSize from application can not change it
Vector2 mSpineShadowParameter; ///< The spine shadow parameter for all the above shader effects
Vector2 mOriginalCenter; ///< The original center set to the PageTurnEffect
Vector2 mCurrentCenter; ///< The current center set to the PageTurnEffect
-
- std::vector<ImageActor> mPageActors; ///< The vector of pages on stage
- int mCurrentPageIndex; ///< The index of the current page, between 0 ~ mTotalPageCount-1
- int mTurningPageIndex; ///< The index of the turning page
- std::map<ImageActor,bool> mIsTurnBack; ///< The map to keep track the page actor's turning direction
- std::map<Animation,int> mAnimationPageIdPair; ///< The map to keep track which page actor is the animation act on
- std::map<Animation, int> mAnimationIndexPair; ///< The map to keep track which PageTurnEffect, PanDisplacementProperty, CurrentCenterProperty is used for the animation
- int mIndex; ///< The index to keep track which PageTurnEffect, PanDisplacementProperty, CurrentCenterProperty is used for the current panning page
- std::vector<bool> mIsAnimating; ///< The boolean vector to keep track which PageTurnEffect, PanDisplacementProperty, CurrentCenterProperty is available for using
- std::vector<bool> mIsSliding; ///< The boolean vector to keep track whether there are animating pages sliding back
-
- ImageActor mPanActor; ///< The page being panned by the pan gesture
Vector2 mPressDownPosition; ///< The first press down position of the pan gesture
- bool mPress; ///< The boolean to keep track the state of the pageTurnEffect is activated or not
- bool mPageUpdated; ///< The boolean to keep track whether is page is updated after any turning activity
float mDistanceUpCorner; ///< The distance between the original center of PageTurnEffect and the top-left corner of the page
float mDistanceBottomCorner; ///< The distance between the original center of PageTurnEffect and the bottom-left corner of the page
-
- std::vector<Property::Index> mPropertyPanDisplacement; ///< The pan displacement property group
- std::vector<Property::Index> mPropertyCurrentCenter; ///< The current center property group
float mPanDisplacement; ///< The displacement of the pan after the constrains are applied
+
+ int mTotalPageCount; ///< The total number of pages provided by the page factory
+ int mCurrentPageIndex; ///< The index of the current page, between 0 ~ mTotalPageCount-1
+ int mTurningPageIndex; ///< The index of the turning page
+ int mIndex; ///< The index to keep track which PanDisplacementProperty, CurrentCenterProperty is used for the current panning page
+ int mSlidingCount; ///< The boolean vector to keep track whether there are animating pages sliding back
+ int mAnimatingCount; ///< The boolean vector to keep track which PageTurnEffect, PanDisplacementProperty, CurrentCenterProperty is available for using
+
bool mConstraints; ///< The boolean to keep track the constrains are applied or not
+ bool mPress; ///< The boolean to keep track the state of the pageTurnEffect is activated or not
+ bool mPageUpdated; ///< The boolean to keep track whether is page is updated after any turning activity
Toolkit::PageTurnView::PageTurnSignal mPageTurnStartedSignal; ///< The signal to notify that a page has started turning
Toolkit::PageTurnView::PageTurnSignal mPageTurnFinishedSignal; ///< The signal to notify that a page has finished turning
Toolkit::PageTurnView::PagePanSignal mPagePanStartedSignal; ///< The signal to notify that a page has started panning
Toolkit::PageTurnView::PagePanSignal mPagePanFinishedSignal; ///< The signal to notify that a page has finished panning
+ static const char * const PROPERTY_TEXTURE_WIDTH; ///< The uniform name of texture width
+ static const char * const PROPERTY_ORIGINAL_CENTER; ///< The property name of original center, which is used to constrain the uniforms
+ static const char * const PROPERTY_CURRENT_CENTER; ///< The property name of current center, which is used to constrain the uniforms
+
static const int MAXIMUM_TURNING_NUM; ///< How many pages are allowed to animating in the same time
static const int NUMBER_OF_CACHED_PAGES_EACH_SIDE; ///< The maximum number of pages kept, (MAXIMUM_ANIMATION_NUM+1) pages for each side
static const int NUMBER_OF_CACHED_PAGES; ///< The maximum number of pages kept, (MAXIMUM_ANIMATION_NUM+1)*2 pages in total
}\n
);
-
-Geometry GenerateGeometry( const Vector< Vector2 >& vertices, const Vector< unsigned int >& indices )
-{
- Property::Map vertexFormat;
- vertexFormat[ "aPosition" ] = Property::VECTOR2;
- PropertyBuffer vertexPropertyBuffer = PropertyBuffer::New( vertexFormat );
- if( vertices.Size() > 0 )
- {
- vertexPropertyBuffer.SetData( &vertices[ 0 ], vertices.Size() );
- }
-
- Property::Map indexFormat;
- indexFormat[ "indices" ] = Property::INTEGER;
- PropertyBuffer indexPropertyBuffer = PropertyBuffer::New( indexFormat );
- if( indices.Size() > 0 )
- {
- indexPropertyBuffer.SetData( &indices[ 0 ], indices.Size() );
- }
-
- // Create the geometry object
- Geometry geometry = Geometry::New();
- geometry.AddVertexBuffer( vertexPropertyBuffer );
- geometry.SetIndexBuffer( indexPropertyBuffer );
- geometry.SetGeometryType( Geometry::TRIANGLE_STRIP );
-
- return geometry;
-}
-
Geometry CreateGeometry( RendererFactoryCache& factoryCache, ImageDimensions gridSize )
{
Geometry geometry;
geometry = factoryCache.GetGeometry( RendererFactoryCache::QUAD_GEOMETRY );
if( !geometry )
{
- geometry = factoryCache.CreateQuadGeometry();
+ geometry = RendererFactoryCache::CreateQuadGeometry();
factoryCache.SaveGeometry( RendererFactoryCache::QUAD_GEOMETRY, geometry );
}
}
else
{
- uint16_t gridWidth = gridSize.GetWidth();
- uint16_t gridHeight = gridSize.GetHeight();
-
- // Create vertices
- Vector< Vector2 > vertices;
- vertices.Reserve( ( gridWidth + 1 ) * ( gridHeight + 1 ) );
-
- for( int y = 0; y < gridHeight + 1; ++y )
- {
- for( int x = 0; x < gridWidth + 1; ++x )
- {
- vertices.PushBack( Vector2( (float)x/gridWidth - 0.5f, (float)y/gridHeight - 0.5f) );
- }
- }
-
- // Create indices
- Vector< unsigned int > indices;
- indices.Reserve( (gridWidth+2)*gridHeight*2 - 2);
-
- for( unsigned int row = 0u; row < gridHeight; ++row )
- {
- unsigned int rowStartIndex = row*(gridWidth+1u);
- unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u;
-
- if( row != 0u ) // degenerate index on non-first row
- {
- indices.PushBack( rowStartIndex );
- }
-
- for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip
- {
- indices.PushBack( rowStartIndex + column);
- indices.PushBack( nextRowStartIndex + column);
- }
-
- if( row != gridHeight-1u ) // degenerate index on non-last row
- {
- indices.PushBack( nextRowStartIndex + gridWidth );
- }
- }
-
- return GenerateGeometry( vertices, indices );
+ geometry = RendererFactoryCache::CreateGridGeometry( gridSize );
}
return geometry;
QuadVertex quadVertexData[4] =
{
{ Vector2(-halfWidth, -halfHeight) },
- { Vector2( halfWidth, -halfHeight) },
{ Vector2(-halfWidth, halfHeight) },
+ { Vector2( halfWidth, -halfHeight) },
{ Vector2( halfWidth, halfHeight) }
};
}
}
+Geometry RendererFactoryCache::CreateGridGeometry( Uint16Pair gridSize )
+{
+ uint16_t gridWidth = gridSize.GetWidth();
+ uint16_t gridHeight = gridSize.GetHeight();
+
+ // Create vertices
+ Vector< Vector2 > vertices;
+ vertices.Reserve( ( gridWidth + 1 ) * ( gridHeight + 1 ) );
+
+ for( int y = 0; y < gridHeight + 1; ++y )
+ {
+ for( int x = 0; x < gridWidth + 1; ++x )
+ {
+ vertices.PushBack( Vector2( (float)x/gridWidth - 0.5f, (float)y/gridHeight - 0.5f) );
+ }
+ }
+
+ // Create indices
+ Vector< unsigned int > indices;
+ indices.Reserve( (gridWidth+2)*gridHeight*2 - 2);
+
+ for( unsigned int row = 0u; row < gridHeight; ++row )
+ {
+ unsigned int rowStartIndex = row*(gridWidth+1u);
+ unsigned int nextRowStartIndex = rowStartIndex + gridWidth +1u;
+
+ if( row != 0u ) // degenerate index on non-first row
+ {
+ indices.PushBack( rowStartIndex );
+ }
+
+ for( unsigned int column = 0u; column < gridWidth+1u; column++) // main strip
+ {
+ indices.PushBack( rowStartIndex + column);
+ indices.PushBack( nextRowStartIndex + column);
+ }
+
+ if( row != gridHeight-1u ) // degenerate index on non-last row
+ {
+ indices.PushBack( nextRowStartIndex + gridWidth );
+ }
+ }
+
+ Property::Map vertexFormat;
+ vertexFormat[ "aPosition" ] = Property::VECTOR2;
+ PropertyBuffer vertexPropertyBuffer = PropertyBuffer::New( vertexFormat );
+ if( vertices.Size() > 0 )
+ {
+ vertexPropertyBuffer.SetData( &vertices[ 0 ], vertices.Size() );
+ }
+
+ Property::Map indexFormat;
+ indexFormat[ "indices" ] = Property::INTEGER;
+ PropertyBuffer indexPropertyBuffer = PropertyBuffer::New( indexFormat );
+ if( indices.Size() > 0 )
+ {
+ indexPropertyBuffer.SetData( &indices[ 0 ], indices.Size() );
+ }
+
+ // Create the geometry object
+ Geometry geometry = Geometry::New();
+ geometry.AddVertexBuffer( vertexPropertyBuffer );
+ geometry.SetIndexBuffer( indexPropertyBuffer );
+ geometry.SetGeometryType( Geometry::TRIANGLE_STRIP );
+
+ return geometry;
+}
+
} // namespace Internal
} // namespace Toolkit
#include "svg/svg-rasterize-thread.h"
// EXTERNAL INCLUDES
+#include <dali/public-api/math/uint-16-pair.h>
#include <dali/public-api/object/ref-object.h>
#include <dali/devel-api/rendering/geometry.h>
#include <dali/devel-api/rendering/shader.h>
*/
static Geometry CreateQuadGeometry();
+ /**
+ * Create the grid geometry.
+ * @param[in] gridSize The size of the grid.
+ * @return The created grid geometry.
+ */
+ static Geometry CreateGridGeometry( Uint16Pair gridSize );
+
public:
/**
/**
* @brief PageFactory is an abstract interface for providing image actors to PageTurnView
- * Each image actor is identified by a unique ID, and has a linear order from 0 to GetNumberOfPages()-1
+ * Each page is identified by a unique ID, and has a linear order from 0 to GetNumberOfPages()-1
*
* @SINCE_1_1.4
*/
{
public:
+ class Extension; ///< Forward declare future extension interface
+
/**
* @brief Virtual destructor
* @SINCE_1_1.4
/**
* @brief Query the number of pages available from the factory.
+ *
* The maximum available page has an ID of GetNumberOfPages()-1.
* @SINCE_1_1.4
+ * @return The page count.
*/
virtual unsigned int GetNumberOfPages() = 0;
/**
* @brief Create an actor to represent the page content.
- * @SINCE_1_1.4
+ * @SINCE_1_1.30
+ *
+ * If no valid image provided, a broken image is displayed.
+ * For double-sided page( PageTurnLandscapeView ), the left half of image is used as page front side, and the right half as page back side.
+ *
* @param[in] pageId The ID of the page to create.
* @return An actor, or an uninitialized pointer if the ID is out of range.
*/
- virtual Actor NewPage( unsigned int pageId ) = 0;
+ virtual Image NewPage( unsigned int pageId ) = 0;
+
+ /**
+ * @brief Retrieve the extension for this factory
+ * @SINCE_1_1.30
+ *
+ * @return The extension if available, NULL otherwise.
+ */
+ virtual Extension* GetExtension()
+ {
+ return NULL;
+ }
};
} // namespace Toolkit