Commit 5b74d885f033ea9d6763d9d6a923de86d572b5e3
Committed by
Gerrit Code Review
Merge "Update refraction-effect & radial-menu to use new mesh" into devel/new_mesh
Showing
6 changed files
with
1736 additions
and
0 deletions
examples/radial-menu/radial-menu-example.cpp
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + * | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | +#include <dali/dali.h> | ||
| 19 | +#include <dali-toolkit/dali-toolkit.h> | ||
| 20 | +#include "shared/view.h" | ||
| 21 | +#include "radial-sweep-view.h" | ||
| 22 | +#include "radial-sweep-view-impl.h" | ||
| 23 | + | ||
| 24 | +using namespace Dali; | ||
| 25 | +using namespace Dali::Toolkit; | ||
| 26 | + | ||
| 27 | +namespace | ||
| 28 | +{ | ||
| 29 | +const char* TEST_OUTER_RING_FILENAME = DALI_IMAGE_DIR "layer2.png"; // Image to be masked | ||
| 30 | +const char* TEST_INNER_RING_FILENAME = DALI_IMAGE_DIR "layer1.png"; // Image to be masked | ||
| 31 | +const char* TEST_MENU_FILENAME = DALI_IMAGE_DIR "layer3.png"; // Image to be masked | ||
| 32 | +const char* TEST_DIAL_FILENAME = DALI_IMAGE_DIR "layer4.png"; // Image to be masked | ||
| 33 | +const char* TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" ); // Background for toolbar | ||
| 34 | +const char* APPLICATION_TITLE( "Radial Menu" ); | ||
| 35 | +const char * const PLAY_ICON( DALI_IMAGE_DIR "icon-play.png" ); | ||
| 36 | +const char * const STOP_ICON( DALI_IMAGE_DIR "icon-stop.png" ); | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | + | ||
| 40 | +/******************************************************************************** | ||
| 41 | + * Application controller class | ||
| 42 | + */ | ||
| 43 | + | ||
| 44 | +// This example shows how to create a mesh actor for use as a stencil buffer | ||
| 45 | +class RadialMenuExample : public ConnectionTracker | ||
| 46 | +{ | ||
| 47 | +public: | ||
| 48 | + /** | ||
| 49 | + * Constructor | ||
| 50 | + * @param[in] app The application handle | ||
| 51 | + */ | ||
| 52 | + RadialMenuExample(Application app); | ||
| 53 | + | ||
| 54 | + /** | ||
| 55 | + * Destructor | ||
| 56 | + */ | ||
| 57 | + ~RadialMenuExample(); | ||
| 58 | + | ||
| 59 | +private: | ||
| 60 | + | ||
| 61 | + /** | ||
| 62 | + * Initialization signal handler - all actor initialization should happen here | ||
| 63 | + * @param[in] app The application handle | ||
| 64 | + */ | ||
| 65 | + void OnInit(Application& app); | ||
| 66 | + | ||
| 67 | + /** | ||
| 68 | + * Create a sweep view with the given image and parameters | ||
| 69 | + */ | ||
| 70 | + RadialSweepView CreateSweepView( std::string imageName, Degree initial, Degree final ); | ||
| 71 | + | ||
| 72 | + /** | ||
| 73 | + * Start the sweep animation on the menu | ||
| 74 | + */ | ||
| 75 | + void StartAnimation(); | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * Play or pause the animation when the button is clicked | ||
| 79 | + */ | ||
| 80 | + bool OnButtonClicked( Toolkit::Button button ); | ||
| 81 | + | ||
| 82 | + /** | ||
| 83 | + * Update the state flag and change the button icon when the animation is finished | ||
| 84 | + */ | ||
| 85 | + void OnAnimationFinished( Animation& source ); | ||
| 86 | + | ||
| 87 | + /** | ||
| 88 | + * Main key event handler | ||
| 89 | + * | ||
| 90 | + * @param[in] event The key event to respond to | ||
| 91 | + */ | ||
| 92 | + void OnKeyEvent(const KeyEvent& event); | ||
| 93 | + | ||
| 94 | +private: // Member variables | ||
| 95 | + enum AnimState | ||
| 96 | + { | ||
| 97 | + STOPPED, | ||
| 98 | + PAUSED, | ||
| 99 | + PLAYING | ||
| 100 | + }; | ||
| 101 | + | ||
| 102 | + Application mApplication; ///< The application handle | ||
| 103 | + Toolkit::Control mView; ///< The toolbar view | ||
| 104 | + Layer mContents; ///< The toolbar contents pane | ||
| 105 | + ImageActor mImageActor; ///< Image actor shown by stencil mask | ||
| 106 | + Animation mAnimation; | ||
| 107 | + AnimState mAnimationState; | ||
| 108 | + | ||
| 109 | + Image mIconPlay; | ||
| 110 | + Image mIconStop; | ||
| 111 | + Toolkit::PushButton mPlayStopButton; | ||
| 112 | + ImageActor mDialActor; | ||
| 113 | + RadialSweepView mRadialSweepView1; | ||
| 114 | + RadialSweepView mRadialSweepView2; | ||
| 115 | + RadialSweepView mRadialSweepView3; | ||
| 116 | +}; | ||
| 117 | + | ||
| 118 | +RadialMenuExample::RadialMenuExample(Application app) | ||
| 119 | +: mApplication( app ), | ||
| 120 | + mAnimationState(STOPPED) | ||
| 121 | +{ | ||
| 122 | + // Connect to the Application's Init signal | ||
| 123 | + app.InitSignal().Connect(this, &RadialMenuExample::OnInit); | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +RadialMenuExample::~RadialMenuExample() | ||
| 127 | +{ | ||
| 128 | + // Nothing to do here; actor handles will clean up themselves. | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +void RadialMenuExample::OnInit(Application& app) | ||
| 132 | +{ | ||
| 133 | + DemoHelper::RequestThemeChange(); | ||
| 134 | + | ||
| 135 | + Stage stage = Dali::Stage::GetCurrent(); | ||
| 136 | + | ||
| 137 | + // The Init signal is received once (only) during the Application lifetime | ||
| 138 | + stage.KeyEventSignal().Connect(this, &RadialMenuExample::OnKeyEvent); | ||
| 139 | + | ||
| 140 | + // Create toolbar & view | ||
| 141 | + Toolkit::ToolBar toolBar; | ||
| 142 | + mContents = DemoHelper::CreateView( mApplication, | ||
| 143 | + mView, | ||
| 144 | + toolBar, | ||
| 145 | + "", | ||
| 146 | + TOOLBAR_IMAGE, | ||
| 147 | + APPLICATION_TITLE ); | ||
| 148 | + | ||
| 149 | + mIconPlay = ResourceImage::New( PLAY_ICON ); | ||
| 150 | + mIconStop = ResourceImage::New( STOP_ICON ); | ||
| 151 | + mPlayStopButton = Toolkit::PushButton::New(); | ||
| 152 | + mPlayStopButton.SetBackgroundImage( mIconStop ); | ||
| 153 | + | ||
| 154 | + mPlayStopButton.ClickedSignal().Connect( this, &RadialMenuExample::OnButtonClicked ); | ||
| 155 | + | ||
| 156 | + toolBar.AddControl( mPlayStopButton, | ||
| 157 | + DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, | ||
| 158 | + Toolkit::Alignment::HorizontalRight, | ||
| 159 | + DemoHelper::DEFAULT_PLAY_PADDING ); | ||
| 160 | + | ||
| 161 | + | ||
| 162 | + const ImageDimensions intImgSize = ResourceImage::GetImageSize(TEST_OUTER_RING_FILENAME); | ||
| 163 | + Vector2 imgSize = Vector2( intImgSize.GetWidth(), intImgSize.GetHeight() ); | ||
| 164 | + Vector2 stageSize = stage.GetSize(); | ||
| 165 | + float scale = stageSize.width / imgSize.width; | ||
| 166 | + float availableHeight = stageSize.height - DemoHelper::DEFAULT_VIEW_STYLE.mToolBarHeight * 2.0f; | ||
| 167 | + if(availableHeight <= stageSize.width) | ||
| 168 | + { | ||
| 169 | + scale = availableHeight / imgSize.width; | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + mRadialSweepView1 = CreateSweepView( TEST_OUTER_RING_FILENAME, Degree(-90.0f), Degree(-90.0f)); | ||
| 173 | + mRadialSweepView2 = CreateSweepView( TEST_INNER_RING_FILENAME, Degree(90.0f), Degree(0.0f)); | ||
| 174 | + mRadialSweepView3 = CreateSweepView( TEST_MENU_FILENAME, Degree(100.0f), Degree(0.0f)); | ||
| 175 | + mRadialSweepView3.SetInitialActorAngle(Degree(-110)); | ||
| 176 | + mRadialSweepView3.SetFinalActorAngle(Degree(0)); | ||
| 177 | + | ||
| 178 | + Image dial = ResourceImage::New( TEST_DIAL_FILENAME ); | ||
| 179 | + mDialActor = ImageActor::New( dial ); | ||
| 180 | + mDialActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); | ||
| 181 | + mDialActor.SetPositionInheritanceMode(USE_PARENT_POSITION); | ||
| 182 | + mDialActor.SetScale(scale); | ||
| 183 | + Layer dialLayer = Layer::New(); | ||
| 184 | + | ||
| 185 | + dialLayer.Add(mDialActor); | ||
| 186 | + dialLayer.SetPositionInheritanceMode(USE_PARENT_POSITION); | ||
| 187 | + dialLayer.SetSize(stage.GetSize()); | ||
| 188 | + mContents.Add(dialLayer); | ||
| 189 | + | ||
| 190 | + mRadialSweepView1.SetScale(scale); | ||
| 191 | + mRadialSweepView2.SetScale(scale); | ||
| 192 | + mRadialSweepView3.SetScale(scale); | ||
| 193 | + | ||
| 194 | + StartAnimation(); | ||
| 195 | +} | ||
| 196 | + | ||
| 197 | +void RadialMenuExample::StartAnimation() | ||
| 198 | +{ | ||
| 199 | + mDialActor.SetOpacity(0.0f); | ||
| 200 | + mRadialSweepView1.SetOpacity(0.0f); | ||
| 201 | + mAnimation = Animation::New(6.0f); | ||
| 202 | + mRadialSweepView1.Activate(mAnimation, 0.0f, 3.0f); | ||
| 203 | + mRadialSweepView2.Activate(mAnimation, 1.5f, 3.0f); | ||
| 204 | + mRadialSweepView3.Activate(mAnimation, 3.0f, 3.0f); | ||
| 205 | + mAnimation.AnimateTo( Property( mDialActor, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN, TimePeriod( 0.0f, 0.8f ) ); | ||
| 206 | + mAnimation.AnimateTo( Property( mRadialSweepView1, Actor::Property::COLOR_ALPHA ), 1.0f, AlphaFunction::EASE_IN, TimePeriod( 0.0f, 0.5f ) ); | ||
| 207 | + mAnimation.FinishedSignal().Connect( this, &RadialMenuExample::OnAnimationFinished ); | ||
| 208 | + | ||
| 209 | + mAnimationState = PLAYING; | ||
| 210 | + mAnimation.Play(); | ||
| 211 | +} | ||
| 212 | + | ||
| 213 | +bool RadialMenuExample::OnButtonClicked( Toolkit::Button button ) | ||
| 214 | +{ | ||
| 215 | + switch( mAnimationState ) | ||
| 216 | + { | ||
| 217 | + case PLAYING: | ||
| 218 | + { | ||
| 219 | + mAnimation.Pause(); | ||
| 220 | + mAnimationState = PAUSED; | ||
| 221 | + mPlayStopButton.SetBackgroundImage( mIconPlay ); | ||
| 222 | + } | ||
| 223 | + break; | ||
| 224 | + | ||
| 225 | + case PAUSED: | ||
| 226 | + { | ||
| 227 | + mAnimation.Play(); | ||
| 228 | + mAnimationState = PLAYING; | ||
| 229 | + mPlayStopButton.SetBackgroundImage( mIconStop ); | ||
| 230 | + } | ||
| 231 | + break; | ||
| 232 | + | ||
| 233 | + case STOPPED: | ||
| 234 | + { | ||
| 235 | + mPlayStopButton.SetBackgroundImage( mIconStop ); | ||
| 236 | + mRadialSweepView1.Deactivate(); | ||
| 237 | + mRadialSweepView2.Deactivate(); | ||
| 238 | + mRadialSweepView3.Deactivate(); | ||
| 239 | + StartAnimation(); | ||
| 240 | + } | ||
| 241 | + } | ||
| 242 | + return false; | ||
| 243 | +} | ||
| 244 | + | ||
| 245 | +void RadialMenuExample::OnAnimationFinished( Animation& source ) | ||
| 246 | +{ | ||
| 247 | + mAnimationState = STOPPED; | ||
| 248 | + mPlayStopButton.SetBackgroundImage( mIconPlay ); | ||
| 249 | +} | ||
| 250 | + | ||
| 251 | +RadialSweepView RadialMenuExample::CreateSweepView( std::string imageName, | ||
| 252 | + Degree initialAngle, | ||
| 253 | + Degree finalAngle) | ||
| 254 | +{ | ||
| 255 | + // Create the image | ||
| 256 | + Image image = ResourceImage::New(imageName); | ||
| 257 | + mImageActor = ImageActor::New(image); | ||
| 258 | + mImageActor.SetParentOrigin(ParentOrigin::CENTER); | ||
| 259 | + mImageActor.SetAnchorPoint(AnchorPoint::CENTER); | ||
| 260 | + mImageActor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); | ||
| 261 | + | ||
| 262 | + // Create the stencil | ||
| 263 | + const ImageDimensions imageSize = ResourceImage::GetImageSize(imageName); | ||
| 264 | + float diameter = std::max(imageSize.GetWidth(), imageSize.GetHeight()); | ||
| 265 | + RadialSweepView radialSweepView = RadialSweepView::New(); | ||
| 266 | + radialSweepView.SetDiameter( diameter ); | ||
| 267 | + radialSweepView.SetInitialAngle( initialAngle ); | ||
| 268 | + radialSweepView.SetFinalAngle( finalAngle ); | ||
| 269 | + radialSweepView.SetInitialSector( Degree(0.0f) ); | ||
| 270 | + radialSweepView.SetFinalSector( Degree(359.999f) ); | ||
| 271 | + radialSweepView.SetSize( Stage::GetCurrent().GetSize()); | ||
| 272 | + radialSweepView.SetEasingFunction( Dali::AlphaFunction::EASE_IN_OUT ); | ||
| 273 | + radialSweepView.SetPositionInheritanceMode(USE_PARENT_POSITION); | ||
| 274 | + mContents.Add(radialSweepView); | ||
| 275 | + radialSweepView.Add( mImageActor ); | ||
| 276 | + mImageActor.SetPositionInheritanceMode(USE_PARENT_POSITION); | ||
| 277 | + | ||
| 278 | + return radialSweepView; | ||
| 279 | +} | ||
| 280 | + | ||
| 281 | + | ||
| 282 | +void RadialMenuExample::OnKeyEvent(const KeyEvent& event) | ||
| 283 | +{ | ||
| 284 | + if(event.state == KeyEvent::Down) | ||
| 285 | + { | ||
| 286 | + if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) ) | ||
| 287 | + { | ||
| 288 | + mApplication.Quit(); | ||
| 289 | + } | ||
| 290 | + } | ||
| 291 | +} | ||
| 292 | + | ||
| 293 | +void RunTest(Application app) | ||
| 294 | +{ | ||
| 295 | + RadialMenuExample test(app); | ||
| 296 | + | ||
| 297 | + app.MainLoop(); | ||
| 298 | +} | ||
| 299 | + | ||
| 300 | +// Entry point for Linux & Tizen applications | ||
| 301 | +int main(int argc, char **argv) | ||
| 302 | +{ | ||
| 303 | + Application app = Application::New(&argc, &argv); | ||
| 304 | + | ||
| 305 | + RunTest(app); | ||
| 306 | + | ||
| 307 | + return 0; | ||
| 308 | +} |
examples/radial-menu/radial-sweep-view-impl.cpp
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + * | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | +#include "radial-sweep-view-impl.h" | ||
| 19 | + | ||
| 20 | +#include <sstream> | ||
| 21 | + | ||
| 22 | +using namespace Dali; | ||
| 23 | + | ||
| 24 | +namespace | ||
| 25 | +{ | ||
| 26 | + | ||
| 27 | +const char* VERTEX_SHADER_PREFIX( "#define MATH_PI_2 1.570796\n#define MATH_PI_4 0.785398\n" ); | ||
| 28 | + | ||
| 29 | +const char* VERTEX_SHADER = DALI_COMPOSE_SHADER( | ||
| 30 | +attribute mediump float aAngleIndex;\n | ||
| 31 | +attribute mediump vec2 aPosition1;\n | ||
| 32 | +attribute mediump vec2 aPosition2;\n | ||
| 33 | +uniform mediump mat4 uMvpMatrix;\n | ||
| 34 | +uniform mediump float uStartAngle;\n | ||
| 35 | +uniform mediump float uRotationAngle;\n | ||
| 36 | +\n | ||
| 37 | +void main()\n | ||
| 38 | +{\n | ||
| 39 | + float currentAngle = uStartAngle + uRotationAngle;\n | ||
| 40 | + float angleInterval1 = MATH_PI_4 * aAngleIndex;\n | ||
| 41 | + vec4 vertexPosition = vec4(0.0, 0.0, 0.0, 1.0);\n | ||
| 42 | + if( currentAngle >= angleInterval1)\n | ||
| 43 | + {\n | ||
| 44 | + float angleInterval2 = angleInterval1 + MATH_PI_2;\n | ||
| 45 | + float angle = currentAngle < angleInterval2 ? currentAngle : angleInterval2;\n | ||
| 46 | + float delta;\n | ||
| 47 | + if( mod( aAngleIndex+4.0, 4.0) < 2.0 )\n | ||
| 48 | + {\n | ||
| 49 | + delta = 0.5 - 0.5*cos(angle) / sin(angle);\n | ||
| 50 | + }\n | ||
| 51 | + else\n | ||
| 52 | + {\n | ||
| 53 | + delta = 0.5 + 0.5*sin(angle) / cos(angle);\n | ||
| 54 | + }\n | ||
| 55 | + vertexPosition.xy = mix( aPosition1, aPosition2, delta );\n | ||
| 56 | + }\n | ||
| 57 | + gl_Position = uMvpMatrix * vertexPosition;\n | ||
| 58 | +} | ||
| 59 | +); | ||
| 60 | + | ||
| 61 | +const char* FRAGMENT_SHADER = DALI_COMPOSE_SHADER( | ||
| 62 | +uniform lowp vec4 uColor;\n | ||
| 63 | +\n | ||
| 64 | +void main()\n | ||
| 65 | +{\n | ||
| 66 | + gl_FragColor = uColor;\n | ||
| 67 | +}\n | ||
| 68 | +); | ||
| 69 | + | ||
| 70 | +float HoldZeroFastEaseInOutHoldOne(float progress) | ||
| 71 | +{ | ||
| 72 | + if( progress < 0.2f) | ||
| 73 | + { | ||
| 74 | + return 0.0f; | ||
| 75 | + } | ||
| 76 | + else if(progress < 0.5f) | ||
| 77 | + { | ||
| 78 | + progress = (progress-0.2) / 0.3f; | ||
| 79 | + return progress*progress*progress*0.5f; | ||
| 80 | + } | ||
| 81 | + else if(progress < 0.8f) | ||
| 82 | + { | ||
| 83 | + progress = ((progress - 0.5f) / 0.3f) - 1.0f; | ||
| 84 | + return (progress*progress*progress+1.0f) * 0.5f + 0.5f; | ||
| 85 | + } | ||
| 86 | + else | ||
| 87 | + { | ||
| 88 | + return 1.0f; | ||
| 89 | + } | ||
| 90 | +} | ||
| 91 | + | ||
| 92 | +} // anonymous namespace | ||
| 93 | + | ||
| 94 | + | ||
| 95 | +RadialSweepView RadialSweepViewImpl::New( ) | ||
| 96 | +{ | ||
| 97 | + return New( 2.0f, 100.0f, ANGLE_0, ANGLE_0, ANGLE_0, ANGLE_360 ); | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | + | ||
| 101 | +RadialSweepView RadialSweepViewImpl::New( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector ) | ||
| 102 | +{ | ||
| 103 | + RadialSweepViewImpl* impl= new RadialSweepViewImpl(duration, diameter, initialAngle, finalAngle, initialSector, finalSector); | ||
| 104 | + RadialSweepView handle = RadialSweepView(*impl); | ||
| 105 | + return handle; | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +RadialSweepViewImpl::RadialSweepViewImpl( float duration, float diameter, Radian initialAngle, Radian finalAngle, Radian initialSector, Radian finalSector ) | ||
| 109 | +: Control( ControlBehaviour( ACTOR_BEHAVIOUR_NONE ) ), | ||
| 110 | + mDuration(duration), | ||
| 111 | + mDiameter(diameter), | ||
| 112 | + mInitialAngle(initialAngle), | ||
| 113 | + mFinalAngle(finalAngle), | ||
| 114 | + mInitialSector(initialSector), | ||
| 115 | + mFinalSector(finalSector), | ||
| 116 | + mInitialActorAngle(0), | ||
| 117 | + mFinalActorAngle(0), | ||
| 118 | + mEasingFunction(HoldZeroFastEaseInOutHoldOne), | ||
| 119 | + mStartAngleIndex(Property::INVALID_INDEX), | ||
| 120 | + mRotationAngleIndex(Property::INVALID_INDEX), | ||
| 121 | + mRotateActorsWithStencil(false), | ||
| 122 | + mRotateActors(false) | ||
| 123 | +{ | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +void RadialSweepViewImpl::SetDuration(float duration) | ||
| 127 | +{ | ||
| 128 | + mDuration = duration; | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +void RadialSweepViewImpl::SetEasingFunction( Dali::AlphaFunction easingFunction ) | ||
| 132 | +{ | ||
| 133 | + mEasingFunction = easingFunction; | ||
| 134 | +} | ||
| 135 | + | ||
| 136 | +void RadialSweepViewImpl::SetDiameter(float diameter) | ||
| 137 | +{ | ||
| 138 | + mDiameter = diameter; | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | +void RadialSweepViewImpl::SetInitialAngle( Dali::Radian initialAngle) | ||
| 142 | +{ | ||
| 143 | + mInitialAngle = initialAngle; | ||
| 144 | +} | ||
| 145 | + | ||
| 146 | +void RadialSweepViewImpl::SetFinalAngle( Dali::Radian finalAngle) | ||
| 147 | +{ | ||
| 148 | + mFinalAngle = finalAngle; | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +void RadialSweepViewImpl::SetInitialSector( Dali::Radian initialSector) | ||
| 152 | +{ | ||
| 153 | + mInitialSector = initialSector; | ||
| 154 | +} | ||
| 155 | + | ||
| 156 | +void RadialSweepViewImpl::SetFinalSector( Dali::Radian finalSector) | ||
| 157 | +{ | ||
| 158 | + mFinalSector = finalSector; | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +void RadialSweepViewImpl::SetInitialActorAngle( Dali::Radian initialAngle ) | ||
| 162 | +{ | ||
| 163 | + mInitialActorAngle = initialAngle; | ||
| 164 | + mRotateActors = true; | ||
| 165 | +} | ||
| 166 | + | ||
| 167 | +void RadialSweepViewImpl::SetFinalActorAngle( Dali::Radian finalAngle ) | ||
| 168 | +{ | ||
| 169 | + mFinalActorAngle = finalAngle; | ||
| 170 | + mRotateActors = true; | ||
| 171 | +} | ||
| 172 | + | ||
| 173 | +float RadialSweepViewImpl::GetDuration( ) | ||
| 174 | +{ | ||
| 175 | + return mDuration; | ||
| 176 | +} | ||
| 177 | + | ||
| 178 | +float RadialSweepViewImpl::GetDiameter( ) | ||
| 179 | +{ | ||
| 180 | + return mDiameter; | ||
| 181 | +} | ||
| 182 | + | ||
| 183 | +Dali::Radian RadialSweepViewImpl::GetInitialAngle( ) | ||
| 184 | +{ | ||
| 185 | + return mInitialAngle; | ||
| 186 | +} | ||
| 187 | + | ||
| 188 | +Dali::Radian RadialSweepViewImpl::GetFinalAngle( ) | ||
| 189 | +{ | ||
| 190 | + return mFinalAngle; | ||
| 191 | +} | ||
| 192 | + | ||
| 193 | +Dali::Radian RadialSweepViewImpl::GetInitialSector( ) | ||
| 194 | +{ | ||
| 195 | + return mInitialSector; | ||
| 196 | +} | ||
| 197 | + | ||
| 198 | +Dali::Radian RadialSweepViewImpl::GetFinalSector( ) | ||
| 199 | +{ | ||
| 200 | + return mFinalSector; | ||
| 201 | +} | ||
| 202 | + | ||
| 203 | +Dali::Radian RadialSweepViewImpl::GetInitialActorAngle( ) | ||
| 204 | +{ | ||
| 205 | + return mInitialActorAngle; | ||
| 206 | +} | ||
| 207 | + | ||
| 208 | +Dali::Radian RadialSweepViewImpl::GetFinalActorAngle( ) | ||
| 209 | +{ | ||
| 210 | + return mFinalActorAngle; | ||
| 211 | +} | ||
| 212 | + | ||
| 213 | +void RadialSweepViewImpl::RotateActorsWithStencil(bool rotate) | ||
| 214 | +{ | ||
| 215 | + mRotateActorsWithStencil = rotate; | ||
| 216 | +} | ||
| 217 | + | ||
| 218 | +void RadialSweepViewImpl::Add(Actor actor) | ||
| 219 | +{ | ||
| 220 | + if( ! mLayer ) | ||
| 221 | + { | ||
| 222 | + mLayer = Layer::New(); | ||
| 223 | + Self().Add(mLayer); | ||
| 224 | + mLayer.SetSize( Stage::GetCurrent().GetSize() ); | ||
| 225 | + mLayer.SetPositionInheritanceMode(USE_PARENT_POSITION); | ||
| 226 | + } | ||
| 227 | + | ||
| 228 | + mLayer.Add(actor); | ||
| 229 | +} | ||
| 230 | + | ||
| 231 | +void RadialSweepViewImpl::Activate( Animation anim, float offsetTime, float duration ) | ||
| 232 | +{ | ||
| 233 | + bool startAnimation=false; | ||
| 234 | + if( ! anim ) | ||
| 235 | + { | ||
| 236 | + mAnim = Animation::New( mDuration ); | ||
| 237 | + anim = mAnim; | ||
| 238 | + startAnimation = true; | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + if( ! mStencilActor ) | ||
| 242 | + { | ||
| 243 | + CreateStencil( mInitialSector ); | ||
| 244 | + mLayer.Add( mStencilActor ); | ||
| 245 | + mStencilActor.SetScale(mDiameter); | ||
| 246 | + } | ||
| 247 | + | ||
| 248 | + mStencilActor.SetOrientation( mInitialAngle, Vector3::ZAXIS ); | ||
| 249 | + mStencilActor.SetProperty( mRotationAngleIndex, mInitialSector.radian ); | ||
| 250 | + | ||
| 251 | + if( mRotateActors ) | ||
| 252 | + { | ||
| 253 | + for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++) | ||
| 254 | + { | ||
| 255 | + Actor actor = mLayer.GetChildAt(i); | ||
| 256 | + if( actor != mStencilActor ) | ||
| 257 | + { | ||
| 258 | + anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mInitialActorAngle ), Vector3::ZAXIS ) ); | ||
| 259 | + } | ||
| 260 | + } | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + anim.AnimateTo( Property( mStencilActor, mRotationAngleIndex ), mFinalSector.radian, mEasingFunction, TimePeriod( offsetTime, duration ) ); | ||
| 264 | + anim.AnimateTo( Property( mStencilActor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) ); | ||
| 265 | + | ||
| 266 | + if( mRotateActorsWithStencil ) | ||
| 267 | + { | ||
| 268 | + for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++) | ||
| 269 | + { | ||
| 270 | + Actor actor = mLayer.GetChildAt(i); | ||
| 271 | + if( actor != mStencilActor ) | ||
| 272 | + { | ||
| 273 | + anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalAngle.radian - mInitialAngle.radian ) , Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) ); | ||
| 274 | + } | ||
| 275 | + } | ||
| 276 | + } | ||
| 277 | + else if( mRotateActors ) | ||
| 278 | + { | ||
| 279 | + for(unsigned int i=0, count=mLayer.GetChildCount(); i<count; i++) | ||
| 280 | + { | ||
| 281 | + Actor actor = mLayer.GetChildAt(i); | ||
| 282 | + if( actor != mStencilActor ) | ||
| 283 | + { | ||
| 284 | + anim.AnimateTo( Property( actor, Actor::Property::ORIENTATION ), Quaternion( Radian( mFinalActorAngle ), Vector3::ZAXIS ), mEasingFunction, TimePeriod( offsetTime, duration ) ); | ||
| 285 | + } | ||
| 286 | + } | ||
| 287 | + } | ||
| 288 | + | ||
| 289 | + | ||
| 290 | + if( startAnimation ) | ||
| 291 | + { | ||
| 292 | + anim.SetLooping(true); | ||
| 293 | + anim.Play(); | ||
| 294 | + } | ||
| 295 | +} | ||
| 296 | + | ||
| 297 | + | ||
| 298 | +void RadialSweepViewImpl::Deactivate() | ||
| 299 | +{ | ||
| 300 | + if( mAnim ) | ||
| 301 | + { | ||
| 302 | + mAnim.Stop(); | ||
| 303 | + } | ||
| 304 | + // mLayer.Remove( mStencilActor ); | ||
| 305 | + // mStencilActor.Reset(); | ||
| 306 | + // mMesh.Reset(); | ||
| 307 | + // mMaterial.Reset(); | ||
| 308 | +} | ||
| 309 | + | ||
| 310 | +void RadialSweepViewImpl::CreateStencil( Radian initialSector ) | ||
| 311 | +{ | ||
| 312 | + // Create the stencil mesh geometry | ||
| 313 | + // 3-----2 | ||
| 314 | + // | \ / | | ||
| 315 | + // | 0--1 , 6 | ||
| 316 | + // | / \ | | ||
| 317 | + // 4-----5 | ||
| 318 | + | ||
| 319 | + struct VertexPosition { float angleIndex; Vector2 position1; Vector2 position2; }; | ||
| 320 | + VertexPosition vertexData[7] = { // With X coordinate inverted to make the animation go anti clockwise from left center | ||
| 321 | + { 9.f, Vector2( 0.f, 0.f ), Vector2( 0.f, 0.f ) }, // center point, keep static | ||
| 322 | + { 0.f, Vector2( -0.5f, 0.f ), Vector2( -0.5f, 0.f ) }, // vertex 1, 0 degree, keep static | ||
| 323 | + { -1.f, Vector2( -0.5f, 0.5f ), Vector2( -0.5f, -0.5f ) }, // -45 ~ 45 degrees ( 0 ~ 45) | ||
| 324 | + { 1.f, Vector2( -0.5f, -0.5f ), Vector2( 0.5f, -0.5f ) }, // 45 ~ 135 degrees | ||
| 325 | + { 3.f, Vector2( 0.5f, -0.5f ), Vector2( 0.5f, 0.5f ) }, // 135 ~ 225 degrees | ||
| 326 | + { 5.f, Vector2( 0.5f, 0.5f ), Vector2( -0.5f, 0.5f ) }, // 225 ~ 315 degrees | ||
| 327 | + { 7.f, Vector2( -0.5f, 0.5f ), Vector2( -0.5f, -0.5f ) } // 315 ~ 405 degrees ( 315 ~ 359.999 ) | ||
| 328 | + }; | ||
| 329 | + Property::Map vertexFormat; | ||
| 330 | + vertexFormat["aAngleIndex"] = Property::FLOAT; | ||
| 331 | + vertexFormat["aPosition1"] = Property::VECTOR2; | ||
| 332 | + vertexFormat["aPosition2"] = Property::VECTOR2; | ||
| 333 | + PropertyBuffer vertices = PropertyBuffer::New( PropertyBuffer::STATIC, vertexFormat, 7u ); | ||
| 334 | + vertices.SetData( vertexData ); | ||
| 335 | + | ||
| 336 | + unsigned int indexData[15] = { 0,1,2,0,2,3,0,3,4,0,4,5,0,5,6 }; | ||
| 337 | + Property::Map indexFormat; | ||
| 338 | + indexFormat["indices"] = Property::UNSIGNED_INTEGER; | ||
| 339 | + PropertyBuffer indices = PropertyBuffer::New( PropertyBuffer::STATIC, indexFormat, 15u ); | ||
| 340 | + indices.SetData( indexData ); | ||
| 341 | + | ||
| 342 | + Geometry meshGeometry = Geometry::New(); | ||
| 343 | + meshGeometry.AddVertexBuffer( vertices ); | ||
| 344 | + meshGeometry.SetIndexBuffer( indices ); | ||
| 345 | + | ||
| 346 | + // Create material | ||
| 347 | + std::ostringstream vertexShaderStringStream; | ||
| 348 | + vertexShaderStringStream<<VERTEX_SHADER_PREFIX<<VERTEX_SHADER; | ||
| 349 | + Shader shader = Shader::New( vertexShaderStringStream.str(), FRAGMENT_SHADER ); | ||
| 350 | + Material material = Material::New( shader ); | ||
| 351 | + | ||
| 352 | + // Create renderer | ||
| 353 | + Renderer renderer = Renderer::New( meshGeometry, material ); | ||
| 354 | + | ||
| 355 | + mStencilActor = Actor::New(); | ||
| 356 | + mStencilActor.AddRenderer( renderer ); | ||
| 357 | + mStencilActor.SetSize(1.f, 1.f); | ||
| 358 | + | ||
| 359 | + // register properties | ||
| 360 | + mStartAngleIndex = mStencilActor.RegisterProperty("start-angle", 0.f); | ||
| 361 | + mStencilActor.AddUniformMapping( mStartAngleIndex, "uStartAngle " ); | ||
| 362 | + mRotationAngleIndex = mStencilActor.RegisterProperty("rotation-angle", initialSector.radian); | ||
| 363 | + mStencilActor.AddUniformMapping( mRotationAngleIndex, "uRotationAngle" ); | ||
| 364 | + | ||
| 365 | + mStencilActor.SetDrawMode( DrawMode::STENCIL ); | ||
| 366 | + mStencilActor.SetPositionInheritanceMode(USE_PARENT_POSITION); | ||
| 367 | +} |
examples/radial-menu/radial-sweep-view-impl.h
0 → 100644
| 1 | +#ifndef DALI_DEMO_RADIAL_SWEEP_VIEW_IMPL_H | ||
| 2 | +#define DALI_DEMO_RADIAL_SWEEP_VIEW_IMPL_H | ||
| 3 | + | ||
| 4 | +/* | ||
| 5 | + * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||
| 6 | + * | ||
| 7 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 8 | + * you may not use this file except in compliance with the License. | ||
| 9 | + * You may obtain a copy of the License at | ||
| 10 | + * | ||
| 11 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 12 | + * | ||
| 13 | + * Unless required by applicable law or agreed to in writing, software | ||
| 14 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 15 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 16 | + * See the License for the specific language governing permissions and | ||
| 17 | + * limitations under the License. | ||
| 18 | + * | ||
| 19 | + */ | ||
| 20 | + | ||
| 21 | +#include <dali-toolkit/dali-toolkit.h> | ||
| 22 | +#include "radial-sweep-view.h" | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +/******************************************************************************** | ||
| 26 | + * Class to implement a layer with a radial sweep stencil mask and an actor tree | ||
| 27 | + */ | ||
| 28 | +class RadialSweepViewImpl : public Dali::Toolkit::Internal::Control | ||
| 29 | +{ | ||
| 30 | +public: | ||
| 31 | + static RadialSweepView New(); | ||
| 32 | + | ||
| 33 | + static RadialSweepView New( float duration, | ||
| 34 | + float diameter, | ||
| 35 | + Dali::Radian initialAngle, | ||
| 36 | + Dali::Radian finalAngle, | ||
| 37 | + Dali::Radian initialSector, | ||
| 38 | + Dali::Radian finalSector ); | ||
| 39 | + | ||
| 40 | + RadialSweepViewImpl( float duration, | ||
| 41 | + float diameter, | ||
| 42 | + Dali::Radian initialAngle, | ||
| 43 | + Dali::Radian finalAngle, | ||
| 44 | + Dali::Radian initialSector, | ||
| 45 | + Dali::Radian finalSector ); | ||
| 46 | + | ||
| 47 | + void SetDuration(float duration); | ||
| 48 | + void SetEasingFunction( Dali::AlphaFunction easingFunction ); | ||
| 49 | + | ||
| 50 | + void SetDiameter(float diameter); | ||
| 51 | + void SetInitialAngle( Dali::Radian initialAngle); | ||
| 52 | + void SetFinalAngle( Dali::Radian finalAngle); | ||
| 53 | + void SetInitialSector( Dali::Radian initialSector); | ||
| 54 | + void SetFinalSector( Dali::Radian finalSector); | ||
| 55 | + void SetInitialActorAngle( Dali::Radian initialAngle ); | ||
| 56 | + void SetFinalActorAngle( Dali::Radian finalAngle ); | ||
| 57 | + | ||
| 58 | + float GetDuration( ); | ||
| 59 | + float GetDiameter( ); | ||
| 60 | + Dali::Radian GetInitialAngle( ); | ||
| 61 | + Dali::Radian GetFinalAngle( ); | ||
| 62 | + Dali::Radian GetInitialSector( ); | ||
| 63 | + Dali::Radian GetFinalSector( ); | ||
| 64 | + Dali::Radian GetInitialActorAngle( ); | ||
| 65 | + Dali::Radian GetFinalActorAngle( ); | ||
| 66 | + | ||
| 67 | + void RotateActorsWithStencil(bool rotate); | ||
| 68 | + | ||
| 69 | + void Add( Dali::Actor actor ); | ||
| 70 | + | ||
| 71 | + void Activate( Dali::Animation anim = Dali::Animation(), float offsetTime=0, float duration=2.0f ); | ||
| 72 | + | ||
| 73 | + void Deactivate(); | ||
| 74 | + | ||
| 75 | +private: | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * Create the stencil mask | ||
| 79 | + */ | ||
| 80 | + void CreateStencil(Dali::Radian initialSector ); | ||
| 81 | + | ||
| 82 | +private: | ||
| 83 | + Dali::Layer mLayer; | ||
| 84 | + Dali::Animation mAnim; | ||
| 85 | + float mDuration; | ||
| 86 | + float mDiameter; | ||
| 87 | + Dali::Radian mInitialAngle; | ||
| 88 | + Dali::Radian mFinalAngle; | ||
| 89 | + Dali::Radian mInitialSector; | ||
| 90 | + Dali::Radian mFinalSector; | ||
| 91 | + Dali::Radian mInitialActorAngle; | ||
| 92 | + Dali::Radian mFinalActorAngle; | ||
| 93 | + Dali::AlphaFunction mEasingFunction; | ||
| 94 | + Dali::Actor mStencilActor; ///< Stencil actor which generates mask | ||
| 95 | + Dali::Property::Index mStartAngleIndex; ///< Index of start-angle property | ||
| 96 | + Dali::Property::Index mRotationAngleIndex; ///< Index of rotation-angle property | ||
| 97 | + bool mRotateActorsWithStencil:1; | ||
| 98 | + bool mRotateActors; | ||
| 99 | +}; | ||
| 100 | + | ||
| 101 | + | ||
| 102 | +inline RadialSweepViewImpl& GetImpl( RadialSweepView& obj ) | ||
| 103 | +{ | ||
| 104 | + DALI_ASSERT_ALWAYS(obj); | ||
| 105 | + Dali::RefObject& handle = obj.GetImplementation(); | ||
| 106 | + return static_cast<RadialSweepViewImpl&>(handle); | ||
| 107 | +} | ||
| 108 | + | ||
| 109 | +inline const RadialSweepViewImpl& GetImpl( const RadialSweepView& obj ) | ||
| 110 | +{ | ||
| 111 | + DALI_ASSERT_ALWAYS(obj); | ||
| 112 | + const Dali::RefObject& handle = obj.GetImplementation(); | ||
| 113 | + return static_cast<const RadialSweepViewImpl&>(handle); | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | + | ||
| 117 | + | ||
| 118 | +#endif // DALI_DEMO_RADIAL_SWEEP_VIEW_IMPL_H |
examples/radial-menu/radial-sweep-view.cpp
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + * | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | +#include "radial-sweep-view.h" | ||
| 19 | +#include "radial-sweep-view-impl.h" | ||
| 20 | + | ||
| 21 | +using namespace Dali; | ||
| 22 | + | ||
| 23 | +RadialSweepView::RadialSweepView() | ||
| 24 | +{ | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +RadialSweepView::RadialSweepView(const RadialSweepView& handle) | ||
| 28 | +: Control(handle) | ||
| 29 | +{ | ||
| 30 | +} | ||
| 31 | + | ||
| 32 | +RadialSweepView& RadialSweepView::operator=(const RadialSweepView& rhs) | ||
| 33 | +{ | ||
| 34 | + if( &rhs != this ) | ||
| 35 | + { | ||
| 36 | + Control::operator=(rhs); | ||
| 37 | + } | ||
| 38 | + return *this; | ||
| 39 | +} | ||
| 40 | + | ||
| 41 | +RadialSweepView::~RadialSweepView() | ||
| 42 | +{ | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +RadialSweepView RadialSweepView::DownCast( BaseHandle handle ) | ||
| 46 | +{ | ||
| 47 | + return Control::DownCast<RadialSweepView, RadialSweepViewImpl>(handle); | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +RadialSweepView RadialSweepView::New( ) | ||
| 51 | +{ | ||
| 52 | + return RadialSweepViewImpl::New(); | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +RadialSweepView RadialSweepView::New( float duration, | ||
| 56 | + float diameter, | ||
| 57 | + Radian initialAngle, | ||
| 58 | + Radian finalAngle, | ||
| 59 | + Radian initialSector, | ||
| 60 | + Radian finalSector ) | ||
| 61 | +{ | ||
| 62 | + return RadialSweepViewImpl::New(duration, diameter, initialAngle, finalAngle, initialSector, finalSector ); | ||
| 63 | +} | ||
| 64 | + | ||
| 65 | +RadialSweepView::RadialSweepView( RadialSweepViewImpl& impl ) | ||
| 66 | +: Control( impl ) | ||
| 67 | +{ | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +RadialSweepView::RadialSweepView( Dali::Internal::CustomActor* impl ) | ||
| 71 | +: Control( impl ) | ||
| 72 | +{ | ||
| 73 | + VerifyCustomActorPointer<RadialSweepViewImpl>(impl); | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +void RadialSweepView::SetDuration(float duration) | ||
| 77 | +{ | ||
| 78 | + GetImpl(*this).SetDuration(duration); | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +void RadialSweepView::SetEasingFunction( Dali::AlphaFunction easingFunction ) | ||
| 82 | +{ | ||
| 83 | + GetImpl(*this).SetEasingFunction( easingFunction ); | ||
| 84 | +} | ||
| 85 | + | ||
| 86 | +void RadialSweepView::SetDiameter(float diameter) | ||
| 87 | +{ | ||
| 88 | + GetImpl(*this).SetDiameter(diameter); | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +void RadialSweepView::SetInitialAngle( Dali::Radian initialAngle) | ||
| 92 | +{ | ||
| 93 | + GetImpl(*this).SetInitialAngle(initialAngle); | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +void RadialSweepView::SetFinalAngle( Dali::Radian finalAngle) | ||
| 97 | +{ | ||
| 98 | + GetImpl(*this).SetFinalAngle(finalAngle); | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +void RadialSweepView::SetInitialSector( Dali::Radian initialSector) | ||
| 102 | +{ | ||
| 103 | + GetImpl(*this).SetInitialSector(initialSector); | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +void RadialSweepView::SetFinalSector( Dali::Radian finalSector) | ||
| 107 | +{ | ||
| 108 | + GetImpl(*this).SetFinalSector(finalSector); | ||
| 109 | +} | ||
| 110 | + | ||
| 111 | +void RadialSweepView::SetInitialActorAngle( Dali::Radian initialAngle ) | ||
| 112 | +{ | ||
| 113 | + GetImpl(*this).SetInitialActorAngle(initialAngle); | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | +void RadialSweepView::SetFinalActorAngle( Dali::Radian finalAngle ) | ||
| 117 | +{ | ||
| 118 | + GetImpl(*this).SetFinalActorAngle(finalAngle); | ||
| 119 | +} | ||
| 120 | + | ||
| 121 | +float RadialSweepView::GetDuration( ) | ||
| 122 | +{ | ||
| 123 | + return GetImpl(*this).GetDuration(); | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +float RadialSweepView::GetDiameter( ) | ||
| 127 | +{ | ||
| 128 | + return GetImpl(*this).GetDiameter(); | ||
| 129 | +} | ||
| 130 | + | ||
| 131 | +Dali::Radian RadialSweepView::GetInitialAngle( ) | ||
| 132 | +{ | ||
| 133 | + return GetImpl(*this).GetInitialAngle(); | ||
| 134 | +} | ||
| 135 | + | ||
| 136 | +Dali::Radian RadialSweepView::GetFinalAngle( ) | ||
| 137 | +{ | ||
| 138 | + return GetImpl(*this).GetFinalAngle(); | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | +Dali::Radian RadialSweepView::GetInitialSector( ) | ||
| 142 | +{ | ||
| 143 | + return GetImpl(*this).GetInitialSector(); | ||
| 144 | +} | ||
| 145 | + | ||
| 146 | +Dali::Radian RadialSweepView::GetFinalSector( ) | ||
| 147 | +{ | ||
| 148 | + return GetImpl(*this).GetFinalSector(); | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +Dali::Radian RadialSweepView::GetInitialActorAngle( ) | ||
| 152 | +{ | ||
| 153 | + return GetImpl(*this).GetInitialActorAngle(); | ||
| 154 | +} | ||
| 155 | + | ||
| 156 | +Dali::Radian RadialSweepView::GetFinalActorAngle( ) | ||
| 157 | +{ | ||
| 158 | + return GetImpl(*this).GetFinalActorAngle(); | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +void RadialSweepView::RotateActorsWithStencil(bool rotate) | ||
| 162 | +{ | ||
| 163 | + GetImpl(*this).RotateActorsWithStencil(rotate); | ||
| 164 | +} | ||
| 165 | + | ||
| 166 | +void RadialSweepView::Add(Actor actor) | ||
| 167 | +{ | ||
| 168 | + GetImpl(*this).Add(actor); | ||
| 169 | +} | ||
| 170 | + | ||
| 171 | +void RadialSweepView::Activate() | ||
| 172 | +{ | ||
| 173 | + GetImpl(*this).Activate(); | ||
| 174 | +} | ||
| 175 | + | ||
| 176 | +void RadialSweepView::Activate( Dali::Animation anim, float offsetTime, float duration ) | ||
| 177 | +{ | ||
| 178 | + GetImpl(*this).Activate(anim, offsetTime, duration); | ||
| 179 | +} | ||
| 180 | + | ||
| 181 | +void RadialSweepView::Deactivate() | ||
| 182 | +{ | ||
| 183 | + GetImpl(*this).Deactivate(); | ||
| 184 | +} |
examples/radial-menu/radial-sweep-view.h
0 → 100644
| 1 | +#ifndef DALI_DEMO_RADIAL_SWEEP_VIEW_H | ||
| 2 | +#define DALI_DEMO_RADIAL_SWEEP_VIEW_H | ||
| 3 | + | ||
| 4 | +/* | ||
| 5 | + * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||
| 6 | + * | ||
| 7 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 8 | + * you may not use this file except in compliance with the License. | ||
| 9 | + * You may obtain a copy of the License at | ||
| 10 | + * | ||
| 11 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 12 | + * | ||
| 13 | + * Unless required by applicable law or agreed to in writing, software | ||
| 14 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 15 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 16 | + * See the License for the specific language governing permissions and | ||
| 17 | + * limitations under the License. | ||
| 18 | + * | ||
| 19 | + */ | ||
| 20 | + | ||
| 21 | +#include <dali-toolkit/dali-toolkit.h> | ||
| 22 | + | ||
| 23 | +class RadialSweepViewImpl; | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +/******************************************************************************** | ||
| 27 | + * Handle to RadialSweepView implementation | ||
| 28 | + */ | ||
| 29 | +class RadialSweepView : public Dali::Toolkit::Control | ||
| 30 | +{ | ||
| 31 | +public: | ||
| 32 | + /** | ||
| 33 | + * Create a new RadialSweepView with default parameters (2 second animation, | ||
| 34 | + * no rotation, sweeping out a full circle). | ||
| 35 | + */ | ||
| 36 | + static RadialSweepView New( ); | ||
| 37 | + | ||
| 38 | + /** | ||
| 39 | + * Create a new RadialSweepView. | ||
| 40 | + * @param[in] duration The duration of the sweep animation | ||
| 41 | + * @param[in] diameter The diameter of the stencil mask | ||
| 42 | + * @param[in] initialAngle The initial angle of the anticlockwise line of the sweep sector | ||
| 43 | + * @param[in] finalAngle The final angle of the anticlockwise line of the sweep sector | ||
| 44 | + * @param[in] initialSector The angle of the starting sector | ||
| 45 | + * @param[in] finalSector The angle of the sector at the end of the animation. | ||
| 46 | + * Note, to cover the entire circle, use a value of 359.9999 degrees, not zero or 360 degrees. | ||
| 47 | + * | ||
| 48 | + * initial sector | ||
| 49 | + * \ | . | ||
| 50 | + * \ | . | ||
| 51 | + * initialAngle \ | . final sector | ||
| 52 | + * \| _| | ||
| 53 | + * .________ | ||
| 54 | + */ | ||
| 55 | + static RadialSweepView New( float duration, | ||
| 56 | + float diameter, | ||
| 57 | + Dali::Radian initialAngle, | ||
| 58 | + Dali::Radian finalAngle, | ||
| 59 | + Dali::Radian initialSector, | ||
| 60 | + Dali::Radian finalSector ); | ||
| 61 | + | ||
| 62 | + void SetDuration(float duration); | ||
| 63 | + | ||
| 64 | + void SetEasingFunction( Dali::AlphaFunction easingFunction ); | ||
| 65 | + | ||
| 66 | + void SetDiameter(float diameter); | ||
| 67 | + | ||
| 68 | + void SetInitialAngle( Dali::Radian initialAngle); | ||
| 69 | + | ||
| 70 | + void SetFinalAngle( Dali::Radian finalAngle); | ||
| 71 | + | ||
| 72 | + void SetInitialSector( Dali::Radian initialSector); | ||
| 73 | + | ||
| 74 | + void SetFinalSector( Dali::Radian finalSector); | ||
| 75 | + | ||
| 76 | + void SetInitialActorAngle( Dali::Radian initialAngle ); | ||
| 77 | + | ||
| 78 | + void SetFinalActorAngle( Dali::Radian finalAngle ); | ||
| 79 | + | ||
| 80 | + float GetDuration( ); | ||
| 81 | + | ||
| 82 | + float GetDiameter( ); | ||
| 83 | + | ||
| 84 | + Dali::Radian GetInitialAngle( ); | ||
| 85 | + | ||
| 86 | + Dali::Radian GetFinalAngle( ); | ||
| 87 | + | ||
| 88 | + Dali::Radian GetInitialSector( ); | ||
| 89 | + | ||
| 90 | + Dali::Radian GetFinalSector( ); | ||
| 91 | + | ||
| 92 | + Dali::Radian GetInitialActorAngle( ); | ||
| 93 | + | ||
| 94 | + Dali::Radian GetFinalActorAngle( ); | ||
| 95 | + | ||
| 96 | + /** | ||
| 97 | + * @param[in] rotate True if the actors should rotate with the stencil | ||
| 98 | + */ | ||
| 99 | + void RotateActorsWithStencil(bool rotate); | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * Add actors to the view | ||
| 103 | + */ | ||
| 104 | + void Add(Actor actor); | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * Activate the sweep animation | ||
| 108 | + */ | ||
| 109 | + void Activate( ); | ||
| 110 | + | ||
| 111 | + void Activate( Dali::Animation anim, float offsetTime, float duration ); | ||
| 112 | + | ||
| 113 | + /** | ||
| 114 | + * Deactivate the sweep animation | ||
| 115 | + */ | ||
| 116 | + void Deactivate(); | ||
| 117 | + | ||
| 118 | + /** | ||
| 119 | + * Default constructor. Create an uninitialized handle. | ||
| 120 | + */ | ||
| 121 | + RadialSweepView(); | ||
| 122 | + | ||
| 123 | + /** | ||
| 124 | + * Copy constructor | ||
| 125 | + */ | ||
| 126 | + RadialSweepView(const RadialSweepView& handle); | ||
| 127 | + | ||
| 128 | + /** | ||
| 129 | + * Assignment operator | ||
| 130 | + */ | ||
| 131 | + RadialSweepView& operator=(const RadialSweepView& rhs); | ||
| 132 | + | ||
| 133 | + /** | ||
| 134 | + * Destructor | ||
| 135 | + */ | ||
| 136 | + ~RadialSweepView(); | ||
| 137 | + | ||
| 138 | + /** | ||
| 139 | + * Downcast method | ||
| 140 | + */ | ||
| 141 | + static RadialSweepView DownCast( BaseHandle handle ); | ||
| 142 | + | ||
| 143 | +public: // Not for use by application developers | ||
| 144 | + | ||
| 145 | + RadialSweepView( RadialSweepViewImpl& impl ); | ||
| 146 | + | ||
| 147 | + RadialSweepView( Dali::Internal::CustomActor* impl ); | ||
| 148 | +}; | ||
| 149 | + | ||
| 150 | +#endif |
examples/refraction-effect/refraction-effect-example.cpp
0 → 100644
| 1 | +/* | ||
| 2 | + * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||
| 3 | + * | ||
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + * you may not use this file except in compliance with the License. | ||
| 6 | + * You may obtain a copy of the License at | ||
| 7 | + * | ||
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + * | ||
| 10 | + * Unless required by applicable law or agreed to in writing, software | ||
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + * See the License for the specific language governing permissions and | ||
| 14 | + * limitations under the License. | ||
| 15 | + * | ||
| 16 | + */ | ||
| 17 | + | ||
| 18 | +#include <dali/dali.h> | ||
| 19 | +#include <dali-toolkit/dali-toolkit.h> | ||
| 20 | +#include "shared/view.h" | ||
| 21 | + | ||
| 22 | +#include <fstream> | ||
| 23 | +#include <sstream> | ||
| 24 | +#include <limits> | ||
| 25 | + | ||
| 26 | +using namespace Dali; | ||
| 27 | + | ||
| 28 | +namespace | ||
| 29 | +{ | ||
| 30 | +const char * const APPLICATION_TITLE( "Refraction Effect" ); | ||
| 31 | +const char * const TOOLBAR_IMAGE( DALI_IMAGE_DIR "top-bar.png" ); | ||
| 32 | +const char * const CHANGE_TEXTURE_ICON( DALI_IMAGE_DIR "icon-change.png" ); | ||
| 33 | +const char * const CHANGE_MESH_ICON( DALI_IMAGE_DIR "icon-replace.png" ); | ||
| 34 | + | ||
| 35 | +const char* MESH_FILES[] = | ||
| 36 | +{ | ||
| 37 | + DALI_MODEL_DIR "surface_pattern_v01.obj", | ||
| 38 | + DALI_MODEL_DIR "surface_pattern_v02.obj" | ||
| 39 | +}; | ||
| 40 | +const unsigned int NUM_MESH_FILES( sizeof( MESH_FILES ) / sizeof( MESH_FILES[0] ) ); | ||
| 41 | + | ||
| 42 | +const char* TEXTURE_IMAGES[]= | ||
| 43 | +{ | ||
| 44 | + DALI_IMAGE_DIR "background-1.jpg", | ||
| 45 | + DALI_IMAGE_DIR "background-2.jpg", | ||
| 46 | + DALI_IMAGE_DIR "background-3.jpg", | ||
| 47 | + DALI_IMAGE_DIR "background-4.jpg" | ||
| 48 | +}; | ||
| 49 | +const unsigned int NUM_TEXTURE_IMAGES( sizeof( TEXTURE_IMAGES ) / sizeof( TEXTURE_IMAGES[0] ) ); | ||
| 50 | + | ||
| 51 | +struct LightOffsetConstraint | ||
| 52 | +{ | ||
| 53 | + LightOffsetConstraint( float radius ) | ||
| 54 | + : mRadius( radius ) | ||
| 55 | + { | ||
| 56 | + } | ||
| 57 | + | ||
| 58 | + void operator()( Vector2& current, const PropertyInputContainer& inputs ) | ||
| 59 | + { | ||
| 60 | + float spinAngle = inputs[0]->GetFloat(); | ||
| 61 | + current.x = cos( spinAngle ); | ||
| 62 | + current.y = sin( spinAngle ); | ||
| 63 | + | ||
| 64 | + current *= mRadius; | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + float mRadius; | ||
| 68 | +}; | ||
| 69 | + | ||
| 70 | +/** | ||
| 71 | + * @brief Load an image, scaled-down to no more than the stage dimensions. | ||
| 72 | + * | ||
| 73 | + * Uses image scaling mode SCALE_TO_FILL to resize the image at | ||
| 74 | + * load time to cover the entire stage with pixels with no borders, | ||
| 75 | + * and filter mode BOX_THEN_LINEAR to sample the image with maximum quality. | ||
| 76 | + */ | ||
| 77 | +ResourceImage LoadStageFillingImage( const char * const imagePath ) | ||
| 78 | +{ | ||
| 79 | + Size stageSize = Stage::GetCurrent().GetSize(); | ||
| 80 | + return ResourceImage::New( imagePath, ImageDimensions( stageSize.x, stageSize.y ), Dali::FittingMode::SCALE_TO_FILL, Dali::SamplingMode::BOX_THEN_LINEAR ); | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +/** | ||
| 84 | + * structure of the vertex in the mesh | ||
| 85 | + */ | ||
| 86 | +struct Vertex | ||
| 87 | +{ | ||
| 88 | + Vector3 position; | ||
| 89 | + Vector3 normal; | ||
| 90 | + Vector2 textureCoord; | ||
| 91 | + | ||
| 92 | + Vertex() | ||
| 93 | + {} | ||
| 94 | + | ||
| 95 | + Vertex( const Vector3& position, const Vector3& normal, const Vector2& textureCoord ) | ||
| 96 | + : position( position ), normal( normal ), textureCoord( textureCoord ) | ||
| 97 | + {} | ||
| 98 | +}; | ||
| 99 | + | ||
| 100 | +/************************************************************************************************ | ||
| 101 | + *** The shader source is used when the MeshActor is not touched*** | ||
| 102 | + ************************************************************************************************/ | ||
| 103 | +const char* VERTEX_SHADER_FLAT = DALI_COMPOSE_SHADER( | ||
| 104 | +attribute mediump vec3 aPosition;\n | ||
| 105 | +attribute mediump vec3 aNormal;\n | ||
| 106 | +attribute highp vec2 aTexCoord;\n | ||
| 107 | +uniform mediump mat4 uMvpMatrix;\n | ||
| 108 | +varying mediump vec2 vTexCoord;\n | ||
| 109 | +void main()\n | ||
| 110 | +{\n | ||
| 111 | + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n | ||
| 112 | + vTexCoord = aTexCoord.xy;\n | ||
| 113 | +}\n | ||
| 114 | +); | ||
| 115 | + | ||
| 116 | +const char* FRAGMENT_SHADER_FLAT = DALI_COMPOSE_SHADER( | ||
| 117 | +uniform lowp vec4 uColor;\n | ||
| 118 | +uniform sampler2D sTexture;\n | ||
| 119 | +varying mediump vec2 vTexCoord;\n | ||
| 120 | +void main()\n | ||
| 121 | +{\n | ||
| 122 | + gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n | ||
| 123 | +}\n | ||
| 124 | +); | ||
| 125 | + | ||
| 126 | +/************************************************************ | ||
| 127 | + ** Custom refraction effect shader*************************** | ||
| 128 | + ************************************************************/ | ||
| 129 | +const char* VERTEX_SHADER_REFRACTION = DALI_COMPOSE_SHADER( | ||
| 130 | +attribute mediump vec3 aPosition;\n | ||
| 131 | +attribute mediump vec3 aNormal;\n | ||
| 132 | +attribute highp vec2 aTexCoord;\n | ||
| 133 | +uniform mediump mat4 uMvpMatrix;\n | ||
| 134 | +varying mediump vec4 vVertex;\n | ||
| 135 | +varying mediump vec3 vNormal;\n | ||
| 136 | +varying mediump vec2 vTexCoord;\n | ||
| 137 | +varying mediump vec2 vTextureOffset;\n | ||
| 138 | +void main()\n | ||
| 139 | +{\n | ||
| 140 | + gl_Position = uMvpMatrix * vec4( aPosition.xy, 0.0, 1.0 );\n | ||
| 141 | + vTexCoord = aTexCoord.xy;\n | ||
| 142 | + | ||
| 143 | + vNormal = aNormal;\n | ||
| 144 | + vVertex = vec4( aPosition, 1.0 );\n | ||
| 145 | + float length = max(0.01, length(aNormal.xy)) * 40.0;\n | ||
| 146 | + vTextureOffset = aNormal.xy / length;\n | ||
| 147 | +}\n | ||
| 148 | +); | ||
| 149 | + | ||
| 150 | +const char* FRAGMENT_SHADER_REFRACTION = DALI_COMPOSE_SHADER( | ||
| 151 | +precision mediump float;\n | ||
| 152 | +uniform mediump float uEffectStrength;\n | ||
| 153 | +uniform mediump vec3 uLightPosition;\n | ||
| 154 | +uniform mediump vec2 uLightXYOffset;\n | ||
| 155 | +uniform mediump vec2 uLightSpinOffset;\n | ||
| 156 | +uniform mediump float uLightIntensity;\n | ||
| 157 | +uniform lowp vec4 uColor;\n | ||
| 158 | +uniform sampler2D sTexture;\n | ||
| 159 | +varying mediump vec4 vVertex;\n | ||
| 160 | +varying mediump vec3 vNormal;\n | ||
| 161 | +varying mediump vec2 vTexCoord;\n | ||
| 162 | +varying mediump vec2 vTextureOffset;\n | ||
| 163 | + | ||
| 164 | +vec3 rgb2hsl(vec3 rgb)\n | ||
| 165 | +{\n | ||
| 166 | + float epsilon = 1.0e-10;\n | ||
| 167 | + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n | ||
| 168 | + vec4 P = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g));\n | ||
| 169 | + vec4 Q = mix(vec4(P.xyw, rgb.r), vec4(rgb.r, P.yzx), step(P.x, rgb.r));\n | ||
| 170 | + \n | ||
| 171 | + // RGB -> HCV | ||
| 172 | + float value = Q.x;\n | ||
| 173 | + float chroma = Q.x - min(Q.w, Q.y);\n | ||
| 174 | + float hue = abs(Q.z + (Q.w-Q.y) / (6.0*chroma+epsilon));\n | ||
| 175 | + // HCV -> HSL | ||
| 176 | + float lightness = value - chroma*0.5;\n | ||
| 177 | + return vec3( hue, chroma/max( 1.0-abs(lightness*2.0-1.0), 1.0e-1 ), lightness );\n | ||
| 178 | +}\n | ||
| 179 | + | ||
| 180 | +vec3 hsl2rgb( vec3 hsl )\n | ||
| 181 | +{\n | ||
| 182 | + // pure hue->RGB | ||
| 183 | + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n | ||
| 184 | + vec3 p = abs(fract(hsl.xxx + K.xyz) * 6.0 - K.www);\n | ||
| 185 | + vec3 RGB = clamp(p - K.xxx, 0.0, 1.0);\n | ||
| 186 | + \n | ||
| 187 | + float chroma = ( 1.0 - abs( hsl.z*2.0-1.0 ) ) * hsl.y;\n | ||
| 188 | + return ( RGB - 0.5 ) * chroma + hsl.z;\n | ||
| 189 | +}\n | ||
| 190 | + | ||
| 191 | +void main()\n | ||
| 192 | +{\n | ||
| 193 | + vec3 normal = normalize( vNormal);\n | ||
| 194 | + | ||
| 195 | + vec3 lightPosition = uLightPosition + vec3(uLightXYOffset+uLightSpinOffset, 0.0);\n | ||
| 196 | + mediump vec3 vecToLight = normalize( (lightPosition - vVertex.xyz) * 0.01 );\n | ||
| 197 | + mediump float spotEffect = pow( max(0.05, vecToLight.z ) - 0.05, 8.0);\n | ||
| 198 | + | ||
| 199 | + spotEffect = spotEffect * uEffectStrength;\n | ||
| 200 | + mediump float lightDiffuse = ( ( dot( vecToLight, normal )-0.75 ) *uLightIntensity ) * spotEffect;\n | ||
| 201 | + | ||
| 202 | + lowp vec4 color = texture2D( sTexture, vTexCoord + vTextureOffset * spotEffect );\n | ||
| 203 | + vec3 lightedColor = hsl2rgb( rgb2hsl(color.rgb) + vec3(0.0,0.0,lightDiffuse) );\n | ||
| 204 | + | ||
| 205 | + gl_FragColor = vec4( lightedColor, color.a ) * uColor;\n | ||
| 206 | +}\n | ||
| 207 | +); | ||
| 208 | + | ||
| 209 | +} // namespace | ||
| 210 | + | ||
| 211 | + | ||
| 212 | +/*************************************************/ | ||
| 213 | +/*Demo using RefractionEffect*****************/ | ||
| 214 | +/*************************************************/ | ||
| 215 | +class RefractionEffectExample : public ConnectionTracker | ||
| 216 | +{ | ||
| 217 | +public: | ||
| 218 | + RefractionEffectExample( Application &application ) | ||
| 219 | + : mApplication( application ), | ||
| 220 | + mCurrentTextureId( 1 ), | ||
| 221 | + mCurrentMeshId( 0 ) | ||
| 222 | + { | ||
| 223 | + // Connect to the Application's Init signal | ||
| 224 | + application.InitSignal().Connect(this, &RefractionEffectExample::Create); | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + ~RefractionEffectExample() | ||
| 228 | + { | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | +private: | ||
| 232 | + | ||
| 233 | + // The Init signal is received once (only) during the Application lifetime | ||
| 234 | + void Create(Application& application) | ||
| 235 | + { | ||
| 236 | + DemoHelper::RequestThemeChange(); | ||
| 237 | + | ||
| 238 | + Stage stage = Stage::GetCurrent(); | ||
| 239 | + Vector2 stageSize = stage.GetSize(); | ||
| 240 | + | ||
| 241 | + stage.KeyEventSignal().Connect(this, &RefractionEffectExample::OnKeyEvent); | ||
| 242 | + | ||
| 243 | + // Creates a default view with a default tool bar. | ||
| 244 | + // The view is added to the stage. | ||
| 245 | + Toolkit::ToolBar toolBar; | ||
| 246 | + Toolkit::Control view; | ||
| 247 | + mContent = DemoHelper::CreateView( application, | ||
| 248 | + view, | ||
| 249 | + toolBar, | ||
| 250 | + "", | ||
| 251 | + TOOLBAR_IMAGE, | ||
| 252 | + APPLICATION_TITLE ); | ||
| 253 | + | ||
| 254 | + // Add a button to change background. (right of toolbar) | ||
| 255 | + mChangeTextureButton = Toolkit::PushButton::New(); | ||
| 256 | + mChangeTextureButton.SetBackgroundImage( ResourceImage::New( CHANGE_TEXTURE_ICON ) ); | ||
| 257 | + mChangeTextureButton.ClickedSignal().Connect( this, &RefractionEffectExample::OnChangeTexture ); | ||
| 258 | + toolBar.AddControl( mChangeTextureButton, | ||
| 259 | + DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, | ||
| 260 | + Toolkit::Alignment::HorizontalRight, | ||
| 261 | + DemoHelper::DEFAULT_MODE_SWITCH_PADDING ); | ||
| 262 | + // Add a button to change mesh pattern. ( left of bar ) | ||
| 263 | + mChangeMeshButton = Toolkit::PushButton::New(); | ||
| 264 | + mChangeMeshButton.SetBackgroundImage( ResourceImage::New( CHANGE_MESH_ICON ) ); | ||
| 265 | + mChangeMeshButton.ClickedSignal().Connect( this, &RefractionEffectExample::OnChangeMesh ); | ||
| 266 | + toolBar.AddControl( mChangeMeshButton, | ||
| 267 | + DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, | ||
| 268 | + Toolkit::Alignment::HorizontalLeft, | ||
| 269 | + DemoHelper::DEFAULT_MODE_SWITCH_PADDING ); | ||
| 270 | + | ||
| 271 | + | ||
| 272 | + | ||
| 273 | + // shader used when the screen is not touched, render a flat surface | ||
| 274 | + mShaderFlat = Shader::New( VERTEX_SHADER_FLAT, FRAGMENT_SHADER_FLAT ); | ||
| 275 | + mGeometry = CreateGeometry( MESH_FILES[mCurrentMeshId] ); | ||
| 276 | + | ||
| 277 | + Image texture = LoadStageFillingImage( TEXTURE_IMAGES[mCurrentTextureId] ); | ||
| 278 | + mSampler = Sampler::New( texture, "sTexture" ); | ||
| 279 | + mMaterial = Material::New( mShaderFlat ); | ||
| 280 | + mMaterial.AddSampler( mSampler ); | ||
| 281 | + | ||
| 282 | + mRenderer = Renderer::New( mGeometry, mMaterial ); | ||
| 283 | + | ||
| 284 | + mMeshActor = Actor::New(); | ||
| 285 | + mMeshActor.AddRenderer( mRenderer ); | ||
| 286 | + mMeshActor.SetSize( stageSize ); | ||
| 287 | + mMeshActor.SetParentOrigin(ParentOrigin::CENTER); | ||
| 288 | + mContent.Add( mMeshActor ); | ||
| 289 | + | ||
| 290 | + // Connect the callback to the touch signal on the mesh actor | ||
| 291 | + mContent.TouchedSignal().Connect( this, &RefractionEffectExample::OnTouch ); | ||
| 292 | + | ||
| 293 | + // shader used when the finger is touching the screen. render refraction effect | ||
| 294 | + mShaderRefraction = Shader::New( VERTEX_SHADER_REFRACTION, FRAGMENT_SHADER_REFRACTION ); | ||
| 295 | + | ||
| 296 | + // register uniforms | ||
| 297 | + mLightXYOffsetIndex = mMeshActor.RegisterProperty( "light-XY-offset", Vector2::ZERO ); | ||
| 298 | + mMeshActor.AddUniformMapping( mLightXYOffsetIndex, "uLightXYOffset" ); | ||
| 299 | + | ||
| 300 | + mLightIntensityIndex = mMeshActor.RegisterProperty( "light-intensity", 2.5f ); | ||
| 301 | + mMeshActor.AddUniformMapping( mLightIntensityIndex, "uLightIntensity" ); | ||
| 302 | + | ||
| 303 | + mEffectStrengthIndex = mMeshActor.RegisterProperty( "effect-strength", 0.f ); | ||
| 304 | + mMeshActor.AddUniformMapping( mEffectStrengthIndex, "uEffectStrength" ); | ||
| 305 | + | ||
| 306 | + Vector3 lightPosition( -stageSize.x*0.5f, -stageSize.y*0.5f, stageSize.x*0.5f ); // top_left | ||
| 307 | + Property::Index lightPositionIndex = mMeshActor.RegisterProperty( "light-position", lightPosition ); | ||
| 308 | + mMeshActor.AddUniformMapping( lightPositionIndex, "uLightPosition"); | ||
| 309 | + | ||
| 310 | + Property::Index lightSpinOffsetIndex = mMeshActor.RegisterProperty( "light-spin-offset", Vector2::ZERO ); | ||
| 311 | + mMeshActor.AddUniformMapping( lightSpinOffsetIndex, "uLightSpinOffset" ); | ||
| 312 | + | ||
| 313 | + mSpinAngleIndex = mMeshActor.RegisterProperty("spin-angle", 0.f ); | ||
| 314 | + Constraint constraint = Constraint::New<Vector2>( mMeshActor, lightSpinOffsetIndex, LightOffsetConstraint(stageSize.x*0.1f) ); | ||
| 315 | + constraint.AddSource( LocalSource(mSpinAngleIndex) ); | ||
| 316 | + constraint.Apply(); | ||
| 317 | + | ||
| 318 | + // the animation which spin the light around the finger touch position | ||
| 319 | + mLightAnimation = Animation::New(2.f); | ||
| 320 | + mLightAnimation.AnimateTo( Property( mMeshActor, mSpinAngleIndex ), Math::PI*2.f ); | ||
| 321 | + mLightAnimation.SetLooping( true ); | ||
| 322 | + mLightAnimation.Pause(); | ||
| 323 | + } | ||
| 324 | + | ||
| 325 | + void SetLightXYOffset( const Vector2& offset ) | ||
| 326 | + { | ||
| 327 | + mMeshActor.SetProperty( mLightXYOffsetIndex, offset ); | ||
| 328 | + } | ||
| 329 | + | ||
| 330 | + /** | ||
| 331 | + * Create a mesh actor with different geometry to replace the current one | ||
| 332 | + */ | ||
| 333 | + bool OnChangeMesh( Toolkit::Button button ) | ||
| 334 | + { | ||
| 335 | + mCurrentMeshId = ( mCurrentMeshId + 1 ) % NUM_MESH_FILES; | ||
| 336 | + mGeometry = CreateGeometry( MESH_FILES[mCurrentMeshId] ); | ||
| 337 | + mRenderer.SetGeometry( mGeometry ); | ||
| 338 | + | ||
| 339 | + return true; | ||
| 340 | + } | ||
| 341 | + | ||
| 342 | + bool OnChangeTexture( Toolkit::Button button ) | ||
| 343 | + { | ||
| 344 | + mCurrentTextureId = ( mCurrentTextureId + 1 ) % NUM_TEXTURE_IMAGES; | ||
| 345 | + Image texture = LoadStageFillingImage( TEXTURE_IMAGES[mCurrentTextureId] ); | ||
| 346 | + mSampler.SetImage( texture ); | ||
| 347 | + return true; | ||
| 348 | + } | ||
| 349 | + | ||
| 350 | + bool OnTouch( Actor actor , const TouchEvent& event ) | ||
| 351 | + { | ||
| 352 | + const TouchPoint &point = event.GetPoint(0); | ||
| 353 | + switch(point.state) | ||
| 354 | + { | ||
| 355 | + case TouchPoint::Down: | ||
| 356 | + { | ||
| 357 | + mMaterial.SetShader( mShaderRefraction ); | ||
| 358 | + | ||
| 359 | + SetLightXYOffset( point.screen ); | ||
| 360 | + | ||
| 361 | + mLightAnimation.Play(); | ||
| 362 | + | ||
| 363 | + if( mStrenghAnimation ) | ||
| 364 | + { | ||
| 365 | + mStrenghAnimation.Clear(); | ||
| 366 | + } | ||
| 367 | + | ||
| 368 | + mStrenghAnimation= Animation::New(0.5f); | ||
| 369 | + mStrenghAnimation.AnimateTo( Property( mMeshActor, mEffectStrengthIndex ), 1.f ); | ||
| 370 | + mStrenghAnimation.Play(); | ||
| 371 | + | ||
| 372 | + break; | ||
| 373 | + } | ||
| 374 | + case TouchPoint::Motion: | ||
| 375 | + { | ||
| 376 | + // make the light position following the finger movement | ||
| 377 | + SetLightXYOffset( point.screen ); | ||
| 378 | + break; | ||
| 379 | + } | ||
| 380 | + case TouchPoint::Up: | ||
| 381 | + case TouchPoint::Leave: | ||
| 382 | + case TouchPoint::Interrupted: | ||
| 383 | + { | ||
| 384 | + mLightAnimation.Pause(); | ||
| 385 | + | ||
| 386 | + if( mStrenghAnimation ) | ||
| 387 | + { | ||
| 388 | + mStrenghAnimation.Clear(); | ||
| 389 | + } | ||
| 390 | + mStrenghAnimation = Animation::New(0.5f); | ||
| 391 | + mStrenghAnimation.AnimateTo( Property( mMeshActor, mEffectStrengthIndex ), 0.f ); | ||
| 392 | + mStrenghAnimation.FinishedSignal().Connect( this, &RefractionEffectExample::OnTouchFinished ); | ||
| 393 | + mStrenghAnimation.Play(); | ||
| 394 | + break; | ||
| 395 | + } | ||
| 396 | + case TouchPoint::Stationary: | ||
| 397 | + case TouchPoint::Last: | ||
| 398 | + default: | ||
| 399 | + { | ||
| 400 | + break; | ||
| 401 | + } | ||
| 402 | + } | ||
| 403 | + | ||
| 404 | + return true; | ||
| 405 | + } | ||
| 406 | + | ||
| 407 | + void OnTouchFinished( Animation& source ) | ||
| 408 | + { | ||
| 409 | + mMaterial.SetShader( mShaderFlat ); | ||
| 410 | + SetLightXYOffset( Vector2::ZERO ); | ||
| 411 | + } | ||
| 412 | + | ||
| 413 | + Geometry CreateGeometry(const std::string& objFileName) | ||
| 414 | + { | ||
| 415 | + std::vector<Vector3> vertexPositions; | ||
| 416 | + Vector<unsigned int> faceIndices; | ||
| 417 | + Vector<float> boundingBox; | ||
| 418 | + // read the vertice and faces from the .obj file, and record the bounding box | ||
| 419 | + ReadObjFile( objFileName, boundingBox, vertexPositions, faceIndices ); | ||
| 420 | + | ||
| 421 | + std::vector<Vector2> textureCoordinates; | ||
| 422 | + // align the mesh, scale it to fit the screen size, and calculate the texture coordinate for each vertex | ||
| 423 | + ShapeResizeAndTexureCoordinateCalculation( boundingBox, vertexPositions, textureCoordinates ); | ||
| 424 | + | ||
| 425 | + // re-organize the mesh, the vertices are duplicated, each vertex only belongs to one triangle. | ||
| 426 | + // Without sharing vertex between triangle, so we can manipulate the texture offset on each triangle conveniently. | ||
| 427 | + std::vector<Vertex> vertices; | ||
| 428 | + | ||
| 429 | + std::size_t size = faceIndices.Size(); | ||
| 430 | + vertices.reserve( size ); | ||
| 431 | + | ||
| 432 | + for( std::size_t i=0; i<size; i=i+3 ) | ||
| 433 | + { | ||
| 434 | + Vector3 edge1 = vertexPositions[ faceIndices[i+2] ] - vertexPositions[ faceIndices[i] ]; | ||
| 435 | + Vector3 edge2 = vertexPositions[ faceIndices[i+1] ] - vertexPositions[ faceIndices[i] ]; | ||
| 436 | + Vector3 normal = edge1.Cross(edge2); | ||
| 437 | + normal.Normalize(); | ||
| 438 | + | ||
| 439 | + // make sure all the faces are front-facing | ||
| 440 | + if( normal.z > 0 ) | ||
| 441 | + { | ||
| 442 | + vertices.push_back( Vertex( vertexPositions[ faceIndices[i] ], normal, textureCoordinates[ faceIndices[i] ] ) ); | ||
| 443 | + vertices.push_back( Vertex( vertexPositions[ faceIndices[i+1] ], normal, textureCoordinates[ faceIndices[i+1] ] ) ); | ||
| 444 | + vertices.push_back( Vertex( vertexPositions[ faceIndices[i+2] ], normal, textureCoordinates[ faceIndices[i+2] ] ) ); | ||
| 445 | + } | ||
| 446 | + else | ||
| 447 | + { | ||
| 448 | + normal *= -1.f; | ||
| 449 | + vertices.push_back( Vertex( vertexPositions[ faceIndices[i] ], normal, textureCoordinates[ faceIndices[i] ] ) ); | ||
| 450 | + vertices.push_back( Vertex( vertexPositions[ faceIndices[i+2] ], normal, textureCoordinates[ faceIndices[i+2] ] ) ); | ||
| 451 | + vertices.push_back( Vertex( vertexPositions[ faceIndices[i+1] ], normal, textureCoordinates[ faceIndices[i+1] ] ) ); | ||
| 452 | + } | ||
| 453 | + } | ||
| 454 | + | ||
| 455 | + Property::Map vertexFormat; | ||
| 456 | + vertexFormat["aPosition"] = Property::VECTOR3; | ||
| 457 | + vertexFormat["aNormal"] = Property::VECTOR3; | ||
| 458 | + vertexFormat["aTexCoord"] = Property::VECTOR2; | ||
| 459 | + PropertyBuffer surfaceVertices = PropertyBuffer::New( PropertyBuffer::STATIC, vertexFormat, vertices.size() ); | ||
| 460 | + surfaceVertices.SetData( &vertices[0] ); | ||
| 461 | + | ||
| 462 | + Geometry surface = Geometry::New(); | ||
| 463 | + surface.AddVertexBuffer( surfaceVertices ); | ||
| 464 | + | ||
| 465 | + return surface; | ||
| 466 | + } | ||
| 467 | + | ||
| 468 | + void ReadObjFile( const std::string& objFileName, | ||
| 469 | + Vector<float>& boundingBox, | ||
| 470 | + std::vector<Vector3>& vertexPositions, | ||
| 471 | + Vector<unsigned int>& faceIndices) | ||
| 472 | + { | ||
| 473 | + std::ifstream ifs( objFileName.c_str(), std::ios::in ); | ||
| 474 | + | ||
| 475 | + boundingBox.Resize( 6 ); | ||
| 476 | + boundingBox[0]=boundingBox[2]=boundingBox[4] = std::numeric_limits<float>::max(); | ||
| 477 | + boundingBox[1]=boundingBox[3]=boundingBox[5] = -std::numeric_limits<float>::max(); | ||
| 478 | + | ||
| 479 | + std::string line; | ||
| 480 | + while( std::getline( ifs, line ) ) | ||
| 481 | + { | ||
| 482 | + if( line[0] == 'v' && std::isspace(line[1])) // vertex | ||
| 483 | + { | ||
| 484 | + std::istringstream iss(line.substr(2), std::istringstream::in); | ||
| 485 | + unsigned int i = 0; | ||
| 486 | + Vector3 vertex; | ||
| 487 | + while( iss >> vertex[i++] && i < 3); | ||
| 488 | + if( vertex.x < boundingBox[0] ) boundingBox[0] = vertex.x; | ||
| 489 | + if( vertex.x > boundingBox[1] ) boundingBox[1] = vertex.x; | ||
| 490 | + if( vertex.y < boundingBox[2] ) boundingBox[2] = vertex.y; | ||
| 491 | + if( vertex.y > boundingBox[3] ) boundingBox[3] = vertex.y; | ||
| 492 | + if( vertex.z < boundingBox[4] ) boundingBox[4] = vertex.z; | ||
| 493 | + if( vertex.z > boundingBox[5] ) boundingBox[5] = vertex.z; | ||
| 494 | + vertexPositions.push_back( vertex ); | ||
| 495 | + } | ||
| 496 | + else if( line[0] == 'f' ) //face | ||
| 497 | + { | ||
| 498 | + unsigned int numOfInt = 3; | ||
| 499 | + while( true ) | ||
| 500 | + { | ||
| 501 | + std::size_t found = line.find('/'); | ||
| 502 | + if( found == std::string::npos ) | ||
| 503 | + { | ||
| 504 | + break; | ||
| 505 | + } | ||
| 506 | + line[found] = ' '; | ||
| 507 | + numOfInt++; | ||
| 508 | + } | ||
| 509 | + | ||
| 510 | + std::istringstream iss(line.substr(2), std::istringstream::in); | ||
| 511 | + unsigned int indices[ numOfInt ]; | ||
| 512 | + unsigned int i=0; | ||
| 513 | + while( iss >> indices[i++] && i < numOfInt); | ||
| 514 | + unsigned int step = (i+1) / 3; | ||
| 515 | + faceIndices.PushBack( indices[0]-1 ); | ||
| 516 | + faceIndices.PushBack( indices[step]-1 ); | ||
| 517 | + faceIndices.PushBack( indices[2*step]-1 ); | ||
| 518 | + } | ||
| 519 | + } | ||
| 520 | + | ||
| 521 | + ifs.close(); | ||
| 522 | + } | ||
| 523 | + | ||
| 524 | + void ShapeResizeAndTexureCoordinateCalculation( const Vector<float>& boundingBox, | ||
| 525 | + std::vector<Vector3>& vertexPositions, | ||
| 526 | + std::vector<Vector2>& textureCoordinates) | ||
| 527 | + { | ||
| 528 | + Vector3 bBoxSize( boundingBox[1] - boundingBox[0], boundingBox[3] - boundingBox[2], boundingBox[5] - boundingBox[4]); | ||
| 529 | + Vector3 bBoxMinCorner( boundingBox[0], boundingBox[2], boundingBox[4] ); | ||
| 530 | + | ||
| 531 | + Vector2 stageSize = Stage::GetCurrent().GetSize(); | ||
| 532 | + Vector3 scale( stageSize.x / bBoxSize.x, stageSize.y / bBoxSize.y, 1.f ); | ||
| 533 | + scale.z = (scale.x + scale.y)/2.f; | ||
| 534 | + | ||
| 535 | + textureCoordinates.reserve(vertexPositions.size()); | ||
| 536 | + | ||
| 537 | + for( std::vector<Vector3>::iterator iter = vertexPositions.begin(); iter != vertexPositions.end(); iter++ ) | ||
| 538 | + { | ||
| 539 | + Vector3 newPosition( (*iter) - bBoxMinCorner ) ; | ||
| 540 | + | ||
| 541 | + textureCoordinates.push_back( Vector2( newPosition.x / bBoxSize.x, newPosition.y / bBoxSize.y ) ); | ||
| 542 | + | ||
| 543 | + newPosition -= bBoxSize * 0.5f; | ||
| 544 | + (*iter) = newPosition * scale; | ||
| 545 | + } | ||
| 546 | + } | ||
| 547 | + | ||
| 548 | + /** | ||
| 549 | + * Main key event handler | ||
| 550 | + */ | ||
| 551 | + void OnKeyEvent(const KeyEvent& event) | ||
| 552 | + { | ||
| 553 | + if(event.state == KeyEvent::Down) | ||
| 554 | + { | ||
| 555 | + if( IsKey( event, Dali::DALI_KEY_ESCAPE) || IsKey( event, Dali::DALI_KEY_BACK) ) | ||
| 556 | + { | ||
| 557 | + mApplication.Quit(); | ||
| 558 | + } | ||
| 559 | + } | ||
| 560 | + } | ||
| 561 | + | ||
| 562 | +private: | ||
| 563 | + | ||
| 564 | + Application& mApplication; | ||
| 565 | + Layer mContent; | ||
| 566 | + | ||
| 567 | + Sampler mSampler; | ||
| 568 | + Material mMaterial; | ||
| 569 | + Geometry mGeometry; | ||
| 570 | + Renderer mRenderer; | ||
| 571 | + Actor mMeshActor; | ||
| 572 | + | ||
| 573 | + Shader mShaderFlat; | ||
| 574 | + Shader mShaderRefraction; | ||
| 575 | + | ||
| 576 | + Animation mLightAnimation; | ||
| 577 | + Animation mStrenghAnimation; | ||
| 578 | + | ||
| 579 | + Property::Index mLightXYOffsetIndex; | ||
| 580 | + Property::Index mSpinAngleIndex; | ||
| 581 | + Property::Index mLightIntensityIndex; | ||
| 582 | + Property::Index mEffectStrengthIndex; | ||
| 583 | + | ||
| 584 | + Toolkit::PushButton mChangeTextureButton; | ||
| 585 | + Toolkit::PushButton mChangeMeshButton; | ||
| 586 | + unsigned int mCurrentTextureId; | ||
| 587 | + unsigned int mCurrentMeshId; | ||
| 588 | +}; | ||
| 589 | + | ||
| 590 | +/*****************************************************************************/ | ||
| 591 | + | ||
| 592 | +static void | ||
| 593 | +RunTest(Application& app) | ||
| 594 | +{ | ||
| 595 | + RefractionEffectExample theApp(app); | ||
| 596 | + app.MainLoop(); | ||
| 597 | +} | ||
| 598 | + | ||
| 599 | +/*****************************************************************************/ | ||
| 600 | + | ||
| 601 | +int | ||
| 602 | +main(int argc, char **argv) | ||
| 603 | +{ | ||
| 604 | + Application app = Application::New(&argc, &argv); | ||
| 605 | + | ||
| 606 | + RunTest(app); | ||
| 607 | + | ||
| 608 | + return 0; | ||
| 609 | +} |