etqw-sdk/source/game/guis/UIRadialMenu.h

275 lines
8.1 KiB
C++

// Copyright (C) 2007 Id Software, Inc.
//
#ifndef __GAME_GUIS_USERINTERFACERADIALMENU_H__
#define __GAME_GUIS_USERINTERFACERADIALMENU_H__
#include "UserInterfaceTypes.h"
extern const char sdUITemplateFunctionInstance_IdentifierRadialMenu[];
/*
============
sdUIRadialMenu
============
*/
SD_UI_PROPERTY_TAG(
alias = "radialmenu";
)
class sdUIRadialMenu :
public sdUIWindow {
protected:
typedef enum radialMenuEvent_e {
RME_COMMAND = WE_NUM_EVENTS + 1,
RME_MEASUREITEM,
RME_DRAWITEM,
RME_DRAWCONTEXT,
RME_DRAWDEADZONE,
RME_PAGE_PUSHED,
RME_PAGE_POPPED,
RME_NUM_EVENTS,
} bindEvent_t;
static const char* eventNames[ RME_NUM_EVENTS - WE_NUM_EVENTS ];
public:
typedef sdUITemplateFunction< sdUIRadialMenu > uiTemplateFunction_t;
SD_UI_DECLARE_CLASS( sdUIRadialMenu )
enum eDrawStyle { DS_INVALID = -1, DS_ARC, DS_VERTICAL, DS_MAX };
enum eRadialMenuFlag {
RMF_USE_NUMBER_SHORTCUTS = BITT< sdUIWindow::NEXT_WINDOW_FLAG + 0 >::VALUE,
};
sdUIRadialMenu();
virtual ~sdUIRadialMenu();
virtual const char* GetScopeClassName() const { return "sdUIRadialMenu"; }
virtual bool PostEvent( const sdSysEvent* event );
virtual sdUIFunctionInstance* GetFunction( const char* name );
virtual bool RunNamedMethod( const char* name, sdUIFunctionStack& stack );
void Script_InsertItem( sdUIFunctionStack& stack );
void Script_InsertPage( sdUIFunctionStack& stack );
void Script_GetItemData( sdUIFunctionStack& stack );
void Script_Clear( sdUIFunctionStack& stack );
void Script_ClearPage( sdUIFunctionStack& stack );
void Script_PostCommand( sdUIFunctionStack& stack );
void Script_PushPage( sdUIFunctionStack& stack );
void Script_PopPage( sdUIFunctionStack& stack );
void Script_ClearPageStack( sdUIFunctionStack& stack );
void Script_LoadFromDef( sdUIFunctionStack& stack );
void Script_AppendFromDef( sdUIFunctionStack& stack );
void Script_FillFromEnumerator( sdUIFunctionStack& stack );
void Script_TransitionItemVec4( sdUIFunctionStack& stack );
void Script_GetItemTransitionVec4Result( sdUIFunctionStack& stack );
void Script_ClearTransitions( sdUIFunctionStack& stack );
static void Clear( sdUIRadialMenu* menu );
static int InsertPage( sdUIRadialMenu* menu, int page, const char* text );
static int InsertItem( sdUIRadialMenu* menu, int page, const char* text );
virtual void EnumerateEvents( const char* name, const idList<unsigned short>& flags, idList< sdUIEventInfo >& events, const idTokenCache& tokenCache );
virtual int GetMaxEventTypes( void ) const { return RME_NUM_EVENTS; }
virtual void ApplyLayout();
static void InitFunctions( void );
static void ShutdownFunctions( void ) { radialMenuFunctions.DeleteContents(); }
static const uiTemplateFunction_t* FindFunction( const char* name );
private:
enum radialItemStyle { RIS_LEFT = BITT< 0 >::VALUE,
RIS_RIGHT = BITT< 1 >::VALUE,
RIS_CENTER = BITT< 2 >::VALUE,
RIS_TOP = BITT< 3 >::VALUE,
RIS_BOTTOM = BITT< 4 >::VALUE,
};
enum radialTransitionProperty_e{ RTP_FORECOLOR = -2,
RTP_BACKCOLOR = -1,
RTP_PROPERTY_0 = 0,
RTP_PROPERTY_1 = 1,
RTP_PROPERTY_2 = 2,
RTP_PROPERTY_3 = 3,
RTP_PROPERTY_MAX = 4
};
static const int MAX_VEC4_EVALUATORS = RTP_PROPERTY_MAX;
typedef sdTransitionEvaluator< idVec4 > vec4Evaluator_t;
typedef idStaticList< vec4Evaluator_t, MAX_VEC4_EVALUATORS > vec4EvaluatorList_t;
class sdTransition {
public:
sdTransition() : evaluators( NULL ) {
backColor.InitConstant( idVec4( 0.0f, 0.0f, 0.0f, 0.0f ) );
foreColor.InitConstant( colorWhite );
}
~sdTransition() {
FreeEvaluators();
}
vec4Evaluator_t* GetEvaluator( int index, bool allowCreate );
void FreeEvaluators() {
vec4EvaluatorListAllocator.Free( evaluators );
evaluators = NULL;
}
vec4Evaluator_t backColor;
vec4Evaluator_t foreColor;
vec4EvaluatorList_t* evaluators;
};
static idBlockAlloc< vec4EvaluatorList_t, 32 > vec4EvaluatorListAllocator;
struct radialItem_t {
radialItem_t() :
title( NULL ),
owner( NULL ) {
commandID.SetGranularity( 1 );
commandData.SetGranularity( 1 );
flags.enabled = true;
flags.drawChevron = false;
size.Zero();
lastDrawAngle = 0.0f;
}
bool Update();
const sdDeclLocStr* title;
idStrList commandID;
idStrList commandData;
idStr commandKey;
idStr commandNumberKey;
idStr drawCallback;
uiDrawPart_t part;
idVec2 size;
vec4EvaluatorList_t evaluators;
idStr scriptUpdateCallback;
idStr scriptUpdateParm;
float lastDrawAngle;
struct flags_t {
bool enabled : 1;
bool drawChevron : 1;
} flags;
sdTransition transition;
sdUIWindow* owner;
};
struct radialPage_t {
radialPage_t() : currentItem( 0 ), popFactor( 1.5f ), title( NULL ) {}
const sdDeclLocStr* title;
idList< radialItem_t > items;
int currentItem;
float popFactor;
idVec2 maxSize; // dimensions of the largest items
};
protected:
bool OnValidateDrawStyle( const float newValue );
void LoadFromDef( const sdDeclRadialMenu& def, radialPage_t& page );
virtual void DrawLocal();
void DrawItem( radialPage_t& page, radialItem_t& item, int index, const idVec2& center, const idVec2& offset, int radialItemStyle );
void DrawTitle( radialPage_t& page, const idVec2& center );
void OnCurrentPageChanged( const float oldValue, const float newValue );
void OnDrawStyleChanged( const float oldValue, const float newValue );
bool OnValidateCurrentItem( const float newValue );
radialPage_t* GetSafePage( int index ) {
if( index < 0 || index >= pages.Num() ) {
return NULL;
}
return &pages[ index ];
}
radialItem_t* GetSafeItem( int pageIndex, int index ) {
if( radialPage_t* page = GetSafePage( pageIndex )) {
if( index >= 0 && index < page->items.Num() ) {
return &page->items[ index ];
}
}
return NULL;
}
void DrawItemCircle( radialPage_t& page, const idVec2& center );
void DrawItemLine( radialPage_t& page, const idVec2& center );
void HandleArcMouseMove( const sdSysEvent* event, const idVec2 delta, radialPage_t& page, int& currentItem );
void ClearTransition( sdTransition& transition );
void InitVec4Transition( const int property, const idVec4& from, const idVec4& to, const int time, const idStr& accel, int item, int page );
void MoveToFirstEnabledItem( int index );
protected:
SD_UI_PROPERTY_TAG(
title = "1. Object/Radius";
desc = "Radius of the menu";
editor = "edit";
datatype = "float";
)
sdFloatProperty radius;
SD_UI_PROPERTY_TAG(
title = "1. Object/CurrentPage";
desc = "Current page";
editor = "edit";
datatype = "float";
)
sdFloatProperty currentPage;
SD_UI_PROPERTY_TAG(
title = "1. Object/CurrentItem";
desc = "CurrentItem";
editor = "edit";
datatype = "float";
)
sdFloatProperty currentItem;
SD_UI_PROPERTY_TAG(
title = "1. Object/VerticalPaddin";
desc = "Vertical padding";
editor = "edit";
datatype = "float";
)
sdFloatProperty verticalPadding;
SD_UI_PROPERTY_TAG(
title = "1. Object/DrawStyle";
desc = "Radial menu draw style";
editor = "edit";
datatype = "float";
)
sdFloatProperty drawStyle;
idVec2 lastArcMoveInfo;
idVec2 imaginaryCursorPos;
protected:
static idHashMap< sdUITemplateFunction< sdUIRadialMenu >* > radialMenuFunctions;
private:
idList< radialPage_t > pages;
sdStack< int > pageStack;
static const int MAX_ITEMS_PER_PAGE = 10;
int lastActiveEventFrame;
};
#endif // ! __GAME_GUIS_USERINTERFACERADIALMENU_H__