// ==================================================================== // Class: UT2K4UI.GUIComponent // // GUIComponents are the most basic building blocks of menus. // // Written by Joe Wilcox // (c) 2002, Epic Games, Inc. All Rights Reserved // ==================================================================== class GUIComponent extends GUI Abstract Native; cpptext { TCHAR* GetMenuPath( TCHAR* Str = NULL ) const; virtual void PreDraw(UCanvas *Canvas); // Should be overridden in a subclass virtual void Draw(UCanvas* Canvas); // Should be overridden in a subclass UBOOL WithinBounds( FLOAT PosX, FLOAT PosY ) const { return PosX >= Bounds[0] && PosX <= Bounds[2] && PosY >= Bounds[1] && PosY <= Bounds[3]; } virtual UBOOL PerformHitTest(INT MouseX, INT MouseY); // Check to see if a mouse press affects the control virtual void UpdateBounds(); // Updates the Bounds for hit tests and such FLOAT ActualWidth( FLOAT Val = INDEX_NONE, UBOOL bForce = 0 ) const; // Returns the actual width (including scaling) of a component FLOAT ActualHeight( FLOAT Val = INDEX_NONE, UBOOL bForce = 0 ) const; // Returns the actual height (including scaling) of a component FLOAT ActualLeft( FLOAT Val = INDEX_NONE, UBOOL bForce = 0 ) const; // Returns the actual left (including scaling) of a component FLOAT ActualTop( FLOAT Val = INDEX_NONE, UBOOL bForce = 0 ) const; // Returns the actual top (including scaling) of a component FLOAT RelativeWidth( FLOAT RealWidth = INDEX_NONE, UBOOL bForce = 0 ) const; FLOAT RelativeHeight( FLOAT RealHeight = INDEX_NONE, UBOOL bForce = 0) const; FLOAT RelativeLeft( FLOAT RealLeft = INDEX_NONE, UBOOL bForce = 0 ) const; FLOAT RelativeTop( FLOAT RealTop = INDEX_NONE, UBOOL bForce = 0 ) const; virtual UGUIComponent* UnderCursor(FLOAT MouseX, FLOAT MouseY); // Focusing stubs virtual UGUIComponent* GetFocused() const { return NULL; } virtual UBOOL IsFocusedOn( const UGUIComponent* Comp ) const { return 0; } virtual UBOOL MouseMove(INT XDelta, INT YDelta); // The Mouse has moved virtual UBOOL MousePressed(UBOOL IsRepeat); // The Mouse was pressed virtual UBOOL MouseReleased(); // The Mouse was released virtual UBOOL MouseHover(); // The Mouse is over a non-pressed thing virtual UBOOL NativeKeyType(BYTE& iKey, TCHAR Unicode ); // Handle key presses virtual UBOOL NativeKeyEvent(BYTE& iKey, BYTE& State, FLOAT Delta); // Handle key events virtual UBOOL PerformDoubleClick(); virtual void SetAdjustedDims(FLOAT Width, FLOAT Height, FLOAT Left, FLOAT Top); // Smarter version of SetDims that takes into account scaling and bounding virtual void SetDims(FLOAT Width, FLOAT Height, FLOAT Left, FLOAT Top); // Set the dims quickly virtual void CloneDims(UGUIComponent* From); // Clones the Width,Height, Top, Left settings virtual UBOOL IsAnimating() { for ( UGUIComponent* Comp = this; Comp; Comp = Comp->MenuOwner ) if ( Comp->bAnimating ) return true; return false; } virtual UBOOL SpecialHit( UBOOL bForce ); virtual void NativeInvalidate(UGUIComponent* Who); virtual void UpdateOffset(FLOAT PosX, FLOAT PosY, FLOAT PosW, FLOAT PosH); virtual void AutoPosition( TArray& Components, FLOAT PosL, FLOAT PosT, FLOAT PosR, FLOAT PosB, INT Col = 1, FLOAT ColSpace = 0.f ); virtual void AutoPositionOn( TArray& Components, UGUIComponent* Frame, FLOAT LPerc, FLOAT TPerc, FLOAT RPerc, FLOAT BPerc, INT Col = 1, FLOAT ColSpace = 0.f ); virtual void NotifyResolutionChange( INT NewResX, INT NewResY ); #ifdef UCONST_Counter virtual void ResetCounter(); #endif } // Variables var(Menu) noexport editconst GUIPage PageOwner; // Callback to the GUIPage that contains this control var(Menu) noexport editconst GUIComponent MenuOwner; // Callback to the Component that owns this one var(State) noexport GUIComponent FocusInstead; // Who should get the focus instead of this control if bNeverFocus var(State) noexport eMenuState MenuState; // Used to determine the current state of this component var(State) editconst noexport eMenuState LastMenuState; // The previous MenuState of this component var(State) noexport eDropState DropState; // Used to determine the current drop state of this component var(Style) eFontScale FontScale; // If this component has a style, which size font should be applied to the style // RenderStyle and MenuColor are usually pulled from the Parent menu, unless specificlly overridden var() string IniOption; // Points to the INI option to load for this component var() string IniDefault; // The default value for a missing ini option var(Style) string StyleName; // Name of my Style var() localized string Hint; // The hint that gets displayed for this component var() noexport GUILabel FriendlyLabel; // My state is projected on this objects state. var(Menu) float WinTop,WinLeft; // Where does this component exist (in world space) - Grr.. damn Left() var(Menu) float WinWidth,WinHeight; // Where does this component exist (in world space) - Grr.. damn Left() var() float RenderWeight; // Used to determine sorting in the controls stack var(Style) int MouseCursorIndex; // The mouse cursor to use when over this control var(Menu) int TabOrder; // Used to figure out tabbing var() int Tag; // Free (can be used for anything) var() bool bDebugging; var(Menu) bool bTabStop; // Does a TAB/Shift-Tab stop here var() bool bFocusOnWatch; // If true, watching focuses var(Menu) bool bBoundToParent; // Use the Parents Bounds for all positioning var(Menu) bool bScaleToParent; // Use the Parent for scaling var(State) noexport bool bHasFocus; // Does this component currently have input focus var(State) bool bVisible; // Is this component currently visible var(State) bool bAcceptsInput; // Does this control accept input var() bool bCaptureTabs; // If true, OnKeyEvent() is called for tab presses, overriding default behavior (NextControl()/PrevControl()) var(State) bool bCaptureMouse; // Control should capture the mouse when pressed var(State) bool bNeverFocus; // This control should never fully receive focus var(State) bool bRepeatClick; // Whether this component should receive OnClick() events when the mouse button is held down var(State) bool bRequireReleaseClick; // If True, this component wants the click on release even if it's not active var() bool bMouseOverSound; // Should component bleep when mouse goes over it var() bool bDropSource; // Can this component act as a drag-n-drop source var() bool bDropTarget; // Can this component act as a drag-n-drop target var(State) noexport bool bPendingFocus; // Big big hack for ComboBoxes.. var() bool bInit; // Can be used by any component as an "initialization" hook var() bool bNeverScale; // Do not treat position/dimension values in the -2.0 to 2.0 range as scaled values // useful for internally managed components (GUIComboBox's list, button, etc.) /* This property is solely for the benefit of mod authors, to indicate components which will be skipped by the native rendering code if the component doesn't have a valid style. Mod authors: changing the value of this property in your subclasses will cause your menus to crash the game */ var const noexport bool bRequiresStyle; var() editconst const noexport bool bPositioned; // Whether this component has been positioned yet (first Pre-Render) var() editconst noexport bool bAnimating; // If true, all input/focus/etc will be ignored var() editconst noexport const bool bTravelling, bSizing; // Travelling is true when animating position, Sizing is true when animating dimensions var() editconst noexport const array MotionFrame, SizeFrame; // Notes about the Top/Left/Width/Height : This is a somewhat hack but it's really good for functionality. If // the value is < 2, then the control is considered to be scaled. If they are >= 2 they are considered to be normal world coords. // If bNeverScale is set, then values between -2/2 will also be considered actual values // 0 = 0, 1 = 100%, 2 = 2px var(Menu) editconst const noexport float Bounds[4]; // Internal normalized positions in world space var(Menu) editconst const noexport float ClientBounds[4]; // The bounds of the actual client area (minus any borders) // Timer Support var() bool bTimerRepeat; var() noexport editconst const int TimerIndex; // For easier maintenance var() float TimerCountdown; var() float TimerInterval; var noexport const float MouseOffset[4]; // Used natively for drawing outlines var() editconst GUIContextMenu ContextMenu; var() editconst GUIToolTip ToolTip; // Used for Saving the last state before drawing natively var noexport const color WhiteColor; // Style holds a pointer to the GUI style of this component. var(Style) noexport GUIStyles Style; // My GUI Style var(Style) enum EClickSound { CS_None, CS_Click, CS_Edit, CS_Up, CS_Down, CS_Drag, CS_Fade, CS_Hover, CS_Slide, } OnClickSound; var() enum EParentScaleType // Used to bound/scale in one dimension only { SCALE_All, SCALE_X, SCALE_Y, } BoundingType, ScalingType; var(Menu) bool bStandardized; var(Menu) float StandardHeight; // FOR TESTING var editconst const noexport int PreDrawCount, DrawCount; var editconst noexport int OnRenderCount, OnRenderedCount, OnPreDrawCount, OnDrawCount; // Delegates Delegate OnArrival(GUIComponent Sender, EAnimationType Type); // Called when an animating component arrives at a spot Delegate OnEndAnimation( GUIComponent Sender, EAnimationType Type ); // Called immediately after the component arrives at the last keypoint // Drawing delegates return true if you want to short-circuit the default drawing code // Called for all components, but natively, only ContextMenus do not perform native PreDraw if delegate returns false // Bounds/ClientBounds are updated just before the call to OnPreDraw(). // If you modify the positions of the component, you can force an immediate refresh of the Bounds by returning true from OnPreDraw /* Delegate bool OnPreDraw(canvas Canvas); // Called from the GUIComponent's native PreDraw function. Delegate bool OnDraw(canvas Canvas); // Called the moment the native Draw function is called on a component Delegate OnRender(canvas Canvas); // Called immediately after a component's native Super.Draw is called Delegate OnRendered(canvas Canvas); // Called immediately after a component has finished rendering. */ // The "default" versions of these delegates are only called if GUI.Counter > 0 Delegate bool OnPreDraw(canvas Canvas) { if ( Counter < 1 ) return false; OnPreDrawCount++; if ( OnPreDrawCount > Counter ) log("OnPreDraw called"@OnPreDrawCount@"times: "$GetMenuPath()); return false; } Delegate bool OnDraw(canvas Canvas) { if ( COUNTER < 1 ) return false; OnDrawCount++; if ( OnDrawCount > Counter ) log("OnDraw called"@OnDrawCount@"times: "$GetMenuPath()); return false; } Delegate OnRender(canvas Canvas) { if ( COUNTER < 1 ) return; OnRenderCount++; if ( OnRenderCount > Counter ) log("OnRender called"@OnRenderCount@"times: "$GetMenuPath()); } Delegate OnRendered(canvas Canvas) { if ( COUNTER < 1 ) return; OnRenderedCount++; if ( OnRenderedCount > Counter ) log("OnRendered called"@OnRenderedCount@"times:"@GetMenuPath()); } Delegate OnActivate(); // Called when the component gains focus Delegate OnDeActivate(); // Called when the component loses focus Delegate OnWatch(); // Called when the component is being watched Delegate OnHitTest(float MouseX, float MouseY); // Called when Hit test is performed for mouse input Delegate OnMessage(coerce string Msg, float MsgLife); // When a message comes down the line Delegate OnHide(); Delegate OnShow(); // Called just before OnHover() // Controller assigns the value of its MouseOver property to the result of this function delegate GUIToolTip OnBeginTooltip() { if ( ToolTip != None ) return ToolTip.EnterArea(); else if ( MenuOwner != None ) return MenuOwner.OnBeginTooltip(); return None; } // Called on the current ActiveControl when the mouse is moved over a new component // This is called before OnBeginTooltip is called on the new control // Return false if the tooltip will remain visible after leaving this control delegate bool OnEndTooltip() { if ( ToolTip != None ) return ToolTip.LeaveArea(); else if ( MenuOwner != None ) return MenuOwner.OnEndTooltip(); return true; } Delegate OnInvalidate(GUIComponent Who); // Called when the background is clicked // Return true to override default behavior // Called on both the active control & active page delegate bool OnHover( GUIComponent Sender ) { return false; } // -- Input event delegates Delegate bool OnClick(GUIComponent Sender); // The mouse was clicked on this control Delegate bool OnDblClick(GUIComponent Sender); // The mouse was double-clicked on this control Delegate bool OnRightClick(GUIComponent Sender); // Return false to prevent context menu from appearing Delegate OnMousePressed(GUIComponent Sender, bool bRepeat); // Sent when a mouse is pressed (initially) Delegate OnMouseRelease(GUIComponent Sender); // Sent when the mouse is released. Delegate OnTimer(GUIComponent Sender); // Called from Timer() Delegate OnChange(GUIComponent Sender); // Called when a component changes it's value Delegate bool OnKeyType(out byte Key, optional string Unicode) // Key Strokes { return false; } Delegate bool OnKeyEvent(out byte Key, out byte State, float delta) { return false; } delegate bool OnDesignModeKeyEvent( Interactions.EInputKey Key, Interactions.EInputAction State ) { return false; } Delegate bool OnCapturedMouseMove(float deltaX, float deltaY) { return false; } Delegate OnLoadINI(GUIComponent Sender, string s); // Do the actual work here Delegate string OnSaveINI(GUIComponent Sender); // Do the actual work here // drag-n-drop // Called when mouse is released over the DropSource to detemine whether OnClick() should be called delegate bool OnMultiSelect( GUIComponent Sender ) { return true; } delegate bool OnBeginDrag(GUIComponent Sender) // Called on the source component when a drag & drop operation begins { return bDropSource; } delegate OnEndDrag(GUIComponent Sender, bool bAccepted); // Called on the target component when data is dropped // DropStateChange() will be called on the source - DRP_Accept if it returns true, DRP_Reject if it returns false delegate bool OnDragDrop(GUIComponent Sender) { return false; } delegate OnDragEnter(GUIComponent Sender); // Called on the target component when the mouse enters the components bounds delegate OnDragLeave(GUIComponent Sender); // Called on a target component when the mouse leaves the components bounds delegate OnDragOver(GUIComponent Sender); // Called when the mouse is moved inside a target's bounds native(812) final function PlayerController PlayerOwner(); native(813) function final SetTimer(float Interval, optional bool bRepeat); native(814) function final KillTimer(); // Auto-positioning - accounts for bBoundToParent & bScaleToParent native(815) final function AutoPosition( array Components, float LeftBound, float UpperBound, float RightBound, float LowerBound, float LeftPad, float UpperPad, float RightPad, float LowerPad, optional int NumberOfColumns, optional float ColumnPadding ); native(816) final function AutoPositionOn( array Components, GUIComponent Frame, float LeftPadPerc, float UpperPadPerc, float RightPadPerc, float LowerPadPerc, optional int NumberOfColumns, optional float ColumnPadding ); native(817) final function UpdateOffset(float PosX, float PosY, float PosW, float PosH); //native(818) final function DrawSpriteWidget(Canvas C, float ResScaleX, float ResScaleY, out HudBase.SpriteWidget Widget); //native(819) final function DrawNumericWidget(Canvas C, float ResScaleX, float ResScaleY, out HudBase.NumericWidget Widget, out HudBase.DigitSet Digit); // The ActualXXXX functions are not viable until after the first pre-render so don't // use them in inits native(820) final function float ActualWidth( optional coerce float Val, optional bool bForce ); native(821) final function float ActualHeight( optional coerce float Val, optional bool bForce ); native(822) final function float ActualLeft( optional coerce float Val, optional bool bForce ); native(823) final function Float ActualTop( optional coerce float Val, optional bool bForce ); native(824) final function float RelativeLeft( optional coerce float RealLeft, optional bool bForce ); native(825) final function float RelativeTop( optional coerce float RealTop, optional bool bForce ); native(826) final function float RelativeWidth( optional coerce float RealWidth, optional bool bForce ); native(827) final function float RelativeHeight( optional coerce float RealHeight, optional bool bForce ); event ResolutionChanged( int ResX, int ResY ); function SetPosition( float NewLeft, float NewTop, float NewWidth, float NewHeight, optional bool bForceRelative ) { if ( bDebugging && (Controller == None || Controller.bModAuthor) ) log(Name$".SetPosition( "$NewLeft$","@NewTop$","@NewWidth$","@NewHeight$","@bForceRelative,'ModAuthor'); if ( bForceRelative ) { WinLeft = RelativeLeft(NewLeft); WinTop = RelativeTop(NewTop); WinWidth = RelativeWidth(NewWidth); WinHeight = RelativeHeight(NewHeight); } else { WinLeft = NewLeft; WinTop = NewTop; WinWidth = NewWidth; WinHeight = NewHeight; } if ( bDebugging && bForceRelative && (Controller == None || Controller.bModAuthor) ) log(Name@"SetPosition() Current L:"$WinLeft$"("$Bounds[0]$") T:"$WinTop$"("$Bounds[1]$") W:"$WinWidth$"("$Bounds[0]+Bounds[2]$") H:"$WinHeight$"("$Bounds[1]+Bounds[3]$")",'ModAuthor'); } // For debugging native(828) final function string GetMenuPath(); // Used only for design mode - performs raw hit detection, without regard to properties that affect // hit detection (bAcceptsInput, MenuState, etc.) native(829) final function bool SpecialHit( optional bool bForce ); event string AdditionalDebugString() { return ""; } event Timer() { OnTimer(Self); } event Opened(GUIComponent Sender) // Called when the Menu Owner is opened { LoadIni(); if ( ToolTip != None ) { ToolTip.InitComponent( Controller, Self ); SetToolTipText( Hint ); } } event Closed(GUIComponent Sender, bool bCancelled) // Called when the Menu Owner is closed { if (!bCancelled) SaveIni(); } event Free() // This control is no longer needed { MenuOwner = None; PageOwner = None; Controller = None; FocusInstead = None; FriendlyLabel = None; Style = None; if ( ToolTip != None ) ToolTip.Free(); ToolTip = None; } function string LoadINI() { local string s; if ( (PlayerOwner()==None) || (INIOption=="") ) return ""; if ( IniOption ~= "@Internal" ) { OnLoadIni(Self,""); return ""; } s = PlayerOwner().ConsoleCommand("get"@IniOption); if (s=="") s = IniDefault; OnLoadINI(Self,s); return s; } function SaveINI(optional string Value) { if (PlayerOwner()==None) return; OnSaveINI(Self); } // Take a string and strip out colour codes static function string StripColorCodes(string InString) { local int CodePos; CodePos = InStr(InString, Chr(27)); // while(CodePos != -1 && CodePos < Len(InString)-3) // ignore colour codes at the end of the string while ( CodePos != -1 ) // do not ignore color codes at the end of the word, or they aren't stripped { InString = Left(InString, CodePos)$Mid(InString, CodePos+4); CodePos = InStr(InString, Chr(27)); } return InString; } static function string MakeColorCode(color NewColor) { // Text colours use 1 as 0. if(NewColor.R == 0) NewColor.R = 1; if(NewColor.G == 0) NewColor.G = 1; if(NewColor.B == 0) NewColor.B = 1; return Chr(0x1B)$Chr(NewColor.R)$Chr(NewColor.G)$Chr(NewColor.B); } // Functions event MenuStateChange(eMenuState Newstate) { //log("MenuStateChange:"$NewState@Self.Name); if ( MenuState != MSAT_Watched ) LastMenuState = MenuState; bPendingFocus = false; MenuState = NewState; switch (MenuState) { case MSAT_Focused: if ( !bNeverFocus ) { bHasFocus = true; break; } MenuState = MSAT_Blurry; case MSAT_Blurry: bHasFocus = false; if ( LastMenuState != MSAT_Blurry && LastMenuState != MSAT_Disabled ) OnDeActivate(); break; case MSAT_Watched: if (bFocusOnWatch) { SetFocus(None); return; } OnWatch(); break; case MSAT_Disabled: if (Controller.ActiveControl == Self) Controller.ActiveControl = None; if (Controller.FocusedControl == Self) LoseFocus(None); break; } if ( FriendlyLabel != None ) FriendlyLabel.MenuState = MenuState; } event bool IsMultiSelect() { if ( Controller == None ) return false; return bDropSource && DropState != DRP_Source && Controller.CtrlPressed && OnMultiSelect(Self); } event DropStateChange(eDropState NewState) { if (Controller == None) return; // log( Name$".DropStateChange Current:"$GetEnum(enum'eDropState',DropState)@"New:"$GetEnum(enum'eDropState',NewState) // @"DropSource:"$Controller.DropSource == Self@"DropTarget:"$Controller.DropTarget==Self); switch (NewState) { case DRP_None: // might be DropTarget with DropState == DRP_Source if we are mousing over the DropSource if ( Controller.DropTarget == Self ) { OnDragLeave(Self); Controller.DropTarget = None; // If this component is also the DropSource, do not alter the DropState if ( Controller.DropSource == Self ) return; } else if (Controller.DropSource == Self) { UpdateOffset(0,0,0,0); Controller.DropSource = None; } break; case DRP_Source: // Don't alter the drop state if component didn't want to begin a drag operation if ( !OnBeginDrag(Self) ) return; Controller.DropSource = Self; Controller.PlayInterfaceSound(CS_Drag); break; case DRP_Target: Controller.DropTarget = Self; if (DropState == DRP_None) OnDragEnter(Self); break; case DRP_Accept: Controller.PlayInterfaceSound(CS_Up); if ( Controller.DropSource != None ) Controller.DropSource.OnEndDrag(Self, True); Controller.DropTarget = None; NewState = DRP_None; break; case DRP_Reject: Controller.PlayInterfaceSound(CS_Down); if ( Controller.DropSource != None ) Controller.DropSource.OnEndDrag(Self, False); Controller.DropTarget = None; NewState = DRP_None; break; } DropState = NewState; } event InitComponent(GUIController MyController, GUIComponent MyOwner) { Controller = MyController; MenuOwner = MyOwner; PageOwner = OwnerPage(); if (Style==None) Style = Controller.GetStyle(StyleName, FontScale); } function bool IsInBounds() // Script version of PerformHitTest { return ( (Controller.MouseX >= Bounds[0] && Controller.MouseX<=Bounds[2]) && (Controller.MouseY >= Bounds[1] && Controller.MouseY <=Bounds[3]) ); } function bool IsInClientBounds() { return ( (Controller.MouseX >= ClientBounds[0] && Controller.MouseX<=ClientBounds[2]) && (Controller.MouseY >= ClientBounds[1] && Controller.MouseY <=ClientBounds[3]) ); } event bool CanAcceptFocus() { return MenuState != MSAT_Disabled && bVisible && !bNeverFocus; } event SetFocus(GUIComponent Who) { if (Who==None) { if (bNeverFocus) { if (FocusInstead != None) FocusInstead.SetFocus(Who); return; } bPendingFocus = true; if (Controller.FocusedControl!=None) { if (Controller.FocusedControl == Self) // Already Focused return; else Controller.FocusedControl.LoseFocus(Self); } MenuStateChange(MSAT_Focused); Controller.FocusedControl = self; OnActivate(); } else MenuStateChange(MSAT_Focused); if (MenuOwner!=None) MenuOwner.SetFocus(self); } event LoseFocus(GUIComponent Sender) { if (Controller!=None) Controller.FocusedControl = None; if (MenuState != MSAT_Disabled) MenuStateChange(MSAT_Blurry); if (MenuOwner!=None) MenuOwner.LoseFocus(Self); } event bool FocusFirst(GUIComponent Sender) // Focus your first child, or yourself if no childrean { if ( !bTabStop || !CanAcceptFocus() ) return false; SetFocus(None); return true; } event bool FocusLast(GUIComponent Sender) // Focus your last child, or yourself { if ( !bTabStop || !CanAcceptFocus() ) return false; SetFocus(None); return true; } event bool NextControl(GUIComponent Sender) { if (MenuOwner!=None) return MenuOwner.NextControl(Self); return false; } event bool PrevControl(GUIComponent Sender) { if (MenuOwner!=None) return MenuOwner.PrevControl(Self); return false; } event bool NextPage() { if (MenuOwner != None) return MenuOwner.NextPage(); return false; } event bool PrevPage() { if (MenuOwner != None) return MenuOwner.PrevPage(); return false; } // Force control to use same area as its MenuOwner. function FillOwner() { WinLeft = 0.0; WinTop = 0.0; WinWidth = 1.0; WinHeight = 1.0; bScaleToParent = true; bBoundToParent = true; } event SetVisibility( coerce bool bIsVisible) { bVisible = bIsVisible; if (bVisible) OnShow(); else OnHide(); } function CenterMouse() { local PlayerController PC; local float MidX, MidY; PC = PlayerOwner(); if ( PC != None ) { MidX = ActualLeft() + ActualWidth() / 2; MidY = ActualTop() + ActualHeight() / 2; PC.ConsoleCommand("SETMOUSE" @ MidX @ MidY); } } event Hide() { SetVisibility(false); } event Show() { SetVisibility(true); } function SetFocusInstead( GUIComponent InFocusComp ) { if ( InFocusComp != None ) bNeverFocus = true; FocusInstead = InFocusComp; } function SetFriendlyLabel(GUILabel NewLabel) { FriendlyLabel = NewLabel; } function SetHint(string NewHint) { Hint = NewHint; SetToolTipText(Hint); } function SetToolTipText( string NewToolTipText ) { if ( ToolTip != None ) ToolTip.SetTip( NewToolTipText ); } function SetTooltip( GUIToolTip InTooltip ) { if ( ToolTip != None ) ToolTip.LeaveArea(); ToolTip = InToolTip; if ( ToolTip != None ) ToolTip.InitComponent( Controller, Self ); } function PadLeft( out string Src, int StrLen, optional string PadStr ) { if ( PadStr == "" ) PadStr = " "; while ( Len(Src) < StrLen ) Src = PadStr $ Src; } function PadRight( out string Src, int StrLen, optional string PadStr ) { if ( PadStr == "" ) PadStr = " "; while ( Len(Src) < StrLen ) Src = Src $ PadStr; } final function DebugFocus( GUIComponent Who, bool bLose ) { return; if ( Controller != None && Controller.CtrlPressed ) { if ( bLose ) { if ( Who == None ) log(Name@"losing focus chain down"); else log(Name@"losing focus of"@Who); } else { if ( Who == None ) log(Name@"sending focus chain down"); else log(Name@"setting focus to"@Who); } } } final function DebugFocusPosition( GUIComponent Who, bool Last ) { return; if ( Controller.CtrlPressed ) { if ( Last ) { if ( Who == None ) log(Name@"FocusLast going down"); else log(Name@"FocusLast call from"@Who); } else { if ( Who == None ) log(Name@"FocusFirst going down"); else log(Name@"FocusFirst call from"@Who); } } } event GUIPage OwnerPage() { local GUIComponent C; if ( PageOwner != None ) return PageOwner; C = Self; while ( C != None ) { if ( GUIPage(C) != None ) return GUIPage(C); C = C.MenuOwner; } Warn( "OwnerPage not found!" ); return None; } // By default, we don't care which components are animating // Input is disabled while bAnimating event BeginAnimation( GUIComponent Animating ) { bAnimating = True; if ( MenuOwner != None ) MenuOwner.BeginAnimation(Animating); } event EndAnimation( GUIComponent Animating, EAnimationType Type ) { bAnimating = False; if ( MenuOwner != None ) MenuOwner.EndAnimation( Animating, Type ); if ( Animating == Self ) OnEndAnimation(Animating, Type); } // If you short circuit these functions (by modifying the animation arrays directly) // you must call BeginAnimation() on the owning page for each frame function Animate( float NewLeft, float NewTop, optional float Time ) { local int i; i = MotionFrame.Length; MotionFrame.Length = i + 1; MotionFrame[i].X = NewLeft; MotionFrame[i].Y = NewTop; MotionFrame[i].Z = Time; if ( i < 1 ) BeginAnimation(Self); } function Resize( float NewWidth, float NewHeight, optional float Time ) { local int i; i = SizeFrame.Length; SizeFrame.Length = i + 1; SizeFrame[i].X = NewWidth; SizeFrame[i].Y = NewHeight; SizeFrame[i].Z = Time; if ( i < 1 ) BeginAnimation(Self); } function DAnimate( float NewLeft, float NewTop, float NewWidth, float NewHeight, optional float PositionTime, optional float DimensionTime ) { Animate( NewLeft, NewTop, PositionTime ); Resize( NewWidth, NewHeight, DimensionTime ); } function KillAnimation() { if ( MotionFrame.Length > 0 ) { MotionFrame.Remove( 0, MotionFrame.Length ); EndAnimation( Self, AT_Position ); } if ( SizeFrame.Length > 0 ) { SizeFrame.Remove( 0, SizeFrame.Length ); EndAnimation( Self, AT_Dimension ); } } final function EnableComponent(GUIComponent Comp) { if ( Comp == None ) return; Comp.EnableMe(); } final function DisableComponent(GUIComponent Comp) { if ( Comp == None ) return; Comp.DisableMe(); } function EnableMe() { if ( MenuState != MSAT_Disabled ) return; MenuStateChange(MSAT_Blurry); } function DisableMe() { if ( MenuState == MSAT_Disabled ) return; MenuStateChange(MSAT_Disabled); } function LevelChanged() { if ( ToolTip != None ) ToolTip.Free(); } function DebugTabOrder(); defaultproperties { MenuState=MSAT_Blurry FontScale=FNS_Medium IniOption="" bBoundToParent=false bScaleToParent=false bHasFocus=false bVisible=true bAcceptsInput=false bCaptureTabs=false bCaptureMouse=false bNeverFocus=false bRepeatClick=false WinTop=0.0 WinLeft=0.0 WinWidth=1.0 WinHeight1.0 Tag=-1 MouseCursorIndex=0 bFocusOnWatch=false bRequireReleaseClick=false TimerIndex=-1 bMouseOverSound=false OnClickSound=CS_None RenderWeight=0.5 bTabStop=false bInit=True TabOrder=-1 BoundingType=SCALE_All ScalingType=SCALE_All WhiteColor=(R=253,G=237,B=244,A=255) bStandardized=false StandardHeight=0 }