/* * Copyright (c) 2002-2022 Julien Nadeau Carriere * 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 #include #include #include #include #include #include #include #include #include #include /* * Insert a static map item (MAP_Item). */ static void Init(void *_Nonnull obj) { MAP_InsertTool *tool = obj; tool->snap_mode = RG_SNAP_NONE; tool->replace_mode = 0; tool->angle = 0; // AG_ObjectInitStatic(&tool->mTmp, &mapClass); tool->mvTmp = NULL; MAP_ToolPushStatus(tool, _("Select a position and Left-Click to Insert. " "Use Middle-Click to Rotate.")); } static void Destroy(void *_Nonnull obj) { // MAP_InsertTool *tool = obj; // AG_ObjectDestroy(&tool->mTmp); } #if 0 static void SnapTile(MAP_InsertTool *_Nonnull tool, MAP_Item *_Nonnull mi, RG_Tile *_Nonnull tile) { MAP_View *mv = TOOL(tool)->mv; switch (tool->snap_mode) { case RG_SNAP_NONE: mi->data.tile.xCenter += mv->cxoffs * MAP_TILESZ_DEF / MAP_TILESZ(mv); mi->data.tile.yCenter += mv->cyoffs * MAP_TILESZ_DEF / MAP_TILESZ(mv); break; default: break; } } #endif #if 0 static void GenerateTileMap(MAP_InsertTool *_Nonnull tool, RG_Tile *_Nonnull tile) { MAP *mapTmp = &tool->mTmp; int sy,sx, dx,dy; int sw = tile->su->w / MAP_TILESZ_DEF; int sh = tile->su->h / MAP_TILESZ_DEF; if (tile->su->w % MAP_TILESZ_DEF > 0) sw++; if (tile->su->h % MAP_TILESZ_DEF > 0) sh++; MAP_AllocNodes(mapTmp, sw, sh); mapTmp->xOrigin = tile->xOrig / MAP_TILESZ_DEF; mapTmp->yOrigin = tile->yOrig / MAP_TILESZ_DEF; for (sy=0, dy=0; sy < tile->su->h; sy += MAP_TILESZ_DEF, dy++) { for (sx=0, dx=0; sx < tile->su->w; sx += MAP_TILESZ_DEF, dx++) { MAP_Tile *mt; int dw,dh, nlayer; if (dx >= (int)mapTmp->w || dy >= (int)mapTmp->h) continue; dw = tile->su->w - sx; dh = tile->su->h - sy; mt = MAP_TileNew(mapTmp, &mapTmp->map[dy][dx], tile->ts, tile->main_id); mt->rs.x = dx * MAP_TILESZ_DEF; mt->rs.y = dy * MAP_TILESZ_DEF; mt->rs.w = (dw >= MAP_TILESZ_DEF) ? MAP_TILESZ_DEF : dw; mt->rs.h = (dh >= MAP_TILESZ_DEF) ? MAP_TILESZ_DEF : dh; MAPITEM(mt)->flags |= RG_TILE_ATTR2(tile,dx,dy); nlayer = RG_TILE_LAYER2(tile,dx,dy); if (nlayer < 0) { nlayer = 0; } else { if (nlayer >= (int)mapTmp->nLayers) MAP_PushLayer(mapTmp, ""); } MAPITEM(mt)->layer = nlayer; /* XXX also need to rotate the whole map */ // RG_TransformRotate(mt, tool->angle); } } } #endif static void EditPane(void *_Nonnull obj, void *_Nonnull con) { #if 0 MAP_InsertTool *tool = obj; AG_TlistItem *it; MAP_View *mvMain = TOOL(tool)->mv; MAP_View *mv; RG_Tile *tile; AG_Notebook *nb; AG_NotebookTab *nt; if ((it = AG_TlistSelectedItem(mvMain->lib_tl)) == NULL || strcmp(it->cat, "tile") != 0) { return; } tile = it->p1; nb = AG_NotebookNew(con, AG_NOTEBOOK_EXPAND); nt = AG_NotebookAdd(nb, _("Tiles"), AG_BOX_VERT); { mv = tool->mvTmp = MAP_ViewNew(nt, &tool->mTmp, MAP_VIEW_EDIT | MAP_VIEW_GRID, NULL, NULL); MAP_ViewSizeHint(mv, 7,7); MAP_ViewSelectTool(mv, MAP_ViewRegTool(mv, &mapNodeselOps, &tool->mTmp), &tool->mTmp); GenerateTileMap(tool, tile); } nt = AG_NotebookAdd(nb, _("Settings"), AG_BOX_VERT); { AG_Numerical *num; AG_LabelNewS(nt, 0, _("Snap to: ")); AG_RadioNewUint(nt, AG_RADIO_HFILL, rgTileSnapModes, &tool->snap_mode); AG_CheckboxNewInt(nt, 0, _("Replace mode"), &tool->replace_mode); num = AG_NumericalNewIntR(nt, 0, "deg", _("Rotation: "), &tool->angle, 0, 360); AG_SetInt(num, "inc", 90); } #endif } static int Effect(void *_Nonnull obj, MAP_Node *_Nonnull node) { #if 0 MAP_InsertTool *tool = obj; MAP_View *mv = TOOL(tool)->mv; MAP *mapSrc = &tool->mTmp; MAP *mapDst = mv->map; AG_TlistItem *it; int sx, sy, sx0, sy0, sx1, sy1; int dx, dy, dx0, dy0; const int tileSz = MAP_TILESZ(mv); if (mv->lib_tl == NULL || (it = AG_TlistSelectedItem(mv->lib_tl)) == 0 || strcmp(it->cat, "tile") != 0) { return (1); } /* tile = it->p1; */ if (tool->mvTmp->esel.set) { sx0 = tool->mvTmp->esel.x; sy0 = tool->mvTmp->esel.y; sx1 = sx0 + tool->mvTmp->esel.w - 1; sy1 = sy0 + tool->mvTmp->esel.h - 1; dx0 = mv->cx; dy0 = mv->cy; } else { sx0 = 0; sy0 = 0; sx1 = mapSrc->w - 1; sy1 = mapSrc->h - 1; dx0 = mv->cx - mapSrc->xOrigin; dy0 = mv->cy - mapSrc->yOrigin; } MAP_BeginRevision(mapDst); for (sy=sy0, dy=dy0; sy <= sy1 && dy < (int)mapDst->h; sy++, dy++) { for (sx = sx0, dx = dx0; sx <= sx1 && dx < (int)mapDst->w; sx++, dx++) { MAP_Node *sn, *dn; MAP_Item *miSrc, *mi; if (dx < 0 || dx >= (int)mapDst->w || dy < 0 || dy >= (int)mapDst->h) { continue; } sn = &mapSrc->map[sy][sx]; dn = &mapDst->map[dy][dx]; MAP_NodeRevision(mapDst, dx,dy, map->undo, map->nUndo); if (tool->replace_mode) { MAP_NodeClear(mapDst, dn, mapDst->layerCur); } TAILQ_FOREACH(miSrc, &sn->items, items) { mi = MAP_DuplicateItem(miSrc, mapDst, dn, -1); mi->layer += mapDst->layerCur; while (mi->layer >= mapDst->nLayers) { if (MAP_PushLayer(mapDst, "") == 0) MAP_ChangeLayerAdd(mapDst, mapDst->nLayers - 1); } if (mi->type == MAP_ITEM_TILE && tool->snap_mode == RG_SNAP_NONE) { MAP_Tile *mt = MAPTILE(mi); mt->xCenter += mv->cxoffs * MAP_TILESZ_DEF / tileSz; mt->yCenter += mv->cyoffs * MAP_TILESZ_DEF / tileSz; } } } } MAP_CommitRevision(mapDst); #endif return (1); } static int Cursor(void *_Nonnull obj, AG_Rect *_Nonnull rd) { #if 0 MAP_InsertTool *tool = obj; MAP_View *mv = TOOL(tool)->mv; MAP *mapSrc = &tool->mTmp; AG_TlistItem *it; RG_Tile *tile; AG_Rect r; AG_Color c; const int tileSz = MAP_TILESZ(mv); int sx0, sy0, sx1, sy1; int dx0, dy0; int dx, dy, sx, sy; if (mv->lib_tl == NULL || (it = AG_TlistSelectedItem(mv->lib_tl)) == NULL || strcmp(it->cat, "tile") != 0 || (tile = it->p1) == NULL || tile->su == NULL) { return (-1); } if (tool->snap_mode == RG_SNAP_NONE) { r.x = rd->x + 1; r.y = rd->y + 1; r.w = tileSz - 1; r.h = tileSz - 1; AG_ColorRGB_8(&c, 200,200,200); AG_DrawRectOutline(mv, &r, &c); } if (tool->mvTmp->esel.set) { sx0 = tool->mvTmp->esel.x; sy0 = tool->mvTmp->esel.y; sx1 = sx0 + tool->mvTmp->esel.w - 1; sy1 = sy0 + tool->mvTmp->esel.h - 1; dx0 = WIDGET(mv)->rView.x1 + rd->x; dy0 = WIDGET(mv)->rView.y1 + rd->y; } else { sx0 = 0; sy0 = 0; sx1 = mapSrc->w - 1; sy1 = mapSrc->h - 1; dx0 = WIDGET(mv)->rView.x1 + rd->x - mapSrc->xOrigin * tileSz; dy0 = WIDGET(mv)->rView.y1 + rd->y - mapSrc->yOrigin * tileSz; } if (tool->snap_mode == RG_SNAP_NONE) { dx0 += mv->cxoffs * MAP_TILESZ_DEF / tileSz; dy0 += mv->cyoffs * MAP_TILESZ_DEF / tileSz; } for (sy = sy0, dy = dy0; sy <= sy1; sy++, dy += tileSz) { for (sx = sx0, dx = dx0; sx <= sx1; sx++, dx += tileSz) { MAP_Node *sn = &mapSrc->map[sy][sx]; MAP_Item *mi; TAILQ_FOREACH(mi, &sn->items, items) MAP_ItemDraw(mv->map, mi, dx,dy, mv->cam); } } #endif return (0); } static int MouseButtonDown(void *_Nonnull obj, int x, int y, int btn) { MAP_InsertTool *tool = obj; if (btn == AG_MOUSE_MIDDLE) { tool->angle = (tool->angle + 90) % 360; return (1); } return (0); } static int MouseMotion(void *_Nonnull obj, int x, int y, int xrel, int yrel) { MAP_InsertTool *tool = obj; MAP_View *mv = TOOL(tool)->mv; const int tileSz = MAP_TILESZ(mv); const int nx = x / tileSz; const int ny = y / tileSz; AG_TlistItem *it; if (nx == mv->mouse.x && ny == mv->mouse.y) return (0); if ((it = AG_TlistSelectedItem(mv->lib_tl)) == NULL || mv->cx == -1 || mv->cy == -1) { return (1); } if (strcmp(it->cat, "tile") == 0) { MAP_ToolSetStatus(tool, _("Insert %s tile at [%d,%d] (Click Left = Confirm | Middle = Rotate)."), it->text, mv->cx, mv->cy); } return (0); } const MAP_ToolOps mapInsertOps = { "Insert", N_("Insert static map item"), &mapIconStamp, sizeof(MAP_InsertTool), 0, 1, Init, Destroy, EditPane, NULL, /* edit */ Cursor, Effect, MouseMotion, MouseButtonDown, NULL, /* mousebuttonup */ NULL, /* keydown */ NULL /* keyup */ };