mirror of https://github.com/OpenRCT2/OpenRCT2.git
Refactor invalidation logic to be generic to the callee
This commit is contained in:
parent
5ae54eb9f9
commit
efa1db826e
|
@ -1601,7 +1601,7 @@ static int32_t cc_mp_desync(InteractiveConsole& console, const arguments_t& argv
|
||||||
if (peeps.size() > 1)
|
if (peeps.size() > 1)
|
||||||
peep = peeps[util_rand() % peeps.size() - 1];
|
peep = peeps[util_rand() % peeps.size() - 1];
|
||||||
peep->TshirtColour = util_rand() & 0xFF;
|
peep->TshirtColour = util_rand() & 0xFF;
|
||||||
peep->Invalidate0();
|
peep->Invalidate();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -331,11 +331,6 @@ Staff* Peep::AsStaff()
|
||||||
return AssignedPeepType == PeepType::Staff ? static_cast<Staff*>(this) : nullptr;
|
return AssignedPeepType == PeepType::Staff ? static_cast<Staff*>(this) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Peep::Invalidate()
|
|
||||||
{
|
|
||||||
Invalidate2();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Peep::MoveTo(const CoordsXYZ& newLocation)
|
void Peep::MoveTo(const CoordsXYZ& newLocation)
|
||||||
{
|
{
|
||||||
Invalidate(); // Invalidate current position.
|
Invalidate(); // Invalidate current position.
|
||||||
|
|
|
@ -735,7 +735,6 @@ public: // Peep
|
||||||
std::optional<CoordsXY> UpdateAction();
|
std::optional<CoordsXY> UpdateAction();
|
||||||
void SetState(PeepState new_state);
|
void SetState(PeepState new_state);
|
||||||
void Remove();
|
void Remove();
|
||||||
void Invalidate();
|
|
||||||
void UpdateCurrentActionSpriteType();
|
void UpdateCurrentActionSpriteType();
|
||||||
void SwitchToSpecialSprite(uint8_t special_sprite_id);
|
void SwitchToSpecialSprite(uint8_t special_sprite_id);
|
||||||
void StateReset();
|
void StateReset();
|
||||||
|
|
|
@ -1421,7 +1421,7 @@ private:
|
||||||
dst->sprite_height_positive = spriteBounds->sprite_height_positive;
|
dst->sprite_height_positive = spriteBounds->sprite_height_positive;
|
||||||
|
|
||||||
dst->MoveTo({ src->x, src->y, src->z });
|
dst->MoveTo({ src->x, src->y, src->z });
|
||||||
dst->Invalidate2();
|
dst->Invalidate();
|
||||||
|
|
||||||
dst->sprite_direction = src->sprite_direction;
|
dst->sprite_direction = src->sprite_direction;
|
||||||
|
|
||||||
|
@ -1663,7 +1663,7 @@ private:
|
||||||
litter->sprite_height_negative = srcLitter->sprite_height_negative;
|
litter->sprite_height_negative = srcLitter->sprite_height_negative;
|
||||||
|
|
||||||
litter->MoveTo({ srcLitter->x, srcLitter->y, srcLitter->z });
|
litter->MoveTo({ srcLitter->x, srcLitter->y, srcLitter->z });
|
||||||
litter->Invalidate2();
|
litter->Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1722,7 +1722,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
dst->MoveTo({ src->x, src->y, src->z });
|
dst->MoveTo({ src->x, src->y, src->z });
|
||||||
dst->Invalidate2();
|
dst->Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -832,11 +832,6 @@ Vehicle* try_get_vehicle(uint16_t spriteIndex)
|
||||||
return TryGetEntity<Vehicle>(spriteIndex);
|
return TryGetEntity<Vehicle>(spriteIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vehicle::Invalidate()
|
|
||||||
{
|
|
||||||
Invalidate2();
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template<typename T> class TrainIterator;
|
template<typename T> class TrainIterator;
|
||||||
|
|
|
@ -318,7 +318,6 @@ struct Vehicle : SpriteBase
|
||||||
Vehicle* GetHead();
|
Vehicle* GetHead();
|
||||||
const Vehicle* GetHead() const;
|
const Vehicle* GetHead() const;
|
||||||
Vehicle* GetCar(size_t carIndex) const;
|
Vehicle* GetCar(size_t carIndex) const;
|
||||||
void Invalidate();
|
|
||||||
void SetState(Vehicle::Status vehicleStatus, uint8_t subState = 0);
|
void SetState(Vehicle::Status vehicleStatus, uint8_t subState = 0);
|
||||||
bool IsGhost() const;
|
bool IsGhost() const;
|
||||||
void UpdateSoundParams(std::vector<OpenRCT2::Audio::VehicleSoundParams>& vehicleSoundParamsList) const;
|
void UpdateSoundParams(std::vector<OpenRCT2::Audio::VehicleSoundParams>& vehicleSoundParamsList) const;
|
||||||
|
|
|
@ -104,9 +104,9 @@ namespace OpenRCT2::Scripting
|
||||||
auto entity = GetEntity();
|
auto entity = GetEntity();
|
||||||
if (entity != nullptr)
|
if (entity != nullptr)
|
||||||
{
|
{
|
||||||
entity->Invalidate2();
|
entity->Invalidate();
|
||||||
entity->MoveTo({ value, entity->y, entity->z });
|
entity->MoveTo({ value, entity->y, entity->z });
|
||||||
entity->Invalidate2();
|
entity->Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,9 +122,9 @@ namespace OpenRCT2::Scripting
|
||||||
auto entity = GetEntity();
|
auto entity = GetEntity();
|
||||||
if (entity != nullptr)
|
if (entity != nullptr)
|
||||||
{
|
{
|
||||||
entity->Invalidate2();
|
entity->Invalidate();
|
||||||
entity->MoveTo({ entity->x, value, entity->z });
|
entity->MoveTo({ entity->x, value, entity->z });
|
||||||
entity->Invalidate2();
|
entity->Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +140,9 @@ namespace OpenRCT2::Scripting
|
||||||
auto entity = GetEntity();
|
auto entity = GetEntity();
|
||||||
if (entity != nullptr)
|
if (entity != nullptr)
|
||||||
{
|
{
|
||||||
entity->Invalidate2();
|
entity->Invalidate();
|
||||||
entity->MoveTo({ entity->x, entity->y, value });
|
entity->MoveTo({ entity->x, entity->y, value });
|
||||||
entity->Invalidate2();
|
entity->Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ namespace OpenRCT2::Scripting
|
||||||
auto entity = GetEntity();
|
auto entity = GetEntity();
|
||||||
if (entity != nullptr)
|
if (entity != nullptr)
|
||||||
{
|
{
|
||||||
entity->Invalidate2();
|
entity->Invalidate();
|
||||||
switch (entity->sprite_identifier)
|
switch (entity->sprite_identifier)
|
||||||
{
|
{
|
||||||
case SpriteIdentifier::Vehicle:
|
case SpriteIdentifier::Vehicle:
|
||||||
|
|
|
@ -21,7 +21,7 @@ template<> bool SpriteBase::Is<Balloon>() const
|
||||||
|
|
||||||
void Balloon::Update()
|
void Balloon::Update()
|
||||||
{
|
{
|
||||||
Invalidate2();
|
Invalidate();
|
||||||
if (popped == 1)
|
if (popped == 1)
|
||||||
{
|
{
|
||||||
frame++;
|
frame++;
|
||||||
|
|
|
@ -71,11 +71,6 @@ template<> bool SpriteBase::Is<Duck>() const
|
||||||
return sprite_identifier == SpriteIdentifier::Misc && static_cast<MiscEntityType>(type) == MiscEntityType::Duck;
|
return sprite_identifier == SpriteIdentifier::Misc && static_cast<MiscEntityType>(type) == MiscEntityType::Duck;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Duck::Invalidate()
|
|
||||||
{
|
|
||||||
Invalidate1();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Duck::IsFlying()
|
bool Duck::IsFlying()
|
||||||
{
|
{
|
||||||
return this->state == DuckState::FlyAway || this->state == DuckState::FlyToWater;
|
return this->state == DuckState::FlyAway || this->state == DuckState::FlyToWater;
|
||||||
|
|
|
@ -403,7 +403,7 @@ void footpath_remove_litter(const CoordsXYZ& footpathPos)
|
||||||
int32_t distanceZ = abs(litter->z - footpathPos.z);
|
int32_t distanceZ = abs(litter->z - footpathPos.z);
|
||||||
if (distanceZ <= 32)
|
if (distanceZ <= 32)
|
||||||
{
|
{
|
||||||
litter->Invalidate0();
|
litter->Invalidate();
|
||||||
sprite_remove(litter);
|
sprite_remove(litter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,7 @@ void JumpingFountain::Update()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Invalidate0();
|
Invalidate();
|
||||||
frame++;
|
frame++;
|
||||||
|
|
||||||
switch (static_cast<MiscEntityType>(type))
|
switch (static_cast<MiscEntityType>(type))
|
||||||
|
|
|
@ -205,7 +205,7 @@ static bool map_animation_invalidate_small_scenery(const CoordsXYZ& loc)
|
||||||
peep->ActionFrame = 0;
|
peep->ActionFrame = 0;
|
||||||
peep->ActionSpriteImageOffset = 0;
|
peep->ActionSpriteImageOffset = 0;
|
||||||
peep->UpdateCurrentActionSpriteType();
|
peep->UpdateCurrentActionSpriteType();
|
||||||
peep->Invalidate1();
|
peep->Invalidate();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ void MoneyEffect::Create(money32 value, const CoordsXYZ& loc)
|
||||||
*/
|
*/
|
||||||
void MoneyEffect::Update()
|
void MoneyEffect::Update()
|
||||||
{
|
{
|
||||||
Invalidate2();
|
Invalidate();
|
||||||
Wiggle++;
|
Wiggle++;
|
||||||
if (Wiggle >= 22)
|
if (Wiggle >= 22)
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,7 +60,7 @@ void crashed_vehicle_particle_create(rct_vehicle_colour colours, const CoordsXYZ
|
||||||
*/
|
*/
|
||||||
void VehicleCrashParticle::Update()
|
void VehicleCrashParticle::Update()
|
||||||
{
|
{
|
||||||
Invalidate0();
|
Invalidate();
|
||||||
time_to_live--;
|
time_to_live--;
|
||||||
if (time_to_live == 0)
|
if (time_to_live == 0)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +107,7 @@ void VehicleCrashParticle::Update()
|
||||||
newLoc.z = landZ;
|
newLoc.z = landZ;
|
||||||
}
|
}
|
||||||
MoveTo(newLoc);
|
MoveTo(newLoc);
|
||||||
Invalidate0();
|
Invalidate();
|
||||||
|
|
||||||
frame += 85;
|
frame += 85;
|
||||||
if (frame >= 3072)
|
if (frame >= 3072)
|
||||||
|
@ -141,7 +141,7 @@ void crash_splash_create(const CoordsXYZ& splashPos)
|
||||||
*/
|
*/
|
||||||
void CrashSplashParticle::Update()
|
void CrashSplashParticle::Update()
|
||||||
{
|
{
|
||||||
Invalidate2();
|
Invalidate();
|
||||||
frame += 85;
|
frame += 85;
|
||||||
if (frame >= 7168)
|
if (frame >= 7168)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Copyright (c) 2014-2020 OpenRCT2 developers
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
||||||
*
|
*
|
||||||
* For a complete list of all authors, please refer to contributors.md
|
* For a complete list of all authors, please refer to contributors.md
|
||||||
|
@ -133,31 +133,47 @@ static void invalidate_sprite_max_zoom(SpriteBase* sprite, int32_t maxZoom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void SpriteBase::Invalidate()
|
||||||
* Invalidate the sprite if at closest zoom.
|
|
||||||
* rct2: 0x006EC60B
|
|
||||||
*/
|
|
||||||
void SpriteBase::Invalidate0()
|
|
||||||
{
|
{
|
||||||
invalidate_sprite_max_zoom(this, 0);
|
int32_t maxZoom = 0;
|
||||||
}
|
switch (sprite_identifier)
|
||||||
|
{
|
||||||
/**
|
case SpriteIdentifier::Vehicle:
|
||||||
* Invalidate sprite if at closest zoom or next zoom up from closest.
|
maxZoom = 2;
|
||||||
* rct2: 0x006EC53F
|
break;
|
||||||
*/
|
case SpriteIdentifier::Peep:
|
||||||
void SpriteBase::Invalidate1()
|
maxZoom = 0;
|
||||||
{
|
break;
|
||||||
invalidate_sprite_max_zoom(this, 1);
|
case SpriteIdentifier::Misc:
|
||||||
}
|
switch (static_cast<MiscEntityType>(type))
|
||||||
|
{
|
||||||
/**
|
case MiscEntityType::CrashedVehicleParticle:
|
||||||
* Invalidate sprite if not at furthest zoom.
|
case MiscEntityType::JumpingFountainWater:
|
||||||
* rct2: 0x006EC473
|
case MiscEntityType::JumpingFountainSnow:
|
||||||
*/
|
maxZoom = 0;
|
||||||
void SpriteBase::Invalidate2()
|
break;
|
||||||
{
|
case MiscEntityType::Duck:
|
||||||
invalidate_sprite_max_zoom(this, 2);
|
maxZoom = 1;
|
||||||
|
break;
|
||||||
|
case MiscEntityType::SteamParticle:
|
||||||
|
case MiscEntityType::MoneyEffect:
|
||||||
|
case MiscEntityType::ExplosionCloud:
|
||||||
|
case MiscEntityType::CrashSplash:
|
||||||
|
case MiscEntityType::ExplosionFlare:
|
||||||
|
case MiscEntityType::Balloon:
|
||||||
|
maxZoom = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SpriteIdentifier::Litter:
|
||||||
|
maxZoom = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
invalidate_sprite_max_zoom(this, maxZoom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -301,8 +317,8 @@ rct_sprite_checksum sprite_checksum()
|
||||||
copy.peep.Name = {};
|
copy.peep.Name = {};
|
||||||
|
|
||||||
// We set this to 0 because as soon the client selects a guest the window will remove the
|
// We set this to 0 because as soon the client selects a guest the window will remove the
|
||||||
// invalidation flags causing the sprite checksum to be different than on server, the flag does not affect
|
// invalidation flags causing the sprite checksum to be different than on server, the flag does not
|
||||||
// game state.
|
// affect game state.
|
||||||
copy.peep.WindowInvalidateFlags = 0;
|
copy.peep.WindowInvalidateFlags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,8 +514,8 @@ static void move_sprite_to_list(SpriteBase* sprite, EntityListId newListIndex)
|
||||||
|
|
||||||
sprite->next = gSpriteListHead[static_cast<uint8_t>(
|
sprite->next = gSpriteListHead[static_cast<uint8_t>(
|
||||||
newListIndex)]; // This sprite's next sprite is the old head, since we're the new head
|
newListIndex)]; // This sprite's next sprite is the old head, since we're the new head
|
||||||
gSpriteListHead[static_cast<uint8_t>(newListIndex)] = sprite->sprite_index; // Store this sprite's index as head of its new
|
gSpriteListHead[static_cast<uint8_t>(newListIndex)] = sprite->sprite_index; // Store this sprite's index as head of its
|
||||||
// list
|
// new list
|
||||||
|
|
||||||
if (sprite->next != SPRITE_INDEX_NULL)
|
if (sprite->next != SPRITE_INDEX_NULL)
|
||||||
{
|
{
|
||||||
|
@ -527,9 +543,8 @@ static void move_sprite_to_list(SpriteBase* sprite, EntityListId newListIndex)
|
||||||
*/
|
*/
|
||||||
void SteamParticle::Update()
|
void SteamParticle::Update()
|
||||||
{
|
{
|
||||||
Invalidate2();
|
|
||||||
|
|
||||||
// Move up 1 z every 3 ticks (Starts after 4 ticks)
|
// Move up 1 z every 3 ticks (Starts after 4 ticks)
|
||||||
|
Invalidate();
|
||||||
time_to_move++;
|
time_to_move++;
|
||||||
if (time_to_move >= 4)
|
if (time_to_move >= 4)
|
||||||
{
|
{
|
||||||
|
@ -568,7 +583,7 @@ void sprite_misc_explosion_cloud_create(const CoordsXYZ& cloudPos)
|
||||||
*/
|
*/
|
||||||
void ExplosionCloud::Update()
|
void ExplosionCloud::Update()
|
||||||
{
|
{
|
||||||
Invalidate2();
|
Invalidate();
|
||||||
frame += 128;
|
frame += 128;
|
||||||
if (frame >= (36 * 128))
|
if (frame >= (36 * 128))
|
||||||
{
|
{
|
||||||
|
@ -601,7 +616,7 @@ void sprite_misc_explosion_flare_create(const CoordsXYZ& flarePos)
|
||||||
*/
|
*/
|
||||||
void ExplosionFlare::Update()
|
void ExplosionFlare::Update()
|
||||||
{
|
{
|
||||||
Invalidate2();
|
Invalidate();
|
||||||
frame += 64;
|
frame += 64;
|
||||||
if (frame >= (124 * 64))
|
if (frame >= (124 * 64))
|
||||||
{
|
{
|
||||||
|
@ -725,6 +740,12 @@ static void SpriteSpatialMove(SpriteBase* sprite, const CoordsXY& newLoc)
|
||||||
*/
|
*/
|
||||||
void SpriteBase::MoveTo(const CoordsXYZ& newLocation)
|
void SpriteBase::MoveTo(const CoordsXYZ& newLocation)
|
||||||
{
|
{
|
||||||
|
if (x != LOCATION_NULL)
|
||||||
|
{
|
||||||
|
// Invalidate old position.
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
auto loc = newLocation;
|
auto loc = newLocation;
|
||||||
if (!map_is_location_valid(loc))
|
if (!map_is_location_valid(loc))
|
||||||
{
|
{
|
||||||
|
@ -743,6 +764,7 @@ void SpriteBase::MoveTo(const CoordsXYZ& newLocation)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sprite_set_coordinates(loc, this);
|
sprite_set_coordinates(loc, this);
|
||||||
|
Invalidate(); // Invalidate new position.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -833,7 +855,7 @@ void litter_create(const CoordsXYZD& litterPos, int32_t type)
|
||||||
|
|
||||||
if (newestLitter != nullptr)
|
if (newestLitter != nullptr)
|
||||||
{
|
{
|
||||||
newestLitter->Invalidate0();
|
newestLitter->Invalidate();
|
||||||
sprite_remove(newestLitter);
|
sprite_remove(newestLitter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -849,7 +871,6 @@ void litter_create(const CoordsXYZD& litterPos, int32_t type)
|
||||||
litter->sprite_identifier = SpriteIdentifier::Litter;
|
litter->sprite_identifier = SpriteIdentifier::Litter;
|
||||||
litter->type = type;
|
litter->type = type;
|
||||||
litter->MoveTo(offsetLitterPos);
|
litter->MoveTo(offsetLitterPos);
|
||||||
litter->Invalidate0();
|
|
||||||
litter->creationTick = gScenarioTicks;
|
litter->creationTick = gScenarioTicks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,7 +886,7 @@ void litter_remove_at(const CoordsXYZ& litterPos)
|
||||||
{
|
{
|
||||||
if (abs(litter->x - litterPos.x) <= 8 && abs(litter->y - litterPos.y) <= 8)
|
if (abs(litter->x - litterPos.x) <= 8 && abs(litter->y - litterPos.y) <= 8)
|
||||||
{
|
{
|
||||||
litter->Invalidate0();
|
litter->Invalidate();
|
||||||
sprite_remove(litter);
|
sprite_remove(litter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -966,7 +987,7 @@ void sprite_position_tween_all(float alpha)
|
||||||
static_cast<int32_t>(std::round(posB.y * alpha + posA.y * inv)),
|
static_cast<int32_t>(std::round(posB.y * alpha + posA.y * inv)),
|
||||||
static_cast<int32_t>(std::round(posB.z * alpha + posA.z * inv)) },
|
static_cast<int32_t>(std::round(posB.z * alpha + posA.z * inv)) },
|
||||||
sprite);
|
sprite);
|
||||||
sprite->Invalidate2();
|
sprite->Invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -981,7 +1002,7 @@ void sprite_position_tween_restore()
|
||||||
auto* sprite = GetEntity(i);
|
auto* sprite = GetEntity(i);
|
||||||
if (sprite != nullptr && sprite_should_tween(sprite))
|
if (sprite != nullptr && sprite_should_tween(sprite))
|
||||||
{
|
{
|
||||||
sprite->Invalidate2();
|
sprite->Invalidate();
|
||||||
|
|
||||||
auto pos = _spritelocations2[i];
|
auto pos = _spritelocations2[i];
|
||||||
sprite_set_coordinates(pos, sprite);
|
sprite_set_coordinates(pos, sprite);
|
||||||
|
|
|
@ -71,7 +71,6 @@ struct Duck : SpriteGeneric
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
uint32_t GetFrameImage(int32_t direction) const;
|
uint32_t GetFrameImage(int32_t direction) const;
|
||||||
void Invalidate();
|
|
||||||
bool IsFlying();
|
bool IsFlying();
|
||||||
void Remove();
|
void Remove();
|
||||||
|
|
||||||
|
|
|
@ -35,9 +35,7 @@ struct SpriteBase
|
||||||
uint8_t sprite_direction;
|
uint8_t sprite_direction;
|
||||||
|
|
||||||
void MoveTo(const CoordsXYZ& newLocation);
|
void MoveTo(const CoordsXYZ& newLocation);
|
||||||
void Invalidate0();
|
void Invalidate();
|
||||||
void Invalidate1();
|
|
||||||
void Invalidate2();
|
|
||||||
template<typename T> bool Is() const;
|
template<typename T> bool Is() const;
|
||||||
template<typename T> T* As()
|
template<typename T> T* As()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue