#include <stdlib.h>
#include <dali-toolkit-test-suite-utils.h>
+#include <dali-toolkit/internal/text/text-run-container.h>
#include <dali-toolkit/dali-toolkit.h>
#include <toolkit-text-model.h>
namespace
{
+struct CreateParagraphData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ CharacterIndex index; ///< The first character index.
+ Length numberOfCharacters; ///< The number of characters.
+ unsigned int numberOfParagraphs; ///< The expected number of paragraphs.
+ unsigned int* indices; ///< The expected paragraph info indices.
+ unsigned int* numberOfCharactersPerParagraph; ///< The expected number of characters of each paragraph.
+};
+
+struct FindParagraphData
+{
+ std::string description; ///< Description of the test.
+ std::string text; ///< Input text.
+ CharacterIndex index; ///< The first character index.
+ Length numberOfCharacters; ///< The number of characters.
+ unsigned int numberOfParagraphs; ///< The expected number of paragraphs.
+ unsigned int* paragraphs; ///< The expected paragraph info.
+};
struct SetVisualToLogicalMapData
{
unsigned int* visualToLogical; ///< The expected visual to logical conversion table.
};
+bool CreateParagraphTest( const CreateParagraphData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 60.f);
+ Size layoutSize;
+
+ Vector<FontDescriptionRun> fontDescriptionRuns;
+ LayoutOptions options;
+ CreateTextModel( data.text,
+ textArea,
+ fontDescriptionRuns,
+ options,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // 2) Clear the paragraphs.
+ Vector<ParagraphRun>& paragraphs = logicalModel->mParagraphInfo;
+ ClearCharacterRuns( data.index,
+ data.index + data.numberOfCharacters - 1u,
+ paragraphs );
+
+ // 3) Call the LogicalModel::CreateParagraphInfo() method
+ logicalModel->CreateParagraphInfo( data.index,
+ data.numberOfCharacters );
+
+ // 4) Compare the results.
+ if( data.numberOfParagraphs != paragraphs.Count() )
+ {
+ std::cout << " Different number of paragraphs : " << paragraphs.Count() << ", expected : " << data.numberOfParagraphs << std::endl;
+ return false;
+ }
+
+ unsigned int index = 0u;
+ for( Vector<ParagraphRun>::ConstIterator it = paragraphs.Begin(),
+ endIt = paragraphs.End();
+ it != endIt;
+ ++it, ++index )
+ {
+ const ParagraphRun& paragraph( *it );
+
+ if( data.indices[index] != paragraph.characterRun.characterIndex )
+ {
+ std::cout << " Different character index for paragraph : " << index << ", " << paragraph.characterRun.characterIndex << ", expected : " << data.indices[index] << std::endl;
+ return false;
+ }
+ if( data.numberOfCharactersPerParagraph[index] != paragraph.characterRun.numberOfCharacters )
+ {
+ std::cout << " Different number of characters for paragraph : " << index << ", " << paragraph.characterRun.numberOfCharacters << ", expected : " << data.numberOfCharactersPerParagraph[index] << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool FindParagraphTest( const FindParagraphData& data )
+{
+ // 1) Create the model.
+ LogicalModelPtr logicalModel = LogicalModel::New();
+ VisualModelPtr visualModel = VisualModel::New();
+ Size textArea(100.f, 60.f);
+ Size layoutSize;
+
+ Vector<FontDescriptionRun> fontDescriptionRuns;
+ LayoutOptions options;
+ CreateTextModel( data.text,
+ textArea,
+ fontDescriptionRuns,
+ options,
+ layoutSize,
+ logicalModel,
+ visualModel );
+
+ // 2) Find the paragraphs.
+ Vector<ParagraphRunIndex> paragraphs;
+ logicalModel->FindParagraphs( data.index, data.numberOfCharacters, paragraphs );
+
+ // 3) compare the results.
+ if( data.numberOfParagraphs != paragraphs.Count() )
+ {
+ return false;
+ }
+
+ unsigned int index = 0u;
+ for( Vector<ParagraphRunIndex>::ConstIterator it = paragraphs.Begin(),
+ endIt = paragraphs.End();
+ it != endIt;
+ ++it, ++index )
+ {
+ const ParagraphRunIndex paragraphIndex = *it;
+
+ if( paragraphIndex != data.paragraphs[index] )
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool SetVisualToLogicalMapTest( const SetVisualToLogicalMapData& data )
{
std::cout << " testing : " << data.description << std::endl;
} // namespace
//////////////////////////////////////////////////////////
+//
+// UtcDaliCreateParagraph
+// UtcDaliFindParagraph
+// UtcDaliSetVisualToLogicalMap
+//
+//////////////////////////////////////////////////////////
-int UtcDaliSetVisualToLogicalMap(void)
+int UtcDaliCreateParagraph(void)
{
ToolkitTestApplication application;
+ tet_infoline(" UtcDaliCreateParagraph");
+
+ unsigned int paragraphsIndices01[] = { 0u };
+ unsigned int paragraphsNumberOfCharacters01[] = { 0u };
+ unsigned int paragraphsIndices02[] = { 0u, 12u, 17u };
+ unsigned int paragraphsNumberOfCharacters02[] = { 12u, 5u, 1u };
+ unsigned int paragraphsIndices03[] = { 0u, 12u, 17u, 34u };
+ unsigned int paragraphsNumberOfCharacters03[] = { 12u, 5u, 17u ,1u };
+
+ struct CreateParagraphData data[] =
+ {
+ {
+ "Zero characters",
+ "",
+ 0u,
+ 0u,
+ 0u,
+ paragraphsIndices01,
+ paragraphsNumberOfCharacters01,
+ },
+ {
+ "Some paragraphs",
+ "Hello world\ndemo\n\n",
+ 0u,
+ 18u,
+ 3u,
+ paragraphsIndices02,
+ paragraphsNumberOfCharacters02,
+ },
+ {
+ "Some paragraphs. Update the initial paragraphs.",
+ "Hello world\ndemo\nhello world demo\n\n",
+ 0u,
+ 17u,
+ 4u,
+ paragraphsIndices03,
+ paragraphsNumberOfCharacters03,
+ },
+ {
+ "Some paragraphs. Update the mid paragraphs.",
+ "Hello world\ndemo\nhello world demo\n\n",
+ 12u,
+ 5u,
+ 4u,
+ paragraphsIndices03,
+ paragraphsNumberOfCharacters03,
+ },
+ {
+ "Some paragraphs. Update the final paragraphs.",
+ "Hello world\ndemo\nhello world demo\n\n",
+ 17u,
+ 18u,
+ 4u,
+ paragraphsIndices03,
+ paragraphsNumberOfCharacters03,
+ },
+ };
+ const unsigned int numberOfTests = 5u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ // ToolkitTestApplication application;
+ if( !CreateParagraphTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliFindParagraph(void)
+{
+ tet_infoline(" UtcDaliFindParagraph");
+
+ unsigned int paragraphs01[] = {};
+ unsigned int paragraphs02[] = { 0u, 1u, 2u };
+ unsigned int paragraphs03[] = { 0u };
+ unsigned int paragraphs04[] = { 1u };
+ unsigned int paragraphs05[] = { 0u, 1u, 2u };
+
+ struct FindParagraphData data[] =
+ {
+ {
+ "Zero characters",
+ "",
+ 0u,
+ 100u,
+ 0u,
+ paragraphs01,
+ },
+ {
+ "Some paragraphs",
+ "Hello world\ndemo\n\n",
+ 0u,
+ 18u,
+ 3u,
+ paragraphs02
+ },
+ {
+ "Some paragraphs",
+ "Hello world\ndemo\n\n",
+ 0u,
+ 12u,
+ 1u,
+ paragraphs03
+ },
+ {
+ "Some paragraphs",
+ "Hello world\ndemo\n\n",
+ 12u,
+ 5u,
+ 1u,
+ paragraphs04
+ },
+ {
+ "Some paragraphs",
+ "Hello world\ndemo\n\n",
+ 3u,
+ 15u,
+ 3u,
+ paragraphs05
+ },
+ };
+ const unsigned int numberOfTests = 5u;
+
+ for( unsigned int index = 0u; index < numberOfTests; ++index )
+ {
+ ToolkitTestApplication application;
+ if( !FindParagraphTest( data[index] ) )
+ {
+ tet_result(TET_FAIL);
+ }
+ }
+
+ tet_result(TET_PASS);
+ END_TEST;
+}
+
+int UtcDaliSetVisualToLogicalMap(void)
+{
tet_infoline(" UtcDaliSetVisualToLogicalMap");
unsigned int* visualToLogical01 = NULL;
for( unsigned int index = 0u; index < numberOfTests; ++index )
{
+ ToolkitTestApplication application;
if( !SetVisualToLogicalMapTest( data[index] ) )
{
tet_result(TET_FAIL);
utf32.Resize( numberOfCharacters );
- // 2) Set the line break info.
+ // 2) Set the line break info for the whole text.
Vector<LineBreakInfo> lineBreakInfo;
lineBreakInfo.Resize( numberOfCharacters );
- SetLineBreakInfo( utf32, lineBreakInfo );
+ SetLineBreakInfo( utf32,
+ 0u,
+ numberOfCharacters,
+ lineBreakInfo );
+
+ // 3) Update the word text info if it's requested for part of the text.
+ if( ( 0u != data.index ) &&
+ ( numberOfCharacters != data.numberOfCharacters ) )
+ {
+ // Clear part of the line break info.
+ lineBreakInfo.Erase( lineBreakInfo.Begin() + data.index,
+ lineBreakInfo.Begin() + data.index + data.numberOfCharacters );
- // 3) compare the results
+ // Update the word line info.
+ SetLineBreakInfo( utf32,
+ data.index,
+ data.numberOfCharacters,
+ lineBreakInfo );
+ }
+
+ // 4) compare the results
std::ostringstream breakInfo;
for( unsigned int index = 0u; index < numberOfCharacters; ++index )
if( data.breakInfo != breakInfo.str() )
{
- std::cout << " expected : [" << data.breakInfo << "]" << std::endl;
- std::cout << " got : [" << breakInfo.str() << "]" << std::endl;
+ std::cout << " text : [" << data.text << "]" << std::endl;
+ std::cout << " index : " << data.index << std::endl;
+ std::cout << " numberOfCharacters : " << data.numberOfCharacters << std::endl;
+ std::cout << " expected : [" << data.breakInfo << "]" << std::endl;
+ std::cout << " got : [" << breakInfo.str() << "]" << std::endl;
return false;
}
int UtcDaliTextSegnemtationSetLineBreakInfo(void)
{
- ToolkitTestApplication application;
tet_infoline(" UtcDaliTextSegnemtationSetLineBreakInfo");
struct BreakInfoData data[] =
"222222122222221221222212212221222222122222222220",
},
{
+ "Latin script. Update initial paragraphs.",
+ "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+ "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+ "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+ "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+ "Quidam corpora at duo. An eos possim scripserit?",
+ 0u,
+ 141u,
+ "22222122222122222122212222212222212222222222122122221222221222222222122122220"
+ "2221221222212222222122222222221222222122222222122222222122212220"
+ "221222122222122222221222222222122212222221222222212220"
+ "22122222212222222122222222222122221222122222122222222222122222222222212220"
+ "222222122222221221222212212221222222122222222220",
+ },
+ {
+ "Latin script. Update mid paragraphs.",
+ "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+ "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+ "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+ "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+ "Quidam corpora at duo. An eos possim scripserit?",
+ 141u,
+ 128u,
+ "22222122222122222122212222212222212222222222122122221222221222222222122122220"
+ "2221221222212222222122222222221222222122222222122222222122212220"
+ "221222122222122222221222222222122212222221222222212220"
+ "22122222212222222122222222222122221222122222122222222222122222222222212220"
+ "222222122222221221222212212221222222122222222220",
+ },
+ {
+ "Latin script. Update final paragraphs.",
+ "Lorem ipsum dolor sit amet, aeque definiebas ea mei, posse iracundia ne cum.\n"
+ "Usu ne nisl maiorum iudicabit, veniam epicurei oporteat eos an.\n"
+ "Ne nec nulla regione albucius, mea doctus delenit ad!\n"
+ "Et everti blandit adversarium mei, eam porro neglegentur suscipiantur an.\n"
+ "Quidam corpora at duo. An eos possim scripserit?",
+ 195u,
+ 122u,
+ "22222122222122222122212222212222212222222222122122221222221222222222122122220"
+ "2221221222212222222122222222221222222122222222122222222122212220"
+ "221222122222122222221222222222122212222221222222212220"
+ "22122222212222222122222222222122221222122222122222222222122222222222212220"
+ "222222122222221221222212212221222222122222222220",
+ },
+ {
"Japanese script",
"韓国側は北朝鮮当局を通じて米ドルで賃金を支払う。\n"
"国際社会から様々な経済制裁を受ける北朝鮮にとっては出稼ぎ労働などと並んで重要な外貨稼ぎの手段となっている。\n"
"21111112112111111111111211121111111111120",
}
};
- const unsigned int numberOfTests = 4u;
+ const unsigned int numberOfTests = 7u;
for( unsigned int index = 0u; index < numberOfTests; ++index )
{
+ ToolkitTestApplication application;
if( !LineBreakInfoTest( data[index] ) )
{
tet_result(TET_FAIL);
int UtcDaliTextSegnemtationSetWordBreakInfo(void)
{
- ToolkitTestApplication application;
tet_infoline(" UtcDaliTextSegnemtationSetWordBreakInfo");
struct BreakInfoData data[] =
for( unsigned int index = 0u; index < numberOfTests; ++index )
{
+ ToolkitTestApplication application;
if( !WordBreakInfoTest( data[index] ) )
{
tet_result(TET_FAIL);
Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
+ GlyphIndex startGlyphIndex = 0u;
if( 0u != charactersToGlyph.Count() )
{
// The number of glyphs to be removed.
const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
+ startGlyphIndex = charactersToGlyph[data.startIndex];
charactersToGlyph.Erase( charactersToGlyph.Begin() + data.startIndex,
charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters );
// 3) Call the CreateGlyphsPerCharacterTable() function
visualModel->CreateGlyphsPerCharacterTable( data.startIndex,
+ startGlyphIndex,
data.numberOfCharacters );
// 4) Compare the results.
Vector<GlyphIndex>& charactersToGlyph = visualModel->mCharactersToGlyph;
Vector<Length>& glyphsPerCharacter = visualModel->mGlyphsPerCharacter;
+ GlyphIndex startGlyphIndex = 0u;
if( 0u != charactersToGlyph.Count() )
{
// The number of glyphs to be removed.
const Length numberOfGlyphs = charactersToGlyph[data.startIndex + data.numberOfCharacters - 1u] + glyphsPerCharacter[data.startIndex + data.numberOfCharacters - 1u] - charactersToGlyph[data.startIndex];
+ startGlyphIndex = charactersToGlyph[data.startIndex];
charactersToGlyph.Erase( charactersToGlyph.Begin() + data.startIndex,
charactersToGlyph.Begin() + data.startIndex + data.numberOfCharacters );
// 3) Call the CreateCharacterToGlyphTable() function
visualModel->CreateCharacterToGlyphTable( data.startIndex,
+ startGlyphIndex,
data.numberOfCharacters );
// 4) Compare the results.
void DummyControlImplOverride::OnPan(const PanGesture& pan) { panCalled = true; }
void DummyControlImplOverride::OnTap(const TapGesture& tap) { tapCalled = true; }
void DummyControlImplOverride::OnLongPress(const LongPressGesture& longPress) { longPressCalled = true; }
-void DummyControlImplOverride::OnStageConnection( int depth ) { stageConnectionCalled = true; }
-void DummyControlImplOverride::OnStageDisconnection() { stageDisconnectionCalled = true; }
+void DummyControlImplOverride::OnStageConnection( int depth ) { Control::OnStageConnection( depth ); stageConnectionCalled = true; }
+void DummyControlImplOverride::OnStageDisconnection() { stageDisconnectionCalled = true; Control::OnStageDisconnection(); }
void DummyControlImplOverride::OnChildAdd(Actor& child) { childAddCalled = true; }
void DummyControlImplOverride::OnChildRemove(Actor& child) { childRemoveCalled = true; }
-void DummyControlImplOverride::OnSizeSet(const Vector3& targetSize) { sizeSetCalled = true; }
-void DummyControlImplOverride::OnSizeAnimation(Animation& animation, const Vector3& targetSize) { sizeAnimationCalled = true; }
+void DummyControlImplOverride::OnSizeSet(const Vector3& targetSize) { Control::OnSizeSet( targetSize ); sizeSetCalled = true; }
+void DummyControlImplOverride::OnSizeAnimation(Animation& animation, const Vector3& targetSize) { Control::OnSizeAnimation( animation, targetSize ); sizeAnimationCalled = true; }
bool DummyControlImplOverride::OnTouchEvent(const TouchEvent& event) { touchEventCalled = true; return false; }
bool DummyControlImplOverride::OnHoverEvent(const HoverEvent& event) { hoverEventCalled = true; return false; }
bool DummyControlImplOverride::OnWheelEvent(const WheelEvent& event) { wheelEventCalled = true; return false; }
Vector<LineBreakInfo>& lineBreakInfo = logicalModel->mLineBreakInfo;
lineBreakInfo.Resize( numberOfCharacters );
- SetLineBreakInfo( utf32Characters, lineBreakInfo );
+ SetLineBreakInfo( utf32Characters,
+ 0u,
+ numberOfCharacters,
+ lineBreakInfo );
if( 0u == numberOfCharacters )
{
numberOfCharacters,
bidirectionalInfo );
+ // Create the paragraph info.
+ logicalModel->CreateParagraphInfo( 0u,
+ numberOfCharacters );
+
// 6) Set character directions.
Vector<CharacterDirection>& characterDirections = logicalModel->mCharacterDirections;
if( 0u != bidirectionalInfo.Count() )
newParagraphGlyphs );
// Create the 'number of glyphs' per character and the glyph to character conversion tables.
- visualModel->CreateGlyphsPerCharacterTable( 0u, numberOfCharacters );
- visualModel->CreateCharacterToGlyphTable( 0u, numberOfCharacters );
+ visualModel->CreateGlyphsPerCharacterTable( 0u, 0u, numberOfCharacters );
+ visualModel->CreateCharacterToGlyphTable( 0u, 0u, numberOfCharacters );
const Length numberOfGlyphs = glyphs.Count();
EffectsView view;
DALI_TEST_CHECK( !view );
- view = EffectsView::New();
+ view = EffectsView::New( EffectsView::DROP_SHADOW );
DALI_TEST_CHECK( view );
Stage::GetCurrent().Add( view );
+ view.Reset();
+ view = EffectsView::New( EffectsView::EMBOSS );
+ DALI_TEST_CHECK( view );
+
application.SendNotification();
application.Render();
{
ToolkitTestApplication application;
- EffectsView view = EffectsView::New();
+ EffectsView view = EffectsView::New( EffectsView::DROP_SHADOW );
DALI_TEST_CHECK( view );
EffectsView copy( view );
{
ToolkitTestApplication application;
- BaseHandle view = EffectsView::New();
+ BaseHandle view = EffectsView::New( EffectsView::EMBOSS );
DALI_TEST_CHECK( EffectsView::DownCast( view ) );
BaseHandle empty;
END_TEST;
}
-int UtcDaliEffectsViewSetGetTypeP(void)
+// Positive test case for a method
+int UtcDaliEffectsViewAddRemove(void)
{
ToolkitTestApplication application;
+ tet_infoline("UtcDaliGaussianBlurViewAddRemove");
- EffectsView view = EffectsView::New();
- DALI_TEST_CHECK( view.GetType() == EffectsView::INVALID_TYPE );
+ EffectsView view = EffectsView::New( EffectsView::DROP_SHADOW );
+ DALI_TEST_CHECK( view );
- view.SetType( EffectsView::DROP_SHADOW );
- DALI_TEST_CHECK( view.GetType() == EffectsView::DROP_SHADOW );
+ Actor actor = Actor::New();
+ DALI_TEST_CHECK( !actor.OnStage() );
- view.SetType( EffectsView::EMBOSS );
- DALI_TEST_CHECK( view.GetType() == EffectsView::EMBOSS );
- END_TEST;
-}
+ view.SetParentOrigin(ParentOrigin::CENTER);
+ view.SetSize(Stage::GetCurrent().GetSize());
+ view.Add(actor);
+ Stage::GetCurrent().Add(view);
-int UtcDaliEffectsViewSetTypeN(void)
-{
- ToolkitTestApplication application;
+ DALI_TEST_CHECK( actor.OnStage() );
+ DALI_TEST_CHECK( actor.GetParent() );
+ DALI_TEST_CHECK( actor.GetParent() != view );
- EffectsView view;
- try
- {
- view.SetType( EffectsView::DROP_SHADOW );
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
+ view.Remove(actor);
+ DALI_TEST_CHECK( !actor.OnStage() );
END_TEST;
}
-int UtcDaliEffectsViewGetTypeN(void)
+int UtcDaliEffectsViewGetTypeP(void)
{
ToolkitTestApplication application;
- EffectsView view;
- try
- {
- EffectsView::EffectType type = view.GetType();
- (void) type;
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
+ EffectsView view = EffectsView::New( EffectsView::DROP_SHADOW );
+ DALI_TEST_CHECK( view.GetType() == EffectsView::DROP_SHADOW );
+
+ view.Reset();
+ view = EffectsView::New( EffectsView::EMBOSS );
+ DALI_TEST_CHECK( view.GetType() == EffectsView::EMBOSS );
END_TEST;
}
-int UtcDaliEffectsViewEnableP(void)
+int UtcDaliEffectsViewOnStage(void)
{
ToolkitTestApplication application;
- EffectsView view = EffectsView::New();
+ EffectsView view = EffectsView::New(EffectsView::EMBOSS);
+ view.SetSize(100.f, 100.f);
Stage stage = Stage::GetCurrent();
DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
- view.Enable();
+ stage.Add( view );
+ application.SendNotification();
+ application.Render();
DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() > 1 );
END_TEST;
}
-int UtcDaliEffectsViewEnableN(void)
+int UtcDaliEffectsViewOffStage(void)
{
ToolkitTestApplication application;
- EffectsView view;
- try
- {
- view.Enable();
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
-
- END_TEST;
-}
-
-int UtcDaliEffectsViewDisableP(void)
-{
- ToolkitTestApplication application;
-
- EffectsView view = EffectsView::New();
+ EffectsView view = EffectsView::New(EffectsView::DROP_SHADOW);
+ view.SetSize(100.f, 100.f);
Stage stage = Stage::GetCurrent();
DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
- view.Enable();
+ stage.Add( view );
+ application.SendNotification();
+ application.Render();
DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() > 1 );
- view.Disable();
+ stage.Remove( view );
+ application.SendNotification();
+ application.Render();
DALI_TEST_CHECK( stage.GetRenderTaskList().GetTaskCount() == 1 );
END_TEST;
}
-int UtcDaliEffectsViewDisableN(void)
-{
- ToolkitTestApplication application;
-
- EffectsView view;
- try
- {
- view.Disable();
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
-
- END_TEST;
-}
-
int UtcDaliEffectsViewRefreshP(void)
{
ToolkitTestApplication application;
- EffectsView view = EffectsView::New();
+ EffectsView view = EffectsView::New( EffectsView::DROP_SHADOW );
try
{
view.Refresh();
{
ToolkitTestApplication application;
- EffectsView view = EffectsView::New();
+ EffectsView view = EffectsView::New( EffectsView::DROP_SHADOW );
try
{
view.SetPixelFormat( Pixel::RGBA8888 );
END_TEST;
}
-int UtcDaliEffectsViewSetGetOutputImage(void)
-{
- ToolkitTestApplication application;
-
- EffectsView view = EffectsView::New();
- FrameBufferImage image = FrameBufferImage::New();
- DALI_TEST_CHECK( image );
-
- view.SetOutputImage( image );
- DALI_TEST_CHECK( view.GetOutputImage() == image );
-
- // Replace with another image
- FrameBufferImage image2 = FrameBufferImage::New();
- DALI_TEST_CHECK( image2 );
- view.SetOutputImage( image2 );
- DALI_TEST_CHECK( view.GetOutputImage() == image2 );
-
- // Remove output image
- view.SetOutputImage( FrameBufferImage() );
- DALI_TEST_CHECK( ! view.GetOutputImage() );
-
- END_TEST;
-}
-
-int UtcDaliEffectsViewSetOutputImageN(void)
-{
- ToolkitTestApplication application;
-
- EffectsView view;
- try
- {
- view.SetOutputImage( FrameBufferImage::New() );
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
-
- END_TEST;
-}
-
-int UtcDaliEffectsViewGetOutputImageN(void)
+int UtcDaliEffectsViewSizeProperty(void)
{
ToolkitTestApplication application;
- EffectsView view;
- try
- {
- FrameBufferImage image = view.GetOutputImage();
- (void)image;
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
-
- END_TEST;
-}
+ EffectsView view = EffectsView::New( EffectsView::DROP_SHADOW );
-int UtcDaliEffectsViewGetEffectSizePropertyIndexP(void)
-{
- ToolkitTestApplication application;
+ Property::Index idx = view.GetPropertyIndex( "effectSize" );
+ DALI_TEST_EQUALS( idx, (Property::Index)EffectsView::Property::EFFECT_SIZE, TEST_LOCATION );
- EffectsView view = EffectsView::New();
- DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectSizePropertyIndex() );
+ view.SetProperty( idx, 5 );
+ Property::Value value = view.GetProperty( EffectsView::Property::EFFECT_SIZE );
+ int size;
+ DALI_TEST_CHECK( value.Get(size) );
+ DALI_TEST_CHECK( size == 5 );
END_TEST;
}
-int UtcDaliEffectsViewGetEffectSizePropertyIndexN(void)
+int UtcDaliEffectsViewOffsetProperty(void)
{
ToolkitTestApplication application;
- EffectsView view;
- try
- {
- Property::Index index = view.GetEffectSizePropertyIndex();
- (void)index;
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
-
- END_TEST;
-}
-
-int UtcDaliEffectsViewGetEffectStrengthPropertyIndexP(void)
-{
- ToolkitTestApplication application;
-
- EffectsView view = EffectsView::New();
- DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectStrengthPropertyIndex() );
-
- END_TEST;
-}
-
-int UtcDaliEffectsViewGetEffectStrengthPropertyIndexN(void)
-{
- ToolkitTestApplication application;
-
- EffectsView view;
- try
- {
- Property::Index index = view.GetEffectStrengthPropertyIndex();
- (void)index;
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
-
- END_TEST;
-}
-
-int UtcDaliEffectsViewGetEffectOffsetPropertyIndexP(void)
-{
- ToolkitTestApplication application;
-
- EffectsView view = EffectsView::New();
- DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectOffsetPropertyIndex() );
+ EffectsView view = EffectsView::New( EffectsView::EMBOSS );
+ Stage::GetCurrent().Add( view );
- END_TEST;
-}
+ Property::Value value = view.GetProperty( EffectsView::Property::EFFECT_OFFSET );
+ Vector3 offsetValue;
+ DALI_TEST_CHECK( value.Get(offsetValue) );
+ DALI_TEST_EQUALS( offsetValue, Vector3::ZERO, TEST_LOCATION );
-int UtcDaliEffectsViewGetEffectOffsetPropertyIndexN(void)
-{
- ToolkitTestApplication application;
+ Vector3 offsetSet( 2.f, 3.f, 4.f );
+ view.SetProperty( EffectsView::Property::EFFECT_OFFSET, offsetSet);
+ application.SendNotification();
+ application.Render(0);
+ value = view.GetProperty( EffectsView::Property::EFFECT_OFFSET );
+ value.Get(offsetValue);
+ DALI_TEST_EQUALS( offsetValue, offsetSet, TEST_LOCATION );
+
+ Vector3 offsetAnimate( 4.f, 6.f, 8.f );
+ float durationSeconds(0.05f);
+ Animation animation = Animation::New( durationSeconds );
+ animation.AnimateTo( Property(view,EffectsView::Property::EFFECT_OFFSET ), offsetAnimate );
+ animation.Play();
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/);
- EffectsView view;
- try
- {
- Property::Index index = view.GetEffectOffsetPropertyIndex();
- (void)index;
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
+ value = view.GetProperty( EffectsView::Property::EFFECT_OFFSET );
+ value.Get(offsetValue);
+ DALI_TEST_EQUALS( offsetValue, offsetAnimate, TEST_LOCATION );
END_TEST;
}
-int UtcDaliEffectsViewGetEffectColorPropertyIndexP(void)
+int UtcDaliEffectsViewColorProperty(void)
{
ToolkitTestApplication application;
- EffectsView view = EffectsView::New();
- DALI_TEST_CHECK( Property::INVALID_INDEX != view.GetEffectColorPropertyIndex() );
+ EffectsView view = EffectsView::New( EffectsView::DROP_SHADOW );
+ Stage::GetCurrent().Add( view );
- END_TEST;
-}
+ Property::Value value = view.GetProperty( EffectsView::Property::EFFECT_COLOR );
+ Vector4 colorValue;
+ DALI_TEST_CHECK( value.Get(colorValue) );
+ DALI_TEST_EQUALS( colorValue, Color::WHITE, TEST_LOCATION );
-int UtcDaliEffectsViewGetEffectColorPropertyIndexN(void)
-{
- ToolkitTestApplication application;
+ Vector4 colorSet( 0.2f, 0.3f, 0.4f, 0.5f );
+ view.SetProperty( EffectsView::Property::EFFECT_COLOR, colorSet);
+ application.SendNotification();
+ application.Render(0);
+ value = view.GetProperty( EffectsView::Property::EFFECT_COLOR );
+ value.Get(colorValue);
+ DALI_TEST_EQUALS( colorValue, colorSet, TEST_LOCATION );
+
+ Vector4 colorAnimate( 0.5f, 0.6f, 0.8f, 1.f );
+ float durationSeconds(0.05f);
+ Animation animation = Animation::New( durationSeconds );
+ animation.AnimateTo( Property(view,EffectsView::Property::EFFECT_COLOR ), colorAnimate );
+ animation.Play();
+ application.SendNotification();
+ application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/);
- EffectsView view;
- try
- {
- Property::Index index = view.GetEffectColorPropertyIndex();
- (void)index;
- DALI_TEST_CHECK( false ); // Should not get here
- }
- catch( ... )
- {
- DALI_TEST_CHECK( true );
- }
+ value = view.GetProperty( EffectsView::Property::EFFECT_COLOR );
+ value.Get(colorValue);
+ DALI_TEST_EQUALS( colorValue, colorAnimate, TEST_LOCATION );
END_TEST;
}
{
ToolkitTestApplication application;
- EffectsView view = EffectsView::New();
+ EffectsView view = EffectsView::New(EffectsView::DROP_SHADOW);
view.SetBackgroundColor( Color::RED );
DALI_TEST_CHECK( Color::RED == view.GetBackgroundColor() );
{
ToolkitTestApplication application;
- EffectsView view = EffectsView::New();
- FrameBufferImage image = FrameBufferImage::New();
- view.SetOutputImage( image );
- view.Enable();
+ EffectsView view = EffectsView::New(EffectsView::DROP_SHADOW);
+ view.SetSize(100.f, 100.f);
Stage stage = Stage::GetCurrent();
stage.Add( view );
+ application.SendNotification();
+ application.Render();
RenderTaskList renderTaskList = stage.GetRenderTaskList();
DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
- DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
view.SetRefreshOnDemand( true );
DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ONCE );
- DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ONCE );
view.SetRefreshOnDemand( false );
DALI_TEST_CHECK( renderTaskList.GetTask( 1 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
- DALI_TEST_CHECK( renderTaskList.GetTask( 2 ).GetRefreshRate() == RenderTask::REFRESH_ALWAYS );
END_TEST;
}
Stage stage = Stage::GetCurrent();
{
- EffectsView view = EffectsView::New();
+ EffectsView view = EffectsView::New(EffectsView::DROP_SHADOW);
view.SetSize( 200.0f, 200.0f, 0.0f );
stage.Add( view );
- view.Enable();
application.SendNotification();
application.Render();
- view.Disable();
- application.SendNotification();
- application.Render();
-
DALI_TEST_EQUALS( view.GetCurrentSize(), Vector3( 200.0f, 200.0f, 0.0f ), TEST_LOCATION );
}
{
- EffectsView view = EffectsView::New();
- view.SetOutputImage( FrameBufferImage::New( 200, 200 ) );
- view.SetType( EffectsView::EMBOSS );
+ EffectsView view = EffectsView::New(EffectsView::EMBOSS);
view.SetSize( 200.0f, 200.0f, 0.0f );
stage.Add( view );
application.SendNotification();
}
{
- EffectsView view = EffectsView::New();
- view.SetType( EffectsView::DROP_SHADOW );
+ EffectsView view = EffectsView::New(EffectsView::DROP_SHADOW);
view.SetSize( 200.0f, 200.0f, 0.0f );
stage.Add( view );
application.SendNotification();
#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;
+}
namespace Toolkit
{
-EffectsView EffectsView::New()
+EffectsView EffectsView::New( EffectType type )
{
- return Internal::EffectsView::New();
+ EffectsView effectsView = Internal::EffectsView::New();
+ GetImpl(effectsView).SetType( type );
+ return effectsView;
}
EffectsView::EffectsView()
{
}
-void EffectsView::SetType( EffectsView::EffectType type )
-{
- GetImpl(*this).SetType( type );
-}
-
EffectsView::EffectType EffectsView::GetType() const
{
return GetImpl(*this).GetType();
}
-void EffectsView::Enable()
-{
- GetImpl(*this).Enable();
-}
-
-void EffectsView::Disable()
-{
- GetImpl(*this).Disable();
-}
-
void EffectsView::Refresh()
{
GetImpl(*this).Refresh();
GetImpl(*this).SetPixelFormat( pixelFormat );
}
-void EffectsView::SetOutputImage( FrameBufferImage image )
-{
- GetImpl(*this).SetOutputImage( image );
-}
-
-FrameBufferImage EffectsView::GetOutputImage()
-{
- return GetImpl(*this).GetOutputImage();
-}
-
-Property::Index EffectsView::GetEffectSizePropertyIndex() const
-{
- return GetImpl(*this).GetEffectSizePropertyIndex();
-}
-
-Property::Index EffectsView::GetEffectStrengthPropertyIndex() const
-{
- return GetImpl(*this).GetEffectStrengthPropertyIndex();
-}
-
-Property::Index EffectsView::GetEffectOffsetPropertyIndex() const
-{
- return GetImpl(*this).GetEffectOffsetPropertyIndex();
-}
-
-Property::Index EffectsView::GetEffectColorPropertyIndex() const
-{
- return GetImpl(*this).GetEffectColorPropertyIndex();
-}
-
void EffectsView::SetBackgroundColor( const Vector4& color )
{
GetImpl(*this).SetBackgroundColor(color);
*
* Example usage: Applying an emboss effect
* ...
- * EffectsView effectsView = EffectsView::New();
+ * EffectsView effectsView = EffectsView::New( Toolkit::EffectsView::EMBOSS );
*
* // set position and format
* effectsView.SetParentOrigin( ParentOrigin::CENTER );
* effectsView.SetPixelFormat( Pixel::RGBA8888 );
*
* // set effect type and properties
- * effectsView.SetType( Toolkit::EffectsView::EMBOSS );
* effectsView.SetProperty( effectsView.GetEffectSizePropertyIndex(), static_cast< float >( shadowSize ) );
* effectsView.SetProperty( effectsView.GetEffectOffsetPropertyIndex(), Vector3( shadowDistance.x, shadowDistance.y, 0.0f ) );
* effectsView.SetProperty( effectsView.GetEffectColorPropertyIndex(), shadowColor );
*
- * // Render result to an offscreen
- * effectsView.SetOutputImage( image );
- *
* // Render once
* effectsView.SetRefreshOnDemand( true );
*
* // optionally set a clear color
* effectsView.SetBackgroundColor( Vector4( 0.0f, 0.0f, 0.0f, 0.0f ) );
- *
- * // start effect processing
- * effectsView.Enable();
*/
class DALI_IMPORT_API EffectsView : public Control
{
INVALID_TYPE
};
+ /**
+ * @brief The start and end property ranges for this control.
+ */
+ enum PropertyRange
+ {
+ PROPERTY_START_INDEX = Control::CONTROL_PROPERTY_END_INDEX + 1, ///< @SINCE_1_0.0
+ PROPERTY_END_INDEX = PROPERTY_START_INDEX + 1000, ///< Reserve property indices @SINCE_1_0.0
+
+ ANIMATABLE_PROPERTY_START_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX, ///< @SINCE_1_1.18
+ ANIMATABLE_PROPERTY_END_INDEX = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1000 ///< Reserve animatable property indices, @SINCE_1_1.18
+ };
+
+ /**
+ * @brief An enumeration of properties belonging to the EffectsView class.
+ */
+ struct Property
+ {
+ enum
+ {
+ // Event side properties
+ EFFECT_SIZE = PROPERTY_START_INDEX, ///< name "effectSize", type INTEGER
+
+ // Animatable properties
+ EFFECT_OFFSET = ANIMATABLE_PROPERTY_START_INDEX, ///< name "effectOffset", type VECTOR3
+ EFFECT_COLOR, ///< name "effectColor", type VECTOR4
+ };
+ };
+
public:
/**
* Create an EffectsView object with default configuration
+ * @param[in] type The type of effect to be performed by the EffectView.
+ * A member of the EffectType enumeration.
*/
- static EffectsView New();
+ static EffectsView New( EffectType type );
/**
* Create an uninitialized EffectsView. Only derived versions can be instantiated.
public:
/**
- * Set the effect type
- * @param[in] type The type of effect to be performed by the EffectView.
- * A member of the EffectType enumeration.
- */
- void SetType( EffectType type );
-
- /**
* Get the effect type
* @return The type of effect performed by the EffectView. A member of the EffectType enumeration.
*/
EffectType GetType() const;
/**
- * Enable the effect
- */
- void Enable();
-
- /**
- * Disable the effect
- */
- void Disable();
-
- /**
* Refresh/Redraw the effect
*/
void Refresh();
void SetPixelFormat( Pixel::Format pixelFormat );
/**
- * Set the FrameBufferImage that will receive the final output of the EffectsView.
- * @param[in] image User supplied FrameBufferImage that will receive the final output of the EffectsView.
- */
- void SetOutputImage( FrameBufferImage image );
-
- /**
- * Get the FrameBufferImage that holds the final output of the EffectsView.
- * @return The FrameBufferImage that holds the final output of the EffectsView.
- */
- FrameBufferImage GetOutputImage();
-
- /**
- * Get the property index to the effect size
- * @return The property index to the effect size
- */
- Dali::Property::Index GetEffectSizePropertyIndex() const;
-
- /**
- * Get the property index to the effect strength
- * @return The property index to the effect strength
- */
- Dali::Property::Index GetEffectStrengthPropertyIndex() const;
-
- /**
- * Get the property index to the Vector3 specifying the effect offset (eg drop shadow offset)
- * @return The property index to the Vector3 specifying the effect offset
- */
- Dali::Property::Index GetEffectOffsetPropertyIndex() const;
-
- /**
- * Get the property index to the effect color (eg shadow color)
- * @return The property index to the effect color
- */
- Dali::Property::Index GetEffectColorPropertyIndex() const;
-
- /**
* Set background color for the view. The background will be filled with this color.
* @param[in] color The background color.
*/
void BloomView::OnSizeSet(const Vector3& targetSize)
{
+ Control::OnSizeSet( targetSize );
+
mTargetSize = Vector2(targetSize);
mChildrenRoot.SetSize(targetSize);
mCompositeImageActor.SetSize(targetSize);
}
}
-void BloomView::OnControlChildAdd( Actor& child )
+void BloomView::OnChildAdd( Actor& child )
{
+ Control::OnChildAdd( child );
+
if( child != mChildrenRoot && child != mInternalRoot)
{
mChildrenRoot.Add( child );
}
}
-void BloomView::OnControlChildRemove( Actor& child )
+void BloomView::OnChildRemove( Actor& child )
{
mChildrenRoot.Remove( child );
+
+ Control::OnChildRemove( child );
}
void BloomView::AllocateResources()
virtual void OnSizeSet(const Vector3& targetSize);
/**
- * @copydoc Control::OnControlChildAdd()
+ * @copydoc Control::OnChildAdd()
*/
- virtual void OnControlChildAdd( Actor& child );
+ virtual void OnChildAdd( Actor& child );
/**
- * @copydoc Control::OnControlChildRemove()
+ * @copydoc Control::OnChildRemove()
*/
- virtual void OnControlChildRemove( Actor& child );
+ virtual void OnChildRemove( Actor& child );
void AllocateResources();
void CreateRenderTasks();
return false;
}
-void Button::OnButtonStageDisconnection()
-{
- if( ButtonDown == mState )
- {
- if( !mTogglableButton )
- {
- Released();
-
- if( mAutoRepeating )
- {
- mAutoRepeatingTimer.Reset();
- }
- }
- }
-}
-
void Button::OnButtonDown()
{
if( !mTogglableButton )
mTapDetector.Attach( self );
mTapDetector.DetectedSignal().Connect(this, &Button::OnTap);
- OnButtonInitialize();
-
self.SetKeyboardFocusable( true );
}
return ret;
}
-void Button::OnControlStageDisconnection()
+void Button::OnStageDisconnection()
{
- OnButtonStageDisconnection(); // Notification for derived classes.
+ if( ButtonDown == mState )
+ {
+ if( !mTogglableButton )
+ {
+ Released();
+
+ if( mAutoRepeating )
+ {
+ mAutoRepeatingTimer.Reset();
+ }
+ }
+ }
+
mState = ButtonUp;
+
+ Control::OnStageDisconnection();
}
void Button::OnTap(Actor actor, const TapGesture& tap)
bool DoClickAction( const Property::Map& attributes );
/**
- * This method is called after the button initialization.
- * Could be reimplemented in subclasses to provide specific behaviour.
- */
- virtual void OnButtonInitialize() { }
-
- /**
* This method is called when the label is set.
* @param[in] noPadding Used to bypass padding if the label is to be treated generically.
*/
virtual void OnTouchPointInterrupted();
/**
- * This method is called when the button is removed from the stage.
- * Could be reimplemented in subclasses to provide specific behaviour.
- */
- virtual void OnButtonStageDisconnection();
-
- /**
* This method is called when the \e selected property is changed.
*/
virtual void OnSelected() {}
*/
static Property::Value GetProperty( BaseObject* object, Property::Index propertyIndex );
-protected: // From CustomActorImpl
+protected: // From Control
/**
- * @copydoc Dali::CustomActorImpl::OnTouchEvent( const TouchEvent& event )
+ * @copydoc Dali::Control::OnTouchEvent( const TouchEvent& event )
*/
virtual bool OnTouchEvent( const TouchEvent& event );
-private: // From Control
-
/**
* @copydoc Toolkit::Control::OnInitialize()
+ * @note If overridden by deriving button classes, then an up-call to Button::OnInitialize MUST be made at the start.
*/
virtual void OnInitialize();
virtual bool OnKeyboardEnter();
/**
- * Callback received when the button is disconnected from the stage.
- * It resets the button status.
+ * @copydoc Toolkit::Control::OnStageDisconnection()
+ * @note If overridden by deriving button classes, then an up-call to Button::OnStageDisconnection MUST be made at the end.
*/
- void OnControlStageDisconnection();
+ void OnStageDisconnection();
private:
}
}
-void CheckBoxButton::OnButtonInitialize()
+void CheckBoxButton::OnInitialize()
{
+ Button::OnInitialize();
+
// Wrap around all children
Self().SetResizePolicy( ResizePolicy::FIT_TO_CHILDREN, Dimension::ALL_DIMENSIONS );
/**
- * @copydoc Toolkit::Internal::Button::OnButtonInitialize
+ * @copydoc Toolkit::Internal::Button::OnInitialize
*/
- virtual void OnButtonInitialize();
+ virtual void OnInitialize();
/**
* @copydoc Toolkit::Internal::Button::OnLabelSet
{
}
-void PushButton::OnButtonInitialize()
+void PushButton::OnInitialize()
{
+ Button::OnInitialize();
+
// Push button requires the Leave event.
Actor self = Self();
self.SetLeaveRequired( true );
private: // From Button
/**
- * @copydoc Toolkit::Internal::Button::OnButtonInitialize
+ * @copydoc Toolkit::Internal::Button::OnInitialize
*/
- virtual void OnButtonInitialize();
+ virtual void OnInitialize();
/**
* @copydoc Toolkit::Internal::Button::OnLabelSet
{
}
-void RadioButton::OnButtonInitialize()
+void RadioButton::OnInitialize()
{
+ Button::OnInitialize();
+
Actor self = Self();
// Wrap size of radio button around all its children
private: // From Button
/**
- * @copydoc Toolkit::Internal::Button::OnButtonInitialize
+ * @copydoc Toolkit::Internal::Button::OnInitialize
*/
- virtual void OnButtonInitialize();
+ virtual void OnInitialize();
/**
* @copydoc Toolkit::Internal::Button::OnButtonUp
#include <dali/public-api/animation/constraint.h>
#include <dali/public-api/animation/constraints.h>
#include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/property-map.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>
// INTERNAL INCLUDES
-#include "../../filters/blur-two-pass-filter.h"
-#include "../../filters/emboss-filter.h"
-#include "../../filters/spread-filter.h"
+#include <dali-toolkit/devel-api/controls/control-depth-index-ranges.h>
+#include <dali-toolkit/internal/filters/blur-two-pass-filter.h>
+#include <dali-toolkit/internal/filters/emboss-filter.h>
+#include <dali-toolkit/internal/filters/spread-filter.h>
namespace Dali
{
Dali::BaseHandle Create()
{
- return Toolkit::EffectsView::New();
+ return EffectsView::New();
}
DALI_TYPE_REGISTRATION_BEGIN( Toolkit::EffectsView, Toolkit::Control, Create )
+DALI_PROPERTY_REGISTRATION( Toolkit, EffectsView, "effectSize", INTEGER, EFFECT_SIZE )
+DALI_ANIMATABLE_PROPERTY_REGISTRATION( Toolkit, EffectsView, "effectOffset", VECTOR3, EFFECT_OFFSET )
+DALI_ANIMATABLE_PROPERTY_REGISTRATION_WITH_DEFAULT( Toolkit, EffectsView, "effectColor", Color::WHITE, EFFECT_COLOR )
DALI_TYPE_REGISTRATION_END()
const Pixel::Format EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT = Pixel::RGBA8888;
const Vector4 EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR( 1.0f, 1.0f, 1.0f, 0.0 );
const bool EFFECTS_VIEW_REFRESH_ON_DEMAND(false);
-// Custom properties
-const char* const EFFECT_SIZE_PROPERTY_NAME = "EffectSize";
-const char* const EFFECT_STRENGTH_PROPERTY_NAME = "EffectStrength";
-const char* const EFFECT_OFFSET_PROPERTY_NAME = "EffectOffset";
-const char* const EFFECT_COLOR_PROPERTY_NAME = "EffectColor";
-
-const float EFFECT_SIZE_DEFAULT( 1.0f );
-const float EFFECT_STRENGTH_DEFAULT( 0.5f );
-const Vector3 EFFECT_OFFSET_DEFAULT( 0.0f, 0.0f, 0.0f );
-const Vector4 EFFECT_COLOR_DEFAULT( Color::WHITE );
-
-const char* const EFFECTS_VIEW_FRAGMENT_SOURCE =
- "void main()\n"
- "{\n"
- " gl_FragColor = uColor;\n"
- " gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n"
- "}\n";
+const char* EFFECTS_VIEW_VERTEX_SOURCE = DALI_COMPOSE_SHADER(
+ attribute mediump vec2 aPosition;\n
+ varying mediump vec2 vTexCoord;\n
+ uniform mediump mat4 uMvpMatrix;\n
+ uniform mediump vec3 uSize;\n
+ uniform mediump vec3 effectOffset;\n
+ \n
+ void main()\n
+ {\n
+ mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);\n
+ vertexPosition.xyz *= uSize;\n
+ vertexPosition.xyz += effectOffset;\n
+ vertexPosition = uMvpMatrix * vertexPosition;\n
+ \n
+ vTexCoord = aPosition + vec2(0.5);\n
+ gl_Position = vertexPosition;\n
+ }\n
+);
+
+const char* EFFECTS_VIEW_FRAGMENT_SOURCE = DALI_COMPOSE_SHADER(
+ varying mediump vec2 vTexCoord;\n
+ uniform sampler2D sTexture;\n
+ uniform lowp vec4 effectColor;\n
+ \n
+ void main()\n
+ {\n
+ gl_FragColor = effectColor;\n
+ gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n
+ }\n
+);
const float BLUR_KERNEL0[] = { 12.0f/16.0f,
2.0f/16.0f, 2.0f/16.0f };
EffectsView::EffectsView()
: Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
- mEffectType( Toolkit::EffectsView::INVALID_TYPE ),
- mPixelFormat( EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT ),
- mSpread(0.0f),
+ mChildrenRoot(Actor::New()),
mBackgroundColor( EFFECTS_VIEW_DEFAULT_BACKGROUND_COLOR ),
mTargetSize( Vector2::ZERO ),
mLastSize( Vector2::ZERO ),
- mRefreshOnDemand(EFFECTS_VIEW_REFRESH_ON_DEMAND),
- mEffectSizePropertyIndex(Property::INVALID_INDEX),
- mEffectStrengthPropertyIndex(Property::INVALID_INDEX),
- mEffectOffsetPropertyIndex(Property::INVALID_INDEX),
- mEffectColorPropertyIndex(Property::INVALID_INDEX)
+ mEffectSize(0),
+ mEffectType( Toolkit::EffectsView::INVALID_TYPE ),
+ mPixelFormat( EFFECTS_VIEW_DEFAULT_PIXEL_FORMAT ),
+ mEnabled( false ),
+ mRefreshOnDemand(EFFECTS_VIEW_REFRESH_ON_DEMAND)
{
}
{
if( mEffectType != type )
{
- mEffectType = type;
-
RemoveFilters();
- switch( mEffectType )
+ Actor self = Self();
+ Property::Map rendererMap;
+ rendererMap.Insert( "rendererType", "image" );
+
+ switch( type )
{
case Toolkit::EffectsView::DROP_SHADOW:
{
- mFilters.push_back( new SpreadFilter );
- mFilters.push_back( new BlurTwoPassFilter );
+ mFilters.PushBack( new SpreadFilter );
+ mFilters.PushBack( new BlurTwoPassFilter );
break;
}
case Toolkit::EffectsView::EMBOSS:
{
- mFilters.push_back( new SpreadFilter );
- mFilters.push_back( new EmbossFilter );
- mFilters.push_back( new BlurTwoPassFilter );
- mActorPostFilter.RemoveShaderEffect();
+ mFilters.PushBack( new SpreadFilter );
+ mFilters.PushBack( new EmbossFilter );
+ mFilters.PushBack( new BlurTwoPassFilter );
break;
}
default:
break;
}
}
+
+ Property::Map customShader;
+ customShader[ "vertexShader" ] = EFFECTS_VIEW_VERTEX_SOURCE;
+ customShader[ "fragmentShader" ] = EFFECTS_VIEW_FRAGMENT_SOURCE;
+ rendererMap[ "shader" ] = customShader;
+ Toolkit::RendererFactory::Get().ResetRenderer( mRendererPostFilter, self, rendererMap );
+
+ mEffectType = type;
}
}
// make sure resources are allocated and start the render tasks processing
AllocateResources();
CreateRenderTasks();
+ mEnabled = true;
}
void EffectsView::Disable()
// stop render tasks processing
// Note: render target resources are automatically freed since we set the Image::Unused flag
RemoveRenderTasks();
+ mEnabled = false;
}
void EffectsView::Refresh()
mPixelFormat = pixelFormat;
}
-void EffectsView::SetOutputImage( FrameBufferImage image )
-{
- CustomActor self = Self();
-
- if( mImageForResult != image )
- {
- if( !image )
- {
- if( mImageForResult )
- {
- self.Remove( mActorForResult );
- mActorForResult.Reset();
-
- self.Add( mActorPostFilter );
- self.Add( mActorForChildren );
- }
- }
- else
- {
- if( mImageForResult )
- {
- self.Remove( mActorForResult );
- }
- mActorForResult = Actor::New();
- mActorForResult.SetParentOrigin( ParentOrigin::CENTER );
- mActorForResult.SetSize( mTargetSize );
- mActorForResult.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
-
- Self().Add( mActorForResult );
- mActorForResult.Add( mActorPostFilter );
- mActorForResult.Add( mActorForChildren );
- }
- mImageForResult = image;
- }
-}
-
-FrameBufferImage EffectsView::GetOutputImage()
-{
- return mImageForResult;
-}
-
-Property::Index EffectsView::GetEffectSizePropertyIndex() const
-{
- return mEffectSizePropertyIndex;
-}
-
-Property::Index EffectsView::GetEffectStrengthPropertyIndex() const
-{
- return mEffectStrengthPropertyIndex;
-}
-
-Property::Index EffectsView::GetEffectOffsetPropertyIndex() const
+void EffectsView::SetBackgroundColor( const Vector4& color )
{
- return mEffectOffsetPropertyIndex;
+ mBackgroundColor = color;
}
-Property::Index EffectsView::GetEffectColorPropertyIndex() const
+Vector4 EffectsView::GetBackgroundColor() const
{
- return mEffectColorPropertyIndex;
+ return mBackgroundColor;
}
-void EffectsView::SetupProperties()
+void EffectsView::SetEffectSize( int effectSize )
{
- CustomActor self = Self();
+ mEffectSize = effectSize;
- // Register a property that the user can control the drop shadow offset
- mEffectSizePropertyIndex = self.RegisterProperty(EFFECT_SIZE_PROPERTY_NAME, EFFECT_SIZE_DEFAULT, Property::READ_WRITE);
- mEffectStrengthPropertyIndex = self.RegisterProperty(EFFECT_STRENGTH_PROPERTY_NAME, EFFECT_STRENGTH_DEFAULT, Property::READ_WRITE);
- mEffectOffsetPropertyIndex = self.RegisterProperty(EFFECT_OFFSET_PROPERTY_NAME, EFFECT_OFFSET_DEFAULT);
- mEffectColorPropertyIndex = self.RegisterProperty(EFFECT_COLOR_PROPERTY_NAME, EFFECT_COLOR_DEFAULT);
-
- Constraint positionConstraint = Constraint::New<Vector3>( mActorPostFilter, Actor::Property::POSITION, EqualToConstraint() );
- positionConstraint.AddSource( Source( self, mEffectOffsetPropertyIndex ) );
- positionConstraint.Apply();
+ if( mEnabled )
+ {
+ const size_t numFilters( mFilters.Size() );
+ for( size_t i = 0; i < numFilters; ++i )
+ {
+ mFilters[i]->Disable();
+ }
- Constraint colorConstraint = Constraint::New<Vector4>( mActorPostFilter, Actor::Property::COLOR, EqualToConstraint() );
- colorConstraint.AddSource( Source( self, mEffectColorPropertyIndex ) );
- colorConstraint.Apply();
-}
+ SetupFilters();
-void EffectsView::SetBackgroundColor( const Vector4& color )
-{
- mBackgroundColor = color;
+ for( size_t i = 0; i < numFilters; ++i )
+ {
+ mFilters[i]->Enable();
+ }
+ }
}
-Vector4 EffectsView::GetBackgroundColor() const
+int EffectsView::GetEffectSize()
{
- return mBackgroundColor;
+ return mEffectSize;
}
// From Control
void EffectsView::OnInitialize()
{
- //////////////////////////////////////////////////////
- // Create cameras
- mCameraForChildren = CameraActor::New();
- mCameraForChildren.SetParentOrigin(ParentOrigin::CENTER);
-
- mActorForChildren = ImageActor::New();
- mActorForChildren.SetParentOrigin( ParentOrigin::CENTER );
- mActorForChildren.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
-
- mActorPostFilter = ImageActor::New();
- mActorPostFilter.SetParentOrigin( ParentOrigin::CENTER );
- mActorPostFilter.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
- mActorPostFilter.SetShaderEffect( ShaderEffect::New( "", EFFECTS_VIEW_FRAGMENT_SOURCE ) );
-
- // Connect to actor tree
- Self().Add( mActorPostFilter );
- Self().Add( mActorForChildren );
- Self().Add( mCameraForChildren );
-
- SetupProperties();
+ CustomActor self = Self();
+ mChildrenRoot.SetParentOrigin( ParentOrigin::CENTER );
+ self.Add( mChildrenRoot );
}
void EffectsView::OnSizeSet(const Vector3& targetSize)
{
+ Control::OnSizeSet( targetSize );
+
mTargetSize = Vector2(targetSize);
// if we are already on stage, need to update render target sizes now to reflect the new size of this actor
- if(Self().OnStage())
+ if(mEnabled)
{
- AllocateResources();
+ if( mLastSize != Vector2::ZERO )
+ {
+ Disable();
+ }
+ Enable();
}
- if( mActorForResult )
+ mChildrenRoot.SetSize( targetSize );
+}
+
+void EffectsView::OnStageConnection( int depth )
+{
+ Control::OnStageConnection( depth );
+
+ Enable();
+
+ Actor self = Self();
+ if( mRendererPostFilter )
{
- mActorForResult.SetSize( targetSize );
+ mRendererPostFilter.SetOnStage( self );
}
- if( mActorForChildren )
+ if( mRendererForChildren )
{
- mActorForChildren.SetSize( targetSize );
+ mRendererForChildren.SetOnStage( self );
}
- if( mActorPostFilter )
+}
+
+void EffectsView::OnStageDisconnection()
+{
+ Disable();
+
+ const size_t numFilters( mFilters.Size() );
+ for( size_t i = 0; i < numFilters; ++i )
{
- mActorPostFilter.SetSize( targetSize );
+ mFilters[i]->Disable();
}
- // Children render camera must move when EffectsView object is resized.
- // This is since we cannot change render target size - so we need to remap the child actors' rendering
- // accordingly so they still exactly fill the render target.
- // Note that this means the effective resolution of the child render changes as the EffectsView object
- // changes size, this is the trade off for not being able to modify render target size
- // Change camera z position based on EffectsView actor height
- if( mCameraForChildren )
+ Actor self = Self();
+ if( mRendererPostFilter )
{
- const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
- mCameraForChildren.SetZ( targetSize.height * cameraPosScale );
+ mRendererPostFilter.SetOffStage( self );
}
-
- const size_t numFilters( mFilters.size() );
- for( size_t i = 0; i < numFilters; ++i )
+ if( mRendererForChildren )
{
- mFilters[i]->SetSize( mTargetSize );
+ mRendererForChildren.SetOffStage( self );
}
+ Control::OnStageDisconnection();
}
-void EffectsView::OnStageDisconnection()
+void EffectsView::OnChildAdd( Actor& child )
{
- const size_t numFilters( mFilters.size() );
- for( size_t i = 0; i < numFilters; ++i )
+ Control::OnChildAdd( child );
+
+ if( child != mChildrenRoot && child != mCameraForChildren )
{
- mFilters[i]->Disable();
+ mChildrenRoot.Add( child );
}
}
+void EffectsView::OnChildRemove( Actor& child )
+{
+ mChildrenRoot.Remove( child );
+
+ Control::OnChildRemove( child );
+}
+
void EffectsView::SetupFilters()
{
- int effectSize = static_cast< int >( Self().GetProperty( mEffectSizePropertyIndex ).Get<float>() );
switch( mEffectType )
{
case Toolkit::EffectsView::DROP_SHADOW:
SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
spreadFilter->SetInputImage( mImageForChildren );
spreadFilter->SetOutputImage( mImagePostFilter );
- spreadFilter->SetRootActor( Self() );
+ spreadFilter->SetRootActor( mChildrenRoot );
spreadFilter->SetBackgroundColor( mBackgroundColor );
spreadFilter->SetPixelFormat( mPixelFormat );
spreadFilter->SetSize( mTargetSize );
- spreadFilter->SetSpread( effectSize );
+ spreadFilter->SetSpread( mEffectSize );
BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[1] );
blurFilter->SetInputImage( mImagePostFilter );
blurFilter->SetOutputImage( mImagePostFilter );
- blurFilter->SetRootActor( Self() );
+ blurFilter->SetRootActor( mChildrenRoot );
blurFilter->SetBackgroundColor( mBackgroundColor );
blurFilter->SetPixelFormat( mPixelFormat );
blurFilter->SetSize( mTargetSize );
const float* kernel(NULL);
size_t kernelSize(0);
- switch( effectSize )
+ switch( mEffectSize )
{
case 4: { kernel = BLUR_KERNEL4; kernelSize = sizeof(BLUR_KERNEL4)/sizeof(BLUR_KERNEL4[0]); break; }
case 3: { kernel = BLUR_KERNEL3; kernelSize = sizeof(BLUR_KERNEL3)/sizeof(BLUR_KERNEL3[0]); break; }
SpreadFilter* spreadFilter = static_cast< SpreadFilter* >( mFilters[0] );
spreadFilter->SetInputImage( mImageForChildren );
spreadFilter->SetOutputImage( mImagePostFilter );
- spreadFilter->SetRootActor( Self() );
+ spreadFilter->SetRootActor( mChildrenRoot );
spreadFilter->SetBackgroundColor( mBackgroundColor );
spreadFilter->SetPixelFormat( Pixel::RGBA8888 );
spreadFilter->SetSize( mTargetSize );
- spreadFilter->SetSpread( effectSize );
+ spreadFilter->SetSpread( mEffectSize );
EmbossFilter* embossFilter = static_cast< EmbossFilter* >( mFilters[1] );
embossFilter->SetInputImage( mImagePostFilter );
embossFilter->SetOutputImage( mImagePostFilter );
- embossFilter->SetRootActor( Self() );
+ embossFilter->SetRootActor( mChildrenRoot );
embossFilter->SetBackgroundColor( mBackgroundColor );
embossFilter->SetPixelFormat( Pixel::RGBA8888 );
embossFilter->SetSize( mTargetSize );
BlurTwoPassFilter* blurFilter = static_cast< BlurTwoPassFilter* >( mFilters[2] );
blurFilter->SetInputImage( mImagePostFilter );
blurFilter->SetOutputImage( mImagePostFilter );
- blurFilter->SetRootActor( Self() );
+ blurFilter->SetRootActor( mChildrenRoot );
blurFilter->SetBackgroundColor( Vector4( 0.5f, 0.5f, 0.5f, 0.0 ) );
blurFilter->SetPixelFormat( Pixel::RGBA8888 );
blurFilter->SetSize( mTargetSize );
if(mTargetSize != mLastSize)
{
mLastSize = mTargetSize;
-
SetupCameras();
+ Toolkit::RendererFactory rendererFactory = Toolkit::RendererFactory::Get();
+ Actor self = Self();
+
mImageForChildren = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
- mActorForChildren.SetImage(mImageForChildren);
+ rendererFactory.ResetRenderer(mRendererForChildren, self, mImageForChildren);
+ mRendererForChildren.SetDepthIndex( DepthIndex::CONTENT+1 );
mImagePostFilter = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Dali::Image::UNUSED );
- mActorPostFilter.SetImage(mImagePostFilter);
+ rendererFactory.ResetRenderer(mRendererPostFilter, self, mImagePostFilter);
+ mRendererPostFilter.SetDepthIndex( DepthIndex::CONTENT );
SetupFilters();
}
void EffectsView::SetupCameras()
{
- const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
-
- // Create and place a camera for the children render, corresponding to its render target size
- mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
- // TODO: how do we pick a reasonable value for near clip? Needs to relate to normal camera the user renders with, but we don't have a handle on it
- mCameraForChildren.SetNearClippingPlane(1.0f);
- mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
- mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
- mCameraForChildren.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosScale);
- mCameraForChildren.SetZ( mTargetSize.height * cameraPosScale );
+ if( !mCameraForChildren )
+ {
+ // Create a camera for the children render, corresponding to its render target size
+ mCameraForChildren = CameraActor::New(mTargetSize);
+ mCameraForChildren.SetParentOrigin(ParentOrigin::CENTER);
+ mCameraForChildren.SetInvertYAxis( true );
+ Self().Add( mCameraForChildren );
+ }
+ else
+ {
+ // place the camera for the children render, corresponding to its render target size
+ const float cameraPosScale( 0.5f / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f) );
+ mCameraForChildren.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
+ mCameraForChildren.SetNearClippingPlane(1.0f);
+ mCameraForChildren.SetAspectRatio(mTargetSize.width / mTargetSize.height);
+ mCameraForChildren.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
+ mCameraForChildren.SetPosition(0.0f, 0.0f, mTargetSize.height * cameraPosScale);
+ mCameraForChildren.SetZ( mTargetSize.height * cameraPosScale );
+ }
}
void EffectsView::CreateRenderTasks()
{
+ if( mTargetSize == Vector2::ZERO )
+ {
+ return;
+ }
RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
// create render task to render our child actors to offscreen buffer
mRenderTaskForChildren = taskList.CreateTask();
mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
- mRenderTaskForChildren.SetSourceActor( Self() );
+ mRenderTaskForChildren.SetSourceActor( mChildrenRoot );
mRenderTaskForChildren.SetExclusive(true);
mRenderTaskForChildren.SetInputEnabled( false );
mRenderTaskForChildren.SetClearColor( mBackgroundColor );
mRenderTaskForChildren.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
// Enable image filters
- const size_t numFilters( mFilters.size() );
+ const size_t numFilters( mFilters.Size() );
for( size_t i = 0; i < numFilters; ++i )
{
mFilters[i]->Enable();
}
-
- // create render task to render result of the image filters to the final offscreen
- if( mImageForResult )
- {
- mRenderTaskForResult = taskList.CreateTask();
- mRenderTaskForResult.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
- mRenderTaskForResult.SetSourceActor( mActorForResult );
- mRenderTaskForResult.SetExclusive(true);
- mRenderTaskForResult.SetInputEnabled( false );
- mRenderTaskForResult.SetClearColor( mBackgroundColor );
- mRenderTaskForResult.SetClearEnabled( true );
- mRenderTaskForResult.SetTargetFrameBuffer( mImageForResult );
- mRenderTaskForResult.SetCameraActor(mCameraForChildren); // use camera that covers render target exactly
- }
}
void EffectsView::RemoveRenderTasks()
{
+ if( mTargetSize == Vector2::ZERO )
+ {
+ return;
+ }
+
RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
taskList.RemoveTask(mRenderTaskForChildren);
- taskList.RemoveTask(mRenderTaskForResult);
- const size_t numFilters( mFilters.size() );
+ const size_t numFilters( mFilters.Size() );
for( size_t i = 0; i < numFilters; ++i )
{
mFilters[i]->Disable();
mRenderTaskForChildren.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
}
- if( mRenderTaskForResult )
- {
- mRenderTaskForResult.SetRefreshRate( mRefreshOnDemand ? RenderTask::REFRESH_ONCE : RenderTask::REFRESH_ALWAYS );
- }
-
- const size_t numFilters( mFilters.size() );
+ const size_t numFilters( mFilters.Size() );
for( size_t i = 0; i < numFilters; ++i )
{
mFilters[i]->Refresh();
void EffectsView::RemoveFilters()
{
- const size_t numFilters( mFilters.size() );
+ const size_t numFilters( mFilters.Size() );
for( size_t i = 0; i < numFilters; ++i )
{
delete mFilters[i];
}
- mFilters.clear();
+ mFilters.Release();
+}
+
+void EffectsView::SetProperty( BaseObject* object, Property::Index index, const Property::Value& value )
+{
+ Toolkit::EffectsView effectsView = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
+
+ if ( effectsView )
+ {
+ switch ( index )
+ {
+ case Toolkit::EffectsView::Property::EFFECT_SIZE:
+ {
+ int effectSize;
+ if( value.Get( effectSize ) )
+ {
+ GetImpl( effectsView ).SetEffectSize( effectSize );
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+}
+
+Property::Value EffectsView::GetProperty( BaseObject* object, Property::Index propertyIndex )
+{
+ Property::Value value;
+
+ Toolkit::EffectsView imageview = Toolkit::EffectsView::DownCast( Dali::BaseHandle( object ) );
+
+ if ( imageview )
+ {
+ EffectsView& impl = GetImpl( imageview );
+ switch ( propertyIndex )
+ {
+ case Toolkit::EffectsView::Property::EFFECT_SIZE:
+ {
+ value = impl.GetEffectSize();
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ return value;
}
} // namespace Internal
// EXTERNAL INCLUDES
#include <dali/public-api/actors/camera-actor.h>
-#include <dali/public-api/actors/image-actor.h>
#include <dali/public-api/common/dali-vector.h>
#include <dali/public-api/render-tasks/render-task.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
// INTERNAL INCLUDES
-#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/devel-api/controls/effects-view/effects-view.h>
+#include <dali-toolkit/public-api/controls/control-impl.h>
#include <dali-toolkit/public-api/controls/gaussian-blur-view/gaussian-blur-view.h>
+#include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
namespace Dali
{
/// @copydoc Dali::Toolkit::EffectsView::GetType
Toolkit::EffectsView::EffectType GetType() const;
- /// @copydoc Dali::Toolkit::EffectsView::Enable
- void Enable();
-
- /// @copydoc Dali::Toolkit::EffectsView::Disable
- void Disable();
-
/// @copydoc Dali::Toolkit::EffectsView::Refresh
void Refresh();
/// @copydoc Dali::Toolkit::EffectsView::SetPixelFormat
void SetPixelFormat( Pixel::Format pixelFormat );
- /// @copydoc Dali::Toolkit::EffectsView::SetOutputImage
- void SetOutputImage( FrameBufferImage image );
-
- /// @copydoc Dali::Toolkit::EffectsView::GetOutputImage
- FrameBufferImage GetOutputImage();
-
- /// @copydoc Dali::Toolkit::EffectsView::GetEffectSizePropertyIndex
- Property::Index GetEffectSizePropertyIndex() const;
-
- /// @copydoc Dali::Toolkit::EffectsView::GetEffectStrengthPropertyIndex
- Property::Index GetEffectStrengthPropertyIndex() const;
-
- /// @copydoc Dali::Toolkit::EffectsView::GetEffectOffsetPropertyIndex
- Property::Index GetEffectOffsetPropertyIndex() const;
-
- /// @copydoc Dali::Toolkit::EffectsView::GetEffectColorPropertyIndex
- Property::Index GetEffectColorPropertyIndex() const;
-
/// @copydoc Dali::Toolkit::EffectsView::SetBackgroundColor(const Vector4&)
void SetBackgroundColor( const Vector4& color );
/// @copydoc Dali::Toolkit::GaussianBlurView::GetBackgroundColor
Vector4 GetBackgroundColor() const;
-private:
/**
- * Register and setup indices for EffectsView properties
+ * Set the effect size which decides the size of filter kernel.
+ * @param[in] effectSize The effect size.
+ */
+ void SetEffectSize( int effectSize );
+
+ /**
+ * Get the effect size.
+ * @return The effect size.
+ */
+ int GetEffectSize();
+
+ // Properties
+ /**
+ * Called when a property of an object of this type is set.
+ * @param[in] object The object whose property is set.
+ * @param[in] index The property index.
+ * @param[in] value The new property value.
+ */
+ static void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value );
+
+
+ /**
+ * Called to retrieve a property of an object of this type.
+ * @param[in] object The object whose property is to be retrieved.
+ * @param[in] index The property index.
+ * @return The current value of the property.
*/
- void SetupProperties();
+ static Property::Value GetProperty( BaseObject* object, Property::Index propertyIndex );
private: // From Control
/**
- * @copydoc Toolkit::Control::OnInitialize()
+ * @copydoc Toolkit::Internal::Control::OnInitialize()
*/
virtual void OnInitialize();
*/
virtual void OnSizeSet( const Vector3& targetSize );
+ /**
+ * @copydoc Toolkit::Internal::Control::OnStageConnection
+ */
+ virtual void OnStageConnection( int depth );
+
+ /**
+ * @copydoc Toolkit::Internal::Control::OnStageDisconnection
+ */
+ virtual void OnStageDisconnection();
+
+ /**
+ * @copydoc Toolkit::Internal::Control::OnChildAdd
+ */
+ virtual void OnChildAdd( Actor& child );
+
+ /**
+ * @copydoc Toolkit::Internal::Control::OnChildRemove
+ */
+ virtual void OnChildRemove( Actor& child );
+
private:
/**
- * Callback received when the control is disconnected from the stage.
+ * Enable the effect when the control is set on stage
*/
- void OnStageDisconnection();
+ void Enable();
+
+ /**
+ * Disable the effect when the control is set off stage
+ */
+ void Disable();
/**
* Setup image filters
EffectsView& operator = ( const EffectsView& );
private: // attributes/properties
- Toolkit::EffectsView::EffectType mEffectType;
/////////////////////////////////////////////////////////////
// for rendering all user added children to offscreen target
FrameBufferImage mImageForChildren;
- ImageActor mActorForChildren;
+ Toolkit::ControlRenderer mRendererForChildren;
RenderTask mRenderTaskForChildren;
CameraActor mCameraForChildren;
-
- /////////////////////////////////////////////////////////////
- Pixel::Format mPixelFormat; ///< pixel format used by render targets
-
- /////////////////////////////////////////////////////////////
- // downsampling is used for the separated blur passes to get increased blur with the same number of samples and also to make rendering quicker
- float mSpread;
+ Actor mChildrenRoot; // for creating a subtree for all user added child actors
/////////////////////////////////////////////////////////////
// background fill color
// for checking if we need to reallocate render targets
Vector2 mTargetSize;
Vector2 mLastSize;
-
- bool mRefreshOnDemand;
-
- /////////////////////////////////////////////////////////////
- // horizontal spread objects
- FrameBufferImage mImageForHorzSpread;
- ImageActor mActorForHorzSpread;
- RenderTask mRenderTaskForHorzSpread;
-
- /////////////////////////////////////////////////////////////
- // vertical spread objects
- FrameBufferImage mImageForVertSpread;
- ImageActor mActorForVertSpread;
- RenderTask mRenderTaskForVertSpread;
-
- CameraActor mCameraForSpread;
-
/////////////////////////////////////////////////////////////
// post blur image
FrameBufferImage mImagePostFilter;
- ImageActor mActorPostFilter;
+ Toolkit::ControlRenderer mRendererPostFilter;
+
+ Vector<ImageFilter*> mFilters;
/////////////////////////////////////////////////////////////
- // final image
- FrameBufferImage mImageForResult;
- Actor mActorForResult;
- RenderTask mRenderTaskForResult;
+ // downsampling is used for the separated blur passes to get increased blur with the same number of samples and also to make rendering quicker
+ int mEffectSize;
- Property::Index mEffectSizePropertyIndex;
- Property::Index mEffectStrengthPropertyIndex;
- Property::Index mEffectOffsetPropertyIndex;
- Property::Index mEffectColorPropertyIndex;
+ /////////////////////////////////////////////////////////////
+ Toolkit::EffectsView::EffectType mEffectType;
+ Pixel::Format mPixelFormat; ///< pixel format used by render targets
- std::vector<ImageFilter*> mFilters;
+ bool mEnabled:1;
+ bool mRefreshOnDemand:1;
}; // class EffectsView
} // namespace Internal
void GaussianBlurView::OnSizeSet(const Vector3& targetSize)
{
+ Control::OnSizeSet( targetSize );
+
mTargetSize = Vector2(targetSize);
mChildrenRoot.SetSize(targetSize);
}
}
-void GaussianBlurView::OnControlChildAdd( Actor& child )
+void GaussianBlurView::OnChildAdd( Actor& child )
{
+ Control::OnChildAdd( child );
+
if( child != mChildrenRoot && child != mInternalRoot)
{
mChildrenRoot.Add( child );
}
}
-void GaussianBlurView::OnControlChildRemove( Actor& child )
+void GaussianBlurView::OnChildRemove( Actor& child )
{
mChildrenRoot.Remove( child );
+
+ Control::OnChildRemove( child );
}
void GaussianBlurView::AllocateResources()
virtual void OnSizeSet(const Vector3& targetSize);
/**
- * @copydoc Control::OnControlChildAdd()
+ * @copydoc Control::OnChildAdd()
*/
- virtual void OnControlChildAdd( Actor& child );
+ virtual void OnChildAdd( Actor& child );
/**
- * @copydoc Control::OnControlChildRemove()
+ * @copydoc Control::OnChildRemove()
*/
- virtual void OnControlChildRemove( Actor& child );
+ virtual void OnChildRemove( Actor& child );
void SetBlurBellCurveWidth(float blurBellCurveWidth);
float CalcGaussianWeight(float x);
void ImageView::OnSizeSet( const Vector3& targetSize )
{
+ Control::OnSizeSet( targetSize );
+
if( mRenderer )
{
Vector2 size( targetSize );
void Magnifier::OnSizeSet(const Vector3& targetSize)
{
+ Control::OnSizeSet( targetSize );
+
// TODO: Once Camera/CameraActor properties function as proper animatable properties
// this code can disappear.
// whenever the size of the magnifier changes, the field of view needs to change
*
*/
-// 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
// EXTERNAL INCLUDES
#include <dali/public-api/object/type-registry.h>
#include <dali/devel-api/object/type-registry-helper.h>
-#include <dali/devel-api/rendering/cull-face.h>
namespace Dali
{
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
#include <dali/public-api/animation/animation.h>
#include <dali/public-api/object/type-registry.h>
#include <dali/devel-api/object/type-registry-helper.h>
-#include <dali/devel-api/rendering/cull-face.h>
//INTERNAL INCLUDES
#include <dali-toolkit/internal/controls/page-turn-view/page-turn-effect.h>
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
return true;
}
-void Popup::OnControlStageConnection()
+void Popup::OnStageConnection( int depth )
{
+ Control::OnStageConnection( depth );
+
mLayoutDirty = true;
RelayoutRequest();
}
-void Popup::OnControlChildAdd( Actor& child )
+void Popup::OnChildAdd( Actor& child )
{
+ Control::OnChildAdd( child );
+
// Re-parent any children added by user to the body layer.
if( mAlterAddedChild )
{
/**
* Called when the popup is directly or indirectly parented to the stage.
*/
- virtual void OnControlStageConnection();
+ virtual void OnStageConnection( int depth );
/**
* From Control; called after a child has been added to the owning actor.
* @param[in] child The child which has been added.
*/
- virtual void OnControlChildAdd( Actor& child );
+ virtual void OnChildAdd( Actor& child );
/**
* @copydoc Control::OnRelayOut()
}\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:
/**
void ScrollView::OnChildAdd(Actor& child)
{
+ ScrollBase::OnChildAdd( child );
+
Dali::Toolkit::ScrollBar scrollBar = Dali::Toolkit::ScrollBar::DownCast(child);
if(scrollBar)
{
{
// TODO: Actor needs a RemoveConstraint method to take out an individual constraint.
UnbindActor(child);
+
+ ScrollBase::OnChildRemove( child );
}
void ScrollView::StartTouchDownTimer()
blurStrengthConstraint.Apply();
}
-void ShadowView::OnControlChildAdd( Actor& child )
+void ShadowView::OnChildAdd( Actor& child )
{
+ Control::OnChildAdd( child );
+
if( child != mChildrenRoot && child != mBlurRootActor)
{
mChildrenRoot.Add( child );
}
}
-void ShadowView::OnControlChildRemove( Actor& child )
+void ShadowView::OnChildRemove( Actor& child )
{
mChildrenRoot.Remove( child );
+
+ Control::OnChildRemove( child );
}
void ShadowView::ConstrainCamera()
virtual void OnInitialize();
/**
- * @copydoc Control::OnControlChildAdd()
+ * @copydoc Control::OnChildAdd()
*/
- virtual void OnControlChildAdd( Actor& child );
+ virtual void OnChildAdd( Actor& child );
/**
- * @copydoc Control::OnControlChildRemove()
+ * @copydoc Control::OnChildRemove()
*/
- virtual void OnControlChildRemove( Actor& child );
+ virtual void OnChildRemove( Actor& child );
/**
* Constrain the camera actor to the position of the point light, pointing
if( child )
{
RelayoutingLock lock( *this );
- // Remove the child, this will trigger a call to OnControlChildRemove
+ // Remove the child, this will trigger a call to OnChildRemove
Self().Remove( child );
// relayout the table only if instances were found
return value;
}
-void TableView::OnControlChildAdd( Actor& child )
+void TableView::OnChildAdd( Actor& child )
{
+ Control::OnChildAdd( child );
+
if( mLayoutingChild )
{
// we're in the middle of laying out children so no point doing anything here
RelayoutRequest();
}
-void TableView::OnControlChildRemove( Actor& child )
+void TableView::OnChildRemove( Actor& child )
{
// dont process if we're in the middle of bigger operation like delete row, column or resize
if( !mLayoutingChild )
RelayoutRequest();
}
}
+
+ Control::OnChildRemove( child );
}
TableView::TableView( unsigned int initialRows, unsigned int initialColumns )
private: // From Control
/**
- * @copydoc Control::OnControlChildAdd(Actor& child)
+ * @copydoc Control::OnChildAdd(Actor& child)
*/
- virtual void OnControlChildAdd( Actor& child );
+ virtual void OnChildAdd( Actor& child );
/**
- * @copydoc Control::OnControlChildRemove(Actor& child)
+ * @copydoc Control::OnChildRemove(Actor& child)
*/
- virtual void OnControlChildRemove( Actor& child );
+ virtual void OnChildRemove( Actor& child );
/**
* @copydoc Control::OnRelayout
mLayout.SetRelativeWidth( 1, mRightRelativeSpace );
}
-void ToolBar::OnControlChildAdd(Actor& child)
+void ToolBar::OnChildAdd(Actor& child)
{
+ Control::OnChildAdd( child );
+
if( !mInitializing )
{
// An actor is being added through the Actor's API.
AddControl( child, DEFAULT_RELATIVE_SIZE, DEFAULT_ALIGNMENT, Toolkit::ToolBar::DEFAULT_PADDING );
}
- // No OnControlChildRemove method required because Actors are added to the mLayout table view, so if an
+ // No OnChildRemove method required because Actors are added to the mLayout table view, so if an
// actor is removed using the Actor::RemoveChild method it will not remove anything because the
// actor is in mLayout not in Self().
}
* Adds a control using some default values (the control uses 10% of the tool bar space and is placed on the left group).
* @param child The control to be added.
*
- * @see Control::OnControlChildAdd()
+ * @see Control::OnChildAdd()
*/
- virtual void OnControlChildAdd(Actor& child);
+ virtual void OnChildAdd(Actor& child);
private:
/**
#include <sstream>
#include <dali/public-api/animation/constraints.h>
#include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/property-map.h>
#include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/devel-api/rendering/renderer.h>
// INTERNAL INCLUDES
1.0f/16.0f, 1.0f/16.0f, 1.0f/16.0f, 0.5f/16.0f,
0.5f/16.0f, 0.5f/16.0f, 0.5f/16.0f };
-
-const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
-
const char* BLUR_TWO_PASS_FRAGMENT_SOURCE =
{
"precision highp float;\n"
+ "varying mediump vec2 vTexCoord;\n"
+ "uniform sampler2D sTexture;\n"
"uniform vec2 uSampleOffsets[NUM_SAMPLES];\n"
"uniform float uSampleWeights[NUM_SAMPLES];\n"
"void main()\n"
"{\n"
" vec4 color = vec4(0.0);\n"
- "# ifdef DEBUG_RENDER\n"
- " if( vTexCoord.s < 0.495 )\n"
- " {\n"
- "# endif //def DEBUG_RENDER\n"
- " for( int i = 0; i < NUM_SAMPLES; ++i )\n"
- " {\n"
- " color += texture2D( sTexture, vTexCoord + uSampleOffsets[i] ) * uSampleWeights[i];\n"
- " }\n"
- "# ifdef DEBUG_RENDER\n"
- " }\n"
- " else if( vTexCoord.s > 0.505 )\n"
- " {\n"
- " color = texture2D( sTexture, vTexCoord );\n"
- " }\n"
- " else\n"
+ " for( int i = 0; i < NUM_SAMPLES; ++i )\n"
" {\n"
- " color = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
+ " color += texture2D( sTexture, vTexCoord + uSampleOffsets[i] ) * uSampleWeights[i];\n"
" }\n"
- "# endif //def DEBUG_RENDER\n"
" gl_FragColor = color;\n"
"}\n"
};
const char* BLEND_TWO_IMAGES_FRAGMENT_SOURCE =
{
"precision highp float;\n"
- "uniform float uBlurStrength; \n "
+ "uniform float uBlurStrength;\n "
+ "uniform sampler2D sTexture;\n"
+ "uniform sampler2D sEffect;\n"
+ "varying mediump vec2 vTexCoord;\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D( sTexture, vTexCoord ) * uBlurStrength"
"}\n"
};
-std::string GetBlurStrengthUniformName()
-{
- return "uBlurStrength";
-}
+const char* const BLUR_STRENGTH_UNIFORM_NAME( "uBlurStrength" );
+const char* const EFFECT_IMAGE_NAME( "sEffect" );
} // namespace
BlurTwoPassFilter::BlurTwoPassFilter()
: ImageFilter()
{
- mShaderForBlending = ShaderEffect::New( "", BLEND_TWO_IMAGES_FRAGMENT_SOURCE );
- mShaderForBlending.SetUniform( GetBlurStrengthUniformName(), 1.f );
- mBlurStrengthPropertyIndex = mShaderForBlending.GetPropertyIndex( GetBlurStrengthUniformName() );
+ // create blending actor and register the property in constructor
+ // to make sure that GetBlurStrengthPropertyIndex() always returns a valid index
+ mActorForBlending = Toolkit::ImageView::New();
+ mBlurStrengthPropertyIndex = mActorForBlending.RegisterProperty( BLUR_STRENGTH_UNIFORM_NAME, 1.f );
}
BlurTwoPassFilter::~BlurTwoPassFilter()
void BlurTwoPassFilter::Enable()
{
- mCameraForBlur = CameraActor::New();
- mCameraForBlur.SetParentOrigin(ParentOrigin::CENTER);
-
// create actor to render input with applied emboss effect
- mActorForInput = ImageActor::New( mInputImage );
+ mActorForInput = Toolkit::ImageView::New( mInputImage );
mActorForInput.SetParentOrigin( ParentOrigin::CENTER );
mActorForInput.SetSize( mTargetSize );
- mActorForInput.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
// create internal offscreen for result of horizontal pass
mImageForHorz = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED );
-
// create an actor to render mImageForHorz for vertical blur pass
- mActorForHorz = ImageActor::New( mImageForHorz );
+ mActorForHorz = Toolkit::ImageView::New( mImageForHorz );
mActorForHorz.SetParentOrigin( ParentOrigin::CENTER );
mActorForHorz.SetSize( mTargetSize );
- mActorForHorz.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
// create internal offscreen for result of the two pass blurred image
mBlurredImage = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED);
-
// create an actor to blend the blurred image and the input image with the given blur strength
- mActorForBlending = ImageActor::New( mBlurredImage );
+ mActorForBlending.SetImage( mBlurredImage );
mActorForBlending.SetParentOrigin( ParentOrigin::CENTER );
mActorForBlending.SetSize( mTargetSize );
- mActorForBlending.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
-
- mRootActor.Add( mActorForInput );
- mRootActor.Add( mActorForHorz );
- mRootActor.Add( mActorForBlending );
- mRootActor.Add( mCameraForBlur );
// create custom shader effect
if( !GetKernelSize() )
}
int kernelSize( static_cast< int >(GetKernelSize()) );
- std::ostringstream fragmentSource;
- if( mDebugRender )
- {
- fragmentSource << "#define DEBUG_RENDER\n";
- }
- fragmentSource << "#define NUM_SAMPLES " << kernelSize << "\n";
- fragmentSource << BLUR_TWO_PASS_FRAGMENT_SOURCE;
- mShaderForHorz = ShaderEffect::New( "", fragmentSource.str() );
- mActorForInput.SetShaderEffect( mShaderForHorz );
- mShaderForVert = ShaderEffect::New( "", fragmentSource.str() );
- mActorForHorz.SetShaderEffect( mShaderForVert );
-
for( int i = 0; i < kernelSize; ++i )
{
const std::string offsetUniform( GetOffsetUniformName( i ) );
const std::string weightUniform( GetWeightUniformName( i ) );
- mShaderForHorz.SetUniform( offsetUniform, Vector2(mKernel[i]) * Vector2::XAXIS );
- mShaderForHorz.SetUniform( weightUniform, mKernel[i].z );
+ mActorForInput.RegisterProperty( offsetUniform, Vector2(mKernel[i]) * Vector2::XAXIS );
+ mActorForInput.RegisterProperty( weightUniform, mKernel[i].z );
- mShaderForVert.SetUniform( offsetUniform, Vector2(mKernel[i]) * Vector2::YAXIS );
- mShaderForVert.SetUniform( weightUniform, mKernel[i].z );
+ mActorForHorz.RegisterProperty( offsetUniform, Vector2(mKernel[i]) * Vector2::YAXIS );
+ mActorForHorz.RegisterProperty( weightUniform, mKernel[i].z );
}
- mActorForBlending.SetShaderEffect( mShaderForBlending );
- mShaderForBlending.SetEffectImage( mInputImage );
+ // Set up blur-two-pass custom shader
+ std::ostringstream fragmentSource;
+ fragmentSource << "#define NUM_SAMPLES " << kernelSize << "\n";
+ fragmentSource << BLUR_TWO_PASS_FRAGMENT_SOURCE;
+
+ Property::Map customShader;
+ customShader[ "fragmentShader" ] = fragmentSource.str();
+ Property::Map rendererMap;
+ rendererMap.Insert( "shader", customShader );
+ mActorForInput.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
+ mActorForHorz.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
+
+ // Set up blend-two-image custom shader
+ customShader[ "fragmentShader" ] = BLEND_TWO_IMAGES_FRAGMENT_SOURCE;
+ rendererMap[ "shader"] = customShader;
+ mActorForBlending.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
+
+ mRootActor.Add( mActorForInput );
+ mRootActor.Add( mActorForHorz );
+ mRootActor.Add( mActorForBlending );
+
+ // Add effect texture to blend-two-image custom shader
+ Material material = mActorForBlending.GetRendererAt(0).GetMaterial();
+ int textureIndex = material.GetTextureIndex( EFFECT_IMAGE_NAME );
+ if( textureIndex == -1 )
+ {
+ material.AddTexture( mInputImage, EFFECT_IMAGE_NAME );
+ }
+ else
+ {
+ material.SetTextureImage( textureIndex, mInputImage );
+ }
SetupCamera();
CreateRenderTasks();
{
if( mRootActor )
{
- if( mCameraForBlur )
+ if( mCameraActor )
{
- mRootActor.Remove( mCameraForBlur );
- mCameraForBlur.Reset();
+ mRootActor.Remove( mCameraActor );
+ mCameraActor.Reset();
}
if( mActorForInput )
mActorForHorz.Reset();
}
- if( mActorForBlending )
- {
- mRootActor.Remove( mActorForBlending );
- mActorForBlending.Reset();
- }
-
RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
if( mRenderTaskForHorz )
Handle BlurTwoPassFilter::GetHandleForAnimateBlurStrength()
{
- return mShaderForBlending;
-}
-
-void BlurTwoPassFilter::SetupCamera()
-{
- // Create and place a camera for the embossing render, corresponding to its render target size
- mCameraForBlur.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
- mCameraForBlur.SetNearClippingPlane(1.0f);
- mCameraForBlur.SetAspectRatio(mTargetSize.width / mTargetSize.height);
- mCameraForBlur.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
- mCameraForBlur.SetPosition(0.0f, 0.0f, ((mTargetSize.height * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
+ return mActorForBlending;
}
void BlurTwoPassFilter::CreateRenderTasks()
mRenderTaskForHorz.SetClearEnabled( true );
mRenderTaskForHorz.SetClearColor( mBackgroundColor );
mRenderTaskForHorz.SetTargetFrameBuffer( mImageForHorz );
- mRenderTaskForHorz.SetCameraActor( mCameraForBlur );
+ mRenderTaskForHorz.SetCameraActor( mCameraActor );
// use the internal buffer and perform a horizontal blur targeting the output buffer
mRenderTaskForVert = taskList.CreateTask();
mRenderTaskForVert.SetClearEnabled( true );
mRenderTaskForVert.SetClearColor( mBackgroundColor );
mRenderTaskForVert.SetTargetFrameBuffer( mBlurredImage );
- mRenderTaskForVert.SetCameraActor( mCameraForBlur );
+ mRenderTaskForVert.SetCameraActor( mCameraActor );
//Perform a blending between the blurred image and the input image
mRenderTaskForBlending = taskList.CreateTask();
mRenderTaskForBlending.SetClearEnabled( true );
mRenderTaskForBlending.SetClearColor( mBackgroundColor );
mRenderTaskForBlending.SetTargetFrameBuffer( mOutputImage );
- mRenderTaskForBlending.SetCameraActor( mCameraForBlur );
+ mRenderTaskForBlending.SetCameraActor( mCameraActor );
}
} // namespace Internal
*/
// EXTERNAL INCLUDES
-#include <dali/public-api/actors/camera-actor.h>
-#include <dali/public-api/actors/image-actor.h>
#include <dali/public-api/render-tasks/render-task.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
+#include <dali/public-api/actors/image-actor.h>
// INTERNAL INCLUDES
#include "image-filter.h"
Handle GetHandleForAnimateBlurStrength();
private:
- /**
- * Setup position and parameters for camera
- */
- void SetupCamera();
/**
* Setup render tasks for blur
private: // Attributes
- CameraActor mCameraForBlur;
-
// To perform horizontal blur from mInputImage to mImageForHorz
- RenderTask mRenderTaskForHorz;
- ImageActor mActorForInput;
- FrameBufferImage mImageForHorz;
- ShaderEffect mShaderForHorz;
+ RenderTask mRenderTaskForHorz;
+ Toolkit::ImageView mActorForInput;
+ FrameBufferImage mImageForHorz;
// To perform vertical blur from mImageForHorz to mOutputImage
- RenderTask mRenderTaskForVert;
- ImageActor mActorForHorz;
- ShaderEffect mShaderForVert;
- FrameBufferImage mBlurredImage;
+ RenderTask mRenderTaskForVert;
+ Toolkit::ImageView mActorForHorz;
+ FrameBufferImage mBlurredImage;
// To blend the blurred image and input image according to the blur strength
- RenderTask mRenderTaskForBlending;
- ImageActor mActorForBlending;
- Actor mRootActorForBlending;
- ShaderEffect mShaderForBlending;
- Property::Index mBlurStrengthPropertyIndex;
+ RenderTask mRenderTaskForBlending;
+ Toolkit::ImageView mActorForBlending;
+ Actor mRootActorForBlending;
+ Property::Index mBlurStrengthPropertyIndex;
}; // class BlurTwoPassFilter
#include <sstream>
#include <dali/public-api/animation/constraints.h>
#include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/property-map.h>
#include <dali/public-api/render-tasks/render-task-list.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/devel-api/rendering/renderer.h>
+#include <dali-toolkit/devel-api/controls/renderer-factory/renderer-factory.h>
// INTERNAL INCLUDES
namespace
{
-const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
-
-const char* EMBOSS_FRAGMENT_SOURCE1 =
+const char* EMBOSS_FRAGMENT_SOURCE =
{
"precision highp float;\n"
+ "varying mediump vec2 vTexCoord;\n"
+ "uniform sampler2D sTexture;\n"
"uniform vec2 uTexScale;\n"
+ "uniform vec3 uCoefficient;\n"
"\n"
"void main()\n"
"{\n"
- " vec4 color;\n"
- "# ifdef DEBUG_RENDER\n"
- " if( vTexCoord.s < 0.495 )\n"
- " {\n"
- "# endif //def DEBUG_RENDER\n"
- " color = 2.0 * texture2D( sTexture, vTexCoord + vec2(0.0, -uTexScale.y) );\n"
- " color += -1.0 * texture2D( sTexture, vTexCoord );\n"
- " color += -1.0 * texture2D( sTexture, vTexCoord + vec2(0.0, uTexScale.y) );\n"
- "# ifdef DEBUG_RENDER\n"
- " }\n"
- " else if( vTexCoord.s > 0.505 )\n"
- " {\n"
- " color = texture2D( sTexture, vTexCoord );\n"
- " }\n"
- " else\n"
- " {\n"
- " color = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
- " }\n"
- "# endif //def DEBUG_RENDER\n"
- " gl_FragColor = uColor * color;\n"
+ " vec4 color = uCoefficient.x * texture2D( sTexture, vTexCoord + vec2(0.0, -uTexScale.y) );\n"
+ " color += uCoefficient.y * texture2D( sTexture, vTexCoord );\n"
+ " color += uCoefficient.z * texture2D( sTexture, vTexCoord + vec2(0.0, uTexScale.y) );\n"
+ " gl_FragColor = color;\n"
"}\n"
};
-const char* EMBOSS_FRAGMENT_SOURCE2 =
+const char* const COMPOSITE_FRAGMENT_SOURCE =
{
- "precision highp float;\n"
- "uniform vec2 uTexScale;\n"
- "\n"
- "void main()\n"
- "{\n"
- " vec4 color;\n"
- "# ifdef DEBUG_RENDER\n"
- " if( vTexCoord.s < 0.495 )\n"
- " {\n"
- "# endif //def DEBUG_RENDER\n"
- " color = -1.0 * texture2D( sTexture, vTexCoord + vec2(0.0, -uTexScale.y) );\n"
- " color += -1.0 * texture2D( sTexture, vTexCoord );\n"
- " color += 2.0 * texture2D( sTexture, vTexCoord + vec2(0.0, uTexScale.y) );\n"
- "# ifdef DEBUG_RENDER\n"
- " }\n"
- " else if( vTexCoord.s > 0.505 )\n"
- " {\n"
- " color = texture2D( sTexture, vTexCoord );\n"
- " }\n"
- " else\n"
- " {\n"
- " color = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
- " }\n"
- "# endif //def DEBUG_RENDER\n"
- " gl_FragColor = uColor * color;\n"
- "}\n"
+ "varying mediump vec2 vTexCoord;\n"
+ "uniform sampler2D sTexture;\n"
+ "uniform lowp vec4 uEffectColor;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = uEffectColor;\n"
+ " gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n"
+ "}\n"
};
-const char* const COMPOSITE_FRAGMENT_SOURCE =
- "void main()\n"
- "{\n"
- " gl_FragColor = uColor;\n"
- " gl_FragColor.a *= texture2D( sTexture, vTexCoord).a;\n"
- "}\n";
+const char* const TEX_SCALE_UNIFORM_NAME( "uTexScale" );
+const char* const COEFFICIENT_UNIFORM_NAME( "uCoefficient" );
+const char* const COLOR_UNIFORM_NAME( "uEffectColor" );
} // namespace
void EmbossFilter::Enable()
{
- // Create camera
- mCameraActor = CameraActor::New();
- mCameraActor.SetParentOrigin(ParentOrigin::CENTER);
-
mImageForEmboss1 = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED );
mImageForEmboss2 = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED );
+ Property::Map customShader;
+ customShader[ "fragmentShader" ] = EMBOSS_FRAGMENT_SOURCE;
+ Property::Map rendererMap;
+ rendererMap.Insert( "shader", customShader );
+
// create actor to render input with applied emboss effect
- mActorForInput1 = ImageActor::New( mInputImage );
+ mActorForInput1 = Toolkit::ImageView::New( mInputImage );
mActorForInput1.SetParentOrigin( ParentOrigin::CENTER );
mActorForInput1.SetSize(mTargetSize);
- mActorForInput1.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
- mActorForInput1.SetColor( Color::WHITE );
+ Vector2 textureScale( 1.5f/mTargetSize.width, 1.5f/mTargetSize.height);
+ mActorForInput1.RegisterProperty( TEX_SCALE_UNIFORM_NAME, textureScale );
+ mActorForInput1.RegisterProperty( COEFFICIENT_UNIFORM_NAME, Vector3( 2.f, -1.f, -1.f ) );
+ // set EMBOSS custom shader
+ mActorForInput1.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
+ mRootActor.Add( mActorForInput1 );
- mActorForInput2 = ImageActor::New( mInputImage );
+ mActorForInput2 = Toolkit::ImageView::New( mInputImage );
mActorForInput2.SetParentOrigin( ParentOrigin::CENTER );
mActorForInput2.SetSize(mTargetSize);
- mActorForInput2.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
- mActorForInput2.SetColor( Color::WHITE );
-
- mActorForEmboss1 = ImageActor::New( mImageForEmboss1 );
- mActorForEmboss1.SetParentOrigin( ParentOrigin::CENTER );
- mActorForEmboss1.SetSize(mTargetSize);
- mActorForEmboss1.SetColor( Color::BLACK );
- mActorForEmboss1.SetShaderEffect( ShaderEffect::New( "", COMPOSITE_FRAGMENT_SOURCE ) );
-
- mActorForEmboss2 = ImageActor::New( mImageForEmboss2 );
- mActorForEmboss2.SetParentOrigin( ParentOrigin::CENTER );
- mActorForEmboss2.SetSize(mTargetSize);
- mActorForEmboss2.SetColor( Color::WHITE );
- mActorForEmboss2.SetShaderEffect( ShaderEffect::New( "", COMPOSITE_FRAGMENT_SOURCE ) );
+ mActorForInput2.RegisterProperty( TEX_SCALE_UNIFORM_NAME, textureScale );
+ mActorForInput2.RegisterProperty( COEFFICIENT_UNIFORM_NAME, Vector3( -1.f, -1.f, 2.f ) );
+ // set EMBOSS custom shader
+ mActorForInput2.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
+ mRootActor.Add( mActorForInput2 );
mActorForComposite = Actor::New();
mActorForComposite.SetParentOrigin( ParentOrigin::CENTER );
mActorForComposite.SetSize(mTargetSize);
- mActorForComposite.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
-
- // create custom shader effect
- std::ostringstream embossFragmentSource1;
- if( mDebugRender )
- {
- embossFragmentSource1 << "#define DEBUG_RENDER\n";
- }
- embossFragmentSource1 << EMBOSS_FRAGMENT_SOURCE1;
- ShaderEffect effect1 = ShaderEffect::New( "", embossFragmentSource1.str() );
- mActorForInput1.SetShaderEffect( effect1 );
- effect1.SetUniform( "uTexScale", Vector2( 1.0f/mTargetSize.width, 1.0f/mTargetSize.height) * 1.5f );
-
- std::ostringstream embossFragmentSource2;
- if( mDebugRender )
- {
- embossFragmentSource2 << "#define DEBUG_RENDER\n";
- }
- embossFragmentSource2 << EMBOSS_FRAGMENT_SOURCE2;
- ShaderEffect effect2 = ShaderEffect::New( "", embossFragmentSource2.str() );
- mActorForInput2.SetShaderEffect( effect2 );
- effect2.SetUniform( "uTexScale", Vector2( 1.0f/mTargetSize.width, 1.0f/mTargetSize.height) * 1.5f );
+ mActorForComposite.SetColor( Color::BLACK );
+
+ customShader[ "fragmentShader" ] = COMPOSITE_FRAGMENT_SOURCE;
+ rendererMap[ "shader"] = customShader;
+ Toolkit::RendererFactory rendererFactory = Toolkit::RendererFactory::Get();
+ mRendererForEmboss1 = rendererFactory.GetControlRenderer( mImageForEmboss1 );
+ mRendererForEmboss2 = rendererFactory.GetControlRenderer( mImageForEmboss2 );
+ // set COMPOSITE custom shader to both renderers
+ rendererFactory.ResetRenderer( mRendererForEmboss1, mActorForComposite, rendererMap);
+ rendererFactory.ResetRenderer( mRendererForEmboss2, mActorForComposite, rendererMap);
+ // apply renderers to the actor
+ mRendererForEmboss1.SetOnStage( mActorForComposite );
+ mRendererForEmboss2.SetOnStage( mActorForComposite );
+ mActorForComposite.GetRendererAt(0).RegisterProperty( COLOR_UNIFORM_NAME, Color::BLACK );
+ mActorForComposite.GetRendererAt(1).RegisterProperty( COLOR_UNIFORM_NAME, Color::WHITE );
+ mRootActor.Add( mActorForComposite );
SetupCamera();
CreateRenderTasks();
-
- mRootActor.Add( mActorForInput1 );
- mRootActor.Add( mActorForInput2 );
- mRootActor.Add( mActorForComposite );
- mActorForComposite.Add( mActorForEmboss1 );
- mActorForComposite.Add( mActorForEmboss2 );
- mRootActor.Add( mCameraActor );
}
void EmbossFilter::Disable()
if( mActorForComposite )
{
+ mRendererForEmboss1.SetOffStage( mActorForComposite );
+ mRendererForEmboss2.SetOffStage( mActorForComposite );
+ mRendererForEmboss1.Reset();
+ mRendererForEmboss2.Reset();
mRootActor.Remove( mActorForComposite );
mActorForComposite.Reset();
- mActorForEmboss1.Reset();
- mActorForEmboss2.Reset();
}
RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
{
mActorForInput2.SetSize(mTargetSize);
}
- if( mActorForEmboss1 )
- {
- mActorForEmboss1.SetSize(mTargetSize);
- }
- if( mActorForEmboss2 )
- {
- mActorForEmboss2.SetSize(mTargetSize);
- }
if( mActorForComposite )
{
mActorForComposite.SetSize(mTargetSize);
}
}
-void EmbossFilter::SetupCamera()
-{
- // Create and place a camera for the embossing render, corresponding to its render target size
- mCameraActor.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
- mCameraActor.SetNearClippingPlane(1.0f);
- mCameraActor.SetAspectRatio(mTargetSize.width / mTargetSize.height);
- mCameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
- mCameraActor.SetPosition(0.0f, 0.0f, ((mTargetSize.height * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
-}
-
void EmbossFilter::CreateRenderTasks()
{
RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
*/
// EXTERNAL INCLUDES
-#include <dali/public-api/actors/camera-actor.h>
-#include <dali/public-api/actors/image-actor.h>
#include <dali/public-api/render-tasks/render-task.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
+#include <dali-toolkit/devel-api/controls/renderer-factory/control-renderer.h>
// INTERNAL INCLUDES
#include "image-filter.h"
private:
/**
- * Setup position and parameters for camera
- */
- void SetupCamera();
-
- /**
* Setup render tasks for blur
*/
void CreateRenderTasks();
private: // Attributes
- RenderTask mRenderTaskForEmboss1;
- RenderTask mRenderTaskForEmboss2;
- RenderTask mRenderTaskForOutput;
- FrameBufferImage mImageForEmboss1;
- FrameBufferImage mImageForEmboss2;
- CameraActor mCameraActor;
- ImageActor mActorForInput1;
- ImageActor mActorForInput2;
- ImageActor mActorForEmboss1;
- ImageActor mActorForEmboss2;
- Actor mActorForComposite;
+ RenderTask mRenderTaskForEmboss1;
+ RenderTask mRenderTaskForEmboss2;
+ RenderTask mRenderTaskForOutput;
+ FrameBufferImage mImageForEmboss1;
+ FrameBufferImage mImageForEmboss2;
+ Toolkit::ImageView mActorForInput1;
+ Toolkit::ImageView mActorForInput2;
+ Toolkit::ControlRenderer mRendererForEmboss1;
+ Toolkit::ControlRenderer mRendererForEmboss2;
+ Actor mActorForComposite;
}; // class EmbossFilter
} // namespace Internal
namespace
{
-
+const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
} // namespace
ImageFilter::ImageFilter()
: mBackgroundColor( Vector4( 1.0f, 1.0f, 1.0f, 0.0f ) ),
mTargetSize( Vector2::ZERO ),
mPixelFormat( Pixel::RGBA8888 ),
- mRefreshOnDemand( false ),
- mDebugRender( false )
+ mRefreshOnDemand( false )
{
}
mBackgroundColor = color;
}
-void ImageFilter::RenderDebug( bool flag )
+void ImageFilter::SetupCamera()
{
- mDebugRender = flag;
+ if( !mCameraActor )
+ {
+ // create a camera for the render task, corresponding to its render target size
+ mCameraActor = CameraActor::New(mTargetSize);
+ mCameraActor.SetParentOrigin(ParentOrigin::CENTER);
+ mCameraActor.SetInvertYAxis( true );
+ mRootActor.Add( mCameraActor );
+ }
+ else
+ {
+ // place the camera for the render task, corresponding to its render target size
+ mCameraActor.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
+ mCameraActor.SetNearClippingPlane(1.0f);
+ mCameraActor.SetAspectRatio(mTargetSize.width / mTargetSize.height);
+ mCameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
+ mCameraActor.SetPosition(0.0f, 0.0f, ((mTargetSize.height * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
+ }
}
+
} // namespace Internal
} // namespace Toolkit
*/
// EXTERNAL INCLUDES
+#include <dali/public-api/actors/camera-actor.h>
// INTERNAL INCLUDES
#include <dali-toolkit/public-api/controls/control-impl.h>
*/
void SetBackgroundColor( const Vector4& color );
+protected:
+
/**
- * Enable optional debug output in the shader
- * @param[in] flag Set true to enable, dalse to disable.
+ * Setup position and parameters for camera
*/
- void RenderDebug( bool flag );
+ void SetupCamera();
protected:
Image mInputImage;
FrameBufferImage mOutputImage;
FilterKernel mKernel;
Actor mRootActor;
+ CameraActor mCameraActor;
Vector4 mBackgroundColor;
Vector2 mTargetSize;
Pixel::Format mPixelFormat;
bool mRefreshOnDemand;
- bool mDebugRender;
+
}; // class Imagefilter
} // namespace Internal
#include "spread-filter.h"
// EXTERNAL INCLUDES
-#include <sstream>
#include <dali/public-api/animation/constraints.h>
#include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/property-map.h>
#include <dali/public-api/render-tasks/render-task-list.h>
// INTERNAL INCLUDES
namespace
{
-const float ARBITRARY_FIELD_OF_VIEW = Math::PI / 4.0f;
-
const char* const SPREAD_FRAGMENT_SOURCE =
{
"precision highp float;\n"
- "uniform float uSpread;\n"
+ "varying mediump vec2 vTexCoord;\n"
+ "uniform sampler2D sTexture;\n"
+ "uniform int uSpread;\n"
"uniform vec2 uTexScale;\n"
"void main()\n"
"{\n"
" vec4 color = texture2D( sTexture, vTexCoord);\n"
- "# ifdef DEBUG_RENDER\n"
- " if( vTexCoord.s < 0.495 )\n"
- " {\n"
- "# endif //def DEBUG_RENDER\n"
- " int spread = int(uSpread);\n"
- " for( int i = 1; i <= spread; ++i )\n"
- " {\n"
- " vec2 offset = uTexScale * float(i);\n"
- " color = max( texture2D( sTexture, vTexCoord + offset), color );\n"
- " color = max( texture2D( sTexture, vTexCoord - offset), color );\n"
- " }\n"
- "# ifdef DEBUG_RENDER\n"
- " }\n"
- " else if( vTexCoord.s <= 0.505 )\n"
+ " for( int i = 1; i <= uSpread; ++i )\n"
" {\n"
- " color = vec4( 1.0, 0.0, 0.0, 1.0 );\n"
+ " vec2 offset = uTexScale * float(i);\n"
+ " color = max( texture2D( sTexture, vTexCoord + offset), color );\n"
+ " color = max( texture2D( sTexture, vTexCoord - offset), color );\n"
" }\n"
- "# endif //def DEBUG_RENDER\n"
" gl_FragColor = color;\n"
"}\n"
};
+const char* const SPREAD_UNIFORM_NAME( "uSpread" );
+const char* const TEX_SCALE_UNIFORM_NAME( "uTexScale" );
+
} // namespace
void SpreadFilter::Enable()
{
- mCameraActor = CameraActor::New();
- mCameraActor.SetParentOrigin(ParentOrigin::CENTER);
-
// create actor to render input with applied emboss effect
- mActorForInput = ImageActor::New( mInputImage );
+ mActorForInput = Toolkit::ImageView::New( mInputImage );
mActorForInput.SetParentOrigin( ParentOrigin::CENTER );
mActorForInput.SetSize(mTargetSize);
- mActorForInput.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
+ // register properties as shader uniforms
+ mActorForInput.RegisterProperty( SPREAD_UNIFORM_NAME, mSpread );
+ mActorForInput.RegisterProperty( TEX_SCALE_UNIFORM_NAME, Vector2( 1.0f / mTargetSize.width, 0.0f ) );
// create internal offscreen for result of horizontal pass
mImageForHorz = FrameBufferImage::New( mTargetSize.width, mTargetSize.height, mPixelFormat, Image::UNUSED );
-
// create an actor to render mImageForHorz for vertical blur pass
- mActorForHorz = ImageActor::New( mImageForHorz );
+ mActorForHorz = Toolkit::ImageView::New( mImageForHorz );
mActorForHorz.SetParentOrigin( ParentOrigin::CENTER );
mActorForHorz.SetSize(mTargetSize);
- mActorForHorz.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) );
-
- mRootActor.Add( mActorForInput );
- mRootActor.Add( mActorForHorz );
- mRootActor.Add( mCameraActor );
+ // register properties as shader uniforms
+ mActorForHorz.RegisterProperty( SPREAD_UNIFORM_NAME, mSpread );
+ mActorForHorz.RegisterProperty( TEX_SCALE_UNIFORM_NAME, Vector2( 0.0f, 1.0f / mTargetSize.height ) );
- std::ostringstream fragmentSource;
- if( mDebugRender )
- {
- fragmentSource << "#define DEBUG_RENDER\n";
- }
- fragmentSource << SPREAD_FRAGMENT_SOURCE;
+ Property::Map customShader;
+ customShader[ "fragmentShader" ] = SPREAD_FRAGMENT_SOURCE;
+ Property::Map rendererMap;
+ rendererMap.Insert( "shader", customShader );
- mShaderForHorz = ShaderEffect::New( "", fragmentSource.str() );
- mActorForInput.SetShaderEffect( mShaderForHorz );
- mShaderForHorz.SetUniform( "uSpread", mSpread );
- mShaderForHorz.SetUniform( "uTexScale", Vector2( 1.0f / mTargetSize.width, 0.0f ) );
+ // set SPREAD custom shader
+ mActorForInput.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
+ mActorForHorz.SetProperty( Toolkit::ImageView::Property::IMAGE, rendererMap );
- mShaderForVert = ShaderEffect::New( "", fragmentSource.str() );
- mActorForHorz.SetShaderEffect( mShaderForVert );
- mShaderForVert.SetUniform( "uSpread", mSpread );
- mShaderForVert.SetUniform( "uTexScale", Vector2( 0.0f, 1.0f / mTargetSize.height ) );
+ mRootActor.Add( mActorForInput );
+ mRootActor.Add( mActorForHorz );
SetupCamera();
CreateRenderTasks();
}
}
-void SpreadFilter::SetupCamera()
-{
- // Create and place a camera for the embossing render, corresponding to its render target size
- mCameraActor.SetFieldOfView(ARBITRARY_FIELD_OF_VIEW);
- mCameraActor.SetNearClippingPlane(1.0f);
- mCameraActor.SetAspectRatio(mTargetSize.width / mTargetSize.height);
- mCameraActor.SetType(Dali::Camera::FREE_LOOK); // camera orientation based solely on actor
- mCameraActor.SetPosition(0.0f, 0.0f, ((mTargetSize.height * 0.5f) / tanf(ARBITRARY_FIELD_OF_VIEW * 0.5f)));
-}
-
void SpreadFilter::CreateRenderTasks()
{
RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
*/
// EXTERNAL INCLUDES
-#include <dali/public-api/actors/camera-actor.h>
-#include <dali/public-api/actors/image-actor.h>
#include <dali/public-api/render-tasks/render-task.h>
-#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali-toolkit/public-api/controls/image-view/image-view.h>
// INTERNAL INCLUDES
#include "image-filter.h"
virtual void SetSize( const Vector2& size );
private:
- /**
- * Setup position and parameters for camera
- */
- void SetupCamera();
/**
* Setup render tasks for blur
SpreadFilter& operator=( const SpreadFilter& );
private: // Attributes
- int mSpread;
- CameraActor mCameraActor;
// To perform horizontal spread from mInputImage to mImageForHorz
- RenderTask mRenderTaskForHorz;
- ImageActor mActorForInput;
- FrameBufferImage mImageForHorz;
- ShaderEffect mShaderForHorz;
+ RenderTask mRenderTaskForHorz;
+ Toolkit::ImageView mActorForInput;
+ FrameBufferImage mImageForHorz;
// To perform vertical spread from mImageForHorz to mOutputImage
- RenderTask mRenderTaskForVert;
- ImageActor mActorForHorz;
- ShaderEffect mShaderForVert;
+ RenderTask mRenderTaskForVert;
+ Toolkit::ImageView mActorForHorz;
+
+ int mSpread;
}; // class SpreadFilter
} // namespace Internal
FreeFontFamilyNames( mFontDescriptionRuns );
}
+void LogicalModel::CreateParagraphInfo( CharacterIndex startIndex,
+ Length numberOfCharacters )
+{
+ const Length totalNumberOfCharacters = mLineBreakInfo.Count();
+
+ // Count the number of LINE_MUST_BREAK to reserve some space for the vector of paragraph's info.
+ Vector<CharacterIndex> paragraphs;
+ paragraphs.Reserve( numberOfCharacters );
+ const TextAbstraction::LineBreakInfo* lineBreakInfoBuffer = mLineBreakInfo.Begin();
+ const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters;
+ for( Length index = startIndex; index < lastCharacterIndexPlusOne; ++index )
+ {
+ if( TextAbstraction::LINE_MUST_BREAK == *( lineBreakInfoBuffer + index ) )
+ {
+ paragraphs.PushBack( index );
+ }
+ }
+
+ // Whether the current paragraphs are updated or set from scratch.
+ const bool updateCurrentParagraphs = numberOfCharacters < totalNumberOfCharacters;
+
+ // Reserve space for current paragraphs plus new ones.
+ const Length numberOfNewParagraphs = paragraphs.Count();
+ const Length totalNumberOfParagraphs = mParagraphInfo.Count() + numberOfNewParagraphs;
+ mParagraphInfo.Resize( totalNumberOfParagraphs );
+
+ ParagraphRun* paragraphInfoBuffer = NULL;
+ Vector<ParagraphRun> newParagraphs;
+
+ if( updateCurrentParagraphs )
+ {
+ newParagraphs.Resize( numberOfNewParagraphs );
+ paragraphInfoBuffer = newParagraphs.Begin();
+ }
+ else
+ {
+ paragraphInfoBuffer = mParagraphInfo.Begin();
+ }
+
+ // Find where to insert the new paragraphs.
+ ParagraphRunIndex paragraphIndex = 0u;
+ CharacterIndex firstIndex = startIndex;
+
+ if( updateCurrentParagraphs )
+ {
+ for( Vector<ParagraphRun>::ConstIterator it = mParagraphInfo.Begin(),
+ endIt = mParagraphInfo.Begin() + totalNumberOfParagraphs - numberOfNewParagraphs;
+ it != endIt;
+ ++it )
+ {
+ const ParagraphRun& paragraph( *it );
+
+ if( startIndex < paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters )
+ {
+ firstIndex = paragraph.characterRun.characterIndex;
+ break;
+ }
+
+ ++paragraphIndex;
+ }
+ }
+
+ // Create the paragraph info.
+ ParagraphRunIndex newParagraphIndex = 0u;
+ for( Vector<CharacterIndex>::ConstIterator it = paragraphs.Begin(),
+ endIt = paragraphs.End();
+ it != endIt;
+ ++it, ++newParagraphIndex )
+ {
+ const CharacterIndex index = *it;
+
+ ParagraphRun& paragraph = *( paragraphInfoBuffer + newParagraphIndex );
+ paragraph.characterRun.characterIndex = firstIndex;
+ paragraph.characterRun.numberOfCharacters = 1u + index - firstIndex;
+
+ firstIndex += paragraph.characterRun.numberOfCharacters;
+ }
+
+
+ // Insert the new paragraphs.
+ if( updateCurrentParagraphs )
+ {
+ mParagraphInfo.Insert( mParagraphInfo.Begin() + paragraphIndex,
+ newParagraphs.Begin(),
+ newParagraphs.End() );
+
+ mParagraphInfo.Resize( totalNumberOfParagraphs );
+
+ // Update the next paragraph indices.
+ for( Vector<ParagraphRun>::Iterator it = mParagraphInfo.Begin() + paragraphIndex + newParagraphs.Count(),
+ endIt = mParagraphInfo.End();
+ it != endIt;
+ ++it )
+ {
+ ParagraphRun& paragraph( *it );
+
+ paragraph.characterRun.characterIndex += numberOfCharacters;
+ }
+ }
+}
+
+void LogicalModel::FindParagraphs( CharacterIndex index,
+ Length numberOfCharacters,
+ Vector<ParagraphRunIndex>& paragraphs )
+{
+ // Reserve som space for the paragraph indices.
+ paragraphs.Reserve( mParagraphInfo.Count() );
+
+ // Traverse the paragraphs to find which ones contain the given characters.
+ ParagraphRunIndex paragraphIndex = 0u;
+ for( Vector<ParagraphRun>::ConstIterator it = mParagraphInfo.Begin(),
+ endIt = mParagraphInfo.End();
+ it != endIt;
+ ++it, ++paragraphIndex )
+ {
+ const ParagraphRun& paragraph( *it );
+
+ if( ( paragraph.characterRun.characterIndex + paragraph.characterRun.numberOfCharacters > index ) &&
+ ( paragraph.characterRun.characterIndex < index + numberOfCharacters ) )
+ {
+ paragraphs.PushBack( paragraphIndex );
+ }
+ }
+}
+
LogicalModel::~LogicalModel()
{
ClearFontDescriptionRuns();
#include <dali-toolkit/internal/text/color-run.h>
#include <dali-toolkit/internal/text/font-run.h>
#include <dali-toolkit/internal/text/font-description-run.h>
+#include <dali-toolkit/internal/text/paragraph-run.h>
#include <dali-toolkit/internal/text/script-run.h>
namespace Dali
*/
void ClearFontDescriptionRuns();
+ // Paragraphs
+
+ /**
+ * @brief Creates the paragraph info.
+ *
+ * @pre The line break info must be set.
+ *
+ * @param[in] startIndex The character from where the paragraph info is set.
+ * @param[in] numberOfCharacters The number of characters.
+ */
+ void CreateParagraphInfo( CharacterIndex startIndex,
+ Length numberOfCharacters );
+
+ /**
+ * @brief Find the paragraphs which contains the given characters.
+ *
+ * @param[in] index The first character's index of the run.
+ * @param[in] numberOfCharacters The number of characters of the run.
+ * @param[out] paragraphs Indices to the paragraphs which contain the characters.
+ */
+ void FindParagraphs( CharacterIndex index,
+ Length numberOfCharacters,
+ Vector<ParagraphRunIndex>& paragraphs );
+
protected:
/**
Vector<FontDescriptionRun> mFontDescriptionRuns;
Vector<LineBreakInfo> mLineBreakInfo;
Vector<WordBreakInfo> mWordBreakInfo;
+ Vector<ParagraphRun> mParagraphInfo;
Vector<BidirectionalParagraphInfoRun> mBidirectionalParagraphInfo;
Vector<CharacterDirection> mCharacterDirections; ///< For each character, whether is right to left. ( @e flase is left to right, @e true right to left ).
Vector<BidirectionalLineInfoRun> mBidirectionalLineInfo;
--- /dev/null
+#ifndef __DALI_TOOLKIT_TEXT_PARAGRAPH_RUN_H__
+#define __DALI_TOOLKIT_TEXT_PARAGRAPH_RUN_H__
+
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/math/vector2.h>
+
+// INTERNAL INCLUDES
+#include <dali-toolkit/internal/text/character-run.h>
+
+namespace Dali
+{
+
+namespace Toolkit
+{
+
+namespace Text
+{
+
+/**
+ * @brief ParagraphRun
+ *
+ * In terms of the bidirectional algorithm, a 'paragraph' is understood as a run of characters between Paragraph Separators or appropriate Newline Functions.
+ * A 'paragraph' may also be determined by higher-level protocols like a mark-up tag.
+ */
+struct ParagraphRun
+{
+ CharacterRun characterRun; ///< The initial character index within the whole text and the number of characters of the run.
+ Size layoutSize; ///< The size of the paragraph when is laid-out.
+};
+
+} // namespace Text
+
+} // namespace Toolkit
+
+} // namespace Dali
+
+#endif // __DALI_TOOLKIT_TEXT_PARAGRAPH_RUN_H__
{
void SetLineBreakInfo( const Vector<Character>& text,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<LineBreakInfo>& lineBreakInfo )
{
- const Length numberOfCharacters = text.Count();
+ const Length totalNumberOfCharacters = text.Count();
- if( 0u == numberOfCharacters )
+ if( 0u == totalNumberOfCharacters )
{
// Nothing to do if there are no characters.
return;
}
// Retrieve the line break info.
- lineBreakInfo.Resize( numberOfCharacters );
- TextAbstraction::Segmentation::Get().GetLineBreakPositions( text.Begin(),
+ lineBreakInfo.Resize( totalNumberOfCharacters );
+
+ // Whether the current buffer is being updated or is set from scratch.
+ const bool updateCurrentBuffer = numberOfCharacters < totalNumberOfCharacters;
+
+ LineBreakInfo* lineBreakInfoBuffer = NULL;
+ Vector<LineBreakInfo> newLineBreakInfo;
+
+ if( updateCurrentBuffer )
+ {
+ newLineBreakInfo.Resize( numberOfCharacters );
+ lineBreakInfoBuffer = newLineBreakInfo.Begin();
+ }
+ else
+ {
+ lineBreakInfoBuffer = lineBreakInfo.Begin();
+ }
+
+ // Retrieve the line break info.
+ TextAbstraction::Segmentation::Get().GetLineBreakPositions( text.Begin() + startIndex,
numberOfCharacters,
- lineBreakInfo.Begin() );
+ lineBreakInfoBuffer );
+
+ // If the line break info is updated, it needs to be inserted in the model.
+ if( updateCurrentBuffer )
+ {
+ lineBreakInfo.Insert( lineBreakInfo.Begin() + startIndex,
+ newLineBreakInfo.Begin(),
+ newLineBreakInfo.End() );
+ lineBreakInfo.Resize( totalNumberOfCharacters );
+ }
+
#ifdef DEBUG_ENABLED
if( gLogFilter->IsEnabledFor(Debug::Verbose) )
{
* - 2 is a LINE_NO_BREAK. Text can't be broken into a new line.
*
* @param[in] text Vector of UTF-32 characters.
+ * @param[in] startIndex The character from where the break info is set.
+ * @param[in] numberOfCharacters The number of characters.
* @param[out] lineBreakInfo The line break info
*/
void SetLineBreakInfo( const Vector<Character>& text,
+ CharacterIndex startIndex,
+ Length numberOfCharacters,
Vector<LineBreakInfo>& lineBreakInfo );
/**
shaping.GetGlyphs( tmpGlyphs.Begin(),
tmpGlyphToCharacterMap.Begin() );
- // Update the indices.
+ // Update the new indices of the glyph to character map.
if( 0u != totalNumberOfGlyphs )
{
for( Vector<CharacterIndex>::Iterator it = tmpGlyphToCharacterMap.Begin(),
lineBreakInfo.Resize( numberOfCharacters, TextAbstraction::LINE_NO_BREAK );
SetLineBreakInfo( utf32Characters,
+ startIndex,
+ requestedNumberOfCharacters,
lineBreakInfo );
+
+ // Create the paragraph info.
+ mLogicalModel->CreateParagraphInfo( startIndex,
+ requestedNumberOfCharacters );
}
Vector<WordBreakInfo>& wordBreakInfo = mLogicalModel->mWordBreakInfo;
newParagraphGlyphs );
// Create the 'number of glyphs' per character and the glyph to character conversion tables.
- mVisualModel->CreateGlyphsPerCharacterTable( startIndex, numberOfCharacters );
- mVisualModel->CreateCharacterToGlyphTable( startIndex, numberOfCharacters );
+ mVisualModel->CreateGlyphsPerCharacterTable( startIndex, startGlyphIndex, numberOfCharacters );
+ mVisualModel->CreateCharacterToGlyphTable( startIndex, startGlyphIndex, numberOfCharacters );
}
const Length numberOfGlyphs = glyphs.Count();
return 0.0f;
}
-void Controller::UpdateAfterFontChange( std::string& newDefaultFont )
+void Controller::UpdateAfterFontChange( const std::string& newDefaultFont )
{
DALI_LOG_INFO( gLogFilter, Debug::Concise, "Controller::UpdateAfterFontChange");
return mImpl->mTextColor;
}
-bool Controller::RemoveText( int cursorOffset, int numberOfChars )
+bool Controller::RemoveText( int cursorOffset, int numberOfCharacters )
{
bool removed = false;
return removed;
}
- DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfChars %d\n",
- this, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition, cursorOffset, numberOfChars );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p mText.Count() %d cursor %d cursorOffset %d numberOfCharacters %d\n",
+ this, mImpl->mLogicalModel->mText.Count(), mImpl->mEventData->mPrimaryCursorPosition, cursorOffset, numberOfCharacters );
if( !mImpl->IsShowingPlaceholderText() )
{
cursorIndex = oldCursorIndex + cursorOffset;
}
- if( ( cursorIndex + numberOfChars ) > currentText.Count() )
+ if( ( cursorIndex + numberOfCharacters ) > currentText.Count() )
{
- numberOfChars = currentText.Count() - cursorIndex;
+ numberOfCharacters = currentText.Count() - cursorIndex;
}
- if( ( cursorIndex + numberOfChars ) <= currentText.Count() )
+ if( ( cursorIndex + numberOfCharacters ) <= currentText.Count() )
{
// Update the input style and remove the text's style before removing the text.
mImpl->mLogicalModel->RetrieveStyle( cursorIndex, mImpl->mEventData->mInputStyle );
// Remove the text's style before removing the text.
- mImpl->mLogicalModel->UpdateTextStyleRuns( cursorIndex, -numberOfChars );
+ mImpl->mLogicalModel->UpdateTextStyleRuns( cursorIndex, -numberOfCharacters );
// Remove the characters.
Vector<Character>::Iterator first = currentText.Begin() + cursorIndex;
- Vector<Character>::Iterator last = first + numberOfChars;
+ Vector<Character>::Iterator last = first + numberOfCharacters;
currentText.Erase( first, last );
// Cursor position retreat
oldCursorIndex = cursorIndex;
- DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", this, numberOfChars );
+ DALI_LOG_INFO( gLogFilter, Debug::General, "Controller::RemoveText %p removed %d\n", this, numberOfCharacters );
removed = true;
}
}
// Remove the previous IMF pre-edit (predicitive text)
if( mImpl->mEventData->mPreEditFlag &&
- ( 0 != mImpl->mEventData->mPreEditLength ) )
+ ( 0u != mImpl->mEventData->mPreEditLength ) )
{
- CharacterIndex offset = mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition;
+ const CharacterIndex offset = mImpl->mEventData->mPrimaryCursorPosition - mImpl->mEventData->mPreEditStartPosition;
- removedPrevious = RemoveText( -static_cast<int>(offset), mImpl->mEventData->mPreEditLength );
+ removedPrevious = RemoveText( -static_cast<int>( offset ), mImpl->mEventData->mPreEditLength );
mImpl->mEventData->mPrimaryCursorPosition = mImpl->mEventData->mPreEditStartPosition;
- mImpl->mEventData->mPreEditLength = 0;
+ mImpl->mEventData->mPreEditLength = 0u;
}
else
{
const Length numberOfCharactersInModel = mImpl->mLogicalModel->mText.Count();
- // Restrict new text to fit within Maximum characters setting
+ // Restrict new text to fit within Maximum characters setting.
Length maxSizeOfNewText = std::min( ( mImpl->mMaximumNumberOfCharacters - numberOfCharactersInModel ), characterCount );
maxLengthReached = ( characterCount > maxSizeOfNewText );
// Transform a text array encoded in utf8 into an array encoded in utf32.
// It returns the actual number of characters.
- Length characterCount = Utf8ToUtf32( utf8, size, utf32Characters.Begin() );
+ const Length characterCount = Utf8ToUtf32( utf8, size, utf32Characters.Begin() );
utf32Characters.Resize( characterCount );
// Reset the cursor position
* @brief Remove a given number of characters
*
* @param[in] cursorOffset Start position from the current cursor position to start deleting characters.
- * @param[in] numberOfChars The number of characters to delete from the cursorOffset.
+ * @param[in] numberOfCharacters The number of characters to delete from the cursorOffset.
* @return True if the remove was successful.
*/
- bool RemoveText( int cursorOffset, int numberOfChars );
+ bool RemoveText( int cursorOffset, int numberOfCharacters );
/**
* @brief Retrieve the current cursor position.
* @ brief Update the text after a font change
* @param[in] newDefaultFont The new font to change to
*/
- void UpdateAfterFontChange( std::string& newDefaultFont );
+ void UpdateAfterFontChange( const std::string& newDefaultFont );
/**
* @brief Set the text color
typedef uint32_t BidirectionalRunIndex; ///< An index into an array of bidirectional info.
typedef uint32_t BidirectionalLineRunIndex; ///< An index into an array of bidirectional line info.
typedef uint32_t LineIndex; ///< An index into an array of lines.
+typedef uint32_t ParagraphRunIndex; ///< An index into an array of paragraphs.
} // namespace Text
-#ifndef __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__
-#define __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__
+#ifndef __DALI_TOOLKIT_TEXT_RUN_CONTAINER_H__
+#define __DALI_TOOLKIT_TEXT_RUN_CONTAINER_H__
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
( startIndex >= run->glyphRun.glyphIndex + run->glyphRun.numberOfGlyphs ) )
{
// Run found. Nothing else to do.
+ break;
}
++run;
} // namespace Dali
-#endif // __DALI_TOOLKIT_TEXT_STYLE_RUN_CONTAINER_H__
+#endif // __DALI_TOOLKIT_TEXT_RUN_CONTAINER_H__
}
void VisualModel::CreateCharacterToGlyphTable( CharacterIndex startIndex,
+ GlyphIndex startGlyphIndex,
Length numberOfCharacters )
{
if( 0u == numberOfCharacters )
// 2) Traverse the glyphs and set the glyph indices per character.
// Index to the glyph.
- const GlyphIndex startGlyphIndex = updateCurrentBuffer ? *( mCharactersToGlyph.Begin() + startIndex ) : 0u;
GlyphIndex glyphIndex = startGlyphIndex;
CharacterIndex characterIndex = startIndex;
const CharacterIndex lastCharacterIndexPlusOne = startIndex + numberOfCharacters;
}
void VisualModel::CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
+ GlyphIndex startGlyphIndex,
Length numberOfCharacters )
{
if( 0u == numberOfCharacters )
// 2) Traverse the glyphs and set the number of glyphs per character.
- // The glyph index.
- const GlyphIndex glyphIndex = updateCurrentBuffer ? *( mCharactersToGlyph.Begin() + startIndex ) : 0u;
Length traversedCharacters = 0;
// The number of 'characters per glyph' equal to zero.
Length zeroCharactersPerGlyph = 0u;
- for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin() + glyphIndex,
+ for( Vector<Length>::ConstIterator it = mCharactersPerGlyph.Begin() + startGlyphIndex,
endIt = mCharactersPerGlyph.End();
( it != endIt ) && ( traversedCharacters < numberOfCharacters );
++it )
* @pre The glyphs per character table needs to be created first.
*
* @param[in] startIndex The character from where the conversion table is created.
+ * @param[in] startGlyphIndex The glyph from where the conversion table is created.
* @param[in] numberOfCharacters The number of characters.
*/
void CreateCharacterToGlyphTable( CharacterIndex startIndex,
+ GlyphIndex startGlyphIndex,
Length numberOfCharacters );
/**
* @brief Creates an array containing the number of glyphs per character.
*
* @param[in] startIndex The character from where the table is created.
+ * @param[in] startGlyphIndex The glyph from where the conversion table is created.
* @param[in] numberOfCharacters The number of characters.
*/
void CreateGlyphsPerCharacterTable( CharacterIndex startIndex,
+ GlyphIndex startGlyphIndex,
Length numberOfCharacters );
/**
void CubeTransitionEffect::OnStageConnection( int depth )
{
+ Control::OnStageConnection( depth );
+
Geometry geometry = CreateQuadGeometry();
Shader shader = Shader::New( VERTEX_SHADER, FRAGMENT_SHADER );
}
mTargetRenderer.Reset();
}
+
+ Control::OnStageDisconnection();
}
void CubeTransitionEffect::SetTransitionDuration( float duration )
mLongPressGestureDetector(),
mFlags( Control::ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ),
mIsKeyboardNavigationSupported( false ),
- mIsKeyboardFocusGroup( false ),
- mAddRemoveBackgroundChild( false )
+ mIsKeyboardFocusGroup( false )
{
}
ControlBehaviour mFlags :CONTROL_BEHAVIOUR_FLAG_COUNT; ///< Flags passed in from constructor.
bool mIsKeyboardNavigationSupported :1; ///< Stores whether keyboard navigation is supported by the control.
bool mIsKeyboardFocusGroup :1; ///< Stores whether the control is a focus group.
- bool mAddRemoveBackgroundChild:1; ///< Flag to know when we are adding or removing our own actor to avoid call to OnControlChildAdd
// Properties - these need to be members of Internal::Control::Impl as they need to function within this class.
static const PropertyRegistration PROPERTY_1;
void Control::OnChildAdd(Actor& child)
{
- // If this is the background actor, then we do not want to inform deriving classes
- if ( mImpl->mAddRemoveBackgroundChild )
- {
- return;
- }
-
// Notify derived classes.
OnControlChildAdd( child );
}
void Control::OnChildRemove(Actor& child)
{
- // If this is the background actor, then we do not want to inform deriving classes
- if ( mImpl->mAddRemoveBackgroundChild )
- {
- return;
- }
-
// Notify derived classes.
OnControlChildRemove( child );
}
void Control::OnSizeSet(const Vector3& targetSize)
{
- // Background is resized through size negotiation
+ if( mImpl->mBackgroundRenderer )
+ {
+ Vector2 size( targetSize );
+ mImpl->mBackgroundRenderer.SetSize( size );
+ }
}
void Control::OnSizeAnimation(Animation& animation, const Vector3& targetSize)
/**
* @copydoc CustomActorImpl::OnStageConnection()
+ * @note If overridden, then an up-call to Control::OnStageConnection MUST be made at the start.
*/
virtual void OnStageConnection( int depth );
/**
* @copydoc CustomActorImpl::OnStageDisconnection()
+ * @note If overridden, then an up-call to Control::OnStageDisconnection MUST be made at the end.
*/
virtual void OnStageDisconnection();
/**
* @copydoc CustomActorImpl::OnChildAdd()
+ * @note If overridden, then an up-call to Control::OnChildAdd MUST be made at the start.
*/
virtual void OnChildAdd( Actor& child );
/**
* @copydoc CustomActorImpl::OnChildRemove()
+ * @note If overridden, then an up-call to Control::OnChildRemove MUST be made at the end.
*/
virtual void OnChildRemove( Actor& child );
/**
* @copydoc CustomActorImpl::OnSizeSet()
+ * @note If overridden, then an up-call to Control::OnSizeSet MUST be made at the start.
*/
virtual void OnSizeSet( const Vector3& targetSize );
/**
* @copydoc CustomActorImpl::OnSizeAnimation()
+ * @note If overridden, then an up-call to Control::OnSizeAnimation MUST be made at the start.
*/
virtual void OnSizeAnimation( Animation& animation, const Vector3& targetSize );
virtual void OnInitialize();
/**
+ * @DEPRECATED_1_1.30. Override OnChildAdd instead.
+ *
* @brief Called whenever an Actor is added to the control.
*
* Could be overridden by derived classes.
virtual void OnControlChildAdd( Actor& child );
/**
+ * @DEPRECATED_1_1.30. Override OnChildRemove instead.
+ *
* @brief Called whenever an Actor is removed from the control.
*
* Could be overridden by derived classes.
/**
* @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
const unsigned int TOOLKIT_MAJOR_VERSION = 1;
const unsigned int TOOLKIT_MINOR_VERSION = 1;
-const unsigned int TOOLKIT_MICRO_VERSION = 29;
+const unsigned int TOOLKIT_MICRO_VERSION = 30;
const char * const TOOLKIT_BUILD_DATE = __DATE__ " " __TIME__;
#ifdef DEBUG_ENABLED
customControl.MyCustomSignal.Connect( this, &AppFunction );
~~~
+
+___________________________________________________________________________________________________
+
+### Children Added/Removed {#creating-controls-children}
+
+Methods are provided that can be overridden if notification is required when a child is added or removed from our control.
+An up call to the Control class is necessary if these methods are overridden.
+
+~~~{.cpp}
+// C++
+void MyUIControlImpl::OnChildAdd( Actor& child );
+{
+ // Up call to Control first
+ Control::OnChildAdd( child );
+
+ // Do any other operations required upon child addition
+}
+~~~
+~~~{.cpp}
+// C++
+void MyUIControlImpl::OnChildRemove( Actor& child );
+{
+ // Do any other operations required upon child removal
+
+ // Up call to Control at the end
+ Control::OnChildRemove( child );
+}
+~~~
+
+Avoid adding or removing the child again within these methods.
+
+___________________________________________________________________________________________________
+
+### Stage Connection {#creating-controls-stage}
+
+Methods are provided that can be overridden if notification is required when our control is connected to or disconnected from the stage.
+An up call to the Control class is necessary if these methods are overridden.
+
+~~~{.cpp}
+// C++
+void MyUIControlImpl::OnStageConnection( int depth )
+{
+ // Up call to Control first
+ Control::OnStageConnection( depth );
+
+ // Do any other operations required upon stage connection
+}
+~~~
+~~~{.cpp}
+// C++
+void MyUIControlImpl::OnStageDisconnection()
+{
+ // Do any other operations required upon stage disconnection
+
+ // Up call to Control at the end
+ Control::OnStageDisconnection();
+}
+~~~
+
+___________________________________________________________________________________________________
+
+### Size {#creating-controls-size}
+
+Methods are provided that can be overridden if notification is required when our control's size is manipulated.
+An up call to the Control class is necessary if these methods are overridden.
+
+~~~{.cpp}
+// C++
+void MyUIControlImpl::OnSizeSet( const Vector3& targetSize )
+{
+ // Up call to Control
+ Control::OnSizeSet( targetSize );
+
+ // Do any other operations required upon size set
+}
+~~~
+~~~{.cpp}
+// C++
+void MyUIControlImpl::OnSizeAnimation( Animation& animation, const Vector3& targetSize )
+{
+ // Up call to Control
+ Control::OnSizeAnimation( animation, targetSize );
+
+ // Do any other operations required upon size animation
+}
+~~~
+
___________________________________________________________________________________________________
### Other Features {#creating-controls-other}
Name: dali-toolkit
Summary: The OpenGLES Canvas Core Library Toolkit
-Version: 1.1.29
+Version: 1.1.30
Release: 1
Group: System/Libraries
License: Apache-2.0 and BSD-2-Clause and MIT