#include "cbase.h" #include "asw_vgui_manipulator.h" #include "vgui_controls/Button.h" #include "vgui_controls/Label.h" #include // memdbgon must be the last include file in a .cpp file!!! #include using namespace vgui; // This panel is used to manipulate other panels and report their sizes, for easy coding and positioning of panels // I know there's editablepanel, but this class can attach to any panel and is designed for the way I've been coding vgui stuff so far (i.e. code created and driven, with lots of animation, frameless) // todo: // [ ] Check our panel doesn't block mouse clicks // [ ] Figure out how we're going to create and attach one of these CASW_VGUI_Manipulator *g_pASW_VGUI_Manipulator = NULL; CASW_VGUI_Manipulator::CASW_VGUI_Manipulator(vgui::Panel *pParent, vgui::Panel *pTarget) : Panel(pParent, "ASWManipulator") { SetTarget(pTarget); SetMouseInputEnabled(true); MoveToFront(); m_pResizeButton[0] = new vgui::Button(this, "ManipButtonLL", "<", this, "ResizeLeftLeft"); m_pResizeButton[1] = new vgui::Button(this, "ManipButtonLR", ">", this, "ResizeLeftRight"); m_pResizeButton[2] = new vgui::Button(this, "ManipButtonRR", ">", this, "ResizeRightRight"); m_pResizeButton[3] = new vgui::Button(this, "ManipButtonRL", "<", this, "ResizeRightLeft"); m_pResizeButton[4] = new vgui::Button(this, "ManipButtonUU", "^", this, "ResizeUpperUp"); m_pResizeButton[5] = new vgui::Button(this, "ManipButtonUD", "v", this, "ResizeUpperDown"); m_pResizeButton[6] = new vgui::Button(this, "ManipButtonLD", "v", this, "ResizeLowerDown"); m_pResizeButton[7] = new vgui::Button(this, "ManipButtonLU", "^", this, "ResizeLowerUp"); m_pPositionLabel = new vgui::Label(this, "ManipPositionLabel", "Position:"); m_pPositionLabel->SetMouseInputEnabled(true); } CASW_VGUI_Manipulator::~CASW_VGUI_Manipulator() { } void CASW_VGUI_Manipulator::OnScreenSizeChanged(int iOldWide, int iOldTall) { ResizeFor(ScreenWidth(), ScreenHeight()); } void CASW_VGUI_Manipulator::ResizeFor(int width, int height) { if (!GetParent()) return; SetBounds(0, 0, GetParent()->GetWide(), GetParent()->GetTall()); // make our manipulator full screen m_pPositionLabel->SetSize(GetParent()->GetWide(), GetParent()->GetTall() * 0.1f); PositionButtons(); // position our arrow buttons around the target panel } void CASW_VGUI_Manipulator::Think() { if (!m_pTarget) return; int x, y, w, t; m_pTarget->GetBounds(x,y,w,t); //m_pTarget->LocalToScreen(x, y); float fx = float(x) / float(GetWide()); float fy = float(y) / float(GetTall()); float fw = float(w) / float(GetWide()); float ft = float(t) / float(GetTall()); char buffer[512]; Q_snprintf(buffer, sizeof(buffer), "Name: %s Class: %s\nPosition: %d, %d, %d, %d\nFraction: %f, %f, %f, %f (%f/%f)", m_pTarget->GetName(), m_pTarget->GetClassName(), x,y,w,t, fx, fy, fw, ft, float(GetWide()), float(GetTall())); m_pPositionLabel->SetText(buffer); int current_posx, current_posy; vgui::input()->GetCursorPos(current_posx, current_posy); if (current_posy < GetTall() * 0.5f) { m_pPositionLabel->SetPos(0,GetTall() * 0.9f); } else { m_pPositionLabel->SetPos(0,0); } PositionButtons(); } void CASW_VGUI_Manipulator::PositionButtons() { if (!m_pTarget) return; int iButtonSize = ScreenWidth() * 0.02f; for (int i=0;i<8;i++) { m_pResizeButton[i]->SetSize(iButtonSize, iButtonSize); } int x, y, w, t; m_pTarget->GetBounds(x,y,w,t); //m_pTarget->LocalToScreen(x,y); m_pResizeButton[0]->SetPos(x - iButtonSize, y + t * 0.5f - iButtonSize); // left left m_pResizeButton[1]->SetPos(x - iButtonSize, y + t * 0.5f); // left right m_pResizeButton[2]->SetPos(x + w, y + t * 0.5f); // right right m_pResizeButton[3]->SetPos(x + w, y + t * 0.5f - iButtonSize); // right left m_pResizeButton[4]->SetPos(x + w * 0.5f - iButtonSize, y - iButtonSize); // upper up m_pResizeButton[5]->SetPos(x + w * 0.5f, y - iButtonSize); // upper down m_pResizeButton[6]->SetPos(x + w * 0.5f, y + t); // lower down m_pResizeButton[7]->SetPos(x + w * 0.5f - iButtonSize, y + t); // lower up } void CASW_VGUI_Manipulator::OnCommand(const char *command) { int iShiftAmount = 1; int x, y, w, t; m_pTarget->GetBounds(x,y,w,t); // todo: if shift/ctrl is held down, adjust the size accordingly if (!stricmp(command, "ResizeLeftRight")) { x += iShiftAmount; } else if (!stricmp(command, "ResizeLeftLeft")) { x -= iShiftAmount; } else if (!stricmp(command, "ResizeRightRight")) { w += iShiftAmount; } else if (!stricmp(command, "ResizeRightLeft")) { w -= iShiftAmount; } else if (!stricmp(command, "ResizeUpperDown")) { y += iShiftAmount; } else if (!stricmp(command, "ResizeUpperUp")) { y -= iShiftAmount; } else if (!stricmp(command, "ResizeLowerDown")) { t += iShiftAmount; } else if (!stricmp(command, "ResizeLowerUp")) { t -= iShiftAmount; } else { BaseClass::OnCommand(command); } m_pTarget->SetBounds(x,y,w,t); } void CASW_VGUI_Manipulator::EditPanel(vgui::Panel *pParent, vgui::Panel *pTargetPanel) { Msg("EditPanel request\n"); if (g_pASW_VGUI_Manipulator != NULL) { delete g_pASW_VGUI_Manipulator; } if (pTargetPanel != NULL && pParent != NULL) { g_pASW_VGUI_Manipulator = new CASW_VGUI_Manipulator(pParent, pTargetPanel); g_pASW_VGUI_Manipulator->ResizeFor(ScreenWidth(), ScreenHeight()); } } void CASW_VGUI_Manipulator::ApplySchemeSettings(vgui::IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme); for (int i=0;i<8;i++) { m_pResizeButton[i]->SetDefaultColor(Color(68,140,203,255), Color(0,0,0,255)); m_pResizeButton[i]->SetArmedColor(Color(255,255,255,255), Color(65,74,96,255)); m_pResizeButton[i]->SetDepressedColor(Color(255,255,255,255), Color(65,74,96,255)); m_pResizeButton[i]->SetDefaultBorder(pScheme->GetBorder("ASWBriefingButtonBorder")); m_pResizeButton[i]->SetDepressedBorder(pScheme->GetBorder("ASWBriefingButtonBorder")); m_pResizeButton[i]->SetKeyFocusBorder(pScheme->GetBorder("ASWBriefingButtonBorder")); } m_pPositionLabel->SetPaintBackgroundEnabled(true); m_pPositionLabel->SetBgColor(Color(0,0,255,64)); } void CASW_VGUI_Manipulator::OnMouseReleased(vgui::MouseCode code) { if ( code == MOUSE_LEFT ) { // iterate through all of our parent's children, seeing if any are under the mouse and sets one as the target if so FindAllPanelsUnderCursor(); } } void CASW_VGUI_Manipulator::FindAllPanelsUnderCursor() { m_UnderCursorList.RemoveAll(); FindAllPanelsUnderCursorRecurse(GetParent()); // is our current target in the list? int c = m_UnderCursorList.Count(); for (int i=0;i 0) { SetTarget(m_UnderCursorList[0]); return; } Msg("No panel under cursor!"); } // void CASW_VGUI_Manipulator::FindAllPanelsUnderCursorRecurse(vgui::Panel *pPanel) { if (!pPanel) return; for (int i=0;iGetChildCount();i++) { Panel *pChild = pPanel->GetChild(i); // add child to the list? if (pChild->IsCursorOver() && !ShouldSkipPanel(pChild)) m_UnderCursorList.AddToTail(pChild); // get all the child's children too FindAllPanelsUnderCursorRecurse(pChild); } } bool CASW_VGUI_Manipulator::ShouldSkipPanel(vgui::Panel *pPanel) { // Don't manipulate ourselves! We'll go blind if (pPanel == this && pPanel->GetParent() == this) return true; // try to skip backdrops and the window itself int x,y,w,t; pPanel->GetBounds(x,y,w,t); if (x == 0 && y == 0 && w>=GetWide() && t>=GetTall()) return true; return false; } void CASW_VGUI_Manipulator::SetTarget(vgui::Panel *pPanel) { m_pTarget = pPanel; }