CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/UI/GamepadEmu.h
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#pragma once1819#include "Common/Input/InputState.h"20#include "Common/Render/DrawBuffer.h"2122#include "Common/UI/View.h"23#include "Common/UI/ViewGroup.h"24#include "Core/CoreParameter.h"25#include "Core/HLE/sceCtrl.h"26#include "UI/EmuScreen.h"2728class GamepadView : public UI::View {29public:30GamepadView(const char *key, UI::LayoutParams *layoutParams);3132bool Key(const KeyInput &input) override {33return false;34}35std::string DescribeText() const override;3637protected:38std::string key_;39};4041class MultiTouchButton : public GamepadView {42public:43MultiTouchButton(const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams)44: GamepadView(key, layoutParams), scale_(scale), bgImg_(bgImg), bgDownImg_(bgDownImg), img_(img) {45}4647bool Touch(const TouchInput &input) override;48void Draw(UIContext &dc) override;49void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;50virtual bool IsDown() { return pointerDownMask_ != 0; }51// chainable52MultiTouchButton *FlipImageH(bool flip) { flipImageH_ = flip; return this; }53MultiTouchButton *SetAngle(float angle) { angle_ = angle; bgAngle_ = angle; return this; }54MultiTouchButton *SetAngle(float angle, float bgAngle) { angle_ = angle; bgAngle_ = bgAngle; return this; }5556protected:57uint32_t pointerDownMask_ = 0;58float scale_;5960private:61ImageID bgImg_;62ImageID bgDownImg_;63ImageID img_;64float bgAngle_ = 0.0f;65float angle_ = 0.0f;66bool flipImageH_ = false;67};6869class BoolButton : public MultiTouchButton {70public:71BoolButton(bool *value, const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams)72: MultiTouchButton(key, bgImg, bgDownImg, img, scale, layoutParams), value_(value) {7374}75bool Touch(const TouchInput &input) override;76bool IsDown() override { return *value_; }7778UI::Event OnChange;7980private:81bool *value_;82};8384class PSPButton : public MultiTouchButton {85public:86PSPButton(int pspButtonBit, const char *key, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, UI::LayoutParams *layoutParams)87: MultiTouchButton(key, bgImg, bgDownImg, img, scale, layoutParams), pspButtonBit_(pspButtonBit) {88}89bool Touch(const TouchInput &input) override;90bool IsDown() override;9192private:93int pspButtonBit_;94};9596class PSPDpad : public GamepadView {97public:98PSPDpad(ImageID arrowIndex, const char *key, ImageID arrowDownIndex, ImageID overlayIndex, float scale, float spacing, UI::LayoutParams *layoutParams);99100bool Touch(const TouchInput &input) override;101void Draw(UIContext &dc) override;102void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;103104private:105void ProcessTouch(float x, float y, bool down);106ImageID arrowIndex_;107ImageID arrowDownIndex_;108ImageID overlayIndex_;109110float scale_;111float spacing_;112113int dragPointerId_;114int down_;115};116117class PSPStick : public GamepadView {118public:119PSPStick(ImageID bgImg, const char *key, ImageID stickImg, ImageID stickDownImg, int stick, float scale, UI::LayoutParams *layoutParams);120121bool Touch(const TouchInput &input) override;122void Draw(UIContext &dc) override;123void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;124125protected:126int dragPointerId_;127ImageID bgImg_;128ImageID stickImageIndex_;129ImageID stickDownImg_;130131int stick_;132float stick_size_;133float scale_;134135float centerX_;136float centerY_;137138private:139void ProcessTouch(float x, float y, bool down);140};141142class PSPCustomStick : public PSPStick {143public:144PSPCustomStick(ImageID bgImg, const char *key, ImageID stickImg, ImageID stickDownImg, int stick, float scale, UI::LayoutParams *layoutParams);145146bool Touch(const TouchInput &input) override;147void Draw(UIContext &dc) override;148149private:150void ProcessTouch(float x, float y, bool down);151152float posX_ = 0.0f;153float posY_ = 0.0f;154};155156//initializes the layout from Config. if a default layout does not exist,157//it sets up default values158void InitPadLayout(float xres, float yres, float globalScale = 1.15f);159UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPauseButton, ControlMapper* controllMapper);160161const int D_pad_Radius = 50;162const int baseActionButtonSpacing = 60;163164class CustomButton : public MultiTouchButton {165public:166CustomButton(uint64_t pspButtonBit, const char *key, bool toggle, bool repeat, ControlMapper* controllMapper, ImageID bgImg, ImageID bgDownImg, ImageID img, float scale, bool invertedContextDimension, UI::LayoutParams *layoutParams)167: MultiTouchButton(key, bgImg, bgDownImg, img, scale, layoutParams), pspButtonBit_(pspButtonBit), toggle_(toggle), repeat_(repeat), controlMapper_(controllMapper), on_(false), invertedContextDimension_(invertedContextDimension) {168}169bool Touch(const TouchInput &input) override;170void Update() override;171bool IsDown() override;172173void GetContentDimensions(const UIContext &dc, float &w, float &h) const override;174private:175uint64_t pspButtonBit_;176bool toggle_;177bool repeat_;178int pressedFrames_ = 0;179ControlMapper* controlMapper_;180bool on_;181bool invertedContextDimension_; // Swap width and height182};183184class GestureGamepad : public UI::View {185public:186GestureGamepad(ControlMapper* controllMapper) : controlMapper_(controllMapper) {};187188bool Touch(const TouchInput &input) override;189void Update() override;190void Draw(UIContext &dc) override;191192protected:193194float lastX_ = 0.0f;195float lastY_ = 0.0f;196float deltaX_ = 0.0f;197float deltaY_ = 0.0f;198float downX_;199float downY_;200float lastTapRelease_ = 0.0f;201float lastTouchDown_ = 0.0f;202int dragPointerId_ = -1;203bool swipeLeftReleased_ = true;204bool swipeRightReleased_ = true;205bool swipeUpReleased_ = true;206bool swipeDownReleased_ = true;207bool haveDoubleTapped_ = false;208ControlMapper* controlMapper_;209};210211// Just edit this to add new image, shape or button function212namespace CustomKeyData {213// Image list214struct keyImage {215ImageID i; // ImageID216float r; // Rotation angle in degree217};218static const keyImage customKeyImages[] = {219{ ImageID("I_1"), 0.0f },220{ ImageID("I_2"), 0.0f },221{ ImageID("I_3"), 0.0f },222{ ImageID("I_4"), 0.0f },223{ ImageID("I_5"), 0.0f },224{ ImageID("I_6"), 0.0f },225{ ImageID("I_A"), 0.0f },226{ ImageID("I_B"), 0.0f },227{ ImageID("I_C"), 0.0f },228{ ImageID("I_D"), 0.0f },229{ ImageID("I_E"), 0.0f },230{ ImageID("I_F"), 0.0f },231{ ImageID("I_CIRCLE"), 0.0f },232{ ImageID("I_CROSS"), 0.0f },233{ ImageID("I_SQUARE"), 0.0f },234{ ImageID("I_TRIANGLE"), 0.0f },235{ ImageID("I_L"), 0.0f },236{ ImageID("I_R"), 0.0f },237{ ImageID("I_START"), 0.0f },238{ ImageID("I_SELECT"), 0.0f },239{ ImageID("I_CROSS"), 45.0f },240{ ImageID("I_SQUARE"), 45.0f },241{ ImageID("I_TRIANGLE"), 180.0f },242{ ImageID("I_ARROW"), 90.0f},243{ ImageID("I_ARROW"), 270.0f},244{ ImageID("I_ARROW"), 0.0f},245{ ImageID("I_ARROW"), 180.0f},246{ ImageID("I_GEAR"), 0.0f},247{ ImageID("I_ROTATE_LEFT"), 0.0f},248{ ImageID("I_ROTATE_RIGHT"), 0.0f},249{ ImageID("I_ARROW_LEFT"), 0.0f},250{ ImageID("I_ARROW_RIGHT"), 0.0f},251{ ImageID("I_ARROW_UP"), 0.0f},252{ ImageID("I_ARROW_DOWN"), 0.0f},253{ ImageID("I_THREE_DOTS"), 0.0f},254{ ImageID("I_EMPTY"), 0.0f},255};256257// Shape list258struct keyShape {259ImageID i; // ImageID260ImageID l; // ImageID line version261float r; // Rotation angle in dregree262bool f; // Flip Horizontally263bool d; // Invert height and width for context dimension (for example for 90 degree rot)264};265static const keyShape customKeyShapes[] = {266{ ImageID("I_ROUND"), ImageID("I_ROUND_LINE"), 0.0f, false, false },267{ ImageID("I_RECT"), ImageID("I_RECT_LINE"), 0.0f, false, false },268{ ImageID("I_RECT"), ImageID("I_RECT_LINE"), 90.0f, false, true },269{ ImageID("I_SHOULDER"), ImageID("I_SHOULDER_LINE"), 0.0f, false, false },270{ ImageID("I_SHOULDER"), ImageID("I_SHOULDER_LINE"), 0.0f, true, false },271{ ImageID("I_DIR"), ImageID("I_DIR_LINE"), 270.0f, false, true },272{ ImageID("I_DIR"), ImageID("I_DIR_LINE"), 90.0f, false, true },273{ ImageID("I_DIR"), ImageID("I_DIR_LINE"), 180.0f, false, false },274{ ImageID("I_DIR"), ImageID("I_DIR_LINE"), 0.0f, false, false },275{ ImageID("I_SQUARE_SHAPE"), ImageID("I_SQUARE_SHAPE_LINE"), 0.0f, false, false },276{ ImageID("I_EMPTY"), ImageID("I_EMPTY"), 0.0f, false, false },277};278279// Button list280struct keyList {281ImageID i; // UI ImageID282uint32_t c; // Key code283};284static const keyList customKeyList[] = {285{ ImageID("I_SQUARE"), CTRL_SQUARE },286{ ImageID("I_TRIANGLE"), CTRL_TRIANGLE },287{ ImageID("I_CIRCLE"), CTRL_CIRCLE },288{ ImageID("I_CROSS"), CTRL_CROSS },289{ ImageID::invalid(), CTRL_UP },290{ ImageID::invalid(), CTRL_DOWN },291{ ImageID::invalid(), CTRL_LEFT },292{ ImageID::invalid(), CTRL_RIGHT },293{ ImageID("I_START"), CTRL_START },294{ ImageID("I_SELECT"), CTRL_SELECT },295{ ImageID("I_L"), CTRL_LTRIGGER },296{ ImageID("I_R"), CTRL_RTRIGGER },297{ ImageID::invalid(), VIRTKEY_RAPID_FIRE },298{ ImageID::invalid(), VIRTKEY_FASTFORWARD },299{ ImageID::invalid(), VIRTKEY_SPEED_TOGGLE },300{ ImageID::invalid(), VIRTKEY_REWIND },301{ ImageID::invalid(), VIRTKEY_SAVE_STATE },302{ ImageID::invalid(), VIRTKEY_LOAD_STATE },303{ ImageID::invalid(), VIRTKEY_NEXT_SLOT },304#if !defined(MOBILE_DEVICE)305{ ImageID::invalid(), VIRTKEY_TOGGLE_FULLSCREEN },306#endif307{ ImageID::invalid(), VIRTKEY_SPEED_CUSTOM1 },308{ ImageID::invalid(), VIRTKEY_SPEED_CUSTOM2 },309{ ImageID::invalid(), VIRTKEY_TEXTURE_DUMP },310{ ImageID::invalid(), VIRTKEY_TEXTURE_REPLACE },311{ ImageID::invalid(), VIRTKEY_SCREENSHOT },312{ ImageID::invalid(), VIRTKEY_MUTE_TOGGLE },313{ ImageID::invalid(), VIRTKEY_OPENCHAT },314{ ImageID::invalid(), VIRTKEY_ANALOG_ROTATE_CW },315{ ImageID::invalid(), VIRTKEY_ANALOG_ROTATE_CCW },316{ ImageID::invalid(), VIRTKEY_PAUSE },317{ ImageID::invalid(), VIRTKEY_RESET_EMULATION },318{ ImageID::invalid(), VIRTKEY_DEVMENU },319#ifndef MOBILE_DEVICE320{ ImageID::invalid(), VIRTKEY_RECORD },321#endif322{ ImageID::invalid(), VIRTKEY_AXIS_X_MIN },323{ ImageID::invalid(), VIRTKEY_AXIS_Y_MIN },324{ ImageID::invalid(), VIRTKEY_AXIS_X_MAX },325{ ImageID::invalid(), VIRTKEY_AXIS_Y_MAX },326{ ImageID::invalid(), VIRTKEY_PREVIOUS_SLOT },327};328static_assert(ARRAY_SIZE(customKeyList) <= 64, "Too many key for a uint64_t bit mask");329};330331// Gesture key only have virtual button that can work without constant press332namespace GestureKey {333static const uint32_t keyList[] = {334CTRL_SQUARE,335CTRL_TRIANGLE,336CTRL_CIRCLE,337CTRL_CROSS,338CTRL_UP,339CTRL_DOWN,340CTRL_LEFT,341CTRL_RIGHT,342CTRL_START,343CTRL_SELECT,344CTRL_LTRIGGER,345CTRL_RTRIGGER,346VIRTKEY_AXIS_Y_MAX,347VIRTKEY_AXIS_Y_MIN,348VIRTKEY_AXIS_X_MIN,349VIRTKEY_AXIS_X_MAX,350VIRTKEY_SPEED_TOGGLE,351VIRTKEY_REWIND,352VIRTKEY_SAVE_STATE,353VIRTKEY_LOAD_STATE,354VIRTKEY_PREVIOUS_SLOT,355VIRTKEY_NEXT_SLOT,356VIRTKEY_TEXTURE_DUMP,357VIRTKEY_TEXTURE_REPLACE,358VIRTKEY_SCREENSHOT,359VIRTKEY_MUTE_TOGGLE,360VIRTKEY_OPENCHAT,361VIRTKEY_PAUSE,362VIRTKEY_DEVMENU,363#ifndef MOBILE_DEVICE364VIRTKEY_RECORD,365#endif366VIRTKEY_AXIS_X_MIN,367VIRTKEY_AXIS_Y_MIN,368VIRTKEY_AXIS_X_MAX,369VIRTKEY_AXIS_Y_MAX,370};371}372373void GamepadTouch(bool reset = false);374void GamepadUpdateOpacity(float force = -1.0f);375float GamepadGetOpacity();376377378