| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | #include "ground_lib.h"
 | 
					
						
							|  |  |  | #include <SDL3/SDL.h>
 | 
					
						
							|  |  |  | #include <SDL3/SDL_main.h>
 | 
					
						
							|  |  |  | #include <SDL3/SDL_render.h>
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | #include <iostream>
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | SDL_Window* window = nullptr; | 
					
						
							|  |  |  | SDL_Renderer* renderer = nullptr; | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | SDL_Event event; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | int width = 0; | 
					
						
							|  |  |  | int height = 0; | 
					
						
							|  |  |  | bool hasRunInit = false; | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | // Helper function to clamp values
 | 
					
						
							|  |  |  | int clamp(int value, int min, int max) { | 
					
						
							|  |  |  |     if (value < min) return min; | 
					
						
							|  |  |  |     if (value > max) return max; | 
					
						
							|  |  |  |     return value; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | // Initialize SDL and create window
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | GroundValue initSDL(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (hasRunInit) return GROUND_INT_VAL(2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     VALIDATE_ARGS_3(GROUND_STRING, GROUND_INT, GROUND_INT); | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (SDL_Init(SDL_INIT_VIDEO) < 0) { | 
					
						
							|  |  |  |         std::cout << "SDL could not initialize! SDL Error: " << SDL_GetError() << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |     width = GET_INT(args[1]); | 
					
						
							|  |  |  |     height = GET_INT(args[2]); | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Validate dimensions
 | 
					
						
							|  |  |  |     if (width <= 0 || height <= 0) { | 
					
						
							|  |  |  |         std::cout << "Invalid window dimensions" << std::endl; | 
					
						
							|  |  |  |         SDL_Quit(); | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |         return GROUND_INT_VAL(1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (SDL_CreateWindowAndRenderer(GET_STRING(args[0]), width, height, | 
					
						
							|  |  |  |                                    SDL_WINDOW_OPENGL, &window, &renderer) < 0) { | 
					
						
							|  |  |  |         std::cout << "Window could not be created! SDL Error: " << SDL_GetError() << std::endl; | 
					
						
							|  |  |  |         SDL_Quit(); | 
					
						
							|  |  |  |         return GROUND_INT_VAL(1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |     hasRunInit = true; | 
					
						
							|  |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | // Poll for events (enhanced with more event types)
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | GroundValue pollEvent(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot poll event, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  |     if (SDL_PollEvent(&event)) { | 
					
						
							|  |  |  |         switch (event.type) { | 
					
						
							|  |  |  |             case SDL_EVENT_QUIT: | 
					
						
							|  |  |  |                 return GROUND_INT_VAL(0); | 
					
						
							|  |  |  |             case SDL_EVENT_KEY_DOWN: | 
					
						
							|  |  |  |                 return GROUND_INT_VAL(1); | 
					
						
							|  |  |  |             case SDL_EVENT_KEY_UP: | 
					
						
							|  |  |  |                 return GROUND_INT_VAL(2); | 
					
						
							|  |  |  |             case SDL_EVENT_MOUSE_BUTTON_DOWN: | 
					
						
							|  |  |  |                 return GROUND_INT_VAL(3); | 
					
						
							|  |  |  |             case SDL_EVENT_MOUSE_BUTTON_UP: | 
					
						
							|  |  |  |                 return GROUND_INT_VAL(4); | 
					
						
							|  |  |  |             case SDL_EVENT_MOUSE_MOTION: | 
					
						
							|  |  |  |                 return GROUND_INT_VAL(5); | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 return GROUND_INT_VAL(6); // Other event
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return GROUND_INT_VAL(-1); // No event
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Get last key pressed (requires polling events first)
 | 
					
						
							|  |  |  | GroundValue getLastKey(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot get key, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (event.type == SDL_EVENT_KEY_DOWN || event.type == SDL_EVENT_KEY_UP) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL(event.key.key); | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |     } | 
					
						
							|  |  |  |     return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | // Get mouse position
 | 
					
						
							|  |  |  | GroundValue getMousePos(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot get mouse position, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     VALIDATE_ARGS_1(GROUND_INT); | 
					
						
							|  |  |  |     int coord = GET_INT(args[0]); // 0 for x, 1 for y
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     float mouseX, mouseY; | 
					
						
							|  |  |  |     SDL_GetMouseState(&mouseX, &mouseY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (coord == 0) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL((int)mouseX); | 
					
						
							|  |  |  |     } else if (coord == 1) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL((int)mouseY); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Clear renderer with optional color
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | GroundValue clearRenderer(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot clear renderer, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (arg_count == 3) { | 
					
						
							|  |  |  |         VALIDATE_ARGS_3(GROUND_INT, GROUND_INT, GROUND_INT); | 
					
						
							|  |  |  |         int r = clamp(GET_INT(args[0]), 0, 255); | 
					
						
							|  |  |  |         int g = clamp(GET_INT(args[1]), 0, 255); | 
					
						
							|  |  |  |         int b = clamp(GET_INT(args[2]), 0, 255); | 
					
						
							|  |  |  |         SDL_SetRenderDrawColor(renderer, r, g, b, 255); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         // Default to black
 | 
					
						
							|  |  |  |         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |     SDL_RenderClear(renderer); | 
					
						
							|  |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | // Render frame to screen
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | GroundValue renderFrame(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot render frame, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     SDL_RenderPresent(renderer); | 
					
						
							| 
									
										
										
										
											2025-09-21 16:03:19 +10:00
										 |  |  |     return GROUND_INT_VAL(0); | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | // Set a single pixel
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | GroundValue setPixel(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot set pixel, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     VALIDATE_ARGS_5(GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT); | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |     int pixelX = GET_INT(args[0]); | 
					
						
							|  |  |  |     int pixelY = GET_INT(args[1]); | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  |     int red = clamp(GET_INT(args[2]), 0, 255); | 
					
						
							|  |  |  |     int green = clamp(GET_INT(args[3]), 0, 255); | 
					
						
							|  |  |  |     int blue = clamp(GET_INT(args[4]), 0, 255); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Bounds checking
 | 
					
						
							|  |  |  |     if (pixelX < 0 || pixelX >= width || pixelY < 0 || pixelY >= height) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); // Out of bounds
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SDL_SetRenderDrawColor(renderer, red, green, blue, 255); | 
					
						
							|  |  |  |     SDL_RenderPoint(renderer, (float)pixelX, (float)pixelY); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Draw a line
 | 
					
						
							|  |  |  | GroundValue drawLine(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot draw line, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     VALIDATE_ARGS_7(GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int x1 = GET_INT(args[0]); | 
					
						
							|  |  |  |     int y1 = GET_INT(args[1]); | 
					
						
							|  |  |  |     int x2 = GET_INT(args[2]); | 
					
						
							|  |  |  |     int y2 = GET_INT(args[3]); | 
					
						
							|  |  |  |     int red = clamp(GET_INT(args[4]), 0, 255); | 
					
						
							|  |  |  |     int green = clamp(GET_INT(args[5]), 0, 255); | 
					
						
							|  |  |  |     int blue = clamp(GET_INT(args[6]), 0, 255); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SDL_SetRenderDrawColor(renderer, red, green, blue, 255); | 
					
						
							|  |  |  |     SDL_RenderLine(renderer, (float)x1, (float)y1, (float)x2, (float)y2); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Draw a filled rectangle
 | 
					
						
							|  |  |  | GroundValue drawRect(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot draw rectangle, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     VALIDATE_ARGS_7(GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int x = GET_INT(args[0]); | 
					
						
							|  |  |  |     int y = GET_INT(args[1]); | 
					
						
							|  |  |  |     int w = GET_INT(args[2]); | 
					
						
							|  |  |  |     int h = GET_INT(args[3]); | 
					
						
							|  |  |  |     int red = clamp(GET_INT(args[4]), 0, 255); | 
					
						
							|  |  |  |     int green = clamp(GET_INT(args[5]), 0, 255); | 
					
						
							|  |  |  |     int blue = clamp(GET_INT(args[6]), 0, 255); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (w <= 0 || h <= 0) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); // Invalid dimensions
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SDL_FRect rect = {(float)x, (float)y, (float)w, (float)h}; | 
					
						
							|  |  |  |     SDL_SetRenderDrawColor(renderer, red, green, blue, 255); | 
					
						
							|  |  |  |     SDL_RenderFillRect(renderer, &rect); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Draw a rectangle outline
 | 
					
						
							|  |  |  | GroundValue drawRectOutline(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot draw rectangle outline, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     VALIDATE_ARGS_7(GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int x = GET_INT(args[0]); | 
					
						
							|  |  |  |     int y = GET_INT(args[1]); | 
					
						
							|  |  |  |     int w = GET_INT(args[2]); | 
					
						
							|  |  |  |     int h = GET_INT(args[3]); | 
					
						
							|  |  |  |     int red = clamp(GET_INT(args[4]), 0, 255); | 
					
						
							|  |  |  |     int green = clamp(GET_INT(args[5]), 0, 255); | 
					
						
							|  |  |  |     int blue = clamp(GET_INT(args[6]), 0, 255); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (w <= 0 || h <= 0) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); // Invalid dimensions
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SDL_FRect rect = {(float)x, (float)y, (float)w, (float)h}; | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |     SDL_SetRenderDrawColor(renderer, red, green, blue, 255); | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  |     SDL_RenderRect(renderer, &rect); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  | // Draw a circle (filled)
 | 
					
						
							|  |  |  | GroundValue drawCircle(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot draw circle, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     VALIDATE_ARGS_6(GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT, GROUND_INT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int centerX = GET_INT(args[0]); | 
					
						
							|  |  |  |     int centerY = GET_INT(args[1]); | 
					
						
							|  |  |  |     int radius = GET_INT(args[2]); | 
					
						
							|  |  |  |     int red = clamp(GET_INT(args[3]), 0, 255); | 
					
						
							|  |  |  |     int green = clamp(GET_INT(args[4]), 0, 255); | 
					
						
							|  |  |  |     int blue = clamp(GET_INT(args[5]), 0, 255); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (radius <= 0) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); // Invalid radius
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SDL_SetRenderDrawColor(renderer, red, green, blue, 255); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Simple circle drawing using midpoint algorithm
 | 
					
						
							|  |  |  |     for (int y = -radius; y <= radius; y++) { | 
					
						
							|  |  |  |         for (int x = -radius; x <= radius; x++) { | 
					
						
							|  |  |  |             if (x*x + y*y <= radius*radius) { | 
					
						
							|  |  |  |                 SDL_RenderPoint(renderer, (float)(centerX + x), (float)(centerY + y)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Get window dimensions
 | 
					
						
							|  |  |  | GroundValue getWindowSize(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (!hasRunInit) { | 
					
						
							|  |  |  |         std::cout << "Cannot get window size, please run !grogs:initSDL first" << std::endl; | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     VALIDATE_ARGS_1(GROUND_INT); | 
					
						
							|  |  |  |     int dimension = GET_INT(args[0]); // 0 for width, 1 for height
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (dimension == 0) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL(width); | 
					
						
							|  |  |  |     } else if (dimension == 1) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL(height); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Delay execution (useful for frame rate control)
 | 
					
						
							|  |  |  | GroundValue delay(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     VALIDATE_ARGS_1(GROUND_INT); | 
					
						
							|  |  |  |     int milliseconds = GET_INT(args[0]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (milliseconds < 0) { | 
					
						
							|  |  |  |         return GROUND_INT_VAL(-1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SDL_Delay(milliseconds); | 
					
						
							|  |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Cleanup SDL resources
 | 
					
						
							|  |  |  | GroundValue cleanup(GroundValue* args, int arg_count) { | 
					
						
							|  |  |  |     if (hasRunInit) { | 
					
						
							|  |  |  |         if (renderer) { | 
					
						
							|  |  |  |             SDL_DestroyRenderer(renderer); | 
					
						
							|  |  |  |             renderer = nullptr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (window) { | 
					
						
							|  |  |  |             SDL_DestroyWindow(window); | 
					
						
							|  |  |  |             window = nullptr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         SDL_Quit(); | 
					
						
							|  |  |  |         hasRunInit = false; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |     return GROUND_INT_VAL(0); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GROUND_LIBRARY_INTERFACE() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GROUND_LIBRARY_INIT() | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(initSDL); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(renderFrame); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(pollEvent); | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  |     REGISTER_GROUND_FUNCTION(getLastKey); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(getMousePos); | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  |     REGISTER_GROUND_FUNCTION(clearRenderer); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(setPixel); | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  |     REGISTER_GROUND_FUNCTION(drawLine); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(drawRect); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(drawRectOutline); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(drawCircle); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(getWindowSize); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(delay); | 
					
						
							|  |  |  |     REGISTER_GROUND_FUNCTION(cleanup); | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | GROUND_LIBRARY_INIT_END() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GROUND_LIBRARY_CLEANUP() | 
					
						
							| 
									
										
										
										
											2025-09-21 20:41:09 +10:00
										 |  |  |     cleanup(nullptr, 0); | 
					
						
							| 
									
										
										
										
											2025-09-21 15:50:03 +10:00
										 |  |  | GROUND_LIBRARY_CLEANUP_END() |