The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

300 lines
10KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2015 - ROLI Ltd.
  5. Permission is granted to use this software under the terms of either:
  6. a) the GPL v2 (or any later version)
  7. b) the Affero GPL v3
  8. Details of these licenses can be found at: www.gnu.org/licenses
  9. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  11. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. ------------------------------------------------------------------------------
  13. To release a closed-source product which uses JUCE, commercial licenses are
  14. available: visit www.juce.com for more information.
  15. ==============================================================================
  16. */
  17. #include "../JuceDemoHeader.h"
  18. //==============================================================================
  19. /** This will be the source of our balls and can be dragged around. */
  20. class BallGeneratorComponent : public Component
  21. {
  22. public:
  23. BallGeneratorComponent()
  24. {
  25. }
  26. void paint (Graphics& g) override
  27. {
  28. Rectangle<float> area (getLocalBounds().toFloat().reduced (2.0f));
  29. g.setColour (Colours::orange);
  30. g.drawRoundedRectangle (area, 10.0f, 2.0f);
  31. AttributedString s;
  32. s.setJustification (Justification::centred);
  33. s.setWordWrap (AttributedString::none);
  34. s.append ("Drag Me!");
  35. s.setColour (Colours::white);
  36. s.draw (g, area);
  37. }
  38. void resized() override
  39. {
  40. // Just set the limits of our constrainer so that we don't drag ourselves off the screen
  41. constrainer.setMinimumOnscreenAmounts (getHeight(), getWidth(), getHeight(), getWidth());
  42. }
  43. void mouseDown (const MouseEvent& e) override
  44. {
  45. // Prepares our dragger to drag this Component
  46. dragger.startDraggingComponent (this, e);
  47. }
  48. void mouseDrag (const MouseEvent& e) override
  49. {
  50. // Moves this Component according to the mouse drag event and applies our constraints to it
  51. dragger.dragComponent (this, e, &constrainer);
  52. }
  53. private:
  54. ComponentBoundsConstrainer constrainer;
  55. ComponentDragger dragger;
  56. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BallGeneratorComponent)
  57. };
  58. //==============================================================================
  59. struct BallComponent : public Component
  60. {
  61. BallComponent (const Point<float>& pos)
  62. : position (pos),
  63. speed (Random::getSystemRandom().nextFloat() * 4.0f - 2.0f,
  64. Random::getSystemRandom().nextFloat() * -6.0f - 2.0f),
  65. colour (Colours::white)
  66. {
  67. setSize (20, 20);
  68. step();
  69. }
  70. bool step()
  71. {
  72. position += speed;
  73. speed.y += 0.1f;
  74. setCentrePosition ((int) position.x,
  75. (int) position.y);
  76. if (Component* parent = getParentComponent())
  77. return isPositiveAndBelow (position.x, (float) parent->getWidth())
  78. && position.y < (float) parent->getHeight();
  79. return position.y < 400.0f && position.x >= -10.0f;
  80. }
  81. void paint (Graphics& g) override
  82. {
  83. g.setColour (colour);
  84. g.fillEllipse (2.0f, 2.0f, getWidth() - 4.0f, getHeight() - 4.0f);
  85. g.setColour (Colours::darkgrey);
  86. g.drawEllipse (2.0f, 2.0f, getWidth() - 4.0f, getHeight() - 4.0f, 1.0f);
  87. }
  88. Point<float> position, speed;
  89. Colour colour;
  90. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BallComponent)
  91. };
  92. //==============================================================================
  93. class AnimationDemo : public Component,
  94. private Button::Listener,
  95. private Timer
  96. {
  97. public:
  98. AnimationDemo()
  99. {
  100. setOpaque (true);
  101. setSize (620, 620);
  102. for (int i = 11; --i >= 0;)
  103. {
  104. Button* b = createButton();
  105. componentsToAnimate.add (b);
  106. addAndMakeVisible (b);
  107. b->addListener (this);
  108. }
  109. addAndMakeVisible (ballGenerator);
  110. ballGenerator.centreWithSize (80, 50);
  111. cycleCount = 2;
  112. for (int i = 0; i < componentsToAnimate.size(); ++i)
  113. componentsToAnimate.getUnchecked (i)->setBounds (getLocalBounds().reduced (250, 250));
  114. for (int i = 0; i < componentsToAnimate.size(); ++i)
  115. {
  116. const int newIndex = (i + 3) % componentsToAnimate.size();
  117. const float angle = newIndex * 2.0f * float_Pi / componentsToAnimate.size();
  118. const float radius = getWidth() * 0.35f;
  119. Rectangle<int> r (getWidth() / 2 + (int) (radius * std::sin (angle)) - 50,
  120. getHeight() / 2 + (int) (radius * std::cos (angle)) - 50,
  121. 100, 100);
  122. animator.animateComponent (componentsToAnimate.getUnchecked(i),
  123. r.reduced (10),
  124. 1.0f,
  125. 500 + i * 100,
  126. false,
  127. 0.0,
  128. 0.0);
  129. }
  130. startTimerHz (60);
  131. }
  132. void paint (Graphics& g) override
  133. {
  134. fillStandardDemoBackground (g);
  135. }
  136. private:
  137. OwnedArray<Component> componentsToAnimate;
  138. OwnedArray<BallComponent> balls;
  139. BallGeneratorComponent ballGenerator;
  140. ComponentAnimator animator;
  141. int cycleCount;
  142. Button* createRandomButton()
  143. {
  144. DrawablePath normal, over;
  145. Path star1;
  146. star1.addStar (Point<float>(), 5, 20.0f, 50.0f, 0.2f);
  147. normal.setPath (star1);
  148. normal.setFill (Colours::red);
  149. Path star2;
  150. star2.addStar (Point<float>(), 7, 30.0f, 50.0f, 0.0f);
  151. over.setPath (star2);
  152. over.setFill (Colours::pink);
  153. over.setStrokeFill (Colours::black);
  154. over.setStrokeThickness (5.0f);
  155. Image juceIcon = ImageCache::getFromMemory (BinaryData::juce_icon_png,
  156. BinaryData::juce_icon_pngSize);
  157. DrawableImage down;
  158. down.setImage (juceIcon);
  159. down.setOverlayColour (Colours::black.withAlpha (0.3f));
  160. if (Random::getSystemRandom().nextInt (10) > 2)
  161. {
  162. int type = Random::getSystemRandom().nextInt (3);
  163. DrawableButton* d = new DrawableButton ("Button",
  164. type == 0 ? DrawableButton::ImageOnButtonBackground
  165. : (type == 1 ? DrawableButton::ImageFitted
  166. : DrawableButton::ImageAboveTextLabel));
  167. d->setImages (&normal,
  168. Random::getSystemRandom().nextBool() ? &over : nullptr,
  169. Random::getSystemRandom().nextBool() ? &down : nullptr);
  170. if (Random::getSystemRandom().nextBool())
  171. {
  172. d->setColour (DrawableButton::backgroundColourId, getRandomBrightColour());
  173. d->setColour (DrawableButton::backgroundOnColourId, getRandomBrightColour());
  174. }
  175. d->setClickingTogglesState (Random::getSystemRandom().nextBool());
  176. return d;
  177. }
  178. ImageButton* b = new ImageButton ("ImageButton");
  179. b->setImages (true, true, true,
  180. juceIcon, 0.7f, Colours::transparentBlack,
  181. juceIcon, 1.0f, getRandomDarkColour().withAlpha (0.2f),
  182. juceIcon, 1.0f, getRandomBrightColour().withAlpha (0.8f),
  183. 0.5f);
  184. return b;
  185. }
  186. Button* createButton()
  187. {
  188. Image juceIcon = ImageCache::getFromMemory (BinaryData::juce_icon_png,
  189. BinaryData::juce_icon_pngSize)
  190. .rescaled (128, 128);
  191. ImageButton* b = new ImageButton ("ImageButton");
  192. b->setImages (true, true, true,
  193. juceIcon, 1.0f, Colours::transparentBlack,
  194. juceIcon, 1.0f, Colours::white,
  195. juceIcon, 1.0f, Colours::white,
  196. 0.5f);
  197. return b;
  198. }
  199. void buttonClicked (Button*) override
  200. {
  201. for (int i = 0; i < componentsToAnimate.size(); ++i)
  202. {
  203. const int newIndex = (i + 3 * cycleCount) % componentsToAnimate.size();
  204. const float angle = newIndex * 2.0f * float_Pi / componentsToAnimate.size();
  205. const float radius = getWidth() * 0.35f;
  206. Rectangle<int> r (getWidth() / 2 + (int) (radius * std::sin (angle)) - 50,
  207. getHeight() / 2 + (int) (radius * std::cos (angle)) - 50,
  208. 100, 100);
  209. animator.animateComponent (componentsToAnimate.getUnchecked(i),
  210. r.reduced (10),
  211. 1.0f,
  212. 900 + (int) (300 * std::sin (angle)),
  213. false,
  214. 0.0,
  215. 0.0);
  216. }
  217. ++cycleCount;
  218. }
  219. void timerCallback() override
  220. {
  221. // Go through each of our balls and update their position
  222. for (int i = balls.size(); --i >= 0;)
  223. if (! balls.getUnchecked(i)->step())
  224. balls.remove (i);
  225. // Randomly generate new balls
  226. if (Random::getSystemRandom().nextInt (100) < 4)
  227. {
  228. BallComponent* ball = new BallComponent (ballGenerator.getBounds().getCentre().toFloat());
  229. addAndMakeVisible (ball);
  230. balls.add (ball);
  231. }
  232. }
  233. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimationDemo)
  234. };
  235. // This static object will register this demo type in a global list of demos..
  236. static JuceDemoType<AnimationDemo> demo ("10 Components: Animation");