animation_curve.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*******************************************************************************************
  2. *
  3. * Animation curves - An example demo for animation curves
  4. *
  5. * DEPENDENCIES:
  6. * raylib 4.0 - Windowing/input management and drawing.
  7. * raygui 3.0 - Immediate-mode GUI controls.
  8. *
  9. * COMPILATION (Windows - MinGW):
  10. * gcc -o $(NAME_PART).exe $(FILE_NAME) -I../../src -lraylib -lopengl32 -lgdi32 -std=c99
  11. *
  12. * LICENSE: zlib/libpng
  13. *
  14. * Copyright (c) 2023 Pierre Jaffuer (@smallcluster)
  15. *
  16. **********************************************************************************************/
  17. #include "raylib.h"
  18. #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24
  19. #define RAYGUI_IMPLEMENTATION
  20. #include "../../src/raygui.h"
  21. // raygui embedded styles
  22. #include "../styles/style_cyber.h" // raygui style: cyber
  23. #include "../styles/style_jungle.h" // raygui style: jungle
  24. #include "../styles/style_lavanda.h" // raygui style: lavanda
  25. #include "../styles/style_dark.h" // raygui style: dark
  26. #include "../styles/style_bluish.h" // raygui style: bluish
  27. #include "../styles/style_terminal.h" // raygui style: terminal
  28. #undef RAYGUI_IMPLEMENTATION // Avoid including raygui implementation again
  29. #define GUI_CURVE_EDITOR_IMPLEMENTATION
  30. #include "gui_curve_editor.h"
  31. //------------------------------------------------------------------------------------
  32. // Helper function
  33. //------------------------------------------------------------------------------------
  34. void LoadCurveDefaults(GuiCurveEditorState curves[]);
  35. //------------------------------------------------------------------------------------
  36. // Program main entry point
  37. //------------------------------------------------------------------------------------
  38. int main()
  39. {
  40. // Initialization
  41. //---------------------------------------------------------------------------------------
  42. const int screenWidth = 800;
  43. const int screenHeight = 540;
  44. InitWindow(screenWidth, screenHeight, "raygui - animation curves");
  45. SetTargetFPS(60);
  46. // Gui style
  47. GuiLoadStyleDefault();
  48. int visualStyleActive = 0;
  49. int prevVisualStyleActive = 0;
  50. float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
  51. const float margin = 8;
  52. // Gui states
  53. Vector2 scrollOffset = (Vector2){ 0, 0 };
  54. Rectangle contentRect = (Rectangle){ 0, 0, 0, 0 };
  55. bool moveSlider = false;
  56. bool sectionActive[5] = { 0 };
  57. sectionActive[0] = true;
  58. const char *sectionNames[5] = { "X Position", "Y Position", "Width", "Height", "Rotation" };
  59. bool editValueBox[5][4] = { 0 };
  60. char *valTextBox[5][4][20] = { 0 };
  61. bool playAnimation = true;
  62. bool showHelp = true;
  63. Rectangle settingsRect = (Rectangle){ screenWidth - screenWidth/3, 0, screenWidth/3, screenHeight };
  64. // Animation curves
  65. // 0 -> Ball X position
  66. // 1 -> Ball Y position
  67. // 2 -> Ball Width
  68. // 3 -> Ball Height
  69. // 4 -> Ball rotation
  70. GuiCurveEditorState curves[5] = { 0 };
  71. LoadCurveDefaults(curves);
  72. // Animation time
  73. float time = 0.0f;
  74. float animationTime = 4.0f;
  75. //SetTargetFPS(60);
  76. //--------------------------------------------------------------------------------------
  77. // Main game loop
  78. while (!WindowShouldClose()) // Detect window close button or ESC key
  79. {
  80. // Update
  81. //----------------------------------------------------------------------------------
  82. if (playAnimation) time += GetFrameTime();
  83. // Reset timer
  84. if (time > animationTime) time = 0;
  85. // Ball animation
  86. const float t = time/animationTime;
  87. Vector2 ballPos = (Vector2){ GuiCurveEval(&curves[0], t), GuiCurveEval(&curves[1], t) };
  88. Vector2 ballSize = (Vector2){ GuiCurveEval(&curves[2], t), GuiCurveEval(&curves[3], t) };
  89. float ballRotation = GuiCurveEval(&curves[4], t);
  90. // Update style
  91. if (visualStyleActive != prevVisualStyleActive)
  92. {
  93. switch (visualStyleActive)
  94. {
  95. case 0: GuiLoadStyleDefault(); break;
  96. case 1: GuiLoadStyleJungle(); break;
  97. case 2: GuiLoadStyleLavanda(); break;
  98. case 3: GuiLoadStyleDark(); break;
  99. case 4: GuiLoadStyleBluish(); break;
  100. case 5: GuiLoadStyleCyber(); break;
  101. case 6: GuiLoadStyleTerminal(); break;
  102. default: break;
  103. }
  104. fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
  105. prevVisualStyleActive = visualStyleActive;
  106. }
  107. // Update settings panel rect
  108. Rectangle sliderRect = (Rectangle){ settingsRect.x - 4, settingsRect.y, 4, settingsRect.height };
  109. if (CheckCollisionPointRec(GetMousePosition(), sliderRect) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) moveSlider = true;
  110. if (IsMouseButtonUp(MOUSE_BUTTON_LEFT)) moveSlider = false;
  111. if (moveSlider)
  112. {
  113. settingsRect.x = GetMouseX();
  114. // Minimum-Maximum size
  115. if (settingsRect.x > (screenWidth - 4)) settingsRect.x = screenWidth - 4;
  116. else if (settingsRect.x < 4) settingsRect.x = 4;
  117. settingsRect.width = screenWidth - settingsRect.x;
  118. }
  119. //----------------------------------------------------------------------------------
  120. // Draw
  121. //----------------------------------------------------------------------------------
  122. BeginDrawing();
  123. ClearBackground(GetColor( GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
  124. // Scene
  125. //----------------------------------------------------------------------------------
  126. DrawRectangle(curves[0].start, curves[1].end, curves[0].end-curves[0].start, curves[1].start-curves[1].end, BLUE); // Sky
  127. DrawRectangle(curves[0].start, curves[1].start, curves[0].end-curves[0].start, 32, DARKGREEN); // Ground
  128. BeginScissorMode(curves[0].start, curves[1].end, curves[0].end-curves[0].start, curves[1].start-curves[1].end+32);
  129. DrawRectanglePro((Rectangle){ballPos.x, ballPos.y, ballSize.x, ballSize.y}, (Vector2){ballSize.x/2.f,ballSize.y/2.f}, ballRotation, PINK); // Ball
  130. DrawLine(ballPos.x, ballPos.y, ballPos.x + cosf(ballRotation*DEG2RAD)*ballSize.x, ballPos.y +sinf(ballRotation*DEG2RAD)*ballSize.y, RED);
  131. DrawLine(ballPos.x, ballPos.y, ballPos.x + cosf((ballRotation+90)*DEG2RAD)*ballSize.x, ballPos.y +sinf((ballRotation+90)*DEG2RAD)*ballSize.y, GREEN);
  132. EndScissorMode();
  133. // Bounds
  134. DrawRectangleLines(curves[0].start, curves[1].end, curves[0].end-curves[0].start, curves[1].start-curves[1].end+32, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)));
  135. //----------------------------------------------------------------------------------
  136. // GUI
  137. //----------------------------------------------------------------------------------
  138. if (showHelp)
  139. {
  140. if (GuiWindowBox((Rectangle) {margin, margin, settingsRect.x-2*margin, curves[1].end-2*margin}, "help")) showHelp = false;
  141. Rectangle helpTextRect = (Rectangle) { 2*margin, 2*margin+RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, settingsRect.x - 4 - 4*margin, 0 };
  142. GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "Curve widget controls:");
  143. helpTextRect.height += fontSize+margin;
  144. GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "- Left click to move/add point or move tangents");
  145. helpTextRect.height += fontSize+margin/2;
  146. GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "- While moving a tangent, hold SHIFT to disable tangent symetry");
  147. helpTextRect.height += fontSize+margin/2;
  148. GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "- Right click to remove a point");
  149. helpTextRect.height += fontSize+margin/2;
  150. DrawRectangleGradientV(margin, margin+curves[1].end - 2*margin, settingsRect.x - 2*margin, 12, (Color){ 0,0,0,100 }, BLANK);
  151. }
  152. // Settings panel
  153. GuiScrollPanel(settingsRect, "Settings", contentRect, &scrollOffset, NULL);
  154. BeginScissorMode(settingsRect.x, settingsRect.y+RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, settingsRect.width, settingsRect.height);
  155. // Rebuild the content Rect
  156. contentRect = (Rectangle){ settingsRect.x + margin, RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT+margin, settingsRect.width - 2*margin - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), 0 };
  157. // Help button
  158. if (GuiButton((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width, 1.5*fontSize }, GuiIconText(showHelp? ICON_EYE_ON : ICON_EYE_OFF, "Curve controls help"))) showHelp = !showHelp;
  159. contentRect.height += 1.5*fontSize + margin;
  160. // Animation Time slider
  161. GuiSlider((Rectangle){ contentRect.x, contentRect.y+contentRect.height+scrollOffset.y, contentRect.width/2, fontSize }, NULL, TextFormat("Animation Time: %.2fs", animationTime), &animationTime, 1, 8);
  162. contentRect.height += fontSize + margin;
  163. // Load default curves
  164. if (GuiButton((Rectangle){ contentRect.x, contentRect.y+contentRect.height+scrollOffset.y, contentRect.width, 1.5*fontSize }, "Load default"))
  165. {
  166. LoadCurveDefaults(curves);
  167. animationTime = 4.0f;
  168. time = 0.0f;
  169. }
  170. contentRect.height += 1.5f*fontSize + margin;
  171. // Styles
  172. GuiLabel((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width, fontSize }, "Style:");
  173. contentRect.height += fontSize;
  174. GuiComboBox((Rectangle){contentRect.x, contentRect.y+contentRect.height+scrollOffset.y, contentRect.width, 1.5*fontSize }, "default;Jungle;Lavanda;Dark;Bluish;Cyber;Terminal", &visualStyleActive);
  175. contentRect.height += 1.5f*fontSize + margin;
  176. // Draw curves with their controls
  177. //----------------------------------------------------------------------------------
  178. for (int i = 0; i < 5; i++)
  179. {
  180. // Collapsing section
  181. Rectangle headerRect = (Rectangle){ contentRect.x, contentRect.y + contentRect.height+scrollOffset.y, contentRect.width, 1.5f*fontSize };
  182. GuiStatusBar(headerRect, NULL);
  183. if (GuiLabelButton(headerRect, GuiIconText(sectionActive[i] ? ICON_ARROW_DOWN_FILL : ICON_ARROW_RIGHT_FILL, sectionNames[i]))) sectionActive[i] = !sectionActive[i];
  184. contentRect.height += 1.5f*fontSize + margin;
  185. // Skip this section
  186. if (!sectionActive[i]) continue;
  187. // Draw curve control
  188. Rectangle curveRect = (Rectangle){ contentRect.x, contentRect.y+contentRect.height + scrollOffset.y, contentRect.width, fontSize*12 };
  189. EndScissorMode(); // Stop clipping from setting rect
  190. // Curves can leaks from control boundary... scissor it !
  191. BeginScissorMode(curveRect.x, curveRect.y, curveRect.width, curveRect.height);
  192. GuiCurveEditor(&curves[i], curveRect);
  193. EndScissorMode();
  194. // Resume clipping from setting rect
  195. BeginScissorMode(settingsRect.x, settingsRect.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, settingsRect.width, settingsRect.height);
  196. contentRect.height += fontSize*12 + margin;
  197. // Draw selected point controls
  198. GuiCurveEditorPoint *p = &(curves[i].points[curves[i].selectedIndex]);
  199. GuiCheckBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, 1.5f*fontSize, 1.5f*fontSize }, "Left Linear", &p->leftLinear);
  200. GuiCheckBox((Rectangle){ contentRect.x+contentRect.width/2, contentRect.y + contentRect.height + scrollOffset.y, 1.5f*fontSize, 1.5f*fontSize }, "Right Linear", &p->rightLinear);
  201. contentRect.height += 1.5f*fontSize + margin;
  202. // Positions
  203. GuiLabel((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width, fontSize }, "Position");
  204. contentRect.height += fontSize;
  205. if (!editValueBox[i][0]) gcvt(p->position.x, 6, (char *)valTextBox[i][0]); // Transform x position to string
  206. if (!editValueBox[i][1]) gcvt(curves[i].start + (curves[i].end-curves[i].start)*p->position.y, 6, (char *)valTextBox[i][1]); // Transform y position to string
  207. // X pos
  208. if (GuiTextBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2-margin, 1.5f*fontSize }, (char *)valTextBox[i][0], 20, editValueBox[i][0]))
  209. {
  210. editValueBox[i][0] = !editValueBox[i][0];
  211. // Input ended
  212. if (!editValueBox[i][0])
  213. {
  214. // Try to convert text to float and assign it to the point
  215. char *endPtr = NULL;
  216. double value = strtod((char *)valTextBox[i][0], &endPtr);
  217. if (endPtr != (char *)valTextBox[i][0]) p->position.x = (value < 0)? 0 : (value > 1)? 1 : value;
  218. }
  219. }
  220. // Y pos
  221. if (GuiTextBox((Rectangle){ contentRect.x + contentRect.width/2, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2.0f, 1.5f*fontSize }, (char *)valTextBox[i][1], 20, editValueBox[i][1]))
  222. {
  223. editValueBox[i][1] = !editValueBox[i][1];
  224. // Input ended
  225. if (!editValueBox[i][1])
  226. {
  227. // Try to convert text to float and assign it to the point
  228. char *endPtr = NULL;
  229. double value = strtod((char *)valTextBox[i][1], &endPtr);
  230. if (endPtr != (char *)valTextBox[i][1])
  231. {
  232. float normalizedVal = (value - curves[i].start)/(curves[i].end - curves[i].start);
  233. p->position.y = (normalizedVal < 0)? 0 : (normalizedVal > 1)? 1 : normalizedVal;
  234. }
  235. }
  236. }
  237. contentRect.height += 1.5f*fontSize + margin;
  238. // Tangents
  239. GuiLabel((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width, fontSize }, "Tangents");
  240. contentRect.height += fontSize;
  241. if (!editValueBox[i][2]) gcvt(p->tangents.x, 6, (char *)valTextBox[i][2]); // Transform left tangent to string
  242. if (!editValueBox[i][3]) gcvt(p->tangents.y, 6, (char *)valTextBox[i][3]); // Transform right tangent to string
  243. // Left tan
  244. if (GuiTextBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2 - margin, 1.5f*fontSize }, (char *)valTextBox[i][2], 20, editValueBox[i][2]))
  245. {
  246. editValueBox[i][2] = !editValueBox[i][2];
  247. // Input ended
  248. if (!editValueBox[i][2])
  249. {
  250. // Try to convert text to float and assign it to the point
  251. char *endPtr = NULL;
  252. double value = strtod((char *)valTextBox[i][2], &endPtr);
  253. if (endPtr != (char *)valTextBox[i][2]) p->tangents.x = value;
  254. }
  255. }
  256. // Right tan
  257. if (GuiTextBox((Rectangle){ contentRect.x + contentRect.width/2.0f, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2.0f, 1.5f*fontSize }, (char *)valTextBox[i][3], 20, editValueBox[i][3]))
  258. {
  259. editValueBox[i][3] = !editValueBox[i][3];
  260. // Input ended
  261. if (!editValueBox[i][3])
  262. {
  263. // Try to convert text to float and assign it to the point
  264. char *endPtr = NULL;
  265. double value = strtod((char *)valTextBox[i][3], &endPtr);
  266. if (endPtr != (char *)valTextBox[i][3]) p->tangents.y = value;
  267. }
  268. }
  269. contentRect.height += 1.5*fontSize + margin;
  270. }
  271. contentRect.height += margin;
  272. EndScissorMode();
  273. // Settings panel shadow
  274. DrawRectangleGradientH(settingsRect.x - 12, 0, 12, settingsRect.height, BLANK, (Color){ 0, 0, 0, 100 });
  275. // Slider
  276. if (moveSlider) DrawRectangle(sliderRect.x, sliderRect.y, sliderRect.width, sliderRect.height, GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED)));
  277. else if(CheckCollisionPointRec(GetMousePosition(), sliderRect)) DrawRectangle(sliderRect.x, sliderRect.y, sliderRect.width, sliderRect.height, GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED)));
  278. // Draw Time controls
  279. //----------------------------------------------------------------------------------
  280. Rectangle timeLineRect = (Rectangle){ 0, screenHeight-4*fontSize, settingsRect.x, 4*fontSize };
  281. GuiPanel((Rectangle){ timeLineRect.x, timeLineRect.y, timeLineRect.width, 2*fontSize }, NULL);
  282. GuiLabel((Rectangle){ timeLineRect.x, timeLineRect.y, timeLineRect.width, 2*fontSize }, TextFormat("Normalized Time: %.3f", time/animationTime));
  283. if (GuiButton((Rectangle){ timeLineRect.x+timeLineRect.width/2 - 2*fontSize - margin/4, timeLineRect.y, 2*fontSize, 2*fontSize }, GuiIconText((playAnimation? ICON_PLAYER_PAUSE : ICON_PLAYER_PLAY), ""))) playAnimation = !playAnimation;
  284. if (GuiButton((Rectangle){ timeLineRect.x+timeLineRect.width/2 + margin/4, timeLineRect.y, 2*fontSize, 2*fontSize }, GuiIconText(ICON_PLAYER_STOP, "")))
  285. {
  286. playAnimation = false;
  287. time = 0;
  288. }
  289. float animTime = time/animationTime;
  290. GuiSlider((Rectangle){timeLineRect.x, timeLineRect.y + 2*fontSize, timeLineRect.width, timeLineRect.height - 2*fontSize }, NULL, NULL, &animTime, 0, 1);
  291. time = animationTime*animTime;
  292. // Time panel shadow
  293. DrawRectangleGradientV(timeLineRect.x, timeLineRect.y - 12, timeLineRect.width, 12, BLANK, (Color){ 0, 0, 0, 100 });
  294. EndDrawing();
  295. //----------------------------------------------------------------------------------
  296. }
  297. CloseWindow(); // Close window and OpenGL context
  298. //--------------------------------------------------------------------------------------
  299. return 0;
  300. }
  301. void LoadCurveDefaults(GuiCurveEditorState curves[])
  302. {
  303. // X pos
  304. curves[0].start = 28;
  305. curves[0].end = 506;
  306. curves[0].numPoints = 4;
  307. curves[0].selectedIndex = 0;
  308. curves[0].editLeftTangent = false;
  309. curves[0].editRightTangent = false;
  310. curves[0].points[0].position =(Vector2) {0.000000, 0.000000}; curves[0].points[0].tangents = (Vector2) {0.000000, 1.515101}; curves[0].points[0].leftLinear = 1;curves[0].points[0].rightLinear = 1;
  311. curves[0].points[1].position =(Vector2) {0.422414, 0.640000}; curves[0].points[1].tangents = (Vector2) {-2.824348, -4.494999};curves[0].points[1].leftLinear = 0;curves[0].points[1].rightLinear = 0;
  312. curves[0].points[2].position =(Vector2) {0.732759, 0.210000}; curves[0].points[2].tangents = (Vector2) {0.000000, 2.956133}; curves[0].points[2].leftLinear = 0;curves[0].points[2].rightLinear = 1;
  313. curves[0].points[3].position =(Vector2) {1.000000, 1.000000}; curves[0].points[3].tangents = (Vector2) {2.956133, 0.000000}; curves[0].points[3].leftLinear = 1;curves[0].points[3].rightLinear = 1;
  314. // Y pos
  315. curves[1].start = 405;
  316. curves[1].end = 135;
  317. curves[1].numPoints = 7;
  318. curves[1].selectedIndex = 0;
  319. curves[1].editLeftTangent = false;
  320. curves[1].editRightTangent = false;
  321. curves[1].points[0].position = (Vector2) {0.000000, 1.000000};curves[1].points[0].tangents = (Vector2) { 0.000000 , 0.000000};curves[1].points[0].leftLinear = 0;curves[1].points[0].rightLinear = 0;
  322. curves[1].points[1].position = (Vector2) {0.140000, 0.000000};curves[1].points[1].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[1].leftLinear = 0;curves[1].points[1].rightLinear = 0;
  323. curves[1].points[2].position = (Vector2) {0.450000, 0.000000};curves[1].points[2].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[2].leftLinear = 0;curves[1].points[2].rightLinear = 0;
  324. curves[1].points[3].position = (Vector2) {0.670000, 0.000000};curves[1].points[3].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[3].leftLinear = 0;curves[1].points[3].rightLinear = 0;
  325. curves[1].points[4].position = (Vector2) {0.830000, 0.000000};curves[1].points[4].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[4].leftLinear = 0;curves[1].points[4].rightLinear = 0;
  326. curves[1].points[5].position = (Vector2) {0.940000, 0.000000};curves[1].points[5].tangents = (Vector2) {-10.000000 ,10.000000};curves[1].points[5].leftLinear = 0;curves[1].points[5].rightLinear = 0;
  327. curves[1].points[6].position = (Vector2) {1.000000, 0.000000};curves[1].points[6].tangents = (Vector2) {-10.000000 , 0.000000};curves[1].points[6].leftLinear = 0;curves[1].points[6].rightLinear = 0;
  328. // X size
  329. curves[2].start = 1;
  330. curves[2].end = 64;
  331. curves[2].numPoints = 16;
  332. curves[2].selectedIndex = 0;
  333. curves[2].editLeftTangent = false;
  334. curves[2].editRightTangent = false;
  335. curves[2].points[0].position = (Vector2) {0.000000, 0.492063}; curves[2].points[0].tangents = (Vector2) {0,0}; curves[2].points[0].leftLinear = 0; curves[2].points[0].rightLinear = 0;
  336. curves[2].points[1].position = (Vector2) {0.130000, 0.492063}; curves[2].points[1].tangents = (Vector2) {0,0}; curves[2].points[1].leftLinear = 0; curves[2].points[1].rightLinear = 0;
  337. curves[2].points[2].position = (Vector2) {0.140000, 0.746032}; curves[2].points[2].tangents = (Vector2) {0,0}; curves[2].points[2].leftLinear = 0; curves[2].points[2].rightLinear = 0;
  338. curves[2].points[3].position = (Vector2) {0.150000, 0.492063}; curves[2].points[3].tangents = (Vector2) {0,0}; curves[2].points[3].leftLinear = 0; curves[2].points[3].rightLinear = 0;
  339. curves[2].points[4].position = (Vector2) {0.440000, 0.490000}; curves[2].points[4].tangents = (Vector2) {0,0}; curves[2].points[4].leftLinear = 0; curves[2].points[4].rightLinear = 0;
  340. curves[2].points[5].position = (Vector2) {0.450000, 0.682540}; curves[2].points[5].tangents = (Vector2) {0,0}; curves[2].points[5].leftLinear = 0; curves[2].points[5].rightLinear = 0;
  341. curves[2].points[6].position = (Vector2) {0.460000, 0.480000}; curves[2].points[6].tangents = (Vector2) {0,0}; curves[2].points[6].leftLinear = 0; curves[2].points[6].rightLinear = 0;
  342. curves[2].points[7].position = (Vector2) {0.660000, 0.492063}; curves[2].points[7].tangents = (Vector2) {0,0}; curves[2].points[7].leftLinear = 0; curves[2].points[7].rightLinear = 0;
  343. curves[2].points[8].position = (Vector2) {0.670000, 0.619048}; curves[2].points[8].tangents = (Vector2) {0,0}; curves[2].points[8].leftLinear = 0; curves[2].points[8].rightLinear = 0;
  344. curves[2].points[9].position = (Vector2) {0.680000, 0.492063}; curves[2].points[9].tangents = (Vector2) {0,0}; curves[2].points[9].leftLinear = 0; curves[2].points[9].rightLinear = 0;
  345. curves[2].points[10].position = (Vector2) {0.820000, 0.492063}; curves[2].points[10].tangents = (Vector2) {0,0}; curves[2].points[10].leftLinear = 0; curves[2].points[10].rightLinear = 0;
  346. curves[2].points[11].position = (Vector2) {0.830000, 0.619048}; curves[2].points[11].tangents = (Vector2) {0,0}; curves[2].points[11].leftLinear = 0; curves[2].points[11].rightLinear = 0;
  347. curves[2].points[12].position = (Vector2) {0.840000, 0.492063}; curves[2].points[12].tangents = (Vector2) {0,0}; curves[2].points[12].leftLinear = 0; curves[2].points[12].rightLinear = 0;
  348. curves[2].points[13].position = (Vector2) {0.930000, 0.492063}; curves[2].points[13].tangents = (Vector2) {0,0}; curves[2].points[13].leftLinear = 0; curves[2].points[13].rightLinear = 0;
  349. curves[2].points[14].position = (Vector2) {0.940000, 0.619048}; curves[2].points[14].tangents = (Vector2) {0,0}; curves[2].points[14].leftLinear = 0; curves[2].points[14].rightLinear = 0;
  350. curves[2].points[15].position = (Vector2) {0.950000, 0.492063}; curves[2].points[15].tangents = (Vector2) {0,0}; curves[2].points[15].leftLinear = 0; curves[2].points[15].rightLinear = 0;
  351. // Y Size
  352. curves[3].start = 1;
  353. curves[3].end = 64;
  354. curves[3].numPoints = 16;
  355. curves[3].selectedIndex = 0;
  356. curves[3].editLeftTangent = false;
  357. curves[3].editRightTangent = false;
  358. curves[3].points[0].position = (Vector2) {0.000000, 0.492063};curves[3].points[0].tangents = (Vector2) {0,0};curves[3].points[0].leftLinear = 0;curves[3].points[0].rightLinear = 0;
  359. curves[3].points[1].position = (Vector2) {0.130000, 0.492063};curves[3].points[1].tangents = (Vector2) {0,0};curves[3].points[1].leftLinear = 0;curves[3].points[1].rightLinear = 0;
  360. curves[3].points[2].position = (Vector2) {0.140000, 0.238095};curves[3].points[2].tangents = (Vector2) {0,0};curves[3].points[2].leftLinear = 0;curves[3].points[2].rightLinear = 0;
  361. curves[3].points[3].position = (Vector2) {0.150000, 0.492063};curves[3].points[3].tangents = (Vector2) {0,0};curves[3].points[3].leftLinear = 0;curves[3].points[3].rightLinear = 0;
  362. curves[3].points[4].position = (Vector2) {0.440000, 0.492063};curves[3].points[4].tangents = (Vector2) {0,0};curves[3].points[4].leftLinear = 0;curves[3].points[4].rightLinear = 0;
  363. curves[3].points[5].position = (Vector2) {0.450000, 0.301587};curves[3].points[5].tangents = (Vector2) {0,0};curves[3].points[5].leftLinear = 0;curves[3].points[5].rightLinear = 0;
  364. curves[3].points[6].position = (Vector2) {0.460000, 0.492063};curves[3].points[6].tangents = (Vector2) {0,0};curves[3].points[6].leftLinear = 0;curves[3].points[6].rightLinear = 0;
  365. curves[3].points[7].position = (Vector2) {0.660000, 0.492063};curves[3].points[7].tangents = (Vector2) {0,0};curves[3].points[7].leftLinear = 0;curves[3].points[7].rightLinear = 0;
  366. curves[3].points[8].position = (Vector2) {0.670000, 0.365079};curves[3].points[8].tangents = (Vector2) {0,0};curves[3].points[8].leftLinear = 0;curves[3].points[8].rightLinear = 0;
  367. curves[3].points[9].position = (Vector2) {0.680000, 0.492063};curves[3].points[9].tangents = (Vector2) {0,0};curves[3].points[9].leftLinear = 0;curves[3].points[9].rightLinear = 0;
  368. curves[3].points[10].position = (Vector2) {0.820000, 0.492063};curves[3].points[10].tangents = (Vector2) {0,0};curves[3].points[10].leftLinear = 0;curves[3].points[10].rightLinear = 0;
  369. curves[3].points[11].position = (Vector2) {0.830000, 0.365079};curves[3].points[11].tangents = (Vector2) {0,0};curves[3].points[11].leftLinear = 0;curves[3].points[11].rightLinear = 0;
  370. curves[3].points[12].position = (Vector2) {0.840000, 0.492063};curves[3].points[12].tangents = (Vector2) {0,0};curves[3].points[12].leftLinear = 0;curves[3].points[12].rightLinear = 0;
  371. curves[3].points[13].position = (Vector2) {0.930000, 0.492063};curves[3].points[13].tangents = (Vector2) {0,0};curves[3].points[13].leftLinear = 0;curves[3].points[13].rightLinear = 0;
  372. curves[3].points[14].position = (Vector2) {0.940000, 0.365079};curves[3].points[14].tangents = (Vector2) {0,0};curves[3].points[14].leftLinear = 0;curves[3].points[14].rightLinear = 0;
  373. curves[3].points[15].position = (Vector2) {0.950000, 0.507937};curves[3].points[15].tangents = (Vector2) {0,0};curves[3].points[15].leftLinear = 0;curves[3].points[15].rightLinear = 0;
  374. // Rotation
  375. curves[4].start = -360;
  376. curves[4].end = 360;
  377. curves[4].numPoints = 9;
  378. curves[4].selectedIndex = 0;
  379. curves[4].editLeftTangent = false;
  380. curves[4].editRightTangent = false;
  381. curves[4].points[0].position = (Vector2) {0.140000, 0.500000};curves[4].points[0].tangents = (Vector2) {0,0};curves[4].points[0].leftLinear = 0;curves[4].points[0].rightLinear = 0;
  382. curves[4].points[1].position = (Vector2) {0.450000, 0.500000};curves[4].points[1].tangents = (Vector2) {0,0};curves[4].points[1].leftLinear = 0;curves[4].points[1].rightLinear = 0;
  383. curves[4].points[2].position = (Vector2) {0.670000, 0.500000};curves[4].points[2].tangents = (Vector2) {0,0};curves[4].points[2].leftLinear = 0;curves[4].points[2].rightLinear = 0;
  384. curves[4].points[3].position = (Vector2) {0.830000, 0.500000};curves[4].points[3].tangents = (Vector2) {0,0};curves[4].points[3].leftLinear = 0;curves[4].points[3].rightLinear = 0;
  385. curves[4].points[4].position = (Vector2) {0.940000, 0.500000};curves[4].points[4].tangents = (Vector2) {0,0};curves[4].points[4].leftLinear = 0;curves[4].points[4].rightLinear = 0;
  386. curves[4].points[5].position = (Vector2) {1.000000, 0.500000};curves[4].points[5].tangents = (Vector2) {0,0};curves[4].points[5].leftLinear = 0;curves[4].points[5].rightLinear = 0;
  387. curves[4].points[6].position = (Vector2) {0.000000, 0.472222};curves[4].points[6].tangents = (Vector2) {0,0};curves[4].points[6].leftLinear = 0;curves[4].points[6].rightLinear = 0;
  388. curves[4].points[7].position = (Vector2) {0.302752, 0.527778};curves[4].points[7].tangents = (Vector2) {0,0};curves[4].points[7].leftLinear = 0;curves[4].points[7].rightLinear = 0;
  389. curves[4].points[8].position = (Vector2) {0.577982, 0.472222};curves[4].points[8].tangents = (Vector2) {0,0};curves[4].points[8].leftLinear = 0;curves[4].points[8].rightLinear = 0;
  390. }