main.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. 
  2. // TODO:
  3. // * A catalogue of SDK examples with images and descriptions loaded automatically from their folder.
  4. // Offer one-click build and execution of SDK examples on multiple platforms, while explaining how the building works.
  5. // How can the file library execute other applications and scripts in a portable way when scripts need to select a terminal application to execute them?
  6. // Maybe call the builder as a static library and have it call the compiler directly in a simulated terminal window embedded into the wizard, instead of using unreliable scripts?
  7. // * Let the user browse a file system and select a location for a new or existing project.
  8. #include "../../DFPSR/includeFramework.h"
  9. #include "sound.h"
  10. using namespace dsr;
  11. // Global
  12. bool running = true;
  13. Window window;
  14. String interfaceContent =
  15. UR"QUOTE(
  16. Begin : Panel
  17. Name = "mainPanel"
  18. Solid = 0
  19. Begin : Panel
  20. Name = "upperPanel"
  21. Bottom = 50
  22. Solid = 1
  23. Color = 120,120,100
  24. End
  25. Begin : Panel
  26. Name = "lowerPanel"
  27. Solid = 1
  28. Top = 50
  29. Color = 120,120,100
  30. Begin : ListBox
  31. Name = "projectList"
  32. Color = 180,180,140
  33. Left = 90%-100
  34. Right = 100%-5
  35. Top = 5
  36. Bottom = 100%-50
  37. End
  38. Begin : Button
  39. Name = "buildButton"
  40. Text = "Build and run"
  41. Color = 160,150,150
  42. Left = 90%-100
  43. Right = 100%-5
  44. Top = 100%-45
  45. Bottom = 100%-5
  46. End
  47. Begin : Label
  48. Name = "descriptionLabel"
  49. Text = "DFPSR wizard application"
  50. Left = 5
  51. Right = 90%-105
  52. Top = 5
  53. Bottom = 100%-5
  54. End
  55. End
  56. End
  57. )QUOTE";
  58. // Visual components
  59. Component projectList;
  60. Component buildButton;
  61. Component descriptionLabel;
  62. // Media
  63. int boomSound;
  64. struct Project {
  65. String buildScript; // To execute
  66. String projectFolderName; // To display
  67. Project(const ReadableString &buildScript, const ReadableString &projectFolderName)
  68. : buildScript(buildScript), projectFolderName(projectFolderName) {}
  69. };
  70. List<Project> projects;
  71. static ReadableString findParent(const ReadableString& startPath, const ReadableString& parentName) {
  72. int64_t pathEndIndex = -1; // Last character of path leading to Source.
  73. file_getPathEntries(startPath, [&pathEndIndex, &parentName](ReadableString entry, int64_t firstIndex, int64_t lastIndex) {
  74. if (string_match(entry, parentName)) {
  75. pathEndIndex = lastIndex;
  76. }
  77. });
  78. if (pathEndIndex == -1) {
  79. throwError(U"Could not find the Source folder with SDK examples.");
  80. return startPath;
  81. } else {
  82. return string_until(startPath, pathEndIndex);
  83. }
  84. }
  85. static void findProjects(const ReadableString& folderPath) {
  86. file_getFolderContent(folderPath, [](const ReadableString& entryPath, const ReadableString& entryName, EntryType entryType) {
  87. if (entryType == EntryType::Folder) {
  88. findProjects(entryPath);
  89. } else if (entryType == EntryType::File) {
  90. ReadableString extension = string_upperCase(file_getExtension(entryName));
  91. // If we find a project within folderPath...
  92. if (string_match(extension, U"DSRPROJ")) {
  93. String projectFolderName = file_getPathlessName(file_getRelativeParentFolder(entryPath));
  94. // ...and the folder is not namned wizard...
  95. if (!string_match(projectFolderName, U"wizard")) {
  96. // ...then add it to the list of projects.
  97. projects.pushConstruct(entryPath, projectFolderName);
  98. }
  99. }
  100. }
  101. });
  102. }
  103. static void populateInterface(const ReadableString& folderPath) {
  104. findProjects(folderPath);
  105. for (int p = 0; p < projects.length(); p++) {
  106. component_call(projectList, U"PushElement", projects[p].projectFolderName);
  107. }
  108. component_setProperty_integer(projectList, U"SelectedIndex", 0, false);
  109. }
  110. DSR_MAIN_CALLER(dsrMain)
  111. void dsrMain(List<String> args) {
  112. // Start sound
  113. sound_initialize();
  114. boomSound = loadSoundFromFile(file_combinePaths(file_getApplicationFolder(), U"Boom.wav"));
  115. // Create a window
  116. window = window_create(U"DFPSR wizard application", 800, 600);
  117. window_loadInterfaceFromString(window, interfaceContent);
  118. // Find components
  119. projectList = window_findComponentByName(window, U"projectList");
  120. buildButton = window_findComponentByName(window, U"buildButton");
  121. descriptionLabel = window_findComponentByName(window, U"descriptionLabel");
  122. // Find projects to showcase
  123. // On systems that don't allow getting the application's folder, the program must be started somewhere within the Source folder.
  124. String applicationFolder = file_getApplicationFolder();
  125. String sourceFolder = findParent(applicationFolder, U"Source");
  126. populateInterface(sourceFolder);
  127. // Bind methods to events
  128. window_setKeyboardEvent(window, [](const KeyboardEvent& event) {
  129. DsrKey key = event.dsrKey;
  130. if (event.keyboardEventType == KeyboardEventType::KeyDown) {
  131. if (key == DsrKey_Escape) {
  132. running = false;
  133. }
  134. }
  135. });
  136. component_setPressedEvent(buildButton, []() {
  137. // TODO: Implement building and running of the selected project.
  138. component_setProperty_string(descriptionLabel, U"Text", U"Compiling and running projects from the wizard application is not yet implemented.");
  139. });
  140. component_setSelectEvent(projectList, [](int64_t index) {
  141. // TODO: Load description from a text file with a specific name in the project's folder.
  142. playSound(boomSound, false, 0.5, 0.5, 0.5);
  143. component_setProperty_string(descriptionLabel, U"Text", string_combine(U"Project at ", projects[index].buildScript));
  144. });
  145. window_setCloseEvent(window, []() {
  146. running = false;
  147. });
  148. // Execute
  149. playSound(boomSound, false, 1.0, 1.0, 0.25);
  150. while(running) {
  151. // Wait for actions so that we don't render until an action has been recieved
  152. // This will save battery on laptops for applications that don't require animation
  153. while (!window_executeEvents(window)) {
  154. time_sleepSeconds(0.01);
  155. }
  156. // Fill the background
  157. AlignedImageRgbaU8 canvas = window_getCanvas(window);
  158. image_fill(canvas, ColorRgbaI32(64, 64, 64, 255));
  159. // Draw interface
  160. window_drawComponents(window);
  161. // Show the final image
  162. window_showCanvas(window);
  163. }
  164. // Close sound
  165. sound_terminate();
  166. }