Add CTileset::getTileNumber and fillSolidTiles

cleanup editloop.cpp
Use loop.
This commit is contained in:
joris 2013-04-19 12:49:04 +02:00
parent c348a93f61
commit 2773438529
5 changed files with 301 additions and 355 deletions

View file

@ -174,74 +174,26 @@ static EditorSliderListener *editorSliderListener;
-- Edit
----------------------------------------------------------------------------*/
/**
** Get tile number.
**
** @param basic Basic tile number
** @param random Return random tile
** @param filler Get a decorated tile.
**
** @return Tile number used in pud.
**
** @todo FIXME: Solid tiles are here still hardcoded.
*/
static int GetTileNumber(int basic, int random, int filler)
{
int tile = basic;
if (random) {
int i, n;
for (n = i = 0; i < 16; ++i) {
if (!Map.Tileset->Table[tile + i]) {
if (!filler) {
break;
}
} else {
++n;
}
}
n = MyRand() % n;
i = -1;
do {
while (++i < 16 && !Map.Tileset->Table[tile + i]) {
}
} while (i < 16 && n--);
Assert(i != 16);
return tile + i;
}
if (filler) {
int i = 0;
for (; i < 16 && Map.Tileset->Table[tile + i]; ++i) {
}
for (; i < 16 && !Map.Tileset->Table[tile + i]; ++i) {
}
if (i != 16) {
return tile + i;
}
}
return tile;
}
/**
** Edit tile.
**
** @param pos map tile coordinate.
** @param tile Tile type to edit.
*/
void EditTile(const Vec2i &pos, int tile)
static void EditTile(const Vec2i &pos, int tile)
{
Assert(Map.Info.IsPointOnMap(pos));
ChangeTile(pos, GetTileNumber(tile, TileToolRandom, TileToolDecoration));
int tileIndex = Map.Tileset->findTileIndexByTile(tile);
ChangeTile(pos, Map.Tileset->getTileNumber(tileIndex, TileToolRandom, TileToolDecoration));
//
// Change the flags
//
CMapField *mf = Map.Field(pos);
mf->Flags &= ~(MapFieldHuman | MapFieldLandAllowed | MapFieldCoastAllowed |
MapFieldWaterAllowed | MapFieldNoBuilding | MapFieldUnpassable |
MapFieldWall | MapFieldRocks | MapFieldForest);
mf->Flags |= Map.Tileset->FlagsTable[GetTileNumber(tile, 0, 0)];
CMapField &mf = *Map.Field(pos);
mf.Flags &= ~(MapFieldHuman | MapFieldLandAllowed | MapFieldCoastAllowed |
MapFieldWaterAllowed | MapFieldNoBuilding | MapFieldUnpassable |
MapFieldWall | MapFieldRocks | MapFieldForest);
mf.Flags |= Map.Tileset->FlagsTable[tileIndex];
UI.Minimap.UpdateSeenXY(pos);
UI.Minimap.UpdateXY(pos);
@ -281,7 +233,7 @@ static void EditTilesInternal(const Vec2i &pos, int tile, int size)
** @param tile Tile type to edit.
** @param size Size of rectangle
*/
void EditTiles(const Vec2i &pos, int tile, int size)
static void EditTiles(const Vec2i &pos, int tile, int size)
{
EditTilesInternal(pos, tile, size);
@ -717,7 +669,6 @@ static void DrawTileIcon(unsigned tilenum, unsigned x, unsigned y, unsigned flag
*/
static void DrawTileIcons()
{
int i;
CLabel label(GetGameFont());
int x = UI.InfoPanel.X + 46;
int y = UI.InfoPanel.Y + 4 + IconHeight + 11;
@ -745,8 +696,7 @@ static void DrawTileIcons()
//MenuButtonG->DrawFrame(MBUTTON_GEM_SQUARE + (TileToolDecoration ? 2 : 0), x + 40, y - 3);
y += 20;
unsigned int tile;
i = Editor.TileIndex;
int i = Editor.TileIndex;
Assert(Editor.TileIndex != -1);
y = UI.ButtonPanel.Y + 24;
while (y < UI.ButtonPanel.Y + ButtonPanelHeight - PixelTileSize.y) {
@ -758,9 +708,9 @@ static void DrawTileIcons()
if (i >= (int) Editor.ShownTileTypes.size()) {
break;
}
tile = Editor.ShownTileTypes[i];
unsigned int tile = Editor.ShownTileTypes[i];
Map.TileGraphic->DrawFrameClip(Map.Tileset->Table[tile], x, y);
Map.TileGraphic->DrawFrameClip(tile, x, y);
Video.DrawRectangleClip(ColorGray, x, y, PixelTileSize.x, PixelTileSize.y);
if (i == Editor.SelectedTileIndex) {
@ -906,7 +856,7 @@ static void DrawMapCursor()
const PixelPos screenPos = UI.MouseViewport->TilePosToScreen_TopLeft(tilePos);
if (Editor.State == EditorEditTile && Editor.SelectedTileIndex != -1) {
const unsigned short frame = Map.Tileset->Table[Editor.ShownTileTypes[Editor.SelectedTileIndex]];
const unsigned short tile = Editor.ShownTileTypes[Editor.SelectedTileIndex];
PushClipping();
UI.MouseViewport->SetClipping();
@ -921,7 +871,7 @@ static void DrawMapCursor()
if (screenPosIt.x >= UI.MouseViewport->GetBottomRightPos().x) {
break;
}
Map.TileGraphic->DrawFrameClip(frame, screenPosIt.x, screenPosIt.y);
Map.TileGraphic->DrawFrameClip(tile, screenPosIt.x, screenPosIt.y);
}
}
Video.DrawRectangleClip(ColorWhite, screenPos.x, screenPos.y, PixelTileSize.x * TileCursorSize, PixelTileSize.y * TileCursorSize);
@ -1514,17 +1464,126 @@ static void EditorCallbackKeyRepeated(unsigned key, unsigned)
}
}
static bool EditorCallbackMouse_EditUnitArea(const PixelPos &screenPos)
{
Assert(Editor.State == EditorEditUnit || Editor.State == EditorSetStartLocation);
// Scrollbar
if (UI.ButtonPanel.X + 4 < CursorScreenPos.x
&& CursorScreenPos.x < UI.ButtonPanel.X + 176 - 4
&& UI.ButtonPanel.Y + 4 < CursorScreenPos.y
&& CursorScreenPos.y < UI.ButtonPanel.Y + 24) {
return true;
}
int bx = UI.InfoPanel.X + 8;
int by = UI.InfoPanel.Y + 4 + IconHeight + 10;
for (int i = 0; i < PlayerMax; ++i) {
if (i == PlayerMax / 2) {
bx = UI.InfoPanel.X + 8;
by += 20;
}
if (bx < screenPos.x && screenPos.x < bx + 20 && by < screenPos.y && screenPos.y < by + 20) {
if (Map.Info.PlayerType[i] != PlayerNobody) {
char buf[256];
snprintf(buf, sizeof(buf), "Select player #%d", i);
UI.StatusLine.Set(buf);
} else {
UI.StatusLine.Clear();
}
Editor.CursorPlayer = i;
#if 0
ButtonUnderCursor = i + 100;
CursorOn = CursorOnButton;
#endif
return true;
}
bx += 20;
}
int i = Editor.UnitIndex;
by = UI.ButtonPanel.Y + 24;
while (by < UI.ButtonPanel.Y + ButtonPanelHeight - IconHeight) {
if (i >= (int)Editor.ShownUnitTypes.size()) {
break;
}
bx = UI.ButtonPanel.X + 10;
while (bx < UI.ButtonPanel.X + ButtonPanelWidth - IconWidth) {
if (i >= (int)Editor.ShownUnitTypes.size()) {
break;
}
if (bx < screenPos.x && screenPos.x < bx + IconWidth
&& by < screenPos.y && screenPos.y < by + IconHeight) {
char buf[256];
snprintf(buf, sizeof(buf), "%s \"%s\"",
Editor.ShownUnitTypes[i]->Ident.c_str(),
Editor.ShownUnitTypes[i]->Name.c_str());
UI.StatusLine.Set(buf);
Editor.CursorUnitIndex = i;
#if 0
ButtonUnderCursor = i + 100;
CursorOn = CursorOnButton;
#endif
return true;
}
bx += IconWidth + 8;
i++;
}
by += IconHeight + 2;
}
return false;
}
static bool EditorCallbackMouse_EditTileArea(const PixelPos &screenPos)
{
int bx = UI.InfoPanel.X + 4;
int by = UI.InfoPanel.Y + 4 + IconHeight + 10;
for (int i = 0; i < 6; ++i) {
if (bx < screenPos.x && screenPos.x < bx + 100 && by < screenPos.y && screenPos.y < by + 18) {
ButtonUnderCursor = i + 300;
CursorOn = CursorOnButton;
return true;
}
by += 20;
}
int i = Editor.TileIndex;
by = UI.ButtonPanel.Y + 24;
while (by < UI.ButtonPanel.Y + ButtonPanelHeight - PixelTileSize.y) {
if (i >= (int)Editor.ShownTileTypes.size()) {
break;
}
bx = UI.ButtonPanel.X + 10;
while (bx < UI.ButtonPanel.X + ButtonPanelWidth - PixelTileSize.x) {
if (i >= (int)Editor.ShownTileTypes.size()) {
break;
}
if (bx < screenPos.x && screenPos.x < bx + PixelTileSize.x
&& by < screenPos.y && screenPos.y < by + PixelTileSize.y) {
const int tile = Editor.ShownTileTypes[i];
const int tileindex = Map.Tileset->findTileIndexByTile(tile);
const int base = Map.Tileset->Tiles[tileindex].BaseTerrain;
UI.StatusLine.Set(Map.Tileset->SolidTerrainTypes[base].TerrainName);
Editor.CursorTileIndex = i;
return true;
}
bx += PixelTileSize.x + 8;
i++;
}
by += PixelTileSize.y + 2;
}
return false;
}
/**
** Callback for input movement of the cursor.
**
** @param x Screen X position.
** @param y Screen Y position.
** @param pos Screen position.
*/
static void EditorCallbackMouse(const PixelPos &pos)
{
static int LastMapX;
static int LastMapY;
char buf[256];
PixelPos restrictPos = pos;
HandleCursorMove(&restrictPos.x, &restrictPos.y); // Reduce to screen
@ -1642,109 +1701,17 @@ static void EditorCallbackMouse(const PixelPos &pos)
if (UI.Minimap.Contains(screenPos)) {
CursorOn = CursorOnMinimap;
}
//
// Handle edit unit area
//
if (Editor.State == EditorEditUnit || Editor.State == EditorSetStartLocation) {
// Scrollbar
if (UI.ButtonPanel.X + 4 < CursorScreenPos.x
&& CursorScreenPos.x < UI.ButtonPanel.X + 176 - 4
&& UI.ButtonPanel.Y + 4 < CursorScreenPos.y
&& CursorScreenPos.y < UI.ButtonPanel.Y + 24) {
if (EditorCallbackMouse_EditUnitArea(screenPos) == true) {
return;
}
int bx = UI.InfoPanel.X + 8;
int by = UI.InfoPanel.Y + 4 + IconHeight + 10;
for (int i = 0; i < PlayerMax; ++i) {
if (i == PlayerMax / 2) {
bx = UI.InfoPanel.X + 8;
by += 20;
}
if (bx < screenPos.x && screenPos.x < bx + 20 && by < screenPos.y && screenPos.y < by + 20) {
if (Map.Info.PlayerType[i] != PlayerNobody) {
snprintf(buf, sizeof(buf), "Select player #%d", i);
UI.StatusLine.Set(buf);
} else {
UI.StatusLine.Clear();
}
Editor.CursorPlayer = i;
#if 0
ButtonUnderCursor = i + 100;
CursorOn = CursorOnButton;
#endif
return;
}
bx += 20;
}
int i = Editor.UnitIndex;
by = UI.ButtonPanel.Y + 24;
while (by < UI.ButtonPanel.Y + ButtonPanelHeight - IconHeight) {
if (i >= (int)Editor.ShownUnitTypes.size()) {
break;
}
bx = UI.ButtonPanel.X + 10;
while (bx < UI.ButtonPanel.X + ButtonPanelWidth - IconWidth) {
if (i >= (int)Editor.ShownUnitTypes.size()) {
break;
}
if (bx < screenPos.x && screenPos.x < bx + IconWidth
&& by < screenPos.y && screenPos.y < by + IconHeight) {
snprintf(buf, sizeof(buf), "%s \"%s\"",
Editor.ShownUnitTypes[i]->Ident.c_str(),
Editor.ShownUnitTypes[i]->Name.c_str());
UI.StatusLine.Set(buf);
Editor.CursorUnitIndex = i;
#if 0
ButtonUnderCursor = i + 100;
CursorOn = CursorOnButton;
#endif
return;
}
bx += IconWidth + 8;
i++;
}
by += IconHeight + 2;
}
}
// Handle tile area
if (Editor.State == EditorEditTile) {
int bx = UI.InfoPanel.X + 4;
int by = UI.InfoPanel.Y + 4 + IconHeight + 10;
for (int i = 0; i < 6; ++i) {
if (bx < screenPos.x && screenPos.x < bx + 100 && by < screenPos.y && screenPos.y < by + 18) {
ButtonUnderCursor = i + 300;
CursorOn = CursorOnButton;
return;
}
by += 20;
}
int i = Editor.TileIndex;
by = UI.ButtonPanel.Y + 24;
while (by < UI.ButtonPanel.Y + ButtonPanelHeight - PixelTileSize.y) {
if (i >= (int)Editor.ShownTileTypes.size()) {
break;
}
bx = UI.ButtonPanel.X + 10;
while (bx < UI.ButtonPanel.X + ButtonPanelWidth - PixelTileSize.x) {
if (i >= (int)Editor.ShownTileTypes.size()) {
break;
}
if (bx < screenPos.x && screenPos.x < bx + PixelTileSize.x
&& by < screenPos.y && screenPos.y < by + PixelTileSize.y) {
int base = Map.Tileset->Tiles[Editor.ShownTileTypes[i]].BaseTerrain;
UI.StatusLine.Set(Map.Tileset->SolidTerrainTypes[base].TerrainName);
Editor.CursorTileIndex = i;
return;
}
bx += PixelTileSize.x + 8;
i++;
}
by += PixelTileSize.y + 2;
if (EditorCallbackMouse_EditTileArea(screenPos) == true) {
return;
}
}
@ -1797,13 +1764,11 @@ static void EditorCallbackMouse(const PixelPos &pos)
UI.StatusLine.Set(_("Set start location mode"));
return;
}
if (UI.MenuButton.X != -1) {
if (UI.MenuButton.Contains(screenPos)) {
ButtonAreaUnderCursor = ButtonAreaMenu;
ButtonUnderCursor = ButtonUnderMenu;
CursorOn = CursorOnButton;
return;
}
if (UI.MenuButton.X != -1 && UI.MenuButton.Contains(screenPos)) {
ButtonAreaUnderCursor = ButtonAreaMenu;
ButtonUnderCursor = ButtonUnderMenu;
CursorOn = CursorOnButton;
return;
}
// Minimap
@ -1854,27 +1819,6 @@ static void EditorCallbackExit()
{
}
/**
** Create the tile icons
*/
static void CreateTileIcons()
{
for (int i = 0; 0x10 + i < Map.Tileset->NumTiles; i += 16) {
TileInfo *info = &Map.Tileset->Tiles[0x10 + i];
if (info->BaseTerrain && !info->MixTerrain) {
Editor.ShownTileTypes.push_back(0x10 + i);
}
}
}
/**
** Clean up the tile icons
*/
static void CleanTileIcons()
{
Editor.ShownTileTypes.clear();
}
/**
** Create editor.
*/
@ -1965,7 +1909,7 @@ void CEditor::Init()
Units.Icon = NULL;
Units.Load();
CreateTileIcons();
Map.Tileset->fillSolidTiles(&Editor.ShownTileTypes);
VisibleTileIcons = CalculateVisibleIcons(true);
RecalculateShownUnits();
@ -2160,7 +2104,7 @@ void StartEditor(const char *filename)
Editor.TerrainEditable = true;
CleanTileIcons();
Editor.ShownTileTypes.clear();
CleanGame();
CleanPlayers();

View file

@ -53,7 +53,7 @@
#define RH_QUAD_M 0x00FF00FF /// Right half quad mask
/// Callback for changed tile (with direction mask)
static void EditorTileChanged2(const Vec2i &pos, int d);
static void EditorChangeSurrounding(const Vec2i &pos, int d);
/*----------------------------------------------------------------------------
-- Variables
@ -86,57 +86,35 @@ static void EditorTileChanged2(const Vec2i &pos, int d);
*/
static unsigned QuadFromTile(const Vec2i &pos)
{
int i;
// find the abstact tile number
const int tile = Map.Field(pos)->Tile;
for (i = 0; i < Map.Tileset->NumTiles; ++i) {
if (tile == Map.Tileset->Table[i]) {
break;
}
}
Assert(i != Map.Tileset->NumTiles);
const int tileIndex = Map.Tileset->findTileIndexByTile(tile);
Assert(tileIndex != -1);
unsigned base = Map.Tileset->Tiles[i].BaseTerrain;
unsigned mix = Map.Tileset->Tiles[i].MixTerrain;
unsigned base = Map.Tileset->Tiles[tileIndex].BaseTerrain;
unsigned mix = Map.Tileset->Tiles[tileIndex].MixTerrain;
if (!mix) { // a solid tile
return base | (base << 8) | (base << 16) | (base << 24);
}
// Mixed tiles, mix together
switch ((i & 0x00F0) >> 4) {
case 0:
return (base << 24) | (mix << 16) | (mix << 8) | mix;
case 1:
return (mix << 24) | (base << 16) | (mix << 8) | mix;
case 2:
return (base << 24) | (base << 16) | (mix << 8) | mix;
case 3:
return (mix << 24) | (mix << 16) | (base << 8) | mix;
case 4:
return (base << 24) | (mix << 16) | (base << 8) | mix;
case 5:
return (base << 24) | (base << 16) | (base << 8) | mix;
case 6:
return (base << 24) | (base << 16) | (base << 8) | mix;
case 7:
return (mix << 24) | (mix << 16) | (mix << 8) | base;
case 8:
return (base << 24) | (mix << 16) | (mix << 8) | base;
case 9:
return (mix << 24) | (base << 16) | (mix << 8) | base;
case 10:
return (base << 24) | (base << 16) | (mix << 8) | base;
case 11:
return (mix << 24) | (mix << 16) | (base << 8) | base;
case 12:
return (base << 24) | (mix << 16) | (base << 8) | base;
case 13:
return (mix << 24) | (base << 16) | (base << 8) | base;
switch ((tileIndex & 0x00F0) >> 4) {
case 0: return (base << 24) | (mix << 16) | (mix << 8) | mix;
case 1: return (mix << 24) | (base << 16) | (mix << 8) | mix;
case 2: return (base << 24) | (base << 16) | (mix << 8) | mix;
case 3: return (mix << 24) | (mix << 16) | (base << 8) | mix;
case 4: return (base << 24) | (mix << 16) | (base << 8) | mix;
case 5: return (base << 24) | (base << 16) | (base << 8) | mix;
case 6: return (base << 24) | (base << 16) | (base << 8) | mix;
case 7: return (mix << 24) | (mix << 16) | (mix << 8) | base;
case 8: return (base << 24) | (mix << 16) | (mix << 8) | base;
case 9: return (mix << 24) | (base << 16) | (mix << 8) | base;
case 10: return (base << 24) | (base << 16) | (mix << 8) | base;
case 11: return (mix << 24) | (mix << 16) | (base << 8) | base;
case 12: return (base << 24) | (mix << 16) | (base << 8) | base;
case 13: return (mix << 24) | (base << 16) | (base << 8) | base;
}
Assert(0);
return base | (base << 8) | (base << 16) | (base << 24);
}
@ -147,16 +125,16 @@ static unsigned QuadFromTile(const Vec2i &pos)
** @param goal Goal tile type.
** @param length Best found path length.
** @param marks Already visited tile types.
** @param tile Tile pointer.
** @param tileIndex Tile pointer.
*/
static int FindTilePath(int base, int goal, int length, std::vector<char> &marks, int *tile)
static int FindTilePath(int base, int goal, int length, std::vector<char> &marks, int *tileIndex)
{
int tileres = Map.Tileset->findTileIndex(base, goal);
if (tileres == -1) {
tileres = Map.Tileset->findTileIndex(goal, base);
}
if (tileres != -1) {
*tile = tileres;
*tileIndex = tileres;
return length;
}
@ -169,11 +147,11 @@ static int FindTilePath(int base, int goal, int length, std::vector<char> &marks
const int j = Map.Tileset->Tiles[i].MixTerrain;
if (!marks[j]) {
marks[j] = j;
int dummytile;
const int n = FindTilePath(j, goal, length + 1, marks, &dummytile);
int dummytileIndex;
const int n = FindTilePath(j, goal, length + 1, marks, &dummytileIndex);
marks[j] = 0;
if (n < l) {
*tile = i;
*tileIndex = i;
l = n;
}
}
@ -183,11 +161,11 @@ static int FindTilePath(int base, int goal, int length, std::vector<char> &marks
const int j = Map.Tileset->Tiles[i].BaseTerrain;
if (!marks[j]) {
marks[j] = j;
int dummytile;
const int n = FindTilePath(j, goal, length + 1, marks, &dummytile);
int dummytileIndex;
const int n = FindTilePath(j, goal, length + 1, marks, &dummytileIndex);
marks[j] = 0;
if (n < l) {
*tile = i;
*tileIndex = i;
l = n;
}
}
@ -238,7 +216,7 @@ static int TileFromQuad(unsigned fixed, unsigned quad)
}
} else {
std::vector<char> marks;
int dummytile;
int dummytileIndex;
marks.resize(Map.Tileset->SolidTerrainTypes.size(), 0);
@ -246,85 +224,44 @@ static int TileFromQuad(unsigned fixed, unsigned quad)
marks[type2] = type2;
// What fixed tile-type should replace the non useable tile-types.
// FIXME: write a loop.
fixed = (quad >> 0) & 0xFF;
if (fixed != type1 && fixed != type2) {
quad &= 0xFFFFFF00;
if (FindTilePath(type1, fixed, 0, marks, &dummytile) < FindTilePath(type2, fixed, 0, marks, &dummytile)) {
quad |= type1 << 0;
} else {
quad |= type2 << 0;
}
}
fixed = (quad >> 8) & 0xFF;
if (fixed != type1 && fixed != type2) {
quad &= 0xFFFF00FF;
if (FindTilePath(type1, fixed, 0, marks, &dummytile) < FindTilePath(type2, fixed, 0, marks, &dummytile)) {
quad |= type1 << 8;
} else {
quad |= type2 << 8;
}
}
fixed = (quad >> 16) & 0xFF;
if (fixed != type1 && fixed != type2) {
quad &= 0xFF00FFFF;
if (FindTilePath(type1, fixed, 0, marks, &dummytile) < FindTilePath(type2, fixed, 0, marks, &dummytile)) {
quad |= type1 << 16;
} else {
quad |= type2 << 16;
}
}
fixed = (quad >> 24) & 0xFF;
if (fixed != type1 && fixed != type2) {
quad &= 0x00FFFFFF;
if (FindTilePath(type1, fixed, 0, marks, &dummytile) < FindTilePath(type2, fixed, 0, marks, &dummytile)) {
quad |= type1 << 24;
} else {
quad |= type2 << 24;
for (int i = 0; i != 4; ++i) {
unsigned int type3 = (quad >> (8 * i)) & 0xFF;
if (type3 != type1 && type3 != type2) {
quad &= ~(0xFF << (8 * i));
if (FindTilePath(type1, type3, 0, marks, &dummytileIndex) < FindTilePath(type2, fixed, 0, marks, &dummytileIndex)) {
quad |= type1 << (8 * i);
} else {
quad |= type2 << (8 * i);
}
}
}
}
// Need a mixed tile
int tile = Map.Tileset->findTileIndex(type1, type2);
if (tile == -1) {
tile = Map.Tileset->findTileIndex(type1, type2);
if (tile != -1) {
std::swap(type1, type2);
}
int tileIndex = Map.Tileset->getTileIndex(type1, type2, quad);
if (tileIndex != -1) {
return tileIndex;
}
if (tile == -1) {
// Find the best tile path.
std::vector<char> marks;
marks.resize(Map.Tileset->SolidTerrainTypes.size(), 0);
marks[type1] = type1;
if (FindTilePath(type1, type2, 0, marks, &tile) == INT_MAX) {
DebugPrint("Huch, no mix found!!!!!!!!!!!\n");
const int res = Map.Tileset->findTileIndex(type1);
Assert(res != -1);
return res;
}
if (type1 == Map.Tileset->Tiles[tile].MixTerrain) {
// Other mixed
std::swap(type1, type2);
}
// Find the best tile path.
std::vector<char> marks;
marks.resize(Map.Tileset->SolidTerrainTypes.size(), 0);
marks[type1] = type1;
if (FindTilePath(type1, type2, 0, marks, &tileIndex) == INT_MAX) {
DebugPrint("Huch, no mix found!!!!!!!!!!!\n");
const int res = Map.Tileset->findTileIndex(type1);
Assert(res != -1);
return res;
}
int base = tile;
if (type1 == Map.Tileset->Tiles[tileIndex].MixTerrain) {
// Other mixed
std::swap(type1, type2);
}
int base = tileIndex;
int direction = 0;
if (((quad >> 24) & 0xFF) == type1) {
direction |= 8;
}
if (((quad >> 16) & 0xFF) == type1) {
direction |= 4;
}
if (((quad >> 8) & 0xFF) == type1) {
direction |= 2;
}
if (((quad >> 0) & 0xFF) == type1) {
direction |= 1;
for (int i = 0; i != 4; ++i) {
if (((quad >> (8 * i)) & 0xFF) == type1) {
direction |= 1 << i;
}
}
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
const char table[16] = { 0, 7, 3, 11, 1, 9, 5, 13, 0, 8, 4, 12, 2, 10, 6, 0 };
@ -335,18 +272,17 @@ static int TileFromQuad(unsigned fixed, unsigned quad)
** Change tile from abstract tile-type.
**
** @param pos map tile coordinate.
** @param tile Abstract tile type to edit.
** @param tile tile type to edit.
**
** @note this is a rather dumb function, doesn't do any tile fixing.
*/
void ChangeTile(const Vec2i &pos, int tile)
{
Assert(Map.Info.IsPointOnMap(pos));
Assert(tile >= 0 && tile < Map.Tileset->NumTiles);
CMapField *mf = Map.Field(pos);
mf->Tile = Map.Tileset->Table[tile];
mf->playerInfo.SeenTile = mf->Tile;
CMapField &mf = *Map.Field(pos);
mf.Tile = tile;
mf.playerInfo.SeenTile = tile;
}
#define DIR_UP 8 /// Go up allowed
@ -358,29 +294,27 @@ void ChangeTile(const Vec2i &pos, int tile)
** Editor change tile.
**
** @param pos map tile coordinate.
** @param tile Tile type to edit.
** @param tileIndex Tile type to edit.
** @param d Fix direction flag 8 up, 4 down, 2 left, 1 right.
*/
static void EditorChangeTile(const Vec2i &pos, int tile, int d)
static void EditorChangeTile(const Vec2i &pos, int tileIndex, int d)
{
Assert(Map.Info.IsPointOnMap(pos));
ChangeTile(pos, tile);
ChangeTile(pos, Map.Tileset->Table[tileIndex]);
//
// Change the flags
//
CMapField *mf = Map.Field(pos);
mf->Flags &= ~(MapFieldHuman | MapFieldLandAllowed | MapFieldCoastAllowed
| MapFieldWaterAllowed | MapFieldNoBuilding | MapFieldUnpassable
| MapFieldWall | MapFieldRocks | MapFieldForest);
CMapField &mf = *Map.Field(pos);
mf.Flags &= ~(MapFieldHuman | MapFieldLandAllowed | MapFieldCoastAllowed
| MapFieldWaterAllowed | MapFieldNoBuilding | MapFieldUnpassable
| MapFieldWall | MapFieldRocks | MapFieldForest);
mf->Flags |= Map.Tileset->FlagsTable[tile];
mf.Flags |= Map.Tileset->FlagsTable[tileIndex];
UI.Minimap.UpdateSeenXY(pos);
UI.Minimap.UpdateXY(pos);
EditorTileChanged2(pos, d);
EditorChangeSurrounding(pos, d);
}
/**
@ -389,7 +323,7 @@ static void EditorChangeTile(const Vec2i &pos, int tile, int d)
** @param pos Map tile position of change.
** @param d Fix direction flag 8 up, 4 down, 2 left, 1 right.
*/
static void EditorTileChanged2(const Vec2i &pos, int d)
static void EditorChangeSurrounding(const Vec2i &pos, int d)
{
unsigned quad = QuadFromTile(pos);
@ -397,26 +331,20 @@ static void EditorTileChanged2(const Vec2i &pos, int d)
// Change the surrounding
//
//
// Special case 1) Walls.
//
CMapField *mf = Map.Field(pos);
if (mf->Flags & MapFieldWall) {
Map.SetWall(pos, mf->Flags & MapFieldHuman);
CMapField &mf = *Map.Field(pos);
if (mf.Flags & MapFieldWall) {
Map.SetWall(pos, mf.Flags & MapFieldHuman);
return;
}
//
// How this works:
// first get the quad of the neighbouring tile, then
// check if the margin matches. otherwise, call
// EditorChangeTile again.
//
if (d & DIR_UP && pos.y) {
const Vec2i offset(0, -1);
//
// Insert into the bottom the new tile.
//
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & TH_QUAD_M) | ((quad >> 16) & BH_QUAD_M);
if (u != q2) {
@ -426,9 +354,7 @@ static void EditorTileChanged2(const Vec2i &pos, int d)
}
if (d & DIR_DOWN && pos.y < Map.Info.MapHeight - 1) {
const Vec2i offset(0, 1);
//
// Insert into the top the new tile.
//
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & BH_QUAD_M) | ((quad << 16) & TH_QUAD_M);
if (u != q2) {
@ -438,9 +364,7 @@ static void EditorTileChanged2(const Vec2i &pos, int d)
}
if (d & DIR_LEFT && pos.x) {
const Vec2i offset(-1, 0);
//
// Insert into the left the new tile.
//
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & LH_QUAD_M) | ((quad >> 8) & RH_QUAD_M);
if (u != q2) {
@ -450,9 +374,7 @@ static void EditorTileChanged2(const Vec2i &pos, int d)
}
if (d & DIR_RIGHT && pos.x < Map.Info.MapWidth - 1) {
const Vec2i offset(1, 0);
//
// Insert into the right the new tile.
//
unsigned q2 = QuadFromTile(pos + offset);
unsigned u = (q2 & RH_QUAD_M) | ((quad << 8) & LH_QUAD_M);
if (u != q2) {
@ -469,7 +391,7 @@ static void EditorTileChanged2(const Vec2i &pos, int d)
*/
void EditorTileChanged(const Vec2i &pos)
{
EditorTileChanged2(pos, 0xF);
EditorChangeSurrounding(pos, 0x0F);
}
/**

View file

@ -127,11 +127,6 @@ extern int EditorSaveMap(const std::string &file);
/// Register ccl features
extern void EditorCclRegister();
/// Edit tile
extern void EditTile(const Vec2i &pos, int tile);
/// Edit tiles
extern void EditTiles(const Vec2i &pos, int tile, int size);
/// Change the view of a tile
extern void ChangeTile(const Vec2i &pos, int tile);
/// Update surroundings for tile changes

View file

@ -98,8 +98,11 @@ public:
public:
unsigned int getOrAddSolidTileIndexByName(const std::string &name);
int findTileIndex(unsigned char baseTerrain, unsigned char mixTerrain = 0) const;
int findTileIndexByTile(unsigned int tile) const;
int getTileIndex(unsigned char baseTerrain, unsigned char mixTerrain, unsigned int quad) const;
int findTileIndexByTile(unsigned int tile) const;
unsigned int getTileNumber(int basic, bool random, bool filler) const;
void fillSolidTiles(std::vector<unsigned int> *tiles) const;
public:
void parse(lua_State *l);
void buildTable(lua_State *l);

View file

@ -307,6 +307,29 @@ int CTileset::findTileIndex(unsigned char baseTerrain, unsigned char mixTerrain)
return -1;
}
int CTileset::getTileIndex(unsigned char baseTerrain, unsigned char mixTerrain, unsigned int quad) const
{
int tileIndex = findTileIndex(baseTerrain, mixTerrain);
if (tileIndex == -1) {
tileIndex = findTileIndex(mixTerrain, baseTerrain);
if (tileIndex == -1) {
return -1;
}
std::swap(baseTerrain, mixTerrain);
}
int base = tileIndex;
int direction = 0;
for (int i = 0; i != 4; ++i) {
if (((quad >> (8 * i)) & 0xFF) == baseTerrain) {
direction |= 1 << i;
}
}
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
const char table[16] = { 0, 7, 3, 11, 1, 9, 5, 13, 0, 8, 4, 12, 2, 10, 6, 0 };
return base | (table[direction] << 4);
}
int CTileset::findTileIndexByTile(unsigned int tile) const
{
for (int i = 0; i != NumTiles; ++i) {
@ -317,6 +340,65 @@ int CTileset::findTileIndexByTile(unsigned int tile) const
return -1;
}
/**
** Get tile number.
**
** @param basic Basic tile number
** @param random Return random tile
** @param filler Get a decorated tile.
**
** @return Tile number.
**
** @todo FIXME: Solid tiles are here still hardcoded.
*/
unsigned int CTileset::getTileNumber(int basic, bool random, bool filler) const
{
int tile = basic;
if (random) {
int n = 0;
for (int i = 0; i < 16; ++i) {
if (!Table[tile + i]) {
if (!filler) {
break;
}
} else {
++n;
}
}
n = MyRand() % n;
int i = -1;
do {
while (++i < 16 && !Map.Tileset->Table[tile + i]) {
}
} while (i < 16 && n--);
Assert(i != 16);
return tile + i;
}
if (filler) {
int i = 0;
for (; i < 16 && Table[tile + i]; ++i) {
}
for (; i < 16 && !Table[tile + i]; ++i) {
}
if (i != 16) {
return Table[tile + i];
}
}
return Table[tile];
}
void CTileset::fillSolidTiles(std::vector<unsigned int> *tiles) const
{
for (int i = 16; i < Map.Tileset->NumTiles; i += 16) {
const TileInfo &info = Map.Tileset->Tiles[i];
if (info.BaseTerrain && info.MixTerrain == 0) {
tiles->push_back(Map.Tileset->Table[i]);
}
}
}
unsigned CTileset::getHumanWallTile(int index) const
{
unsigned tile = HumanWallTable[index];