Show datgrid.c syntax highlighted
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* Grabber plugin for the grab-from-grid and autocrop functions.
*
* By Shawn Hargreaves.
*
* See readme.txt for copyright information.
*/
#include <stdio.h>
#include <string.h>
#include "allegro.h"
#include "../datedit.h"
static int gg_text_proc(int msg, AL_DIALOG *d, int c);
static int gg_edit_proc(int msg, AL_DIALOG *d, int c);
static void *added_item[1024];
static int added_count;
/* helper for cropping bitmaps */
static AL_BITMAP *crop_bitmap(AL_BITMAP *bmp, int *tx, int *ty)
{
int tw, th, i, j, c;
int changed = FALSE;
*tx = 0;
*ty = 0;
tw = bmp->w;
th = bmp->h;
if ((tw > 0) && (th > 0)) {
c = al_get_pixel(bmp, 0, 0);
for (j=*ty; j<(*ty)+th; j++) { /* top of image */
for (i=*tx; i<(*tx)+tw; i++) {
if (al_get_pixel(bmp, i, j) != c)
goto finishedtop;
}
(*ty)++;
th--;
changed = TRUE;
}
finishedtop:
for (j=(*ty)+th-1; j>*ty; j--) { /* bottom of image */
for (i=*tx; i<(*tx)+tw; i++) {
if (al_get_pixel(bmp, i, j) != c)
goto finishedbottom;
}
th--;
changed = TRUE;
}
finishedbottom:
for (j=*tx; j<*(tx)+tw; j++) { /* left of image */
for (i=*ty; i<(*ty)+th; i++) {
if (al_get_pixel(bmp, j, i) != c)
goto finishedleft;
}
(*tx)++;
tw--;
changed = TRUE;
}
finishedleft:
for (j=*(tx)+tw-1; j>*tx; j--) { /* right of image */
for (i=*ty; i<(*ty)+th; i++) {
if (al_get_pixel(bmp, j, i) != c)
goto finishedright;
}
tw--;
changed = TRUE;
}
finishedright:
;
}
if ((tw != 0) && (th != 0) && (changed)) {
AL_BITMAP *b2 = al_create_bitmap_ex(al_bitmap_color_depth(bmp), tw, th);
al_clear_to_color(b2, b2->vtable->mask_color);
al_blit(bmp, b2, *tx, *ty, 0, 0, tw, th);
al_destroy_bitmap(bmp);
return b2;
}
else
return bmp;
}
/* worker function for counting bitmap objects */
static int do_bitmap_check(AL_DATAFILE *dat, int *param, int param2)
{
if ((dat->type == DAT_BITMAP) || (dat->type == DAT_RLE_SPRITE) ||
(dat->type == DAT_C_SPRITE) || (dat->type == DAT_XC_SPRITE))
(*param)++;
return D_O_K;
}
/* checks whether our grab-from-grid command is allowed at the moment */
static int griddler_query(int popup)
{
AL_DATAFILE *dat;
AL_CONST char *s;
if (popup) {
dat = grabber_single_selection();
if (!dat)
return FALSE;
if ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
(dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE))
return FALSE;
s = al_get_datafile_property(dat, DAT_NAME);
if ((s[0]) && (al_uisdigit(s[strlen(s)-1])))
return TRUE;
else
return FALSE;
}
return TRUE;
}
/* checks whether a bitmap contains any data */
static int bitmap_is_empty(AL_BITMAP *bmp)
{
int x, y;
int c = al_get_pixel(bmp, 0, 0);
for (y=0; y<bmp->h; y++)
for (x=0; x<bmp->w; x++)
if (al_get_pixel(bmp, x, y) != c)
return FALSE;
return TRUE;
}
/* helper for grabbing images from a grid */
static void *griddlit(AL_DATAFILE **parent, AL_CONST char *name, int c, int type, int skipempty, int autocrop, int depth, int x, int y, int w, int h)
{
AL_DATAFILE *dat;
AL_BITMAP *bmp;
void *v;
char buf[256];
AL_RGB tmprgb = datedit_current_palette[0];
int tx = 0, ty = 0;
if ((type == DAT_RLE_SPRITE) || (type == DAT_C_SPRITE) || (type == DAT_XC_SPRITE)) {
datedit_current_palette[0].r = 63;
datedit_current_palette[0].g = 0;
datedit_current_palette[0].b = 63;
}
al_select_palette(datedit_current_palette);
bmp = al_create_bitmap_ex(depth, w, h);
al_clear_to_color(bmp, bmp->vtable->mask_color);
al_blit(grabber_graphic, bmp, x, y, 0, 0, w, h);
al_unselect_palette();
datedit_current_palette[0] = tmprgb;
if ((skipempty) && (bitmap_is_empty(bmp))) {
al_destroy_bitmap(bmp);
return NULL;
}
if (autocrop)
bmp = crop_bitmap(bmp, &tx, &ty);
if (type == DAT_RLE_SPRITE) {
v = al_create_rle_sprite(bmp);
al_destroy_bitmap(bmp);
}
else
v = bmp;
sprintf(buf, "%s%03d", name, c);
*parent = datedit_insert(*parent, &dat, buf, type, v, 0);
sprintf(buf, "%d", x);
datedit_set_property(dat, DAT_XPOS, buf);
sprintf(buf, "%d", y);
datedit_set_property(dat, DAT_YPOS, buf);
sprintf(buf, "%d", w);
datedit_set_property(dat, DAT_XSIZ, buf);
sprintf(buf, "%d", h);
datedit_set_property(dat, DAT_YSIZ, buf);
if (tx || ty) {
sprintf(buf, "%d", tx);
datedit_set_property(dat, DAT_XCRP, buf);
sprintf(buf, "%d", ty);
datedit_set_property(dat, DAT_YCRP, buf);
}
datedit_set_property(dat, DAT_ORIG, grabber_graphic_origin);
datedit_set_property(dat, DAT_DATE, grabber_graphic_date);
datedit_sort_properties(dat->prop);
if (added_count < (int)(sizeof(added_item)/sizeof(added_item[0])))
added_item[added_count++] = v;
return v;
}
/* grabs images from a grid, using boxes of color #255 */
static void *box_griddle(AL_DATAFILE **parent, AL_CONST char *name, int type, int skipempty, int autocrop, int depth)
{
void *ret = NULL;
void *item;
int x, y, w, h;
int c = 0;
x = 0;
y = 0;
datedit_find_character(grabber_graphic, &x, &y, &w, &h);
while ((w > 0) && (h > 0)) {
item = griddlit(parent, name, c, type, skipempty, autocrop, depth, x+1, y+1, w, h);
if (item) {
c++;
if (!ret)
ret = item;
}
x += w;
datedit_find_character(grabber_graphic, &x, &y, &w, &h);
}
return ret;
}
/* grabs images from a regular grid */
static void *grid_griddle(AL_DATAFILE **parent, AL_CONST char *name, int type, int skipempty, int autocrop, int depth, int xgrid, int ygrid)
{
void *ret = NULL;
void *item;
int x, y;
int c = 0;
for (y=0; y+ygrid<=grabber_graphic->h; y+=ygrid) {
for (x=0; x+xgrid<=grabber_graphic->w; x+=xgrid) {
item = griddlit(parent, name, c, type, skipempty, autocrop, depth, x, y, xgrid, ygrid);
if (item) {
c++;
if (!ret)
ret = item;
}
}
}
return ret;
}
static char griddle_xgrid[8] = "32";
static char griddle_ygrid[8] = "32";
static char griddle_name[256] = "";
/* dialog callback for retrieving the contents of the object type list */
static AL_CONST char *typelist_getter(int index, int *list_size)
{
static char *str[] =
{
"Bitmap",
"RLE Sprite",
"Compiled Sprite",
"Mode-X Compiled Sprite"
};
if (index < 0) {
if (list_size)
*list_size = 4;
return NULL;
}
return str[index];
}
/* dialog callback for retrieving the contents of the color depth list */
static AL_CONST char *depthlist_getter(int index, int *list_size)
{
static char *str[] =
{
"256 color palette",
"15 bit hicolor",
"16 bit hicolor",
"24 bit truecolor",
"32 bit truecolor"
};
if (index < 0) {
if (list_size)
*list_size = 5;
return NULL;
}
return str[index];
}
static AL_DIALOG griddle_dlg[] =
{
/* (dialog proc) (x) (y) (w) (h) (fg) (bg) (al_key) (flags) (d1) (d2) (dp) (dp2) (dp3) */
{ al_dialog_shadow_box_proc, 0, 0, 277, 305, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
{ al_dialog_ctext_proc, 138, 8, 0, 0, 0, 0, 0, 0, 0, 0, "Grab from Grid", NULL, NULL },
{ al_dialog_radio_proc, 16, 32, 121, 13, 0, 0, 0, D_SELECTED, 0, 0, "Use col #255", NULL, NULL },
{ al_dialog_radio_proc, 16, 56, 121, 13, 0, 0, 0, 0, 0, 0, "Regular grid", NULL, NULL },
{ gg_text_proc, 160, 58, 0, 0, 0, 0, 0, 0, 0, 0, "X-grid:", NULL, NULL },
{ gg_edit_proc, 224, 58, 40, 8, 0, 0, 0, 0, 4, 0, griddle_xgrid, NULL, NULL },
{ gg_text_proc, 160, 80, 0, 0, 0, 0, 0, 0, 0, 0, "Y-grid:", NULL, NULL },
{ gg_edit_proc, 224, 82, 40, 8, 0, 0, 0, 0, 4, 0, griddle_ygrid, NULL, NULL },
{ al_dialog_check_proc, 16, 82, 123, 13, 0, 0, 0, 0, 0, 0, "Skip empties:", NULL, NULL },
{ al_dialog_check_proc, 16, 106, 91, 13, 0, 0, 0, 0, 0, 0, "Autocrop:", NULL, NULL },
{ al_dialog_text_proc, 16, 138, 0, 0, 0, 0, 0, 0, 0, 0, "Name:", NULL, NULL },
{ al_dialog_edit_proc, 64, 138, 204, 8, 0, 0, 0, 0, 255, 0, griddle_name, NULL, NULL },
{ al_dialog_text_proc, 16, 160, 0, 0, 0, 0, 0, 0, 0, 0, "Type:", NULL, NULL },
{ al_dialog_list_proc, 64, 160, 197, 36, 0, 0, 0, 0, 0, 0, (void*)typelist_getter, NULL, NULL },
{ al_dialog_text_proc, 16, 208, 0, 0, 0, 0, 0, 0, 0, 0, "Cols:", NULL, NULL },
{ al_dialog_list_proc, 64, 208, 197, 44, 0, 0, 0, 0, 0, 0, (void*)depthlist_getter, NULL, NULL },
{ al_dialog_button_proc, 50, 272, 81, 17, 0, 0, 13, D_EXIT, 0, 0, "OK", NULL, NULL },
{ al_dialog_button_proc, 146, 272, 81, 17, 0, 0, 27, D_EXIT, 0, 0, "Cancel", NULL, NULL },
{ NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
};
#define GRIDDLE_DLG_BOXES 2
#define GRIDDLE_DLG_GRID 3
#define GRIDDLE_DLG_XGRID 5
#define GRIDDLE_DLG_YGRID 7
#define GRIDDLE_DLG_EMPTIES 8
#define GRIDDLE_DLG_AUTOCROP 9
#define GRIDDLE_DLG_NAME 11
#define GRIDDLE_DLG_TYPE 13
#define GRIDDLE_DLG_DEPTH 15
#define GRIDDLE_DLG_OK 16
#define GRIDDLE_DLG_CANCEL 17
/* wrapper for al_dialog_text_proc, that greys out when invalid */
static int gg_text_proc(int msg, AL_DIALOG *d, int c)
{
if (msg == MSG_IDLE) {
int valid = (griddle_dlg[GRIDDLE_DLG_BOXES].flags & D_SELECTED) ? 0 : 1;
int enabled = (d->flags & D_DISABLED) ? 0 : 1;
if (valid != enabled) {
if (valid)
d->flags &= ~D_DISABLED;
else
d->flags |= D_DISABLED;
al_show_mouse(NULL);
al_object_message(d, MSG_DRAW, 0);
al_show_mouse(al_screen);
}
return D_O_K;
}
else
return al_dialog_text_proc(msg, d, c);
}
/* wrapper for al_dialog_edit_proc, that greys out when invalid */
static int gg_edit_proc(int msg, AL_DIALOG *d, int c)
{
if (msg == MSG_IDLE) {
int valid = (griddle_dlg[GRIDDLE_DLG_BOXES].flags & D_SELECTED) ? 0 : 1;
int enabled = (d->flags & D_DISABLED) ? 0 : 1;
if (valid != enabled) {
if (valid)
d->flags &= ~D_DISABLED;
else
d->flags |= D_DISABLED;
al_show_mouse(NULL);
al_object_message(d, MSG_DRAW, 0);
al_show_mouse(al_screen);
}
return D_O_K;
}
else
return al_dialog_edit_proc(msg, d, c);
}
/* checks whether an object name matches the grid grab base name */
static int grid_name_matches(AL_CONST char *gn, AL_CONST char *n)
{
AL_CONST char *s;
if (strncmp(gn, n, strlen(gn)) != 0)
return FALSE;
s = n + strlen(gn);
if (*s == 0)
return FALSE;
while (*s) {
if (!al_uisdigit(*s))
return FALSE;
s++;
}
return TRUE;
}
/* handle the griddle command */
static int griddler(void)
{
AL_DATAFILE *dat;
AL_DATAFILE **parent;
void *selitem;
char *s;
int c;
int xgrid, ygrid;
int done, type, skipempty, autocrop;
int depth = 8;
if (!grabber_graphic) {
al_show_alert("You must read in a bitmap file",
"before you can grab data from it",
NULL, "OK", NULL, 13, 0);
return D_O_K;
}
grabber_get_selection_info(&dat, &parent);
if (!dat) {
griddle_name[0] = 0;
depth = al_bitmap_color_depth(grabber_graphic);
}
else {
strcpy(griddle_name, al_get_datafile_property(dat, DAT_NAME));
s = griddle_name + strlen(griddle_name) - 1;
while ((s >= griddle_name) && (al_uisdigit(*s))) {
*s = 0;
s--;
}
if (dat->type == DAT_BITMAP) {
griddle_dlg[GRIDDLE_DLG_TYPE].d1 = 0;
depth = al_bitmap_color_depth(dat->dat);
}
else if (dat->type == DAT_RLE_SPRITE) {
griddle_dlg[GRIDDLE_DLG_TYPE].d1 = 1;
depth = ((AL_RLE_SPRITE *)dat->dat)->color_depth;
}
else if (dat->type == DAT_C_SPRITE) {
griddle_dlg[GRIDDLE_DLG_TYPE].d1 = 2;
depth = al_bitmap_color_depth(dat->dat);
}
else if (dat->type == DAT_XC_SPRITE) {
griddle_dlg[GRIDDLE_DLG_TYPE].d1 = 3;
depth = 8;
}
}
if (depth == 8)
griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 0;
else if (depth == 15)
griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 1;
else if (depth == 16)
griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 2;
else if (depth == 24)
griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 3;
else if (depth == 32)
griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 4;
al_centre_dialog(griddle_dlg);
al_set_dialog_color(griddle_dlg, al_gui_fg_color, al_gui_bg_color);
if (al_do_dialog(griddle_dlg, GRIDDLE_DLG_NAME) == GRIDDLE_DLG_CANCEL)
return D_REDRAW;
grabber_sel_palette(grabber_palette);
do {
done = TRUE;
for (c=0; (*parent)[c].type != DAT_END; c++) {
if (grid_name_matches(griddle_name, al_get_datafile_property((*parent)+c, DAT_NAME))) {
*parent = datedit_delete(*parent, c);
done = FALSE;
break;
}
}
} while (!done);
switch (griddle_dlg[GRIDDLE_DLG_TYPE].d1) {
case 0:
default:
type = DAT_BITMAP;
break;
case 1:
type = DAT_RLE_SPRITE;
break;
case 2:
type = DAT_C_SPRITE;
break;
case 3:
type = DAT_XC_SPRITE;
break;
}
switch (griddle_dlg[GRIDDLE_DLG_DEPTH].d1) {
case 0:
default:
depth = 8;
break;
case 1:
depth = 15;
break;
case 2:
depth = 16;
break;
case 3:
depth = 24;
break;
case 4:
depth = 32;
break;
}
skipempty = griddle_dlg[GRIDDLE_DLG_EMPTIES].flags & D_SELECTED;
autocrop = griddle_dlg[GRIDDLE_DLG_AUTOCROP].flags & D_SELECTED;
added_count = 0;
if (griddle_dlg[GRIDDLE_DLG_BOXES].flags & D_SELECTED)
selitem = box_griddle(parent, griddle_name, type, skipempty, autocrop, depth);
else {
xgrid = MID(1, atoi(griddle_xgrid), 0xFFFF);
ygrid = MID(1, atoi(griddle_ygrid), 0xFFFF);
selitem = grid_griddle(parent, griddle_name, type, skipempty, autocrop, depth, xgrid, ygrid);
}
datedit_sort_datafile(*parent);
grabber_rebuild_list(selitem, TRUE);
grabber_select_property(DAT_NAME);
for (c=0; c<added_count; c++)
grabber_set_selection(added_item[c]);
if (selitem) {
grabber_sel_palette(grabber_palette);
grabber_modified(1);
}
else
al_show_alert("No grid found - nothing grabbed!", NULL, NULL, "Hmm...", NULL, 13, 0);
al_set_config_string("grabber", "griddle_xgrid", griddle_xgrid);
al_set_config_string("grabber", "griddle_ygrid", griddle_ygrid);
if (griddle_dlg[GRIDDLE_DLG_BOXES].flags & D_SELECTED)
al_set_config_string("grabber", "griddle_mode", "boxes");
else
al_set_config_string("grabber", "griddle_mode", "grid");
if (griddle_dlg[GRIDDLE_DLG_EMPTIES].flags & D_SELECTED)
al_set_config_string("grabber", "griddle_empties", "y");
else
al_set_config_string("grabber", "griddle_empties", "n");
if (griddle_dlg[GRIDDLE_DLG_AUTOCROP].flags & D_SELECTED)
al_set_config_string("grabber", "griddle_autocrop", "y");
else
al_set_config_string("grabber", "griddle_autocrop", "n");
al_set_config_int("grabber", "griddle_type", griddle_dlg[GRIDDLE_DLG_TYPE].d1);
return D_REDRAW;
}
/* worker function for cropping an image */
static int do_autocropper(AL_DATAFILE *dat, int *param, int param2)
{
AL_BITMAP *bmp;
AL_RLE_SPRITE *spr;
char buf[256];
int tx, ty;
if ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
(dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE)) {
(*param)++;
return D_O_K;
}
if (dat->type == DAT_RLE_SPRITE) {
spr = (AL_RLE_SPRITE *)dat->dat;
bmp = al_create_bitmap_ex(spr->color_depth, spr->w, spr->h);
al_clear_to_color(bmp, bmp->vtable->mask_color);
al_draw_rle_sprite(bmp, spr, 0, 0);
al_destroy_rle_sprite(spr);
bmp = crop_bitmap(bmp, &tx, &ty);
dat->dat = al_create_rle_sprite(bmp);
al_destroy_bitmap(bmp);
}
else
dat->dat = crop_bitmap((AL_BITMAP *)dat->dat, &tx, &ty);
if (tx || ty) {
sprintf(buf, "%d", tx);
datedit_set_property(dat, DAT_XCRP, buf);
sprintf(buf, "%d", ty);
datedit_set_property(dat, DAT_YCRP, buf);
}
grabber_modified(1);
return D_REDRAW;
}
/* checks whether our autocrop command is allowed at the moment */
static int autocrop_query(int popup)
{
int n, p;
if (popup) {
p = 0;
grabber_foreach_selection(do_bitmap_check, &n, &p, 0);
return (p > 0);
}
return TRUE;
}
/* menu hook for the autocrop command */
static int autocrop(void)
{
char buf[80];
int ret, n;
int p = 0;
ret = grabber_foreach_selection(do_autocropper, &n, &p, 0);
if (n <= 0) {
al_show_alert ("Nothing to crop!", NULL, NULL, "OK", NULL, 13, 0);
}
else if (p > 0) {
sprintf(buf, "%d non-bitmap object%s ignored", p, (p==1) ? " was" : "s were");
al_show_alert(buf, NULL, NULL, "OK", NULL, 13, 0);
}
return ret;
}
/* initialisation code for the grab-from-grid plugin */
void datgrid_init()
{
int i;
if (al_screen) {
if (AL_SCREEN_H < 400) {
griddle_dlg[0].h = griddle_dlg[0].h * 2/3;
for (i=1; griddle_dlg[i].proc; i++) {
griddle_dlg[i].y = griddle_dlg[i].y * 2/3;
if (griddle_dlg[i].h > 32)
griddle_dlg[i].h -= 8;
}
}
}
sprintf(griddle_xgrid, "%d", al_get_config_int("grabber", "griddle_xgrid", 32));
sprintf(griddle_ygrid, "%d", al_get_config_int("grabber", "griddle_ygrid", 32));
if (stricmp(al_get_config_string("grabber", "griddle_mode", ""), "grid") == 0) {
griddle_dlg[GRIDDLE_DLG_BOXES].flags &= ~D_SELECTED;
griddle_dlg[GRIDDLE_DLG_GRID].flags |= D_SELECTED;
}
else {
griddle_dlg[GRIDDLE_DLG_BOXES].flags |= D_SELECTED;
griddle_dlg[GRIDDLE_DLG_GRID].flags &= ~D_SELECTED;
}
if (strpbrk(al_get_config_string("grabber", "griddle_empties", ""), "yY1"))
griddle_dlg[GRIDDLE_DLG_EMPTIES].flags |= D_SELECTED;
else
griddle_dlg[GRIDDLE_DLG_EMPTIES].flags &= ~D_SELECTED;
if (strpbrk(al_get_config_string("grabber", "griddle_autocrop", ""), "yY1"))
griddle_dlg[GRIDDLE_DLG_AUTOCROP].flags |= D_SELECTED;
else
griddle_dlg[GRIDDLE_DLG_AUTOCROP].flags &= ~D_SELECTED;
griddle_dlg[GRIDDLE_DLG_TYPE].d1 = al_get_config_int("grabber", "griddle_type", 0);
}
/* hook ourselves into the grabber menu system */
static AL_MENU griddler_menu =
{
"Grab from Grid",
griddler,
NULL,
0,
NULL
};
DATEDIT_MENU_INFO datgrid_griddler_menu =
{
&griddler_menu,
griddler_query,
DATEDIT_MENU_FILE | DATEDIT_MENU_POPUP,
0
};
static AL_MENU autocrop_menu =
{
"Autocrop",
autocrop,
NULL,
0,
NULL
};
DATEDIT_MENU_INFO datgrid_autocrop_menu =
{
&autocrop_menu,
autocrop_query,
DATEDIT_MENU_OBJECT | DATEDIT_MENU_POPUP,
0
};
See more files for this project here