X Tutup
/* WindowSystem.cpp -- window system Copyright (C) 2019 a1batross This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "Primitive.h" #include "WindowSystem.h" #include "BaseWindow.h" #include "con_nprint.h" void CWindowStack::VidInit( bool calledOnce ) { // now recalc all the menus in stack FOR_EACH_LL( stack, i ) { CMenuBaseWindow *item = stack[i]; if( item ) { int cursor, cursorPrev; bool valid = false; // HACKHACK: Save cursor values when VidInit is called once // this don't let menu "forget" actual cursor values after, for example, window resizing if( calledOnce && item->GetCursor() > 0 // ignore 0, because useless && item->GetCursor() < item->ItemCount() && item->GetCursorPrev() > 0 && item->GetCursorPrev() < item->ItemCount() ) { valid = true; cursor = item->GetCursor(); cursorPrev = item->GetCursorPrev(); } // do vid restart for all pushed elements item->VidInit(); item->Reload(); if( valid ) { // don't notify menu widget about cursor changes item->SetCursor( cursorPrev, false ); item->SetCursor( cursor, false ); } } } } bool CWindowStack::IsVisible( const CMenuBaseWindow *menu ) const { if( menu == Current() ) return true; if( FBitSet( menu->iFlags, QMF_HIDDEN )) return false; // for some reason const_cast need here if( stack.Find( const_cast( menu )) == stack.InvalidIndex()) return false; return true; } void CWindowStack::Update( ) { if( !IsActive() ) return; CUtlVector drawList( 16 ); CUtlVector removeList( 16 ); bool stop = Current()->IsRoot(); // always add current window drawList.AddToTail( Current() ); FOR_EACH_LL_BACK( stack, i ) { stack[i]->Think(); // any window must think if( i == active ) continue; // will be added last if( stack[i]->eTransitionType ) { drawList.AddToTail( stack[i] ); continue; } if( FBitSet( stack[i]->iFlags, QMF_CLOSING )) { // it's better to not change stack while we traverse it ClearBits( stack[i]->iFlags, QMF_CLOSING ); removeList.AddToTail( i ); continue; } // minimized windows if( stack[i]->iFlags & QMF_HIDDEN ) continue; if( stop ) // we don't need to search windows to draw continue; // maximized, no need to go further anymore, // but we need to check for closing windows, so don't break if( stack[i]->IsRoot() ) { stop = true; } else { // start region test bool inside = false; Rect window( stack[i]->GetRenderPosition(), stack[i]->GetRenderSize() ); if( !inside ) { FOR_EACH_VEC( drawList, j ) { if( drawList[j]->eTransitionType ) continue; // skip animating window Rect drawnWindow( drawList[j]->GetRenderPosition(), drawList[j]->GetRenderSize() ); if( drawnWindow.IsInside( window )) inside = true; } } // region test complete if( inside ) continue; } // add to draw list drawList.AddToTail( stack[i] ); } FOR_EACH_VEC( removeList, j ) { stack.Remove( removeList[j] ); } FOR_EACH_VEC_BACK( drawList, k ) { CMenuBaseWindow *window = drawList[k]; if( window->eTransitionType > CMenuBaseWindow::ANIM_CLOSING ) { if( window->DrawAnimation( ) ) window->DisableTransition(); } if( !window->eTransitionType ) drawList[k]->Draw(); if( k != drawList.Count() - 1 ) { window = drawList[k+1]; if( window->eTransitionType == CMenuBaseWindow::ANIM_CLOSING ) { if( window->DrawAnimation( ) ) window->DisableTransition(); } } } if( ui_show_window_stack && ui_show_window_stack->value ) { con_nprint_t con; con.index = 0; con.time_to_live = 0.01f; con.color[0] = con.color[1] = con.color[2] = 1.0f; Con_NXPrintf( &con, "Stack:\n" ); FOR_EACH_LL( stack, l ) { con.index++; if( active == l ) { con.color[0] = 0.0f; con.color[1] = 1.0f; con.color[2] = 0.0f; } else if( FBitSet( stack[l]->iFlags, QMF_CLOSING )) { // bloody :) con.color[0] = 1.0f; con.color[1] = 0.0f; con.color[2] = 0.0f; } else { con.color[0] = con.color[1] = con.color[2] = 1.0f; } char visible = '-'; if( drawList.Find( stack[l] ) != drawList.InvalidIndex() ) visible = '+'; if( stack[l]->IsRoot() ) { Con_NXPrintf( &con, "%c %p - %s\n", visible, stack[l], stack[l]->szName ); } else { Con_NXPrintf( &con, "%c %p - %s\n", visible, stack[l], stack[l]->szName ); } } } } void CWindowStack::Add( CMenuBaseWindow *menu ) { if( menu == Current() ) return; // do nothing if( stack.IsValidIndex( active )) { if( stack[active]->IsRoot() && menu->IsRoot() ) { stack[active]->EnableTransition( CMenuBaseWindow::ANIM_CLOSING ); } } // check if menu already in stack and set it active int i; if( ( i = stack.Find( menu )) != stack.InvalidIndex() ) { active = i; ClearBits( menu->iFlags, QMF_CLOSING ); return; } active = stack.AddToTail( menu ); ClearBits( menu->iFlags, QMF_CLOSING ); if( this == &uiStatic.menu ) // hack! { uiStatic.firstDraw = true; EngFuncs::KEY_SetDest( KEY_MENU ); } } void CWindowStack::Remove( CMenuBaseWindow *menu ) { int min; int idx = stack.Find( menu ); if( idx == stack.InvalidIndex() ) { Con_DPrintf( "CWindowStack::Remove: can't remove not opened window" ); } if( this == &uiStatic.menu ) // hack! min = 1; // main menu can't close last menu else min = 0; if( stack.Count() > min ) { SetBits( menu->iFlags, QMF_CLOSING ); FOR_EACH_LL_BACK( stack, i ) { if( !FBitSet( stack[i]->iFlags, QMF_CLOSING )) { active = i; // maybe isn't best solution if( stack[active]->IsRoot() && menu->IsRoot() ) stack[active]->EnableTransition( CMenuBaseWindow::ANIM_OPENING ); // notify new active window about changed mouse position stack[active]->MouseMove( uiStatic.cursorX, uiStatic.cursorY ); break; } } } else { if( CL_IsActive() ) { UI_CloseMenu(); } else { EngFuncs::KEY_SetDest( KEY_CONSOLE ); } } // hacks for demos and some environments where we can't play them on background if( this == &uiStatic.menu && uiStatic.m_fDemosPlayed && uiStatic.m_iOldMenuDepth == stack.Count() - 1 ) { EngFuncs::ClientCmd( false, "demos\n" ); uiStatic.m_fDemosPlayed = false; uiStatic.m_iOldMenuDepth = 0; } } void CWindowStack::InputMethodResized( void ) { if( Current() && Current()->ItemAtCursor() ) { Current()->ItemAtCursor()->_Event( QM_IMRESIZED ); } } void CWindowStack::KeyUpEvent( int key ) { if( Current() ) Current()->KeyUp( key ); } void CWindowStack::KeyDownEvent( int key ) { if( Current() ) Current()->KeyDown( key ); } void CWindowStack::CharEvent( int key ) { if( Current() ) Current()->Char( key ); } void CWindowStack::MouseEvent( int x, int y ) { if( Current() ) Current()->MouseMove( x, y ); }
X Tutup