ppsspp/ui/ui.h

301 lines
8.0 KiB
C
Raw Normal View History

2012-04-10 10:36:38 +00:00
// Simple immediate mode UI implementation.
//
// Heavily inspired by Sol's tutorial at http://sol.gfxile.net/imgui/.
//
// A common pattern is Adapter classes for changing how things are drawn
// in lists, for example.
//
2012-07-26 11:47:15 +00:00
// Immediate UI works great for overlay UI for games, for example, but is actually
// not really a good idea for full app UIs. Also, animations are difficult because
// there's not really any good place to store state.
//
2012-04-10 10:36:38 +00:00
// hrydgard@gmail.com
#pragma once
// Simple ID generators. Absolutely no guarantee of collision avoidance if you implement
// multiple parts of a single screen of UI over multiple files unless you use IMGUI_SRC_ID.
#ifdef IMGUI_SRC_ID
2013-03-30 18:23:02 +00:00
#define GEN_ID (int)((IMGUI_SRC_ID) + (__LINE__))
#define GEN_ID_LOOP(i) (int)((IMGUI_SRC_ID) + (__LINE__) + (i) * 13612)
2012-04-10 10:36:38 +00:00
#else
#define GEN_ID (__LINE__)
#define GEN_ID_LOOP(i) ((__LINE__) + ((int)i) * 13612)
2012-04-10 10:36:38 +00:00
#endif
2012-04-12 10:52:55 +00:00
#include <string>
2012-04-10 10:36:38 +00:00
#include <vector>
#include "gfx_es2/draw_buffer.h"
#include "input/input_state.h"
2013-03-30 18:23:02 +00:00
class Texture;
class UIContext;
2012-04-12 17:45:21 +00:00
class LayoutManager {
public:
2012-10-29 13:49:09 +00:00
virtual void GetPos(float *w, float *h, float *x, float *y) const = 0;
2012-04-12 17:45:21 +00:00
};
class Pos : public LayoutManager {
public:
2012-10-29 13:49:09 +00:00
Pos(float x, float y) : x_(x), y_(y) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
}
2012-04-12 17:45:21 +00:00
private:
2012-10-29 13:49:09 +00:00
float x_;
float y_;
2012-04-12 17:45:21 +00:00
};
class HLinear : public LayoutManager {
public:
2012-10-29 13:49:09 +00:00
HLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
x_ += *w + spacing_;
}
void Space(float x) {
x_ += x;
}
2012-04-12 17:45:21 +00:00
private:
2012-10-29 13:49:09 +00:00
mutable float x_;
float y_;
float spacing_;
2012-04-12 17:45:21 +00:00
};
class VLinear : public LayoutManager {
public:
2012-10-29 13:49:09 +00:00
VLinear(float x, float y, float spacing = 2.0f) : x_(x), y_(y), spacing_(spacing) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
y_ += *h + spacing_;
}
2012-04-12 17:45:21 +00:00
private:
2012-10-29 13:49:09 +00:00
float x_;
mutable float y_;
float spacing_;
2012-04-12 17:45:21 +00:00
};
class HGrid : public LayoutManager {
public:
HGrid(float x, float y, float xMax, float xSpacing = 2.0f, float ySpacing = 2.0f)
: x_(x), y_(y), xInit_(x), xMax_(xMax), xSpacing_(xSpacing), ySpacing_(ySpacing) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
x_ += *w + xSpacing_;
if (x_ >= xMax_) {
x_ = xInit_;
y_ += *h + ySpacing_;
}
}
private:
mutable float x_;
mutable float y_;
float xInit_;
float xMax_;
float xSpacing_;
float ySpacing_;
};
class VGrid : public LayoutManager {
public:
VGrid(float x, float y, float yMax, float xSpacing = 2.0f, float ySpacing = 2.0f)
: x_(x), y_(y), yInit_(y), yMax_(yMax), xSpacing_(xSpacing), ySpacing_(ySpacing) {}
virtual void GetPos(float *w, float *h, float *x, float *y) const {
*x = x_;
*y = y_;
y_ += *h + ySpacing_;
if (y_ + *h >= yMax_) {
x_ += *w + xSpacing_;
y_ = yInit_;
}
}
private:
mutable float x_;
mutable float y_;
float yInit_;
float yMax_;
float xSpacing_;
float ySpacing_;
};
2012-10-29 13:49:09 +00:00
// "Mouse" out of habit, applies just as well to touch events.
// TODO: Change to "pointer"
2012-05-13 22:42:42 +00:00
// This struct is zeroed on init, so should be valid at that state.
2012-10-28 10:37:10 +00:00
// Never inherit from this.
2012-04-10 10:36:38 +00:00
struct UIState {
2012-10-29 13:49:09 +00:00
int mousex[MAX_POINTERS];
int mousey[MAX_POINTERS];
bool mousedown[MAX_POINTERS];
bool mousepressed[MAX_POINTERS];
short mouseframesdown[MAX_POINTERS];
2012-04-10 10:36:38 +00:00
2012-10-29 13:49:09 +00:00
int mouseStartX[MAX_POINTERS];
int mouseStartY[MAX_POINTERS];
2012-04-10 10:36:38 +00:00
2012-10-29 13:49:09 +00:00
int hotitem[MAX_POINTERS];
int activeitem[MAX_POINTERS];
2012-04-10 10:36:38 +00:00
2012-10-29 13:49:09 +00:00
// keyboard focus, not currently used
int kbdwidget;
int lastwidget;
2012-04-11 15:07:28 +00:00
2012-10-29 13:49:09 +00:00
int ui_tick;
// deprecated: tempfloat
float tempfloat;
2012-04-10 10:36:38 +00:00
};
// This needs to be extern so that additional UI controls can be developed outside this file.
extern UIState uistate;
struct Atlas;
// This is the drawbuffer used for UI. Remember to flush it at the end of the frame.
// TODO: One should probably pass it in through UIInit.
extern DrawBuffer ui_draw2d;
2012-10-29 13:49:09 +00:00
extern DrawBuffer ui_draw2d_front; // for things that need to be on top of the rest
2012-04-10 10:36:38 +00:00
2012-07-16 22:00:48 +00:00
struct UITheme {
2012-10-29 13:49:09 +00:00
int uiFont;
int uiFontSmall;
int uiFontSmaller;
int buttonImage;
2012-10-30 16:36:28 +00:00
int buttonSelected;
2012-10-29 13:49:09 +00:00
int checkOn;
int checkOff;
2012-07-16 22:00:48 +00:00
};
// The atlas needs to stick around, the theme is copied.
void UIInit(const Atlas *atlas, const UITheme &theme);
// Between these, UI components won't see pointer events.
void UIDisableBegin();
void UIDisableEnd();
2012-07-16 22:00:48 +00:00
// Just lets you retrieve the theme that was passed into UIInit, for your own controls for example.
UITheme &UIGetTheme();
2012-04-10 10:36:38 +00:00
// TODO: These don't really belong here.
const int UI_SPACE = 32;
const int SMALL_BUTTON_WIDTH = 128;
const int LARGE_BUTTON_WIDTH = 192;
const int BUTTON_HEIGHT = 72;
struct SlideItem {
2012-10-29 13:49:09 +00:00
const char *text;
int image;
uint32_t bgColor;
2012-04-10 10:36:38 +00:00
};
struct UISlideState {
2012-10-29 13:49:09 +00:00
float scroll;
2012-04-10 10:36:38 +00:00
};
// Implement this interface to style your lists
class UIListAdapter {
public:
2012-10-29 13:49:09 +00:00
virtual size_t getCount() const = 0;
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const = 0;
virtual float itemHeight(int itemIndex) const { return 64; }
virtual bool itemEnabled(int itemIndex) const { return true; }
2012-04-10 10:36:38 +00:00
};
class StringVectorListAdapter : public UIListAdapter {
public:
2012-10-29 13:49:09 +00:00
StringVectorListAdapter(const std::vector<std::string> *items) : items_(items) {}
virtual size_t getCount() const { return items_->size(); }
virtual void drawItem(int item, int x, int y, int w, int h, bool active) const;
2012-04-10 10:36:38 +00:00
private:
2012-10-29 13:49:09 +00:00
const std::vector<std::string> *items_;
2012-04-10 10:36:38 +00:00
};
2012-04-11 15:07:28 +00:00
// Utility functions, useful when implementing your own controls
2012-04-26 22:48:30 +00:00
bool UIRegionHit(int pointerId, int x, int y, int w, int h, int margin);
2012-04-11 15:07:28 +00:00
2012-04-10 10:36:38 +00:00
// Call at start of frame
2013-03-30 18:23:02 +00:00
void UIBegin(const GLSLProgram *shader);
// Call at end of frame.
void UIEnd();
void UIFlush();
2012-04-10 10:36:38 +00:00
2012-04-26 22:48:30 +00:00
void UIUpdateMouse(int i, float x, float y, bool down);
2012-04-10 10:36:38 +00:00
2012-10-28 10:37:10 +00:00
// Call when you switch screens
void UIReset();
2012-04-10 10:36:38 +00:00
// Returns 1 if clicked
2013-04-13 13:01:09 +00:00
int UIButton(int id, const LayoutManager &layout, float w, float h, const char *text, int button_align);
2012-10-29 13:49:09 +00:00
int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images.
2013-04-17 15:08:31 +00:00
int UITextureButton(UIContext *ctx, int id, const LayoutManager &layout, float w, float h, Texture *texture, int button_align, uint32_t color, int drop_shadow=0); // uses current UI atlas for fetching images.
2012-04-10 10:36:38 +00:00
// Returns 1 if clicked, puts the value in *value (where it also gets the current state).
int UICheckBox(int id, int x, int y, const char *text, int align, bool *value);
// Vertical slider. Not yet working.
2012-04-26 22:48:30 +00:00
// int UIVSlider(int id, int x, int y, int h, int max, int *value);
2012-04-10 10:36:38 +00:00
// Horizontal slider. Not yet working.
int UIHSlider(int id, int x, int y, int w, int max, int *value);
// Draws static text, that does not participate in any focusing scheme etc, it just is.
2012-04-12 10:52:55 +00:00
void UIText(int font, int x, int y, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT);
2012-04-10 10:36:38 +00:00
void UIText(int x, int y, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT);
2013-01-02 19:56:09 +00:00
void UIText(int font, const LayoutManager &layout, const char *text, uint32_t color, float scale = 1.0f, int align = ALIGN_TOPLEFT);
2012-04-10 10:36:38 +00:00
// Slide choice, like the Angry Birds level selector. Not yet working.
void UISlideChoice(int id, int y, const SlideItem *items, int numItems, UISlideState *state);
class UIList {
2012-10-29 13:49:09 +00:00
public:
UIList();
bool scrolling;
int activePointer;
float startScrollY;
2012-10-29 13:49:09 +00:00
float scrollY;
float lastX;
float lastY;
2012-10-29 13:49:09 +00:00
float startDragY;
float movedDistanceX;
2012-10-29 13:49:09 +00:00
float movedDistanceY;
float inertiaY;
2012-10-29 13:49:09 +00:00
int dragFinger;
int selected;
// List view.
// return -1 = no selection
int Do(int id, int x, int y, int w, int h, UIListAdapter *adapter);
2012-10-31 12:35:11 +00:00
// Call this when the content has changed, to reset scroll position etc.
void contentChanged() {
scrollY = 0.0f;
inertiaY = 0.0f;
}
2013-07-08 09:03:14 +00:00
void scrollRelative(float delta) {
scrollY += delta;
}
2012-10-29 13:49:09 +00:00
private:
// TODO: Migrate to using these directly.
void pointerDown(int pointer, float x, float y);
void pointerUp(int pointer, float x, float y, bool inside);
void pointerMove(int pointer, float x, float y, bool inside);
2012-10-29 13:49:09 +00:00
DISALLOW_COPY_AND_ASSIGN(UIList);
};
2012-04-10 10:36:38 +00:00