|
|
|
|
#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 "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 DrawVirtualGamepad(const Surface &out)
|
|
|
|
|
{
|
|
|
|
|
Renderer.Render(out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VirtualGamepadRenderer::LoadArt()
|
|
|
|
|
{
|
|
|
|
|
directionPadRenderer.LoadArt();
|
|
|
|
|
|
|
|
|
|
const int Frames = 14;
|
|
|
|
|
buttonArt.surface.reset(LoadPNG("ui_art\\button.png"));
|
|
|
|
|
buttonArt.logical_width = buttonArt.surface->w;
|
|
|
|
|
buttonArt.frame_height = buttonArt.surface->h / Frames;
|
|
|
|
|
buttonArt.frames = Frames;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VirtualDirectionPadRenderer::LoadArt()
|
|
|
|
|
{
|
|
|
|
|
padSurface.reset(LoadPNG("ui_art\\directions.png"));
|
|
|
|
|
knobSurface.reset(LoadPNG("ui_art\\directions2.png"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VirtualGamepadRenderer::Render(const Surface &out)
|
|
|
|
|
{
|
|
|
|
|
directionPadRenderer.Render(out);
|
|
|
|
|
primaryActionButtonRenderer.Render(out);
|
|
|
|
|
secondaryActionButtonRenderer.Render(out);
|
|
|
|
|
spellActionButtonRenderer.Render(out);
|
|
|
|
|
cancelButtonRenderer.Render(out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VirtualDirectionPadRenderer::Render(const Surface &out)
|
|
|
|
|
{
|
|
|
|
|
RenderPad(out);
|
|
|
|
|
RenderKnob(out);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VirtualDirectionPadRenderer::RenderPad(const Surface &out)
|
|
|
|
|
{
|
|
|
|
|
if (padSurface == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
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 };
|
|
|
|
|
SDL_BlitScaled(padSurface.get(), nullptr, out.surface, &rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VirtualDirectionPadRenderer::RenderKnob(const Surface &out)
|
|
|
|
|
{
|
|
|
|
|
if (knobSurface == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
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 };
|
|
|
|
|
SDL_BlitScaled(knobSurface.get(), nullptr, out.surface, &rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VirtualPadButtonRenderer::Render(const Surface &out)
|
|
|
|
|
{
|
|
|
|
|
if (buttonArt->surface == nullptr)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
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 };
|
|
|
|
|
SDL_BlitScaled(buttonArt->surface.get(), &src, out.surface, &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.surface = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void VirtualDirectionPadRenderer::UnloadArt()
|
|
|
|
|
{
|
|
|
|
|
padSurface = nullptr;
|
|
|
|
|
knobSurface = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void InitVirtualGamepadGFX()
|
|
|
|
|
{
|
|
|
|
|
Renderer.LoadArt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FreeVirtualGamepadGFX()
|
|
|
|
|
{
|
|
|
|
|
Renderer.UnloadArt();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace devilution
|