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