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.

226 lines
8.4 KiB

  1. /*******************************************************************************************
  2. *
  3. * raylib [textures] example - Mouse painting
  4. *
  5. * Example originally created with raylib 3.0, last time updated with raylib 3.0
  6. *
  7. * Example contributed by Chris Dill (@MysteriousSpace) and reviewed by Ramon Santamaria (@raysan5)
  8. *
  9. * Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
  10. * BSD-like license that allows static linking with closed source software
  11. *
  12. * Copyright (c) 2019-2024 Chris Dill (@MysteriousSpace) and Ramon Santamaria (@raysan5)
  13. *
  14. ********************************************************************************************/
  15. #include "raylib.h"
  16. #define MAX_COLORS_COUNT 23 // Number of colors available
  17. //------------------------------------------------------------------------------------
  18. // Program main entry point
  19. //------------------------------------------------------------------------------------
  20. int main(void)
  21. {
  22. // Initialization
  23. //--------------------------------------------------------------------------------------
  24. const int screenWidth = 800;
  25. const int screenHeight = 450;
  26. InitWindow(screenWidth, screenHeight, "raylib [textures] example - mouse painting");
  27. // Colors to choose from
  28. Color colors[MAX_COLORS_COUNT] = {
  29. RAYWHITE, YELLOW, GOLD, ORANGE, PINK, RED, MAROON, GREEN, LIME, DARKGREEN,
  30. SKYBLUE, BLUE, DARKBLUE, PURPLE, VIOLET, DARKPURPLE, BEIGE, BROWN, DARKBROWN,
  31. LIGHTGRAY, GRAY, DARKGRAY, BLACK };
  32. // Define colorsRecs data (for every rectangle)
  33. Rectangle colorsRecs[MAX_COLORS_COUNT] = { 0 };
  34. for (int i = 0; i < MAX_COLORS_COUNT; i++)
  35. {
  36. colorsRecs[i].x = 10 + 30.0f*i + 2*i;
  37. colorsRecs[i].y = 10;
  38. colorsRecs[i].width = 30;
  39. colorsRecs[i].height = 30;
  40. }
  41. int colorSelected = 0;
  42. int colorSelectedPrev = colorSelected;
  43. int colorMouseHover = 0;
  44. float brushSize = 20.0f;
  45. bool mouseWasPressed = false;
  46. Rectangle btnSaveRec = { 750, 10, 40, 30 };
  47. bool btnSaveMouseHover = false;
  48. bool showSaveMessage = false;
  49. int saveMessageCounter = 0;
  50. // Create a RenderTexture2D to use as a canvas
  51. RenderTexture2D target = LoadRenderTexture(screenWidth, screenHeight);
  52. // Clear render texture before entering the game loop
  53. BeginTextureMode(target);
  54. ClearBackground(colors[0]);
  55. EndTextureMode();
  56. SetTargetFPS(120); // Set our game to run at 120 frames-per-second
  57. //--------------------------------------------------------------------------------------
  58. // Main game loop
  59. while (!WindowShouldClose()) // Detect window close button or ESC key
  60. {
  61. // Update
  62. //----------------------------------------------------------------------------------
  63. Vector2 mousePos = GetMousePosition();
  64. // Move between colors with keys
  65. if (IsKeyPressed(KEY_RIGHT)) colorSelected++;
  66. else if (IsKeyPressed(KEY_LEFT)) colorSelected--;
  67. if (colorSelected >= MAX_COLORS_COUNT) colorSelected = MAX_COLORS_COUNT - 1;
  68. else if (colorSelected < 0) colorSelected = 0;
  69. // Choose color with mouse
  70. for (int i = 0; i < MAX_COLORS_COUNT; i++)
  71. {
  72. if (CheckCollisionPointRec(mousePos, colorsRecs[i]))
  73. {
  74. colorMouseHover = i;
  75. break;
  76. }
  77. else colorMouseHover = -1;
  78. }
  79. if ((colorMouseHover >= 0) && IsMouseButtonPressed(MOUSE_BUTTON_LEFT))
  80. {
  81. colorSelected = colorMouseHover;
  82. colorSelectedPrev = colorSelected;
  83. }
  84. // Change brush size
  85. brushSize += GetMouseWheelMove()*5;
  86. if (brushSize < 2) brushSize = 2;
  87. if (brushSize > 50) brushSize = 50;
  88. if (IsKeyPressed(KEY_C))
  89. {
  90. // Clear render texture to clear color
  91. BeginTextureMode(target);
  92. ClearBackground(colors[0]);
  93. EndTextureMode();
  94. }
  95. if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) || (GetGestureDetected() == GESTURE_DRAG))
  96. {
  97. // Paint circle into render texture
  98. // NOTE: To avoid discontinuous circles, we could store
  99. // previous-next mouse points and just draw a line using brush size
  100. BeginTextureMode(target);
  101. if (mousePos.y > 50) DrawCircle((int)mousePos.x, (int)mousePos.y, brushSize, colors[colorSelected]);
  102. EndTextureMode();
  103. }
  104. if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT))
  105. {
  106. if (!mouseWasPressed)
  107. {
  108. colorSelectedPrev = colorSelected;
  109. colorSelected = 0;
  110. }
  111. mouseWasPressed = true;
  112. // Erase circle from render texture
  113. BeginTextureMode(target);
  114. if (mousePos.y > 50) DrawCircle((int)mousePos.x, (int)mousePos.y, brushSize, colors[0]);
  115. EndTextureMode();
  116. }
  117. else if (IsMouseButtonReleased(MOUSE_BUTTON_RIGHT) && mouseWasPressed)
  118. {
  119. colorSelected = colorSelectedPrev;
  120. mouseWasPressed = false;
  121. }
  122. // Check mouse hover save button
  123. if (CheckCollisionPointRec(mousePos, btnSaveRec)) btnSaveMouseHover = true;
  124. else btnSaveMouseHover = false;
  125. // Image saving logic
  126. // NOTE: Saving painted texture to a default named image
  127. if ((btnSaveMouseHover && IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) || IsKeyPressed(KEY_S))
  128. {
  129. Image image = LoadImageFromTexture(target.texture);
  130. ImageFlipVertical(&image);
  131. ExportImage(image, "my_amazing_texture_painting.png");
  132. UnloadImage(image);
  133. showSaveMessage = true;
  134. }
  135. if (showSaveMessage)
  136. {
  137. // On saving, show a full screen message for 2 seconds
  138. saveMessageCounter++;
  139. if (saveMessageCounter > 240)
  140. {
  141. showSaveMessage = false;
  142. saveMessageCounter = 0;
  143. }
  144. }
  145. //----------------------------------------------------------------------------------
  146. // Draw
  147. //----------------------------------------------------------------------------------
  148. BeginDrawing();
  149. ClearBackground(RAYWHITE);
  150. // NOTE: Render texture must be y-flipped due to default OpenGL coordinates (left-bottom)
  151. DrawTextureRec(target.texture, (Rectangle) { 0, 0, (float)target.texture.width, (float)-target.texture.height }, (Vector2) { 0, 0 }, WHITE);
  152. // Draw drawing circle for reference
  153. if (mousePos.y > 50)
  154. {
  155. if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) DrawCircleLines((int)mousePos.x, (int)mousePos.y, brushSize, GRAY);
  156. else DrawCircle(GetMouseX(), GetMouseY(), brushSize, colors[colorSelected]);
  157. }
  158. // Draw top panel
  159. DrawRectangle(0, 0, GetScreenWidth(), 50, RAYWHITE);
  160. DrawLine(0, 50, GetScreenWidth(), 50, LIGHTGRAY);
  161. // Draw color selection rectangles
  162. for (int i = 0; i < MAX_COLORS_COUNT; i++) DrawRectangleRec(colorsRecs[i], colors[i]);
  163. DrawRectangleLines(10, 10, 30, 30, LIGHTGRAY);
  164. if (colorMouseHover >= 0) DrawRectangleRec(colorsRecs[colorMouseHover], Fade(WHITE, 0.6f));
  165. DrawRectangleLinesEx((Rectangle){ colorsRecs[colorSelected].x - 2, colorsRecs[colorSelected].y - 2,
  166. colorsRecs[colorSelected].width + 4, colorsRecs[colorSelected].height + 4 }, 2, BLACK);
  167. // Draw save image button
  168. DrawRectangleLinesEx(btnSaveRec, 2, btnSaveMouseHover ? RED : BLACK);
  169. DrawText("SAVE!", 755, 20, 10, btnSaveMouseHover ? RED : BLACK);
  170. // Draw save image message
  171. if (showSaveMessage)
  172. {
  173. DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(RAYWHITE, 0.8f));
  174. DrawRectangle(0, 150, GetScreenWidth(), 80, BLACK);
  175. DrawText("IMAGE SAVED: my_amazing_texture_painting.png", 150, 180, 20, RAYWHITE);
  176. }
  177. EndDrawing();
  178. //----------------------------------------------------------------------------------
  179. }
  180. // De-Initialization
  181. //--------------------------------------------------------------------------------------
  182. UnloadRenderTexture(target); // Unload render texture
  183. CloseWindow(); // Close window and OpenGL context
  184. //--------------------------------------------------------------------------------------
  185. return 0;
  186. }