TBTR: Fix palette recolouring of templates

Fix group overrides affecting template image when cloning vehicle
Update template when changing company colours

Update template images on demand instead of at load
This commit is contained in:
Jonathan G Rennison
2020-12-26 09:37:26 +00:00
parent 369c98e3e0
commit 78b06ddc40
13 changed files with 98 additions and 44 deletions

View File

@@ -35,6 +35,7 @@
#include "goal_base.h"
#include "story_base.h"
#include "zoning.h"
#include "tbtr_template_vehicle_func.h"
#include "table/strings.h"
@@ -1039,6 +1040,7 @@ CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1,
}
ResetVehicleColourMap();
InvalidateTemplateReplacementImages();
MarkWholeScreenDirty();
/* All graph related to companies use the company colour. */

View File

@@ -51,6 +51,7 @@
#include "linkgraph/refresh.h"
#include "tracerestrict.h"
#include "tbtr_template_vehicle.h"
#include "tbtr_template_vehicle_func.h"
#include "scope_info.h"
#include "pathfinder/yapf/yapf_cache.h"
@@ -578,6 +579,8 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
NotifyRoadLayoutChanged();
InvalidateTemplateReplacementImages();
cur_company.Restore();
RegisterGameEvents(new_owner != INVALID_OWNER ? GEF_COMPANY_MERGE : GEF_COMPANY_DELETE);

View File

@@ -37,6 +37,7 @@
#include "command_func.h"
#include "zoning.h"
#include "cargopacket.h"
#include "tbtr_template_vehicle_func.h"
#include "safeguards.h"
@@ -153,6 +154,7 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
InvalidateVehicleTickCaches();
ClearVehicleTickCaches();
InvalidateTemplateReplacementImages();
ResetObjectToPlace();
ResetRailPlacementSnapping();

View File

@@ -77,6 +77,7 @@
#include "industry.h"
#include "cargopacket.h"
#include "core/checksum_func.hpp"
#include "tbtr_template_vehicle_func.h"
#include "linkgraph/linkgraphschedule.h"
#include "tracerestrict.h"
@@ -431,6 +432,7 @@ static void ShutdownGame()
ViewportMapClearTunnelCache();
InvalidateVehicleTickCaches();
ClearVehicleTickCaches();
InvalidateTemplateReplacementImages();
ClearCommandLog();
ClearDesyncMsgLog();

View File

@@ -3838,7 +3838,7 @@ bool AfterLoadGame()
AfterLoadLinkGraphs();
AfterLoadTraceRestrict();
AfterLoadTemplateVehiclesUpdateImage();
AfterLoadTemplateVehiclesUpdate();
if (SlXvIsFeaturePresent(XSLFI_TEMPLATE_REPLACEMENT, 1, 5)) {
AfterLoadTemplateVehiclesUpdateProperties();
}
@@ -3937,7 +3937,7 @@ void ReloadNewGRFData()
/* redraw the whole screen */
MarkWholeScreenDirty();
CheckTrainsLengths();
AfterLoadTemplateVehiclesUpdateImage();
AfterLoadTemplateVehiclesUpdateImages();
AfterLoadTemplateVehiclesUpdateProperties();
UpdateAllAnimatedTileSpeeds();
}

View File

@@ -50,7 +50,8 @@ void ResetTempEngineData();
Engine *GetTempDataEngine(EngineID index);
void CopyTempEngineData();
void AfterLoadTemplateVehiclesUpdateImage();
void AfterLoadTemplateVehiclesUpdate();
void AfterLoadTemplateVehiclesUpdateImages();
void AfterLoadTemplateVehiclesUpdateProperties();
extern int32 _saved_scrollpos_x;

View File

@@ -99,7 +99,7 @@ void AfterLoadTemplateVehicles()
}
}
void AfterLoadTemplateVehiclesUpdateImage()
void AfterLoadTemplateVehiclesUpdate()
{
SavedRandomSeeds saved_seeds;
SaveRandomSeeds(&saved_seeds);
@@ -113,36 +113,14 @@ void AfterLoadTemplateVehiclesUpdateImage()
}
}
for (TemplateVehicle *tv : TemplateVehicle::Iterate()) {
if (tv->Prev() == nullptr) {
Backup<CompanyID> cur_company(_current_company, tv->owner, FILE_LINE);
StringID err;
Train* t = VirtualTrainFromTemplateVehicle(tv, err, 0);
if (t != nullptr) {
int tv_len = 0;
for (TemplateVehicle *u = tv; u != nullptr; u = u->Next()) {
tv_len++;
}
int t_len = 0;
for (Train *u = t; u != nullptr; u = u->Next()) {
t_len++;
}
if (t_len == tv_len) {
Train *v = t;
for (TemplateVehicle *u = tv; u != nullptr; u = u->Next(), v = v->Next()) {
v->GetImage(DIR_W, EIT_IN_DEPOT, &u->sprite_seq);
u->image_dimensions.SetFromTrain(v);
}
} else {
DEBUG(misc, 0, "AfterLoadTemplateVehiclesUpdateImage: vehicle count mismatch: %u, %u", t_len, tv_len);
}
delete t;
}
cur_company.Restore();
}
RestoreRandomSeeds(saved_seeds);
InvalidateTemplateReplacementImages();
}
RestoreRandomSeeds(saved_seeds);
void AfterLoadTemplateVehiclesUpdateImages()
{
InvalidateTemplateReplacementImages();
}
void AfterLoadTemplateVehiclesUpdateProperties()

View File

@@ -642,6 +642,8 @@ public:
void DrawTemplateList(const Rect &r) const
{
if (!_template_vehicle_images_valid) UpdateAllTemplateVehicleImages();
const_cast<TemplateReplaceWindow *>(this)->BuildTemplateGuiList();
int left = r.left;

View File

@@ -42,6 +42,8 @@ static const uint16 CONSIST_TAIL = 0xffff;
typedef Pool<TemplateVehicle, TemplateID, 512, 64000> TemplatePool;
extern TemplatePool _template_pool;
extern bool _template_vehicle_images_valid;
/// listing/sorting templates
typedef GUIList<const TemplateVehicle*> GUITemplateList;
@@ -107,6 +109,7 @@ public:
VehicleSpriteSeq sprite_seq; ///< NOSAVE: Vehicle appearance.
TemplateVehicleImageDimensions image_dimensions; ///< NOSAVE: image dimensions
SpriteID colourmap; ///< NOSAVE: cached colour mapping
TemplateVehicle(VehicleType type = VEH_INVALID, EngineID e = INVALID_ENGINE, byte B = 0, Owner = _local_company);
TemplateVehicle(EngineID, RailVehicleInfo*);

View File

@@ -19,6 +19,8 @@
#include "core/geometry_type.hpp"
#include "debug.h"
#include "zoom_func.h"
#include "core/backup_type.hpp"
#include "core/random_func.hpp"
#include "table/sprites.h"
#include "table/strings.h"
@@ -41,7 +43,7 @@
#include "safeguards.h"
Vehicle *vhead, *vtmp;
bool _template_vehicle_images_valid = false;
#ifdef _DEBUG
// debugging printing functions for convenience, usually called from gdb
@@ -125,8 +127,7 @@ void DrawTemplate(const TemplateVehicle *tv, int left, int right, int y)
int offset = 0;
while (t) {
PaletteID pal = GetEnginePalette(t->engine_type, _current_company);
t->sprite_seq.Draw(offset + t->image_dimensions.GetOffsetX(), t->image_dimensions.GetOffsetY() + ScaleGUITrad(10), pal, false);
t->sprite_seq.Draw(offset + t->image_dimensions.GetOffsetX(), t->image_dimensions.GetOffsetY() + ScaleGUITrad(10), t->colourmap, false);
offset += t->image_dimensions.GetDisplayImageWidth();
t = t->Next();
@@ -170,6 +171,7 @@ void SetupTemplateVehicleFromVirtual(TemplateVehicle *tmp, TemplateVehicle *prev
virt->GetImage(DIR_W, EIT_IN_DEPOT, &tmp->sprite_seq);
tmp->image_dimensions.SetFromTrain(virt);
tmp->colourmap = GetUncachedTrainPaletteIgnoringGroup(virt);
}
// create a full TemplateVehicle based train according to a virtual train
@@ -428,3 +430,43 @@ void TransferCargoForTrain(Train *old_veh, Train *new_head)
/* Update train weight etc., the old vehicle will be sold anyway */
new_head->ConsistChanged(CCF_LOADUNLOAD);
}
void UpdateAllTemplateVehicleImages()
{
SavedRandomSeeds saved_seeds;
SaveRandomSeeds(&saved_seeds);
for (TemplateVehicle *tv : TemplateVehicle::Iterate()) {
if (tv->Prev() == nullptr) {
Backup<CompanyID> cur_company(_current_company, tv->owner, FILE_LINE);
StringID err;
Train* t = VirtualTrainFromTemplateVehicle(tv, err, 0);
if (t != nullptr) {
int tv_len = 0;
for (TemplateVehicle *u = tv; u != nullptr; u = u->Next()) {
tv_len++;
}
int t_len = 0;
for (Train *u = t; u != nullptr; u = u->Next()) {
t_len++;
}
if (t_len == tv_len) {
Train *v = t;
for (TemplateVehicle *u = tv; u != nullptr; u = u->Next(), v = v->Next()) {
v->GetImage(DIR_W, EIT_IN_DEPOT, &u->sprite_seq);
u->image_dimensions.SetFromTrain(v);
u->colourmap = GetVehiclePalette(v);
}
} else {
DEBUG(misc, 0, "UpdateAllTemplateVehicleImages: vehicle count mismatch: %u, %u", t_len, tv_len);
}
delete t;
}
cur_company.Restore();
}
}
RestoreRandomSeeds(saved_seeds);
_template_vehicle_images_valid = true;
}

View File

@@ -15,7 +15,7 @@
#include "tbtr_template_vehicle.h"
Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err, uint32 user);
Train* VirtualTrainFromTemplateVehicle(const TemplateVehicle* tv, StringID &err, uint32 user);
void BuildTemplateGuiList(GUITemplateList*, Scrollbar*, Owner, RailType);
@@ -59,4 +59,11 @@ void NeutralizeStatus(Train *t);
bool TrainMatchesTemplate(const Train *t, const TemplateVehicle *tv);
bool TrainMatchesTemplateRefit(const Train *t, const TemplateVehicle *tv);
void UpdateAllTemplateVehicleImages();
inline void InvalidateTemplateReplacementImages()
{
_template_vehicle_images_valid = false;
}
#endif

View File

@@ -2670,15 +2670,16 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_
* @param parent_engine_type EngineID of the front vehicle. INVALID_VEHICLE if vehicle is at front itself.
* @param v the vehicle. nullptr if in purchase list etc.
* @param livery_setting The livery settings to use for acquiring the livery information.
* @param ignore_group Ignore group overrides.
* @return livery to use
*/
const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, byte livery_setting)
const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, byte livery_setting, bool ignore_group)
{
const Company *c = Company::Get(company);
LiveryScheme scheme = LS_DEFAULT;
if (livery_setting == LIT_ALL || (livery_setting == LIT_COMPANY && company == _local_company)) {
if (v != nullptr) {
if (v != nullptr && !ignore_group) {
const Group *g = Group::GetIfValid(v->First()->group_id);
if (g != nullptr) {
/* Traverse parents until we find a livery or reach the top */
@@ -2701,9 +2702,9 @@ const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID
}
static PaletteID GetEngineColourMap(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v)
static PaletteID GetEngineColourMap(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, bool ignore_group = false)
{
PaletteID map = (v != nullptr) ? v->colourmap : PAL_NONE;
PaletteID map = (v != nullptr && !ignore_group) ? v->colourmap : PAL_NONE;
/* Return cached value if any */
if (map != PAL_NONE) return map;
@@ -2734,13 +2735,13 @@ static PaletteID GetEngineColourMap(EngineID engine_type, CompanyID company, Eng
/* Spectator has news shown too, but has invalid company ID - as well as dedicated server */
if (!Company::IsValidID(company)) return map;
const Livery *livery = GetEngineLivery(engine_type, company, parent_engine_type, v, _settings_client.gui.liveries);
const Livery *livery = GetEngineLivery(engine_type, company, parent_engine_type, v, _settings_client.gui.liveries, ignore_group);
map += livery->colour1;
if (twocc) map += livery->colour2 * 16;
/* Update cache */
if (v != nullptr) const_cast<Vehicle *>(v)->colourmap = map;
if (v != nullptr && !ignore_group) const_cast<Vehicle *>(v)->colourmap = map;
return map;
}
@@ -2769,6 +2770,16 @@ PaletteID GetVehiclePalette(const Vehicle *v)
return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);
}
/**
* Get the uncached colour map for a train, ignoring the vehicle's group.
* @param v Vehicle to get colour map for
* @return A ready-to-use palette modifier
*/
PaletteID GetUncachedTrainPaletteIgnoringGroup(const Train *v)
{
return GetEngineColourMap(v->engine_type, v->owner, v->GetGroundVehicleCache()->first_engine, v, true);
}
/**
* Delete all implicit orders which were not reached.
*/

View File

@@ -183,10 +183,11 @@ static inline bool IsCompanyBuildableVehicleType(const BaseVehicle *v)
}
LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v);
const struct Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, byte livery_setting);
const struct Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, byte livery_setting, bool ignore_group = false);
SpriteID GetEnginePalette(EngineID engine_type, CompanyID company);
SpriteID GetVehiclePalette(const Vehicle *v);
SpriteID GetUncachedTrainPaletteIgnoringGroup(const Train *v);
extern const uint32 _veh_build_proc_table[];
extern const uint32 _veh_sell_proc_table[];