/*
* Copyright (c) 2002-2007 Hypertriton, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include
#include
#include
#include
struct rg_fill_tool {
MAP_Tool tool;
enum fill_mode {
FILL_FROM_CLIPBRD,
FILL_FROM_ART,
FILL_CLEAR
} mode;
int randomize_angle;
};
static void
init(void *p)
{
struct rg_fill_tool *fi = p;
fi->mode = FILL_FROM_ART;
fi->randomize_angle = 0;
MAP_ToolPushStatus(fi, _("Select a node and fill with $(L)."));
}
static void
pane(void *p, void *con)
{
struct rg_fill_tool *fi = p;
static const char *mode_items[] = {
N_("Clipboard pattern"),
N_("Source artwork"),
N_("Clear"),
NULL
};
AG_RadioNewUint(con, AG_RADIO_HFILL, mode_items, &fi->mode);
AG_CheckboxNewInt(con, 0, _("Randomize angle"), &fi->randomize_angle);
}
static int
effect(void *p, MAP_Node *n)
{
struct rg_fill_tool *fi = p;
MAP_View *mv = TOOL(fi)->mv;
MAP *m = mv->map;
MAP *copybuf = &mapEditor.copybuf;
int sx = 0, sy = 0, dx = 0, dy = 0;
int dw = m->mapw, dh = m->maph;
int x, y;
AG_TlistItem *it;
RG_Tile *tile;
#if 0
int i = 0;
#endif
MAP_ViewGetSelection(mv, &dx, &dy, &dw, &dh);
MAP_ModBegin(m);
switch (fi->mode) {
case FILL_FROM_CLIPBRD:
if (copybuf->mapw == 0 || copybuf->maph == 0) {
AG_TextMsg(AG_MSG_ERROR, _("The clipboard is empty."));
return (1);
}
for (y = dy; y < dy+dh; y++) {
for (x = dx; x < dx+dw; x++) {
MAP_Node *sn = ©buf->map[sy][sx];
MAP_Node *dn = &m->map[y][x];
MAP_Item *r;
MAP_ModNodeChg(m, x, y);
MAP_NodeRemoveAll(m, dn, m->cur_layer);
TAILQ_FOREACH(r, &sn->nrefs, nrefs) {
MAP_NodeCopyItem(r, m, dn,
m->cur_layer);
}
if (++sx >= (int)copybuf->mapw)
sx = 0;
}
}
if (++sy >= (int)copybuf->maph) {
sy = 0;
}
break;
case FILL_FROM_ART:
if (mv->lib_tl == NULL ||
(it = AG_TlistSelectedItem(mv->lib_tl)) == NULL ||
strcmp(it->cat, "tile") != 0) {
break;
}
tile = it->p1;
for (y = dy; y < dy+dh; y++) {
for (x = dx; x < dx+dw; x++) {
MAP_Node *n = &m->map[y][x];
MAP_Item *r;
MAP_ModNodeChg(m, x, y);
MAP_NodeRemoveAll(m, n, m->cur_layer);
r = Malloc(sizeof(MAP_Item));
MAP_ItemInit(r, MAP_ITEM_TILE);
MAP_ItemSetTile(r, m, tile->ts, tile->main_id);
MAP_ItemSetLayer(r, m->cur_layer);
r->r_gfx.xorigin = tile->xOrig;
r->r_gfx.yorigin = tile->yOrig;
r->r_gfx.xcenter = MAPTILESZ/2;
r->r_gfx.ycenter = MAPTILESZ/2;
TAILQ_INSERT_TAIL(&n->nrefs, r, nrefs);
#if 0
if (fi->randomize_angle) {
Uint32 rand = 0;
Uint8 byte = 0;
switch (i++) {
case 0:
rand = arc4random();
byte = (rand&0xff000000) >> 24;
break;
case 1:
byte = (rand&0x00ff0000) >> 16;
break;
case 2:
byte = (rand&0x0000ff00) >> 8;
break;
case 3:
byte = (rand&0x000000ff);
i = 0;
break;
}
if (byte < 60) {
RG_TransformRotate(r, 0);
} else if (byte < 120) {
RG_TransformRotate(r, 90);
} else if (byte < 180) {
RG_TransformRotate(r, 180);
} else if (byte < 240) {
RG_TransformRotate(r, 270);
}
}
#endif
}
}
break;
case FILL_CLEAR:
for (y = dy; y < dy+dh; y++) {
for (x = dx; x < dx+dw; x++) {
MAP_ModNodeChg(m, x, y);
MAP_NodeRemoveAll(m, &m->map[y][x],
m->cur_layer);
}
}
break;
}
MAP_ModEnd(m);
return (1);
}
const MAP_ToolOps mapFillOps = {
"Fill", N_("Clear/fill layer"),
&mapIconFill,
sizeof(struct rg_fill_tool),
0,
init,
NULL, /* destroy */
pane,
NULL, /* edit */
NULL, /* cursor */
effect,
NULL, /* mousemotion */
NULL, /* mousebuttondown */
NULL, /* mousebuttonup */
NULL, /* keydown */
NULL, /* keyup */
};