This commit is contained in:
Rachael Alexanderson 2017-03-02 04:22:32 -05:00
commit d84ba4b953
14 changed files with 245 additions and 23 deletions

View file

@ -210,6 +210,9 @@ struct FCommandBuffer
unsigned CursorPos; unsigned CursorPos;
unsigned StartPos; // First character to display unsigned StartPos; // First character to display
FString YankBuffer; // Deleted text buffer
bool AppendToYankBuffer; // Append consecutive deletes to buffer
FCommandBuffer() FCommandBuffer()
{ {
CursorPos = StartPos = 0; CursorPos = StartPos = 0;
@ -282,6 +285,30 @@ struct FCommandBuffer
StartPos = MAX(0, n); StartPos = MAX(0, n);
} }
unsigned WordBoundaryRight()
{
unsigned index = CursorPos;
while (index < Text.Len() && Text[index] == ' ') {
index++;
}
while (index < Text.Len() && Text[index] != ' ') {
index++;
}
return index;
}
unsigned WordBoundaryLeft()
{
int index = CursorPos - 1;
while (index > -1 && Text[index] == ' ') {
index--;
}
while (index > -1 && Text[index] != ' ') {
index--;
}
return (unsigned)index + 1;
}
void CursorStart() void CursorStart()
{ {
CursorPos = 0; CursorPos = 0;
@ -313,6 +340,18 @@ struct FCommandBuffer
} }
} }
void CursorWordLeft()
{
CursorPos = WordBoundaryLeft();
MakeStartPosGood();
}
void CursorWordRight()
{
CursorPos = WordBoundaryRight();
MakeStartPosGood();
}
void DeleteLeft() void DeleteLeft()
{ {
if (CursorPos > 0) if (CursorPos > 0)
@ -332,6 +371,50 @@ struct FCommandBuffer
} }
} }
void DeleteWordLeft()
{
if (CursorPos > 0)
{
unsigned index = WordBoundaryLeft();
if (AppendToYankBuffer) {
YankBuffer = FString(&Text[index], CursorPos - index) + YankBuffer;
} else {
YankBuffer = FString(&Text[index], CursorPos - index);
}
Text.Remove(index, CursorPos - index);
CursorPos = index;
MakeStartPosGood();
}
}
void DeleteLineLeft()
{
if (CursorPos > 0)
{
if (AppendToYankBuffer) {
YankBuffer = FString(&Text[0], CursorPos) + YankBuffer;
} else {
YankBuffer = FString(&Text[0], CursorPos);
}
Text.Remove(0, CursorPos);
CursorStart();
}
}
void DeleteLineRight()
{
if (CursorPos < Text.Len())
{
if (AppendToYankBuffer) {
YankBuffer += FString(&Text[CursorPos], Text.Len() - CursorPos);
} else {
YankBuffer = FString(&Text[CursorPos], Text.Len() - CursorPos);
}
Text.Truncate(CursorPos);
CursorEnd();
}
}
void AddChar(int character) void AddChar(int character)
{ {
///FIXME: Not Unicode-aware ///FIXME: Not Unicode-aware
@ -1349,6 +1432,7 @@ DEFINE_ACTION_FUNCTION(_Console, Printf)
static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer) static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
{ {
int data1 = ev->data1; int data1 = ev->data1;
bool keepappending = false;
switch (ev->subtype) switch (ev->subtype)
{ {
@ -1356,8 +1440,22 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
return false; return false;
case EV_GUI_Char: case EV_GUI_Char:
if (ev->data2)
{
// Bash-style shortcuts
if (data1 == 'b')
{
buffer.CursorWordLeft();
break;
}
else if (data1 == 'f')
{
buffer.CursorWordRight();
break;
}
}
// Add keypress to command line // Add keypress to command line
buffer.AddChar(ev->data1); buffer.AddChar(data1);
HistPos = NULL; HistPos = NULL;
TabbedLast = false; TabbedLast = false;
TabbedList = false; TabbedList = false;
@ -1658,6 +1756,56 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
break; break;
} }
break; break;
// Bash-style shortcuts
case 'A':
if (ev->data3 & GKM_CTRL)
{
buffer.CursorStart();
}
break;
case 'E':
if (ev->data3 & GKM_CTRL)
{
buffer.CursorEnd();
}
break;
case 'W':
if (ev->data3 & GKM_CTRL)
{
buffer.DeleteWordLeft();
keepappending = true;
TabbedLast = false;
TabbedList = false;
}
break;
case 'U':
if (ev->data3 & GKM_CTRL)
{
buffer.DeleteLineLeft();
keepappending = true;
TabbedLast = false;
TabbedList = false;
}
break;
case 'K':
if (ev->data3 & GKM_CTRL)
{
buffer.DeleteLineRight();
keepappending = true;
TabbedLast = false;
TabbedList = false;
}
break;
case 'Y':
if (ev->data3 & GKM_CTRL)
{
buffer.AddString(buffer.YankBuffer);
TabbedLast = false;
TabbedList = false;
HistPos = NULL;
}
break;
} }
break; break;
@ -1668,6 +1816,9 @@ static bool C_HandleKey (event_t *ev, FCommandBuffer &buffer)
break; break;
#endif #endif
} }
buffer.AppendToYankBuffer = keepappending;
// Ensure that the cursor is always visible while typing // Ensure that the cursor is always visible while typing
CursorTicker = C_BLINKRATE; CursorTicker = C_BLINKRATE;
cursoron = 1; cursoron = 1;

View file

@ -86,6 +86,7 @@ enum
CP_SETTHINGZ, CP_SETTHINGZ,
CP_SETTAG, CP_SETTAG,
CP_SETTHINGFLAGS, CP_SETTHINGFLAGS,
CP_SETVERTEX,
}; };
// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
@ -345,6 +346,18 @@ void ParseCompatibility()
sc.MustGetNumber(); sc.MustGetNumber();
CompatParams.Push(sc.Number); CompatParams.Push(sc.Number);
} }
else if (sc.Compare("setvertex"))
{
if (flags.ExtCommandIndex == ~0u) flags.ExtCommandIndex = CompatParams.Size();
CompatParams.Push(CP_SETVERTEX);
sc.MustGetNumber();
CompatParams.Push(sc.Number);
sc.MustGetFloat();
CompatParams.Push(int(sc.Float * 256)); // do not use full fixed here so that it can eventually handle larger levels
sc.MustGetFloat();
CompatParams.Push(int(sc.Float * 256)); // do not use full fixed here so that it can eventually handle larger levels
flags.CompatFlags[SLOT_BCOMPAT] |= BCOMPATF_REBUILDNODES;
}
else else
{ {
sc.UnGet(); sc.UnGet();
@ -600,6 +613,16 @@ void SetCompatibilityParams()
i += 3; i += 3;
break; break;
} }
case CP_SETVERTEX:
{
if ((unsigned)CompatParams[i + 1] < level.vertexes.Size())
{
level.vertexes[CompatParams[i + 1]].p.X = CompatParams[i + 2] / 256.;
level.vertexes[CompatParams[i + 1]].p.Y = CompatParams[i + 3] / 256.;
}
i += 4;
break;
}
} }
} }
} }

View file

@ -2307,7 +2307,7 @@ void PStruct::WriteFields(FSerializer &ar, const void *addr, const TArray<PField
{ {
const PField *field = fields[i]; const PField *field = fields[i];
// Skip fields without or with native serialization // Skip fields without or with native serialization
if (!(field->Flags & VARF_Transient)) if (!(field->Flags & (VARF_Transient|VARF_Meta)))
{ {
field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const BYTE *)addr + field->Offset); field->Type->WriteValue(ar, field->SymbolName.GetChars(), (const BYTE *)addr + field->Offset);
} }
@ -2340,6 +2340,11 @@ bool PStruct::ReadFields(FSerializer &ar, void *addr) const
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n", DPrintf(DMSG_ERROR, "Symbol %s in %s is not a field\n",
label, TypeName.GetChars()); label, TypeName.GetChars());
} }
else if ((static_cast<const PField *>(sym)->Flags & (VARF_Transient | VARF_Meta)))
{
DPrintf(DMSG_ERROR, "Symbol %s in %s is not a serializable field\n",
label, TypeName.GetChars());
}
else else
{ {
readsomething |= static_cast<const PField *>(sym)->Type->ReadValue(ar, nullptr, readsomething |= static_cast<const PField *>(sym)->Type->ReadValue(ar, nullptr,
@ -2638,7 +2643,7 @@ static void RecurseWriteFields(const PClass *type, FSerializer &ar, const void *
// Don't write this part if it has no non-transient variables // Don't write this part if it has no non-transient variables
for (unsigned i = 0; i < type->Fields.Size(); ++i) for (unsigned i = 0; i < type->Fields.Size(); ++i)
{ {
if (!(type->Fields[i]->Flags & VARF_Transient)) if (!(type->Fields[i]->Flags & (VARF_Transient|VARF_Meta)))
{ {
// Tag this section with the class it came from in case // Tag this section with the class it came from in case
// a more-derived class has variables that shadow a less- // a more-derived class has variables that shadow a less-
@ -3397,7 +3402,6 @@ PClass *PClass::FindClassTentative(FName name)
PClass *type = static_cast<PClass *>(GetClass()->CreateNew()); PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); DPrintf(DMSG_SPAMMY, "Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
assert(MetaSize == 0);
Derive(type, name); Derive(type, name);
type->Size = TentativeClass; type->Size = TentativeClass;
TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket); TypeTable.AddType(type, RUNTIME_CLASS(PClass), 0, name, bucket);

View file

@ -203,7 +203,8 @@ void ADynamicLight::Activate(AActor *activator)
float pulseTime = specialf1 / TICRATE; float pulseTime = specialf1 / TICRATE;
m_lastUpdate = level.maptime; m_lastUpdate = level.maptime;
m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime); if (!swapped) m_cycler.SetParams(float(args[LIGHT_SECONDARY_INTENSITY]), float(args[LIGHT_INTENSITY]), pulseTime);
else m_cycler.SetParams(float(args[LIGHT_INTENSITY]), float(args[LIGHT_SECONDARY_INTENSITY]), pulseTime);
m_cycler.ShouldCycle(true); m_cycler.ShouldCycle(true);
m_cycler.SetCycleType(CYCLE_Sin); m_cycler.SetCycleType(CYCLE_Sin);
m_currentRadius = m_cycler.GetVal(); m_currentRadius = m_cycler.GetVal();

View file

@ -135,6 +135,16 @@ public:
void SetDontLightSelf(bool add) { m_dontlightself = add; } void SetDontLightSelf(bool add) { m_dontlightself = add; }
void SetAttenuate(bool on) { m_attenuate = on; } void SetAttenuate(bool on) { m_attenuate = on; }
void SetHalo(bool halo) { m_halo = halo; } void SetHalo(bool halo) { m_halo = halo; }
void OrderIntensities()
{
if (m_Args[LIGHT_INTENSITY] > m_Args[LIGHT_SECONDARY_INTENSITY])
{
std::swap(m_Args[LIGHT_INTENSITY], m_Args[LIGHT_SECONDARY_INTENSITY]);
m_swapped = true;
}
}
protected: protected:
FName m_Name; FName m_Name;
int m_Args[5]; int m_Args[5];
@ -143,6 +153,7 @@ protected:
ELightType m_type; ELightType m_type;
int8_t m_attenuate; int8_t m_attenuate;
bool m_subtractive, m_additive, m_halo, m_dontlightself; bool m_subtractive, m_additive, m_halo, m_dontlightself;
bool m_swapped = false;
}; };
TArray<FLightDefaults *> LightDefaults; TArray<FLightDefaults *> LightDefaults;
@ -178,8 +189,8 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const
light->SetOffset(m_Pos); light->SetOffset(m_Pos);
light->halo = m_halo; light->halo = m_halo;
for (int a = 0; a < 3; a++) light->args[a] = clamp<int>((int)(m_Args[a]), 0, 255); for (int a = 0; a < 3; a++) light->args[a] = clamp<int>((int)(m_Args[a]), 0, 255);
light->args[LIGHT_INTENSITY] = int(m_Args[LIGHT_INTENSITY]); light->args[LIGHT_INTENSITY] = m_Args[LIGHT_INTENSITY];
light->args[LIGHT_SECONDARY_INTENSITY] = int(m_Args[LIGHT_SECONDARY_INTENSITY]); light->args[LIGHT_SECONDARY_INTENSITY] = m_Args[LIGHT_SECONDARY_INTENSITY];
light->flags4 &= ~(MF4_ADDITIVE | MF4_SUBTRACTIVE | MF4_DONTLIGHTSELF); light->flags4 &= ~(MF4_ADDITIVE | MF4_SUBTRACTIVE | MF4_DONTLIGHTSELF);
if (m_subtractive) light->flags4 |= MF4_SUBTRACTIVE; if (m_subtractive) light->flags4 |= MF4_SUBTRACTIVE;
if (m_additive) light->flags4 |= MF4_ADDITIVE; if (m_additive) light->flags4 |= MF4_ADDITIVE;
@ -190,11 +201,13 @@ void FLightDefaults::ApplyProperties(ADynamicLight * light) const
float pulseTime = float(m_Param / TICRATE); float pulseTime = float(m_Param / TICRATE);
light->m_lastUpdate = level.maptime; light->m_lastUpdate = level.maptime;
light->m_cycler.SetParams(float(light->args[LIGHT_SECONDARY_INTENSITY]), float(light->args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight); if (m_swapped) light->m_cycler.SetParams(float(light->args[LIGHT_SECONDARY_INTENSITY]), float(light->args[LIGHT_INTENSITY]), pulseTime, oldtype == PulseLight);
else light->m_cycler.SetParams(float(light->args[LIGHT_INTENSITY]), float(light->args[LIGHT_SECONDARY_INTENSITY]), pulseTime, oldtype == PulseLight);
light->m_cycler.ShouldCycle(true); light->m_cycler.ShouldCycle(true);
light->m_cycler.SetCycleType(CYCLE_Sin); light->m_cycler.SetCycleType(CYCLE_Sin);
light->m_currentRadius = light->m_cycler.GetVal(); light->m_currentRadius = light->m_cycler.GetVal();
if (light->m_currentRadius <= 0) light->m_currentRadius = 1; if (light->m_currentRadius <= 0) light->m_currentRadius = 1;
light->swapped = m_swapped;
} }
switch (m_attenuate) switch (m_attenuate)
@ -474,13 +487,7 @@ void gl_ParsePulseLight(FScanner &sc)
sc.ScriptError("Unknown tag: %s\n", sc.String); sc.ScriptError("Unknown tag: %s\n", sc.String);
} }
} }
if (defaults->GetArg(LIGHT_INTENSITY) > defaults->GetArg(LIGHT_SECONDARY_INTENSITY)) defaults->OrderIntensities();
{
auto i = defaults->GetArg(LIGHT_INTENSITY);
auto j = defaults->GetArg(LIGHT_SECONDARY_INTENSITY);
defaults->SetArg(LIGHT_INTENSITY, j);
defaults->SetArg(LIGHT_SECONDARY_INTENSITY, i);
}
gl_AddLightDefaults(defaults); gl_AddLightDefaults(defaults);
} }
@ -564,6 +571,7 @@ void gl_ParseFlickerLight(FScanner &sc)
sc.ScriptError("Unknown tag: %s\n", sc.String); sc.ScriptError("Unknown tag: %s\n", sc.String);
} }
} }
defaults->OrderIntensities();
gl_AddLightDefaults(defaults); gl_AddLightDefaults(defaults);
} }
else else

View file

@ -141,6 +141,7 @@ public:
bool halo; bool halo;
BYTE color2[3]; BYTE color2[3];
bool visibletoplayer; bool visibletoplayer;
bool swapped;
int bufferindex; int bufferindex;

View file

@ -395,9 +395,10 @@ void MessagePump (const SDL_Event &sev)
{ {
event.type = EV_GUI_Event; event.type = EV_GUI_Event;
event.subtype = sev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp; event.subtype = sev.type == SDL_KEYDOWN ? EV_GUI_KeyDown : EV_GUI_KeyUp;
event.data3 = ((sev.key.keysym.mod & KMOD_SHIFT) ? GKM_SHIFT : 0) | SDL_Keymod kmod = SDL_GetModState();
((sev.key.keysym.mod & KMOD_CTRL) ? GKM_CTRL : 0) | event.data3 = ((kmod & KMOD_SHIFT) ? GKM_SHIFT : 0) |
((sev.key.keysym.mod & KMOD_ALT) ? GKM_ALT : 0); ((kmod & KMOD_CTRL) ? GKM_CTRL : 0) |
((kmod & KMOD_ALT) ? GKM_ALT : 0);
if (event.subtype == EV_GUI_KeyDown) if (event.subtype == EV_GUI_KeyDown)
{ {
@ -458,6 +459,7 @@ void MessagePump (const SDL_Event &sev)
event.type = EV_GUI_Event; event.type = EV_GUI_Event;
event.subtype = EV_GUI_Char; event.subtype = EV_GUI_Char;
event.data1 = sev.text.text[0]; event.data1 = sev.text.text[0];
event.data2 = !!(SDL_GetModState() & KMOD_ALT);
D_PostEvent (&event); D_PostEvent (&event);
} }
break; break;

View file

@ -1059,6 +1059,33 @@ DEFINE_PROPERTY(bloodcolor, C, Actor)
static_cast<PClassActor *>(info)->BloodColor = pe; static_cast<PClassActor *>(info)->BloodColor = pe;
} }
//==========================================================================
//
//==========================================================================
DEFINE_PROPERTY(bloodtype, Sss, Actor)
{
PROP_STRING_PARM(str, 0)
PROP_STRING_PARM(str1, 1)
PROP_STRING_PARM(str2, 2)
FName blood = str;
// normal blood
defaults->NameVar("BloodType") = blood;
if (PROP_PARM_COUNT > 1)
{
blood = str1;
}
// blood splatter
defaults->NameVar("BloodType2") = blood;
if (PROP_PARM_COUNT > 2)
{
blood = str2;
}
// axe blood
defaults->NameVar("BloodType3") = blood;
}
//========================================================================== //==========================================================================
// //

View file

@ -393,7 +393,6 @@ void FString::Remove(size_t index, size_t remlen)
} }
else else
{ {
remlen = Len() - remlen < remlen ? Len() - remlen : remlen;
if (Data()->RefCount == 1) if (Data()->RefCount == 1)
{ // Can do this in place { // Can do this in place
memmove(Chars + index, Chars + index + remlen, Len() - index - remlen); memmove(Chars + index, Chars + index + remlen, Len() - index - remlen);

View file

@ -497,6 +497,12 @@ ABC4EB5A1535ECCD0061AD14F3547908 // Plutonia Experiment, map26
setsectorspecial 156 0 setsectorspecial 156 0
} }
B68EB7CFB4CC481796E2919B9C16DFBD // Moc11.wad e1m6
{
setvertex 1650 -3072 2671
setvertex 1642 -2944 2671
}
712BB4CFBD0753178CA0C6814BE4C288 // map12 BTSX_E1 - patch some rendering glitches that are problematic to detect 712BB4CFBD0753178CA0C6814BE4C288 // map12 BTSX_E1 - patch some rendering glitches that are problematic to detect
{ {
setsectortag 545 32000 setsectortag 545 32000

View file

@ -106,7 +106,6 @@ CMPTMNU_RENDERINGBEHAVIOR = "Rendering Behaviour";
CMPTMNU_SOUNDBEHAVIOR = "Sound Behaviour"; CMPTMNU_SOUNDBEHAVIOR = "Sound Behaviour";
CMPTMNU_SECTORSOUNDS = "Sector sounds use centre as source"; CMPTMNU_SECTORSOUNDS = "Sector sounds use centre as source";
OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colours only"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colours only";
OPTVAL_NODOORS = "All except doors";
C_GRAY = "\ccgrey"; C_GRAY = "\ccgrey";
C_DARKGRAY = "\cudark grey"; C_DARKGRAY = "\cudark grey";

View file

@ -2298,6 +2298,7 @@ OPTVAL_FRONT = "Front";
OPTVAL_ANIMATED = "Animated"; OPTVAL_ANIMATED = "Animated";
OPTVAL_ROTATED = "Rotated"; OPTVAL_ROTATED = "Rotated";
OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colors only"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colors only";
OPTVAL_NODOORS = "All except doors";
OPTVAL_DOUBLE = "Double"; OPTVAL_DOUBLE = "Double";
OPTVAL_TRIPLE = "Triple"; OPTVAL_TRIPLE = "Triple";
OPTVAL_QUADRUPLE = "Quadruple"; OPTVAL_QUADRUPLE = "Quadruple";

View file

@ -1052,7 +1052,7 @@ OptionValue MapBackTypes
OptionValue MapTriggers OptionValue MapTriggers
{ {
0, "$OPTVAL_OFF" 0, "$OPTVAL_OFF"
1, "$OPTVAL_NO_DOORS" 1, "$OPTVAL_NODOORS"
2, "$OPTVAL_ON" 2, "$OPTVAL_ON"
} }

View file

@ -224,7 +224,7 @@ class Actor : Thinker native
Property DontHurtShooter: DontHurtShooter; Property DontHurtShooter: DontHurtShooter;
Property ExplosionRadius: ExplosionRadius; Property ExplosionRadius: ExplosionRadius;
Property ExplosionDamage: ExplosionDamage; Property ExplosionDamage: ExplosionDamage;
Property BloodType: BloodType, BloodType2, BloodType3; //Property BloodType: BloodType, BloodType2, BloodType3;
Property FastSpeed: FastSpeed; Property FastSpeed: FastSpeed;
Property HowlSound: HowlSound; Property HowlSound: HowlSound;
Property GibHealth: GibHealth; Property GibHealth: GibHealth;