From 078a02d9f161250f5a07eacbb55298ecce4702e8 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Thu, 15 Dec 2022 18:09:56 -0600 Subject: [PATCH] Palette editing is working. --- CMakeLists.txt | 1 + include/color.h | 2 +- include/common.h | 2 +- include/config.h.in | 3 + include/palette.h | 30 ++++++++ src/color.c | 9 +-- src/draw.c | 21 ++---- src/palette.c | 172 ++++++++++++++++++++++++++++++++++++++++++++ src/vector.c | 41 +++++++++-- ui/Vector.glade | 3 +- 10 files changed, 258 insertions(+), 26 deletions(-) create mode 100644 include/palette.h create mode 100644 src/palette.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c06cc5..b12127d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ set(SOURCE_FILES src/image.c src/vecparse.c src/color.c + src/palette.c ) configure_file(include/config.h.in config.h) diff --git a/include/color.h b/include/color.h index 3c0d526..41cdbbb 100644 --- a/include/color.h +++ b/include/color.h @@ -35,7 +35,7 @@ typedef struct ColorS { int color_dialog_get_selected(GtkWidget *colorDialog); -GtkWidget *color_dialog_new(GtkWidget *parent, ColorT colors[]); +GtkWidget *color_dialog_new(GtkWidget *parent, char *title, ColorT colors[]); #endif //COLOR_H diff --git a/include/common.h b/include/common.h index 34e7d8b..4977d04 100644 --- a/include/common.h +++ b/include/common.h @@ -29,7 +29,7 @@ #include "array.h" -#ifdef DEBUG_OUTPUTx +#ifdef DEBUG_OUTPUT #define debug(...) printf(__VA_ARGS__) #define MEMWATCH #else diff --git a/include/config.h.in b/include/config.h.in index c62ba40..ad7b657 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -29,6 +29,9 @@ #define JOEYDEV_VERSION "@joeydev_VERSION_MAJOR@.@joeydev_VERSION_MINOR@" +#define VICTOR_VERSION "1.0" // Used for file format versioning. + + #cmakedefine DEBUG_OUTPUT diff --git a/include/palette.h b/include/palette.h new file mode 100644 index 0000000..e08ac29 --- /dev/null +++ b/include/palette.h @@ -0,0 +1,30 @@ +/* + * JoeyDev + * Copyright (C) 2018-2023 Scott Duensing + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef PALETTE_H +#define PALETTE_H + +void palette_dialog_get_color(GtkWidget *paletteDialog, unsigned char *r, unsigned char *g, unsigned char *b); +GtkWidget *palette_dialog_new(GtkWidget *parent, char *title, unsigned char r, unsigned char g, unsigned char b); + + +#endif // PALETTE_H diff --git a/src/color.c b/src/color.c index c266e3e..b20ef5f 100644 --- a/src/color.c +++ b/src/color.c @@ -84,7 +84,7 @@ int color_dialog_get_selected(GtkWidget *colorDialog) { } -GtkWidget *color_dialog_new(GtkWidget *parent, ColorT colors[]) { +GtkWidget *color_dialog_new(GtkWidget *parent, char *title, ColorT colors[]) { GtkWidget *dialog; GtkWidget *contentArea; GtkWidget *grid; @@ -107,15 +107,16 @@ GtkWidget *color_dialog_new(GtkWidget *parent, ColorT colors[]) { gtk_widget_set_hexpand(self->buttons[i], TRUE); gtk_widget_set_vexpand(self->buttons[i], TRUE); g_signal_connect(G_OBJECT(self->buttons[i]), "clicked", G_CALLBACK(colorClicked), self); - snprintf(temp, 256, "* { background-image:none; background-color: #%02x%02x%02x; }", colors[i].red, colors[i].green, colors[i].blue); + snprintf(temp, 256, "* { background-image:none; background-color: #%02x%02x%02x; }", colors[i].red * 16, colors[i].green * 16, colors[i].blue * 16); addCss(self->buttons[i], temp); - gtk_grid_attach(GTK_GRID (grid), self->buttons[i], x, y, 1, 1); + gtk_grid_attach(GTK_GRID(grid), self->buttons[i], x, y, 1, 1); i++; } } - dialog = gtk_dialog_new_with_buttons("Color", + dialog = gtk_dialog_new_with_buttons( + title, GTK_WINDOW(parent), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, "_Cancel", diff --git a/src/draw.c b/src/draw.c index b0f4498..259ebfd 100644 --- a/src/draw.c +++ b/src/draw.c @@ -376,17 +376,15 @@ jbyte jlDrawPixelGet(jlContextT *c, jint16 x, jint16 y) { void jlDrawPixelSet(jlContextT *c, jint16 x, jint16 y) { unsigned int offset = (x + y * 320) * 4; - c->_pixels[offset] = c->_jlPalette[c->_jlDrawColor].b; - c->_pixels[offset + 1] = c->_jlPalette[c->_jlDrawColor].g; - c->_pixels[offset + 2] = c->_jlPalette[c->_jlDrawColor].r; + c->_pixels[offset] = c->_jlPalette[c->_jlDrawColor].b * 16; + c->_pixels[offset + 1] = c->_jlPalette[c->_jlDrawColor].g * 16; + c->_pixels[offset + 2] = c->_jlPalette[c->_jlDrawColor].r * 16; // We're using CAIRO_FORMAT_RGB24 so the upper 8 bits are not used. c->_pixels[offset + 3] = 255; // This is alpha in CAIRO_FORMAT_ARGB32 mode. } void jlPaletteDefault(jlContextT *c) { - jbyte i; - // Set palette. c->_jlPalette[ 0].r = 0; c->_jlPalette[ 0].g = 0; c->_jlPalette[ 0].b = 0; // 000000 Black c->_jlPalette[ 1].r = 0; c->_jlPalette[ 1].g = 0; c->_jlPalette[ 1].b = 10; // 0000AA Blue @@ -404,13 +402,6 @@ void jlPaletteDefault(jlContextT *c) { c->_jlPalette[13].r = 15; c->_jlPalette[13].g = 5; c->_jlPalette[13].b = 15; // FF55FF Bright Magenta c->_jlPalette[14].r = 15; c->_jlPalette[14].g = 15; c->_jlPalette[14].b = 5; // FFFF55 Bright Yellow c->_jlPalette[15].r = 15; c->_jlPalette[15].g = 15; c->_jlPalette[15].b = 15; // FFFFFF White - - // Adjust 4 bit color values to 8 bit. - for (i=0; i<16; i++) { - c->_jlPalette[i].r *= 16; - c->_jlPalette[i].g *= 16; - c->_jlPalette[i].b *= 16; - } } @@ -423,9 +414,9 @@ void jlPaletteGet(jlContextT *c, jbyte index, jbyte *r, jbyte *g, jbyte *b) { void jlPaletteSet(jlContextT *c, jbyte index, jbyte r, jbyte g, jbyte b) { - c->_jlPalette[index].r = r * 16; - c->_jlPalette[index].g = g * 16; - c->_jlPalette[index].b = b * 16; + c->_jlPalette[index].r = r; + c->_jlPalette[index].g = g; + c->_jlPalette[index].b = b; } diff --git a/src/palette.c b/src/palette.c new file mode 100644 index 0000000..62227ef --- /dev/null +++ b/src/palette.c @@ -0,0 +1,172 @@ +/* + * JoeyDev + * Copyright (C) 2018-2023 Scott Duensing + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "common.h" +#include "palette.h" + + +typedef struct PaletteDialogDataS { + GtkWidget *drawingArea; + GtkAdjustment *adjustmentRed; + GtkAdjustment *adjustmentGreen; + GtkAdjustment *adjustmentBlue; + GtkWidget *scaleRed; + GtkWidget *scaleGreen; + GtkWidget *scaleBlue; +} PaletteDialogDataT; + + +EVENT gboolean paletteDialogClose(GtkWidget *widget, GdkEvent *event, gpointer userData); +EVENT gboolean paletteDialogDraw(GtkWidget *widget, cairo_t *cr, gpointer userData); +EVENT void paletteValueChanged(GtkRange *widget, gpointer userData); + + +EVENT gboolean paletteDialogClose(GtkWidget *widget, GdkEvent *event, gpointer userData) { + PaletteDialogDataT *self = g_object_get_data(G_OBJECT(widget), "paletteData"); + + (void)event; + (void)userData; + + DEL(self); + + return FALSE; +} + + +EVENT gboolean paletteDialogDraw(GtkWidget *widget, cairo_t *cr, gpointer userData) { + PaletteDialogDataT *self = (PaletteDialogDataT *)userData; + double scale = 1.0/16.0; + double r; + double g; + double b; + + (void)widget; + + r = gtk_adjustment_get_value(self->adjustmentRed); + g = gtk_adjustment_get_value(self->adjustmentGreen); + b = gtk_adjustment_get_value(self->adjustmentBlue); + + cairo_set_source_rgb(cr, r * scale, g * scale, b * scale); + cairo_paint(cr); + + return FALSE; +} + + +EVENT void paletteValueChanged(GtkRange *widget, gpointer userData) { + PaletteDialogDataT *self = (PaletteDialogDataT *)userData; + + (void)widget; + + // Refresh widget. + gtk_widget_queue_draw(self->drawingArea); +} + + +void palette_dialog_get_color(GtkWidget *paletteDialog, unsigned char *r, unsigned char *g, unsigned char *b) { + PaletteDialogDataT *self = g_object_get_data(G_OBJECT(paletteDialog), "paletteData"); + + *r = (int)gtk_adjustment_get_value(self->adjustmentRed); + *g = (int)gtk_adjustment_get_value(self->adjustmentGreen); + *b = (int)gtk_adjustment_get_value(self->adjustmentBlue); +} + + +GtkWidget *palette_dialog_new(GtkWidget *parent, char *title, unsigned char r, unsigned char g, unsigned char b) { + GtkWidget *dialog; + GtkWidget *contentArea; + PaletteDialogDataT *self; + GtkWidget *vbox; + GtkWidget *grid; + GtkWidget *labelRed; + GtkWidget *labelGreen; + GtkWidget *labelBlue; + + self = NEW(PaletteDialogDataT); + + vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_box_set_spacing(vbox, 10); + + self->drawingArea = gtk_drawing_area_new(); + gtk_widget_set_size_request(self->drawingArea, 128, 64); + g_signal_connect(G_OBJECT(self->drawingArea), "draw", G_CALLBACK(paletteDialogDraw), self); + + grid = gtk_grid_new(); + gtk_grid_set_column_spacing(grid, 10); + gtk_grid_set_row_spacing(grid, 10); + + labelRed = gtk_label_new("Red:"); + labelGreen = gtk_label_new("Green:"); + labelBlue = gtk_label_new("Blue:"); + gtk_widget_set_halign(labelRed, GTK_ALIGN_END); + gtk_widget_set_halign(labelGreen, GTK_ALIGN_END); + gtk_widget_set_halign(labelBlue, GTK_ALIGN_END); + + self->adjustmentRed = gtk_adjustment_new((double)r, 0.0, 15.0, 1.0, 4.0, 0.00); + self->adjustmentGreen = gtk_adjustment_new((double)g, 0.0, 15.0, 1.0, 4.0, 0.00); + self->adjustmentBlue = gtk_adjustment_new((double)b, 0.0, 15.0, 1.0, 4.0, 0.00); + + self->scaleRed = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, self->adjustmentRed); + self->scaleGreen = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, self->adjustmentGreen); + self->scaleBlue = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, self->adjustmentBlue); + gtk_scale_set_draw_value(GTK_SCALE(self->scaleRed), FALSE); + gtk_scale_set_draw_value(GTK_SCALE(self->scaleGreen), FALSE); + gtk_scale_set_draw_value(GTK_SCALE(self->scaleBlue), FALSE); + gtk_range_set_round_digits(GTK_RANGE(self->scaleRed), 0); + gtk_range_set_round_digits(GTK_RANGE(self->scaleGreen), 0); + gtk_range_set_round_digits(GTK_RANGE(self->scaleBlue), 0); + gtk_widget_set_hexpand(self->scaleRed, TRUE); + gtk_widget_set_hexpand(self->scaleGreen, TRUE); + gtk_widget_set_hexpand(self->scaleBlue, TRUE); + g_signal_connect(G_OBJECT(self->scaleRed), "value-changed", G_CALLBACK(paletteValueChanged), self); + g_signal_connect(G_OBJECT(self->scaleGreen), "value-changed", G_CALLBACK(paletteValueChanged), self); + g_signal_connect(G_OBJECT(self->scaleBlue), "value-changed", G_CALLBACK(paletteValueChanged), self); + + dialog = gtk_dialog_new_with_buttons( + title, + GTK_WINDOW(parent), + GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Select", + GTK_RESPONSE_OK, + NULL + ); + g_signal_connect(G_OBJECT(dialog), "destroy", G_CALLBACK(paletteDialogClose), self); + g_object_set_data(G_OBJECT(dialog), "paletteData", self); + contentArea = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); + + gtk_grid_attach(GTK_GRID(grid), labelRed, 0, 0, 1, 1); + gtk_grid_attach(GTK_GRID(grid), labelGreen, 0, 1, 1, 1); + gtk_grid_attach(GTK_GRID(grid), labelBlue, 0, 2, 1, 1); + gtk_grid_attach(GTK_GRID(grid), self->scaleRed, 1, 0, 1, 1); + gtk_grid_attach(GTK_GRID(grid), self->scaleGreen, 1, 1, 1, 1); + gtk_grid_attach(GTK_GRID(grid), self->scaleBlue, 1, 2, 1, 1); + + gtk_container_add(GTK_CONTAINER(vbox), self->drawingArea); + gtk_container_add(GTK_CONTAINER(vbox), grid); + gtk_container_add(GTK_CONTAINER(contentArea), vbox); + + gtk_widget_show_all(dialog); + + return dialog; +} diff --git a/src/vector.c b/src/vector.c index c689600..3eec23d 100644 --- a/src/vector.c +++ b/src/vector.c @@ -26,9 +26,10 @@ #pragma ide diagnostic ignored "hicpp-multiway-paths-covered" -#include "common.h" #include #include + +#include "common.h" #include "scintillaHeaders.h" #include "vector.h" #include "utils.h" @@ -36,9 +37,9 @@ #include "image.h" #include "vecparse.h" #include "color.h" +#include "palette.h" -#define VICTOR_VERSION "1.00" #define RENDER_TIMEOUT 5 // In seconds #define SSM(m, w, l) scintilla_send_message(self->sci, m, w, l) @@ -1274,7 +1275,7 @@ EVENT void toolColorClicked(GtkToolButton *object, gpointer userData) { } // Build the dialog. - dialog = color_dialog_new(self->windowData.window, colors); + dialog = color_dialog_new(self->windowData.window, "Select Color", colors); // Run the dialog. if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) { @@ -1325,9 +1326,41 @@ EVENT void toolLineClicked(GtkToolButton *object, gpointer userData) { EVENT void toolPaletteClicked(GtkToolButton *object, gpointer userData) { - VectorDataT *self = (VectorDataT *)userData; + VectorDataT *self = (VectorDataT *)userData; + GtkWidget *colorDialog; + GtkWidget *paletteDialog; + ColorT colors[16]; + char temp[32]; + int i; (void)object; + + // Load the current JoeyLib palette into the dialog. + for (i=0; i<16; i++) { + jlPaletteGet(self->jlc, i, &colors[i].red, &colors[i].green, &colors[i].blue); + } + + // Build the dialog. + colorDialog = color_dialog_new(self->windowData.window, "Select Color to Edit", colors); + + // Run the dialog. + if (gtk_dialog_run(GTK_DIALOG(colorDialog)) == GTK_RESPONSE_OK) { + i = color_dialog_get_selected(colorDialog); + if (i >= 0) { + // User selected a color, now edit it. + paletteDialog = palette_dialog_new(colorDialog, "Edit Palette Entry", colors[i].red, colors[i].green, colors[i].blue); + if (gtk_dialog_run(GTK_DIALOG(paletteDialog)) == GTK_RESPONSE_OK) { + palette_dialog_get_color(paletteDialog, &colors[i].red, &colors[i].green, &colors[i].blue); + // Write our new palette entry into the editor. + snprintf(temp, 32, "%d as %d,%d,%d", i, colors[i].red, colors[i].green, colors[i].blue); + insertCommand(self, "palette"); + insertText(self, temp); + } + gtk_widget_destroy(paletteDialog); + } + } + + gtk_widget_destroy(colorDialog); } diff --git a/ui/Vector.glade b/ui/Vector.glade index 9166cac..d93f72c 100644 --- a/ui/Vector.glade +++ b/ui/Vector.glade @@ -1,5 +1,5 @@ -