diff --git a/src/game/client/CMakeLists.txt b/src/game/client/CMakeLists.txt index d4a76fa0..5b4cffc1 100644 --- a/src/game/client/CMakeLists.txt +++ b/src/game/client/CMakeLists.txt @@ -479,6 +479,8 @@ set(VGUI_MS "ui/ms/vgui_storesell.cpp" "ui/ms/vgui_storesell.h" "ui/ms/vgui_vote.h" + "ui/ms/vgui_moveitempanel.cpp" + "ui/ms/vgui_moveitempanel.h" ) source_group("VGUI\\ms" FILES ${VGUI_MS}) diff --git a/src/game/client/clientlibrary.cpp b/src/game/client/clientlibrary.cpp index bd439302..a9b7c382 100644 --- a/src/game/client/clientlibrary.cpp +++ b/src/game/client/clientlibrary.cpp @@ -54,7 +54,6 @@ void CClientLibrary::HUDInit() CVAR_CREATE("ms_quickslot_timeout", "2.5", FCVAR_ARCHIVE); // Timeout for the quickslots CVAR_CREATE("ms_autocharge", "1", FCVAR_ARCHIVE); // MiB MAR2012_05 - Let's you auto-charge your attack CVAR_CREATE("ms_doubletapdodge", "0", FCVAR_ARCHIVE); // MiB MAR2012_05 -Enable/Disable double tapping to dodge - CVAR_CREATE("ms_invtype", "1", FCVAR_ARCHIVE); // MiB FEB2012_12 - Inventory types (added post-doc by Thothie) CVAR_CREATE("ms_showotherglow", "1", FCVAR_ARCHIVE); CVAR_CREATE("ms_chargebar_sound", "magic/chargebar_alt1.wav", FCVAR_ARCHIVE); CVAR_CREATE("ms_glowcolor", "(255,255,255)", FCVAR_ARCHIVE); // This is called in player think and was breaking the entire think cycle. @@ -79,6 +78,10 @@ void CClientLibrary::HUDInit() CVAR_CREATE("ms_txthud_width", "640", FCVAR_ARCHIVE); // Width of console CVAR_CREATE("ms_hidehud", "0", FCVAR_ARCHIVE); // Hides the HUD and viewmodel completely CVAR_CREATE("ms_lildude", "1", FCVAR_ARCHIVE); // Thothie MAR2007a - Hides the 3d Guy if set 0 + CVAR_CREATE("ms_invtype", "1", FCVAR_ARCHIVE); // MiB FEB2012_12 - Inventory types (added post-doc by Thothie) + CVAR_CREATE("ms_alpha_inventory", "0", FCVAR_ARCHIVE); // MiB FEB2019_24 [ALPHABETICAL_INVENTORY] + CVAR_CREATE("ms_doubleclicktime", "1", FCVAR_ARCHIVE); + CVAR_CREATE("ms_scrollamount", "30", FCVAR_ARCHIVE); //debug outputs ; remove later - always add where they are set! This way let's us get data after something goes wrong out of a string CVAR_CREATE("DEBUG_bestxpstat", "0", FCVAR_CLIENTDLL); // Called @ playerstats.cpp line 123 diff --git a/src/game/client/ui/ms/vgui_container.cpp b/src/game/client/ui/ms/vgui_container.cpp index fb5f7636..b3102b26 100644 --- a/src/game/client/ui/ms/vgui_container.cpp +++ b/src/game/client/ui/ms/vgui_container.cpp @@ -28,67 +28,76 @@ #include "vgui_container.h" // Menu Dimensions -#define GEARPNL_PACK_SPACER_Y YRES(10) +#define GEARPNL_PACK_SPACER_Y YRES(2) #define LINESPACER_Y YRES(10) const char *VGUI_ContainerPanel::m_Text_DoubleClick = "Double click to use item or click Remove to unequip container"; COLOR Color_GearSelected = COLOR(255, 0, 0, 0), - Color_GearNormal = COLOR(200, 200, 200, 0), + Color_GearNormal = COLOR(255, 255, 255, 0), Color_GearNonContainer = COLOR(160, 160, 160, 0), Color_TextHighlighted = COLOR(255, 255, 255, 0), Color_TextNormal = COLOR(100, 100, 100, 0); -int last_clicked = 0; //AUG2013_15 Thothie - fix double click functionality for gear items - class CHandler_GearButton : public InputSignal { public: VGUI_ItemCallbackPanel *m_Callback; + VGUI_DoubleClickDetector *mpDoubleClickDetector; int m_Idx; - CHandler_GearButton(VGUI_ItemCallbackPanel *pParent, int idx) + VGUI_Inv_GearItem* mpHighlightCallback; + + CHandler_GearButton(VGUI_ItemCallbackPanel *pParent, VGUI_DoubleClickDetector *pDoubleClickDetector, VGUI_Inv_GearItem *pHighlightCallback, int idx) { m_Callback = pParent; + mpDoubleClickDetector = pDoubleClickDetector; + mpHighlightCallback = pHighlightCallback; m_Idx = idx; } + void mousePressed(MouseCode code, Panel *panel) { - //AUG2013_15 Thothie - fix double click functionality for gear items - if (last_clicked == m_Idx && m_Idx != 0) + if ( code == MOUSE_LEFT ) { - m_Callback->GearItemDoubleClicked(m_Idx); - } - else - { - last_clicked = m_Idx; - m_Callback->GearItemClicked(m_Idx); + if ( mpDoubleClickDetector->Click( this, code ) ) + { + mouseDoublePressed( code, panel ); + } + else + { + m_Callback->GearItemClicked( m_Idx ); + } } } - void cursorEntered(Panel *panel) {} - void cursorMoved(int x, int y, Panel *panel){}; - void mouseReleased(MouseCode code, Panel *panel){}; + + void cursorEntered(Panel *panel) { mpHighlightCallback->mbMouseOver = true; } + void cursorMoved(int x, int y, Panel *panel) {}; + void mouseReleased(MouseCode code, Panel *panel) {}; void mouseDoublePressed(MouseCode code, Panel *panel) { m_Callback->GearItemDoubleClicked(m_Idx); }; - void cursorExited(Panel *panel){}; - void mouseWheeled(int delta, Panel *panel){}; - void keyPressed(KeyCode code, Panel *panel){}; - void keyTyped(KeyCode code, Panel *panel){}; - void keyReleased(KeyCode code, Panel *panel){}; - void keyFocusTicked(Panel *panel){}; + void cursorExited(Panel *panel) { mpHighlightCallback->mbMouseOver = false; }; + void mouseWheeled(int delta, Panel *panel) {}; + void keyPressed(KeyCode code, Panel *panel) {}; + void keyTyped(KeyCode code, Panel *panel) {}; + void keyReleased(KeyCode code, Panel *panel) {}; + void keyFocusTicked(Panel *panel) {}; }; -VGUI_Inv_GearItem::VGUI_Inv_GearItem(Panel *pContainerParent, VGUI_ItemCallbackPanel *pItemCallbackPanel, VGUI_ItemCallbackPanel *pGearCallback, Panel *pParent) : CTransparentPanel(255, 0, 0, GEARPNL_SIZE_X, YRES(13)) +VGUI_Inv_GearItem::VGUI_Inv_GearItem(Panel *pContainerParent, VGUI_ItemCallbackPanel *pItemCallbackPanel, VGUI_ItemCallbackPanel *pGearCallback, Panel *pParent) : + CTransparentPanel(255, 0, 0, GEARPNL_SIZE_X, YRES(13)) { setParent(pParent); m_ContainerParent = pContainerParent; m_Name = new MSLabel(this, "", 0, 0, getWide(), getTall(), MSLabel::a_center); - m_Name->addInputSignal(m_pSignal = new CHandler_GearButton(pGearCallback, m_Idx)); + m_Name->addInputSignal(m_pSignal = new CHandler_GearButton(pGearCallback, pGearCallback, this, m_Idx)); m_ItemContainer = new VGUI_Container(ITEM_CONTAINER_X, ITEM_CONTAINER_Y, ITEM_CONTAINER_SIZE_X, ITEM_CONTAINER_SIZE_Y, pItemCallbackPanel, pContainerParent); + mbMouseOver = false; } + VGUI_Inv_GearItem::~VGUI_Inv_GearItem() { /*m_ContainerParent->removeChild( m_ItemContainer ); @@ -98,15 +107,14 @@ VGUI_Inv_GearItem::~VGUI_Inv_GearItem() removeChild( m_Name ); delete m_Name;*/ } + void VGUI_Inv_GearItem::Update(gearitem_t &GearItem, int idx) { - last_clicked = 0; //Thothie AUG2013_19 - seems double click fix jams sometimes - m_Idx = idx; m_pSignal->m_Idx = m_Idx; m_GearItemID = GearItem.ID; m_GearItem = GearItem; - setPos(0, YRES(10) + (getTall() + GEARPNL_PACK_SPACER_Y) * idx); + setPos(0, GEARPNL_PACK_SPACER_Y + (getTall() + GEARPNL_PACK_SPACER_Y) * idx); setVisible(true); m_Name->setText(GearItem.Name); @@ -115,14 +123,17 @@ void VGUI_Inv_GearItem::Update(gearitem_t &GearItem, int idx) //Delete all items in the container m_ItemContainer->PurgeButtons(); } + void VGUI_Inv_GearItem::Reset() { //Delete all items in the container m_ItemContainer->PurgeButtons(); setVisible(false); + mbMouseOver = false; DeSelect(); } + void VGUI_Inv_GearItem::Select() { m_Name->SetFGColorRGB(Color_GearSelected); @@ -134,6 +145,7 @@ void VGUI_Inv_GearItem::Select() m_ItemContainer->Update(); } } + void VGUI_Inv_GearItem::DeSelect() { if (m_GearItem.IsContainer) @@ -145,8 +157,9 @@ void VGUI_Inv_GearItem::DeSelect() m_ItemContainer->m_pInvTypePanel->setVisible(false); } -VGUI_InventoryPanel::VGUI_InventoryPanel(VGUI_ItemCallbackPanel *pCallbackPanel, Panel *pParent) : CTransparentPanel(INVENTORY_TRANSPARENCY, GEARPNL_X, GEARPNL_Y, GEARPNL_SIZE_X, GEARPNL_SIZE_Y), - VGUI_ItemCallbackPanel() +VGUI_InventoryPanel::VGUI_InventoryPanel(VGUI_ItemCallbackPanel *pCallbackPanel, Panel *pParent) : + CTransparentPanel(INVENTORY_TRANSPARENCY, GEARPNL_X, GEARPNL_Y, GEARPNL_SIZE_X, GEARPNL_SIZE_Y), + VGUI_ItemCallbackPanel() { setParent(pParent); m_pCallbackPanel = pCallbackPanel; @@ -158,7 +171,11 @@ VGUI_InventoryPanel::VGUI_InventoryPanel(VGUI_ItemCallbackPanel *pCallbackPanel, m_Scroll->setScrollBarAutoVisible(false, true); m_Scroll->setScrollBarVisible(false, false); m_Scroll->validate(); + + mbScrollHighlighted = false; + m_Scroll->addInputSignal( new CSimpleInputSignal( this, NULL, NULL ) ); } + VGUI_Inv_GearItem *VGUI_InventoryPanel::AddGearItem(gearitem_t &GearItem) { if (GearItemButtonTotal >= MAX_CONTAINERS) @@ -196,6 +213,7 @@ void VGUI_InventoryPanel::Reset() GearItemButtons[i]->Reset(); GearItemButtonTotal = 0; } + void VGUI_InventoryPanel::Select(int Idx) { if (Idx < 0 || Idx >= GearItemButtonTotal) @@ -211,6 +229,7 @@ void VGUI_InventoryPanel::Select(int Idx) if (m_pCallbackPanel) m_pCallbackPanel->GearItemSelected(GearItemButton.m_GearItemID); } + bool VGUI_InventoryPanel::GearItemClicked(ulong ID) { if (ID < 0 || ID >= (unsigned)GearItemButtonTotal) @@ -225,11 +244,21 @@ bool VGUI_InventoryPanel::GearItemClicked(ulong ID) return false; } -// MIB FEB2015_21 [INV_SCROLL] - Pass it along to the container that's open (if any) -void VGUI_InventoryPanel::StepInput(bool bDirUp) +CTFScrollPanel* VGUI_InventoryPanel::GetScrollForStepInput() { - if ((int)GearItemButtons.size() > m_Selected && GearItemButtons[m_Selected]->m_ItemContainer) - GearItemButtons[m_Selected]->m_ItemContainer->StepInput(bDirUp); + if ( mbScrollHighlighted ) return m_Scroll; + + for (int i = 0; i < GearItemButtons.size(); i++) + { + if (GearItemButtons[i]->IsMouseOver()) + { + return m_Scroll; + } + } + + if (static_cast(GearItemButtons.size()) > m_Selected && GearItemButtons[ m_Selected ]->m_ItemContainer) + return GearItemButtons[m_Selected]->m_ItemContainer->GetScrollForStepInput(); + return nullptr; } bool VGUI_InventoryPanel::GearItemDoubleClicked(ulong ID) @@ -244,10 +273,17 @@ bool VGUI_InventoryPanel::GearItemDoubleClicked(ulong ID) return false; } -#define INFOPANEL_X GEARPNL_X -#define INFOPANEL_Y GEARPNL_Y + YRES(180) +// wtf is with the overuse of macros here....... +#define GOLDLABEL_SPACER_Y YRES(5) +#define GOLDLABEL_X GEARPNL_X +#define GOLDLABEL_Y (GEARPNL_Y + GEARPNL_SIZE_Y + GOLDLABEL_SPACER_Y) +#define GOLDLABEL_SIZE_X GEARPNL_SIZE_X +#define GOLDLABEL_SIZE_Y YRES(12) + +#define INFOPANEL_X GEARPNL_X +#define INFOPANEL_Y (GOLDLABEL_Y + GOLDLABEL_SIZE_Y + GOLDLABEL_SPACER_Y) #define INFOPANEL_SIZE_X GEARPNL_SIZE_X -#define INFOPANEL_SIZE_Y YRES(80) +#define INFOPANEL_SIZE_Y ((ITEM_CONTAINER_Y + ITEM_CONTAINER_SIZE_Y) - INFOPANEL_Y) //Info panel VGUI_ItemInfoPanel::VGUI_ItemInfoPanel(Panel *pParent) : CTransparentPanel(INVENTORY_TRANSPARENCY, INFOPANEL_X, INFOPANEL_Y, INFOPANEL_SIZE_X, INFOPANEL_SIZE_Y) @@ -284,6 +320,7 @@ VGUI_ItemInfoPanel::VGUI_ItemInfoPanel(Panel *pParent) : CTransparentPanel(INVEN m_Scroll->setScrollBarVisible(false, false); m_Scroll->validate(); } + void VGUI_ItemInfoPanel::Update(containeritem_t &Item) { m_Name->setText(Item.getFullName()); @@ -297,21 +334,20 @@ void VGUI_ItemInfoPanel::Update(containeritem_t &Item) // Creation VGUI_ContainerPanel::VGUI_ContainerPanel() : CMenuPanel(100, FALSE, 0, 0, ScreenWidth, ScreenHeight), VGUI_ItemCallbackPanel() { -#define TITLE_X ITEM_CONTAINER_X -#define TITLE_Y YRES(48) - COLOR Color_TitleText = COLOR(255, 100, 100, 0), Color_SubtitleText = COLOR(160, 160, 160, 0), Color_GoldText = COLOR(255, 255, 0, 0), - Color_TransparentTextBG = COLOR(0, 0, 0, 255); + Color_TransparentTextBG = COLOR(0, 0, 0, 255), + Color_Red = COLOR(255, 0, 0, 0), + Color_White = COLOR(255, 255, 255, 0); // Create the title - m_pTitle = new MSLabel(this, "Inventory", TITLE_X, TITLE_Y); + m_pTitle = new MSLabel(this, "Inventory", ITEM_CONTAINER_X, 0); m_pTitle->setFont(g_FontTitle); m_pTitle->SetFGColorRGB(Color_TitleText); // Create the Label - m_pSubtitle = new MSLabel(this, m_Text_DoubleClick, TITLE_X, TITLE_Y + m_pTitle->getTall() + YRES(4)); + m_pSubtitle = new MSLabel(this, m_Text_DoubleClick, ITEM_CONTAINER_X, 0 + m_pTitle->getTall() + YRES(4)); m_pSubtitle->SetFGColorRGB(Color_SubtitleText); //Create the panel showing all the gear I'm wearing @@ -320,54 +356,34 @@ VGUI_ContainerPanel::VGUI_ContainerPanel() : CMenuPanel(100, FALSE, 0, 0, Screen //Create the Info panel m_InfoPanel = new VGUI_ItemInfoPanel(this); - //Line separation - COLOR colTemp1 = COLOR(90, 90, 90, 128); - COLOR colTemp2 = COLOR(255, 0, 0, 0); - COLOR colTemp3 = COLOR(255, 255, 255, 0); - - new VGUI_Line((GEARPNL_X + GEARPNL_SIZE_X) + (GEARPNL_SPACER_X / 2.0f), GEARPNL_Y + LINESPACER_Y, ITEM_CONTAINER_SIZE_Y - (LINESPACER_Y * 2), false, colTemp1, this); - - //Line separation - new VGUI_Line(LINESPACER_Y, GEARPNL_Y + YRES(170), m_InfoPanel->getWide() - (LINESPACER_Y * 2), true, colTemp1, this); - -#define ACTBTN_SIZE_X XRES(100) -#define ACTBTN_SIZE_Y YRES(30) -#define ACTBTN_X (ITEM_CONTAINER_X + ITEM_CONTAINER_SIZE_X) - ACTBTN_SIZE_X -#define ACTBTN_Y ITEM_CONTAINER_Y + ITEM_CONTAINER_SIZE_Y - m_ActButton = new MSButton(this, Localized("#REMOVE"), ACTBTN_X, ACTBTN_Y, ACTBTN_SIZE_X, ACTBTN_SIZE_Y); m_ActButton->setFont(g_FontTitle); m_ActButton->setContentAlignment(vgui::Label::a_east); - m_ActButton->SetArmedColor(colTemp2); - m_ActButton->SetUnArmedColor(colTemp3); + m_ActButton->SetArmedColor(Color_Red); + m_ActButton->SetUnArmedColor(Color_White); -#define BUTTON_CANCEL_SIZE_X XRES(40) -#define BUTTON_CANCEL_SIZE_Y YRES(13) - -//Create the Gold display labal -#define GOLDLABEL_X GEARPNL_X -#define GOLDLABEL_Y GEARPNL_Y + YRES(150) -#define GOLDLABEL_SIZE_X GEARPNL_SIZE_X -#define GOLDLABEL_SIZE_Y YRES(12) + #define BUTTON_CANCEL_SIZE_X XRES(40) + #define BUTTON_CANCEL_SIZE_Y YRES(13) + //Create the Gold display labal m_GoldLabel = new MSLabel(this, "", GOLDLABEL_X, GOLDLABEL_Y, GOLDLABEL_SIZE_X, GOLDLABEL_SIZE_Y, MSLabel::a_center); m_GoldLabel->setFont(g_FontTitle); m_GoldLabel->SetFGColorRGB(Color_GoldText); // Create the Cancel button - m_pCancelButton = new MSButton(this, Localized("#CANCEL"), (ITEM_CONTAINER_X + ITEM_CONTAINER_SIZE_X) - BUTTON_CANCEL_SIZE_X, ITEM_CONTAINER_Y - BUTTON_CANCEL_SIZE_Y, BUTTON_CANCEL_SIZE_X, BUTTON_CANCEL_SIZE_Y); + m_pCancelButton = new MSButton(this, Localized("#CANCEL"), (ITEM_CONTAINER_X + ITEM_CONTAINER_SIZE_X) - BUTTON_CANCEL_SIZE_X, ITEM_CONTAINER_Y - BUTTON_CANCEL_SIZE_Y, BUTTON_CANCEL_SIZE_X,BUTTON_CANCEL_SIZE_Y); m_pCancelButton->setFont(g_FontID); m_pCancelButton->addActionSignal(new CMenuHandler_TextWindow(HIDE_TEXTWINDOW)); - m_pCancelButton->SetArmedColor(colTemp2); + m_pCancelButton->SetArmedColor(Color_Red); m_pCancelButton->SetUnArmedColor(Color_TextNormal); - m_AllowUpdate = m_bIsOpened = false; + m_AllowUpdate = false; } // Update void VGUI_ContainerPanel::Update() { - if (!m_AllowUpdate || !m_bIsOpened) + if (!m_AllowUpdate) return; m_GearPanel->Reset(); @@ -377,12 +393,13 @@ void VGUI_ContainerPanel::Update() removeChild(m_pCancelButton); m_pCancelButton->setParent(this); - msstring sGold; - _snprintf(sGold, MSSTRING_SIZE, Localized("#PLAYER_GOLD"), player.m_Gold); + char sGold[255]; + snprintf(sGold, 255, Localized("#PLAYER_GOLD"), player.m_Gold); m_GoldLabel->setText(sGold); m_AllowUpdate = false; } + void VGUI_ContainerPanel::AddInventoryItems() { gearitem_t GearItem; @@ -463,17 +480,38 @@ class InvTypeButtonSignal : public ActionSignal gEngfuncs.Cvar_SetValue("ms_invtype", m_iInvType); m_pCallbackPanel->Update(); m_pCallbackPanel->m_pScrollPanel->setScrollValue(0, 0); // Reset scroll bar + m_pCallbackPanel->m_CallbackPanel->InvTypeChanged( m_iInvType ); + } +}; + +// MIB FEB2019_25 [ALPHABETICAL_INVENTORY] +class AlphabetizeCheckBoxHandler : public VGUI_CheckBoxHandler +{ +private: + class VGUI_Container *m_pCallbackPanel; +public: + AlphabetizeCheckBoxHandler( VGUI_Container *pCallbackPanel ) + { + m_pCallbackPanel = pCallbackPanel; + } + + virtual void CheckChange(VGUI_CheckBox *pButton) + { + gEngfuncs.Cvar_SetValue("ms_alpha_inventory", pButton->IsChecked() ? 1 : 0); + m_pCallbackPanel->Update(); + m_pCallbackPanel->m_CallbackPanel->AlphabeticChanged(pButton->IsChecked()); } }; -#define INVTYPE_PANEL_X ITEM_CONTAINER_X -#define INVTYPE_PANEL_Y ITEM_CONTAINER_Y + ITEM_CONTAINER_SIZE_Y +// MIB FEB2019_25 [ALPHABETICAL_INVENTORY] +#define INVTYPE_PANEL_X ITEM_CONTAINER_X +#define INVTYPE_PANEL_Y (ITEM_CONTAINER_Y + ITEM_CONTAINER_SIZE_Y) + YRES(30) #define INVTYPE_PANEL_SIZE_X ITEM_CONTAINER_SIZE_X - ACTBTN_SIZE_X -#define INVTYPE_PANEL_SIZE_Y YRES(30) +#define INVTYPE_PANEL_SIZE_Y YRES(64) #define INVTYPE_BUTTON_SIZE_X XRES(80) #define INVTYPE_BUTTON_SIZE_Y YRES(15) -#define INVTYPE_BUTTON_Y (INVTYPE_PANEL_SIZE_Y / 2.0) - (INVTYPE_BUTTON_SIZE_Y / 2.0) -#define INVTYPE_BUTTON_X_SPACER XRES(12) +#define INVTYPE_BUTTON_X_SPACER XRES(12) +#define INVTYPE_BUTTON_Y_SPACER YRES(12) // MiB FEB2015_07 - Inventory type buttons VGUI_InvTypePanel::VGUI_InvTypePanel(Panel *pParent, VGUI_Container *pCallback) : CTransparentPanel(0, INVTYPE_PANEL_X, INVTYPE_PANEL_Y, INVTYPE_PANEL_SIZE_X, INVTYPE_PANEL_SIZE_Y) @@ -481,18 +519,23 @@ VGUI_InvTypePanel::VGUI_InvTypePanel(Panel *pParent, VGUI_Container *pCallback) setParent(pParent); const char ButtonText[INVTYPE_BUTTONS_TOTAL][16] = {"Tiled", "Small", "Descriptions"}; + pAlphaCheckBox = new VGUI_CheckBox("Alphabetic", INVTYPE_BUTTON_X_SPACER, INVTYPE_BUTTON_SIZE_Y + INVTYPE_BUTTON_Y_SPACER, INVTYPE_BUTTON_SIZE_X, INVTYPE_BUTTON_SIZE_Y, pCallback->IsAlphabetical()); + pAlphaCheckBox->setVisible(true); + pAlphaCheckBox->SetHandler(new AlphabetizeCheckBoxHandler(pCallback)); + addChild(pAlphaCheckBox); + for (int i = 0; i < INVTYPE_BUTTONS_TOTAL; i++) { int x = 0, y; if (i) { - ClassButton *pLast = InvTypeButtons[i - 1]; + ClassButton *pLast = InvTypeButtons[i-1]; pLast->getPos(x, y); x += pLast->getWide(); } - ClassButton *pCur = new ClassButton(0, ButtonText[i], x + INVTYPE_BUTTON_X_SPACER, INVTYPE_BUTTON_Y, INVTYPE_BUTTON_SIZE_X, INVTYPE_BUTTON_SIZE_Y, false); + ClassButton *pCur = new ClassButton(0, ButtonText[i], x + INVTYPE_BUTTON_X_SPACER, 0, INVTYPE_BUTTON_SIZE_X, INVTYPE_BUTTON_SIZE_Y, false); pCur->setContentAlignment(vgui::Label::Alignment::a_center); pCur->setVisible(true); pCur->addActionSignal(new InvTypeButtonSignal(i, pCallback)); @@ -506,17 +549,18 @@ VGUI_InvTypePanel::VGUI_InvTypePanel(Panel *pParent, VGUI_Container *pCallback) void VGUI_ContainerPanel::Open(void) { // Update before opening - m_AllowUpdate = m_bIsOpened = true; + m_AllowUpdate = true; Update(); CMenuPanel::Open(); } + void VGUI_ContainerPanel::Close(void) { player.BlockButton(IN_ATTACK); m_pCancelButton->setArmed(false); //If the user presses cancel, the cancel button doesn't automaticaly get unarmed... so manually do it m_ActButton->setArmed(false); CMenuPanel::Close(); - m_AllowUpdate = m_bIsOpened = false; + m_AllowUpdate = false; } bool VGUI_ContainerPanel::SlotInput(int iSlot) { @@ -548,6 +592,22 @@ void VGUI_ContainerPanel::ItemHighlighted(void *pData) m_InfoPanel->Update(ItemButton.m_Data); } +bool VGUI_ContainerPanel::HasSelectedItems() +{ + for(int i = 0; i < m_GearPanel->GearItemButtonTotal; i++) + { + VGUI_Inv_GearItem &GearItem = *m_GearPanel->GearItemButtons[i]; + for(int g = 0; g < GearItem.m_ItemContainer->m_ItemButtonTotal; g++) + { + VGUI_ItemButton &ItemButton = *GearItem.m_ItemContainer->m_ItemButtons[g]; + if(ItemButton.m_Selected) + return true; + } + } + + return false; +} + void VGUI_ContainerPanel::GetSelectedItems(mslist &SelectedItems) { SelectedItems.clear(); diff --git a/src/game/client/ui/ms/vgui_container.h b/src/game/client/ui/ms/vgui_container.h index a028bcd2..96787602 100644 --- a/src/game/client/ui/ms/vgui_container.h +++ b/src/game/client/ui/ms/vgui_container.h @@ -7,17 +7,22 @@ #define CLASSMENU_BUTTON_SPACER_X XRES(6) #define CLASSMENU_BUTTON_SPACER_Y ((LABEL_ITEMNAME_SIZE_Y + LABEL_ITEM_SPACER_Y) * STORE_INFO_LABELS + YRES(6)) -#define GEARPNL_X XRES(0) -#define GEARPNL_Y YRES(110) -#define GEARPNL_SIZE_X (128 + XRES(10)) -#define GEARPNL_SIZE_Y YRES(145) +#define CONTAINERMENU_SPACER_X XRES(15) -#define GEARPNL_SPACER_X XRES(15) +#define GEARPNL_X CONTAINERMENU_SPACER_X +#define GEARPNL_Y YRES(50) +#define GEARPNL_SIZE_X YRES(80) +#define GEARPNL_SIZE_Y YRES(235) -#define ITEM_CONTAINER_X (GEARPNL_X + GEARPNL_SIZE_X) + GEARPNL_SPACER_X +#define ITEM_CONTAINER_X (GEARPNL_X + GEARPNL_SIZE_X) + CONTAINERMENU_SPACER_X #define ITEM_CONTAINER_Y GEARPNL_Y -#define ITEM_CONTAINER_SIZE_X XRES(440) -#define ITEM_CONTAINER_SIZE_Y YRES(260) +#define ITEM_CONTAINER_SIZE_X (ScreenWidth - (ITEM_CONTAINER_X + CONTAINERMENU_SPACER_X)) +#define ITEM_CONTAINER_SIZE_Y YRES(340) + +#define ACTBTN_SIZE_X XRES(130) +#define ACTBTN_SIZE_Y YRES(30) +#define ACTBTN_X (ITEM_CONTAINER_X + ITEM_CONTAINER_SIZE_X) - ACTBTN_SIZE_X +#define ACTBTN_Y ITEM_CONTAINER_Y + ITEM_CONTAINER_SIZE_Y #define MAX_CONTAINERS 32 @@ -40,6 +45,7 @@ class VGUI_Inv_GearItem : public CTransparentPanel VGUI_Container *m_ItemContainer; class CHandler_GearButton *m_pSignal; gearitem_t m_GearItem; //Determines where to obtain my list of items + bool mbMouseOver; VGUI_Inv_GearItem(Panel *pContainerParent, VGUI_ItemCallbackPanel *pItemCallbackPanel, VGUI_ItemCallbackPanel *pGearCallback, Panel *pParent); ~VGUI_Inv_GearItem(); @@ -48,17 +54,19 @@ class VGUI_Inv_GearItem : public CTransparentPanel void Reset(); void Select(); void DeSelect(); + bool IsMouseOver() { return mbMouseOver; } }; -class VGUI_InventoryPanel : public CTransparentPanel, public VGUI_ItemCallbackPanel +class VGUI_InventoryPanel : public CTransparentPanel, public VGUI_ItemCallbackPanel, public CCursorMovementHandler { public: - mslist GearItemButtons; + mslist GearItemButtons; int GearItemButtonTotal; int m_Selected; int m_InitializedItemButtons; VGUI_ItemCallbackPanel *m_pCallbackPanel; CTFScrollPanel *m_Scroll; + bool mbScrollHighlighted; VGUI_InventoryPanel(VGUI_ItemCallbackPanel *pCallbackPanel, Panel *pParent); @@ -70,7 +78,10 @@ class VGUI_InventoryPanel : public CTransparentPanel, public VGUI_ItemCallbackPa bool GearItemClicked(ulong ID); bool GearItemDoubleClicked(ulong ID); - void StepInput(bool bDirUp); // MIB FEB2015_21 [INV_SCROLL] + virtual CTFScrollPanel *GetScrollForStepInput(); + + virtual void cursorEntered( Panel *pPanel ) { mbScrollHighlighted = true; } + virtual void cursorExited( Panel *pPanel ) { mbScrollHighlighted = false; } }; class VGUI_ItemInfoPanel : public CTransparentPanel @@ -88,18 +99,19 @@ class VGUI_ItemInfoPanel : public CTransparentPanel class VGUI_ContainerPanel : public CMenuPanel, public VGUI_ItemCallbackPanel { protected: - Label *m_pTitle, - *m_pSubtitle; + Label *m_pTitle, *m_pSubtitle; MSLabel *m_GoldLabel; MSButton *m_pCancelButton; VGUI_InventoryPanel *m_GearPanel; VGUI_ItemInfoPanel *m_InfoPanel; MSButton *m_ActButton; + bool m_AllowUpdate; public: static const char *m_Text_DoubleClick; VGUI_ContainerPanel(); + virtual bool HasSelectedItems(); virtual void GetSelectedItems(mslist &SelectedItems); //in, out virtual void UnSelectAllItems(); virtual void AddInventoryItems(); @@ -112,10 +124,8 @@ class VGUI_ContainerPanel : public CMenuPanel, public VGUI_ItemCallbackPanel //Callbacks virtual void ItemHighlighted(void* pData); - virtual void ItemCreated(void* pData) { m_AllowUpdate = true; } - bool m_AllowUpdate; - bool m_bIsOpened; + virtual CTFScrollPanel *GetScrollForStepInput() { return m_GearPanel ? m_GearPanel->GetScrollForStepInput() : nullptr;} }; #endif //VGUI_CONTAINER_H diff --git a/src/game/client/ui/ms/vgui_containerlist.cpp b/src/game/client/ui/ms/vgui_containerlist.cpp index 693cd255..5986cf00 100644 --- a/src/game/client/ui/ms/vgui_containerlist.cpp +++ b/src/game/client/ui/ms/vgui_containerlist.cpp @@ -71,14 +71,13 @@ class CContainerInputHandler : public InputSignal virtual void keyFocusTicked(Panel *panel){}; }; -class CAction_RemoveGear : public ActionSignal +class CContainer_ActionButtonSignal : public ActionSignal { protected: CContainerPanel *m_Panel; - public: - CAction_RemoveGear(CContainerPanel *pPanel) { m_Panel = pPanel; } - virtual void actionPerformed(Panel *panel) { m_Panel->RemoveGear(); } + CContainer_ActionButtonSignal( CContainerPanel *pPanel ) { m_Panel = pPanel; } + virtual void actionPerformed(Panel* panel) { m_Panel->ActionPerformed(); } }; //------------ @@ -93,48 +92,101 @@ class CAction_RemoveGear : public ActionSignal // Creation CContainerPanel::CContainerPanel(int iTrans, int iRemoveMe, int x, int y, int wide, int tall) : VGUI_ContainerPanel() { + addChild(mpMoveItemPanel = new VGUI_MoveItemPanel(this)); m_pCancelButton->setText(Localized("#CLOSE")); - m_ActButton->addActionSignal(new CAction_RemoveGear(this)); - //m_ActButton->setVisible( false ); + m_ActButton->addActionSignal(new CContainer_ActionButtonSignal(this)); + m_ActButton->setVisible(true); +} + +void CContainerPanel::ActionPerformed() +{ + mpMoveItemPanel->setVisible(false); + if (HasSelectedItems()) + { + DropAllSelected(); + } + else + { + RemoveGear(); + } +} + +void CContainerPanel::InvTypeChanged(int vInvType) +{ + VGUI_ItemCallbackPanel::InvTypeChanged(vInvType); + mpMoveItemPanel->setVisible(false); } + +void CContainerPanel::AlphabeticChanged(bool bAlphabetic) +{ + VGUI_ItemCallbackPanel::AlphabeticChanged(bAlphabetic); + mpMoveItemPanel->setVisible(false); +} + void CContainerPanel::UpdateSubtitle() { mslist SelectedItems; GetSelectedItems(SelectedItems); VGUI_Inv_GearItem &GearButton = *m_GearPanel->GearItemButtons[m_GearPanel->m_Selected]; - m_ActButton->setText(Localized("#REMOVE")); if (!m_GearPanel->m_Selected || SelectedItems.size() > 0) { m_pSubtitle->setText("Click container to move selected item, or click again to equip"); - m_ActButton->setEnabled(false); - //if( SelectedItems.size() == 1 ) - // m_ActButton->setText( Localized("#USE") ); + if (!m_GearPanel->m_Selected) + { + m_ActButton->setVisible(false); + } + else + { + m_ActButton->setText("Drop Selected"); + m_ActButton->setVisible(true); + } } else { m_pSubtitle->setText(m_Text_DoubleClick); CGenericItem *pGearItem = player.GetGearItem(GearButton.m_GearItemID); - if (pGearItem) + if(pGearItem) { - if (!FBitSet(pGearItem->MSProperties(), ITEM_CONTAINER)) + if(!FBitSet(pGearItem->MSProperties(), ITEM_CONTAINER)) m_pSubtitle->setText("Remove wearable item"); } - m_ActButton->setEnabled(true); + m_ActButton->setText(Localized("#REMOVE")); + m_ActButton->setVisible(true); } GearButton.m_ItemContainer->setVisible(GearButton.m_GearItem.IsContainer); } + void CContainerPanel::RemoveGear() { msstring Cmd = msstring("remove ") + m_GearPanel->GearItemButtons[m_GearPanel->m_Selected]->m_GearItemID + "\n"; ServerCmd(Cmd); gViewPort->HideTopMenu(); } + +void CContainerPanel::DropAllSelected() +{ + mslist vSelectedItems; + GetSelectedItems( vSelectedItems ); + for(int i = 0; i < vSelectedItems.size(); i++) + { + ServerCmd( msstring("drop ") + (int)vSelectedItems[i]->m_Data.ID + "\n" ); + } + gViewPort->HideTopMenu(); +} + void CContainerPanel::ItemSelectChanged(ulong ID, bool fSelected) { UpdateSubtitle(); } + +bool CContainerPanel::ItemClicked(void *pData) +{ + mpMoveItemPanel->setVisible( false ); + return false; // Let the button finish handling +} + void CContainerPanel::ItemDoubleclicked(ulong ID) { if (m_GearPanel->m_Selected == 0) @@ -152,12 +204,57 @@ void CContainerPanel::ItemDoubleclicked(ulong ID) //if( pItem->GiveTo( &player, false, false ) ) // { char sz[32]; - _snprintf(sz, sizeof(sz), "inv transfer %u 0", pItem->m_iId ); + _snprintf(sz, sizeof(sz), "inv transfer %u 0", pItem->m_iId); gEngfuncs.pfnClientCmd(sz); gViewPort->HideTopMenu(); // } } + +void CContainerPanel::ItemRightClicked(void *pData) +{ + mslist vSelectedItems; + VGUI_ItemButton *pButton = static_cast(pData); + containeritem_t vItem = pButton->m_Data; + + // Don't do it if any other items are selected, + // because... Okay, I don't have a good reason, + // just seems wrong. + GetSelectedItems(vSelectedItems); + if (vSelectedItems.size() > 1 || ( vSelectedItems.size() == 1 && vSelectedItems[0] != pButton)) + { + return; + } + + // Must be stackable + if (!FBitSet(vItem.Properties,ITEM_GROUPABLE)) + return; + + // Must have enough for at least the minimum + if (vItem.Quantity < gMoveNumbers[0]) + return; + + // Not when already in the hands + if (!m_GearPanel->m_Selected) + return; + + // Remove then add so it's on top + removeChild(mpMoveItemPanel); + addChild(mpMoveItemPanel); + + mpMoveItemPanel->ShowForButton(pButton); +} + +void CContainerPanel::MoveItem(VGUI_ItemButton *pButton, int vNumMove) +{ + if ( !vNumMove ) + return; // Sanity + + char pszCommand[128]; + snprintf(pszCommand, sizeof(pszCommand), "inv split %i %i\n", pButton->m_Data.ID, vNumMove); + ServerCmd(pszCommand); +} + void CContainerPanel::GearItemSelected(ulong ID) { //Unselect all items @@ -178,6 +275,7 @@ void CContainerPanel::GearItemSelected(ulong ID) m_pTitle->setText(Title); UpdateSubtitle(); } + bool CContainerPanel::GearItemClicked(ulong ID) { mslist SelectedItems; @@ -218,6 +316,7 @@ bool CContainerPanel::GearItemClicked(ulong ID) return true; } + bool CContainerPanel::GearItemDoubleClicked(ulong ID) { CGenericItem *pWornItem = player.GetGearItem(ID); @@ -227,10 +326,11 @@ bool CContainerPanel::GearItemDoubleClicked(ulong ID) if (!pWornItem->IsWorn()) return false; - m_ActButton->doClick(); //Remove the item + RemoveGear(); return true; } + // Update void CContainerPanel::Close(void) { @@ -239,13 +339,6 @@ void CContainerPanel::Close(void) VGUI_ContainerPanel::Close(); } -// MIB FEB2015_21 [INV_SCROLL] - Pass to the gear panel -void CContainerPanel::StepInput(bool bDirUp) -{ - if (m_GearPanel) - m_GearPanel->StepInput(bDirUp); -} - //====================================== // Update the Class menu before opening it void CContainerPanel::Open(void) @@ -291,14 +384,15 @@ void ContainerWindowOpen(ulong ContainerID) gViewPort->m_pContainerMenu->m_OpenContainerID = ContainerID; ShowVGUIMenu(MENU_CONTAINER); } + void ContainerWindowUpdate() { if (!gViewPort || !gViewPort->m_pContainerMenu) return; - gViewPort->m_pContainerMenu->m_AllowUpdate = true; gViewPort->m_pContainerMenu->Update(); } + void ContainerWindowClose() { gViewPort->HideTopMenu(); diff --git a/src/game/client/ui/ms/vgui_containerlist.h b/src/game/client/ui/ms/vgui_containerlist.h index 9d199fb2..6fe4de30 100644 --- a/src/game/client/ui/ms/vgui_containerlist.h +++ b/src/game/client/ui/ms/vgui_containerlist.h @@ -1,4 +1,5 @@ #include "vgui_storemainwin.h" +#include "vgui_moveitempanel.h" class ContainerButton; #define CONTAINER_INFO_LABELS 1 @@ -7,12 +8,16 @@ class ContainerButton; class CContainerPanel : public VGUI_ContainerPanel { +private: + VGUI_MoveItemPanel *mpMoveItemPanel; + public: ulong m_OpenContainerID; CContainerPanel(int iTrans, int iRemoveMe, int x, int y, int wide, int tall); void UpdateSubtitle(); void RemoveGear(); + void DropAllSelected(); virtual void Open(void); virtual void Close(void); @@ -24,5 +29,13 @@ class CContainerPanel : public VGUI_ContainerPanel bool GearItemDoubleClicked(ulong ID); void ItemDoubleclicked(ulong ID); + virtual void ItemRightClicked(void *pData); + virtual void MoveItem(VGUI_ItemButton *pButton, int vNumMove); + virtual bool ItemClicked(void *pData); + virtual void InvTypeChanged(int vInvType); + virtual void AlphabeticChanged(bool bAlphabetic); + + void ActionPerformed(); + void StepInput(bool bDirUp); // MIB FEB2015_21 [INV_SCROLL] }; \ No newline at end of file diff --git a/src/game/client/ui/ms/vgui_moveitempanel.cpp b/src/game/client/ui/ms/vgui_moveitempanel.cpp new file mode 100644 index 00000000..ee417289 --- /dev/null +++ b/src/game/client/ui/ms/vgui_moveitempanel.cpp @@ -0,0 +1,94 @@ +#include "../hud.h" +#include "../cl_util.h" +#include "vgui_teamfortressviewport.h" +#include "sharedutil.h" +#include "vgui_moveitempanel.h" +#include "vgui_containerlist.h" + +VGUI_MoveItemPanel::VGUI_MoveItemPanel(CContainerPanel *pParent) : CTransparentPanel(80, 0, 0, 0, 0) +{ + vgui::Font *pFont = g_FontSml; + int vButtonHeight = g_FontSml->getTall(); + int y = 0; + int w = 0; + + for(int i = 0; i < gNumMoveNumbers + 1; i++) + { + int vNumMove; + msstring vsText; + if (i == gNumMoveNumbers) + { + vNumMove = 0; + vsText = "Cancel"; + } + else + { + vNumMove = gMoveNumbers[i]; + vsText = msstring("Move ") + vNumMove + " To Hands"; + } + + int vButtonW; + int vButtonH; + pFont->getTextSize(vsText, vButtonW, vButtonH); + MSButton *pButton = new MSButton(this, "", XRES(5), y + YRES(5), vButtonW, vButtonH, COLOR(255, 0, 0, 0), COLOR(100, 100, 100, 0)); + pButton->setText(vsText); + pButton->setFont(pFont); + pButton->setContentAlignment(vgui::Label::Alignment::a_west); + pButton->addActionSignal(new CMoveItemSignal(this, vNumMove)); + mButtons.add(pButton); + pButton->setVisible(true); + + y += vButtonH; + w = V_max(w, vButtonW); + } + + setSize(w + XRES(10), y + YRES(10)); + setParent(mpParent = pParent); + setVisible(false); + setBorder(new LineBorder(2, Color(0,128,0,128))); +} + +void VGUI_MoveItemPanel::ShowForButton(VGUI_ItemButton *pButton) +{ + mpCurrentItemButton = pButton; + int x, y, w, h; + + // Move to be over the clicked button + pButton->getAbsExtents(x, y, w, h); + setPos(x,y); + + for(int i = 0; i < gNumMoveNumbers; i++) + { + mButtons[i]->setEnabled(pButton->m_Data.Quantity >= gMoveNumbers[i]); + } + + setVisible(true); +} + +void VGUI_MoveItemPanel::Move(int vNumMove) +{ + if (vNumMove) + mpParent->MoveItem(mpCurrentItemButton, vNumMove); + + setVisible(false); +} + +void VGUI_MoveItemPanel::setVisible(bool bVisible) +{ + CTransparentPanel::setVisible(bVisible); + for(int i = 0; i < gNumMoveNumbers + 1; i++) + { + mButtons[i]->setArmed(false); + } +} + +CMoveItemSignal::CMoveItemSignal(VGUI_MoveItemPanel *pMoveItemPanel, int vNumMove) +{ + mpMoveItemPanel = pMoveItemPanel; + mNumMove = vNumMove; +} + +void CMoveItemSignal::actionPerformed(Panel *pPanel) +{ + mpMoveItemPanel->Move(mNumMove); +} \ No newline at end of file diff --git a/src/game/client/ui/ms/vgui_moveitempanel.h b/src/game/client/ui/ms/vgui_moveitempanel.h new file mode 100644 index 00000000..01552346 --- /dev/null +++ b/src/game/client/ui/ms/vgui_moveitempanel.h @@ -0,0 +1,35 @@ +// vgui_MoveItemPanel by MiB, for the "Move X to hand" pop-up +#ifndef MOVEITEMPANEL_H +#define MOVEITEMPANEL_H + +#include "vgui_mscontrols.h" + +static const int gNumMoveNumbers = 5; +static const int gMoveNumbers[ gNumMoveNumbers ] = { 5, 10, 25, 50, 100 }; + +class VGUI_MoveItemPanel : public CTransparentPanel +{ +private: + mslist mButtons; + CContainerPanel *mpParent; + VGUI_ItemButton *mpCurrentItemButton; + +public: + VGUI_MoveItemPanel(CContainerPanel *pParent); + void ShowForButton(VGUI_ItemButton *pButton); + void Move(int vNumMove); + virtual void setVisible(bool bVisible); +}; + +class CMoveItemSignal : public ActionSignal +{ +private: + VGUI_MoveItemPanel *mpMoveItemPanel; + int mNumMove; + +public: + CMoveItemSignal(VGUI_MoveItemPanel *pMoveItemPanel, int vNumMove); + void actionPerformed(Panel *pPanel); +}; + +#endif // MOVEITEMPANEL_H \ No newline at end of file diff --git a/src/game/client/ui/ms/vgui_mscontrols.cpp b/src/game/client/ui/ms/vgui_mscontrols.cpp index a62521d9..b2a8fe2c 100644 --- a/src/game/client/ui/ms/vgui_mscontrols.cpp +++ b/src/game/client/ui/ms/vgui_mscontrols.cpp @@ -295,15 +295,35 @@ class CHandler_ItemButton : public InputSignal { private: VGUI_ItemButton *m_pItemButton; + VGUI_DoubleClickDetector *mpDoubleClickDetector; + public: - CHandler_ItemButton( VGUI_ItemButton *pItemButton ) + CHandler_ItemButton(VGUI_ItemButton *pItemButton, VGUI_DoubleClickDetector* pDoubleClickDetector) { m_pItemButton = pItemButton; + mpDoubleClickDetector = pDoubleClickDetector; } - void cursorEntered( Panel *panel ) { m_pItemButton->Highlight( true ); } - void cursorExited( Panel* panel ) { m_pItemButton->Highlight( false ); }; - void mousePressed( MouseCode code,Panel* panel ) { m_pItemButton->Clicked( ); }; + void cursorEntered(Panel *panel) { m_pItemButton->Highlight(true); } + void cursorExited(Panel* panel) { m_pItemButton->Highlight(false); }; + void mousePressed(MouseCode code,Panel* panel) + { + if (code == MOUSE_LEFT) + { + if ( mpDoubleClickDetector->Click(this, code) && m_pItemButton->m_Selected) + { + mouseDoublePressed(code, panel); + } + else + { + m_pItemButton->Clicked(); + } + } + else if (code == MOUSE_RIGHT) + { + m_pItemButton->RightClicked(); + } + }; void cursorMoved(int x,int y,Panel* panel) {}; void mouseReleased(MouseCode code,Panel* panel) {}; void mouseDoublePressed( MouseCode code, Panel* panel ) { m_pItemButton->Doubleclicked( ); }; @@ -353,8 +373,9 @@ VGUI_ItemButton::VGUI_ItemButton( int x, int y, VGUI_ItemCallbackPanel *pCallbac m_Button = new CTransparentPanel( 0, 0, 0, getWide(), getTall() ); m_Button->setParent( this ); - m_Button->addInputSignal( m_Signal = new CHandler_ItemButton( this ) ); + m_Button->addInputSignal( m_Signal = new CHandler_ItemButton( this, pCallbackPanel ) ); } + /*VGUI_ItemButton::~VGUI_ItemButton( ) { removeChild( Image ); @@ -367,6 +388,7 @@ VGUI_ItemButton::VGUI_ItemButton( int x, int y, VGUI_ItemCallbackPanel *pCallbac delete Labels[i]; } }*/ + void VGUI_ItemButton::SetItem( containeritem_t &Item ) { m_Data = Item; @@ -468,38 +490,44 @@ void VGUI_ItemButton::Update( ) setVisible( true ); m_Button->setEnabled( !m_Data.Disabled ); } + void VGUI_ItemButton::Reset( ) { setVisible( false ); m_Selected = false; m_Highlighted = false; } + void VGUI_ItemButton::Clicked( ) { - if( m_Selected ) - { - Doubleclicked(); //MAY2013_15 Thothie Fake Double Click - } - else - { - if( !m_CallbackPanel || !m_CallbackPanel->ItemClicked( this ) ) - Select( !m_Selected ); - } + if( !m_CallbackPanel || !m_CallbackPanel->ItemClicked( this ) ) + Select( !m_Selected ); +} + +void VGUI_ItemButton::RightClicked() +{ + if ( m_CallbackPanel ) + m_CallbackPanel->ItemRightClicked(this); } + void VGUI_ItemButton::Doubleclicked( ) { - if( m_CallbackPanel ) m_CallbackPanel->ItemDoubleclicked( m_Data.ID ); + if( m_CallbackPanel ) + m_CallbackPanel->ItemDoubleclicked( m_Data.ID ); } + void VGUI_ItemButton::Select( bool fSelect ) { m_Selected = fSelect; - if( m_CallbackPanel ) m_CallbackPanel->ItemSelectChanged( m_Data.ID, m_Selected ); + if( m_CallbackPanel ) + m_CallbackPanel->ItemSelectChanged( m_Data.ID, m_Selected ); } void VGUI_ItemButton::Highlight( bool fSelect ) { m_Highlighted = fSelect; - if( m_CallbackPanel ) m_CallbackPanel->ItemHighlighted( this ); + if( m_CallbackPanel ) + m_CallbackPanel->ItemHighlighted( this ); //if( !m_Highlighted ) } @@ -536,7 +564,7 @@ void VGUI_ItemButton::paint( ) } m_Image.SetFGColorRGB( ImageColor ); - for (int i = 0; i < ITEMBTN_LABELS_MAX; i++) + for (int i = 0; i < ITEMBTN_LABELS_MAX; i++) m_Labels[i]->SetFGColorRGB( LabelColor ); m_Description->SetFGColorRGB( LabelColor ); } @@ -577,17 +605,6 @@ class CHandler_ScrollPanel : public InputSignal void keyFocusTicked(Panel* panel) { } }; -// MIB FEB2015_21 [INV_SCROLL] - Do the actual moving of the scroll bar -void VGUI_Container::StepInput( bool bDirUp ) -{ - int h, v, ScrollAmount = 20; // MIB FEB2015_21 [INV_SCROLL] - Change this if you want to alter the scroll sensitivity - if ( m_pScrollPanel ) - { - m_pScrollPanel->getScrollValue( h, v ); - m_pScrollPanel->setScrollValue( h, v - (bDirUp ? ScrollAmount : -ScrollAmount) ); - } -} - // Container Creation VGUI_Container::VGUI_Container( int x, int y, int w, int h, VGUI_ItemCallbackPanel *pCallbackPanel, Panel *pParent ) : CTransparentPanel( INVENTORY_TRANSPARENCY, x, y, w, h ) @@ -627,25 +644,83 @@ VGUI_ItemButton *VGUI_Container::AddItem( containeritem_t &Item ) { //Initialize the item button m_ItemButtons.add( new VGUI_ItemButton( 0, 0, m_CallbackPanel, m_pScrollPanel ) ); // // MiB FEB2015_07 - Set position in UpdatePosition + m_AlphabetizedItemButtons.add( m_ItemButtons[m_ItemButtonTotal] ); m_InitializedItemButtons++; } VGUI_ItemButton &NewItemButton = *m_ItemButtons[m_ItemButtonTotal]; NewItemButton.SetItem( Item ); - UpdatePosition( m_ItemButtonTotal ); - m_ItemButtonTotal++; - m_NoItems->setVisible( false ); - m_pScrollPanel->validate( ); + // MiB FEB2019_24 [ALPHABETICAL_INVENTORY] + int iAlphaLoc = 0; + if (!m_ItemButtonTotal) + { + m_AlphabetizedItemButtons[0] = &NewItemButton; + } + else + { + // Find the location of this item + msstring sNewItemName = Item.getFullName(); + + // Walk the list backwards + for (int i = m_ItemButtonTotal - 1; i >= 0; --i) + { + msstring sCurItemName = m_AlphabetizedItemButtons[i]->m_Data.getFullName(); + + // If i-button's name < new name, add at i+1 and break + if (_stricmp(sCurItemName, sNewItemName) <= 0) + { + iAlphaLoc = i+1; + m_AlphabetizedItemButtons[iAlphaLoc] = &NewItemButton; + break; + } + // Else move i-button to i+1 and continue + else + { + m_AlphabetizedItemButtons[i+1] = m_AlphabetizedItemButtons[i]; + // That was the last one, set to the beginning + if ( i == 0 ) + { + m_AlphabetizedItemButtons[0] = &NewItemButton; + break; + } + } + } + } + + m_NoItems->setVisible(false); + m_ItemButtonTotal++; + if (IsAlphabetical()) + { + // Need to update everything at the new location and after + for(int i = iAlphaLoc; i < m_ItemButtonTotal; ++i) + { + UpdatePosition(i); + } + } + else + { + UpdatePosition(m_ItemButtonTotal-1); + } + m_pScrollPanel->validate(); return &NewItemButton; } void VGUI_Container::Update( ) { - for (int i = 0; i < m_ItemButtonTotal; i++) + bool bIsAlpha = IsAlphabetical(); + for (int i = 0; i < m_ItemButtonTotal; i++) { - m_ItemButtons[i]->Update( ); + // MiB FEB2019_24 [ALPHABETICAL_INVENTORY] + if ( bIsAlpha ) + { + m_AlphabetizedItemButtons[i]->Update(); + } + else + { + m_ItemButtons[i]->Update( ); + } UpdatePosition( i ); } m_pScrollPanel->validate(); @@ -658,8 +733,17 @@ void VGUI_Container::UpdatePosition( int idx ) //Find the spot for this item if( idx ) { - VGUI_ItemButton &LastItemButton = *m_ItemButtons[idx-1]; - LastItemButton.getPos( x, y ); + // MiB FEB2019_24 [ALPHABETICAL_INVENTORY] + VGUI_ItemButton *LastItemButton = nullptr; + if ( IsAlphabetical() ) + { + LastItemButton = m_AlphabetizedItemButtons[idx-1]; + } + else + { + LastItemButton = m_ItemButtons[idx-1]; + } + LastItemButton->getPos( x, y ); switch( atoi(gEngfuncs.pfnGetCvarString("ms_invtype")) ) { case INVTYPE_ORIGINAL: // Original @@ -668,11 +752,11 @@ void VGUI_Container::UpdatePosition( int idx ) [ icon 1 ] [ icon 2 ] [Item Name1] [Item Name2] */ - x += LastItemButton.getWide( ); - if( x + LastItemButton.getWide( ) >= (m_pScrollPanel->getWide() - m_pScrollPanel->getVerticalScrollBar()->getWide()) ) + x += LastItemButton->getWide(); + if(x + LastItemButton->getWide() >= (m_pScrollPanel->getWide() - m_pScrollPanel->getVerticalScrollBar()->getWide())) { x = 0; - y += LastItemButton.getTall( ); + y += LastItemButton->getTall(); } } break; @@ -694,12 +778,19 @@ void VGUI_Container::UpdatePosition( int idx ) */ // Both require the same thing here: All the way to the left and on a new line x = 0; - y += LastItemButton.getTall( ); + y += LastItemButton->getTall( ); } break; } } - m_ItemButtons[idx]->setPos( x , y ); + if ( IsAlphabetical() ) + { + m_AlphabetizedItemButtons[idx]->setPos( x , y ); + } + else + { + m_ItemButtons[idx]->setPos( x , y ); + } } void VGUI_Container::PurgeButtons( ) @@ -763,3 +854,62 @@ void VGUI_TextPanel::KeyInput( int down, int keynum, const char *pszCurrentBindi AddLetter( Temp ); #endif } + +// MiB FEB2019_24 [ALPHABETICAL_INVENTORY] +VGUI_CheckBox::VGUI_CheckBox(const char *pszText, int x, int y, int w, int h, bool bStartChecked) + : Panel( x, y, w, h ) +{ + int vTmp; + mpHandler = nullptr; + SetChecked(bStartChecked); + SetArmed(false); + mpTextLabel = new Label(pszText); + mpTextLabel->getTextSize(vTmp,mCheckSquareSize); + mCheckSquareSize = V_min(mCheckSquareSize, h / 2); + mpTextLabel->setPos(CHECKBOX_LABELPOS_X, 0); + mpTextLabel->setSize(w - CHECKBOX_LABELPOS_X, h); + mpTextLabel->setBgColor(0, 0, 0, 255); + mpTextLabel->setParent(this); + mpTextLabel->setContentAlignment(Label::Alignment::a_west); + + // MiB Note: Make sure this is always last so the layering makes this on top + // Make the hitbox button cover the whole thing + mpOverlayButton = new CTransparentPanel(0, 0, 0, getWide(), getTall()); + mpOverlayButton->setParent(this); + mpOverlayButton->addInputSignal(new CheckHandler(this)); +} + +VGUI_CheckBox::~VGUI_CheckBox() +{ + if ( mpHandler ) + delete mpHandler; +} + +void VGUI_CheckBox::paint() +{ + Scheme::SchemeColor vSchemeColor = IsArmed() ? Scheme::sc_secondary2 : Scheme::sc_primary1; + + setFgColor(vSchemeColor); + mpTextLabel->setFgColor(vSchemeColor); + + drawSetColor(vSchemeColor); + drawOutlinedRect(CHECKBOX_CHECKSPACER, CHECKBOX_CHECKPOS_Y, CHECKBOX_CHECKSPACER + mCheckSquareSize, CHECKBOX_CHECKPOS_Y + mCheckSquareSize); + if (IsChecked()) + { + drawFilledRect( CHECKBOX_CHECKSPACER + CHECKBOX_INNERSPACER, CHECKBOX_CHECKPOS_Y + CHECKBOX_INNERSPACER, CHECKBOX_CHECKSPACER + mCheckSquareSize - CHECKBOX_INNERSPACER, CHECKBOX_CHECKPOS_Y + mCheckSquareSize - CHECKBOX_INNERSPACER); + } + + Panel::paint(); +} + +void VGUI_CheckBox::paintBackground() +{ + if (IsArmed()) + { + drawSetColor(Scheme::sc_primary2); + drawFilledRect(0,0,_size[0],_size[1]); + } + + drawSetColor(Scheme::sc_secondary1); + drawOutlinedRect(0,0,_size[0],_size[1]); +} diff --git a/src/game/client/ui/ms/vgui_mscontrols.h b/src/game/client/ui/ms/vgui_mscontrols.h index 31df2750..49e9c3c8 100644 --- a/src/game/client/ui/ms/vgui_mscontrols.h +++ b/src/game/client/ui/ms/vgui_mscontrols.h @@ -52,18 +52,22 @@ class MSButton : public CommandButton { m_ArmedColor = Color; } + inline void SetUnArmedColor( COLOR &Color ) { m_UnArmedColor = Color; } + inline void SetDisabledColor( COLOR &Color ) { m_DisabledColor = Color; } + inline void SetBgColor( COLOR &Color ) { setBgColor( Color.r, Color.g, Color.b, Color.a ); } + void paint( ) { if( isEnabled() ) @@ -84,6 +88,7 @@ class MSButton : public CommandButton Button::paint( ); } + void paintBackground( ) { //Button::paintBackground( ); @@ -95,6 +100,7 @@ class MSButton : public CommandButton CommandButton::setText( Text ); if( m_AutoFitText ) FitText( );; } + void FitText( ) { int w, h; @@ -105,6 +111,7 @@ class MSButton : public CommandButton COLOR m_ArmedColor, m_UnArmedColor, m_DisabledColor; bool m_AutoFitText; }; + class MSLabel : public Label { public: @@ -265,7 +272,7 @@ class CheckButton : public CommandButton public: CheckButton( char *CVARName, int x, int y, int wide, int tall ) : CommandButton( "", x, y, wide, tall, true ) { - strncpy(m_CVARName, CVARName, sizeof(m_CVARName) ); + strncpy(m_CVARName, CVARName, sizeof(m_CVARName) ); m_CVARName[255] = 0; addActionSignal( new Action_ClickCheck( this ) ); } @@ -357,23 +364,65 @@ class VGUI_Image3D : public CImageDelayed void paintBackground( ); }; +// MiB APR2019_17 - Fix for double click being broken +// Call Click at the beginning of mousePressed +// If it returns true, call mouseDoublePressed and return +// Otherwise, continue +class VGUI_DoubleClickDetector +{ +private: + float mLastClick; + void *mpLastClicked; + MouseCode mLastMouseCode; + +public: + VGUI_DoubleClickDetector() + { + mLastClick = 0; + mpLastClicked = NULL; + mLastMouseCode = MOUSE_LAST; + } + + // Returns true if double-clicked + bool Click(void *pClicked, MouseCode vMouseCode) + { + float vCurTime = gEngfuncs.GetClientTime(); + if (pClicked == mpLastClicked && mLastMouseCode == vMouseCode) + { + float vThreshhold = gEngfuncs.pfnGetCvarFloat("ms_doubleclicktime") + mLastClick; + if (vCurTime < vThreshhold) + { + mLastClick = vCurTime; + return true; + } + } + mLastClick = vCurTime; + mpLastClicked = pClicked; + mLastMouseCode = vMouseCode; + return false; + } +}; + //Callback for when items get selected, etc. -class VGUI_ItemCallbackPanel +class VGUI_ItemCallbackPanel : public VGUI_DoubleClickDetector { public: virtual void ItemSelectChanged( ulong ID, bool fSelected ) { } virtual bool ItemClicked( void *pData ) { return false; } //Return true to override the default behavior + virtual void ItemRightClicked( void *pData ) { } virtual void ItemCreated( void *pData ) { } virtual void ItemHighlighted( void *pData ) { } virtual void ItemDoubleclicked( ulong ID ) { }; virtual void GearItemSelected( ulong ID ) { } virtual bool GearItemClicked( ulong ID ) { return false; } //Return true to override the default behavior virtual bool GearItemDoubleClicked( ulong ID ) { return false; } //Return true to override the default behavior + virtual void InvTypeChanged( int vInvType ) { } + virtual void AlphabeticChanged( bool bAlphabetic ) { } }; //An item in a pack or player hands #define ITEMBTN_LABELS_MAX 1 -#define INVENTORY_TRANSPARENCY 90 +#define INVENTORY_TRANSPARENCY 90 class VGUI_ItemButton : public CTransparentPanel { @@ -395,6 +444,7 @@ class VGUI_ItemButton : public CTransparentPanel void Reset( ); void Clicked( ); + void RightClicked( ); void Doubleclicked( ); void Select( bool fSelect ); void Highlight( bool fSelect ); @@ -406,39 +456,115 @@ class VGUI_ItemButton : public CTransparentPanel class VGUI_Container : public CTransparentPanel { public: - mslist m_ItemButtons; - int m_ItemButtonTotal; - int m_InitializedItemButtons; - CTFScrollPanel *m_pScrollPanel; - VGUI_ItemCallbackPanel *m_CallbackPanel; - MSLabel *m_NoItems; + mslist m_ItemButtons; + mslist m_AlphabetizedItemButtons; // MiB FEB2019_24 [ALPHABETICAL_INVENTORY] + int m_ItemButtonTotal; + int m_InitializedItemButtons; + CTFScrollPanel *m_pScrollPanel; + VGUI_ItemCallbackPanel *m_CallbackPanel; + MSLabel *m_NoItems; + + class VGUI_InvTypePanel *m_pInvTypePanel; - class VGUI_InvTypePanel *m_pInvTypePanel; + void Update(); + void UpdatePosition(int idx); - void Update(); - void UpdatePosition( int idx ); + virtual CTFScrollPanel *GetScrollForStepInput() { return m_pScrollPanel; } - void StepInput( bool bDirUp ); // MIB FEB2015_21 [INV_SCROLL] + // MiB FEB2019_24 [ALPHABETICAL_INVENTORY] + bool IsAlphabetical() { return gEngfuncs.pfnGetCvarFloat("ms_alpha_inventory") == 1; } - #define INVTYPE_ORIGINAL 0 - #define INVTYPE_SMALL 1 - #define INVTYPE_DESC 2 + #define INVTYPE_ORIGINAL 0 + #define INVTYPE_SMALL 1 + #define INVTYPE_DESC 2 //pGearItem == NULL means uses held items instead of pack items - VGUI_Container( int x, int y, int w, int h, class VGUI_ItemCallbackPanel *pCallbackPanel, Panel *pParent ); - ~VGUI_Container( ); + VGUI_Container(int x, int y, int w, int h, class VGUI_ItemCallbackPanel *pCallbackPanel, Panel *pParent); + ~VGUI_Container(); + + VGUI_ItemButton *AddItem(containeritem_t &Item); + void PurgeButtons(); +}; + +class VGUI_CheckBox; +class VGUI_CheckBoxHandler +{ +public: + virtual void CheckChange( VGUI_CheckBox * ) = 0; +}; + +#define CHECKBOX_CHECKSPACER ( mCheckSquareSize / 2 ) +#define CHECKBOX_INNERSPACER ( mCheckSquareSize / 4 ) +#define CHECKBOX_CHECKPOS_Y ( (getTall() - mCheckSquareSize) / 2 ) +#define CHECKBOX_LABELPOS_X ( mCheckSquareSize * 2 ) +class VGUI_CheckBox : public Panel +{ +protected: + bool mbChecked; + VGUI_CheckBoxHandler *mpHandler; + Label *mpTextLabel; + CTransparentPanel *mpOverlayButton; + bool mbArmed; + int mCheckSquareSize; + +public: + VGUI_CheckBox(const char *pszText, int x, int y, int h, int w, bool bStartChecked = false); + ~VGUI_CheckBox(); - VGUI_ItemButton *AddItem( containeritem_t &Item ); - void PurgeButtons( ); + bool IsChecked() { return mbChecked; } + void SetChecked(bool bChecked) { mbChecked = bChecked; } + bool IsArmed() { return mbArmed; } + void SetArmed(bool bArmed) { mbArmed = bArmed; } + void SetHandler(VGUI_CheckBoxHandler *pHandler) { mpHandler = pHandler; } + virtual void setText(const char *pszText) { mpTextLabel->setText(pszText); } + + virtual void paint(); + virtual void paintBackground(); + + class CheckHandler : public InputSignal + { + private: + VGUI_CheckBox *mpCheckBox; + public: + CheckHandler(VGUI_CheckBox *pCheckBox) { mpCheckBox = pCheckBox; } + + virtual void cursorMoved(int x,int y,Panel* panel) {}; + virtual void cursorEntered(Panel* panel) + { + if (mpCheckBox->isEnabled()) + { + //PlaySound("ui/buttonrollover.wav", 0.8f); + mpCheckBox->SetArmed( true ); + } + } + virtual void cursorExited(Panel* panel) {mpCheckBox->SetArmed(false);} + virtual void mouseDoublePressed(MouseCode code,Panel* panel) {}; + virtual void mouseWheeled(int delta,Panel* panel) {}; + virtual void keyPressed(KeyCode code,Panel* panel) {}; + virtual void keyTyped(KeyCode code,Panel* panel) {}; + virtual void keyReleased(KeyCode code,Panel* panel) {}; + virtual void keyFocusTicked(Panel* panel) {}; + virtual void mouseReleased(MouseCode code,Panel* panel) {}; + virtual void mousePressed(MouseCode code,Panel* panel) + { + mpCheckBox->SetChecked(!mpCheckBox->IsChecked()); + if (mpCheckBox->mpHandler) + { + mpCheckBox->mpHandler->CheckChange(mpCheckBox); + } + } + }; }; class VGUI_InvTypePanel : public CTransparentPanel { public: #define INVTYPE_BUTTONS_TOTAL 3 + VGUI_CheckBox *pAlphaCheckBox; mslist InvTypeButtons; VGUI_InvTypePanel( Panel *pParent, VGUI_Container *pCallback ); + ~VGUI_InvTypePanel(); }; // One-line Text box - Can be typed in by user @@ -509,7 +635,7 @@ class VGUI_TextPanel : public CTransparentPanel m_VisibleMsg = m_Message; m_MessageLabel->setText( m_Message ); int sz = m_FadeLabels.size(); - for (int i = 0; i < sz; i++) + for (int i = 0; i < sz; i++) { m_FadeLabels[0]->setParent( NULL ); delete m_FadeLabels[0]; @@ -526,7 +652,7 @@ class VGUI_TextPanel : public CTransparentPanel void Update( ) { - for (int i = 0; i < m_FadeLabels.size(); i++) + for (int i = 0; i < m_FadeLabels.size(); i++) { VGUI_FadeText *pFadeText = m_FadeLabels[i]; pFadeText->Update( ); @@ -545,5 +671,202 @@ class VGUI_TextPanel : public CTransparentPanel void KeyInput( int down, int keynum, const char *pszCurrentBinding ); }; +// MiB APR2019_24 - Adding a bunch of simple input signal handlers so we don't have to override every single signal every time +class CCursorMovementHandler +{ +public: + virtual void cursorMoved(int x, int y, Panel *pPanel) + { + // Do nothing by default + } + + virtual void cursorEntered(Panel *pPanel) + { + // Do nothing by default + } + + virtual void cursorExited(Panel *pPanel) + { + // Do nothing by default + } +}; + +class CMouseInputHandler +{ +protected: + VGUI_DoubleClickDetector *mpDoubleClickDetector; + void *mpDoubleClickTarget; +public: + CMouseInputHandler(VGUI_DoubleClickDetector *pDoubleClickDetector = nullptr, void *pDoubleClickTarget = nullptr) + { + mpDoubleClickDetector = pDoubleClickDetector; + } + + virtual void mouseWheeled(int vDelta, Panel *pPanel) + { + // Do nothing by default + } + + virtual void mousePressed(MouseCode vCode, Panel *pPanel) + { + // Bit awkward here. Want to automatically enable double-click detection, + // but don't get overridden if single press needs to do something + // So, in this case, you should override mouseSinglePress instead + + if (mpDoubleClickDetector) + { + void *pDoubleClickTarget = mpDoubleClickTarget ? mpDoubleClickTarget : pPanel; + if (mpDoubleClickDetector->Click(pDoubleClickTarget, vCode)) + { + mouseDoublePressed(vCode, pPanel); + return; + } + } + mouseSinglePress(vCode, pPanel); + } + + virtual void mouseSinglePress(MouseCode vCode, Panel *pPanel) + { + // Do nothing by default + } + + virtual void mouseReleased(MouseCode vCode, Panel *pPanel) + { + // Do nothing by default + } + + virtual void mouseDoublePressed(MouseCode vCode, Panel *pPanel) + { + // Do nothing by default + } +}; + +class CKeyHandler +{ +public: + virtual void keyPressed(KeyCode vCode, Panel *pPanel) + { + // Do nothing by default + } + + virtual void keyTyped(KeyCode vCode, Panel *pPanel) + { + // Do nothing by default + } + + virtual void keyReleased(KeyCode vCode, Panel *pPanel) + { + // Do nothing by default + } + + virtual void keyFocusTicked(Panel *pPanel) + { + // Do nothing by default + } +}; + +// Base overrides all +class CSimpleInputSignal : public InputSignal +{ +protected: + CCursorMovementHandler *mpCursorMovementHandler; + CMouseInputHandler *mpMouseInputHandler; + CKeyHandler *mpKeyHandler; + + // Whether or not to handle deletes. Likely false, but just in case + bool mbDeleteCursorMovementHandler; + bool mbDeleteMouseInputHandler; + bool mbDeleteKeyHandler; +public: + CSimpleInputSignal(CCursorMovementHandler *pCursorMovementHandler, CMouseInputHandler *pMouseInputHandler, CKeyHandler *pKeyHandler) + { + mpCursorMovementHandler = pCursorMovementHandler; + mpMouseInputHandler = pMouseInputHandler; + mpKeyHandler = pKeyHandler; + mbDeleteCursorMovementHandler = false; + mbDeleteMouseInputHandler = false; + mbDeleteKeyHandler = false; + } + void SetDeleteCursorMovementHandler(bool bDeleteCursorMovementHandler) { mbDeleteCursorMovementHandler = bDeleteCursorMovementHandler; } + void SetDeleteMouseInputHandler(bool bDeleteMouseInputHandler) { mbDeleteMouseInputHandler = bDeleteMouseInputHandler; } + void SetDeleteKeyHandler(bool bDeleteKeyHandler) { mbDeleteKeyHandler = bDeleteKeyHandler; } + + ~CSimpleInputSignal() + { + if (mbDeleteCursorMovementHandler && mpCursorMovementHandler) + delete mpCursorMovementHandler; + if (mbDeleteMouseInputHandler && mpMouseInputHandler) + delete mpMouseInputHandler; + if (mbDeleteKeyHandler && mpKeyHandler) + delete mpKeyHandler; + } + + virtual void cursorMoved(int x, int y, Panel *pPanel) + { + if (mpCursorMovementHandler) + mpCursorMovementHandler->cursorMoved(x, y, pPanel); + } + + virtual void cursorEntered(Panel *pPanel) + { + if (mpCursorMovementHandler) + mpCursorMovementHandler->cursorEntered(pPanel); + } + + virtual void cursorExited(Panel *pPanel) + { + if (mpCursorMovementHandler) + mpCursorMovementHandler->cursorExited(pPanel); + } + + virtual void mouseWheeled(int vDelta, Panel *pPanel) + { + if (mpMouseInputHandler) + mpMouseInputHandler->mouseWheeled(vDelta, pPanel); + } + + virtual void mousePressed(MouseCode vCode, Panel *pPanel) + { + if (mpMouseInputHandler) + mpMouseInputHandler->mousePressed(vCode, pPanel); + } + + virtual void mouseReleased(MouseCode vCode, Panel *pPanel) + { + if (mpMouseInputHandler) + mpMouseInputHandler->mouseReleased(vCode, pPanel); + } + + virtual void mouseDoublePressed(MouseCode vCode, Panel *pPanel) + { + // Broken, but hey, I have to override it anyway... + if (mpMouseInputHandler) + mpMouseInputHandler->mouseDoublePressed(vCode, pPanel); + } + + virtual void keyPressed(KeyCode vCode, Panel *pPanel) + { + if (mpKeyHandler) + mpKeyHandler->keyPressed(vCode, pPanel); + } + + virtual void keyTyped(KeyCode vCode, Panel *pPanel) + { + if (mpKeyHandler) + mpKeyHandler->keyTyped(vCode, pPanel); + } + + virtual void keyReleased(KeyCode vCode, Panel *pPanel) + { + if (mpKeyHandler) + mpKeyHandler->keyReleased(vCode, pPanel); + } + + virtual void keyFocusTicked(Panel *pPanel) + { + if (mpKeyHandler) + mpKeyHandler->keyFocusTicked(pPanel); + } +}; #endif diff --git a/src/game/client/ui/ms/vgui_storage.cpp b/src/game/client/ui/ms/vgui_storage.cpp index d5286266..f2d1b594 100644 --- a/src/game/client/ui/ms/vgui_storage.cpp +++ b/src/game/client/ui/ms/vgui_storage.cpp @@ -304,7 +304,6 @@ void Storage_Update() { if (gViewPort && gViewPort->m_pStoreStorageMenu) { - gViewPort->m_pStoreStorageMenu->m_AllowUpdate = true; gViewPort->m_pStoreStorageMenu->Update(); } } diff --git a/src/game/client/ui/ms/vgui_storebuy.cpp b/src/game/client/ui/ms/vgui_storebuy.cpp index aaef2c06..53835f01 100644 --- a/src/game/client/ui/ms/vgui_storebuy.cpp +++ b/src/game/client/ui/ms/vgui_storebuy.cpp @@ -63,6 +63,7 @@ void CStoreBuyPanel::AddInventoryItems() return; } + bool CStoreBuyPanel::ItemClicked(void *pData) { VGUI_ItemButton &ItemButton = *(VGUI_ItemButton *)pData; @@ -72,6 +73,7 @@ bool CStoreBuyPanel::ItemClicked(void *pData) Close(); return true; } + void CStoreBuyPanel::ItemHighlighted(void *pData) { CStorePanel::ItemHighlighted(pData); @@ -96,7 +98,7 @@ void CStoreBuyPanel::ItemHighlighted(void *pData) continue; char cTemp[256]; - _snprintf(cTemp, sizeof(cTemp), Localized("#ITEM_COST"), StoreItem.iCost ); + _snprintf(cTemp, sizeof(cTemp), Localized("#ITEM_COST"), StoreItem.iCost ); m_InfoPanel->m_SaleText->setText(cTemp); break; } @@ -111,7 +113,6 @@ void Update_StoreBuy() { if (gViewPort->m_pStoreBuyMenu) { - gViewPort->m_pStoreBuyMenu->m_AllowUpdate = true; gViewPort->m_pStoreBuyMenu->Update(); } } diff --git a/src/game/client/ui/ms/vgui_storemainwin.cpp b/src/game/client/ui/ms/vgui_storemainwin.cpp index 68346868..86c7cecb 100644 --- a/src/game/client/ui/ms/vgui_storemainwin.cpp +++ b/src/game/client/ui/ms/vgui_storemainwin.cpp @@ -50,13 +50,6 @@ static COLOR Color_TitleText = COLOR(255, 0, 0, 0), //255, 100, 100 // Creation CStorePanel::CStorePanel() : VGUI_ContainerPanel() { -#define TITLE_X ITEM_CONTAINER_X -#define TITLE_Y YRES(48) - -//Create the sell calculation -#define SELLLABEL_X ITEM_CONTAINER_X + XRES(2) -#define SELLLABEL_Y ITEM_CONTAINER_Y + ITEM_CONTAINER_SIZE_Y + YRES(20) - m_SaleLabel = new MSLabel(this, "", SELLLABEL_X, SELLLABEL_Y); m_SaleLabel->setFont(g_FontTitle); m_SaleLabel->SetFGColorRGB(Color_SubtitleText); diff --git a/src/game/client/ui/ms/vgui_storemainwin.h b/src/game/client/ui/ms/vgui_storemainwin.h index 1cd4ff41..2b2bfb34 100644 --- a/src/game/client/ui/ms/vgui_storemainwin.h +++ b/src/game/client/ui/ms/vgui_storemainwin.h @@ -3,6 +3,14 @@ #include "vgui_container.h" +#define TITLE_X ITEM_CONTAINER_X +#define TITLE_Y 0 + +#define SELLLABEL_X ITEM_CONTAINER_X +#define SELLLABEL_Y ITEM_CONTAINER_Y + ITEM_CONTAINER_SIZE_Y +#define SELLLABEL_W ITEM_CONTAINER_SIZE_X - ACTBTN_SIZE_X +#define SELLLABEL_H YRES(30) + class CStorePanel : public VGUI_ContainerPanel { protected: diff --git a/src/game/client/ui/ms/vgui_storesell.cpp b/src/game/client/ui/ms/vgui_storesell.cpp index d9a5bf95..c31154ab 100644 --- a/src/game/client/ui/ms/vgui_storesell.cpp +++ b/src/game/client/ui/ms/vgui_storesell.cpp @@ -174,7 +174,6 @@ void SellWindow_Update() { if (gViewPort && gViewPort->m_pStoreSellMenu) { - gViewPort->m_pStoreSellMenu->m_AllowUpdate = true; gViewPort->m_pStoreSellMenu->Update(); } } diff --git a/src/game/client/ui/vgui_teamfortressviewport.cpp b/src/game/client/ui/vgui_teamfortressviewport.cpp index 27419593..40a0a250 100644 --- a/src/game/client/ui/vgui_teamfortressviewport.cpp +++ b/src/game/client/ui/vgui_teamfortressviewport.cpp @@ -2159,16 +2159,23 @@ void __CmdFunc_HUDScroll() else return; //Invalid command - if (gViewPort->m_pCurrentMenu && gViewPort->m_pCurrentMenu->m_Flags & MENUFLAG_TRAPSTEPINPUT) + CTFScrollPanel *pScrollPanel; + + if (gViewPort->m_pCurrentMenu && ScrollCmd != HUDSCROLL_SELECT && (pScrollPanel = gViewPort->m_pCurrentMenu->GetScrollForStepInput())) + { + // PGup and PGdn affect some menus + // MiB APR2019_17 - Trapping this separately so I can standardize use a cvar + int h, v; + int vAmt = static_cast(CVAR_GET_FLOAT("ms_scrollamount")); + if ( ScrollCmd == HUDSCROLL_UP ) vAmt *= -1; + pScrollPanel->getScrollValue( h, v ); + pScrollPanel->setScrollValue( h, v + vAmt ); + } + else if (gViewPort->m_pCurrentMenu && gViewPort->m_pCurrentMenu->m_Flags & MENUFLAG_TRAPSTEPINPUT) { // PGup and PGdn affect some menus gViewPort->m_pCurrentMenu->StepInput(ScrollCmd); } - else if (gViewPort->m_pContainerMenu && gViewPort->m_pContainerMenu->isVisible()) - { - // MIB FEB2015_21 [INV_SCROLL] - Pass to the container menu - gViewPort->m_pContainerMenu->StepInput(ScrollCmd == HUDSCROLL_UP); - } else if (!gViewPort->m_pCurrentMenu) { //If no menu open, pass down to the HUD diff --git a/src/game/client/ui/vgui_teamfortressviewport.h b/src/game/client/ui/vgui_teamfortressviewport.h index 9ceef631..c6d74ad7 100644 --- a/src/game/client/ui/vgui_teamfortressviewport.h +++ b/src/game/client/ui/vgui_teamfortressviewport.h @@ -1091,6 +1091,7 @@ enum hudscroll_e HUDSCROLL_SELECT, }; +class CTFScrollPanel; class CMenuPanel : public VGUI_MainPanel { private: @@ -1175,6 +1176,7 @@ class CMenuPanel : public VGUI_MainPanel //Master Sword int m_Flags; virtual void StepInput(hudscroll_e HUDScroll) {} + virtual CTFScrollPanel *GetScrollForStepInput() { return nullptr; } }; //================================================================ diff --git a/src/game/server/client.cpp b/src/game/server/client.cpp index b693c75e..ab771d10 100644 --- a/src/game/server/client.cpp +++ b/src/game/server/client.cpp @@ -1491,6 +1491,40 @@ void ClientCommand2(edict_t *pEntity) } } } + else if (FStrEq(CMD_ARGV(1), "split")) + { + CGenericItem *pItem = MSUtil_GetItemByID(atol(CMD_ARGV(2)), pPlayer); + int vNewStackAmount = atoi(CMD_ARGV(3)); + if(pItem && vNewStackAmount && pItem->m_pParentContainer) + { + CGenericItem *pAddToHand = nullptr; + + if(pItem->iQuantity == vNewStackAmount) + { + // Not sure why player "split" the whole stack, but don't + // bother creating a new item and deleting the current one, + // just move the current one + pAddToHand = pItem; + } + else + { + pAddToHand = NewGenericItem(pItem->m_Name); + if(pAddToHand) + { + pAddToHand->iQuantity = vNewStackAmount; + pItem->iQuantity -= vNewStackAmount; + + MESSAGE_BEGIN(MSG_ONE, g_netmsg[NETMSG_ITEM], NULL, pPlayer->pev); + WRITE_BYTE(1); + SendGenericItem(pPlayer, pItem, false); + MESSAGE_END(); + } + } + + if(pAddToHand) + pAddToHand->GiveTo(pPlayer, true, false, true); + } + } } else if (FStrEq(pcmd, "inv") && !bCanUseInventory) {