Browse Source

Hardware rendering for the virtual gamepad

pull/2922/head
staphen 5 years ago committed by Anders Jenbo
parent
commit
1142d2ee7b
  1. 12
      Source/DiabloUI/art.h
  2. 108
      Source/controls/touch/renderers.cpp
  3. 56
      Source/controls/touch/renderers.h
  4. 4
      Source/diablo.cpp
  5. 7
      Source/dx.cpp
  6. 6
      Source/scrollrt.cpp

12
Source/DiabloUI/art.h

@ -13,6 +13,10 @@ struct Art {
int frame_height;
unsigned int palette_version;
#ifndef USE_SDL1
SDLTextureUniquePtr texture;
#endif
Art()
{
surface = nullptr;
@ -20,6 +24,10 @@ struct Art {
logical_width = 0;
frame_height = 0; // logical frame height (before scaling)
palette_version = 0;
#ifndef USE_SDL1
texture = nullptr;
#endif
}
int w() const
@ -35,6 +43,10 @@ struct Art {
void Unload()
{
surface = nullptr;
#ifndef USE_SDL1
texture = nullptr;
#endif
}
};

108
Source/controls/touch/renderers.cpp

@ -5,6 +5,7 @@
#include "doom.h"
#include "engine.h"
#include "gendung.h"
#include "init.h"
#include "inv.h"
#include "minitext.h"
#include "stores.h"
@ -53,48 +54,85 @@ VirtualGamepadButtonType GetBlankButtonType(bool isPressed)
} // namespace
void DrawVirtualGamepad(const Surface &out)
void RenderVirtualGamepad(SDL_Renderer *renderer)
{
Renderer.Render(out);
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 VirtualGamepadRenderer::LoadArt()
void RenderVirtualGamepad(SDL_Surface *surface)
{
directionPadRenderer.LoadArt();
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()
void VirtualDirectionPadRenderer::LoadArt(SDL_Renderer *renderer)
{
padSurface.reset(LoadPNG("ui_art\\directions.png"));
knobSurface.reset(LoadPNG("ui_art\\directions2.png"));
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(const Surface &out)
void VirtualGamepadRenderer::Render(RenderFunction renderFunction)
{
directionPadRenderer.Render(out);
primaryActionButtonRenderer.Render(out);
secondaryActionButtonRenderer.Render(out);
spellActionButtonRenderer.Render(out);
cancelButtonRenderer.Render(out);
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(const Surface &out)
void VirtualDirectionPadRenderer::Render(RenderFunction renderFunction)
{
RenderPad(out);
RenderKnob(out);
RenderPad(renderFunction);
RenderKnob(renderFunction);
}
void VirtualDirectionPadRenderer::RenderPad(const Surface &out)
void VirtualDirectionPadRenderer::RenderPad(RenderFunction renderFunction)
{
if (padSurface == nullptr)
return;
auto center = virtualDirectionPad->area.position;
auto radius = virtualDirectionPad->area.radius;
int diameter = 2 * radius;
@ -104,14 +142,11 @@ void VirtualDirectionPadRenderer::RenderPad(const Surface &out)
int width = diameter;
int height = diameter;
SDL_Rect rect { x, y, width, height };
SDL_BlitScaled(padSurface.get(), nullptr, out.surface, &rect);
renderFunction(padArt, nullptr, &rect);
}
void VirtualDirectionPadRenderer::RenderKnob(const Surface &out)
void VirtualDirectionPadRenderer::RenderKnob(RenderFunction renderFunction)
{
if (knobSurface == nullptr)
return;
auto center = virtualDirectionPad->position;
auto radius = virtualDirectionPad->area.radius / 3;
int diameter = 2 * radius;
@ -121,17 +156,14 @@ void VirtualDirectionPadRenderer::RenderKnob(const Surface &out)
int width = diameter;
int height = diameter;
SDL_Rect rect { x, y, width, height };
SDL_BlitScaled(knobSurface.get(), nullptr, out.surface, &rect);
renderFunction(knobArt, nullptr, &rect);
}
void VirtualPadButtonRenderer::Render(const Surface &out)
void VirtualPadButtonRenderer::Render(RenderFunction renderFunction, Art &buttonArt)
{
if (buttonArt->surface == nullptr)
return;
VirtualGamepadButtonType buttonType = GetButtonType();
int frame = buttonType;
int offset = buttonArt->h() * frame;
int offset = buttonArt.h() * frame;
auto center = virtualPadButton->area.position;
auto radius = virtualPadButton->area.radius;
@ -142,9 +174,9 @@ void VirtualPadButtonRenderer::Render(const Surface &out)
int width = diameter;
int height = diameter;
SDL_Rect src { 0, offset, buttonArt->w(), buttonArt->h() };
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);
renderFunction(buttonArt, &src, &dst);
}
VirtualGamepadButtonType PrimaryActionButtonRenderer::GetButtonType()
@ -214,18 +246,18 @@ VirtualGamepadButtonType CancelButtonRenderer::GetButtonType()
void VirtualGamepadRenderer::UnloadArt()
{
directionPadRenderer.UnloadArt();
buttonArt.surface = nullptr;
buttonArt.Unload();
}
void VirtualDirectionPadRenderer::UnloadArt()
{
padSurface = nullptr;
knobSurface = nullptr;
padArt.Unload();
knobArt.Unload();
}
void InitVirtualGamepadGFX()
void InitVirtualGamepadGFX(SDL_Renderer *renderer)
{
Renderer.LoadArt();
Renderer.LoadArt(renderer);
}
void FreeVirtualGamepadGFX()

56
Source/controls/touch/renderers.h

@ -26,6 +26,8 @@ enum VirtualGamepadButtonType {
GAMEPAD_BLANKDOWN,
};
typedef std::function<void(Art &art, SDL_Rect *src, SDL_Rect *dst)> RenderFunction;
class VirtualDirectionPadRenderer {
public:
VirtualDirectionPadRenderer(VirtualDirectionPad *virtualDirectionPad)
@ -33,42 +35,38 @@ public:
{
}
void LoadArt();
void Render(const Surface &out);
void LoadArt(SDL_Renderer *renderer);
void Render(RenderFunction renderFunction);
void UnloadArt();
private:
VirtualDirectionPad *virtualDirectionPad;
SDLSurfaceUniquePtr padSurface;
SDLSurfaceUniquePtr knobSurface;
Art padArt;
Art knobArt;
void RenderPad(const Surface &out);
void RenderKnob(const Surface &out);
void RenderPad(RenderFunction renderFunction);
void RenderKnob(RenderFunction renderFunction);
};
class VirtualPadButtonRenderer {
public:
VirtualPadButtonRenderer(VirtualPadButton *virtualPadButton, Art *buttonArt)
VirtualPadButtonRenderer(VirtualPadButton *virtualPadButton)
: virtualPadButton(virtualPadButton)
, buttonArt(buttonArt)
{
}
void Render(const Surface &out);
void Render(RenderFunction renderFunction, Art &buttonArt);
protected:
VirtualPadButton *virtualPadButton;
virtual VirtualGamepadButtonType GetButtonType() = 0;
private:
Art *buttonArt;
};
class PrimaryActionButtonRenderer : public VirtualPadButtonRenderer {
public:
PrimaryActionButtonRenderer(VirtualPadButton *primaryActionButton, Art *buttonArt)
: VirtualPadButtonRenderer(primaryActionButton, buttonArt)
PrimaryActionButtonRenderer(VirtualPadButton *primaryActionButton)
: VirtualPadButtonRenderer(primaryActionButton)
{
}
@ -81,8 +79,8 @@ private:
class SecondaryActionButtonRenderer : public VirtualPadButtonRenderer {
public:
SecondaryActionButtonRenderer(VirtualPadButton *secondaryActionButton, Art *buttonArt)
: VirtualPadButtonRenderer(secondaryActionButton, buttonArt)
SecondaryActionButtonRenderer(VirtualPadButton *secondaryActionButton)
: VirtualPadButtonRenderer(secondaryActionButton)
{
}
@ -92,8 +90,8 @@ private:
class SpellActionButtonRenderer : public VirtualPadButtonRenderer {
public:
SpellActionButtonRenderer(VirtualPadButton *spellActionButton, Art *buttonArt)
: VirtualPadButtonRenderer(spellActionButton, buttonArt)
SpellActionButtonRenderer(VirtualPadButton *spellActionButton)
: VirtualPadButtonRenderer(spellActionButton)
{
}
@ -103,8 +101,8 @@ private:
class CancelButtonRenderer : public VirtualPadButtonRenderer {
public:
CancelButtonRenderer(VirtualPadButton *cancelButton, Art *buttonArt)
: VirtualPadButtonRenderer(cancelButton, buttonArt)
CancelButtonRenderer(VirtualPadButton *cancelButton)
: VirtualPadButtonRenderer(cancelButton)
{
}
@ -116,15 +114,15 @@ class VirtualGamepadRenderer {
public:
VirtualGamepadRenderer(VirtualGamepad *virtualGamepad)
: directionPadRenderer(&virtualGamepad->directionPad)
, primaryActionButtonRenderer(&virtualGamepad->primaryActionButton, &buttonArt)
, secondaryActionButtonRenderer(&virtualGamepad->secondaryActionButton, &buttonArt)
, spellActionButtonRenderer(&virtualGamepad->spellActionButton, &buttonArt)
, cancelButtonRenderer(&virtualGamepad->cancelButton, &buttonArt)
, primaryActionButtonRenderer(&virtualGamepad->primaryActionButton)
, secondaryActionButtonRenderer(&virtualGamepad->secondaryActionButton)
, spellActionButtonRenderer(&virtualGamepad->spellActionButton)
, cancelButtonRenderer(&virtualGamepad->cancelButton)
{
}
void LoadArt();
void Render(const Surface &out);
void LoadArt(SDL_Renderer *renderer);
void Render(RenderFunction renderFunction);
void UnloadArt();
private:
@ -136,9 +134,9 @@ private:
Art buttonArt;
};
void DrawVirtualGamepad(const Surface &out);
void InitVirtualGamepadGFX();
void InitVirtualGamepadGFX(SDL_Renderer *renderer);
void RenderVirtualGamepad(SDL_Renderer *renderer);
void RenderVirtualGamepad(SDL_Surface *surface);
void FreeVirtualGamepadGFX();
} // namespace devilution

4
Source/diablo.cpp

@ -1057,7 +1057,7 @@ void LoadAllGFX()
{
IncProgress();
#if defined(VIRTUAL_GAMEPAD) && !defined(USE_SDL1)
InitVirtualGamepadGFX();
InitVirtualGamepadGFX(renderer);
#endif
IncProgress();
InitObjectGFX();
@ -1861,7 +1861,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
} else {
IncProgress();
#if defined(VIRTUAL_GAMEPAD) && !defined(USE_SDL1)
InitVirtualGamepadGFX();
InitVirtualGamepadGFX(renderer);
#endif
IncProgress();
InitMissileGFX(gbIsHellfire);

7
Source/dx.cpp

@ -7,6 +7,7 @@
#include <SDL.h>
#include "controls/touch/renderers.h"
#include "engine.h"
#include "options.h"
#include "storm/storm.h"
@ -323,12 +324,18 @@ void RenderPresent()
if (SDL_RenderCopy(renderer, texture.get(), nullptr, nullptr) <= -1) {
ErrSdl();
}
#ifdef VIRTUAL_GAMEPAD
RenderVirtualGamepad(renderer);
#endif
SDL_RenderPresent(renderer);
if (!sgOptions.Graphics.bVSync) {
LimitFrameRate();
}
} else {
#ifdef VIRTUAL_GAMEPAD
RenderVirtualGamepad(surface);
#endif
if (SDL_UpdateWindowSurface(ghMainWnd) <= -1) {
ErrSdl();
}

6
Source/scrollrt.cpp

@ -1725,12 +1725,6 @@ void DrawAndBlit()
DrawMain(hgt, ddsdesc, drawhpflag, drawmanaflag, drawsbarflag, drawbtnflag);
#if defined(VIRTUAL_GAMEPAD) && !defined(USE_SDL1)
SDL_Surface *sdlOutputSurface = GetOutputSurface();
Surface outputSurface(sdlOutputSurface);
DrawVirtualGamepad(outputSurface);
#endif
RenderPresent();
drawhpflag = false;

Loading…
Cancel
Save