about summary refs log tree commit diff
path: root/src/game/client/components/menus_demo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/client/components/menus_demo.cpp')
-rw-r--r--src/game/client/components/menus_demo.cpp545
1 files changed, 283 insertions, 262 deletions
diff --git a/src/game/client/components/menus_demo.cpp b/src/game/client/components/menus_demo.cpp
index 07019d46..62c03a92 100644
--- a/src/game/client/components/menus_demo.cpp
+++ b/src/game/client/components/menus_demo.cpp
@@ -1,86 +1,82 @@
 
-#include <base/math.hpp>
+#include <base/math.h>
 
-//#include <string.h> // strcmp, strlen, strncpy
-//#include <stdlib.h> // atoi
 
-#include <engine/e_client_interface.h>
-#include <game/client/render.hpp>
-#include <game/client/gameclient.hpp>
+#include <engine/demo.h>
+#include <engine/keys.h>
 
-//#include <game/generated/g_protocol.hpp>
-//#include <game/generated/gc_data.hpp>
+#include <game/client/render.h>
+#include <game/client/gameclient.h>
+#include <game/localization.h>
 
-#include <game/client/ui.hpp>
-//#include <game/client/gameclient.hpp>
-//#include <game/client/animstate.hpp>
+#include <game/client/ui.h>
 
-#include "menus.hpp"
+#include "menus.h"
 
-int MENUS::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
+int CMenus::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
 {
-	RenderTools()->DrawUIRect(pRect, vec4(1,1,1, Checked ? 0.10f : 0.5f)*button_color_mul(pID), CUI::CORNER_ALL, 5.0f);
+	RenderTools()->DrawUIRect(pRect, vec4(1,1,1, Checked ? 0.10f : 0.5f)*ButtonColorMul(pID), CUI::CORNER_ALL, 5.0f);
 	UI()->DoLabel(pRect, pText, 14.0f, 0);
 	return UI()->DoButtonLogic(pID, pText, Checked, pRect);
 }
 
-void MENUS::render_demoplayer(CUIRect main_view)
+void CMenus::RenderDemoPlayer(CUIRect MainView)
 {
-	const DEMOPLAYBACK_INFO *info = client_demoplayer_getinfo();
+	const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
 	
-	const float seekbar_height = 15.0f;
-	const float buttonbar_height = 20.0f;
-	const float margins = 5.0f;
-	float total_height;
+	const float SeekBarHeight = 15.0f;
+	const float ButtonbarHeight = 20.0f;
+	const float Margins = 5.0f;
+	float TotalHeight;
 	
-	if(menu_active)
-		total_height = seekbar_height+buttonbar_height+margins*3;
+	if(m_MenuActive)
+		TotalHeight = SeekBarHeight+ButtonbarHeight+Margins*3;
 	else
-		total_height = seekbar_height+margins*2;
+		TotalHeight = SeekBarHeight+Margins*2;
 	
-	main_view.HSplitBottom(total_height, 0, &main_view);
-	main_view.VSplitLeft(250.0f, 0, &main_view);
-	main_view.VSplitRight(250.0f, &main_view, 0);
+	MainView.HSplitBottom(TotalHeight, 0, &MainView);
+	MainView.VSplitLeft(250.0f, 0, &MainView);
+	MainView.VSplitRight(250.0f, &MainView, 0);
 	
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_T, 10.0f);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_T, 10.0f);
 		
-	main_view.Margin(5.0f, &main_view);
+	MainView.Margin(5.0f, &MainView);
 	
-	CUIRect seekbar, buttonbar;
+	CUIRect SeekBar, ButtonBar;
 	
-	if(menu_active)
+	if(m_MenuActive)
 	{
-		main_view.HSplitTop(seekbar_height, &seekbar, &buttonbar);
-		buttonbar.HSplitTop(margins, 0, &buttonbar);
+		MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
+		ButtonBar.HSplitTop(Margins, 0, &ButtonBar);
 	}
 	else
-		seekbar = main_view;
+		SeekBar = MainView;
 
 	// do seekbar
 	{
-		static int seekbar_id = 0;
-		void *id = &seekbar_id;
-		char buffer[128];
+		static int s_SeekBarId = 0;
+		void *id = &s_SeekBarId;
+		char aBuffer[128];
 		
-		RenderTools()->DrawUIRect(&seekbar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f);
+		RenderTools()->DrawUIRect(&SeekBar, vec4(0,0,0,0.5f), CUI::CORNER_ALL, 5.0f);
 		
-		int current_tick = info->current_tick - info->first_tick;
-		int total_ticks = info->last_tick - info->first_tick;
+		int CurrentTick = pInfo->m_CurrentTick - pInfo->m_FirstTick;
+		int TotalTicks = pInfo->m_LastTick - pInfo->m_FirstTick;
 		
-		float amount = current_tick/(float)total_ticks;
+		float Amount = CurrentTick/(float)TotalTicks;
 		
-		CUIRect filledbar = seekbar;
-		filledbar.w = 10.0f + (filledbar.w-10.0f)*amount;
+		CUIRect FilledBar = SeekBar;
+		FilledBar.w = 10.0f + (FilledBar.w-10.0f)*Amount;
 		
-		RenderTools()->DrawUIRect(&filledbar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
+		RenderTools()->DrawUIRect(&FilledBar, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 5.0f);
 		
-		str_format(buffer, sizeof(buffer), "%d:%02d / %d:%02d",
-			current_tick/SERVER_TICK_SPEED/60, (current_tick/SERVER_TICK_SPEED)%60,
-			total_ticks/SERVER_TICK_SPEED/60, (total_ticks/SERVER_TICK_SPEED)%60);
-		UI()->DoLabel(&seekbar, buffer, seekbar.h*0.70f, 0);
+		str_format(aBuffer, sizeof(aBuffer), "%d:%02d / %d:%02d",
+			CurrentTick/SERVER_TICK_SPEED/60, (CurrentTick/SERVER_TICK_SPEED)%60,
+			TotalTicks/SERVER_TICK_SPEED/60, (TotalTicks/SERVER_TICK_SPEED)%60);
+		UI()->DoLabel(&SeekBar, aBuffer, SeekBar.h*0.70f, 0);
 
 		// do the logic
-	    int inside = UI()->MouseInside(&seekbar);
+	    int Inside = UI()->MouseInside(&SeekBar);
 			
 		if(UI()->ActiveItem() == id)
 		{
@@ -88,13 +84,15 @@ void MENUS::render_demoplayer(CUIRect main_view)
 				UI()->SetActiveItem(0);
 			else
 			{
-				float amount = (UI()->MouseX()-seekbar.x)/(float)seekbar.w;
-				if(amount > 0 && amount < 1.0f)
+				static float PrevAmount = 0.0f;
+				float Amount = (UI()->MouseX()-SeekBar.x)/(float)SeekBar.w;
+				if(Amount > 0 && Amount < 1.0f && PrevAmount != Amount)
 				{
-					gameclient.on_reset();
-					gameclient.suppress_events = true;
-					client_demoplayer_setpos(amount);
-					gameclient.suppress_events = false;
+					PrevAmount = Amount;
+					m_pClient->OnReset();
+					m_pClient->m_SuppressEvents = true;
+					DemoPlayer()->SetPos(Amount);
+					m_pClient->m_SuppressEvents = false;
 				}
 			}
 		}
@@ -104,334 +102,357 @@ void MENUS::render_demoplayer(CUIRect main_view)
 				UI()->SetActiveItem(id);
 		}		
 		
-		if(inside)
+		if(Inside)
 			UI()->SetHotItem(id);
 	}	
 	
 
-	if(menu_active)
+	if(m_MenuActive)
 	{
 		// do buttons
-		CUIRect button;
+		CUIRect Button;
 
 		// pause button
-		buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar);
-		static int pause_button = 0;
-		if(DoButton_DemoPlayer(&pause_button, "| |", info->paused, &button))
-			client_demoplayer_setpause(!info->paused);
+		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
+		static int s_PauseButton = 0;
+		if(DoButton_DemoPlayer(&s_PauseButton, "| |", pInfo->m_Paused, &Button))
+		{
+			if(pInfo->m_Paused)
+				DemoPlayer()->Unpause();
+			else
+				DemoPlayer()->Pause();
+		}
 		
 		// play button
-		buttonbar.VSplitLeft(margins, 0, &buttonbar);
-		buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar);
-		static int play_button = 0;
-		if(DoButton_DemoPlayer(&play_button, ">", !info->paused, &button))
+		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
+		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
+		static int s_PlayButton = 0;
+		if(DoButton_DemoPlayer(&s_PlayButton, ">", !pInfo->m_Paused, &Button))
 		{
-			client_demoplayer_setpause(0);
-			client_demoplayer_setspeed(1.0f);
+			DemoPlayer()->Unpause();
+			DemoPlayer()->SetSpeed(1.0f);
 		}
 
 		// slowdown
-		buttonbar.VSplitLeft(margins, 0, &buttonbar);
-		buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar);
-		static int slowdown_button = 0;
-		if(DoButton_DemoPlayer(&slowdown_button, "<<", 0, &button))
+		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
+		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
+		static int s_SlowDownButton = 0;
+		if(DoButton_DemoPlayer(&s_SlowDownButton, "<<", 0, &Button))
 		{
-			if(info->speed > 4.0f) client_demoplayer_setspeed(4.0f);
-			else if(info->speed > 2.0f) client_demoplayer_setspeed(2.0f);
-			else if(info->speed > 1.0f) client_demoplayer_setspeed(1.0f);
-			else if(info->speed > 0.5f) client_demoplayer_setspeed(0.5f);
-			else client_demoplayer_setspeed(0.05f);
+			if(pInfo->m_Speed > 4.0f) DemoPlayer()->SetSpeed(4.0f);
+			else if(pInfo->m_Speed > 2.0f) DemoPlayer()->SetSpeed(2.0f);
+			else if(pInfo->m_Speed > 1.0f) DemoPlayer()->SetSpeed(1.0f);
+			else if(pInfo->m_Speed > 0.5f) DemoPlayer()->SetSpeed(0.5f);
+			else DemoPlayer()->SetSpeed(0.05f);
 		}
 		
 		// fastforward
-		buttonbar.VSplitLeft(margins, 0, &buttonbar);
-		buttonbar.VSplitLeft(buttonbar_height, &button, &buttonbar);
-		static int fastforward_button = 0;
-		if(DoButton_DemoPlayer(&fastforward_button, ">>", 0, &button))
+		ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
+		ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
+		static int s_FastForwardButton = 0;
+		if(DoButton_DemoPlayer(&s_FastForwardButton, ">>", 0, &Button))
 		{
-			if(info->speed < 0.5f) client_demoplayer_setspeed(0.5f);
-			else if(info->speed < 1.0f) client_demoplayer_setspeed(1.0f);
-			else if(info->speed < 2.0f) client_demoplayer_setspeed(2.0f);
-			else if(info->speed < 4.0f) client_demoplayer_setspeed(4.0f);
-			else client_demoplayer_setspeed(8.0f);
+			if(pInfo->m_Speed < 0.5f) DemoPlayer()->SetSpeed(0.5f);
+			else if(pInfo->m_Speed < 1.0f) DemoPlayer()->SetSpeed(1.0f);
+			else if(pInfo->m_Speed < 2.0f) DemoPlayer()->SetSpeed(2.0f);
+			else if(pInfo->m_Speed < 4.0f) DemoPlayer()->SetSpeed(4.0f);
+			else DemoPlayer()->SetSpeed(8.0f);
 		}
 
 		// speed meter
-		buttonbar.VSplitLeft(margins*3, 0, &buttonbar);
-		char buffer[64];
-		if(info->speed >= 1.0f)
-			str_format(buffer, sizeof(buffer), "x%.0f", info->speed);
+		ButtonBar.VSplitLeft(Margins*3, 0, &ButtonBar);
+		char aBuffer[64];
+		if(pInfo->m_Speed >= 1.0f)
+			str_format(aBuffer, sizeof(aBuffer), "x%.0f", pInfo->m_Speed);
 		else
-			str_format(buffer, sizeof(buffer), "x%.1f", info->speed);
-		UI()->DoLabel(&buttonbar, buffer, button.h*0.7f, -1);
+			str_format(aBuffer, sizeof(aBuffer), "x%.1f", pInfo->m_Speed);
+		UI()->DoLabel(&ButtonBar, aBuffer, Button.h*0.7f, -1);
 
 		// close button
-		buttonbar.VSplitRight(buttonbar_height*3, &buttonbar, &button);
-		static int exit_button = 0;
-		if(DoButton_DemoPlayer(&exit_button, localize("Close"), 0, &button))
-			client_disconnect();
+		ButtonBar.VSplitRight(ButtonbarHeight*3, &ButtonBar, &Button);
+		static int s_ExitButton = 0;
+		if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button))
+			Client()->Disconnect();
 	}
 }
 
-static CUIRect listbox_originalview;
-static CUIRect listbox_view;
-static float listbox_rowheight;
-static int listbox_itemindex;
-static int listbox_selected_index;
-static int listbox_new_selected;
-static int listbox_doneevents;
-static int listbox_numitems;
-
-void MENUS::ui_do_listbox_start(void *id, const CUIRect *rect, float row_height, const char *title, int num_items, int selected_index)
+static CUIRect gs_ListBoxOriginalView;
+static CUIRect gs_ListBoxView;
+static float gs_ListBoxRowHeight;
+static int gs_ListBoxItemIndex;
+static int gs_ListBoxSelectedIndex;
+static int gs_ListBoxNewSelected;
+static int gs_ListBoxDoneEvents;
+static int gs_ListBoxNumItems;
+static int gs_ListBoxItemsPerRow;
+static float gs_ListBoxScrollValue;
+static bool gs_ListBoxItemActivated;
+
+void CMenus::UiDoListboxStart(void *pId, const CUIRect *pRect, float RowHeight, const char *pTitle, const char *pBottomText, int NumItems,
+								int ItemsPerRow, int SelectedIndex, float ScrollValue)
 {
-	CUIRect scroll, row;
-	CUIRect view = *rect;
-	CUIRect header, footer;
+	CUIRect Scroll, Row;
+	CUIRect View = *pRect;
+	CUIRect Header, Footer;
 	
 	// draw header
-	view.HSplitTop(listheader_height, &header, &view);
-	RenderTools()->DrawUIRect(&header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); 
-	UI()->DoLabel(&header, title, header.h*fontmod_height, 0);
+	View.HSplitTop(ms_ListheaderHeight, &Header, &View);
+	RenderTools()->DrawUIRect(&Header, vec4(1,1,1,0.25f), CUI::CORNER_T, 5.0f); 
+	UI()->DoLabel(&Header, pTitle, Header.h*ms_FontmodHeight, 0);
 
 	// draw footers
-	view.HSplitBottom(listheader_height, &view, &footer);
-	RenderTools()->DrawUIRect(&footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); 
-	footer.VSplitLeft(10.0f, 0, &footer);
+	View.HSplitBottom(ms_ListheaderHeight, &View, &Footer);
+	RenderTools()->DrawUIRect(&Footer, vec4(1,1,1,0.25f), CUI::CORNER_B, 5.0f); 
+	Footer.VSplitLeft(10.0f, 0, &Footer);
+	UI()->DoLabel(&Footer, pBottomText, Header.h*ms_FontmodHeight, 0);
 
 	// background
-	RenderTools()->DrawUIRect(&view, vec4(0,0,0,0.15f), 0, 0);
+	RenderTools()->DrawUIRect(&View, vec4(0,0,0,0.15f), 0, 0);
 
 	// prepare the scroll
-	view.VSplitRight(15, &view, &scroll);
+	View.VSplitRight(15, &View, &Scroll);
 
 	// setup the variables	
-	listbox_originalview = view;
-	listbox_selected_index = selected_index;
-	listbox_new_selected = selected_index;
-	listbox_itemindex = 0;
-	listbox_rowheight = row_height;
-	listbox_numitems = num_items;
-	listbox_doneevents = 0;
-	//int num_servers = client_serverbrowse_sorted_num();
-
+	gs_ListBoxOriginalView = View;
+	gs_ListBoxSelectedIndex = SelectedIndex;
+	gs_ListBoxNewSelected = SelectedIndex;
+	gs_ListBoxItemIndex = 0;
+	gs_ListBoxRowHeight = RowHeight;
+	gs_ListBoxNumItems = NumItems;
+	gs_ListBoxItemsPerRow = ItemsPerRow;
+	gs_ListBoxDoneEvents = 0;
+	gs_ListBoxScrollValue = ScrollValue;
+	gs_ListBoxItemActivated = false;
 
 	// do the scrollbar
-	view.HSplitTop(listbox_rowheight, &row, 0);
+	View.HSplitTop(gs_ListBoxRowHeight, &Row, 0);
 	
-	int num_viewable = (int)(listbox_originalview.h/row.h) + 1;
-	int num = num_items-num_viewable+1;
-	if(num < 0)
-		num = 0;
+	int NumViewable = (int)(gs_ListBoxOriginalView.h/Row.h) + 1;
+	int Num = (NumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1;
+	if(Num < 0)
+		Num = 0;
+	if(Num > 0)
+	{
+		if(Input()->KeyPresses(KEY_MOUSE_WHEEL_UP))
+			gs_ListBoxScrollValue -= 1.0f/Num;
+		if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
+			gs_ListBoxScrollValue += 1.0f/Num;
 		
-	static float scrollvalue = 0;
-	scroll.HMargin(5.0f, &scroll);
-	scrollvalue = DoScrollbarV(id, &scroll, scrollvalue);
-
-	int start = (int)(num*scrollvalue);
-	if(start < 0)
-		start = 0;
+		if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f;
+		if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f;
+	}
+		
+	Scroll.HMargin(5.0f, &Scroll);
+	gs_ListBoxScrollValue = DoScrollbarV(pId, &Scroll, gs_ListBoxScrollValue);
 	
 	// the list
-	listbox_view = listbox_originalview;
-	listbox_view.VMargin(5.0f, &listbox_view);
-	UI()->ClipEnable(&listbox_view);
-	listbox_view.y -= scrollvalue*num*row.h;	
+	gs_ListBoxView = gs_ListBoxOriginalView;
+	gs_ListBoxView.VMargin(5.0f, &gs_ListBoxView);
+	UI()->ClipEnable(&gs_ListBoxView);
+	gs_ListBoxView.y -= gs_ListBoxScrollValue*Num*Row.h;
 }
 
-MENUS::LISTBOXITEM MENUS::ui_do_listbox_nextrow()
+CMenus::CListboxItem CMenus::UiDoListboxNextRow()
 {
-	LISTBOXITEM item = {0};
-	listbox_view.HSplitTop(listbox_rowheight /*-2.0f*/, &item.rect, &listbox_view);
-	item.visible = 1;
+	static CUIRect s_RowView;
+	CListboxItem Item = {0};
+	if(gs_ListBoxItemIndex%gs_ListBoxItemsPerRow == 0)
+		gs_ListBoxView.HSplitTop(gs_ListBoxRowHeight /*-2.0f*/, &s_RowView, &gs_ListBoxView);
+
+	s_RowView.VSplitLeft(s_RowView.w/(gs_ListBoxItemsPerRow-gs_ListBoxItemIndex%gs_ListBoxItemsPerRow), &Item.m_Rect, &s_RowView);
+
+	Item.m_Visible = 1;
 	//item.rect = row;
 	
-	item.hitrect = item.rect;
+	Item.m_HitRect = Item.m_Rect;
 	
 	//CUIRect select_hit_box = item.rect;
 
-	if(listbox_selected_index == listbox_itemindex)
-		item.selected = 1;
+	if(gs_ListBoxSelectedIndex == gs_ListBoxItemIndex)
+		Item.m_Selected = 1;
 	
 	// make sure that only those in view can be selected
-	if(item.rect.y+item.rect.h > listbox_originalview.y)
+	if(Item.m_Rect.y+Item.m_Rect.h > gs_ListBoxOriginalView.y)
 	{
 		
-		if(item.hitrect.y < item.hitrect.y) // clip the selection
+		if(Item.m_HitRect.y < Item.m_HitRect.y) // clip the selection
 		{
-			item.hitrect.h -= listbox_originalview.y-item.hitrect.y;
-			item.hitrect.y = listbox_originalview.y;
+			Item.m_HitRect.h -= gs_ListBoxOriginalView.y-Item.m_HitRect.y;
+			Item.m_HitRect.y = gs_ListBoxOriginalView.y;
 		}
 		
 	}
 	else
-		item.visible = 0;
+		Item.m_Visible = 0;
 
 	// check if we need to do more
-	if(item.rect.y > listbox_originalview.y+listbox_originalview.h)
-		item.visible = 0;
+	if(Item.m_Rect.y > gs_ListBoxOriginalView.y+gs_ListBoxOriginalView.h)
+		Item.m_Visible = 0;
 		
-	listbox_itemindex++;
-	return item;
+	gs_ListBoxItemIndex++;
+	return Item;
 }
 
-MENUS::LISTBOXITEM MENUS::ui_do_listbox_nextitem(void *id)
+CMenus::CListboxItem CMenus::UiDoListboxNextItem(void *pId, bool Selected)
 {
-	int this_itemindex = listbox_itemindex;
-	
-	LISTBOXITEM item = ui_do_listbox_nextrow();
-
-	if(UI()->DoButtonLogic(id, "", listbox_selected_index == listbox_itemindex, &item.hitrect))
-		listbox_new_selected = listbox_itemindex;
-	
-	//CUIRect row;
-	//LISTBOXITEM item = {0};
-	//listbox_view.HSplitTop(listbox_rowheight /*-2.0f*/, &row, &listbox_view);
-	//listbox_view.HSplitTop(2.0f, 0, &listbox_view);
-	/*
-	CUIRect select_hit_box = row;
-
-	item.visible = 1;
-	if(listbox_selected_index == listbox_itemindex)
-		item.selected = 1;
-	
-	// make sure that only those in view can be selected
-	if(row.y+row.h > listbox_originalview.y)
+	int ThisItemIndex = gs_ListBoxItemIndex;
+	if(Selected)
 	{
-		
-		if(select_hit_box.y < listbox_originalview.y) // clip the selection
-		{
-			select_hit_box.h -= listbox_originalview.y-select_hit_box.y;
-			select_hit_box.y = listbox_originalview.y;
-		}
-		
-		if(UI()->DoButton(id, "", listbox_selected_index==listbox_itemindex, &select_hit_box, 0, 0))
-			listbox_new_selected = listbox_itemindex;
+		if(gs_ListBoxSelectedIndex == gs_ListBoxNewSelected)
+			gs_ListBoxNewSelected = ThisItemIndex;
+		gs_ListBoxSelectedIndex = ThisItemIndex;
 	}
-	else
-		item.visible = 0;
-	
-	item.rect = row;
-	*/
 	
+	CListboxItem Item = UiDoListboxNextRow();
 
-	if(listbox_selected_index == this_itemindex)
+	if(Item.m_Visible && UI()->DoButtonLogic(pId, "", gs_ListBoxSelectedIndex == gs_ListBoxItemIndex, &Item.m_HitRect))
+		gs_ListBoxNewSelected = ThisItemIndex;
+	
+	// process input, regard selected index
+	if(gs_ListBoxSelectedIndex == ThisItemIndex)
 	{
-		if(!listbox_doneevents)
+		if(!gs_ListBoxDoneEvents)
 		{
-			listbox_doneevents = 1;
-			
-			for(int i = 0; i < num_inputevents; i++)
+			gs_ListBoxDoneEvents = 1;
+
+			if(m_EnterPressed || (Input()->MouseDoubleClick() && UI()->ActiveItem() == pId))
 			{
-				if(inputevents[i].flags&INPFLAG_PRESS)
+				gs_ListBoxItemActivated = true;
+			}
+			else
+			{			
+				for(int i = 0; i < m_NumInputEvents; i++)
 				{
-					if(inputevents[i].key == KEY_DOWN) listbox_new_selected++;
-					if(inputevents[i].key == KEY_UP) listbox_new_selected--;
+					int NewIndex = -1;
+					if(m_aInputEvents[i].m_Flags&IInput::FLAG_PRESS)
+					{
+						if(m_aInputEvents[i].m_Key == KEY_DOWN) NewIndex = gs_ListBoxNewSelected + 1;
+						if(m_aInputEvents[i].m_Key == KEY_UP) NewIndex = gs_ListBoxNewSelected - 1;
+					}
+					if(NewIndex > -1 && NewIndex < gs_ListBoxNumItems)
+					{
+						// scroll
+						int NumViewable = (int)(gs_ListBoxOriginalView.h/gs_ListBoxRowHeight) + 1;
+						int ScrollNum = (gs_ListBoxNumItems+gs_ListBoxItemsPerRow-1)/gs_ListBoxItemsPerRow-NumViewable+1;
+						if(ScrollNum > 0 && NewIndex/gs_ListBoxItemsPerRow-gs_ListBoxSelectedIndex/gs_ListBoxItemsPerRow)
+						{
+							// TODO: make the scrolling better
+							if(NewIndex - gs_ListBoxSelectedIndex > 0)
+								gs_ListBoxScrollValue += 1.0f/ScrollNum;
+							else
+								gs_ListBoxScrollValue -= 1.0f/ScrollNum;
+							if(gs_ListBoxScrollValue < 0.0f) gs_ListBoxScrollValue = 0.0f;
+							if(gs_ListBoxScrollValue > 1.0f) gs_ListBoxScrollValue = 1.0f;
+						}
+						
+						gs_ListBoxNewSelected = NewIndex;
+					}
 				}
 			}
-
-			if(listbox_new_selected >= listbox_numitems)
-				listbox_new_selected = listbox_numitems-1;
-			if(listbox_new_selected < 0)
-				listbox_new_selected = 0;
 		}
 		
 		//selected_index = i;
-		CUIRect r = item.rect;
+		CUIRect r = Item.m_Rect;
 		r.Margin(1.5f, &r);
 		RenderTools()->DrawUIRect(&r, vec4(1,1,1,0.5f), CUI::CORNER_ALL, 4.0f);
 	}	
 
-	//listbox_itemindex++;
-	return item;
+	return Item;
 }
 
-int MENUS::ui_do_listbox_end()
+int CMenus::UiDoListboxEnd(float *pScrollValue, bool *pItemActivated)
 {
 	UI()->ClipDisable();
-	return listbox_new_selected;
+	if(pScrollValue)
+		*pScrollValue = gs_ListBoxScrollValue;
+	if(pItemActivated)
+		*pItemActivated = gs_ListBoxItemActivated;
+	return gs_ListBoxNewSelected;
 }
 
 struct FETCH_CALLBACKINFO
 {
-	MENUS *self;
-	const char *prefix;
-	int count;
+	CMenus *m_pSelf;
+	const char *m_pPrefix;
+	int m_Count;
 };
 
-void MENUS::demolist_fetch_callback(const char *name, int is_dir, void *user)
+void CMenus::DemolistFetchCallback(const char *pName, int IsDir, void *pUser)
 {
-	if(is_dir || name[0] == '.')
+	if(IsDir || pName[0] == '.')
 		return;
 			
-	FETCH_CALLBACKINFO *info = (FETCH_CALLBACKINFO *)user;
+	FETCH_CALLBACKINFO *pInfo = (FETCH_CALLBACKINFO *)pUser;
 	
-	DEMOITEM item;
-	str_format(item.filename, sizeof(item.filename), "%s/%s", info->prefix, name);
-	str_copy(item.name, name, sizeof(item.name));
-	info->self->demos.add(item);
+	CDemoItem Item;
+	str_format(Item.m_aFilename, sizeof(Item.m_aFilename), "%s/%s", pInfo->m_pPrefix, pName);
+	str_copy(Item.m_aName, pName, sizeof(Item.m_aName));
+	pInfo->m_pSelf->m_lDemos.add(Item);
 }
 
-void MENUS::demolist_populate()
+void CMenus::DemolistPopulate()
 {
-	demos.clear();
+	m_lDemos.clear();
 	
-	char buf[512];
-	str_format(buf, sizeof(buf), "%s/demos", client_user_directory());
+	char aBuf[512];
+	str_format(aBuf, sizeof(aBuf), "%s/demos", Client()->UserDirectory());
 
-	FETCH_CALLBACKINFO info = {this, buf, 0};
-	fs_listdir(buf, demolist_fetch_callback, &info);
-	info.prefix = "demos";
-	fs_listdir("demos", demolist_fetch_callback, &info);
+	FETCH_CALLBACKINFO Info = {this, aBuf, 0};
+	fs_listdir(aBuf, DemolistFetchCallback, &Info);
+	Info.m_pPrefix = "demos";
+	fs_listdir("demos", DemolistFetchCallback, &Info);
 }
 
 
-void MENUS::render_demolist(CUIRect main_view)
+void CMenus::RenderDemoList(CUIRect MainView)
 {
-	static int inited = 0;
-	if(!inited)
-		demolist_populate();
-	inited = 1;
+	static int s_Inited = 0;
+	if(!s_Inited)
+		DemolistPopulate();
+	s_Inited = 1;
 	
 	// render background
-	RenderTools()->DrawUIRect(&main_view, color_tabbar_active, CUI::CORNER_ALL, 10.0f);
-	main_view.Margin(10.0f, &main_view);
+	RenderTools()->DrawUIRect(&MainView, ms_ColorTabbarActive, CUI::CORNER_ALL, 10.0f);
+	MainView.Margin(10.0f, &MainView);
 	
-	CUIRect buttonbar;
-	main_view.HSplitBottom(button_height+5.0f, &main_view, &buttonbar);
-	buttonbar.HSplitTop(5.0f, 0, &buttonbar);
+	CUIRect ButtonBar;
+	MainView.HSplitBottom(ms_ButtonHeight+5.0f, &MainView, &ButtonBar);
+	ButtonBar.HSplitTop(5.0f, 0, &ButtonBar);
 	
-	static int selected_item = -1;
-	static int demolist_id = 0;
+	static int s_SelectedItem = -1;
+	static int s_DemoListId = 0;
+	static float s_ScrollValue = 0;
 	
-	ui_do_listbox_start(&demolist_id, &main_view, 17.0f, localize("Demos"), demos.size(), selected_item);
+	UiDoListboxStart(&s_DemoListId, &MainView, 17.0f, Localize("Demos"), "", m_lDemos.size(), 1, s_SelectedItem, s_ScrollValue);
 	//for(int i = 0; i < num_demos; i++)
-	for(sorted_array<DEMOITEM>::range r = demos.all(); !r.empty(); r.pop_front())
+	for(sorted_array<CDemoItem>::range r = m_lDemos.all(); !r.empty(); r.pop_front())
 	{
-		LISTBOXITEM item = ui_do_listbox_nextitem((void*)(&r.front()));
-		if(item.visible)
-			UI()->DoLabel(&item.rect, r.front().name, item.rect.h*fontmod_height, -1);
+		CListboxItem Item = UiDoListboxNextItem((void*)(&r.front()));
+		if(Item.m_Visible)
+			UI()->DoLabel(&Item.m_Rect, r.front().m_aName, Item.m_Rect.h*ms_FontmodHeight, -1);
 	}
-	selected_item = ui_do_listbox_end();
-	
-	CUIRect refresh_rect, play_rect;
-	buttonbar.VSplitRight(250.0f, &buttonbar, &refresh_rect);
-	refresh_rect.VSplitRight(130.0f, &refresh_rect, &play_rect);
-	play_rect.VSplitRight(120.0f, 0x0, &play_rect);
+	bool Activated = false;
+	s_SelectedItem = UiDoListboxEnd(&s_ScrollValue, &Activated);
 	
-	static int refresh_button = 0;
-	if(DoButton_Menu(&refresh_button, localize("Refresh"), 0, &refresh_rect))
-	{
-		demolist_populate();
-	}	
+	CUIRect RefreshRect, PlayRect;
+	ButtonBar.VSplitRight(250.0f, &ButtonBar, &RefreshRect);
+	RefreshRect.VSplitRight(130.0f, &RefreshRect, &PlayRect);
+	PlayRect.VSplitRight(120.0f, 0x0, &PlayRect);
 	
-	static int play_button = 0;
-	if(DoButton_Menu(&play_button, localize("Play"), 0, &play_rect))
+	static int s_RefreshButton = 0;
+	if(DoButton_Menu(&s_RefreshButton, Localize("Refresh"), 0, &RefreshRect))
 	{
-		if(selected_item >= 0 && selected_item < demos.size())
+		DemolistPopulate();
+	}
+		
+	static int s_PlayButton = 0;
+	if(DoButton_Menu(&s_PlayButton, Localize("Play"), 0, &PlayRect) || Activated)
+	{		
+		if(s_SelectedItem >= 0 && s_SelectedItem < m_lDemos.size())
 		{
-			const char *error = client_demoplayer_play(demos[selected_item].filename);
-			if(error)
-				popup_message(localize("Error"), error, localize("Ok"));
+			const char *pError = Client()->DemoPlayer_Play(m_lDemos[s_SelectedItem].m_aFilename);
+			if(pError)
+				PopupMessage(Localize("Error"), pError, Localize("Ok"));
 		}
 	}