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
pull/211/head
Jonathan G Rennison 3 years ago
parent 369c98e3e0
commit 78b06ddc40

@ -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. */

@ -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);

@ -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();

@ -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();

@ -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();
}

@ -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;

@ -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();
}
void AfterLoadTemplateVehiclesUpdateImages()
{
InvalidateTemplateReplacementImages();
}
void AfterLoadTemplateVehiclesUpdateProperties()

@ -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;

@ -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*);

@ -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;
}

@ -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

@ -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.
*/

@ -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[];

Loading…
Cancel
Save