-
Notifications
You must be signed in to change notification settings - Fork 0
Examples
Ryan Srichai edited this page Jun 12, 2026
·
19 revisions
This page contains the full source code for examples using turtle's features. See this page to learn how to build and run a project.
#define TURTLE_IMPLEMENTATION // exclude this line if compiling with -lturtle
#include "turtle.h"
int main(int argc, char *argv[]) {
int32_t numberOfPrimes = 100;
list_t *primes = list_init();
list_append(primes, (unitype) 2, 'i');
int32_t checkNumber = 3;
while (primes -> length < numberOfPrimes) {
int8_t isPrime = 1;
for (int32_t j = 0; j < primes -> length; j++) {
if (primes -> data[j].i > sqrt(checkNumber)) {
break;
}
if (checkNumber % primes -> data[j].i == 0) {
isPrime = 0;
break;
}
}
if (isPrime) {
list_append(primes, (unitype) checkNumber, 'i');
}
checkNumber++;
}
list_print(primes);
}#define TURTLE_IMPLEMENTATION // exclude this line if compiling with -lturtle
#include "turtle.h"
#include <time.h>
int main(int argc, char *argv[]) {
/* Initialise window */
GLFWwindow *window = turtleCreateWindow(TURTLE_WINDOW_DEFAULT_WIDTH, TURTLE_WINDOW_DEFAULT_HEIGHT, "draw mouse demo");
/* initialise turtle */
turtleInit(window, -320, -180, 320, 180);
uint32_t tps = 60; // ticks per second (locked to fps in this case)
uint64_t tick = 0; // count number of ticks since application started
clock_t start, end;
turtlePenColor(0, 0, 0); // set color to black
turtlePenSize(10); // set size to 10
while (turtle.close == 0) {
start = clock();
turtleGetMouseCoordinates();
turtleGoto(turtle.mouseX, turtle.mouseY);
if (turtleMouseDown()) {
turtlePenDown();
} else {
turtlePenUp();
}
turtleUpdate(); // update the screen
end = clock();
while ((double) (end - start) / CLOCKS_PER_SEC < (1.0 / tps)) {
end = clock();
}
tick++;
}
turtleFree();
glfwTerminate();
}#define TURTLE_IMPLEMENTATION // exclude this line if compiling with -lturtle
#include "turtle.h"
#include <time.h>
int main(int argc, char *argv[]) {
/* Initialise window */
GLFWwindow *window = turtleCreateWindow(TURTLE_WINDOW_DEFAULT_WIDTH, TURTLE_WINDOW_DEFAULT_HEIGHT, "controls demo");
/* initialise turtle */
turtleInit(window, -320, -180, 320, 180);
uint32_t tps = 60; // ticks per second (locked to fps in this case)
uint64_t tick = 0; // count number of ticks since application started
clock_t start, end;
turtlePenColor(0, 0, 0); // set color to black
turtlePenSize(50); // set size to 10
double ballX = 0;
double ballY = 0;
double ballSpeed = 5.0;
while (turtle.close == 0) {
start = clock();
if (turtleKeyPressed(GLFW_KEY_UP)) {
ballY += ballSpeed;
}
if (turtleKeyPressed(GLFW_KEY_DOWN)) {
ballY -= ballSpeed;
}
if (turtleKeyPressed(GLFW_KEY_RIGHT)) {
ballX += ballSpeed;
}
if (turtleKeyPressed(GLFW_KEY_LEFT)) {
ballX -= ballSpeed;
}
turtleClear(); // clear the screen
turtleGoto(ballX, ballY);
turtlePenDown();
turtlePenUp();
turtleUpdate(); // update the screen
end = clock();
while ((double) (end - start) / CLOCKS_PER_SEC < (1.0 / tps)) {
end = clock();
}
tick++;
}
turtleFree();
glfwTerminate();
}#define TURTLE_IMPLEMENTATION // exclude this line if compiling with -lturtle
#include "turtle.h"
#include <time.h>
int main(int argc, char *argv[]) {
/* Initialise window */
GLFWwindow *window = turtleCreateWindow(TURTLE_WINDOW_DEFAULT_WIDTH, TURTLE_WINDOW_DEFAULT_HEIGHT, "draw mouse demo");
/* initialise turtle */
turtleInit(window, -320, -180, 320, 180);
/* initialise turtleText */
turtleTextInit("config/roberto.tgl");
uint32_t tps = 60; // ticks per second (locked to fps in this case)
uint64_t tick = 0; // count number of ticks since application started
clock_t start, end;
turtlePenColor(0, 0, 0);
turtlePenSize(0.5);
while (turtle.close == 0) {
start = clock();
turtleClear(); // clear the screen
turtleGetMouseCoordinates();
turtleGoto(turtle.mouseX - 3, turtle.mouseY);
turtlePenDown();
turtleGoto(turtle.mouseX + 3, turtle.mouseY);
turtlePenUp();
turtleGoto(turtle.mouseX, turtle.mouseY - 3);
turtlePenDown();
turtleGoto(turtle.mouseX, turtle.mouseY + 3);
turtlePenUp();
turtleTextWriteStringf(turtle.mouseX + 2, turtle.mouseY + 6, 5, 0, "%.2lf, %.2lf", turtle.mouseX, turtle.mouseY);
turtleUpdate(); // update the screen
end = clock();
while ((double) (end - start) / CLOCKS_PER_SEC < (1.0 / tps)) {
end = clock();
}
tick++;
}
turtleFree();
glfwTerminate();
}#define TURTLE_IMPLEMENTATION // exclude this line if compiling with -lturtle
#include "turtle.h"
#include <time.h>
int main(int argc, char *argv[]) {
/* Initialise window */
GLFWwindow *window = turtleCreateWindow(TURTLE_WINDOW_DEFAULT_WIDTH, TURTLE_WINDOW_DEFAULT_HEIGHT, "dialog demo");
/* initialise turtle */
turtleInit(window, -320, -180, 320, 180);
/* initialise turtleText */
turtleTextInit("config/roberto.tgl");
uint32_t tps = 60; // ticks per second (locked to fps in this case)
uint64_t tick = 0; // count number of ticks since application started
clock_t start, end;
char dialog[][128] = {
"Hey it's nice to meet you",
"This world is imperfect.",
"What",
"If only I could wipe away the impurities,",
"Is anybody else listening to this",
"and make it as beautiful as me!",
"14 hours of gameplay later",
"Lysanderoth! You were behind all this?",
"Yes it was I. My machinations lay undetected for years\nfor I am a master of deception",
};
uint8_t color[][3] = {
140, 140, 255,
255, 80, 80,
140, 140, 255,
255, 80, 80,
140, 140, 255,
255, 80, 80,
160, 160, 160,
255, 40, 140,
255, 80, 80,
};
int32_t dialogLength = sizeof(dialog) / 128;
int32_t dialogIndex = 0;
int32_t mouseFlag = 0;
char text[8][128];
while (turtle.close == 0) {
start = clock();
turtleClear(); // clear the screen
turtlePenColor(60, 60, 60);
turtleRectangle(-320, -110, 320, -180);
turtlePenColor(color[dialogIndex][0], color[dialogIndex][1], color[dialogIndex][2]);
int32_t lines = 0;
int32_t next = 0;
for (int32_t i = 0; i < strlen(dialog[dialogIndex]); i++) {
text[lines][next] = dialog[dialogIndex][i];
if (dialog[dialogIndex][i] == '\n') {
text[lines][next] = '\0';
lines++;
next = -1;
}
next++;
}
text[lines][next] = '\0';
lines++;
for (int32_t i = 0; i < lines; i++) {
turtleTextWriteUnicode(text[i], -305, -130 - i * 20, 12, 0);
}
if (turtleMouseDown()) {
if (mouseFlag == 0) {
dialogIndex++;
mouseFlag = 1;
if (dialogIndex >= dialogLength) {
dialogIndex = 0;
}
}
} else {
mouseFlag = 0;
}
turtleUpdate(); // update the screen
end = clock();
while ((double) (end - start) / CLOCKS_PER_SEC < (1.0 / tps)) {
end = clock();
}
tick++;
}
turtleFree();
glfwTerminate();
}// #define TURTLE_IMPLEMENTATION // exclude this line if compiling with -lturtle
#include "turtle.h"
#include <time.h>
enum {
EDITOR_KEYS_LMB = 0,
EDITOR_KEYS_RMB = 1,
EDITOR_KEYS_LEFT_SHIFT = 2,
};
enum {
DRAW_INDEX_RED = 0,
DRAW_INDEX_GREEN = 1,
DRAW_INDEX_BLUE = 2,
DRAW_INDEX_ALPHA = 3,
DRAW_INDEX_SIZE = 4,
DRAW_INDEX_X = 5,
DRAW_INDEX_Y = 6,
DRAW_INDEX_PEN_DOWN = 7,
DRAW_INDEX_NUMBER_OF_FIELDS = 8,
};
typedef struct {
list_t *draw; // see DRAW_INDEX_X
double sidebarX;
double canvasX;
double canvasY;
double canvasWidth;
double canvasHeight;
double editingX;
double editingY;
double editingZoom;
double anchorMouseX;
double anchorMouseY;
double anchorEditingX;
double anchorEditingY;
int8_t editingMoving;
int8_t drawing;
turtle_texture_t transparentTexture;
tt_button_t *cameraButton;
int32_t cameraAnimation;
tt_slider_t *redChannel;
double redSave;
tt_slider_t *greenChannel;
double greenSave;
tt_slider_t *blueChannel;
double blueSave;
tt_slider_t *sizeSlider;
int8_t lockOffsets;
int8_t keys[8];
} image_editor_t;
image_editor_t self;
void init() {
self.draw = list_init();
self.sidebarX = 200;
self.canvasX = -100;
self.canvasY = 0;
self.canvasWidth = 320;
self.canvasHeight = self.canvasWidth / 4.0 * 3;
self.editingX = 0;
self.editingY = 0;
self.editingZoom = 1;
self.editingMoving = 0;
self.drawing = 0;
turtleToolsSetTheme(TT_THEME_DARK);
/* create transparent texture */
int32_t textureWidth = 1024;
int32_t textureHeight = 768;
uint8_t tColor1[3] = {60, 60, 60};
uint8_t tColor2[3] = {80, 80, 80};
int32_t gridSize = 16;
uint8_t *transparent = malloc(textureWidth * textureHeight * 3);
for (int32_t i = 0; i < textureHeight; i++) {
int32_t color = 0;
if (i % (gridSize * 2) < gridSize) {
color = 1;
}
int32_t grid = 0;
for (int32_t j = 0; j < textureWidth; j++) {
if (color) {
memcpy(transparent + i * textureWidth * 3 + j * 3, tColor1, 3);
grid++;
} else {
memcpy(transparent + i * textureWidth * 3 + j * 3, tColor2, 3);
grid++;
}
if (grid == gridSize) {
color = !color;
grid = 0;
}
}
}
self.transparentTexture = turtleTextureLoadArray(transparent, textureWidth, textureHeight, GL_RGB);
free(transparent);
/* set up sidebar UI */
self.cameraButton = tt_buttonInit(" 📷 ", NULL, 300, -165, 10);
self.cameraButton -> shape = TT_BUTTON_SHAPE_ROUNDED_RECTANGLE;
self.redChannel = tt_sliderInit("", NULL, TT_SLIDER_TYPE_HORIZONTAL, TT_SLIDER_ALIGN_CENTER, self.sidebarX, 120, 10, 80, 0, 255, 0);
self.redChannel -> value = 255;
self.redChannel -> defaultValue = self.redChannel -> value;
self.greenChannel = tt_sliderInit("", NULL, TT_SLIDER_TYPE_HORIZONTAL, TT_SLIDER_ALIGN_CENTER, self.sidebarX, 100, 10, 80, 0, 255, 0);
self.greenChannel -> value = 255;
self.greenChannel -> defaultValue = self.greenChannel -> value;
self.blueChannel = tt_sliderInit("", NULL, TT_SLIDER_TYPE_HORIZONTAL, TT_SLIDER_ALIGN_CENTER, self.sidebarX, 80, 10, 80, 0, 255, 0);
self.blueChannel -> value = 255;
self.blueChannel -> defaultValue = self.blueChannel -> value;
self.sizeSlider = tt_sliderInit("", NULL, TT_SLIDER_TYPE_HORIZONTAL, TT_SLIDER_ALIGN_CENTER, self.sidebarX, 60, 10, 80, 1, 25, 0);
self.sizeSlider -> value = 5;
self.sizeSlider -> defaultValue = self.sizeSlider -> value;
}
void render() {
/* canvas */
// turtleTexture(self.transparentTexture, self.canvasX - self.canvasWidth / 2, self.canvasY + self.canvasHeight / 2, self.canvasX + self.canvasWidth / 2, self.canvasY - self.canvasHeight / 2, 0, 255, 255, 255);
turtleTexture(self.transparentTexture, (self.canvasX + self.editingX - self.canvasWidth / 2) * self.editingZoom, (self.canvasY + self.editingY + self.canvasHeight / 2) * self.editingZoom, (self.canvasX + self.editingX + self.canvasWidth / 2) * self.editingZoom, (self.canvasY + self.editingY - self.canvasHeight / 2) * self.editingZoom, 0, 255, 255, 255);
for (int32_t drawIndex = 0; drawIndex < self.draw -> length; drawIndex += DRAW_INDEX_NUMBER_OF_FIELDS) {
if (self.draw -> data[drawIndex + DRAW_INDEX_PEN_DOWN].i == 0) {
turtlePenUp();
}
turtleGoto((self.draw -> data[drawIndex + DRAW_INDEX_X].d + self.editingX + self.canvasX) * self.editingZoom, (self.draw -> data[drawIndex + DRAW_INDEX_Y].d + self.editingY + self.canvasY) * self.editingZoom);
turtlePenSize(self.draw -> data[drawIndex + DRAW_INDEX_SIZE].d * self.editingZoom);
turtlePenColorAlpha(self.draw -> data[drawIndex + DRAW_INDEX_RED].d, self.draw -> data[drawIndex + DRAW_INDEX_GREEN].d, self.draw -> data[drawIndex + DRAW_INDEX_BLUE].d, self.draw -> data[drawIndex + DRAW_INDEX_ALPHA].d);
if (self.draw -> data[drawIndex + DRAW_INDEX_PEN_DOWN].i) {
turtlePenDown();
}
}
turtlePenUp();
turtleGoto(turtle.mouseX, turtle.mouseY);
turtlePenSize(self.sizeSlider -> value * self.editingZoom);
turtlePenColorAlpha(self.redChannel -> value, self.greenChannel -> value, self.blueChannel -> value, 0.0);
turtlePenDown();
turtlePenUp();
/* occlude */
tt_setColor(TT_COLOR_BACKGROUND);
turtleRectangle(-320, -180, 320, self.canvasY - self.canvasHeight / 2);
turtleRectangle(-320, 180, 320, self.canvasY + self.canvasHeight / 2);
turtleRectangle(-320, 180, self.canvasX - self.canvasWidth / 2, -180);
turtleRectangle(320, 180, self.canvasX + self.canvasWidth / 2, -180);
/* handle camera button */
if (self.cameraButton -> value) {
self.cameraButton -> value = 0;
self.cameraAnimation = 1;
}
/* handle RGB slider sync */
if (self.lockOffsets) {
if (self.redChannel -> value != self.redSave) {
double offset = self.redChannel -> value - self.redSave;
if (self.greenSave + offset > 255) {
offset = 255 - self.greenSave;
}
if (self.blueSave + offset > 255) {
offset = 255 - self.blueSave;
}
if (self.greenSave + offset < 0) {
offset = 0 - self.greenSave;
}
if (self.blueSave + offset < 0) {
offset = 0 - self.blueSave;
}
self.redChannel -> value = self.redSave + offset;
self.greenChannel -> value = self.greenSave + offset;
self.blueChannel -> value = self.blueSave + offset;
self.greenSave = self.greenChannel -> value;
self.blueSave = self.blueChannel -> value;
self.redSave = self.redChannel -> value;
}
if (self.greenChannel -> value != self.greenSave) {
double offset = self.greenChannel -> value - self.greenSave;
if (self.redSave + offset > 255) {
offset = 255 - self.redSave;
}
if (self.blueSave + offset > 255) {
offset = 255 - self.blueSave;
}
if (self.redSave + offset < 0) {
offset = 0 - self.redSave;
}
if (self.blueSave + offset < 0) {
offset = 0 - self.blueSave;
}
self.greenChannel -> value = self.greenSave + offset;
self.redChannel -> value = self.redSave + offset;
self.blueChannel -> value = self.blueSave + offset;
self.redSave = self.redChannel -> value;
self.blueSave = self.blueChannel -> value;
self.greenSave = self.greenChannel -> value;
}
if (self.blueChannel -> value != self.blueSave) {
double offset = self.blueChannel -> value - self.blueSave;
if (self.greenSave + offset > 255) {
offset = 255 - self.greenSave;
}
if (self.redSave + offset > 255) {
offset = 255 - self.redSave;
}
if (self.greenSave + offset < 0) {
offset = 0 - self.greenSave;
}
if (self.redSave + offset < 0) {
offset = 0 - self.redSave;
}
self.blueChannel -> value = self.blueSave + offset;
self.greenChannel -> value = self.greenSave + offset;
self.redChannel -> value = self.redSave + offset;
self.greenSave = self.greenChannel -> value;
self.redSave = self.redChannel -> value;
self.blueSave = self.blueChannel -> value;
}
}
/* render annotations to sliders */
tt_setColor(TT_COLOR_TEXT);
turtleTextWriteString("Red", self.redChannel -> x - self.redChannel -> length / 2 - self.redChannel -> size, self.redChannel -> y, self.redChannel -> size - 1, 100);
turtleTextWriteStringf(self.redChannel -> x + self.redChannel -> length / 2 + self.redChannel -> size, self.redChannel -> y, self.redChannel -> size - 1, 0, "%.0lf", round(self.redChannel -> value));
turtleTextWriteString("Green", self.greenChannel -> x -self. greenChannel -> length / 2 - self.greenChannel -> size, self.greenChannel -> y, self.greenChannel -> size - 1, 100);
turtleTextWriteStringf(self.greenChannel -> x + self.greenChannel -> length / 2 + self.greenChannel -> size, self.greenChannel -> y, self.greenChannel -> size - 1, 0, "%.0lf", round(self.greenChannel -> value));
turtleTextWriteString("Blue", self.blueChannel -> x - self.blueChannel -> length / 2 - self.blueChannel -> size, self.blueChannel -> y, self.blueChannel -> size - 1, 100);
turtleTextWriteStringf(self.blueChannel -> x + self.blueChannel -> length / 2 + self.blueChannel -> size, self.blueChannel -> y, self.blueChannel -> size - 1, 0, "%.0lf", round(self.blueChannel -> value));
turtleTextWriteString("Size", self.sizeSlider -> x - self.sizeSlider -> length / 2 - self.sizeSlider -> size, self.sizeSlider -> y, self.sizeSlider -> size - 1, 100);
turtleTextWriteStringf(self.sizeSlider -> x + self.sizeSlider -> length / 2 + self.sizeSlider -> size, self.sizeSlider -> y, self.sizeSlider -> size - 1, 0, "%.0lf", round(self.sizeSlider -> value));
turtlePenColor(self.redChannel -> value, self.greenChannel -> value, self.blueChannel -> value);
turtlePenSize(16);
turtleGoto(self.sidebarX, 40);
turtlePenDown();
turtlePenUp();
}
void frameBoundsCheck() {
if ((self.canvasX + self.canvasWidth / 2 + self.editingX) * self.editingZoom < self.canvasX + self.canvasWidth / 2) {
self.editingX = (self.canvasX + self.canvasWidth / 2) / self.editingZoom - self.canvasX - self.canvasWidth / 2;
}
if ((self.canvasX - self.canvasWidth / 2 + self.editingX) * self.editingZoom > self.canvasX - self.canvasWidth / 2) {
self.editingX = (self.canvasX - self.canvasWidth / 2) / self.editingZoom - self.canvasX + self.canvasWidth / 2;
}
if ((self.canvasY + self.canvasHeight / 2 + self.editingY) * self.editingZoom < self.canvasY + self.canvasHeight / 2) {
self.editingY = (self.canvasY + self.canvasHeight / 2) / self.editingZoom - self.canvasY - self.canvasHeight / 2;
}
if ((self.canvasY - self.canvasHeight / 2 + self.editingY) * self.editingZoom > self.canvasY - self.canvasHeight / 2) {
self.editingY = (self.canvasY - self.canvasHeight / 2) / self.editingZoom - self.canvasY + self.canvasHeight / 2;
}
}
void mouse() {
if (turtleKeyPressed(GLFW_KEY_LEFT_SHIFT)) {
self.keys[EDITOR_KEYS_LEFT_SHIFT] = 1;
if (self.lockOffsets == 0) {
self.lockOffsets = 1;
self.redSave = self.redChannel -> value;
self.greenSave = self.greenChannel -> value;
self.blueSave = self.blueChannel -> value;
}
} else {
self.lockOffsets = 0;
self.keys[EDITOR_KEYS_LEFT_SHIFT] = 0;
}
if (turtleMouseLeft()) {
if (self.keys[EDITOR_KEYS_LMB] == 0) {
self.keys[EDITOR_KEYS_LMB] = 1;
if (turtle.mouseX >= self.canvasX - self.canvasWidth / 2 && turtle.mouseX <= self.canvasX + self.canvasWidth / 2 && turtle.mouseY >= self.canvasY - self.canvasHeight / 2 && turtle.mouseY <= self.canvasY + self.canvasHeight / 2) {
list_append(self.draw, (unitype) self.redChannel -> value, 'i'); // DRAW_INDEX_RED
list_append(self.draw, (unitype) self.greenChannel -> value, 'i'); // DRAW_INDEX_GREEN
list_append(self.draw, (unitype) self.blueChannel -> value, 'i'); // DRAW_INDEX_BLUE
list_append(self.draw, (unitype) 0, 'i'); // DRAW_INDEX_ALPHA
list_append(self.draw, (unitype) self.sizeSlider -> value, 'd'); // DRAW_INDEX_SIZE
list_append(self.draw, (unitype) (turtle.mouseX / self.editingZoom - self.editingX - self.canvasX), 'd'); // DRAW_INDEX_X
list_append(self.draw, (unitype) (turtle.mouseY / self.editingZoom - self.editingY - self.canvasY), 'd'); // DRAW_INDEX_Y
list_append(self.draw, (unitype) 0, 'i'); // DRAW_INDEX_PEN_DOWN
self.drawing = 1;
}
}
if (self.drawing) {
list_append(self.draw, (unitype) self.redChannel -> value, 'd'); // DRAW_INDEX_RED
list_append(self.draw, (unitype) self.greenChannel -> value, 'd'); // DRAW_INDEX_GREEN
list_append(self.draw, (unitype) self.blueChannel -> value, 'd'); // DRAW_INDEX_BLUE
list_append(self.draw, (unitype) 0.0, 'd'); // DRAW_INDEX_ALPHA
list_append(self.draw, (unitype) self.sizeSlider -> value, 'd'); // DRAW_INDEX_SIZE
list_append(self.draw, (unitype) (turtle.mouseX / self.editingZoom - self.editingX - self.canvasX), 'd'); // DRAW_INDEX_X
list_append(self.draw, (unitype) (turtle.mouseY / self.editingZoom - self.editingY - self.canvasY), 'd'); // DRAW_INDEX_Y
list_append(self.draw, (unitype) 1, 'i'); // DRAW_INDEX_PEN_DOWN
}
} else {
self.keys[EDITOR_KEYS_LMB] = 0;
self.drawing = 0;
}
if (turtleMouseRight()) {
if (self.keys[EDITOR_KEYS_RMB] == 0) {
self.keys[EDITOR_KEYS_RMB] = 1;
if (turtle.mouseX >= self.canvasX - self.canvasWidth / 2 && turtle.mouseX <= self.canvasX + self.canvasWidth / 2 && turtle.mouseY >= self.canvasY - self.canvasHeight / 2 && turtle.mouseY <= self.canvasY + self.canvasHeight / 2) {
self.anchorEditingX = self.editingX;
self.anchorEditingY = self.editingY;
self.anchorMouseX = turtle.mouseX;
self.anchorMouseY = turtle.mouseY;
self.editingMoving = 1;
}
} else {
if (self.editingMoving) {
self.editingX = self.anchorEditingX + (turtle.mouseX - self.anchorMouseX) / self.editingZoom;
self.editingY = self.anchorEditingY + (turtle.mouseY - self.anchorMouseY) / self.editingZoom;
frameBoundsCheck();
}
}
} else {
self.keys[EDITOR_KEYS_RMB] = 0;
}
/* scrollwheel */
double scroll = turtleMouseWheel();
if (scroll > 0) {
if (turtle.mouseX >= self.canvasX - self.canvasWidth / 2 && turtle.mouseX <= self.canvasX + self.canvasWidth / 2 && turtle.mouseY >= self.canvasY - self.canvasHeight / 2 && turtle.mouseY <= self.canvasY + self.canvasHeight / 2) {
/* zoom in (frame) */
const double scrollSpeed = 1.1;
self.editingX -= (turtle.mouseX * (-1 / scrollSpeed + 1)) / self.editingZoom;
self.editingY -= (turtle.mouseY * (-1 / scrollSpeed + 1)) / self.editingZoom;
self.editingZoom *= scrollSpeed;
frameBoundsCheck();
}
} else if (scroll < 0) {
if (turtle.mouseX >= self.canvasX - self.canvasWidth / 2 && turtle.mouseX <= self.canvasX + self.canvasWidth / 2 && turtle.mouseY >= self.canvasY - self.canvasHeight / 2 && turtle.mouseY <= self.canvasY + self.canvasHeight / 2) {
/* zoom out (frame) */
const double scrollSpeed = 1.1;
self.editingZoom /= scrollSpeed;
if (self.editingZoom < 1) {
self.editingZoom = 1;
}
self.editingX += (turtle.mouseX * (-1 / scrollSpeed + 1)) / self.editingZoom;
self.editingY += (turtle.mouseY * (-1 / scrollSpeed + 1)) / self.editingZoom;
frameBoundsCheck();
}
}
}
void parseRibbonOutput() {
if (tt_ribbon.output[0] == 0) {
return;
}
tt_ribbon.output[0] = 0;
if (tt_ribbon.output[1] == 0) { // File
if (tt_ribbon.output[2] == 1) { // New
list_clear(osToolsFileDialog.selectedFilenames);
list_clear(self.draw);
printf("New\n");
}
if (tt_ribbon.output[2] == 2) { // Save
if (osToolsFileDialog.selectedFilenames -> length == 0) {
if (osToolsFileDialogSave(OSTOOLS_FILE_DIALOG_FILE, "Save.txt", NULL) != -1) {
printf("Saved to: %s\n", osToolsFileDialog.selectedFilenames -> data[0].s);
}
} else {
printf("Saved to: %s\n", osToolsFileDialog.selectedFilenames -> data[0].s);
}
}
if (tt_ribbon.output[2] == 3) { // Save As...
list_clear(osToolsFileDialog.selectedFilenames);
if (osToolsFileDialogSave(OSTOOLS_FILE_DIALOG_FILE, "Save.txt", NULL) != -1) {
printf("Saved to: %s\n", osToolsFileDialog.selectedFilenames -> data[0].s);
}
}
if (tt_ribbon.output[2] == 4) { // Open
list_clear(osToolsFileDialog.selectedFilenames);
if (osToolsFileDialogOpen(OSTOOLS_FILE_DIALOG_MULTIPLE_SELECT, OSTOOLS_FILE_DIALOG_FILE, "", NULL) != -1) {
printf("Loaded data from: ");
list_print(osToolsFileDialog.selectedFilenames);
}
}
}
if (tt_ribbon.output[1] == 1) { // View
if (tt_ribbon.output[2] == 1) { // Change theme
if (tt_theme == TT_THEME_DARK) {
turtleBackgroundColor(36, 30, 32);
turtleToolsSetTheme(TT_THEME_COLT);
printf("Theme: Colt\n");
} else if (tt_theme == TT_THEME_COLT) {
turtleBackgroundColor(212, 201, 190);
turtleToolsSetTheme(TT_THEME_NAVY);
printf("Theme: Navy\n");
} else if (tt_theme == TT_THEME_NAVY) {
turtleBackgroundColor(255, 255, 255);
turtleToolsSetTheme(TT_THEME_LIGHT);
printf("Theme: Light\n");
} else if (tt_theme == TT_THEME_LIGHT) {
turtleBackgroundColor(30, 30, 30);
turtleToolsSetTheme(TT_THEME_DARK);
printf("Theme: Dark\n");
}
}
}
}
int main(int argc, char *argv[]) {
/* Initialise window */
GLFWwindow *window = turtleCreateWindow(TURTLE_WINDOW_DEFAULT_WIDTH, TURTLE_WINDOW_DEFAULT_HEIGHT, "draw mouse demo");
/* initialise turtle */
turtleInit(window, -320, -180, 320, 180);
/* initialise turtleText */
turtleTextInit("config/roberto.tgl");
/* initialise ribbon */
list_t *ribbonConfig = list_init();
list_append(ribbonConfig, (unitype) "File, 📄 New, 📄 Save, 📄 Save As..., 📄 Open", 's');
list_append(ribbonConfig, (unitype) "View, Change Theme", 's');
tt_ribbonInitList(ribbonConfig);
/* initialise osTools */
osToolsInit(argv[0], window);
init();
uint32_t tps = 60; // ticks per second (locked to fps in this case)
uint64_t tick = 0; // count number of ticks since application started
clock_t start, end;
while (turtle.close == 0) {
start = clock();
turtleClear(); // clear the screen
turtleGetMouseCoordinates();
mouse();
render();
parseRibbonOutput(); // user defined function to use ribbon
turtleToolsUpdate(); // update turtleTools
/* render camera flash (in front of all UI) */
if (self.cameraAnimation > 0) {
turtleRectangleColor(-320, -180, 320, 180, 255, 255, 255, self.cameraAnimation * 10);
self.cameraAnimation++;
if (self.cameraAnimation > 25) {
self.cameraAnimation = 0;
}
}
turtleUpdate(); // update the screen
end = clock();
while ((double) (end - start) / CLOCKS_PER_SEC < (1.0 / tps)) {
end = clock();
}
tick++;
}
turtleFree();
glfwTerminate();
}