- Refactored SBarInfo flow control so negatable commands are handled statically.

- Made TArray movable and TDeletingArray a move only type.
This commit is contained in:
Braden Obrzut 2016-04-02 23:11:59 -04:00
parent 1648a71e45
commit 81f29556bf
4 changed files with 137 additions and 163 deletions

View file

@ -206,67 +206,31 @@ class SBarInfoCommandFlowControl : public SBarInfoCommand
{ {
public: public:
SBarInfoCommandFlowControl(SBarInfo *script) : SBarInfoCommand(script), truth(false) {} SBarInfoCommandFlowControl(SBarInfo *script) : SBarInfoCommand(script), truth(false) {}
~SBarInfoCommandFlowControl()
{
for(unsigned int i = 0;i < 2;i++)
{
for(unsigned int j = 0;j < commands[i].Size();j++)
delete commands[i][j];
}
}
void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar) void Draw(const SBarInfoMainBlock *block, const DSBarInfo *statusBar)
{ {
for(unsigned int i = 0;i < commands[truth].Size();i++) for(auto command : commands[truth])
commands[truth][i]->Draw(block, statusBar); command->Draw(block, statusBar);
} }
int NumCommands() const { return commands[truth].Size(); } int NumCommands() const { return commands[truth].Size(); }
void Parse(FScanner &sc, bool fullScreenOffsets) void Parse(FScanner &sc, bool fullScreenOffsets)
{ {
bool elseBlock = false; ParseBlock(commands[1], sc, fullScreenOffsets);
SBarInfoCommand *cmd = NULL; if(sc.CheckToken(TK_Else))
// Should loop no more than twice. ParseBlock(commands[0], sc, fullScreenOffsets);
while(true)
{
if(sc.CheckToken('{'))
{
while((cmd = NextCommand(sc)) != NULL)
{
cmd->Parse(sc, fullScreenOffsets);
commands[!elseBlock].Push(cmd);
}
}
else
{
if((cmd = NextCommand(sc)) != NULL)
{
cmd->Parse(sc, fullScreenOffsets);
commands[!elseBlock].Push(cmd);
}
else
sc.ScriptError("Missing command for flow control statement.");
}
if(!elseBlock && sc.CheckToken(TK_Else))
{
elseBlock = true;
continue;
}
break;
}
} }
void Reset() void Reset()
{ {
for(unsigned int i = 0;i < 2;i++) for(unsigned int i = 0;i < 2;i++)
{ {
for(unsigned int j = 0;j < commands[i].Size();j++) for(auto command : commands[i])
commands[i][j]->Reset(); command->Reset();
} }
} }
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{ {
for(unsigned int i = 0;i < commands[truth].Size();i++) for(auto command : commands[truth])
commands[truth][i]->Tick(block, statusBar, hudChanged); command->Tick(block, statusBar, hudChanged);
} }
protected: protected:
@ -283,11 +247,65 @@ class SBarInfoCommandFlowControl : public SBarInfoCommand
Tick(block, statusBar, true); Tick(block, statusBar, true);
} }
void Negate()
{
swapvalues(commands[0], commands[1]);
}
private: private:
void ParseBlock(TDeletingArray<SBarInfoCommand *> &commands, FScanner &sc, bool fullScreenOffsets)
{
if(sc.CheckToken('{'))
{
while(SBarInfoCommand *cmd = NextCommand(sc))
{
cmd->Parse(sc, fullScreenOffsets);
commands.Push(cmd);
}
}
else
{
if(SBarInfoCommand *cmd = NextCommand(sc))
{
cmd->Parse(sc, fullScreenOffsets);
commands.Push(cmd);
}
else
sc.ScriptError("Missing command for flow control statement.");
}
}
SBarInfoCommand *NextCommand(FScanner &sc); SBarInfoCommand *NextCommand(FScanner &sc);
bool truth; TDeletingArray<SBarInfoCommand *> commands[2];
TArray<SBarInfoCommand *> commands[2]; bool truth;
};
class SBarInfoNegatableFlowControl : public SBarInfoCommandFlowControl
{
public:
SBarInfoNegatableFlowControl(SBarInfo *script) : SBarInfoCommandFlowControl(script) {}
void Parse(FScanner &sc, bool fullScreenOffsets)
{
bool negate = false;
if(sc.CheckToken(TK_Identifier))
{
if(sc.Compare("not"))
negate = true;
else
sc.UnGet();
}
ParseNegatable(sc, fullScreenOffsets);
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
if(negate)
Negate();
}
virtual void ParseNegatable(FScanner &sc, bool fullScreenOffsets) {}
}; };
class SBarInfoMainBlock : public SBarInfoCommandFlowControl class SBarInfoMainBlock : public SBarInfoCommandFlowControl

View file

@ -1830,33 +1830,17 @@ const char* const CommandGameMode::modeNames[] =
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class CommandUsesAmmo : public SBarInfoCommandFlowControl class CommandUsesAmmo : public SBarInfoNegatableFlowControl
{ {
public: public:
CommandUsesAmmo(SBarInfo *script) : SBarInfoCommandFlowControl(script), CommandUsesAmmo(SBarInfo *script) : SBarInfoNegatableFlowControl(script) {}
negate(false)
{
}
void Parse(FScanner &sc, bool fullScreenOffsets)
{
if(sc.CheckToken(TK_Identifier))
{
if(sc.Compare("not"))
negate = true;
else
sc.ScriptError("Expected 'not', but got '%s' instead.", sc.String);
}
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
}
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{ {
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged);
SetTruth((statusBar->CPlayer->ReadyWeapon != NULL && (statusBar->CPlayer->ReadyWeapon->AmmoType1 != NULL || statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL)) ^ negate, block, statusBar); SetTruth(statusBar->CPlayer->ReadyWeapon != NULL && (statusBar->CPlayer->ReadyWeapon->AmmoType1 != NULL || statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL), block, statusBar);
} }
protected:
bool negate;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1872,7 +1856,7 @@ class CommandUsesSecondaryAmmo : public CommandUsesAmmo
{ {
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged);
SetTruth((statusBar->CPlayer->ReadyWeapon != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType1 != statusBar->CPlayer->ReadyWeapon->AmmoType2) ^ negate, block, statusBar); SetTruth(statusBar->CPlayer->ReadyWeapon != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType2 != NULL && statusBar->CPlayer->ReadyWeapon->AmmoType1 != statusBar->CPlayer->ReadyWeapon->AmmoType2, block, statusBar);
} }
}; };
@ -2890,28 +2874,18 @@ class CommandDrawBar : public SBarInfoCommand
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class CommandIsSelected : public SBarInfoCommandFlowControl class CommandIsSelected : public SBarInfoNegatableFlowControl
{ {
public: public:
CommandIsSelected(SBarInfo *script) : SBarInfoCommandFlowControl(script), CommandIsSelected(SBarInfo *script) : SBarInfoNegatableFlowControl(script)
negate(false)
{ {
weapon[0] = NULL; weapon[0] = NULL;
weapon[1] = NULL; weapon[1] = NULL;
} }
void Parse(FScanner &sc, bool fullScreenOffsets) void ParseNegatable(FScanner &sc, bool fullScreenOffsets)
{ {
if(sc.CheckToken(TK_Identifier)) if(!sc.CheckToken(TK_Identifier))
{
if(sc.Compare("not"))
{
negate = true;
if(!sc.CheckToken(TK_StringConst))
sc.MustGetToken(TK_Identifier);
}
}
else
sc.MustGetToken(TK_StringConst); sc.MustGetToken(TK_StringConst);
for(int i = 0;i < 2;i++) for(int i = 0;i < 2;i++)
{ {
@ -2930,24 +2904,18 @@ class CommandIsSelected : public SBarInfoCommandFlowControl
else else
break; break;
} }
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
} }
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{ {
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged);
if(statusBar->CPlayer->ReadyWeapon != NULL) if(statusBar->CPlayer->ReadyWeapon != NULL)
{ {
const PClass *readyWeapon = statusBar->CPlayer->ReadyWeapon->GetClass(); const PClass *readyWeapon = statusBar->CPlayer->ReadyWeapon->GetClass();
SetTruth(((weapon[1] != NULL) && SetTruth(weapon[0] == readyWeapon || (weapon[1] && weapon[1] == readyWeapon), block, statusBar);
((negate && (weapon[0] != readyWeapon && weapon[1] != readyWeapon)) ||
(!negate && (weapon[0] == readyWeapon || weapon[1] == readyWeapon)))) ||
((weapon[1] == NULL) &&
((!negate && weapon[0] == readyWeapon) || (negate && weapon[0] != readyWeapon))), block, statusBar);
} }
} }
protected: protected:
bool negate;
const PClass *weapon[2]; const PClass *weapon[2];
}; };
@ -3245,26 +3213,20 @@ FRandom CommandDrawGem::pr_chainwiggle; //use the same method of chain wiggling
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class CommandWeaponAmmo : public SBarInfoCommandFlowControl class CommandWeaponAmmo : public SBarInfoNegatableFlowControl
{ {
public: public:
CommandWeaponAmmo(SBarInfo *script) : SBarInfoCommandFlowControl(script), CommandWeaponAmmo(SBarInfo *script) : SBarInfoNegatableFlowControl(script),
conditionAnd(false), negate(false) conditionAnd(false)
{ {
ammo[0] = NULL; ammo[0] = NULL;
ammo[1] = NULL; ammo[1] = NULL;
} }
void Parse(FScanner &sc, bool fullScreenOffsets) void ParseNegatable(FScanner &sc, bool fullScreenOffsets)
{ {
if(!sc.CheckToken(TK_StringConst)) if(!sc.CheckToken(TK_StringConst))
sc.MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
if(sc.Compare("not") && sc.TokenType == TK_Identifier)
{
negate = true;
if(!sc.CheckToken(TK_StringConst))
sc.MustGetToken(TK_Identifier);
}
for(int i = 0;i < 2;i++) for(int i = 0;i < 2;i++)
{ {
ammo[i] = PClass::FindClass(sc.String); ammo[i] = PClass::FindClass(sc.String);
@ -3289,11 +3251,10 @@ class CommandWeaponAmmo : public SBarInfoCommandFlowControl
else else
break; break;
} }
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
} }
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{ {
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged);
if(statusBar->CPlayer->ReadyWeapon != NULL) if(statusBar->CPlayer->ReadyWeapon != NULL)
{ {
@ -3301,41 +3262,25 @@ class CommandWeaponAmmo : public SBarInfoCommandFlowControl
const PClass *AmmoType2 = statusBar->CPlayer->ReadyWeapon->AmmoType2; const PClass *AmmoType2 = statusBar->CPlayer->ReadyWeapon->AmmoType2;
bool usesammo1 = (AmmoType1 != NULL); bool usesammo1 = (AmmoType1 != NULL);
bool usesammo2 = (AmmoType2 != NULL); bool usesammo2 = (AmmoType2 != NULL);
if(negate && !usesammo1 && !usesammo2) //if the weapon doesn't use ammo don't go though the trouble. //if(!usesammo1 && !usesammo2) //if the weapon doesn't use ammo don't go though the trouble.
{ //{
SetTruth(true, block, statusBar); // SetTruth(false, block, statusBar);
return; // return;
} //}
//Or means only 1 ammo type needs to match and means both need to match. //Or means only 1 ammo type needs to match and means both need to match.
if(ammo[1] != NULL) if(ammo[1] != NULL)
{ {
bool match1 = ((usesammo1 && (AmmoType1 == ammo[0] || AmmoType1 == ammo[1])) || !usesammo1); bool match1 = ((usesammo1 && (AmmoType1 == ammo[0] || AmmoType1 == ammo[1])) || !usesammo1);
bool match2 = ((usesammo2 && (AmmoType2 == ammo[0] || AmmoType2 == ammo[1])) || !usesammo2); bool match2 = ((usesammo2 && (AmmoType2 == ammo[0] || AmmoType2 == ammo[1])) || !usesammo2);
if((!conditionAnd && (match1 || match2)) || (conditionAnd && (match1 && match2))) if((!conditionAnd && (match1 || match2)) || (conditionAnd && (match1 && match2)))
{
if(!negate)
{
SetTruth(true, block, statusBar);
return;
}
}
else if(negate)
{ {
SetTruth(true, block, statusBar); SetTruth(true, block, statusBar);
return; return;
} }
} }
else //Every thing here could probably be one long if statement but then it would be more confusing. else
{ {
if((usesammo1 && (AmmoType1 == ammo[0])) || (usesammo2 && (AmmoType2 == ammo[0]))) if((usesammo1 && (AmmoType1 == ammo[0])) || (usesammo2 && (AmmoType2 == ammo[0])))
{
if(!negate)
{
SetTruth(true, block, statusBar);
return;
}
}
else if(negate)
{ {
SetTruth(true, block, statusBar); SetTruth(true, block, statusBar);
return; return;
@ -3345,33 +3290,26 @@ class CommandWeaponAmmo : public SBarInfoCommandFlowControl
SetTruth(false, block, statusBar); SetTruth(false, block, statusBar);
} }
protected: protected:
bool conditionAnd;
bool negate;
const PClass *ammo[2]; const PClass *ammo[2];
bool conditionAnd;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class CommandInInventory : public SBarInfoCommandFlowControl class CommandInInventory : public SBarInfoNegatableFlowControl
{ {
public: public:
CommandInInventory(SBarInfo *script) : SBarInfoCommandFlowControl(script), CommandInInventory(SBarInfo *script) : SBarInfoNegatableFlowControl(script),
conditionAnd(false), negate(false) conditionAnd(false)
{ {
item[0] = item[1] = NULL; item[0] = item[1] = NULL;
amount[0] = amount[1] = 0; amount[0] = amount[1] = 0;
} }
void Parse(FScanner &sc, bool fullScreenOffsets) void ParseNegatable(FScanner &sc, bool fullScreenOffsets)
{ {
if(!sc.CheckToken(TK_StringConst)) if(!sc.CheckToken(TK_StringConst))
sc.MustGetToken(TK_Identifier); sc.MustGetToken(TK_Identifier);
if(sc.Compare("not") && sc.TokenType == TK_Identifier)
{
negate = true;
if(!sc.CheckToken(TK_StringConst))
sc.MustGetToken(TK_Identifier);
}
for(int i = 0;i < 2;i++) for(int i = 0;i < 2;i++)
{ {
item[i] = PClass::FindActor(sc.String); item[i] = PClass::FindActor(sc.String);
@ -3402,11 +3340,10 @@ class CommandInInventory : public SBarInfoCommandFlowControl
else else
break; break;
} }
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
} }
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{ {
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged);
AInventory *invItem[2] = { statusBar->CPlayer->mo->FindInventory(item[0]), statusBar->CPlayer->mo->FindInventory(item[1]) }; AInventory *invItem[2] = { statusBar->CPlayer->mo->FindInventory(item[0]), statusBar->CPlayer->mo->FindInventory(item[1]) };
if (invItem[0] != NULL && amount[0] > 0 && invItem[0]->Amount < amount[0]) invItem[0] = NULL; if (invItem[0] != NULL && amount[0] > 0 && invItem[0]->Amount < amount[0]) invItem[0] = NULL;
@ -3415,16 +3352,15 @@ class CommandInInventory : public SBarInfoCommandFlowControl
if (item[1]) if (item[1])
{ {
if (conditionAnd) if (conditionAnd)
SetTruth((invItem[0] && invItem[1]) != negate, block, statusBar); SetTruth(invItem[0] && invItem[1], block, statusBar);
else else
SetTruth((invItem[0] || invItem[1]) != negate, block, statusBar); SetTruth(invItem[0] || invItem[1], block, statusBar);
} }
else else
SetTruth((invItem[0] != NULL) != negate, block, statusBar); SetTruth(invItem[0] != NULL, block, statusBar);
} }
protected: protected:
bool conditionAnd; bool conditionAnd;
bool negate;
PClassActor *item[2]; PClassActor *item[2];
int amount[2]; int amount[2];
}; };
@ -3459,42 +3395,31 @@ class CommandAlpha : public SBarInfoMainBlock
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
class CommandIfHealth : public SBarInfoCommandFlowControl class CommandIfHealth : public SBarInfoNegatableFlowControl
{ {
public: public:
CommandIfHealth(SBarInfo *script) : SBarInfoCommandFlowControl(script), CommandIfHealth(SBarInfo *script) : SBarInfoNegatableFlowControl(script),
negate(false), percentage(false) percentage(false)
{ {
} }
void Parse(FScanner &sc, bool fullScreenOffsets) void ParseNegatable(FScanner &sc, bool fullScreenOffsets)
{ {
if (sc.CheckToken(TK_Identifier))
{
if (sc.Compare("not"))
negate = true;
else
sc.ScriptError("Expected 'not', but got '%s' instead.", sc.String);
}
sc.MustGetToken(TK_IntConst); sc.MustGetToken(TK_IntConst);
percentage = sc.CheckToken('%'); percentage = sc.CheckToken('%');
hpamount = sc.Number; hpamount = sc.Number;
SBarInfoCommandFlowControl::Parse(sc, fullScreenOffsets);
} }
void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged) void Tick(const SBarInfoMainBlock *block, const DSBarInfo *statusBar, bool hudChanged)
{ {
SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); SBarInfoNegatableFlowControl::Tick(block, statusBar, hudChanged);
int phealth = percentage ? statusBar->CPlayer->mo->health * 100 / statusBar->CPlayer->mo->GetMaxHealth() : statusBar->CPlayer->mo->health; int phealth = percentage ? statusBar->CPlayer->mo->health * 100 / statusBar->CPlayer->mo->GetMaxHealth() : statusBar->CPlayer->mo->health;
SetTruth((phealth >= hpamount) ^ negate, block, statusBar); SetTruth(phealth >= hpamount, block, statusBar);
} }
protected: protected:
bool negate;
bool percentage;
int hpamount; int hpamount;
bool percentage;
}; };
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -39,6 +39,7 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <new> #include <new>
#include <utility>
#if !defined(_WIN32) #if !defined(_WIN32)
#include <inttypes.h> // for intptr_t #include <inttypes.h> // for intptr_t
@ -137,11 +138,17 @@ public:
Count = 0; Count = 0;
Array = (T *)M_Malloc (sizeof(T)*max); Array = (T *)M_Malloc (sizeof(T)*max);
} }
TArray (const TArray<T> &other) TArray (const TArray<T,TT> &other)
{ {
DoCopy (other); DoCopy (other);
} }
TArray<T> &operator= (const TArray<T> &other) TArray (TArray<T,TT> &&other)
{
Array = other.Array; other.Array = NULL;
Most = other.Most; other.Most = 0;
Count = other.Count; other.Count = 0;
}
TArray<T,TT> &operator= (const TArray<T,TT> &other)
{ {
if (&other != this) if (&other != this)
{ {
@ -157,6 +164,21 @@ public:
} }
return *this; return *this;
} }
TArray<T,TT> &operator= (TArray<T,TT> &&other)
{
if (Array)
{
if (Count > 0)
{
DoDelete (0, Count-1);
}
M_Free (Array);
}
Array = other.Array; other.Array = NULL;
Most = other.Most; other.Most = 0;
Count = other.Count; other.Count = 0;
return *this;
}
~TArray () ~TArray ()
{ {
if (Array) if (Array)
@ -417,6 +439,14 @@ template<class T, class TT=T>
class TDeletingArray : public TArray<T, TT> class TDeletingArray : public TArray<T, TT>
{ {
public: public:
TDeletingArray() : TArray<T,TT>() {}
TDeletingArray(TDeletingArray<T,TT> &&other) : TArray<T,TT>(std::move(other)) {}
TDeletingArray<T,TT> &operator=(TDeletingArray<T,TT> &&other)
{
TArray<T,TT>::operator=(std::move(other));
return *this;
}
~TDeletingArray<T, TT> () ~TDeletingArray<T, TT> ()
{ {
for (unsigned int i = 0; i < TArray<T,TT>::Size(); ++i) for (unsigned int i = 0; i < TArray<T,TT>::Size(); ++i)

View file

@ -40,6 +40,7 @@
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <utility>
//========================================================================== //==========================================================================
// //
@ -204,7 +205,7 @@ template<class T>
inline inline
void swapvalues (T &a, T &b) void swapvalues (T &a, T &b)
{ {
T temp = a; a = b; b = temp; T temp = std::move(a); a = std::move(b); b = std::move(temp);
} }
#endif //__TEMPLATES_H__ #endif //__TEMPLATES_H__