Merge branch 'save_ext' into cargo_type_order
# Conflicts: # src/core/smallstack_type.hpp
This commit is contained in:
2
src/3rdparty/squirrel/squirrel/sqdebug.cpp
vendored
2
src/3rdparty/squirrel/squirrel/sqdebug.cpp
vendored
@@ -115,7 +115,7 @@ void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger ty
|
||||
SQInteger found = 0;
|
||||
for(SQInteger i=0; i<16; i++)
|
||||
{
|
||||
SQInteger mask = 0x00000001 << i;
|
||||
SQInteger mask = 0x00000001LL << i;
|
||||
if(typemask & (mask)) {
|
||||
if(found>0) StringCat(exptypes,SQString::Create(_ss(this), "|", -1), exptypes);
|
||||
found ++;
|
||||
|
||||
2
src/3rdparty/squirrel/squirrel/squtils.h
vendored
2
src/3rdparty/squirrel/squirrel/squtils.h
vendored
@@ -90,7 +90,7 @@ public:
|
||||
{
|
||||
_vals[idx].~T();
|
||||
if(idx < (_size - 1)) {
|
||||
memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - (size_t)idx - 1));
|
||||
memmove(static_cast<void *>(&_vals[idx]), &_vals[idx+1], sizeof(T) * (_size - (size_t)idx - 1));
|
||||
}
|
||||
_size--;
|
||||
}
|
||||
|
||||
17
src/3rdparty/squirrel/squirrel/sqvm.cpp
vendored
17
src/3rdparty/squirrel/squirrel/sqvm.cpp
vendored
@@ -215,7 +215,7 @@ bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
|
||||
_RET_SUCCEED(_integer(res))
|
||||
}
|
||||
}
|
||||
//continues through (no break needed)
|
||||
FALLTHROUGH;
|
||||
default:
|
||||
_RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
|
||||
}
|
||||
@@ -287,6 +287,7 @@ void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
|
||||
//else keeps going to the default
|
||||
}
|
||||
}
|
||||
FALLTHROUGH;
|
||||
default:
|
||||
seprintf(buf, lastof(buf),"(%s : 0x%p)",GetTypeName(o),(void*)_rawval(o));
|
||||
}
|
||||
@@ -377,8 +378,7 @@ bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQIntege
|
||||
}
|
||||
|
||||
if (!tailcall) {
|
||||
CallInfo lc;
|
||||
memset(&lc, 0, sizeof(lc));
|
||||
CallInfo lc = {};
|
||||
lc._generator = NULL;
|
||||
lc._etraps = 0;
|
||||
lc._prevstkbase = (SQInt32) ( stackbase - _stackbase );
|
||||
@@ -539,7 +539,7 @@ bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
|
||||
_generator(o1)->Resume(this, arg_2+1);
|
||||
_FINISH(0);
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
default:
|
||||
Raise_Error("cannot iterate %s", GetTypeName(o1));
|
||||
}
|
||||
@@ -769,7 +769,7 @@ exception_restore:
|
||||
ct_stackbase = _stackbase;
|
||||
goto common_call;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
case _OP_CALL: {
|
||||
ct_tailcall = false;
|
||||
ct_target = arg0;
|
||||
@@ -1101,7 +1101,7 @@ exception_trap:
|
||||
_lasterror = currerror;
|
||||
return false;
|
||||
}
|
||||
assert(0);
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)
|
||||
@@ -1158,8 +1158,7 @@ bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackb
|
||||
SQInteger oldtop = _top;
|
||||
SQInteger oldstackbase = _stackbase;
|
||||
_top = stackbase + nargs;
|
||||
CallInfo lci;
|
||||
memset(&lci, 0, sizeof(lci));
|
||||
CallInfo lci = {};
|
||||
lci._closure = nclosure;
|
||||
lci._generator = NULL;
|
||||
lci._etraps = 0;
|
||||
@@ -1330,7 +1329,7 @@ bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//keeps going
|
||||
FALLTHROUGH;
|
||||
case OT_USERDATA:
|
||||
if(_delegable(self)->_delegate) {
|
||||
SQObjectPtr t;
|
||||
|
||||
@@ -306,7 +306,6 @@ struct AISettingsWindow : public Window {
|
||||
timeout(0)
|
||||
{
|
||||
this->ai_config = GetConfig(slot);
|
||||
this->RebuildVisibleSettings();
|
||||
|
||||
this->CreateNestedTree();
|
||||
this->vscroll = this->GetScrollbar(WID_AIS_SCROLLBAR);
|
||||
@@ -314,7 +313,7 @@ struct AISettingsWindow : public Window {
|
||||
|
||||
this->SetWidgetDisabledState(WID_AIS_RESET, _game_mode != GM_MENU && Company::IsValidID(this->slot));
|
||||
|
||||
this->vscroll->SetCount((int)this->visible_settings.size());
|
||||
this->RebuildVisibleSettings();
|
||||
}
|
||||
|
||||
virtual void SetStringParameters(int widget) const
|
||||
@@ -342,6 +341,8 @@ struct AISettingsWindow : public Window {
|
||||
visible_settings.push_back(&(*it));
|
||||
}
|
||||
}
|
||||
|
||||
this->vscroll->SetCount((int)this->visible_settings.size());
|
||||
}
|
||||
|
||||
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
|
||||
@@ -531,21 +532,23 @@ struct AISettingsWindow : public Window {
|
||||
virtual void OnQueryTextFinished(char *str)
|
||||
{
|
||||
if (StrEmpty(str)) return;
|
||||
ScriptConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
|
||||
VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
||||
for (int i = 0; i < this->clicked_row; i++) it++;
|
||||
if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (it->flags & SCRIPTCONFIG_INGAME) == 0) return;
|
||||
const ScriptConfigItem config_item = **it;
|
||||
if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
|
||||
int32 value = atoi(str);
|
||||
this->ai_config->SetSetting((*it).name, value);
|
||||
this->ai_config->SetSetting(config_item.name, value);
|
||||
this->SetDirty();
|
||||
}
|
||||
|
||||
virtual void OnDropdownSelect(int widget, int index)
|
||||
{
|
||||
assert(this->clicked_dropdown);
|
||||
ScriptConfigItemList::const_iterator it = this->ai_config->GetConfigList()->begin();
|
||||
VisibleSettingsList::const_iterator it = this->visible_settings.begin();
|
||||
for (int i = 0; i < this->clicked_row; i++) it++;
|
||||
if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (it->flags & SCRIPTCONFIG_INGAME) == 0) return;
|
||||
this->ai_config->SetSetting((*it).name, index);
|
||||
const ScriptConfigItem config_item = **it;
|
||||
if (_game_mode == GM_NORMAL && ((this->slot == OWNER_DEITY) || Company::IsValidID(this->slot)) && (config_item.flags & SCRIPTCONFIG_INGAME) == 0) return;
|
||||
this->ai_config->SetSetting(config_item.name, index);
|
||||
this->SetDirty();
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ static bool CheckAPIVersion(const char *api_version)
|
||||
{
|
||||
return strcmp(api_version, "0.7") == 0 || strcmp(api_version, "1.0") == 0 || strcmp(api_version, "1.1") == 0 ||
|
||||
strcmp(api_version, "1.2") == 0 || strcmp(api_version, "1.3") == 0 || strcmp(api_version, "1.4") == 0 ||
|
||||
strcmp(api_version, "1.5") == 0 || strcmp(api_version, "1.6") == 0 || strcmp(api_version, "1.7") == 0;
|
||||
strcmp(api_version, "1.5") == 0 || strcmp(api_version, "1.6") == 0 || strcmp(api_version, "1.7") == 0 ||
|
||||
strcmp(api_version, "1.8") == 0 || strcmp(api_version, "1.9") == 0;
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
@@ -114,7 +114,7 @@ AIInfo *AIScannerInfo::FindInfo(const char *nameParam, int versionParam, bool fo
|
||||
*e = '\0';
|
||||
e++;
|
||||
versionParam = atoi(e);
|
||||
/* FALL THROUGH, like we were calling this function with a version. */
|
||||
/* Continue, like we were calling this function with a version. */
|
||||
}
|
||||
|
||||
if (force_exact_match) {
|
||||
|
||||
@@ -90,10 +90,10 @@ struct Aircraft FINAL : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
|
||||
virtual ~Aircraft() { this->PreDestructor(); }
|
||||
|
||||
void MarkDirty();
|
||||
void UpdateDeltaXY(Direction direction);
|
||||
void UpdateDeltaXY();
|
||||
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_AIRCRAFT_INC : EXPENSES_AIRCRAFT_RUN; }
|
||||
bool IsPrimaryVehicle() const { return this->IsNormalAircraft(); }
|
||||
SpriteID GetImage(Direction direction, EngineImageType image_type) const;
|
||||
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const;
|
||||
int GetDisplaySpeed() const { return this->cur_speed; }
|
||||
int GetDisplayMaxSpeed() const { return this->vcache.cached_max_speed; }
|
||||
int GetSpeedOldUnits() const { return this->vcache.cached_max_speed * 10 / 128; }
|
||||
@@ -137,11 +137,11 @@ struct Aircraft FINAL : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
|
||||
};
|
||||
|
||||
/**
|
||||
* Macro for iterating over all aircrafts.
|
||||
* Macro for iterating over all aircraft.
|
||||
*/
|
||||
#define FOR_ALL_AIRCRAFT(var) FOR_ALL_VEHICLES_OF_TYPE(Aircraft, var)
|
||||
|
||||
SpriteID GetRotorImage(const Aircraft *v, EngineImageType image_type);
|
||||
void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result);
|
||||
|
||||
Station *GetTargetAirportIfValid(const Aircraft *v);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
void Aircraft::UpdateDeltaXY(Direction direction)
|
||||
void Aircraft::UpdateDeltaXY()
|
||||
{
|
||||
this->x_offs = -1;
|
||||
this->y_offs = -1;
|
||||
@@ -152,64 +152,69 @@ static StationID FindNearestHangar(const Aircraft *v)
|
||||
return index;
|
||||
}
|
||||
|
||||
SpriteID Aircraft::GetImage(Direction direction, EngineImageType image_type) const
|
||||
void Aircraft::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
|
||||
{
|
||||
uint8 spritenum = this->spritenum;
|
||||
|
||||
if (is_custom_sprite(spritenum)) {
|
||||
SpriteID sprite = GetCustomVehicleSprite(this, direction, image_type);
|
||||
if (sprite != 0) return sprite;
|
||||
GetCustomVehicleSprite(this, direction, image_type, result);
|
||||
if (result->IsValid()) return;
|
||||
|
||||
spritenum = this->GetEngine()->original_image_index;
|
||||
}
|
||||
|
||||
assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
|
||||
return direction + _aircraft_sprite[spritenum];
|
||||
result->Set(direction + _aircraft_sprite[spritenum]);
|
||||
}
|
||||
|
||||
SpriteID GetRotorImage(const Aircraft *v, EngineImageType image_type)
|
||||
void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result)
|
||||
{
|
||||
assert(v->subtype == AIR_HELICOPTER);
|
||||
|
||||
const Aircraft *w = v->Next()->Next();
|
||||
if (is_custom_sprite(v->spritenum)) {
|
||||
SpriteID sprite = GetCustomRotorSprite(v, false, image_type);
|
||||
if (sprite != 0) return sprite;
|
||||
GetCustomRotorSprite(v, false, image_type, result);
|
||||
if (result->IsValid()) return;
|
||||
}
|
||||
|
||||
/* Return standard rotor sprites if there are no custom sprites for this helicopter */
|
||||
return SPR_ROTOR_STOPPED + w->state;
|
||||
result->Set(SPR_ROTOR_STOPPED + w->state);
|
||||
}
|
||||
|
||||
static SpriteID GetAircraftIcon(EngineID engine, EngineImageType image_type)
|
||||
static void GetAircraftIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
|
||||
{
|
||||
const Engine *e = Engine::Get(engine);
|
||||
uint8 spritenum = e->u.air.image_index;
|
||||
|
||||
if (is_custom_sprite(spritenum)) {
|
||||
SpriteID sprite = GetCustomVehicleIcon(engine, DIR_W, image_type);
|
||||
if (sprite != 0) return sprite;
|
||||
GetCustomVehicleIcon(engine, DIR_W, image_type, result);
|
||||
if (result->IsValid()) return;
|
||||
|
||||
spritenum = e->original_image_index;
|
||||
}
|
||||
|
||||
assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
|
||||
return DIR_W + _aircraft_sprite[spritenum];
|
||||
result->Set(DIR_W + _aircraft_sprite[spritenum]);
|
||||
}
|
||||
|
||||
void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
|
||||
{
|
||||
SpriteID sprite = GetAircraftIcon(engine, image_type);
|
||||
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
|
||||
VehicleSpriteSeq seq;
|
||||
GetAircraftIcon(engine, image_type, &seq);
|
||||
|
||||
Rect rect;
|
||||
seq.GetBounds(&rect);
|
||||
preferred_x = Clamp(preferred_x,
|
||||
left - UnScaleGUI(real_sprite->x_offs),
|
||||
right - UnScaleGUI(real_sprite->width) - UnScaleGUI(real_sprite->x_offs));
|
||||
DrawSprite(sprite, pal, preferred_x, y);
|
||||
left - UnScaleGUI(rect.left),
|
||||
right - UnScaleGUI(rect.right));
|
||||
|
||||
seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
|
||||
|
||||
if (!(AircraftVehInfo(engine)->subtype & AIR_CTOL)) {
|
||||
SpriteID rotor_sprite = GetCustomRotorIcon(engine, image_type);
|
||||
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
|
||||
DrawSprite(rotor_sprite, PAL_NONE, preferred_x, y - ScaleGUITrad(5));
|
||||
VehicleSpriteSeq rotor_seq;
|
||||
GetCustomRotorIcon(engine, image_type, &rotor_seq);
|
||||
if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
|
||||
rotor_seq.Draw(preferred_x, y - ScaleGUITrad(5), PAL_NONE, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,12 +229,16 @@ void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID en
|
||||
*/
|
||||
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
|
||||
{
|
||||
const Sprite *spr = GetSprite(GetAircraftIcon(engine, image_type), ST_NORMAL);
|
||||
VehicleSpriteSeq seq;
|
||||
GetAircraftIcon(engine, image_type, &seq);
|
||||
|
||||
width = UnScaleGUI(spr->width);
|
||||
height = UnScaleGUI(spr->height);
|
||||
xoffs = UnScaleGUI(spr->x_offs);
|
||||
yoffs = UnScaleGUI(spr->y_offs);
|
||||
Rect rect;
|
||||
seq.GetBounds(&rect);
|
||||
|
||||
width = UnScaleGUI(rect.right - rect.left + 1);
|
||||
height = UnScaleGUI(rect.bottom - rect.top + 1);
|
||||
xoffs = UnScaleGUI(rect.left);
|
||||
yoffs = UnScaleGUI(rect.top);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,10 +303,10 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
|
||||
u->engine_type = e->index;
|
||||
|
||||
v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER);
|
||||
v->UpdateDeltaXY(INVALID_DIR);
|
||||
v->UpdateDeltaXY();
|
||||
|
||||
u->subtype = AIR_SHADOW;
|
||||
u->UpdateDeltaXY(INVALID_DIR);
|
||||
u->UpdateDeltaXY();
|
||||
|
||||
v->reliability = e->reliability;
|
||||
v->reliability_spd_dec = e->reliability_spd_dec;
|
||||
@@ -317,7 +326,8 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
|
||||
v->date_of_last_service = _date;
|
||||
v->build_year = u->build_year = _cur_year;
|
||||
|
||||
v->cur_image = u->cur_image = SPR_IMG_QUERY;
|
||||
v->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
u->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
|
||||
v->random_bits = VehicleRandomBits();
|
||||
u->random_bits = VehicleRandomBits();
|
||||
@@ -349,11 +359,11 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
|
||||
w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE;
|
||||
w->spritenum = 0xFF;
|
||||
w->subtype = AIR_ROTOR;
|
||||
w->cur_image = SPR_ROTOR_STOPPED;
|
||||
w->sprite_seq.Set(SPR_ROTOR_STOPPED);
|
||||
w->random_bits = VehicleRandomBits();
|
||||
/* Use rotor's air.state to store the rotor animation frame */
|
||||
w->state = HRS_ROTOR_STOPPED;
|
||||
w->UpdateDeltaXY(INVALID_DIR);
|
||||
w->UpdateDeltaXY();
|
||||
|
||||
u->SetNext(w);
|
||||
w->UpdatePosition();
|
||||
@@ -468,21 +478,21 @@ static void HelicopterTickHandler(Aircraft *v)
|
||||
int tick = ++u->tick_counter;
|
||||
int spd = u->cur_speed >> 4;
|
||||
|
||||
SpriteID img;
|
||||
VehicleSpriteSeq seq;
|
||||
if (spd == 0) {
|
||||
u->state = HRS_ROTOR_STOPPED;
|
||||
img = GetRotorImage(v, EIT_ON_MAP);
|
||||
if (u->cur_image == img) return;
|
||||
GetRotorImage(v, EIT_ON_MAP, &seq);
|
||||
if (u->sprite_seq == seq) return;
|
||||
} else if (tick >= spd) {
|
||||
u->tick_counter = 0;
|
||||
u->state++;
|
||||
if (u->state > HRS_ROTOR_MOVING_3) u->state = HRS_ROTOR_MOVING_1;
|
||||
img = GetRotorImage(v, EIT_ON_MAP);
|
||||
GetRotorImage(v, EIT_ON_MAP, &seq);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
u->cur_image = img;
|
||||
u->sprite_seq = seq;
|
||||
|
||||
u->UpdatePositionAndViewport();
|
||||
}
|
||||
@@ -502,7 +512,9 @@ void SetAircraftPosition(Aircraft *v, int x, int y, int z)
|
||||
|
||||
v->UpdatePosition();
|
||||
v->UpdateViewport(true, false);
|
||||
if (v->subtype == AIR_HELICOPTER) v->Next()->Next()->cur_image = GetRotorImage(v, EIT_ON_MAP);
|
||||
if (v->subtype == AIR_HELICOPTER) {
|
||||
GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_seq);
|
||||
}
|
||||
|
||||
Aircraft *u = v->Next();
|
||||
|
||||
@@ -513,7 +525,7 @@ void SetAircraftPosition(Aircraft *v, int x, int y, int z)
|
||||
|
||||
safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
|
||||
u->z_pos = GetSlopePixelZ(safe_x, safe_y);
|
||||
u->cur_image = v->cur_image;
|
||||
u->sprite_seq.CopyWithoutPalette(v->sprite_seq); // the shadow is never coloured
|
||||
|
||||
u->UpdatePositionAndViewport();
|
||||
|
||||
@@ -737,7 +749,7 @@ int GetAircraftFlightLevel(T *v, bool takeoff)
|
||||
GetAircraftFlightLevelBounds(v, &aircraft_min_altitude, &aircraft_max_altitude);
|
||||
int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2;
|
||||
|
||||
/* If those assumptions would be violated, aircrafts would behave fairly strange. */
|
||||
/* If those assumptions would be violated, aircraft would behave fairly strange. */
|
||||
assert(aircraft_min_altitude < aircraft_middle_altitude);
|
||||
assert(aircraft_middle_altitude < aircraft_max_altitude);
|
||||
|
||||
@@ -1237,7 +1249,9 @@ void Aircraft::MarkDirty()
|
||||
{
|
||||
this->colourmap = PAL_NONE;
|
||||
this->UpdateViewport(true, false);
|
||||
if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this, EIT_ON_MAP);
|
||||
if (this->subtype == AIR_HELICOPTER) {
|
||||
GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_seq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1347,7 +1361,7 @@ static void AircraftEntersTerminal(Aircraft *v)
|
||||
*/
|
||||
static void AircraftLandAirplane(Aircraft *v)
|
||||
{
|
||||
v->UpdateDeltaXY(INVALID_DIR);
|
||||
v->UpdateDeltaXY();
|
||||
|
||||
if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) {
|
||||
SndPlayVehicleFx(SND_17_SKID_PLANE, v);
|
||||
@@ -1539,7 +1553,7 @@ static void AircraftEventHandler_TakeOff(Aircraft *v, const AirportFTAClass *apc
|
||||
static void AircraftEventHandler_StartTakeOff(Aircraft *v, const AirportFTAClass *apc)
|
||||
{
|
||||
v->state = ENDTAKEOFF;
|
||||
v->UpdateDeltaXY(INVALID_DIR);
|
||||
v->UpdateDeltaXY();
|
||||
}
|
||||
|
||||
static void AircraftEventHandler_EndTakeOff(Aircraft *v, const AirportFTAClass *apc)
|
||||
@@ -1552,7 +1566,7 @@ static void AircraftEventHandler_EndTakeOff(Aircraft *v, const AirportFTAClass *
|
||||
static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass *apc)
|
||||
{
|
||||
v->state = FLYING;
|
||||
v->UpdateDeltaXY(INVALID_DIR);
|
||||
v->UpdateDeltaXY();
|
||||
|
||||
/* get the next position to go to, differs per airport */
|
||||
AircraftNextAirportPos_and_Order(v);
|
||||
@@ -1618,7 +1632,7 @@ static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *apc
|
||||
static void AircraftEventHandler_HeliLanding(Aircraft *v, const AirportFTAClass *apc)
|
||||
{
|
||||
v->state = HELIENDLANDING;
|
||||
v->UpdateDeltaXY(INVALID_DIR);
|
||||
v->UpdateDeltaXY();
|
||||
}
|
||||
|
||||
static void AircraftEventHandler_EndLanding(Aircraft *v, const AirportFTAClass *apc)
|
||||
|
||||
@@ -83,11 +83,14 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s
|
||||
{
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
|
||||
SpriteID sprite = v->GetImage(rtl ? DIR_E : DIR_W, image_type);
|
||||
const Sprite *real_sprite = GetSprite(sprite, ST_NORMAL);
|
||||
VehicleSpriteSeq seq;
|
||||
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
|
||||
|
||||
int width = UnScaleGUI(real_sprite->width);
|
||||
int x_offs = UnScaleGUI(real_sprite->x_offs);
|
||||
Rect rect;
|
||||
seq.GetBounds(&rect);
|
||||
|
||||
int width = UnScaleGUI(rect.right - rect.left + 1);
|
||||
int x_offs = UnScaleGUI(rect.left);
|
||||
int x = rtl ? right - width - x_offs : left - x_offs;
|
||||
bool helicopter = v->subtype == AIR_HELICOPTER;
|
||||
|
||||
@@ -95,17 +98,18 @@ void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID s
|
||||
int heli_offs = 0;
|
||||
|
||||
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
|
||||
DrawSprite(sprite, pal, x, y + y_offs);
|
||||
seq.Draw(x, y + y_offs, pal, (v->vehstatus & VS_CRASHED) != 0);
|
||||
if (helicopter) {
|
||||
const Aircraft *a = Aircraft::From(v);
|
||||
SpriteID rotor_sprite = GetCustomRotorSprite(a, true, image_type);
|
||||
if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
|
||||
VehicleSpriteSeq rotor_seq;
|
||||
GetCustomRotorSprite(a, true, image_type, &rotor_seq);
|
||||
if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
|
||||
heli_offs = ScaleGUITrad(5);
|
||||
DrawSprite(rotor_sprite, PAL_NONE, x, y + y_offs - heli_offs);
|
||||
rotor_seq.Draw(x, y + y_offs - heli_offs, PAL_NONE, false);
|
||||
}
|
||||
if (v->index == selection) {
|
||||
x += x_offs;
|
||||
y += UnScaleGUI(real_sprite->y_offs) + y_offs - heli_offs;
|
||||
DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleGUI(real_sprite->height) + heli_offs + 1, COLOUR_WHITE, FR_BORDERONLY);
|
||||
y += UnScaleGUI(rect.top) + y_offs - heli_offs;
|
||||
DrawFrameRect(x - 1, y - 1, x + width + 1, y + UnScaleGUI(rect.bottom - rect.top + 1) + heli_offs + 1, COLOUR_WHITE, FR_BORDERONLY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
* @param delta_z Height of the airport above the land.
|
||||
*/
|
||||
#define AIRPORT_GENERIC(name, terminals, num_helipads, flags, delta_z) \
|
||||
static AirportFTAClass _airportfta_ ## name(_airport_moving_data_ ## name, terminals, \
|
||||
static const AirportFTAClass _airportfta_ ## name(_airport_moving_data_ ## name, terminals, \
|
||||
num_helipads, _airport_entries_ ## name, flags, _airport_fta_ ## name, delta_z);
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,17 +11,14 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "core/alloc_func.hpp"
|
||||
#include "core/smallvec_type.hpp"
|
||||
#include "tile_cmd.h"
|
||||
#include "viewport_func.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
/** The table/list with animated tiles. */
|
||||
TileIndex *_animated_tile_list = NULL;
|
||||
/** The number of animated tiles in the current state. */
|
||||
uint _animated_tile_count = 0;
|
||||
/** The number of slots for animated tiles allocated currently. */
|
||||
uint _animated_tile_allocated = 0;
|
||||
SmallVector<TileIndex, 256> _animated_tiles;
|
||||
|
||||
/**
|
||||
* Removes the given tile from the animated tile table.
|
||||
@@ -29,17 +26,11 @@ uint _animated_tile_allocated = 0;
|
||||
*/
|
||||
void DeleteAnimatedTile(TileIndex tile)
|
||||
{
|
||||
for (TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) {
|
||||
if (tile == *ti) {
|
||||
/* Remove the hole
|
||||
* The order of the remaining elements must stay the same, otherwise the animation loop
|
||||
* may miss a tile; that's why we must use memmove instead of just moving the last element.
|
||||
*/
|
||||
memmove(ti, ti + 1, (_animated_tile_list + _animated_tile_count - (ti + 1)) * sizeof(*ti));
|
||||
_animated_tile_count--;
|
||||
MarkTileDirtyByTile(tile);
|
||||
return;
|
||||
}
|
||||
TileIndex *to_remove = _animated_tiles.Find(tile);
|
||||
if (to_remove != _animated_tiles.End()) {
|
||||
/* The order of the remaining elements must stay the same, otherwise the animation loop may miss a tile. */
|
||||
_animated_tiles.ErasePreservingOrder(to_remove);
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,19 +42,7 @@ void DeleteAnimatedTile(TileIndex tile)
|
||||
void AddAnimatedTile(TileIndex tile)
|
||||
{
|
||||
MarkTileDirtyByTile(tile);
|
||||
|
||||
for (const TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) {
|
||||
if (tile == *ti) return;
|
||||
}
|
||||
|
||||
/* Table not large enough, so make it larger */
|
||||
if (_animated_tile_count == _animated_tile_allocated) {
|
||||
_animated_tile_allocated *= 2;
|
||||
_animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, _animated_tile_allocated);
|
||||
}
|
||||
|
||||
_animated_tile_list[_animated_tile_count] = tile;
|
||||
_animated_tile_count++;
|
||||
_animated_tiles.Include(tile);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,8 +50,8 @@ void AddAnimatedTile(TileIndex tile)
|
||||
*/
|
||||
void AnimateAnimatedTiles()
|
||||
{
|
||||
const TileIndex *ti = _animated_tile_list;
|
||||
while (ti < _animated_tile_list + _animated_tile_count) {
|
||||
const TileIndex *ti = _animated_tiles.Begin();
|
||||
while (ti < _animated_tiles.End()) {
|
||||
const TileIndex curr = *ti;
|
||||
AnimateTile(curr);
|
||||
/* During the AnimateTile call, DeleteAnimatedTile could have been called,
|
||||
@@ -93,7 +72,5 @@ void AnimateAnimatedTiles()
|
||||
*/
|
||||
void InitializeAnimatedTiles()
|
||||
{
|
||||
_animated_tile_list = ReallocT<TileIndex>(_animated_tile_list, 256);
|
||||
_animated_tile_count = 0;
|
||||
_animated_tile_allocated = 256;
|
||||
_animated_tiles.Clear();
|
||||
}
|
||||
|
||||
@@ -119,12 +119,12 @@ static inline uint16 GetVehicleDefaultCapacity(EngineID engine, CargoID *cargo_t
|
||||
* @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask
|
||||
* @return bit set of CargoIDs
|
||||
*/
|
||||
static inline uint32 GetAvailableVehicleCargoTypes(EngineID engine, bool include_initial_cargo_type)
|
||||
static inline CargoTypes GetAvailableVehicleCargoTypes(EngineID engine, bool include_initial_cargo_type)
|
||||
{
|
||||
const Engine *e = Engine::Get(engine);
|
||||
if (!e->CanCarryCargo()) return 0;
|
||||
|
||||
uint32 cargoes = e->info.refit_mask;
|
||||
CargoTypes cargoes = e->info.refit_mask;
|
||||
|
||||
if (include_initial_cargo_type) {
|
||||
SetBit(cargoes, e->GetDefaultCargoType());
|
||||
@@ -169,7 +169,7 @@ CargoArray GetCapacityOfArticulatedParts(EngineID engine)
|
||||
* @param[out] cargoes Total amount of units that can be transported, summed by cargo.
|
||||
* @param[out] refits Whether a (possibly partial) refit for each cargo is possible.
|
||||
*/
|
||||
void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, uint32 *refits)
|
||||
void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, CargoTypes *refits)
|
||||
{
|
||||
cargoes->Clear();
|
||||
*refits = 0;
|
||||
@@ -228,12 +228,12 @@ bool IsArticulatedVehicleRefittable(EngineID engine)
|
||||
* @param union_mask returns bit mask of CargoIDs which are a refit option for at least one articulated part
|
||||
* @param intersection_mask returns bit mask of CargoIDs which are a refit option for every articulated part (with default capacity > 0)
|
||||
*/
|
||||
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, uint32 *union_mask, uint32 *intersection_mask)
|
||||
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask)
|
||||
{
|
||||
const Engine *e = Engine::Get(engine);
|
||||
uint32 veh_cargoes = GetAvailableVehicleCargoTypes(engine, include_initial_cargo_type);
|
||||
CargoTypes veh_cargoes = GetAvailableVehicleCargoTypes(engine, include_initial_cargo_type);
|
||||
*union_mask = veh_cargoes;
|
||||
*intersection_mask = (veh_cargoes != 0) ? veh_cargoes : UINT32_MAX;
|
||||
*intersection_mask = (veh_cargoes != 0) ? veh_cargoes : ALL_CARGOTYPES;
|
||||
|
||||
if (!e->IsGroundVehicle()) return;
|
||||
if (!HasBit(e->info.callback_mask, CBM_VEHICLE_ARTIC_ENGINE)) return;
|
||||
@@ -254,9 +254,9 @@ void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type,
|
||||
* @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask
|
||||
* @return bit mask of CargoIDs which are a refit option for at least one articulated part
|
||||
*/
|
||||
uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
|
||||
CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
|
||||
{
|
||||
uint32 union_mask, intersection_mask;
|
||||
CargoTypes union_mask, intersection_mask;
|
||||
GetArticulatedRefitMasks(engine, include_initial_cargo_type, &union_mask, &intersection_mask);
|
||||
return union_mask;
|
||||
}
|
||||
@@ -267,9 +267,9 @@ uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_car
|
||||
* @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask
|
||||
* @return bit mask of CargoIDs which are a refit option for every articulated part (with default capacity > 0)
|
||||
*/
|
||||
uint32 GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
|
||||
CargoTypes GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
|
||||
{
|
||||
uint32 union_mask, intersection_mask;
|
||||
CargoTypes union_mask, intersection_mask;
|
||||
GetArticulatedRefitMasks(engine, include_initial_cargo_type, &union_mask, &intersection_mask);
|
||||
return intersection_mask;
|
||||
}
|
||||
@@ -314,16 +314,16 @@ void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
|
||||
{
|
||||
const Engine *engine = v->GetEngine();
|
||||
|
||||
uint32 purchase_refit_union, purchase_refit_intersection;
|
||||
CargoTypes purchase_refit_union, purchase_refit_intersection;
|
||||
GetArticulatedRefitMasks(v->engine_type, true, &purchase_refit_union, &purchase_refit_intersection);
|
||||
CargoArray purchase_default_capacity = GetCapacityOfArticulatedParts(v->engine_type);
|
||||
|
||||
uint32 real_refit_union = 0;
|
||||
uint32 real_refit_intersection = UINT_MAX;
|
||||
CargoTypes real_refit_union = 0;
|
||||
CargoTypes real_refit_intersection = ALL_CARGOTYPES;
|
||||
CargoArray real_default_capacity;
|
||||
|
||||
do {
|
||||
uint32 refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, true);
|
||||
CargoTypes refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, true);
|
||||
real_refit_union |= refit_mask;
|
||||
if (refit_mask != 0) real_refit_intersection &= refit_mask;
|
||||
|
||||
@@ -441,7 +441,7 @@ void AddArticulatedParts(Vehicle *first)
|
||||
v->max_age = 0;
|
||||
v->engine_type = engine_type;
|
||||
v->value = 0;
|
||||
v->cur_image = SPR_IMG_QUERY;
|
||||
v->sprite_seq.Set(SPR_IMG_QUERY);
|
||||
v->random_bits = VehicleRandomBits();
|
||||
|
||||
if (flip_image) v->spritenum++;
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
uint CountArticulatedParts(EngineID engine_type, bool purchase_window);
|
||||
CargoArray GetCapacityOfArticulatedParts(EngineID engine);
|
||||
void AddArticulatedParts(Vehicle *first);
|
||||
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, uint32 *union_mask, uint32 *intersection_mask);
|
||||
uint32 GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type);
|
||||
uint32 GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type);
|
||||
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask);
|
||||
CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type);
|
||||
CargoTypes GetIntersectionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type);
|
||||
bool IsArticulatedVehicleCarryingDifferentCargoes(const Vehicle *v, CargoID *cargo_type);
|
||||
bool IsArticulatedVehicleRefittable(EngineID engine);
|
||||
bool IsArticulatedEngine(EngineID engine_type);
|
||||
|
||||
@@ -37,8 +37,8 @@ extern void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index);
|
||||
*/
|
||||
static bool EnginesHaveCargoInCommon(EngineID engine_a, EngineID engine_b)
|
||||
{
|
||||
uint32 available_cargoes_a = GetUnionOfArticulatedRefitMasks(engine_a, true);
|
||||
uint32 available_cargoes_b = GetUnionOfArticulatedRefitMasks(engine_b, true);
|
||||
CargoTypes available_cargoes_a = GetUnionOfArticulatedRefitMasks(engine_a, true);
|
||||
CargoTypes available_cargoes_b = GetUnionOfArticulatedRefitMasks(engine_b, true);
|
||||
return (available_cargoes_a == 0 || available_cargoes_b == 0 || (available_cargoes_a & available_cargoes_b) != 0);
|
||||
}
|
||||
|
||||
@@ -173,9 +173,8 @@ static void TransferCargo(Vehicle *old_veh, Vehicle *new_head, bool part_of_chai
|
||||
*/
|
||||
static bool VerifyAutoreplaceRefitForOrders(const Vehicle *v, EngineID engine_type)
|
||||
{
|
||||
|
||||
uint32 union_refit_mask_a = GetUnionOfArticulatedRefitMasks(v->engine_type, false);
|
||||
uint32 union_refit_mask_b = GetUnionOfArticulatedRefitMasks(engine_type, false);
|
||||
CargoTypes union_refit_mask_a = GetUnionOfArticulatedRefitMasks(v->engine_type, false);
|
||||
CargoTypes union_refit_mask_b = GetUnionOfArticulatedRefitMasks(engine_type, false);
|
||||
|
||||
const Order *o;
|
||||
const Vehicle *u = (v->type == VEH_TRAIN) ? v->First() : v;
|
||||
@@ -201,7 +200,7 @@ static bool VerifyAutoreplaceRefitForOrders(const Vehicle *v, EngineID engine_ty
|
||||
*/
|
||||
static CargoID GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type, bool part_of_chain)
|
||||
{
|
||||
uint32 available_cargo_types, union_mask;
|
||||
CargoTypes available_cargo_types, union_mask;
|
||||
GetArticulatedRefitMasks(engine_type, true, &union_mask, &available_cargo_types);
|
||||
|
||||
if (union_mask == 0) return CT_NO_REFIT; // Don't try to refit an engine with no cargo capacity
|
||||
|
||||
@@ -87,7 +87,7 @@ class ReplaceVehicleWindow : public Window {
|
||||
byte sort_criteria; ///< Criteria of sorting vehicles.
|
||||
bool descending_sort_order; ///< Order of sorting vehicles.
|
||||
bool show_hidden_engines; ///< Whether to show the hidden engines.
|
||||
RailType sel_railtype; ///< Type of rail tracks selected.
|
||||
RailType sel_railtype; ///< Type of rail tracks selected. #INVALID_RAILTYPE to show all.
|
||||
Scrollbar *vscroll[2];
|
||||
|
||||
/**
|
||||
@@ -104,7 +104,7 @@ class ReplaceVehicleWindow : public Window {
|
||||
/* Ensure that the wagon/engine selection fits the engine. */
|
||||
if ((rvi->railveh_type == RAILVEH_WAGON) == show_engines) return false;
|
||||
|
||||
if (draw_left && show_engines) {
|
||||
if (draw_left && this->sel_railtype != INVALID_RAILTYPE) {
|
||||
/* Ensure that the railtype is specific to the selected one */
|
||||
if (rvi->railtype != this->sel_railtype) return false;
|
||||
}
|
||||
@@ -211,24 +211,7 @@ class ReplaceVehicleWindow : public Window {
|
||||
public:
|
||||
ReplaceVehicleWindow(WindowDesc *desc, VehicleType vehicletype, GroupID id_g) : Window(desc)
|
||||
{
|
||||
if (vehicletype == VEH_TRAIN) {
|
||||
/* For rail vehicles find the most used vehicle type, which is usually
|
||||
* better than 'just' the first/previous vehicle type. */
|
||||
uint type_count[RAILTYPE_END];
|
||||
memset(type_count, 0, sizeof(type_count));
|
||||
|
||||
const Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
|
||||
if (e->u.rail.railveh_type == RAILVEH_WAGON) continue;
|
||||
type_count[e->u.rail.railtype] += GetGroupNumEngines(_local_company, id_g, e->index);
|
||||
}
|
||||
|
||||
this->sel_railtype = RAILTYPE_BEGIN;
|
||||
for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
|
||||
if (type_count[this->sel_railtype] < type_count[rt]) this->sel_railtype = rt;
|
||||
}
|
||||
}
|
||||
|
||||
this->sel_railtype = INVALID_RAILTYPE;
|
||||
this->replace_engines = true; // start with locomotives (all other vehicles will not read this bool)
|
||||
this->engines[0].ForceRebuild();
|
||||
this->engines[1].ForceRebuild();
|
||||
@@ -288,12 +271,9 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_RV_TRAIN_ENGINEWAGON_TOGGLE: {
|
||||
StringID str = this->GetWidget<NWidgetCore>(widget)->widget_data;
|
||||
SetDParam(0, STR_REPLACE_ENGINES);
|
||||
Dimension d = GetStringBoundingBox(str);
|
||||
SetDParam(0, STR_REPLACE_WAGONS);
|
||||
d = maxdim(d, GetStringBoundingBox(str));
|
||||
case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN: {
|
||||
Dimension d = GetStringBoundingBox(STR_REPLACE_ENGINES);
|
||||
d = maxdim(d, GetStringBoundingBox(STR_REPLACE_WAGONS));
|
||||
d.width += padding.width;
|
||||
d.height += padding.height;
|
||||
*size = maxdim(*size, d);
|
||||
@@ -367,7 +347,7 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_RV_TRAIN_ENGINEWAGON_TOGGLE:
|
||||
case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN:
|
||||
SetDParam(0, this->replace_engines ? STR_REPLACE_ENGINES : STR_REPLACE_WAGONS);
|
||||
break;
|
||||
}
|
||||
@@ -432,12 +412,8 @@ public:
|
||||
this->SetWidgetDisabledState(WID_RV_STOP_REPLACE, this->sel_engine[0] == INVALID_ENGINE || !EngineHasReplacementForCompany(c, this->sel_engine[0], this->sel_group));
|
||||
|
||||
if (this->window_number == VEH_TRAIN) {
|
||||
/* sets the colour of that art thing */
|
||||
this->GetWidget<NWidgetCore>(WID_RV_TRAIN_FLUFF_LEFT)->colour = _company_colours[_local_company];
|
||||
this->GetWidget<NWidgetCore>(WID_RV_TRAIN_FLUFF_RIGHT)->colour = _company_colours[_local_company];
|
||||
|
||||
/* Show the selected railtype in the pulldown menu */
|
||||
this->GetWidget<NWidgetCore>(WID_RV_TRAIN_RAILTYPE_DROPDOWN)->widget_data = GetRailTypeInfo(sel_railtype)->strings.replace_text;
|
||||
this->GetWidget<NWidgetCore>(WID_RV_TRAIN_RAILTYPE_DROPDOWN)->widget_data = sel_railtype == INVALID_RAILTYPE ? STR_REPLACE_ALL_RAILTYPE : GetRailTypeInfo(sel_railtype)->strings.replace_text;
|
||||
}
|
||||
|
||||
this->DrawWidgets();
|
||||
@@ -483,15 +459,16 @@ public:
|
||||
DisplayVehicleSortDropDown(this, static_cast<VehicleType>(this->window_number), this->sort_criteria, WID_RV_SORT_DROPDOWN);
|
||||
break;
|
||||
|
||||
case WID_RV_TRAIN_ENGINEWAGON_TOGGLE:
|
||||
this->replace_engines = !(this->replace_engines);
|
||||
this->engines[0].ForceRebuild();
|
||||
this->reset_sel_engine = true;
|
||||
this->SetDirty();
|
||||
case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN: {
|
||||
DropDownList *list = new DropDownList();
|
||||
*list->Append() = new DropDownListStringItem(STR_REPLACE_ENGINES, 1, false);
|
||||
*list->Append() = new DropDownListStringItem(STR_REPLACE_WAGONS, 0, false);
|
||||
ShowDropDownList(this, list, this->replace_engines ? 1 : 0, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN);
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_RV_TRAIN_RAILTYPE_DROPDOWN: // Railtype selection dropdown menu
|
||||
ShowDropDownList(this, GetRailTypeDropDownList(true), sel_railtype, WID_RV_TRAIN_RAILTYPE_DROPDOWN);
|
||||
ShowDropDownList(this, GetRailTypeDropDownList(true, true), sel_railtype, WID_RV_TRAIN_RAILTYPE_DROPDOWN);
|
||||
break;
|
||||
|
||||
case WID_RV_TRAIN_WAGONREMOVE_TOGGLE: // toggle renew_keep_length
|
||||
@@ -566,6 +543,14 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN: {
|
||||
this->replace_engines = index != 0;
|
||||
this->engines[0].ForceRebuild();
|
||||
this->reset_sel_engine = true;
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_RV_START_REPLACE:
|
||||
this->ReplaceClick_StartReplace(index != 0);
|
||||
break;
|
||||
@@ -611,7 +596,13 @@ static const NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_RAILTYPE_DROPDOWN), SetMinimalSize(136, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE), SetFill(1, 0), SetResize(1, 0),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN), SetDataTip(STR_BLACK_STRING, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_SORT_ASCENDING_DESCENDING), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), SetFill(1, 1),
|
||||
@@ -631,20 +622,16 @@ static const NWidgetPart _nested_replace_rail_vehicle_widgets[] = {
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL, NC_EQUALSIZE),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_LEFT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_RIGHT_DETAILS), SetMinimalSize(240, 122), SetResize(1, 0), EndContainer(),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_REMOVE_WAGON, STR_REPLACE_REMOVE_WAGON_HELP), SetFill(1, 0), SetResize(1, 0),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_PUSHBUTTON_DROPDOWN, COLOUR_GREY, WID_RV_START_REPLACE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_VEHICLES_START, STR_REPLACE_HELP_START_BUTTON),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_INFO_TAB), SetMinimalSize(167, 12), SetDataTip(0x0, STR_REPLACE_HELP_REPLACE_INFO_TAB), SetResize(1, 0),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_STOP_REPLACE), SetMinimalSize(150, 12), SetDataTip(STR_REPLACE_VEHICLES_STOP, STR_REPLACE_HELP_STOP_BUTTON),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_ENGINEWAGON_TOGGLE), SetMinimalSize(139, 12), SetDataTip(STR_REPLACE_ENGINE_WAGON_SELECT, STR_REPLACE_ENGINE_WAGON_SELECT_HELP),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_TRAIN_FLUFF_LEFT), SetMinimalSize(15, 12), EndContainer(),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_RV_TRAIN_RAILTYPE_DROPDOWN), SetMinimalSize(136, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE), SetResize(1, 0),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_RV_TRAIN_FLUFF_RIGHT), SetMinimalSize(16, 12), EndContainer(),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_RV_TRAIN_WAGONREMOVE_TOGGLE), SetMinimalSize(138, 12), SetDataTip(STR_REPLACE_REMOVE_WAGON, STR_REPLACE_REMOVE_WAGON_HELP),
|
||||
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
};
|
||||
|
||||
@@ -26,6 +26,7 @@ struct ContentInfo;
|
||||
struct MD5File {
|
||||
/** The result of a checksum check */
|
||||
enum ChecksumResult {
|
||||
CR_UNKNOWN, ///< The file has not been checked yet
|
||||
CR_MATCH, ///< The file did exist and the md5 checksum did match
|
||||
CR_MISMATCH, ///< The file did exist, just the md5 checksum did not match
|
||||
CR_NO_FILE, ///< The file did not exist
|
||||
@@ -34,6 +35,7 @@ struct MD5File {
|
||||
const char *filename; ///< filename
|
||||
uint8 hash[16]; ///< md5 sum of the file
|
||||
const char *missing_warning; ///< warning when this file is missing
|
||||
ChecksumResult check_result; ///< cached result of md5 check
|
||||
|
||||
ChecksumResult CheckMD5(Subdirectory subdir, size_t max_size) const;
|
||||
};
|
||||
@@ -219,6 +221,11 @@ public:
|
||||
static bool HasSet(const ContentInfo *ci, bool md5sum);
|
||||
};
|
||||
|
||||
template <class Tbase_set> /* static */ const char *BaseMedia<Tbase_set>::ini_set;
|
||||
template <class Tbase_set> /* static */ const Tbase_set *BaseMedia<Tbase_set>::used_set;
|
||||
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::available_sets;
|
||||
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::duplicate_sets;
|
||||
|
||||
/**
|
||||
* Check whether there's a base set matching some information.
|
||||
* @param ci The content info to compare it to.
|
||||
@@ -280,11 +287,32 @@ static const uint NUM_SONGS_AVAILABLE = 1 + NUM_SONG_CLASSES * NUM_SONGS_CLASS;
|
||||
/** Maximum number of songs in the (custom) playlist */
|
||||
static const uint NUM_SONGS_PLAYLIST = 32;
|
||||
|
||||
/* Functions to read DOS music CAT files, similar to but not quite the same as sound effect CAT files */
|
||||
char *GetMusicCatEntryName(const char *filename, size_t entrynum);
|
||||
byte *GetMusicCatEntryData(const char *filename, size_t entrynum, size_t &entrylen);
|
||||
|
||||
enum MusicTrackType {
|
||||
MTT_STANDARDMIDI, ///< Standard MIDI file
|
||||
MTT_MPSMIDI, ///< MPS GM driver MIDI format (contained in a CAT file)
|
||||
};
|
||||
|
||||
/** Metadata about a music track. */
|
||||
struct MusicSongInfo {
|
||||
char songname[32]; ///< name of song displayed in UI
|
||||
byte tracknr; ///< track number of song displayed in UI
|
||||
const char *filename; ///< file on disk containing song (when used in MusicSet class, this pointer is owned by MD5File object for the file)
|
||||
MusicTrackType filetype; ///< decoder required for song file
|
||||
int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI
|
||||
bool loop; ///< song should play in a tight loop if possible, never ending
|
||||
int override_start; ///< MIDI ticks to skip over in beginning
|
||||
int override_end; ///< MIDI tick to end the song at (0 if no override)
|
||||
};
|
||||
|
||||
/** All data of a music set. */
|
||||
struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false> {
|
||||
/** The name of the different songs. */
|
||||
char song_name[NUM_SONGS_AVAILABLE][32];
|
||||
byte track_nr[NUM_SONGS_AVAILABLE];
|
||||
/** Data about individual songs in set. */
|
||||
MusicSongInfo songinfo[NUM_SONGS_AVAILABLE];
|
||||
/** Number of valid songs in set. */
|
||||
byte num_available;
|
||||
|
||||
bool FillSetDetails(struct IniFile *ini, const char *path, const char *full_filename);
|
||||
|
||||
@@ -17,11 +17,6 @@
|
||||
#include "ini_type.h"
|
||||
#include "string_func.h"
|
||||
|
||||
template <class Tbase_set> /* static */ const char *BaseMedia<Tbase_set>::ini_set;
|
||||
template <class Tbase_set> /* static */ const Tbase_set *BaseMedia<Tbase_set>::used_set;
|
||||
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::available_sets;
|
||||
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::duplicate_sets;
|
||||
|
||||
/**
|
||||
* Try to read a single piece of metadata and return false if it doesn't exist.
|
||||
* @param name the name of the item to fetch.
|
||||
@@ -45,8 +40,6 @@ template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::duplica
|
||||
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
|
||||
bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const char *path, const char *full_filename, bool allow_empty_filename)
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
||||
IniGroup *metadata = ini->GetGroup("metadata");
|
||||
IniItem *item;
|
||||
|
||||
@@ -134,7 +127,11 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
|
||||
file->missing_warning = stredup(item->value);
|
||||
}
|
||||
|
||||
switch (T::CheckMD5(file, BASESET_DIR)) {
|
||||
file->check_result = T::CheckMD5(file, BASESET_DIR);
|
||||
switch (file->check_result) {
|
||||
case MD5File::CR_UNKNOWN:
|
||||
break;
|
||||
|
||||
case MD5File::CR_MATCH:
|
||||
this->valid_files++;
|
||||
this->found_files++;
|
||||
|
||||
@@ -71,7 +71,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
|
||||
uint16 random_bits; ///< Random bits assigned to this station
|
||||
byte waiting_triggers; ///< Waiting triggers (NewGRF) for this station
|
||||
uint8 cached_anim_triggers; ///< NOSAVE: Combined animation trigger bitmask, used to determine if trigger processing should happen.
|
||||
uint32 cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask
|
||||
CargoTypes cached_cargo_triggers; ///< NOSAVE: Combined cargo trigger bitmask
|
||||
|
||||
TileArea train_station; ///< Tile area the train 'station' part covers
|
||||
StationRect rect; ///< NOSAVE: Station spread out rectangle maintained by StationRect::xxx() functions
|
||||
|
||||
@@ -22,7 +22,7 @@ static FBlitter_32bppAnim iFBlitter_32bppAnim;
|
||||
|
||||
Blitter_32bppAnim::~Blitter_32bppAnim()
|
||||
{
|
||||
free(this->anim_buf);
|
||||
free(this->anim_alloc);
|
||||
}
|
||||
|
||||
template <BlitterMode mode>
|
||||
@@ -39,13 +39,13 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
||||
}
|
||||
|
||||
Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
|
||||
uint16 *anim = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;
|
||||
uint16 *anim = this->anim_buf + this->ScreenToAnimOffset((uint32 *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left;
|
||||
|
||||
const byte *remap = bp->remap; // store so we don't have to access it via bp everytime
|
||||
|
||||
for (int y = 0; y < bp->height; y++) {
|
||||
Colour *dst_ln = dst + bp->pitch;
|
||||
uint16 *anim_ln = anim + this->anim_buf_width;
|
||||
uint16 *anim_ln = anim + this->anim_buf_pitch;
|
||||
|
||||
const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
|
||||
src_px++;
|
||||
@@ -279,9 +279,7 @@ void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height,
|
||||
}
|
||||
|
||||
Colour *udst = (Colour *)dst;
|
||||
uint16 *anim;
|
||||
|
||||
anim = this->anim_buf + ((uint32 *)dst - (uint32 *)_screen.dst_ptr);
|
||||
uint16 *anim = this->anim_buf + this->ScreenToAnimOffset((uint32 *)dst);
|
||||
|
||||
if (pal == PALETTE_TO_TRANSPARENT) {
|
||||
do {
|
||||
@@ -292,7 +290,7 @@ void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height,
|
||||
anim++;
|
||||
}
|
||||
udst = udst - width + _screen.pitch;
|
||||
anim = anim - width + this->anim_buf_width;
|
||||
anim = anim - width + this->anim_buf_pitch;
|
||||
} while (--height);
|
||||
return;
|
||||
}
|
||||
@@ -305,7 +303,7 @@ void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height,
|
||||
anim++;
|
||||
}
|
||||
udst = udst - width + _screen.pitch;
|
||||
anim = anim - width + this->anim_buf_width;
|
||||
anim = anim - width + this->anim_buf_pitch;
|
||||
} while (--height);
|
||||
return;
|
||||
}
|
||||
@@ -319,7 +317,8 @@ void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour)
|
||||
|
||||
/* Set the colour in the anim-buffer too, if we are rendering to the screen */
|
||||
if (_screen_disable_anim) return;
|
||||
this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = colour | (DEFAULT_BRIGHTNESS << 8);
|
||||
|
||||
this->anim_buf[this->ScreenToAnimOffset((uint32 *)video) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8);
|
||||
}
|
||||
|
||||
void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour)
|
||||
@@ -331,9 +330,7 @@ void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colou
|
||||
}
|
||||
|
||||
Colour colour32 = LookupColourInPalette(colour);
|
||||
uint16 *anim_line;
|
||||
|
||||
anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
|
||||
uint16 *anim_line = this->ScreenToAnimOffset((uint32 *)video) + this->anim_buf;
|
||||
|
||||
do {
|
||||
Colour *dst = (Colour *)video;
|
||||
@@ -347,7 +344,7 @@ void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colou
|
||||
anim++;
|
||||
}
|
||||
video = (uint32 *)video + _screen.pitch;
|
||||
anim_line += this->anim_buf_width;
|
||||
anim_line += this->anim_buf_pitch;
|
||||
} while (--height);
|
||||
}
|
||||
|
||||
@@ -357,20 +354,20 @@ void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width,
|
||||
assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
|
||||
Colour *dst = (Colour *)video;
|
||||
const uint32 *usrc = (const uint32 *)src;
|
||||
uint16 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
|
||||
uint16 *anim_line = this->ScreenToAnimOffset((uint32 *)video) + this->anim_buf;
|
||||
|
||||
for (; height > 0; height--) {
|
||||
/* We need to keep those for palette animation. */
|
||||
Colour *dst_pal = dst;
|
||||
uint16 *anim_pal = anim_line;
|
||||
|
||||
memcpy(dst, usrc, width * sizeof(uint32));
|
||||
memcpy(static_cast<void *>(dst), usrc, width * sizeof(uint32));
|
||||
usrc += width;
|
||||
dst += _screen.pitch;
|
||||
/* Copy back the anim-buffer */
|
||||
memcpy(anim_line, usrc, width * sizeof(uint16));
|
||||
usrc = (const uint32 *)((const uint16 *)usrc + width);
|
||||
anim_line += this->anim_buf_width;
|
||||
anim_line += this->anim_buf_pitch;
|
||||
|
||||
/* Okay, it is *very* likely that the image we stored is using
|
||||
* the wrong palette animated colours. There are two things we
|
||||
@@ -397,11 +394,10 @@ void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, in
|
||||
assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
|
||||
uint32 *udst = (uint32 *)dst;
|
||||
const uint32 *src = (const uint32 *)video;
|
||||
const uint16 *anim_line;
|
||||
|
||||
if (this->anim_buf == NULL) return;
|
||||
|
||||
anim_line = ((const uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
|
||||
const uint16 *anim_line = this->ScreenToAnimOffset((const uint32 *)video) + this->anim_buf;
|
||||
|
||||
for (; height > 0; height--) {
|
||||
memcpy(udst, src, width * sizeof(uint32));
|
||||
@@ -410,7 +406,7 @@ void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, in
|
||||
/* Copy the anim-buffer */
|
||||
memcpy(udst, anim_line, width * sizeof(uint16));
|
||||
udst = (uint32 *)((uint16 *)udst + width);
|
||||
anim_line += this->anim_buf_width;
|
||||
anim_line += this->anim_buf_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,8 +418,8 @@ void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt
|
||||
|
||||
/* We need to scroll the anim-buffer too */
|
||||
if (scroll_y > 0) {
|
||||
dst = this->anim_buf + left + (top + height - 1) * this->anim_buf_width;
|
||||
src = dst - scroll_y * this->anim_buf_width;
|
||||
dst = this->anim_buf + left + (top + height - 1) * this->anim_buf_pitch;
|
||||
src = dst - scroll_y * this->anim_buf_pitch;
|
||||
|
||||
/* Adjust left & width */
|
||||
if (scroll_x >= 0) {
|
||||
@@ -436,13 +432,13 @@ void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt
|
||||
uint th = height - scroll_y;
|
||||
for (; th > 0; th--) {
|
||||
memcpy(dst, src, tw * sizeof(uint16));
|
||||
src -= this->anim_buf_width;
|
||||
dst -= this->anim_buf_width;
|
||||
src -= this->anim_buf_pitch;
|
||||
dst -= this->anim_buf_pitch;
|
||||
}
|
||||
} else {
|
||||
/* Calculate pointers */
|
||||
dst = this->anim_buf + left + top * this->anim_buf_width;
|
||||
src = dst - scroll_y * this->anim_buf_width;
|
||||
dst = this->anim_buf + left + top * this->anim_buf_pitch;
|
||||
src = dst - scroll_y * this->anim_buf_pitch;
|
||||
|
||||
/* Adjust left & width */
|
||||
if (scroll_x >= 0) {
|
||||
@@ -457,8 +453,8 @@ void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt
|
||||
uint th = height + scroll_y;
|
||||
for (; th > 0; th--) {
|
||||
memmove(dst, src, tw * sizeof(uint16));
|
||||
src += this->anim_buf_width;
|
||||
dst += this->anim_buf_width;
|
||||
src += this->anim_buf_pitch;
|
||||
dst += this->anim_buf_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,17 +480,22 @@ void Blitter_32bppAnim::PaletteAnimate(const Palette &palette)
|
||||
Colour *dst = (Colour *)_screen.dst_ptr;
|
||||
|
||||
/* Let's walk the anim buffer and try to find the pixels */
|
||||
const int width = this->anim_buf_width;
|
||||
const int pitch_offset = _screen.pitch - width;
|
||||
const int anim_pitch_offset = this->anim_buf_pitch - width;
|
||||
for (int y = this->anim_buf_height; y != 0 ; y--) {
|
||||
for (int x = this->anim_buf_width; x != 0 ; x--) {
|
||||
uint colour = GB(*anim, 0, 8);
|
||||
for (int x = width; x != 0 ; x--) {
|
||||
uint16 value = *anim;
|
||||
uint8 colour = GB(value, 0, 8);
|
||||
if (colour >= PALETTE_ANIM_START) {
|
||||
/* Update this pixel */
|
||||
*dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim, 8, 8));
|
||||
*dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(value, 8, 8));
|
||||
}
|
||||
dst++;
|
||||
anim++;
|
||||
}
|
||||
dst += _screen.pitch - this->anim_buf_width;
|
||||
dst += pitch_offset;
|
||||
anim += anim_pitch_offset;
|
||||
}
|
||||
|
||||
/* Make sure the backend redraws the whole screen */
|
||||
@@ -508,11 +509,16 @@ Blitter::PaletteAnimation Blitter_32bppAnim::UsePaletteAnimation()
|
||||
|
||||
void Blitter_32bppAnim::PostResize()
|
||||
{
|
||||
if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
|
||||
if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height ||
|
||||
_screen.pitch != this->anim_buf_pitch) {
|
||||
/* The size of the screen changed; we can assume we can wipe all data from our buffer */
|
||||
free(this->anim_buf);
|
||||
this->anim_buf = CallocT<uint16>(_screen.width * _screen.height);
|
||||
free(this->anim_alloc);
|
||||
this->anim_buf_width = _screen.width;
|
||||
this->anim_buf_height = _screen.height;
|
||||
this->anim_buf_pitch = (_screen.width + 7) & ~7;
|
||||
this->anim_alloc = CallocT<uint16>(this->anim_buf_pitch * this->anim_buf_height + 8);
|
||||
|
||||
/* align buffer to next 16 byte boundary */
|
||||
this->anim_buf = reinterpret_cast<uint16 *>((reinterpret_cast<uintptr_t>(this->anim_alloc) + 0xF) & (~0xF));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,16 +18,22 @@
|
||||
class Blitter_32bppAnim : public Blitter_32bppOptimized {
|
||||
protected:
|
||||
uint16 *anim_buf; ///< In this buffer we keep track of the 8bpp indexes so we can do palette animation
|
||||
void *anim_alloc; ///< The raw allocated buffer, not necessarily aligned correctly
|
||||
int anim_buf_width; ///< The width of the animation buffer.
|
||||
int anim_buf_height; ///< The height of the animation buffer.
|
||||
int anim_buf_pitch; ///< The pitch of the animation buffer (width rounded up to 16 byte boundary).
|
||||
Palette palette; ///< The current palette.
|
||||
|
||||
public:
|
||||
Blitter_32bppAnim() :
|
||||
anim_buf(NULL),
|
||||
anim_alloc(NULL),
|
||||
anim_buf_width(0),
|
||||
anim_buf_height(0)
|
||||
{}
|
||||
anim_buf_height(0),
|
||||
anim_buf_pitch(0)
|
||||
{
|
||||
this->palette = _cur_palette;
|
||||
}
|
||||
|
||||
~Blitter_32bppAnim();
|
||||
|
||||
@@ -54,6 +60,15 @@ public:
|
||||
return this->palette.palette[index];
|
||||
}
|
||||
|
||||
inline int ScreenToAnimOffset(const uint32 *video)
|
||||
{
|
||||
int raw_offset = video - (const uint32 *)_screen.dst_ptr;
|
||||
if (_screen.pitch == this->anim_buf_pitch) return raw_offset;
|
||||
int lines = raw_offset / _screen.pitch;
|
||||
int across = raw_offset % _screen.pitch;
|
||||
return across + (lines * this->anim_buf_pitch);
|
||||
}
|
||||
|
||||
template <BlitterMode mode> void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
||||
};
|
||||
|
||||
|
||||
100
src/blitter/32bpp_anim_sse2.cpp
Normal file
100
src/blitter/32bpp_anim_sse2.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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 32bpp_anim.cpp Implementation of a partially SSSE2 32bpp blitter with animation support. */
|
||||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#include "../stdafx.h"
|
||||
#include "../video/video_driver.hpp"
|
||||
#include "32bpp_anim_sse2.hpp"
|
||||
#include "32bpp_sse_func.hpp"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
/** Instantiation of the partially SSSE2 32bpp with animation blitter factory. */
|
||||
static FBlitter_32bppSSE2_Anim iFBlitter_32bppSSE2_Anim;
|
||||
|
||||
void Blitter_32bppSSE2_Anim::PaletteAnimate(const Palette &palette)
|
||||
{
|
||||
assert(!_screen_disable_anim);
|
||||
|
||||
this->palette = palette;
|
||||
/* If first_dirty is 0, it is for 8bpp indication to send the new
|
||||
* palette. However, only the animation colours might possibly change.
|
||||
* Especially when going between toyland and non-toyland. */
|
||||
assert(this->palette.first_dirty == PALETTE_ANIM_START || this->palette.first_dirty == 0);
|
||||
|
||||
const uint16 *anim = this->anim_buf;
|
||||
Colour *dst = (Colour *)_screen.dst_ptr;
|
||||
|
||||
bool screen_dirty = false;
|
||||
|
||||
/* Let's walk the anim buffer and try to find the pixels */
|
||||
const int width = this->anim_buf_width;
|
||||
const int screen_pitch = _screen.pitch;
|
||||
const int anim_pitch = this->anim_buf_pitch;
|
||||
__m128i anim_cmp = _mm_set1_epi16(PALETTE_ANIM_START - 1);
|
||||
__m128i brightness_cmp = _mm_set1_epi16(Blitter_32bppBase::DEFAULT_BRIGHTNESS);
|
||||
__m128i colour_mask = _mm_set1_epi16(0xFF);
|
||||
for (int y = this->anim_buf_height; y != 0 ; y--) {
|
||||
Colour *next_dst_ln = dst + screen_pitch;
|
||||
const uint16 *next_anim_ln = anim + anim_pitch;
|
||||
int x = width;
|
||||
while (x > 0) {
|
||||
__m128i data = _mm_load_si128((const __m128i *) anim);
|
||||
|
||||
/* low bytes only, shifted into high positions */
|
||||
__m128i colour_data = _mm_and_si128(data, colour_mask);
|
||||
|
||||
/* test if any colour >= PALETTE_ANIM_START */
|
||||
int colour_cmp_result = _mm_movemask_epi8(_mm_cmpgt_epi16(colour_data, anim_cmp));
|
||||
if (colour_cmp_result) {
|
||||
/* test if any brightness is unexpected */
|
||||
if (x < 8 || colour_cmp_result != 0xFFFF ||
|
||||
_mm_movemask_epi8(_mm_cmpeq_epi16(_mm_srli_epi16(data, 8), brightness_cmp)) != 0xFFFF) {
|
||||
/* slow path: < 8 pixels left or unexpected brightnesses */
|
||||
for (int z = min<int>(x, 8); z != 0 ; z--) {
|
||||
int value = _mm_extract_epi16(data, 0);
|
||||
uint8 colour = GB(value, 0, 8);
|
||||
if (colour >= PALETTE_ANIM_START) {
|
||||
/* Update this pixel */
|
||||
*dst = AdjustBrightneSSE(LookupColourInPalette(colour), GB(value, 8, 8));
|
||||
screen_dirty = true;
|
||||
}
|
||||
data = _mm_srli_si128(data, 2);
|
||||
dst++;
|
||||
}
|
||||
} else {
|
||||
/* medium path: 8 pixels to animate all of expected brightnesses */
|
||||
for (int z = 0; z < 8; z++) {
|
||||
*dst = LookupColourInPalette(_mm_extract_epi16(colour_data, 0));
|
||||
colour_data = _mm_srli_si128(colour_data, 2);
|
||||
dst++;
|
||||
}
|
||||
screen_dirty = true;
|
||||
}
|
||||
} else {
|
||||
/* fast path, no animation */
|
||||
dst += 8;
|
||||
}
|
||||
anim += 8;
|
||||
x -= 8;
|
||||
}
|
||||
dst = next_dst_ln;
|
||||
anim = next_anim_ln;
|
||||
}
|
||||
|
||||
if (screen_dirty) {
|
||||
/* Make sure the backend redraws the whole screen */
|
||||
VideoDriver::GetInstance()->MakeDirty(0, 0, _screen.width, _screen.height);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
43
src/blitter/32bpp_anim_sse2.hpp
Normal file
43
src/blitter/32bpp_anim_sse2.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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 32bpp_anim.hpp A partially SSE2 32 bpp blitter with animation support. */
|
||||
|
||||
#ifndef BLITTER_32BPP_SSE2_ANIM_HPP
|
||||
#define BLITTER_32BPP_SSE2_ANIM_HPP
|
||||
|
||||
#ifdef WITH_SSE
|
||||
|
||||
#ifndef SSE_VERSION
|
||||
#define SSE_VERSION 2
|
||||
#endif
|
||||
|
||||
#ifndef FULL_ANIMATION
|
||||
#define FULL_ANIMATION 1
|
||||
#endif
|
||||
|
||||
#include "32bpp_anim.hpp"
|
||||
#include "32bpp_sse2.hpp"
|
||||
|
||||
/** A partially 32 bpp blitter with palette animation. */
|
||||
class Blitter_32bppSSE2_Anim : public Blitter_32bppAnim {
|
||||
public:
|
||||
/* virtual */ void PaletteAnimate(const Palette &palette);
|
||||
/* virtual */ const char *GetName() { return "32bpp-sse2-anim"; }
|
||||
};
|
||||
|
||||
/** Factory for the partially 32bpp blitter with animation. */
|
||||
class FBlitter_32bppSSE2_Anim : public BlitterFactory {
|
||||
public:
|
||||
FBlitter_32bppSSE2_Anim() : BlitterFactory("32bpp-sse2-anim", "32bpp partially SSE2 Animation Blitter (palette animation)", HasCPUIDFlag(1, 3, 26)) {}
|
||||
/* virtual */ Blitter *CreateInstance() { return new Blitter_32bppSSE2_Anim(); }
|
||||
};
|
||||
|
||||
#endif /* WITH_SSE */
|
||||
#endif /* BLITTER_32BPP_ANIM_HPP */
|
||||
@@ -35,7 +35,7 @@ inline void Blitter_32bppSSE4_Anim::Draw(const Blitter::BlitterParams *bp, ZoomL
|
||||
{
|
||||
const byte * const remap = bp->remap;
|
||||
Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left;
|
||||
uint16 *anim_line = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;
|
||||
uint16 *anim_line = this->anim_buf + this->ScreenToAnimOffset((uint32 *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left;
|
||||
int effective_width = bp->width;
|
||||
|
||||
/* Find where to start reading in the source sprite. */
|
||||
@@ -353,7 +353,7 @@ next_line:
|
||||
if (mode != BM_TRANSPARENT) src_mv_line += si->sprite_width;
|
||||
src_rgba_line = (const Colour*) ((const byte*) src_rgba_line + si->sprite_line_size);
|
||||
dst_line += bp->pitch;
|
||||
anim_line += this->anim_buf_width;
|
||||
anim_line += this->anim_buf_pitch;
|
||||
}
|
||||
}
|
||||
IGNORE_UNINITIALIZED_WARNING_STOP
|
||||
|
||||
@@ -23,13 +23,14 @@
|
||||
#endif
|
||||
|
||||
#include "32bpp_anim.hpp"
|
||||
#include "32bpp_anim_sse2.hpp"
|
||||
#include "32bpp_sse4.hpp"
|
||||
|
||||
#undef MARGIN_NORMAL_THRESHOLD
|
||||
#define MARGIN_NORMAL_THRESHOLD 4
|
||||
|
||||
/** The SSE4 32 bpp blitter with palette animation. */
|
||||
class Blitter_32bppSSE4_Anim FINAL : public Blitter_32bppAnim, public Blitter_32bppSSE_Base {
|
||||
class Blitter_32bppSSE4_Anim FINAL : public Blitter_32bppSSE2_Anim, public Blitter_32bppSSE_Base {
|
||||
private:
|
||||
|
||||
public:
|
||||
|
||||
@@ -143,6 +143,36 @@ void Blitter_32bppBase::PaletteAnimate(const Palette &palette)
|
||||
/* By default, 32bpp doesn't have palette animation */
|
||||
}
|
||||
|
||||
Colour Blitter_32bppBase::ReallyAdjustBrightness(Colour colour, uint8 brightness)
|
||||
{
|
||||
assert(DEFAULT_BRIGHTNESS == 1 << 7);
|
||||
|
||||
uint64 combined = (((uint64) colour.r) << 32) | (((uint64) colour.g) << 16) | ((uint64) colour.b);
|
||||
combined *= brightness;
|
||||
|
||||
uint16 r = GB(combined, 39, 9);
|
||||
uint16 g = GB(combined, 23, 9);
|
||||
uint16 b = GB(combined, 7, 9);
|
||||
|
||||
if ((combined & 0x800080008000L) == 0L) {
|
||||
return Colour(r, g, b, colour.a);
|
||||
}
|
||||
|
||||
uint16 ob = 0;
|
||||
/* Sum overbright */
|
||||
if (r > 255) ob += r - 255;
|
||||
if (g > 255) ob += g - 255;
|
||||
if (b > 255) ob += b - 255;
|
||||
|
||||
/* Reduce overbright strength */
|
||||
ob /= 2;
|
||||
return Colour(
|
||||
r >= 255 ? 255 : min(r + ob * (255 - r) / 256, 255),
|
||||
g >= 255 ? 255 : min(g + ob * (255 - g) / 256, 255),
|
||||
b >= 255 ? 255 : min(b + ob * (255 - b) / 256, 255),
|
||||
colour.a);
|
||||
}
|
||||
|
||||
Blitter::PaletteAnimation Blitter_32bppBase::UsePaletteAnimation()
|
||||
{
|
||||
return Blitter::PALETTE_ANIMATION_NONE;
|
||||
|
||||
@@ -146,30 +146,14 @@ public:
|
||||
|
||||
static const int DEFAULT_BRIGHTNESS = 128;
|
||||
|
||||
static Colour ReallyAdjustBrightness(Colour colour, uint8 brightness);
|
||||
|
||||
static inline Colour AdjustBrightness(Colour colour, uint8 brightness)
|
||||
{
|
||||
/* Shortcut for normal brightness */
|
||||
if (brightness == DEFAULT_BRIGHTNESS) return colour;
|
||||
|
||||
uint16 ob = 0;
|
||||
uint16 r = colour.r * brightness / DEFAULT_BRIGHTNESS;
|
||||
uint16 g = colour.g * brightness / DEFAULT_BRIGHTNESS;
|
||||
uint16 b = colour.b * brightness / DEFAULT_BRIGHTNESS;
|
||||
|
||||
/* Sum overbright */
|
||||
if (r > 255) ob += r - 255;
|
||||
if (g > 255) ob += g - 255;
|
||||
if (b > 255) ob += b - 255;
|
||||
|
||||
if (ob == 0) return Colour(r, g, b, colour.a);
|
||||
|
||||
/* Reduce overbright strength */
|
||||
ob /= 2;
|
||||
return Colour(
|
||||
r >= 255 ? 255 : min(r + ob * (255 - r) / 256, 255),
|
||||
g >= 255 ? 255 : min(g + ob * (255 - g) / 256, 255),
|
||||
b >= 255 ? 255 : min(b + ob * (255 - b) / 256, 255),
|
||||
colour.a);
|
||||
return ReallyAdjustBrightness(colour, brightness);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#define MARGIN_NORMAL_THRESHOLD (zoom == ZOOM_LVL_OUT_32X ? 8 : 4) ///< Minimum width to use margins with BM_NORMAL.
|
||||
#define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BM_COLOUR_REMAP.
|
||||
|
||||
#undef ALIGN
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define ALIGN(n) __declspec(align(n))
|
||||
#else
|
||||
|
||||
@@ -48,7 +48,7 @@ void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoom
|
||||
break;
|
||||
|
||||
case BM_BLACK_REMAP:
|
||||
colour = 0;
|
||||
if (*src != 0) *dst = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -264,6 +264,6 @@ bool HandleBootstrap()
|
||||
|
||||
/* Failure to get enough working to get a graphics set. */
|
||||
failure:
|
||||
usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD. See section 4.1 of readme.txt.");
|
||||
usererror("Failed to find a graphics set. Please acquire a graphics set for OpenTTD. See section 4.1 of README.md.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -524,7 +524,7 @@ const StringID _engine_sort_listing[][12] = {{
|
||||
static bool CDECL CargoFilter(const EngineID *eid, const CargoID cid)
|
||||
{
|
||||
if (cid == CF_ANY) return true;
|
||||
uint32 refit_mask = GetUnionOfArticulatedRefitMasks(*eid, true) & _standard_cargo_mask;
|
||||
CargoTypes refit_mask = GetUnionOfArticulatedRefitMasks(*eid, true) & _standard_cargo_mask;
|
||||
return (cid == CF_NONE ? refit_mask == 0 : HasBit(refit_mask, cid));
|
||||
}
|
||||
|
||||
@@ -535,7 +535,7 @@ static GUIEngineList::FilterFunction * const _filter_funcs[] = {
|
||||
static int DrawCargoCapacityInfo(int left, int right, int y, EngineID engine)
|
||||
{
|
||||
CargoArray cap;
|
||||
uint32 refits;
|
||||
CargoTypes refits;
|
||||
GetArticulatedVehicleCargoesAndRefits(engine, &cap, &refits);
|
||||
|
||||
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
||||
@@ -719,7 +719,15 @@ static int DrawShipPurchaseInfo(int left, int right, int y, EngineID engine_numb
|
||||
return y;
|
||||
}
|
||||
|
||||
/* Draw aircraft specific details */
|
||||
/**
|
||||
* Draw aircraft specific details in the buy window.
|
||||
* @param left Left edge of the window to draw in.
|
||||
* @param right Right edge of the window to draw in.
|
||||
* @param y Top of the area to draw in.
|
||||
* @param engine_number Engine to display.
|
||||
* @param refittable If set, the aircraft can be refitted.
|
||||
* @return Bottom of the used area.
|
||||
*/
|
||||
static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_number, bool refittable)
|
||||
{
|
||||
const Engine *e = Engine::Get(engine_number);
|
||||
@@ -755,6 +763,12 @@ static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_
|
||||
DrawString(left, right, y, STR_PURCHASE_INFO_RUNNINGCOST);
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
|
||||
/* Aircraft type */
|
||||
SetDParam(0, e->GetAircraftTypeText());
|
||||
DrawString(left, right, y, STR_PURCHASE_INFO_AIRCRAFT_TYPE);
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
|
||||
/* Aircraft range, if available. */
|
||||
uint16 range = e->GetRange();
|
||||
if (range != 0) {
|
||||
SetDParam(0, range);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
typedef byte CargoID;
|
||||
|
||||
/** Available types of cargo */
|
||||
enum CargoTypes {
|
||||
enum CargoType {
|
||||
/* Temperate */
|
||||
CT_PASSENGERS = 0,
|
||||
CT_COAL = 1,
|
||||
@@ -63,13 +63,17 @@ enum CargoTypes {
|
||||
CT_PLASTIC = 10,
|
||||
CT_FIZZY_DRINKS = 11,
|
||||
|
||||
NUM_CARGO = 32, ///< Maximal number of cargo types in a game.
|
||||
NUM_CARGO = 64, ///< Maximal number of cargo types in a game.
|
||||
|
||||
CT_AUTO_REFIT = 0xFD, ///< Automatically choose cargo type when doing auto refitting.
|
||||
CT_NO_REFIT = 0xFE, ///< Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-new).
|
||||
CT_INVALID = 0xFF, ///< Invalid cargo type.
|
||||
};
|
||||
|
||||
typedef uint64 CargoTypes;
|
||||
|
||||
static const CargoTypes ALL_CARGOTYPES = (CargoTypes)UINT32_MAX;
|
||||
|
||||
/** Class for storing amounts of cargo */
|
||||
struct CargoArray {
|
||||
private:
|
||||
|
||||
@@ -28,12 +28,12 @@ CargoSpec CargoSpec::array[NUM_CARGO];
|
||||
* Bitmask of cargo types available. This includes phony cargoes like regearing cargoes.
|
||||
* Initialized during a call to #SetupCargoForClimate.
|
||||
*/
|
||||
uint32 _cargo_mask;
|
||||
CargoTypes _cargo_mask;
|
||||
|
||||
/**
|
||||
* Bitmask of real cargo types available. Phony cargoes like regearing cargoes are excluded.
|
||||
*/
|
||||
uint32 _standard_cargo_mask;
|
||||
CargoTypes _standard_cargo_mask;
|
||||
|
||||
/**
|
||||
* Set up the default cargo types for the given landscape type.
|
||||
|
||||
@@ -129,8 +129,8 @@ private:
|
||||
friend void SetupCargoForClimate(LandscapeID l);
|
||||
};
|
||||
|
||||
extern uint32 _cargo_mask;
|
||||
extern uint32 _standard_cargo_mask;
|
||||
extern CargoTypes _cargo_mask;
|
||||
extern CargoTypes _standard_cargo_mask;
|
||||
|
||||
void SetupCargoForClimate(LandscapeID l);
|
||||
CargoID GetCargoIDByLabel(CargoLabel cl);
|
||||
@@ -156,7 +156,7 @@ static inline bool IsCargoInClass(CargoID c, CargoClass cc)
|
||||
if ((var = CargoSpec::Get(cargospec_index))->IsValid())
|
||||
#define FOR_ALL_CARGOSPECS(var) FOR_ALL_CARGOSPECS_FROM(var, 0)
|
||||
|
||||
#define FOR_EACH_SET_CARGO_ID(var, cargo_bits) FOR_EACH_SET_BIT_EX(CargoID, var, uint, cargo_bits)
|
||||
#define FOR_EACH_SET_CARGO_ID(var, cargo_bits) FOR_EACH_SET_BIT_EX(CargoID, var, CargoTypes, cargo_bits)
|
||||
|
||||
/**
|
||||
* Loop header for iterating over cargoes, sorted by name. This includes phony cargoes like regearing cargoes.
|
||||
|
||||
@@ -56,7 +56,7 @@ void DrawHillyLandTile(const TileInfo *ti)
|
||||
if (ti->tileh != SLOPE_FLAT) {
|
||||
DrawGroundSprite(SPR_FLAT_ROUGH_LAND + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
|
||||
} else {
|
||||
DrawGroundSprite(_landscape_clear_sprites_rough[GB(ti->x ^ ti->y, 4, 3)], PAL_NONE);
|
||||
DrawGroundSprite(_landscape_clear_sprites_rough[GB(TileHash(ti->x, ti->y), 0, 3)], PAL_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -167,6 +167,7 @@ CommandProc CmdSetStoryPageDate;
|
||||
CommandProc CmdShowStoryPage;
|
||||
CommandProc CmdRemoveStoryPage;
|
||||
CommandProc CmdRemoveStoryPageElement;
|
||||
CommandProc CmdScrollViewport;
|
||||
|
||||
CommandProc CmdLevelLand;
|
||||
|
||||
@@ -322,6 +323,7 @@ static const Command _command_proc_table[] = {
|
||||
DEF_CMD(CmdShowStoryPage, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_SHOW_STORY_PAGE
|
||||
DEF_CMD(CmdRemoveStoryPage, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_REMOVE_STORY_PAGE
|
||||
DEF_CMD(CmdRemoveStoryPageElement, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_REMOVE_STORY_ELEMENT_PAGE
|
||||
DEF_CMD(CmdScrollViewport, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_SCROLL_VIEWPORT
|
||||
|
||||
DEF_CMD(CmdLevelLand, CMD_ALL_TILES | CMD_NO_TEST | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_LEVEL_LAND; test run might clear tiles multiple times, in execution that only happens once
|
||||
|
||||
|
||||
@@ -293,6 +293,8 @@ enum Commands {
|
||||
CMD_SHOW_STORY_PAGE, ///< show a story page
|
||||
CMD_REMOVE_STORY_PAGE, ///< remove a story page
|
||||
CMD_REMOVE_STORY_PAGE_ELEMENT, ///< remove a story page element
|
||||
CMD_SCROLL_VIEWPORT, ///< scroll main viewport of players
|
||||
|
||||
CMD_LEVEL_LAND, ///< level land
|
||||
|
||||
CMD_BUILD_LOCK, ///< build a lock
|
||||
|
||||
@@ -52,10 +52,10 @@ extern CompanyPool _company_pool;
|
||||
/** Statically loadable part of Company pool item */
|
||||
struct CompanyProperties {
|
||||
uint32 name_2; ///< Parameter of #name_1.
|
||||
uint16 name_1; ///< Name of the company if the user did not change it.
|
||||
StringID name_1; ///< Name of the company if the user did not change it.
|
||||
char *name; ///< Name of the company if the user changed it.
|
||||
|
||||
uint16 president_name_1; ///< Name of the president if the user did not change it.
|
||||
StringID president_name_1; ///< Name of the president if the user did not change it.
|
||||
uint32 president_name_2; ///< Parameter of #president_name_1
|
||||
char *president_name; ///< Name of the president if the user changed it.
|
||||
|
||||
@@ -67,8 +67,6 @@ struct CompanyProperties {
|
||||
|
||||
byte colour; ///< Company colour.
|
||||
|
||||
RailTypes avail_railtypes; ///< Rail types available to the company.
|
||||
|
||||
byte block_preview; ///< Number of quarters that the company is not allowed to get new exclusive engine previews (see CompaniesGenStatistics).
|
||||
|
||||
TileIndex location_of_HQ; ///< Northern tile of HQ; #INVALID_TILE when there is none.
|
||||
@@ -98,7 +96,13 @@ struct CompanyProperties {
|
||||
CompanyEconomyEntry old_economy[MAX_HISTORY_QUARTERS]; ///< Economic data of the company of the last #MAX_HISTORY_QUARTERS quarters.
|
||||
byte num_valid_stat_ent; ///< Number of valid statistical entries in #old_economy.
|
||||
|
||||
CompanyProperties() : name(NULL), president_name(NULL) {}
|
||||
// TODO: Change some of these member variables to use relevant INVALID_xxx constants
|
||||
CompanyProperties()
|
||||
: name_2(0), name_1(0), name(NULL), president_name_1(0), president_name_2(0), president_name(NULL),
|
||||
face(0), money(0), money_fraction(0), current_loan(0), colour(0), block_preview(0),
|
||||
location_of_HQ(0), last_build_coordinate(0), share_owners(), inaugurated_year(0),
|
||||
months_of_bankruptcy(0), bankrupt_asked(0), bankrupt_timeout(0), bankrupt_value(0),
|
||||
terraform_limit(0), clear_limit(0), tree_limit(0), is_ai(false) {}
|
||||
|
||||
~CompanyProperties()
|
||||
{
|
||||
@@ -112,6 +116,7 @@ struct Company : CompanyPool::PoolItem<&_company_pool>, CompanyProperties {
|
||||
~Company();
|
||||
|
||||
Livery livery[LS_END];
|
||||
RailTypes avail_railtypes; ///< Rail types available to this company.
|
||||
RoadTypes avail_roadtypes; ///< Road types available to this company.
|
||||
|
||||
class AIInstance *ai_instance;
|
||||
|
||||
@@ -162,7 +162,7 @@ static bool IsValidCompanyManagerFace(CompanyManagerFace cmf)
|
||||
for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
|
||||
switch (cmfv) {
|
||||
case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
|
||||
case CMFV_LIPS: // FALL THROUGH
|
||||
case CMFV_LIPS:
|
||||
case CMFV_NOSE: if (has_moustache) continue; break;
|
||||
case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
|
||||
case CMFV_GLASSES: if (!has_glasses) continue; break;
|
||||
|
||||
@@ -318,7 +318,8 @@ struct CompanyFinancesWindow : Window {
|
||||
case WID_CF_EXPS_PRICE2:
|
||||
case WID_CF_EXPS_PRICE3:
|
||||
size->height = _expenses_list_types[type].GetHeight();
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
|
||||
case WID_CF_BALANCE_VALUE:
|
||||
case WID_CF_LOAN_VALUE:
|
||||
case WID_CF_TOTAL_VALUE:
|
||||
@@ -636,7 +637,8 @@ public:
|
||||
size->width = 0;
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
|
||||
case WID_SCL_PRI_COL_DROPDOWN: {
|
||||
int padding = this->square.width + NWidgetScrollbar::GetVerticalDimension().width + 10;
|
||||
for (const StringID *id = _colour_dropdown; id != endof(_colour_dropdown); id++) {
|
||||
@@ -892,7 +894,7 @@ void DrawCompanyManagerFace(CompanyManagerFace cmf, int colour, int x, int y)
|
||||
for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
|
||||
switch (cmfv) {
|
||||
case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
|
||||
case CMFV_LIPS: // FALL THROUGH
|
||||
case CMFV_LIPS:
|
||||
case CMFV_NOSE: if (has_moustache) continue; break;
|
||||
case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
|
||||
case CMFV_GLASSES: if (!has_glasses) continue; break;
|
||||
@@ -1365,7 +1367,7 @@ public:
|
||||
/* OK button */
|
||||
case WID_SCMF_ACCEPT:
|
||||
DoCommandP(0, 0, this->face, CMD_SET_COMPANY_MANAGER_FACE);
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
|
||||
/* Cancel button */
|
||||
case WID_SCMF_CANCEL:
|
||||
@@ -2381,7 +2383,7 @@ struct CompanyWindow : Window
|
||||
|
||||
virtual void OnPlaceObject(Point pt, TileIndex tile)
|
||||
{
|
||||
if (DoCommandP(tile, OBJECT_HQ, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS))) {
|
||||
if (DoCommandP(tile, OBJECT_HQ, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS)) && !_shift_pressed) {
|
||||
ResetObjectToPlace();
|
||||
this->RaiseButtons();
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ static const CompanyManagerFaceBitsInfo _cmf_info[] = {
|
||||
/* CMFV_MOUSTACHE */ { 13, 2, { 3, 0, 3, 0 }, { 0x367, 0, 0x397, 0 } }, ///< Depends on CMFV_HAS_MOUSTACHE
|
||||
/* CMFV_LIPS */ { 13, 4, { 12, 10, 9, 9 }, { 0x35B, 0x351, 0x3A5, 0x3C8 } }, ///< Depends on !CMFV_HAS_MOUSTACHE
|
||||
/* CMFV_NOSE */ { 17, 3, { 8, 4, 4, 5 }, { 0x349, 0x34C, 0x393, 0x3B3 } }, ///< Depends on !CMFV_HAS_MOUSTACHE
|
||||
/* CMFV_HAIR */ { 20, 4, { 9, 5, 5, 4 }, { 0x382, 0x38B, 0x3D4, 0x3D9 } },
|
||||
/* CMFV_HAIR */ { 20, 4, { 9, 5, 5, 5 }, { 0x382, 0x38B, 0x3D4, 0x3D9 } },
|
||||
/* CMFV_JACKET */ { 24, 2, { 3, 3, 3, 3 }, { 0x36B, 0x378, 0x36B, 0x378 } },
|
||||
/* CMFV_COLLAR */ { 26, 2, { 4, 4, 4, 4 }, { 0x36E, 0x37B, 0x36E, 0x37B } },
|
||||
/* CMFV_TIE_EARRING */ { 28, 3, { 6, 3, 6, 3 }, { 0x372, 0x37F, 0x372, 0x3D1 } }, ///< Depends on CMFV_HAS_TIE_EARRING
|
||||
|
||||
@@ -434,7 +434,10 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
* enclosed in "" are taken as one token. We can only go as far as the amount
|
||||
* of characters in our stream or the max amount of tokens we can handle */
|
||||
for (cmdptr = cmdstr, t_index = 0, tstream_i = 0; *cmdptr != '\0'; cmdptr++) {
|
||||
if (t_index >= lengthof(tokens) || tstream_i >= lengthof(tokenstream)) break;
|
||||
if (tstream_i >= lengthof(tokenstream)) {
|
||||
IConsoleError("command line too long");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (*cmdptr) {
|
||||
case ' ': // Token separator
|
||||
@@ -452,6 +455,10 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
case '"': // Tokens enclosed in "" are one token
|
||||
longtoken = !longtoken;
|
||||
if (!foundtoken) {
|
||||
if (t_index >= lengthof(tokens)) {
|
||||
IConsoleError("command line too long");
|
||||
return;
|
||||
}
|
||||
tokens[t_index++] = &tokenstream[tstream_i];
|
||||
foundtoken = true;
|
||||
}
|
||||
@@ -461,11 +468,15 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
tokenstream[tstream_i++] = *++cmdptr;
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
default: // Normal character
|
||||
tokenstream[tstream_i++] = *cmdptr;
|
||||
|
||||
if (!foundtoken) {
|
||||
if (t_index >= lengthof(tokens)) {
|
||||
IConsoleError("command line too long");
|
||||
return;
|
||||
}
|
||||
tokens[t_index++] = &tokenstream[tstream_i - 1];
|
||||
foundtoken = true;
|
||||
}
|
||||
@@ -473,7 +484,7 @@ void IConsoleCmdExec(const char *cmdstr)
|
||||
}
|
||||
}
|
||||
|
||||
for (uint i = 0; tokens[i] != NULL; i++) {
|
||||
for (uint i = 0; i < lengthof(tokens) && tokens[i] != NULL; i++) {
|
||||
DEBUG(console, 8, "Token %d is: '%s'", i, tokens[i]);
|
||||
}
|
||||
|
||||
|
||||
@@ -553,29 +553,36 @@ DEF_CONSOLE_CMD(ConBan)
|
||||
|
||||
DEF_CONSOLE_CMD(ConUnBan)
|
||||
{
|
||||
|
||||
if (argc == 0) {
|
||||
IConsoleHelp("Unban a client from a network game. Usage: 'unban <ip | client-id>'");
|
||||
IConsoleHelp("Unban a client from a network game. Usage: 'unban <ip | banlist-index>'");
|
||||
IConsoleHelp("For a list of banned IP's, see the command 'banlist'");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (argc != 2) return false;
|
||||
|
||||
uint index = (strchr(argv[1], '.') == NULL) ? atoi(argv[1]) : 0;
|
||||
index--;
|
||||
uint i = 0;
|
||||
|
||||
for (char **iter = _network_ban_list.Begin(); iter != _network_ban_list.End(); iter++, i++) {
|
||||
if (strcmp(_network_ban_list[i], argv[1]) == 0 || index == i) {
|
||||
free(_network_ban_list[i]);
|
||||
_network_ban_list.Erase(iter);
|
||||
IConsolePrint(CC_DEFAULT, "IP unbanned.");
|
||||
return true;
|
||||
}
|
||||
/* Try by IP. */
|
||||
uint index;
|
||||
for (index = 0; index < _network_ban_list.Length(); index++) {
|
||||
if (strcmp(_network_ban_list[index], argv[1]) == 0) break;
|
||||
}
|
||||
|
||||
/* Try by index. */
|
||||
if (index >= _network_ban_list.Length()) {
|
||||
index = atoi(argv[1]) - 1U; // let it wrap
|
||||
}
|
||||
|
||||
if (index < _network_ban_list.Length()) {
|
||||
char msg[64];
|
||||
seprintf(msg, lastof(msg), "Unbanned %s", _network_ban_list[index]);
|
||||
IConsolePrint(CC_DEFAULT, msg);
|
||||
free(_network_ban_list[index]);
|
||||
_network_ban_list.Erase(_network_ban_list.Get(index));
|
||||
} else {
|
||||
IConsolePrint(CC_DEFAULT, "Invalid list index or IP not in ban-list.");
|
||||
IConsolePrint(CC_DEFAULT, "For a list of banned IP's, see the command 'banlist'");
|
||||
}
|
||||
|
||||
IConsolePrint(CC_DEFAULT, "IP not in ban-list.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ static inline T *ReallocT(T *t_ptr, size_t num_elements)
|
||||
/* Ensure the size does not overflow. */
|
||||
CheckAllocationConstraints<T>(num_elements);
|
||||
|
||||
t_ptr = (T*)realloc(t_ptr, num_elements * sizeof(T));
|
||||
t_ptr = (T*)realloc(static_cast<void *>(t_ptr), num_elements * sizeof(T));
|
||||
if (t_ptr == NULL) ReallocError(num_elements * sizeof(T));
|
||||
return t_ptr;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ struct Backup {
|
||||
{
|
||||
/* We cannot assert here, as missing restoration is 'normal' when exceptions are thrown.
|
||||
* Exceptions are especially used to abort world generation. */
|
||||
DEBUG(misc, 0, "%s:%d: Backupped value was not restored!", this->file, this->line);
|
||||
DEBUG(misc, 0, "%s:%d: Backed-up value was not restored!", this->file, this->line);
|
||||
this->Restore();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,13 +365,32 @@ static inline T ROR(const T x, const uint8 n)
|
||||
* (since it will use hardware swapping if available).
|
||||
* Even though they should return uint16 and uint32, we get
|
||||
* warnings if we don't cast those (why?) */
|
||||
#define BSWAP64(x) ((uint64)CFSwapInt64(x))
|
||||
#define BSWAP32(x) ((uint32)CFSwapInt32(x))
|
||||
#define BSWAP16(x) ((uint16)CFSwapInt16(x))
|
||||
#elif defined(_MSC_VER)
|
||||
/* MSVC has intrinsics for swapping, resulting in faster code */
|
||||
#define BSWAP64(x) (_byteswap_uint64(x))
|
||||
#define BSWAP32(x) (_byteswap_ulong(x))
|
||||
#define BSWAP16(x) (_byteswap_ushort(x))
|
||||
#else
|
||||
/**
|
||||
* Perform a 64 bits endianness bitswap on x.
|
||||
* @param x the variable to bitswap
|
||||
* @return the bitswapped value.
|
||||
*/
|
||||
static inline uint64 BSWAP64(uint64 x)
|
||||
{
|
||||
#if !defined(__ICC) && (defined(__GNUC__) || defined(__clang__))
|
||||
/* GCC >= 4.3 provides a builtin, resulting in faster code */
|
||||
return (uint64)__builtin_bswap64((uint64)x);
|
||||
#else
|
||||
return ((x >> 56) & 0xFFULL) | ((x >> 40) & 0xFF00ULL) | ((x >> 24) & 0xFF0000ULL) | ((x >> 8) & 0xFF000000ULL) |
|
||||
((x << 8) & 0xFF00000000ULL) | ((x << 24) & 0xFF0000000000ULL) | ((x << 40) & 0xFF000000000000ULL) | ((x << 56) & 0xFF000000000000ULL);
|
||||
;
|
||||
#endif /* __GNUC__ || __clang__ */
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a 32 bits endianness bitswap on x.
|
||||
* @param x the variable to bitswap
|
||||
|
||||
42
src/core/container_func.hpp
Normal file
42
src/core/container_func.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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 container_func.hpp Functions related to use of containers. */
|
||||
|
||||
#ifndef CONTAINER_FUNC_HPP
|
||||
#define CONTAINER_FUNC_HPP
|
||||
|
||||
#include <iterator>
|
||||
|
||||
template <typename C, typename UP> unsigned int container_unordered_remove_if (C &container, UP predicate) {
|
||||
unsigned int removecount = 0;
|
||||
for (auto it = container.begin(); it != container.end();) {
|
||||
if (predicate(*it)) {
|
||||
removecount++;
|
||||
if (std::next(it) != container.end()) {
|
||||
*it = std::move(container.back());
|
||||
container.pop_back();
|
||||
} else {
|
||||
container.pop_back();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
return removecount;
|
||||
}
|
||||
|
||||
template <typename C, typename V> unsigned int container_unordered_remove(C &container, const V &value) {
|
||||
return container_unordered_remove_if (container, [&](const typename C::value_type &v) {
|
||||
return v == value;
|
||||
});
|
||||
}
|
||||
|
||||
#endif /* CONTAINER_FUNC_HPP */
|
||||
102
src/core/dyn_arena_alloc.hpp
Normal file
102
src/core/dyn_arena_alloc.hpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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 dyn_arena_alloc.hpp Dynamic chunk-size arena allocator. */
|
||||
|
||||
#ifndef DYN_ARENA_ALLOC_HPP
|
||||
#define DYN_ARENA_ALLOC_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
/**
|
||||
* Custom arena allocator for uniform-size allocations of a variable size.
|
||||
* The allocation and chunk sizes may only be changed when the arena is empty.
|
||||
*/
|
||||
class DynUniformArenaAllocator {
|
||||
std::vector<void *> used_blocks;
|
||||
|
||||
void *current_block = nullptr;
|
||||
void *last_freed = nullptr;
|
||||
size_t next_position = 0;
|
||||
|
||||
size_t item_size = 0;
|
||||
size_t items_per_chunk = 0;
|
||||
|
||||
void NewBlock()
|
||||
{
|
||||
current_block = malloc(item_size * items_per_chunk);
|
||||
assert(current_block != nullptr);
|
||||
next_position = 0;
|
||||
used_blocks.push_back(current_block);
|
||||
}
|
||||
|
||||
public:
|
||||
DynUniformArenaAllocator() = default;
|
||||
DynUniformArenaAllocator(const DynUniformArenaAllocator &other) = delete;
|
||||
DynUniformArenaAllocator& operator=(const DynUniformArenaAllocator &other) = delete;
|
||||
|
||||
~DynUniformArenaAllocator()
|
||||
{
|
||||
EmptyArena();
|
||||
}
|
||||
|
||||
void EmptyArena()
|
||||
{
|
||||
current_block = nullptr;
|
||||
last_freed = nullptr;
|
||||
next_position = 0;
|
||||
for (void *block : used_blocks) {
|
||||
free(block);
|
||||
}
|
||||
used_blocks.clear();
|
||||
}
|
||||
|
||||
void ResetArena()
|
||||
{
|
||||
EmptyArena();
|
||||
item_size = 0;
|
||||
items_per_chunk = 0;
|
||||
}
|
||||
|
||||
void *Allocate() {
|
||||
assert(item_size != 0);
|
||||
if (last_freed) {
|
||||
void *ptr = last_freed;
|
||||
last_freed = *reinterpret_cast<void**>(ptr);
|
||||
return ptr;
|
||||
} else {
|
||||
if (current_block == nullptr || next_position == items_per_chunk) {
|
||||
NewBlock();
|
||||
}
|
||||
void *out = reinterpret_cast<char *>(current_block) + (item_size * next_position);
|
||||
next_position++;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
void Free(void *ptr) {
|
||||
if (!ptr) return;
|
||||
assert(current_block != nullptr);
|
||||
|
||||
*reinterpret_cast<void**>(ptr) = last_freed;
|
||||
last_freed = ptr;
|
||||
}
|
||||
|
||||
void SetParameters(size_t item_size, size_t items_per_chunk)
|
||||
{
|
||||
if (item_size < sizeof(void *)) item_size = sizeof(void *);
|
||||
if (this->item_size == item_size && this->items_per_chunk == items_per_chunk) return;
|
||||
|
||||
assert(current_block == nullptr);
|
||||
this->item_size = item_size;
|
||||
this->items_per_chunk = items_per_chunk;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* DYN_ARENA_ALLOC_HPP */
|
||||
@@ -19,25 +19,33 @@
|
||||
#if TTD_ENDIAN == TTD_BIG_ENDIAN
|
||||
#define FROM_BE16(x) (x)
|
||||
#define FROM_BE32(x) (x)
|
||||
#define FROM_BE64(x) (x)
|
||||
#define TO_BE16(x) (x)
|
||||
#define TO_BE32(x) (x)
|
||||
#define TO_BE32X(x) (x)
|
||||
#define TO_BE64(x) (x)
|
||||
#define FROM_LE16(x) BSWAP16(x)
|
||||
#define FROM_LE32(x) BSWAP32(x)
|
||||
#define FROM_LE64(x) BSWAP64(x)
|
||||
#define TO_LE16(x) BSWAP16(x)
|
||||
#define TO_LE32(x) BSWAP32(x)
|
||||
#define TO_LE32X(x) BSWAP32(x)
|
||||
#define TO_LE64(x) BSWAP64(x)
|
||||
#else
|
||||
#define FROM_BE16(x) BSWAP16(x)
|
||||
#define FROM_BE32(x) BSWAP32(x)
|
||||
#define FROM_BE64(x) BSWAP64(x)
|
||||
#define TO_BE16(x) BSWAP16(x)
|
||||
#define TO_BE32(x) BSWAP32(x)
|
||||
#define TO_BE32X(x) BSWAP32(x)
|
||||
#define TO_BE64(x) BSWAP64(x)
|
||||
#define FROM_LE16(x) (x)
|
||||
#define FROM_LE32(x) (x)
|
||||
#define FROM_LE64(x) (x)
|
||||
#define TO_LE16(x) (x)
|
||||
#define TO_LE32(x) (x)
|
||||
#define TO_LE32X(x) (x)
|
||||
#define TO_LE64(x) (x)
|
||||
#endif /* TTD_ENDIAN == TTD_BIG_ENDIAN */
|
||||
|
||||
static inline uint16 ReadLE16Aligned(const void *x)
|
||||
|
||||
@@ -27,14 +27,21 @@
|
||||
|
||||
/* Windows has always LITTLE_ENDIAN */
|
||||
#if defined(WIN32) || defined(__OS2__) || defined(WIN64)
|
||||
#define TTD_ENDIAN TTD_LITTLE_ENDIAN
|
||||
# define TTD_ENDIAN TTD_LITTLE_ENDIAN
|
||||
#elif defined(OSX)
|
||||
# include <sys/types.h>
|
||||
# if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
|
||||
# define TTD_ENDIAN TTD_LITTLE_ENDIAN
|
||||
# else
|
||||
# define TTD_ENDIAN TTD_BIG_ENDIAN
|
||||
# endif
|
||||
#elif !defined(TESTING)
|
||||
/* Else include endian[target/host].h, which has the endian-type, autodetected by the Makefile */
|
||||
#if defined(STRGEN) || defined(SETTINGSGEN)
|
||||
#include "endian_host.h"
|
||||
#else
|
||||
#include "endian_target.h"
|
||||
#endif
|
||||
# include <sys/param.h>
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define TTD_ENDIAN TTD_LITTLE_ENDIAN
|
||||
# else
|
||||
# define TTD_ENDIAN TTD_BIG_ENDIAN
|
||||
# endif
|
||||
#endif /* WIN32 || __OS2__ || WIN64 */
|
||||
|
||||
#endif /* ENDIAN_TYPE_HPP */
|
||||
|
||||
@@ -318,6 +318,18 @@ static inline uint CeilDiv(uint a, uint b)
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes ceil(a / b) for non-negative a and b (templated).
|
||||
* @param a Numerator
|
||||
* @param b Denominator
|
||||
* @return Quotient, rounded up
|
||||
*/
|
||||
template <typename T>
|
||||
static inline T CeilDivT(T a, T b)
|
||||
{
|
||||
return (a + b - 1) / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes ceil(a / b) * b for non-negative a and b.
|
||||
* @param a Numerator
|
||||
@@ -329,6 +341,18 @@ static inline uint Ceil(uint a, uint b)
|
||||
return CeilDiv(a, b) * b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes ceil(a / b) * b for non-negative a and b (templated).
|
||||
* @param a Numerator
|
||||
* @param b Denominator
|
||||
* @return a rounded up to the nearest multiple of b.
|
||||
*/
|
||||
template <typename T>
|
||||
static inline T CeilT(T a, T b)
|
||||
{
|
||||
return CeilDivT<T>(a, b) * b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes round(a / b) for signed a and unsigned b.
|
||||
* @param a Numerator
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
template<typename Tkey, typename Tvalue, typename Tcompare>
|
||||
template<typename Tkey, typename Tvalue, typename Tcontainer, typename Tcompare>
|
||||
class MultiMap;
|
||||
|
||||
/**
|
||||
@@ -23,14 +23,15 @@ class MultiMap;
|
||||
* @tparam Tmap_iter Iterator type for the map in the MultiMap.
|
||||
* @tparam Tlist_iter Iterator type for the lists in the MultiMap.
|
||||
* @tparam Tkey Key type of the MultiMap.
|
||||
* @tparam Tvalue Value type of the MultMap.
|
||||
* @tparam Tvalue Value type of the MultiMap.
|
||||
* @tparam Tcontainer Container type for the values of the MultiMap.
|
||||
* @tparam Tcompare Comparator type for keys of the MultiMap.
|
||||
*/
|
||||
template<class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcompare>
|
||||
template<class Tmap_iter, class Tlist_iter, class Tkey, class Tvalue, class Tcontainer, class Tcompare>
|
||||
class MultiMapIterator {
|
||||
protected:
|
||||
friend class MultiMap<Tkey, Tvalue, Tcompare>;
|
||||
typedef MultiMapIterator<Tmap_iter, Tlist_iter, Tkey, Tvalue, Tcompare> Self;
|
||||
friend class MultiMap<Tkey, Tvalue, Tcontainer, Tcompare>;
|
||||
typedef MultiMapIterator<Tmap_iter, Tlist_iter, Tkey, Tvalue, Tcontainer, Tcompare> Self;
|
||||
|
||||
Tlist_iter list_iter; ///< Iterator pointing to current position in the current list of items with equal keys.
|
||||
Tmap_iter map_iter; ///< Iterator pointing to the position of the current list of items with equal keys in the map.
|
||||
@@ -201,8 +202,8 @@ public:
|
||||
* @param iter2 Second iterator to compare.
|
||||
* @return If iter1 and iter2 are equal.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
|
||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcontainer1, class Tcontainer2, class Tcompare>
|
||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcontainer1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcontainer2, Tcompare> &iter2)
|
||||
{
|
||||
if (iter1.GetMapIter() != iter2.GetMapIter()) return false;
|
||||
if (!iter1.ListValid()) return !iter2.ListValid();
|
||||
@@ -218,8 +219,8 @@ bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, T
|
||||
* @param iter2 Second iterator to compare.
|
||||
* @return If iter1 and iter2 are not equal.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcompare>
|
||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcompare> &iter2)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tlist_iter2, class Tkey, class Tvalue1, class Tvalue2, class Tcontainer1, class Tcontainer2, class Tcompare>
|
||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, Tcontainer1, Tcompare> &iter1, const MultiMapIterator<Tmap_iter2, Tlist_iter2, Tkey, Tvalue2, Tcontainer2, Tcompare> &iter2)
|
||||
{
|
||||
return !(iter1 == iter2);
|
||||
}
|
||||
@@ -232,8 +233,8 @@ bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue1, T
|
||||
* @param iter2 Map iterator.
|
||||
* @return If iter1 points to the begin of the list pointed to by iter2.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||
bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||
{
|
||||
return !iter1.ListValid() && iter1.GetMapIter() == iter2;
|
||||
}
|
||||
@@ -244,8 +245,8 @@ bool operator==(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tc
|
||||
* @param iter2 Map iterator.
|
||||
* @return If iter1 doesn't point to the begin of the list pointed to by iter2.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||
bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1, const Tmap_iter2 &iter2)
|
||||
{
|
||||
return iter1.ListValid() || iter1.GetMapIter() != iter2;
|
||||
}
|
||||
@@ -256,8 +257,8 @@ bool operator!=(const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tc
|
||||
* @param iter1 MultiMap iterator.
|
||||
* @return If iter1 points to the begin of the list pointed to by iter2.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
||||
bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||
bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1)
|
||||
{
|
||||
return !iter1.ListValid() && iter1.GetMapIter() == iter2;
|
||||
}
|
||||
@@ -268,8 +269,8 @@ bool operator==(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlis
|
||||
* @param iter1 MultiMap iterator.
|
||||
* @return If iter1 doesn't point to the begin of the list pointed to by iter2.
|
||||
*/
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcompare >
|
||||
bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcompare> &iter1)
|
||||
template<class Tmap_iter1, class Tlist_iter1, class Tmap_iter2, class Tkey, class Tvalue, class Tcontainer, class Tcompare >
|
||||
bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlist_iter1, Tkey, Tvalue, Tcontainer, Tcompare> &iter1)
|
||||
{
|
||||
return iter1.ListValid() || iter1.GetMapIter() != iter2;
|
||||
}
|
||||
@@ -282,10 +283,10 @@ bool operator!=(const Tmap_iter2 &iter2, const MultiMapIterator<Tmap_iter1, Tlis
|
||||
* STL-compatible members are named in STL style, all others are named in OpenTTD
|
||||
* style.
|
||||
*/
|
||||
template<typename Tkey, typename Tvalue, typename Tcompare = std::less<Tkey> >
|
||||
class MultiMap : public std::map<Tkey, std::list<Tvalue>, Tcompare > {
|
||||
template<typename Tkey, typename Tvalue, typename Tcontainer = std::list<Tvalue>, typename Tcompare = std::less<Tkey> >
|
||||
class MultiMap : public std::map<Tkey, Tcontainer, Tcompare > {
|
||||
public:
|
||||
typedef typename std::list<Tvalue> List;
|
||||
typedef Tcontainer List;
|
||||
typedef typename List::iterator ListIterator;
|
||||
typedef typename List::const_iterator ConstListIterator;
|
||||
|
||||
@@ -293,8 +294,8 @@ public:
|
||||
typedef typename Map::iterator MapIterator;
|
||||
typedef typename Map::const_iterator ConstMapIterator;
|
||||
|
||||
typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcompare> iterator;
|
||||
typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcompare> const_iterator;
|
||||
typedef MultiMapIterator<MapIterator, ListIterator, Tkey, Tvalue, Tcontainer, Tcompare> iterator;
|
||||
typedef MultiMapIterator<ConstMapIterator, ConstListIterator, Tkey, const Tvalue, Tcontainer, Tcompare> const_iterator;
|
||||
|
||||
/**
|
||||
* Erase the value pointed to by an iterator. The iterator may be invalid afterwards.
|
||||
|
||||
@@ -196,6 +196,7 @@ DEFINE_POOL_METHOD(void)::FreeItem(size_t index)
|
||||
DEFINE_POOL_METHOD(void)::CleanPool()
|
||||
{
|
||||
this->cleaning = true;
|
||||
Titem::PreCleanPool();
|
||||
for (size_t i = 0; i < this->first_unused; i++) {
|
||||
delete this->Get(i); // 'delete NULL;' is very valid
|
||||
}
|
||||
|
||||
@@ -286,6 +286,13 @@ struct Pool : PoolBase {
|
||||
* @note it's called only when !CleaningPool()
|
||||
*/
|
||||
static inline void PostDestructor(size_t index) { }
|
||||
|
||||
/**
|
||||
* Dummy function called before a pool is about to be cleaned.
|
||||
* If you want to use it, override it in PoolItem's subclass.
|
||||
* @note it's called only when CleaningPool()
|
||||
*/
|
||||
static inline void PreCleanPool() { }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
@@ -183,9 +183,9 @@ public:
|
||||
inline void Push(const Titem &item)
|
||||
{
|
||||
if (this->value != Tinvalid) {
|
||||
Tindex new_item = _pool.Create();
|
||||
Tindex new_item = SmallStack::GetPool().Create();
|
||||
if (new_item != Tmax_size) {
|
||||
PooledSmallStack &pushed = _pool.Get(new_item);
|
||||
PooledSmallStack &pushed = SmallStack::GetPool().Get(new_item);
|
||||
pushed.value = this->value;
|
||||
pushed.next = this->next;
|
||||
pushed.branch_count = 0;
|
||||
@@ -205,13 +205,15 @@ public:
|
||||
if (this->next == Tmax_size) {
|
||||
this->value = Tinvalid;
|
||||
} else {
|
||||
PooledSmallStack &popped = _pool.Get(this->next);
|
||||
PooledSmallStack &popped = SmallStack::GetPool().Get(this->next);
|
||||
this->value = popped.value;
|
||||
if (popped.branch_count == 0) {
|
||||
_pool.Destroy(this->next);
|
||||
SmallStack::GetPool().Destroy(this->next);
|
||||
} else {
|
||||
--popped.branch_count;
|
||||
this->Branch();
|
||||
if (popped.next != Tmax_size) {
|
||||
++(SmallStack::GetPool().Get(popped.next).branch_count);
|
||||
}
|
||||
}
|
||||
/* Accessing popped here is no problem as the pool will only set
|
||||
* the validity flag, not actually delete the item, on Destroy().
|
||||
@@ -243,7 +245,7 @@ public:
|
||||
const SmallStack *in_list = this;
|
||||
do {
|
||||
in_list = static_cast<const SmallStack *>(
|
||||
static_cast<const Item *>(&_pool.Get(in_list->next)));
|
||||
static_cast<const Item *>(&SmallStack::GetPool().Get(in_list->next)));
|
||||
if (in_list->value == item) return true;
|
||||
} while (in_list->next != Tmax_size);
|
||||
}
|
||||
@@ -251,7 +253,11 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
static SmallStackPool _pool;
|
||||
static SmallStackPool &GetPool()
|
||||
{
|
||||
static SmallStackPool pool;
|
||||
return pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a branch in the pool if necessary.
|
||||
@@ -259,7 +265,7 @@ protected:
|
||||
inline void Branch()
|
||||
{
|
||||
if (this->next != Tmax_size) {
|
||||
++(_pool.Get(this->next).branch_count);
|
||||
++(SmallStack::GetPool().Get(this->next).branch_count);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,6 +158,23 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new item at a specific position into the vector, moving all following items.
|
||||
* @param item Position at which the new item should be inserted
|
||||
* @return pointer to the new item
|
||||
*/
|
||||
inline T *Insert(T *item)
|
||||
{
|
||||
assert(item >= this->Begin() && item <= this->End());
|
||||
|
||||
size_t to_move = this->End() - item;
|
||||
size_t start = item - this->Begin();
|
||||
|
||||
this->Append();
|
||||
if (to_move > 0) MemMoveT(this->Begin() + start + 1, this->Begin() + start, to_move);
|
||||
return this->Begin() + start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for the first occurrence of an item.
|
||||
* The '!=' operator of T is used for comparison.
|
||||
@@ -232,13 +249,24 @@ public:
|
||||
* @param count Number of consecutive items to remove.
|
||||
*/
|
||||
void ErasePreservingOrder(uint pos, uint count = 1)
|
||||
{
|
||||
ErasePreservingOrder(this->data + pos, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove items from the vector while preserving the order of other items.
|
||||
* @param item First item to remove.
|
||||
* @param count Number of consecutive items to remove.
|
||||
*/
|
||||
inline void ErasePreservingOrder(T *item, uint count = 1)
|
||||
{
|
||||
if (count == 0) return;
|
||||
assert(pos < this->items);
|
||||
assert(pos + count <= this->items);
|
||||
assert(item >= this->Begin());
|
||||
assert(item + count <= this->End());
|
||||
|
||||
this->items -= count;
|
||||
uint to_move = this->items - pos;
|
||||
if (to_move > 0) MemMoveT(this->data + pos, this->data + pos + count, to_move);
|
||||
ptrdiff_t to_move = this->End() - item;
|
||||
if (to_move > 0) MemMoveT(item, item + count, to_move);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
/* rdtsc for MSC_VER, uses simple inline assembly, or _rdtsc
|
||||
* from external win64.asm because VS2005 does not support inline assembly */
|
||||
#if defined(_MSC_VER) && !defined(RDTSC_AVAILABLE) && !defined(WINCE)
|
||||
#if defined(_MSC_VER) && !defined(RDTSC_AVAILABLE)
|
||||
#include <intrin.h>
|
||||
uint64 ottd_rdtsc()
|
||||
{
|
||||
@@ -71,10 +71,7 @@ uint64 ottd_rdtsc()
|
||||
/* In all other cases we have no support for rdtsc. No major issue,
|
||||
* you just won't be able to profile your code with TIC()/TOC() */
|
||||
#if !defined(RDTSC_AVAILABLE)
|
||||
/* MSVC (in case of WinCE) can't handle #warning */
|
||||
# if !defined(_MSC_VER)
|
||||
#warning "(non-fatal) No support for rdtsc(), you won't be able to profile with TIC/TOC"
|
||||
# endif
|
||||
uint64 ottd_rdtsc() {return 0;}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "network/network.h"
|
||||
#include "language.h"
|
||||
#include "fontcache.h"
|
||||
#include "news_gui.h"
|
||||
|
||||
#include "ai/ai_info.hpp"
|
||||
#include "game/game.hpp"
|
||||
@@ -308,6 +309,27 @@ char *CrashLog::LogGamelog(char *buffer, const char *last) const
|
||||
return CrashLog::gamelog_buffer + seprintf(CrashLog::gamelog_buffer, last, "\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes any recent news messages to the buffer.
|
||||
* @param buffer The begin where to write at.
|
||||
* @param last The last position in the buffer to write to.
|
||||
* @return the position of the \c '\0' character after the buffer.
|
||||
*/
|
||||
char *CrashLog::LogRecentNews(char *buffer, const char *last) const
|
||||
{
|
||||
buffer += seprintf(buffer, last, "Recent news messages:\n");
|
||||
|
||||
for (NewsItem *news = _oldest_news; news != NULL; news = news->next) {
|
||||
YearMonthDay ymd;
|
||||
ConvertDateToYMD(news->date, &ymd);
|
||||
buffer += seprintf(buffer, last, "(%i-%02i-%02i) StringID: %u, Type: %u, Ref1: %u, %u, Ref2: %u, %u\n",
|
||||
ymd.year, ymd.month + 1, ymd.day, news->string_id, news->type,
|
||||
news->reftype1, news->ref1, news->reftype2, news->ref2);
|
||||
}
|
||||
buffer += seprintf(buffer, last, "\n");
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the crash log buffer with all data of a crash log.
|
||||
* @param buffer The begin where to write at.
|
||||
@@ -334,6 +356,7 @@ char *CrashLog::FillCrashLog(char *buffer, const char *last) const
|
||||
buffer = this->LogLibraries(buffer, last);
|
||||
buffer = this->LogModules(buffer, last);
|
||||
buffer = this->LogGamelog(buffer, last);
|
||||
buffer = this->LogRecentNews(buffer, last);
|
||||
|
||||
buffer += seprintf(buffer, last, "*** End of OpenTTD Crash Report ***\n");
|
||||
return buffer;
|
||||
|
||||
@@ -85,6 +85,7 @@ protected:
|
||||
char *LogConfiguration(char *buffer, const char *last) const;
|
||||
char *LogLibraries(char *buffer, const char *last) const;
|
||||
char *LogGamelog(char *buffer, const char *last) const;
|
||||
char *LogRecentNews(char *buffer, const char *list) const;
|
||||
|
||||
public:
|
||||
/** Stub destructor to silence some compilers. */
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
#include "fileio_func.h"
|
||||
#include "settings_type.h"
|
||||
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
#include "os/windows/win32.h"
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#if defined(ENABLE_NETWORK)
|
||||
@@ -100,8 +104,6 @@ char *DumpDebugFacilityNames(char *buf, char *last)
|
||||
return buf;
|
||||
}
|
||||
|
||||
#if !defined(NO_DEBUG_MESSAGES)
|
||||
|
||||
/**
|
||||
* Internal function for outputting the debug line.
|
||||
* @param dbg Debug category.
|
||||
@@ -137,10 +139,10 @@ static void debug_print(const char *dbg, const char *buf)
|
||||
} else {
|
||||
char buffer[512];
|
||||
seprintf(buffer, lastof(buffer), "%sdbg: [%s] %s\n", GetLogPrefix(), dbg, buf);
|
||||
#if defined(WINCE)
|
||||
NKDbgPrintfW(OTTD2FS(buffer));
|
||||
#elif defined(WIN32) || defined(WIN64)
|
||||
_fputts(OTTD2FS(buffer, true), stderr);
|
||||
#if defined(WIN32) || defined(WIN64)
|
||||
TCHAR system_buf[512];
|
||||
convert_to_fs(buffer, system_buf, lengthof(system_buf), true);
|
||||
_fputts(system_buf, stderr);
|
||||
#else
|
||||
fputs(buffer, stderr);
|
||||
#endif
|
||||
@@ -168,7 +170,6 @@ void CDECL debug(const char *dbg, const char *format, ...)
|
||||
|
||||
debug_print(dbg, buf);
|
||||
}
|
||||
#endif /* NO_DEBUG_MESSAGES */
|
||||
|
||||
/**
|
||||
* Set debugging levels by parsing the text in \a s.
|
||||
|
||||
50
src/debug.h
50
src/debug.h
@@ -28,37 +28,33 @@
|
||||
* 6.. - extremely detailed spamming
|
||||
*/
|
||||
|
||||
#ifdef NO_DEBUG_MESSAGES
|
||||
#define DEBUG(name, level, ...) { }
|
||||
#else /* NO_DEBUG_MESSAGES */
|
||||
/**
|
||||
* Output a line of debugging information.
|
||||
* @param name Category
|
||||
* @param level Debugging level, higher levels means more detailed information.
|
||||
*/
|
||||
#define DEBUG(name, level, ...) if ((level) == 0 || _debug_ ## name ## _level >= (level)) debug(#name, __VA_ARGS__)
|
||||
/**
|
||||
* Output a line of debugging information.
|
||||
* @param name Category
|
||||
* @param level Debugging level, higher levels means more detailed information.
|
||||
*/
|
||||
#define DEBUG(name, level, ...) if ((level) == 0 || _debug_ ## name ## _level >= (level)) debug(#name, __VA_ARGS__)
|
||||
|
||||
extern int _debug_driver_level;
|
||||
extern int _debug_grf_level;
|
||||
extern int _debug_map_level;
|
||||
extern int _debug_misc_level;
|
||||
extern int _debug_net_level;
|
||||
extern int _debug_sprite_level;
|
||||
extern int _debug_oldloader_level;
|
||||
extern int _debug_npf_level;
|
||||
extern int _debug_yapf_level;
|
||||
extern int _debug_freetype_level;
|
||||
extern int _debug_script_level;
|
||||
extern int _debug_sl_level;
|
||||
extern int _debug_gamelog_level;
|
||||
extern int _debug_desync_level;
|
||||
extern int _debug_console_level;
|
||||
extern int _debug_driver_level;
|
||||
extern int _debug_grf_level;
|
||||
extern int _debug_map_level;
|
||||
extern int _debug_misc_level;
|
||||
extern int _debug_net_level;
|
||||
extern int _debug_sprite_level;
|
||||
extern int _debug_oldloader_level;
|
||||
extern int _debug_npf_level;
|
||||
extern int _debug_yapf_level;
|
||||
extern int _debug_freetype_level;
|
||||
extern int _debug_script_level;
|
||||
extern int _debug_sl_level;
|
||||
extern int _debug_gamelog_level;
|
||||
extern int _debug_desync_level;
|
||||
extern int _debug_console_level;
|
||||
#ifdef RANDOM_DEBUG
|
||||
extern int _debug_random_level;
|
||||
extern int _debug_random_level;
|
||||
#endif
|
||||
|
||||
void CDECL debug(const char *dbg, const char *format, ...) WARN_FORMAT(2, 3);
|
||||
#endif /* NO_DEBUG_MESSAGES */
|
||||
void CDECL debug(const char *dbg, const char *format, ...) WARN_FORMAT(2, 3);
|
||||
|
||||
char *DumpDebugFacilityNames(char *buf, char *last);
|
||||
void SetDebugString(const char *s);
|
||||
|
||||
@@ -147,6 +147,7 @@ static void TrainDepotMoveVehicle(const Vehicle *wagon, VehicleID sel, const Veh
|
||||
|
||||
static VehicleCellSize _base_block_sizes_depot[VEH_COMPANY_END]; ///< Cell size for vehicle images in the depot view.
|
||||
static VehicleCellSize _base_block_sizes_purchase[VEH_COMPANY_END]; ///< Cell size for vehicle images in the purchase list.
|
||||
static uint _consistent_train_width; ///< Whether trains of all lengths are consistently scaled. Either TRAININFO_DEFAULT_VEHICLE_WIDTH, VEHICLEINFO_FULL_VEHICLE_WIDTH, or 0.
|
||||
|
||||
/**
|
||||
* Get the GUI cell size for a vehicle image.
|
||||
@@ -219,6 +220,34 @@ void InitDepotWindowBlockSizes()
|
||||
InitBlocksizeForVehicles(vt, EIT_IN_DEPOT);
|
||||
InitBlocksizeForVehicles(vt, EIT_PURCHASE);
|
||||
}
|
||||
|
||||
_consistent_train_width = TRAININFO_DEFAULT_VEHICLE_WIDTH;
|
||||
bool first = true;
|
||||
const Engine *e;
|
||||
FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
|
||||
if (!e->IsEnabled()) continue;
|
||||
|
||||
uint w = TRAININFO_DEFAULT_VEHICLE_WIDTH;
|
||||
if (e->GetGRF() != NULL && is_custom_sprite(e->u.rail.image_index)) {
|
||||
w = e->GetGRF()->traininfo_vehicle_width;
|
||||
if (w != VEHICLEINFO_FULL_VEHICLE_WIDTH) {
|
||||
/* Hopeless.
|
||||
* This is a NewGRF vehicle that uses TRAININFO_DEFAULT_VEHICLE_WIDTH.
|
||||
* If the vehicles are shorter than 8/8 we have fractional lengths, which are not consistent after rounding.
|
||||
*/
|
||||
_consistent_train_width = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first) {
|
||||
_consistent_train_width = w;
|
||||
first = false;
|
||||
} else if (w != _consistent_train_width) {
|
||||
_consistent_train_width = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void DepotSellAllConfirmationCallback(Window *w, bool confirmed);
|
||||
@@ -292,7 +321,10 @@ struct DepotWindow : Window {
|
||||
const Train *u = Train::From(v);
|
||||
free_wagon = u->IsFreeWagon();
|
||||
|
||||
uint x_space = free_wagon ? ScaleGUITrad(TRAININFO_DEFAULT_VEHICLE_WIDTH) : 0;
|
||||
uint x_space = free_wagon ?
|
||||
ScaleGUITrad(_consistent_train_width != 0 ? _consistent_train_width : TRAININFO_DEFAULT_VEHICLE_WIDTH) :
|
||||
0;
|
||||
|
||||
DrawTrainImage(u, image_left + (rtl ? 0 : x_space), image_right - (rtl ? x_space : 0), sprite_y - 1,
|
||||
this->sel, EIT_IN_DEPOT, free_wagon ? 0 : this->hscroll->GetPosition(), this->vehicle_over);
|
||||
|
||||
@@ -340,6 +372,29 @@ struct DepotWindow : Window {
|
||||
|
||||
/* Set the row and number of boxes in each row based on the number of boxes drawn in the matrix */
|
||||
const NWidgetCore *wid = this->GetWidget<NWidgetCore>(WID_D_MATRIX);
|
||||
|
||||
/* Draw vertical separators at whole tiles.
|
||||
* This only works in two cases:
|
||||
* - All vehicles use VEHICLEINFO_FULL_VEHICLE_WIDTH as reference width.
|
||||
* - All vehicles are 8/8. This cannot be checked for NewGRF, so instead we check for "all vehicles are original vehicles".
|
||||
*/
|
||||
if (this->type == VEH_TRAIN && _consistent_train_width != 0) {
|
||||
int w = ScaleGUITrad(2 * _consistent_train_width);
|
||||
int col = _colour_gradient[wid->colour][4];
|
||||
int image_left = rtl ? r.left + this->count_width : r.left + this->header_width;
|
||||
int image_right = rtl ? r.right - this->header_width : r.right - this->count_width;
|
||||
int first_line = w + (-this->hscroll->GetPosition()) % w;
|
||||
if (rtl) {
|
||||
for (int x = image_right - first_line; x >= image_left; x -= w) {
|
||||
GfxDrawLine(x, r.top, x, r.bottom, col, 1, 3);
|
||||
}
|
||||
} else {
|
||||
for (int x = image_left + first_line; x <= image_right; x += w) {
|
||||
GfxDrawLine(x, r.top, x, r.bottom, col, 1, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16 rows_in_display = wid->current_y / wid->resize_y;
|
||||
|
||||
uint16 num = this->vscroll->GetPosition() * this->num_columns;
|
||||
@@ -445,7 +500,8 @@ struct DepotWindow : Window {
|
||||
switch (this->type) {
|
||||
case VEH_TRAIN:
|
||||
if (wagon) return MODE_ERROR;
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
|
||||
case VEH_ROAD:
|
||||
if (xm <= this->flag_width) return MODE_START_STOP;
|
||||
break;
|
||||
@@ -679,7 +735,8 @@ struct DepotWindow : Window {
|
||||
}
|
||||
/* Always have 1 empty row, so people can change the setting of the train */
|
||||
this->vscroll->SetCount(this->vehicle_list.Length() + this->wagon_list.Length() + 1);
|
||||
this->hscroll->SetCount(max_width);
|
||||
/* Always make it longer than the longest train, so you can attach vehicles at the end, and also see the next vertical tile separator line */
|
||||
this->hscroll->SetCount(max_width + ScaleGUITrad(2 * VEHICLEINFO_FULL_VEHICLE_WIDTH + 1));
|
||||
} else {
|
||||
this->vscroll->SetCount(CeilDiv(this->vehicle_list.Length(), this->num_columns));
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ void DisasterVehicle::UpdateImage()
|
||||
{
|
||||
SpriteID img = this->image_override;
|
||||
if (img == 0) img = _disaster_images[this->subtype][this->direction];
|
||||
this->cur_image = img;
|
||||
this->sprite_seq.Set(img);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,7 +164,7 @@ DisasterVehicle::DisasterVehicle(int x, int y, Direction direction, DisasterSubT
|
||||
this->direction = direction;
|
||||
this->tile = TileVirtXY(x, y);
|
||||
this->subtype = subtype;
|
||||
this->UpdateDeltaXY(INVALID_DIR);
|
||||
this->UpdateDeltaXY();
|
||||
this->owner = OWNER_NONE;
|
||||
this->image_override = 0;
|
||||
this->current_order.Free();
|
||||
@@ -499,7 +499,8 @@ static bool DisasterTick_Helicopter_Rotors(DisasterVehicle *v)
|
||||
v->tick_counter++;
|
||||
if (HasBit(v->tick_counter, 0)) return true;
|
||||
|
||||
if (++v->cur_image > SPR_ROTOR_MOVING_3) v->cur_image = SPR_ROTOR_MOVING_1;
|
||||
SpriteID &cur_image = v->sprite_seq.seq[0].sprite;
|
||||
if (++cur_image > SPR_ROTOR_MOVING_3) cur_image = SPR_ROTOR_MOVING_1;
|
||||
|
||||
v->UpdatePositionAndViewport();
|
||||
|
||||
@@ -972,7 +973,7 @@ void ReleaseDisastersTargetingVehicle(VehicleID vehicle)
|
||||
}
|
||||
}
|
||||
|
||||
void DisasterVehicle::UpdateDeltaXY(Direction direction)
|
||||
void DisasterVehicle::UpdateDeltaXY()
|
||||
{
|
||||
this->x_offs = -1;
|
||||
this->y_offs = -1;
|
||||
|
||||
@@ -48,7 +48,7 @@ struct DisasterVehicle FINAL : public SpecializedVehicle<DisasterVehicle, VEH_DI
|
||||
virtual ~DisasterVehicle() {}
|
||||
|
||||
void UpdatePosition(int x, int y, int z);
|
||||
void UpdateDeltaXY(Direction direction);
|
||||
void UpdateDeltaXY();
|
||||
void UpdateImage();
|
||||
bool Tick();
|
||||
};
|
||||
|
||||
@@ -654,12 +654,16 @@ static void CompanyCheckBankrupt(Company *c)
|
||||
*/
|
||||
static void CompaniesGenStatistics()
|
||||
{
|
||||
Station *st;
|
||||
/* Check for bankruptcy each month */
|
||||
Company *c;
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
CompanyCheckBankrupt(c);
|
||||
}
|
||||
|
||||
Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
|
||||
Company *c;
|
||||
|
||||
if (!_settings_game.economy.infrastructure_maintenance) {
|
||||
Station *st;
|
||||
FOR_ALL_STATIONS(st) {
|
||||
cur_company.Change(st->owner);
|
||||
CommandCost cost(EXPENSES_PROPERTY, _price[PR_STATION_VALUE] >> 1);
|
||||
@@ -688,18 +692,14 @@ static void CompaniesGenStatistics()
|
||||
}
|
||||
cur_company.Restore();
|
||||
|
||||
/* Check for bankruptcy each month */
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
CompanyCheckBankrupt(c);
|
||||
}
|
||||
|
||||
/* Only run the economic statics and update company stats every 3rd month (1st of quarter). */
|
||||
if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month)) return;
|
||||
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
|
||||
/* Drop the oldest history off the end */
|
||||
std::copy_backward(c->old_economy, c->old_economy + MAX_HISTORY_QUARTERS - 1, c->old_economy + MAX_HISTORY_QUARTERS);
|
||||
c->old_economy[0] = c->cur_economy;
|
||||
memset(&c->cur_economy, 0, sizeof(c->cur_economy));
|
||||
c->cur_economy = {};
|
||||
|
||||
if (c->num_valid_stat_ent != MAX_HISTORY_QUARTERS) c->num_valid_stat_ent++;
|
||||
|
||||
@@ -1392,14 +1392,14 @@ struct IsEmptyAction
|
||||
struct PrepareRefitAction
|
||||
{
|
||||
CargoArray &consist_capleft; ///< Capacities left in the consist.
|
||||
uint32 &refit_mask; ///< Bitmask of possible refit cargoes.
|
||||
CargoTypes &refit_mask; ///< Bitmask of possible refit cargoes.
|
||||
|
||||
/**
|
||||
* Create a refit preparation action.
|
||||
* @param consist_capleft Capacities left in consist, to be updated here.
|
||||
* @param refit_mask Refit mask to be constructed from refit information of vehicles.
|
||||
*/
|
||||
PrepareRefitAction(CargoArray &consist_capleft, uint32 &refit_mask) :
|
||||
PrepareRefitAction(CargoArray &consist_capleft, CargoTypes &refit_mask) :
|
||||
consist_capleft(consist_capleft), refit_mask(refit_mask) {}
|
||||
|
||||
/**
|
||||
@@ -1497,7 +1497,7 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station
|
||||
|
||||
Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
|
||||
|
||||
uint32 refit_mask = v->GetEngine()->info.refit_mask;
|
||||
CargoTypes refit_mask = v->GetEngine()->info.refit_mask;
|
||||
|
||||
/* Remove old capacity from consist capacity and collect refit mask. */
|
||||
IterateVehicleParts(v_start, PrepareRefitAction(consist_capleft, refit_mask));
|
||||
@@ -1671,10 +1671,10 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
bool completely_emptied = true;
|
||||
bool anything_unloaded = false;
|
||||
bool anything_loaded = false;
|
||||
uint32 full_load_amount = 0;
|
||||
uint32 cargo_not_full = 0;
|
||||
uint32 cargo_full = 0;
|
||||
uint32 reservation_left = 0;
|
||||
CargoTypes full_load_amount = 0;
|
||||
CargoTypes cargo_not_full = 0;
|
||||
CargoTypes cargo_full = 0;
|
||||
CargoTypes reservation_left = 0;
|
||||
|
||||
front->cur_speed = 0;
|
||||
|
||||
@@ -1686,13 +1686,11 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
if (v->cargo_cap == 0) continue;
|
||||
artic_part++;
|
||||
|
||||
uint load_amount = GetLoadAmount(v);
|
||||
|
||||
GoodsEntry *ge = &st->goods[v->cargo_type];
|
||||
|
||||
if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) && (GetUnloadType(v) & OUFB_NO_UNLOAD) == 0) {
|
||||
uint cargo_count = v->cargo.UnloadCount();
|
||||
uint amount_unloaded = _settings_game.order.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
|
||||
uint amount_unloaded = _settings_game.order.gradual_loading ? min(cargo_count, GetLoadAmount(v)) : cargo_count;
|
||||
bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
|
||||
|
||||
assert(payment != NULL);
|
||||
@@ -1771,7 +1769,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
/* update stats */
|
||||
int t;
|
||||
switch (front->type) {
|
||||
case VEH_TRAIN: /* FALL THROUGH */
|
||||
case VEH_TRAIN:
|
||||
case VEH_SHIP:
|
||||
t = front->vcache.cached_max_speed;
|
||||
break;
|
||||
@@ -1797,8 +1795,8 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
* has capacity for it, load it on the vehicle. */
|
||||
uint cap_left = v->cargo_cap - v->cargo.StoredCount();
|
||||
if (cap_left > 0 && (v->cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0 || ge->cargo.AvailableCount() > 0)) {
|
||||
if (_settings_game.order.gradual_loading) cap_left = min(cap_left, load_amount);
|
||||
if (v->cargo.StoredCount() == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
|
||||
if (_settings_game.order.gradual_loading) cap_left = min(cap_left, GetLoadAmount(v));
|
||||
|
||||
uint loaded = ge->cargo.Load(cap_left, &v->cargo, st->xy, next_station.Get(v->cargo_type));
|
||||
if (v->cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0) {
|
||||
@@ -1894,7 +1892,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||
/* if the aircraft carries passengers and is NOT full, then
|
||||
* continue loading, no matter how much mail is in */
|
||||
if ((front->type == VEH_AIRCRAFT && IsCargoInClass(front->cargo_type, CC_PASSENGERS) && front->cargo_cap > front->cargo.StoredCount()) ||
|
||||
(cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are still non-full cargoes
|
||||
(cargo_not_full != 0 && (cargo_full & ~cargo_not_full) == 0)) { // There are still non-full cargoes
|
||||
finished_loading = false;
|
||||
}
|
||||
} else if (cargo_not_full != 0) {
|
||||
|
||||
@@ -152,12 +152,12 @@ enum ExpensesType {
|
||||
EXPENSES_NEW_VEHICLES, ///< New vehicles.
|
||||
EXPENSES_TRAIN_RUN, ///< Running costs trains.
|
||||
EXPENSES_ROADVEH_RUN, ///< Running costs road vehicles.
|
||||
EXPENSES_AIRCRAFT_RUN, ///< Running costs aircrafts.
|
||||
EXPENSES_AIRCRAFT_RUN, ///< Running costs aircraft.
|
||||
EXPENSES_SHIP_RUN, ///< Running costs ships.
|
||||
EXPENSES_PROPERTY, ///< Property costs.
|
||||
EXPENSES_TRAIN_INC, ///< Income from trains.
|
||||
EXPENSES_ROADVEH_INC, ///< Income from road vehicles.
|
||||
EXPENSES_AIRCRAFT_INC, ///< Income from aircrafts.
|
||||
EXPENSES_AIRCRAFT_INC, ///< Income from aircraft.
|
||||
EXPENSES_SHIP_INC, ///< Income from ships.
|
||||
EXPENSES_LOAN_INT, ///< Interest payments over the loan.
|
||||
EXPENSES_OTHER, ///< Other expenses.
|
||||
|
||||
@@ -22,10 +22,26 @@
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
/**
|
||||
* Increment the sprite unless it has reached the end of the animation.
|
||||
* @param v Vehicle to increment sprite of.
|
||||
* @param last Last sprite of animation.
|
||||
* @return true if the sprite was incremented, false if the end was reached.
|
||||
*/
|
||||
static bool IncrementSprite(EffectVehicle *v, SpriteID last)
|
||||
{
|
||||
if (v->sprite_seq.seq[0].sprite != last) {
|
||||
v->sprite_seq.seq[0].sprite++;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void ChimneySmokeInit(EffectVehicle *v)
|
||||
{
|
||||
uint32 r = Random();
|
||||
v->cur_image = SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3);
|
||||
v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3));
|
||||
v->progress = GB(r, 16, 3);
|
||||
}
|
||||
|
||||
@@ -40,10 +56,8 @@ static bool ChimneySmokeTick(EffectVehicle *v)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (v->cur_image != SPR_CHIMNEY_SMOKE_7) {
|
||||
v->cur_image++;
|
||||
} else {
|
||||
v->cur_image = SPR_CHIMNEY_SMOKE_0;
|
||||
if (!IncrementSprite(v, SPR_CHIMNEY_SMOKE_7)) {
|
||||
v->sprite_seq.Set(SPR_CHIMNEY_SMOKE_0);
|
||||
}
|
||||
v->progress = 7;
|
||||
v->UpdatePositionAndViewport();
|
||||
@@ -54,7 +68,7 @@ static bool ChimneySmokeTick(EffectVehicle *v)
|
||||
|
||||
static void SteamSmokeInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_STEAM_SMOKE_0;
|
||||
v->sprite_seq.Set(SPR_STEAM_SMOKE_0);
|
||||
v->progress = 12;
|
||||
}
|
||||
|
||||
@@ -70,9 +84,7 @@ static bool SteamSmokeTick(EffectVehicle *v)
|
||||
}
|
||||
|
||||
if ((v->progress & 0xF) == 4) {
|
||||
if (v->cur_image != SPR_STEAM_SMOKE_4) {
|
||||
v->cur_image++;
|
||||
} else {
|
||||
if (!IncrementSprite(v, SPR_STEAM_SMOKE_4)) {
|
||||
delete v;
|
||||
return false;
|
||||
}
|
||||
@@ -86,7 +98,7 @@ static bool SteamSmokeTick(EffectVehicle *v)
|
||||
|
||||
static void DieselSmokeInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_DIESEL_SMOKE_0;
|
||||
v->sprite_seq.Set(SPR_DIESEL_SMOKE_0);
|
||||
v->progress = 0;
|
||||
}
|
||||
|
||||
@@ -98,13 +110,11 @@ static bool DieselSmokeTick(EffectVehicle *v)
|
||||
v->z_pos++;
|
||||
v->UpdatePositionAndViewport();
|
||||
} else if ((v->progress & 7) == 1) {
|
||||
if (v->cur_image != SPR_DIESEL_SMOKE_5) {
|
||||
v->cur_image++;
|
||||
v->UpdatePositionAndViewport();
|
||||
} else {
|
||||
if (!IncrementSprite(v, SPR_DIESEL_SMOKE_5)) {
|
||||
delete v;
|
||||
return false;
|
||||
}
|
||||
v->UpdatePositionAndViewport();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -112,7 +122,7 @@ static bool DieselSmokeTick(EffectVehicle *v)
|
||||
|
||||
static void ElectricSparkInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_ELECTRIC_SPARK_0;
|
||||
v->sprite_seq.Set(SPR_ELECTRIC_SPARK_0);
|
||||
v->progress = 1;
|
||||
}
|
||||
|
||||
@@ -122,13 +132,12 @@ static bool ElectricSparkTick(EffectVehicle *v)
|
||||
v->progress++;
|
||||
} else {
|
||||
v->progress = 0;
|
||||
if (v->cur_image != SPR_ELECTRIC_SPARK_5) {
|
||||
v->cur_image++;
|
||||
v->UpdatePositionAndViewport();
|
||||
} else {
|
||||
|
||||
if (!IncrementSprite(v, SPR_ELECTRIC_SPARK_5)) {
|
||||
delete v;
|
||||
return false;
|
||||
}
|
||||
v->UpdatePositionAndViewport();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -136,7 +145,7 @@ static bool ElectricSparkTick(EffectVehicle *v)
|
||||
|
||||
static void SmokeInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_SMOKE_0;
|
||||
v->sprite_seq.Set(SPR_SMOKE_0);
|
||||
v->progress = 12;
|
||||
}
|
||||
|
||||
@@ -152,9 +161,7 @@ static bool SmokeTick(EffectVehicle *v)
|
||||
}
|
||||
|
||||
if ((v->progress & 0xF) == 4) {
|
||||
if (v->cur_image != SPR_SMOKE_4) {
|
||||
v->cur_image++;
|
||||
} else {
|
||||
if (!IncrementSprite(v, SPR_SMOKE_4)) {
|
||||
delete v;
|
||||
return false;
|
||||
}
|
||||
@@ -168,7 +175,7 @@ static bool SmokeTick(EffectVehicle *v)
|
||||
|
||||
static void ExplosionLargeInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_EXPLOSION_LARGE_0;
|
||||
v->sprite_seq.Set(SPR_EXPLOSION_LARGE_0);
|
||||
v->progress = 0;
|
||||
}
|
||||
|
||||
@@ -176,13 +183,11 @@ static bool ExplosionLargeTick(EffectVehicle *v)
|
||||
{
|
||||
v->progress++;
|
||||
if ((v->progress & 3) == 0) {
|
||||
if (v->cur_image != SPR_EXPLOSION_LARGE_F) {
|
||||
v->cur_image++;
|
||||
v->UpdatePositionAndViewport();
|
||||
} else {
|
||||
if (!IncrementSprite(v, SPR_EXPLOSION_LARGE_F)) {
|
||||
delete v;
|
||||
return false;
|
||||
}
|
||||
v->UpdatePositionAndViewport();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -190,7 +195,7 @@ static bool ExplosionLargeTick(EffectVehicle *v)
|
||||
|
||||
static void BreakdownSmokeInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_BREAKDOWN_SMOKE_0;
|
||||
v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
|
||||
v->progress = 0;
|
||||
}
|
||||
|
||||
@@ -198,10 +203,8 @@ static bool BreakdownSmokeTick(EffectVehicle *v)
|
||||
{
|
||||
v->progress++;
|
||||
if ((v->progress & 7) == 0) {
|
||||
if (v->cur_image != SPR_BREAKDOWN_SMOKE_3) {
|
||||
v->cur_image++;
|
||||
} else {
|
||||
v->cur_image = SPR_BREAKDOWN_SMOKE_0;
|
||||
if (!IncrementSprite(v, SPR_BREAKDOWN_SMOKE_3)) {
|
||||
v->sprite_seq.Set(SPR_BREAKDOWN_SMOKE_0);
|
||||
}
|
||||
v->UpdatePositionAndViewport();
|
||||
}
|
||||
@@ -217,7 +220,7 @@ static bool BreakdownSmokeTick(EffectVehicle *v)
|
||||
|
||||
static void ExplosionSmallInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_EXPLOSION_SMALL_0;
|
||||
v->sprite_seq.Set(SPR_EXPLOSION_SMALL_0);
|
||||
v->progress = 0;
|
||||
}
|
||||
|
||||
@@ -225,13 +228,11 @@ static bool ExplosionSmallTick(EffectVehicle *v)
|
||||
{
|
||||
v->progress++;
|
||||
if ((v->progress & 3) == 0) {
|
||||
if (v->cur_image != SPR_EXPLOSION_SMALL_B) {
|
||||
v->cur_image++;
|
||||
v->UpdatePositionAndViewport();
|
||||
} else {
|
||||
if (!IncrementSprite(v, SPR_EXPLOSION_SMALL_B)) {
|
||||
delete v;
|
||||
return false;
|
||||
}
|
||||
v->UpdatePositionAndViewport();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -239,7 +240,7 @@ static bool ExplosionSmallTick(EffectVehicle *v)
|
||||
|
||||
static void BulldozerInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_BULLDOZER_NE;
|
||||
v->sprite_seq.Set(SPR_BULLDOZER_NE);
|
||||
v->progress = 0;
|
||||
v->animation_state = 0;
|
||||
v->animation_substate = 0;
|
||||
@@ -290,7 +291,7 @@ static bool BulldozerTick(EffectVehicle *v)
|
||||
if ((v->progress & 7) == 0) {
|
||||
const BulldozerMovement *b = &_bulldozer_movement[v->animation_state];
|
||||
|
||||
v->cur_image = SPR_BULLDOZER_NE + b->image;
|
||||
v->sprite_seq.Set(SPR_BULLDOZER_NE + b->image);
|
||||
|
||||
v->x_pos += _inc_by_dir[b->direction].x;
|
||||
v->y_pos += _inc_by_dir[b->direction].y;
|
||||
@@ -312,7 +313,7 @@ static bool BulldozerTick(EffectVehicle *v)
|
||||
|
||||
static void BubbleInit(EffectVehicle *v)
|
||||
{
|
||||
v->cur_image = SPR_BUBBLE_GENERATE_0;
|
||||
v->sprite_seq.Set(SPR_BUBBLE_GENERATE_0);
|
||||
v->spritenum = 0;
|
||||
v->progress = 0;
|
||||
}
|
||||
@@ -475,8 +476,8 @@ static bool BubbleTick(EffectVehicle *v)
|
||||
if ((v->progress & 3) != 0) return true;
|
||||
|
||||
if (v->spritenum == 0) {
|
||||
v->cur_image++;
|
||||
if (v->cur_image < SPR_BUBBLE_GENERATE_3) {
|
||||
v->sprite_seq.seq[0].sprite++;
|
||||
if (v->sprite_seq.seq[0].sprite < SPR_BUBBLE_GENERATE_3) {
|
||||
v->UpdatePositionAndViewport();
|
||||
return true;
|
||||
}
|
||||
@@ -521,7 +522,7 @@ static bool BubbleTick(EffectVehicle *v)
|
||||
v->x_pos += b->x;
|
||||
v->y_pos += b->y;
|
||||
v->z_pos += b->z;
|
||||
v->cur_image = SPR_BUBBLE_0 + b->image;
|
||||
v->sprite_seq.Set(SPR_BUBBLE_0 + b->image);
|
||||
|
||||
v->UpdatePositionAndViewport();
|
||||
|
||||
@@ -602,7 +603,7 @@ EffectVehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicleType type)
|
||||
v->y_pos = y;
|
||||
v->z_pos = z;
|
||||
v->tile = 0;
|
||||
v->UpdateDeltaXY(INVALID_DIR);
|
||||
v->UpdateDeltaXY();
|
||||
v->vehstatus = VS_UNCLICKABLE;
|
||||
|
||||
_effect_init_procs[type](v);
|
||||
@@ -646,7 +647,7 @@ bool EffectVehicle::Tick()
|
||||
return _effect_tick_procs[this->subtype](this);
|
||||
}
|
||||
|
||||
void EffectVehicle::UpdateDeltaXY(Direction direction)
|
||||
void EffectVehicle::UpdateDeltaXY()
|
||||
{
|
||||
this->x_offs = 0;
|
||||
this->y_offs = 0;
|
||||
|
||||
@@ -32,7 +32,7 @@ struct EffectVehicle FINAL : public SpecializedVehicle<EffectVehicle, VEH_EFFECT
|
||||
/** We want to 'destruct' the right class. */
|
||||
virtual ~EffectVehicle() {}
|
||||
|
||||
void UpdateDeltaXY(Direction direction);
|
||||
void UpdateDeltaXY();
|
||||
bool Tick();
|
||||
TransparencyOption GetTransparencyOption() const;
|
||||
};
|
||||
|
||||
@@ -89,7 +89,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
|
||||
{
|
||||
switch (GetTileType(t)) {
|
||||
case MP_RAILWAY:
|
||||
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
switch (GetRailTileType(t)) {
|
||||
case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
|
||||
return GetTrackBits(t);
|
||||
@@ -99,7 +99,8 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
|
||||
break;
|
||||
|
||||
case MP_TUNNELBRIDGE:
|
||||
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) return TRACK_BIT_NONE;
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
if (override != NULL && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) {
|
||||
*override = 1 << GetTunnelBridgeDirection(t);
|
||||
}
|
||||
@@ -107,12 +108,12 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
|
||||
|
||||
case MP_ROAD:
|
||||
if (!IsLevelCrossing(t)) return TRACK_BIT_NONE;
|
||||
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
return GetCrossingRailBits(t);
|
||||
|
||||
case MP_STATION:
|
||||
if (!HasStationRail(t)) return TRACK_BIT_NONE;
|
||||
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE;
|
||||
return TrackToTrackBits(GetRailStationTrack(t));
|
||||
|
||||
default:
|
||||
@@ -135,7 +136,7 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
|
||||
* axis that still display wires to preserve visual continuity. */
|
||||
TileIndex next_tile = TileAddByDiagDir(t, d);
|
||||
RailType rt = GetTileRailType(next_tile);
|
||||
if (rt == INVALID_RAILTYPE || !HasCatenary(rt) ||
|
||||
if (rt == INVALID_RAILTYPE || !HasRailCatenary(rt) ||
|
||||
((TrackStatusToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, 0)) & DiagdirReachesTracks(d)) == TRACK_BIT_NONE &&
|
||||
(!HasStationTileRail(next_tile) || GetRailStationAxis(next_tile) != DiagDirToAxis(d) || !CanStationTileHaveWires(next_tile)))) {
|
||||
neighbour_tdb |= DiagdirReachesTrackdirs(ReverseDiagDir(d));
|
||||
@@ -241,7 +242,7 @@ static int GetPCPElevation(TileIndex tile, DiagDirection PCPpos)
|
||||
*
|
||||
* @param ti The Tileinfo to draw the tile for
|
||||
*/
|
||||
void DrawCatenaryOnTunnel(const TileInfo *ti)
|
||||
void DrawRailCatenaryOnTunnel(const TileInfo *ti)
|
||||
{
|
||||
/* xmin, ymin, xmax + 1, ymax + 1 of BB */
|
||||
static const int _tunnel_wire_BB[4][4] = {
|
||||
@@ -255,7 +256,7 @@ void DrawCatenaryOnTunnel(const TileInfo *ti)
|
||||
|
||||
SpriteID wire_base = GetWireBase(ti->tile);
|
||||
|
||||
const SortableSpriteStruct *sss = &CatenarySpriteData_Tunnel[dir];
|
||||
const SortableSpriteStruct *sss = &RailCatenarySpriteData_Tunnel[dir];
|
||||
const int *BB_data = _tunnel_wire_BB[dir];
|
||||
AddSortableSpriteToDraw(
|
||||
wire_base + sss->image_offset, PAL_NONE, ti->x + sss->x_offset, ti->y + sss->y_offset,
|
||||
@@ -270,7 +271,7 @@ void DrawCatenaryOnTunnel(const TileInfo *ti)
|
||||
* Draws wires and, if required, pylons on a given tile
|
||||
* @param ti The Tileinfo to draw the tile for
|
||||
*/
|
||||
static void DrawCatenaryRailway(const TileInfo *ti)
|
||||
static void DrawRailCatenaryRailway(const TileInfo *ti)
|
||||
{
|
||||
/* Pylons are placed on a tile edge, so we need to take into account
|
||||
* the track configuration of 2 adjacent tiles. trackconfig[0] stores the
|
||||
@@ -379,7 +380,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
|
||||
if (IsTileType(neighbour, MP_STATION) || IsTileType(neighbour, MP_ROAD)) tileh[TS_NEIGHBOUR] = SLOPE_FLAT;
|
||||
|
||||
/* Read the foundations if they are present, and adjust the tileh */
|
||||
if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && HasCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
|
||||
if (trackconfig[TS_NEIGHBOUR] != TRACK_BIT_NONE && IsTileType(neighbour, MP_RAILWAY) && HasRailCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TS_NEIGHBOUR], trackconfig[TS_NEIGHBOUR]);
|
||||
if (IsBridgeTile(neighbour)) {
|
||||
foundation = GetBridgeFoundation(tileh[TS_NEIGHBOUR], DiagDirToAxis(GetTunnelBridgeDirection(neighbour)));
|
||||
}
|
||||
@@ -442,7 +443,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
|
||||
}
|
||||
}
|
||||
|
||||
/* The wire above the tunnel is drawn together with the tunnel-roof (see DrawCatenaryOnTunnel()) */
|
||||
/* The wire above the tunnel is drawn together with the tunnel-roof (see DrawRailCatenaryOnTunnel()) */
|
||||
if (IsTunnelTile(ti->tile)) return;
|
||||
|
||||
/* Don't draw a wire under a low bridge */
|
||||
@@ -478,7 +479,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
|
||||
|
||||
assert(PCPconfig != 0); // We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that)
|
||||
assert(!IsSteepSlope(tileh[TS_HOME]));
|
||||
sss = &CatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
|
||||
sss = &RailCatenarySpriteData[Wires[tileh_selector][t][PCPconfig]];
|
||||
|
||||
/*
|
||||
* The "wire"-sprite position is inside the tile, i.e. 0 <= sss->?_offset < TILE_SIZE.
|
||||
@@ -498,7 +499,7 @@ static void DrawCatenaryRailway(const TileInfo *ti)
|
||||
*
|
||||
* @param ti The Tileinfo to draw the tile for
|
||||
*/
|
||||
void DrawCatenaryOnBridge(const TileInfo *ti)
|
||||
void DrawRailCatenaryOnBridge(const TileInfo *ti)
|
||||
{
|
||||
TileIndex end = GetSouthernBridgeEnd(ti->tile);
|
||||
TileIndex start = GetOtherBridgeEnd(end);
|
||||
@@ -511,15 +512,15 @@ void DrawCatenaryOnBridge(const TileInfo *ti)
|
||||
Axis axis = GetBridgeAxis(ti->tile);
|
||||
TLG tlg = GetTLG(ti->tile);
|
||||
|
||||
CatenarySprite offset = (CatenarySprite)(axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH);
|
||||
RailCatenarySprite offset = (RailCatenarySprite)(axis == AXIS_X ? 0 : WIRE_Y_FLAT_BOTH - WIRE_X_FLAT_BOTH);
|
||||
|
||||
if ((length % 2) && num == length) {
|
||||
/* Draw the "short" wire on the southern end of the bridge
|
||||
* only needed if the length of the bridge is odd */
|
||||
sss = &CatenarySpriteData[WIRE_X_FLAT_BOTH + offset];
|
||||
sss = &RailCatenarySpriteData[WIRE_X_FLAT_BOTH + offset];
|
||||
} else {
|
||||
/* Draw "long" wires on all other tiles of the bridge (one pylon every two tiles) */
|
||||
sss = &CatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset];
|
||||
sss = &RailCatenarySpriteData[WIRE_X_FLAT_SW + (num % 2) + offset];
|
||||
}
|
||||
|
||||
height = GetBridgePixelHeight(end);
|
||||
@@ -558,14 +559,14 @@ void DrawCatenaryOnBridge(const TileInfo *ti)
|
||||
/**
|
||||
* Draws overhead wires and pylons for electric railways.
|
||||
* @param ti The TileInfo struct of the tile being drawn
|
||||
* @see DrawCatenaryRailway
|
||||
* @see DrawRailCatenaryRailway
|
||||
*/
|
||||
void DrawCatenary(const TileInfo *ti)
|
||||
void DrawRailCatenary(const TileInfo *ti)
|
||||
{
|
||||
switch (GetTileType(ti->tile)) {
|
||||
case MP_RAILWAY:
|
||||
if (IsRailDepot(ti->tile)) {
|
||||
const SortableSpriteStruct *sss = &CatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
|
||||
const SortableSpriteStruct *sss = &RailCatenarySpriteData_Depot[GetRailDepotDirection(ti->tile)];
|
||||
|
||||
SpriteID wire_base = GetWireBase(ti->tile);
|
||||
|
||||
@@ -587,7 +588,7 @@ void DrawCatenary(const TileInfo *ti)
|
||||
|
||||
default: return;
|
||||
}
|
||||
DrawCatenaryRailway(ti);
|
||||
DrawRailCatenaryRailway(ti);
|
||||
}
|
||||
|
||||
bool SettingsDisableElrail(int32 p1)
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
* Test if a rail type has catenary
|
||||
* @param rt Rail type to test
|
||||
*/
|
||||
static inline bool HasCatenary(RailType rt)
|
||||
static inline bool HasRailCatenary(RailType rt)
|
||||
{
|
||||
return HasBit(GetRailTypeInfo(rt)->flags, RTF_CATENARY);
|
||||
}
|
||||
@@ -29,14 +29,14 @@ static inline bool HasCatenary(RailType rt)
|
||||
* Test if we should draw rail catenary
|
||||
* @param rt Rail type to test
|
||||
*/
|
||||
static inline bool HasCatenaryDrawn(RailType rt)
|
||||
static inline bool HasRailCatenaryDrawn(RailType rt)
|
||||
{
|
||||
return HasCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_settings_game.vehicle.disable_elrails;
|
||||
return HasRailCatenary(rt) && !IsInvisibilitySet(TO_CATENARY) && !_settings_game.vehicle.disable_elrails;
|
||||
}
|
||||
|
||||
void DrawCatenary(const TileInfo *ti);
|
||||
void DrawCatenaryOnTunnel(const TileInfo *ti);
|
||||
void DrawCatenaryOnBridge(const TileInfo *ti);
|
||||
void DrawRailCatenary(const TileInfo *ti);
|
||||
void DrawRailCatenaryOnTunnel(const TileInfo *ti);
|
||||
void DrawRailCatenaryOnBridge(const TileInfo *ti);
|
||||
|
||||
bool SettingsDisableElrail(int32 p1); ///< _settings_game.disable_elrail callback
|
||||
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* 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 endian_check.cpp
|
||||
* This pretty simple file checks if the system is LITTLE_ENDIAN or BIG_ENDIAN
|
||||
* it does that by putting a 1 and a 0 in an array, and read it out as one
|
||||
* number. If it is 1, it is LITTLE_ENDIAN, if it is 256, it is BIG_ENDIAN
|
||||
*
|
||||
* After that it outputs the contents of an include files (endian.h)
|
||||
* that says or TTD_LITTLE_ENDIAN, or TTD_BIG_ENDIAN. Makefile takes
|
||||
* care of the real writing to the file.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/** Supported endian types */
|
||||
enum Endian {
|
||||
ENDIAN_LITTLE, ///< little endian
|
||||
ENDIAN_BIG, ///< big endian
|
||||
};
|
||||
|
||||
/**
|
||||
* Shortcut to printf("#define TTD_ENDIAN TTD_*_ENDIAN")
|
||||
* @param endian endian type to define
|
||||
*/
|
||||
static inline void printf_endian(Endian endian)
|
||||
{
|
||||
printf("#define TTD_ENDIAN %s\n", endian == ENDIAN_LITTLE ? "TTD_LITTLE_ENDIAN" : "TTD_BIG_ENDIAN");
|
||||
}
|
||||
|
||||
/**
|
||||
* Main call of the endian_check program
|
||||
* @param argc argument count
|
||||
* @param argv arguments themselves
|
||||
* @return exit code
|
||||
*/
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
unsigned char endian_test[2] = { 1, 0 };
|
||||
int force_BE = 0, force_LE = 0, force_PREPROCESSOR = 0;
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "BE") == 0) force_BE = 1;
|
||||
if (argc > 1 && strcmp(argv[1], "LE") == 0) force_LE = 1;
|
||||
if (argc > 1 && strcmp(argv[1], "PREPROCESSOR") == 0) force_PREPROCESSOR = 1;
|
||||
|
||||
printf("#ifndef ENDIAN_H\n#define ENDIAN_H\n");
|
||||
|
||||
if (force_LE == 1) {
|
||||
printf_endian(ENDIAN_LITTLE);
|
||||
} else if (force_BE == 1) {
|
||||
printf_endian(ENDIAN_BIG);
|
||||
} else if (force_PREPROCESSOR == 1) {
|
||||
/* Support for universal binaries on OSX
|
||||
* Universal binaries supports both PPC and x86
|
||||
* If a compiler for OSX gets this setting, it will always pick the correct endian and no test is needed
|
||||
*/
|
||||
printf("#ifdef __BIG_ENDIAN__\n");
|
||||
printf_endian(ENDIAN_BIG);
|
||||
printf("#else\n");
|
||||
printf_endian(ENDIAN_LITTLE);
|
||||
printf("#endif\n");
|
||||
} else if (*(short*)endian_test == 1 ) {
|
||||
printf_endian(ENDIAN_LITTLE);
|
||||
} else {
|
||||
printf_endian(ENDIAN_BIG);
|
||||
}
|
||||
printf("#endif\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -48,11 +48,6 @@ EngineOverrideManager _engine_mngr;
|
||||
*/
|
||||
static Year _year_engine_aging_stops;
|
||||
|
||||
/**
|
||||
* The railtypes that have been or never will be introduced, or
|
||||
* an inverse bitmap of rail types that have to be introduced. */
|
||||
static uint16 _introduced_railtypes;
|
||||
|
||||
/** Number of engines of each vehicle type in original engine data */
|
||||
const uint8 _engine_counts[4] = {
|
||||
lengthof(_orig_rail_vehicle_info),
|
||||
@@ -469,7 +464,26 @@ uint16 Engine::GetRange() const
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the EngineOverrideManager with the default engines.
|
||||
* Get the name of the aircraft type for display purposes.
|
||||
* @return Aircraft type string.
|
||||
*/
|
||||
StringID Engine::GetAircraftTypeText() const
|
||||
{
|
||||
switch (this->type) {
|
||||
case VEH_AIRCRAFT:
|
||||
switch (this->u.air.subtype) {
|
||||
case AIR_HELI: return STR_LIVERY_HELICOPTER;
|
||||
case AIR_CTOL: return STR_LIVERY_SMALL_PLANE;
|
||||
case AIR_CTOL | AIR_FAST: return STR_LIVERY_LARGE_PLANE;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the #EngineOverrideManager with the default engines.
|
||||
*/
|
||||
void EngineOverrideManager::ResetToDefaultMapping()
|
||||
{
|
||||
@@ -543,29 +557,6 @@ void SetupEngines()
|
||||
const Engine *e = new Engine(eid->type, eid->internal_id);
|
||||
assert(e->index == index);
|
||||
}
|
||||
|
||||
_introduced_railtypes = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the railtypes should be introduced.
|
||||
*/
|
||||
static void CheckRailIntroduction()
|
||||
{
|
||||
/* All railtypes have been introduced. */
|
||||
if (_introduced_railtypes == UINT16_MAX || Company::GetPoolSize() == 0) return;
|
||||
|
||||
/* We need to find the railtypes that are known to all companies. */
|
||||
RailTypes rts = (RailTypes)UINT16_MAX;
|
||||
|
||||
/* We are at, or past the introduction date of the rail. */
|
||||
Company *c;
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, _date);
|
||||
rts &= c->avail_railtypes;
|
||||
}
|
||||
|
||||
_introduced_railtypes |= rts;
|
||||
}
|
||||
|
||||
void ShowEnginePreviewWindow(EngineID engine);
|
||||
@@ -711,19 +702,6 @@ void StartupEngines()
|
||||
c->avail_roadtypes = GetCompanyRoadtypes(c->index);
|
||||
}
|
||||
|
||||
/* Rail types that are invalid or never introduced are marked as
|
||||
* being introduced upon start. That way we can easily check whether
|
||||
* there is any date related introduction that is still going to
|
||||
* happen somewhere in the future. */
|
||||
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
|
||||
const RailtypeInfo *rti = GetRailTypeInfo(rt);
|
||||
if (rti->label != 0 && IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue;
|
||||
|
||||
SetBit(_introduced_railtypes, rt);
|
||||
}
|
||||
|
||||
CheckRailIntroduction();
|
||||
|
||||
/* Invalidate any open purchase lists */
|
||||
InvalidateWindowClassesData(WC_BUILD_VEHICLE);
|
||||
}
|
||||
@@ -774,7 +752,7 @@ static CompanyID GetPreviewCompany(Engine *e)
|
||||
CompanyID best_company = INVALID_COMPANY;
|
||||
|
||||
/* For trains the cargomask has no useful meaning, since you can attach other wagons */
|
||||
uint32 cargomask = e->type != VEH_TRAIN ? GetUnionOfArticulatedRefitMasks(e->index, true) : (uint32)-1;
|
||||
CargoTypes cargomask = e->type != VEH_TRAIN ? GetUnionOfArticulatedRefitMasks(e->index, true) : ALL_CARGOTYPES;
|
||||
|
||||
int32 best_hist = -1;
|
||||
const Company *c;
|
||||
@@ -820,7 +798,10 @@ static bool IsVehicleTypeDisabled(VehicleType type, bool ai)
|
||||
/** Daily check to offer an exclusive engine preview to the companies. */
|
||||
void EnginesDailyLoop()
|
||||
{
|
||||
CheckRailIntroduction();
|
||||
Company *c;
|
||||
FOR_ALL_COMPANIES(c) {
|
||||
c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, _date);
|
||||
}
|
||||
|
||||
if (_cur_year >= _year_engine_aging_stops) return;
|
||||
|
||||
@@ -1136,7 +1117,9 @@ bool IsEngineRefittable(EngineID engine)
|
||||
|
||||
/* Is there any cargo except the default cargo? */
|
||||
CargoID default_cargo = e->GetDefaultCargoType();
|
||||
return default_cargo != CT_INVALID && ei->refit_mask != 1U << default_cargo;
|
||||
CargoTypes default_cargo_mask = 0;
|
||||
SetBit(default_cargo_mask, default_cargo);
|
||||
return default_cargo != CT_INVALID && ei->refit_mask != default_cargo_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -111,6 +111,7 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> {
|
||||
uint GetDisplayMaxTractiveEffort() const;
|
||||
Date GetLifeLengthInDays() const;
|
||||
uint16 GetRange() const;
|
||||
StringID GetAircraftTypeText() const;
|
||||
|
||||
/**
|
||||
* Check whether the engine is hidden in the GUI for the given company.
|
||||
|
||||
@@ -26,7 +26,7 @@ extern const uint8 _engine_offsets[4];
|
||||
|
||||
bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company);
|
||||
bool IsEngineRefittable(EngineID engine);
|
||||
void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, uint32 *refits);
|
||||
void GetArticulatedVehicleCargoesAndRefits(EngineID engine, CargoArray *cargoes, CargoTypes *refits);
|
||||
void SetYearEngineAgingStops();
|
||||
void StartupOneEngine(Engine *e, Date aging_date);
|
||||
|
||||
|
||||
@@ -126,9 +126,9 @@ struct EnginePreviewWindow : Window {
|
||||
switch (widget) {
|
||||
case WID_EP_YES:
|
||||
DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW);
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
case WID_EP_NO:
|
||||
delete this;
|
||||
if (!_shift_pressed) delete this;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -196,6 +196,7 @@ static StringID GetAircraftEngineInfoString(const Engine *e)
|
||||
uint i = 0;
|
||||
SetDParam(i++, e->GetCost());
|
||||
SetDParam(i++, e->GetDisplayMaxSpeed());
|
||||
SetDParam(i++, e->GetAircraftTypeText());
|
||||
if (range > 0) SetDParam(i++, range);
|
||||
SetDParam(i++, cargo);
|
||||
SetDParam(i++, capacity);
|
||||
@@ -204,10 +205,10 @@ static StringID GetAircraftEngineInfoString(const Engine *e)
|
||||
SetDParam(i++, CT_MAIL);
|
||||
SetDParam(i++, mail_capacity);
|
||||
SetDParam(i++, e->GetRunningCost());
|
||||
return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_RANGE_CAPACITY_CAPACITY_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_CAPACITY_RUNCOST;
|
||||
return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST;
|
||||
} else {
|
||||
SetDParam(i++, e->GetRunningCost());
|
||||
return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_RANGE_CAPACITY_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
|
||||
return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +225,7 @@ static StringID GetRoadVehEngineInfoString(const Engine *e)
|
||||
SetDParam(2, CT_INVALID);
|
||||
}
|
||||
SetDParam(4, e->GetRunningCost());
|
||||
return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
|
||||
return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST;
|
||||
} else {
|
||||
SetDParam(0, e->GetCost());
|
||||
SetDParam(2, e->GetDisplayMaxSpeed());
|
||||
@@ -252,7 +253,7 @@ static StringID GetShipEngineInfoString(const Engine *e)
|
||||
SetDParam(2, e->GetDefaultCargoType());
|
||||
SetDParam(3, e->GetDisplayDefaultCapacity());
|
||||
SetDParam(4, e->GetRunningCost());
|
||||
return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
|
||||
return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ struct EngineInfo {
|
||||
byte load_amount;
|
||||
byte climates; ///< Climates supported by the engine.
|
||||
CargoID cargo_type;
|
||||
uint32 refit_mask;
|
||||
CargoTypes refit_mask;
|
||||
byte refit_cost;
|
||||
byte misc_flags; ///< Miscellaneous flags. @see EngineMiscFlags
|
||||
byte callback_mask; ///< Bitmask of vehicle callbacks that have to be called
|
||||
@@ -158,6 +158,7 @@ enum EngineMiscFlags {
|
||||
EF_AUTO_REFIT = 4, ///< Automatic refitting is allowed
|
||||
EF_NO_DEFAULT_CARGO_MULTIPLIER = 5, ///< Use the new capacity algorithm. The default cargotype of the vehicle does not affect capacity multipliers. CB 15 is also called in purchase list.
|
||||
EF_NO_BREAKDOWN_SMOKE = 6, ///< Do not show black smoke during a breakdown.
|
||||
EF_SPRITE_STACK = 7, ///< Draw vehicle by stacking multiple sprites.
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -325,15 +325,7 @@ bool FioCheckFileExists(const char *filename, Subdirectory subdir)
|
||||
*/
|
||||
bool FileExists(const char *filename)
|
||||
{
|
||||
#if defined(WINCE)
|
||||
/* There is always one platform that doesn't support basic commands... */
|
||||
HANDLE hand = CreateFile(OTTD2FS(filename), 0, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hand == INVALID_HANDLE_VALUE) return 1;
|
||||
CloseHandle(hand);
|
||||
return 0;
|
||||
#else
|
||||
return access(OTTD2FS(filename), 0) == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -522,7 +514,7 @@ FILE *FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir,
|
||||
case BASESET_DIR:
|
||||
f = FioFOpenFile(filename, mode, OLD_GM_DIR, filesize);
|
||||
if (f != NULL) break;
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
case NEWGRF_DIR:
|
||||
f = FioFOpenFile(filename, mode, OLD_DATA_DIR, filesize);
|
||||
break;
|
||||
@@ -540,11 +532,11 @@ FILE *FioFOpenFile(const char *filename, const char *mode, Subdirectory subdir,
|
||||
* Create a directory with the given name
|
||||
* @param name the new name of the directory
|
||||
*/
|
||||
static void FioCreateDirectory(const char *name)
|
||||
void FioCreateDirectory(const char *name)
|
||||
{
|
||||
/* Ignore directory creation errors; they'll surface later on, and most
|
||||
* of the time they are 'directory already exists' errors anyhow. */
|
||||
#if defined(WIN32) || defined(WINCE)
|
||||
#if defined(WIN32)
|
||||
CreateDirectory(OTTD2FS(name), NULL);
|
||||
#elif defined(OS2) && !defined(__INNOTEK_LIBC__)
|
||||
mkdir(OTTD2FS(name));
|
||||
@@ -584,32 +576,6 @@ bool AppendPathSeparator(char *buf, const char *last)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and files a variable with the full path
|
||||
* based on the given directory.
|
||||
* @param dir the directory to base the path on
|
||||
* @return the malloced full path
|
||||
*/
|
||||
char *BuildWithFullPath(const char *dir)
|
||||
{
|
||||
char *dest = MallocT<char>(MAX_PATH);
|
||||
char *last = dest + MAX_PATH - 1;
|
||||
strecpy(dest, dir, last);
|
||||
|
||||
/* Check if absolute or relative path */
|
||||
const char *s = strchr(dest, PATHSEPCHAR);
|
||||
|
||||
/* Add absolute path */
|
||||
if (s == NULL || dest != s) {
|
||||
if (getcwd(dest, MAX_PATH) == NULL) *dest = '\0';
|
||||
AppendPathSeparator(dest, last);
|
||||
strecat(dest, dir, last);
|
||||
}
|
||||
AppendPathSeparator(dest, last);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first directory in a tar archive.
|
||||
* @param tarname the name of the tar archive to look in.
|
||||
@@ -1014,14 +980,14 @@ bool ExtractTar(const char *tar_filename, Subdirectory subdir)
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(WIN32) || defined(WINCE)
|
||||
#if defined(WIN32)
|
||||
/**
|
||||
* Determine the base (personal dir and game data dir) paths
|
||||
* @param exe the path from the current path to the executable
|
||||
* @note defined in the OS related files (os2.cpp, win32.cpp, unix.cpp etc)
|
||||
*/
|
||||
extern void DetermineBasePaths(const char *exe);
|
||||
#else /* defined(WIN32) || defined(WINCE) */
|
||||
#else /* defined(WIN32) */
|
||||
|
||||
/**
|
||||
* Changes the working directory to the path of the give executable.
|
||||
@@ -1032,30 +998,29 @@ extern void DetermineBasePaths(const char *exe);
|
||||
*/
|
||||
static bool ChangeWorkingDirectoryToExecutable(const char *exe)
|
||||
{
|
||||
char tmp[MAX_PATH];
|
||||
strecpy(tmp, exe, lastof(tmp));
|
||||
|
||||
bool success = false;
|
||||
#ifdef WITH_COCOA
|
||||
char *app_bundle = strchr(exe, '.');
|
||||
char *app_bundle = strchr(tmp, '.');
|
||||
while (app_bundle != NULL && strncasecmp(app_bundle, ".app", 4) != 0) app_bundle = strchr(&app_bundle[1], '.');
|
||||
|
||||
if (app_bundle != NULL) app_bundle[0] = '\0';
|
||||
if (app_bundle != NULL) *app_bundle = '\0';
|
||||
#endif /* WITH_COCOA */
|
||||
char *s = const_cast<char *>(strrchr(exe, PATHSEPCHAR));
|
||||
char *s = strrchr(tmp, PATHSEPCHAR);
|
||||
if (s != NULL) {
|
||||
*s = '\0';
|
||||
#if defined(__DJGPP__)
|
||||
/* If we want to go to the root, we can't use cd C:, but we must use '/' */
|
||||
if (s[-1] == ':') chdir("/");
|
||||
if (s > tmp && *(s - 1) == ':') chdir("/");
|
||||
#endif
|
||||
if (chdir(exe) != 0) {
|
||||
if (chdir(tmp) != 0) {
|
||||
DEBUG(misc, 0, "Directory with the binary does not exist?");
|
||||
} else {
|
||||
success = true;
|
||||
}
|
||||
*s = PATHSEPCHAR;
|
||||
}
|
||||
#ifdef WITH_COCOA
|
||||
if (app_bundle != NULL) app_bundle[0] = '.';
|
||||
#endif /* WITH_COCOA */
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -1185,7 +1150,7 @@ extern void cocoaSetApplicationBundleDir();
|
||||
_searchpaths[SP_APPLICATION_BUNDLE_DIR] = NULL;
|
||||
#endif
|
||||
}
|
||||
#endif /* defined(WIN32) || defined(WINCE) */
|
||||
#endif /* defined(WIN32) */
|
||||
|
||||
const char *_personal_dir;
|
||||
|
||||
@@ -1478,7 +1443,7 @@ uint FileScanner::Scan(const char *extension, Subdirectory sd, bool tars, bool r
|
||||
switch (sd) {
|
||||
case BASESET_DIR:
|
||||
num += this->Scan(extension, OLD_GM_DIR, tars, recursive);
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
case NEWGRF_DIR:
|
||||
num += this->Scan(extension, OLD_DATA_DIR, tars, recursive);
|
||||
break;
|
||||
|
||||
@@ -55,6 +55,7 @@ char *FioGetFullPath(char *buf, const char *last, Searchpath sp, Subdirectory su
|
||||
char *FioFindFullPath(char *buf, const char *last, Subdirectory subdir, const char *filename);
|
||||
char *FioAppendDirectory(char *buf, const char *last, Searchpath sp, Subdirectory subdir);
|
||||
char *FioGetDirectory(char *buf, const char *last, Subdirectory subdir);
|
||||
void FioCreateDirectory(const char *name);
|
||||
|
||||
const char *FiosGetScreenshotDir();
|
||||
|
||||
@@ -149,4 +150,17 @@ static inline DIR *ttd_opendir(const char *path)
|
||||
return opendir(OTTD2FS(path));
|
||||
}
|
||||
|
||||
|
||||
/** Auto-close a file upon scope exit. */
|
||||
class FileCloser {
|
||||
FILE *f;
|
||||
|
||||
public:
|
||||
FileCloser(FILE *_f) : f(_f) {}
|
||||
~FileCloser()
|
||||
{
|
||||
fclose(f);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FILEIO_FUNC_H */
|
||||
|
||||
@@ -77,7 +77,7 @@ void FileList::BuildFileList(AbstractFileType abstract_filetype, SaveLoadOperati
|
||||
{
|
||||
this->Clear();
|
||||
|
||||
assert(fop == SLO_LOAD || SLO_SAVE);
|
||||
assert(fop == SLO_LOAD || fop == SLO_SAVE);
|
||||
switch (abstract_filetype) {
|
||||
case FT_NONE:
|
||||
break;
|
||||
@@ -153,12 +153,11 @@ const char *FiosBrowseTo(const FiosItem *item)
|
||||
{
|
||||
switch (item->type) {
|
||||
case FIOS_TYPE_DRIVE:
|
||||
#if defined(WINCE)
|
||||
seprintf(_fios_path, _fios_path_last, PATHSEP "");
|
||||
#elif defined(WIN32) || defined(__OS2__)
|
||||
#if defined(WIN32) || defined(__OS2__)
|
||||
seprintf(_fios_path, _fios_path_last, "%c:" PATHSEP, item->title[0]);
|
||||
#endif
|
||||
/* FALL THROUGH */
|
||||
break;
|
||||
|
||||
case FIOS_TYPE_INVALID:
|
||||
break;
|
||||
|
||||
|
||||
11
src/fios.h
11
src/fios.h
@@ -81,20 +81,17 @@ extern LoadCheckData _load_check_data;
|
||||
|
||||
enum FileSlots {
|
||||
/**
|
||||
* Slot used for the GRF scanning and such. This slot cannot be reused
|
||||
* as it will otherwise cause issues when pressing "rescan directories".
|
||||
* It can furthermore not be larger than LAST_GRF_SLOT as that complicates
|
||||
* the testing for "too much NewGRFs".
|
||||
* Slot used for the GRF scanning and such.
|
||||
* This slot is used for all temporary accesses to files when scanning/testing files,
|
||||
* and thus cannot be used for files, which are continuously accessed during a game.
|
||||
*/
|
||||
CONFIG_SLOT = 0,
|
||||
/** Slot for the sound. */
|
||||
SOUND_SLOT = 1,
|
||||
/** First slot usable for (New)GRFs used during the game. */
|
||||
FIRST_GRF_SLOT = 2,
|
||||
/** Last slot usable for (New)GRFs used during the game. */
|
||||
LAST_GRF_SLOT = 63,
|
||||
/** Maximum number of slots. */
|
||||
MAX_FILE_SLOTS = 64
|
||||
MAX_FILE_SLOTS = 128,
|
||||
};
|
||||
|
||||
/** Deals with finding savegames */
|
||||
|
||||
@@ -702,7 +702,8 @@ public:
|
||||
this->vscroll->SetCount(this->fios_items.Length());
|
||||
this->selected = NULL;
|
||||
_load_check_data.Clear();
|
||||
/* FALL THROUGH */
|
||||
FALLTHROUGH;
|
||||
|
||||
case 1:
|
||||
/* Selection changes */
|
||||
if (!gui_scope) break;
|
||||
|
||||
@@ -41,7 +41,7 @@ FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs), height(_
|
||||
ascender(_default_font_ascender[fs]), descender(_default_font_ascender[fs] - _default_font_height[fs]),
|
||||
units_per_em(1)
|
||||
{
|
||||
assert(parent == NULL || this->fs == parent->fs);
|
||||
assert(this->parent == NULL || this->fs == this->parent->fs);
|
||||
FontCache::caches[this->fs] = this;
|
||||
Layouter::ResetFontCache(this->fs);
|
||||
}
|
||||
@@ -49,7 +49,7 @@ FontCache::FontCache(FontSize fs) : parent(FontCache::Get(fs)), fs(fs), height(_
|
||||
/** Clean everything up. */
|
||||
FontCache::~FontCache()
|
||||
{
|
||||
assert(this->fs == parent->fs);
|
||||
assert(this->fs == this->parent->fs);
|
||||
FontCache::caches[this->fs] = this->parent;
|
||||
Layouter::ResetFontCache(this->fs);
|
||||
}
|
||||
@@ -86,6 +86,7 @@ public:
|
||||
virtual GlyphID MapCharToGlyph(WChar key) { assert(IsPrintable(key)); return SPRITE_GLYPH | key; }
|
||||
virtual const void *GetFontTable(uint32 tag, size_t &length) { length = 0; return NULL; }
|
||||
virtual const char *GetFontName() { return "sprite"; }
|
||||
virtual bool IsBuiltInFont() { return true; }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -126,7 +127,7 @@ void SpriteFontCache::InitializeUnicodeGlyphMap()
|
||||
SpriteID base;
|
||||
switch (this->fs) {
|
||||
default: NOT_REACHED();
|
||||
case FS_MONO: // Use normal as default for mono spaced font, i.e. FALL THROUGH
|
||||
case FS_MONO: // Use normal as default for mono spaced font
|
||||
case FS_NORMAL: base = SPR_ASCII_SPACE; break;
|
||||
case FS_SMALL: base = SPR_ASCII_SPACE_SMALL; break;
|
||||
case FS_LARGE: base = SPR_ASCII_SPACE_BIG; break;
|
||||
@@ -208,6 +209,7 @@ bool SpriteFontCache::GetDrawGlyphShadow()
|
||||
class FreeTypeFontCache : public FontCache {
|
||||
private:
|
||||
FT_Face face; ///< The font face associated with this font.
|
||||
int req_size; ///< Requested font size.
|
||||
|
||||
typedef SmallMap<uint32, SmallPair<size_t, const void*> > FontTable; ///< Table with font table cache
|
||||
FontTable font_tables; ///< Cached font tables.
|
||||
@@ -236,6 +238,7 @@ private:
|
||||
|
||||
GlyphEntry *GetGlyphPtr(GlyphID key);
|
||||
void SetGlyphPtr(GlyphID key, const GlyphEntry *glyph, bool duplicate = false);
|
||||
void SetFontSize(FontSize fs, FT_Face face, int pixels);
|
||||
|
||||
public:
|
||||
FreeTypeFontCache(FontSize fs, FT_Face face, int pixels);
|
||||
@@ -250,6 +253,7 @@ public:
|
||||
virtual GlyphID MapCharToGlyph(WChar key);
|
||||
virtual const void *GetFontTable(uint32 tag, size_t &length);
|
||||
virtual const char *GetFontName() { return face->family_name; }
|
||||
virtual bool IsBuiltInFont() { return false; }
|
||||
};
|
||||
|
||||
FT_Library _library = NULL;
|
||||
@@ -265,20 +269,26 @@ static const byte SHADOW_COLOUR = 2;
|
||||
* @param face The font that has to be loaded.
|
||||
* @param pixels The number of pixels this font should be high.
|
||||
*/
|
||||
FreeTypeFontCache::FreeTypeFontCache(FontSize fs, FT_Face face, int pixels) : FontCache(fs), face(face), glyph_to_sprite(NULL)
|
||||
FreeTypeFontCache::FreeTypeFontCache(FontSize fs, FT_Face face, int pixels) : FontCache(fs), face(face), req_size(pixels), glyph_to_sprite(NULL)
|
||||
{
|
||||
assert(face != NULL);
|
||||
|
||||
this->SetFontSize(fs, face, pixels);
|
||||
}
|
||||
|
||||
void FreeTypeFontCache::SetFontSize(FontSize fs, FT_Face face, int pixels)
|
||||
{
|
||||
if (pixels == 0) {
|
||||
/* Try to determine a good height based on the minimal height recommended by the font. */
|
||||
pixels = _default_font_height[this->fs];
|
||||
int scaled_height = ScaleGUITrad(_default_font_height[this->fs]);
|
||||
pixels = scaled_height;
|
||||
|
||||
TT_Header *head = (TT_Header *)FT_Get_Sfnt_Table(this->face, ft_sfnt_head);
|
||||
if (head != NULL) {
|
||||
/* Font height is minimum height plus the difference between the default
|
||||
* height for this font size and the small size. */
|
||||
int diff = _default_font_height[this->fs] - _default_font_height[FS_SMALL];
|
||||
pixels = Clamp(min(head->Lowest_Rec_PPEM, 20) + diff, _default_font_height[this->fs], MAX_FONT_SIZE);
|
||||
int diff = scaled_height - ScaleGUITrad(_default_font_height[FS_SMALL]);
|
||||
pixels = Clamp(min(head->Lowest_Rec_PPEM, 20) + diff, scaled_height, MAX_FONT_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,6 +403,7 @@ found_face:
|
||||
FreeTypeFontCache::~FreeTypeFontCache()
|
||||
{
|
||||
FT_Done_Face(this->face);
|
||||
this->face = NULL;
|
||||
this->ClearFontCache();
|
||||
|
||||
for (FontTable::iterator iter = this->font_tables.Begin(); iter != this->font_tables.End(); iter++) {
|
||||
@@ -422,6 +433,9 @@ void FreeTypeFontCache::ClearFontCache()
|
||||
this->glyph_to_sprite = NULL;
|
||||
|
||||
Layouter::ResetFontCache(this->fs);
|
||||
|
||||
/* GUI scaling might have changed, determine font size anew if it was automatically selected. */
|
||||
if (this->face != NULL && this->req_size == 0) this->SetFontSize(this->fs, this->face, this->req_size);
|
||||
}
|
||||
|
||||
FreeTypeFontCache::GlyphEntry *FreeTypeFontCache::GetGlyphPtr(GlyphID key)
|
||||
@@ -474,7 +488,7 @@ static bool GetFontAAState(FontSize size)
|
||||
|
||||
const Sprite *FreeTypeFontCache::GetGlyph(GlyphID key)
|
||||
{
|
||||
if ((key & SPRITE_GLYPH) != 0) return parent->GetGlyph(key);
|
||||
if ((key & SPRITE_GLYPH) != 0) return this->parent->GetGlyph(key);
|
||||
|
||||
/* Check for the glyph in our cache */
|
||||
GlyphEntry *glyph = this->GetGlyphPtr(key);
|
||||
|
||||
@@ -143,6 +143,11 @@ public:
|
||||
{
|
||||
return this->parent != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this a built-in sprite font?
|
||||
*/
|
||||
virtual bool IsBuiltInFont() = 0;
|
||||
};
|
||||
|
||||
/** Get the SpriteID mapped to the given font size and key */
|
||||
|
||||
@@ -382,38 +382,67 @@ FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
|
||||
FT_Error err = FT_Err_Cannot_Open_Resource;
|
||||
|
||||
/* Get font reference from name. */
|
||||
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8);
|
||||
ATSFontRef font = ATSFontFindFromName(name, kATSOptionFlagsDefault);
|
||||
CFRelease(name);
|
||||
if (font == kInvalidFont) return err;
|
||||
|
||||
/* Get a file system reference for the font. */
|
||||
FSRef ref;
|
||||
UInt8 file_path[PATH_MAX];
|
||||
OSStatus os_err = -1;
|
||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
|
||||
if (MacOSVersionIsAtLeast(10, 5, 0)) {
|
||||
os_err = ATSFontGetFileReference(font, &ref);
|
||||
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8);
|
||||
|
||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
|
||||
if (MacOSVersionIsAtLeast(10, 6, 0)) {
|
||||
/* Simply creating the font using CTFontCreateWithNameAndSize will *always* return
|
||||
* something, no matter the name. As such, we can't use it to check for existance.
|
||||
* We instead query the list of all font descriptors that match the given name which
|
||||
* does not do this stupid name fallback. */
|
||||
CTFontDescriptorRef name_desc = CTFontDescriptorCreateWithNameAndSize(name, 0.0);
|
||||
CFSetRef mandatory_attribs = CFSetCreate(kCFAllocatorDefault, (const void **)&kCTFontNameAttribute, 1, &kCFTypeSetCallBacks);
|
||||
CFArrayRef descs = CTFontDescriptorCreateMatchingFontDescriptors(name_desc, mandatory_attribs);
|
||||
CFRelease(mandatory_attribs);
|
||||
CFRelease(name_desc);
|
||||
CFRelease(name);
|
||||
|
||||
/* Loop over all matches until we can get a path for one of them. */
|
||||
for (CFIndex i = 0; descs != NULL && i < CFArrayGetCount(descs) && os_err != noErr; i++) {
|
||||
CTFontRef font = CTFontCreateWithFontDescriptor((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs, i), 0.0, NULL);
|
||||
CFURLRef fontURL = (CFURLRef)CTFontCopyAttribute(font, kCTFontURLAttribute);
|
||||
if (CFURLGetFileSystemRepresentation(fontURL, true, file_path, lengthof(file_path))) os_err = noErr;
|
||||
CFRelease(font);
|
||||
CFRelease(fontURL);
|
||||
}
|
||||
if (descs != NULL) CFRelease(descs);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !defined(__LP64__)
|
||||
/* This type was introduced with the 10.5 SDK. */
|
||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
|
||||
#define ATSFSSpec FSSpec
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6)
|
||||
ATSFontRef font = ATSFontFindFromName(name, kATSOptionFlagsDefault);
|
||||
CFRelease(name);
|
||||
if (font == kInvalidFont) return err;
|
||||
|
||||
/* Get a file system reference for the font. */
|
||||
FSRef ref;
|
||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
|
||||
if (MacOSVersionIsAtLeast(10, 5, 0)) {
|
||||
os_err = ATSFontGetFileReference(font, &ref);
|
||||
} else
|
||||
#endif
|
||||
FSSpec spec;
|
||||
os_err = ATSFontGetFileSpecification(font, (ATSFSSpec *)&spec);
|
||||
if (os_err == noErr) os_err = FSpMakeFSRef(&spec, &ref);
|
||||
{
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) && !defined(__LP64__)
|
||||
/* This type was introduced with the 10.5 SDK. */
|
||||
#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
|
||||
#define ATSFSSpec FSSpec
|
||||
#endif
|
||||
FSSpec spec;
|
||||
os_err = ATSFontGetFileSpecification(font, (ATSFSSpec *)&spec);
|
||||
if (os_err == noErr) os_err = FSpMakeFSRef(&spec, &ref);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Get unix path for file. */
|
||||
if (os_err == noErr) os_err = FSRefMakePath(&ref, file_path, sizeof(file_path));
|
||||
#endif
|
||||
}
|
||||
|
||||
if (os_err == noErr) {
|
||||
/* Get unix path for file. */
|
||||
UInt8 file_path[PATH_MAX];
|
||||
if (FSRefMakePath(&ref, file_path, sizeof(file_path)) == noErr) {
|
||||
DEBUG(freetype, 3, "Font path for %s: %s", font_name, file_path);
|
||||
err = FT_New_Face(_library, (const char *)file_path, 0, face);
|
||||
}
|
||||
DEBUG(freetype, 3, "Font path for %s: %s", font_name, file_path);
|
||||
err = FT_New_Face(_library, (const char *)file_path, 0, face);
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -496,6 +525,7 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6)
|
||||
/* Create a font iterator and iterate over all fonts that
|
||||
* are available to the application. */
|
||||
ATSFontIterator itr;
|
||||
@@ -529,6 +559,7 @@ bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, i
|
||||
}
|
||||
}
|
||||
ATSFontIteratorRelease(&itr);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
|
||||
/**
|
||||
* Resume execution of the Game Script. This function will not actually execute
|
||||
* the script, but set a flag so that the script is executed my the usual
|
||||
* the script, but set a flag so that the script is executed by the usual
|
||||
* mechanism that executes the script.
|
||||
*/
|
||||
static void Unpause();
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
static bool CheckAPIVersion(const char *api_version)
|
||||
{
|
||||
return strcmp(api_version, "1.2") == 0 || strcmp(api_version, "1.3") == 0 || strcmp(api_version, "1.4") == 0 ||
|
||||
strcmp(api_version, "1.5") == 0 || strcmp(api_version, "1.6") == 0 || strcmp(api_version, "1.7") == 0;
|
||||
strcmp(api_version, "1.5") == 0 || strcmp(api_version, "1.6") == 0 || strcmp(api_version, "1.7") == 0 ||
|
||||
strcmp(api_version, "1.8") == 0 || strcmp(api_version, "1.9") == 0;
|
||||
}
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
#include "../script/api/game/game_cargo.hpp.sq"
|
||||
#include "../script/api/game/game_cargolist.hpp.sq"
|
||||
#include "../script/api/game/game_cargomonitor.hpp.sq"
|
||||
#include "../script/api/game/game_client.hpp.sq"
|
||||
#include "../script/api/game/game_clientlist.hpp.sq"
|
||||
#include "../script/api/game/game_company.hpp.sq"
|
||||
#include "../script/api/game/game_companymode.hpp.sq"
|
||||
#include "../script/api/game/game_controller.hpp.sq"
|
||||
@@ -122,6 +124,9 @@ void GameInstance::RegisterAPI()
|
||||
SQGSCargoList_IndustryProducing_Register(this->engine);
|
||||
SQGSCargoList_StationAccepting_Register(this->engine);
|
||||
SQGSCargoMonitor_Register(this->engine);
|
||||
SQGSClient_Register(this->engine);
|
||||
SQGSClientList_Register(this->engine);
|
||||
SQGSClientList_Company_Register(this->engine);
|
||||
SQGSCompany_Register(this->engine);
|
||||
SQGSCompanyMode_Register(this->engine);
|
||||
SQGSDate_Register(this->engine);
|
||||
|
||||
@@ -55,7 +55,7 @@ GameInfo *GameScannerInfo::FindInfo(const char *nameParam, int versionParam, boo
|
||||
*e = '\0';
|
||||
e++;
|
||||
versionParam = atoi(e);
|
||||
/* FALL THROUGH, like we were calling this function with a version. */
|
||||
/* Continue like we were calling this function with a version. */
|
||||
}
|
||||
|
||||
if (force_exact_match) {
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
|
||||
#include "../core/smallvec_type.hpp"
|
||||
|
||||
/** The tab we place our strings in. */
|
||||
static const uint GAME_TEXT_TAB = 18;
|
||||
|
||||
const char *GetGameStringPtr(uint id);
|
||||
void RegisterGameTranslation(class Squirrel *engine);
|
||||
void ReconsiderGameScriptLanguage();
|
||||
|
||||
@@ -38,7 +38,7 @@ void GamelogReset();
|
||||
* @param s The string to print.
|
||||
*/
|
||||
typedef void GamelogPrintProc(const char *s);
|
||||
void GamelogPrint(GamelogPrintProc *proc); // needed for WIN32 / WINCE crash.log
|
||||
void GamelogPrint(GamelogPrintProc *proc); // needed for WIN32 crash.log
|
||||
|
||||
void GamelogPrintDebug(int level);
|
||||
void GamelogPrintConsole();
|
||||
|
||||
@@ -331,7 +331,7 @@ void GenerateWorld(GenWorldMode mode, uint size_x, uint size_y, bool reset_setti
|
||||
_gw.thread = NULL;
|
||||
}
|
||||
|
||||
if (!VideoDriver::GetInstance()->HasGUI() || !ThreadObject::New(&_GenerateWorld, NULL, &_gw.thread)) {
|
||||
if (!VideoDriver::GetInstance()->HasGUI() || !ThreadObject::New(&_GenerateWorld, NULL, &_gw.thread, "ottd:genworld")) {
|
||||
DEBUG(misc, 1, "Cannot create genworld thread, reverting to single-threaded mode");
|
||||
_gw.threaded = false;
|
||||
_modal_progress_work_mutex->EndCritical();
|
||||
|
||||
@@ -288,7 +288,7 @@ static DropDownList *BuildMapsizeDropDown()
|
||||
|
||||
for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) {
|
||||
DropDownListParamStringItem *item = new DropDownListParamStringItem(STR_JUST_INT, i, false);
|
||||
item->SetParam(0, 1 << i);
|
||||
item->SetParam(0, 1LL << i);
|
||||
*list->Append() = item;
|
||||
}
|
||||
|
||||
@@ -336,8 +336,8 @@ struct GenerateLandscapeWindow : public Window {
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_GL_START_DATE_TEXT: SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); break;
|
||||
case WID_GL_MAPSIZE_X_PULLDOWN: SetDParam(0, 1 << _settings_newgame.game_creation.map_x); break;
|
||||
case WID_GL_MAPSIZE_Y_PULLDOWN: SetDParam(0, 1 << _settings_newgame.game_creation.map_y); break;
|
||||
case WID_GL_MAPSIZE_X_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_x); break;
|
||||
case WID_GL_MAPSIZE_Y_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_y); break;
|
||||
case WID_GL_MAX_HEIGHTLEVEL_TEXT: SetDParam(0, _settings_newgame.construction.max_heightlevel); break;
|
||||
case WID_GL_SNOW_LEVEL_TEXT: SetDParam(0, _settings_newgame.game_creation.snow_line_height); break;
|
||||
|
||||
@@ -896,11 +896,11 @@ struct CreateScenarioWindow : public Window
|
||||
break;
|
||||
|
||||
case WID_CS_MAPSIZE_X_PULLDOWN:
|
||||
SetDParam(0, 1 << _settings_newgame.game_creation.map_x);
|
||||
SetDParam(0, 1LL << _settings_newgame.game_creation.map_x);
|
||||
break;
|
||||
|
||||
case WID_CS_MAPSIZE_Y_PULLDOWN:
|
||||
SetDParam(0, 1 << _settings_newgame.game_creation.map_y);
|
||||
SetDParam(0, 1LL << _settings_newgame.game_creation.map_y);
|
||||
break;
|
||||
|
||||
case WID_CS_FLAT_LAND_HEIGHT_TEXT:
|
||||
|
||||
12
src/gfx.cpp
12
src/gfx.cpp
@@ -1111,16 +1111,17 @@ void DoPaletteAnimations()
|
||||
/**
|
||||
* Determine a contrasty text colour for a coloured background.
|
||||
* @param background Background colour.
|
||||
* @param threshold Background colour brightness threshold below which the background is considered dark and TC_WHITE is returned, range: 0 - 255, default 128.
|
||||
* @return TC_BLACK or TC_WHITE depending on what gives a better contrast.
|
||||
*/
|
||||
TextColour GetContrastColour(uint8 background)
|
||||
TextColour GetContrastColour(uint8 background, uint8 threshold)
|
||||
{
|
||||
Colour c = _cur_palette.palette[background];
|
||||
/* Compute brightness according to http://www.w3.org/TR/AERT#color-contrast.
|
||||
* The following formula computes 1000 * brightness^2, with brightness being in range 0 to 255. */
|
||||
uint sq1000_brightness = c.r * c.r * 299 + c.g * c.g * 587 + c.b * c.b * 114;
|
||||
/* Compare with threshold brightness 128 (50%) */
|
||||
return sq1000_brightness < 128 * 128 * 1000 ? TC_WHITE : TC_BLACK;
|
||||
/* Compare with threshold brightness which defaults to 128 (50%) */
|
||||
return sq1000_brightness < ((uint) threshold) * ((uint) threshold) * 1000 ? TC_WHITE : TC_BLACK;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1214,11 +1215,6 @@ void UndrawMouseCursor()
|
||||
|
||||
void DrawMouseCursor()
|
||||
{
|
||||
#if defined(WINCE)
|
||||
/* Don't ever draw the mouse for WinCE, as we work with a stylus */
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* Don't draw the mouse cursor if the screen is not ready */
|
||||
if (_screen.dst_ptr == NULL) return;
|
||||
|
||||
|
||||
@@ -142,6 +142,18 @@ void CheckBlitter();
|
||||
|
||||
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height);
|
||||
|
||||
/**
|
||||
* Determine where to draw a centred object inside a widget.
|
||||
* @param min The top or left coordinate.
|
||||
* @param max The bottom or right coordinate.
|
||||
* @param size The height or width of the object to draw.
|
||||
* @return Offset of where to start drawing the object.
|
||||
*/
|
||||
static inline int CenterBounds(int min, int max, int size)
|
||||
{
|
||||
return min + (max - min - size + 1) / 2;
|
||||
}
|
||||
|
||||
/* window.cpp */
|
||||
void DrawOverlappedWindowForAll(int left, int top, int right, int bottom);
|
||||
|
||||
@@ -161,21 +173,21 @@ void GetBroadestDigit(uint *front, uint *next, FontSize size = FS_NORMAL);
|
||||
|
||||
int GetCharacterHeight(FontSize size);
|
||||
|
||||
/** Height of characters in the small (#FS_SMALL) font. */
|
||||
/** Height of characters in the small (#FS_SMALL) font. @note Some characters may be oversized. */
|
||||
#define FONT_HEIGHT_SMALL (GetCharacterHeight(FS_SMALL))
|
||||
|
||||
/** Height of characters in the normal (#FS_NORMAL) font. */
|
||||
/** Height of characters in the normal (#FS_NORMAL) font. @note Some characters may be oversized. */
|
||||
#define FONT_HEIGHT_NORMAL (GetCharacterHeight(FS_NORMAL))
|
||||
|
||||
/** Height of characters in the large (#FS_LARGE) font. */
|
||||
/** Height of characters in the large (#FS_LARGE) font. @note Some characters may be oversized. */
|
||||
#define FONT_HEIGHT_LARGE (GetCharacterHeight(FS_LARGE))
|
||||
|
||||
/** Height of characters in the large (#FS_MONO) font. */
|
||||
/** Height of characters in the large (#FS_MONO) font. @note Some characters may be oversized. */
|
||||
#define FONT_HEIGHT_MONO (GetCharacterHeight(FS_MONO))
|
||||
|
||||
extern DrawPixelInfo *_cur_dpi;
|
||||
|
||||
TextColour GetContrastColour(uint8 background);
|
||||
TextColour GetContrastColour(uint8 background, uint8 threshold = 128);
|
||||
|
||||
/**
|
||||
* All 16 colour gradients
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include <unicode/ustring.h>
|
||||
#endif /* WITH_ICU_LAYOUT */
|
||||
|
||||
#ifdef WITH_UNISCRIBE
|
||||
#include "os/windows/string_uniscribe.h"
|
||||
#endif /* WITH_UNISCRIBE */
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
|
||||
@@ -113,26 +117,12 @@ le_bool Font::getGlyphPoint(LEGlyphID glyph, le_int32 pointNumber, LEPoint &poin
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static size_t AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
|
||||
{
|
||||
/* Transform from UTF-32 to internal ICU format of UTF-16. */
|
||||
int32 length = 0;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
|
||||
return length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for doing layouts with ICU.
|
||||
*/
|
||||
class ICUParagraphLayout : public AutoDeleteSmallVector<ParagraphLayouter::Line *, 4>, public ParagraphLayouter {
|
||||
ParagraphLayout *p; ///< The actual ICU paragraph layout.
|
||||
public:
|
||||
/** Helper for GetLayouter, to get the right type. */
|
||||
typedef UChar CharType;
|
||||
/** Helper for GetLayouter, to get whether the layouter supports RTL. */
|
||||
static const bool SUPPORTS_RTL = true;
|
||||
|
||||
/** Visual run contains data about the bit of text with the same font. */
|
||||
class ICUVisualRun : public ParagraphLayouter::VisualRun {
|
||||
const ParagraphLayout::VisualRun *vr; ///< The actual ICU vr.
|
||||
@@ -184,35 +174,54 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping)
|
||||
{
|
||||
int32 length = buff_end - buff;
|
||||
/**
|
||||
* Helper class to construct a new #ICUParagraphLayout.
|
||||
*/
|
||||
class ICUParagraphLayoutFactory {
|
||||
public:
|
||||
/** Helper for GetLayouter, to get the right type. */
|
||||
typedef UChar CharType;
|
||||
/** Helper for GetLayouter, to get whether the layouter supports RTL. */
|
||||
static const bool SUPPORTS_RTL = true;
|
||||
|
||||
if (length == 0) {
|
||||
/* ICU's ParagraphLayout cannot handle empty strings, so fake one. */
|
||||
buff[0] = ' ';
|
||||
length = 1;
|
||||
fontMapping.End()[-1].first++;
|
||||
static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontMap &fontMapping)
|
||||
{
|
||||
int32 length = buff_end - buff;
|
||||
|
||||
if (length == 0) {
|
||||
/* ICU's ParagraphLayout cannot handle empty strings, so fake one. */
|
||||
buff[0] = ' ';
|
||||
length = 1;
|
||||
fontMapping.End()[-1].first++;
|
||||
}
|
||||
|
||||
/* Fill ICU's FontRuns with the right data. */
|
||||
FontRuns runs(fontMapping.Length());
|
||||
for (FontMap::iterator iter = fontMapping.Begin(); iter != fontMapping.End(); iter++) {
|
||||
runs.add(iter->second, iter->first);
|
||||
}
|
||||
|
||||
LEErrorCode status = LE_NO_ERROR;
|
||||
/* ParagraphLayout does not copy "buff", so it must stay valid.
|
||||
* "runs" is copied according to the ICU source, but the documentation does not specify anything, so this might break somewhen. */
|
||||
ParagraphLayout *p = new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
|
||||
if (status != LE_NO_ERROR) {
|
||||
delete p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new ICUParagraphLayout(p);
|
||||
}
|
||||
|
||||
/* Fill ICU's FontRuns with the right data. */
|
||||
FontRuns runs(fontMapping.Length());
|
||||
for (FontMap::iterator iter = fontMapping.Begin(); iter != fontMapping.End(); iter++) {
|
||||
runs.add(iter->second, iter->first);
|
||||
static size_t AppendToBuffer(UChar *buff, const UChar *buffer_last, WChar c)
|
||||
{
|
||||
/* Transform from UTF-32 to internal ICU format of UTF-16. */
|
||||
int32 length = 0;
|
||||
UErrorCode err = U_ZERO_ERROR;
|
||||
u_strFromUTF32(buff, buffer_last - buff, &length, (UChar32*)&c, 1, &err);
|
||||
return length;
|
||||
}
|
||||
|
||||
LEErrorCode status = LE_NO_ERROR;
|
||||
/* ParagraphLayout does not copy "buff", so it must stay valid.
|
||||
* "runs" is copied according to the ICU source, but the documentation does not specify anything, so this might break somewhen. */
|
||||
ParagraphLayout *p = new ParagraphLayout(buff, length, &runs, NULL, NULL, NULL, _current_text_dir == TD_RTL ? UBIDI_DEFAULT_RTL : UBIDI_DEFAULT_LTR, false, status);
|
||||
if (status != LE_NO_ERROR) {
|
||||
delete p;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new ICUParagraphLayout(p);
|
||||
}
|
||||
|
||||
};
|
||||
#endif /* WITH_ICU_LAYOUT */
|
||||
|
||||
/*** Paragraph layout ***/
|
||||
@@ -236,11 +245,6 @@ static ParagraphLayouter *GetParagraphLayout(UChar *buff, UChar *buff_end, FontM
|
||||
*/
|
||||
class FallbackParagraphLayout : public ParagraphLayouter {
|
||||
public:
|
||||
/** Helper for GetLayouter, to get the right type. */
|
||||
typedef WChar CharType;
|
||||
/** Helper for GetLayouter, to get whether the layouter supports RTL. */
|
||||
static const bool SUPPORTS_RTL = false;
|
||||
|
||||
/** Visual run contains data about the bit of text with the same font. */
|
||||
class FallbackVisualRun : public ParagraphLayouter::VisualRun {
|
||||
Font *font; ///< The font used to layout these.
|
||||
@@ -280,6 +284,42 @@ public:
|
||||
const ParagraphLayouter::Line *NextLine(int max_width);
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to construct a new #FallbackParagraphLayout.
|
||||
*/
|
||||
class FallbackParagraphLayoutFactory {
|
||||
public:
|
||||
/** Helper for GetLayouter, to get the right type. */
|
||||
typedef WChar CharType;
|
||||
/** Helper for GetLayouter, to get whether the layouter supports RTL. */
|
||||
static const bool SUPPORTS_RTL = false;
|
||||
|
||||
/**
|
||||
* Get the actual ParagraphLayout for the given buffer.
|
||||
* @param buff The begin of the buffer.
|
||||
* @param buff_end The location after the last element in the buffer.
|
||||
* @param fontMapping THe mapping of the fonts.
|
||||
* @return The ParagraphLayout instance.
|
||||
*/
|
||||
static ParagraphLayouter *GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
|
||||
{
|
||||
return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a wide character to the internal buffer.
|
||||
* @param buff The buffer to append to.
|
||||
* @param buffer_last The end of the buffer.
|
||||
* @param c The character to add.
|
||||
* @return The number of buffer spaces that were used.
|
||||
*/
|
||||
static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
|
||||
{
|
||||
*buff = c;
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the visual run.
|
||||
* @param font The font to use for this run.
|
||||
@@ -536,31 +576,6 @@ const ParagraphLayouter::Line *FallbackParagraphLayout::NextLine(int max_width)
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appand a wide character to the internal buffer.
|
||||
* @param buff The buffer to append to.
|
||||
* @param buffer_last The end of the buffer.
|
||||
* @param c The character to add.
|
||||
* @return The number of buffer spaces that were used.
|
||||
*/
|
||||
static size_t AppendToBuffer(WChar *buff, const WChar *buffer_last, WChar c)
|
||||
{
|
||||
*buff = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the actual ParagraphLayout for the given buffer.
|
||||
* @param buff The begin of the buffer.
|
||||
* @param buff_end The location after the last element in the buffer.
|
||||
* @param fontMapping THe mapping of the fonts.
|
||||
* @return The ParagraphLayout instance.
|
||||
*/
|
||||
static FallbackParagraphLayout *GetParagraphLayout(WChar *buff, WChar *buff_end, FontMap &fontMapping)
|
||||
{
|
||||
return new FallbackParagraphLayout(buff, buff_end - buff, fontMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for getting a ParagraphLayouter of the given type.
|
||||
*
|
||||
@@ -582,6 +597,7 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str,
|
||||
Font *f = Layouter::GetFont(state.fontsize, state.cur_colour);
|
||||
|
||||
line.buffer = buff_begin;
|
||||
fontMapping.Clear();
|
||||
|
||||
/*
|
||||
* Go through the whole string while adding Font instances to the font map
|
||||
@@ -594,18 +610,18 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str,
|
||||
break;
|
||||
} else if (c >= SCC_BLUE && c <= SCC_BLACK) {
|
||||
state.SetColour((TextColour)(c - SCC_BLUE));
|
||||
} else if (c == SCC_PREVIOUS_COLOUR) { // Revert to the previous colour.
|
||||
state.SetPreviousColour();
|
||||
} else if (c == SCC_TINYFONT) {
|
||||
state.SetFontSize(FS_SMALL);
|
||||
} else if (c == SCC_BIGFONT) {
|
||||
state.SetFontSize(FS_LARGE);
|
||||
} else if (c == SCC_PUSH_COLOUR) {
|
||||
state.PushColour();
|
||||
} else if (c == SCC_POP_COLOUR) {
|
||||
state.PopColour();
|
||||
} else if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
|
||||
state.SetFontSize((FontSize)(c - SCC_FIRST_FONT));
|
||||
} else {
|
||||
/* Filter out text direction characters that shouldn't be drawn, and
|
||||
* will not be handled in the fallback non ICU case because they are
|
||||
* mostly needed for RTL languages which need more ICU support. */
|
||||
if (!T::SUPPORTS_RTL && IsTextDirectionChar(c)) continue;
|
||||
buff += AppendToBuffer(buff, buffer_last, c);
|
||||
buff += T::AppendToBuffer(buff, buffer_last, c);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -621,7 +637,7 @@ static inline void GetLayouter(Layouter::LineCacheItem &line, const char *&str,
|
||||
if (!fontMapping.Contains(buff - buff_begin)) {
|
||||
fontMapping.Insert(buff - buff_begin, f);
|
||||
}
|
||||
line.layout = GetParagraphLayout(buff_begin, buff, fontMapping);
|
||||
line.layout = T::GetParagraphLayout(buff_begin, buff, fontMapping);
|
||||
line.state_after = state;
|
||||
}
|
||||
|
||||
@@ -654,11 +670,11 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
|
||||
line.layout->Reflow();
|
||||
} else {
|
||||
/* Line is new, layout it */
|
||||
#ifdef WITH_ICU_LAYOUT
|
||||
FontState old_state = state;
|
||||
const char *old_str = str;
|
||||
|
||||
GetLayouter<ICUParagraphLayout>(line, str, state);
|
||||
#ifdef WITH_ICU_LAYOUT
|
||||
GetLayouter<ICUParagraphLayoutFactory>(line, str, state);
|
||||
if (line.layout == NULL) {
|
||||
static bool warned = false;
|
||||
if (!warned) {
|
||||
@@ -668,11 +684,22 @@ Layouter::Layouter(const char *str, int maxw, TextColour colour, FontSize fontsi
|
||||
|
||||
state = old_state;
|
||||
str = old_str;
|
||||
GetLayouter<FallbackParagraphLayout>(line, str, state);
|
||||
}
|
||||
#else
|
||||
GetLayouter<FallbackParagraphLayout>(line, str, state);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_UNISCRIBE
|
||||
if (line.layout == NULL) {
|
||||
GetLayouter<UniscribeParagraphLayoutFactory>(line, str, state);
|
||||
if (line.layout == NULL) {
|
||||
state = old_state;
|
||||
str = old_str;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (line.layout == NULL) {
|
||||
GetLayouter<FallbackParagraphLayoutFactory>(line, str, state);
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy all lines into a local cache so we can reuse them later on more easily. */
|
||||
@@ -809,6 +836,10 @@ void Layouter::ResetFontCache(FontSize size)
|
||||
|
||||
/* We must reset the linecache since it references the just freed fonts */
|
||||
ResetLineCache();
|
||||
|
||||
#if defined(WITH_UNISCRIBE)
|
||||
UniscribeResetScriptCache(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
|
||||
#ifdef WITH_ICU_LAYOUT
|
||||
#include "layout/ParagraphLayout.h"
|
||||
@@ -33,10 +34,11 @@
|
||||
struct FontState {
|
||||
FontSize fontsize; ///< Current font size.
|
||||
TextColour cur_colour; ///< Current text colour.
|
||||
TextColour prev_colour; ///< Text colour from before the last colour switch.
|
||||
|
||||
FontState() : fontsize(FS_END), cur_colour(TC_INVALID), prev_colour(TC_INVALID) {}
|
||||
FontState(TextColour colour, FontSize fontsize) : fontsize(fontsize), cur_colour(colour), prev_colour(colour) {}
|
||||
std::stack<TextColour> colour_stack; ///< Stack of colours to assist with colour switching.
|
||||
|
||||
FontState() : fontsize(FS_END), cur_colour(TC_INVALID) {}
|
||||
FontState(TextColour colour, FontSize fontsize) : fontsize(fontsize), cur_colour(colour) {}
|
||||
|
||||
/**
|
||||
* Switch to new colour \a c.
|
||||
@@ -45,14 +47,25 @@ struct FontState {
|
||||
inline void SetColour(TextColour c)
|
||||
{
|
||||
assert(c >= TC_BLUE && c <= TC_BLACK);
|
||||
this->prev_colour = this->cur_colour;
|
||||
this->cur_colour = c;
|
||||
}
|
||||
|
||||
/** Switch to previous colour. */
|
||||
inline void SetPreviousColour()
|
||||
/**
|
||||
* Switch to and pop the last saved colour on the stack.
|
||||
*/
|
||||
inline void PopColour()
|
||||
{
|
||||
Swap(this->cur_colour, this->prev_colour);
|
||||
if (colour_stack.empty()) return;
|
||||
SetColour(colour_stack.top());
|
||||
colour_stack.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the current colour on to the stack.
|
||||
*/
|
||||
inline void PushColour()
|
||||
{
|
||||
colour_stack.push(this->cur_colour);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +162,7 @@ class Layouter : public AutoDeleteSmallVector<const ParagraphLayouter::Line *, 4
|
||||
{
|
||||
if (this->state_before.fontsize != other.state_before.fontsize) return this->state_before.fontsize < other.state_before.fontsize;
|
||||
if (this->state_before.cur_colour != other.state_before.cur_colour) return this->state_before.cur_colour < other.state_before.cur_colour;
|
||||
if (this->state_before.prev_colour != other.state_before.prev_colour) return this->state_before.prev_colour < other.state_before.prev_colour;
|
||||
if (this->state_before.colour_stack != other.state_before.colour_stack) return this->state_before.colour_stack < other.state_before.colour_stack;
|
||||
return this->str < other.str;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -139,7 +139,7 @@ void CheckExternalFiles()
|
||||
|
||||
if (used_set->GetNumInvalid() != 0) {
|
||||
/* Not all files were loaded successfully, see which ones */
|
||||
add_pos += seprintf(add_pos, last, "Trying to load graphics set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of readme.txt.\n\nThe following files are corrupted or missing:\n", used_set->name);
|
||||
add_pos += seprintf(add_pos, last, "Trying to load graphics set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", used_set->name);
|
||||
for (uint i = 0; i < GraphicsSet::NUM_FILES; i++) {
|
||||
MD5File::ChecksumResult res = GraphicsSet::CheckMD5(&used_set->files[i], BASESET_DIR);
|
||||
if (res != MD5File::CR_MATCH) add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", used_set->files[i].filename, res == MD5File::CR_MISMATCH ? "corrupt" : "missing", used_set->files[i].missing_warning);
|
||||
@@ -149,7 +149,7 @@ void CheckExternalFiles()
|
||||
|
||||
const SoundsSet *sounds_set = BaseSounds::GetUsedSet();
|
||||
if (sounds_set->GetNumInvalid() != 0) {
|
||||
add_pos += seprintf(add_pos, last, "Trying to load sound set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of readme.txt.\n\nThe following files are corrupted or missing:\n", sounds_set->name);
|
||||
add_pos += seprintf(add_pos, last, "Trying to load sound set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", sounds_set->name);
|
||||
|
||||
assert_compile(SoundsSet::NUM_FILES == 1);
|
||||
/* No need to loop each file, as long as there is only a single
|
||||
@@ -197,31 +197,49 @@ static void LoadSpriteTables()
|
||||
InitializeUnicodeGlyphMap();
|
||||
|
||||
/*
|
||||
* Load the base NewGRF with OTTD required graphics as first NewGRF.
|
||||
* Load the base and extra NewGRF with OTTD required graphics as first NewGRF.
|
||||
* However, we do not want it to show up in the list of used NewGRFs,
|
||||
* so we have to manually add it, and then remove it later.
|
||||
*/
|
||||
GRFConfig *top = _grfconfig;
|
||||
GRFConfig *master = new GRFConfig(used_set->files[GFT_EXTRA].filename);
|
||||
|
||||
/* Default extra graphics */
|
||||
GRFConfig *master = new GRFConfig("OPENTTD.GRF");
|
||||
master->palette |= GRFP_GRF_DOS;
|
||||
FillGRFDetails(master, false, BASESET_DIR);
|
||||
ClrBit(master->flags, GCF_INIT_ONLY);
|
||||
|
||||
/* Baseset extra graphics */
|
||||
GRFConfig *extra = new GRFConfig(used_set->files[GFT_EXTRA].filename);
|
||||
|
||||
/* We know the palette of the base set, so if the base NewGRF is not
|
||||
* setting one, use the palette of the base set and not the global
|
||||
* one which might be the wrong palette for this base NewGRF.
|
||||
* The value set here might be overridden via action14 later. */
|
||||
switch (used_set->palette) {
|
||||
case PAL_DOS: master->palette |= GRFP_GRF_DOS; break;
|
||||
case PAL_WINDOWS: master->palette |= GRFP_GRF_WINDOWS; break;
|
||||
case PAL_DOS: extra->palette |= GRFP_GRF_DOS; break;
|
||||
case PAL_WINDOWS: extra->palette |= GRFP_GRF_WINDOWS; break;
|
||||
default: break;
|
||||
}
|
||||
FillGRFDetails(master, false, BASESET_DIR);
|
||||
FillGRFDetails(extra, false, BASESET_DIR);
|
||||
ClrBit(extra->flags, GCF_INIT_ONLY);
|
||||
|
||||
ClrBit(master->flags, GCF_INIT_ONLY);
|
||||
master->next = top;
|
||||
extra->next = top;
|
||||
master->next = extra;
|
||||
_grfconfig = master;
|
||||
|
||||
LoadNewGRF(SPR_NEWGRFS_BASE, i);
|
||||
LoadNewGRF(SPR_NEWGRFS_BASE, i, 2);
|
||||
|
||||
uint total_extra_graphics = SPR_NEWGRFS_BASE - SPR_OPENTTD_BASE;
|
||||
_missing_extra_graphics = GetSpriteCountForSlot(i, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE);
|
||||
DEBUG(sprite, 1, "%u extra sprites, %u from baseset, %u from fallback", total_extra_graphics, total_extra_graphics - _missing_extra_graphics, _missing_extra_graphics);
|
||||
|
||||
/* The original baseset extra graphics intentionally make use of the fallback graphics.
|
||||
* Let's say everything which provides less than 500 sprites misses the rest intentionally. */
|
||||
if (500 + _missing_extra_graphics > total_extra_graphics) _missing_extra_graphics = 0;
|
||||
|
||||
/* Free and remove the top element. */
|
||||
delete extra;
|
||||
delete master;
|
||||
_grfconfig = top;
|
||||
}
|
||||
@@ -266,12 +284,17 @@ static bool SwitchNewGRFBlitter()
|
||||
#endif
|
||||
{ "8bpp-optimized", 2, 8, 8, 8, 8 },
|
||||
{ "32bpp-optimized", 0, 8, 32, 8, 32 },
|
||||
#ifdef WITH_SSE
|
||||
{ "32bpp-sse2-anim", 1, 8, 32, 8, 32 },
|
||||
#endif
|
||||
{ "32bpp-anim", 1, 8, 32, 8, 32 },
|
||||
};
|
||||
|
||||
const bool animation_wanted = HasBit(_display_opt, DO_FULL_ANIMATION);
|
||||
const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName();
|
||||
|
||||
VideoDriver::GetInstance()->AcquireBlitterLock();
|
||||
|
||||
for (uint i = 0; i < lengthof(replacement_blitters); i++) {
|
||||
if (animation_wanted && (replacement_blitters[i].animation == 0)) continue;
|
||||
if (!animation_wanted && (replacement_blitters[i].animation == 1)) continue;
|
||||
@@ -280,7 +303,10 @@ static bool SwitchNewGRFBlitter()
|
||||
if (!IsInsideMM(depth_wanted_by_grf, replacement_blitters[i].min_grf_depth, replacement_blitters[i].max_grf_depth + 1)) continue;
|
||||
const char *repl_blitter = replacement_blitters[i].name;
|
||||
|
||||
if (strcmp(repl_blitter, cur_blitter) == 0) return false;
|
||||
if (strcmp(repl_blitter, cur_blitter) == 0) {
|
||||
VideoDriver::GetInstance()->ReleaseBlitterLock();
|
||||
return false;
|
||||
}
|
||||
if (BlitterFactory::GetBlitterFactory(repl_blitter) == NULL) continue;
|
||||
|
||||
DEBUG(misc, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter);
|
||||
@@ -295,6 +321,8 @@ static bool SwitchNewGRFBlitter()
|
||||
if (BlitterFactory::SelectBlitter(cur_blitter) == NULL || !VideoDriver::GetInstance()->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config");
|
||||
}
|
||||
|
||||
VideoDriver::GetInstance()->ReleaseBlitterLock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
32
src/goal.cpp
32
src/goal.cpp
@@ -23,6 +23,8 @@
|
||||
#include "string_func.h"
|
||||
#include "gui.h"
|
||||
#include "network/network.h"
|
||||
#include "network/network_base.h"
|
||||
#include "network/network_func.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
@@ -234,7 +236,9 @@ CommandCost CmdSetGoalCompleted(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
||||
* @param flags type of operation
|
||||
* @param p1 various bitstuffed elements
|
||||
* - p1 = (bit 0 - 15) - Unique ID to use for this question.
|
||||
* - p1 = (bit 16 - 23) - Company for which this question is.
|
||||
* - p1 = (bit 16 - 23) - Company or client for which this question is.
|
||||
* - p1 = (bit 24 - 25) - Question type.
|
||||
* - p1 = (bit 31) - Question target: 0 - company, 1 - client.
|
||||
* @param p2 Buttons of the question.
|
||||
* @param text Text of the question.
|
||||
* @return the cost of this operation or an error
|
||||
@@ -243,17 +247,37 @@ CommandCost CmdGoalQuestion(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
|
||||
{
|
||||
uint16 uniqueid = (GoalType)GB(p1, 0, 16);
|
||||
CompanyID company = (CompanyID)GB(p1, 16, 8);
|
||||
byte type = GB(p1, 24, 8);
|
||||
#ifdef ENABLE_NETWORK
|
||||
ClientIndex client = (ClientIndex)GB(p1, 16, 8);
|
||||
#endif
|
||||
byte type = GB(p1, 24, 2);
|
||||
bool is_client = HasBit(p1, 31);
|
||||
|
||||
if (_current_company != OWNER_DEITY) return CMD_ERROR;
|
||||
if (StrEmpty(text)) return CMD_ERROR;
|
||||
if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
|
||||
if (is_client) {
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (!NetworkClientInfo::IsValidID(client)) return CMD_ERROR;
|
||||
#else
|
||||
return CMD_ERROR;
|
||||
#endif
|
||||
} else {
|
||||
if (company != INVALID_COMPANY && !Company::IsValidID(company)) return CMD_ERROR;
|
||||
}
|
||||
if (CountBits(p2) < 1 || CountBits(p2) > 3) return CMD_ERROR;
|
||||
if (p2 >= (1 << GOAL_QUESTION_BUTTON_COUNT)) return CMD_ERROR;
|
||||
if (type >= GOAL_QUESTION_TYPE_COUNT) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if ((company != INVALID_COMPANY && company == _local_company) || (company == INVALID_COMPANY && Company::IsValidID(_local_company))) ShowGoalQuestion(uniqueid, type, p2, text);
|
||||
if (is_client) {
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (NetworkClientInfo::Get(client)->client_id != _network_own_client_id) return CommandCost();
|
||||
#endif
|
||||
} else {
|
||||
if (company == INVALID_COMPANY && !Company::IsValidID(_local_company)) return CommandCost();
|
||||
if (company != INVALID_COMPANY && company != _local_company) return CommandCost();
|
||||
}
|
||||
ShowGoalQuestion(uniqueid, type, p2, text);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
#include "safeguards.h"
|
||||
|
||||
/* Bitmasks of company and cargo indices that shouldn't be drawn. */
|
||||
static uint _legend_excluded_companies;
|
||||
static uint _legend_excluded_cargo;
|
||||
static CompanyMask _legend_excluded_companies;
|
||||
static CargoTypes _legend_excluded_cargo;
|
||||
|
||||
/* Apparently these don't play well with enums. */
|
||||
static const OverflowSafeInt64 INVALID_DATAPOINT(INT64_MAX); // Value used for a datapoint that shouldn't be drawn.
|
||||
@@ -166,14 +166,14 @@ struct ValuesInterval {
|
||||
|
||||
struct BaseGraphWindow : Window {
|
||||
protected:
|
||||
static const int GRAPH_MAX_DATASETS = 32;
|
||||
static const int GRAPH_MAX_DATASETS = 64;
|
||||
static const int GRAPH_AXIS_LINE_COLOUR = PC_BLACK;
|
||||
static const int GRAPH_NUM_MONTHS = 24; ///< Number of months displayed in the graph.
|
||||
|
||||
static const int MIN_GRAPH_NUM_LINES_Y = 9; ///< Minimal number of horizontal lines to draw.
|
||||
static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines.
|
||||
|
||||
uint excluded_data; ///< bitmask of the datasets that shouldn't be displayed.
|
||||
uint64 excluded_data; ///< bitmask of the datasets that shouldn't be displayed.
|
||||
byte num_dataset;
|
||||
byte num_on_x_axis;
|
||||
byte num_vert_lines;
|
||||
@@ -561,7 +561,7 @@ public:
|
||||
*/
|
||||
void UpdateStatistics(bool initialize)
|
||||
{
|
||||
uint excluded_companies = _legend_excluded_companies;
|
||||
CompanyMask excluded_companies = _legend_excluded_companies;
|
||||
|
||||
/* Exclude the companies which aren't valid */
|
||||
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
|
||||
|
||||
@@ -58,8 +58,8 @@ void GroundVehicle<T, Type>::PowerChanged()
|
||||
|
||||
this->gcache.cached_air_drag = air_drag + 3 * air_drag * number_of_parts / 20;
|
||||
|
||||
max_te *= 10000; // Tractive effort in (tonnes * 1000 * 10 =) N.
|
||||
max_te /= 256; // Tractive effort is a [0-255] coefficient.
|
||||
max_te *= 9800; // Tractive effort in (tonnes * 1000 * 9.8 =) N.
|
||||
max_te /= 256; // Tractive effort is a [0-255] coefficient.
|
||||
if (this->gcache.cached_power != total_power || this->gcache.cached_max_te != max_te) {
|
||||
/* Stop the vehicle if it has no power. */
|
||||
if (total_power == 0) this->vehstatus |= VS_STOPPED;
|
||||
|
||||
@@ -55,6 +55,7 @@ static const NWidgetPart _nested_group_widgets[] = {
|
||||
SetFill(1, 0), SetResize(0, 1), SetScrollbar(WID_GL_LIST_GROUP_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_GL_LIST_GROUP_SCROLLBAR),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_GL_INFO), SetFill(1, 0), EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_GL_CREATE_GROUP), SetFill(0, 1),
|
||||
SetDataTip(SPR_GROUP_CREATE_TRAIN, STR_GROUP_CREATE_TOOLTIP),
|
||||
@@ -371,6 +372,9 @@ public:
|
||||
max_icon_height = max(max_icon_height, GetSpriteSize(this->GetWidget<NWidgetCore>(WID_GL_DELETE_GROUP)->widget_data).height);
|
||||
max_icon_height = max(max_icon_height, GetSpriteSize(this->GetWidget<NWidgetCore>(WID_GL_REPLACE_PROTECTION)->widget_data).height);
|
||||
|
||||
/* ... minus the height of the group info ... */
|
||||
max_icon_height += (FONT_HEIGHT_NORMAL * 3) + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
|
||||
|
||||
/* Get a multiple of tiny_step_height of that amount */
|
||||
size->height = Ceil(size->height - max_icon_height, tiny_step_height);
|
||||
break;
|
||||
@@ -403,6 +407,11 @@ public:
|
||||
*size = maxdim(*size, d);
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_GL_INFO: {
|
||||
size->height = (FONT_HEIGHT_NORMAL * 3) + WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,6 +536,44 @@ public:
|
||||
DrawGroupInfo(r.top + WD_FRAMERECT_TOP, r.left, r.right, DEFAULT_GROUP);
|
||||
break;
|
||||
|
||||
case WID_GL_INFO: {
|
||||
Money this_year = 0;
|
||||
Money last_year = 0;
|
||||
uint32 occupancy = 0;
|
||||
uint32 vehicle_count = this->vehicles.Length();
|
||||
|
||||
for (uint i = 0; i < vehicle_count; i++) {
|
||||
const Vehicle *v = this->vehicles[i];
|
||||
assert(v->owner == this->owner);
|
||||
|
||||
this_year += v->GetDisplayProfitThisYear();
|
||||
last_year += v->GetDisplayProfitLastYear();
|
||||
occupancy += v->trip_occupancy;
|
||||
}
|
||||
|
||||
const int left = r.left + WD_FRAMERECT_LEFT + 8;
|
||||
const int right = r.right - WD_FRAMERECT_RIGHT - 8;
|
||||
|
||||
int y = r.top + WD_FRAMERECT_TOP;
|
||||
DrawString(left, right, y, STR_GROUP_PROFIT_THIS_YEAR, TC_BLACK);
|
||||
SetDParam(0, this_year);
|
||||
DrawString(left, right, y, STR_JUST_CURRENCY_LONG, TC_BLACK, SA_RIGHT);
|
||||
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
DrawString(left, right, y, STR_GROUP_PROFIT_LAST_YEAR, TC_BLACK);
|
||||
SetDParam(0, last_year);
|
||||
DrawString(left, right, y, STR_JUST_CURRENCY_LONG, TC_BLACK, SA_RIGHT);
|
||||
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
DrawString(left, right, y, STR_GROUP_OCCUPANCY, TC_BLACK);
|
||||
if (vehicle_count > 0) {
|
||||
SetDParam(0, occupancy / vehicle_count);
|
||||
DrawString(left, right, y, STR_GROUP_OCCUPANCY_VALUE, TC_BLACK, SA_RIGHT);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_GL_LIST_GROUP: {
|
||||
int y1 = r.top + WD_FRAMERECT_TOP;
|
||||
int max = min(this->group_sb->GetPosition() + this->group_sb->GetCapacity(), this->groups.Length());
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user