Files
devilutionX/Source/control.h
T
Gleb Mazovetskiy 680ab5ec40 Overhaul backbuffer state handling
When rendering directly to the output buffer, we need to maintain the
state of what has been drawn and what needs redrawing per-buffer.

We previously tried to do it implicitly by checking `SDL_DOUBLEBUF` and
other flags. The previous implementation was broken in several
ways, resulting in rendering issues on devices that support 8-bit output
directly.

Changes this mechanism to explicitly maintain buffer state per output
buffer. The new mechanism doesn't require knowledge of the number of
buffers, and thus also works correctly with triple-buffering.

Fixes #5447
2022-11-01 02:43:24 +00:00

189 lines
5.5 KiB
C++

/**
* @file control.h
*
* Interface of the character and main control panels
*/
#pragma once
#include <cstddef>
#include <cstdint>
#include <SDL.h>
#ifdef USE_SDL1
#include "utils/sdl2_to_1_2_backports.h"
#endif
#include "DiabloUI/ui_flags.hpp"
#include "engine.h"
#include "engine/point.hpp"
#include "engine/rectangle.hpp"
#include "engine/render/text_render.hpp"
#include "panels/ui_panels.hpp"
#include "spelldat.h"
#include "spells.h"
#include "utils/attributes.h"
#include "utils/stdcompat/optional.hpp"
#include "utils/stdcompat/string_view.hpp"
#include "utils/string_or_view.hpp"
#include "utils/ui_fwd.h"
namespace devilution {
constexpr Size SidePanelSize { 320, 352 };
extern bool dropGoldFlag;
extern bool chrbtn[4];
extern bool lvlbtndown;
extern int dropGoldValue;
extern bool chrbtnactive;
extern UiFlags InfoColor;
extern int sbooktab;
extern int8_t initialDropGoldIndex;
extern bool talkflag;
extern bool sbookflag;
extern bool chrflag;
extern StringOrView InfoString;
extern bool panelflag;
extern int initialDropGoldValue;
extern bool panbtndown;
extern bool spselflag;
const Rectangle &GetMainPanel();
const Rectangle &GetLeftPanel();
const Rectangle &GetRightPanel();
bool IsLeftPanelOpen();
bool IsRightPanelOpen();
extern std::optional<OwnedSurface> pBtmBuff;
extern OptionalOwnedClxSpriteList pGBoxBuff;
extern SDL_Rect PanBtnPos[8];
void CalculatePanelAreas();
bool IsChatAvailable();
/**
* @brief Check if the UI can cover the game area entierly
*/
inline bool CanPanelsCoverView()
{
const Rectangle &mainPanel = GetMainPanel();
return GetScreenWidth() <= mainPanel.size.width && GetScreenHeight() <= SidePanelSize.height + mainPanel.size.height;
}
void DrawSpellList(const Surface &out);
void SetSpell();
void SetSpeedSpell(size_t slot);
void ToggleSpell(size_t slot);
void AddPanelString(string_view str);
void AddPanelString(std::string &&str);
void DrawPanelBox(const Surface &out, SDL_Rect srcRect, Point targetPosition);
Point GetPanelPosition(UiPanels panel, Point offset = { 0, 0 });
/**
* Draws the top dome of the life flask (that part that protrudes out of the control panel).
* The empty flask cel is drawn from the top of the flask to the fill level (there is always a 2 pixel "air gap") and
* the filled flask cel is drawn from that level to the top of the control panel if required.
*/
void DrawLifeFlaskUpper(const Surface &out);
/**
* Controls the drawing of the area of the life flask within the control panel.
* First sets the fill amount then draws the empty flask cel portion then the filled
* flask portion.
*/
void DrawLifeFlaskLower(const Surface &out);
/**
* Draws the top dome of the mana flask (that part that protrudes out of the control panel).
* The empty flask cel is drawn from the top of the flask to the fill level (there is always a 2 pixel "air gap") and
* the filled flask cel is drawn from that level to the top of the control panel if required.
*/
void DrawManaFlaskUpper(const Surface &out);
/**
* Controls the drawing of the area of the mana flask within the control panel.
*/
void DrawManaFlaskLower(const Surface &out);
/**
* Controls drawing of current / max values (health, mana) within the control panel.
*/
void DrawFlaskValues(const Surface &out, Point pos, int currValue, int maxValue);
/**
* @brief calls on the active player object to update HP/Mana percentage variables
*
* This is used to ensure that DrawFlask routines display an accurate representation of the players health/mana
*
* @see Player::UpdateHitPointPercentage() and Player::UpdateManaPercentage()
*/
void control_update_life_mana();
/**
* @brief draws the current right mouse button spell.
* @param out screen buffer representing the main UI panel
*/
void DrawSpell(const Surface &out);
void InitControlPan();
void DrawCtrlPan(const Surface &out);
/**
* Draws the control panel buttons in their current state. If the button is in the default
* state draw it from the panel cel(extract its sub-rect). Else draw it from the buttons cel.
*/
void DrawCtrlBtns(const Surface &out);
/**
* Clears panel button flags.
*/
void ClearPanBtn();
/**
* Checks if the mouse cursor is within any of the panel buttons and flag it if so.
*/
void DoPanBtn();
void control_check_btn_press();
void DoAutoMap();
/**
* Checks the mouse cursor position within the control panel and sets information
* strings if needed.
*/
void CheckPanelInfo();
/**
* Check if the mouse is within a control panel button that's flagged.
* Takes apropiate action if so.
*/
void CheckBtnUp();
void FreeControlPan();
/**
* Sets a string to be drawn in the info box and then draws it.
*/
void DrawInfoBox(const Surface &out);
void CheckLvlBtn();
void ReleaseLvlBtn();
void DrawLevelUpIcon(const Surface &out);
void CheckChrBtns();
void ReleaseChrBtns(bool addAllStatPoints);
void DrawDurIcon(const Surface &out);
void RedBack(const Surface &out);
void DrawSpellBook(const Surface &out);
void DrawGoldSplit(const Surface &out, int amount);
void control_drop_gold(SDL_Keycode vkey);
void DrawTalkPan(const Surface &out);
bool control_check_talk_btn();
void control_release_talk_btn();
void control_type_message();
void control_reset_talk();
bool IsTalkActive();
void control_new_text(string_view text);
bool control_presskeys(SDL_Keycode vkey);
void DiabloHotkeyMsg(uint32_t dwMsg);
void CloseGoldDrop();
void GoldDropNewText(string_view text);
extern Rectangle ChrBtnsRect[4];
} // namespace devilution