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.

256 lines
9.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE examples.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. The code included in this file is provided under the terms of the ISC license
  6. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  7. To use, copy, modify, and/or distribute this software for any purpose with or
  8. without fee is hereby granted provided that the above copyright notice and
  9. this permission notice appear in all copies.
  10. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
  11. WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
  12. PURPOSE, ARE DISCLAIMED.
  13. ==============================================================================
  14. */
  15. #pragma once
  16. #include <JuceHeader.h>
  17. #ifndef PIP_DEMO_UTILITIES_INCLUDED
  18. #define PIP_DEMO_UTILITIES_INCLUDED 1
  19. #endif
  20. //==============================================================================
  21. /*
  22. This file contains a bunch of miscellaneous utilities that are
  23. used by the various demos.
  24. */
  25. //==============================================================================
  26. inline Colour getRandomColour (float brightness) noexcept
  27. {
  28. return Colour::fromHSV (Random::getSystemRandom().nextFloat(), 0.5f, brightness, 1.0f);
  29. }
  30. inline Colour getRandomBrightColour() noexcept { return getRandomColour (0.8f); }
  31. inline Colour getRandomDarkColour() noexcept { return getRandomColour (0.3f); }
  32. inline Colour getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour uiColour, Colour fallback = Colour (0xff4d4d4d)) noexcept
  33. {
  34. if (auto* v4 = dynamic_cast<LookAndFeel_V4*> (&LookAndFeel::getDefaultLookAndFeel()))
  35. return v4->getCurrentColourScheme().getUIColour (uiColour);
  36. return fallback;
  37. }
  38. inline File getExamplesDirectory() noexcept
  39. {
  40. #ifdef PIP_JUCE_EXAMPLES_DIRECTORY
  41. MemoryOutputStream mo;
  42. auto success = Base64::convertFromBase64 (mo, JUCE_STRINGIFY (PIP_JUCE_EXAMPLES_DIRECTORY));
  43. ignoreUnused (success);
  44. jassert (success);
  45. return mo.toString();
  46. #elif defined PIP_JUCE_EXAMPLES_DIRECTORY_STRING
  47. return File { PIP_JUCE_EXAMPLES_DIRECTORY_STRING };
  48. #else
  49. auto currentFile = File::getSpecialLocation (File::SpecialLocationType::currentApplicationFile);
  50. auto exampleDir = currentFile.getParentDirectory().getChildFile ("examples");
  51. if (exampleDir.exists())
  52. return exampleDir;
  53. // keep track of the number of parent directories so we don't go on endlessly
  54. for (int numTries = 0; numTries < 15; ++numTries)
  55. {
  56. if (currentFile.getFileName() == "examples")
  57. return currentFile;
  58. const auto sibling = currentFile.getSiblingFile ("examples");
  59. if (sibling.exists())
  60. return sibling;
  61. currentFile = currentFile.getParentDirectory();
  62. }
  63. return currentFile;
  64. #endif
  65. }
  66. inline std::unique_ptr<InputStream> createAssetInputStream (const char* resourcePath)
  67. {
  68. #if JUCE_ANDROID
  69. ZipFile apkZip (File::getSpecialLocation (File::invokedExecutableFile));
  70. return std::unique_ptr<InputStream> (apkZip.createStreamForEntry (apkZip.getIndexOfFileName ("assets/" + String (resourcePath))));
  71. #else
  72. #if JUCE_IOS
  73. auto assetsDir = File::getSpecialLocation (File::currentExecutableFile)
  74. .getParentDirectory().getChildFile ("Assets");
  75. #elif JUCE_MAC
  76. auto assetsDir = File::getSpecialLocation (File::currentExecutableFile)
  77. .getParentDirectory().getParentDirectory().getChildFile ("Resources").getChildFile ("Assets");
  78. if (! assetsDir.exists())
  79. assetsDir = getExamplesDirectory().getChildFile ("Assets");
  80. #else
  81. auto assetsDir = getExamplesDirectory().getChildFile ("Assets");
  82. #endif
  83. auto resourceFile = assetsDir.getChildFile (resourcePath);
  84. jassert (resourceFile.existsAsFile());
  85. return resourceFile.createInputStream();
  86. #endif
  87. }
  88. inline Image getImageFromAssets (const char* assetName)
  89. {
  90. auto hashCode = (String (assetName) + "@juce_demo_assets").hashCode64();
  91. auto img = ImageCache::getFromHashCode (hashCode);
  92. if (img.isNull())
  93. {
  94. std::unique_ptr<InputStream> juceIconStream (createAssetInputStream (assetName));
  95. if (juceIconStream == nullptr)
  96. return {};
  97. img = ImageFileFormat::loadFrom (*juceIconStream);
  98. ImageCache::addImageToCache (img, hashCode);
  99. }
  100. return img;
  101. }
  102. inline String loadEntireAssetIntoString (const char* assetName)
  103. {
  104. std::unique_ptr<InputStream> input (createAssetInputStream (assetName));
  105. if (input == nullptr)
  106. return {};
  107. return input->readString();
  108. }
  109. //==============================================================================
  110. inline Path getJUCELogoPath()
  111. {
  112. return Drawable::parseSVGPath (
  113. "M250,301.3c-37.2,0-67.5-30.3-67.5-67.5s30.3-67.5,67.5-67.5s67.5,30.3,67.5,67.5S287.2,301.3,250,301.3zM250,170.8c-34.7,0-63,28.3-63,63s28.3,63,63,63s63-28.3,63-63S284.7,170.8,250,170.8z"
  114. "M247.8,180.4c0-2.3-1.8-4.1-4.1-4.1c-0.2,0-0.3,0-0.5,0c-10.6,1.2-20.6,5.4-29,12c-1,0.8-1.5,1.8-1.6,2.9c-0.1,1.2,0.4,2.3,1.3,3.2l32.5,32.5c0.5,0.5,1.4,0.1,1.4-0.6V180.4z"
  115. "M303.2,231.6c1.2,0,2.3-0.4,3.1-1.2c0.9-0.9,1.3-2.1,1.1-3.3c-1.2-10.6-5.4-20.6-12-29c-0.8-1-1.9-1.6-3.2-1.6c-1.1,0-2.1,0.5-3,1.3l-32.5,32.5c-0.5,0.5-0.1,1.4,0.6,1.4L303.2,231.6z"
  116. "M287.4,191.3c-0.1-1.1-0.6-2.2-1.6-2.9c-8.4-6.6-18.4-10.8-29-12c-0.2,0-0.3,0-0.5,0c-2.3,0-4.1,1.9-4.1,4.1v46c0,0.7,0.9,1.1,1.4,0.6l32.5-32.5C287,193.6,287.5,192.5,287.4,191.3z"
  117. "M252.2,287.2c0,2.3,1.8,4.1,4.1,4.1c0.2,0,0.3,0,0.5,0c10.6-1.2,20.6-5.4,29-12c1-0.8,1.5-1.8,1.6-2.9c0.1-1.2-0.4-2.3-1.3-3.2l-32.5-32.5c-0.5-0.5-1.4-0.1-1.4,0.6V287.2z"
  118. "M292.3,271.2L292.3,271.2c1.2,0,2.4-0.6,3.2-1.6c6.6-8.4,10.8-18.4,12-29c0.1-1.2-0.3-2.4-1.1-3.3c-0.8-0.8-1.9-1.2-3.1-1.2l-45.9,0c-0.7,0-1.1,0.9-0.6,1.4l32.5,32.5C290.2,270.8,291.2,271.2,292.3,271.2z"
  119. "M207.7,196.4c-1.2,0-2.4,0.6-3.2,1.6c-6.6,8.4-10.8,18.4-12,29c-0.1,1.2,0.3,2.4,1.1,3.3c0.8,0.8,1.9,1.2,3.1,1.2l45.9,0c0.7,0,1.1-0.9,0.6-1.4l-32.5-32.5C209.8,196.8,208.8,196.4,207.7,196.4z"
  120. "M242.6,236.1l-45.9,0c-1.2,0-2.3,0.4-3.1,1.2c-0.9,0.9-1.3,2.1-1.1,3.3c1.2,10.6,5.4,20.6,12,29c0.8,1,1.9,1.6,3.2,1.6c1.1,0,2.1-0.5,3-1.3c0,0,0,0,0,0l32.5-32.5C243.7,236.9,243.4,236.1,242.6,236.1z"
  121. "M213.8,273.1L213.8,273.1c-0.9,0.9-1.3,2-1.3,3.2c0.1,1.1,0.6,2.2,1.6,2.9c8.4,6.6,18.4,10.8,29,12c0.2,0,0.3,0,0.5,0h0c1.2,0,2.3-0.5,3.1-1.4c0.7-0.8,1-1.8,1-2.9v-45.9c0-0.7-0.9-1.1-1.4-0.6l-13.9,13.9L213.8,273.1z"
  122. "M197.2,353c-4.1,0-7.4-1.5-10.4-5.4l4-3.5c2,2.6,3.9,3.6,6.4,3.6c4.4,0,7.4-3.3,7.4-8.3v-24.7h5.6v24.7C210.2,347.5,204.8,353,197.2,353z"
  123. "M232.4,353c-8.1,0-15-6-15-15.8v-22.5h5.6v22.2c0,6.6,3.9,10.8,9.5,10.8c5.6,0,9.5-4.3,9.5-10.8v-22.2h5.6v22.5C247.5,347,240.5,353,232.4,353z"
  124. "M272,353c-10.8,0-19.5-8.6-19.5-19.3c0-10.8,8.8-19.3,19.5-19.3c4.8,0,9,1.6,12.3,4.4l-3.3,4.1c-3.4-2.4-5.7-3.2-8.9-3.2c-7.7,0-13.8,6.2-13.8,14.1c0,7.9,6.1,14.1,13.8,14.1c3.1,0,5.6-1,8.8-3.2l3.3,4.1C280.1,351.9,276.4,353,272,353z"
  125. "M290.4,352.5v-37.8h22.7v5H296v11.2h16.5v5H296v11.6h17.2v5H290.4z");
  126. }
  127. //==============================================================================
  128. #if JUCE_MODULE_AVAILABLE_juce_gui_extra
  129. inline CodeEditorComponent::ColourScheme getDarkCodeEditorColourScheme()
  130. {
  131. struct Type
  132. {
  133. const char* name;
  134. juce::uint32 colour;
  135. };
  136. const Type types[] =
  137. {
  138. { "Error", 0xffe60000 },
  139. { "Comment", 0xff72d20c },
  140. { "Keyword", 0xffee6f6f },
  141. { "Operator", 0xffc4eb19 },
  142. { "Identifier", 0xffcfcfcf },
  143. { "Integer", 0xff42c8c4 },
  144. { "Float", 0xff885500 },
  145. { "String", 0xffbc45dd },
  146. { "Bracket", 0xff058202 },
  147. { "Punctuation", 0xffcfbeff },
  148. { "Preprocessor Text", 0xfff8f631 }
  149. };
  150. CodeEditorComponent::ColourScheme cs;
  151. for (auto& t : types)
  152. cs.set (t.name, Colour (t.colour));
  153. return cs;
  154. }
  155. inline CodeEditorComponent::ColourScheme getLightCodeEditorColourScheme()
  156. {
  157. struct Type
  158. {
  159. const char* name;
  160. juce::uint32 colour;
  161. };
  162. const Type types[] =
  163. {
  164. { "Error", 0xffcc0000 },
  165. { "Comment", 0xff00aa00 },
  166. { "Keyword", 0xff0000cc },
  167. { "Operator", 0xff225500 },
  168. { "Identifier", 0xff000000 },
  169. { "Integer", 0xff880000 },
  170. { "Float", 0xff885500 },
  171. { "String", 0xff990099 },
  172. { "Bracket", 0xff000055 },
  173. { "Punctuation", 0xff004400 },
  174. { "Preprocessor Text", 0xff660000 }
  175. };
  176. CodeEditorComponent::ColourScheme cs;
  177. for (auto& t : types)
  178. cs.set (t.name, Colour (t.colour));
  179. return cs;
  180. }
  181. #endif
  182. //==============================================================================
  183. // This is basically a sawtooth wave generator - maps a value that bounces between
  184. // 0.0 and 1.0 at a random speed
  185. struct BouncingNumber
  186. {
  187. BouncingNumber()
  188. : speed (0.0004 + 0.0007 * Random::getSystemRandom().nextDouble()),
  189. phase (Random::getSystemRandom().nextDouble())
  190. {
  191. }
  192. float getValue() const
  193. {
  194. double v = fmod (phase + speed * Time::getMillisecondCounterHiRes(), 2.0);
  195. return (float) (v >= 1.0 ? (2.0 - v) : v);
  196. }
  197. protected:
  198. double speed, phase;
  199. };
  200. struct SlowerBouncingNumber : public BouncingNumber
  201. {
  202. SlowerBouncingNumber()
  203. {
  204. speed *= 0.3;
  205. }
  206. };