Pie menus from feb

This commit is contained in:
jsalmon3 2004-05-23 19:16:32 +00:00
parent 6d37639d93
commit 191c85a63f
10 changed files with 292 additions and 31 deletions

View file

@ -894,6 +894,18 @@ FIXME
</dd>
</dl>
</dd>
<dt>"pie-menu", {tag, value, ...}</dt>
<dd>
<dl>
<dt>"radius", radius</dt>
<dd>The radius in pixels of the pie menu.</dd>
<dt>"file", "filename"</dt>
<dd>The image file for the background of the pie menu.</dd>
<dt>"mouse-button", "buttonname"</dt>
<dd>Which mouse button pops up the pie menu. Can be "right", "middle" or "left".
</dd>
</dl>
</dd>
<dt>"map-area", {"pos", {x, y}, size, {w, h}}</dt>
<dd>FIXME</dd>
<dt>"menu-panel", {tag, value}</dt>

View file

@ -166,6 +166,7 @@ typedef enum _cursor_states_ {
CursorStatePoint, ///< Normal cursor
CursorStateSelect, ///< Select position
CursorStateRectangle, ///< Rectangle selecting
CursorStatePieMenu, ///< Displaying Pie Menu
} CursorStates;
/*----------------------------------------------------------------------------

View file

@ -179,6 +179,7 @@ enum _key_modifiers_ {
/// pressed mouse button flags
enum _mouse_buttons_ {
NoButton = 0, ///< No button
LeftButton = 2, ///< Left button on mouse
MiddleButton = 4, ///< Middle button on mouse
RightButton = 8, ///< Right button on mouse
@ -390,6 +391,10 @@ extern void DrawTimer(void);
extern void UpdateTimer(void);
/// Draw the unit button panel
extern void DrawButtonPanel(void);
/// Update the status line with hints from the button
extern void UpdateStatusLineForButton(const ButtonAction*);
/// Draw the Pie Menu
extern void DrawPieMenu(void);
/// Update the content of the unit button panel
extern void UpdateButtonPanel(void);
/// Handle button click in button panel area

View file

@ -249,6 +249,12 @@ typedef struct _ui_ {
int ButtonPanelY; ///< Button panel screen Y position
int CommandKeyFont; ///< Command key font
// Pie Menu
GraphicConfig PieMenuBackground; ///< Optional background image for the piemenu
enum _mouse_buttons_ PieMouseButton; ///< Which mouse button pops up the piemenu. Deactivate with the NoButton value.
int PieX[8]; ///< X position of the pies
int PieY[8]; ///< Y position of the pies
// Map area
ViewportMode ViewportMode; ///< Current viewport mode
Viewport* MouseViewport; ///< Viewport containing mouse

View file

@ -376,6 +376,7 @@ global void UpdateDisplay(void)
DrawTimer();
}
DrawPieMenu(); // draw pie menu only if needed
DrawMenu(CurrentMenu);
DrawAnyCursor();

View file

@ -220,7 +220,6 @@ global void DrawButtonPanel(void)
int i;
int v;
Player* player;
const UnitStats* stats;
const ButtonAction* buttons;
char buf[8];
@ -351,29 +350,7 @@ global void DrawButtonPanel(void)
//
if (ButtonAreaUnderCursor == ButtonAreaButton &&
ButtonUnderCursor == i && KeyState != KeyStateInput) {
SetStatusLine(buttons[i].Hint);
// FIXME: Draw costs
v = buttons[i].Value;
switch (buttons[i].Action) {
case ButtonBuild:
case ButtonTrain:
case ButtonUpgradeTo:
// FIXME: store pointer in button table!
stats = &UnitTypes[v]->Stats[player->Player];
SetCosts(0, UnitTypes[v]->Demand, stats->Costs);
break;
case ButtonResearch:
SetCosts(0, 0, Upgrades[v].Costs);
break;
case ButtonSpellCast:
SetCosts(SpellTypeTable[v]->ManaCost, 0, NULL);
break;
default:
ClearCosts();
break;
}
UpdateStatusLineForButton(&buttons[i]);
}
//
@ -403,6 +380,39 @@ global void DrawButtonPanel(void)
}
}
/**
** Update the status line with hints from the button
**
** @param button Button
*/
global void UpdateStatusLineForButton(const ButtonAction* button)
{
int v;
const UnitStats* stats;
SetStatusLine(button->Hint);
// FIXME: Draw costs
v = button->Value;
switch (button->Action) {
case ButtonBuild:
case ButtonTrain:
case ButtonUpgradeTo:
// FIXME: store pointer in button table!
stats = &UnitTypes[v]->Stats[ThisPlayer->Player];
SetCosts(0, UnitTypes[v]->Demand, stats->Costs);
break;
case ButtonResearch:
SetCosts(0, 0, Upgrades[v].Costs);
break;
case ButtonSpellCast:
SetCosts(SpellTypeTable[v]->ManaCost, 0, NULL);
break;
default:
ClearCosts();
break;
}
}
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/

View file

@ -347,7 +347,7 @@ global const char* IdentOfIcon(const Icon* icon)
global void DrawIcon(const Player* player, Icon* icon, int x, int y)
{
GraphicPlayerPixels(player, icon->Sprite);
VideoDraw(icon->Sprite, icon->Index, x, y);
VideoDrawClip(icon->Sprite, icon->Index, x, y);
}
/**

View file

@ -30,12 +30,16 @@
//@{
#define ICON_SIZE_X (TheUI.ButtonButtons[0].Width)
#define ICON_SIZE_Y (TheUI.ButtonButtons[0].Height)
/*----------------------------------------------------------------------------
-- Includes
----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "stratagus.h"
#include "tileset.h"
@ -78,6 +82,7 @@ global enum _cursor_on_ CursorOn = CursorOnUnknown; /// Cursor on field
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
local void HandlePieMenuMouseSelection(void);
/**
** Cancel building cursor mode.
@ -657,6 +662,23 @@ global void UIHandleMouseMove(int x, int y)
return;
}
if (CursorState == CursorStatePieMenu && CursorOn == CursorOnMap) {
// in the map area
// make the piemenu "follow" the mouse
if (CursorX - CursorStartX > TheUI.PieX[2]) {
CursorStartX = CursorX - TheUI.PieX[2];
}
if (CursorStartX - CursorX > TheUI.PieX[2]) {
CursorStartX = CursorX + TheUI.PieX[2];
}
if (CursorStartY - CursorY > TheUI.PieY[4]) {
CursorStartY = CursorY + TheUI.PieY[4];
}
if (CursorY - CursorStartY > TheUI.PieY[4]) {
CursorStartY = CursorY - TheUI.PieY[4];
}
}
//
// Move map.
//
@ -1320,6 +1342,7 @@ local void UISelectStateButtonDown(unsigned button __attribute__((unused)))
UpdateButtonPanel();
}
/**
** Called if mouse button pressed down.
**
@ -1374,6 +1397,16 @@ global void UIHandleButtonDown(unsigned button)
return;
}
if (CursorState == CursorStatePieMenu) {
if (CursorOn == CursorOnMap) {
HandlePieMenuMouseSelection();
} else {
// Pie Menu canceled
CursorState = CursorStatePoint;
}
return;
}
//
// Cursor is on the map area
//
@ -1431,7 +1464,15 @@ global void UIHandleButtonDown(unsigned button)
return;
}
if (MouseButtons & LeftButton) { // enter select mode
if (MouseButtons & TheUI.PieMouseButton) { // enter pie menu
CursorStartX = CursorX;
CursorStartY = CursorY;
if (NumSelected && Selected[0]->Player == ThisPlayer &&
CursorState == CursorStatePoint) {
CursorState = CursorStatePieMenu;
MustRedraw |= RedrawCursor;
}
} else if (MouseButtons & LeftButton) { // enter select mode
CursorStartX = CursorX;
CursorStartY = CursorY;
CursorStartScrMapX = CursorStartX - TheUI.MouseViewport->X +
@ -1458,8 +1499,8 @@ global void UIHandleButtonDown(unsigned button)
y = Viewport2MapY(TheUI.MouseViewport, CursorY);
if (UnitUnderCursor && (unit = UnitOnMapTile(x, y)) &&
!UnitUnderCursor->Type->Decoration) {
unit->Blink = 4; // if right click on building -- blink
!UnitUnderCursor->Type->Decoration) {
unit->Blink = 4; // if right click on building -- blink
} else { // if not not click on building -- green cross
if (ClickMissile) {
MakeLocalMissile(MissileTypeByIdent(ClickMissile),
@ -1525,7 +1566,7 @@ global void UIHandleButtonDown(unsigned button)
if (ButtonUnderCursor == 0 && NumSelected == 1) {
PlayGameSound(GameSounds.Click.Sound, MaxSampleVolume);
ViewportCenterViewpoint(TheUI.SelectedViewport, Selected[0]->X,
Selected[0]->Y, Selected[0]->IX + TileSizeX / 2,
Selected[0]->Y, Selected[0]->IX + TileSizeX / 2,
Selected[0]->IY + TileSizeY / 2);
}
//
@ -1559,7 +1600,7 @@ global void UIHandleButtonDown(unsigned button)
// clicked on researching button
//
} else if (ButtonAreaUnderCursor == ButtonAreaResearching) {
if (!GameObserve && !GamePaused &&
if (!GameObserve && !GamePaused &&
PlayersTeamed(ThisPlayer->Player, Selected[0]->Player->Player)) {
if (ButtonUnderCursor == 0 && NumSelected == 1) {
DebugPrint("Cancel research %s\n" _C_
@ -1628,6 +1669,18 @@ global void UIHandleButtonUp(unsigned button)
return;
}
//
// Pie Menu
//
if (CursorState == CursorStatePieMenu) {
if (CursorStartX == CursorX && CursorStartY == CursorY) {
// no move; wait for a click to select the pie
} else {
// there was a move, handle the selected button/pie
HandlePieMenuMouseSelection();
}
}
//
// Menu (F10) button
//
@ -1797,7 +1850,7 @@ global void UIHandleButtonUp(unsigned button)
if (Selected[0]->Player == ThisPlayer) {
char buf[64];
if (Selected[0]->Player->UnitTypesCount[Selected[0]->Type->Slot] > 1) {
sprintf(buf, "You have ~<%d~> %ss",
sprintf(buf, "You have ~<%d~> %ss",
Selected[0]->Player->UnitTypesCount[Selected[0]->Type->Slot],
Selected[0]->Type->Name);
} else {
@ -1817,4 +1870,118 @@ global void UIHandleButtonUp(unsigned button)
}
}
/**
** Get pie menu under the cursor
*/
local int GetPieUnderCursor(void)
{
int i;
int x;
int y;
x = CursorX - (CursorStartX - ICON_SIZE_X / 2);
y = CursorY - (CursorStartY - ICON_SIZE_Y / 2);
for (i = 0; i < 8; ++i) {
if (x > TheUI.PieX[i] && x < TheUI.PieX[i] + ICON_SIZE_X &&
y > TheUI.PieY[i] && y < TheUI.PieY[i] + ICON_SIZE_Y) {
return i;
}
}
return -1; // no pie under cursor
}
/**
** Draw Pie Menu
*/
global void DrawPieMenu(void)
{
int i;
const ButtonAction* buttons;
Viewport* vp;
Player* player;
char buf[2] = "?";
if(CursorState != CursorStatePieMenu)
return;
if (!(buttons = CurrentButtons)) { // no buttons
CursorState = CursorStatePoint;
return;
}
vp = TheUI.SelectedViewport;
PushClipping();
SetClipping(vp->X, vp->Y, vp->EndX, vp->EndY);
// Draw background
if (TheUI.PieMenuBackground.Graphic) {
VideoDrawClip(TheUI.PieMenuBackground.Graphic, 0,
CursorStartX - TheUI.PieMenuBackground.Graphic->Width / 2,
CursorStartY - TheUI.PieMenuBackground.Graphic->Height / 2);
}
player = Selected[0]->Player;
for (i = 0; i < TheUI.NumButtonButtons && i < 8; ++i) {
if (buttons[i].Pos != -1) {
int x;
int y;
x = CursorStartX - ICON_SIZE_X / 2 + TheUI.PieX[i];
y = CursorStartY - ICON_SIZE_Y / 2 + TheUI.PieY[i];
// Draw icon
DrawIcon(player, buttons[i].Icon.Icon, x, y);
// Tutorial show command key in icons
if (ShowCommandKey) {
char* text;
if (CurrentButtons[i].Key == 27) {
text = "ESC";
} else {
buf[0] = toupper(CurrentButtons[i].Key);
text = buf;
}
VideoDrawText(x + 4, y + 4, GameFont, text);
}
}
}
PopClipping();
i = GetPieUnderCursor();
if (i != -1 && KeyState != KeyStateInput && buttons[i].Pos!=-1) {
UpdateStatusLineForButton(&buttons[i]);
}
}
/**
** Handle pie menu mouse selection
*/
local void HandlePieMenuMouseSelection(void)
{
int pie;
if (!CurrentButtons) { // no buttons
return;
}
pie = GetPieUnderCursor();
if (pie != -1) {
if (CurrentButtons[pie].Action == ButtonButton) {
// there is a submenu => stay in piemenu mode
// and recenter the piemenu around the cursor
CursorStartX = CursorX;
CursorStartY = CursorY;
} else {
CursorState = CursorStatePoint;
}
DoButtonButtonClicked(pie);
} else {
CursorState = CursorStatePoint;
}
return;
}
//@}

View file

@ -1574,6 +1574,57 @@ local int CclDefineUI(lua_State* l)
LuaError(l, "Unsupported tag: %s" _C_ value);
}
}
} else if (!strcmp(value, "piemenu")) {
k = 0;
if (!lua_istable(l, j + 1)) {
lua_pushstring(l, "incorrect argument");
lua_error(l);
}
subargs = luaL_getn(l, j + 1);
for (k = 0; k < subargs; ++k) {
lua_rawgeti(l, j + 1, k + 1);
value = LuaToString(l, -1);
lua_pop(l, 1);
++k;
if (!strcmp(value, "file")) {
lua_rawgeti(l, j + 1, k + 1);
ui->PieMenuBackground.File = strdup(LuaToString(l, -1));
lua_pop(l, 1);
} else if (!strcmp(value, "radius")) {
// Position of the pies in a piemenu
int coeffX[] = { 0, 193, 256, 193, 0, -193, -256, -193};
int coeffY[] = { -256, -193, 0, 193, 256, 193, 0, -193};
int pie;
int radius;
lua_rawgeti(l, j + 1, k + 1);
radius = LuaToNumber(l, -1);
lua_pop(l, 1);
for (pie = 0; pie < 8; ++pie) {
ui->PieX[pie]= (coeffX[pie] * radius) >> 8;
ui->PieY[pie]= (coeffY[pie] * radius) >> 8;
}
} else if (!strcmp(value, "mouse-button")) {
const char *button;
lua_rawgeti(l, j + 1, k + 1);
button = LuaToString(l, -1);
if (!strcmp(button, "right")) {
ui->PieMouseButton = RightButton;
} else if (!strcmp(button, "middle")) {
ui->PieMouseButton = MiddleButton;
} else if (!strcmp(button, "left")) {
ui->PieMouseButton = LeftButton;
} else {
ui->PieMouseButton = NoButton;
}
lua_pop(l, 1);
} else {
lua_pushfstring(l, "Unsupported tag: %s", value);
lua_error(l);
}
}
lua_pop(l, 1);
} else if (!strcmp(value, "map-area")) {
int w;
int h;

View file

@ -99,6 +99,7 @@ local void CleanUIGraphics(UI* ui)
VideoSafeFree(ui->MenuPanel.Graphic);
VideoSafeFree(ui->MinimapPanel.Graphic);
VideoSafeFree(ui->StatusLine.Graphic);
VideoSafeFree(ui->PieMenuBackground.Graphic);
menupanel = ui->MenuPanels;
while (menupanel) {
@ -238,6 +239,10 @@ global void LoadUserInterface(void)
if (TheUI.ButtonPanel.File) {
TheUI.ButtonPanel.Graphic = LoadGraphic(TheUI.ButtonPanel.File);
}
if (TheUI.PieMenuBackground.File) {
TheUI.PieMenuBackground.Graphic =
LoadGraphic(TheUI.PieMenuBackground.File);
}
if (TheUI.MenuPanel.File) {
TheUI.MenuPanel.Graphic = LoadGraphic(TheUI.MenuPanel.File);
}
@ -362,6 +367,9 @@ global void CleanUI(UI* ui)
// Menu Button
free(ui->MenuPanel.File);
// Pie Menu
free(ui->PieMenuBackground.File);
// Minimap
free(ui->MinimapPanel.File);