r664 - trunk/game
spike at icculus.org
spike at icculus.org
Tue Mar 7 21:30:28 EST 2006
Author: spike
Date: 2006-03-07 21:30:28 -0500 (Tue, 07 Mar 2006)
New Revision: 664
Modified:
trunk/game/m_menucore.c
trunk/game/m_menucore.h
Log:
Added editable(edit) items and List-Of-Values(combo) menu item types. Added test/demo items to the main menu.
Modified: trunk/game/m_menucore.c
===================================================================
--- trunk/game/m_menucore.c 2006-03-08 02:19:29 UTC (rev 663)
+++ trunk/game/m_menucore.c 2006-03-08 02:30:28 UTC (rev 664)
@@ -115,6 +115,10 @@
if (thisi->parent->selecteditem == item)
thisi->parent->selecteditem = NULL;
Menu_RemoveFromParent(item);
+
+ if (Menu.grabs == item)
+ Menu.grabs = NULL; //hrm.
+
Mem_Free(&item);
}
Menu_Item *Menu_CreateGenericItem(Menu_SubMenu *parent, int x, int y, int bytes)
@@ -153,18 +157,23 @@
R_SetTexture(R.resource_font);
R_DrawString(thisi->text, 0, thisi->super.pos[0] + inh->addpos[0], thisi->super.pos[1] + inh->addpos[1], 8, 8, Console_DefaultColorTable, Console_DefaultColorTableSize, thisi->super.parent->selecteditem == &thisi->super);
}
+void Menu_Text_DefaultUse (struct Menu_TextItem *item)
+{
+ Shell_ExecuteScript("console", item->command);
+}
Nbool Menu_Text_KeyPress (void *item, UNUSED NUint mod, NUint sym, UNUSED NUint character, Nbool downevent)
{
Menu_TextItem *thisi = item;
if (sym == SDLK_RETURN || sym == MOUSE1)
{
if (downevent)
- Shell_ExecuteScript("console", thisi->command);
+ if (thisi->UseTextItem)
+ thisi->UseTextItem(thisi);
return true;
}
return false;
}
-Menu_TextItem *Menu_CreateTextItem(Menu_SubMenu *parent, int x, int y, char *text, char *command)
+Menu_TextItem *Menu_CreateTextItem(Menu_SubMenu *parent, int x, int y, char *text, void *command, void (*UseTextItem) (struct Menu_TextItem *item))
{
Menu_TextItem *it;
it = (Menu_TextItem*)Menu_CreateGenericItem(parent, x, y, sizeof(Menu_TextItem));
@@ -181,17 +190,276 @@
it->text = text;
it->command = command;
+ if (UseTextItem == NULL && command)
+ UseTextItem = Menu_Text_DefaultUse;
+
+ it->UseTextItem = UseTextItem;
+
return it;
}
+//text-edit fields
+//fixme: only work with grabs?
+void Menu_DrawEditItem(void *item, Menu_Inheritance *inh)
+{
+ Menu_EditItem *thisi = item;
+ R_SetBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ R_SetTexture(R.resource_font);
+ R_DrawString(thisi->text, 0, thisi->super.pos[0] + inh->addpos[0], thisi->super.pos[1] + inh->addpos[1], 8, 8, Console_DefaultColorTable, Console_DefaultColorTableSize, thisi->super.parent->selecteditem == &thisi->super);
+ if (thisi->super.parent->selecteditem == &thisi->super)
+ R_DrawString("_", 0, thisi->super.pos[0] + inh->addpos[0] + thisi->cursorpos*8, thisi->super.pos[1] + inh->addpos[1], 8, 8, Console_DefaultColorTable, Console_DefaultColorTableSize, 0);
+}
+Nbool Menu_Edit_KeyPress (void *item, UNUSED NUint mod, NUint sym, NUint character, Nbool downevent)
+{
+ Menu_EditItem *thisi = item;
+ if (sym == SDLK_RETURN || sym == MOUSE1)
+ {
+// if (downevent)
+// Shell_ExecuteScript("console", thisi->command);
+ return true;
+ }
+ if (sym == SDLK_BACKSPACE)
+ {
+ if (!downevent)
+ return true;
+ if (!thisi->cursorpos)
+ {
+ if (*thisi->text)
+ thisi->cursorpos = 1;
+ else
+ return true;
+ }
+ memmove(thisi->text+thisi->cursorpos-1, thisi->text+thisi->cursorpos, strlen(thisi->text+thisi->cursorpos)+1);
+ thisi->cursorpos--;
+ return true;
+ }
+ if (sym == SDLK_HOME)
+ {
+ thisi->cursorpos = 0;
+ return true;
+ }
+ if (sym == SDLK_END)
+ {
+ thisi->cursorpos = strlen(thisi->text);
+ return true;
+ }
+ if (sym == SDLK_LEFT)
+ {
+ thisi->cursorpos -= downevent;
+ if (thisi->cursorpos < 0)
+ thisi->cursorpos = 0;
+ return true;
+ }
+ if (sym == SDLK_RIGHT)
+ {
+ thisi->cursorpos += downevent;
+ if (thisi->cursorpos > strlen(thisi->text))
+ thisi->cursorpos = strlen(thisi->text);
+ return true;
+ }
+ if (character && character != SDLK_TAB)
+ {
+ char *newt;
+ if (!downevent)
+ return true;
+ if (thisi->maxchars && thisi->maxchars <= strlen(thisi->text))
+ return true; //already reached the max
+ newt = Mem_Alloc(Menu.menu_zone, strlen(thisi->text)+2);
+ memcpy(newt, thisi->text, thisi->cursorpos);
+ memcpy(newt+thisi->cursorpos+1, thisi->text+thisi->cursorpos, strlen(thisi->text+thisi->cursorpos)+1);
+ newt[thisi->cursorpos] = character;
+ Mem_Free(&thisi->text);
+ thisi->text = newt;
+
+ thisi->cursorpos++;
+ return true;
+ }
+ return false;
+}
+Menu_EditItem *Menu_CreateEditItem(Menu_SubMenu *parent, int x, int y, char *text)
+{
+ Menu_EditItem *it;
+ it = (Menu_EditItem*)Menu_CreateGenericItem(parent, x, y, sizeof(Menu_EditItem));
+
+ it->super.DrawMenu = Menu_DrawEditItem;
+ it->super.MouseMove = Menu_Generic_MouseMoveSelectable;
+ it->super.KeyEvent = Menu_Edit_KeyPress;
+ it->super.size[0] = 8*strlen(text);
+ it->super.size[1] = 8;
+
+ //FIXME: No delete to free the text
+ it->text = Mem_Alloc(Menu.menu_zone, strlen(text)+1);
+ strcpy(it->text, text);
+ it->cursorpos = strlen(text);
+// it->command = command;
+
+ return it;
+}
+
+
+
+
+
+
+
+
+
+
+//combos
+void Menu_DrawComboItem(void *item, Menu_Inheritance *inh)
+{
+ Menu_ComboItem *thisi = item;
+ R_SetBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ R_SetTexture(R.resource_font);
+ R_DrawString(thisi->text, 0, thisi->super.pos[0] + inh->addpos[0], thisi->super.pos[1] + inh->addpos[1], 8, 8, Console_DefaultColorTable, Console_DefaultColorTableSize, thisi->super.parent->selecteditem == &thisi->super);
+
+ R_DrawString("V", 0, thisi->super.pos[0] + thisi->super.size[0]-8 + inh->addpos[0], thisi->super.pos[1] + inh->addpos[1], 8, 8, Console_DefaultColorTable, Console_DefaultColorTableSize, thisi->super.parent->selecteditem == &thisi->super);
+}
+
+void Menu_Combo_SetText(Menu_ComboItem *thisi, char *text)//it's just easier. not sure weather this should be public or not.
+{
+ Menu_ComboOption *option;
+ char *oldtext;
+ oldtext = thisi->text;
+ thisi->text = Mem_Alloc(Menu.menu_zone, strlen(text)+1);
+ strcpy(thisi->text, text);
+
+ thisi->selected = NULL;
+ for (option = thisi->options; option; option = option->next)
+ {
+ if (!strcmp(option->text, text))
+ {
+ thisi->selected = option;
+ break;
+ }
+ }
+
+ Mem_Free(&oldtext);
+}
+
+void Menu_ComboSlider (struct Menu_SliderItem *slider)
+{
+ Menu_SubMenu *thisi = slider->data;
+ thisi->subwindow.pos[1] = -slider->value;
+}
+void Menu_UseOption (Menu_TextItem *it)
+{
+ Menu_ComboItem *thisi = (void*)it->command;
+ Menu_Combo_SetText(thisi, it->text);
+
+ //seeing as this happens from a key event, and the text control will return true, we can safly kill the popup
+ thisi->popup->super.Destroy(thisi->popup);
+}
+
+
+Nbool Menu_Combo_KeyPress (void *item, UNUSED NUint mod, UNUSED NUint sym, UNUSED NUint character, UNUSED Nbool downevent)
+{
+ int i;
+ Menu_TextItem *txt;
+ Menu_ComboItem *thisi = item;
+ Menu_ComboOption *option;
+ Menu_SubMenu *interior;
+ int pixels;
+ if (sym == SDLK_RETURN || sym == MOUSE1)
+ {
+ thisi->popup = Menu_CreateMenu(&Menu.rootmenu);
+ Menu_BringToFront(thisi->popup);
+ interior = Menu_CreateMenu(thisi->popup);
+ interior->allowclose = false;
+ Menu.grabs = &thisi->popup->super;
+ option = thisi->options;
+ for (i = 0; option; i+=8, option = option->next)
+ {
+ txt = Menu_CreateTextItem(interior, 0, i, option->text, thisi, Menu_UseOption);
+ txt->super.size[0] = thisi->super.size[0] - 8;
+ }
+ pixels = i-64;
+ if (pixels < 0)
+ pixels = 0;
+ Menu_CreateVSliderItem(thisi->popup, thisi->super.size[0] - 8, 0, 8, ((i>64)?64:i), 0, pixels, 0, Menu_ComboSlider, NULL, interior);
+
+ thisi->popup->super.pos[0] = Input.mouse[0];
+ thisi->popup->super.pos[1] = Input.mouse[1];
+
+ thisi->popup->subwindow.pos[0] = thisi->popup->super.pos[0];
+ thisi->popup->subwindow.pos[1] = thisi->popup->super.pos[1];
+ Menu_FinishMenu(interior);
+ interior->super.size[1] = ((i>64)?64:i);
+ Menu_FinishMenu(thisi->popup);
+ return true;
+ }
+ return false;
+}
+
+void Menu_Combo_Destroy(void *item)
+{
+ Menu_ComboItem *combo = item;
+ if (combo->popup)
+ combo->popup->super.Destroy(combo->popup);
+ Menu_Generic_Destroy(item);
+}
+
+Menu_ComboItem *Menu_CreateComboItem(Menu_SubMenu *parent, int x, int y, int w, char *defalt, char *list)
+{
+ char *pipe;
+ int chars;
+ int ident;
+ Menu_ComboOption *option;
+ //list is pipe-sperated
+ Menu_ComboItem *it;
+ it = (Menu_ComboItem*)Menu_CreateGenericItem(parent, x, y, sizeof(Menu_ComboItem));
+
+ it->super.DrawMenu = Menu_DrawComboItem;
+ it->super.MouseMove = Menu_Generic_MouseMoveSelectable;
+ it->super.KeyEvent = Menu_Combo_KeyPress;
+ it->super.Destroy = Menu_Combo_Destroy;
+ it->super.size[0] = w;
+ it->super.size[1] = 8;
+
+ //FIXME: no delete to free the text
+ it->text = Mem_Alloc(Menu.menu_zone, strlen(defalt)+1);
+ strcpy(it->text, defalt);
+
+ if (*list)
+ {
+ ident = 0;
+ for (pipe = list; ; pipe++)
+ {
+ if (*pipe == '|' || *pipe == '\0')
+ {
+ chars = pipe - list;
+
+ option = Mem_Alloc(Menu.menu_zone, sizeof(Menu_ComboOption) + chars+1);
+ option->text = (char*)(option+1);
+ option->ident = ident++;
+ strncpy(option->text, list, chars);
+ option->text[chars] = '\0';
+ option->next = it->options;
+ it->options = option;
+
+ if (*pipe == '\0')
+ break;
+ pipe++;
+ list = pipe;
+ }
+ }
+ }
+
+ return it;
+}
+
+
+
+
+
//picture items
void Menu_Picture_Draw(void *item, Menu_Inheritance *inh)
{
@@ -427,7 +695,7 @@
int j;
int wmin, wmax;
- if (Menu.grabs == &thisi->super)
+ if (Menu.grabs == &thisi->super && thisi->dragable)
{
thisi->subwindow.pos[0] += Input.mouse[0] - thisi->dragmousepos[0];
thisi->subwindow.pos[1] += Input.mouse[1] - thisi->dragmousepos[1];
@@ -478,7 +746,7 @@
void Menu_DrawSubMenu(void *item, Menu_Inheritance *inh)
{
Menu_SubMenu *thisi = item;
- Menu_Item *subitem;
+ Menu_Item *subitem, *next;
Menu_Inheritance ninh;
int wmin, wmax;
int j;
@@ -507,8 +775,11 @@
R_SetScissor(ninh.window.pos[0], ninh.window.pos[1], ninh.window.size[0], ninh.window.size[1]);
- for (subitem = thisi->subitems; subitem; subitem = subitem->next)
+ for (subitem = thisi->subitems; subitem; subitem = next)
+ {
+ next = subitem->next;//this funkyness is so that we can unlink and kill things in the draw function (if the need arises).
subitem->DrawMenu(subitem, &ninh);
+ }
R_SetScissor(inh->window.pos[0], inh->window.pos[1], inh->window.size[0], inh->window.size[1]);
}
@@ -637,41 +908,52 @@
void Menu_ArrangeSubItems(Menu_SubMenu *menu, Nbool horizontal, int pad, Menu_ArrangeStyle arrange)
{
Menu_Item *sitem;
- int side;
+ int axis, otheraxis;
int val = 0;
int maxval=0;
+ //axis is usually the 'vertical' axis, where each field is spaced with padding
+ //otheraxis is the axis on which we align stuff (rather than just space it)
+
if (horizontal)
- side = 0;
+ axis = 0;
else
- side = 1;
+ axis = 1;
+ otheraxis = !axis;
+
for (sitem = menu->subitems; sitem; sitem = sitem->next)
{
- sitem->pos[side] = maxval;
- maxval += sitem->size[side] + pad;
+ sitem->pos[axis] = maxval;
+ maxval += sitem->size[axis] + pad;
}
val = maxval;
for (sitem = menu->subitems; sitem; sitem = sitem->next)
{
- val -= sitem->size[side] + pad;
- sitem->pos[side] = val;
+ val -= sitem->size[axis] + pad;
+ sitem->pos[axis] = val;
switch(arrange)
{
+ case MENU_ARRANGESTYLE_LEAVEALONE:
+ break;
+
case MENU_ARRANGESTYLE_LEFT:
- sitem->pos[side^1] = 0;
+ sitem->pos[otheraxis] = 0;
break;
+
case MENU_ARRANGESTYLE_CENTER:
- sitem->pos[side^1] = (menu->subwindow.size[side^1] - sitem->size[side^1])/2;
+ sitem->pos[otheraxis] = (menu->subwindow.size[otheraxis] - sitem->size[otheraxis])/2;
break;
+
case MENU_ARRANGESTYLE_RIGHT:
- sitem->pos[side^1] = (menu->subwindow.size[side^1] - sitem->size[side^1]);
+ sitem->pos[otheraxis] = (menu->subwindow.size[otheraxis] - sitem->size[otheraxis]);
break;
+
case MENU_ARRANGESTYLE_RESIZE:
- sitem->pos[side^1] = 0;
- sitem->size[side^1] = menu->subwindow.size[side^1];
+ sitem->pos[otheraxis] = 0;
+ sitem->size[otheraxis] = menu->subwindow.size[otheraxis];
break;
}
}
@@ -708,6 +990,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
float sliderscale = 8;
float imagesize = 512;
float windowsize = 128;
@@ -782,17 +1077,20 @@
Menu_SubMenu *menu = Menu_CreateMenu(&Menu.rootmenu);
menu->dragable = true;
- Menu_CreateTextItem(menu, 0, 0, "Main menu", NULL);
+ Menu_CreateTextItem(menu, 0, 0, "Main menu", NULL, NULL);
- Menu_CreateTextItem(menu, 0, 16, "Hello World", "echo Hello World\n");
- Menu_CreateTextItem(menu, 0, 24, "Start up test map", "map test\n");
- Menu_CreateTextItem(menu, 0, 32, "Go to the west!", "map west\n");
- Menu_CreateTextItem(menu, 0, 40, "quit", "menu_quit\n");
+ Menu_CreateTextItem(menu, 0, 16, "Hello World", "echo Hello World\n", NULL);
+ Menu_CreateTextItem(menu, 0, 24, "Start up test map", "map test\n", NULL);
+ Menu_CreateTextItem(menu, 0, 32, "Go to the west!", "map west\n", NULL);
+ Menu_CreateTextItem(menu, 0, 40, "quit", "menu_quit\n", NULL);
- Menu_CreateTextItem(menu, 0, 56, "Close menu", "menu_close\n");
+ Menu_CreateTextItem(menu, 0, 56, "Close menu", "menu_close\n", NULL);
- Menu_CreateTextItem(menu, 0, 56+16, "test menu", "menu_test\n");
+ Menu_CreateTextItem(menu, 0, 56+16, "test menu", "menu_test\n", NULL);
+ Menu_CreateEditItem(menu, 0, 56, "EditItem");
+ Menu_CreateComboItem(menu, 0, 56, 21*8, "ComboItem", "Option 1|Option 2|Option 3|Fuzzy Little Bunnies|Big Rocket Launcher|Children|Lightning Gun|Newborn Chicks|Grenade Launcher|Rodents|Nukes");
+
Menu_FinishMenu(menu);
Menu_ArrangeSubItems(menu, false, 0, MENU_ARRANGESTYLE_CENTER);
Menu_FinishMenu(menu);
@@ -833,10 +1131,10 @@
Menu_SubMenu *menu = Menu_CreateMenu(&Menu.rootmenu);
menu->dragable = true;
- Menu_CreateTextItem(menu, 0, 0, "Really Quit?", NULL);
+ Menu_CreateTextItem(menu, 0, 0, "Really Quit?", NULL, NULL);
- Menu_CreateTextItem(menu, 0, 16, "Yes, and wipe my harddrive too.", "quit\n");
- Menu_CreateTextItem(menu, 0, 24, "No. I want to keep playing this awesome game", "menu_close\n");
+ Menu_CreateTextItem(menu, 0, 16, "Yes, and wipe my harddrive too.", "quit\n", NULL);
+ Menu_CreateTextItem(menu, 0, 24, "No. I want to keep playing this awesome game", "menu_close\n", NULL);
Menu_FinishMenu(menu);
Modified: trunk/game/m_menucore.h
===================================================================
--- trunk/game/m_menucore.h 2006-03-08 02:19:29 UTC (rev 663)
+++ trunk/game/m_menucore.h 2006-03-08 02:30:28 UTC (rev 664)
@@ -54,17 +54,55 @@
{
Menu_Item super;
- char *text;
- char *command; //it's handy
+ char *text; //what to display (warning: it's a pointer, isn't freed, and isn't copied)
+ void *command; //command is a misnomer, it should be used as a cookie for the text item
+
+ void (*UseTextItem) (struct Menu_TextItem *item); //called when the user uses this item
}
Menu_TextItem;
+typedef struct Menu_EditItem
+{
+ Menu_Item super;
+
+ char *text; //what it currently says
+ int cursorpos; //where the cursor is, set between 0 and strlen(text)
+ int scrollpos; //fixme
+ int maxchars; //0 for unlimited
+}
+Menu_EditItem;
+
+typedef struct Menu_ComboOption
+{
+ char *text; //the text of the item
+ int ident; //if you wish to assosiate an int key with the item.
+ struct Menu_ComboOption *next;
+}
+Menu_ComboOption;
+
+typedef struct Menu_ComboItem
+{
+ Menu_Item super;
+
+ Nbool editable; //user may type into the control
+ struct Menu_ComboOption *options; //a list of the current options
+ struct Menu_ComboOption *selected; //set
+
+ char *text;
+ int cursorpos;
+ int scrollpos;
+ int maxchars;
+
+ struct Menu_SubMenu *popup;
+}
+Menu_ComboItem;
+
typedef struct Menu_PictureItem
{
Menu_Item super;
char *imagename;
- char *command; //it's handy
+ char *command; //console command when clicked
}
Menu_PictureItem;
@@ -75,22 +113,23 @@
void *data; //for custom stuff
float value;//set and used in the slider code
- float minv;
- float maxv;
+ float minv;//min value
+ float maxv;//max (can be inverted)
- float scale;
+ float scale;//size of slider, in pixels.
//notification function
void (*SliderChanged) (struct Menu_SliderItem *slider); //the user just changed the slider->value
void (*SliderUpdate) (struct Menu_SliderItem *slider); //about to draw the slider's value, where you should feel free to update the value from external sources
//internal
- Nbool mousepressed;
+ Nbool mousepressed; //adjust the slider with the mouse
}
Menu_SliderItem;
typedef enum Menu_ArrangeStyle
{
+ MENU_ARRANGESTYLE_LEAVEALONE,
MENU_ARRANGESTYLE_LEFT,
MENU_ARRANGESTYLE_CENTER,
MENU_ARRANGESTYLE_RIGHT,
@@ -114,4 +153,13 @@
Nbool Menu_IsVisible(void);
Nbool Menu_KeyEvent(NUint mod, NUint sym, UNUSED NUint character, Nbool downevent);
+
+Menu_SubMenu *Menu_CreateMenu(Menu_SubMenu *parent);
+Menu_SliderItem *Menu_CreateVSliderItem(Menu_SubMenu *parent, int x, int y, int w, int h, float minv, float maxv, float defaultv, void (*ChangeNotification)(Menu_SliderItem*), void (*UpdateSlider)(Menu_SliderItem*), void *data);//vertical scrolling bar
+Menu_SliderItem *Menu_CreateHSliderItem(Menu_SubMenu *parent, int x, int y, int w, int h, float minv, float maxv, float defaultv, void (*ChangeNotification)(Menu_SliderItem*), void (*UpdateSlider)(Menu_SliderItem*), void *data);//horizontal scrolling bar
+Menu_TextItem *Menu_CreateTextItem(Menu_SubMenu *parent, int x, int y, char *text, void *command, void (*UseTextItem) (struct Menu_TextItem *item)); //if usetextitem == null, interpret as a console command. if not null, command can be used as a magic cookie. If both null, item is non-selectable.
+Menu_EditItem *Menu_CreateEditItem(Menu_SubMenu *parent, int x, int y, char *text); //an item for editing text (fixme: needs callbacks and stuff)
+Menu_ComboItem *Menu_CreateComboItem(Menu_SubMenu *parent, int x, int y, int w, char *defalt, char *list);//a list of multiple choices.
+Menu_PictureItem *Menu_CreatePictureItem(Menu_SubMenu *parent, int x, int y, int w, int h, char *imagename, char *command); //just a simple picture. clicking it can give a console command (fixme: make like text)
+
#endif
More information about the neither-commits
mailing list