mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Reindent UI
This commit is contained in:
parent
ef01fc2121
commit
4b123b25cc
128
ui/screen.cpp
128
ui/screen.cpp
@ -15,50 +15,50 @@ ScreenManager::~ScreenManager() {
|
||||
}
|
||||
|
||||
void ScreenManager::switchScreen(Screen *screen) {
|
||||
if (dialog_.size())
|
||||
{
|
||||
WLOG("Switching screens - dropping the whole dialog stack");
|
||||
while (dialog_.size())
|
||||
pop();
|
||||
}
|
||||
// TODO: is this still true?
|
||||
// Note that if a dialog is found, this will be a silent background switch that
|
||||
// will only become apparent if the dialog is closed. The previous screen will stick around
|
||||
// until that switch.
|
||||
if (nextScreen_ != 0) {
|
||||
FLOG("WTF? Already had a nextScreen_");
|
||||
}
|
||||
if (screen != currentScreen_) {
|
||||
nextScreen_ = screen;
|
||||
if (dialog_.size())
|
||||
{
|
||||
WLOG("Switching screens - dropping the whole dialog stack");
|
||||
while (dialog_.size())
|
||||
pop();
|
||||
}
|
||||
// TODO: is this still true?
|
||||
// Note that if a dialog is found, this will be a silent background switch that
|
||||
// will only become apparent if the dialog is closed. The previous screen will stick around
|
||||
// until that switch.
|
||||
if (nextScreen_ != 0) {
|
||||
FLOG("WTF? Already had a nextScreen_");
|
||||
}
|
||||
if (screen != currentScreen_) {
|
||||
nextScreen_ = screen;
|
||||
nextScreen_->setScreenManager(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenManager::update(InputState &input) {
|
||||
if (dialog_.size()) {
|
||||
dialog_.back()->update(input);
|
||||
return;
|
||||
}
|
||||
if (dialog_.size()) {
|
||||
dialog_.back()->update(input);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextScreen_) {
|
||||
ILOG("Screen switch!");
|
||||
Screen *temp = currentScreen_;
|
||||
ILOG("Screen switch!");
|
||||
Screen *temp = currentScreen_;
|
||||
currentScreen_ = nextScreen_;
|
||||
delete temp;
|
||||
temp = 0;
|
||||
delete temp;
|
||||
temp = 0;
|
||||
nextScreen_ = 0;
|
||||
}
|
||||
|
||||
if (currentScreen_) {
|
||||
currentScreen_->update(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenManager::render() {
|
||||
if (dialog_.size()) {
|
||||
dialog_.back()->render();
|
||||
return;
|
||||
}
|
||||
if (dialog_.size()) {
|
||||
dialog_.back()->render();
|
||||
return;
|
||||
}
|
||||
if (currentScreen_) {
|
||||
currentScreen_->render();
|
||||
}
|
||||
@ -76,53 +76,53 @@ void ScreenManager::deviceLost()
|
||||
}
|
||||
|
||||
Screen *ScreenManager::topScreen() {
|
||||
if (dialog_.size())
|
||||
return dialog_.back();
|
||||
else
|
||||
return currentScreen_;
|
||||
if (dialog_.size())
|
||||
return dialog_.back();
|
||||
else
|
||||
return currentScreen_;
|
||||
}
|
||||
|
||||
void ScreenManager::shutdown() {
|
||||
if (nextScreen_) {
|
||||
delete nextScreen_;
|
||||
nextScreen_ = 0;
|
||||
}
|
||||
if (currentScreen_) {
|
||||
delete currentScreen_;
|
||||
currentScreen_ = 0;
|
||||
}
|
||||
if (nextScreen_) {
|
||||
delete nextScreen_;
|
||||
nextScreen_ = 0;
|
||||
}
|
||||
if (currentScreen_) {
|
||||
delete currentScreen_;
|
||||
currentScreen_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenManager::push(Screen *screen) {
|
||||
screen->setScreenManager(this);
|
||||
dialog_.push_back(screen);
|
||||
dialog_.push_back(screen);
|
||||
}
|
||||
|
||||
void ScreenManager::pop() {
|
||||
if (dialog_.size()) {
|
||||
delete dialog_.back();
|
||||
dialog_.pop_back();
|
||||
} else {
|
||||
ELOG("Can't push when no dialog is shown");
|
||||
}
|
||||
if (dialog_.size()) {
|
||||
delete dialog_.back();
|
||||
dialog_.pop_back();
|
||||
} else {
|
||||
ELOG("Can't push when no dialog is shown");
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenManager::finishDialog(const Screen *dialog, DialogResult result)
|
||||
{
|
||||
if (!dialog_.size()) {
|
||||
ELOG("Must be in a dialog to finishDialog");
|
||||
return;
|
||||
}
|
||||
Screen *dlg = dialog_.back();
|
||||
if (dialog != dialog_.back())
|
||||
{
|
||||
ELOG("Wrong dialog being finished!");
|
||||
return;
|
||||
}
|
||||
if (dialog_.size()) {
|
||||
dialog_.pop_back();
|
||||
}
|
||||
Screen *caller = topScreen();
|
||||
caller->dialogFinished(dialog, result);
|
||||
delete dialog;
|
||||
if (!dialog_.size()) {
|
||||
ELOG("Must be in a dialog to finishDialog");
|
||||
return;
|
||||
}
|
||||
Screen *dlg = dialog_.back();
|
||||
if (dialog != dialog_.back())
|
||||
{
|
||||
ELOG("Wrong dialog being finished!");
|
||||
return;
|
||||
}
|
||||
if (dialog_.size()) {
|
||||
dialog_.pop_back();
|
||||
}
|
||||
Screen *caller = topScreen();
|
||||
caller->dialogFinished(dialog, result);
|
||||
delete dialog;
|
||||
}
|
||||
|
34
ui/screen.h
34
ui/screen.h
@ -21,10 +21,10 @@
|
||||
struct InputState;
|
||||
|
||||
enum DialogResult {
|
||||
DR_OK,
|
||||
DR_CANCEL,
|
||||
DR_YES,
|
||||
DR_NO,
|
||||
DR_OK,
|
||||
DR_CANCEL,
|
||||
DR_YES,
|
||||
DR_NO,
|
||||
};
|
||||
|
||||
class ScreenManager;
|
||||
@ -36,14 +36,14 @@ public:
|
||||
virtual void update(InputState &input) = 0;
|
||||
virtual void render() {}
|
||||
virtual void deviceLost() {}
|
||||
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
|
||||
virtual void dialogFinished(const Screen *dialog, DialogResult result) {}
|
||||
|
||||
ScreenManager *screenManager() { return screenManager_; }
|
||||
void setScreenManager(ScreenManager *sm) { screenManager_ = sm; }
|
||||
|
||||
private:
|
||||
ScreenManager *screenManager_;
|
||||
DISALLOW_COPY_AND_ASSIGN(Screen);
|
||||
DISALLOW_COPY_AND_ASSIGN(Screen);
|
||||
};
|
||||
|
||||
class Transition {
|
||||
@ -60,22 +60,22 @@ public:
|
||||
void update(InputState &input);
|
||||
void render();
|
||||
void deviceLost();
|
||||
void shutdown();
|
||||
void shutdown();
|
||||
|
||||
// Push a dialog box in front. Currently 1-level only.
|
||||
void push(Screen *screen);
|
||||
// Push a dialog box in front. Currently 1-level only.
|
||||
void push(Screen *screen);
|
||||
|
||||
// Pops the dialog away.
|
||||
void finishDialog(const Screen *dialog, DialogResult result = DR_OK);
|
||||
// Pops the dialog away.
|
||||
void finishDialog(const Screen *dialog, DialogResult result = DR_OK);
|
||||
|
||||
private:
|
||||
void pop();
|
||||
Screen *topScreen();
|
||||
// Base screen. These don't "stack" and you can move in any order between them.
|
||||
void pop();
|
||||
Screen *topScreen();
|
||||
// Base screen. These don't "stack" and you can move in any order between them.
|
||||
Screen *currentScreen_;
|
||||
Screen *nextScreen_;
|
||||
|
||||
// Dialog stack. These are shown "on top" of base screens and the Android back button works as expected.
|
||||
// Used for options, in-game menus and other things you expect to be able to back out from onto something.
|
||||
std::list<Screen *> dialog_;
|
||||
// Dialog stack. These are shown "on top" of base screens and the Android back button works as expected.
|
||||
// Used for options, in-game menus and other things you expect to be able to back out from onto something.
|
||||
std::list<Screen *> dialog_;
|
||||
};
|
||||
|
484
ui/ui.cpp
484
ui/ui.cpp
@ -19,29 +19,29 @@ static const Atlas *themeAtlas;
|
||||
static UITheme theme;
|
||||
|
||||
void UIInit(const Atlas *atlas, const UITheme &ui_theme) {
|
||||
ui_draw2d.SetAtlas(atlas);
|
||||
ui_draw2d_front.SetAtlas(atlas);
|
||||
themeAtlas = atlas;
|
||||
theme = ui_theme;
|
||||
memset(&uistate, 0, sizeof(uistate));
|
||||
ui_draw2d.SetAtlas(atlas);
|
||||
ui_draw2d_front.SetAtlas(atlas);
|
||||
themeAtlas = atlas;
|
||||
theme = ui_theme;
|
||||
memset(&uistate, 0, sizeof(uistate));
|
||||
}
|
||||
|
||||
void UIUpdateMouse(int i, float x, float y, bool down) {
|
||||
if (down && !uistate.mousedown[i]) {
|
||||
uistate.mousepressed[i] = 1;
|
||||
uistate.mouseStartX[i] = x;
|
||||
uistate.mouseStartY[i] = y;
|
||||
} else {
|
||||
uistate.mousepressed[i] = 0;
|
||||
}
|
||||
if (uistate.mousedown[i])
|
||||
uistate.mouseframesdown[i]++;
|
||||
else
|
||||
uistate.mouseframesdown[i] = 0;
|
||||
if (down && !uistate.mousedown[i]) {
|
||||
uistate.mousepressed[i] = 1;
|
||||
uistate.mouseStartX[i] = x;
|
||||
uistate.mouseStartY[i] = y;
|
||||
} else {
|
||||
uistate.mousepressed[i] = 0;
|
||||
}
|
||||
if (uistate.mousedown[i])
|
||||
uistate.mouseframesdown[i]++;
|
||||
else
|
||||
uistate.mouseframesdown[i] = 0;
|
||||
|
||||
uistate.mousex[i] = x;
|
||||
uistate.mousey[i] = y;
|
||||
uistate.mousedown[i] = down;
|
||||
uistate.mousex[i] = x;
|
||||
uistate.mousey[i] = y;
|
||||
uistate.mousedown[i] = down;
|
||||
}
|
||||
|
||||
void UIReset() {
|
||||
@ -49,259 +49,265 @@ void UIReset() {
|
||||
}
|
||||
|
||||
bool UIRegionHit(int i, int x, int y, int w, int h, int margin) {
|
||||
// Input handling
|
||||
if (uistate.mousex[i] < x - margin ||
|
||||
uistate.mousey[i] < y - margin ||
|
||||
uistate.mousex[i] >= x + w + margin ||
|
||||
uistate.mousey[i] >= y + h + margin) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
// Input handling
|
||||
if (uistate.mousex[i] < x - margin ||
|
||||
uistate.mousey[i] < y - margin ||
|
||||
uistate.mousex[i] >= x + w + margin ||
|
||||
uistate.mousey[i] >= y + h + margin) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void UIBegin() {
|
||||
for (int i = 0; i < MAX_POINTERS; i++)
|
||||
uistate.hotitem[i] = 0;
|
||||
ui_draw2d.Begin();
|
||||
ui_draw2d_front.Begin();
|
||||
for (int i = 0; i < MAX_POINTERS; i++)
|
||||
uistate.hotitem[i] = 0;
|
||||
ui_draw2d.Begin();
|
||||
ui_draw2d_front.Begin();
|
||||
}
|
||||
|
||||
void UIEnd() {
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
if (uistate.mousedown[i] == 0) {
|
||||
uistate.activeitem[i] = 0;
|
||||
} else {
|
||||
if (uistate.activeitem[i] == 0) {
|
||||
uistate.activeitem[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_draw2d.End();
|
||||
ui_draw2d_front.End();
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
if (uistate.mousedown[i] == 0) {
|
||||
uistate.activeitem[i] = 0;
|
||||
} else {
|
||||
if (uistate.activeitem[i] == 0) {
|
||||
uistate.activeitem[i] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ui_draw2d.End();
|
||||
ui_draw2d_front.End();
|
||||
|
||||
if (uistate.ui_tick > 0)
|
||||
uistate.ui_tick--;
|
||||
if (uistate.ui_tick > 0)
|
||||
uistate.ui_tick--;
|
||||
}
|
||||
|
||||
void UIText(int x, int y, const char *text, uint32_t color, float scale, int align) {
|
||||
UIText(theme.uiFont, x, y, text, color, scale, align);
|
||||
UIText(theme.uiFont, x, y, text, color, scale, align);
|
||||
}
|
||||
|
||||
void UIText(int font, int x, int y, const char *text, uint32_t color, float scale, int align) {
|
||||
ui_draw2d.SetFontScale(scale, scale);
|
||||
ui_draw2d.DrawTextShadow(font, text, x, y, color, align);
|
||||
ui_draw2d.SetFontScale(1.0f, 1.0f);
|
||||
ui_draw2d.SetFontScale(scale, scale);
|
||||
ui_draw2d.DrawTextShadow(font, text, x, y, color, align);
|
||||
ui_draw2d.SetFontScale(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align) {
|
||||
float h = themeAtlas->images[theme.buttonImage].h;
|
||||
float h = themeAtlas->images[theme.buttonImage].h;
|
||||
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
|
||||
if (button_align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (button_align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (button_align & ALIGN_RIGHT) x -= w;
|
||||
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
if (button_align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (button_align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (button_align & ALIGN_RIGHT) x -= w;
|
||||
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
|
||||
int txOffset = 0;
|
||||
int txOffset = 0;
|
||||
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot, use a generous margin for touch ease
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) {
|
||||
uistate.activeitem[i] = id;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot, use a generous margin for touch ease
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) {
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Render button
|
||||
// Render button
|
||||
|
||||
ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w);
|
||||
ui_draw2d.DrawTextShadow(theme.uiFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w);
|
||||
ui_draw2d.DrawTextShadow(theme.uiFont, text, x + w/2, y + h/2 + txOffset, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
|
||||
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
}
|
||||
|
||||
int UIImageButton(int id, const LayoutManager &layout, float w, int image, int button_align) {
|
||||
float h = 64;
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
float h = 64;
|
||||
float x, y;
|
||||
layout.GetPos(&w, &h, &x, &y);
|
||||
|
||||
if (button_align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (button_align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (button_align & ALIGN_RIGHT) x -= w;
|
||||
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
if (button_align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (button_align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (button_align & ALIGN_RIGHT) x -= w;
|
||||
if (button_align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
|
||||
int txOffset = 0;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot, use a generous margin for touch ease
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
int txOffset = 0;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot, use a generous margin for touch ease
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active§
|
||||
}
|
||||
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Render button
|
||||
// Render button
|
||||
|
||||
ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w);
|
||||
ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w);
|
||||
ui_draw2d.DrawImage(image, x + w/2, y + h/2 + txOffset, 1.0f, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_VCENTER);
|
||||
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
}
|
||||
|
||||
|
||||
int UICheckBox(int id, int x, int y, const char *text, int align, bool *value) {
|
||||
const int h = 64;
|
||||
float tw, th;
|
||||
ui_draw2d.MeasureText(theme.uiFont, text, &tw, &th);
|
||||
int w = themeAtlas->images[theme.checkOn].w + UI_SPACE + tw;
|
||||
if (align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (align & ALIGN_RIGHT) x -= w;
|
||||
if (align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
const int h = 64;
|
||||
float tw, th;
|
||||
ui_draw2d.MeasureText(theme.uiFont, text, &tw, &th);
|
||||
int w = themeAtlas->images[theme.checkOn].w + UI_SPACE + tw;
|
||||
if (align & ALIGN_HCENTER) x -= w / 2;
|
||||
if (align & ALIGN_VCENTER) y -= h / 2;
|
||||
if (align & ALIGN_RIGHT) x -= w;
|
||||
if (align & ALIGN_BOTTOMRIGHT) y -= h;
|
||||
|
||||
int txOffset = 0;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
int txOffset = 0;
|
||||
int clicked = 0;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
|
||||
// Check whether the button should be hot
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
// Check whether the button should be hot
|
||||
if (UIRegionHit(i, x, y, w, h, 8)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
// Render button
|
||||
// Render button
|
||||
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
*value = !(*value);
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
if (uistate.hotitem[i] == id) {
|
||||
if (uistate.activeitem[i] == id) {
|
||||
// Button is both 'hot' and 'active'
|
||||
txOffset = 2;
|
||||
} else {
|
||||
// Button is merely 'hot'
|
||||
}
|
||||
} else {
|
||||
// button is not hot, but it may be active
|
||||
}
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked the button.
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id) {
|
||||
*value = !(*value);
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ui_draw2d.DrawImage((*value) ? theme.checkOn : theme.checkOff, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawTextShadow(theme.uiFont, text, x + themeAtlas->images[theme.checkOn].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawImage((*value) ? theme.checkOn : theme.checkOff, x, y+h/2, 1.0f, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawTextShadow(theme.uiFont, text, x + themeAtlas->images[theme.checkOn].w + UI_SPACE, y + txOffset + h/2, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
|
||||
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
uistate.lastwidget = id;
|
||||
return clicked;
|
||||
}
|
||||
|
||||
void StringVectorListAdapter::drawItem(int item, int x, int y, int w, int h, bool selected) const
|
||||
{
|
||||
ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w);
|
||||
ui_draw2d.DrawTextShadow(theme.uiFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
ui_draw2d.DrawImage2GridH(theme.buttonImage, x, y, x + w);
|
||||
ui_draw2d.DrawTextShadow(theme.uiFont, (*items_)[item].c_str(), x + UI_SPACE , y, 0xFFFFFFFF, ALIGN_LEFT | ALIGN_VCENTER);
|
||||
}
|
||||
|
||||
UIList::UIList()
|
||||
UIList::UIList()
|
||||
: scrollY(0.0f), startDragY(0.0f), dragFinger(-1), selected(-1) {
|
||||
movedDistanceY = 0.0f;
|
||||
|
||||
}
|
||||
|
||||
int UIList::Do(int id, int x, int y, int w, int h, UIListAdapter *adapter) {
|
||||
int clicked = 0;
|
||||
bool pointerDown = false;
|
||||
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check whether the button should be hot
|
||||
if (UIRegionHit(i, x, y, w, h, 0)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
// UIList only cares about the first pointer for simplicity.
|
||||
// Probably not much need to scroll one of these while dragging something
|
||||
// else.
|
||||
for (int i = 0; i < 1; i++) {
|
||||
// Check for hover
|
||||
if (UIRegionHit(i, x, y, w, h, 0)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i]) {
|
||||
// Mousedown
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
}
|
||||
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked a list item (unless after the last item).
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id &&
|
||||
selected != -1) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
// If button is hot and active, but mouse button is not
|
||||
// down, the user must have clicked a list item (unless after the last item).
|
||||
if (uistate.mousedown[i] == 0 &&
|
||||
uistate.hotitem[i] == id &&
|
||||
uistate.activeitem[i] == id &&
|
||||
selected != -1) {
|
||||
clicked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// render items
|
||||
int itemHeight = adapter->itemHeight(0);
|
||||
int numItems = adapter->getCount();
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
int item_y = y + i * itemHeight - scrollY;
|
||||
// render items
|
||||
int itemHeight = adapter->itemHeight(0);
|
||||
int numItems = adapter->getCount();
|
||||
for (int i = 0; i < numItems; i++) {
|
||||
int item_y = y + i * itemHeight - scrollY;
|
||||
|
||||
for (int k = 0; k < MAX_POINTERS; k++) {
|
||||
if (uistate.mousedown[k] &&
|
||||
uistate.mouseframesdown[k] > 10 &&
|
||||
adapter->itemEnabled(i) &&
|
||||
item_y >= y - itemHeight &&
|
||||
adapter->itemEnabled(i) &&
|
||||
item_y >= y - itemHeight &&
|
||||
item_y <= y + h &&
|
||||
UIRegionHit(k, x, item_y, w, itemHeight, 0)) {
|
||||
printf("%i", item_y);
|
||||
selected = i;
|
||||
}
|
||||
}
|
||||
adapter->drawItem(i, x, item_y, w, itemHeight, i == selected);
|
||||
}
|
||||
uistate.lastwidget = id;
|
||||
adapter->drawItem(i, x, item_y, w, itemHeight, i == selected);
|
||||
}
|
||||
uistate.lastwidget = id;
|
||||
|
||||
// Otherwise, no clicky.
|
||||
return clicked;
|
||||
// Otherwise, no clicky.
|
||||
return clicked;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -311,7 +317,7 @@ int image;
|
||||
uint32_t bgColor;
|
||||
};
|
||||
|
||||
struct SlideState
|
||||
struct SlideState
|
||||
{
|
||||
float scroll;
|
||||
|
||||
@ -323,49 +329,49 @@ void UISlideChoice(int id, int y, const SlideItem *items, int numItems, SlideSta
|
||||
|
||||
// TODO
|
||||
int UIHSlider(int id, int x, int y, int w, int max, int *value) {
|
||||
// Calculate mouse cursor's relative y offset
|
||||
int xpos = ((256 - 16) * *value) / max;
|
||||
// Calculate mouse cursor's relative y offset
|
||||
int xpos = ((256 - 16) * *value) / max;
|
||||
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check for hotness
|
||||
if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
// Check for hotness
|
||||
if (UIRegionHit(i, x+8, y+8, 16, 255, 0)) {
|
||||
uistate.hotitem[i] = id;
|
||||
if (uistate.activeitem[i] == 0 && uistate.mousedown[i])
|
||||
uistate.activeitem[i] = id;
|
||||
}
|
||||
|
||||
// Update widget value
|
||||
if (uistate.activeitem[i] == id) {
|
||||
int mousepos = uistate.mousey[i] - (y + 8);
|
||||
if (mousepos < 0) mousepos = 0;
|
||||
if (mousepos > 255) mousepos = 255;
|
||||
int v = (mousepos * max) / 255;
|
||||
if (v != *value) {
|
||||
*value = v;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Render the scrollbar
|
||||
ui_draw2d.Rect(x, y, 32, 256+16, 0x777777);
|
||||
// Update widget value
|
||||
if (uistate.activeitem[i] == id) {
|
||||
int mousepos = uistate.mousey[i] - (y + 8);
|
||||
if (mousepos < 0) mousepos = 0;
|
||||
if (mousepos > 255) mousepos = 255;
|
||||
int v = (mousepos * max) / 255;
|
||||
if (v != *value) {
|
||||
*value = v;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Render the scrollbar
|
||||
ui_draw2d.Rect(x, y, 32, 256+16, 0x777777);
|
||||
|
||||
ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff);
|
||||
ui_draw2d.Rect(x+8+xpos, y+8, 16, 16, 0xffffff);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
// TODO
|
||||
int UIVSlider(int id, int x, int y, int h, int max, int *value) {
|
||||
// Calculate mouse cursor's relative y offset
|
||||
int ypos = ((256 - 16) * *value) / max;
|
||||
// Calculate mouse cursor's relative y offset
|
||||
int ypos = ((256 - 16) * *value) / max;
|
||||
|
||||
// Check for hotness
|
||||
if (UIRegionHit(x+8, y+8, 16, 255, 0)) {
|
||||
uistate.hotitem = id;
|
||||
if (uistate.activeitem == 0 && uistate.mousedown)
|
||||
uistate.activeitem = id;
|
||||
}
|
||||
// Check for hotness
|
||||
if (UIRegionHit(x+8, y+8, 16, 255, 0)) {
|
||||
uistate.hotitem = id;
|
||||
if (uistate.activeitem == 0 && uistate.mousedown)
|
||||
uistate.activeitem = id;
|
||||
}
|
||||
// Update widget value
|
||||
if (uistate.activeitem == id) {
|
||||
int mousepos = uistate.mousey - (y + 8);
|
||||
@ -377,12 +383,12 @@ int UIVSlider(int id, int x, int y, int h, int max, int *value) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// Render the scrollbar
|
||||
ui_draw2d.Rect(x, y, 32, 256+16, 0x777777);
|
||||
|
||||
ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xffffff);
|
||||
// Render the scrollbar
|
||||
ui_draw2d.Rect(x, y, 32, 256+16, 0x777777);
|
||||
|
||||
|
||||
return 0;
|
||||
ui_draw2d.Rect(x+8, y+8 + ypos, 16, 16, 0xffffff);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
162
ui/ui.h
162
ui/ui.h
@ -31,84 +31,84 @@
|
||||
|
||||
class LayoutManager {
|
||||
public:
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const = 0;
|
||||
virtual void GetPos(float *w, float *h, float *x, float *y) const = 0;
|
||||
};
|
||||
|
||||
class Pos : public LayoutManager {
|
||||
public:
|
||||
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_;
|
||||
}
|
||||
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_;
|
||||
}
|
||||
private:
|
||||
float x_;
|
||||
float y_;
|
||||
float x_;
|
||||
float y_;
|
||||
};
|
||||
|
||||
class HLinear : public LayoutManager {
|
||||
public:
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable float x_;
|
||||
float y_;
|
||||
float spacing_;
|
||||
mutable float x_;
|
||||
float y_;
|
||||
float spacing_;
|
||||
};
|
||||
|
||||
class VLinear : public LayoutManager {
|
||||
public:
|
||||
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_;
|
||||
}
|
||||
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_;
|
||||
}
|
||||
|
||||
private:
|
||||
float x_;
|
||||
mutable float y_;
|
||||
float spacing_;
|
||||
float x_;
|
||||
mutable float y_;
|
||||
float spacing_;
|
||||
};
|
||||
|
||||
#ifndef MAX_POINTERS
|
||||
#define MAX_POINTERS 8
|
||||
#endif
|
||||
|
||||
// Mouse out of habit, applies just as well to touch events.
|
||||
// UI does not yet support multitouch.
|
||||
// "Mouse" out of habit, applies just as well to touch events.
|
||||
// TODO: Change to "pointer"
|
||||
// This struct is zeroed on init, so should be valid at that state.
|
||||
// Never inherit from this.
|
||||
struct UIState {
|
||||
int mousex[MAX_POINTERS];
|
||||
int mousey[MAX_POINTERS];
|
||||
bool mousedown[MAX_POINTERS];
|
||||
bool mousepressed[MAX_POINTERS];
|
||||
short mouseframesdown[MAX_POINTERS];
|
||||
int mousex[MAX_POINTERS];
|
||||
int mousey[MAX_POINTERS];
|
||||
bool mousedown[MAX_POINTERS];
|
||||
bool mousepressed[MAX_POINTERS];
|
||||
short mouseframesdown[MAX_POINTERS];
|
||||
|
||||
int mouseStartX[MAX_POINTERS];
|
||||
int mouseStartY[MAX_POINTERS];
|
||||
int mouseStartX[MAX_POINTERS];
|
||||
int mouseStartY[MAX_POINTERS];
|
||||
|
||||
int hotitem[MAX_POINTERS];
|
||||
int activeitem[MAX_POINTERS];
|
||||
int hotitem[MAX_POINTERS];
|
||||
int activeitem[MAX_POINTERS];
|
||||
|
||||
// keyboard focus, not currently used
|
||||
int kbdwidget;
|
||||
int lastwidget;
|
||||
// keyboard focus, not currently used
|
||||
int kbdwidget;
|
||||
int lastwidget;
|
||||
|
||||
// Used by controls that need to keep track of the initial value for drags, for example.
|
||||
// Should probably be indexed by finger - would be neat to be able to move two knobs at the same time.
|
||||
float tempfloat;
|
||||
// Used by controls that need to keep track of the initial value for drags, for example.
|
||||
// Should probably be indexed by finger - would be neat to be able to move two knobs at the same time.
|
||||
float tempfloat;
|
||||
|
||||
int ui_tick;
|
||||
int ui_tick;
|
||||
};
|
||||
|
||||
// This needs to be extern so that additional UI controls can be developed outside this file.
|
||||
@ -119,15 +119,15 @@ 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;
|
||||
extern DrawBuffer ui_draw2d_front; // for things that need to be on top of the rest
|
||||
extern DrawBuffer ui_draw2d_front; // for things that need to be on top of the rest
|
||||
|
||||
struct UITheme {
|
||||
int uiFont;
|
||||
int uiFontSmall;
|
||||
int uiFontSmaller;
|
||||
int buttonImage;
|
||||
int checkOn;
|
||||
int checkOff;
|
||||
int uiFont;
|
||||
int uiFontSmall;
|
||||
int uiFontSmaller;
|
||||
int buttonImage;
|
||||
int checkOn;
|
||||
int checkOff;
|
||||
};
|
||||
|
||||
// The atlas needs to stick around, the theme is copied.
|
||||
@ -143,32 +143,32 @@ const int LARGE_BUTTON_WIDTH = 192;
|
||||
const int BUTTON_HEIGHT = 72;
|
||||
|
||||
struct SlideItem {
|
||||
const char *text;
|
||||
int image;
|
||||
uint32_t bgColor;
|
||||
const char *text;
|
||||
int image;
|
||||
uint32_t bgColor;
|
||||
};
|
||||
|
||||
struct UISlideState {
|
||||
float scroll;
|
||||
float scroll;
|
||||
};
|
||||
|
||||
// Implement this interface to style your lists
|
||||
class UIListAdapter {
|
||||
public:
|
||||
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; }
|
||||
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; }
|
||||
};
|
||||
|
||||
class StringVectorListAdapter : public UIListAdapter {
|
||||
public:
|
||||
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;
|
||||
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;
|
||||
|
||||
private:
|
||||
const std::vector<std::string> *items_;
|
||||
const std::vector<std::string> *items_;
|
||||
};
|
||||
|
||||
|
||||
@ -185,7 +185,7 @@ void UIReset();
|
||||
|
||||
// Returns 1 if clicked
|
||||
int UIButton(int id, const LayoutManager &layout, float w, const char *text, int button_align);
|
||||
int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images.
|
||||
int UIImageButton(int id, const LayoutManager &layout, float w, int image_id, int button_align); // uses current UI atlas for fetching images.
|
||||
|
||||
// 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);
|
||||
@ -205,17 +205,23 @@ void UISlideChoice(int id, int y, const SlideItem *items, int numItems, UISlideS
|
||||
|
||||
|
||||
class UIList {
|
||||
public:
|
||||
UIList();
|
||||
float scrollY;
|
||||
float startDragY;
|
||||
int dragFinger;
|
||||
int selected;
|
||||
// List view.
|
||||
// return -1 = no selection
|
||||
int Do(int id, int x, int y, int w, int h, UIListAdapter *adapter);
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(UIList);
|
||||
public:
|
||||
UIList();
|
||||
|
||||
bool scrolling;
|
||||
int activePointer;
|
||||
float scrollY;
|
||||
float startDragY;
|
||||
float movedDistanceY;
|
||||
|
||||
int dragFinger;
|
||||
int selected;
|
||||
// List view.
|
||||
// return -1 = no selection
|
||||
int Do(int id, int x, int y, int w, int h, UIListAdapter *adapter);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(UIList);
|
||||
};
|
||||
|
||||
// Call at end of frame.
|
||||
|
@ -10,13 +10,13 @@ TouchButton::TouchButton(const Atlas *atlas, int imageIndex, int overlayImageInd
|
||||
memset(pointerDown, 0, sizeof(pointerDown));
|
||||
w_ = atlas_->images[imageIndex_].w;
|
||||
h_ = atlas_->images[imageIndex_].h;
|
||||
rotationAngle_ = (float)rotationAngle * 3.1415927 / 180.0f;
|
||||
isDown_ = false;
|
||||
rotationAngle_ = (float)rotationAngle * 3.1415927 / 180.0f;
|
||||
isDown_ = false;
|
||||
}
|
||||
|
||||
void TouchButton::update(InputState &input_state)
|
||||
{
|
||||
isDown_ = false;
|
||||
isDown_ = false;
|
||||
for (int i = 0; i < MAX_POINTERS; i++) {
|
||||
if (input_state.pointer_down[i] && isInside(input_state.pointer_x[i], input_state.pointer_y[i]))
|
||||
isDown_ = true;
|
||||
@ -31,12 +31,12 @@ void TouchButton::update(InputState &input_state)
|
||||
|
||||
void TouchButton::draw(DrawBuffer &db)
|
||||
{
|
||||
uint32_t color = 0xAAFFFFFF;
|
||||
float scale = 1.0f;
|
||||
if (isDown_) {
|
||||
color = 0xFFFFFFFF;
|
||||
scale = 2.0f;
|
||||
}
|
||||
uint32_t color = 0xAAFFFFFF;
|
||||
float scale = 1.0f;
|
||||
if (isDown_) {
|
||||
color = 0xFFFFFFFF;
|
||||
scale = 2.0f;
|
||||
}
|
||||
db.DrawImageRotated(imageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color);
|
||||
if (overlayImageIndex_ != -1)
|
||||
db.DrawImageRotated(overlayImageIndex_, x_ + w_/2, y_ + h_/2, scale, rotationAngle_, color);
|
||||
|
@ -37,16 +37,16 @@ private:
|
||||
float w_;
|
||||
float h_;
|
||||
|
||||
bool isDown_;
|
||||
bool isDown_;
|
||||
|
||||
// TODO: simplify into flags.
|
||||
bool pointerDown[MAX_POINTERS];
|
||||
};
|
||||
|
||||
|
||||
// Multi-touch enabled virtual joystick
|
||||
// Multi-touch enabled virtual joystick
|
||||
// (any finger will work, simultaneously with other virtual button/stick actions).
|
||||
class TouchStick
|
||||
class TouchStick
|
||||
{
|
||||
public:
|
||||
TouchStick(const Atlas *atlas, int bgImageIndex, int stickImageIndex, int stick);
|
||||
|
Loading…
Reference in New Issue
Block a user