diff --git a/src/am_map.cpp b/src/am_map.cpp index fad6a13ac..be92fd37a 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2934,8 +2934,8 @@ static void DrawMarker (FTexture *tex, double x, double y, int yadjust, DTA_ClipLeft, f_x, DTA_ClipRight, f_x + f_w, DTA_FlipX, flip, - DTA_Translation, TranslationToTable(translation), - DTA_AlphaF, alpha, + DTA_TranslationIndex, translation, + DTA_Alpha, alpha, DTA_FillColor, fillcolor, DTA_RenderStyle, DWORD(renderstyle), TAG_DONE); diff --git a/src/b_move.cpp b/src/b_move.cpp index b31e4acbe..2a3d40bcb 100644 --- a/src/b_move.cpp +++ b/src/b_move.cpp @@ -65,11 +65,11 @@ bool DBot::Move (ticcmd_t *cmd) bool try_ok; int good; - if (player->mo->movedir == DI_NODIR) + if (player->mo->movedir >= DI_NODIR) + { + player->mo->movedir = DI_NODIR; // make sure it's valid. return false; - - if ((unsigned)player->mo->movedir >= 8) - I_Error ("Weird bot movedir!"); + } tryx = player->mo->X() + 8*xspeed[player->mo->movedir]; tryy = player->mo->Y() + 8*yspeed[player->mo->movedir]; diff --git a/src/c_console.cpp b/src/c_console.cpp index 1b4cbd36a..0b1e58287 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1005,23 +1005,23 @@ void FNotifyBuffer::Draw() { if (!center) screen->DrawText (SmallFont, color, 0, line, notify.Text, - DTA_CleanNoMove, true, DTA_AlphaF, alpha, TAG_DONE); + DTA_CleanNoMove, true, DTA_Alpha, alpha, TAG_DONE); else screen->DrawText (SmallFont, color, (SCREENWIDTH - SmallFont->StringWidth (notify.Text)*CleanXfac)/2, line, notify.Text, DTA_CleanNoMove, true, - DTA_AlphaF, alpha, TAG_DONE); + DTA_Alpha, alpha, TAG_DONE); } else if (active_con_scaletext() == 1) { if (!center) screen->DrawText (SmallFont, color, 0, line, notify.Text, - DTA_AlphaF, alpha, TAG_DONE); + DTA_Alpha, alpha, TAG_DONE); else screen->DrawText (SmallFont, color, (SCREENWIDTH - SmallFont->StringWidth (notify.Text))/2, line, notify.Text, - DTA_AlphaF, alpha, TAG_DONE); + DTA_Alpha, alpha, TAG_DONE); } else { @@ -1030,7 +1030,7 @@ void FNotifyBuffer::Draw() DTA_VirtualWidth, screen->GetWidth() / active_con_scaletext(), DTA_VirtualHeight, screen->GetHeight() / active_con_scaletext(), DTA_KeepRatio, true, - DTA_AlphaF, alpha, TAG_DONE); + DTA_Alpha, alpha, TAG_DONE); else screen->DrawText (SmallFont, color, (screen->GetWidth() - SmallFont->StringWidth (notify.Text) * active_con_scaletext()) / 2 / active_con_scaletext(), @@ -1038,7 +1038,7 @@ void FNotifyBuffer::Draw() DTA_VirtualWidth, screen->GetWidth() / active_con_scaletext(), DTA_VirtualHeight, screen->GetHeight() / active_con_scaletext(), DTA_KeepRatio, true, - DTA_AlphaF, alpha, TAG_DONE); + DTA_Alpha, alpha, TAG_DONE); } line += lineadv; canskip = false; @@ -1119,7 +1119,7 @@ void C_DrawConsole (bool hw2d) DTA_DestWidth, screen->GetWidth(), DTA_DestHeight, screen->GetHeight(), DTA_ColorOverlay, conshade, - DTA_AlphaF, (hw2d && gamestate != GS_FULLCONSOLE) ? (double)con_alpha : 1., + DTA_Alpha, (hw2d && gamestate != GS_FULLCONSOLE) ? (double)con_alpha : 1., DTA_Masked, false, TAG_DONE); if (conline && visheight < screen->GetHeight()) @@ -1762,11 +1762,10 @@ void C_MidPrintBold (FFont *font, const char *msg) DEFINE_ACTION_FUNCTION(_Console, MidPrint) { PARAM_PROLOGUE; - PARAM_STRING(font); + PARAM_POINTER_NOT_NULL(fnt, FFont); PARAM_STRING(text); PARAM_BOOL_DEF(bold); - FFont *fnt = FFont::FindFont(font); const char *txt = text[0] == '$'? GStrings(&text[1]) : text.GetChars(); if (!bold) C_MidPrint(fnt, txt); else C_MidPrintBold(fnt, txt); diff --git a/src/d_main.cpp b/src/d_main.cpp index 2ed553d0b..36e70b2b9 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2475,6 +2475,9 @@ void D_DoomMain (void) TexMan.Init(); C_InitConback(); + StartScreen->Progress(); + V_InitFonts(); + // [CW] Parse any TEAMINFO lumps. if (!batchrun) Printf ("ParseTeamInfo: Load team definitions.\n"); TeamLibrary.ParseTeamInfo (); diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 7468b6dab..e4d9fc177 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -88,6 +88,7 @@ PColor *TypeColor; PTextureID *TypeTextureID; PSpriteID *TypeSpriteID; PStatePointer *TypeState; +PPointer *TypeFont; PStateLabel *TypeStateLabel; PStruct *TypeVector2; PStruct *TypeVector3; @@ -437,6 +438,7 @@ void PType::StaticInit() TypeVoidPtr = NewPointer(TypeVoid, false); TypeColorStruct = NewStruct("@ColorStruct", nullptr); //This name is intentionally obfuscated so that it cannot be used explicitly. The point of this type is to gain access to the single channels of a color value. TypeStringStruct = NewNativeStruct("Stringstruct", nullptr); + TypeFont = NewPointer(NewNativeStruct("Font", nullptr)); #ifdef __BIG_ENDIAN__ TypeColorStruct->AddField(NAME_a, TypeUInt8); TypeColorStruct->AddField(NAME_r, TypeUInt8); diff --git a/src/dobjtype.h b/src/dobjtype.h index 2726ebff1..8cbe79966 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -940,6 +940,7 @@ extern PStruct *TypeVector3; extern PStruct *TypeColorStruct; extern PStruct *TypeStringStruct; extern PStatePointer *TypeState; +extern PPointer *TypeFont; extern PStateLabel *TypeStateLabel; extern PPointer *TypeNullPtr; extern PPointer *TypeVoidPtr; diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index 0db6d4743..86ddc4bfd 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -457,7 +457,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight) { screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, DTA_CleanNoMove, clean, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, DTA_RenderStyle, Style, TAG_DONE); } @@ -466,7 +466,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight) screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(), DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(), - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, DTA_RenderStyle, Style, DTA_KeepRatio, true, TAG_DONE); @@ -481,7 +481,7 @@ void DHUDMessage::DoDraw (int linenum, int x, int y, bool clean, int hudheight) DTA_ClipRight, ClipRight, DTA_ClipTop, ClipTop, DTA_ClipBottom, ClipBot, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, DTA_RenderStyle, Style, TAG_DONE); } @@ -560,7 +560,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh { screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, DTA_CleanNoMove, clean, - DTA_AlphaF, trans, + DTA_Alpha, trans, DTA_RenderStyle, Style, TAG_DONE); } @@ -569,7 +569,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(), DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(), - DTA_AlphaF, trans, + DTA_Alpha, trans, DTA_RenderStyle, Style, DTA_KeepRatio, true, TAG_DONE); @@ -584,7 +584,7 @@ void DHUDMessageFadeOut::DoDraw (int linenum, int x, int y, bool clean, int hudh DTA_ClipRight, ClipRight, DTA_ClipTop, ClipTop, DTA_ClipBottom, ClipBot, - DTA_AlphaF, trans, + DTA_Alpha, trans, DTA_RenderStyle, Style, TAG_DONE); } @@ -660,7 +660,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu { screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, DTA_CleanNoMove, clean, - DTA_AlphaF, trans, + DTA_Alpha, trans, DTA_RenderStyle, Style, TAG_DONE); } @@ -669,7 +669,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, DTA_VirtualWidth, SCREENWIDTH / active_con_scaletext(), DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(), - DTA_AlphaF, trans, + DTA_Alpha, trans, DTA_RenderStyle, Style, DTA_KeepRatio, true, TAG_DONE); @@ -684,7 +684,7 @@ void DHUDMessageFadeInOut::DoDraw (int linenum, int x, int y, bool clean, int hu DTA_ClipRight, ClipRight, DTA_ClipTop, ClipTop, DTA_ClipBottom, ClipBot, - DTA_AlphaF, trans, + DTA_Alpha, trans, DTA_RenderStyle, Style, TAG_DONE); } @@ -842,7 +842,7 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in screen->DrawText (Font, TextColor, x, y, Lines[linenum].Text, DTA_CleanNoMove, clean, DTA_TextLen, LineVisible, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, DTA_RenderStyle, Style, TAG_DONE); } @@ -853,7 +853,7 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in DTA_VirtualHeight, SCREENHEIGHT / active_con_scaletext(), DTA_KeepRatio, true, DTA_TextLen, LineVisible, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, DTA_RenderStyle, Style, TAG_DONE); } @@ -867,7 +867,7 @@ void DHUDMessageTypeOnFadeOut::DoDraw (int linenum, int x, int y, bool clean, in DTA_ClipRight, ClipRight, DTA_ClipTop, ClipTop, DTA_ClipBottom, ClipBot, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, DTA_TextLen, LineVisible, DTA_RenderStyle, Style, TAG_DONE); diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 37312748c..4ab0c8133 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -138,7 +138,7 @@ void SetHUDIcon(PClassInventory *cls, FTextureID tex) // center of the box. The image is scaled down if it doesn't fit // //--------------------------------------------------------------------------- -static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, int trans=0xc000) +static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, double trans = 0.75) { double scale1, scale2; @@ -174,7 +174,7 @@ static void DrawImageToBox(FTexture * tex, int x, int y, int w, int h, int trans // //--------------------------------------------------------------------------- -static void DrawHudText(FFont *font, int color, char * text, int x, int y, int trans=0xc000) +static void DrawHudText(FFont *font, int color, char * text, int x, int y, double trans = 0.75) { int zerowidth; FTexture *tex_zero = font->GetChar('0', &zerowidth); @@ -207,7 +207,7 @@ static void DrawHudText(FFont *font, int color, char * text, int x, int y, int t // //--------------------------------------------------------------------------- -static void DrawHudNumber(FFont *font, int color, int num, int x, int y, int trans=0xc000) +static void DrawHudNumber(FFont *font, int color, int num, int x, int y, double trans = 0.75) { char text[15]; @@ -227,11 +227,11 @@ static void DrawStatLine(int x, int &y, const char *prefix, const char *string) y -= SmallFont->GetHeight()-1; screen->DrawText(SmallFont, hudcolor_statnames, x, y, prefix, DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); + DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.75, TAG_DONE); screen->DrawText(SmallFont, hudcolor_stats, x+statspace, y, string, DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0xc000, TAG_DONE); + DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.75, TAG_DONE); } static void DrawStatus(player_t * CPlayer, int x, int y) @@ -654,7 +654,7 @@ static int DrawAmmo(player_t *CPlayer, int x, int y) FTextureID icon = !AltIcon.isNull()? AltIcon : inv->Icon; if (!icon.isValid()) continue; - int trans= (wi && (type==wi->AmmoType1 || type==wi->AmmoType2)) ? 0xc000:0x6000; + double trans= (wi && (type==wi->AmmoType1 || type==wi->AmmoType2)) ? 0.75 : 0.375; int maxammo = inv->MaxAmount; int ammo = ammoitem? ammoitem->Amount : 0; @@ -731,16 +731,16 @@ FTextureID GetInventoryIcon(AInventory *item, DWORD flags, bool *applyscale=NULL static void DrawOneWeapon(player_t * CPlayer, int x, int & y, AWeapon * weapon) { - int trans; + double trans; // Powered up weapons and inherited sister weapons are not displayed. if (weapon->WeaponFlags & WIF_POWERED_UP) return; if (weapon->SisterWeapon && weapon->IsKindOf(weapon->SisterWeapon->GetClass())) return; - trans=0x6666; + trans=0.4; if (CPlayer->ReadyWeapon) { - if (weapon==CPlayer->ReadyWeapon || weapon==CPlayer->ReadyWeapon->SisterWeapon) trans=0xd999; + if (weapon==CPlayer->ReadyWeapon || weapon==CPlayer->ReadyWeapon->SisterWeapon) trans = 0.85; } FTextureID picnum = GetInventoryIcon(weapon, DI_ALTICONFIRST); @@ -809,7 +809,7 @@ static void DrawInventory(player_t * CPlayer, int x,int y) { screen->DrawTexture(invgems[!!(level.time&4)], x-10, y, DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0x6666, TAG_DONE); + DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.4, TAG_DONE); } for(i=0;iNextInv()) @@ -820,7 +820,7 @@ static void DrawInventory(player_t * CPlayer, int x,int y) if (AltIcon.Exists() && (rover->Icon.isValid() || AltIcon.isValid()) ) { - int trans = rover==CPlayer->mo->InvSel ? 0x10000 : 0x6666; + double trans = rover==CPlayer->mo->InvSel ? 1.0 : 0.4; DrawImageToBox(TexMan[AltIcon.isValid()? AltIcon : rover->Icon], x, y, 19, 25, trans); if (rover->Amount>1) @@ -845,7 +845,7 @@ static void DrawInventory(player_t * CPlayer, int x,int y) { screen->DrawTexture(invgems[2 + !!(level.time&4)], x-10, y, DTA_KeepRatio, true, - DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0x6666, TAG_DONE); + DTA_VirtualWidth, hudwidth, DTA_VirtualHeight, hudheight, DTA_Alpha, 0.4, TAG_DONE); } } } diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index d6e5f6dbf..2fd21737f 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -1267,10 +1267,10 @@ public: DTA_ClipTop, static_cast(dcy), DTA_ClipRight, static_cast(MIN(INT_MAX, dcr)), DTA_ClipBottom, static_cast(MIN(INT_MAX, dcb)), - DTA_Translation, translate ? GetTranslation() : 0, + DTA_TranslationIndex, translate ? GetTranslation() : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, DTA_AlphaChannel, alphaMap, DTA_FillColor, 0, TAG_DONE); @@ -1284,10 +1284,10 @@ public: DTA_ClipTop, static_cast(dcy), DTA_ClipRight, static_cast(MIN(INT_MAX, dcr)), DTA_ClipBottom, static_cast(MIN(INT_MAX, dcb)), - DTA_Translation, translate ? GetTranslation() : 0, + DTA_TranslationIndex, translate ? GetTranslation() : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, TAG_DONE); } } @@ -1344,10 +1344,10 @@ public: DTA_ClipTop, static_cast(rcy), DTA_ClipRight, static_cast(rcr), DTA_ClipBottom, static_cast(rcb), - DTA_Translation, translate ? GetTranslation() : 0, + DTA_TranslationIndex, translate ? GetTranslation() : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, DTA_AlphaChannel, alphaMap, DTA_FillColor, 0, TAG_DONE); @@ -1361,10 +1361,10 @@ public: DTA_ClipTop, static_cast(rcy), DTA_ClipRight, static_cast(rcr), DTA_ClipBottom, static_cast(rcb), - DTA_Translation, translate ? GetTranslation() : 0, + DTA_TranslationIndex, translate ? GetTranslation() : 0, DTA_ColorOverlay, dim ? DIM_OVERLAY : 0, DTA_CenterBottomOffset, (offsetflags & SBarInfoCommand::CENTER_BOTTOM) == SBarInfoCommand::CENTER_BOTTOM, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, TAG_DONE); } } @@ -1382,7 +1382,7 @@ public: const BYTE* str = (const BYTE*) cstring; const EColorRange boldTranslation = EColorRange(translation ? translation - 1 : NumTextColors - 1); - FRemapTable *remap = font->GetColorTranslation(translation); + int fontcolor = translation; if(fullScreenOffsets) { @@ -1408,7 +1408,7 @@ public: { EColorRange newColor = V_ParseFontColor(++str, translation, boldTranslation); if(newColor != CR_UNDEFINED) - remap = font->GetColorTranslation(newColor); + fontcolor = newColor; continue; } @@ -1417,20 +1417,22 @@ public: width = font->GetCharWidth((unsigned char) *str); else width = font->GetCharWidth((unsigned char) script->spacingCharacter); - FTexture* character = font->GetChar((unsigned char) *str, &width); - if(character == NULL) //missing character. + FTexture* c = font->GetChar((unsigned char) *str, &width); + if(c == NULL) //missing character. { str++; continue; } + int character = (unsigned char)*str; + if(script->spacingCharacter == '\0') //If we are monospaced lets use the offset - ax += (character->LeftOffset+1); //ignore x offsets since we adapt to character size + ax += (c->LeftOffset+1); //ignore x offsets since we adapt to character size double rx, ry, rw, rh; rx = ax + xOffset; ry = ay + yOffset; - rw = character->GetScaledWidthDouble(); - rh = character->GetScaledHeightDouble(); + rw = c->GetScaledWidthDouble(); + rh = c->GetScaledHeightDouble(); if(script->spacingCharacter != '\0') { @@ -1484,32 +1486,31 @@ public: double salpha = (Alpha *HR_SHADOW); double srx = rx + (shadowX*xScale); double sry = ry + (shadowY*yScale); - screen->DrawTexture(character, srx, sry, + screen->DrawChar(font, CR_UNTRANSLATED, srx, sry, character, DTA_DestWidthF, rw, DTA_DestHeightF, rh, - DTA_AlphaF, salpha, + DTA_Alpha, salpha, DTA_FillColor, 0, TAG_DONE); } - screen->DrawTexture(character, rx, ry, + screen->DrawChar(font, fontcolor, rx, ry, character, DTA_DestWidthF, rw, DTA_DestHeightF, rh, - DTA_Translation, remap, - DTA_AlphaF, Alpha, + DTA_Alpha, Alpha, TAG_DONE); if(script->spacingCharacter == '\0') - ax += width + spacing - (character->LeftOffset+1); + ax += width + spacing - (c->LeftOffset+1); else //width gets changed at the call to GetChar() ax += font->GetCharWidth((unsigned char) script->spacingCharacter) + spacing; str++; } } - FRemapTable* GetTranslation() const + uint32_t GetTranslation() const { if(gameinfo.gametype & GAME_Raven) - return translationtables[TRANSLATION_PlayersExtra][int(CPlayer - players)]; - return translationtables[TRANSLATION_Players][int(CPlayer - players)]; + return TRANSLATION(TRANSLATION_PlayersExtra, int(CPlayer - players)); + return TRANSLATION(TRANSLATION_Players, int(CPlayer - players)); } AInventory *ammo1, *ammo2; diff --git a/src/g_statusbar/strife_sbar.cpp b/src/g_statusbar/strife_sbar.cpp index d2511c42d..177117eb2 100644 --- a/src/g_statusbar/strife_sbar.cpp +++ b/src/g_statusbar/strife_sbar.cpp @@ -451,7 +451,7 @@ private: screen->DrawTexture (Images[CursorImage], 42 + 35*i + ST_X, 12 + ST_Y, DTA_Bottom320x200, Scaled, - DTA_AlphaF, 1. - ItemFlash, + DTA_Alpha, 1. - ItemFlash, TAG_DONE); } if (item->Icon.isValid()) @@ -523,7 +523,7 @@ private: DTA_HUDRules, HUD_Normal, DTA_LeftOffset, cursor->GetWidth(), DTA_TopOffset, cursor->GetHeight(), - DTA_AlphaF, ItemFlash, + DTA_Alpha, ItemFlash, TAG_DONE); } DrINumberOuter (CPlayer->mo->InvSel->Amount, -51, -10, false, 7); @@ -547,7 +547,7 @@ private: { screen->DrawTexture (Images[CursorImage], -100+i*35, -21, DTA_HUDRules, HUD_HorizCenter, - DTA_Alpha, TRANSLUC75, + DTA_Alpha, 0.75, TAG_DONE); } if (item->Icon.isValid()) @@ -580,7 +580,7 @@ private: left = screen->GetWidth()/2 - 160*CleanXfac; top = bottom + height * yscale; - screen->DrawTexture (Images[back], left, top, DTA_CleanNoMove, true, DTA_AlphaF, 0.75, TAG_DONE); + screen->DrawTexture (Images[back], left, top, DTA_CleanNoMove, true, DTA_Alpha, 0.75, TAG_DONE); screen->DrawTexture (Images[bars], left, top, DTA_CleanNoMove, true, TAG_DONE); @@ -849,7 +849,7 @@ private: void DrINumberOuter(signed int val, int x, int y, bool center = false, int w = 9) const; void DrBNumberOuterFont(signed int val, int x, int y, int w = 3) const; void DrawDimImage(FTexture *image, int x, int y, bool dimmed) const; - void DrawImage(FTexture *image, int x, int y, FRemapTable *translation = NULL) const; + void DrawImage(FTexture *image, int x, int y/*, FRemapTable *translation = NULL*/) const; }; @@ -874,7 +874,7 @@ void DStrifeStatusBar::DrINumberOuter(signed int val, int x, int y, bool center, else if (val == 0) { screen->DrawTexture(Images[imgINumbers], x + 1, y + 1, - DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, + DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); screen->DrawTexture(Images[imgINumbers], x, y, DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); @@ -888,7 +888,7 @@ void DStrifeStatusBar::DrINumberOuter(signed int val, int x, int y, bool center, while (val != 0) { screen->DrawTexture(Images[imgINumbers + val % 10], x + 1, y + 1, - DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, + DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); x -= w; val /= 10; @@ -896,7 +896,7 @@ void DStrifeStatusBar::DrINumberOuter(signed int val, int x, int y, bool center, if (negative) { screen->DrawTexture(Images[imgNEGATIVE], x + 1, y + 1, - DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, + DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, DTA_HUDRules, center ? HUD_HorizCenter : HUD_Normal, TAG_DONE); } @@ -945,15 +945,13 @@ void DStrifeStatusBar::DrBNumberOuterFont(signed int val, int x, int y, int size if (val == 0) { pic = BigFont->GetChar('0', &v); - screen->DrawTexture(pic, xpos - v / 2 + 2, y + 2, + screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, '0', DTA_HUDRules, HUD_Normal, - DTA_AlphaF, HR_SHADOW, + DTA_Alpha, HR_SHADOW, DTA_FillColor, 0, - DTA_Translation, BigFont->GetColorTranslation(CR_UNTRANSLATED), TAG_DONE); - screen->DrawTexture(pic, xpos - v / 2, y, + screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2, y, '0', DTA_HUDRules, HUD_Normal, - DTA_Translation, BigFont->GetColorTranslation(CR_UNTRANSLATED), TAG_DONE); return; } @@ -970,11 +968,10 @@ void DStrifeStatusBar::DrBNumberOuterFont(signed int val, int x, int y, int size while (val != 0) { pic = BigFont->GetChar('0' + val % 10, &v); - screen->DrawTexture(pic, xpos - v / 2 + 2, y + 2, + screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, DTA_HUDRules, HUD_Normal, - DTA_AlphaF, HR_SHADOW, + DTA_Alpha, HR_SHADOW, DTA_FillColor, 0, - DTA_Translation, BigFont->GetColorTranslation(CR_UNTRANSLATED), TAG_DONE); val /= 10; xpos -= w; @@ -984,11 +981,10 @@ void DStrifeStatusBar::DrBNumberOuterFont(signed int val, int x, int y, int size pic = BigFont->GetChar('-', &v); if (pic != NULL) { - screen->DrawTexture(pic, xpos - v / 2 + 2, y + 2, + screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2 + 2, y + 2, '-', DTA_HUDRules, HUD_Normal, - DTA_AlphaF, HR_SHADOW, + DTA_Alpha, HR_SHADOW, DTA_FillColor, 0, - DTA_Translation, BigFont->GetColorTranslation(CR_UNTRANSLATED), TAG_DONE); } } @@ -999,9 +995,8 @@ void DStrifeStatusBar::DrBNumberOuterFont(signed int val, int x, int y, int size while (val != 0) { pic = BigFont->GetChar('0' + val % 10, &v); - screen->DrawTexture(pic, xpos - v / 2, y, + screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2, y, '0', DTA_HUDRules, HUD_Normal, - DTA_Translation, BigFont->GetColorTranslation(CR_UNTRANSLATED), TAG_DONE); val /= 10; xpos -= w; @@ -1011,9 +1006,8 @@ void DStrifeStatusBar::DrBNumberOuterFont(signed int val, int x, int y, int size pic = BigFont->GetChar('-', &v); if (pic != NULL) { - screen->DrawTexture(pic, xpos - v / 2, y, + screen->DrawChar(BigFont, CR_UNTRANSLATED, xpos - v / 2, y, '-', DTA_HUDRules, HUD_Normal, - DTA_Translation, BigFont->GetColorTranslation(CR_UNTRANSLATED), TAG_DONE); } } @@ -1028,12 +1022,11 @@ void DStrifeStatusBar::DrBNumberOuterFont(signed int val, int x, int y, int size //--------------------------------------------------------------------------- void DStrifeStatusBar::DrawImage(FTexture *img, - int x, int y, FRemapTable *translation) const + int x, int y) const { if (img != NULL) { screen->DrawTexture(img, x + ST_X, y + ST_Y, - DTA_Translation, translation, DTA_Bottom320x200, Scaled, TAG_DONE); } diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 2612bdd63..8310914be 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -388,15 +388,8 @@ void DIntermissionScreenText::Drawer () w *= CleanXfac; if (cx + w > SCREENWIDTH) continue; - if (pic != NULL) - { - screen->DrawTexture (pic, - cx, - cy, - DTA_Translation, range, - DTA_CleanNoMove, true, - TAG_DONE); - } + + screen->DrawChar(SmallFont, mTextColor, cx, cy, c, DTA_CleanNoMove, true, TAG_DONE); cx += w; } } @@ -432,16 +425,15 @@ void DIntermissionScreenCast::Init(FIntermissionAction *desc, bool first) if (mClass->IsDescendantOf(RUNTIME_CLASS(APlayerPawn))) { advplayerstate = mDefaults->MissileState; - casttranslation = translationtables[TRANSLATION_Players][consoleplayer]; + casttranslation = TRANSLATION(TRANSLATION_Players, consoleplayer); } else { advplayerstate = NULL; - casttranslation = NULL; + casttranslation = 0; if (mDefaults->Translation != 0) { - casttranslation = translationtables[GetTranslationType(mDefaults->Translation)] - [GetTranslationIndex(mDefaults->Translation)]; + casttranslation = mDefaults->Translation; } } castdeath = false; @@ -630,8 +622,8 @@ void DIntermissionScreenCast::Drawer () DTA_DestHeightF, pic->GetScaledHeightDouble() * castscale.Y, DTA_DestWidthF, pic->GetScaledWidthDouble() * castscale.X, DTA_RenderStyle, mDefaults->RenderStyle, - DTA_AlphaF, mDefaults->Alpha, - DTA_Translation, casttranslation, + DTA_Alpha, mDefaults->Alpha, + DTA_TranslationIndex, casttranslation, TAG_DONE); } } diff --git a/src/intermission/intermission.h b/src/intermission/intermission.h index 0f2c38dde..cdc100d88 100644 --- a/src/intermission/intermission.h +++ b/src/intermission/intermission.h @@ -234,7 +234,7 @@ class DIntermissionScreenCast : public DIntermissionScreen TArray mCastSounds; int casttics; - const FRemapTable *casttranslation; // [RH] Draw "our hero" with their chosen suit color + uint32_t casttranslation; // [RH] Draw "our hero" with their chosen suit color FState* caststate; FState* basestate; FState* advplayerstate; diff --git a/src/menu/colorpickermenu.cpp b/src/menu/colorpickermenu.cpp index 6ace5bd70..df96b37a0 100644 --- a/src/menu/colorpickermenu.cpp +++ b/src/menu/colorpickermenu.cpp @@ -89,6 +89,10 @@ public: desc->mItems[mStartItem+5] = new DOptionMenuItemStaticText(" ", false); desc->mItems[mStartItem+6] = new DOptionMenuItemCommand("Undo changes", "undocolorpic"); desc->mItems[mStartItem+7] = new DOptionMenuItemStaticText(" ", false); + for (auto &p : desc->mItems) + { + GC::WriteBarrier(p); + } desc->mSelectedItem = mStartItem + 2; Init(parent, desc); desc->mIndent = 0; diff --git a/src/menu/joystickmenu.cpp b/src/menu/joystickmenu.cpp index 702a6b09f..21bb370b4 100644 --- a/src/menu/joystickmenu.cpp +++ b/src/menu/joystickmenu.cpp @@ -322,6 +322,10 @@ FOptionMenuDescriptor *UpdateJoystickConfigMenu(IJoystickConfig *joy) opt->mItems.Push(it); } } + for (auto &p : opt->mItems) + { + GC::WriteBarrier(p); + } opt->mScrollPos = 0; opt->mSelectedItem = -1; opt->mIndent = 0; @@ -402,6 +406,10 @@ void UpdateJoystickMenu(IJoystickConfig *selected) if (i == itemnum) opt->mSelectedItem = opt->mItems.Size(); } } + for (auto &p : opt->mItems) + { + GC::WriteBarrier(p); + } if (opt->mSelectedItem >= (int)opt->mItems.Size()) { opt->mSelectedItem = opt->mItems.Size() - 1; diff --git a/src/menu/listmenu.cpp b/src/menu/listmenu.cpp index 03223b6a7..020a540c5 100644 --- a/src/menu/listmenu.cpp +++ b/src/menu/listmenu.cpp @@ -44,6 +44,10 @@ IMPLEMENT_CLASS(DListMenu, false, false) +IMPLEMENT_POINTERS_START(DListMenu) +IMPLEMENT_POINTER(mFocusControl) +IMPLEMENT_POINTERS_END + //============================================================================= // // @@ -101,7 +105,7 @@ void DListMenu::Init(DMenu *parent, FListMenuDescriptor *desc) // //============================================================================= -DListMenuItem *DListMenu::GetItem(FName name) +DMenuItemBase *DListMenu::GetItem(FName name) { for(unsigned i=0;imItems.Size(); i++) { @@ -274,27 +278,27 @@ void DListMenu::Drawer () // base class for menu items // //============================================================================= -IMPLEMENT_CLASS(DListMenuItem, true, false) +IMPLEMENT_CLASS(DMenuItemBase, true, false) -bool DListMenuItem::CheckCoordinate(int x, int y) +bool DMenuItemBase::CheckCoordinate(int x, int y) { return false; } -void DListMenuItem::Ticker() +void DMenuItemBase::Ticker() { } -void DListMenuItem::Drawer(bool selected) +void DMenuItemBase::Drawer(bool selected) { } -bool DListMenuItem::Selectable() +bool DMenuItemBase::Selectable() { return false; } -void DListMenuItem::DrawSelector(int xofs, int yofs, FTextureID tex) +void DMenuItemBase::DrawSelector(int xofs, int yofs, FTextureID tex) { if (tex.isNull()) { @@ -315,57 +319,57 @@ void DListMenuItem::DrawSelector(int xofs, int yofs, FTextureID tex) } } -bool DListMenuItem::Activate() +bool DMenuItemBase::Activate() { return false; // cannot be activated } -FName DListMenuItem::GetAction(int *pparam) +FName DMenuItemBase::GetAction(int *pparam) { return mAction; } -bool DListMenuItem::SetString(int i, const char *s) +bool DMenuItemBase::SetString(int i, const char *s) { return false; } -bool DListMenuItem::GetString(int i, char *s, int len) +bool DMenuItemBase::GetString(int i, char *s, int len) { return false; } -bool DListMenuItem::SetValue(int i, int value) +bool DMenuItemBase::SetValue(int i, int value) { return false; } -bool DListMenuItem::GetValue(int i, int *pvalue) +bool DMenuItemBase::GetValue(int i, int *pvalue) { return false; } -void DListMenuItem::Enable(bool on) +void DMenuItemBase::Enable(bool on) { mEnabled = on; } -bool DListMenuItem::MenuEvent(int mkey, bool fromcontroller) +bool DMenuItemBase::MenuEvent(int mkey, bool fromcontroller) { return false; } -bool DListMenuItem::MouseEvent(int type, int x, int y) +bool DMenuItemBase::MouseEvent(int type, int x, int y) { return false; } -bool DListMenuItem::CheckHotkey(int c) +bool DMenuItemBase::CheckHotkey(int c) { return false; } -int DListMenuItem::GetWidth() +int DMenuItemBase::GetWidth() { return 0; } @@ -379,7 +383,7 @@ int DListMenuItem::GetWidth() IMPLEMENT_CLASS(DListMenuItemStaticPatch, false, false) DListMenuItemStaticPatch::DListMenuItemStaticPatch(int x, int y, FTextureID patch, bool centered) -: DListMenuItem(x, y) +: DMenuItemBase(x, y) { mTexture = patch; mCentered = centered; @@ -415,7 +419,7 @@ void DListMenuItemStaticPatch::Drawer(bool selected) IMPLEMENT_CLASS(DListMenuItemStaticText, false, false) DListMenuItemStaticText::DListMenuItemStaticText(int x, int y, const char *text, FFont *font, EColorRange color, bool centered) -: DListMenuItem(x, y) +: DMenuItemBase(x, y) { mText = text; mFont = font; @@ -452,7 +456,7 @@ void DListMenuItemStaticText::Drawer(bool selected) IMPLEMENT_CLASS(DListMenuItemSelectable, false, false) DListMenuItemSelectable::DListMenuItemSelectable(int x, int y, int height, FName action, int param) -: DListMenuItem(x, y, action) +: DMenuItemBase(x, y, action) { mHeight = height; mParam = param; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index acec65f90..c047a145d 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -305,7 +305,7 @@ void DMenu::Drawer () } else { - screen->DrawTexture(tex, x, y, DTA_CleanNoMove, true, DTA_AlphaF, BackbuttonAlpha, TAG_DONE); + screen->DrawTexture(tex, x, y, DTA_CleanNoMove, true, DTA_Alpha, BackbuttonAlpha, TAG_DONE); } } } diff --git a/src/menu/menu.h b/src/menu/menu.h index 24833f280..23a4e8718 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -92,12 +92,12 @@ struct FMenuDescriptor virtual size_t PropagateMark() { return 0; } }; -class DListMenuItem; +class DMenuItemBase; class DOptionMenuItem; struct FListMenuDescriptor : public FMenuDescriptor { - TArray mItems; + TArray mItems; int mSelectedItem; int mSelectOfsX; int mSelectOfsY; @@ -255,9 +255,9 @@ public: // //============================================================================= -class DListMenuItem : public DObject +class DMenuItemBase : public DObject { - DECLARE_CLASS(DListMenuItem, DObject) + DECLARE_CLASS(DMenuItemBase, DObject) protected: int mXpos, mYpos; FName mAction; @@ -265,7 +265,7 @@ protected: public: bool mEnabled; - DListMenuItem(int xpos = 0, int ypos = 0, FName action = NAME_None) + DMenuItemBase(int xpos = 0, int ypos = 0, FName action = NAME_None) { mXpos = xpos; mYpos = ypos; @@ -295,9 +295,9 @@ public: void SetX(int x) { mXpos = x; } }; -class DListMenuItemStaticPatch : public DListMenuItem +class DListMenuItemStaticPatch : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemStaticPatch, DListMenuItem) + DECLARE_CLASS(DListMenuItemStaticPatch, DMenuItemBase) protected: FTextureID mTexture; bool mCentered; @@ -308,9 +308,9 @@ public: void Drawer(bool selected); }; -class DListMenuItemStaticText : public DListMenuItem +class DListMenuItemStaticText : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemStaticText, DListMenuItem) + DECLARE_CLASS(DListMenuItemStaticText, DMenuItemBase) protected: FString mText; FFont *mFont; @@ -329,9 +329,9 @@ public: // //============================================================================= -class DListMenuItemPlayerDisplay : public DListMenuItem +class DListMenuItemPlayerDisplay : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemPlayerDisplay, DListMenuItem) + DECLARE_CLASS(DListMenuItemPlayerDisplay, DMenuItemBase) FListMenuDescriptor *mOwner; FTexture *mBackdrop; @@ -379,9 +379,9 @@ public: // //============================================================================= -class DListMenuItemSelectable : public DListMenuItem +class DListMenuItemSelectable : public DMenuItemBase { - DECLARE_CLASS(DListMenuItemSelectable, DListMenuItem) + DECLARE_CLASS(DListMenuItemSelectable, DMenuItemBase) protected: int mHotkey; int mHeight; @@ -520,25 +520,26 @@ public: class DListMenu : public DMenu { DECLARE_CLASS(DListMenu, DMenu) + HAS_OBJECT_POINTERS; protected: FListMenuDescriptor *mDesc; - DListMenuItem *mFocusControl; + DMenuItemBase *mFocusControl; public: DListMenu(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL); virtual void Init(DMenu *parent = NULL, FListMenuDescriptor *desc = NULL); - DListMenuItem *GetItem(FName name); + DMenuItemBase *GetItem(FName name); bool Responder (event_t *ev); bool MenuEvent (int mkey, bool fromcontroller); bool MouseEvent(int type, int x, int y); void Ticker (); void Drawer (); - void SetFocus(DListMenuItem *fc) + void SetFocus(DMenuItemBase *fc) { mFocusControl = fc; } - bool CheckFocus(DListMenuItem *fc) + bool CheckFocus(DMenuItemBase *fc) { return mFocusControl == fc; } @@ -555,9 +556,9 @@ public: // //============================================================================= -class DOptionMenuItem : public DListMenuItem +class DOptionMenuItem : public DMenuItemBase { - DECLARE_ABSTRACT_CLASS(DOptionMenuItem, DListMenuItem) + DECLARE_ABSTRACT_CLASS(DOptionMenuItem, DMenuItemBase) protected: FString mLabel; bool mCentered; @@ -566,7 +567,7 @@ protected: public: DOptionMenuItem(const char *text = nullptr, FName action = NAME_None, bool center = false) - : DListMenuItem(0, 0, action) + : DMenuItemBase(0, 0, action) { mLabel = text; mCentered = center; @@ -609,6 +610,7 @@ extern FOptionMap OptionValues; class DOptionMenu : public DMenu { DECLARE_CLASS(DOptionMenu, DMenu) + HAS_OBJECT_POINTERS; bool CanScrollUp; bool CanScrollDown; diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index a8822470f..efb444d5c 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -294,7 +294,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) sc.MustGetString(); FTextureID tex = GetMenuTexture(sc.String); - DListMenuItem *it = new DListMenuItemStaticPatch(x, y, tex, centered); + DMenuItemBase *it = new DListMenuItemStaticPatch(x, y, tex, centered); desc->mItems.Push(it); } else if (sc.Compare("StaticText") || sc.Compare("StaticTextCentered")) @@ -315,7 +315,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) cr = V_FindFontColor(sc.String); if (cr == CR_UNTRANSLATED && !sc.Compare("untranslated")) cr = desc->mFontColor; } - DListMenuItem *it = new DListMenuItemStaticText(x, y, label, desc->mFont, cr, centered); + DMenuItemBase *it = new DListMenuItemStaticText(x, y, label, desc->mFont, cr, centered); desc->mItems.Push(it); } else if (sc.Compare("PatchItem")) @@ -335,7 +335,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) param = sc.Number; } - DListMenuItem *it = new DListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); + DMenuItemBase *it = new DListMenuItemPatch(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, tex, action, param); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -357,7 +357,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) param = sc.Number; } - DListMenuItem *it = new DListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); + DMenuItemBase *it = new DListMenuItemText(desc->mXpos, desc->mYpos, desc->mLinespacing, hotkey, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, param); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -426,7 +426,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) int ofs = sc.Number; sc.MustGetStringName(","); sc.MustGetString(); - DListMenuItem *it = new DPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String); + DMenuItemBase *it = new DPlayerNameBox(desc->mXpos, desc->mYpos, desc->mLinespacing, ofs, text, desc->mFont, desc->mFontColor, sc.String); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -444,7 +444,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) sc.MustGetString(); values = sc.String; } - DListMenuItem *it = new DValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values); + DMenuItemBase *it = new DValueTextItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, desc->mFontColor2, action, values); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -465,7 +465,7 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) sc.MustGetStringName(","); sc.MustGetNumber(); int step = sc.Number; - DListMenuItem *it = new DSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step); + DMenuItemBase *it = new DSliderItem(desc->mXpos, desc->mYpos, desc->mLinespacing, text, desc->mFont, desc->mFontColor, action, min, max, step); desc->mItems.Push(it); desc->mYpos += desc->mLinespacing; if (desc->mSelectedItem == -1) desc->mSelectedItem = desc->mItems.Size()-1; @@ -475,6 +475,10 @@ static void ParseListMenuBody(FScanner &sc, FListMenuDescriptor *desc) sc.ScriptError("Unknown keyword '%s'", sc.String); } } + for (auto &p : desc->mItems) + { + GC::WriteBarrier(p); + } } //============================================================================= @@ -927,6 +931,10 @@ static void ParseOptionMenuBody(FScanner &sc, FOptionMenuDescriptor *desc) sc.ScriptError("Unknown keyword '%s'", sc.String); } } + for (auto &p : desc->mItems) + { + GC::WriteBarrier(p); + } } //============================================================================= @@ -1081,7 +1089,7 @@ static void BuildEpisodeMenu() ld->mSelectedItem = ld->mItems.Size(); for(unsigned i = 0; i < AllEpisodes.Size(); i++) { - DListMenuItem *it; + DMenuItemBase *it; if (AllEpisodes[i].mPicName.IsNotEmpty()) { FTextureID tex = GetMenuTexture(AllEpisodes[i].mPicName); @@ -1101,6 +1109,10 @@ static void BuildEpisodeMenu() ld->mAutoselect = ld->mSelectedItem; } success = true; + for (auto &p : ld->mItems) + { + GC::WriteBarrier(p); + } } } } @@ -1125,6 +1137,7 @@ static void BuildEpisodeMenu() { DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu(AllEpisodes[i].mEpisodeName, "Skillmenu", i); od->mItems.Push(it); + GC::WriteBarrier(it); } } } @@ -1230,6 +1243,10 @@ static void BuildPlayerclassMenu() } } success = true; + for (auto &p : ld->mItems) + { + GC::WriteBarrier(p); + } } } } @@ -1261,11 +1278,13 @@ static void BuildPlayerclassMenu() { DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu(pname, "Episodemenu", i); od->mItems.Push(it); + GC::WriteBarrier(it); } } } DOptionMenuItemSubmenu *it = new DOptionMenuItemSubmenu("Random", "Episodemenu", -1); od->mItems.Push(it); + GC::WriteBarrier(it); } } @@ -1355,6 +1374,10 @@ static void InitKeySections() menu->mItems.Push(item); } } + for (auto &p : menu->mItems) + { + GC::WriteBarrier(p); + } } } } @@ -1465,7 +1488,7 @@ void M_StartupSkillMenu(FGameStartup *gs) for(unsigned int i = 0; i < AllSkills.Size(); i++) { FSkillInfo &skill = AllSkills[i]; - DListMenuItem *li; + DMenuItemBase *li; // Using a different name for skills that must be confirmed makes handling this easier. FName action = (skill.MustConfirm && !AllEpisodes[gs->Episode].mNoSkill) ? NAME_StartgameConfirm : NAME_Startgame; @@ -1488,6 +1511,7 @@ void M_StartupSkillMenu(FGameStartup *gs) pItemText? *pItemText : skill.MenuName, ld->mFont, color,ld->mFontColor2, action, i); } ld->mItems.Push(li); + GC::WriteBarrier(li); y += ld->mLinespacing; } if (AllEpisodes[gs->Episode].mNoSkill || AllSkills.Size() == 1) @@ -1541,6 +1565,7 @@ fail: } li = new DOptionMenuItemSubmenu(pItemText? *pItemText : skill.MenuName, action, i); od->mItems.Push(li); + GC::WriteBarrier(li); if (!done) { done = true; diff --git a/src/menu/menuinput.cpp b/src/menu/menuinput.cpp index cca4756f5..71646410d 100644 --- a/src/menu/menuinput.cpp +++ b/src/menu/menuinput.cpp @@ -332,29 +332,25 @@ void DTextEnterMenu::Drawer () const int ch = InputGridChars[y * INPUTGRID_WIDTH + x]; FTexture *pic = SmallFont->GetChar(ch, &width); EColorRange color; - FRemapTable *remap; // The highlighted character is yellow; the rest are dark gray. color = (x == InputGridX && y == InputGridY) ? CR_YELLOW : CR_DARKGRAY; - remap = SmallFont->GetColorTranslation(color); if (pic != NULL) { // Draw a normal character. - screen->DrawTexture(pic, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding, - DTA_Translation, remap, - DTA_CleanNoMove, true, - TAG_DONE); + screen->DrawChar(SmallFont, color, xx + cell_width/2 - width*CleanXfac/2, yy + top_padding, ch, DTA_CleanNoMove, true, TAG_DONE); } else if (ch == ' ') { + FRemapTable *remap = SmallFont->GetColorTranslation(color); // Draw the space as a box outline. We also draw it 50% wider than it really is. const int x1 = xx + cell_width/2 - width * CleanXfac * 3 / 4; const int x2 = x1 + width * 3 * CleanXfac / 2; const int y1 = yy + top_padding; const int y2 = y1 + SmallFont->GetHeight() * CleanYfac; - const int palentry = remap->Remap[remap->NumEntries*2/3]; - const uint32 palcolor = remap->Palette[remap->NumEntries*2/3]; + const int palentry = remap->Remap[remap->NumEntries * 2 / 3]; + const uint32 palcolor = remap->Palette[remap->NumEntries * 2 / 3]; screen->Clear(x1, y1, x2, y1+CleanYfac, palentry, palcolor); // top screen->Clear(x1, y2, x2, y2+CleanYfac, palentry, palcolor); // bottom screen->Clear(x1, y1+CleanYfac, x1+CleanXfac, y2, palentry, palcolor); // left diff --git a/src/menu/optionmenu.cpp b/src/menu/optionmenu.cpp index f6e129ebc..e27ae20a2 100644 --- a/src/menu/optionmenu.cpp +++ b/src/menu/optionmenu.cpp @@ -66,6 +66,10 @@ void M_DrawConText (int color, int x, int y, const char *str) IMPLEMENT_CLASS(DOptionMenu, false, false) +IMPLEMENT_POINTERS_START(DOptionMenu) +IMPLEMENT_POINTER(mFocusControl) +IMPLEMENT_POINTERS_END + //============================================================================= // // diff --git a/src/menu/optionmenuitems.h b/src/menu/optionmenuitems.h index 0acaea9cc..b1821eebf 100644 --- a/src/menu/optionmenuitems.h +++ b/src/menu/optionmenuitems.h @@ -402,7 +402,7 @@ public: if (mParentMenu->IsKindOf(RUNTIME_CLASS(DOptionMenu))) { DOptionMenu *m = barrier_cast(mParentMenu); - DListMenuItem *it = m->GetItem(NAME_Controlmessage); + DMenuItemBase *it = m->GetItem(NAME_Controlmessage); if (it != NULL) { it->SetValue(0, which); @@ -1242,7 +1242,7 @@ IMPLEMENT_CLASS(DOptionMenuTextField, false, false) //============================================================================= // -// [TP] DOptionMenuNumberField +// [TP] FOptionMenuNumberField // // A numeric input field widget, for use with number CVars where sliders are inappropriate (i.e. // where the user is interested in the exact value specifically) diff --git a/src/menu/playerdisplay.cpp b/src/menu/playerdisplay.cpp index bba255bcf..57c8ecf26 100644 --- a/src/menu/playerdisplay.cpp +++ b/src/menu/playerdisplay.cpp @@ -355,19 +355,19 @@ void FBackdropTexture::Render() // //============================================================================= IMPLEMENT_CLASS(DListMenuItemPlayerDisplay, false, false) - DListMenuItemPlayerDisplay::DListMenuItemPlayerDisplay(FListMenuDescriptor *menu, int x, int y, PalEntry c1, PalEntry c2, bool np, FName action) -: DListMenuItem(x, y, action) +: DMenuItemBase(x, y, action) { mOwner = menu; + FRemapTable *bdremap = translationtables[TRANSLATION_Players][MAXPLAYERS + 1]; for (int i = 0; i < 256; i++) { int r = c1.r + c2.r * i / 255; int g = c1.g + c2.g * i / 255; int b = c1.b + c2.b * i / 255; - mRemap.Remap[i] = ColorMatcher.Pick (r, g, b); - mRemap.Palette[i] = PalEntry(255, r, g, b); + bdremap->Remap[i] = ColorMatcher.Pick (r, g, b); + bdremap->Palette[i] = PalEntry(255, r, g, b); } mBackdrop = new FBackdropTexture; mPlayerClass = NULL; @@ -575,10 +575,10 @@ void DListMenuItemPlayerDisplay::Drawer(bool selected) int x = (mXpos - 160) * CleanXfac + (SCREENWIDTH>>1); int y = (mYpos - 100) * CleanYfac + (SCREENHEIGHT>>1); - screen->DrawTexture (mBackdrop, x, y - 1, + screen->DrawTexture(mBackdrop, x, y - 1, DTA_DestWidth, 72 * CleanXfac, DTA_DestHeight, 80 * CleanYfac, - DTA_Translation, &mRemap, + DTA_TranslationIndex, TRANSLATION(TRANSLATION_Players, MAXPLAYERS + 1), DTA_Masked, true, TAG_DONE); @@ -606,13 +606,12 @@ void DListMenuItemPlayerDisplay::Drawer(bool selected) FTexture *tex = TexMan(sprframe->Texture[mRotation]); if (tex != NULL && tex->UseType != FTexture::TEX_Null) { - FRemapTable *trans = NULL; - if (mTranslate) trans = translationtables[TRANSLATION_Players](MAXPLAYERS); + int trans = mTranslate? TRANSLATION(TRANSLATION_Players, MAXPLAYERS) : 0; screen->DrawTexture (tex, x + 36*CleanXfac, y + 71*CleanYfac, DTA_DestWidthF, tex->GetScaledWidthDouble() * CleanXfac * Scale.X, DTA_DestHeightF, tex->GetScaledHeightDouble() * CleanYfac * Scale.Y, - DTA_Translation, trans, + DTA_TranslationIndex, trans, DTA_FlipX, sprframe->Flip & (1 << mRotation), TAG_DONE); } diff --git a/src/menu/playermenu.cpp b/src/menu/playermenu.cpp index ea2489e9c..7116608b3 100644 --- a/src/menu/playermenu.cpp +++ b/src/menu/playermenu.cpp @@ -499,11 +499,11 @@ class DPlayerMenu : public DListMenu void UpdateTranslation(); void SendNewColor (int red, int green, int blue); - void PlayerNameChanged(DListMenuItem *li); - void ColorSetChanged (DListMenuItem *li); - void ClassChanged (DListMenuItem *li); - void AutoaimChanged (DListMenuItem *li); - void SkinChanged (DListMenuItem *li); + void PlayerNameChanged(DMenuItemBase *li); + void ColorSetChanged (DMenuItemBase *li); + void ClassChanged (DMenuItemBase *li); + void AutoaimChanged (DMenuItemBase *li); + void SkinChanged (DMenuItemBase *li); public: @@ -527,7 +527,7 @@ IMPLEMENT_CLASS(DPlayerMenu, false, false) void DPlayerMenu::Init(DMenu *parent, FListMenuDescriptor *desc) { - DListMenuItem *li; + DMenuItemBase *li; Super::Init(parent, desc); PickPlayerClass(); @@ -655,7 +655,7 @@ bool DPlayerMenu::Responder (event_t *ev) { // turn the player sprite around mRotation = 8 - mRotation; - DListMenuItem *li = GetItem(NAME_Playerdisplay); + DMenuItemBase *li = GetItem(NAME_Playerdisplay); if (li != NULL) { li->SetValue(DListMenuItemPlayerDisplay::PDF_ROTATION, mRotation); @@ -745,7 +745,7 @@ void DPlayerMenu::SendNewColor (int red, int green, int blue) void DPlayerMenu::UpdateColorsets() { - DListMenuItem *li = GetItem(NAME_Color); + DMenuItemBase *li = GetItem(NAME_Color); if (li != NULL) { int sel = 0; @@ -781,7 +781,7 @@ void DPlayerMenu::UpdateSkins() { int sel = 0; int skin; - DListMenuItem *li = GetItem(NAME_Skin); + DMenuItemBase *li = GetItem(NAME_Skin); if (li != NULL) { if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN || @@ -824,7 +824,7 @@ void DPlayerMenu::UpdateSkins() // //============================================================================= -void DPlayerMenu::PlayerNameChanged(DListMenuItem *li) +void DPlayerMenu::PlayerNameChanged(DMenuItemBase *li) { char pp[MAXPLAYERNAME+1]; const char *p; @@ -852,7 +852,7 @@ void DPlayerMenu::PlayerNameChanged(DListMenuItem *li) // //============================================================================= -void DPlayerMenu::ColorSetChanged (DListMenuItem *li) +void DPlayerMenu::ColorSetChanged (DMenuItemBase *li) { int sel; @@ -862,9 +862,9 @@ void DPlayerMenu::ColorSetChanged (DListMenuItem *li) if (sel > 0) mycolorset = PlayerColorSets[sel-1]; - DListMenuItem *red = GetItem(NAME_Red); - DListMenuItem *green = GetItem(NAME_Green); - DListMenuItem *blue = GetItem(NAME_Blue); + DMenuItemBase *red = GetItem(NAME_Red); + DMenuItemBase *green = GetItem(NAME_Green); + DMenuItemBase *blue = GetItem(NAME_Blue); // disable the sliders if a valid colorset is selected if (red != NULL) red->Enable(mycolorset == -1); @@ -885,7 +885,7 @@ void DPlayerMenu::ColorSetChanged (DListMenuItem *li) // //============================================================================= -void DPlayerMenu::ClassChanged (DListMenuItem *li) +void DPlayerMenu::ClassChanged (DMenuItemBase *li) { if (PlayerClasses.Size () == 1) { @@ -919,7 +919,7 @@ void DPlayerMenu::ClassChanged (DListMenuItem *li) // //============================================================================= -void DPlayerMenu::SkinChanged (DListMenuItem *li) +void DPlayerMenu::SkinChanged (DMenuItemBase *li) { if (GetDefaultByType (PlayerClass->Type)->flags4 & MF4_NOSKIN || players[consoleplayer].userinfo.GetPlayerClassNum() == -1) @@ -950,7 +950,7 @@ void DPlayerMenu::SkinChanged (DListMenuItem *li) // //============================================================================= -void DPlayerMenu::AutoaimChanged (DListMenuItem *li) +void DPlayerMenu::AutoaimChanged (DMenuItemBase *li) { int sel; @@ -971,7 +971,7 @@ bool DPlayerMenu::MenuEvent (int mkey, bool fromcontroller) int v; if (mDesc->mSelectedItem >= 0) { - DListMenuItem *li = mDesc->mItems[mDesc->mSelectedItem]; + DMenuItemBase *li = mDesc->mItems[mDesc->mSelectedItem]; if (li->MenuEvent(mkey, fromcontroller)) { FName current = li->GetAction(NULL); @@ -1067,7 +1067,7 @@ bool DPlayerMenu::MenuEvent (int mkey, bool fromcontroller) bool DPlayerMenu::MouseEvent(int type, int x, int y) { int v; - DListMenuItem *li = mFocusControl; + DMenuItemBase *li = mFocusControl; bool res = Super::MouseEvent(type, x, y); if (li == NULL) li = mFocusControl; if (li != NULL) diff --git a/src/menu/readthis.cpp b/src/menu/readthis.cpp index f1e82cd51..06d4620da 100644 --- a/src/menu/readthis.cpp +++ b/src/menu/readthis.cpp @@ -105,7 +105,7 @@ void DReadThisMenu::Drawer() { screen->DrawTexture (prevpic, 0, 0, DTA_Fullscreen, true, TAG_DONE); } - screen->DrawTexture (tex, 0, 0, DTA_Fullscreen, true, DTA_AlphaF, alpha, TAG_DONE); + screen->DrawTexture (tex, 0, 0, DTA_Fullscreen, true, DTA_Alpha, alpha, TAG_DONE); } diff --git a/src/namedef.h b/src/namedef.h index ef7f1c58d..2bdb74ee6 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -346,6 +346,7 @@ xx(SinH) xx(TanH) xx(ATan2) xx(VectorAngle) +xx(New) xx(Alpha) xx(Angle) xx(Args) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index f89a560ab..c732ea18c 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -79,6 +79,7 @@ #include "thingdef.h" #include "math/cmath.h" #include "g_levellocals.h" +#include "r_utility.h" AActor *SingleActorFromTID(int tid, AActor *defactor); @@ -6913,3 +6914,27 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetSize) ACTION_RETURN_BOOL(true); } + +DEFINE_ACTION_FUNCTION(AActor, SetCamera) +{ + PARAM_ACTION_PROLOGUE(AActor); + PARAM_OBJECT(cam, AActor); + PARAM_BOOL_DEF(revert); + + if (self->player == nullptr || self->player->mo != self) return 0; + + if (camera == nullptr) + { + camera = self; + revert = false; + } + AActor *oldcamera = self->player->camera; + self->player->camera = camera; + if (revert) self->player->cheats |= CF_REVERTPLEASE; + + if (oldcamera != camera) + { + R_ClearPastViewer(camera); + } + return 0; +} diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index ac6c2bc23..a77a7358d 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -1061,10 +1061,10 @@ public: mysnprintf(goldstr, countof(goldstr), "%d", coin != NULL ? coin->Amount : 0); screen->DrawText(SmallFont, CR_GRAY, 21, 191, goldstr, DTA_320x200, true, - DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE); + DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE); screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon), 3, 190, DTA_320x200, true, - DTA_FillColor, 0, DTA_AlphaF, HR_SHADOW, TAG_DONE); + DTA_FillColor, 0, DTA_Alpha, HR_SHADOW, TAG_DONE); screen->DrawText(SmallFont, CR_GRAY, 20, 190, goldstr, DTA_320x200, true, TAG_DONE); screen->DrawTexture(TexMan(((AInventory *)GetDefaultByType(cointype))->Icon), 2, 189, DTA_320x200, true, TAG_DONE); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 2926e4e8c..bd5a9cb17 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -570,8 +570,9 @@ bool P_Move (AActor *actor) return true; } - if (actor->movedir == DI_NODIR) + if (actor->movedir >= DI_NODIR) { + actor->movedir = DI_NODIR; // make sure it's valid. return false; } @@ -585,9 +586,6 @@ bool P_Move (AActor *actor) return false; } - if ((unsigned)actor->movedir >= 8) - I_Error ("Weird actor->movedir!"); - // killough 10/98: allow dogs to drop off of taller ledges sometimes. // dropoff==1 means always allow it, dropoff==2 means only up to 128 high, // and only if the target is immediately on the other side of the line. diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 78d6e22c9..64f490b30 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -740,6 +740,8 @@ void R_InitTranslationTables () } // The menu player also gets a separate translation table PushIdentityTable(TRANSLATION_Players); + // This one is for the backdrop in the menu + PushIdentityTable(TRANSLATION_Players); // The three standard translations from Doom or Heretic (seven for Strife), // plus the generic ice translation. diff --git a/src/r_things.cpp b/src/r_things.cpp index a468e4c58..488d771bd 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1713,7 +1713,7 @@ void R_DrawRemainingPlayerSprites() viewwindowy + viewheight/2 - vis->texturemid * vis->yscale - 0.5, DTA_DestWidthF, FIXED2DBL(vis->pic->GetWidth() * vis->xscale), DTA_DestHeightF, vis->pic->GetHeight() * vis->yscale, - DTA_Translation, TranslationToTable(vis->Translation), + DTA_TranslationIndex, vis->Translation, DTA_FlipX, flip, DTA_TopOffset, 0, DTA_LeftOffset, 0, @@ -1721,7 +1721,7 @@ void R_DrawRemainingPlayerSprites() DTA_ClipTop, viewwindowy, DTA_ClipRight, viewwindowx + viewwidth, DTA_ClipBottom, viewwindowy + viewheight, - DTA_AlphaF, vis->Style.Alpha, + DTA_Alpha, vis->Style.Alpha, DTA_RenderStyle, vis->RenderStyle, DTA_FillColor, vis->FillColor, DTA_SpecialColormap, special, diff --git a/src/r_utility.cpp b/src/r_utility.cpp index d2358d8b3..a7a3860bb 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -337,8 +337,6 @@ void R_Init () { atterm (R_Shutdown); - StartScreen->Progress(); - V_InitFonts(); StartScreen->Progress(); // Colormap init moved back to InitPalette() //R_InitColormaps (); diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c05065802..6f5286af1 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -1420,6 +1420,76 @@ ExpEmit FxSoundCast::Emit(VMFunctionBuilder *build) return to; } +//========================================================================== +// +// +// +//========================================================================== + +FxFontCast::FxFontCast(FxExpression *x) + : FxExpression(EFX_FontCast, x->ScriptPosition) +{ + basex = x; + ValueType = TypeSound; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFontCast::~FxFontCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxFontCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType == TypeFont) + { + FxExpression *x = basex; + basex = nullptr; + delete this; + return x; + } + // This intentionally does not convert non-constants. + // The sole reason for this cast is to allow passing both font pointers and string constants to printing functions and have the font names checked at compile time. + else if ((basex->ValueType == TypeString || basex->ValueType == TypeName) && basex->isConstant()) + { + ExpVal constval = static_cast(basex)->GetValue(); + FFont *font = V_GetFont(constval.GetString()); + // Font must exist. Most internal functions working with fonts do not like null pointers. + // If checking is needed scripts will have to call Font.GetFont themselves. + if (font == nullptr) + { + ScriptPosition.Message(MSG_ERROR, "Unknown font '%s'", constval.GetString().GetChars()); + delete this; + return nullptr; + } + + FxExpression *x = new FxConstant(font, ScriptPosition); + delete this; + return x; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Cannot convert to font"); + delete this; + return nullptr; + } +} + + //========================================================================== // // generic type cast operator @@ -1649,6 +1719,14 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) { goto basereturn; } + else if (ValueType == TypeFont) + { + FxExpression *x = new FxFontCast(basex); + x = x->Resolve(ctx); + basex = nullptr; + delete this; + return x; + } // todo: pointers to class objects. // All other types are only compatible to themselves and have already been handled above by the equality check. // Anything that falls through here is not compatible and must print an error. @@ -4918,6 +4996,70 @@ ExpEmit FxATan2::Emit(VMFunctionBuilder *build) return out; } +//========================================================================== +// +// +// +//========================================================================== +FxNew::FxNew(FxExpression *v) + : FxExpression(EFX_New, v->ScriptPosition) +{ + val = new FxClassTypeCast(NewClassPointer(RUNTIME_CLASS(DObject)), v, false); + ValueType = NewPointer(RUNTIME_CLASS(DObject)); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxNew::~FxNew() +{ + SAFE_DELETE(val); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxNew::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(val, ctx); + + if (!val->ValueType->IsKindOf(RUNTIME_CLASS(PClassPointer))) + { + ScriptPosition.Message(MSG_ERROR, "Class type expected"); + delete this; + return nullptr; + } + if (val->isConstant()) + { + auto cls = static_cast(static_cast(val)->GetValue().GetPointer()); + ValueType = NewPointer(cls); + } + return this; +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpEmit FxNew::Emit(VMFunctionBuilder *build) +{ + assert(ValueType == val->ValueType); + ExpEmit from = val->Emit(build); + from.Free(build); + ExpEmit to(build, REGT_POINTER); + build->Emit(from.Konst ? OP_NEW_K : OP_NEW, to.RegNum, from.RegNum); + return to; +} + //========================================================================== // // The atan2 opcode only takes registers as parameters, so any constants @@ -6489,7 +6631,9 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build) if (membervar->BitValue == -1) { if (offsetreg == -1) offsetreg = build->GetConstantInt(0); - build->Emit(membervar->Type->GetLoadOp(), loc.RegNum, build->FramePointer.RegNum, offsetreg); + auto op = membervar->Type->GetLoadOp(); + if (op == OP_LO) op = OP_LOS; + build->Emit(op, loc.RegNum, build->FramePointer.RegNum, offsetreg); } else { @@ -7428,6 +7572,15 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } break; + case NAME_New: + if (CheckArgSize(MethodName, ArgList, 1, 1, ScriptPosition)) + { + func = new FxNew(ArgList[0]); + ArgList[0] = nullptr; + } + break; + + default: ScriptPosition.Message(MSG_ERROR, "Call to unknown function '%s'", MethodName.GetChars()); break; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 42d5b0ccf..6438e0868 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -242,6 +242,7 @@ enum EFxType EFX_Conditional, EFX_Abs, EFX_ATan2, + EFX_New, EFX_MinMax, EFX_Random, EFX_RandomPick, @@ -293,6 +294,7 @@ enum EFxType EFX_StrLen, EFX_ColorLiteral, EFX_GetDefaultByType, + EFX_FontCast, EFX_COUNT }; @@ -487,6 +489,13 @@ public: isresolved = true; } + FxConstant(FFont *state, const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) + { + value.pointer = state; + ValueType = value.Type = TypeFont; + isresolved = true; + } + FxConstant(const FScriptPosition &pos) : FxExpression(EFX_Constant, pos) { value.pointer = nullptr; @@ -663,6 +672,18 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +class FxFontCast : public FxExpression +{ + FxExpression *basex; + +public: + + FxFontCast(FxExpression *x); + ~FxFontCast(); + FxExpression *Resolve(FCompileContext&); +}; + + //========================================================================== // // FxTypeCast @@ -1176,6 +1197,26 @@ public: private: ExpEmit ToReg(VMFunctionBuilder *build, FxExpression *val); }; + +//========================================================================== +// +// +// +//========================================================================== + +class FxNew : public FxExpression +{ + FxExpression *val; + +public: + + FxNew(FxExpression *v); + ~FxNew(); + FxExpression *Resolve(FCompileContext&); + + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index e15792df6..218fc7bc4 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -53,6 +53,7 @@ #include "vm.h" #include "p_checkposition.h" #include "r_sky.h" +#include "v_font.h" static TArray properties; static TArray AFTable; @@ -801,34 +802,51 @@ void InitThingdef() pstruct->Size = sizeof(player_t); pstruct->Align = alignof(player_t); PArray *parray = NewArray(pstruct, MAXPLAYERS); - PField *playerf = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players); - Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf); + PField *fieldptr = new PField("players", parray, VARF_Native | VARF_Static, (intptr_t)&players); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); pstruct->AddNativeField("weapons", NewNativeStruct("WeaponSlots", nullptr), myoffsetof(player_t, weapons), VARF_Native); parray = NewArray(TypeBool, MAXPLAYERS); - playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); - Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf); + fieldptr = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); - playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction); - Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf); + fieldptr = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); - playerf = new PField("skyflatnum", TypeTextureID, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&skyflatnum); - Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf); + fieldptr = new PField("skyflatnum", TypeTextureID, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&skyflatnum); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); - playerf = new PField("globalfreeze", TypeUInt8, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&bglobal.freeze); - Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf); + fieldptr = new PField("globalfreeze", TypeUInt8, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&bglobal.freeze); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); - playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer); - Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf); + fieldptr = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); + + auto fontptr = NewPointer(NewNativeStruct("Font", nullptr)); + + fieldptr = new PField("smallfont", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&SmallFont); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); + + fieldptr = new PField("smallfont2", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&SmallFont2); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); + + fieldptr = new PField("bigfont", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&BigFont); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); + + fieldptr = new PField("confont", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&ConFont); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); + + fieldptr = new PField("intermissionfont", fontptr, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&IntermissionFont); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); // Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag. // It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution' // is to create a static variable from it and reference that in the script. Yuck!!! static AWeapon *wpnochg = WP_NOCHANGE; - playerf = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg); - Namespaces.GlobalNamespace->Symbols.AddSymbol(playerf); + fieldptr = new PField("WP_NOCHANGE", NewPointer(RUNTIME_CLASS(AWeapon), false), VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&wpnochg); + Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr); // synthesize a symbol for each flag from the flag name tables to avoid redundant declaration of them. for (auto &fl : FlagLists) diff --git a/src/scripting/vm/vm.h b/src/scripting/vm/vm.h index 060fa0a76..1a5c10b4e 100644 --- a/src/scripting/vm/vm.h +++ b/src/scripting/vm/vm.h @@ -193,6 +193,7 @@ enum enum EVMAbortException { + X_OTHER, X_READ_NIL, X_WRITE_NIL, X_TOO_MANY_TRIES, diff --git a/src/scripting/vm/vmbuilder.cpp b/src/scripting/vm/vmbuilder.cpp index 46553ab72..19fe81c32 100644 --- a/src/scripting/vm/vmbuilder.cpp +++ b/src/scripting/vm/vmbuilder.cpp @@ -281,8 +281,8 @@ unsigned VMFunctionBuilder::GetConstantAddress(void *ptr, VM_ATAG tag) AddrKonst *locp = AddressConstantMap.CheckKey(ptr); if (locp != NULL) { - // There should only be one tag associated with a memory location. - assert(locp->Tag == tag); + // There should only be one tag associated with a memory location. Exceptions are made for null pointers that got allocated through constant arrays. + assert(ptr == nullptr || locp->Tag == tag); return locp->KonstNum; } else diff --git a/src/scripting/vm/vmdisasm.cpp b/src/scripting/vm/vmdisasm.cpp index d21e38d20..276533e2d 100644 --- a/src/scripting/vm/vmdisasm.cpp +++ b/src/scripting/vm/vmdisasm.cpp @@ -72,6 +72,7 @@ #define RFRF MODE_AF | MODE_BF | MODE_CUNUSED #define RSRS MODE_AS | MODE_BS | MODE_CUNUSED #define RPRP MODE_AP | MODE_BP | MODE_CUNUSED +#define RPKP MODE_AP | MODE_BKP | MODE_CUNUSED #define RXRXI8 MODE_AX | MODE_BX | MODE_CIMMZ #define RPRPRP MODE_AP | MODE_BP | MODE_CP #define RPRPKP MODE_AP | MODE_BP | MODE_CKP diff --git a/src/scripting/vm/vmexec.h b/src/scripting/vm/vmexec.h index d916658d7..38dbbc411 100644 --- a/src/scripting/vm/vmexec.h +++ b/src/scripting/vm/vmexec.h @@ -209,6 +209,18 @@ begin: reg.a[a] = GC::ReadBarrier(*(DObject **)ptr); reg.atag[a] = ATAG_OBJECT; NEXTOP; + OP(LOS): + ASSERTA(a); ASSERTA(B); ASSERTKD(C); + GETADDR(PB,KC,X_READ_NIL); + reg.a[a] = *(DObject **)ptr; + reg.atag[a] = ATAG_OBJECT; + NEXTOP; + OP(LOS_R): + ASSERTA(a); ASSERTA(B); ASSERTD(C); + GETADDR(PB,RC,X_READ_NIL); + reg.a[a] = *(DObject **)ptr; + reg.atag[a] = ATAG_OBJECT; + NEXTOP; OP(LP): ASSERTA(a); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); @@ -759,6 +771,14 @@ begin: assert(0); NEXTOP; + OP(NEW_K): + OP(NEW): + { + PClass *cls = (PClass*)(pc->op == OP_NEW ? reg.a[C] : konsta[C].v); + reg.a[B] = cls->CreateNew(); + NEXTOP; + } + OP(TRY): assert(try_depth < MAX_TRY_DEPTH); if (try_depth >= MAX_TRY_DEPTH) diff --git a/src/scripting/vm/vmframe.cpp b/src/scripting/vm/vmframe.cpp index 7615a4f0f..c44fbb2ea 100644 --- a/src/scripting/vm/vmframe.cpp +++ b/src/scripting/vm/vmframe.cpp @@ -554,6 +554,10 @@ CVMAbortException::CVMAbortException(EVMAbortException reason, const char *morei AppendMessage("string format failed."); break; + case X_OTHER: + // no prepended message. + break; + default: { size_t len = strlen(m_Message); diff --git a/src/scripting/vm/vmops.h b/src/scripting/vm/vmops.h index 0829ab2c6..3fc3d7643 100644 --- a/src/scripting/vm/vmops.h +++ b/src/scripting/vm/vmops.h @@ -44,6 +44,8 @@ xx(LS, ls, RSRPKI, LS_R, 4, REGT_INT), // load string xx(LS_R, ls, RSRPRI, NOP, 0, 0), xx(LO, lo, RPRPKI, LO_R, 4, REGT_INT), // load object xx(LO_R, lo, RPRPRI, NOP, 0, 0), +xx(LOS, los, RPRPKI, LOS_R, 4, REGT_INT), // load object (stack version without read barrier) +xx(LOS_R, lo, RPRPRI, NOP, 0, 0), xx(LP, lp, RPRPKI, LP_R, 4, REGT_INT), // load pointer xx(LP_R, lp, RPRPRI, NOP, 0, 0), xx(LV2, lv2, RVRPKI, LV2_R, 4, REGT_INT), // load vector2 @@ -104,6 +106,8 @@ xx(TAIL_K, tail, KPI8, TAIL, 1, REGT_POINTER), xx(RESULT, result, __BCP, NOP, 0, 0), // Result should go in register encoded in BC (in caller, after CALL) xx(RET, ret, I8BCP, NOP, 0, 0), // Copy value from register encoded in BC to return value A, possibly returning xx(RETI, reti, I8I16, NOP, 0, 0), // Copy immediate from BC to return value A, possibly returning +xx(NEW, new, RPRP, NOP, 0, 0), +xx(NEW_K, new, RPKP, NOP, 0, 0), xx(TRY, try, I24, NOP, 0, 0), // When an exception is thrown, start searching for a handler at pc + ABC xx(UNTRY, untry, I8, NOP, 0, 0), // Pop A entries off the exception stack xx(THROW, throw, THROW, NOP, 0, 0), // A == 0: Throw exception object pB diff --git a/src/serializer.cpp b/src/serializer.cpp index 6d7a6ef7c..a577056af 100644 --- a/src/serializer.cpp +++ b/src/serializer.cpp @@ -2187,17 +2187,17 @@ template<> FSerializer &Serialize(FSerializer &arc, const char *key, FFont *&fon { if (arc.isWriting()) { - const char *n = font->GetName(); - return arc.StringPtr(key, n); + FName n = font->GetName(); + return arc(key, n); } else { - const char *n; - arc.StringPtr(key, n); + FName n; + arc(key, n); font = V_GetFont(n); if (font == nullptr) { - Printf(TEXTCOLOR_ORANGE "Could not load font %s\n", n); + Printf(TEXTCOLOR_ORANGE "Could not load font %s\n", n.GetChars()); font = SmallFont; } return arc; diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 9db885efb..52f8cde7a 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -91,6 +91,17 @@ CVAR (Bool, hud_scale, true, CVAR_ARCHIVE); static int LastPal = -1; static uint32 LastRGB; +DEFINE_ACTION_FUNCTION(_Screen, GetWidth) +{ + PARAM_PROLOGUE; + ACTION_RETURN_INT(screen->GetWidth()); +} + +DEFINE_ACTION_FUNCTION(_Screen, GetHeight) +{ + PARAM_PROLOGUE; + ACTION_RETURN_INT(screen->GetHeight()); +} static int PalFromRGB(uint32 rgb) { @@ -115,6 +126,7 @@ static int PalFromRGB(uint32 rgb) return LastPal; } + void DCanvas::DrawTexture (FTexture *img, double x, double y, int tags_first, ...) { va_list tags; @@ -130,6 +142,31 @@ void DCanvas::DrawTexture (FTexture *img, double x, double y, int tags_first, .. DrawTextureParms(img, parms); } +int ListGetInt(VMVa_List &tags); + +void DCanvas::DrawTexture(FTexture *img, double x, double y, VMVa_List &args) +{ + DrawParms parms; + uint32_t tag = ListGetInt(args); + bool res = ParseDrawTextureTags(img, x, y, tag, args, &parms, false); + if (!res) return; + DrawTextureParms(img, parms); +} + +DEFINE_ACTION_FUNCTION(_Screen, DrawTexture) +{ + PARAM_PROLOGUE; + PARAM_INT(texid); + PARAM_BOOL(animate); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + + FTexture *tex = animate ? TexMan(FSetTextureID(texid)) : TexMan[FSetTextureID(texid)]; + VMVa_List args = { param + 4, 0, numparam - 4 }; + screen->DrawTexture(tex, x, y, args); + return 0; +} + DEFINE_ACTION_FUNCTION(_Screen, DrawHUDTexture) { PARAM_PROLOGUE; @@ -164,7 +201,7 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) { parms.colorOverlay = PalEntry(parms.colorOverlay).InverseColor(); } - // Note that this overrides DTA_Translation in software, but not in hardware. + // Note that this overrides the translation in software, but not in hardware. FDynamicColormap *colormap = GetSpecialLights(MAKERGB(255,255,255), parms.colorOverlay & MAKEARGB(0,255,255,255), 0); translation = &colormap->Maps[(APART(parms.colorOverlay)*NUMCOLORMAPS/255)*256]; @@ -420,7 +457,70 @@ bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double return false; } -bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag, va_list tags, DrawParms *parms, bool fortext) const +static void ListEnd(va_list &tags) +{ + va_end(tags); +} + +static int ListGetInt(va_list &tags) +{ + return va_arg(tags, int); +} + +static inline double ListGetDouble(va_list &tags) +{ + return va_arg(tags, double); +} + +// These two options are only being used by the D3D version of the HUD weapon drawer, they serve no purpose anywhere else. +static inline FSpecialColormap * ListGetSpecialColormap(va_list &tags) +{ + return va_arg(tags, FSpecialColormap *); +} + +static inline FColormapStyle * ListGetColormapStyle(va_list &tags) +{ + return va_arg(tags, FColormapStyle *); +} + +static void ListEnd(VMVa_List &tags) +{ +} + +int ListGetInt(VMVa_List &tags) +{ + if (tags.curindex < tags.numargs && tags.args[tags.curindex].Type == REGT_INT) + { + return tags.args[tags.curindex++].i; + } + ThrowAbortException(X_OTHER, "Invalid parameter in draw function, int expected"); + return 0; +} + +static inline double ListGetDouble(VMVa_List &tags) +{ + if (tags.curindex < tags.numargs && tags.args[tags.curindex].Type == REGT_FLOAT) + { + return tags.args[tags.curindex++].f; + } + ThrowAbortException(X_OTHER, "Invalid parameter in draw function, float expected"); + return 0; +} + +static inline FSpecialColormap * ListGetSpecialColormap(VMVa_List &tags) +{ + ThrowAbortException(X_OTHER, "Invalid tag in draw function"); + return nullptr; +} + +static inline FColormapStyle * ListGetColormapStyle(VMVa_List &tags) +{ + ThrowAbortException(X_OTHER, "Invalid tag in draw function"); + return nullptr; +} + +template +bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, DWORD tag, T& tags, DrawParms *parms, bool fortext) const { INTBOOL boolval; int intval; @@ -431,7 +531,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag { if (img == NULL || img->UseType == FTexture::TEX_Null) { - va_end(tags); + ListEnd(tags); return false; } } @@ -439,7 +539,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag // Do some sanity checks on the coordinates. if (x < -16383 || x > 16383 || y < -16383 || y > 16383) { - va_end(tags); + ListEnd(tags); return false; } @@ -481,44 +581,42 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag // doubles when passed as function arguments.) while (tag != TAG_DONE) { - DWORD data; - switch (tag) { default: - data = va_arg(tags, DWORD); + ListGetInt(tags); break; case DTA_DestWidth: assert(fortext == false); if (fortext) return false; parms->cleanmode = DTA_Base; - parms->destwidth = va_arg(tags, int); + parms->destwidth = ListGetInt(tags); break; case DTA_DestWidthF: assert(fortext == false); if (fortext) return false; parms->cleanmode = DTA_Base; - parms->destwidth = va_arg(tags, double); + parms->destwidth = ListGetDouble(tags); break; case DTA_DestHeight: assert(fortext == false); if (fortext) return false; parms->cleanmode = DTA_Base; - parms->destheight = va_arg(tags, int); + parms->destheight = ListGetInt(tags); break; case DTA_DestHeightF: assert(fortext == false); if (fortext) return false; parms->cleanmode = DTA_Base; - parms->destheight = va_arg(tags, double); + parms->destheight = ListGetDouble(tags); break; case DTA_Clean: - boolval = va_arg(tags, INTBOOL); + boolval = ListGetInt(tags); if (boolval) { parms->scalex = 1; @@ -528,7 +626,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_CleanNoMove: - boolval = va_arg(tags, INTBOOL); + boolval = ListGetInt(tags); if (boolval) { parms->scalex = CleanXfac; @@ -538,7 +636,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_CleanNoMove_1: - boolval = va_arg(tags, INTBOOL); + boolval = ListGetInt(tags); if (boolval) { parms->scalex = CleanXfac_1; @@ -548,7 +646,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_320x200: - boolval = va_arg(tags, INTBOOL); + boolval = ListGetInt(tags); if (boolval) { parms->cleanmode = DTA_Base; @@ -560,7 +658,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_Bottom320x200: - boolval = va_arg(tags, INTBOOL); + boolval = ListGetInt(tags); if (boolval) { parms->cleanmode = DTA_Base; @@ -573,32 +671,32 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_HUDRules: - intval = va_arg(tags, int); + intval = ListGetInt(tags); parms->cleanmode = intval == HUD_HorizCenter ? DTA_HUDRulesC : DTA_HUDRules; break; case DTA_VirtualWidth: parms->cleanmode = DTA_Base; - parms->virtWidth = va_arg(tags, int); + parms->virtWidth = ListGetInt(tags); break; case DTA_VirtualWidthF: parms->cleanmode = DTA_Base; - parms->virtWidth = va_arg(tags, double); + parms->virtWidth = ListGetDouble(tags); break; - + case DTA_VirtualHeight: parms->cleanmode = DTA_Base; - parms->virtHeight = va_arg(tags, int); + parms->virtHeight = ListGetInt(tags); break; case DTA_VirtualHeightF: parms->cleanmode = DTA_Base; - parms->virtHeight = va_arg(tags, double); + parms->virtHeight = ListGetDouble(tags); break; case DTA_Fullscreen: - boolval = va_arg(tags, INTBOOL); + boolval = ListGetInt(tags); if (boolval) { assert(fortext == false); @@ -610,66 +708,58 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_Alpha: - parms->Alpha = FIXED2FLOAT(MIN(OPAQUE, va_arg (tags, fixed_t))); - break; - - case DTA_AlphaF: - parms->Alpha = (float)(MIN(1., va_arg(tags, double))); + parms->Alpha = (float)(MIN(1., ListGetDouble(tags))); break; case DTA_AlphaChannel: - parms->alphaChannel = va_arg(tags, INTBOOL); + parms->alphaChannel = ListGetInt(tags); break; case DTA_FillColor: - parms->fillcolor = va_arg(tags, uint32); + parms->fillcolor = ListGetInt(tags); fillcolorset = true; break; - case DTA_Translation: - parms->remap = va_arg(tags, FRemapTable *); - if (parms->remap != NULL && parms->remap->Inactive) - { // If it's inactive, pretend we were passed NULL instead. - parms->remap = NULL; - } + case DTA_TranslationIndex: + parms->remap = TranslationToTable(ListGetInt(tags)); break; case DTA_ColorOverlay: - parms->colorOverlay = va_arg(tags, DWORD); + parms->colorOverlay = ListGetInt(tags); break; case DTA_FlipX: - parms->flipX = va_arg(tags, INTBOOL); + parms->flipX = ListGetInt(tags); break; case DTA_TopOffset: assert(fortext == false); if (fortext) return false; - parms->top = va_arg(tags, int); + parms->top = ListGetInt(tags); break; case DTA_TopOffsetF: assert(fortext == false); if (fortext) return false; - parms->top = va_arg(tags, double); + parms->top = ListGetDouble(tags); break; case DTA_LeftOffset: assert(fortext == false); if (fortext) return false; - parms->left = va_arg(tags, int); + parms->left = ListGetInt(tags); break; case DTA_LeftOffsetF: assert(fortext == false); if (fortext) return false; - parms->left = va_arg(tags, double); + parms->left = ListGetDouble(tags); break; case DTA_CenterOffset: assert(fortext == false); if (fortext) return false; - if (va_arg(tags, int)) + if (ListGetInt(tags)) { parms->left = img->GetScaledWidthDouble() * 0.5; parms->top = img->GetScaledHeightDouble() * 0.5; @@ -679,7 +769,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag case DTA_CenterBottomOffset: assert(fortext == false); if (fortext) return false; - if (va_arg(tags, int)) + if (ListGetInt(tags)) { parms->left = img->GetScaledWidthDouble() * 0.5; parms->top = img->GetScaledHeightDouble(); @@ -689,29 +779,29 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag case DTA_WindowLeft: assert(fortext == false); if (fortext) return false; - parms->windowleft = va_arg(tags, int); + parms->windowleft = ListGetInt(tags); break; case DTA_WindowLeftF: assert(fortext == false); if (fortext) return false; - parms->windowleft = va_arg(tags, double); + parms->windowleft = ListGetDouble(tags); break; case DTA_WindowRight: assert(fortext == false); if (fortext) return false; - parms->windowright = va_arg(tags, int); + parms->windowright = ListGetInt(tags); break; case DTA_WindowRightF: assert(fortext == false); if (fortext) return false; - parms->windowright = va_arg(tags, double); + parms->windowright = ListGetDouble(tags); break; case DTA_ClipTop: - parms->uclip = va_arg(tags, int); + parms->uclip = ListGetInt(tags); if (parms->uclip < 0) { parms->uclip = 0; @@ -719,7 +809,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_ClipBottom: - parms->dclip = va_arg(tags, int); + parms->dclip = ListGetInt(tags); if (parms->dclip > this->GetHeight()) { parms->dclip = this->GetHeight(); @@ -727,7 +817,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_ClipLeft: - parms->lclip = va_arg(tags, int); + parms->lclip = ListGetInt(tags); if (parms->lclip < 0) { parms->lclip = 0; @@ -735,7 +825,7 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_ClipRight: - parms->rclip = va_arg(tags, int); + parms->rclip = ListGetInt(tags); if (parms->rclip > this->GetWidth()) { parms->rclip = this->GetWidth(); @@ -743,18 +833,18 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_ShadowAlpha: - parms->shadowAlpha = MIN(OPAQUE, va_arg (tags, fixed_t)); + parms->shadowAlpha = (float)MIN(1., ListGetDouble(tags)); break; case DTA_ShadowColor: - parms->shadowColor = va_arg(tags, int); + parms->shadowColor = ListGetInt(tags); break; case DTA_Shadow: - boolval = va_arg(tags, INTBOOL); + boolval = ListGetInt(tags); if (boolval) { - parms->shadowAlpha = FRACUNIT/2; + parms->shadowAlpha = 0.5; parms->shadowColor = 0; } else @@ -764,47 +854,52 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_Masked: - parms->masked = va_arg(tags, INTBOOL); + parms->masked = ListGetInt(tags); break; case DTA_BilinearFilter: - parms->bilinear = va_arg(tags, INTBOOL); + parms->bilinear = ListGetInt(tags); break; case DTA_KeepRatio: // I think this is a terribly misleading name, since it actually turns // *off* aspect ratio correction. - parms->keepratio = va_arg(tags, INTBOOL); + parms->keepratio = ListGetInt(tags); break; case DTA_RenderStyle: - parms->style.AsDWORD = va_arg(tags, DWORD); + parms->style.AsDWORD = ListGetInt(tags); break; case DTA_SpecialColormap: - parms->specialcolormap = va_arg(tags, FSpecialColormap *); + parms->specialcolormap = ListGetSpecialColormap(tags); break; case DTA_ColormapStyle: - parms->colormapstyle = va_arg(tags, FColormapStyle *); + parms->colormapstyle = ListGetColormapStyle(tags); break; case DTA_TextLen: - parms->maxstrlen = va_arg(tags, int); + parms->maxstrlen = ListGetInt(tags); break; case DTA_CellX: - parms->cellx = va_arg(tags, int); + parms->cellx = ListGetInt(tags); break; case DTA_CellY: - parms->celly = va_arg(tags, int); + parms->celly = ListGetInt(tags); break; } - tag = va_arg(tags, DWORD); + tag = ListGetInt(tags); + } + ListEnd(tags); + + if (parms->remap != nullptr && parms->remap->Inactive) + { // If it's inactive, pretend we were passed NULL instead. + parms->remap = nullptr; } - va_end (tags); if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip) { @@ -849,6 +944,10 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag } return true; } +// explicitly instantiate both versions for v_text.cpp. + +template bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, DWORD tag, va_list& tags, DrawParms *parms, bool fortext) const; +template bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, DWORD tag, VMVa_List& tags, DrawParms *parms, bool fortext) const; void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom, bool handleaspect) const diff --git a/src/v_font.cpp b/src/v_font.cpp index f024e2d2b..00d3b10f7 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -94,6 +94,7 @@ The FON2 header is followed by variable length data: #include "r_data/r_translate.h" #include "colormatcher.h" #include "v_palette.h" +#include "v_text.h" // MACROS ------------------------------------------------------------------ @@ -340,6 +341,14 @@ FFont *V_GetFont(const char *name) return font; } +DEFINE_ACTION_FUNCTION(FFont, GetFont) +{ + PARAM_PROLOGUE; + PARAM_NAME(name); + ACTION_RETURN_POINTER(V_GetFont(name.GetChars())); +} + + //========================================================================== // // FFont :: FFont @@ -366,7 +375,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count, LastChar = first + count - 1; FontHeight = 0; GlobalKerning = false; - Name = copystring (name); + FontName = name; Next = FirstFont; FirstFont = this; Cursor = '_'; @@ -478,11 +487,6 @@ FFont::~FFont () delete[] PatchRemap; PatchRemap = NULL; } - if (Name) - { - delete[] Name; - Name = NULL; - } FFont **prev = &FirstFont; FFont *font = *prev; @@ -508,21 +512,27 @@ FFont::~FFont () // //========================================================================== -FFont *FFont::FindFont (const char *name) +FFont *FFont::FindFont (FName name) { - if (name == NULL) + if (name == NAME_None) { - return NULL; + return nullptr; } FFont *font = FirstFont; - while (font != NULL) + while (font != nullptr) { - if (stricmp (font->Name, name) == 0) - break; + if (font->FontName == name) return font; font = font->Next; } - return font; + return nullptr; +} + +DEFINE_ACTION_FUNCTION(FFont, FindFont) +{ + PARAM_PROLOGUE; + PARAM_NAME(name); + ACTION_RETURN_POINTER(FFont::FindFont(name)); } //========================================================================== @@ -836,6 +846,65 @@ int FFont::GetCharWidth (int code) const return (code < 0) ? SpaceWidth : Chars[code - FirstChar].XMove; } +DEFINE_ACTION_FUNCTION(FFont, GetCharWidth) +{ + PARAM_SELF_STRUCT_PROLOGUE(FFont); + PARAM_INT(code); + ACTION_RETURN_INT(self->GetCharWidth(code)); +} + +//========================================================================== +// +// Find string width using this font +// +//========================================================================== + +int FFont::StringWidth(const BYTE *string) const +{ + int w = 0; + int maxw = 0; + + while (*string) + { + if (*string == TEXTCOLOR_ESCAPE) + { + ++string; + if (*string == '[') + { + while (*string != '\0' && *string != ']') + { + ++string; + } + } + if (*string != '\0') + { + ++string; + } + continue; + } + else if (*string == '\n') + { + if (w > maxw) + maxw = w; + w = 0; + ++string; + } + else + { + w += GetCharWidth(*string++) + GlobalKerning; + } + } + + return MAX(maxw, w); +} + +DEFINE_ACTION_FUNCTION(FFont, StringWidth) +{ + PARAM_SELF_STRUCT_PROLOGUE(FFont); + PARAM_STRING(str); + ACTION_RETURN_INT(self->StringWidth(str)); +} + //========================================================================== // // FFont :: LoadTranslations @@ -928,7 +997,7 @@ FFont::FFont (int lump) Lump = lump; Chars = NULL; PatchRemap = NULL; - Name = NULL; + FontName = NAME_None; Cursor = '_'; } @@ -944,7 +1013,7 @@ FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump) { assert(lump >= 0); - Name = copystring (name); + FontName = name; FMemLump data1 = Wads.ReadLump (lump); const BYTE *data = (const BYTE *)data1.GetMem(); @@ -1182,7 +1251,7 @@ void FSingleLumpFont::LoadFON2 (int lump, const BYTE *data) if (destSize < 0) { i += FirstChar; - I_FatalError ("Overflow decompressing char %d (%c) of %s", i, i, Name); + I_FatalError ("Overflow decompressing char %d (%c) of %s", i, i, FontName.GetChars()); } } @@ -1484,7 +1553,7 @@ FSinglePicFont::FSinglePicFont(const char *picname) : FTexture *pic = TexMan[picnum]; - Name = copystring(picname); + FontName = picname; FontHeight = pic->GetScaledHeight(); SpaceWidth = pic->GetScaledWidth(); GlobalKerning = 0; @@ -1896,7 +1965,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l memcpy(this->notranslate, notranslate, 256*sizeof(bool)); - Name = copystring(name); + FontName = name; Chars = new CharData[count]; charlumps = new FTexture*[count]; PatchRemap = new BYTE[256]; @@ -2483,6 +2552,13 @@ EColorRange V_FindFontColor (FName name) return CR_UNTRANSLATED; } +DEFINE_ACTION_FUNCTION(FFont, FindFontColor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FFont); + PARAM_NAME(code); + ACTION_RETURN_INT((int)V_FindFontColor(code)); +} + //========================================================================== // // V_LogColorFromColorRange @@ -2657,12 +2733,3 @@ void V_ClearFonts() SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = NULL; } -void V_RetranslateFonts() -{ - FFont *font = FFont::FirstFont; - while(font) - { - font->LoadTranslations(); - font = font->Next; - } -} diff --git a/src/v_font.h b/src/v_font.h index 7523e6bf0..4c78b3007 100644 --- a/src/v_font.h +++ b/src/v_font.h @@ -66,7 +66,8 @@ enum EColorRange CR_PURPLE, CR_DARKGRAY, CR_CYAN, - NUM_TEXT_COLORS + NUM_TEXT_COLORS, + FORCE_DWORD = 0x7fffffff // required for script access. }; extern int NumTextColors; @@ -87,9 +88,9 @@ public: int GetDefaultKerning () const { return GlobalKerning; } virtual void LoadTranslations(); void Preload() const; - const char *GetName() const { return Name; } + FName GetName() const { return FontName; } - static FFont *FindFont (const char *fontname); + static FFont *FindFont(FName fontname); static void StaticPreloadFonts(); // Return width of string in pixels (unscaled) @@ -126,14 +127,13 @@ protected: BYTE *PatchRemap; int Lump; - char *Name; + FName FontName; FFont *Next; static FFont *FirstFont; friend struct FontsDeleter; friend void V_ClearFonts(); - friend void V_RetranslateFonts(); }; @@ -146,6 +146,5 @@ PalEntry V_LogColorFromColorRange (EColorRange range); EColorRange V_ParseFontColor (const BYTE *&color_value, int normalcolor, int boldcolor); FFont *V_GetFont(const char *); void V_InitFontColors(); -void V_RetranslateFonts(); #endif //__V_FONT_H__ diff --git a/src/v_text.cpp b/src/v_text.cpp index 5772b078c..3394e448a 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -47,12 +47,17 @@ #include "doomstat.h" #include "templates.h" +int ListGetInt(VMVa_List &tags); + +//========================================================================== // // DrawChar // // Write a single character using the given font // -void DCanvas::DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, int tag_first, ...) +//========================================================================== + +void DCanvas::DrawChar (FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...) { if (font == NULL) return; @@ -79,37 +84,61 @@ void DCanvas::DrawChar (FFont *font, int normalcolor, int x, int y, BYTE charact } } +void DCanvas::DrawChar(FFont *font, int normalcolor, double x, double y, int character, VMVa_List &args) +{ + if (font == NULL) + return; + + if (normalcolor >= NumTextColors) + normalcolor = CR_UNTRANSLATED; + + FTexture *pic; + int dummy; + + if (NULL != (pic = font->GetChar(character, &dummy))) + { + DrawParms parms; + uint32_t tag = ListGetInt(args); + bool res = ParseDrawTextureTags(pic, x, y, tag, args, &parms, false); + if (!res) return; + parms.remap = font->GetColorTranslation((EColorRange)normalcolor); + DrawTextureParms(pic, parms); + } +} + +DEFINE_ACTION_FUNCTION(_Screen, DrawChar) +{ + PARAM_PROLOGUE; + PARAM_POINTER(font, FFont); + PARAM_INT(cr); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_INT(chr); + + VMVa_List args = { param + 5, 0, numparam - 5 }; + screen->DrawChar(font, cr, x, y, chr, args); + return 0; +} + +//========================================================================== // // DrawText // // Write a string using the given font // -void DCanvas::DrawText(FFont *font, int normalcolor, int x, int y, const char *string, int tag_first, ...) +//========================================================================== + +void DCanvas::DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms) { int w; const BYTE *ch; int c; - int cx; - int cy; + double cx; + double cy; int boldcolor; FRemapTable *range; int kerning; FTexture *pic; - DrawParms parms; - - va_list tags; - - if (font == NULL || string == NULL) - return; - - va_start(tags, tag_first); - bool res = ParseDrawTextureTags(nullptr, 0, 0, tag_first, tags, &parms, true); - va_end(tags); - if (!res) - { - return; - } - if (parms.celly == 0) parms.celly = font->GetHeight() + 1; parms.celly *= parms.scaley; @@ -118,15 +147,15 @@ void DCanvas::DrawText(FFont *font, int normalcolor, int x, int y, const char *s normalcolor = CR_UNTRANSLATED; boldcolor = normalcolor ? normalcolor - 1 : NumTextColors - 1; - range = font->GetColorTranslation ((EColorRange)normalcolor); + range = font->GetColorTranslation((EColorRange)normalcolor); - kerning = font->GetDefaultKerning (); + kerning = font->GetDefaultKerning(); ch = (const BYTE *)string; cx = x; cy = y; - + while ((const char *)ch - string < parms.maxstrlen) { c = *ch++; @@ -135,14 +164,14 @@ void DCanvas::DrawText(FFont *font, int normalcolor, int x, int y, const char *s if (c == TEXTCOLOR_ESCAPE) { - EColorRange newcolor = V_ParseFontColor (ch, normalcolor, boldcolor); + EColorRange newcolor = V_ParseFontColor(ch, normalcolor, boldcolor); if (newcolor != CR_UNDEFINED) { - range = font->GetColorTranslation (newcolor); + range = font->GetColorTranslation(newcolor); } continue; } - + if (c == '\n') { cx = x; @@ -150,7 +179,7 @@ void DCanvas::DrawText(FFont *font, int normalcolor, int x, int y, const char *s continue; } - if (NULL != (pic = font->GetChar (c, &w))) + if (NULL != (pic = font->GetChar(c, &w))) { parms.remap = range; SetTextureParms(&parms, pic, cx, cy); @@ -166,52 +195,61 @@ void DCanvas::DrawText(FFont *font, int normalcolor, int x, int y, const char *s } } - -// -// Find string width using this font -// -int FFont::StringWidth (const BYTE *string) const +void DCanvas::DrawText(FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...) { - int w = 0; - int maxw = 0; - - while (*string) + va_list tags; + DrawParms parms; + + if (font == NULL || string == NULL) + return; + + va_start(tags, tag_first); + bool res = ParseDrawTextureTags(nullptr, 0, 0, tag_first, tags, &parms, true); + va_end(tags); + if (!res) { - if (*string == TEXTCOLOR_ESCAPE) - { - ++string; - if (*string == '[') - { - while (*string != '\0' && *string != ']') - { - ++string; - } - } - if (*string != '\0') - { - ++string; - } - continue; - } - else if (*string == '\n') - { - if (w > maxw) - maxw = w; - w = 0; - ++string; - } - else - { - w += GetCharWidth (*string++) + GlobalKerning; - } + return; } - - return MAX (maxw, w); + DrawTextCommon(font, normalcolor, x, y, string, parms); } +void DCanvas::DrawText(FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args) +{ + DrawParms parms; + + if (font == NULL || string == NULL) + return; + + uint32_t tag = ListGetInt(args); + bool res = ParseDrawTextureTags(nullptr, 0, 0, tag, args, &parms, true); + if (!res) + { + return; + } + DrawTextCommon(font, normalcolor, x, y, string, parms); +} + +DEFINE_ACTION_FUNCTION(_Screen, DrawText) +{ + PARAM_PROLOGUE; + PARAM_POINTER(font, FFont); + PARAM_INT(cr); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_STRING(chr); + + VMVa_List args = { param + 5, 0, numparam - 5 }; + screen->DrawText(font, cr, x, y, chr, args); + return 0; +} + + +//========================================================================== // // Break long lines of text into multiple lines no longer than maxwidth pixels // +//========================================================================== + static void breakit (FBrokenLines *line, FFont *font, const BYTE *start, const BYTE *stop, FString &linecolor) { if (!linecolor.IsEmpty()) @@ -223,20 +261,19 @@ static void breakit (FBrokenLines *line, FFont *font, const BYTE *start, const B line->Width = font->StringWidth (line->Text); } -FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string, bool preservecolor) +FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string, bool preservecolor, unsigned int *count) { - FBrokenLines lines[128]; // Support up to 128 lines (should be plenty) + TArray Lines(128); const BYTE *space = NULL, *start = string; - size_t i, ii; int c, w, nw; FString lastcolor, linecolor; bool lastWasSpace = false; int kerning = font->GetDefaultKerning (); - i = w = 0; + w = 0; - while ( (c = *string++) && i < countof(lines) ) + while ( (c = *string++) ) { if (c == TEXTCOLOR_ESCAPE) { @@ -283,14 +320,14 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string, bool if (!space) space = string - 1; - breakit (&lines[i], font, start, space, linecolor); + auto index = Lines.Reserve(1); + breakit (&Lines[index], font, start, space, linecolor); if (c == '\n' && !preservecolor) { lastcolor = ""; // Why, oh why, did I do it like this? } linecolor = lastcolor; - i++; w = 0; lastWasSpace = false; start = space; @@ -312,7 +349,7 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string, bool } // String here is pointing one character after the '\0' - if (i < countof(lines) && --string - start >= 1) + if (--string - start >= 1) { const BYTE *s = start; @@ -321,20 +358,25 @@ FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *string, bool // If there is any non-white space in the remainder of the string, add it. if (!isspace (*s++)) { - breakit (&lines[i++], font, start, string, linecolor); + auto i = Lines.Reserve(1); + breakit (&Lines[i], font, start, string, linecolor); break; } } } // Make a copy of the broken lines and return them - FBrokenLines *broken = new FBrokenLines[i+1]; + FBrokenLines *broken = new FBrokenLines[Lines.Size() + 1]; - for (ii = 0; ii < i; ++ii) + for (unsigned ii = 0; ii < Lines.Size(); ++ii) { - broken[ii] = lines[ii]; + broken[ii] = Lines[ii]; + } + broken[Lines.Size()].Width = -1; + if (count != nullptr) + { + *count = Lines.Size(); } - broken[ii].Width = -1; return broken; } @@ -346,3 +388,56 @@ void V_FreeBrokenLines (FBrokenLines *lines) delete[] lines; } } + +class DBrokenLines : public DObject +{ + DECLARE_ABSTRACT_CLASS(DBrokenLines, DObject) + +public: + FBrokenLines *mBroken; + unsigned int mCount; + + DBrokenLines(FBrokenLines *broken, unsigned int count) + { + mBroken = broken; + mCount = count; + } + + void OnDestroy() override + { + V_FreeBrokenLines(mBroken); + } +}; + +IMPLEMENT_CLASS(DBrokenLines, true, false); + +DEFINE_ACTION_FUNCTION(DBrokenLines, Count) +{ + PARAM_SELF_PROLOGUE(DBrokenLines); + ACTION_RETURN_INT(self->mCount); +} + +DEFINE_ACTION_FUNCTION(DBrokenLines, StringWidth) +{ + PARAM_SELF_PROLOGUE(DBrokenLines); + PARAM_INT(index); + ACTION_RETURN_INT((unsigned)index >= self->mCount? -1 : self->mBroken[index].Width); +} + +DEFINE_ACTION_FUNCTION(DBrokenLines, StringAt) +{ + PARAM_SELF_PROLOGUE(DBrokenLines); + PARAM_INT(index); + ACTION_RETURN_STRING((unsigned)index >= self->mCount? -1 : self->mBroken[index].Text); +} + +DEFINE_ACTION_FUNCTION(FFont, BreakLines) +{ + PARAM_SELF_STRUCT_PROLOGUE(FFont); + PARAM_STRING(text); + PARAM_INT(maxwidth); + + unsigned int count; + FBrokenLines *broken = V_BreakLines(self, maxwidth, text, true, &count); + ACTION_RETURN_OBJECT(new DBrokenLines(broken, count)); +} diff --git a/src/v_text.h b/src/v_text.h index 3baf62af7..bd24be405 100644 --- a/src/v_text.h +++ b/src/v_text.h @@ -75,11 +75,11 @@ struct FBrokenLines #define TEXTCOLOR_CHAT "\034*" #define TEXTCOLOR_TEAMCHAT "\034!" -FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *str, bool preservecolor = false); +FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const BYTE *str, bool preservecolor = false, unsigned int *count = nullptr); void V_FreeBrokenLines (FBrokenLines *lines); -inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false) - { return V_BreakLines (font, maxwidth, (const BYTE *)str, preservecolor); } -inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false) - { return V_BreakLines (font, maxwidth, (const BYTE *)str.GetChars(), preservecolor); } +inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const char *str, bool preservecolor = false, unsigned int *count = nullptr) + { return V_BreakLines (font, maxwidth, (const BYTE *)str, preservecolor, count); } +inline FBrokenLines *V_BreakLines (FFont *font, int maxwidth, const FString &str, bool preservecolor = false, unsigned int *count = nullptr) + { return V_BreakLines (font, maxwidth, (const BYTE *)str.GetChars(), preservecolor, count); } #endif //__V_TEXT_H__ diff --git a/src/v_video.h b/src/v_video.h index e9bb1f6a4..a594fa8fe 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -75,9 +75,8 @@ enum DTA_DestWidth, // width of area to draw to DTA_DestHeight, // height of area to draw to DTA_Alpha, // alpha value for translucency - DTA_AlphaF, // alpha value for translucency DTA_FillColor, // color to stencil onto the destination (RGB is the color for truecolor drawers, A is the palette index for paletted drawers) - DTA_Translation, // translation table to recolor the source + DTA_TranslationIndex, // translation table to recolor the source DTA_AlphaChannel, // bool: the source is an alpha channel; used with DTA_FillColor DTA_Clean, // bool: scale texture size and position by CleanXfac and CleanYfac DTA_320x200, // bool: scale texture size and position to fit on a virtual 320x200 screen @@ -163,7 +162,7 @@ struct DrawParms uint32 colorOverlay; INTBOOL alphaChannel; INTBOOL flipX; - fixed_t shadowAlpha; + float shadowAlpha; int shadowColor; INTBOOL keepratio; INTBOOL masked; @@ -178,6 +177,12 @@ struct DrawParms bool virtBottom; }; +struct VMVa_List +{ + VMValue *args; + int curindex; + int numargs; +}; // // VIDEO // @@ -252,6 +257,7 @@ public: // 2D Texture drawing bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const; void DrawTexture (FTexture *img, double x, double y, int tags, ...); + void DrawTexture(FTexture *img, double x, double y, VMVa_List &); void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom=false, bool handleaspect=true) const; @@ -263,8 +269,10 @@ public: #undef DrawText // See WinUser.h for the definition of DrawText as a macro #endif // 2D Text drawing - void DrawText (FFont *font, int normalcolor, int x, int y, const char *string, int tag_first, ...); - void DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, int tag_first, ...); + void DrawText(FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...); + void DrawText(FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args); + void DrawChar(FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...); + void DrawChar(FFont *font, int normalcolor, double x, double y, int character, VMVa_List &args); protected: BYTE *Buffer; @@ -273,10 +281,14 @@ protected: int Pitch; int LockCount; + void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms); + bool ClipBox (int &left, int &top, int &width, int &height, const BYTE *&src, const int srcpitch) const; void DrawTextureV(FTexture *img, double x, double y, uint32 tag, va_list tags) = delete; virtual void DrawTextureParms(FTexture *img, DrawParms &parms); - bool ParseDrawTextureTags (FTexture *img, double x, double y, uint32 tag, va_list tags, DrawParms *parms, bool fortext) const; + + template + bool ParseDrawTextureTags(FTexture *img, double x, double y, DWORD tag, T& tags, DrawParms *parms, bool fortext) const; DCanvas() {} diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index eb1c7d2fa..73a5b9742 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -722,10 +722,10 @@ void WI_drawBackground() static int WI_DrawCharPatch (FFont *font, int charcode, int x, int y, EColorRange translation=CR_UNTRANSLATED, bool nomove=false) { int width; - screen->DrawTexture(font->GetChar(charcode, &width), x, y, + font->GetChar(charcode, &width); + screen->DrawChar(font, translation, x, y, charcode, nomove ? DTA_CleanNoMove : DTA_Clean, true, - DTA_ShadowAlpha, (gameinfo.gametype & GAME_DoomChex) ? 0 : OPAQUE/2, - DTA_Translation, font->GetColorTranslation(translation), + DTA_ShadowAlpha, (gameinfo.gametype & GAME_DoomChex) ? 0 : 0.5, TAG_DONE); return x - width; } diff --git a/wadsrc/static/language.enu b/wadsrc/static/language.enu index bdc1ce3ae..4d567d3ca 100644 --- a/wadsrc/static/language.enu +++ b/wadsrc/static/language.enu @@ -1417,6 +1417,9 @@ TXT_KILLED_ORACLE = "You've Killed The Oracle!"; TXT_KILLED_MACIL = "You Killed Macil!"; TXT_KILLED_LOREMASTER = "You've Killed the Loremaster!"; +TXT_YOUFOOL = "You Fool! You've set off the alarm."; +TXT_YOUREDEAD = "You're dead! You set off the alarm."; + // Strife pickup messages TXT_METALARMOR = "You picked up the Metal Armor."; diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index 9f1033b17..25129a87c 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -7,6 +7,9 @@ #include "zscript/actor_checks.txt" #include "zscript/events.txt" +#include "zscript/menu/menu.txt" +#include "zscript/menu/menuitembase.txt" + #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" #include "zscript/inventory/stateprovider.txt" diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 24afe68e9..9b6f42b88 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -498,6 +498,7 @@ class Actor : Thinker native native bool UsePuzzleItem(int PuzzleItemType); native float AccuracyFactor(); native bool MorphMonster (Class spawntype, int duration, int style, Class enter_flash, Class exit_flash); + native void SetCamera(Actor cam, bool revert = false); // DECORATE compatible functions native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 55da329c9..20ce0f2a7 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -32,16 +32,126 @@ struct TexMan native static TextureID CheckForTexture(String name, int usetype, int flags = TryAny); } +enum DrawTextureTags +{ + TAG_USER = (1<<30), + DTA_Base = TAG_USER + 5000, + DTA_DestWidth, // width of area to draw to + DTA_DestHeight, // height of area to draw to + DTA_Alpha, // alpha value for translucency + DTA_FillColor, // color to stencil onto the destination (RGB is the color for truecolor drawers, A is the palette index for paletted drawers) + DTA_TranslationIndex, // translation table to recolor the source + DTA_AlphaChannel, // bool: the source is an alpha channel; used with DTA_FillColor + DTA_Clean, // bool: scale texture size and position by CleanXfac and CleanYfac + DTA_320x200, // bool: scale texture size and position to fit on a virtual 320x200 screen + DTA_Bottom320x200, // bool: same as DTA_320x200 but centers virtual screen on bottom for 1280x1024 targets + DTA_CleanNoMove, // bool: like DTA_Clean but does not reposition output position + DTA_CleanNoMove_1, // bool: like DTA_CleanNoMove, but uses Clean[XY]fac_1 instead + DTA_FlipX, // bool: flip image horizontally //FIXME: Does not work with DTA_Window(Left|Right) + DTA_ShadowColor, // color of shadow + DTA_ShadowAlpha, // alpha of shadow + DTA_Shadow, // set shadow color and alphas to defaults + DTA_VirtualWidth, // pretend the canvas is this wide + DTA_VirtualHeight, // pretend the canvas is this tall + DTA_TopOffset, // override texture's top offset + DTA_LeftOffset, // override texture's left offset + DTA_CenterOffset, // bool: override texture's left and top offsets and set them for the texture's middle + DTA_CenterBottomOffset,// bool: override texture's left and top offsets and set them for the texture's bottom middle + DTA_WindowLeft, // don't draw anything left of this column (on source, not dest) + DTA_WindowRight, // don't draw anything at or to the right of this column (on source, not dest) + DTA_ClipTop, // don't draw anything above this row (on dest, not source) + DTA_ClipBottom, // don't draw anything at or below this row (on dest, not source) + DTA_ClipLeft, // don't draw anything to the left of this column (on dest, not source) + DTA_ClipRight, // don't draw anything at or to the right of this column (on dest, not source) + DTA_Masked, // true(default)=use masks from texture, false=ignore masks + DTA_HUDRules, // use fullscreen HUD rules to position and size textures + DTA_HUDRulesC, // only used internally for marking HUD_HorizCenter + DTA_KeepRatio, // doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3 + DTA_RenderStyle, // same as render style for actors + DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image; limited to black for software + DTA_Internal1, + DTA_Internal2, + DTA_Internal3, + DTA_Fullscreen, // Draw image fullscreen (same as DTA_VirtualWidth/Height with graphics size.) + + // floating point duplicates of some of the above: + DTA_DestWidthF, + DTA_DestHeightF, + DTA_TopOffsetF, + DTA_LeftOffsetF, + DTA_VirtualWidthF, + DTA_VirtualHeightF, + DTA_WindowLeftF, + DTA_WindowRightF, + + // For DrawText calls only: + DTA_TextLen, // stop after this many characters, even if \0 not hit + DTA_CellX, // horizontal size of character cell + DTA_CellY, // vertical size of character cell +}; + struct Screen native { + enum EColorRange + { + CR_UNDEFINED = -1, + CR_BRICK, + CR_TAN, + CR_GRAY, + CR_GREY = CR_GRAY, + CR_GREEN, + CR_BROWN, + CR_GOLD, + CR_RED, + CR_BLUE, + CR_ORANGE, + CR_WHITE, + CR_YELLOW, + CR_UNTRANSLATED, + CR_BLACK, + CR_LIGHTBLUE, + CR_CREAM, + CR_OLIVE, + CR_DARKGREEN, + CR_DARKRED, + CR_DARKBROWN, + CR_PURPLE, + CR_DARKGRAY, + CR_CYAN, + NUM_TEXT_COLORS + }; + + native static int GetWidth(); + native static int GetHeight(); native static void DrawHUDTexture(TextureID tex, double x, double y); + native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...); + native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...); + native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...); + +} + +class BrokenLines : Object native +{ + native int Count(); + native int StringWidth(int line); + native String StringAt(int line); +} + +struct Font native +{ + native int GetCharWidth(int code); + native int StringWidth(String code); + native static int FindFontColor(Name color); + native static Font FindFont(Name fontname); + native static Font GetFont(Name fontname); + native static BrokenLines BreakLines(String text, int maxlen); } struct Console native { native static void HideConsole(); - native static void MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable. - native static vararg void Printf(string fmt, ...); + native static void MidPrint(Font fontname, string textlabel, bool bold = false); + native static vararg void Printf(string fmt, ...); } struct DamageTypeDefinition native @@ -310,7 +420,7 @@ struct StringStruct native { native void Replace(String pattern, String replacement); native static vararg String Format(String fmt, ...); - native vararg void AppendFormat(String fmt, ...); + native vararg void AppendFormat(String fmt, ...); } class Floor : Thinker native diff --git a/wadsrc/static/zscript/compatibility.txt b/wadsrc/static/zscript/compatibility.txt index 752de8016..1ae88ab85 100644 --- a/wadsrc/static/zscript/compatibility.txt +++ b/wadsrc/static/zscript/compatibility.txt @@ -9,7 +9,9 @@ extend class Object deprecated static void C_MidPrint(string fontname, string textlabel, bool bold = false) // deprecated for 2.4.x { - return Console.MidPrint(fontname, textlabel, bold); + let f = Font.GetFont(fontname); + if (f == null) return; + return Console.MidPrint(f, textlabel, bold); } } diff --git a/wadsrc/static/zscript/hexen/baseweapons.txt b/wadsrc/static/zscript/hexen/baseweapons.txt index f08794648..e0394996a 100644 --- a/wadsrc/static/zscript/hexen/baseweapons.txt +++ b/wadsrc/static/zscript/hexen/baseweapons.txt @@ -40,7 +40,7 @@ extend class Actor void AdjustPlayerAngle(FTranslatedLineTarget t) { - double difference = t.angleFromSource; + double difference = deltaangle(angle, t.angleFromSource); if (abs(difference) > MAX_ANGLE_ADJUST) { if (difference > 0) diff --git a/wadsrc/static/zscript/menu/menu.txt b/wadsrc/static/zscript/menu/menu.txt new file mode 100644 index 000000000..ffada3198 --- /dev/null +++ b/wadsrc/static/zscript/menu/menu.txt @@ -0,0 +1,17 @@ + +class Menu : Object native +{ + //native static int MenuTime(); +} + +struct FOptionMenuSettings +{ + int mTitleColor; + int mFontColor; + int mFontColorValue; + int mFontColorMore; + int mFontColorHeader; + int mFontColorHighlight; + int mFontColorSelection; + int mLinespacing; +} diff --git a/wadsrc/static/zscript/menu/menuitembase.txt b/wadsrc/static/zscript/menu/menuitembase.txt new file mode 100644 index 000000000..e92f17fcf --- /dev/null +++ b/wadsrc/static/zscript/menu/menuitembase.txt @@ -0,0 +1,66 @@ +//============================================================================= +// +// base class for menu items +// +//============================================================================= + +class MenuItemBase : Object native +{ + protected int mXpos, mYpos; + protected Name mAction; + + bool mEnabled; + + protected void Init(int xpos = 0, int ypos = 0, Name actionname = 'None') + { + mXpos = xpos; + mYpos = ypos; + mAction = actionname; + mEnabled = true; + } + + virtual bool CheckCoordinate(int x, int y) { return false; } + virtual void Ticker() {} + virtual void Drawer(bool selected) {} + virtual bool Selectable() {return false; } + virtual bool Activate() { return false; } + virtual Name, int GetAction() { return mAction, 0; } + virtual bool SetString(int i, String s) { return false; } + virtual bool, String GetString(int i) { return false, ""; } + virtual bool SetValue(int i, int value) { return false; } + virtual bool, int GetValue(int i) { return false, 0; } + virtual void Enable(bool on) { mEnabled = on; } + virtual bool MenuEvent (int mkey, bool fromcontroller) { return false; } + virtual bool MouseEvent(int type, int x, int y) { return false; } + virtual bool CheckHotkey(int c) { return false; } + virtual int GetWidth() { return 0; } + virtual void OffsetPositionY(int ydelta) { mYpos += ydelta; } + virtual int GetY() { return mYpos; } + virtual int GetX() { return mXpos; } + virtual void SetX(int x) { mXpos = x; } + + /* + virtual void DrawSelector(int xofs, int yofs, TextureID tex) + { + if (tex.isNull()) + { + if ((Menu.MenuTime() % 8) < 6) + { + screen.DrawText(ConFont, OptionSettings.mFontColorSelection, + (mXpos + xofs - 160) * CleanXfac + screen.GetWidth() / 2, + (mYpos + yofs - 100) * CleanYfac + screen.GetHeight() / 2, + "\xd", + DTA_CellX, 8 * CleanXfac, + DTA_CellY, 8 * CleanYfac, + TAG_DONE); + } + } + else + { + screen.DrawTexture (tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE); + } + } + */ + +} + diff --git a/wadsrc/static/zscript/strife/strifeitems.txt b/wadsrc/static/zscript/strife/strifeitems.txt index 970478cae..4c7311b56 100644 --- a/wadsrc/static/zscript/strife/strifeitems.txt +++ b/wadsrc/static/zscript/strife/strifeitems.txt @@ -632,7 +632,7 @@ class RaiseAlarm : DummyStrifeItem dropper.target.SoundAlert(dropper.target); if (dropper.target.CheckLocalView(consoleplayer)) { - A_Log("You Fool! You've set off the alarm."); + Console.MidPrint(SmallFont, "$TXT_YOUFOOL"); } } Destroy (); @@ -672,7 +672,7 @@ class CloseDoor222 : DummyStrifeItem { if (dropper.target.CheckLocalView(consoleplayer)) { - A_Log("You're dead! You set off the alarm."); + Console.MidPrint(SmallFont, "$TXT_YOUREDEAD"); } dropper.target.SoundAlert(dropper.target); }