You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
268 lines
7.2 KiB
268 lines
7.2 KiB
#include "control.h" |
|
#include "controls/plrctrls.h" |
|
#include "controls/touch/renderers.h" |
|
#include "cursor.h" |
|
#include "doom.h" |
|
#include "engine.h" |
|
#include "gendung.h" |
|
#include "init.h" |
|
#include "inv.h" |
|
#include "minitext.h" |
|
#include "stores.h" |
|
#include "towners.h" |
|
|
|
namespace devilution { |
|
|
|
namespace { |
|
|
|
VirtualGamepadRenderer Renderer(&VirtualGamepadState); |
|
|
|
VirtualGamepadButtonType GetAttackButtonType(bool isPressed) |
|
{ |
|
return isPressed ? GAMEPAD_ATTACKDOWN : GAMEPAD_ATTACK; |
|
} |
|
|
|
VirtualGamepadButtonType GetTalkButtonType(bool isPressed) |
|
{ |
|
return isPressed ? GAMEPAD_TALKDOWN : GAMEPAD_TALK; |
|
} |
|
|
|
VirtualGamepadButtonType GetItemButtonType(bool isPressed) |
|
{ |
|
return isPressed ? GAMEPAD_ITEMDOWN : GAMEPAD_ITEM; |
|
} |
|
|
|
VirtualGamepadButtonType GetObjectButtonType(bool isPressed) |
|
{ |
|
return isPressed ? GAMEPAD_OBJECTDOWN : GAMEPAD_OBJECT; |
|
} |
|
|
|
VirtualGamepadButtonType GetCastButtonType(bool isPressed) |
|
{ |
|
return isPressed ? GAMEPAD_CASTSPELLDOWN : GAMEPAD_CASTSPELL; |
|
} |
|
|
|
VirtualGamepadButtonType GetCancelButtonType(bool isPressed) |
|
{ |
|
return isPressed ? GAMEPAD_BACKDOWN : GAMEPAD_BACK; |
|
} |
|
|
|
VirtualGamepadButtonType GetBlankButtonType(bool isPressed) |
|
{ |
|
return isPressed ? GAMEPAD_BLANKDOWN : GAMEPAD_BLANK; |
|
} |
|
|
|
} // namespace |
|
|
|
void RenderVirtualGamepad(SDL_Renderer *renderer) |
|
{ |
|
RenderFunction renderFunction = [&](Art &art, SDL_Rect *src, SDL_Rect *dst) { |
|
if (art.texture == nullptr) |
|
return; |
|
|
|
if (SDL_RenderCopy(renderer, art.texture.get(), src, dst) <= -1) |
|
ErrSdl(); |
|
}; |
|
|
|
Renderer.Render(renderFunction); |
|
} |
|
|
|
void RenderVirtualGamepad(SDL_Surface *surface) |
|
{ |
|
RenderFunction renderFunction = [&](Art &art, SDL_Rect *src, SDL_Rect *dst) { |
|
if (art.surface == nullptr) |
|
return; |
|
|
|
if (SDL_BlitScaled(art.surface.get(), src, surface, dst) <= -1) |
|
ErrSdl(); |
|
}; |
|
|
|
Renderer.Render(renderFunction); |
|
} |
|
|
|
void VirtualGamepadRenderer::LoadArt(SDL_Renderer *renderer) |
|
{ |
|
directionPadRenderer.LoadArt(renderer); |
|
|
|
const int Frames = 14; |
|
buttonArt.surface.reset(LoadPNG("ui_art\\button.png")); |
|
if (buttonArt.surface == nullptr) |
|
return; |
|
|
|
buttonArt.logical_width = buttonArt.surface->w; |
|
buttonArt.frame_height = buttonArt.surface->h / Frames; |
|
buttonArt.frames = Frames; |
|
|
|
if (renderer != nullptr) { |
|
buttonArt.texture.reset(SDL_CreateTextureFromSurface(renderer, buttonArt.surface.get())); |
|
buttonArt.surface = nullptr; |
|
} |
|
} |
|
|
|
void VirtualDirectionPadRenderer::LoadArt(SDL_Renderer *renderer) |
|
{ |
|
padArt.surface.reset(LoadPNG("ui_art\\directions.png")); |
|
knobArt.surface.reset(LoadPNG("ui_art\\directions2.png")); |
|
|
|
if (renderer != nullptr) { |
|
padArt.texture.reset(SDL_CreateTextureFromSurface(renderer, padArt.surface.get())); |
|
padArt.surface = nullptr; |
|
|
|
knobArt.texture.reset(SDL_CreateTextureFromSurface(renderer, knobArt.surface.get())); |
|
knobArt.surface = nullptr; |
|
} |
|
} |
|
|
|
void VirtualGamepadRenderer::Render(RenderFunction renderFunction) |
|
{ |
|
if (CurrentProc == DisableInputWndProc) |
|
return; |
|
|
|
directionPadRenderer.Render(renderFunction); |
|
primaryActionButtonRenderer.Render(renderFunction, buttonArt); |
|
secondaryActionButtonRenderer.Render(renderFunction, buttonArt); |
|
spellActionButtonRenderer.Render(renderFunction, buttonArt); |
|
cancelButtonRenderer.Render(renderFunction, buttonArt); |
|
} |
|
|
|
void VirtualDirectionPadRenderer::Render(RenderFunction renderFunction) |
|
{ |
|
RenderPad(renderFunction); |
|
RenderKnob(renderFunction); |
|
} |
|
|
|
void VirtualDirectionPadRenderer::RenderPad(RenderFunction renderFunction) |
|
{ |
|
auto center = virtualDirectionPad->area.position; |
|
auto radius = virtualDirectionPad->area.radius; |
|
int diameter = 2 * radius; |
|
|
|
int x = center.x - radius; |
|
int y = center.y - radius; |
|
int width = diameter; |
|
int height = diameter; |
|
SDL_Rect rect { x, y, width, height }; |
|
renderFunction(padArt, nullptr, &rect); |
|
} |
|
|
|
void VirtualDirectionPadRenderer::RenderKnob(RenderFunction renderFunction) |
|
{ |
|
auto center = virtualDirectionPad->position; |
|
auto radius = virtualDirectionPad->area.radius / 3; |
|
int diameter = 2 * radius; |
|
|
|
int x = center.x - radius; |
|
int y = center.y - radius; |
|
int width = diameter; |
|
int height = diameter; |
|
SDL_Rect rect { x, y, width, height }; |
|
renderFunction(knobArt, nullptr, &rect); |
|
} |
|
|
|
void VirtualPadButtonRenderer::Render(RenderFunction renderFunction, Art &buttonArt) |
|
{ |
|
VirtualGamepadButtonType buttonType = GetButtonType(); |
|
int frame = buttonType; |
|
int offset = buttonArt.h() * frame; |
|
|
|
auto center = virtualPadButton->area.position; |
|
auto radius = virtualPadButton->area.radius; |
|
int diameter = 2 * radius; |
|
|
|
int x = center.x - radius; |
|
int y = center.y - radius; |
|
int width = diameter; |
|
int height = diameter; |
|
|
|
SDL_Rect src { 0, offset, buttonArt.w(), buttonArt.h() }; |
|
SDL_Rect dst { x, y, width, height }; |
|
renderFunction(buttonArt, &src, &dst); |
|
} |
|
|
|
VirtualGamepadButtonType PrimaryActionButtonRenderer::GetButtonType() |
|
{ |
|
// NEED: Confirm surface |
|
if (qtextflag) |
|
return GetTalkButtonType(virtualPadButton->isHeld); |
|
if (invflag) |
|
return GetInventoryButtonType(); |
|
if (leveltype == DTYPE_TOWN) |
|
return GetTownButtonType(); |
|
return GetDungeonButtonType(); |
|
} |
|
|
|
VirtualGamepadButtonType PrimaryActionButtonRenderer::GetTownButtonType() |
|
{ |
|
if (stextflag != STORE_NONE || pcursmonst != -1) |
|
return GetTalkButtonType(virtualPadButton->isHeld); |
|
return GetBlankButtonType(virtualPadButton->isHeld); |
|
} |
|
|
|
VirtualGamepadButtonType PrimaryActionButtonRenderer::GetDungeonButtonType() |
|
{ |
|
if (pcursmonst != -1) { |
|
const auto &monster = Monsters[pcursmonst]; |
|
if (M_Talker(monster) || monster.mtalkmsg != TEXT_NONE) |
|
return GetTalkButtonType(virtualPadButton->isHeld); |
|
} |
|
return GetAttackButtonType(virtualPadButton->isHeld); |
|
} |
|
|
|
VirtualGamepadButtonType PrimaryActionButtonRenderer::GetInventoryButtonType() |
|
{ |
|
if (pcursinvitem != -1 || pcurs > CURSOR_HAND) |
|
return GetItemButtonType(virtualPadButton->isHeld); |
|
return GetBlankButtonType(virtualPadButton->isHeld); |
|
} |
|
|
|
VirtualGamepadButtonType SecondaryActionButtonRenderer::GetButtonType() |
|
{ |
|
// NEED: Stairs surface |
|
if (InGameMenu() || QuestLogIsOpen || sbookflag) |
|
return GetBlankButtonType(virtualPadButton->isHeld); |
|
if (pcursobj != -1) |
|
return GetObjectButtonType(virtualPadButton->isHeld); |
|
if (pcursitem != -1) |
|
return GetItemButtonType(virtualPadButton->isHeld); |
|
return GetBlankButtonType(virtualPadButton->isHeld); |
|
} |
|
|
|
VirtualGamepadButtonType SpellActionButtonRenderer::GetButtonType() |
|
{ |
|
if (!InGameMenu() && !QuestLogIsOpen && !sbookflag) |
|
return GetCastButtonType(virtualPadButton->isHeld); |
|
return GetBlankButtonType(virtualPadButton->isHeld); |
|
} |
|
|
|
VirtualGamepadButtonType CancelButtonRenderer::GetButtonType() |
|
{ |
|
if (InGameMenu()) |
|
return GetCancelButtonType(virtualPadButton->isHeld); |
|
if (DoomFlag || invflag || sbookflag || QuestLogIsOpen || chrflag) |
|
return GetCancelButtonType(virtualPadButton->isHeld); |
|
return GetBlankButtonType(virtualPadButton->isHeld); |
|
} |
|
|
|
void VirtualGamepadRenderer::UnloadArt() |
|
{ |
|
directionPadRenderer.UnloadArt(); |
|
buttonArt.Unload(); |
|
} |
|
|
|
void VirtualDirectionPadRenderer::UnloadArt() |
|
{ |
|
padArt.Unload(); |
|
knobArt.Unload(); |
|
} |
|
|
|
void InitVirtualGamepadGFX(SDL_Renderer *renderer) |
|
{ |
|
Renderer.LoadArt(renderer); |
|
} |
|
|
|
void FreeVirtualGamepadGFX() |
|
{ |
|
Renderer.UnloadArt(); |
|
} |
|
|
|
} // namespace devilution
|
|
|