From 5b7659f0561920937f41f5e2afc95dabc6e056db Mon Sep 17 00:00:00 2001 From: Xiangyin Ma Date: Wed, 13 May 2015 13:53:10 +0100 Subject: [PATCH] Update refraction-effect & radial-menu to use new mesh Change-Id: I6007af3cd1f01b9e8845b9edf8cbbffdf2eef6c6 --- examples/radial-menu/radial-menu-example.cpp | 308 +++++++++++ examples/radial-menu/radial-sweep-view-impl.cpp | 367 +++++++++++++ examples/radial-menu/radial-sweep-view-impl.h | 118 ++++ examples/radial-menu/radial-sweep-view.cpp | 184 +++++++ examples/radial-menu/radial-sweep-view.h | 150 +++++ .../refraction-effect-example.cpp | 609 +++++++++++++++++++++ 6 files changed, 1736 insertions(+) create mode 100644 examples/radial-menu/radial-menu-example.cpp create mode 100644 examples/radial-menu/radial-sweep-view-impl.cpp create mode 100644 examples/radial-menu/radial-sweep-view-impl.h create mode 100644 examples/radial-menu/radial-sweep-view.cpp create mode 100644 examples/radial-menu/radial-sweep-view.h create mode 100644 examples/refraction-effect/refraction-effect-example.cpp diff --git a/examples/radial-menu/radial-menu-example.cpp b/examples/radial-menu/radial-menu-example.cpp new file mode 100644 index 0000000..be8d6ee --- /dev/null +++ b/examples/radial-menu/radial-menu-example.cpp @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2015 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. + * + */ + +#include +#include +#include "shared/view.h" +#include "radial-sweep-view.h" +#include "radial-sweep-view-impl.h" + +using namespace Dali; +using namespace Dali::Toolkit; + +namespace +{ +const char* TEST_OUTER_RING_FILENAME = DALI_IMAGE_DIR "layer2.png"; // Image to be masked +const char* TEST_INNER_RING_FILENAME = DALI_IMAGE_DIR "layer1.png"; // Image to be masked +const char* TEST_MENU_FILENAME = DALI_IMAGE_DIR "layer3.png"; // Image to be masked +const char* TEST_DIAL_FILENAME = DALI_IMAGE_DIR "layer4.png"; // Image to be masked +const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" ); // Background for toolbar +const char* APPLICATION_TITLE( "Radial Menu" ); +const char * const PLAY_ICON( DALI_IMAGE_DIR "icon-play.png" ); +const char * const STOP_ICON( DALI_IMAGE_DIR "icon-stop.png" ); +} + + +/******************************************************************************** + * Application controller class + */ + +// This example shows how to create a mesh actor for use as a stencil buffer +class RadialMenuExample : public ConnectionTracker +{ +public: + /** + * Constructor + * @param[in] app The application handle + */ + RadialMenuExample(Application app); + + /** + * Destructor + */ + ~RadialMenuExample(); + +private: + + /** + * Initialization signal handler - all actor initialization should happen here + * @param[in] app The application handle + */ + void OnInit(Application& app); + + /** + * Create a sweep view with the given image and parameters + */ + RadialSweepView CreateSweepView( std::string imageName, Degree initial, Degree final ); + + /** + * Start the sweep animation on the menu + */ + void StartAnimation(); + + /** + * Play or pause the animation when the button is clicked + */ + bool OnButtonClicked( Toolkit::Button button ); + + /** + * Update the state flag and change the button icon when the animation is finished + */ + void OnAnimationFinished( Animation& source ); + + /** + * Main key event handler + * + * @param[in] event The key event to respond to + */ + void OnKeyEvent(const KeyEvent& event); + +private: // Member variables + enum AnimState + { + STOPPED, + PAUSED, + PLAYING + }; + + Application mApplication; ///< The application handle + Toolkit::Control mView; ///< The toolbar view + Layer mContents; ///< The toolbar contents pane + ImageActor mImageActor; ///< Image actor shown by stencil mask + Animation mAnimation; + AnimState mAnimationState; + + Image mIconPlay; + Image mIconStop; + Toolkit::PushButton mPlayStopButton; + ImageActor mDialActor; + RadialSweepView mRadialSweepView1; + RadialSweepView mRadialSweepView2; + RadialSweepView mRadialSweepView3; +}; + +RadialMenuExample::RadialMenuExample(Application app) +: mApplication( app ), + mAnimationState(STOPPED) +{ + // Connect to the Application's Init signal + app.InitSignal().Connect(this, &RadialMenuExample::OnInit); +} + +RadialMenuExample::~RadialMenuExample() +{ + // Nothing to do here; actor handles will clean up themselves. +} + +void RadialMenuExample::OnInit(Application& app) +{ + DemoHelper::RequestThemeChange(); + + Stage stage = Dali::Stage::GetCurrent(); + + // The Init signal is received once (only) during the Application lifetime + stage.KeyEventSignal().Connect(this, &RadialMenuExample::OnKeyEvent); + + // Create toolbar & view + Toolkit::ToolBar toolBar; + mContents = DemoHelper::CreateView( mApplication, + mView, + toolBar, + "", + TOOLBAR_IMAGE, + APPLICATION_TITLE ); + + mIconPlay = ResourceImage::New( PLAY_ICON ); + mIconStop = ResourceImage::New( STOP_ICON ); + mPlayStopButton = Toolkit::PushButton::New(); + mPlayStopButton.SetBackgroundImage( mIconStop ); + + mPlayStopButton.ClickedSignal().Connect( this, &RadialMenuExample::OnButtonClicked ); + + toolBar.AddControl( mPlayStopButton, + DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, + Toolkit::Alignment::HorizontalRight, + DemoHelper::DEFAULT_PLAY_PADDING ); + + + const ImageDimensions intImgSize = ResourceImage::GetImageSize(TEST_OUTER_RING_FILENAME); + Vector2 imgSize = Vector2( intImgSize.GetWidth(), intImgSize.GetHeight() ); + Vector2 stageSize = stage.GetSize(); + float scale = stageSize.width / imgSize.width; + float availableHeight = stageSize.height - DemoHelper::DEFAULT_VIEW_STYLE.mToolBarHeight * 2.0f; + if(availableHeight <= stageSize.width) + { + scale = availableHeight / imgSize.width; + } + + mRadialSweepView1 = CreateSweepView( TEST_OUTER_RING_FILENAME, Degree(-90.0f), Degree(-90.0f)); + mRadialSweepView2 = CreateSweepView( TEST_INNER_RING_FILENAME, Degree(90.0f), Degree(0.0f)); + mRadialSweepView3 = CreateSweepView( TEST_MENU_FILENAME, Degree(100.0f), Degree(0.0f)); + mRadialSweepView3.SetInitialActorAngle(Degree(-110)); + mRadialSweepView3.SetFinalActorAngle(Degree(0)); + + Image dial = ResourceImage::New( TEST_DIAL_FILENAME ); + mDialActor = ImageActor::New( dial ); + mDialActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + mDialActor.SetPositionInheritanceMode(USE_PARENT_POSITION); + mDialActor.SetScale(scale); + Layer dialLayer = Layer::New(); + + dialLayer.Add(mDialActor); + dialLayer.SetPositionInheritanceMode(USE_PARENT_POSITION); + dialLayer.SetSize(stage.GetSize()); + mContents.Add(dialLayer); + + mRadialSweepView1.SetScale(scale); + mRadialSweepView2.SetScale(scale); + mRadialSweepView3.SetScale(scale); + + StartAnimation(); +} + +void RadialMenuExample::StartAnimation() +{ + mDialActor.SetOpacity(0.0f); + mRadialSweepView1.SetOpacity(0.0f); + mAnimation = Animation::New(6.0f); + mRadialSweepView1.Activate(mAnimation, 0.0f, 3.0f); + mRadialSweepView2.Activate(mAnimation, 1.5f, 3.0f); + mRadialSweepView3.Activate(mAnimation, 3.0f, 3.0f); + mAnimation.AnimateTo( Property( mDialActor, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN, TimePeriod( 0.0f, 0.8f ) ); + mAnimation.AnimateTo( Property( mRadialSweepView1, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN, TimePeriod( 0.0f, 0.5f ) ); + mAnimation.FinishedSignal().Connect( this, &RadialMenuExample::OnAnimationFinished ); + + mAnimationState = PLAYING; + mAnimation.Play(); +} + +bool RadialMenuExample::OnButtonClicked( Toolkit::Button button ) +{ + switch( mAnimationState ) + { + case PLAYING: + { + mAnimation.Pause(); + mAnimationState = PAUSED; + mPlayStopButton.SetBackgroundImage( mIconPlay ); + } + break; + + case PAUSED: + { + mAnimation.Play(); + mAnimationState = PLAYING; + mPlayStopButton.SetBackgroundImage( mIconStop ); + } + break; + + case STOPPED: + { + mPlayStopButton.SetBackgroundImage( mIconStop ); + mRadialSweepView1.Deactivate(); + mRadialSweepView2.Deactivate(); + mRadialSweepView3.Deactivate(); + StartAnimation(); + } + } + return false; +} + +void RadialMenuExample::OnAnimationFinished( Animation& source ) +{ + mAnimationState = STOPPED; + mPlayStopButton.SetBackgroundImage( mIconPlay ); +} + +RadialSweepView RadialMenuExample::CreateSweepView( std::string imageName, + Degree initialAngle, + Degree finalAngle) +{ + // Create the image + Image image = ResourceImage::New(imageName); + mImageActor = ImageActor::New(image); + mImageActor.SetParentOrigin(ParentOrigin::CENTER); + mImageActor.SetAnchorPoint(AnchorPoint::CENTER); + mImageActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + + // Create the stencil + const ImageDimensions imageSize = ResourceImage::GetImageSize(imageName); + float diameter = std::max(imageSize.GetWidth(), imageSize.GetHeight()); + RadialSweepView radialSweepView = RadialSweepView::New(); + radialSweepView.SetDiameter( diameter ); + radialSweepView.SetInitialAngle( initialAngle ); + radialSweepView.SetFinalAngle( finalAngle ); + radialSweepView.SetInitialSector( Degree(0.0f) ); + radialSweepView.SetFinalSector( Degree(359.999f) ); + radialSweepView.SetSize( Stage::GetCurrent().GetSize()); + radialSweepView.SetEasingFunction( Dali::AlphaFunction::EASE_IN_OUT ); + radialSweepView.SetPositionInheritanceMode(USE_PARENT_POSITION); + mContents.Add(radialSweepView); + radialSweepView.Add( mImageActor ); + mImageActor.SetPositionInheritanceMode(USE_PARENT_POSITION); + + return radialSweepView; +} + + +void RadialMenuExample::OnKeyEvent(const KeyEvent& event) +{ + if(event.state == KeyEvent::Down) + { + if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) ) + { + mApplication.Quit(); + } + } +} + +void RunTest(Application app) +{ + RadialMenuExample test(app); + + app.MainLoop(); +} + +// Entry point for Linux & Tizen applications +int main(int argc, char **argv) +{ + Application app = Application::New(&argc, &argv); + + RunTest(app); + + return 0; +} diff --git a/examples/radial-menu/radial-sweep-view-impl.cpp b/examples/radial-menu/radial-sweep-view-impl.cpp new file mode 100644 index 0000000..f13d58a --- /dev/null +++ b/examples/radial-menu/radial-sweep-view-impl.cpp @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2015 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. + * + */ + +#include "radial-sweep-view-impl.h" + +#include + +using namespace Dali; + +namespace +{ + +const char* VERTEX_SHADER_PREFIX( "#define MATH_PI_2 1.570796\n#define MATH_PI_4 0.785398\n" ); + +const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( +attribute mediump float aAngleIndex;\n +attribute mediump vec2 aPosition1;\n +attribute mediump vec2 aPosition2;\n +uniform mediump mat4 uMvpMatrix;\n +uniform mediump float uStartAngle;\n +uniform mediump float uRotationAngle;\n +\n +void main()\n +{\n + float currentAngle = uStartAngle + uRotationAngle;\n + float angleInterval1 = MATH_PI_4 * aAngleIndex;\n + vec4 vertexPosition = vec4(0.0, 0.0, 0.0, 1.0);\n + if( currentAngle >= angleInterval1)\n + {\n + float angleInterval2 = angleInterval1 + MATH_PI_2;\n + float angle = currentAngle < angleInterval2 ? currentAngle : angleInterval2;\n + float delta;\n + if( mod( aAngleIndex+4.0, 4.0) < 2.0 )\n + {\n + delta = 0.5 - 0.5*cos(angle) / sin(angle);\n + }\n + else\n + {\n + delta = 0.5 + 0.5*sin(angle) / cos(angle);\n + }\n + vertexPosition.xy = mix( aPosition1, aPosition2, delta );\n + }\n + gl_Position = uMvpMatrix * vertexPosition;\n +} +); + +const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( +uniform lowp vec4 uColor;\n +\n +void main()\n +{\n + gl_FragColor = uColor;\n +}\n +); + +float HoldZeroFastEaseInOutHoldOne(float progress) +{ + if( progress < 0.2f) + { + return 0.0f; + } + else if(progress < 0.5f) + { + progress = (progress-0.2) / 0.3f; + return progress*progress*progress*0.5f; + } + else if(progress < 0.8f) + { + progress = ((progress - 0.5f) / 0.3f) - 1.0f; + return (progress*progress*progress+1.0f) * 0.5f + 0.5f; + } + else + { + return 1.0f; + } +} + +} // anonymous namespace + + +RadialSweepView RadialSweepViewImpl::New( ) +{ + return New( 2.0f, 100.0f, ANGLE_0, ANGLE_0, ANGLE_0, ANGLE_360 ); +} + + +RadialSweepView RadialSweepViewImpl::New( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector ) +{ + RadialSweepViewImpl* impl= new RadialSweepViewImpl(duration, diameter, initialAngle, finalAngle, initialSector, finalSector); + RadialSweepView handle = RadialSweepView(*impl); + return handle; +} + +RadialSweepViewImpl::RadialSweepViewImpl( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector ) +: Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ), + mDuration(duration), + mDiameter(diameter), + mInitialAngle(initialAngle), + mFinalAngle(finalAngle), + mInitialSector(initialSector), + mFinalSector(finalSector), + mInitialActorAngle(0), + mFinalActorAngle(0), + mEasingFunction(HoldZeroFastEaseInOutHoldOne), + mStartAngleIndex(Property::INVALID_INDEX), + mRotationAngleIndex(Property::INVALID_INDEX), + mRotateActorsWithStencil(false), + mRotateActors(false) +{ +} + +void RadialSweepViewImpl::SetDuration(float duration) +{ + mDuration = duration; +} + +void RadialSweepViewImpl::SetEasingFunction( Dali::AlphaFunction easingFunction ) +{ + mEasingFunction = easingFunction; +} + +void RadialSweepViewImpl::SetDiameter(float diameter) +{ + mDiameter = diameter; +} + +void RadialSweepViewImpl::SetInitialAngle( Dali::Radian initialAngle) +{ + mInitialAngle = initialAngle; +} + +void RadialSweepViewImpl::SetFinalAngle( Dali::Radian finalAngle) +{ + mFinalAngle = finalAngle; +} + +void RadialSweepViewImpl::SetInitialSector( Dali::Radian initialSector) +{ + mInitialSector = initialSector; +} + +void RadialSweepViewImpl::SetFinalSector( Dali::Radian finalSector) +{ + mFinalSector = finalSector; +} + +void RadialSweepViewImpl::SetInitialActorAngle( Dali::Radian initialAngle ) +{ + mInitialActorAngle = initialAngle; + mRotateActors = true; +} + +void RadialSweepViewImpl::SetFinalActorAngle( Dali::Radian finalAngle ) +{ + mFinalActorAngle = finalAngle; + mRotateActors = true; +} + +float RadialSweepViewImpl::GetDuration( ) +{ + return mDuration; +} + +float RadialSweepViewImpl::GetDiameter( ) +{ + return mDiameter; +} + +Dali::Radian RadialSweepViewImpl::GetInitialAngle( ) +{ + return mInitialAngle; +} + +Dali::Radian RadialSweepViewImpl::GetFinalAngle( ) +{ + return mFinalAngle; +} + +Dali::Radian RadialSweepViewImpl::GetInitialSector( ) +{ + return mInitialSector; +} + +Dali::Radian RadialSweepViewImpl::GetFinalSector( ) +{ + return mFinalSector; +} + +Dali::Radian RadialSweepViewImpl::GetInitialActorAngle( ) +{ + return mInitialActorAngle; +} + +Dali::Radian RadialSweepViewImpl::GetFinalActorAngle( ) +{ + return mFinalActorAngle; +} + +void RadialSweepViewImpl::RotateActorsWithStencil(bool rotate) +{ + mRotateActorsWithStencil = rotate; +} + +void RadialSweepViewImpl::Add(Actor actor) +{ + if( ! mLayer ) + { + mLayer = Layer::New(); + Self().Add(mLayer); + mLayer.SetSize( Stage::GetCurrent().GetSize() ); + mLayer.SetPositionInheritanceMode(USE_PARENT_POSITION); + } + + mLayer.Add(actor); +} + +void RadialSweepViewImpl::Activate( Animation anim, float offsetTime, float duration ) +{ + bool startAnimation=false; + if( ! anim ) + { + mAnim = Animation::New( mDuration ); + anim = mAnim; + startAnimation = true; + } + + if( ! mStencilActor ) + { + CreateStencil( mInitialSector ); + mLayer.Add( mStencilActor ); + mStencilActor.SetScale(mDiameter); + } + + mStencilActor.SetOrientation( mInitialAngle, Vector3::ZAXIS ); + mStencilActor.SetProperty( mRotationAngleIndex, mInitialSector.radian ); + + if( mRotateActors ) + { + for(unsigned int i=0, count=mLayer.GetChildCount(); i +#include "radial-sweep-view.h" + + +/******************************************************************************** + * Class to implement a layer with a radial sweep stencil mask and an actor tree + */ +class RadialSweepViewImpl : public Dali::Toolkit::Internal::Control +{ +public: + static RadialSweepView New(); + + static RadialSweepView New( float duration, + float diameter, + Dali::Radian initialAngle, + Dali::Radian finalAngle, + Dali::Radian initialSector, + Dali::Radian finalSector ); + + RadialSweepViewImpl( float duration, + float diameter, + Dali::Radian initialAngle, + Dali::Radian finalAngle, + Dali::Radian initialSector, + Dali::Radian finalSector ); + + void SetDuration(float duration); + void SetEasingFunction( Dali::AlphaFunction easingFunction ); + + void SetDiameter(float diameter); + void SetInitialAngle( Dali::Radian initialAngle); + void SetFinalAngle( Dali::Radian finalAngle); + void SetInitialSector( Dali::Radian initialSector); + void SetFinalSector( Dali::Radian finalSector); + void SetInitialActorAngle( Dali::Radian initialAngle ); + void SetFinalActorAngle( Dali::Radian finalAngle ); + + float GetDuration( ); + float GetDiameter( ); + Dali::Radian GetInitialAngle( ); + Dali::Radian GetFinalAngle( ); + Dali::Radian GetInitialSector( ); + Dali::Radian GetFinalSector( ); + Dali::Radian GetInitialActorAngle( ); + Dali::Radian GetFinalActorAngle( ); + + void RotateActorsWithStencil(bool rotate); + + void Add( Dali::Actor actor ); + + void Activate( Dali::Animation anim = Dali::Animation(), float offsetTime=0, float duration=2.0f ); + + void Deactivate(); + +private: + + /** + * Create the stencil mask + */ + void CreateStencil(Dali::Radian initialSector ); + +private: + Dali::Layer mLayer; + Dali::Animation mAnim; + float mDuration; + float mDiameter; + Dali::Radian mInitialAngle; + Dali::Radian mFinalAngle; + Dali::Radian mInitialSector; + Dali::Radian mFinalSector; + Dali::Radian mInitialActorAngle; + Dali::Radian mFinalActorAngle; + Dali::AlphaFunction mEasingFunction; + Dali::Actor mStencilActor; ///< Stencil actor which generates mask + Dali::Property::Index mStartAngleIndex; ///< Index of start-angle property + Dali::Property::Index mRotationAngleIndex; ///< Index of rotation-angle property + bool mRotateActorsWithStencil:1; + bool mRotateActors; +}; + + +inline RadialSweepViewImpl& GetImpl( RadialSweepView& obj ) +{ + DALI_ASSERT_ALWAYS(obj); + Dali::RefObject& handle = obj.GetImplementation(); + return static_cast(handle); +} + +inline const RadialSweepViewImpl& GetImpl( const RadialSweepView& obj ) +{ + DALI_ASSERT_ALWAYS(obj); + const Dali::RefObject& handle = obj.GetImplementation(); + return static_cast(handle); +} + + + +#endif // DALI_DEMO_RADIAL_SWEEP_VIEW_IMPL_H diff --git a/examples/radial-menu/radial-sweep-view.cpp b/examples/radial-menu/radial-sweep-view.cpp new file mode 100644 index 0000000..46e2609 --- /dev/null +++ b/examples/radial-menu/radial-sweep-view.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2015 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. + * + */ + +#include "radial-sweep-view.h" +#include "radial-sweep-view-impl.h" + +using namespace Dali; + +RadialSweepView::RadialSweepView() +{ +} + +RadialSweepView::RadialSweepView(const RadialSweepView& handle) +: Control(handle) +{ +} + +RadialSweepView& RadialSweepView::operator=(const RadialSweepView& rhs) +{ + if( &rhs != this ) + { + Control::operator=(rhs); + } + return *this; +} + +RadialSweepView::~RadialSweepView() +{ +} + +RadialSweepView RadialSweepView::DownCast( BaseHandle handle ) +{ + return Control::DownCast(handle); +} + +RadialSweepView RadialSweepView::New( ) +{ + return RadialSweepViewImpl::New(); +} + +RadialSweepView RadialSweepView::New( float duration, + float diameter, + Radian initialAngle, + Radian finalAngle, + Radian initialSector, + Radian finalSector ) +{ + return RadialSweepViewImpl::New(duration, diameter, initialAngle, finalAngle, initialSector, finalSector ); +} + +RadialSweepView::RadialSweepView( RadialSweepViewImpl& impl ) +: Control( impl ) +{ +} + +RadialSweepView::RadialSweepView( Dali::Internal::CustomActor* impl ) +: Control( impl ) +{ + VerifyCustomActorPointer(impl); +} + +void RadialSweepView::SetDuration(float duration) +{ + GetImpl(*this).SetDuration(duration); +} + +void RadialSweepView::SetEasingFunction( Dali::AlphaFunction easingFunction ) +{ + GetImpl(*this).SetEasingFunction( easingFunction ); +} + +void RadialSweepView::SetDiameter(float diameter) +{ + GetImpl(*this).SetDiameter(diameter); +} + +void RadialSweepView::SetInitialAngle( Dali::Radian initialAngle) +{ + GetImpl(*this).SetInitialAngle(initialAngle); +} + +void RadialSweepView::SetFinalAngle( Dali::Radian finalAngle) +{ + GetImpl(*this).SetFinalAngle(finalAngle); +} + +void RadialSweepView::SetInitialSector( Dali::Radian initialSector) +{ + GetImpl(*this).SetInitialSector(initialSector); +} + +void RadialSweepView::SetFinalSector( Dali::Radian finalSector) +{ + GetImpl(*this).SetFinalSector(finalSector); +} + +void RadialSweepView::SetInitialActorAngle( Dali::Radian initialAngle ) +{ + GetImpl(*this).SetInitialActorAngle(initialAngle); +} + +void RadialSweepView::SetFinalActorAngle( Dali::Radian finalAngle ) +{ + GetImpl(*this).SetFinalActorAngle(finalAngle); +} + +float RadialSweepView::GetDuration( ) +{ + return GetImpl(*this).GetDuration(); +} + +float RadialSweepView::GetDiameter( ) +{ + return GetImpl(*this).GetDiameter(); +} + +Dali::Radian RadialSweepView::GetInitialAngle( ) +{ + return GetImpl(*this).GetInitialAngle(); +} + +Dali::Radian RadialSweepView::GetFinalAngle( ) +{ + return GetImpl(*this).GetFinalAngle(); +} + +Dali::Radian RadialSweepView::GetInitialSector( ) +{ + return GetImpl(*this).GetInitialSector(); +} + +Dali::Radian RadialSweepView::GetFinalSector( ) +{ + return GetImpl(*this).GetFinalSector(); +} + +Dali::Radian RadialSweepView::GetInitialActorAngle( ) +{ + return GetImpl(*this).GetInitialActorAngle(); +} + +Dali::Radian RadialSweepView::GetFinalActorAngle( ) +{ + return GetImpl(*this).GetFinalActorAngle(); +} + +void RadialSweepView::RotateActorsWithStencil(bool rotate) +{ + GetImpl(*this).RotateActorsWithStencil(rotate); +} + +void RadialSweepView::Add(Actor actor) +{ + GetImpl(*this).Add(actor); +} + +void RadialSweepView::Activate() +{ + GetImpl(*this).Activate(); +} + +void RadialSweepView::Activate( Dali::Animation anim, float offsetTime, float duration ) +{ + GetImpl(*this).Activate(anim, offsetTime, duration); +} + +void RadialSweepView::Deactivate() +{ + GetImpl(*this).Deactivate(); +} diff --git a/examples/radial-menu/radial-sweep-view.h b/examples/radial-menu/radial-sweep-view.h new file mode 100644 index 0000000..3abdcb0 --- /dev/null +++ b/examples/radial-menu/radial-sweep-view.h @@ -0,0 +1,150 @@ +#ifndef DALI_DEMO_RADIAL_SWEEP_VIEW_H +#define DALI_DEMO_RADIAL_SWEEP_VIEW_H + +/* + * Copyright (c) 2015 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. + * + */ + +#include + +class RadialSweepViewImpl; + + +/******************************************************************************** + * Handle to RadialSweepView implementation + */ +class RadialSweepView : public Dali::Toolkit::Control +{ +public: + /** + * Create a new RadialSweepView with default parameters (2 second animation, + * no rotation, sweeping out a full circle). + */ + static RadialSweepView New( ); + + /** + * Create a new RadialSweepView. + * @param[in] duration The duration of the sweep animation + * @param[in] diameter The diameter of the stencil mask + * @param[in] initialAngle The initial angle of the anticlockwise line of the sweep sector + * @param[in] finalAngle The final angle of the anticlockwise line of the sweep sector + * @param[in] initialSector The angle of the starting sector + * @param[in] finalSector The angle of the sector at the end of the animation. + * Note, to cover the entire circle, use a value of 359.9999 degrees, not zero or 360 degrees. + * + * initial sector + * \ | . + * \ | . + * initialAngle \ | . final sector + * \| _| + * .________ + */ + static RadialSweepView New( float duration, + float diameter, + Dali::Radian initialAngle, + Dali::Radian finalAngle, + Dali::Radian initialSector, + Dali::Radian finalSector ); + + void SetDuration(float duration); + + void SetEasingFunction( Dali::AlphaFunction easingFunction ); + + void SetDiameter(float diameter); + + void SetInitialAngle( Dali::Radian initialAngle); + + void SetFinalAngle( Dali::Radian finalAngle); + + void SetInitialSector( Dali::Radian initialSector); + + void SetFinalSector( Dali::Radian finalSector); + + void SetInitialActorAngle( Dali::Radian initialAngle ); + + void SetFinalActorAngle( Dali::Radian finalAngle ); + + float GetDuration( ); + + float GetDiameter( ); + + Dali::Radian GetInitialAngle( ); + + Dali::Radian GetFinalAngle( ); + + Dali::Radian GetInitialSector( ); + + Dali::Radian GetFinalSector( ); + + Dali::Radian GetInitialActorAngle( ); + + Dali::Radian GetFinalActorAngle( ); + + /** + * @param[in] rotate True if the actors should rotate with the stencil + */ + void RotateActorsWithStencil(bool rotate); + + /** + * Add actors to the view + */ + void Add(Actor actor); + + /** + * Activate the sweep animation + */ + void Activate( ); + + void Activate( Dali::Animation anim, float offsetTime, float duration ); + + /** + * Deactivate the sweep animation + */ + void Deactivate(); + + /** + * Default constructor. Create an uninitialized handle. + */ + RadialSweepView(); + + /** + * Copy constructor + */ + RadialSweepView(const RadialSweepView& handle); + + /** + * Assignment operator + */ + RadialSweepView& operator=(const RadialSweepView& rhs); + + /** + * Destructor + */ + ~RadialSweepView(); + + /** + * Downcast method + */ + static RadialSweepView DownCast( BaseHandle handle ); + +public: // Not for use by application developers + + RadialSweepView( RadialSweepViewImpl& impl ); + + RadialSweepView( Dali::Internal::CustomActor* impl ); +}; + +#endif diff --git a/examples/refraction-effect/refraction-effect-example.cpp b/examples/refraction-effect/refraction-effect-example.cpp new file mode 100644 index 0000000..8a82398 --- /dev/null +++ b/examples/refraction-effect/refraction-effect-example.cpp @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2015 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. + * + */ + +#include +#include +#include "shared/view.h" + +#include +#include +#include + +using namespace Dali; + +namespace +{ +const char * const APPLICATION_TITLE( "Refraction Effect" ); +const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" ); +const char * const CHANGE_TEXTURE_ICON( DALI_IMAGE_DIR "icon-change.png" ); +const char * const CHANGE_MESH_ICON( DALI_IMAGE_DIR "icon-replace.png" ); + +const char* MESH_FILES[] = +{ + DALI_MODEL_DIR "surface_pattern_v01.obj", + DALI_MODEL_DIR "surface_pattern_v02.obj" +}; +const unsigned int NUM_MESH_FILES( sizeof( MESH_FILES ) / sizeof( MESH_FILES[0] ) ); + +const char* TEXTURE_IMAGES[]= +{ + DALI_IMAGE_DIR "background-1.jpg", + DALI_IMAGE_DIR "background-2.jpg", + DALI_IMAGE_DIR "background-3.jpg", + DALI_IMAGE_DIR "background-4.jpg" +}; +const unsigned int NUM_TEXTURE_IMAGES( sizeof( TEXTURE_IMAGES ) / sizeof( TEXTURE_IMAGES[0] ) ); + +struct LightOffsetConstraint +{ + LightOffsetConstraint( float radius ) + : mRadius( radius ) + { + } + + void operator()( Vector2& current, const PropertyInputContainer& inputs ) + { + float spinAngle = inputs[0]->GetFloat(); + current.x = cos( spinAngle ); + current.y = sin( spinAngle ); + + current *= mRadius; + } + + float mRadius; +}; + +/** + * @brief Load an image, scaled-down to no more than the stage dimensions. + * + * Uses image scaling mode SCALE_TO_FILL to resize the image at + * load time to cover the entire stage with pixels with no borders, + * and filter mode BOX_THEN_LINEAR to sample the image with maximum quality. + */ +ResourceImage LoadStageFillingImage( const char * const imagePath ) +{ + Size stageSize = Stage::GetCurrent().GetSize(); + return ResourceImage::New( imagePath, ImageDimensions( stageSize.x, stageSize.y ), Dali::FittingMode::SCALE_TO_FILL, Dali::SamplingMode::BOX_THEN_LINEAR ); +} + +/** + * structure of the vertex in the mesh + */ +struct Vertex +{ + Vector3 position; + Vector3 normal; + Vector2 textureCoord; + + Vertex() + {} + + Vertex( const Vector3& position, const Vector3& normal, const Vector2& textureCoord ) + : position( position ), normal( normal ), textureCoord( textureCoord ) + {} +}; + +/************************************************************************************************ + *** The shader source is used when the MeshActor is not touched*** + ************************************************************************************************/ +const char* VERTEX_SHADER_FLAT = DALI_COMPOSE_SHADER( +attribute mediump vec3 aPosition;\n +attribute mediump vec3 aNormal;\n +attribute highp vec2 aTexCoord;\n +uniform mediump mat4 uMvpMatrix;\n +varying mediump vec2 vTexCoord;\n +void main()\n +{\n + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n +}\n +); + +const char* FRAGMENT_SHADER_FLAT = DALI_COMPOSE_SHADER( +uniform lowp vec4 uColor;\n +uniform sampler2D sTexture;\n +varying mediump vec2 vTexCoord;\n +void main()\n +{\n + gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n +}\n +); + +/************************************************************ + ** Custom refraction effect shader*************************** + ************************************************************/ +const char* VERTEX_SHADER_REFRACTION = DALI_COMPOSE_SHADER( +attribute mediump vec3 aPosition;\n +attribute mediump vec3 aNormal;\n +attribute highp vec2 aTexCoord;\n +uniform mediump mat4 uMvpMatrix;\n +varying mediump vec4 vVertex;\n +varying mediump vec3 vNormal;\n +varying mediump vec2 vTexCoord;\n +varying mediump vec2 vTextureOffset;\n +void main()\n +{\n + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n + vTexCoord = aTexCoord.xy;\n + + vNormal = aNormal;\n + vVertex = vec4( aPosition, 1.0 );\n + float length = max(0.01, length(aNormal.xy)) * 40.0;\n + vTextureOffset = aNormal.xy / length;\n +}\n +); + +const char* FRAGMENT_SHADER_REFRACTION = DALI_COMPOSE_SHADER( +precision mediump float;\n +uniform mediump float uEffectStrength;\n +uniform mediump vec3 uLightPosition;\n +uniform mediump vec2 uLightXYOffset;\n +uniform mediump vec2 uLightSpinOffset;\n +uniform mediump float uLightIntensity;\n +uniform lowp vec4 uColor;\n +uniform sampler2D sTexture;\n +varying mediump vec4 vVertex;\n +varying mediump vec3 vNormal;\n +varying mediump vec2 vTexCoord;\n +varying mediump vec2 vTextureOffset;\n + +vec3 rgb2hsl(vec3 rgb)\n +{\n + float epsilon = 1.0e-10;\n + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n + vec4 P = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g));\n + vec4 Q = mix(vec4(P.xyw, rgb.r), vec4(rgb.r, P.yzx), step(P.x, rgb.r));\n + \n + // RGB -> HCV + float value = Q.x;\n + float chroma = Q.x - min(Q.w, Q.y);\n + float hue = abs(Q.z + (Q.w-Q.y) / (6.0*chroma+epsilon));\n + // HCV -> HSL + float lightness = value - chroma*0.5;\n + return vec3( hue, chroma/max( 1.0-abs(lightness*2.0-1.0), 1.0e-1 ), lightness );\n +}\n + +vec3 hsl2rgb( vec3 hsl )\n +{\n + // pure hue->RGB + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n + vec3 p = abs(fract(hsl.xxx + K.xyz) * 6.0 - K.www);\n + vec3 RGB = clamp(p - K.xxx, 0.0, 1.0);\n + \n + float chroma = ( 1.0 - abs( hsl.z*2.0-1.0 ) ) * hsl.y;\n + return ( RGB - 0.5 ) * chroma + hsl.z;\n +}\n + +void main()\n +{\n + vec3 normal = normalize( vNormal);\n + + vec3 lightPosition = uLightPosition + vec3(uLightXYOffset+uLightSpinOffset, 0.0);\n + mediump vec3 vecToLight = normalize( (lightPosition - vVertex.xyz) * 0.01 );\n + mediump float spotEffect = pow( max(0.05, vecToLight.z ) - 0.05, 8.0);\n + + spotEffect = spotEffect * uEffectStrength;\n + mediump float lightDiffuse = ( ( dot( vecToLight, normal )-0.75 ) *uLightIntensity ) * spotEffect;\n + + lowp vec4 color = texture2D( sTexture, vTexCoord + vTextureOffset * spotEffect );\n + vec3 lightedColor = hsl2rgb( rgb2hsl(color.rgb) + vec3(0.0,0.0,lightDiffuse) );\n + + gl_FragColor = vec4( lightedColor, color.a ) * uColor;\n +}\n +); + +} // namespace + + +/*************************************************/ +/*Demo using RefractionEffect*****************/ +/*************************************************/ +class RefractionEffectExample : public ConnectionTracker +{ +public: + RefractionEffectExample( Application &application ) + : mApplication( application ), + mCurrentTextureId( 1 ), + mCurrentMeshId( 0 ) + { + // Connect to the Application's Init signal + application.InitSignal().Connect(this, &RefractionEffectExample::Create); + } + + ~RefractionEffectExample() + { + } + +private: + + // The Init signal is received once (only) during the Application lifetime + void Create(Application& application) + { + DemoHelper::RequestThemeChange(); + + Stage stage = Stage::GetCurrent(); + Vector2 stageSize = stage.GetSize(); + + stage.KeyEventSignal().Connect(this, &RefractionEffectExample::OnKeyEvent); + + // Creates a default view with a default tool bar. + // The view is added to the stage. + Toolkit::ToolBar toolBar; + Toolkit::Control view; + mContent = DemoHelper::CreateView( application, + view, + toolBar, + "", + TOOLBAR_IMAGE, + APPLICATION_TITLE ); + + // Add a button to change background. (right of toolbar) + mChangeTextureButton = Toolkit::PushButton::New(); + mChangeTextureButton.SetBackgroundImage( ResourceImage::New( CHANGE_TEXTURE_ICON ) ); + mChangeTextureButton.ClickedSignal().Connect( this, &RefractionEffectExample::OnChangeTexture ); + toolBar.AddControl( mChangeTextureButton, + DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, + Toolkit::Alignment::HorizontalRight, + DemoHelper::DEFAULT_MODE_SWITCH_PADDING ); + // Add a button to change mesh pattern. ( left of bar ) + mChangeMeshButton = Toolkit::PushButton::New(); + mChangeMeshButton.SetBackgroundImage( ResourceImage::New( CHANGE_MESH_ICON ) ); + mChangeMeshButton.ClickedSignal().Connect( this, &RefractionEffectExample::OnChangeMesh ); + toolBar.AddControl( mChangeMeshButton, + DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, + Toolkit::Alignment::HorizontalLeft, + DemoHelper::DEFAULT_MODE_SWITCH_PADDING ); + + + + // shader used when the screen is not touched, render a flat surface + mShaderFlat = Shader::New( VERTEX_SHADER_FLAT, FRAGMENT_SHADER_FLAT ); + mGeometry = CreateGeometry( MESH_FILES[mCurrentMeshId] ); + + Image texture = LoadStageFillingImage( TEXTURE_IMAGES[mCurrentTextureId] ); + mSampler = Sampler::New( texture, "sTexture" ); + mMaterial = Material::New( mShaderFlat ); + mMaterial.AddSampler( mSampler ); + + mRenderer = Renderer::New( mGeometry, mMaterial ); + + mMeshActor = Actor::New(); + mMeshActor.AddRenderer( mRenderer ); + mMeshActor.SetSize( stageSize ); + mMeshActor.SetParentOrigin(ParentOrigin::CENTER); + mContent.Add( mMeshActor ); + + // Connect the callback to the touch signal on the mesh actor + mContent.TouchedSignal().Connect( this, &RefractionEffectExample::OnTouch ); + + // shader used when the finger is touching the screen. render refraction effect + mShaderRefraction = Shader::New( VERTEX_SHADER_REFRACTION, FRAGMENT_SHADER_REFRACTION ); + + // register uniforms + mLightXYOffsetIndex = mMeshActor.RegisterProperty( "light-XY-offset", Vector2::ZERO ); + mMeshActor.AddUniformMapping( mLightXYOffsetIndex, "uLightXYOffset" ); + + mLightIntensityIndex = mMeshActor.RegisterProperty( "light-intensity", 2.5f ); + mMeshActor.AddUniformMapping( mLightIntensityIndex, "uLightIntensity" ); + + mEffectStrengthIndex = mMeshActor.RegisterProperty( "effect-strength", 0.f ); + mMeshActor.AddUniformMapping( mEffectStrengthIndex, "uEffectStrength" ); + + Vector3 lightPosition( -stageSize.x*0.5f, -stageSize.y*0.5f, stageSize.x*0.5f ); // top_left + Property::Index lightPositionIndex = mMeshActor.RegisterProperty( "light-position", lightPosition ); + mMeshActor.AddUniformMapping( lightPositionIndex, "uLightPosition"); + + Property::Index lightSpinOffsetIndex = mMeshActor.RegisterProperty( "light-spin-offset", Vector2::ZERO ); + mMeshActor.AddUniformMapping( lightSpinOffsetIndex, "uLightSpinOffset" ); + + mSpinAngleIndex = mMeshActor.RegisterProperty("spin-angle", 0.f ); + Constraint constraint = Constraint::New( mMeshActor, lightSpinOffsetIndex, LightOffsetConstraint(stageSize.x*0.1f) ); + constraint.AddSource( LocalSource(mSpinAngleIndex) ); + constraint.Apply(); + + // the animation which spin the light around the finger touch position + mLightAnimation = Animation::New(2.f); + mLightAnimation.AnimateTo( Property( mMeshActor, mSpinAngleIndex ), Math::PI*2.f ); + mLightAnimation.SetLooping( true ); + mLightAnimation.Pause(); + } + + void SetLightXYOffset( const Vector2& offset ) + { + mMeshActor.SetProperty( mLightXYOffsetIndex, offset ); + } + + /** + * Create a mesh actor with different geometry to replace the current one + */ + bool OnChangeMesh( Toolkit::Button button ) + { + mCurrentMeshId = ( mCurrentMeshId + 1 ) % NUM_MESH_FILES; + mGeometry = CreateGeometry( MESH_FILES[mCurrentMeshId] ); + mRenderer.SetGeometry( mGeometry ); + + return true; + } + + bool OnChangeTexture( Toolkit::Button button ) + { + mCurrentTextureId = ( mCurrentTextureId + 1 ) % NUM_TEXTURE_IMAGES; + Image texture = LoadStageFillingImage( TEXTURE_IMAGES[mCurrentTextureId] ); + mSampler.SetImage( texture ); + return true; + } + + bool OnTouch( Actor actor , const TouchEvent& event ) + { + const TouchPoint &point = event.GetPoint(0); + switch(point.state) + { + case TouchPoint::Down: + { + mMaterial.SetShader( mShaderRefraction ); + + SetLightXYOffset( point.screen ); + + mLightAnimation.Play(); + + if( mStrenghAnimation ) + { + mStrenghAnimation.Clear(); + } + + mStrenghAnimation= Animation::New(0.5f); + mStrenghAnimation.AnimateTo( Property( mMeshActor, mEffectStrengthIndex ), 1.f ); + mStrenghAnimation.Play(); + + break; + } + case TouchPoint::Motion: + { + // make the light position following the finger movement + SetLightXYOffset( point.screen ); + break; + } + case TouchPoint::Up: + case TouchPoint::Leave: + case TouchPoint::Interrupted: + { + mLightAnimation.Pause(); + + if( mStrenghAnimation ) + { + mStrenghAnimation.Clear(); + } + mStrenghAnimation = Animation::New(0.5f); + mStrenghAnimation.AnimateTo( Property( mMeshActor, mEffectStrengthIndex ), 0.f ); + mStrenghAnimation.FinishedSignal().Connect( this, &RefractionEffectExample::OnTouchFinished ); + mStrenghAnimation.Play(); + break; + } + case TouchPoint::Stationary: + case TouchPoint::Last: + default: + { + break; + } + } + + return true; + } + + void OnTouchFinished( Animation& source ) + { + mMaterial.SetShader( mShaderFlat ); + SetLightXYOffset( Vector2::ZERO ); + } + + Geometry CreateGeometry(const std::string& objFileName) + { + std::vector vertexPositions; + Vector faceIndices; + Vector boundingBox; + // read the vertice and faces from the .obj file, and record the bounding box + ReadObjFile( objFileName, boundingBox, vertexPositions, faceIndices ); + + std::vector textureCoordinates; + // align the mesh, scale it to fit the screen size, and calculate the texture coordinate for each vertex + ShapeResizeAndTexureCoordinateCalculation( boundingBox, vertexPositions, textureCoordinates ); + + // re-organize the mesh, the vertices are duplicated, each vertex only belongs to one triangle. + // Without sharing vertex between triangle, so we can manipulate the texture offset on each triangle conveniently. + std::vector vertices; + + std::size_t size = faceIndices.Size(); + vertices.reserve( size ); + + for( std::size_t i=0; i 0 ) + { + vertices.push_back( Vertex( vertexPositions[ faceIndices[i] ], normal, textureCoordinates[ faceIndices[i] ] ) ); + vertices.push_back( Vertex( vertexPositions[ faceIndices[i+1] ], normal, textureCoordinates[ faceIndices[i+1] ] ) ); + vertices.push_back( Vertex( vertexPositions[ faceIndices[i+2] ], normal, textureCoordinates[ faceIndices[i+2] ] ) ); + } + else + { + normal *= -1.f; + vertices.push_back( Vertex( vertexPositions[ faceIndices[i] ], normal, textureCoordinates[ faceIndices[i] ] ) ); + vertices.push_back( Vertex( vertexPositions[ faceIndices[i+2] ], normal, textureCoordinates[ faceIndices[i+2] ] ) ); + vertices.push_back( Vertex( vertexPositions[ faceIndices[i+1] ], normal, textureCoordinates[ faceIndices[i+1] ] ) ); + } + } + + Property::Map vertexFormat; + vertexFormat["aPosition"] = Property::VECTOR3; + vertexFormat["aNormal"] = Property::VECTOR3; + vertexFormat["aTexCoord"] = Property::VECTOR2; + PropertyBuffer surfaceVertices = PropertyBuffer::New( PropertyBuffer::STATIC, vertexFormat, vertices.size() ); + surfaceVertices.SetData( &vertices[0] ); + + Geometry surface = Geometry::New(); + surface.AddVertexBuffer( surfaceVertices ); + + return surface; + } + + void ReadObjFile( const std::string& objFileName, + Vector& boundingBox, + std::vector& vertexPositions, + Vector& faceIndices) + { + std::ifstream ifs( objFileName.c_str(), std::ios::in ); + + boundingBox.Resize( 6 ); + boundingBox[0]=boundingBox[2]=boundingBox[4] = std::numeric_limits::max(); + boundingBox[1]=boundingBox[3]=boundingBox[5] = -std::numeric_limits::max(); + + std::string line; + while( std::getline( ifs, line ) ) + { + if( line[0] == 'v' && std::isspace(line[1])) // vertex + { + std::istringstream iss(line.substr(2), std::istringstream::in); + unsigned int i = 0; + Vector3 vertex; + while( iss >> vertex[i++] && i < 3); + if( vertex.x < boundingBox[0] ) boundingBox[0] = vertex.x; + if( vertex.x > boundingBox[1] ) boundingBox[1] = vertex.x; + if( vertex.y < boundingBox[2] ) boundingBox[2] = vertex.y; + if( vertex.y > boundingBox[3] ) boundingBox[3] = vertex.y; + if( vertex.z < boundingBox[4] ) boundingBox[4] = vertex.z; + if( vertex.z > boundingBox[5] ) boundingBox[5] = vertex.z; + vertexPositions.push_back( vertex ); + } + else if( line[0] == 'f' ) //face + { + unsigned int numOfInt = 3; + while( true ) + { + std::size_t found = line.find('/'); + if( found == std::string::npos ) + { + break; + } + line[found] = ' '; + numOfInt++; + } + + std::istringstream iss(line.substr(2), std::istringstream::in); + unsigned int indices[ numOfInt ]; + unsigned int i=0; + while( iss >> indices[i++] && i < numOfInt); + unsigned int step = (i+1) / 3; + faceIndices.PushBack( indices[0]-1 ); + faceIndices.PushBack( indices[step]-1 ); + faceIndices.PushBack( indices[2*step]-1 ); + } + } + + ifs.close(); + } + + void ShapeResizeAndTexureCoordinateCalculation( const Vector& boundingBox, + std::vector& vertexPositions, + std::vector& textureCoordinates) + { + Vector3 bBoxSize( boundingBox[1] - boundingBox[0], boundingBox[3] - boundingBox[2], boundingBox[5] - boundingBox[4]); + Vector3 bBoxMinCorner( boundingBox[0], boundingBox[2], boundingBox[4] ); + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Vector3 scale( stageSize.x / bBoxSize.x, stageSize.y / bBoxSize.y, 1.f ); + scale.z = (scale.x + scale.y)/2.f; + + textureCoordinates.reserve(vertexPositions.size()); + + for( std::vector::iterator iter = vertexPositions.begin(); iter != vertexPositions.end(); iter++ ) + { + Vector3 newPosition( (*iter) - bBoxMinCorner ) ; + + textureCoordinates.push_back( Vector2( newPosition.x / bBoxSize.x, newPosition.y / bBoxSize.y ) ); + + newPosition -= bBoxSize * 0.5f; + (*iter) = newPosition * scale; + } + } + + /** + * Main key event handler + */ + void OnKeyEvent(const KeyEvent& event) + { + if(event.state == KeyEvent::Down) + { + if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) ) + { + mApplication.Quit(); + } + } + } + +private: + + Application& mApplication; + Layer mContent; + + Sampler mSampler; + Material mMaterial; + Geometry mGeometry; + Renderer mRenderer; + Actor mMeshActor; + + Shader mShaderFlat; + Shader mShaderRefraction; + + Animation mLightAnimation; + Animation mStrenghAnimation; + + Property::Index mLightXYOffsetIndex; + Property::Index mSpinAngleIndex; + Property::Index mLightIntensityIndex; + Property::Index mEffectStrengthIndex; + + Toolkit::PushButton mChangeTextureButton; + Toolkit::PushButton mChangeMeshButton; + unsigned int mCurrentTextureId; + unsigned int mCurrentMeshId; +}; + +/*****************************************************************************/ + +static void +RunTest(Application& app) +{ + RefractionEffectExample theApp(app); + app.MainLoop(); +} + +/*****************************************************************************/ + +int +main(int argc, char **argv) +{ + Application app = Application::New(&argc, &argv); + + RunTest(app); + + return 0; +} -- 2.7.4