mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
3 Commits
3146b6ca5f
...
a2faa43fff
Author | SHA1 | Date |
---|---|---|
|
a2faa43fff | |
|
67bb5fc5c5 | |
|
a8650c6b06 |
|
@ -454,6 +454,7 @@ add_files(
|
||||||
spritecache.cpp
|
spritecache.cpp
|
||||||
spritecache.h
|
spritecache.h
|
||||||
spritecache_internal.h
|
spritecache_internal.h
|
||||||
|
spritecache_type.h
|
||||||
station.cpp
|
station.cpp
|
||||||
station_base.h
|
station_base.h
|
||||||
station_cmd.cpp
|
station_cmd.cpp
|
||||||
|
|
|
@ -3689,10 +3689,15 @@ STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}Town gro
|
||||||
STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}Town is {RED}not{BLACK} growing
|
STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}Town is {RED}not{BLACK} growing
|
||||||
STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Noise limit in town: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
|
STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Noise limit in town: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
|
||||||
STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Centre the main view on town location. Ctrl+Click to open a new viewport on town location
|
STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Centre the main view on town location. Ctrl+Click to open a new viewport on town location
|
||||||
STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}Local Authority
|
|
||||||
STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}Show information on local authority
|
|
||||||
STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Change town name
|
STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Change town name
|
||||||
|
|
||||||
|
STR_TOWN_VIEW_INFO :Information
|
||||||
|
STR_TOWN_VIEW_INFO_TOOLTIP :Switch to town information tab
|
||||||
|
STR_TOWN_VIEW_RATINGS :Ratings
|
||||||
|
STR_TOWN_VIEW_RATINGS_TOOLTIP :Switch to local authority ratings tab
|
||||||
|
STR_TOWN_VIEW_ACTIONS :Actions
|
||||||
|
STR_TOWN_VIEW_ACTIONS_TOOLTIP :Switch to local authority actions tab
|
||||||
|
|
||||||
STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Expand
|
STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Expand
|
||||||
STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Increase size of town
|
STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Increase size of town
|
||||||
STR_TOWN_VIEW_EXPAND_BUILDINGS_BUTTON :{BLACK}Expand buildings
|
STR_TOWN_VIEW_EXPAND_BUILDINGS_BUTTON :{BLACK}Expand buildings
|
||||||
|
@ -3704,8 +3709,6 @@ STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Delete t
|
||||||
|
|
||||||
STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Rename Town
|
STR_TOWN_VIEW_RENAME_TOWN_BUTTON :Rename Town
|
||||||
|
|
||||||
# Town local authority window
|
|
||||||
STR_LOCAL_AUTHORITY_CAPTION :{WHITE}{TOWN} local authority
|
|
||||||
STR_LOCAL_AUTHORITY_ZONE :{BLACK}Zone
|
STR_LOCAL_AUTHORITY_ZONE :{BLACK}Zone
|
||||||
STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}Show zone within local authority boundaries
|
STR_LOCAL_AUTHORITY_ZONE_TOOLTIP :{BLACK}Show zone within local authority boundaries
|
||||||
STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}Transport company ratings:
|
STR_LOCAL_AUTHORITY_COMPANY_RATINGS :{BLACK}Transport company ratings:
|
||||||
|
|
|
@ -605,7 +605,7 @@ static CommandCost ClearTile_Object(TileIndex tile, DoCommandFlags flags)
|
||||||
if (flags.Test(DoCommandFlag::Execute)) {
|
if (flags.Test(DoCommandFlag::Execute)) {
|
||||||
Town *town = o->town;
|
Town *town = o->town;
|
||||||
town->statues.Reset(GetTileOwner(tile));
|
town->statues.Reset(GetTileOwner(tile));
|
||||||
SetWindowDirty(WC_TOWN_AUTHORITY, town->index);
|
SetWindowDirty(WC_TOWN_VIEW, town->index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -888,7 +888,7 @@ static void ChangeTileOwner_Object(TileIndex tile, Owner old_owner, Owner new_ow
|
||||||
do_clear = true;
|
do_clear = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
|
SetWindowDirty(WC_TOWN_VIEW, t->index);
|
||||||
} else {
|
} else {
|
||||||
do_clear = true;
|
do_clear = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -535,7 +535,7 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
|
||||||
|
|
||||||
struct GrfSpriteOffset {
|
struct GrfSpriteOffset {
|
||||||
size_t file_pos;
|
size_t file_pos;
|
||||||
uint8_t control_flags;
|
SpriteCacheCtrlFlags control_flags{};
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Map from sprite numbers to position in the GRF file. */
|
/** Map from sprite numbers to position in the GRF file. */
|
||||||
|
@ -565,7 +565,7 @@ void ReadGRFSpriteOffsets(SpriteFile &file)
|
||||||
size_t old_pos = file.GetPos();
|
size_t old_pos = file.GetPos();
|
||||||
file.SeekTo(data_offset, SEEK_CUR);
|
file.SeekTo(data_offset, SEEK_CUR);
|
||||||
|
|
||||||
GrfSpriteOffset offset = { 0, 0 };
|
GrfSpriteOffset offset{0};
|
||||||
|
|
||||||
/* Loop over all sprite section entries and store the file
|
/* Loop over all sprite section entries and store the file
|
||||||
* offset for each newly encountered ID. */
|
* offset for each newly encountered ID. */
|
||||||
|
@ -574,7 +574,6 @@ void ReadGRFSpriteOffsets(SpriteFile &file)
|
||||||
if (id != prev_id) {
|
if (id != prev_id) {
|
||||||
_grf_sprite_offsets[prev_id] = offset;
|
_grf_sprite_offsets[prev_id] = offset;
|
||||||
offset.file_pos = file.GetPos() - 4;
|
offset.file_pos = file.GetPos() - 4;
|
||||||
offset.control_flags = 0;
|
|
||||||
}
|
}
|
||||||
prev_id = id;
|
prev_id = id;
|
||||||
uint length = file.ReadDword();
|
uint length = file.ReadDword();
|
||||||
|
@ -585,11 +584,11 @@ void ReadGRFSpriteOffsets(SpriteFile &file)
|
||||||
uint8_t zoom = file.ReadByte();
|
uint8_t zoom = file.ReadByte();
|
||||||
length--;
|
length--;
|
||||||
if (colour.Any() && zoom == 0) { // ZoomLevel::Normal (normal zoom)
|
if (colour.Any() && zoom == 0) { // ZoomLevel::Normal (normal zoom)
|
||||||
SetBit(offset.control_flags, (colour != SpriteComponent::Palette) ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL);
|
offset.control_flags.Set((colour != SpriteComponent::Palette) ? SpriteCacheCtrlFlag::AllowZoomMin1x32bpp : SpriteCacheCtrlFlag::AllowZoomMin1xPal);
|
||||||
SetBit(offset.control_flags, (colour != SpriteComponent::Palette) ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL);
|
offset.control_flags.Set((colour != SpriteComponent::Palette) ? SpriteCacheCtrlFlag::AllowZoomMin2x32bpp : SpriteCacheCtrlFlag::AllowZoomMin2xPal);
|
||||||
}
|
}
|
||||||
if (colour.Any() && zoom == 2) { // ZoomLevel::In2x (2x zoomed in)
|
if (colour.Any() && zoom == 2) { // ZoomLevel::In2x (2x zoomed in)
|
||||||
SetBit(offset.control_flags, (colour != SpriteComponent::Palette) ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL);
|
offset.control_flags.Set((colour != SpriteComponent::Palette) ? SpriteCacheCtrlFlag::AllowZoomMin2x32bpp : SpriteCacheCtrlFlag::AllowZoomMin2xPal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -621,7 +620,7 @@ bool LoadNextSprite(SpriteID load_index, SpriteFile &file, uint file_sprite_id)
|
||||||
uint8_t grf_type = file.ReadByte();
|
uint8_t grf_type = file.ReadByte();
|
||||||
|
|
||||||
SpriteType type;
|
SpriteType type;
|
||||||
uint8_t control_flags = 0;
|
SpriteCacheCtrlFlags control_flags;
|
||||||
if (grf_type == 0xFF) {
|
if (grf_type == 0xFF) {
|
||||||
/* Some NewGRF files have "empty" pseudo-sprites which are 1
|
/* Some NewGRF files have "empty" pseudo-sprites which are 1
|
||||||
* byte long. Catch these so the sprites won't be displayed. */
|
* byte long. Catch these so the sprites won't be displayed. */
|
||||||
|
|
|
@ -11,24 +11,9 @@
|
||||||
#define SPRITECACHE_H
|
#define SPRITECACHE_H
|
||||||
|
|
||||||
#include "gfx_type.h"
|
#include "gfx_type.h"
|
||||||
|
#include "spritecache_type.h"
|
||||||
#include "spriteloader/spriteloader.hpp"
|
#include "spriteloader/spriteloader.hpp"
|
||||||
|
|
||||||
/** Data structure describing a sprite. */
|
|
||||||
struct Sprite {
|
|
||||||
uint16_t height; ///< Height of the sprite.
|
|
||||||
uint16_t width; ///< Width of the sprite.
|
|
||||||
int16_t x_offs; ///< Number of pixels to shift the sprite to the right.
|
|
||||||
int16_t y_offs; ///< Number of pixels to shift the sprite downwards.
|
|
||||||
std::byte data[]; ///< Sprite data.
|
|
||||||
};
|
|
||||||
|
|
||||||
enum SpriteCacheCtrlFlags : uint8_t {
|
|
||||||
SCCF_ALLOW_ZOOM_MIN_1X_PAL = 0, ///< Allow use of sprite min zoom setting at 1x in palette mode.
|
|
||||||
SCCF_ALLOW_ZOOM_MIN_1X_32BPP = 1, ///< Allow use of sprite min zoom setting at 1x in 32bpp mode.
|
|
||||||
SCCF_ALLOW_ZOOM_MIN_2X_PAL = 2, ///< Allow use of sprite min zoom setting at 2x in palette mode.
|
|
||||||
SCCF_ALLOW_ZOOM_MIN_2X_32BPP = 3, ///< Allow use of sprite min zoom setting at 2x in 32bpp mode.
|
|
||||||
};
|
|
||||||
|
|
||||||
extern uint _sprite_cache_size;
|
extern uint _sprite_cache_size;
|
||||||
|
|
||||||
/** SpriteAllocator that allocates memory via a unique_ptr array. */
|
/** SpriteAllocator that allocates memory via a unique_ptr array. */
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include "core/math_func.hpp"
|
#include "core/math_func.hpp"
|
||||||
#include "gfx_type.h"
|
#include "gfx_type.h"
|
||||||
|
#include "spritecache_type.h"
|
||||||
#include "spriteloader/spriteloader.hpp"
|
#include "spriteloader/spriteloader.hpp"
|
||||||
|
|
||||||
#include "table/sprites.h"
|
#include "table/sprites.h"
|
||||||
|
@ -27,7 +28,7 @@ struct SpriteCache {
|
||||||
uint32_t lru = 0;
|
uint32_t lru = 0;
|
||||||
SpriteType type = SpriteType::Invalid; ///< In some cases a single sprite is misused by two NewGRFs. Once as real sprite and once as recolour sprite. If the recolour sprite gets into the cache it might be drawn as real sprite which causes enormous trouble.
|
SpriteType type = SpriteType::Invalid; ///< In some cases a single sprite is misused by two NewGRFs. Once as real sprite and once as recolour sprite. If the recolour sprite gets into the cache it might be drawn as real sprite which causes enormous trouble.
|
||||||
bool warned = false; ///< True iff the user has been warned about incorrect use of this sprite
|
bool warned = false; ///< True iff the user has been warned about incorrect use of this sprite
|
||||||
uint8_t control_flags = 0; ///< Control flags, see SpriteCacheCtrlFlags
|
SpriteCacheCtrlFlags control_flags{}; ///< Control flags, see SpriteCacheCtrlFlags
|
||||||
|
|
||||||
void ClearSpriteData();
|
void ClearSpriteData();
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file spritecache_type.h Types related to the sprite cache. */
|
||||||
|
|
||||||
|
#ifndef SPRITECACHE_TYPE_H
|
||||||
|
#define SPRITECACHE_TYPE_H
|
||||||
|
|
||||||
|
#include "core/enum_type.hpp"
|
||||||
|
|
||||||
|
/** Data structure describing a sprite. */
|
||||||
|
struct Sprite {
|
||||||
|
uint16_t height; ///< Height of the sprite.
|
||||||
|
uint16_t width; ///< Width of the sprite.
|
||||||
|
int16_t x_offs; ///< Number of pixels to shift the sprite to the right.
|
||||||
|
int16_t y_offs; ///< Number of pixels to shift the sprite downwards.
|
||||||
|
std::byte data[]; ///< Sprite data.
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SpriteCacheCtrlFlag : uint8_t {
|
||||||
|
AllowZoomMin1xPal, ///< Allow use of sprite min zoom setting at 1x in palette mode.
|
||||||
|
AllowZoomMin1x32bpp, ///< Allow use of sprite min zoom setting at 1x in 32bpp mode.
|
||||||
|
AllowZoomMin2xPal, ///< Allow use of sprite min zoom setting at 2x in palette mode.
|
||||||
|
AllowZoomMin2x32bpp, ///< Allow use of sprite min zoom setting at 2x in 32bpp mode.
|
||||||
|
};
|
||||||
|
|
||||||
|
using SpriteCacheCtrlFlags = EnumBitSet<SpriteCacheCtrlFlag, uint8_t>;
|
||||||
|
|
||||||
|
#endif /* SPRITECACHE_TYPE_H */
|
|
@ -256,7 +256,7 @@ static ZoomLevels LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||||
{
|
{
|
||||||
static const ZoomLevel zoom_lvl_map[6] = {ZoomLevel::Normal, ZoomLevel::In4x, ZoomLevel::In2x, ZoomLevel::Out2x, ZoomLevel::Out4x, ZoomLevel::Out8x};
|
static const ZoomLevel zoom_lvl_map[6] = {ZoomLevel::Normal, ZoomLevel::In4x, ZoomLevel::In2x, ZoomLevel::Out2x, ZoomLevel::Out4x, ZoomLevel::Out8x};
|
||||||
|
|
||||||
|
@ -295,11 +295,11 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
is_wanted_zoom_lvl = true;
|
is_wanted_zoom_lvl = true;
|
||||||
ZoomLevel zoom_min = sprite_type == SpriteType::Font ? ZoomLevel::Min : _settings_client.gui.sprite_zoom_min;
|
ZoomLevel zoom_min = sprite_type == SpriteType::Font ? ZoomLevel::Min : _settings_client.gui.sprite_zoom_min;
|
||||||
if (zoom_min >= ZoomLevel::In2x &&
|
if (zoom_min >= ZoomLevel::In2x &&
|
||||||
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL) && zoom_lvl < ZoomLevel::In2x) {
|
control_flags.Test(load_32bpp ? SpriteCacheCtrlFlag::AllowZoomMin2x32bpp : SpriteCacheCtrlFlag::AllowZoomMin2xPal) && zoom_lvl < ZoomLevel::In2x) {
|
||||||
is_wanted_zoom_lvl = false;
|
is_wanted_zoom_lvl = false;
|
||||||
}
|
}
|
||||||
if (zoom_min >= ZoomLevel::Normal &&
|
if (zoom_min >= ZoomLevel::Normal &&
|
||||||
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL) && zoom_lvl < ZoomLevel::Normal) {
|
control_flags.Test(load_32bpp ? SpriteCacheCtrlFlag::AllowZoomMin1x32bpp : SpriteCacheCtrlFlag::AllowZoomMin1xPal) && zoom_lvl < ZoomLevel::Normal) {
|
||||||
is_wanted_zoom_lvl = false;
|
is_wanted_zoom_lvl = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -359,7 +359,7 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
return loaded_sprites;
|
return loaded_sprites;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoomLevels SpriteLoaderGrf::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
ZoomLevels SpriteLoaderGrf::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||||
{
|
{
|
||||||
if (this->container_ver >= 2) {
|
if (this->container_ver >= 2) {
|
||||||
return LoadSpriteV2(sprite, file, file_pos, sprite_type, load_32bpp, control_flags, avail_8bpp, avail_32bpp);
|
return LoadSpriteV2(sprite, file, file_pos, sprite_type, load_32bpp, control_flags, avail_8bpp, avail_32bpp);
|
||||||
|
|
|
@ -17,7 +17,7 @@ class SpriteLoaderGrf : public SpriteLoader {
|
||||||
uint8_t container_ver;
|
uint8_t container_ver;
|
||||||
public:
|
public:
|
||||||
SpriteLoaderGrf(uint8_t container_ver) : container_ver(container_ver) {}
|
SpriteLoaderGrf(uint8_t container_ver) : container_ver(container_ver) {}
|
||||||
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SPRITELOADER_GRF_HPP */
|
#endif /* SPRITELOADER_GRF_HPP */
|
||||||
|
|
|
@ -48,7 +48,7 @@ static void Convert32bppTo8bpp(SpriteLoader::Sprite &sprite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoomLevels SpriteLoaderMakeIndexed::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
ZoomLevels SpriteLoaderMakeIndexed::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||||
{
|
{
|
||||||
ZoomLevels avail = this->baseloader.LoadSprite(sprite, file, file_pos, sprite_type, true, control_flags, avail_8bpp, avail_32bpp);
|
ZoomLevels avail = this->baseloader.LoadSprite(sprite, file, file_pos, sprite_type, true, control_flags, avail_8bpp, avail_32bpp);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ class SpriteLoaderMakeIndexed : public SpriteLoader {
|
||||||
SpriteLoader &baseloader;
|
SpriteLoader &baseloader;
|
||||||
public:
|
public:
|
||||||
SpriteLoaderMakeIndexed(SpriteLoader &baseloader) : baseloader(baseloader) {}
|
SpriteLoaderMakeIndexed(SpriteLoader &baseloader) : baseloader(baseloader) {}
|
||||||
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SPRITELOADER_MAKEINDEXED_H */
|
#endif /* SPRITELOADER_MAKEINDEXED_H */
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "../core/alloc_type.hpp"
|
#include "../core/alloc_type.hpp"
|
||||||
#include "../core/enum_type.hpp"
|
#include "../core/enum_type.hpp"
|
||||||
#include "../gfx_type.h"
|
#include "../gfx_type.h"
|
||||||
|
#include "../spritecache_type.h"
|
||||||
#include "sprite_file_type.hpp"
|
#include "sprite_file_type.hpp"
|
||||||
|
|
||||||
struct Sprite;
|
struct Sprite;
|
||||||
|
@ -94,7 +95,7 @@ public:
|
||||||
* @param[out] avail_32bpp Available 32bpp sprites.
|
* @param[out] avail_32bpp Available 32bpp sprites.
|
||||||
* @return Available sprites matching \a load_32bpp.
|
* @return Available sprites matching \a load_32bpp.
|
||||||
*/
|
*/
|
||||||
virtual ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) = 0;
|
virtual ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) = 0;
|
||||||
|
|
||||||
virtual ~SpriteLoader() = default;
|
virtual ~SpriteLoader() = default;
|
||||||
};
|
};
|
||||||
|
|
|
@ -147,7 +147,7 @@ def = true
|
||||||
str = STR_CONFIG_SETTING_BRIBE
|
str = STR_CONFIG_SETTING_BRIBE
|
||||||
strhelp = STR_CONFIG_SETTING_BRIBE_HELPTEXT
|
strhelp = STR_CONFIG_SETTING_BRIBE_HELPTEXT
|
||||||
help_cb = SettingHelpWallclock
|
help_cb = SettingHelpWallclock
|
||||||
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_AUTHORITY); }
|
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_VIEW); }
|
||||||
cat = SC_BASIC
|
cat = SC_BASIC
|
||||||
|
|
||||||
[SDT_BOOL]
|
[SDT_BOOL]
|
||||||
|
@ -157,7 +157,7 @@ def = true
|
||||||
str = STR_CONFIG_SETTING_ALLOW_EXCLUSIVE
|
str = STR_CONFIG_SETTING_ALLOW_EXCLUSIVE
|
||||||
strhelp = STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT
|
strhelp = STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT
|
||||||
help_cb = SettingHelpWallclock
|
help_cb = SettingHelpWallclock
|
||||||
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_AUTHORITY); }
|
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_VIEW); }
|
||||||
cat = SC_BASIC
|
cat = SC_BASIC
|
||||||
|
|
||||||
[SDT_BOOL]
|
[SDT_BOOL]
|
||||||
|
@ -166,7 +166,7 @@ from = SLV_165
|
||||||
def = true
|
def = true
|
||||||
str = STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS
|
str = STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS
|
||||||
strhelp = STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT
|
strhelp = STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT
|
||||||
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_AUTHORITY); }
|
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_VIEW); }
|
||||||
cat = SC_BASIC
|
cat = SC_BASIC
|
||||||
|
|
||||||
[SDT_BOOL]
|
[SDT_BOOL]
|
||||||
|
@ -175,7 +175,7 @@ from = SLV_160
|
||||||
def = true
|
def = true
|
||||||
str = STR_CONFIG_SETTING_ALLOW_FUND_ROAD
|
str = STR_CONFIG_SETTING_ALLOW_FUND_ROAD
|
||||||
strhelp = STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT
|
strhelp = STR_CONFIG_SETTING_ALLOW_FUND_ROAD_HELPTEXT
|
||||||
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_AUTHORITY); }
|
post_cb = [](auto) { InvalidateWindowClassesData(WC_TOWN_VIEW); }
|
||||||
cat = SC_BASIC
|
cat = SC_BASIC
|
||||||
|
|
||||||
[SDT_BOOL]
|
[SDT_BOOL]
|
||||||
|
|
|
@ -33,7 +33,7 @@ static bool MockLoadNextSprite(SpriteID load_index)
|
||||||
sc->id = 0;
|
sc->id = 0;
|
||||||
sc->type = is_mapgen ? SpriteType::MapGen : SpriteType::Normal;
|
sc->type = is_mapgen ? SpriteType::MapGen : SpriteType::Normal;
|
||||||
sc->warned = false;
|
sc->warned = false;
|
||||||
sc->control_flags = 0;
|
sc->control_flags = {};
|
||||||
|
|
||||||
/* Fill with empty sprites up until the default sprite count. */
|
/* Fill with empty sprites up until the default sprite count. */
|
||||||
return load_index < SPR_OPENTTD_BASE + OPENTTD_SPRITE_COUNT;
|
return load_index < SPR_OPENTTD_BASE + OPENTTD_SPRITE_COUNT;
|
||||||
|
|
|
@ -3195,7 +3195,7 @@ CommandCost CmdTownRating(DoCommandFlags flags, TownID town_id, CompanyID compan
|
||||||
int16_t new_rating = Clamp(rating, RATING_MINIMUM, RATING_MAXIMUM);
|
int16_t new_rating = Clamp(rating, RATING_MINIMUM, RATING_MAXIMUM);
|
||||||
if (flags.Test(DoCommandFlag::Execute)) {
|
if (flags.Test(DoCommandFlag::Execute)) {
|
||||||
t->ratings[company_id] = new_rating;
|
t->ratings[company_id] = new_rating;
|
||||||
InvalidateWindowData(WC_TOWN_AUTHORITY, town_id);
|
InvalidateWindowData(WC_TOWN_VIEW, town_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
|
@ -3591,7 +3591,7 @@ static CommandCost TownActionBribe(Town *t, DoCommandFlags flags)
|
||||||
*/
|
*/
|
||||||
if (t->ratings[_current_company] > RATING_BRIBE_DOWN_TO) {
|
if (t->ratings[_current_company] > RATING_BRIBE_DOWN_TO) {
|
||||||
t->ratings[_current_company] = RATING_BRIBE_DOWN_TO;
|
t->ratings[_current_company] = RATING_BRIBE_DOWN_TO;
|
||||||
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
|
SetWindowDirty(WC_TOWN_VIEW, t->index);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ChangeTownRating(t, RATING_BRIBE_UP_STEP, RATING_BRIBE_MAXIMUM, DoCommandFlag::Execute);
|
ChangeTownRating(t, RATING_BRIBE_UP_STEP, RATING_BRIBE_MAXIMUM, DoCommandFlag::Execute);
|
||||||
|
@ -3692,7 +3692,7 @@ CommandCost CmdDoTownAction(DoCommandFlags flags, TownID town_id, TownAction act
|
||||||
if (ret.Failed()) return ret;
|
if (ret.Failed()) return ret;
|
||||||
|
|
||||||
if (flags.Test(DoCommandFlag::Execute)) {
|
if (flags.Test(DoCommandFlag::Execute)) {
|
||||||
SetWindowDirty(WC_TOWN_AUTHORITY, town_id);
|
SetWindowDirty(WC_TOWN_VIEW, town_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -3745,7 +3745,7 @@ static void UpdateTownRating(Town *t)
|
||||||
t->ratings[i] = Clamp(t->ratings[i], RATING_MINIMUM, RATING_MAXIMUM);
|
t->ratings[i] = Clamp(t->ratings[i], RATING_MINIMUM, RATING_MAXIMUM);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
|
SetWindowDirty(WC_TOWN_VIEW, t->index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4017,7 +4017,7 @@ void ChangeTownRating(Town *t, int add, int max, DoCommandFlags flags)
|
||||||
} else {
|
} else {
|
||||||
t->have_ratings.Set(_current_company);
|
t->have_ratings.Set(_current_company);
|
||||||
t->ratings[_current_company] = rating;
|
t->ratings[_current_company] = rating;
|
||||||
SetWindowDirty(WC_TOWN_AUTHORITY, t->index);
|
InvalidateWindowData(WC_TOWN_VIEW, t->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
547
src/town_gui.cpp
547
src/town_gui.cpp
|
@ -57,36 +57,21 @@ TownKdtree _town_local_authority_kdtree{};
|
||||||
|
|
||||||
typedef GUIList<const Town*, const bool &> GUITownList;
|
typedef GUIList<const Town*, const bool &> GUITownList;
|
||||||
|
|
||||||
static constexpr NWidgetPart _nested_town_authority_widgets[] = {
|
/* Town view window. */
|
||||||
NWidget(NWID_HORIZONTAL),
|
struct TownViewWindow : Window {
|
||||||
NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
|
|
||||||
NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TA_CAPTION),
|
|
||||||
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TA_ZONE_BUTTON), SetMinimalSize(50, 0), SetStringTip(STR_LOCAL_AUTHORITY_ZONE, STR_LOCAL_AUTHORITY_ZONE_TOOLTIP),
|
|
||||||
NWidget(WWT_SHADEBOX, COLOUR_BROWN),
|
|
||||||
NWidget(WWT_DEFSIZEBOX, COLOUR_BROWN),
|
|
||||||
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
|
|
||||||
EndContainer(),
|
|
||||||
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_RATING_INFO), SetMinimalSize(317, 92), SetResize(1, 1), EndContainer(),
|
|
||||||
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_COMMAND_LIST), SetMinimalSize(317, 52), SetResize(1, 0), SetToolTip(STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP), EndContainer(),
|
|
||||||
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TA_ACTION_INFO), SetMinimalSize(317, 52), SetResize(1, 0), EndContainer(),
|
|
||||||
NWidget(NWID_HORIZONTAL),
|
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TA_EXECUTE), SetMinimalSize(317, 12), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_LOCAL_AUTHORITY_DO_IT_BUTTON, STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP),
|
|
||||||
NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
|
|
||||||
EndContainer()
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Town authority window. */
|
|
||||||
struct TownAuthorityWindow : Window {
|
|
||||||
private:
|
private:
|
||||||
Town *town = nullptr; ///< Town being displayed.
|
Town *town = nullptr; ///< Town displayed by the window.
|
||||||
TownAction sel_action = TownAction::End; ///< Currently selected town action, TownAction::End means no action selected.
|
TownAction sel_action = TownAction::End; ///< Currently selected town action, TownAction::End means no action selected.
|
||||||
TownActions displayed_actions_on_previous_painting{}; ///< Actions that were available on the previous call to OnPaint()
|
|
||||||
TownActions enabled_actions{}; ///< Actions that are enabled in settings.
|
TownActions enabled_actions{}; ///< Actions that are enabled in settings.
|
||||||
TownActions available_actions{}; ///< Actions that are available to execute for the current company.
|
TownActions available_actions{}; ///< Actions that are available to execute for the current company.
|
||||||
std::array<StringID, to_underlying(TownAction::End)> action_tooltips{};
|
std::array<StringID, to_underlying(TownAction::End)> action_tooltips{};
|
||||||
|
|
||||||
Dimension icon_size{}; ///< Dimensions of company icon
|
Dimension icon_size{}; ///< Dimensions of company icon
|
||||||
Dimension exclusive_size{}; ///< Dimensions of exclusive icon
|
Dimension exclusive_size{}; ///< Dimensions of exclusive icon
|
||||||
|
uint rating_line_height = 0;
|
||||||
|
|
||||||
|
static inline uint initial_visible_pane = 0;
|
||||||
|
uint visible_pane = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all town authority actions enabled in settings.
|
* Gets all town authority actions enabled in settings.
|
||||||
|
@ -107,10 +92,17 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TownAuthorityWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
|
static const int WID_TV_HEIGHT_NORMAL = 150;
|
||||||
|
|
||||||
|
TownViewWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
|
||||||
{
|
{
|
||||||
|
this->visible_pane = TownViewWindow::initial_visible_pane;
|
||||||
|
|
||||||
|
this->CreateNestedTree();
|
||||||
|
|
||||||
this->town = Town::Get(window_number);
|
this->town = Town::Get(window_number);
|
||||||
this->enabled_actions = GetEnabledActions();
|
this->enabled_actions = GetEnabledActions();
|
||||||
|
this->available_actions = GetMaskOfTownActions(_local_company, this->town);
|
||||||
|
|
||||||
auto realtime = TimerGameEconomy::UsingWallclockUnits();
|
auto realtime = TimerGameEconomy::UsingWallclockUnits();
|
||||||
this->action_tooltips[0] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING;
|
this->action_tooltips[0] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING;
|
||||||
|
@ -122,238 +114,7 @@ public:
|
||||||
this->action_tooltips[6] = realtime ? STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MINUTES : STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MONTHS;
|
this->action_tooltips[6] = realtime ? STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MINUTES : STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT_MONTHS;
|
||||||
this->action_tooltips[7] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE;
|
this->action_tooltips[7] = STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE;
|
||||||
|
|
||||||
this->InitNested(window_number);
|
this->SetPaneState();
|
||||||
}
|
|
||||||
|
|
||||||
void OnInit() override
|
|
||||||
{
|
|
||||||
this->icon_size = GetSpriteSize(SPR_COMPANY_ICON);
|
|
||||||
this->exclusive_size = GetSpriteSize(SPR_EXCLUSIVE_TRANSPORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnPaint() override
|
|
||||||
{
|
|
||||||
this->available_actions = GetMaskOfTownActions(_local_company, this->town);
|
|
||||||
if (this->available_actions != displayed_actions_on_previous_painting) this->SetDirty();
|
|
||||||
displayed_actions_on_previous_painting = this->available_actions;
|
|
||||||
|
|
||||||
this->SetWidgetLoweredState(WID_TA_ZONE_BUTTON, this->town->show_zone);
|
|
||||||
this->SetWidgetDisabledState(WID_TA_EXECUTE, (this->sel_action == TownAction::End) || !this->available_actions.Test(this->sel_action));
|
|
||||||
|
|
||||||
this->DrawWidgets();
|
|
||||||
if (!this->IsShaded())
|
|
||||||
{
|
|
||||||
this->DrawRatings();
|
|
||||||
this->DrawActions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StringID GetRatingString(int rating) const
|
|
||||||
{
|
|
||||||
if (rating > RATING_EXCELLENT) return STR_CARGO_RATING_OUTSTANDING;
|
|
||||||
if (rating > RATING_VERYGOOD) return STR_CARGO_RATING_EXCELLENT;
|
|
||||||
if (rating > RATING_GOOD) return STR_CARGO_RATING_VERY_GOOD;
|
|
||||||
if (rating > RATING_MEDIOCRE) return STR_CARGO_RATING_GOOD;
|
|
||||||
if (rating > RATING_POOR) return STR_CARGO_RATING_MEDIOCRE;
|
|
||||||
if (rating > RATING_VERYPOOR) return STR_CARGO_RATING_POOR;
|
|
||||||
if (rating > RATING_APPALLING) return STR_CARGO_RATING_VERY_POOR;
|
|
||||||
return STR_CARGO_RATING_APPALLING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Draw the contents of the ratings panel. May request a resize of the window if the contents does not fit. */
|
|
||||||
void DrawRatings()
|
|
||||||
{
|
|
||||||
Rect r = this->GetWidget<NWidgetBase>(WID_TA_RATING_INFO)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
|
|
||||||
|
|
||||||
int text_y_offset = (this->resize.step_height - GetCharacterHeight(FS_NORMAL)) / 2;
|
|
||||||
int icon_y_offset = (this->resize.step_height - this->icon_size.height) / 2;
|
|
||||||
int exclusive_y_offset = (this->resize.step_height - this->exclusive_size.height) / 2;
|
|
||||||
|
|
||||||
DrawString(r.left, r.right, r.top + text_y_offset, STR_LOCAL_AUTHORITY_COMPANY_RATINGS);
|
|
||||||
r.top += this->resize.step_height;
|
|
||||||
|
|
||||||
bool rtl = _current_text_dir == TD_RTL;
|
|
||||||
Rect icon = r.WithWidth(this->icon_size.width, rtl);
|
|
||||||
Rect exclusive = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(this->exclusive_size.width, rtl);
|
|
||||||
Rect text = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal + this->exclusive_size.width + WidgetDimensions::scaled.hsep_normal, rtl);
|
|
||||||
|
|
||||||
/* Draw list of companies */
|
|
||||||
for (const Company *c : Company::Iterate()) {
|
|
||||||
if ((this->town->have_ratings.Test(c->index) || this->town->exclusivity == c->index)) {
|
|
||||||
DrawCompanyIcon(c->index, icon.left, text.top + icon_y_offset);
|
|
||||||
|
|
||||||
if (this->town->exclusivity == c->index) {
|
|
||||||
DrawSprite(SPR_EXCLUSIVE_TRANSPORT, GetCompanyPalette(c->index), exclusive.left, text.top + exclusive_y_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rating = this->town->ratings[c->index];
|
|
||||||
DrawString(text.left, text.right, text.top + text_y_offset, GetString(STR_LOCAL_AUTHORITY_COMPANY_RATING, c->index, c->index, GetRatingString(rating)));
|
|
||||||
text.top += this->resize.step_height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
text.bottom = text.top - 1;
|
|
||||||
if (text.bottom > r.bottom) {
|
|
||||||
/* If the company list is too big to fit, mark ourself dirty and draw again. */
|
|
||||||
ResizeWindow(this, 0, text.bottom - r.bottom, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Draws the contents of the actions panel. May re-initialise window to resize panel, if the list does not fit. */
|
|
||||||
void DrawActions()
|
|
||||||
{
|
|
||||||
Rect r = this->GetWidget<NWidgetBase>(WID_TA_COMMAND_LIST)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect);
|
|
||||||
|
|
||||||
DrawString(r, STR_LOCAL_AUTHORITY_ACTIONS_TITLE);
|
|
||||||
r.top += GetCharacterHeight(FS_NORMAL);
|
|
||||||
|
|
||||||
/* Draw list of actions */
|
|
||||||
for (TownAction i = {}; i != TownAction::End; ++i) {
|
|
||||||
/* Don't show actions if disabled in settings. */
|
|
||||||
if (!this->enabled_actions.Test(i)) continue;
|
|
||||||
|
|
||||||
/* Set colour of action based on ability to execute and if selected. */
|
|
||||||
TextColour action_colour = TC_GREY | TC_NO_SHADE;
|
|
||||||
if (this->available_actions.Test(i)) action_colour = TC_ORANGE;
|
|
||||||
if (this->sel_action == i) action_colour = TC_WHITE;
|
|
||||||
|
|
||||||
DrawString(r, STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i), action_colour);
|
|
||||||
r.top += GetCharacterHeight(FS_NORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
|
|
||||||
{
|
|
||||||
if (widget == WID_TA_CAPTION) return GetString(STR_LOCAL_AUTHORITY_CAPTION, this->window_number);
|
|
||||||
|
|
||||||
return this->Window::GetWidgetString(widget, stringid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawWidget(const Rect &r, WidgetID widget) const override
|
|
||||||
{
|
|
||||||
switch (widget) {
|
|
||||||
case WID_TA_ACTION_INFO:
|
|
||||||
if (this->sel_action != TownAction::End) {
|
|
||||||
Money action_cost = _price[PR_TOWN_ACTION] * GetTownActionCost(this->sel_action) >> 8;
|
|
||||||
bool affordable = Company::IsValidID(_local_company) && action_cost < GetAvailableMoney(_local_company);
|
|
||||||
|
|
||||||
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect),
|
|
||||||
GetString(this->action_tooltips[to_underlying(this->sel_action)], action_cost),
|
|
||||||
affordable ? TC_YELLOW : TC_RED);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
|
|
||||||
{
|
|
||||||
switch (widget) {
|
|
||||||
case WID_TA_ACTION_INFO: {
|
|
||||||
assert(size.width > padding.width && size.height > padding.height);
|
|
||||||
Dimension d = {0, 0};
|
|
||||||
for (TownAction i = {}; i != TownAction::End; ++i) {
|
|
||||||
Money price = _price[PR_TOWN_ACTION] * GetTownActionCost(i) >> 8;
|
|
||||||
d = maxdim(d, GetStringMultiLineBoundingBox(GetString(this->action_tooltips[to_underlying(i)], price), size));
|
|
||||||
}
|
|
||||||
d.width += padding.width;
|
|
||||||
d.height += padding.height;
|
|
||||||
size = maxdim(size, d);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WID_TA_COMMAND_LIST:
|
|
||||||
size.height = (to_underlying(TownAction::End) + 1) * GetCharacterHeight(FS_NORMAL) + padding.height;
|
|
||||||
size.width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
|
|
||||||
for (TownAction i = {}; i != TownAction::End; ++i) {
|
|
||||||
size.width = std::max(size.width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i)).width + padding.width);
|
|
||||||
}
|
|
||||||
size.width += padding.width;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WID_TA_RATING_INFO:
|
|
||||||
fill.height = resize.height = std::max({this->icon_size.height + WidgetDimensions::scaled.vsep_normal, this->exclusive_size.height + WidgetDimensions::scaled.vsep_normal, (uint)GetCharacterHeight(FS_NORMAL)});
|
|
||||||
size.height = 9 * resize.height + padding.height;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
|
||||||
{
|
|
||||||
switch (widget) {
|
|
||||||
case WID_TA_ZONE_BUTTON: {
|
|
||||||
bool new_show_state = !this->town->show_zone;
|
|
||||||
TownID index = this->town->index;
|
|
||||||
|
|
||||||
new_show_state ? _town_local_authority_kdtree.Insert(index) : _town_local_authority_kdtree.Remove(index);
|
|
||||||
|
|
||||||
this->town->show_zone = new_show_state;
|
|
||||||
this->SetWidgetLoweredState(widget, new_show_state);
|
|
||||||
MarkWholeScreenDirty();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WID_TA_COMMAND_LIST: {
|
|
||||||
int y = this->GetRowFromWidget(pt.y, WID_TA_COMMAND_LIST, 1, GetCharacterHeight(FS_NORMAL)) - 1;
|
|
||||||
|
|
||||||
auto action = this->enabled_actions.GetNthSetBit(y);
|
|
||||||
if (!action.has_value()) break;
|
|
||||||
|
|
||||||
this->sel_action = *action;
|
|
||||||
this->SetDirty();
|
|
||||||
|
|
||||||
/* When double-clicking, continue */
|
|
||||||
if (click_count == 1 || !this->available_actions.Test(this->sel_action)) break;
|
|
||||||
[[fallthrough]];
|
|
||||||
}
|
|
||||||
|
|
||||||
case WID_TA_EXECUTE:
|
|
||||||
Command<CMD_DO_TOWN_ACTION>::Post(STR_ERROR_CAN_T_DO_THIS, this->town->xy, static_cast<TownID>(this->window_number), this->sel_action);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Redraw the whole window on a regular interval. */
|
|
||||||
const IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
|
|
||||||
this->SetDirty();
|
|
||||||
}};
|
|
||||||
|
|
||||||
void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
|
|
||||||
{
|
|
||||||
if (!gui_scope) return;
|
|
||||||
|
|
||||||
this->enabled_actions = this->GetEnabledActions();
|
|
||||||
if (!this->enabled_actions.Test(this->sel_action)) {
|
|
||||||
this->sel_action = TownAction::End;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static WindowDesc _town_authority_desc(
|
|
||||||
WDP_AUTO, "view_town_authority", 317, 222,
|
|
||||||
WC_TOWN_AUTHORITY, WC_NONE,
|
|
||||||
{},
|
|
||||||
_nested_town_authority_widgets
|
|
||||||
);
|
|
||||||
|
|
||||||
static void ShowTownAuthorityWindow(uint town)
|
|
||||||
{
|
|
||||||
AllocateWindowDescFront<TownAuthorityWindow>(_town_authority_desc, town);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Town view window. */
|
|
||||||
struct TownViewWindow : Window {
|
|
||||||
private:
|
|
||||||
Town *town = nullptr; ///< Town displayed by the window.
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const int WID_TV_HEIGHT_NORMAL = 150;
|
|
||||||
|
|
||||||
TownViewWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc)
|
|
||||||
{
|
|
||||||
this->CreateNestedTree();
|
|
||||||
|
|
||||||
this->town = Town::Get(window_number);
|
|
||||||
|
|
||||||
this->FinishInitNested(window_number);
|
this->FinishInitNested(window_number);
|
||||||
|
|
||||||
|
@ -365,6 +126,23 @@ public:
|
||||||
this->SetWidgetDisabledState(WID_TV_CHANGE_NAME, _networking && !_network_server);
|
this->SetWidgetDisabledState(WID_TV_CHANGE_NAME, _networking && !_network_server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetPaneState()
|
||||||
|
{
|
||||||
|
if (auto *nwid = this->GetWidget<NWidgetStacked>(WID_TV_PANE_SEL); nwid != nullptr) {
|
||||||
|
nwid->SetDisplayedPlane(this->visible_pane);
|
||||||
|
this->SetWidgetLoweredState(WID_TV_PANE_INFO, this->visible_pane == 0);
|
||||||
|
this->SetWidgetLoweredState(WID_TV_PANE_RATINGS, this->visible_pane == 1);
|
||||||
|
this->SetWidgetLoweredState(WID_TV_PANE_ACTIONS, this->visible_pane == 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnInit() override
|
||||||
|
{
|
||||||
|
this->icon_size = GetScaledSpriteSize(SPR_COMPANY_ICON);
|
||||||
|
this->exclusive_size = GetScaledSpriteSize(SPR_EXCLUSIVE_TRANSPORT);
|
||||||
|
this->rating_line_height = std::max({this->icon_size.height, this->exclusive_size.height, (uint)GetCharacterHeight(FS_NORMAL)});
|
||||||
|
}
|
||||||
|
|
||||||
void Close([[maybe_unused]] int data = 0) override
|
void Close([[maybe_unused]] int data = 0) override
|
||||||
{
|
{
|
||||||
SetViewportCatchmentTown(Town::Get(this->window_number), false);
|
SetViewportCatchmentTown(Town::Get(this->window_number), false);
|
||||||
|
@ -382,14 +160,24 @@ public:
|
||||||
{
|
{
|
||||||
extern const Town *_viewport_highlight_town;
|
extern const Town *_viewport_highlight_town;
|
||||||
this->SetWidgetLoweredState(WID_TV_CATCHMENT, _viewport_highlight_town == this->town);
|
this->SetWidgetLoweredState(WID_TV_CATCHMENT, _viewport_highlight_town == this->town);
|
||||||
|
this->SetWidgetLoweredState(WID_TV_ZONE, this->town->show_zone);
|
||||||
|
this->SetWidgetDisabledState(WID_TV_EXECUTE, this->visible_pane != 2 || this->sel_action == TownAction::End || !this->available_actions.Test(this->sel_action));
|
||||||
this->DrawWidgets();
|
this->DrawWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawWidget(const Rect &r, WidgetID widget) const override
|
void DrawWidget(const Rect &r, WidgetID widget) const override
|
||||||
{
|
{
|
||||||
if (widget != WID_TV_INFO) return;
|
switch (widget) {
|
||||||
|
case WID_TV_INFO: this->DrawInfo(r); break;
|
||||||
|
case WID_TV_RATING_INFO: this->DrawRatings(r); break;
|
||||||
|
case WID_TV_COMMAND_LIST: this->DrawActions(r); break;
|
||||||
|
case WID_TV_ACTION_INFO: this->DrawActionInfo(r); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawInfo(const Rect &r) const
|
||||||
|
{
|
||||||
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
|
|
||||||
DrawString(tr, GetString(STR_TOWN_VIEW_POPULATION_HOUSES, this->town->cache.population, this->town->cache.num_houses));
|
DrawString(tr, GetString(STR_TOWN_VIEW_POPULATION_HOUSES, this->town->cache.population, this->town->cache.num_houses));
|
||||||
|
@ -465,6 +253,86 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static StringID GetRatingString(int rating)
|
||||||
|
{
|
||||||
|
if (rating > RATING_EXCELLENT) return STR_CARGO_RATING_OUTSTANDING;
|
||||||
|
if (rating > RATING_VERYGOOD) return STR_CARGO_RATING_EXCELLENT;
|
||||||
|
if (rating > RATING_GOOD) return STR_CARGO_RATING_VERY_GOOD;
|
||||||
|
if (rating > RATING_MEDIOCRE) return STR_CARGO_RATING_GOOD;
|
||||||
|
if (rating > RATING_POOR) return STR_CARGO_RATING_MEDIOCRE;
|
||||||
|
if (rating > RATING_VERYPOOR) return STR_CARGO_RATING_POOR;
|
||||||
|
if (rating > RATING_APPALLING) return STR_CARGO_RATING_VERY_POOR;
|
||||||
|
return STR_CARGO_RATING_APPALLING;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Draw the contents of the ratings panel. May request a resize of the window if the contents does not fit. */
|
||||||
|
void DrawRatings(const Rect &r) const
|
||||||
|
{
|
||||||
|
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
|
|
||||||
|
int text_y_offset = (this->rating_line_height - GetCharacterHeight(FS_NORMAL)) / 2;
|
||||||
|
int icon_y_offset = (this->rating_line_height - this->icon_size.height) / 2;
|
||||||
|
int exclusive_y_offset = (this->rating_line_height - this->exclusive_size.height) / 2;
|
||||||
|
|
||||||
|
DrawString(tr.left, tr.right, tr.top + text_y_offset, STR_LOCAL_AUTHORITY_COMPANY_RATINGS);
|
||||||
|
tr.top += this->rating_line_height;
|
||||||
|
|
||||||
|
bool rtl = _current_text_dir == TD_RTL;
|
||||||
|
Rect icon = tr.WithWidth(this->icon_size.width, rtl);
|
||||||
|
Rect exclusive = tr.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(this->exclusive_size.width, rtl);
|
||||||
|
Rect text = tr.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal + this->exclusive_size.width + WidgetDimensions::scaled.hsep_normal, rtl);
|
||||||
|
|
||||||
|
/* Draw list of companies */
|
||||||
|
for (const Company *c : Company::Iterate()) {
|
||||||
|
if ((this->town->have_ratings.Test(c->index) || this->town->exclusivity == c->index)) {
|
||||||
|
DrawCompanyIcon(c->index, icon.left, text.top + icon_y_offset);
|
||||||
|
|
||||||
|
if (this->town->exclusivity == c->index) {
|
||||||
|
DrawSprite(SPR_EXCLUSIVE_TRANSPORT, GetCompanyPalette(c->index), exclusive.left, text.top + exclusive_y_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rating = this->town->ratings[c->index];
|
||||||
|
DrawString(text.left, text.right, text.top + text_y_offset, GetString(STR_LOCAL_AUTHORITY_COMPANY_RATING, c->index, c->index, GetRatingString(rating)));
|
||||||
|
text.top += this->rating_line_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Draws the contents of the actions panel. May re-initialise window to resize panel, if the list does not fit. */
|
||||||
|
void DrawActions(const Rect &r) const
|
||||||
|
{
|
||||||
|
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
|
|
||||||
|
DrawString(tr, STR_LOCAL_AUTHORITY_ACTIONS_TITLE);
|
||||||
|
tr.top += GetCharacterHeight(FS_NORMAL);
|
||||||
|
|
||||||
|
/* Draw list of actions */
|
||||||
|
for (TownAction i = {}; i != TownAction::End; ++i) {
|
||||||
|
/* Don't show actions if disabled in settings. */
|
||||||
|
if (!this->enabled_actions.Test(i)) continue;
|
||||||
|
|
||||||
|
/* Set colour of action based on ability to execute and if selected. */
|
||||||
|
TextColour action_colour = TC_GREY | TC_NO_SHADE;
|
||||||
|
if (this->available_actions.Test(i)) action_colour = TC_ORANGE;
|
||||||
|
if (this->sel_action == i) action_colour = TC_WHITE;
|
||||||
|
|
||||||
|
DrawString(tr, STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i), action_colour);
|
||||||
|
tr.top += GetCharacterHeight(FS_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawActionInfo(const Rect &r) const
|
||||||
|
{
|
||||||
|
if (this->sel_action == TownAction::End) return;
|
||||||
|
|
||||||
|
Money action_cost = _price[PR_TOWN_ACTION] * GetTownActionCost(this->sel_action) >> 8;
|
||||||
|
bool affordable = Company::IsValidID(_local_company) && action_cost < GetAvailableMoney(_local_company);
|
||||||
|
|
||||||
|
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect),
|
||||||
|
GetString(this->action_tooltips[to_underlying(this->sel_action)], action_cost),
|
||||||
|
affordable ? TC_YELLOW : TC_RED);
|
||||||
|
}
|
||||||
|
|
||||||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
|
@ -476,10 +344,6 @@ public:
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_TV_SHOW_AUTHORITY: // town authority
|
|
||||||
ShowTownAuthorityWindow(this->window_number);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WID_TV_CHANGE_NAME: // rename
|
case WID_TV_CHANGE_NAME: // rename
|
||||||
ShowQueryString(GetString(STR_TOWN_NAME, this->window_number), STR_TOWN_VIEW_RENAME_TOWN_BUTTON, MAX_LENGTH_TOWN_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
|
ShowQueryString(GetString(STR_TOWN_NAME, this->window_number), STR_TOWN_VIEW_RENAME_TOWN_BUTTON, MAX_LENGTH_TOWN_NAME_CHARS, this, CS_ALPHANUMERAL, {QueryStringFlag::EnableDefault, QueryStringFlag::LengthIsInChars});
|
||||||
break;
|
break;
|
||||||
|
@ -503,14 +367,68 @@ public:
|
||||||
case WID_TV_DELETE: // delete town - only available on Scenario editor
|
case WID_TV_DELETE: // delete town - only available on Scenario editor
|
||||||
Command<CMD_DELETE_TOWN>::Post(STR_ERROR_TOWN_CAN_T_DELETE, static_cast<TownID>(this->window_number));
|
Command<CMD_DELETE_TOWN>::Post(STR_ERROR_TOWN_CAN_T_DELETE, static_cast<TownID>(this->window_number));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WID_TV_ZONE: {
|
||||||
|
bool new_show_state = !this->town->show_zone;
|
||||||
|
TownID index = this->town->index;
|
||||||
|
|
||||||
|
new_show_state ? _town_local_authority_kdtree.Insert(index) : _town_local_authority_kdtree.Remove(index);
|
||||||
|
|
||||||
|
this->town->show_zone = new_show_state;
|
||||||
|
this->SetWidgetLoweredState(widget, new_show_state);
|
||||||
|
MarkWholeScreenDirty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_TV_COMMAND_LIST: {
|
||||||
|
int y = this->GetRowFromWidget(pt.y, widget, WidgetDimensions::scaled.framerect.top, GetCharacterHeight(FS_NORMAL)) - 1;
|
||||||
|
|
||||||
|
auto action = this->enabled_actions.GetNthSetBit(y);
|
||||||
|
if (!action.has_value()) break;
|
||||||
|
|
||||||
|
this->sel_action = *action;
|
||||||
|
this->SetDirty();
|
||||||
|
|
||||||
|
/* When double-clicking, continue */
|
||||||
|
if (click_count == 1 || !this->available_actions.Test(this->sel_action)) break;
|
||||||
|
[[fallthrough]];
|
||||||
|
}
|
||||||
|
|
||||||
|
case WID_TV_EXECUTE:
|
||||||
|
Command<CMD_DO_TOWN_ACTION>::Post(STR_ERROR_CAN_T_DO_THIS, this->town->xy, static_cast<TownID>(this->window_number), this->sel_action);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TV_PANE_INFO:
|
||||||
|
TownViewWindow::initial_visible_pane = this->visible_pane = 0;
|
||||||
|
this->ResizePanes();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TV_PANE_RATINGS:
|
||||||
|
TownViewWindow::initial_visible_pane = this->visible_pane = 1;
|
||||||
|
this->ResizePanes();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_TV_PANE_ACTIONS:
|
||||||
|
TownViewWindow::initial_visible_pane = this->visible_pane = 2;
|
||||||
|
this->ResizePanes();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
|
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_TV_INFO:
|
case WID_TV_COMMAND_LIST:
|
||||||
size.height = GetDesiredInfoHeight(size.width) + padding.height;
|
if (this->visible_pane != 2) {
|
||||||
|
size.height = 0;
|
||||||
|
} else {
|
||||||
|
size.height = (to_underlying(TownAction::End) + 1) * GetCharacterHeight(FS_NORMAL) + padding.height;
|
||||||
|
size.width = GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTIONS_TITLE).width;
|
||||||
|
for (TownAction i = {}; i != TownAction::End; ++i) {
|
||||||
|
size.width = std::max(size.width, GetStringBoundingBox(STR_LOCAL_AUTHORITY_ACTION_SMALL_ADVERTISING_CAMPAIGN + to_underlying(i)).width + padding.width);
|
||||||
|
}
|
||||||
|
size.width += padding.width;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -521,6 +439,7 @@ public:
|
||||||
*/
|
*/
|
||||||
uint GetDesiredInfoHeight(int width) const
|
uint GetDesiredInfoHeight(int width) const
|
||||||
{
|
{
|
||||||
|
width -= WidgetDimensions::scaled.framerect.Horizontal();
|
||||||
uint aimed_height = static_cast<uint>(1 + CargoSpec::town_production_cargoes[TPE_PASSENGERS].size() + CargoSpec::town_production_cargoes[TPE_MAIL].size()) * GetCharacterHeight(FS_NORMAL);
|
uint aimed_height = static_cast<uint>(1 + CargoSpec::town_production_cargoes[TPE_PASSENGERS].size() + CargoSpec::town_production_cargoes[TPE_MAIL].size()) * GetCharacterHeight(FS_NORMAL);
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
@ -540,23 +459,76 @@ public:
|
||||||
if (_settings_game.economy.station_noise_level) aimed_height += GetCharacterHeight(FS_NORMAL);
|
if (_settings_game.economy.station_noise_level) aimed_height += GetCharacterHeight(FS_NORMAL);
|
||||||
|
|
||||||
if (!this->town->text.empty()) {
|
if (!this->town->text.empty()) {
|
||||||
aimed_height += GetStringHeight(this->town->text.GetDecodedString(), width - WidgetDimensions::scaled.framerect.Horizontal());
|
aimed_height += GetStringHeight(this->town->text.GetDecodedString(), width);
|
||||||
}
|
}
|
||||||
|
|
||||||
return aimed_height;
|
return aimed_height + WidgetDimensions::scaled.framerect.Vertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResizeWindowAsNeeded()
|
uint GetDesiredRatingHeight(int) const
|
||||||
{
|
{
|
||||||
const NWidgetBase *nwid_info = this->GetWidget<NWidgetBase>(WID_TV_INFO);
|
int lines = 1;
|
||||||
uint aimed_height = GetDesiredInfoHeight(nwid_info->current_x);
|
for (const Company *c : Company::Iterate()) {
|
||||||
if (aimed_height > nwid_info->current_y || (aimed_height < nwid_info->current_y && nwid_info->current_y > nwid_info->smallest_y)) {
|
if ((this->town->have_ratings.Test(c->index) || this->town->exclusivity == c->index)) {
|
||||||
this->ReInit();
|
++lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return this->rating_line_height * std::max(3, lines) + WidgetDimensions::scaled.framerect.Vertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint GetDesiredActionInfoHeight(int width) const
|
||||||
|
{
|
||||||
|
width -= WidgetDimensions::scaled.framerect.Horizontal();
|
||||||
|
int height = 0;
|
||||||
|
for (TownAction i = {}; i != TownAction::End; ++i) {
|
||||||
|
Money price = _price[PR_TOWN_ACTION] * GetTownActionCost(i) >> 8;
|
||||||
|
height = std::max(height, GetStringHeight(GetString(this->action_tooltips[to_underlying(i)], price), width));
|
||||||
|
}
|
||||||
|
return height + WidgetDimensions::scaled.framerect.Vertical();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UpdatePaneSizes()
|
||||||
|
{
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
auto *sel = this->GetWidget<NWidgetStacked>(WID_TV_PANE_SEL);
|
||||||
|
if (sel != nullptr) {
|
||||||
|
if (auto *nwid = this->GetWidget<NWidgetCore>(WID_TV_INFO); nwid != nullptr) {
|
||||||
|
uint y = this->visible_pane == 0 ? GetDesiredInfoHeight(nwid->current_x) : 0;
|
||||||
|
changed |= nwid->UpdateVerticalSize(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto *nwid = this->GetWidget<NWidgetCore>(WID_TV_RATING_INFO); nwid != nullptr) {
|
||||||
|
uint y = this->visible_pane == 1 ? GetDesiredRatingHeight(nwid->current_x) : 0;
|
||||||
|
changed |= nwid->UpdateVerticalSize(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto *nwid = this->GetWidget<NWidgetCore>(WID_TV_ACTION_INFO); nwid != nullptr) {
|
||||||
|
uint y = this->visible_pane == 2 ? GetDesiredActionInfoHeight(nwid->current_x) : 0;
|
||||||
|
changed |= nwid->UpdateVerticalSize(y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResizePanes()
|
||||||
|
{
|
||||||
|
this->SetPaneState();
|
||||||
|
|
||||||
|
/* We want to resize the window while maintaining the size of the viewport. */
|
||||||
|
auto *nwid = this->GetWidget<NWidgetViewport>(WID_TV_VIEWPORT);
|
||||||
|
int old_y = static_cast<int>(nwid->current_y);
|
||||||
|
this->OnResize();
|
||||||
|
int new_y = static_cast<int>(nwid->current_y);
|
||||||
|
|
||||||
|
if (old_y != new_y) ResizeWindow(this, 0, old_y - new_y, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
void OnResize() override
|
void OnResize() override
|
||||||
{
|
{
|
||||||
|
if (this->UpdatePaneSizes()) this->ReInit(0, 0);
|
||||||
|
|
||||||
if (this->viewport != nullptr) {
|
if (this->viewport != nullptr) {
|
||||||
NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_TV_VIEWPORT);
|
NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_TV_VIEWPORT);
|
||||||
nvp->UpdateViewportCoordinates(this);
|
nvp->UpdateViewportCoordinates(this);
|
||||||
|
@ -573,6 +545,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Redraw the whole window on a regular interval. */
|
||||||
|
const IntervalTimer<TimerWindow> redraw_interval = {std::chrono::seconds(3), [this](auto) {
|
||||||
|
this->SetDirty();
|
||||||
|
}};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some data on this window has become invalid.
|
* Some data on this window has become invalid.
|
||||||
* @param data Information about the changed data.
|
* @param data Information about the changed data.
|
||||||
|
@ -581,9 +558,16 @@ public:
|
||||||
void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
|
void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
|
||||||
{
|
{
|
||||||
if (!gui_scope) return;
|
if (!gui_scope) return;
|
||||||
|
|
||||||
/* Called when setting station noise or required cargoes have changed, in order to resize the window */
|
/* Called when setting station noise or required cargoes have changed, in order to resize the window */
|
||||||
|
this->enabled_actions = GetEnabledActions();
|
||||||
|
this->available_actions = GetMaskOfTownActions(_local_company, this->town);
|
||||||
|
if (!this->enabled_actions.Test(this->sel_action)) {
|
||||||
|
this->sel_action = TownAction::End;
|
||||||
|
}
|
||||||
|
|
||||||
this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
|
this->SetDirty(); // refresh display for current size. This will allow to avoid glitches when downgrading
|
||||||
this->ResizeWindowAsNeeded();
|
this->ResizePanes();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnQueryTextFinished(std::optional<std::string> str) override
|
void OnQueryTextFinished(std::optional<std::string> str) override
|
||||||
|
@ -614,10 +598,23 @@ static constexpr NWidgetPart _nested_town_game_view_widgets[] = {
|
||||||
NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetResize(1, 1),
|
NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_TV_VIEWPORT), SetMinimalSize(254, 86), SetFill(1, 0), SetResize(1, 1),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetMinimalSize(260, 32), SetResize(1, 0), SetFill(1, 0), EndContainer(),
|
NWidget(NWID_HORIZONTAL),
|
||||||
NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
|
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_PANE_INFO), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_INFO, STR_TOWN_VIEW_INFO_TOOLTIP),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_SHOW_AUTHORITY), SetMinimalSize(80, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON, STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP),
|
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_PANE_RATINGS), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_RATINGS, STR_TOWN_VIEW_RATINGS_TOOLTIP),
|
||||||
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_CATCHMENT), SetMinimalSize(40, 12), SetFill(1, 1), SetResize(1, 0), SetStringTip(STR_BUTTON_CATCHMENT, STR_TOOLTIP_CATCHMENT),
|
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_PANE_ACTIONS), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_TOWN_VIEW_ACTIONS, STR_TOWN_VIEW_ACTIONS_TOOLTIP),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_TV_PANE_SEL),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_INFO), SetResize(1, 0), SetFill(1, 1), EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_RATING_INFO), SetResize(1, 0), SetFill(1, 1), EndContainer(),
|
||||||
|
NWidget(NWID_VERTICAL),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_COMMAND_LIST), SetResize(1, 0), SetFill(1, 1), SetToolTip(STR_LOCAL_AUTHORITY_ACTIONS_TOOLTIP), EndContainer(),
|
||||||
|
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TV_ACTION_INFO), SetResize(1, 0), SetFill(1, 0), EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
EndContainer(),
|
||||||
|
NWidget(NWID_HORIZONTAL),
|
||||||
|
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_TV_EXECUTE), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_LOCAL_AUTHORITY_DO_IT_BUTTON, STR_LOCAL_AUTHORITY_DO_IT_TOOLTIP),
|
||||||
|
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_ZONE), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_LOCAL_AUTHORITY_ZONE, STR_LOCAL_AUTHORITY_ZONE_TOOLTIP),
|
||||||
|
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TV_CATCHMENT), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_BUTTON_CATCHMENT, STR_TOOLTIP_CATCHMENT),
|
||||||
NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
|
NWidget(WWT_RESIZEBOX, COLOUR_BROWN),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,30 +21,27 @@ enum TownDirectoryWidgets : WidgetID {
|
||||||
WID_TD_WORLD_POPULATION, ///< The world's population.
|
WID_TD_WORLD_POPULATION, ///< The world's population.
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Widgets of the #TownAuthorityWindow class. */
|
|
||||||
enum TownAuthorityWidgets : WidgetID {
|
|
||||||
WID_TA_CAPTION, ///< Caption of window.
|
|
||||||
WID_TA_ZONE_BUTTON, ///< Turn on/off showing local authority zone.
|
|
||||||
WID_TA_RATING_INFO, ///< Overview with ratings for each company.
|
|
||||||
WID_TA_COMMAND_LIST, ///< List of commands for the player.
|
|
||||||
WID_TA_SCROLLBAR, ///< Scrollbar of the list of commands.
|
|
||||||
WID_TA_ACTION_INFO, ///< Additional information about the action.
|
|
||||||
WID_TA_EXECUTE, ///< Do-it button.
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Widgets of the #TownViewWindow class. */
|
/** Widgets of the #TownViewWindow class. */
|
||||||
enum TownViewWidgets : WidgetID {
|
enum TownViewWidgets : WidgetID {
|
||||||
WID_TV_CAPTION, ///< Caption of window.
|
WID_TV_CAPTION, ///< Caption of window.
|
||||||
WID_TV_VIEWPORT, ///< View of the center of the town.
|
WID_TV_VIEWPORT, ///< View of the center of the town.
|
||||||
WID_TV_INFO, ///< General information about the town.
|
WID_TV_INFO, ///< General information about the town.
|
||||||
WID_TV_CENTER_VIEW, ///< Center the main view on this town.
|
WID_TV_CENTER_VIEW, ///< Center the main view on this town.
|
||||||
WID_TV_SHOW_AUTHORITY, ///< Show the town authority window.
|
|
||||||
WID_TV_CHANGE_NAME, ///< Change the name of this town.
|
WID_TV_CHANGE_NAME, ///< Change the name of this town.
|
||||||
WID_TV_CATCHMENT, ///< Toggle catchment area highlight.
|
WID_TV_CATCHMENT, ///< Toggle catchment area highlight.
|
||||||
WID_TV_EXPAND, ///< Expand this town (scenario editor only).
|
WID_TV_EXPAND, ///< Expand this town (scenario editor only).
|
||||||
WID_TV_EXPAND_BUILDINGS, ///< Expand number of buildings this town (scenario editor only).
|
WID_TV_EXPAND_BUILDINGS, ///< Expand number of buildings this town (scenario editor only).
|
||||||
WID_TV_EXPAND_ROADS, ///< Expand roads of this town (scenario editor only).
|
WID_TV_EXPAND_ROADS, ///< Expand roads of this town (scenario editor only).
|
||||||
WID_TV_DELETE, ///< Delete this town (scenario editor only).
|
WID_TV_DELETE, ///< Delete this town (scenario editor only).
|
||||||
|
WID_TV_PANE_SEL,
|
||||||
|
WID_TV_PANE_INFO,
|
||||||
|
WID_TV_PANE_RATINGS,
|
||||||
|
WID_TV_PANE_ACTIONS,
|
||||||
|
WID_TV_RATING_INFO, ///< Overview with ratings for each company.
|
||||||
|
WID_TV_COMMAND_LIST, ///< List of commands for the player.
|
||||||
|
WID_TV_ACTION_INFO, ///< Additional information about the action.
|
||||||
|
WID_TV_EXECUTE, ///< Do-it button.
|
||||||
|
WID_TV_ZONE, ///< Turn on/off showing local authority zone.
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Widgets of the #FoundTownWindow class. */
|
/** Widgets of the #FoundTownWindow class. */
|
||||||
|
|
|
@ -189,12 +189,6 @@ enum WindowClass : uint16_t {
|
||||||
WC_TEXTFILE,
|
WC_TEXTFILE,
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Town authority; %Window numbers:
|
|
||||||
* - #TownID = #TownAuthorityWidgets
|
|
||||||
*/
|
|
||||||
WC_TOWN_AUTHORITY,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vehicle details; %Window numbers:
|
* Vehicle details; %Window numbers:
|
||||||
* - #VehicleID = #VehicleDetailsWidgets
|
* - #VehicleID = #VehicleDetailsWidgets
|
||||||
|
|
Loading…
Reference in New Issue