Improve town zones outer highlight speed and visuals
This commit is contained in:
BIN
bin/data/cmclient-1.grf
Normal file
BIN
bin/data/cmclient-1.grf
Normal file
Binary file not shown.
@@ -614,6 +614,8 @@ zoning_cmd.cpp
|
||||
bitstream.cpp
|
||||
citymania/base64.h
|
||||
citymania/base64.cpp
|
||||
citymania/zoning.hpp
|
||||
citymania/zoning.cpp
|
||||
newgrf_revisions.hpp
|
||||
|
||||
# Save/Load handlers
|
||||
|
||||
124
src/citymania/zoning.cpp
Normal file
124
src/citymania/zoning.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#include "../stdafx.h"
|
||||
|
||||
#include "zoning.hpp"
|
||||
|
||||
#include "../house.h"
|
||||
#include "../core/math_func.hpp"
|
||||
#include "../town.h"
|
||||
#include "../tilearea_type.h"
|
||||
#include "../viewport_func.h"
|
||||
#include "../zoning.h"
|
||||
|
||||
namespace citymania {
|
||||
|
||||
struct TileZoning {
|
||||
uint8 town_zone : 3;
|
||||
};
|
||||
|
||||
TileZoning *_mz = nullptr;
|
||||
|
||||
void AllocateZoningMap(uint map_size) {
|
||||
free(_mz);
|
||||
_mz = CallocT<TileZoning>(map_size);
|
||||
}
|
||||
|
||||
uint8 GetTownZone(Town *town, TileIndex tile) {
|
||||
auto dist = DistanceSquare(tile, town->xy);
|
||||
if (dist > town->cache.squared_town_zone_radius[HZB_TOWN_EDGE])
|
||||
return 0;
|
||||
|
||||
uint8 z = 1;
|
||||
for (HouseZonesBits i = HZB_TOWN_OUTSKIRT; i < HZB_END; i++)
|
||||
if (dist < town->cache.squared_town_zone_radius[i])
|
||||
z = (uint8)i + 1;
|
||||
else if (town->cache.squared_town_zone_radius[i] != 0)
|
||||
break;
|
||||
return z;
|
||||
}
|
||||
|
||||
uint8 GetAnyTownZone(TileIndex tile) {
|
||||
HouseZonesBits next_zone = HZB_BEGIN;
|
||||
uint8 z = 0;
|
||||
|
||||
Town *town;
|
||||
FOR_ALL_TOWNS(town) {
|
||||
uint dist = DistanceSquare(tile, town->xy);
|
||||
// town code uses <= for checking town borders (tz0) but < for other zones
|
||||
while (next_zone < HZB_END
|
||||
&& (town->cache.squared_town_zone_radius[next_zone] == 0
|
||||
|| dist <= town->cache.squared_town_zone_radius[next_zone] - (next_zone == HZB_BEGIN ? 0 : 1))
|
||||
) {
|
||||
if (town->cache.squared_town_zone_radius[next_zone] != 0) z = (uint8)next_zone + 1;
|
||||
next_zone++;
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
void UpdateTownZoning(Town *town, uint32 prev_edge) {
|
||||
auto edge = town->cache.squared_town_zone_radius[HZB_TOWN_EDGE];
|
||||
if (prev_edge && edge == prev_edge)
|
||||
return;
|
||||
|
||||
auto area = OrthogonalTileArea(town->xy, 1, 1);
|
||||
bool recalc;
|
||||
if (edge < prev_edge) {
|
||||
area.Expand(IntSqrt(prev_edge));
|
||||
recalc = true;
|
||||
} else {
|
||||
area.Expand(IntSqrt(edge));
|
||||
recalc = false;
|
||||
}
|
||||
// TODO mark dirty only if zoning is on
|
||||
TILE_AREA_LOOP(tile, area) {
|
||||
uint8 group = GetTownZone(town, tile);
|
||||
if (_mz[tile].town_zone > group) {
|
||||
if (recalc) {
|
||||
_mz[tile].town_zone = GetAnyTownZone(tile);
|
||||
if (_zoning.outer == CHECKTOWNZONES)
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
} else if (_mz[tile].town_zone < group) {
|
||||
_mz[tile].town_zone = group;
|
||||
if (_zoning.outer == CHECKTOWNZONES)
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitializeZoningMap() {
|
||||
Town *town;
|
||||
FOR_ALL_TOWNS(town) {
|
||||
UpdateTownZoning(town, 0);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
uint8 Get(uint32 x, uint32 y, F getter) {
|
||||
if (x >= MapSizeX() || y >= MapSizeY()) return 0;
|
||||
return getter(_mz[TileXY(x, y)]);
|
||||
}
|
||||
|
||||
std::pair<ZoningBorder, uint8> GetTownZoneBorder(TileIndex tile) {
|
||||
auto x = TileX(tile), y = TileY(tile);
|
||||
ZoningBorder res = ZoningBorder::NONE;
|
||||
auto z = _mz[tile].town_zone;
|
||||
if (z == 0)
|
||||
return std::make_pair(res, 0);
|
||||
auto getter = [](TileZoning tz) { return tz.town_zone; };
|
||||
auto tr = Get(x - 1, y, getter);
|
||||
auto tl = Get(x, y - 1, getter);
|
||||
auto bl = Get(x + 1, y, getter);
|
||||
auto br = Get(x, y + 1, getter);
|
||||
if (tr < z) res |= ZoningBorder::TOP_RIGHT;
|
||||
if (tl < z) res |= ZoningBorder::TOP_LEFT;
|
||||
if (bl < z) res |= ZoningBorder::BOTTOM_LEFT;
|
||||
if (br < z) res |= ZoningBorder::BOTTOM_RIGHT;
|
||||
if (tr == z && tl == z && Get(x - 1, y - 1, getter) < z) res |= ZoningBorder::TOP_CORNER;
|
||||
if (tr == z && br == z && Get(x - 1, y + 1, getter) < z) res |= ZoningBorder::RIGHT_CORNER;
|
||||
if (br == z && bl == z && Get(x + 1, y + 1, getter) < z) res |= ZoningBorder::BOTTOM_CORNER;
|
||||
if (tl == z && bl == z && Get(x + 1, y - 1, getter) < z) res |= ZoningBorder::LEFT_CORNER;
|
||||
return std::make_pair(res, z);
|
||||
}
|
||||
|
||||
} // namespace citymania
|
||||
43
src/citymania/zoning.hpp
Normal file
43
src/citymania/zoning.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef CITYMANIA_ZONING_HPP
|
||||
#define CITYMANIA_ZONING_HPP
|
||||
|
||||
#include "../core/enum_type.hpp"
|
||||
#include "../tile_type.h"
|
||||
#include "../town_type.h"
|
||||
|
||||
namespace citymania {
|
||||
|
||||
////enum class ZoningBorder : unt8 {
|
||||
enum ZoningBorder: uint8 {
|
||||
NONE = 0,
|
||||
TOP_LEFT = 1,
|
||||
TOP_RIGHT = 2,
|
||||
BOTTOM_RIGHT = 4,
|
||||
BOTTOM_LEFT = 8,
|
||||
TOP_CORNER = 16,
|
||||
RIGHT_CORNER = 32,
|
||||
BOTTOM_CORNER = 64,
|
||||
LEFT_CORNER = 128,
|
||||
};
|
||||
|
||||
DECLARE_ENUM_AS_BIT_SET(ZoningBorder);
|
||||
|
||||
// enum class AdvertisementZone: uint8 {
|
||||
// NONE = 0,
|
||||
// LARGE = 1,
|
||||
// MEDIUM = 2,
|
||||
// SMALL = 3,
|
||||
// };
|
||||
|
||||
|
||||
void AllocateZoningMap(uint map_size);
|
||||
void InitializeZoningMap();
|
||||
|
||||
void UpdateTownZoning(Town *town, uint32 prev_edge);
|
||||
|
||||
std::pair<ZoningBorder, uint8> GetTownZoneBorder(TileIndex tile);
|
||||
std::pair<ZoningBorder, uint8> GetTownAdvertisementBorder(TileIndex tile);
|
||||
|
||||
} // namespace citymania
|
||||
|
||||
#endif
|
||||
@@ -192,7 +192,8 @@ static void LoadSpriteTables()
|
||||
i++
|
||||
);
|
||||
}
|
||||
LoadGrfFile("innerhighlight.grf", SPR_INNER_HIGHLIGHT_BASE, i++);
|
||||
// LoadGrfFile("innerhighlight.grf", SPR_INNER_HIGHLIGHT_BASE, i++);
|
||||
LoadGrfFile("cmclient-1.grf", SPR_INNER_HIGHLIGHT_BASE - 4, i++);
|
||||
|
||||
/* Initialize the unicode to sprite mapping table */
|
||||
InitializeUnicodeGlyphMap();
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "core/alloc_func.hpp"
|
||||
#include "water_map.h"
|
||||
#include "string_func.h"
|
||||
#include "citymania/zoning.hpp"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
@@ -63,6 +64,7 @@ void AllocateMap(uint size_x, uint size_y)
|
||||
|
||||
_m = CallocT<Tile>(_map_size);
|
||||
_me = CallocT<TileExtended>(_map_size);
|
||||
citymania::AllocateZoningMap(_map_size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
|
||||
#include "linkgraph/linkgraphschedule.h"
|
||||
|
||||
#include "citymania/zoning.hpp"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <system_error>
|
||||
|
||||
@@ -962,6 +964,7 @@ static void MakeNewGameDone()
|
||||
|
||||
CheckEngines();
|
||||
CheckIndustries();
|
||||
citymania::InitializeZoningMap();
|
||||
MarkWholeScreenDirty();
|
||||
}
|
||||
|
||||
@@ -978,6 +981,7 @@ static void MakeNewGame(bool from_heightmap, bool reset_settings)
|
||||
static void MakeNewEditorWorldDone()
|
||||
{
|
||||
SetLocalCompany(OWNER_NONE);
|
||||
citymania::InitializeZoningMap();
|
||||
}
|
||||
|
||||
static void MakeNewEditorWorld()
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
#include "../game/game_text.hpp"
|
||||
#include "../table/control_codes.h"
|
||||
|
||||
#include "../citymania/zoning.hpp"
|
||||
|
||||
#include "saveload_internal.h"
|
||||
|
||||
#include <signal.h>
|
||||
@@ -3267,6 +3269,7 @@ bool AfterLoadGame()
|
||||
|
||||
AfterLoadLinkGraphs();
|
||||
AfterLoadFindBTProCBInfo();
|
||||
citymania::InitializeZoningMap();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -317,8 +317,11 @@ static const SpriteID SPR_PALETTE_ZONING_YELLOW = SPR_INNER_HIGHLIGHT_BASE +
|
||||
static const SpriteID SPR_PALETTE_ZONING_PURPLE = SPR_INNER_HIGHLIGHT_BASE + 28;
|
||||
static const SpriteID SPR_INNER_HIGHLIGHT_COUNT = 29;
|
||||
|
||||
static const SpriteID SPR_BORDER_HIGHLIGHT_BASE = SPR_INNER_HIGHLIGHT_BASE + SPR_INNER_HIGHLIGHT_COUNT + 1;
|
||||
static const SpriteID SPR_BORDER_HIGHLIGHT_COUNT = 19 * 19;
|
||||
|
||||
/* From where can we start putting NewGRFs? */
|
||||
static const SpriteID SPR_NEWGRFS_BASE = SPR_INNER_HIGHLIGHT_BASE + SPR_INNER_HIGHLIGHT_COUNT;
|
||||
static const SpriteID SPR_NEWGRFS_BASE = SPR_BORDER_HIGHLIGHT_BASE + SPR_BORDER_HIGHLIGHT_COUNT;
|
||||
|
||||
/* Manager face sprites */
|
||||
static const SpriteID SPR_GRADIENT = 874; // background gradient behind manager face
|
||||
|
||||
@@ -54,6 +54,8 @@
|
||||
#include "table/strings.h"
|
||||
#include "table/town_land.h"
|
||||
|
||||
#include "citymania/zoning.hpp"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
bool _cb_enabled = false;
|
||||
@@ -1816,6 +1818,7 @@ static bool GrowTown(Town *t)
|
||||
|
||||
void UpdateTownRadius(Town *t)
|
||||
{
|
||||
auto prev_tz0 = t->cache.squared_town_zone_radius[0];
|
||||
static const uint32 _town_squared_town_zone_radius_data[23][5] = {
|
||||
{ 4, 0, 0, 0, 0}, // 0
|
||||
{ 16, 0, 0, 0, 0},
|
||||
@@ -1855,6 +1858,8 @@ void UpdateTownRadius(Town *t)
|
||||
t->cache.squared_town_zone_radius[3] = mass * 5 - 5;
|
||||
t->cache.squared_town_zone_radius[4] = mass * 3 + 5;
|
||||
}
|
||||
if (!_generating_world)
|
||||
citymania::UpdateTownZoning(t, prev_tz0);
|
||||
}
|
||||
|
||||
void UpdateTownMaxPass(Town *t)
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "citymania/zoning.hpp"
|
||||
|
||||
|
||||
Zoning _zoning = {CHECKNOTHING, CHECKNOTHING};
|
||||
static const SpriteID INVALID_SPRITE_ID = UINT_MAX;
|
||||
//RED GREEN BLACK LIGHT_BLUE ORANGE WHITE YELLOW PURPLE
|
||||
@@ -268,10 +271,11 @@ SpriteID TileZoneCheckTownZones(TileIndex tile) {
|
||||
|
||||
Town *town;
|
||||
FOR_ALL_TOWNS(town) {
|
||||
uint dist = DistanceSquare(tile, town->xy);
|
||||
// town code uses <= for checking town borders (tz0) but < for other zones
|
||||
while (next_zone < HZB_END
|
||||
&& (town->cache.squared_town_zone_radius[next_zone] == 0
|
||||
|| DistanceSquare(tile, town->xy) <= town->cache.squared_town_zone_radius[next_zone] + (next_zone == HZB_BEGIN ? 0 : 1))
|
||||
|| dist <= town->cache.squared_town_zone_radius[next_zone] - (next_zone == HZB_BEGIN ? 0 : 1))
|
||||
){
|
||||
if(town->cache.squared_town_zone_radius[next_zone] != 0) tz = next_zone;
|
||||
next_zone++;
|
||||
@@ -397,6 +401,38 @@ SpriteID TileZoningSpriteEvaluation(TileIndex tile, Owner owner, EvaluationMode
|
||||
}
|
||||
}
|
||||
|
||||
SpriteID GetTownZoneBorderColor(uint8 zone) {
|
||||
switch (zone) {
|
||||
default: return SPR_PALETTE_ZONING_LIGHT_BLUE; // Tz0
|
||||
case 2: return SPR_PALETTE_ZONING_RED; // Tz1
|
||||
case 3: return SPR_PALETTE_ZONING_YELLOW; // Tz2
|
||||
case 4: return SPR_PALETTE_ZONING_GREEN; // Tz3
|
||||
case 5: return SPR_PALETTE_ZONING_WHITE; // Tz4 - center
|
||||
};
|
||||
}
|
||||
|
||||
void DrawBorderSprites(const TileInfo *ti, citymania::ZoningBorder border, SpriteID color) {
|
||||
auto b = (uint8)border & 15;
|
||||
auto tile_sprite = SPR_BORDER_HIGHLIGHT_BASE + _tileh_to_sprite[ti->tileh] * 19;
|
||||
if (b) {
|
||||
AddSortableSpriteToDraw(tile_sprite + b - 1,
|
||||
color, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
|
||||
}
|
||||
if (border & citymania::ZoningBorder::TOP_CORNER)
|
||||
AddSortableSpriteToDraw(tile_sprite + 15,
|
||||
color, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
|
||||
if (border & citymania::ZoningBorder::RIGHT_CORNER)
|
||||
AddSortableSpriteToDraw(tile_sprite + 16,
|
||||
color, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
|
||||
if (border & citymania::ZoningBorder::BOTTOM_CORNER)
|
||||
AddSortableSpriteToDraw(tile_sprite + 17,
|
||||
color, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
|
||||
if (border & citymania::ZoningBorder::LEFT_CORNER)
|
||||
AddSortableSpriteToDraw(tile_sprite + 18,
|
||||
color, ti->x, ti->y, 0x10, 0x10, 1, ti->z + 7);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw the the zoning on the tile.
|
||||
* @param TileInfo ti
|
||||
@@ -406,7 +442,14 @@ void DrawTileZoning(const TileInfo *ti) {
|
||||
if(_zoning.outer == CHECKNOTHING && _zoning.inner == CHECKNOTHING) return; //nothing to do
|
||||
if (_game_mode != GM_NORMAL || ti->tile >= MapSize() || IsTileType(ti->tile, MP_VOID)) return; //check invalid
|
||||
if (_zoning.outer != CHECKNOTHING){
|
||||
DrawZoningSprites(SPR_SELECT_TILE, TileZoningSpriteEvaluation(ti->tile, _local_company, _zoning.outer), ti);
|
||||
if (_zoning.outer == CHECKTOWNZONES) {
|
||||
auto p = citymania::GetTownZoneBorder(ti->tile);
|
||||
if (p.first && p.second) {
|
||||
DrawBorderSprites(ti, p.first, GetTownZoneBorderColor(p.second));
|
||||
}
|
||||
} else {
|
||||
DrawZoningSprites(SPR_SELECT_TILE, TileZoningSpriteEvaluation(ti->tile, _local_company, _zoning.outer), ti);
|
||||
}
|
||||
}
|
||||
if (_zoning.inner != CHECKNOTHING){
|
||||
DrawZoningSprites(SPR_INNER_HIGHLIGHT_BASE, TileZoningSpriteEvaluation(ti->tile, _local_company, _zoning.inner), ti);
|
||||
|
||||
Reference in New Issue
Block a user