mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
Initial Commit of CyanWorlds.com Engine Open Source Client/Plugin
This commit is contained in:
@ -0,0 +1,392 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIButtonMod Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIButtonMod.h"
|
||||
#include "pfGUIDraggableMod.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plAvatar/plAGModifier.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Control Proc For Managing the Draggable /////////////////////////////////
|
||||
|
||||
class pfGUIButtonDragProc : public pfGUICtrlProcObject
|
||||
{
|
||||
protected:
|
||||
|
||||
pfGUICtrlProcObject *fOrigProc;
|
||||
|
||||
pfGUIButtonMod *fParent;
|
||||
pfGUIDraggableMod *fDraggable;
|
||||
hsBool fReportDrag;
|
||||
|
||||
public:
|
||||
|
||||
pfGUIButtonDragProc( pfGUIButtonMod *parent, pfGUIDraggableMod *draggable, pfGUICtrlProcObject *origProc, hsBool reportDrag )
|
||||
{
|
||||
fParent = parent;
|
||||
fDraggable = draggable;
|
||||
fOrigProc = origProc;
|
||||
fReportDrag = reportDrag;
|
||||
}
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl )
|
||||
{
|
||||
// The draggable was let up, so now we stop dragging, disable the draggable again, and pass
|
||||
// on the event to our original proc
|
||||
if( fOrigProc != nil && fParent->IsTriggering() )
|
||||
fOrigProc->DoSomething( ctrl );
|
||||
if (!fParent->IsButtonDown())
|
||||
fParent->StopDragging( false );
|
||||
}
|
||||
|
||||
virtual void HandleExtendedEvent( pfGUIControlMod *ctrl, UInt32 event )
|
||||
{
|
||||
if( event == pfGUIDraggableMod::kDragging )
|
||||
{
|
||||
// First test if we're inside our button (if so, we stop dragging)
|
||||
if( fParent->PointInBounds( fDraggable->GetLastMousePt() ) )
|
||||
{
|
||||
// Cancel the drag
|
||||
fParent->StopDragging( true );
|
||||
return;
|
||||
}
|
||||
|
||||
if( !fReportDrag )
|
||||
return;
|
||||
}
|
||||
|
||||
if( fOrigProc != nil )
|
||||
fOrigProc->HandleExtendedEvent( ctrl, event );
|
||||
}
|
||||
|
||||
virtual void UserCallback( UInt32 userValue )
|
||||
{
|
||||
if( fOrigProc != nil )
|
||||
fOrigProc->UserCallback( userValue );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void pfGUIButtonMod::StopDragging( hsBool cancel )
|
||||
{
|
||||
fDraggable->StopDragging( cancel );
|
||||
fDraggable->SetVisible( false );
|
||||
fDraggable->SetHandler( fOrigHandler );
|
||||
fOrigHandler = nil;
|
||||
|
||||
if( !fOrigReportedDrag )
|
||||
fDraggable->ClearFlag( pfGUIDraggableMod::kReportDragging );
|
||||
|
||||
// Steal interest back
|
||||
fDialog->SetControlOfInterest( this );
|
||||
}
|
||||
|
||||
void pfGUIButtonMod::StartDragging( void )
|
||||
{
|
||||
fOrigReportedDrag = fDraggable->HasFlag( pfGUIDraggableMod::kReportDragging );
|
||||
fDraggable->SetFlag( pfGUIDraggableMod::kReportDragging );
|
||||
|
||||
fOrigHandler = fDraggable->GetHandler();
|
||||
fDraggable->SetVisible( true );
|
||||
fDraggable->SetHandler( TRACKED_NEW pfGUIButtonDragProc( this, fDraggable, fOrigHandler, fOrigReportedDrag ) );
|
||||
fDraggable->HandleMouseDown( fOrigMouseDownPt, 0 );
|
||||
}
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIButtonMod::pfGUIButtonMod()
|
||||
{
|
||||
fAnimName = nil;
|
||||
fMouseOverAnimName = nil;
|
||||
fDraggable = nil;
|
||||
fOrigHandler = nil;
|
||||
|
||||
fClicking = false;
|
||||
fTriggering = false;
|
||||
fNotifyType = kNotifyOnUp;
|
||||
SetFlag( kWantsInterest );
|
||||
}
|
||||
|
||||
pfGUIButtonMod::~pfGUIButtonMod()
|
||||
{
|
||||
delete [] fAnimName;
|
||||
delete [] fMouseOverAnimName;
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIButtonMod::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIButtonMod::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg );
|
||||
if( refMsg != nil && refMsg->fType == kRefDraggable )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
fDraggable = pfGUIDraggableMod::ConvertNoRef( refMsg->GetRef() );
|
||||
fDraggable->SetVisible( false ); // Disable until we're dragging
|
||||
}
|
||||
else
|
||||
fDraggable = nil;
|
||||
return true;
|
||||
}
|
||||
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIButtonMod::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
|
||||
fAnimationKeys.Reset();
|
||||
UInt32 i, count = s->ReadSwap32();
|
||||
for( i = 0; i < count; i++ )
|
||||
fAnimationKeys.Append( mgr->ReadKey( s ) );
|
||||
fAnimName = s->ReadSafeString();
|
||||
|
||||
fMouseOverAnimKeys.Reset();
|
||||
count = s->ReadSwap32();
|
||||
for( i = 0; i < count; i++ )
|
||||
fMouseOverAnimKeys.Append( mgr->ReadKey( s ) );
|
||||
fMouseOverAnimName = s->ReadSafeString();
|
||||
|
||||
fNotifyType = s->ReadSwap32();
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefDraggable ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
void pfGUIButtonMod::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
|
||||
UInt32 i, count = fAnimationKeys.GetCount();
|
||||
s->WriteSwap32( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->WriteKey( s, fAnimationKeys[ i ] );
|
||||
s->WriteSafeString( fAnimName );
|
||||
|
||||
count = fMouseOverAnimKeys.GetCount();
|
||||
s->WriteSwap32( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->WriteKey( s, fMouseOverAnimKeys[ i ] );
|
||||
s->WriteSafeString( fMouseOverAnimName );
|
||||
|
||||
s->WriteSwap32( fNotifyType );
|
||||
|
||||
mgr->WriteKey( s, fDraggable != nil ? fDraggable->GetKey() : nil );
|
||||
|
||||
}
|
||||
|
||||
//// UpdateBounds ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIButtonMod::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
|
||||
{
|
||||
pfGUIControlMod::UpdateBounds( invXformMatrix, force );
|
||||
if( fAnimationKeys.GetCount() > 0 || fMouseOverAnimKeys.GetCount() > 0 )
|
||||
fBoundsValid = false;
|
||||
}
|
||||
|
||||
//// HandleMouseDown/Up //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIButtonMod::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
fClicking = true;
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
{
|
||||
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
|
||||
msg->SetCmd( plAnimCmdMsg::kContinue );
|
||||
msg->SetCmd( plAnimCmdMsg::kSetForewards );
|
||||
msg->SetCmd( plAnimCmdMsg::kGoToBegin );
|
||||
msg->SetAnimName( fAnimName );
|
||||
msg->AddReceivers( fAnimationKeys );
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
|
||||
IPlaySound( kMouseDown );
|
||||
|
||||
fOrigMouseDownPt = mousePt;
|
||||
if ( fNotifyType == kNotifyOnDown || fNotifyType == kNotifyOnUpAndDown)
|
||||
{
|
||||
fTriggering = true;
|
||||
DoSomething();
|
||||
fTriggering = false;
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIButtonMod::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
|
||||
// make sure that we got the down click first
|
||||
if ( !fClicking )
|
||||
return;
|
||||
|
||||
fClicking = false;
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
{
|
||||
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
|
||||
msg->SetCmd( plAnimCmdMsg::kContinue );
|
||||
msg->SetCmd( plAnimCmdMsg::kSetBackwards );
|
||||
msg->SetCmd( plAnimCmdMsg::kGoToEnd );
|
||||
msg->SetAnimName( fAnimName );
|
||||
msg->AddReceivers( fAnimationKeys );
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
|
||||
IPlaySound( kMouseUp );
|
||||
|
||||
// Don't run the command if the mouse is outside our bounds
|
||||
if( !fBounds.IsInside( &mousePt ) && fNotifyType != kNotifyOnUpAndDown )
|
||||
return;
|
||||
|
||||
if ( fNotifyType == kNotifyOnUp || fNotifyType == kNotifyOnUpAndDown)
|
||||
fTriggering = true;
|
||||
DoSomething();
|
||||
fTriggering = false;
|
||||
}
|
||||
|
||||
void pfGUIButtonMod::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
if( !fClicking )
|
||||
return;
|
||||
|
||||
if( fDraggable == nil )
|
||||
return;
|
||||
|
||||
if( !fDraggable->IsVisible() )
|
||||
{
|
||||
// Are we outside ourselves?
|
||||
if( !PointInBounds( mousePt ) )
|
||||
{
|
||||
// Yes, start dragging
|
||||
StartDragging();
|
||||
|
||||
// Hand off our interest to the draggable
|
||||
fDialog->SetControlOfInterest( fDraggable );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIButtonMod::SetNotifyType(Int32 kind)
|
||||
{
|
||||
fNotifyType = kind;
|
||||
}
|
||||
|
||||
Int32 pfGUIButtonMod::GetNotifyType()
|
||||
{
|
||||
return fNotifyType;
|
||||
}
|
||||
|
||||
hsBool pfGUIButtonMod::IsButtonDown()
|
||||
{
|
||||
return fClicking;
|
||||
}
|
||||
|
||||
//// SetInteresting //////////////////////////////////////////////////////////
|
||||
// Overridden to play mouse over animation when we're interesting
|
||||
|
||||
void pfGUIButtonMod::SetInteresting( hsBool i )
|
||||
{
|
||||
pfGUIControlMod::SetInteresting( i );
|
||||
|
||||
if( fMouseOverAnimKeys.GetCount() )
|
||||
{
|
||||
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
|
||||
msg->SetCmd( plAnimCmdMsg::kContinue );
|
||||
msg->SetCmd( fInteresting ? plAnimCmdMsg::kSetForewards : plAnimCmdMsg::kSetBackwards );
|
||||
msg->SetAnimName( fMouseOverAnimName );
|
||||
msg->AddReceivers( fMouseOverAnimKeys );
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
|
||||
if( i )
|
||||
IPlaySound( kMouseOver );
|
||||
else
|
||||
IPlaySound( kMouseOff );
|
||||
}
|
||||
|
||||
|
||||
void pfGUIButtonMod::SetAnimationKeys( hsTArray<plKey> &keys, const char *name )
|
||||
{
|
||||
fAnimationKeys = keys;
|
||||
delete [] fAnimName;
|
||||
if( name != nil )
|
||||
{
|
||||
fAnimName = TRACKED_NEW char[ strlen( name ) + 1 ];
|
||||
strcpy( fAnimName, name );
|
||||
}
|
||||
else
|
||||
fAnimName = nil;
|
||||
}
|
||||
|
||||
void pfGUIButtonMod::SetMouseOverAnimKeys( hsTArray<plKey> &keys, const char *name )
|
||||
{
|
||||
fMouseOverAnimKeys = keys;
|
||||
delete [] fMouseOverAnimName;
|
||||
if( name != nil )
|
||||
{
|
||||
fMouseOverAnimName = TRACKED_NEW char[ strlen( name ) + 1 ];
|
||||
strcpy( fMouseOverAnimName, name );
|
||||
}
|
||||
else
|
||||
fMouseOverAnimName = nil;
|
||||
}
|
||||
|
||||
|
||||
//// IGetDesiredCursor ///////////////////////////////////////////////////////
|
||||
|
||||
UInt32 pfGUIButtonMod::IGetDesiredCursor( void ) const
|
||||
{
|
||||
if( fHandler == nil )
|
||||
return 0;
|
||||
|
||||
if( fClicking )
|
||||
return plInputInterface::kCursorClicked;
|
||||
|
||||
return plInputInterface::kCursorPoised;
|
||||
}
|
||||
|
@ -0,0 +1,121 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIButtonMod Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIButtonMod_h
|
||||
#define _pfGUIButtonMod_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
class plMessage;
|
||||
class plPostEffectMod;
|
||||
class plAGMasterMod;
|
||||
class pfGUIDraggableMod;
|
||||
|
||||
class pfGUIButtonMod : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
hsTArray<plKey> fAnimationKeys;
|
||||
char *fAnimName;
|
||||
|
||||
hsTArray<plKey> fMouseOverAnimKeys;
|
||||
char *fMouseOverAnimName;
|
||||
|
||||
hsBool fClicking;
|
||||
hsBool fTriggering;
|
||||
|
||||
hsPoint3 fOrigMouseDownPt;
|
||||
pfGUIDraggableMod *fDraggable;
|
||||
pfGUICtrlProcObject *fOrigHandler;
|
||||
hsBool fOrigReportedDrag;
|
||||
|
||||
|
||||
Int32 fNotifyType;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual UInt32 IGetDesiredCursor( void ) const; // As specified in plInputInterface.h
|
||||
|
||||
public:
|
||||
|
||||
pfGUIButtonMod();
|
||||
virtual ~pfGUIButtonMod();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIButtonMod );
|
||||
GETINTERFACE_ANY( pfGUIButtonMod, pfGUIControlMod );
|
||||
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void SetInteresting( hsBool i );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
|
||||
|
||||
virtual void SetNotifyType(Int32 kind);
|
||||
virtual Int32 GetNotifyType();
|
||||
virtual hsBool IsButtonDown();
|
||||
virtual hsBool IsTriggering() { return fTriggering; }
|
||||
enum SoundEvents
|
||||
{
|
||||
kMouseDown,
|
||||
kMouseUp,
|
||||
kMouseOver,
|
||||
kMouseOff
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kRefDraggable = kRefDerivedStart
|
||||
};
|
||||
|
||||
enum NotifyType
|
||||
{
|
||||
kNotifyOnUp = 0,
|
||||
kNotifyOnDown,
|
||||
kNotifyOnUpAndDown
|
||||
};
|
||||
|
||||
void StartDragging( void );
|
||||
void StopDragging( hsBool cancel );
|
||||
|
||||
// Export only
|
||||
void SetAnimationKeys( hsTArray<plKey> &keys, const char *name );
|
||||
void SetMouseOverAnimKeys( hsTArray<plKey> &keys, const char *name );
|
||||
};
|
||||
|
||||
#endif // _pfGUIButtonMod_h
|
@ -0,0 +1,206 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUICheckBoxCtrl Definition //
|
||||
// //
|
||||
// Almost like buttons, only they keep their stated (pressed/unpressed) //
|
||||
// when you click them, instead of reverting on mouse up. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUICheckBoxCtrl.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plAvatar/plAGModifier.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUICheckBoxCtrl::pfGUICheckBoxCtrl()
|
||||
{
|
||||
fAnimName = nil;
|
||||
SetFlag( kWantsInterest );
|
||||
fChecked = false;
|
||||
fClicking = false;
|
||||
fPlaySound = true;
|
||||
}
|
||||
|
||||
pfGUICheckBoxCtrl::~pfGUICheckBoxCtrl()
|
||||
{
|
||||
delete [] fAnimName;
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUICheckBoxCtrl::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUICheckBoxCtrl::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICheckBoxCtrl::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
|
||||
fAnimationKeys.Reset();
|
||||
UInt32 i, count = s->ReadSwap32();
|
||||
for( i = 0; i < count; i++ )
|
||||
fAnimationKeys.Append( mgr->ReadKey( s ) );
|
||||
|
||||
fAnimName = s->ReadSafeString();
|
||||
fChecked = s->ReadBool();
|
||||
}
|
||||
|
||||
void pfGUICheckBoxCtrl::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
|
||||
UInt32 i, count = fAnimationKeys.GetCount();
|
||||
s->WriteSwap32( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->WriteKey( s, fAnimationKeys[ i ] );
|
||||
|
||||
s->WriteSafeString( fAnimName );
|
||||
s->WriteBool( fChecked );
|
||||
}
|
||||
|
||||
//// UpdateBounds ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICheckBoxCtrl::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
|
||||
{
|
||||
pfGUIControlMod::UpdateBounds( invXformMatrix, force );
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
fBoundsValid = false;
|
||||
}
|
||||
|
||||
//// HandleMouseDown/Up //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICheckBoxCtrl::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
fClicking = true;
|
||||
if(fPlaySound)
|
||||
IPlaySound( kMouseDown );
|
||||
}
|
||||
|
||||
void pfGUICheckBoxCtrl::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
if( fClicking )
|
||||
{
|
||||
fClicking = false;
|
||||
|
||||
if(fPlaySound)
|
||||
IPlaySound( kMouseUp );
|
||||
|
||||
// Don't run the command if the mouse is outside our bounds
|
||||
if( fBounds.IsInside( &mousePt ) )
|
||||
{
|
||||
SetChecked( !fChecked );
|
||||
DoSomething();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// SetChecked //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICheckBoxCtrl::SetChecked( hsBool checked, hsBool immediate /*= false*/ )
|
||||
{
|
||||
fChecked = checked;
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
{
|
||||
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
|
||||
if( fChecked )
|
||||
{
|
||||
// Moving to true
|
||||
if( immediate )
|
||||
{
|
||||
msg->SetCmd( plAnimCmdMsg::kGoToEnd );
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->SetCmd( plAnimCmdMsg::kContinue );
|
||||
msg->SetCmd( plAnimCmdMsg::kSetForewards );
|
||||
msg->SetCmd( plAnimCmdMsg::kGoToBegin );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Moving to false
|
||||
if( immediate )
|
||||
{
|
||||
msg->SetCmd( plAnimCmdMsg::kGoToBegin );
|
||||
}
|
||||
else
|
||||
{
|
||||
msg->SetCmd( plAnimCmdMsg::kContinue );
|
||||
msg->SetCmd( plAnimCmdMsg::kSetBackwards );
|
||||
msg->SetCmd( plAnimCmdMsg::kGoToEnd );
|
||||
}
|
||||
}
|
||||
msg->SetAnimName( fAnimName );
|
||||
msg->AddReceivers( fAnimationKeys );
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUICheckBoxCtrl::SetAnimationKeys( hsTArray<plKey> &keys, const char *name )
|
||||
{
|
||||
fAnimationKeys = keys;
|
||||
delete [] fAnimName;
|
||||
if( name != nil )
|
||||
{
|
||||
fAnimName = TRACKED_NEW char[ strlen( name ) + 1 ];
|
||||
strcpy( fAnimName, name );
|
||||
}
|
||||
else
|
||||
fAnimName = nil;
|
||||
}
|
||||
|
||||
//// IGetDesiredCursor ///////////////////////////////////////////////////////
|
||||
|
||||
UInt32 pfGUICheckBoxCtrl::IGetDesiredCursor( void ) const
|
||||
{
|
||||
if( fClicking )
|
||||
return plInputInterface::kCursorClicked;
|
||||
|
||||
return plInputInterface::kCursorPoised;
|
||||
}
|
||||
|
@ -0,0 +1,95 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUICheckBoxCtrl Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUICheckBoxCtrl_h
|
||||
#define _pfGUICheckBoxCtrl_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
class plMessage;
|
||||
class plPostEffectMod;
|
||||
class plAGMasterMod;
|
||||
|
||||
class pfGUICheckBoxCtrl : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
hsTArray<plKey> fAnimationKeys;
|
||||
char *fAnimName;
|
||||
hsBool fClicking;
|
||||
|
||||
hsBool fChecked;
|
||||
hsBool fPlaySound;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual UInt32 IGetDesiredCursor( void ) const; // As specified in plInputInterface.h
|
||||
|
||||
public:
|
||||
|
||||
pfGUICheckBoxCtrl();
|
||||
virtual ~pfGUICheckBoxCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUICheckBoxCtrl );
|
||||
GETINTERFACE_ANY( pfGUICheckBoxCtrl, pfGUIControlMod );
|
||||
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
|
||||
|
||||
void SetChecked( hsBool checked, hsBool immediate = false );
|
||||
hsBool IsChecked( void ) { return fChecked; }
|
||||
|
||||
void DontPlaySounds() { fPlaySound = false; } // should the checkbox play sounds?
|
||||
|
||||
const hsTArray<plKey> &GetAnimationKeys( void ) const { return fAnimationKeys; }
|
||||
const char *GetAnimationName( void ) const { return fAnimName; }
|
||||
|
||||
enum SoundEvents
|
||||
{
|
||||
kMouseDown,
|
||||
kMouseUp,
|
||||
kMouseOver,
|
||||
kMouseOff
|
||||
};
|
||||
|
||||
// Export only
|
||||
void SetAnimationKeys( hsTArray<plKey> &keys, const char *name );
|
||||
};
|
||||
|
||||
#endif // _pfGUICheckBoxCtrl_h
|
@ -0,0 +1,130 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIClickMapCtrl Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIClickMapCtrl.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIClickMapCtrl::pfGUIClickMapCtrl()
|
||||
{
|
||||
fTracking = false;
|
||||
fCustomCursor = -1;
|
||||
}
|
||||
|
||||
pfGUIClickMapCtrl::~pfGUIClickMapCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIClickMapCtrl::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIClickMapCtrl::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIClickMapCtrl::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
}
|
||||
|
||||
void pfGUIClickMapCtrl::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
}
|
||||
|
||||
void pfGUIClickMapCtrl::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
IScreenToLocalPt( mousePt );
|
||||
fLastMousePt = fLastMouseDragPt = mousePt;
|
||||
fTracking = true;
|
||||
}
|
||||
|
||||
void pfGUIClickMapCtrl::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
if( fTracking )
|
||||
{
|
||||
IScreenToLocalPt( mousePt );
|
||||
fLastMousePt = fLastMouseUpPt = fLastMouseDragPt = mousePt;
|
||||
DoSomething();
|
||||
fTracking = false;
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIClickMapCtrl::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
if( fTracking )
|
||||
{
|
||||
IScreenToLocalPt( mousePt );
|
||||
fLastMousePt = fLastMouseDragPt = mousePt;
|
||||
if( HasFlag( kReportDragging ) )
|
||||
HandleExtendedEvent( kMouseDragged );
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIClickMapCtrl::HandleMouseHover( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
IScreenToLocalPt( mousePt );
|
||||
fLastMousePt = mousePt;
|
||||
|
||||
if( HasFlag( kReportHovering ) )
|
||||
HandleExtendedEvent( kMouseHovered );
|
||||
}
|
||||
|
||||
//// IGetDesiredCursor ///////////////////////////////////////////////////////
|
||||
|
||||
UInt32 pfGUIClickMapCtrl::IGetDesiredCursor( void ) const
|
||||
{
|
||||
if( fCustomCursor != -1 )
|
||||
return (UInt32)fCustomCursor;
|
||||
|
||||
return plInputInterface::kCursorPoised;
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIClickMapCtrl Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIClickMapCtrl_h
|
||||
#define _pfGUIClickMapCtrl_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
class plMessage;
|
||||
|
||||
class pfGUIClickMapCtrl : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
hsPoint3 fLastMousePt, fLastMouseUpPt, fLastMouseDragPt;
|
||||
hsBool fTracking;
|
||||
Int32 fCustomCursor;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual UInt32 IGetDesiredCursor( void ) const; // As specified in plInputInterface.h
|
||||
|
||||
public:
|
||||
|
||||
pfGUIClickMapCtrl();
|
||||
virtual ~pfGUIClickMapCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIClickMapCtrl );
|
||||
GETINTERFACE_ANY( pfGUIClickMapCtrl, pfGUIControlMod );
|
||||
|
||||
enum OurFlags
|
||||
{
|
||||
kReportDragging = kDerivedFlagsStart,
|
||||
kReportHovering
|
||||
};
|
||||
|
||||
// Extended event types
|
||||
enum ExtendedEvents
|
||||
{
|
||||
kMouseDragged,
|
||||
kMouseHovered
|
||||
};
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseHover( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
const hsPoint3 &GetLastMousePt( void ) const { return fLastMousePt; }
|
||||
const hsPoint3 &GetLastMouseUpPt( void ) const { return fLastMouseUpPt; }
|
||||
const hsPoint3 &GetLastMouseDragPt( void ) const { return fLastMouseDragPt; }
|
||||
|
||||
void SetCustomCursor( Int32 cursor = -1 ) { fCustomCursor = cursor; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIClickMapCtrl_h
|
@ -0,0 +1,186 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIControl Handler Definitions //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
|
||||
#include "../plMessage/plConsoleMsg.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Writeable Stuff /////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICtrlProcWriteableObject::Write( pfGUICtrlProcWriteableObject *obj, hsStream *s )
|
||||
{
|
||||
if( obj != nil )
|
||||
{
|
||||
s->WriteSwap32( obj->fType );
|
||||
obj->IWrite( s );
|
||||
}
|
||||
else
|
||||
s->WriteSwap32( kNull );
|
||||
}
|
||||
|
||||
pfGUICtrlProcWriteableObject *pfGUICtrlProcWriteableObject::Read( hsStream *s )
|
||||
{
|
||||
pfGUICtrlProcWriteableObject *obj;
|
||||
|
||||
UInt32 type = s->ReadSwap32();
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case kConsoleCmd:
|
||||
obj = TRACKED_NEW pfGUIConsoleCmdProc;
|
||||
break;
|
||||
|
||||
case kPythonScript:
|
||||
obj = TRACKED_NEW pfGUIPythonScriptProc;
|
||||
break;
|
||||
|
||||
case kCloseDlg:
|
||||
obj = TRACKED_NEW pfGUICloseDlgProc;
|
||||
break;
|
||||
|
||||
case kNull:
|
||||
return nil;
|
||||
|
||||
default:
|
||||
hsAssert( false, "Invalid proc type in Read()" );
|
||||
return nil;
|
||||
}
|
||||
|
||||
obj->IRead( s );
|
||||
return obj;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Predefined Exportables //////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// pfGUIConsoleCmdProc /////////////////////////////////////////////////////
|
||||
|
||||
pfGUIConsoleCmdProc::pfGUIConsoleCmdProc() : pfGUICtrlProcWriteableObject( kConsoleCmd )
|
||||
{
|
||||
fCommand = nil;
|
||||
}
|
||||
|
||||
pfGUIConsoleCmdProc::pfGUIConsoleCmdProc( const char *cmd )
|
||||
: pfGUICtrlProcWriteableObject( kConsoleCmd )
|
||||
{
|
||||
fCommand = nil;
|
||||
SetCommand( cmd );
|
||||
}
|
||||
|
||||
pfGUIConsoleCmdProc::~pfGUIConsoleCmdProc()
|
||||
{
|
||||
delete [] fCommand;
|
||||
}
|
||||
|
||||
void pfGUIConsoleCmdProc::IRead( hsStream *s )
|
||||
{
|
||||
int i = s->ReadSwap32();
|
||||
if( i > 0 )
|
||||
{
|
||||
fCommand = TRACKED_NEW char[ i + 1 ];
|
||||
memset( fCommand, 0, i + 1 );
|
||||
s->Read( i, fCommand );
|
||||
}
|
||||
else
|
||||
fCommand = nil;
|
||||
}
|
||||
|
||||
void pfGUIConsoleCmdProc::IWrite( hsStream *s )
|
||||
{
|
||||
if( fCommand != nil )
|
||||
{
|
||||
s->WriteSwap32( strlen( fCommand ) );
|
||||
s->Write( strlen( fCommand ), fCommand );
|
||||
}
|
||||
else
|
||||
s->WriteSwap32( 0 );
|
||||
}
|
||||
|
||||
void pfGUIConsoleCmdProc::DoSomething( pfGUIControlMod *ctrl )
|
||||
{
|
||||
if( fCommand != nil )
|
||||
{
|
||||
plConsoleMsg *cMsg = TRACKED_NEW plConsoleMsg( plConsoleMsg::kExecuteLine, fCommand );
|
||||
plgDispatch::MsgSend( cMsg );
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIConsoleCmdProc::SetCommand( const char *cmd )
|
||||
{
|
||||
delete [] fCommand;
|
||||
|
||||
if( cmd == nil )
|
||||
fCommand = nil;
|
||||
else
|
||||
{
|
||||
fCommand = TRACKED_NEW char[ strlen( cmd ) + 1 ];
|
||||
memset( fCommand, 0, strlen( cmd ) + 1 );
|
||||
strcpy( fCommand, cmd );
|
||||
}
|
||||
}
|
||||
|
||||
//// pfGUIPythonScriptProc ///////////////////////////////////////////////////
|
||||
|
||||
pfGUIPythonScriptProc::pfGUIPythonScriptProc() : pfGUICtrlProcWriteableObject( kPythonScript )
|
||||
{
|
||||
}
|
||||
|
||||
pfGUIPythonScriptProc::~pfGUIPythonScriptProc()
|
||||
{
|
||||
}
|
||||
|
||||
void pfGUIPythonScriptProc::IRead( hsStream *s )
|
||||
{
|
||||
}
|
||||
|
||||
void pfGUIPythonScriptProc::IWrite( hsStream *s )
|
||||
{
|
||||
}
|
||||
|
||||
void pfGUIPythonScriptProc::DoSomething( pfGUIControlMod *ctrl )
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Simple Runtime Ones /////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICloseDlgProc::DoSomething( pfGUIControlMod *ctrl )
|
||||
{
|
||||
ctrl->GetOwnerDlg()->Hide();
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIControlHandlers Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIControlHandlers_h
|
||||
#define _pfGUIControlHandlers_h
|
||||
|
||||
#include "hsStream.h"
|
||||
|
||||
//// pfGUICtrlProcObject Definition //////////////////////////////////////////
|
||||
// Any control which "does something" (buttons, edit boxes on Enter/Return,
|
||||
// etc) uses this in some form. Basically, each control will have an (optional?)
|
||||
// pointer to an object derived from this class type. The class has a single
|
||||
// standard, virtual function that gets called on the "do something" event.
|
||||
// Derive from this class, override the virtual and set the control's handler
|
||||
// to your object and you're all set. Kinda like windowProcs wrapped in a
|
||||
// C++ object.
|
||||
// Note: there are some predefined objects for simple, common events. See
|
||||
// below.
|
||||
// Note the second: DoSomething() takes a parameter--namely, a pointer to
|
||||
// the control that called it. Thus, you can make one object handle
|
||||
// several controls by just switch()ing on that parameter and save yourself
|
||||
// some object creation.
|
||||
//
|
||||
// UserCallback() is an additional function for use in communicating between
|
||||
// procs. Basically, if you want another proc to do something (another dialog),
|
||||
// and want you to get called once it's done, set the callback on the other
|
||||
// proc/whatever to you and override UserCallback().
|
||||
//
|
||||
// HandleExtendedEvent() is similar to DoSomething(), but is called for extended
|
||||
// event types, such as value changing (for an edit control while typing) or
|
||||
// list scrolled. The event parameter is control-type-specific.
|
||||
//
|
||||
// Dialogs will use a similar functionality, but with more functions available.
|
||||
|
||||
class pfGUIControlMod;
|
||||
class pfGUICtrlProcObject
|
||||
{
|
||||
protected:
|
||||
|
||||
UInt32 fRefCnt;
|
||||
|
||||
public:
|
||||
|
||||
pfGUICtrlProcObject() { fRefCnt = 0; }
|
||||
virtual ~pfGUICtrlProcObject() { ; }
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl ) = 0;
|
||||
|
||||
virtual void HandleExtendedEvent( pfGUIControlMod *ctrl, UInt32 event ) { ; }
|
||||
|
||||
virtual void UserCallback( UInt32 userValue ) { ; }
|
||||
|
||||
// ONLY THE GUI SYSTEM SHOULD CALL THESE
|
||||
void IncRef( void ) { fRefCnt++; }
|
||||
hsBool DecRef( void ) { fRefCnt--; return ( fRefCnt > 0 ) ? false : true; }
|
||||
};
|
||||
|
||||
//// pfGUICtrlProcWriteableObject ////////////////////////////////////////////
|
||||
// This one is a read/writeable version of the above. Basically, you can just
|
||||
// call Read/Write() and it'll do all the mini-functionality of the factory
|
||||
// stuff so you don't have to worry about the derived type at runtime. Do
|
||||
// NOT derive from this class for your own handlers; this is just for the
|
||||
// handfull that will get added on export.
|
||||
|
||||
class pfGUICtrlProcWriteableObject : public pfGUICtrlProcObject
|
||||
{
|
||||
protected:
|
||||
|
||||
UInt32 fType;
|
||||
|
||||
virtual void IRead( hsStream *s ) = 0;
|
||||
virtual void IWrite( hsStream *s ) = 0;
|
||||
|
||||
public:
|
||||
|
||||
enum Types
|
||||
{
|
||||
kNull,
|
||||
kConsoleCmd,
|
||||
kPythonScript,
|
||||
kCloseDlg
|
||||
};
|
||||
|
||||
pfGUICtrlProcWriteableObject() { fType = kNull; }
|
||||
pfGUICtrlProcWriteableObject( UInt32 type ) : fType( type ) { ; }
|
||||
virtual ~pfGUICtrlProcWriteableObject() { ; }
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl ) = 0;
|
||||
|
||||
static void Write( pfGUICtrlProcWriteableObject *obj, hsStream *s );
|
||||
|
||||
static pfGUICtrlProcWriteableObject *Read( hsStream *s );
|
||||
};
|
||||
|
||||
//// pfGUIConsoleCmdProc /////////////////////////////////////////////////////
|
||||
// Simply runs the console command specified. Exportable.
|
||||
|
||||
class pfGUIConsoleCmdProc : public pfGUICtrlProcWriteableObject
|
||||
{
|
||||
protected:
|
||||
|
||||
char *fCommand;
|
||||
|
||||
virtual void IRead( hsStream *s );
|
||||
virtual void IWrite( hsStream *s );
|
||||
|
||||
public:
|
||||
|
||||
pfGUIConsoleCmdProc();
|
||||
pfGUIConsoleCmdProc( const char *cmd );
|
||||
virtual ~pfGUIConsoleCmdProc();
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl );
|
||||
|
||||
void SetCommand( const char *cmd );
|
||||
};
|
||||
|
||||
//// pfGUIPythonScriptProc ///////////////////////////////////////////////////
|
||||
|
||||
class pfGUIPythonScriptProc : public pfGUICtrlProcWriteableObject
|
||||
{
|
||||
protected:
|
||||
|
||||
virtual void IRead( hsStream *s );
|
||||
virtual void IWrite( hsStream *s );
|
||||
|
||||
public:
|
||||
|
||||
pfGUIPythonScriptProc();
|
||||
virtual ~pfGUIPythonScriptProc();
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl );
|
||||
};
|
||||
|
||||
//// Simple Runtime Ones /////////////////////////////////////////////////////
|
||||
|
||||
class pfGUICloseDlgProc : public pfGUICtrlProcWriteableObject
|
||||
{
|
||||
protected:
|
||||
|
||||
virtual void IRead( hsStream *s ) {}
|
||||
virtual void IWrite( hsStream *s ) {}
|
||||
|
||||
public:
|
||||
|
||||
pfGUICloseDlgProc() : pfGUICtrlProcWriteableObject( kCloseDlg ) {}
|
||||
virtual ~pfGUICloseDlgProc() {}
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl );
|
||||
};
|
||||
|
||||
#endif // _pfGUIControlHandlers_h
|
@ -0,0 +1,996 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIControlMod Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
#include "pfGUIDialogHandlers.h"
|
||||
#include "pfGUIListElement.h" // Includes dropTargetProc
|
||||
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pnMessage/plEnableMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../pnSceneObject/plDrawInterface.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
#include "../pnSceneObject/plAudioInterface.h"
|
||||
|
||||
#include "../plGImage/plDynamicTextMap.h"
|
||||
#include "../plSurface/plLayer.h"
|
||||
#include "../plMessage/plRenderMsg.h"
|
||||
#include "../pnMessage/plSoundMsg.h"
|
||||
#include "plPipeline.h"
|
||||
|
||||
#include "../plDrawable/plAccessGeometry.h"
|
||||
#include "../plDrawable/plAccessSpan.h"
|
||||
#include "../plDrawable/plAccessVtxSpan.h"
|
||||
|
||||
#include "pfGUIPopUpMenu.h" // For skin, can we move that please? Thank you
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// pfGUIColorScheme Functions //////////////////////////////////////////////
|
||||
|
||||
void pfGUIColorScheme::IReset( void )
|
||||
{
|
||||
fForeColor.Set( 1, 1, 1, 1 );
|
||||
fBackColor.Set( 0, 0, 0, 1 );
|
||||
fSelForeColor.Set( 1, 1, 1, 1 );
|
||||
fSelBackColor.Set( 0, 0, 1, 1 );
|
||||
fTransparent = false;
|
||||
fFontFace = hsStrcpy( "Times New Roman" );
|
||||
fFontSize = 10;
|
||||
fFontFlags = 0;
|
||||
}
|
||||
|
||||
pfGUIColorScheme::pfGUIColorScheme()
|
||||
{
|
||||
IReset();
|
||||
}
|
||||
|
||||
pfGUIColorScheme::~pfGUIColorScheme()
|
||||
{
|
||||
delete [] fFontFace;
|
||||
}
|
||||
|
||||
pfGUIColorScheme::pfGUIColorScheme( hsColorRGBA &foreColor, hsColorRGBA &backColor )
|
||||
{
|
||||
IReset();
|
||||
fForeColor = foreColor;
|
||||
fBackColor = backColor;
|
||||
}
|
||||
|
||||
pfGUIColorScheme::pfGUIColorScheme( const char *face, UInt8 size, UInt8 fontFlags )
|
||||
{
|
||||
IReset();
|
||||
fFontFace = hsStrcpy( face );
|
||||
fFontSize = size;
|
||||
fFontFlags = fontFlags;
|
||||
}
|
||||
|
||||
void pfGUIColorScheme::SetFontFace( const char *face )
|
||||
{
|
||||
delete [] fFontFace;
|
||||
fFontFace = hsStrcpy( face );
|
||||
}
|
||||
|
||||
void pfGUIColorScheme::Read( hsStream *s )
|
||||
{
|
||||
fForeColor.Read( s );
|
||||
fBackColor.Read( s );
|
||||
fSelForeColor.Read( s );
|
||||
fSelBackColor.Read( s );
|
||||
s->ReadSwap( &fTransparent );
|
||||
|
||||
delete [] fFontFace;
|
||||
fFontFace = s->ReadSafeString();
|
||||
s->ReadSwap( &fFontSize );
|
||||
s->ReadSwap( &fFontFlags );
|
||||
}
|
||||
|
||||
void pfGUIColorScheme::Write( hsStream *s )
|
||||
{
|
||||
fForeColor.Write( s );
|
||||
fBackColor.Write( s );
|
||||
fSelForeColor.Write( s );
|
||||
fSelBackColor.Write( s );
|
||||
s->WriteSwap( fTransparent );
|
||||
|
||||
s->WriteSafeString( fFontFace );
|
||||
s->WriteSwap( fFontSize );
|
||||
s->WriteSwap( fFontFlags );
|
||||
}
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIControlMod::pfGUIControlMod()
|
||||
{
|
||||
fEnabled = true;
|
||||
fDialog = nil;
|
||||
fBoundsValid = false;
|
||||
fCenterValid = false;
|
||||
fFocused = false;
|
||||
fInteresting = false;
|
||||
fVisible = true;
|
||||
fHandler = nil;
|
||||
fTagID = 0;
|
||||
fDropTargetHdlr = nil;
|
||||
fDynTextMap = nil;
|
||||
fProxy = nil;
|
||||
|
||||
fColorScheme = nil;
|
||||
fSkin = nil;
|
||||
|
||||
fNotifyOnInteresting = false;
|
||||
}
|
||||
|
||||
pfGUIControlMod::~pfGUIControlMod()
|
||||
{
|
||||
ISetHandler( nil );
|
||||
SetDropTargetHdlr( nil );
|
||||
SetColorScheme( nil );
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIControlMod::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
// UpdateBounds();
|
||||
return false;
|
||||
}
|
||||
|
||||
//// GetBounds ///////////////////////////////////////////////////////////////
|
||||
|
||||
const hsBounds3 &pfGUIControlMod::GetBounds( void )
|
||||
{
|
||||
UpdateBounds();
|
||||
return fBounds;
|
||||
}
|
||||
|
||||
//// SetTransform ////////////////////////////////////////////////////////////
|
||||
// Override from plModifier so we can update our bounds
|
||||
|
||||
void pfGUIControlMod::SetTransform( const hsMatrix44 &l2w, const hsMatrix44 &w2l )
|
||||
{
|
||||
fBoundsValid = false;
|
||||
}
|
||||
|
||||
|
||||
//// GetVectorAngle //////////////////////////////////////////////////////////
|
||||
|
||||
static hsScalar GetVectorAngle( const hsPoint3 &basePt, const hsPoint3 &pointA, const hsPoint3 &pointB )
|
||||
{
|
||||
hsVector3 vectorA( &pointA, &basePt ), vectorB( &pointB, &basePt );
|
||||
|
||||
hsScalar dot = vectorA * vectorB;
|
||||
hsVector3 cross = vectorA % vectorB;
|
||||
hsScalar crossLen = cross.fZ;
|
||||
|
||||
return atan2( crossLen, dot );
|
||||
}
|
||||
|
||||
//// CreateConvexHull ////////////////////////////////////////////////////////
|
||||
// Algorithm is Graham's scan algorithm:
|
||||
// R.L. Graham, "An efficient algorithm for determining the convex hull of a finite
|
||||
// planar set", Info. Proc. Lett. 1, 132-133 (1972).
|
||||
// Note: THIS WILL DESTROY YOUR INPOINTS ARRAY.
|
||||
|
||||
static hsBool CreateConvexHull( hsPoint3 *inPoints, int &numPoints )
|
||||
{
|
||||
int i, j, pointA, pointB, pointC;
|
||||
hsScalar *angles;
|
||||
|
||||
if( numPoints < 3 )
|
||||
return false;
|
||||
|
||||
// Step 1: Find a point interior to our hull. Easiest is average of all our input points...
|
||||
// (plus: set the Zs of all the points to the Z of the first point, since we want to be
|
||||
// working in 2D)
|
||||
hsPoint3 avgPoint = inPoints[ 0 ];
|
||||
for( i = 1; i < numPoints; i++ )
|
||||
{
|
||||
avgPoint += inPoints[ i ];
|
||||
inPoints[ i ].fZ = inPoints[ 0 ].fZ;
|
||||
}
|
||||
avgPoint.fX /= numPoints;
|
||||
avgPoint.fY /= numPoints;
|
||||
avgPoint.fZ /= numPoints;
|
||||
|
||||
// Step 2: Sort all the in points by the angle to the X axis (vector <1,0>).
|
||||
// Step A: Calculate all the angles
|
||||
|
||||
angles = TRACKED_NEW hsScalar[ numPoints ];
|
||||
hsPoint3 xAxisPoint( avgPoint.fX + 1, avgPoint.fY, avgPoint.fZ );
|
||||
for( i = 0; i < numPoints; i++ )
|
||||
angles[ i ] = GetVectorAngle( avgPoint, inPoints[ i ], xAxisPoint );
|
||||
|
||||
// Step B: Bubble sort by the angles
|
||||
for( i = 0; i < numPoints - 1; i++ )
|
||||
{
|
||||
for( j = i + 1; j < numPoints; j++ )
|
||||
{
|
||||
if( angles[ j ] < angles[ i ] )
|
||||
{
|
||||
hsScalar tempAngle = angles[ j ];
|
||||
angles[ j ] = angles[ i ];
|
||||
angles[ i ] = tempAngle;
|
||||
|
||||
hsPoint3 tempPt = inPoints[ j ];
|
||||
inPoints[ j ] = inPoints[ i ];
|
||||
inPoints[ i ] = tempPt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3: Eliminate non-convex points to form the hull
|
||||
for( pointA = 0, pointB = 1, pointC = 2; pointA < numPoints && numPoints > 3; )
|
||||
{
|
||||
// Two cases of wrap-around...
|
||||
if( pointC >= numPoints )
|
||||
pointC -= numPoints;
|
||||
else if( pointC < 0 )
|
||||
pointC += numPoints;
|
||||
if( pointB >= numPoints )
|
||||
pointB -= numPoints;
|
||||
else if( pointB < 0 )
|
||||
pointB += numPoints;
|
||||
|
||||
// For points A, B, and C, find the interior angle between them
|
||||
hsScalar angle = GetVectorAngle( inPoints[ pointB ], inPoints[ pointA ], inPoints[ pointC ] );
|
||||
|
||||
// If the angle is < 180, then it's a good angle and we can advance all our points by 1...
|
||||
// Note: we have a tolerance so that we don't get points that form edges that are pretty darned close...
|
||||
const hsScalar tolerance = hsScalarPI / 90.f;
|
||||
if( angle > tolerance && angle < hsScalarPI - tolerance )
|
||||
{
|
||||
pointA++;
|
||||
pointB++;
|
||||
pointC++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Angle is > 180 degrees, this is bad. This means our middle point doesn't belong,
|
||||
// so we need to remove it
|
||||
for( i = pointB; i < numPoints - 1; i++ )
|
||||
inPoints[ i ] = inPoints[ i + 1 ];
|
||||
numPoints--;
|
||||
if( pointC > pointB )
|
||||
pointC--;
|
||||
// There's one case where point B and C could've wrapped around and so deleting that point
|
||||
// actually moves point A down by 1...
|
||||
if( pointA > pointB )
|
||||
pointA--;
|
||||
|
||||
// Back up the points by 1 if possible (so we can keep checking to make sure we're still convex).
|
||||
// If not, just increment C up
|
||||
if( pointA > 0 )
|
||||
{
|
||||
pointA--;
|
||||
pointB--;
|
||||
}
|
||||
else
|
||||
pointC++;
|
||||
}
|
||||
}
|
||||
|
||||
delete [] angles;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//// GetObjectPoints /////////////////////////////////////////////////////////
|
||||
// Retrieves ALL of the points of a sceneObject's meshes. And I mean ALL of
|
||||
// 'em...
|
||||
|
||||
static void GetObjectPoints( plSceneObject *so, hsTArray<hsPoint3> &outPoints )
|
||||
{
|
||||
const plDrawInterface* di = so->GetDrawInterface();
|
||||
if( !di )
|
||||
return;
|
||||
|
||||
// The following uses mf's spiffy plAccessGeometry/Spans stuff, which, in
|
||||
// one word, kicksAss.
|
||||
hsTArray<plAccessSpan> spans;
|
||||
plAccessGeometry::Instance()->OpenRO( di, spans );
|
||||
|
||||
int i;
|
||||
outPoints.Reset();
|
||||
for( i = 0; i < spans.GetCount(); i++ )
|
||||
{
|
||||
plAccessVtxSpan& vtxSrc = spans[ i ].AccessVtx();
|
||||
plAccPositionIterator iterSrc( &vtxSrc );
|
||||
|
||||
for( iterSrc.Begin(); iterSrc.More(); iterSrc.Advance() )
|
||||
outPoints.Append( *iterSrc.Position() );
|
||||
}
|
||||
|
||||
if (plAccessGeometry::Instance())
|
||||
plAccessGeometry::Instance()->Close( spans );
|
||||
}
|
||||
|
||||
//// PointsOnSameSide ////////////////////////////////////////////////////////
|
||||
// Given two ends of a line segment and two points, tells you whether the
|
||||
// two points are on the same side of the line. Used in PointInTriangle().
|
||||
|
||||
static hsBool PointsOnSameSide( const hsPoint3 &line1, const hsPoint3 &line2, const hsPoint3 &pointA, const hsPoint3 &pointB )
|
||||
{
|
||||
hsVector3 baseVec( &line2, &line1 );
|
||||
hsVector3 cp1 = hsVector3( &pointA, &line1 ) % baseVec;
|
||||
hsVector3 cp2 = hsVector3( &pointB, &line1 ) % baseVec;
|
||||
return ( cp1.fZ * cp2.fZ > 0 ) ? true : false;
|
||||
}
|
||||
|
||||
//// PointInTriangle /////////////////////////////////////////////////////////
|
||||
// Given three points that define a triangle and a fourth point, tells you
|
||||
// whether the fourth point is inside the triangle.
|
||||
|
||||
static hsBool PointInTriangle( hsPoint3 tri1, hsPoint3 tri2, hsPoint3 tri3, const hsPoint3 &testPoint )
|
||||
{
|
||||
tri1.fZ = tri2.fZ = tri3.fZ = testPoint.fZ;
|
||||
if( PointsOnSameSide( tri1, tri2, testPoint, tri3 ) &&
|
||||
PointsOnSameSide( tri2, tri3, testPoint, tri1 ) &&
|
||||
PointsOnSameSide( tri3, tri1, testPoint, tri2 ) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//// PointInBounds ///////////////////////////////////////////////////////////
|
||||
// Tells you whether said point is in the control's bounds.
|
||||
|
||||
hsBool pfGUIControlMod::PointInBounds( const hsPoint3 &point )
|
||||
{
|
||||
UpdateBounds();
|
||||
|
||||
if( fBounds.GetType() != kBoundsEmpty && fBounds.GetType() != kBoundsUninitialized && fBounds.IsInside( &point ) )
|
||||
{
|
||||
if( fBoundsPoints.GetCount() > 0 )
|
||||
{
|
||||
// We have a more-accurate bounds set, so use it
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 1; i < fBoundsPoints.GetCount() - 1; i++ )
|
||||
{
|
||||
// Test the triangle (0,i,i+1)
|
||||
if( PointInTriangle( fBoundsPoints[ 0 ], fBoundsPoints[ i ], fBoundsPoints[ i + 1 ], point ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//// CalcInitialBounds ///////////////////////////////////////////////////////
|
||||
// Called by the dialog once as soon as the dialog adds the control, so that
|
||||
// initial bounds for the control can be calced. This is used for initing
|
||||
// any dynmaic text maps, since we want to use the initial bounds to do so
|
||||
// instead of any currently animated state of the bounds.
|
||||
|
||||
void pfGUIControlMod::CalcInitialBounds( void )
|
||||
{
|
||||
UpdateBounds( nil, true );
|
||||
fInitialBounds = fBounds;
|
||||
}
|
||||
|
||||
//// UpdateBounds ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
|
||||
{
|
||||
hsMatrix44 xformMatrix, projMatrix;
|
||||
hsPoint3 corners[ 8 ];
|
||||
int i;
|
||||
|
||||
|
||||
if( ( !fBoundsValid || force ) && fDialog && GetTarget() )
|
||||
{
|
||||
plDrawInterface *DI = IGetTargetDrawInterface( 0 );
|
||||
if( DI == nil )
|
||||
return;
|
||||
|
||||
if( HasFlag( kBetterHitTesting ) )
|
||||
{
|
||||
hsTArray<hsPoint3> scrnPoints;
|
||||
|
||||
// Create a list of points to make a 2D convex hull from
|
||||
GetObjectPoints( GetTarget(), scrnPoints );
|
||||
hsMatrix44 l2w = GetTarget()->GetLocalToWorld();
|
||||
for( i = 0; i < scrnPoints.GetCount(); i++ )
|
||||
{
|
||||
scrnPoints[ i ] = l2w * scrnPoints[ i ];
|
||||
scrnPoints[ i ] = fDialog->WorldToScreenPoint( scrnPoints[ i ] );
|
||||
}
|
||||
|
||||
// Now create a convex hull from them, assuming the Zs are all the same
|
||||
int numPoints = scrnPoints.GetCount();
|
||||
if( !CreateConvexHull( scrnPoints.AcquireArray(), numPoints ) )
|
||||
return;
|
||||
|
||||
// Copy & store. Also recalc our bounding box just for fun
|
||||
fBounds.MakeEmpty();
|
||||
fBoundsPoints.SetCount( numPoints );
|
||||
for( i = 0; i < numPoints; i++ )
|
||||
{
|
||||
fBoundsPoints[ i ] = scrnPoints[ i ];
|
||||
fBounds.Union( &fBoundsPoints[ i ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fBounds.MakeEmpty();
|
||||
|
||||
hsBounds3Ext worldBounds = DI->GetLocalBounds();
|
||||
hsMatrix44 l2w = GetTarget()->GetLocalToWorld();
|
||||
worldBounds.Transform( &l2w );
|
||||
|
||||
worldBounds.GetCorners( corners );
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
hsPoint3 scrnPt = fDialog->WorldToScreenPoint( corners[ i ] );
|
||||
fBounds.Union( &scrnPt );
|
||||
}
|
||||
}
|
||||
|
||||
// Calc center Z
|
||||
// if( !fCenterValid )
|
||||
{
|
||||
#if 0
|
||||
corners[ 1 ] = GetTarget()->GetLocalToWorld().GetTranslate();
|
||||
float w = corners[ 1 ].fX * fXformMatrix.fMap[3][0]
|
||||
+ corners[ 1 ].fY * fXformMatrix.fMap[3][1]
|
||||
+ corners[ 1 ].fZ * fXformMatrix.fMap[3][2]
|
||||
+ 1.f * fXformMatrix.fMap[3][3];
|
||||
corners[ 1 ] = fXformMatrix * corners[ 1 ];
|
||||
|
||||
corners[ 1 ].fX = ( ( corners[ 1 ].fX / corners[ 1 ].fZ ) + 1.f ) / 2.f;
|
||||
corners[ 1 ].fY = ( ( corners[ 1 ].fY / corners[ 1 ].fZ ) + 1.f ) / 2.f;
|
||||
fScreenCenter = corners[ 1 ];
|
||||
|
||||
// fScreenCenter.fZ = w;
|
||||
|
||||
|
||||
corners[ 1 ] = GetTarget()->GetLocalToWorld().GetTranslate();
|
||||
fDialog->WorldToScreenPoint( corners[ 1 ].fX, corners[ 1 ].fY, corners[ 1 ].fZ, fScreenCenter );
|
||||
fCenterValid = true;
|
||||
#else
|
||||
corners[ 1 ] = GetTarget()->GetLocalToWorld().GetTranslate();
|
||||
fScreenCenter = fDialog->WorldToScreenPoint( corners[ 1 ] );
|
||||
corners[ 1 ] = fScreenCenter;
|
||||
fCenterValid = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
fScreenMinZ = fBounds.GetMins().fZ;
|
||||
|
||||
// Manually change the bounds so we know the z ranges from at least -1 to 1, suitable for us testing against for clicks
|
||||
corners[ 0 ] = fBounds.GetCenter();
|
||||
corners[ 0 ].fZ = -1.f;
|
||||
fBounds.Union( &corners[ 0 ] );
|
||||
corners[ 0 ].fZ = 1.f;
|
||||
fBounds.Union( &corners[ 0 ] );
|
||||
|
||||
fBoundsValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
//// SetObjectCenter /////////////////////////////////////////////////////////
|
||||
// Given the x/y coordinates in 0..1 space, recalcs the sceneObject position
|
||||
// and moves the object to match, retaining the stored fCenterZ coordinate
|
||||
|
||||
void pfGUIControlMod::SetObjectCenter( hsScalar x, hsScalar y )
|
||||
{
|
||||
hsMatrix44 xformMatrix, l2p, p2l;
|
||||
hsPoint3 center, corners[ 8 ];
|
||||
|
||||
|
||||
if( x > 1.f )
|
||||
x = 1.f;
|
||||
else if( x < 0.f )
|
||||
x = 0.f;
|
||||
if( y > 1.f )
|
||||
y = 1.f;
|
||||
else if( y < 0.f )
|
||||
y = 0.f;
|
||||
|
||||
if( fDialog && GetTarget() )
|
||||
{
|
||||
plCoordinateInterface *CI = IGetTargetCoordinateInterface( 0 );
|
||||
if( CI == nil )
|
||||
return;
|
||||
|
||||
// if( !fInvXformValid )
|
||||
// UpdateBounds();
|
||||
|
||||
l2p = GetTarget()->GetLocalToWorld();
|
||||
hsPoint3 oldPt = l2p.GetTranslate();
|
||||
|
||||
hsPoint3 oldScrnPt = fDialog->WorldToScreenPoint( oldPt );
|
||||
hsPoint3 oldPtRedux;
|
||||
fDialog->ScreenToWorldPoint( oldScrnPt.fX, oldScrnPt.fY, oldScrnPt.fZ, oldPtRedux );
|
||||
|
||||
fDialog->ScreenToWorldPoint( x, y, fScreenCenter.fZ, center );
|
||||
|
||||
l2p.SetTranslate( ¢er );
|
||||
l2p.GetInverse( &p2l );
|
||||
|
||||
GetTarget()->SetTransform( l2p, p2l );
|
||||
|
||||
fScreenCenter.fX = x;
|
||||
fScreenCenter.fY = y;
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIControlMod::SetTarget( plSceneObject *object )
|
||||
{
|
||||
plSingleModifier::SetTarget( object );
|
||||
|
||||
UpdateBounds();
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
#include "plProfile.h"
|
||||
plProfile_CreateTimer("Gui", "RenderSetup", GUITime);
|
||||
|
||||
hsBool pfGUIControlMod::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plRenderMsg* rend = plRenderMsg::ConvertNoRef( msg );
|
||||
|
||||
if( rend )
|
||||
{
|
||||
plProfile_BeginLap(GUITime, this->GetKey()->GetUoid().GetObjectName());
|
||||
// Only need it once
|
||||
if( ISetUpDynTextMap( rend->Pipeline() ) )
|
||||
plgDispatch::Dispatch()->UnRegisterForExactType( plRenderMsg::Index(), GetKey() );
|
||||
plProfile_EndLap(GUITime, this->GetKey()->GetUoid().GetObjectName());
|
||||
return true;
|
||||
}
|
||||
|
||||
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg );
|
||||
if( refMsg != nil )
|
||||
{
|
||||
if( refMsg->fType == kRefDynTextMap )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
fDynTextMap = plDynamicTextMap::ConvertNoRef( refMsg->GetRef() );
|
||||
// Register for a render msg so we can leech the material when we finally
|
||||
// have a pipeline to work with
|
||||
plgDispatch::Dispatch()->RegisterForExactType( plRenderMsg::Index(), GetKey() );
|
||||
}
|
||||
else
|
||||
fDynTextMap = nil;
|
||||
return true;
|
||||
}
|
||||
else if( refMsg->fType == kRefDynTextLayer )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fDynTextLayer = plLayerInterface::ConvertNoRef( refMsg->GetRef() );
|
||||
else
|
||||
fDynTextLayer = nil;
|
||||
return true;
|
||||
}
|
||||
else if( refMsg->fType == kRefProxy )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fProxy = plSceneObject::ConvertNoRef( refMsg->GetRef() );
|
||||
else
|
||||
fProxy = nil;
|
||||
return true;
|
||||
}
|
||||
else if( refMsg->fType == kRefSkin )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fSkin = pfGUISkin::ConvertNoRef( refMsg->GetRef() );
|
||||
else
|
||||
fSkin = nil;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return plSingleModifier::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// ISetUpDynTextMap ////////////////////////////////////////////////////////
|
||||
// Given a pointer to a dynamic text map, regurgitates it so it matches our
|
||||
// screen res and fun stuff like that. Also sets the layer transform to give
|
||||
// us a 1:1 textel-pixel ratio, which we like.
|
||||
|
||||
hsBool pfGUIControlMod::ISetUpDynTextMap( plPipeline *pipe )
|
||||
{
|
||||
if( fDynTextMap == nil )
|
||||
{
|
||||
hsAssert( false, "Trying to set up a nil dynamicTextMap in a GUI control" );
|
||||
return true;
|
||||
}
|
||||
if( fDynTextLayer == nil || fInitialBounds.GetType() == kBoundsUninitialized )//|| fDialog == nil )
|
||||
return false;
|
||||
|
||||
UInt32 scrnWidth, scrnHeight;
|
||||
if( !HasFlag( kScaleTextWithResolution ) )
|
||||
{
|
||||
// Scale so that there is a 1:1 pixel:textel ratio
|
||||
scrnWidth = pipe->Width();
|
||||
scrnHeight = pipe->Height();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scale with the resolution so that we take up the same % of screen space no matter what resolution
|
||||
// Assume a base "resolution" of 1024xX, where X is such that the ratio "1024/X = scrnWidth/scrnHt" holds
|
||||
const int kBaseScaleRes = 1024;
|
||||
const int kBaseScaleHeightRes = 768;
|
||||
scrnWidth = kBaseScaleRes;
|
||||
scrnHeight = kBaseScaleHeightRes;
|
||||
// we are going to just force things to be in 4 by 3 ratio...
|
||||
// ...cause it seems to work better.
|
||||
/////// scrnHeight = ( pipe->Height() * kBaseScaleRes ) / pipe->Width();
|
||||
}
|
||||
|
||||
const hsBounds3 &bounds = fInitialBounds;//GetBounds();
|
||||
UInt16 width = (UInt16)(( bounds.GetMaxs().fX - bounds.GetMins().fX ) * scrnWidth);
|
||||
UInt16 height = (UInt16)(( bounds.GetMaxs().fY - bounds.GetMins().fY ) * scrnHeight);
|
||||
|
||||
// Allow derived controls to allocate some extra scratch space if desired
|
||||
// (Do it this way so we can pass in our current calculated dimensions for them to play with)
|
||||
UInt16 extraW = width, extraH = height;
|
||||
IGrowDTMDimsToDesiredSize( extraW, extraH );
|
||||
extraW -= width;
|
||||
extraH -= height;
|
||||
|
||||
fDynTextMap->Reset();
|
||||
fDynTextMap->Create( width, height, HasFlag( kXparentBgnd ), extraW, extraH );
|
||||
|
||||
fDynTextMap->SetFont( GetColorScheme()->fFontFace, GetColorScheme()->fFontSize, GetColorScheme()->fFontFlags,
|
||||
HasFlag( kXparentBgnd ) ? false : true );
|
||||
fDynTextMap->SetTextColor( GetColorScheme()->fForeColor,
|
||||
( HasFlag( kXparentBgnd ) && GetColorScheme()->fBackColor.a == 0.f ) ? true : false );
|
||||
|
||||
// Now we gotta set the texture transform on the layer so our texture comes
|
||||
// out with 1:1 mapping from textel to pixel
|
||||
plLayer *layer = (plLayer *)fDynTextLayer;
|
||||
layer->SetTransform( fDynTextMap->GetLayerTransform() );
|
||||
|
||||
// Let the derived classes do their things
|
||||
IPostSetUpDynTextMap();
|
||||
|
||||
// Do our first update
|
||||
IUpdate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//// Get/SetColorScheme //////////////////////////////////////////////////////
|
||||
|
||||
pfGUIColorScheme *pfGUIControlMod::GetColorScheme( void ) const
|
||||
{
|
||||
if( fColorScheme == nil )
|
||||
return fDialog->GetColorScheme();
|
||||
|
||||
return fColorScheme;
|
||||
}
|
||||
|
||||
void pfGUIControlMod::SetColorScheme( pfGUIColorScheme *newScheme )
|
||||
{
|
||||
if( fColorScheme != nil )
|
||||
{
|
||||
hsRefCnt_SafeUnRef( fColorScheme );
|
||||
fColorScheme = nil;
|
||||
}
|
||||
|
||||
fColorScheme = newScheme;
|
||||
if( fColorScheme != nil )
|
||||
hsRefCnt_SafeRef( fColorScheme );
|
||||
}
|
||||
|
||||
//// SetDynTextMap ///////////////////////////////////////////////////////////
|
||||
// EXPORT ONLY
|
||||
|
||||
void pfGUIControlMod::SetDynTextMap( plLayerInterface *layer, plDynamicTextMap *dynText )
|
||||
{
|
||||
hsgResMgr::ResMgr()->AddViaNotify( layer->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, pfGUIControlMod::kRefDynTextLayer ), plRefFlags::kActiveRef );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( dynText->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, pfGUIControlMod::kRefDynTextMap ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
//// SetEnabled //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::SetEnabled( hsBool e )
|
||||
{
|
||||
if( e == fEnabled )
|
||||
return;
|
||||
|
||||
fEnabled = e;
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
//// SetFocused //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::SetFocused( hsBool e )
|
||||
{
|
||||
if( e == fFocused )
|
||||
return;
|
||||
|
||||
fFocused = e;
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
//// SetInteresting //////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::SetInteresting( hsBool i )
|
||||
{
|
||||
if( i == fInteresting )
|
||||
return;
|
||||
|
||||
fInteresting = i;
|
||||
IUpdate();
|
||||
|
||||
if ( fNotifyOnInteresting && fDialog && fDialog->GetHandler() )
|
||||
fDialog->GetHandler()->OnInterestingEvent(this);
|
||||
|
||||
}
|
||||
|
||||
//// SetVisible //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::SetVisible( hsBool vis )
|
||||
{
|
||||
if( vis == fVisible )
|
||||
return;
|
||||
|
||||
fVisible = vis;
|
||||
if (fTarget)
|
||||
{
|
||||
plEnableMsg *msg = TRACKED_NEW plEnableMsg();
|
||||
msg->SetCmd( fVisible ? plEnableMsg::kEnable : plEnableMsg::kDisable );
|
||||
msg->SetCmd( plEnableMsg::kDrawable );
|
||||
msg->AddReceiver( fTarget->GetKey() );
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
|
||||
if( !fVisible && fFocused )
|
||||
fDialog->SetFocus( nil );
|
||||
}
|
||||
|
||||
void pfGUIControlMod::Refresh( void )
|
||||
{
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
plSingleModifier::Read(s, mgr);
|
||||
s->ReadSwap( &fTagID );
|
||||
fVisible = s->ReadBool();
|
||||
|
||||
// Read the handler in
|
||||
ISetHandler( pfGUICtrlProcWriteableObject::Read( s ) );
|
||||
|
||||
// Read in the dynTextMap if there is one
|
||||
if( s->ReadBool() )
|
||||
{
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefDynTextLayer ), plRefFlags::kActiveRef );
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefDynTextMap ), plRefFlags::kActiveRef );
|
||||
}
|
||||
else
|
||||
{
|
||||
fDynTextLayer = nil;
|
||||
fDynTextMap = nil;
|
||||
}
|
||||
|
||||
if( s->ReadBool() )
|
||||
{
|
||||
SetColorScheme( nil );
|
||||
fColorScheme = TRACKED_NEW pfGUIColorScheme();
|
||||
fColorScheme->Read( s );
|
||||
}
|
||||
|
||||
// Read in our sound indices
|
||||
UInt8 i, count = s->ReadByte();
|
||||
if( count == 0 )
|
||||
fSoundIndices.Reset();
|
||||
else
|
||||
{
|
||||
fSoundIndices.SetCountAndZero( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
fSoundIndices[ i ] = (int)s->ReadSwap32();
|
||||
}
|
||||
|
||||
if( HasFlag( kHasProxy ) )
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefProxy ), plRefFlags::kActiveRef );
|
||||
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefSkin ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
void pfGUIControlMod::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
if( HasFlag( kHasProxy ) && !fProxy )
|
||||
ClearFlag( kHasProxy );
|
||||
|
||||
plSingleModifier::Write( s, mgr );
|
||||
s->WriteSwap( fTagID );
|
||||
s->WriteBool( fVisible );
|
||||
|
||||
// Write the handler out (if it's not a writeable, damn you)
|
||||
pfGUICtrlProcWriteableObject::Write( (pfGUICtrlProcWriteableObject *)fHandler, s );
|
||||
|
||||
// Write out the dynTextMap
|
||||
if( fDynTextMap != nil )
|
||||
{
|
||||
s->WriteBool( true );
|
||||
mgr->WriteKey( s, fDynTextLayer->GetKey() );
|
||||
mgr->WriteKey( s, fDynTextMap->GetKey() );
|
||||
}
|
||||
else
|
||||
s->WriteBool( false );
|
||||
|
||||
if( fColorScheme != nil )
|
||||
{
|
||||
s->WriteBool( true );
|
||||
fColorScheme->Write( s );
|
||||
}
|
||||
else
|
||||
s->WriteBool( false );
|
||||
|
||||
// Write out our sound indices
|
||||
s->WriteByte( fSoundIndices.GetCount() );
|
||||
UInt8 i;
|
||||
for( i = 0; i < fSoundIndices.GetCount(); i++ )
|
||||
s->WriteSwap32( fSoundIndices[ i ] );
|
||||
|
||||
if( HasFlag( kHasProxy ) )
|
||||
mgr->WriteKey( s, fProxy->GetKey() );
|
||||
|
||||
mgr->WriteKey( s, fSkin );
|
||||
}
|
||||
|
||||
//// HandleKeyPress/Event ////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIControlMod::HandleKeyPress( char key, UInt8 modifiers )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
hsBool pfGUIControlMod::HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//// IScreenToLocalPt ////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::IScreenToLocalPt( hsPoint3 &pt )
|
||||
{
|
||||
const hsBounds3 &bnds = GetBounds();
|
||||
|
||||
pt.fX -= bnds.GetMins().fX;
|
||||
pt.fY -= bnds.GetMins().fY;
|
||||
pt.fX /= bnds.GetMaxs().fX - bnds.GetMins().fX;
|
||||
pt.fY /= bnds.GetMaxs().fY - bnds.GetMins().fY;
|
||||
}
|
||||
|
||||
//// ISetHandler /////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::ISetHandler( pfGUICtrlProcObject *h, hsBool clearInheritFlag )
|
||||
{
|
||||
if( fHandler && fHandler->DecRef() )
|
||||
delete fHandler;
|
||||
|
||||
fHandler = h;
|
||||
if( fHandler )
|
||||
fHandler->IncRef();
|
||||
|
||||
if( clearInheritFlag )
|
||||
ClearFlag( kInheritProcFromDlg );
|
||||
}
|
||||
|
||||
//// DoSomething /////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::DoSomething( void )
|
||||
{
|
||||
if( fEnabled && fHandler != nil )
|
||||
fHandler->DoSomething( this );
|
||||
}
|
||||
|
||||
//// HandleExtendedEvent /////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::HandleExtendedEvent( UInt32 event )
|
||||
{
|
||||
if( fEnabled && fHandler != nil )
|
||||
fHandler->HandleExtendedEvent( this, event );
|
||||
}
|
||||
|
||||
//// SetDropTargetHdlr ///////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIControlMod::SetDropTargetHdlr( pfGUIDropTargetProc *h )
|
||||
{
|
||||
if( fDropTargetHdlr && fDropTargetHdlr->DecRef() )
|
||||
delete fDropTargetHdlr;
|
||||
|
||||
fDropTargetHdlr = h;
|
||||
if( fDropTargetHdlr )
|
||||
fDropTargetHdlr->IncRef();
|
||||
}
|
||||
|
||||
//// SetSoundIndex ///////////////////////////////////////////////////////////
|
||||
// Associates the given GUI event with an index of a sound on the target SO's
|
||||
// audioInterface. The guiCtrlEvent is specific to each type of control.
|
||||
|
||||
void pfGUIControlMod::SetSoundIndex( UInt8 guiCtrlEvent, int soundIndex )
|
||||
{
|
||||
if( fSoundIndices.GetCount() < guiCtrlEvent + 1 )
|
||||
fSoundIndices.ExpandAndZero( guiCtrlEvent + 1 );
|
||||
|
||||
fSoundIndices[ guiCtrlEvent ] = soundIndex + 1; // We +1, since 0 means no sound
|
||||
}
|
||||
|
||||
//// IPlaySound //////////////////////////////////////////////////////////////
|
||||
// Sends a sound play message with the soundIndex associated with the given
|
||||
// event.
|
||||
|
||||
void pfGUIControlMod::IPlaySound( UInt8 guiCtrlEvent, hsBool loop /* = false */ )
|
||||
{
|
||||
if( guiCtrlEvent >= fSoundIndices.GetCount() || fSoundIndices[ guiCtrlEvent ] == 0 )
|
||||
return;
|
||||
|
||||
if( GetTarget() == nil || GetTarget()->GetAudioInterface() == nil )
|
||||
return;
|
||||
|
||||
plSoundMsg *msg = TRACKED_NEW plSoundMsg;
|
||||
msg->fIndex = fSoundIndices[ guiCtrlEvent ] - 1;
|
||||
msg->SetCmd( plSoundMsg::kGoToTime );
|
||||
msg->fTime = 0.f;
|
||||
msg->SetCmd( plSoundMsg::kPlay );
|
||||
if (loop)
|
||||
{
|
||||
msg->fLoop = true;
|
||||
msg->SetCmd( plSoundMsg::kSetLooping );
|
||||
}
|
||||
msg->Send( GetTarget()->GetAudioInterface()->GetKey() );
|
||||
}
|
||||
|
||||
void pfGUIControlMod::IStopSound(UInt8 guiCtrlEvent)
|
||||
{
|
||||
if (guiCtrlEvent >= fSoundIndices.GetCount() || fSoundIndices[guiCtrlEvent] == 0)
|
||||
return;
|
||||
|
||||
if (GetTarget() == nil || GetTarget()->GetAudioInterface() == nil )
|
||||
return;
|
||||
|
||||
plSoundMsg *msg = TRACKED_NEW plSoundMsg;
|
||||
msg->fIndex = fSoundIndices[guiCtrlEvent] - 1;
|
||||
msg->SetCmd(plSoundMsg::kStop);
|
||||
msg->Send(GetTarget()->GetAudioInterface()->GetKey());
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIControlMod Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIControlMod_h
|
||||
#define _pfGUIControlMod_h
|
||||
|
||||
|
||||
#include "../pnModifier/plSingleModifier.h"
|
||||
#include "hsBounds.h"
|
||||
#include "../plMessage/plInputEventMsg.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "hsColorRGBA.h"
|
||||
#include "hsRefCnt.h"
|
||||
|
||||
class plMessage;
|
||||
class plPostEffectMod;
|
||||
class pfGUIDialogMod;
|
||||
class pfGUICtrlProcObject;
|
||||
class pfGUIDropTargetProc;
|
||||
class plDynamicTextMap;
|
||||
class plLayerInterface;
|
||||
|
||||
//// pfGUIColorScheme ////////////////////////////////////////////////////////
|
||||
// Tiny helper wrapper for a set of colors used to draw various controls
|
||||
|
||||
class pfGUIColorScheme : public hsRefCnt
|
||||
{
|
||||
public:
|
||||
hsColorRGBA fForeColor, fBackColor;
|
||||
hsColorRGBA fSelForeColor, fSelBackColor;
|
||||
hsBool fTransparent;
|
||||
|
||||
char *fFontFace;
|
||||
UInt8 fFontSize;
|
||||
UInt8 fFontFlags;
|
||||
|
||||
enum FontFlags
|
||||
{
|
||||
kFontBold = 0x01,
|
||||
kFontItalic = 0x02,
|
||||
kFontShadowed = 0x04
|
||||
};
|
||||
|
||||
pfGUIColorScheme();
|
||||
~pfGUIColorScheme();
|
||||
pfGUIColorScheme( hsColorRGBA &foreColor, hsColorRGBA &backColor );
|
||||
pfGUIColorScheme( const char *face, UInt8 size, UInt8 fontFlags );
|
||||
|
||||
void SetFontFace( const char *face );
|
||||
|
||||
void Read( hsStream *s );
|
||||
void Write( hsStream *s );
|
||||
|
||||
hsBool IsBold( void ) { return ( fFontFlags & kFontBold ) ? true : false; }
|
||||
hsBool IsItalic( void ) { return ( fFontFlags & kFontItalic ) ? true : false; }
|
||||
hsBool IsShadowed( void ) { return ( fFontFlags & kFontShadowed ) ? true : false; }
|
||||
|
||||
protected:
|
||||
|
||||
void IReset( void );
|
||||
};
|
||||
|
||||
//// Class Def ///////////////////////////////////////////////////////////////
|
||||
|
||||
class pfGUISkin;
|
||||
class pfGUIControlMod : public plSingleModifier
|
||||
{
|
||||
friend class pfGUIDialogMod;
|
||||
|
||||
protected:
|
||||
|
||||
UInt32 fTagID;
|
||||
hsBool fEnabled, fFocused, fVisible, fInteresting;
|
||||
hsBool fNotifyOnInteresting;
|
||||
pfGUIDialogMod *fDialog;
|
||||
|
||||
hsBounds3 fBounds, fInitialBounds; // Z component is 0-1
|
||||
hsScalar fScreenMinZ; // Closest Z coordinate in screen space
|
||||
hsPoint3 fScreenCenter;
|
||||
hsBool fBoundsValid, fCenterValid;
|
||||
hsMatrix44 fXformMatrix; // Only used for doing drag work, etc.
|
||||
|
||||
pfGUICtrlProcObject *fHandler;
|
||||
pfGUIDropTargetProc *fDropTargetHdlr;
|
||||
|
||||
plDynamicTextMap *fDynTextMap; // Some controls use this; for others, it'll be nil
|
||||
plLayerInterface *fDynTextLayer; // Juse so we can reset the transform. Sheesh!
|
||||
|
||||
pfGUIColorScheme *fColorScheme;
|
||||
plSceneObject *fProxy;
|
||||
|
||||
hsTArray<hsPoint3> fBoundsPoints; // For more accurate bounds tests
|
||||
|
||||
hsTArray<int> fSoundIndices; // Indices of sounds to trigger on the target SO's audible interface
|
||||
|
||||
pfGUISkin *fSkin;
|
||||
|
||||
|
||||
hsBool ISetUpDynTextMap( plPipeline *pipe );
|
||||
virtual void IPostSetUpDynTextMap( void ) {}
|
||||
virtual void IGrowDTMDimsToDesiredSize( UInt16 &width, UInt16 &height ) { }
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
void ISetDialog( pfGUIDialogMod *mod ) { fDialog = mod; }
|
||||
void IScreenToLocalPt( hsPoint3 &pt );
|
||||
|
||||
virtual void IUpdate( void ) {;}
|
||||
void ISetHandler( pfGUICtrlProcObject *h, hsBool clearInheritFlag = false );
|
||||
|
||||
void IPlaySound( UInt8 guiCtrlEvent, hsBool loop = false );
|
||||
void IStopSound( UInt8 guiCtrlEvent );
|
||||
|
||||
virtual UInt32 IGetDesiredCursor( void ) const { return 0; } // As specified in plInputInterface.h
|
||||
|
||||
public:
|
||||
|
||||
pfGUIControlMod();
|
||||
virtual ~pfGUIControlMod();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIControlMod );
|
||||
GETINTERFACE_ANY( pfGUIControlMod, plSingleModifier );
|
||||
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
UInt32 GetTagID( void ) { return fTagID; }
|
||||
|
||||
virtual void SetEnabled( hsBool e );
|
||||
virtual hsBool IsEnabled( void ) { return fEnabled; }
|
||||
virtual void SetFocused( hsBool e );
|
||||
virtual hsBool IsFocused( void ) { return fFocused; }
|
||||
virtual void SetVisible( hsBool vis );
|
||||
virtual hsBool IsVisible( void ) { return fVisible; }
|
||||
|
||||
virtual void SetInteresting( hsBool i );
|
||||
hsBool IsInteresting( void ) { return fInteresting; }
|
||||
|
||||
virtual void SetNotifyOnInteresting( hsBool state ) { fNotifyOnInteresting = state; }
|
||||
|
||||
pfGUIDialogMod *GetOwnerDlg( void ) { return fDialog; }
|
||||
|
||||
virtual void Refresh( void );
|
||||
|
||||
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
|
||||
void SetObjectCenter( hsScalar x, hsScalar y );
|
||||
virtual hsPoint3 GetObjectCenter() { return fScreenCenter; }
|
||||
hsScalar GetScreenMinZ( void ) { return fScreenMinZ; }
|
||||
void CalcInitialBounds( void );
|
||||
|
||||
const hsBounds3 &GetBounds( void );
|
||||
hsBool PointInBounds( const hsPoint3 &point );
|
||||
|
||||
virtual void SetTarget( plSceneObject *object );
|
||||
|
||||
// Return false if you actually DON'T want the mouse clicked at this point (should only be used for non-rectangular region rejection)
|
||||
virtual hsBool FilterMousePosition( hsPoint3 &mousePt ) { return true; }
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers ) {;}
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers ) {;}
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers ) {;}
|
||||
virtual void HandleMouseHover( hsPoint3 &mousePt, UInt8 modifiers ) {;}
|
||||
virtual void HandleMouseDblClick( hsPoint3 &mousePt, UInt8 modifiers ) {;}
|
||||
|
||||
virtual hsBool HandleKeyPress( char key, UInt8 modifiers );
|
||||
virtual hsBool HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers );
|
||||
|
||||
void SetHandler( pfGUICtrlProcObject *h ) { ISetHandler( h, true ); }
|
||||
void DoSomething( void ); // Will call the handler
|
||||
void HandleExtendedEvent( UInt32 event ); // Will call the handler
|
||||
|
||||
pfGUICtrlProcObject *GetHandler( void ) const { return fHandler; }
|
||||
|
||||
void SetDropTargetHdlr( pfGUIDropTargetProc *drop );
|
||||
pfGUIDropTargetProc *GetDropTargetHdlr( void ) { return fDropTargetHdlr; }
|
||||
|
||||
enum
|
||||
{
|
||||
kRefDynTextMap,
|
||||
kRefDynTextLayer,
|
||||
kRefProxy,
|
||||
kRefSkin,
|
||||
kRefDerivedStart = 32
|
||||
};
|
||||
|
||||
enum Flags // plSingleModifier already has SetFlag()/HasFlag()
|
||||
{
|
||||
kWantsInterest,
|
||||
kInheritProcFromDlg,
|
||||
kIntangible, // I.E. it doesn't exists on the screen/can't be clicked on.
|
||||
// Used for group objects like the up/down pair
|
||||
kXparentBgnd,
|
||||
kScaleTextWithResolution, // I.E. take up the same space on screen no matter the resolution
|
||||
kTakesSpecialKeys, // I.E. disable bindings for keys like backspace because we want them
|
||||
kHasProxy,
|
||||
kBetterHitTesting,
|
||||
kDerivedFlagsStart = 32
|
||||
};
|
||||
|
||||
virtual void SetColorScheme( pfGUIColorScheme *newScheme );
|
||||
pfGUIColorScheme *GetColorScheme( void ) const;
|
||||
|
||||
// should be override by specific GUIcontrol
|
||||
virtual void PurgeDynaTextMapImage() {;}
|
||||
|
||||
// Override from plModifier so we can update our bounds
|
||||
virtual void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l);
|
||||
|
||||
// Forces an immediate play of the given GUI control event sound
|
||||
void PlaySound( UInt8 guiCtrlEvent, hsBool loop = false ) { IPlaySound( guiCtrlEvent, loop ); }
|
||||
void StopSound( UInt8 guiCtrlEvent ) { IStopSound( guiCtrlEvent ); }
|
||||
|
||||
// Export only
|
||||
void SetTagID( UInt32 id ) { fTagID = id; }
|
||||
void SetDynTextMap( plLayerInterface *layer, plDynamicTextMap *dynText );
|
||||
void SetSoundIndex( UInt8 guiCtrlEvent, int soundIndex );
|
||||
};
|
||||
|
||||
#endif // _pfGUIControlMod_h
|
@ -0,0 +1,508 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUICtrlGenerator Definitions //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUICtrlGenerator.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
#include "pfGUIButtonMod.h"
|
||||
#include "pfGUIDragBarCtrl.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
#include "pfGUIMenuItem.h"
|
||||
|
||||
#include "../plSurface/hsGMaterial.h"
|
||||
#include "../plSurface/plLayer.h"
|
||||
#include "../plGImage/plMipmap.h"
|
||||
#include "../pnKeyedObject/plFixedKey.h"
|
||||
#include "../plDrawable/plDrawableSpans.h"
|
||||
#include "../plDrawable/plDrawableGenerator.h"
|
||||
#include "../pnSceneObject/plSceneObject.h"
|
||||
#include "../pnSceneObject/plDrawInterface.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
#include "../pnMessage/plIntRefMsg.h"
|
||||
#include "../pnMessage/plObjRefMsg.h"
|
||||
#include "../pnMessage/plNodeRefMsg.h"
|
||||
#include "../plPipeline/plTextGenerator.h"
|
||||
#include "../plScene/plPostEffectMod.h"
|
||||
#include "../plScene/plSceneNode.h"
|
||||
#include "../pnMessage/plClientMsg.h"
|
||||
#include "../plMessage/plLayRefMsg.h"
|
||||
#include "../pnMessage/plAttachMsg.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUICtrlGenerator::pfGUICtrlGenerator()
|
||||
{
|
||||
strcpy( fFontFace, "Arial" );
|
||||
fFontSize = 18;
|
||||
}
|
||||
|
||||
pfGUICtrlGenerator::~pfGUICtrlGenerator()
|
||||
{
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void pfGUICtrlGenerator::Shutdown( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
// Destroy our scene nodes and dialogs
|
||||
for( i = 0; i < fDynDlgNodes.GetCount(); i++ )
|
||||
{
|
||||
pfGameGUIMgr::GetInstance()->UnloadDialog( fDynDialogs[ i ] );
|
||||
fDynDlgNodes[ i ]->GetKey()->UnRefObject();
|
||||
}
|
||||
fDynDlgNodes.Reset();
|
||||
fDynDialogs.Reset();
|
||||
|
||||
for( i = 0; i < fTextGens.GetCount(); i++ )
|
||||
delete fTextGens[ i ];
|
||||
fTextGens.Reset();
|
||||
|
||||
}
|
||||
|
||||
//// Instance ////////////////////////////////////////////////////////////////
|
||||
|
||||
pfGUICtrlGenerator &pfGUICtrlGenerator::Instance( void )
|
||||
{
|
||||
static pfGUICtrlGenerator myInstance;
|
||||
|
||||
return myInstance;
|
||||
}
|
||||
|
||||
//// IGetNextKeyName /////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICtrlGenerator::IGetNextKeyName( char *name, const char *prefix )
|
||||
{
|
||||
static UInt32 keyCount = 0;
|
||||
|
||||
|
||||
sprintf( name, "%s%d", prefix, keyCount++ );
|
||||
}
|
||||
|
||||
//// IAddKey /////////////////////////////////////////////////////////////////
|
||||
|
||||
plKey pfGUICtrlGenerator::IAddKey( hsKeyedObject *ko, const char *prefix )
|
||||
{
|
||||
char keyName[ 128 ];
|
||||
|
||||
|
||||
IGetNextKeyName( keyName, prefix );
|
||||
return hsgResMgr::ResMgr()->NewKey( keyName, ko, plLocation::kGlobalFixedLoc );
|
||||
}
|
||||
|
||||
//// SetFont /////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICtrlGenerator::SetFont( const char *face, UInt16 size )
|
||||
{
|
||||
strcpy( fFontFace, face );
|
||||
fFontSize = size;
|
||||
}
|
||||
|
||||
//// ICreateSolidMaterial ////////////////////////////////////////////////////
|
||||
// Creates a material with no texture, just color.
|
||||
|
||||
hsGMaterial *pfGUICtrlGenerator::ICreateSolidMaterial( hsColorRGBA &color )
|
||||
{
|
||||
hsColorRGBA black;
|
||||
|
||||
|
||||
// Create a material with a simple blank layer, fully ambient
|
||||
hsGMaterial *material = TRACKED_NEW hsGMaterial;
|
||||
IAddKey( material, "GUIMaterial" );
|
||||
|
||||
plLayer *lay = material->MakeBaseLayer();
|
||||
black.Set( 0.f,0.f,0.f,1.f );
|
||||
|
||||
lay->SetRuntimeColor( black );
|
||||
lay->SetPreshadeColor( black );
|
||||
lay->SetAmbientColor( color );
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
//// ICreateTextMaterial /////////////////////////////////////////////////////
|
||||
// Creates a material with a texture that has a string centered on it.
|
||||
|
||||
hsGMaterial *pfGUICtrlGenerator::ICreateTextMaterial( const char *text, hsColorRGBA &bgColor,
|
||||
hsColorRGBA &textColor, float objWidth, float objHeight )
|
||||
{
|
||||
UInt16 pixWidth, pixHeight, strWidth, strHeight;
|
||||
hsColorRGBA black, white;
|
||||
|
||||
|
||||
// Guess at some pixel width and heights we want. We're guessing b/c we want it to look reasonably
|
||||
// good on the screen, but we don't know exactly how big is big, so we guess
|
||||
pixWidth = (UInt16)(objWidth * 64.f);
|
||||
pixHeight = (UInt16)(objHeight * 64.f);
|
||||
|
||||
// Create blank mipmap
|
||||
plMipmap *bitmap = TRACKED_NEW plMipmap( 1, 1, plMipmap::kRGB32Config, 1 );
|
||||
IAddKey( bitmap, "GUIMipmap" );
|
||||
|
||||
// Create textGen to write string with
|
||||
plTextGenerator *textGen = TRACKED_NEW plTextGenerator( bitmap, pixWidth, pixHeight );
|
||||
textGen->SetFont( fFontFace, (UInt16)fFontSize );
|
||||
textGen->ClearToColor( bgColor );
|
||||
textGen->SetTextColor( textColor );
|
||||
strWidth = textGen->CalcStringWidth( text, &strHeight );
|
||||
textGen->DrawString( ( pixWidth - strWidth ) >> 1, ( pixHeight - strHeight ) >> 1, text );
|
||||
textGen->FlushToHost();
|
||||
fTextGens.Append( textGen );
|
||||
|
||||
// Create a material with a simple blank layer, fully ambient
|
||||
hsGMaterial *material = TRACKED_NEW hsGMaterial;
|
||||
IAddKey( material, "GUIMaterial" );
|
||||
|
||||
plLayer *lay = material->MakeBaseLayer();
|
||||
white.Set( 1.f,1.f,1.f,1.f );
|
||||
black.Set( 0.f,0.f,0.f,1.f );
|
||||
|
||||
lay->SetRuntimeColor( black );
|
||||
lay->SetPreshadeColor( black );
|
||||
lay->SetAmbientColor( white );
|
||||
|
||||
hsgResMgr::ResMgr()->AddViaNotify( bitmap->GetKey(), TRACKED_NEW plLayRefMsg( lay->GetKey(), plRefMsg::kOnCreate, 0, plLayRefMsg::kTexture ), plRefFlags::kActiveRef );
|
||||
// lay->SetTexture( bitmap );
|
||||
lay->SetTransform( textGen->GetLayerTransform() );
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
//// GenerateDialog //////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUICtrlGenerator::GenerateDialog( const char *name )
|
||||
{
|
||||
IGenerateDialog( name, 20.f, false );
|
||||
}
|
||||
|
||||
//// IGenSceneObject /////////////////////////////////////////////////////////
|
||||
|
||||
plSceneObject *pfGUICtrlGenerator::IGenSceneObject( pfGUIDialogMod *dlg, plDrawable *myDraw, plSceneObject *parent,
|
||||
hsMatrix44 *l2w, hsMatrix44 *w2l )
|
||||
{
|
||||
plKey snKey = ( dlg != nil ) ? ( dlg->GetTarget() != nil ? dlg->GetTarget()->GetSceneNode() : nil ) : nil;
|
||||
if( snKey == nil )
|
||||
snKey = fDynDlgNodes.Peek()->GetKey();
|
||||
|
||||
hsgResMgr::ResMgr()->SendRef( myDraw->GetKey(), TRACKED_NEW plNodeRefMsg( snKey, plRefMsg::kOnCreate, 0, plNodeRefMsg::kDrawable ), plRefFlags::kActiveRef );
|
||||
|
||||
plDrawInterface *newDI = TRACKED_NEW plDrawInterface;
|
||||
IAddKey( newDI, "GUIDrawIFace" );
|
||||
|
||||
plSceneObject *newObj = TRACKED_NEW plSceneObject;
|
||||
IAddKey( newObj, "GUISceneObject" );
|
||||
|
||||
plCoordinateInterface *newCI = TRACKED_NEW plCoordinateInterface;
|
||||
IAddKey( newCI, "GUICoordIFace" );
|
||||
|
||||
hsgResMgr::ResMgr()->SendRef( newCI->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface ), plRefFlags::kActiveRef );
|
||||
hsgResMgr::ResMgr()->SendRef( newDI->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface ), plRefFlags::kActiveRef );
|
||||
hsgResMgr::ResMgr()->SendRef( myDraw->GetKey(), TRACKED_NEW plIntRefMsg( newDI->GetKey(), plRefMsg::kOnCreate, 0, plIntRefMsg::kDrawable ), plRefFlags::kActiveRef );
|
||||
|
||||
if( parent == nil )
|
||||
{
|
||||
parent = ( fDynDragBars.GetCount() > 0 ) ? fDynDragBars.Peek() : nil;
|
||||
if( parent == nil )
|
||||
parent = dlg->GetTarget();
|
||||
}
|
||||
|
||||
if( parent != nil )
|
||||
// hsgResMgr::ResMgr()->SendRef( newCI->GetKey(), TRACKED_NEW plIntRefMsg( parent->GetKey(), plRefMsg::kOnCreate, 0, plIntRefMsg::kChild ), plRefFlags::kActiveRef );
|
||||
hsgResMgr::ResMgr()->SendRef( newCI->GetKey(), TRACKED_NEW plAttachMsg( parent->GetKey(), nil, plRefMsg::kOnRequest ), plRefFlags::kActiveRef );
|
||||
|
||||
newObj->SetSceneNode( snKey );
|
||||
|
||||
if( l2w != nil )
|
||||
{
|
||||
newObj->SetTransform( *l2w, *w2l );
|
||||
// newCI->SetLocalToParent( *l2w, *w2l );
|
||||
// myDraw->SetTransform( -1, *l2w, *w2l );
|
||||
}
|
||||
|
||||
return newObj;
|
||||
}
|
||||
|
||||
//// GenerateRectButton //////////////////////////////////////////////////////
|
||||
|
||||
pfGUIButtonMod *pfGUICtrlGenerator::GenerateRectButton( const char *title, float x, float y, float width, float height,
|
||||
const char *consoleCmd, hsColorRGBA &color, hsColorRGBA &textColor )
|
||||
{
|
||||
hsGMaterial *material;
|
||||
hsMatrix44 l2w, w2l;
|
||||
hsVector3 vec;
|
||||
pfGUIDialogMod *dlgToAddTo = IGetDialog();
|
||||
|
||||
|
||||
// Get us a material
|
||||
material = ICreateTextMaterial( title, color, textColor, width * 20.f, height * 20.f );
|
||||
|
||||
pfGUIButtonMod *but = CreateRectButton( dlgToAddTo, title, x, y, width, height, material );
|
||||
if( but != nil )
|
||||
but->SetHandler( TRACKED_NEW pfGUIConsoleCmdProc( consoleCmd ) );
|
||||
|
||||
return but;
|
||||
}
|
||||
|
||||
//// CreateRectButton ////////////////////////////////////////////////////////
|
||||
|
||||
pfGUIButtonMod *pfGUICtrlGenerator::CreateRectButton( pfGUIDialogMod *parent, const char *title, float x, float y, float width, float height,
|
||||
hsGMaterial *material, hsBool asMenuItem )
|
||||
{
|
||||
wchar_t *wTitle = hsStringToWString(title);
|
||||
pfGUIButtonMod *retVal = CreateRectButton(parent,wTitle,x,y,width,height,material,asMenuItem);
|
||||
delete [] wTitle;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
pfGUIButtonMod *pfGUICtrlGenerator::CreateRectButton( pfGUIDialogMod *parent, const wchar_t *title, float x, float y, float width, float height,
|
||||
hsGMaterial *material, hsBool asMenuItem )
|
||||
{
|
||||
plDrawableSpans *myDraw;
|
||||
hsMatrix44 l2w, w2l;
|
||||
hsVector3 vec;
|
||||
|
||||
|
||||
// Translate x and y from (0:1) to (-10:10)
|
||||
x = ( x - 0.5f ) * 20.f;
|
||||
y = ( y - 0.5f ) * 20.f;
|
||||
// Translate width and height from (0:1) to (-10:10)
|
||||
width *= 20.f;
|
||||
height *= 20.f;
|
||||
|
||||
// Create drawable that is rectangular
|
||||
l2w.Reset();
|
||||
hsPoint3 corner( x, -y, -100 );
|
||||
hsVector3 xVec( width, 0, 0 ), yVec( 0, height, 0 ), zVec( 0, 0, 0.1f );
|
||||
|
||||
myDraw = plDrawableGenerator::GeneratePlanarDrawable( corner, xVec, yVec, material, l2w );
|
||||
|
||||
plSceneObject *newObj = IGenSceneObject( parent, myDraw );
|
||||
|
||||
pfGUIButtonMod *newBtn = asMenuItem ? TRACKED_NEW pfGUIMenuItem : TRACKED_NEW pfGUIButtonMod;
|
||||
IAddKey( newBtn, "GUIButton" );
|
||||
hsgResMgr::ResMgr()->SendRef( newBtn->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kModifier ), plRefFlags::kActiveRef );
|
||||
parent->AddControl( newBtn );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( newBtn->GetKey(), TRACKED_NEW plGenRefMsg( parent->GetKey(), plRefMsg::kOnCreate, parent->GetNumControls() - 1, pfGUIDialogMod::kControlRef ), plRefFlags::kActiveRef );
|
||||
|
||||
return newBtn;
|
||||
}
|
||||
|
||||
//// GenerateSphereButton ////////////////////////////////////////////////////
|
||||
|
||||
pfGUIButtonMod *pfGUICtrlGenerator::GenerateSphereButton( float x, float y, float radius,
|
||||
const char *consoleCmd, hsColorRGBA &color )
|
||||
{
|
||||
hsGMaterial *material;
|
||||
plDrawableSpans *myDraw;
|
||||
hsMatrix44 l2w, w2l;
|
||||
hsVector3 vec;
|
||||
hsPoint3 pt( x, -y, -100.f );
|
||||
pfGUIDialogMod *dlgToAddTo = IGetDialog();
|
||||
|
||||
|
||||
// Translate x and y from (0:1) to (-10:10)
|
||||
x = ( x - 0.5f ) * 20.f;
|
||||
y = ( y - 0.5f ) * 20.f;
|
||||
// Translate width and height from (0:1) to (-10:10)
|
||||
radius *= 20.f;
|
||||
|
||||
// Get us a material
|
||||
material = ICreateSolidMaterial( color );
|
||||
|
||||
// Create drawable that is rectangular
|
||||
l2w.Reset();
|
||||
// We bump up the quality since we're actually far closer to these things then the normal
|
||||
// world camera would put us
|
||||
myDraw = plDrawableGenerator::GenerateSphericalDrawable( pt, radius, material, l2w,
|
||||
false, nil, nil, nil, 100.f );
|
||||
|
||||
vec.Set( x, -y, 0 );
|
||||
l2w.MakeTranslateMat( &vec );
|
||||
l2w.GetInverse( &w2l );
|
||||
|
||||
plSceneObject *newObj = IGenSceneObject( dlgToAddTo, myDraw );//, nil, &l2w, &w2l );
|
||||
|
||||
pfGUIButtonMod *newBtn = TRACKED_NEW pfGUIButtonMod;
|
||||
IAddKey( newBtn, "GUIButton" );
|
||||
newBtn->SetHandler( TRACKED_NEW pfGUIConsoleCmdProc( consoleCmd ) );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( newBtn->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kModifier ), plRefFlags::kActiveRef );
|
||||
dlgToAddTo->AddControl( newBtn );
|
||||
|
||||
return newBtn;
|
||||
}
|
||||
|
||||
//// GenerateDragBar //////////////////////////////////////////////////////
|
||||
|
||||
pfGUIDragBarCtrl *pfGUICtrlGenerator::GenerateDragBar( float x, float y, float width, float height, hsColorRGBA &color )
|
||||
{
|
||||
hsGMaterial *material;
|
||||
plDrawableSpans *myDraw;
|
||||
hsMatrix44 l2w, w2l;
|
||||
hsVector3 vec;
|
||||
pfGUIDialogMod *dlgToAddTo = IGetDialog();
|
||||
|
||||
|
||||
// Translate x and y from (0:1) to (-10:10)
|
||||
x = ( x - 0.5f ) * 20.f;
|
||||
y = ( y - 0.5f ) * 20.f;
|
||||
// Translate width and height from (0:1) to (-10:10)
|
||||
width *= 20.f;
|
||||
height *= 20.f;
|
||||
|
||||
// Get us a material
|
||||
material = ICreateSolidMaterial( color );
|
||||
|
||||
// Create drawable that is rectangular
|
||||
l2w.Reset();
|
||||
|
||||
hsPoint3 corner( x, -y, -100 );//x - width / 2.f, -y - height / 2.f, -100 );
|
||||
hsVector3 xVec( width, 0, 0 ), yVec( 0, height, 0 ), zVec( 0, 0, 0.1f );
|
||||
|
||||
myDraw = plDrawableGenerator::GenerateBoxDrawable( corner, xVec, yVec, zVec,/*width, height, 0.01f, */material, l2w );
|
||||
|
||||
// Drag bars are special--everything else gets attached to them and they get attached to the dialog
|
||||
vec.Set( x, -y, -100 );
|
||||
l2w.MakeTranslateMat( &vec );
|
||||
l2w.GetInverse( &w2l );
|
||||
|
||||
plSceneObject *newObj = IGenSceneObject( dlgToAddTo, myDraw, dlgToAddTo->GetTarget(), &l2w, &w2l );
|
||||
|
||||
fDynDragBars[ fDynDragBars.GetCount() - 1 ] = newObj;
|
||||
|
||||
pfGUIDragBarCtrl *newBtn = TRACKED_NEW pfGUIDragBarCtrl;
|
||||
IAddKey( newBtn, "GUIDragBar" );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( newBtn->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kModifier ), plRefFlags::kActiveRef );
|
||||
dlgToAddTo->AddControl( newBtn );
|
||||
|
||||
/* vec.Set( -x, y, 100 );
|
||||
l2w.MakeTranslateMat( &vec );
|
||||
l2w.GetInverse( &w2l );
|
||||
|
||||
plCoordinateInterface *ci = (plCoordinateInterface *)dlgToAddTo->GetTarget()->GetCoordinateInterface();
|
||||
ci->SetLocalToParent( l2w, w2l );
|
||||
*/
|
||||
return newBtn;
|
||||
}
|
||||
|
||||
//// IGetDialog //////////////////////////////////////////////////////////////
|
||||
|
||||
pfGUIDialogMod *pfGUICtrlGenerator::IGetDialog( void )
|
||||
{
|
||||
if( fDynDialogs.GetCount() == 0 )
|
||||
IGenerateDialog( "GUIBaseDynamicDlg", 20.f );
|
||||
|
||||
hsAssert( fDynDialogs.GetCount() > 0, "Unable to get a dynamic dialog to add buttons to" );
|
||||
return fDynDialogs.Peek();
|
||||
}
|
||||
|
||||
//// IGenerateDialog /////////////////////////////////////////////////////////
|
||||
|
||||
pfGUIDialogMod *pfGUICtrlGenerator::IGenerateDialog( const char *name, float scrnWidth, hsBool show )
|
||||
{
|
||||
float fovX, fovY;
|
||||
plSceneNode *node;
|
||||
pfGUIDialogMod *dialog;
|
||||
|
||||
|
||||
// Create the rendermod
|
||||
plPostEffectMod *renderMod = TRACKED_NEW plPostEffectMod;
|
||||
IAddKey( renderMod, "GUIRenderMod" );
|
||||
|
||||
renderMod->SetHither( 0.5f );
|
||||
renderMod->SetYon( 200.f );
|
||||
|
||||
// fovX should be such that scrnWidth is the projected width at z=100
|
||||
fovX = atan( scrnWidth / ( 2.f * 100.f ) ) * 2.f;
|
||||
fovY = fovX;// * 3.f / 4.f;
|
||||
|
||||
renderMod->SetFovX( fovX * 180.f / hsScalarPI );
|
||||
renderMod->SetFovY( fovY * 180.f / hsScalarPI );
|
||||
|
||||
// Create the sceneNode to go with it
|
||||
node = TRACKED_NEW plSceneNode;
|
||||
IAddKey( node, "GUISceneNode" );
|
||||
node->GetKey()->RefObject();
|
||||
fDynDlgNodes.Append( node );
|
||||
fDynDragBars.Append( nil );
|
||||
|
||||
hsgResMgr::ResMgr()->AddViaNotify( node->GetKey(), TRACKED_NEW plGenRefMsg( renderMod->GetKey(), plRefMsg::kOnCreate, 0, plPostEffectMod::kNodeRef ), plRefFlags::kPassiveRef );
|
||||
|
||||
// Create the dialog
|
||||
dialog = TRACKED_NEW pfGUIDialogMod;
|
||||
IAddKey( dialog, "GUIDialog" );
|
||||
|
||||
dialog->SetRenderMod( renderMod );
|
||||
dialog->SetName( name );
|
||||
|
||||
// Create the dummy scene object to hold the dialog
|
||||
plSceneObject *newObj = TRACKED_NEW plSceneObject;
|
||||
IAddKey( newObj, "GUISceneObject" );
|
||||
|
||||
// *#&$(*@&#$ need a coordIface...
|
||||
plCoordinateInterface *newCI = TRACKED_NEW plCoordinateInterface;
|
||||
IAddKey( newCI, "GUICoordIFace" );
|
||||
|
||||
hsMatrix44 l2w, w2l;
|
||||
l2w.Reset();
|
||||
// l2w.NotIdentity();
|
||||
|
||||
l2w.GetInverse( &w2l );
|
||||
|
||||
// Using SendRef here because AddViaNotify will queue the messages up, which doesn't do us any good
|
||||
// if we need these refs right away
|
||||
hsgResMgr::ResMgr()->SendRef( dialog->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kModifier ), plRefFlags::kActiveRef );
|
||||
|
||||
hsgResMgr::ResMgr()->AddViaNotify( newCI->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface ), plRefFlags::kActiveRef );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( renderMod->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kModifier ), plRefFlags::kActiveRef );
|
||||
|
||||
// Add the dialog to the GUI mgr
|
||||
plGenRefMsg *refMsg = TRACKED_NEW plGenRefMsg( pfGameGUIMgr::GetInstance()->GetKey(),
|
||||
plRefMsg::kOnCreate, 0, pfGameGUIMgr::kDlgModRef );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( dialog->GetKey(), refMsg, plRefFlags::kActiveRef );
|
||||
|
||||
newObj->SetSceneNode( node->GetKey() );
|
||||
|
||||
newObj->SetTransform( l2w, w2l );
|
||||
// newCI->SetLocalToParent( l2w, w2l );
|
||||
|
||||
if( show )
|
||||
pfGameGUIMgr::GetInstance()->ShowDialog( dialog );
|
||||
|
||||
fDynDialogs.Append( dialog );
|
||||
return dialog;
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUICtrlGenerator Header //
|
||||
// Generates really primitive GUI controls (and dialogs) at runtime. //
|
||||
// Useful for, well, generating really primitive GUI controls and dialogs //
|
||||
// at runtime...
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUICtrlGenerator_h
|
||||
#define _pfGUICtrlGenerator_h
|
||||
|
||||
#include "hsStream.h"
|
||||
#include "hsTemplates.h"
|
||||
|
||||
|
||||
//// pfGUICtrlGenerator Definition ///////////////////////////////////////////
|
||||
|
||||
class pfGUIDialogMod;
|
||||
class pfGUIButtonMod;
|
||||
class pfGUIDragBarCtrl;
|
||||
class hsGMaterial;
|
||||
struct hsColorRGBA;
|
||||
class plSceneNode;
|
||||
class hsKeyedObject;
|
||||
class plKey;
|
||||
class plTextGenerator;
|
||||
class plSceneObject;
|
||||
class plDrawable;
|
||||
struct hsMatrix44;
|
||||
|
||||
class pfGUICtrlGenerator
|
||||
{
|
||||
protected:
|
||||
|
||||
char fFontFace[ 256 ];
|
||||
UInt32 fFontSize;
|
||||
|
||||
hsTArray<plTextGenerator *> fTextGens;
|
||||
|
||||
hsTArray<plSceneNode *> fDynDlgNodes;
|
||||
hsTArray<pfGUIDialogMod *> fDynDialogs;
|
||||
hsTArray<plSceneObject *> fDynDragBars;
|
||||
|
||||
|
||||
plKey IAddKey( hsKeyedObject *ko, const char *prefix );
|
||||
void IGetNextKeyName( char *name, const char *prefix );
|
||||
|
||||
hsGMaterial *ICreateSolidMaterial( hsColorRGBA &color );
|
||||
|
||||
hsGMaterial *ICreateTextMaterial( const char *text, hsColorRGBA &bgColor,
|
||||
hsColorRGBA &textColor, float objWidth, float objHeight );
|
||||
|
||||
pfGUIDialogMod *IGetDialog( void );
|
||||
pfGUIDialogMod *IGenerateDialog( const char *name, float scrnWidth, hsBool show = true );
|
||||
|
||||
plSceneObject *IGenSceneObject( pfGUIDialogMod *dlg, plDrawable *myDraw, plSceneObject *parent = nil, hsMatrix44 *l2w = nil, hsMatrix44 *w2l = nil );
|
||||
|
||||
public:
|
||||
|
||||
pfGUICtrlGenerator();
|
||||
~pfGUICtrlGenerator();
|
||||
|
||||
void Shutdown( void );
|
||||
|
||||
void SetFont( const char *face, UInt16 size );
|
||||
|
||||
|
||||
pfGUIButtonMod *GenerateRectButton( const char *title, float x, float y, float width, float height,
|
||||
const char *consoleCmd, hsColorRGBA &color, hsColorRGBA &textColor );
|
||||
|
||||
pfGUIButtonMod *GenerateSphereButton( float x, float y, float radius,
|
||||
const char *consoleCmd, hsColorRGBA &color );
|
||||
|
||||
pfGUIDragBarCtrl *GenerateDragBar( float x, float y, float width, float height, hsColorRGBA &color );
|
||||
|
||||
void GenerateDialog( const char *name );
|
||||
|
||||
|
||||
pfGUIButtonMod *CreateRectButton( pfGUIDialogMod *parent, const char *title, float x, float y,
|
||||
float width, float height, hsGMaterial *material, hsBool asMenuItem = false );
|
||||
pfGUIButtonMod *CreateRectButton( pfGUIDialogMod *parent, const wchar_t *title, float x, float y,
|
||||
float width, float height, hsGMaterial *material, hsBool asMenuItem = false );
|
||||
|
||||
static pfGUICtrlGenerator &Instance( void );
|
||||
};
|
||||
|
||||
#endif // _pfGUICtrlGenerator_h
|
@ -0,0 +1,97 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDialogHandlers Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIDialogHandlers_h
|
||||
#define _pfGUIDialogHandlers_h
|
||||
|
||||
#include "hsStream.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
|
||||
//// pfGUIDialogProc Definition //////////////////////////////////////////////
|
||||
// This works very much like the control proc objects. The idea is, if you
|
||||
// want to do some custom work on a dialog (and who doesn't?), you create an
|
||||
// object derived from this type, override the functions, and do as you
|
||||
// please. The class type also derives from the control proc type, meaning
|
||||
// that you can implement DoSomething() as well and use the same object for
|
||||
// both your dialog and your control procs. (DoSomething() is overloaded here
|
||||
// so that it's no longer pure virtual, so you can use it for only handling
|
||||
// dialogs if you prefer).
|
||||
|
||||
class pfGUIDialogMod;
|
||||
class pfGUIDialogProc : public pfGUICtrlProcObject
|
||||
{
|
||||
protected:
|
||||
|
||||
pfGUIDialogMod *fDialog;
|
||||
|
||||
public:
|
||||
|
||||
pfGUIDialogProc() { }
|
||||
virtual ~pfGUIDialogProc() { ; }
|
||||
|
||||
// Called by the mgr--don't call yourself!
|
||||
void SetDialog( pfGUIDialogMod *dlg ) { fDialog = dlg; }
|
||||
|
||||
// Enums for OnControlEvent
|
||||
enum ControlEvt
|
||||
{
|
||||
kExitMode
|
||||
};
|
||||
|
||||
//////// FUNCTIONS TO OVERLOAD ////////
|
||||
|
||||
// Overloaded here so you don't have to unless you want to. Overload
|
||||
// it if you want to use this for a control handler as well.
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl ) {;}
|
||||
|
||||
// Called on dialog init (i.e. first showing, before OnShow() is called), only ever called once
|
||||
virtual void OnInit( void ) { ; }
|
||||
|
||||
// Called before the dialog is shown, always after OnInit()
|
||||
virtual void OnShow( void ) { ; }
|
||||
|
||||
// Called before the dialog is hidden
|
||||
virtual void OnHide( void ) { ; }
|
||||
|
||||
// Called on the dialog's destructor, before it's unregistered with the game GUI manager
|
||||
virtual void OnDestroy( void ) { ; }
|
||||
|
||||
// Called when the dialog's focused control changes
|
||||
virtual void OnCtrlFocusChange( pfGUIControlMod *oldCtrl, pfGUIControlMod *newCtrl ) { ; }
|
||||
|
||||
// Called when the key bound to a GUI event is pressed. Only called on the top modal dialog
|
||||
virtual void OnControlEvent( ControlEvt event ) { ; }
|
||||
|
||||
// Called when the GUI changes interesting state
|
||||
virtual void OnInterestingEvent( pfGUIControlMod *ctrl ) { ; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIDialogHandlers_h
|
@ -0,0 +1,832 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDialogMod Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "pfGUIDialogHandlers.h"
|
||||
#include "pfGUIDialogNotifyProc.h"
|
||||
#include "pfGUIListElement.h"
|
||||
#include "../plScene/plPostEffectMod.h"
|
||||
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plScene/plSceneNode.h"
|
||||
#include "../pnSceneObject/plSceneObject.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "../pnKeyedObject/plFixedKey.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
|
||||
#include "../plStatusLog/plStatusLog.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "plViewTransform.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIDialogMod::pfGUIDialogMod() : fRenderMod( nil ), fNext( nil ), fPrevPtr( nil )
|
||||
{
|
||||
memset( fName, 0, sizeof( fName ) );
|
||||
fEnabled = false;
|
||||
fControlOfInterest = nil;
|
||||
fFocusCtrl = nil;
|
||||
fMousedCtrl = nil;
|
||||
fTagID = 0;
|
||||
fHandler = nil;
|
||||
fVersion = 0;
|
||||
|
||||
fDragMode = false;
|
||||
fDragReceptive = false;
|
||||
fDragTarget = nil;
|
||||
fProcReceiver = nil;
|
||||
|
||||
fColorScheme = TRACKED_NEW pfGUIColorScheme();
|
||||
}
|
||||
|
||||
pfGUIDialogMod::~pfGUIDialogMod()
|
||||
{
|
||||
// Call the handler's destroy if there is one
|
||||
if( fHandler )
|
||||
fHandler->OnDestroy();
|
||||
|
||||
// Unregister us with the Game GUI manager
|
||||
plUoid lu( kGameGUIMgr_KEY );
|
||||
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
|
||||
if( mgrKey )
|
||||
{
|
||||
plGenRefMsg *refMsg = TRACKED_NEW plGenRefMsg( mgrKey, plRefMsg::kOnRemove, 0, pfGameGUIMgr::kDlgModRef );
|
||||
refMsg->SetRef( this );
|
||||
plgDispatch::MsgSend( refMsg );
|
||||
}
|
||||
|
||||
SetHandler( nil );
|
||||
|
||||
hsRefCnt_SafeUnRef( fColorScheme );
|
||||
fColorScheme = nil;
|
||||
}
|
||||
|
||||
//// ScreenToWorldPoint //////////////////////////////////////////////////////
|
||||
// Sometimes it just sucks not having access to the pipeline at just the
|
||||
// right time.
|
||||
|
||||
void pfGUIDialogMod::ScreenToWorldPoint( hsScalar x, hsScalar y, hsScalar z, hsPoint3 &outPt )
|
||||
{
|
||||
plViewTransform view = fRenderMod->GetViewTransform();
|
||||
view.SetScreenSize( 1, 1 );
|
||||
|
||||
outPt = view.ScreenToWorld( hsPoint3( x, y, z ) );
|
||||
}
|
||||
|
||||
//// WorldToScreenPoint //////////////////////////////////////////////////////
|
||||
// Given a point in world-space, translates it into screen coordinates
|
||||
// (with range 0-1, origin top-left).
|
||||
|
||||
hsPoint3 pfGUIDialogMod::WorldToScreenPoint( const hsPoint3 &inPt )
|
||||
{
|
||||
plViewTransform view = fRenderMod->GetViewTransform();
|
||||
view.SetScreenSize( 1, 1 );
|
||||
|
||||
hsPoint3 tempPt = view.WorldToScreen( inPt );
|
||||
tempPt.fZ = view.WorldToCamera( inPt ).fZ;
|
||||
return tempPt;
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDialogMod::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDialogMod::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plGenRefMsg *ref = plGenRefMsg::ConvertNoRef( msg );
|
||||
if( ref )
|
||||
{
|
||||
switch( ref->fType )
|
||||
{
|
||||
case kRenderModRef:
|
||||
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
fRenderMod = plPostEffectMod::ConvertNoRef( ref->GetRef() );
|
||||
fRenderMod->EnableLightsOnRenderRequest();
|
||||
|
||||
if( fEnabled )
|
||||
{
|
||||
plAnimCmdMsg *animMsg = TRACKED_NEW plAnimCmdMsg( GetKey(), fRenderMod->GetKey(), nil );
|
||||
animMsg->SetCmd( plAnimCmdMsg::kContinue );
|
||||
plgDispatch::MsgSend( animMsg );
|
||||
}
|
||||
}
|
||||
else if( ref->GetContext() & ( plRefMsg::kOnRemove | plRefMsg::kOnDestroy ) )
|
||||
{
|
||||
plAnimCmdMsg *animMsg = TRACKED_NEW plAnimCmdMsg( GetKey(), fRenderMod->GetKey(), nil );
|
||||
animMsg->SetCmd( plAnimCmdMsg::kStop );
|
||||
plgDispatch::MsgSend( animMsg );
|
||||
|
||||
fRenderMod = nil;
|
||||
}
|
||||
break;
|
||||
|
||||
case kControlRef:
|
||||
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
if( ref->fWhich >= fControls.GetCount() )
|
||||
{
|
||||
hsAssert( false, "Bad index in reffing a control on a GUI dialog" );
|
||||
}
|
||||
else
|
||||
{
|
||||
pfGUIControlMod *oldCtrl = fControls[ ref->fWhich ];
|
||||
|
||||
fControls[ ref->fWhich ] = pfGUIControlMod::ConvertNoRef( ref->GetRef() );
|
||||
fControls[ ref->fWhich ]->ISetDialog( this );
|
||||
if( oldCtrl != fControls[ ref->fWhich ] )
|
||||
// They're equal on export time, when we DON'T want to be updating the bounds
|
||||
fControls[ ref->fWhich ]->CalcInitialBounds();
|
||||
|
||||
if( fControls[ ref->fWhich ]->HasFlag( pfGUIControlMod::kInheritProcFromDlg ) )
|
||||
fControls[ ref->fWhich ]->ISetHandler( fHandler );
|
||||
}
|
||||
}
|
||||
|
||||
else if( ref->GetContext() & ( plRefMsg::kOnRemove | plRefMsg::kOnDestroy ) )
|
||||
{
|
||||
if( ref->fWhich >= fControls.GetCount() )
|
||||
{
|
||||
hsAssert( false, "Bad index in unreffing a control on a GUI dialog." );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fControls[ ref->fWhich ] != nil )
|
||||
fControls[ ref->fWhich ]->ISetDialog( nil );
|
||||
fControls[ ref->fWhich ] = nil;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return plSingleModifier::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// AddControl //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::AddControl( pfGUIControlMod *ctrl )
|
||||
{
|
||||
fControls.Append( ctrl );
|
||||
ctrl->ISetDialog( this );
|
||||
ctrl->CalcInitialBounds();
|
||||
}
|
||||
|
||||
//// AddControlOnExport //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::AddControlOnExport( pfGUIControlMod *ctrl )
|
||||
{
|
||||
fControls.Append( ctrl );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( ctrl->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, fControls.GetCount() - 1, pfGUIDialogMod::kControlRef ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
//// SetEnabled //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::SetEnabled( hsBool e )
|
||||
{
|
||||
if( e == fEnabled )
|
||||
return;
|
||||
|
||||
fEnabled = e;
|
||||
|
||||
if( fHandler != nil )
|
||||
{
|
||||
if( fEnabled )
|
||||
fHandler->OnShow();
|
||||
else
|
||||
fHandler->OnHide();
|
||||
}
|
||||
|
||||
if ( !fEnabled )
|
||||
{
|
||||
// if we are being hidden then there should be no controls that have interest
|
||||
fControlOfInterest = nil;
|
||||
// also we can purge the dynaText images on the controls
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ] == nil )
|
||||
continue;
|
||||
fControls[ i ]->PurgeDynaTextMapImage();
|
||||
}
|
||||
}
|
||||
|
||||
if( fRenderMod != nil )
|
||||
{
|
||||
plAnimCmdMsg *animMsg = TRACKED_NEW plAnimCmdMsg( GetKey(), fRenderMod->GetKey(), nil );
|
||||
if( fEnabled )
|
||||
{
|
||||
animMsg->SetCmd( plAnimCmdMsg::kContinue );
|
||||
|
||||
// Update the bounds on all controls that we own
|
||||
UpdateAllBounds();
|
||||
}
|
||||
else
|
||||
animMsg->SetCmd( plAnimCmdMsg::kStop );
|
||||
plgDispatch::MsgSend( animMsg );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
plSingleModifier::Read(s, mgr);
|
||||
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRenderModRef ), plRefFlags::kActiveRef );
|
||||
|
||||
s->Read( sizeof( fName ), fName );
|
||||
|
||||
UInt32 i, count = s->ReadSwap32();
|
||||
fControls.SetCountAndZero( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, i, kControlRef ), plRefFlags::kActiveRef );
|
||||
|
||||
// Register us with the Game GUI manager
|
||||
plUoid lu( kGameGUIMgr_KEY );
|
||||
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
|
||||
if( mgrKey )
|
||||
{
|
||||
plGenRefMsg *refMsg = TRACKED_NEW plGenRefMsg( mgrKey, plRefMsg::kOnCreate, 0, pfGameGUIMgr::kDlgModRef );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( GetKey(), refMsg, plRefFlags::kPassiveRef );
|
||||
}
|
||||
|
||||
s->ReadSwap( &fTagID );
|
||||
|
||||
fProcReceiver = mgr->ReadKey( s );
|
||||
if( fProcReceiver != nil )
|
||||
SetHandler( TRACKED_NEW pfGUIDialogNotifyProc( fProcReceiver ) );
|
||||
|
||||
s->ReadSwap( &fVersion );
|
||||
|
||||
fColorScheme->Read( s );
|
||||
|
||||
fSceneNodeKey = mgr->ReadKey( s );
|
||||
}
|
||||
|
||||
void pfGUIDialogMod::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
|
||||
plSingleModifier::Write( s, mgr );
|
||||
|
||||
mgr->WriteKey( s, fRenderMod->GetKey() );
|
||||
s->Write( sizeof( fName ), fName );
|
||||
|
||||
s->WriteSwap32( fControls.GetCount() );
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
mgr->WriteKey( s, fControls[ i ]->GetKey() );
|
||||
|
||||
s->WriteSwap( fTagID );
|
||||
|
||||
mgr->WriteKey( s, fProcReceiver );
|
||||
|
||||
s->WriteSwap( fVersion );
|
||||
|
||||
fColorScheme->Write( s );
|
||||
|
||||
mgr->WriteKey( s, fSceneNodeKey );
|
||||
}
|
||||
|
||||
plKey pfGUIDialogMod::GetSceneNodeKey( void )
|
||||
{
|
||||
if( fSceneNodeKey != nil )
|
||||
return fSceneNodeKey;
|
||||
|
||||
// Attempt to grab it
|
||||
if( GetTarget() != nil && GetTarget()->GetSceneNode() != nil )
|
||||
return ( fSceneNodeKey = GetTarget()->GetSceneNode() );
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//// UpdateInterestingThings /////////////////////////////////////////////////
|
||||
// Really. We go through and make sure every control marked as interesting
|
||||
// still has the mouse inside it and vice versa.
|
||||
|
||||
void pfGUIDialogMod::UpdateInterestingThings( hsScalar mouseX, hsScalar mouseY, UInt8 modifiers, hsBool modalPreset )
|
||||
{
|
||||
int i;
|
||||
hsPoint3 mousePoint;
|
||||
|
||||
|
||||
mousePoint.Set( mouseX, mouseY, 0.f );
|
||||
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ] == nil )
|
||||
continue;
|
||||
|
||||
// if there was a modal present and we are not modal, then everything is unInteresting!
|
||||
if ( modalPreset && !HasFlag(pfGUIDialogMod::kModal) )
|
||||
{
|
||||
if( fControls[ i ]->IsInteresting() )
|
||||
fControls[ i ]->SetInteresting( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !fControls[ i ]->HasFlag( pfGUIControlMod::kIntangible ) && fControls[ i ]->PointInBounds( mousePoint ) || fControls[ i ] == fControlOfInterest )
|
||||
{
|
||||
if( !fControls[ i ]->IsInteresting() )
|
||||
fControls[ i ]->SetInteresting( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fControls[ i ]->IsInteresting() )
|
||||
fControls[ i ]->SetInteresting( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// HandleMouseEvent ////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef HS_DEBUGGING // Debugging bounds rects
|
||||
#include "../plPipeline/plDebugText.h"
|
||||
#endif
|
||||
|
||||
hsBool pfGUIDialogMod::HandleMouseEvent( pfGameGUIMgr::EventType event, hsScalar mouseX, hsScalar mouseY,
|
||||
UInt8 modifiers )
|
||||
{
|
||||
hsPoint3 mousePoint;
|
||||
UInt32 i;
|
||||
|
||||
pfGUIControlMod *oldInterestingCtrl = nil;
|
||||
hsScalar smallestZ;
|
||||
|
||||
#ifdef HS_DEBUGGING // Debugging bounds rects
|
||||
static bool showBounds = false;
|
||||
|
||||
if( showBounds )
|
||||
{
|
||||
UInt32 sW, sH;
|
||||
plDebugText::Instance().GetScreenSize(&sW,&sH);
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ] == nil )
|
||||
continue;
|
||||
if( fControls[ i ]->HasFlag( pfGUIControlMod::kIntangible ) )
|
||||
continue;
|
||||
|
||||
if( fControls[ i ]->fBoundsPoints.GetCount() > 0 )
|
||||
{
|
||||
const hsBounds3 &bnds = fControls[ i ]->GetBounds();
|
||||
plDebugText::Instance().Draw3DBorder( (UInt16)(sW * bnds.GetMins().fX),
|
||||
(UInt16)(sH * bnds.GetMins().fY),
|
||||
(UInt16)(sW * bnds.GetMaxs().fX),
|
||||
(UInt16)(sH * bnds.GetMaxs().fY), 0x3000ffff, 0x3000ffff );
|
||||
|
||||
UInt32 color = 0xffff0000;
|
||||
for( int j = 0; j < fControls[ i ]->fBoundsPoints.GetCount(); j++ )
|
||||
{
|
||||
// color = 0xff000000 | ( ( j * 16 ) << 16 );
|
||||
float x = sW * fControls[ i ]->fBoundsPoints[ j ].fX;
|
||||
float y = sH * fControls[ i ]->fBoundsPoints[ j ].fY;
|
||||
plDebugText::Instance().DrawRect( (UInt16)(x - 2), (UInt16)(y - 2), (UInt16)(x + 2), (UInt16)(y + 2), color );
|
||||
char str[ 16 ];
|
||||
itoa( j, str, 10 );
|
||||
plDebugText::Instance().DrawString( (UInt16)(x + 8), (UInt16)(y - 8), str, color );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const hsBounds3 &bnds = fControls[ i ]->GetBounds();
|
||||
plDebugText::Instance().Draw3DBorder( (UInt16)(sW * bnds.GetMins().fX),
|
||||
(UInt16)(sH * bnds.GetMins().fY),
|
||||
(UInt16)(sW * bnds.GetMaxs().fX),
|
||||
(UInt16)(sH * bnds.GetMaxs().fY), 0x300000ff, 0x300000ff );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mousePoint.Set( mouseX, mouseY, 0.f );
|
||||
|
||||
if( fDragMode )
|
||||
{
|
||||
IHandleDrag( mousePoint, event, modifiers );
|
||||
return true; // We ALWAYS handle events if we're in drag mode
|
||||
}
|
||||
|
||||
oldInterestingCtrl = fMousedCtrl;
|
||||
if( fControlOfInterest != nil )
|
||||
{
|
||||
// A particular control already has interest--pass messages directly to it no matter what
|
||||
fMousedCtrl = fControlOfInterest;
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0, fMousedCtrl = nil, smallestZ = 1.e30f; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ] != nil && !fControls[ i ]->HasFlag( pfGUIControlMod::kIntangible ) && fControls[ i ]->PointInBounds( mousePoint ) && fControls[ i ]->IsVisible() && fControls[ i ]->IsEnabled() )
|
||||
{
|
||||
if( fControls[ i ]->GetScreenMinZ() < smallestZ )
|
||||
{
|
||||
if( fControls[ i ]->FilterMousePosition( mousePoint ) )
|
||||
{
|
||||
fMousedCtrl = fControls[ i ];
|
||||
smallestZ = fControls[ i ]->GetScreenMinZ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( fMousedCtrl != nil )
|
||||
{
|
||||
#ifdef HS_DEBUGGING // Debugging bounds rects
|
||||
if( showBounds )
|
||||
{
|
||||
const hsBounds3 &bnds = fMousedCtrl->GetBounds();
|
||||
plDebugText::Instance().DrawString( (UInt16)(bnds.GetMins().fX), (UInt16)(bnds.GetMins().fY), fMousedCtrl->GetKeyName(), (UInt32)0xffffff00 );
|
||||
}
|
||||
#endif
|
||||
|
||||
if( event == pfGameGUIMgr::kMouseDown )
|
||||
{
|
||||
if( fMousedCtrl->HasFlag( pfGUIControlMod::kWantsInterest ) )
|
||||
fControlOfInterest = fMousedCtrl;
|
||||
|
||||
fMousedCtrl->HandleMouseDown( mousePoint, modifiers );
|
||||
|
||||
// Clicking on a control (mouse down) also sets focus to that control. Unlike
|
||||
// control-of-interest, this does NOT get reset until a new control is clicked on
|
||||
if( fFocusCtrl != fMousedCtrl )
|
||||
{
|
||||
if( fHandler != nil )
|
||||
fHandler->OnCtrlFocusChange( fFocusCtrl, fMousedCtrl );
|
||||
|
||||
if( fFocusCtrl != nil )
|
||||
fFocusCtrl->SetFocused( false );
|
||||
fFocusCtrl = fMousedCtrl;
|
||||
fFocusCtrl->SetFocused( true );
|
||||
}
|
||||
}
|
||||
else if( event == pfGameGUIMgr::kMouseUp )
|
||||
{
|
||||
fMousedCtrl->HandleMouseUp( mousePoint, modifiers );
|
||||
|
||||
// Controls lose interest on mouse up
|
||||
fControlOfInterest = nil;
|
||||
}
|
||||
else if( event == pfGameGUIMgr::kMouseMove )
|
||||
fMousedCtrl->HandleMouseHover( mousePoint, modifiers );
|
||||
else if( event == pfGameGUIMgr::kMouseDrag )
|
||||
fMousedCtrl->HandleMouseDrag( mousePoint, modifiers );
|
||||
else if( event == pfGameGUIMgr::kMouseDblClick )
|
||||
fMousedCtrl->HandleMouseDblClick( mousePoint, modifiers );
|
||||
|
||||
return true;
|
||||
}
|
||||
// Clicked on nobody, make sure we lose focus on any controls
|
||||
if( fFocusCtrl != nil && event == pfGameGUIMgr::kMouseDown )
|
||||
{
|
||||
if( fHandler != nil )
|
||||
fHandler->OnCtrlFocusChange( fFocusCtrl, nil );
|
||||
|
||||
if( fFocusCtrl != nil ) // The handler call could've changed it
|
||||
fFocusCtrl->SetFocused( false );
|
||||
fFocusCtrl = nil;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//// HandleKeyEvent //////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDialogMod::HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers )
|
||||
{
|
||||
// Only process if a control has focus...
|
||||
if( fFocusCtrl != nil )
|
||||
{
|
||||
// And guess what, it's up to that control to process it! Gee, how easy...
|
||||
return fFocusCtrl->HandleKeyEvent( event, key, modifiers );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//// HandleKeyPress //////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDialogMod::HandleKeyPress( char key, UInt8 modifiers )
|
||||
{
|
||||
// Same deal as HandleKeyPress. Only problem is, we needed the msg to translate
|
||||
// to a char, so it had to be done up at the mgr level (sadly)
|
||||
// Only process if a control has focus...
|
||||
|
||||
if( fFocusCtrl != nil )
|
||||
{
|
||||
return fFocusCtrl->HandleKeyPress( key, modifiers );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//// SetFocus ////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::SetFocus( pfGUIControlMod *ctrl )
|
||||
{
|
||||
if( ctrl != nil && ctrl->fDialog != this )
|
||||
{
|
||||
if( fHandler != nil )
|
||||
fHandler->OnCtrlFocusChange( fFocusCtrl, nil );
|
||||
|
||||
if( fFocusCtrl != nil )
|
||||
fFocusCtrl->SetFocused( false );
|
||||
fFocusCtrl = nil;
|
||||
|
||||
ctrl->fDialog->SetFocus( ctrl );
|
||||
}
|
||||
else if( ctrl != fFocusCtrl )
|
||||
{
|
||||
if( fFocusCtrl != nil )
|
||||
fFocusCtrl->SetFocused( false );
|
||||
|
||||
if( fHandler != nil )
|
||||
fHandler->OnCtrlFocusChange( fFocusCtrl, ctrl );
|
||||
|
||||
fFocusCtrl = ctrl;
|
||||
if( fFocusCtrl != nil )
|
||||
fFocusCtrl->SetFocused( true );
|
||||
}
|
||||
}
|
||||
|
||||
//// Show/Hide ///////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::Show( void )
|
||||
{
|
||||
pfGameGUIMgr::GetInstance()->ShowDialog( this );
|
||||
}
|
||||
|
||||
void pfGUIDialogMod::ShowNoReset( void )
|
||||
{
|
||||
pfGameGUIMgr::GetInstance()->ShowDialog( this, false );
|
||||
}
|
||||
|
||||
void pfGUIDialogMod::Hide( void )
|
||||
{
|
||||
pfGameGUIMgr::GetInstance()->HideDialog( this );
|
||||
}
|
||||
|
||||
//// GetControlFromTag ///////////////////////////////////////////////////////
|
||||
|
||||
pfGUIControlMod *pfGUIDialogMod::GetControlFromTag( UInt32 tagID )
|
||||
{
|
||||
int i;
|
||||
|
||||
int ctrlCount = fControls.GetCount();
|
||||
|
||||
for( i = 0; i < ctrlCount; i++ )
|
||||
{
|
||||
pfGUIControlMod *ctrl = fControls[i];
|
||||
if( ctrl && ctrl->GetTagID() == tagID )
|
||||
return fControls[ i ];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//// SetControlOfInterest ////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::SetControlOfInterest( pfGUIControlMod *c )
|
||||
{
|
||||
fControlOfInterest = c;
|
||||
}
|
||||
|
||||
//// SetHandler //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::SetHandler( pfGUIDialogProc *hdlr )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
if( fHandler && fHandler->DecRef() )
|
||||
delete fHandler;
|
||||
|
||||
fHandler = hdlr;
|
||||
if( fHandler != nil )
|
||||
{
|
||||
fHandler->IncRef();
|
||||
fHandler->SetDialog( this );
|
||||
}
|
||||
|
||||
// We also set the handler for any controls that are flagged to inherit
|
||||
// from the parent dialog. Note that SetHandlerForAll() can thus be
|
||||
// seen as a function that forces this flag (temporarily) on all controls
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
// Test for nil controls since we get this also on destruct
|
||||
if( fControls[ i ] != nil && fControls[ i ]->HasFlag( pfGUIControlMod::kInheritProcFromDlg ) )
|
||||
fControls[ i ]->ISetHandler( hdlr );
|
||||
}
|
||||
}
|
||||
|
||||
//// SetHandlerForAll ////////////////////////////////////////////////////////
|
||||
// Does SetHandler() for the dialog and all of its controls. Handy if you
|
||||
// have one of those all-encompasing dialog procs. :)
|
||||
|
||||
void pfGUIDialogMod::SetHandlerForAll( pfGUIDialogProc *hdlr )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
SetHandler( hdlr );
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
fControls[ i ]->ISetHandler( hdlr );
|
||||
}
|
||||
|
||||
//// SetControlHandler ///////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::SetControlHandler( UInt32 tagID, pfGUIDialogProc *hdlr )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ]->GetTagID() == tagID )
|
||||
{
|
||||
fControls[ i ]->SetHandler( hdlr );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// UpdateAspectRatio ///////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::UpdateAspectRatio( void )
|
||||
{
|
||||
if (fRenderMod)
|
||||
{
|
||||
// Set width fov respecting height fov
|
||||
fRenderMod->SetFovX(pfGameGUIMgr::GetInstance()->GetAspectRatio() * fRenderMod->GetFovY());
|
||||
}
|
||||
UpdateAllBounds();
|
||||
}
|
||||
|
||||
|
||||
//// UpdateAllBounds /////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::UpdateAllBounds( void )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ] != nil )
|
||||
fControls[ i ]->UpdateBounds( nil, true );
|
||||
}
|
||||
}
|
||||
|
||||
//// RefreshAllControls //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::RefreshAllControls( void )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
fControls[ i ]->IUpdate();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// ListElement Drag Functions //////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// ClearDragList ///////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::ClearDragList( void )
|
||||
{
|
||||
fDragElements.Reset();
|
||||
}
|
||||
|
||||
//// AddToDragList ///////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::AddToDragList( pfGUIListElement *e )
|
||||
{
|
||||
fDragElements.Append( e );
|
||||
}
|
||||
|
||||
//// EnterDragMode ///////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDialogMod::EnterDragMode( pfGUIControlMod *source )
|
||||
{
|
||||
if( fDragElements.GetCount() > 0 )
|
||||
{
|
||||
fDragMode = true;
|
||||
fDragReceptive = false;
|
||||
fDragTarget = nil;
|
||||
|
||||
fDragSource = source;
|
||||
}
|
||||
}
|
||||
|
||||
//// IHandleDrag /////////////////////////////////////////////////////////////
|
||||
// Oooh, we're in dragging-list-elements-around mode! So completely ignore
|
||||
// the normal way we do things; what we need to do is wait until the mouse
|
||||
// button is up, all the while testing to see if the control we're on top of
|
||||
// is capable of receiving the elements we have. Once the mouse button is let
|
||||
// up, if the control is indeed receptive, we call its drag handler for each
|
||||
// of our elements, and either way, exit drag mode.
|
||||
|
||||
void pfGUIDialogMod::IHandleDrag( hsPoint3 &mousePoint, pfGameGUIMgr::EventType event, UInt8 modifiers )
|
||||
{
|
||||
int i;
|
||||
hsScalar smallestZ;
|
||||
|
||||
|
||||
// First, see if our target control has changed
|
||||
for( i = 0, fMousedCtrl = nil, smallestZ = 1.e30f; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ]->PointInBounds( mousePoint ) && fControls[ i ]->GetBounds().GetMaxs().fZ < smallestZ )
|
||||
fMousedCtrl = fControls[ i ];
|
||||
}
|
||||
|
||||
if( fMousedCtrl != fDragTarget )
|
||||
{
|
||||
// Target has changed, update our receptive flag
|
||||
fDragTarget = fMousedCtrl;
|
||||
if( fDragTarget == nil )
|
||||
fDragReceptive = false;
|
||||
else
|
||||
{
|
||||
pfGUIDropTargetProc *dropProc = fDragTarget->GetDropTargetHdlr();
|
||||
if( dropProc == nil )
|
||||
fDragReceptive = false;
|
||||
else
|
||||
{
|
||||
fDragReceptive = true;
|
||||
for( i = 0; i < fDragElements.GetCount(); i++ )
|
||||
{
|
||||
if( !dropProc->CanEat( fDragElements[ i ], fDragSource ) )
|
||||
{
|
||||
fDragReceptive = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( event == pfGameGUIMgr::kMouseUp )
|
||||
{
|
||||
/// Mouse got let up--we're exiting drag mode, but can we process the drop?
|
||||
fDragMode = false;
|
||||
if( fDragReceptive )
|
||||
{
|
||||
pfGUIDropTargetProc *dropProc = fDragTarget->GetDropTargetHdlr();
|
||||
for( i = 0; i < fDragElements.GetCount(); i++ )
|
||||
dropProc->Eat( fDragElements[ i ], fDragSource, fDragTarget );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// GetDesiredCursor ////////////////////////////////////////////////////////
|
||||
|
||||
UInt32 pfGUIDialogMod::GetDesiredCursor( void ) const
|
||||
{
|
||||
if( fMousedCtrl != nil )
|
||||
return fMousedCtrl->IGetDesiredCursor();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,198 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDialogMod Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIDialogMod_h
|
||||
#define _pfGUIDialogMod_h
|
||||
|
||||
|
||||
#include "../pnModifier/plSingleModifier.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "hsMatrix44.h"
|
||||
|
||||
class plMessage;
|
||||
class plPostEffectMod;
|
||||
class pfGUIControlMod;
|
||||
class pfGUIDialogProc;
|
||||
class pfGUIListElement;
|
||||
class pfGUIColorScheme;
|
||||
|
||||
class pfGUIDialogMod : public plSingleModifier
|
||||
{
|
||||
private:
|
||||
pfGUIDialogMod *fNext, **fPrevPtr;
|
||||
|
||||
protected:
|
||||
|
||||
UInt32 fTagID; // 0 if none
|
||||
|
||||
UInt32 fVersion; // Nice for syncing to C++ code
|
||||
|
||||
plPostEffectMod *fRenderMod;
|
||||
hsBool fEnabled;
|
||||
char fName[ 128 ];
|
||||
hsTArray<pfGUIControlMod *> fControls;
|
||||
pfGUIControlMod *fControlOfInterest;
|
||||
pfGUIControlMod *fFocusCtrl;
|
||||
pfGUIControlMod *fMousedCtrl; // Which one is the mouse over?
|
||||
pfGUIColorScheme *fColorScheme;
|
||||
|
||||
pfGUIDialogProc *fHandler;
|
||||
plKey fProcReceiver; // Non-nil means we handle everything by creating notify messages and sending them to this key
|
||||
|
||||
hsTArray<pfGUIListElement *> fDragElements;
|
||||
hsBool fDragMode, fDragReceptive;
|
||||
pfGUIControlMod *fDragTarget;
|
||||
pfGUIControlMod *fDragSource;
|
||||
|
||||
plKey fSceneNodeKey;
|
||||
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
void IHandleDrag( hsPoint3 &mousePt, pfGameGUIMgr::EventType event, UInt8 modifiers );
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kRenderModRef = 0,
|
||||
kControlRef,
|
||||
kRefDerviedStart
|
||||
};
|
||||
|
||||
enum Flags
|
||||
{
|
||||
kModal,
|
||||
kDerivedFlagsStart
|
||||
};
|
||||
|
||||
pfGUIDialogMod();
|
||||
virtual ~pfGUIDialogMod();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIDialogMod );
|
||||
GETINTERFACE_ANY( pfGUIDialogMod, plSingleModifier );
|
||||
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
void SetSceneNodeKey( plKey &key ) { fSceneNodeKey = key; }
|
||||
plKey GetSceneNodeKey( void );
|
||||
|
||||
virtual void SetEnabled( hsBool e );
|
||||
hsBool IsEnabled( void ) { return fEnabled; }
|
||||
|
||||
const char *GetName( void ) { return fName; }
|
||||
|
||||
void ScreenToWorldPoint( hsScalar x, hsScalar y, hsScalar z, hsPoint3 &outPt );
|
||||
hsPoint3 WorldToScreenPoint( const hsPoint3 &inPt );
|
||||
|
||||
virtual hsBool HandleMouseEvent( pfGameGUIMgr::EventType event, hsScalar mouseX, hsScalar mouseY, UInt8 modifiers );
|
||||
hsBool HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers );
|
||||
hsBool HandleKeyPress( char key, UInt8 modifiers );
|
||||
void UpdateInterestingThings( hsScalar mouseX, hsScalar mouseY, UInt8 modifiers, hsBool modalPreset );
|
||||
|
||||
void SetControlOfInterest( pfGUIControlMod *c );
|
||||
pfGUIControlMod *GetControlOfInterest( void ) const { return fControlOfInterest; }
|
||||
UInt32 GetDesiredCursor( void ) const;
|
||||
|
||||
void UpdateAspectRatio( void );
|
||||
void UpdateAllBounds( void );
|
||||
void RefreshAllControls( void );
|
||||
|
||||
void AddControl( pfGUIControlMod *ctrl );
|
||||
UInt32 GetNumControls( void ) { return fControls.GetCount(); }
|
||||
pfGUIControlMod *GetControl( UInt32 idx ) { return fControls[ idx ]; }
|
||||
|
||||
pfGUIColorScheme *GetColorScheme( void ) const { return fColorScheme; }
|
||||
|
||||
void LinkToList( pfGUIDialogMod **prevPtr )
|
||||
{
|
||||
fNext = *prevPtr;
|
||||
if( *prevPtr )
|
||||
(*prevPtr)->fPrevPtr = &fNext;
|
||||
fPrevPtr = prevPtr;
|
||||
*prevPtr = this;
|
||||
}
|
||||
|
||||
void Unlink( void )
|
||||
{
|
||||
if( fNext )
|
||||
fNext->fPrevPtr = fPrevPtr;
|
||||
*fPrevPtr = fNext;
|
||||
|
||||
fPrevPtr = nil;
|
||||
fNext = nil;
|
||||
}
|
||||
|
||||
void SetFocus( pfGUIControlMod *ctrl );
|
||||
void Show( void );
|
||||
void ShowNoReset( void );
|
||||
void Hide( void );
|
||||
hsBool IsVisible( void ) { return IsEnabled(); }
|
||||
|
||||
pfGUIControlMod *GetFocus( void ) { return fFocusCtrl; }
|
||||
|
||||
pfGUIDialogMod *GetNext( void ) { return fNext; }
|
||||
UInt32 GetTagID( void ) { return fTagID; }
|
||||
pfGUIControlMod *GetControlFromTag( UInt32 tagID );
|
||||
|
||||
void SetHandler( pfGUIDialogProc *hdlr );
|
||||
pfGUIDialogProc *GetHandler( void ) const { return fHandler; }
|
||||
|
||||
plPostEffectMod *GetRenderMod( void ) const { return fRenderMod; }
|
||||
|
||||
// This sets the handler for the dialog and ALL of its controls
|
||||
void SetHandlerForAll( pfGUIDialogProc *hdlr );
|
||||
|
||||
// Just a little macro-type thing here
|
||||
void SetControlHandler( UInt32 tagID, pfGUIDialogProc *hdlr );
|
||||
|
||||
/// Methods for doing drag & drop of listElements
|
||||
|
||||
void ClearDragList( void );
|
||||
void AddToDragList( pfGUIListElement *e );
|
||||
void EnterDragMode( pfGUIControlMod *source );
|
||||
|
||||
UInt32 GetVersion( void ) const { return fVersion; }
|
||||
|
||||
// Export only
|
||||
void SetRenderMod( plPostEffectMod *mod ) { fRenderMod = mod; }
|
||||
void SetName( const char *name ) { hsStrncpy( fName, name, sizeof( fName ) - 1 ); }
|
||||
void AddControlOnExport( pfGUIControlMod *ctrl );
|
||||
void SetTagID( UInt32 id ) { fTagID = id; }
|
||||
void SetProcReceiver( plKey key ) { fProcReceiver = key; }
|
||||
void SetVersion( UInt32 version ) { fVersion = version; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIDialogMod_h
|
@ -0,0 +1,131 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDialogNotifyProc //
|
||||
// //
|
||||
// Helper dialog proc that takes all control events and turns them into //
|
||||
// notify messages that get sent out. //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#include "pfGUIDialogNotifyProc.h"
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "pfGUIDialogHandlers.h"
|
||||
#include "pfGUIListElement.h"
|
||||
#include "pfGUIButtonMod.h" // Next three are for notify stuff
|
||||
#include "pfGUIListBoxMod.h"
|
||||
#include "pfGUIEditBoxMod.h"
|
||||
|
||||
#include "../pfMessage/pfGUINotifyMsg.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
pfGUIDialogNotifyProc::pfGUIDialogNotifyProc( plKey &r )
|
||||
{
|
||||
fReceiver = r;
|
||||
}
|
||||
|
||||
|
||||
void pfGUIDialogNotifyProc::ISendNotify( plKey ctrlKey, UInt32 event )
|
||||
{
|
||||
pfGUINotifyMsg *notify = TRACKED_NEW pfGUINotifyMsg( fDialog->GetKey(), fReceiver, nil );
|
||||
notify->SetEvent( ctrlKey, event );
|
||||
plgDispatch::MsgSend( notify );
|
||||
}
|
||||
|
||||
|
||||
void pfGUIDialogNotifyProc::DoSomething( pfGUIControlMod *ctrl )
|
||||
{
|
||||
if( pfGUIButtonMod::ConvertNoRef( ctrl ) != nil ||
|
||||
pfGUIListBoxMod::ConvertNoRef( ctrl ) != nil ||
|
||||
pfGUIEditBoxMod::ConvertNoRef( ctrl ) != nil )
|
||||
{
|
||||
// only fire the button if it is triggering
|
||||
// ... all other types just fire
|
||||
pfGUIButtonMod* btn = pfGUIButtonMod::ConvertNoRef( ctrl );
|
||||
if ( !btn || btn->IsTriggering() )
|
||||
ISendNotify( ctrl->GetKey(), pfGUINotifyMsg::kAction );
|
||||
}
|
||||
else
|
||||
ISendNotify( ctrl->GetKey(), pfGUINotifyMsg::kValueChanged );
|
||||
}
|
||||
|
||||
void pfGUIDialogNotifyProc::OnInit( void )
|
||||
{
|
||||
if ( fDialog )
|
||||
ISendNotify( fDialog->GetKey(), pfGUINotifyMsg::kDialogLoaded );
|
||||
else
|
||||
ISendNotify( nil, pfGUINotifyMsg::kDialogLoaded );
|
||||
}
|
||||
|
||||
void pfGUIDialogNotifyProc::OnShow( void )
|
||||
{
|
||||
if ( fDialog )
|
||||
ISendNotify( fDialog->GetKey(), pfGUINotifyMsg::kShowHide );
|
||||
else
|
||||
ISendNotify( nil, pfGUINotifyMsg::kShowHide );
|
||||
}
|
||||
|
||||
void pfGUIDialogNotifyProc::OnHide( void )
|
||||
{
|
||||
if ( fDialog )
|
||||
ISendNotify( fDialog->GetKey(), pfGUINotifyMsg::kShowHide );
|
||||
else
|
||||
ISendNotify( nil, pfGUINotifyMsg::kShowHide );
|
||||
}
|
||||
|
||||
void pfGUIDialogNotifyProc::OnDestroy( void )
|
||||
{
|
||||
}
|
||||
|
||||
void pfGUIDialogNotifyProc::OnControlEvent( ControlEvt event )
|
||||
{
|
||||
if( event == kExitMode )
|
||||
ISendNotify( ( fDialog != nil ) ? fDialog->GetKey() : nil, pfGUINotifyMsg::kExitMode );
|
||||
}
|
||||
|
||||
// Called when the dialog's focused control changes
|
||||
void pfGUIDialogNotifyProc::OnCtrlFocusChange( pfGUIControlMod *oldCtrl, pfGUIControlMod *newCtrl )
|
||||
{
|
||||
if ( newCtrl )
|
||||
ISendNotify( newCtrl->GetKey(), pfGUINotifyMsg::kFocusChange);
|
||||
else
|
||||
ISendNotify( nil, pfGUINotifyMsg::kFocusChange);
|
||||
|
||||
}
|
||||
|
||||
void pfGUIDialogNotifyProc::OnInterestingEvent( pfGUIControlMod *ctrl )
|
||||
{
|
||||
ISendNotify( ( ctrl != nil ) ? ctrl->GetKey() : nil, pfGUINotifyMsg::kInterestingEvent );
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDialogNotifyProc Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIDialogNotifyProc_h
|
||||
#define _pfGUIDialogNotifyProc_h
|
||||
|
||||
#include "pfGUIDialogHandlers.h"
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
|
||||
class plGUIControlMod;
|
||||
|
||||
//// pfGUIDialogNotifyProc Definition ////////////////////////////////////////
|
||||
// Helper dialog proc that takes all control events and turns them into
|
||||
// notify messages that get sent out.
|
||||
|
||||
class pfGUIDialogNotifyProc : public pfGUIDialogProc
|
||||
{
|
||||
protected:
|
||||
|
||||
plKey fReceiver;
|
||||
|
||||
void ISendNotify( plKey ctrlKey, UInt32 event );
|
||||
|
||||
public:
|
||||
|
||||
pfGUIDialogNotifyProc( plKey &r );
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl );
|
||||
virtual void OnInit( void );
|
||||
virtual void OnShow( void );
|
||||
virtual void OnHide( void );
|
||||
virtual void OnDestroy( void );
|
||||
virtual void OnCtrlFocusChange( pfGUIControlMod *oldCtrl, pfGUIControlMod *newCtrl );
|
||||
virtual void OnControlEvent( ControlEvt event );
|
||||
virtual void OnInterestingEvent( pfGUIControlMod *ctrl );
|
||||
};
|
||||
|
||||
#endif // _pfGUIDialogNotifyProc_h
|
@ -0,0 +1,149 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDragBarCtrl Definition //
|
||||
// //
|
||||
// DragBars are draggable controls that take their dialogs along with //
|
||||
// them. Because they're essentially part of the dialog directly (the part //
|
||||
// that can be dragged), they're processed after the normal hit testing. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIDragBarCtrl.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plAvatar/plAGModifier.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIDragBarCtrl::pfGUIDragBarCtrl()
|
||||
{
|
||||
SetFlag( kWantsInterest );
|
||||
fDragging = false;
|
||||
fAnchored = false;
|
||||
}
|
||||
|
||||
pfGUIDragBarCtrl::~pfGUIDragBarCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDragBarCtrl::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDragBarCtrl::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDragBarCtrl::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
}
|
||||
|
||||
void pfGUIDragBarCtrl::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
}
|
||||
|
||||
//// UpdateBounds ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDragBarCtrl::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
|
||||
{
|
||||
pfGUIControlMod::UpdateBounds( invXformMatrix, force );
|
||||
fBoundsValid = false;
|
||||
}
|
||||
|
||||
//// HandleMouseDown/Up //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDragBarCtrl::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
// if we are anchored <to the floor> then don't let it be moved
|
||||
if ( fAnchored )
|
||||
return;
|
||||
|
||||
fDragging = true;
|
||||
fDragOffset = fScreenCenter - mousePt;
|
||||
|
||||
SetObjectCenter( mousePt.fX + fDragOffset.fX, mousePt.fY + fDragOffset.fY );
|
||||
|
||||
// We know that the entire dialog is going to move, so we better make
|
||||
// sure to update the bounds on all the controls
|
||||
fDialog->UpdateAllBounds();
|
||||
}
|
||||
|
||||
void pfGUIDragBarCtrl::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
// if we are anchored <to the floor> then don't let it be moved
|
||||
if ( fAnchored )
|
||||
return;
|
||||
|
||||
fDragging = false;
|
||||
SetObjectCenter( mousePt.fX + fDragOffset.fX, mousePt.fY + fDragOffset.fY );
|
||||
fDialog->UpdateAllBounds();
|
||||
}
|
||||
|
||||
void pfGUIDragBarCtrl::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
// if we are anchored <to the floor> then don't let it be moved
|
||||
if ( fAnchored )
|
||||
return;
|
||||
|
||||
SetObjectCenter( mousePt.fX + fDragOffset.fX, mousePt.fY + fDragOffset.fY );
|
||||
fDialog->UpdateAllBounds();
|
||||
}
|
||||
|
||||
//// IGetDesiredCursor ///////////////////////////////////////////////////////
|
||||
|
||||
UInt32 pfGUIDragBarCtrl::IGetDesiredCursor( void ) const
|
||||
{
|
||||
// if we are anchored, then no cursors that say we can move
|
||||
if ( fAnchored )
|
||||
return 0;
|
||||
|
||||
if( fDragging )
|
||||
return plInputInterface::kCursor4WayDragging;
|
||||
|
||||
return plInputInterface::kCursor4WayDraggable;
|
||||
}
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDragBarCtrl Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIDragBarCtrl_h
|
||||
#define _pfGUIDragBarCtrl_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
class plMessage;
|
||||
|
||||
class pfGUIDragBarCtrl : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
hsPoint3 fDragOffset;
|
||||
hsBool fDragging;
|
||||
hsBool fAnchored;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual UInt32 IGetDesiredCursor( void ) const; // As specified in plInputInterface.h
|
||||
|
||||
public:
|
||||
|
||||
pfGUIDragBarCtrl();
|
||||
virtual ~pfGUIDragBarCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIDragBarCtrl );
|
||||
GETINTERFACE_ANY( pfGUIDragBarCtrl, pfGUIControlMod );
|
||||
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual void SetAnchored( hsBool anchored ) { fAnchored = anchored; }
|
||||
virtual hsBool IsAnchored(void) { return fAnchored; }
|
||||
|
||||
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
|
||||
|
||||
// Export only
|
||||
};
|
||||
|
||||
#endif // _pfGUIDragBarCtrl_h
|
@ -0,0 +1,165 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDraggableMod Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIDraggableMod.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plAvatar/plAGModifier.h"
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIDraggableMod::pfGUIDraggableMod()
|
||||
{
|
||||
SetFlag( kWantsInterest );
|
||||
fDragging = false;
|
||||
}
|
||||
|
||||
pfGUIDraggableMod::~pfGUIDraggableMod()
|
||||
{
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDraggableMod::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDraggableMod::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDraggableMod::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
}
|
||||
|
||||
void pfGUIDraggableMod::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
}
|
||||
|
||||
//// UpdateBounds ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDraggableMod::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
|
||||
{
|
||||
pfGUIControlMod::UpdateBounds( invXformMatrix, force );
|
||||
fBoundsValid = false;
|
||||
}
|
||||
|
||||
//// HandleMouseDown/Up //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDraggableMod::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
if( !fDragging )
|
||||
{
|
||||
fLastMousePt = mousePt;
|
||||
fOrigCenter = fScreenCenter;
|
||||
|
||||
fDragging = true;
|
||||
fDragOffset = fScreenCenter - mousePt;
|
||||
|
||||
SetObjectCenter( mousePt.fX + fDragOffset.fX, mousePt.fY + fDragOffset.fY );
|
||||
|
||||
HandleExtendedEvent( kStartingDrag );
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIDraggableMod::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
if( fDragging )
|
||||
{
|
||||
fLastMousePt = mousePt;
|
||||
fDragging = false;
|
||||
SetObjectCenter( mousePt.fX + fDragOffset.fX, mousePt.fY + fDragOffset.fY );
|
||||
|
||||
DoSomething();
|
||||
|
||||
if( HasFlag( kAlwaysSnapBackToStart ) )
|
||||
SetObjectCenter( fOrigCenter.fX, fOrigCenter.fY );
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIDraggableMod::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
if( fDragging )
|
||||
{
|
||||
fLastMousePt = mousePt;
|
||||
|
||||
SetObjectCenter( mousePt.fX + fDragOffset.fX, mousePt.fY + fDragOffset.fY );
|
||||
|
||||
if( HasFlag( kReportDragging ) )
|
||||
HandleExtendedEvent( kDragging );
|
||||
}
|
||||
}
|
||||
|
||||
//// IGetDesiredCursor ///////////////////////////////////////////////////////
|
||||
|
||||
UInt32 pfGUIDraggableMod::IGetDesiredCursor( void ) const
|
||||
{
|
||||
// if we are anchored, then no cursors that say we can move
|
||||
if( fDragging )
|
||||
{
|
||||
if( HasFlag( kHideCursorWhileDragging ) )
|
||||
return plInputInterface::kCursorHidden;
|
||||
|
||||
return plInputInterface::kCursor4WayDragging;
|
||||
}
|
||||
|
||||
return plInputInterface::kCursor4WayDraggable;
|
||||
}
|
||||
|
||||
void pfGUIDraggableMod::StopDragging( hsBool cancel )
|
||||
{
|
||||
if( fDragging )
|
||||
{
|
||||
fDragging = false;
|
||||
if( cancel )
|
||||
HandleExtendedEvent( kCancelled );
|
||||
|
||||
if( HasFlag( kAlwaysSnapBackToStart ) )
|
||||
SetObjectCenter( fOrigCenter.fX, fOrigCenter.fY );
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDraggableMod Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIDraggableMod_h
|
||||
#define _pfGUIDraggableMod_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
class plMessage;
|
||||
|
||||
class pfGUIDraggableMod : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
hsPoint3 fDragOffset, fLastMousePt;
|
||||
hsPoint3 fOrigCenter;
|
||||
hsBool fDragging;
|
||||
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual UInt32 IGetDesiredCursor( void ) const; // As specified in plInputInterface.h
|
||||
|
||||
public:
|
||||
|
||||
pfGUIDraggableMod();
|
||||
virtual ~pfGUIDraggableMod();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIDraggableMod );
|
||||
GETINTERFACE_ANY( pfGUIDraggableMod, pfGUIControlMod );
|
||||
|
||||
enum OurFlags
|
||||
{
|
||||
kReportDragging = kDerivedFlagsStart,
|
||||
kHideCursorWhileDragging,
|
||||
kAlwaysSnapBackToStart
|
||||
};
|
||||
|
||||
// Extended event types (endDrag is the default event)
|
||||
enum ExtendedEvents
|
||||
{
|
||||
kDragging,
|
||||
kCancelled,
|
||||
kStartingDrag
|
||||
};
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
|
||||
|
||||
void StopDragging( hsBool cancel );
|
||||
const hsPoint3 &GetLastMousePt( void ) const { return fLastMousePt; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIDraggableMod_h
|
@ -0,0 +1,169 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDynDisplayCtrl Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIDynDisplayCtrl.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../plGImage/plDynamicTextMap.h"
|
||||
#include "../plSurface/plLayerInterface.h"
|
||||
#include "../plSurface/hsGMaterial.h"
|
||||
#include "../plPipeline/plTextGenerator.h"
|
||||
#include "plPipeline.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIDynDisplayCtrl::pfGUIDynDisplayCtrl()
|
||||
{
|
||||
SetFlag( kIntangible );
|
||||
}
|
||||
|
||||
pfGUIDynDisplayCtrl::~pfGUIDynDisplayCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDynDisplayCtrl::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIDynDisplayCtrl::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg );
|
||||
if( refMsg != nil )
|
||||
{
|
||||
if( refMsg->fType == kRefTextMap )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fTextMaps[ refMsg->fWhich ] = plDynamicTextMap::ConvertNoRef( refMsg->GetRef() );
|
||||
else
|
||||
fTextMaps[ refMsg->fWhich ] = nil;
|
||||
return true;
|
||||
}
|
||||
else if( refMsg->fType == kRefLayer )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fLayers[ refMsg->fWhich ] = plLayerInterface::ConvertNoRef( refMsg->GetRef() );
|
||||
else
|
||||
fLayers[ refMsg->fWhich ] = nil;
|
||||
return true;
|
||||
}
|
||||
else if( refMsg->fType == kRefMaterial )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fMaterials[ refMsg->fWhich ] = hsGMaterial::ConvertNoRef( refMsg->GetRef() );
|
||||
else
|
||||
fMaterials[ refMsg->fWhich ] = nil;
|
||||
}
|
||||
}
|
||||
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIDynDisplayCtrl::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
UInt32 count, i;
|
||||
|
||||
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
|
||||
count = s->ReadSwap32();
|
||||
fTextMaps.SetCountAndZero( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, i, kRefTextMap ), plRefFlags::kActiveRef );
|
||||
|
||||
count = s->ReadSwap32();
|
||||
fLayers.SetCountAndZero( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, i, kRefLayer ), plRefFlags::kActiveRef );
|
||||
|
||||
count = s->ReadSwap32();
|
||||
fMaterials.SetCountAndZero( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, i, kRefMaterial ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
void pfGUIDynDisplayCtrl::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
|
||||
s->WriteSwap32( fTextMaps.GetCount() );
|
||||
for( i = 0; i < fTextMaps.GetCount(); i++ )
|
||||
mgr->WriteKey( s, fTextMaps[ i ]->GetKey() );
|
||||
|
||||
s->WriteSwap32( fLayers.GetCount() );
|
||||
for( i = 0; i < fLayers.GetCount(); i++ )
|
||||
mgr->WriteKey( s, fLayers[ i ]->GetKey() );
|
||||
|
||||
s->WriteSwap32( fMaterials.GetCount() );
|
||||
for( i = 0; i < fMaterials.GetCount(); i++ )
|
||||
mgr->WriteKey( s, fMaterials[ i ]->GetKey() );
|
||||
}
|
||||
|
||||
//// AddMap //////////////////////////////////////////////////////////////////
|
||||
// Export only
|
||||
|
||||
void pfGUIDynDisplayCtrl::AddMap( plDynamicTextMap *map )
|
||||
{
|
||||
fTextMaps.Append( map );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( map->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, fTextMaps.GetCount() - 1, kRefTextMap ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
//// AddLayer ////////////////////////////////////////////////////////////////
|
||||
// Export only
|
||||
|
||||
void pfGUIDynDisplayCtrl::AddLayer( plLayerInterface *layer )
|
||||
{
|
||||
fLayers.Append( layer );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( layer->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, fLayers.GetCount() - 1, kRefLayer ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
//// AddMaterial /////////////////////////////////////////////////////////////
|
||||
// Export only
|
||||
|
||||
void pfGUIDynDisplayCtrl::AddMaterial( hsGMaterial *material )
|
||||
{
|
||||
fMaterials.Append( material );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( material->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, fMaterials.GetCount() - 1, kRefMaterial ), plRefFlags::kActiveRef );
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIDynDisplayCtrl Header //
|
||||
// //
|
||||
// Fun little helper control that just stores a pointer to a single //
|
||||
// plDynamicTextMap, chosen in MAX. Note that we could also just search //
|
||||
// for the right key name, but that requires a StupidSearch(tm), while //
|
||||
// this way just requires an extra dummy control that automatically reads //
|
||||
// in the right ref (and searching for controls by TagID is a lot faster //
|
||||
// than searching for keys). //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIDynDisplayCtrl_h
|
||||
#define _pfGUIDynDisplayCtrl_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "hsTemplates.h"
|
||||
|
||||
class plMessage;
|
||||
class plDynamicTextMap;
|
||||
class plLayerInterface;
|
||||
class hsGMaterial;
|
||||
|
||||
class pfGUIDynDisplayCtrl : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kRefTextMap = kRefDerivedStart,
|
||||
kRefLayer,
|
||||
kRefMaterial
|
||||
};
|
||||
|
||||
hsTArray<plDynamicTextMap *> fTextMaps;
|
||||
hsTArray<plLayerInterface *> fLayers;
|
||||
|
||||
hsTArray<hsGMaterial *> fMaterials;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
public:
|
||||
|
||||
pfGUIDynDisplayCtrl();
|
||||
virtual ~pfGUIDynDisplayCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIDynDisplayCtrl );
|
||||
GETINTERFACE_ANY( pfGUIDynDisplayCtrl, pfGUIControlMod );
|
||||
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
UInt32 GetNumMaps( void ) const { return fTextMaps.GetCount(); }
|
||||
plDynamicTextMap *GetMap( UInt32 i ) const { return fTextMaps[ i ]; }
|
||||
|
||||
UInt32 GetNumLayers( void ) const { return fLayers.GetCount(); }
|
||||
plLayerInterface *GetLayer( UInt32 i ) const { return fLayers[ i ]; }
|
||||
|
||||
UInt32 GetNumMaterials( void ) const { return fMaterials.GetCount(); }
|
||||
hsGMaterial *GetMaterial( UInt32 i ) const { return fMaterials[ i ]; }
|
||||
|
||||
// Export only
|
||||
void AddMap( plDynamicTextMap *map );
|
||||
void AddLayer( plLayerInterface *layer );
|
||||
void AddMaterial( hsGMaterial *material );
|
||||
};
|
||||
|
||||
#endif // _pfGUIDynDisplayCtrl_h
|
@ -0,0 +1,650 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIEditBoxMod Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef PLASMA_EXTERNAL_RELEASE
|
||||
//#define LIMIT_VOICE_CHAT 1
|
||||
#endif
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIEditBoxMod.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plAvatar/plAGModifier.h"
|
||||
#include "../plGImage/plDynamicTextMap.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "../pnInputCore/plKeyMap.h"
|
||||
|
||||
#include <locale>
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIEditBoxMod::pfGUIEditBoxMod()
|
||||
{
|
||||
SetFlag( kWantsInterest );
|
||||
SetFlag( kTakesSpecialKeys );
|
||||
fIgnoreNextKey = false;
|
||||
fEscapedFlag = false;
|
||||
fFirstHalfExitKeyPushed = false;
|
||||
fSpecialCaptureKeyEventMode = false;
|
||||
fBuffer = 0;
|
||||
fLastDeadKey = 0;
|
||||
SetBufferSize( 128 );
|
||||
|
||||
SetupDeadKeyConverter();
|
||||
}
|
||||
|
||||
pfGUIEditBoxMod::~pfGUIEditBoxMod()
|
||||
{
|
||||
delete [] fBuffer;
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::SetupDeadKeyConverter()
|
||||
{
|
||||
int i,j;
|
||||
for (i=0; i<255; i++)
|
||||
for (j=0; j<255; j++)
|
||||
fDeadKeyConverter[i][j] = 0L;
|
||||
|
||||
// we are adding 100 to the indexes because some of these chars have a negative index for some reason
|
||||
fDeadKeyConverter['^'+100]['a'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['e'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['i'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['o'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['u'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['A'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['E'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['I'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['O'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['^'+100]['U'] = L'<EFBFBD>';
|
||||
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['a'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['e'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['i'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['o'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['u'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['A'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['E'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['I'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['O'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['U'] = L'<EFBFBD>';
|
||||
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['a'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['e'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['i'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['o'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['u'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['y'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['A'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['E'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['I'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['O'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['U'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['<EFBFBD>'+100]['Y'] = L'<EFBFBD>';
|
||||
|
||||
fDeadKeyConverter['`'+100]['a'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['e'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['i'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['o'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['u'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['A'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['E'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['I'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['O'] = L'<EFBFBD>';
|
||||
fDeadKeyConverter['`'+100]['U'] = L'<EFBFBD>';
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIEditBoxMod::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIEditBoxMod::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// IPostSetUpDynTextMap ////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIEditBoxMod::IPostSetUpDynTextMap( void )
|
||||
{
|
||||
pfGUIColorScheme *scheme = GetColorScheme();
|
||||
fDynTextMap->SetFont( scheme->fFontFace, scheme->fFontSize, scheme->fFontFlags,
|
||||
HasFlag( kXparentBgnd ) ? false : true );
|
||||
}
|
||||
|
||||
//// IUpdate /////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIEditBoxMod::IUpdate( void )
|
||||
{
|
||||
hsColorRGBA c;
|
||||
|
||||
|
||||
if( fDynTextMap == nil || !fDynTextMap->IsValid() )
|
||||
return;
|
||||
|
||||
c.Set( 0.f, 0.f, 0.f, 1.f );
|
||||
if ( fFocused && fSpecialCaptureKeyEventMode )
|
||||
fDynTextMap->ClearToColor( GetColorScheme()->fSelBackColor );
|
||||
else
|
||||
fDynTextMap->ClearToColor( GetColorScheme()->fBackColor );
|
||||
|
||||
if( fBuffer != nil )
|
||||
{
|
||||
// First, calc the cursor position, so we can adjust the scrollPos as necessary
|
||||
Int16 cursorPos, oldCursorPos;
|
||||
if( fFocused && !fSpecialCaptureKeyEventMode )
|
||||
{
|
||||
// Really cheap hack here to figure out where to draw the cursor
|
||||
wchar_t backup = fBuffer[ fCursorPos ];
|
||||
fBuffer[ fCursorPos ] = 0;
|
||||
cursorPos = fDynTextMap->CalcStringWidth( fBuffer );
|
||||
fBuffer[ fCursorPos ] = backup;
|
||||
|
||||
oldCursorPos = cursorPos;
|
||||
cursorPos -= (Int16)fScrollPos;
|
||||
|
||||
if( 4 + cursorPos > fDynTextMap->GetVisibleWidth() - 18 )
|
||||
{
|
||||
fScrollPos += ( 4 + cursorPos ) - ( fDynTextMap->GetVisibleWidth() - 18 );
|
||||
}
|
||||
else if( 4 + cursorPos < 4 )
|
||||
{
|
||||
fScrollPos -= 4 - ( 4 + cursorPos );
|
||||
if( fScrollPos < 0 )
|
||||
fScrollPos = 0;
|
||||
}
|
||||
|
||||
cursorPos = (Int16)(oldCursorPos - fScrollPos);
|
||||
}
|
||||
|
||||
if ( fFocused && fSpecialCaptureKeyEventMode )
|
||||
// if special and has focus then use select
|
||||
fDynTextMap->SetTextColor( GetColorScheme()->fSelForeColor, GetColorScheme()->fTransparent &&
|
||||
GetColorScheme()->fSelBackColor.a == 0.f );
|
||||
else
|
||||
fDynTextMap->SetTextColor( GetColorScheme()->fForeColor, GetColorScheme()->fTransparent &&
|
||||
GetColorScheme()->fBackColor.a == 0.f );
|
||||
fDynTextMap->DrawClippedString( (Int16)(4 - fScrollPos), 4, fBuffer,
|
||||
4, 4, fDynTextMap->GetVisibleWidth() - 8, fDynTextMap->GetVisibleHeight() - 8 );
|
||||
|
||||
if( fFocused && !fSpecialCaptureKeyEventMode )
|
||||
{
|
||||
fDynTextMap->FrameRect( 4 + cursorPos, 4, 2, fDynTextMap->GetVisibleHeight() - 8, GetColorScheme()->fSelForeColor );
|
||||
}
|
||||
}
|
||||
fDynTextMap->FlushToHost();
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::PurgeDynaTextMapImage()
|
||||
{
|
||||
if ( fDynTextMap != nil )
|
||||
fDynTextMap->PurgeImage();
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIEditBoxMod::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
}
|
||||
|
||||
//// HandleMouseDown /////////////////////////////////////////////////////////
|
||||
// What we do: normal click deselects all and selects the item clicked on
|
||||
// (if any). Shift-click and ctrl-click avoids the deselect and toggles
|
||||
// the item clicked on.
|
||||
|
||||
void pfGUIEditBoxMod::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
wchar_t backup;
|
||||
UInt16 width;
|
||||
|
||||
|
||||
if( fBuffer != nil && fDynTextMap != nil )
|
||||
{
|
||||
if( !fBounds.IsInside( &mousePt ) )
|
||||
return;
|
||||
|
||||
IScreenToLocalPt( mousePt );
|
||||
|
||||
mousePt.fX *= fDynTextMap->GetVisibleWidth();
|
||||
mousePt.fX += fScrollPos - 4;
|
||||
for( fCursorPos = 0; fCursorPos < wcslen( fBuffer ); fCursorPos++ )
|
||||
{
|
||||
backup = fBuffer[ fCursorPos + 1 ];
|
||||
fBuffer[ fCursorPos + 1 ] = 0;
|
||||
width = fDynTextMap->CalcStringWidth( fBuffer );
|
||||
fBuffer[ fCursorPos + 1 ] = backup;
|
||||
|
||||
if( width > mousePt.fX )
|
||||
break;
|
||||
}
|
||||
|
||||
IUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
//// HandleMouseUp ///////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIEditBoxMod::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
}
|
||||
|
||||
//// HandleMouseDrag /////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIEditBoxMod::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
}
|
||||
|
||||
hsBool pfGUIEditBoxMod::HandleKeyPress( char inKey, UInt8 modifiers )
|
||||
{
|
||||
wchar_t key = (wchar_t)inKey;
|
||||
|
||||
if( fBuffer == nil )
|
||||
return false;
|
||||
|
||||
if( fIgnoreNextKey )
|
||||
{
|
||||
// So we don't process keys that already got handled by HandleKeyEvent()
|
||||
fIgnoreNextKey = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plKeyboardDevice::KeyIsDeadKey())
|
||||
{
|
||||
if (fLastDeadKey != 0)
|
||||
{
|
||||
wchar_t temp = key; // we have two dead keys in a row, print out the old one and store the new one
|
||||
key = fLastDeadKey;
|
||||
fLastDeadKey = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
fLastDeadKey = key; // store the dead key and don't print it until we get the next char
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int i = wcslen( fBuffer );
|
||||
if (fLastDeadKey != 0) // we have a dead key that needs to be added in
|
||||
{
|
||||
wchar_t translatedKey = fDeadKeyConverter[(char)fLastDeadKey+100][(char)key];
|
||||
if (translatedKey == 0) // no translation possible?
|
||||
{
|
||||
// so we need to print the dead key, followed by the typed key
|
||||
// unless key is a space, then we just type the dead key
|
||||
if (key == L' ')
|
||||
{
|
||||
if (i<fBufferSize - 1)
|
||||
{
|
||||
memmove(fBuffer+fCursorPos+1, fBuffer+fCursorPos, (i - fCursorPos + 1) * sizeof(wchar_t));
|
||||
fBuffer[fCursorPos] = fLastDeadKey;
|
||||
fCursorPos++;
|
||||
HandleExtendedEvent(kValueChanging);
|
||||
}
|
||||
fLastDeadKey = 0L;
|
||||
IUpdate();
|
||||
return true;
|
||||
}
|
||||
// print two chars now
|
||||
if (i<fBufferSize - 2 && key != 0L)
|
||||
{
|
||||
memmove(fBuffer+fCursorPos+2, fBuffer+fCursorPos, (i - fCursorPos + 2) * sizeof(wchar_t));
|
||||
fBuffer[fCursorPos] = fLastDeadKey;
|
||||
fCursorPos++;
|
||||
fBuffer[fCursorPos] = key;
|
||||
fCursorPos++;
|
||||
|
||||
HandleExtendedEvent( kValueChanging );
|
||||
}
|
||||
fLastDeadKey = 0L;
|
||||
IUpdate();
|
||||
return true;
|
||||
}
|
||||
// ok, so we have a translated key now, so assign it to our key and print it normally
|
||||
key = translatedKey;
|
||||
fLastDeadKey = 0;
|
||||
}
|
||||
|
||||
// Insert character at the current cursor position, then inc the cursor by one
|
||||
if( i < fBufferSize - 1 && key != 0 )
|
||||
{
|
||||
memmove( fBuffer + fCursorPos + 1, fBuffer + fCursorPos, (i - fCursorPos + 1) * sizeof(wchar_t) );
|
||||
fBuffer[ fCursorPos ] = key;
|
||||
fCursorPos++;
|
||||
|
||||
HandleExtendedEvent( kValueChanging );
|
||||
}
|
||||
IUpdate();
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool pfGUIEditBoxMod::HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers )
|
||||
{
|
||||
if ( fSpecialCaptureKeyEventMode)
|
||||
{
|
||||
// handle doing special caputre mode
|
||||
if ( event == pfGameGUIMgr::kKeyDown )
|
||||
{
|
||||
#ifdef LIMIT_VOICE_CHAT
|
||||
// don't allow them to map the TAB key to anything! 'cause we'll use it later
|
||||
if ( key == KEY_TAB)
|
||||
{
|
||||
fIgnoreNextKey = true;
|
||||
fFirstHalfExitKeyPushed = false;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
// capture the key
|
||||
fSavedKey = key;
|
||||
fSavedModifiers = modifiers;
|
||||
|
||||
// turn key event into string
|
||||
char keyStr[30];
|
||||
if (plKeyMap::ConvertVKeyToChar( key ))
|
||||
strcpy(keyStr, plKeyMap::ConvertVKeyToChar( key ));
|
||||
else
|
||||
memset(keyStr, 0, sizeof(keyStr));
|
||||
|
||||
static char shortKey[ 2 ];
|
||||
if( strlen(keyStr) == 0 )
|
||||
{
|
||||
if( isalnum( key ) )
|
||||
{
|
||||
shortKey[ 0 ] = (char)key;
|
||||
shortKey[ 1 ] = 0;
|
||||
strcpy(keyStr, shortKey);
|
||||
}
|
||||
else
|
||||
strcpy(keyStr, plKeyMap::GetStringUnmapped());
|
||||
}
|
||||
else
|
||||
{
|
||||
// check to see the buffer has ForewardSlash and change it to ForwardSlash
|
||||
if ( strcmp(keyStr,"ForewardSlash") == 0)
|
||||
{
|
||||
strcpy(keyStr,"ForwardSlash");
|
||||
}
|
||||
}
|
||||
|
||||
static char newKey[ 16 ];
|
||||
newKey[0] = 0;
|
||||
if( modifiers & kShift )
|
||||
strcat( newKey, plKeyMap::GetStringShift() );
|
||||
if( modifiers & kCtrl )
|
||||
strcat( newKey, plKeyMap::GetStringCtrl() );
|
||||
strcat( newKey, keyStr );
|
||||
|
||||
// set something in the buffer to be displayed
|
||||
wchar_t* temp = hsStringToWString(newKey);
|
||||
wcsncpy( fBuffer, temp , fBufferSize - 1 );
|
||||
delete [] temp;
|
||||
fCursorPos = 0;
|
||||
SetCursorToEnd();
|
||||
IUpdate();
|
||||
|
||||
// done capturing... tell the handler
|
||||
DoSomething();
|
||||
}
|
||||
fIgnoreNextKey = true;
|
||||
fFirstHalfExitKeyPushed = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// HACK for now--pass through caps lock so the runlock stuff will work even while a GUI is up
|
||||
if( key == KEY_CAPSLOCK )
|
||||
return false;
|
||||
|
||||
if( event == pfGameGUIMgr::kKeyDown || event == pfGameGUIMgr::kKeyRepeat )
|
||||
{
|
||||
fFirstHalfExitKeyPushed = false;
|
||||
// Use arrow keys to do our dirty work
|
||||
if( key == KEY_UP || key == KEY_HOME )
|
||||
{
|
||||
SetCursorToHome();
|
||||
}
|
||||
else if( key == KEY_DOWN || key == KEY_END )
|
||||
{
|
||||
SetCursorToEnd();
|
||||
}
|
||||
else if( key == KEY_LEFT )
|
||||
{
|
||||
if( fCursorPos > 0 )
|
||||
fCursorPos--;
|
||||
}
|
||||
else if( key == KEY_RIGHT && fBuffer != nil )
|
||||
{
|
||||
if( fCursorPos < wcslen( fBuffer ) )
|
||||
fCursorPos++;
|
||||
}
|
||||
else if( key == KEY_BACKSPACE && fBuffer != nil )
|
||||
{
|
||||
if( fCursorPos > 0 )
|
||||
{
|
||||
fCursorPos--;
|
||||
memmove( fBuffer + fCursorPos, fBuffer + fCursorPos + 1, (wcslen( fBuffer + fCursorPos + 1 ) + 1) * sizeof(wchar_t) );
|
||||
}
|
||||
}
|
||||
else if( key == KEY_DELETE && fBuffer != nil )
|
||||
{
|
||||
if( fCursorPos < wcslen( fBuffer ) )
|
||||
memmove( fBuffer + fCursorPos, fBuffer + fCursorPos + 1, (wcslen( fBuffer + fCursorPos + 1 ) + 1) * sizeof(wchar_t) );
|
||||
}
|
||||
else if( key == KEY_ENTER )
|
||||
{
|
||||
// do nothing here... wait for the keyup event
|
||||
fFirstHalfExitKeyPushed = true;
|
||||
}
|
||||
else if( key == KEY_ESCAPE )
|
||||
{
|
||||
// // do nothing here... wait for the keyup event
|
||||
// fFirstHalfExitKeyPushed = true;
|
||||
fEscapedFlag = true;
|
||||
DoSomething(); // Query WasEscaped() to see if it was escape vs enter
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fIgnoreNextKey = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
fIgnoreNextKey = true;
|
||||
IUpdate();
|
||||
return true;
|
||||
}
|
||||
// wait until the Key up for enter and escape to make sure we capture the whole key
|
||||
// ...before we give on focus control
|
||||
else if( event == pfGameGUIMgr::kKeyUp )
|
||||
{
|
||||
if( key == KEY_ENTER )
|
||||
{
|
||||
if (fFirstHalfExitKeyPushed)
|
||||
{
|
||||
// Do jack, just here to filter out it being added to the buffer
|
||||
// Well, ok, actually do *something*. *cough*.
|
||||
DoSomething();
|
||||
fFirstHalfExitKeyPushed = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if( key == KEY_ESCAPE )
|
||||
{
|
||||
if (fFirstHalfExitKeyPushed)
|
||||
{
|
||||
// fEscapedFlag = true;
|
||||
// DoSomething(); // Query WasEscaped() to see if it was escape vs enter
|
||||
fFirstHalfExitKeyPushed = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
fFirstHalfExitKeyPushed = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't process them, but we don't want anybody else processing them either
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string pfGUIEditBoxMod::GetBuffer( void )
|
||||
{
|
||||
char* temp = hsWStringToString(fBuffer);
|
||||
std::string retVal = temp;
|
||||
delete [] temp;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::ClearBuffer( void )
|
||||
{
|
||||
if( fBuffer != nil )
|
||||
{
|
||||
memset( fBuffer, 0, (fBufferSize + 1) * sizeof(wchar_t) );
|
||||
fCursorPos = 0;
|
||||
fScrollPos = 0;
|
||||
IUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::SetText( const char *str )
|
||||
{
|
||||
wchar_t* temp = hsStringToWString(str);
|
||||
SetText(temp);
|
||||
delete [] temp;
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::SetText( const wchar_t *str )
|
||||
{
|
||||
if( fBuffer != nil )
|
||||
{
|
||||
wcsncpy( fBuffer, str, fBufferSize - 1 );
|
||||
fCursorPos = 0;
|
||||
fScrollPos = 0;
|
||||
IUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::SetBufferSize( UInt32 size )
|
||||
{
|
||||
delete [] fBuffer;
|
||||
|
||||
fBufferSize = size;
|
||||
if( size > 0 )
|
||||
{
|
||||
fBuffer = TRACKED_NEW wchar_t[ size + 1 ];
|
||||
memset( fBuffer, 0, (size + 1) * sizeof(wchar_t) );
|
||||
}
|
||||
else
|
||||
fBuffer = nil;
|
||||
|
||||
fCursorPos = 0;
|
||||
fScrollPos = 0;
|
||||
}
|
||||
|
||||
|
||||
void pfGUIEditBoxMod::SetCursorToHome( void )
|
||||
{
|
||||
fCursorPos = 0;
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::SetCursorToEnd( void )
|
||||
{
|
||||
if( fBuffer != nil )
|
||||
fCursorPos = wcslen( fBuffer );
|
||||
}
|
||||
|
||||
void pfGUIEditBoxMod::SetLastKeyCapture(UInt32 key, UInt8 modifiers)
|
||||
{
|
||||
// capture the key
|
||||
fSavedKey = (plKeyDef)key;
|
||||
fSavedModifiers = modifiers;
|
||||
|
||||
// turn key event into string
|
||||
char keyStr[30];
|
||||
if (plKeyMap::ConvertVKeyToChar( key ))
|
||||
strcpy(keyStr, plKeyMap::ConvertVKeyToChar( key ));
|
||||
else
|
||||
memset(keyStr, 0, sizeof(keyStr));
|
||||
|
||||
static char shortKey[ 2 ];
|
||||
if( strlen(keyStr) == 0 )
|
||||
{
|
||||
if( isalnum( key ) )
|
||||
{
|
||||
shortKey[ 0 ] = (char)key;
|
||||
shortKey[ 1 ] = 0;
|
||||
strcpy(keyStr, shortKey);
|
||||
}
|
||||
else
|
||||
strcpy(keyStr, plKeyMap::GetStringUnmapped());
|
||||
}
|
||||
else
|
||||
{
|
||||
// check to see the buffer has ForewardSlash and change it to ForwardSlash
|
||||
if ( strcmp(keyStr,"ForewardSlash") == 0)
|
||||
{
|
||||
strcpy(keyStr,"ForwardSlash");
|
||||
}
|
||||
}
|
||||
|
||||
static char newKey[ 16 ];
|
||||
newKey[0] = 0;
|
||||
if( modifiers & kShift )
|
||||
strcat( newKey, plKeyMap::GetStringShift() );
|
||||
if( modifiers & kCtrl )
|
||||
strcat( newKey, plKeyMap::GetStringCtrl() );
|
||||
strcat( newKey, keyStr );
|
||||
|
||||
// set something in the buffer to be displayed
|
||||
wchar_t* temp = hsStringToWString(newKey);
|
||||
wcsncpy( fBuffer, temp , fBufferSize - 1 );
|
||||
delete [] temp;
|
||||
|
||||
fCursorPos = 0;
|
||||
SetCursorToEnd();
|
||||
IUpdate();
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIEditBoxMod Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIEditBoxMod_h
|
||||
#define _pfGUIEditBoxMod_h
|
||||
|
||||
#include "hsStlUtils.h"
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "../pnInputCore/plKeyDef.h"
|
||||
|
||||
#include "../plInputCore/plInputDevice.h"
|
||||
|
||||
class plMessage;
|
||||
class hsGMaterial;
|
||||
class plTextGenerator;
|
||||
|
||||
|
||||
class pfGUIEditBoxMod : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
wchar_t *fBuffer;
|
||||
UInt32 fBufferSize, fCursorPos;
|
||||
Int32 fScrollPos;
|
||||
hsBool fIgnoreNextKey, fEscapedFlag;
|
||||
hsBool fFirstHalfExitKeyPushed;
|
||||
|
||||
hsBool fSpecialCaptureKeyEventMode;
|
||||
|
||||
plKeyDef fSavedKey;
|
||||
UInt8 fSavedModifiers;
|
||||
|
||||
wchar_t fLastDeadKey; // if the previous key was a dead key, its value goes here
|
||||
wchar_t fDeadKeyConverter[256][256]; // first index is the dead key, second index is the char to combine it with
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual void IPostSetUpDynTextMap( void );
|
||||
virtual void IUpdate( void );
|
||||
|
||||
void SetupDeadKeyConverter();
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
kShift = 0x01,
|
||||
kCtrl = 0x02
|
||||
};
|
||||
|
||||
pfGUIEditBoxMod();
|
||||
virtual ~pfGUIEditBoxMod();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIEditBoxMod );
|
||||
GETINTERFACE_ANY( pfGUIEditBoxMod, pfGUIControlMod );
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual hsBool HandleKeyPress( char key, UInt8 modifiers );
|
||||
virtual hsBool HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers );
|
||||
|
||||
virtual void PurgeDynaTextMapImage();
|
||||
|
||||
void SetBufferSize( UInt32 size );
|
||||
|
||||
std::string GetBuffer( void );
|
||||
std::wstring GetBufferW( void ) { return fBuffer; }
|
||||
void ClearBuffer( void );
|
||||
void SetText( const char *str );
|
||||
void SetText( const wchar_t *str );
|
||||
|
||||
void SetCursorToHome( void );
|
||||
void SetCursorToEnd( void );
|
||||
|
||||
hsBool WasEscaped( void ) { hsBool e = fEscapedFlag; fEscapedFlag = false; return e; }
|
||||
|
||||
void SetSpecialCaptureKeyMode(hsBool state) { fSpecialCaptureKeyEventMode = state; }
|
||||
UInt32 GetLastKeyCaptured() { return (UInt32)fSavedKey; }
|
||||
UInt8 GetLastModifiersCaptured() { return fSavedModifiers; }
|
||||
void SetLastKeyCapture(UInt32 key, UInt8 modifiers);
|
||||
|
||||
void SetChatMode(hsBool state) { plKeyboardDevice::IgnoreCapsLock(state); }
|
||||
|
||||
// Extended event types
|
||||
enum ExtendedEvents
|
||||
{
|
||||
kValueChanging
|
||||
};
|
||||
};
|
||||
|
||||
#endif // _pfGUIEditBoxMod_h
|
@ -0,0 +1,368 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIKnobCtrl Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIKnobCtrl.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
// #include "../plAvatar/plAGModifier.h"
|
||||
#include "../plAvatar/plAGMasterMod.h"
|
||||
#include "../plAvatar/plAGAnimInstance.h"
|
||||
#include "../plSurface/plLayerAnimation.h"
|
||||
|
||||
#include "../pnSceneObject/plSceneObject.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIKnobCtrl::pfGUIKnobCtrl() :
|
||||
fAnimName(nil),
|
||||
fDragStart(0.f, 0.f, 0.f),
|
||||
fDragging(false),
|
||||
fAnimStartPos(0.f, 0.f, 0.f),
|
||||
fAnimEndPos(0.f, 0.f, 0.f),
|
||||
fDragRangeMin(0.f),
|
||||
fDragRangeMax(0.f),
|
||||
fAnimBegin(0.f),
|
||||
fAnimEnd(0.f),
|
||||
fAnimTimesCalced(false)
|
||||
{
|
||||
SetFlag( kWantsInterest );
|
||||
}
|
||||
|
||||
pfGUIKnobCtrl::~pfGUIKnobCtrl()
|
||||
{
|
||||
delete [] fAnimName;
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIKnobCtrl::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIValueCtrl::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIKnobCtrl::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return pfGUIValueCtrl::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIKnobCtrl::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIValueCtrl::Read(s, mgr);
|
||||
|
||||
fAnimationKeys.Reset();
|
||||
UInt32 i, count = s->ReadSwap32();
|
||||
for( i = 0; i < count; i++ )
|
||||
fAnimationKeys.Append( mgr->ReadKey( s ) );
|
||||
fAnimName = s->ReadSafeString();
|
||||
|
||||
fAnimTimesCalced = false;
|
||||
|
||||
fAnimStartPos.Read( s );
|
||||
fAnimEndPos.Read( s );
|
||||
}
|
||||
|
||||
void pfGUIKnobCtrl::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIValueCtrl::Write( s, mgr );
|
||||
|
||||
UInt32 i, count = fAnimationKeys.GetCount();
|
||||
s->WriteSwap32( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->WriteKey( s, fAnimationKeys[ i ] );
|
||||
s->WriteSafeString( fAnimName );
|
||||
|
||||
fAnimStartPos.Write( s );
|
||||
fAnimEndPos.Write( s );
|
||||
}
|
||||
|
||||
//// UpdateBounds ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIKnobCtrl::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
|
||||
{
|
||||
pfGUIValueCtrl::UpdateBounds( invXformMatrix, force );
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
fBoundsValid = false;
|
||||
}
|
||||
|
||||
//// HandleMouseDown/Up //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIKnobCtrl::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
fDragStart = mousePt;
|
||||
fDragValue = fValue;
|
||||
fDragging = true;
|
||||
|
||||
if( HasFlag( kMapToAnimationRange ) )
|
||||
{
|
||||
hsPoint3 scrnStart, scrnEnd;
|
||||
|
||||
// At mouse-down, we take our local-space start and end points and
|
||||
// translate them by our parent object's local-to-world to get the
|
||||
// right points in world-space. We do this now because our parent
|
||||
// might be animated, which could complicate matters a tad.
|
||||
scrnStart = fAnimStartPos;
|
||||
scrnEnd = fAnimEndPos;
|
||||
|
||||
plSceneObject *target = GetTarget();
|
||||
if( target != nil )
|
||||
{
|
||||
const plCoordinateInterface *ci = target->GetCoordinateInterface();
|
||||
if( ci != nil )
|
||||
{
|
||||
const plCoordinateInterface *parentCI = ci->GetParent();
|
||||
if( parentCI != nil )
|
||||
{
|
||||
const hsMatrix44 &parentLocalToWorld = parentCI->GetLocalToWorld();
|
||||
|
||||
scrnStart = parentLocalToWorld * scrnStart;
|
||||
scrnEnd = parentLocalToWorld * scrnEnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scrnStart = fDialog->WorldToScreenPoint( scrnStart );
|
||||
scrnEnd = fDialog->WorldToScreenPoint( scrnEnd );
|
||||
|
||||
if( HasFlag( kLeftRightOrientation ) )
|
||||
{
|
||||
fDragRangeMin = scrnStart.fX;
|
||||
fDragRangeMax = scrnEnd.fX;
|
||||
}
|
||||
else
|
||||
{
|
||||
fDragRangeMin = scrnStart.fY;
|
||||
fDragRangeMax = scrnEnd.fY;
|
||||
}
|
||||
}
|
||||
else if( HasFlag( kMapToScreenRange ) )
|
||||
{
|
||||
fDragRangeMin = 0.f;
|
||||
fDragRangeMax = 1.f;
|
||||
}
|
||||
else
|
||||
fDragRangeMin = -1;
|
||||
}
|
||||
|
||||
void pfGUIKnobCtrl::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
fDragging = false;
|
||||
HandleMouseDrag( mousePt, modifiers );
|
||||
}
|
||||
|
||||
void pfGUIKnobCtrl::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
hsScalar oldValue = fValue, newValue = fDragValue;
|
||||
|
||||
if( fDragRangeMin != -1 )
|
||||
{
|
||||
if( HasFlag( kLeftRightOrientation ) )
|
||||
{
|
||||
if( mousePt.fX < fDragRangeMin )
|
||||
newValue = fMin;
|
||||
else if( mousePt.fX > fDragRangeMax )
|
||||
newValue = fMax;
|
||||
else
|
||||
newValue = ( ( mousePt.fX - fDragRangeMin ) / ( fDragRangeMax - fDragRangeMin ) ) *
|
||||
( fMax - fMin ) + fMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( mousePt.fY > fDragRangeMin )
|
||||
newValue = fMin;
|
||||
else if( mousePt.fY < fDragRangeMax )
|
||||
newValue = fMax;
|
||||
else
|
||||
newValue = ( ( fDragRangeMin - mousePt.fY) / ( fDragRangeMin - fDragRangeMax ) ) *
|
||||
( fMax - fMin ) + fMin;
|
||||
}
|
||||
|
||||
if( HasFlag( kReverseValues ) )
|
||||
SetCurrValue( fMax - ( newValue - fMin ) );
|
||||
else
|
||||
SetCurrValue( newValue );
|
||||
}
|
||||
else
|
||||
{
|
||||
hsScalar diff;
|
||||
if( HasFlag( kLeftRightOrientation ) )
|
||||
diff = ( mousePt.fX - fDragStart.fX ) * 20.f;
|
||||
else
|
||||
diff = ( fDragStart.fY - mousePt.fY ) * 20.f;
|
||||
|
||||
if( HasFlag( kReverseValues ) )
|
||||
SetCurrValue( fDragValue - diff );
|
||||
else
|
||||
SetCurrValue( fDragValue + diff );
|
||||
}
|
||||
|
||||
// !fDragging = We're mousing-up, so if we're still dragging, we need to not have the only-
|
||||
// on-mouse-up flag set. Just FYI
|
||||
if( !fDragging || !HasFlag( kTriggerOnlyOnMouseUp ) )
|
||||
DoSomething();
|
||||
}
|
||||
|
||||
//// SetAnimationKeys ////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIKnobCtrl::SetAnimationKeys( hsTArray<plKey> &keys, const char *name )
|
||||
{
|
||||
fAnimationKeys = keys;
|
||||
delete [] fAnimName;
|
||||
if( name != nil )
|
||||
{
|
||||
fAnimName = TRACKED_NEW char[ strlen( name ) + 1 ];
|
||||
strcpy( fAnimName, name );
|
||||
}
|
||||
else
|
||||
fAnimName = nil;
|
||||
}
|
||||
|
||||
//// ICalcAnimTimes //////////////////////////////////////////////////////////
|
||||
// Loops through and computes the max begin and end for our animations. If
|
||||
// none of them are loaded and we're not already calced, returns false.
|
||||
|
||||
hsBool pfGUIKnobCtrl::ICalcAnimTimes( void )
|
||||
{
|
||||
if( fAnimTimesCalced )
|
||||
return true;
|
||||
|
||||
hsScalar tBegin = 1e30, tEnd = -1e30;
|
||||
bool foundOne = false;
|
||||
|
||||
for( int i = 0; i < fAnimationKeys.GetCount(); i++ )
|
||||
{
|
||||
// Handle AGMasterMods
|
||||
plAGMasterMod *mod = plAGMasterMod::ConvertNoRef( fAnimationKeys[ i ]->ObjectIsLoaded() );
|
||||
if( mod != nil )
|
||||
{
|
||||
for( int j = 0; j < mod->GetNumAnimations(); j++ )
|
||||
{
|
||||
hsScalar begin = mod->GetAnimInstance( j )->GetTimeConvert()->GetBegin();
|
||||
hsScalar end = mod->GetAnimInstance( j )->GetTimeConvert()->GetEnd();
|
||||
if( begin < tBegin )
|
||||
tBegin = begin;
|
||||
if( end > tEnd )
|
||||
tEnd = end;
|
||||
}
|
||||
foundOne = true;
|
||||
}
|
||||
// Handle layer animations
|
||||
plLayerAnimation *layer = plLayerAnimation::ConvertNoRef( fAnimationKeys[ i ]->ObjectIsLoaded() );
|
||||
if( layer != nil )
|
||||
{
|
||||
hsScalar begin = layer->GetTimeConvert().GetBegin();
|
||||
hsScalar end = layer->GetTimeConvert().GetEnd();
|
||||
if( begin < tBegin )
|
||||
tBegin = begin;
|
||||
if( end > tEnd )
|
||||
tEnd = end;
|
||||
foundOne = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( foundOne )
|
||||
{
|
||||
fAnimBegin = tBegin;
|
||||
fAnimEnd = tEnd;
|
||||
|
||||
fAnimTimesCalced = true;
|
||||
}
|
||||
|
||||
return fAnimTimesCalced;
|
||||
}
|
||||
|
||||
//// SetCurrValue ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIKnobCtrl::SetCurrValue( hsScalar v )
|
||||
{
|
||||
int old = (int)fValue;
|
||||
pfGUIValueCtrl::SetCurrValue( v );
|
||||
|
||||
// if( old == (int)fValue )
|
||||
// return;
|
||||
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
{
|
||||
ICalcAnimTimes();
|
||||
|
||||
hsScalar tLength = fAnimEnd - fAnimBegin;
|
||||
hsScalar newTime = fMin;
|
||||
|
||||
if (fMin != fMax) // Protect against div by zero
|
||||
{
|
||||
if( HasFlag( kReverseValues ) )
|
||||
newTime = ( ( fMax - fValue ) / ( fMax - fMin ) ) * tLength + fAnimBegin;
|
||||
else
|
||||
newTime = ( ( fValue - fMin ) / ( fMax - fMin ) ) * tLength + fAnimBegin;
|
||||
}
|
||||
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
|
||||
msg->SetCmd( plAnimCmdMsg::kGoToTime );
|
||||
msg->SetAnimName( fAnimName );
|
||||
msg->fTime = newTime;
|
||||
msg->AddReceivers( fAnimationKeys );
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
}
|
||||
|
||||
//// IGetDesiredCursor ///////////////////////////////////////////////////////
|
||||
|
||||
UInt32 pfGUIKnobCtrl::IGetDesiredCursor( void ) const
|
||||
{
|
||||
if( HasFlag( kLeftRightOrientation ) )
|
||||
{
|
||||
if( fDragging )
|
||||
return plInputInterface::kCursorLeftRightDragging;
|
||||
|
||||
return plInputInterface::kCursorLeftRightDraggable;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fDragging )
|
||||
return plInputInterface::kCursorUpDownDragging;
|
||||
|
||||
return plInputInterface::kCursorUpDownDraggable;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,100 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIKnobCtrl Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIKnobCtrl_h
|
||||
#define _pfGUIKnobCtrl_h
|
||||
|
||||
#include "pfGUIValueCtrl.h"
|
||||
|
||||
class plMessage;
|
||||
class plAGMasterMod;
|
||||
|
||||
class pfGUIKnobCtrl : public pfGUIValueCtrl
|
||||
{
|
||||
protected:
|
||||
|
||||
hsTArray<plKey> fAnimationKeys;
|
||||
char *fAnimName;
|
||||
|
||||
hsPoint3 fDragStart;
|
||||
hsScalar fDragValue;
|
||||
hsBool fDragging;
|
||||
|
||||
hsPoint3 fAnimStartPos, fAnimEndPos; // Calculated at export time for kMapToScreenRange
|
||||
hsScalar fDragRangeMin, fDragRangeMax;
|
||||
|
||||
// Computed once, once an anim is loaded that we can compute this with
|
||||
hsScalar fAnimBegin, fAnimEnd;
|
||||
hsBool fAnimTimesCalced;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual UInt32 IGetDesiredCursor( void ) const; // As specified in plInputInterface.h
|
||||
|
||||
hsBool ICalcAnimTimes( void );
|
||||
|
||||
public:
|
||||
|
||||
pfGUIKnobCtrl();
|
||||
virtual ~pfGUIKnobCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIKnobCtrl );
|
||||
GETINTERFACE_ANY( pfGUIKnobCtrl, pfGUIValueCtrl );
|
||||
|
||||
|
||||
enum OurFlags
|
||||
{
|
||||
kReverseValues = kDerivedFlagsStart,
|
||||
kLeftRightOrientation,
|
||||
kMapToScreenRange,
|
||||
kTriggerOnlyOnMouseUp,
|
||||
kMapToAnimationRange
|
||||
};
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
|
||||
|
||||
virtual void SetCurrValue( hsScalar v );
|
||||
|
||||
// Export only
|
||||
void SetAnimationKeys( hsTArray<plKey> &keys, const char *name );
|
||||
void SetScreenRange( const hsPoint3 &startPos, const hsPoint3 &endPos ) { fAnimStartPos = startPos; fAnimEndPos = endPos; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIKnobCtrl_h
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,183 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIListBoxMod Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIListBoxMod_h
|
||||
#define _pfGUIListBoxMod_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
class plMessage;
|
||||
class hsGMaterial;
|
||||
class plTextGenerator;
|
||||
class pfGUIListElement;
|
||||
class pfScrollProc;
|
||||
class pfGUIValueCtrl;
|
||||
|
||||
class pfGUIListBoxMod : public pfGUIControlMod
|
||||
{
|
||||
friend class pfScrollProc;
|
||||
|
||||
protected:
|
||||
|
||||
struct plSmallRect
|
||||
{
|
||||
Int16 fLeft, fTop, fRight, fBottom;
|
||||
|
||||
void Set( Int16 l, Int16 t, Int16 r, Int16 b );
|
||||
hsBool Contains( Int16 x, Int16 y );
|
||||
|
||||
plSmallRect& operator=(const int zero) { fLeft = fTop = fRight = fBottom = 0; return *this; }
|
||||
};
|
||||
|
||||
pfGUIValueCtrl *fScrollControl;
|
||||
|
||||
pfScrollProc *fScrollProc;
|
||||
|
||||
hsTArray<pfGUIListElement *> fElements;
|
||||
Int32 fCurrClick, fScrollPos, fCurrHover;
|
||||
UInt8 fModsAtDragTime;
|
||||
Int32 fMinSel, fMaxSel;
|
||||
hsBool fCheckScroll, fClicking;
|
||||
Int32 fSingleSelElement;
|
||||
hsBool fScrollRangeUpdateDeferred;
|
||||
hsBool fLocked, fReadyToRoll;
|
||||
hsTArray<plSmallRect> fElementBounds;
|
||||
hsTArray<Int16> fWrapStartIdxs;
|
||||
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
void ICalcScrollRange( void );
|
||||
void ICalcWrapStarts( void );
|
||||
|
||||
virtual void IUpdate( void );
|
||||
virtual void IPostSetUpDynTextMap( void );
|
||||
virtual UInt32 IGetDesiredCursor( void ) const;
|
||||
|
||||
Int32 IGetItemFromPoint( hsPoint3 &mousePt );
|
||||
void IFindSelectionRange( Int32 *min, Int32 *max );
|
||||
void ISelectRange( Int8 min, Int8 max, hsBool select );
|
||||
|
||||
public:
|
||||
|
||||
pfGUIListBoxMod();
|
||||
virtual ~pfGUIListBoxMod();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIListBoxMod );
|
||||
GETINTERFACE_ANY( pfGUIListBoxMod, pfGUIControlMod );
|
||||
|
||||
enum OurFlags
|
||||
{
|
||||
kSingleSelect = kDerivedFlagsStart,
|
||||
kDragAndDropCapable,
|
||||
kDisableSelection,
|
||||
kDisableKeyActions,
|
||||
kAllowMultipleElementsPerRow,
|
||||
kScrollLeftToRight,
|
||||
kAllowMousePassThrough,
|
||||
kGrowLeavesAndProcessOxygen,
|
||||
kHandsOffMultiSelect, // Do multiselect w/o needing ctrl or shift
|
||||
kForbidNoSelection
|
||||
};
|
||||
|
||||
// Extended event types
|
||||
enum ExtendedEvents
|
||||
{
|
||||
kScrollPosChanged,
|
||||
kItemAdded,
|
||||
kItemRemoved,
|
||||
kListCleared
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kRefScrollCtrl = kRefDerivedStart
|
||||
};
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseHover( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDblClick( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual hsBool HandleKeyPress( char key, UInt8 modifiers );
|
||||
virtual hsBool HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers );
|
||||
|
||||
virtual hsBool FilterMousePosition( hsPoint3 &mousePt );
|
||||
|
||||
virtual void PurgeDynaTextMapImage();
|
||||
|
||||
// Returns selected element. Only valid for kSingleSelect list boxes
|
||||
Int32 GetSelection( void ) { return fSingleSelElement; }
|
||||
void SetSelection( Int32 item );
|
||||
void RemoveSelection( Int32 item );
|
||||
void AddSelection( Int32 item );
|
||||
|
||||
virtual void ScrollToBegin( void );
|
||||
virtual void ScrollToEnd( void );
|
||||
virtual void SetScrollPos( Int32 pos );
|
||||
virtual Int32 GetScrollPos( void );
|
||||
virtual Int32 GetScrollRange( void );
|
||||
|
||||
|
||||
void Refresh( void ) { IUpdate(); }
|
||||
|
||||
virtual void SetColorScheme( pfGUIColorScheme *newScheme );
|
||||
|
||||
// Element manipulation
|
||||
|
||||
UInt16 AddElement( pfGUIListElement *el );
|
||||
void RemoveElement( UInt16 index );
|
||||
Int16 FindElement( pfGUIListElement *toCompareTo );
|
||||
void ClearAllElements( void );
|
||||
|
||||
void LockList( void );
|
||||
void UnlockList( void );
|
||||
|
||||
UInt16 GetNumElements( void );
|
||||
pfGUIListElement *GetElement( UInt16 idx );
|
||||
|
||||
UInt16 AddString( const char *string );
|
||||
UInt16 AddString( const wchar_t *string );
|
||||
Int16 FindString( const char *toCompareTo );
|
||||
Int16 FindString( const wchar_t *toCompareTo );
|
||||
|
||||
// Export only
|
||||
void SetScrollCtrl( pfGUIValueCtrl *ctrl ) { fScrollControl = ctrl; }
|
||||
void SetSingleSelect( hsBool yes ) { if( yes ) SetFlag( kSingleSelect ); else ClearFlag( kSingleSelect ); }
|
||||
};
|
||||
|
||||
#endif // _pfGUIListBoxMod_h
|
@ -0,0 +1,456 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIListElement Class Definitions //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIListElement.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
#include "pfGUIPopUpMenu.h" // For skins
|
||||
|
||||
#include "../plGImage/plDynamicTextMap.h"
|
||||
#include "../plGImage/hsCodecManager.h"
|
||||
#include "../plPipeline/plDebugText.h" // To quickly and hackily get the screen size in pixels
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Base Stuff //////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIListElement::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
fSelected = s->ReadBool();
|
||||
}
|
||||
|
||||
void pfGUIListElement::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
s->WriteBool( fSelected );
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// pfGUIListText ///////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIListText::pfGUIListText() : pfGUIListElement( kText )
|
||||
{
|
||||
fText = nil;
|
||||
fJustify = kLeftJustify;
|
||||
}
|
||||
|
||||
pfGUIListText::pfGUIListText( const char *text ) : pfGUIListElement( kText )
|
||||
{
|
||||
fText = hsStringToWString(text);
|
||||
fJustify = kLeftJustify;
|
||||
}
|
||||
|
||||
pfGUIListText::pfGUIListText( const wchar_t *text ) : pfGUIListElement( kText )
|
||||
{
|
||||
fText = TRACKED_NEW wchar_t[ wcslen( text ) + 1 ];
|
||||
wcscpy( fText, text );
|
||||
fJustify = kLeftJustify;
|
||||
}
|
||||
|
||||
pfGUIListText::~pfGUIListText()
|
||||
{
|
||||
delete [] fText;
|
||||
}
|
||||
|
||||
//// Virtuals ////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIListText::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIListElement::Read( s, mgr );
|
||||
|
||||
char *text = s->ReadSafeString();
|
||||
fText = hsStringToWString(text);
|
||||
delete [] text;
|
||||
}
|
||||
|
||||
void pfGUIListText::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIListElement::Write( s, mgr );
|
||||
|
||||
char *text = hsWStringToString(fText);
|
||||
s->WriteSafeString(text);
|
||||
delete [] text;
|
||||
}
|
||||
|
||||
hsBool pfGUIListText::Draw( plDynamicTextMap *textGen, UInt16 x, UInt16 y, UInt16 maxWidth, UInt16 maxHeight )
|
||||
{
|
||||
textGen->SetJustify( (plDynamicTextMap::Justify)fJustify );
|
||||
if( fSelected )
|
||||
{
|
||||
textGen->FillRect( x, y, maxWidth, maxHeight, fColors->fSelBackColor );
|
||||
textGen->SetTextColor( fColors->fSelForeColor, fColors->fTransparent && fColors->fSelBackColor.a == 0.f );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal back color will be cleared for us
|
||||
textGen->SetTextColor( fColors->fForeColor, fColors->fTransparent && fColors->fBackColor.a == 0.f );
|
||||
}
|
||||
|
||||
textGen->DrawClippedString( x + 4, y, GetText(), maxWidth - 8, maxHeight );
|
||||
return true;
|
||||
}
|
||||
|
||||
void pfGUIListText::GetSize( plDynamicTextMap *textGen, UInt16 *width, UInt16 *height )
|
||||
{
|
||||
*width = textGen->CalcStringWidth( GetText(), height );
|
||||
if( height != nil )
|
||||
{
|
||||
if( *height == 0 )
|
||||
*height = 10; // Never allow zero height elements
|
||||
else
|
||||
*height += 0; // Add one pixel on each side for padding (or not, 3.21.02 mcn)
|
||||
}
|
||||
}
|
||||
|
||||
int pfGUIListText::CompareTo( pfGUIListElement *rightSide )
|
||||
{
|
||||
pfGUIListText *text = (pfGUIListText *)rightSide;
|
||||
|
||||
if( text->fType != kText )
|
||||
return -2;
|
||||
|
||||
return wcscmp( GetText(), text->GetText() );
|
||||
}
|
||||
|
||||
void pfGUIListText::SetText( const char *text )
|
||||
{
|
||||
wchar_t *wText = hsStringToWString(text);
|
||||
SetText(wText);
|
||||
delete [] wText;
|
||||
}
|
||||
|
||||
void pfGUIListText::SetText( const wchar_t *text )
|
||||
{
|
||||
delete [] fText;
|
||||
if( text != nil )
|
||||
{
|
||||
fText = TRACKED_NEW wchar_t[ wcslen( text ) + 1 ];
|
||||
wcscpy( fText, text );
|
||||
}
|
||||
else
|
||||
fText = nil;
|
||||
}
|
||||
|
||||
void pfGUIListText::SetJustify( JustifyTypes justify )
|
||||
{
|
||||
switch( justify )
|
||||
{
|
||||
case kRightJustify:
|
||||
fJustify = plDynamicTextMap::kRightJustify;
|
||||
break;
|
||||
case kCenter:
|
||||
fJustify = plDynamicTextMap::kCenter;
|
||||
break;
|
||||
case kLeftJustify:
|
||||
default:
|
||||
fJustify = plDynamicTextMap::kLeftJustify;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// pfGUIListPicture ////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIListPicture::pfGUIListPicture() : pfGUIListElement( kPicture )
|
||||
{
|
||||
fBorderSize = 2;
|
||||
fMipmapKey = nil;
|
||||
}
|
||||
|
||||
pfGUIListPicture::pfGUIListPicture( plKey mipKey, hsBool respectAlpha ) : pfGUIListElement( kPicture )
|
||||
{
|
||||
fBorderSize = 2;
|
||||
fMipmapKey = mipKey;
|
||||
fRespectAlpha = respectAlpha;
|
||||
|
||||
plMipmap *mip = plMipmap::ConvertNoRef( fMipmapKey->ObjectIsLoaded() );
|
||||
if( mip != nil && mip->IsCompressed() )
|
||||
{
|
||||
// Gotta make and grab an uncompressed one
|
||||
plMipmap *uncompBuffer = hsCodecManager::Instance().CreateUncompressedMipmap( mip, hsCodecManager::k32BitDepth );
|
||||
char str[ 512 ];
|
||||
sprintf( str, "%s_uncomp", mip->GetKeyName() );
|
||||
fMipmapKey = hsgResMgr::ResMgr()->NewKey( str, uncompBuffer, fMipmapKey->GetUoid().GetLocation() );
|
||||
fMipmapKey->RefObject();
|
||||
}
|
||||
}
|
||||
|
||||
pfGUIListPicture::~pfGUIListPicture()
|
||||
{
|
||||
fMipmapKey->UnRefObject();
|
||||
fMipmapKey = nil;
|
||||
}
|
||||
|
||||
//// Virtuals ////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIListPicture::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIListElement::Read( s, mgr );
|
||||
|
||||
}
|
||||
|
||||
void pfGUIListPicture::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIListElement::Write( s, mgr );
|
||||
|
||||
}
|
||||
|
||||
hsBool pfGUIListPicture::Draw( plDynamicTextMap *textGen, UInt16 x, UInt16 y, UInt16 maxWidth, UInt16 maxHeight )
|
||||
{
|
||||
if( fSelected )
|
||||
textGen->FillRect( x, y, maxWidth, maxHeight, fColors->fSelBackColor );
|
||||
|
||||
plMipmap *mip = plMipmap::ConvertNoRef( fMipmapKey->ObjectIsLoaded() );
|
||||
if( mip != nil )
|
||||
{
|
||||
if( mip->GetWidth() + fBorderSize + fBorderSize > maxWidth || mip->GetHeight() + fBorderSize + fBorderSize > maxHeight )
|
||||
return false;
|
||||
|
||||
textGen->DrawImage( x + fBorderSize, y + fBorderSize, mip, fRespectAlpha ? plDynamicTextMap::kImgBlend : plDynamicTextMap::kImgNoAlpha );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void pfGUIListPicture::GetSize( plDynamicTextMap *textGen, UInt16 *width, UInt16 *height )
|
||||
{
|
||||
plMipmap *mip = plMipmap::ConvertNoRef( fMipmapKey->ObjectIsLoaded() );
|
||||
if( mip == nil )
|
||||
{
|
||||
*width = 16;
|
||||
if( height != nil )
|
||||
*height = 16;
|
||||
}
|
||||
|
||||
*width = (UInt16)(mip->GetWidth() + fBorderSize + fBorderSize);
|
||||
if( height != nil )
|
||||
*height = (UInt16)(mip->GetHeight() + fBorderSize + fBorderSize);
|
||||
}
|
||||
|
||||
int pfGUIListPicture::CompareTo( pfGUIListElement *rightSide )
|
||||
{
|
||||
pfGUIListPicture *text = (pfGUIListPicture *)rightSide;
|
||||
|
||||
if( text->fType != kPicture )
|
||||
return -2;
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// pfGUIListTreeRoot ///////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIListTreeRoot::pfGUIListTreeRoot() : pfGUIListElement( kTreeRoot )
|
||||
{
|
||||
fText = nil;
|
||||
fShowChildren = true;
|
||||
}
|
||||
|
||||
pfGUIListTreeRoot::pfGUIListTreeRoot( const char *text ) : pfGUIListElement( kTreeRoot )
|
||||
{
|
||||
fText = hsStringToWString(text);
|
||||
}
|
||||
|
||||
pfGUIListTreeRoot::pfGUIListTreeRoot( const wchar_t *text ) : pfGUIListElement( kTreeRoot )
|
||||
{
|
||||
fText = TRACKED_NEW wchar_t[ wcslen( text ) + 1 ];
|
||||
wcscpy( fText, text );
|
||||
}
|
||||
|
||||
pfGUIListTreeRoot::~pfGUIListTreeRoot()
|
||||
{
|
||||
delete [] fText;
|
||||
}
|
||||
|
||||
//// Virtuals ////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIListTreeRoot::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIListElement::Read( s, mgr );
|
||||
|
||||
char *temp = s->ReadSafeString();
|
||||
fText = hsStringToWString(temp);
|
||||
delete [] temp;
|
||||
}
|
||||
|
||||
void pfGUIListTreeRoot::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIListElement::Write( s, mgr );
|
||||
|
||||
char *temp = hsWStringToString(fText);
|
||||
s->WriteSafeString( temp );
|
||||
delete [] temp;
|
||||
}
|
||||
|
||||
hsBool pfGUIListTreeRoot::Draw( plDynamicTextMap *textGen, UInt16 x, UInt16 y, UInt16 maxWidth, UInt16 maxHeight )
|
||||
{
|
||||
textGen->SetJustify( plDynamicTextMap::kLeftJustify );
|
||||
if( fSelected )
|
||||
{
|
||||
textGen->FillRect( x, y, maxWidth, maxHeight, fColors->fSelBackColor );
|
||||
textGen->SetTextColor( fColors->fSelForeColor, fColors->fTransparent && fColors->fSelBackColor.a == 0.f );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal back color will be cleared for us
|
||||
textGen->SetTextColor( fColors->fForeColor, fColors->fTransparent && fColors->fBackColor.a == 0.f );
|
||||
}
|
||||
|
||||
if( fSkin != nil )
|
||||
{
|
||||
const pfGUISkin::pfSRect &r = fSkin->GetElement( fShowChildren ? pfGUISkin::kTreeButtonOpen : pfGUISkin::kTreeButtonClosed );
|
||||
|
||||
Int16 e = ( maxHeight - r.fHeight );
|
||||
if( e < 0 )
|
||||
e = 0;
|
||||
e >>= 1;
|
||||
|
||||
textGen->DrawClippedImage( x + 2, y + e, fSkin->GetTexture(), r.fX, r.fY, r.fWidth, r.fHeight, plDynamicTextMap::kImgSprite );
|
||||
x += r.fWidth + 4;
|
||||
}
|
||||
|
||||
textGen->DrawClippedString( x + 4, y, GetTitle(), maxWidth - 8, maxHeight );
|
||||
return true;
|
||||
}
|
||||
|
||||
hsBool pfGUIListTreeRoot::MouseClicked( UInt16 localX, UInt16 localY )
|
||||
{
|
||||
if( fSkin != nil )
|
||||
{
|
||||
const pfGUISkin::pfSRect &r = fSkin->GetElement( fShowChildren ? pfGUISkin::kTreeButtonOpen : pfGUISkin::kTreeButtonClosed );
|
||||
|
||||
// For now, I can't think of a clean way of getting the current visible height to this function,
|
||||
// but just testing the X value for tree controls is good enough for now. If we need Y testing for
|
||||
// other elements, I'll figure out something.
|
||||
if( localX >= 2 && localX <= 2 + r.fWidth )
|
||||
{
|
||||
ShowChildren( !fShowChildren );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void pfGUIListTreeRoot::GetSize( plDynamicTextMap *textGen, UInt16 *width, UInt16 *height )
|
||||
{
|
||||
*width = textGen->CalcStringWidth( GetTitle(), height );
|
||||
if( height != nil )
|
||||
{
|
||||
if( *height == 0 )
|
||||
*height = 10; // Never allow zero height elements
|
||||
else
|
||||
*height += 0; // Add one pixel on each side for padding (or not, 3.21.02 mcn)
|
||||
|
||||
if( fSkin != nil )
|
||||
{
|
||||
UInt16 h = fSkin->GetElement( pfGUISkin::kTreeButtonClosed ).fHeight;
|
||||
if( *height < h )
|
||||
*height = h;
|
||||
}
|
||||
}
|
||||
|
||||
if( fSkin != nil )
|
||||
*width += fSkin->GetElement( pfGUISkin::kTreeButtonClosed ).fWidth;
|
||||
}
|
||||
|
||||
int pfGUIListTreeRoot::CompareTo( pfGUIListElement *rightSide )
|
||||
{
|
||||
pfGUIListTreeRoot *text = (pfGUIListTreeRoot *)rightSide;
|
||||
|
||||
if( text->fType != kTreeRoot )
|
||||
return -2;
|
||||
|
||||
return wcscmp( GetTitle(), text->GetTitle() );
|
||||
}
|
||||
|
||||
void pfGUIListTreeRoot::SetTitle( const char *text )
|
||||
{
|
||||
wchar_t *wText = hsStringToWString(text);
|
||||
SetTitle(wText);
|
||||
delete [] wText;
|
||||
}
|
||||
|
||||
void pfGUIListTreeRoot::SetTitle( const wchar_t *text )
|
||||
{
|
||||
delete [] fText;
|
||||
if( text != nil )
|
||||
{
|
||||
fText = TRACKED_NEW wchar_t[ wcslen( text ) + 1 ];
|
||||
wcscpy( fText, text );
|
||||
}
|
||||
else
|
||||
fText = nil;
|
||||
}
|
||||
|
||||
void pfGUIListTreeRoot::AddChild( pfGUIListElement *el )
|
||||
{
|
||||
fChildren.Append( el );
|
||||
el->SetIndentLevel( GetIndentLevel() + 1 );
|
||||
el->SetCollapsed( !fShowChildren );
|
||||
}
|
||||
|
||||
void pfGUIListTreeRoot::RemoveChild( UInt32 idx )
|
||||
{
|
||||
fChildren.Remove( idx );
|
||||
}
|
||||
|
||||
void pfGUIListTreeRoot::ShowChildren( hsBool s )
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
|
||||
fShowChildren = s;
|
||||
for( i = 0; i < fChildren.GetCount(); i++ )
|
||||
fChildren[ i ]->SetCollapsed( !s );
|
||||
}
|
||||
|
||||
void pfGUIListTreeRoot::SetCollapsed( hsBool c )
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
|
||||
pfGUIListElement::SetCollapsed( c );
|
||||
for( i = 0; i < fChildren.GetCount(); i++ )
|
||||
fChildren[ i ]->SetCollapsed( c ? true : !fShowChildren );
|
||||
}
|
@ -0,0 +1,228 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIListElement Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIListElement_h
|
||||
#define _pfGUIListElement_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
class plDynamicTextMap;
|
||||
|
||||
class pfGUISkin;
|
||||
class pfGUIListElement
|
||||
{
|
||||
protected:
|
||||
|
||||
hsBool fSelected;
|
||||
const UInt8 fType;
|
||||
|
||||
hsBool fCollapsed; // For tree view support
|
||||
UInt8 fIndentLevel; // Ditto
|
||||
|
||||
pfGUIColorScheme *fColors;
|
||||
pfGUISkin *fSkin;
|
||||
|
||||
public:
|
||||
|
||||
enum Types
|
||||
{
|
||||
kText,
|
||||
kPicture,
|
||||
kTreeRoot
|
||||
};
|
||||
|
||||
pfGUIListElement( UInt8 type ) : fType( type ), fSelected( false ), fCollapsed( false ), fIndentLevel( 0 ) {}
|
||||
virtual ~pfGUIListElement() {}
|
||||
|
||||
virtual void Read( hsStream *s, hsResMgr *mgr );
|
||||
virtual void Write( hsStream *s, hsResMgr *mgr );
|
||||
|
||||
virtual hsBool Draw( plDynamicTextMap *textGen, UInt16 x, UInt16 y, UInt16 maxWidth, UInt16 maxHeight ) = 0;
|
||||
virtual void GetSize( plDynamicTextMap *textGen, UInt16 *width, UInt16 *height ) = 0;
|
||||
virtual int CompareTo( pfGUIListElement *rightSide ) = 0;
|
||||
|
||||
virtual void SetSelected( hsBool sel ) { fSelected = sel; }
|
||||
virtual hsBool IsSelected( void ) { return fSelected; }
|
||||
|
||||
virtual hsBool CanBeDragged( void ) { return false; }
|
||||
|
||||
// Return true here if you need the list refreshed
|
||||
virtual hsBool MouseClicked( UInt16 localX, UInt16 localY ) { return false; }
|
||||
|
||||
UInt8 GetType( void ) { return fType; }
|
||||
|
||||
void SetColorScheme( pfGUIColorScheme *scheme ) { fColors = scheme; }
|
||||
void SetSkin( pfGUISkin *skin ) { fSkin = skin; }
|
||||
|
||||
hsBool IsCollapsed( void ) const { return fCollapsed; }
|
||||
virtual void SetCollapsed( hsBool c ) { fCollapsed = c; }
|
||||
|
||||
UInt8 GetIndentLevel( void ) const { return fIndentLevel; }
|
||||
void SetIndentLevel( UInt8 i ) { fIndentLevel = i; }
|
||||
};
|
||||
|
||||
class pfGUIListText : public pfGUIListElement
|
||||
{
|
||||
public:
|
||||
// these enums should at least agree with the plDynamicTextMap's version of the Justify types
|
||||
enum JustifyTypes
|
||||
{
|
||||
kLeftJustify = 0,
|
||||
kCenter,
|
||||
kRightJustify
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
wchar_t *fText;
|
||||
UInt8 fJustify; // This is not our JustifyTypes, but from plDynamicTextMap
|
||||
|
||||
public:
|
||||
|
||||
pfGUIListText();
|
||||
pfGUIListText( const char *text );
|
||||
pfGUIListText( const wchar_t *text );
|
||||
virtual ~pfGUIListText();
|
||||
|
||||
virtual void Read( hsStream *s, hsResMgr *mgr );
|
||||
virtual void Write( hsStream *s, hsResMgr *mgr );
|
||||
|
||||
virtual hsBool Draw( plDynamicTextMap *textGen, UInt16 x, UInt16 y, UInt16 maxWidth, UInt16 maxHeight );
|
||||
virtual void GetSize( plDynamicTextMap *textGen, UInt16 *width, UInt16 *height );
|
||||
virtual int CompareTo( pfGUIListElement *rightSide );
|
||||
|
||||
virtual hsBool CanBeDragged( void ) { return true; }
|
||||
virtual void SetJustify( JustifyTypes justify );
|
||||
|
||||
// These two are virtual so we can derive and override them
|
||||
virtual const wchar_t *GetText( void ) { return fText; }
|
||||
virtual void SetText( const char *text );
|
||||
virtual void SetText( const wchar_t *text );
|
||||
};
|
||||
|
||||
class pfGUIListPicture : public pfGUIListElement
|
||||
{
|
||||
protected:
|
||||
|
||||
plKey fMipmapKey;
|
||||
UInt8 fBorderSize; // Defaults to 2
|
||||
hsBool fRespectAlpha;
|
||||
|
||||
public:
|
||||
|
||||
pfGUIListPicture();
|
||||
pfGUIListPicture( plKey mipKey, hsBool respectAlpha );
|
||||
virtual ~pfGUIListPicture();
|
||||
|
||||
virtual void Read( hsStream *s, hsResMgr *mgr );
|
||||
virtual void Write( hsStream *s, hsResMgr *mgr );
|
||||
|
||||
virtual hsBool Draw( plDynamicTextMap *textGen, UInt16 x, UInt16 y, UInt16 maxWidth, UInt16 maxHeight );
|
||||
virtual void GetSize( plDynamicTextMap *textGen, UInt16 *width, UInt16 *height );
|
||||
virtual int CompareTo( pfGUIListElement *rightSide );
|
||||
|
||||
virtual hsBool CanBeDragged( void ) { return false; }
|
||||
|
||||
void SetBorderSize( UInt32 size ) { fBorderSize = (UInt8)size; }
|
||||
void SetRespectAlpha( hsBool r ) { fRespectAlpha = r; }
|
||||
|
||||
};
|
||||
|
||||
class pfGUIListTreeRoot : public pfGUIListElement
|
||||
{
|
||||
protected:
|
||||
|
||||
wchar_t *fText;
|
||||
hsBool fShowChildren;
|
||||
|
||||
hsTArray<pfGUIListElement *> fChildren;
|
||||
|
||||
public:
|
||||
|
||||
pfGUIListTreeRoot();
|
||||
pfGUIListTreeRoot( const char *text );
|
||||
pfGUIListTreeRoot( const wchar_t *text );
|
||||
virtual ~pfGUIListTreeRoot();
|
||||
|
||||
virtual void Read( hsStream *s, hsResMgr *mgr );
|
||||
virtual void Write( hsStream *s, hsResMgr *mgr );
|
||||
|
||||
virtual hsBool Draw( plDynamicTextMap *textGen, UInt16 x, UInt16 y, UInt16 maxWidth, UInt16 maxHeight );
|
||||
virtual void GetSize( plDynamicTextMap *textGen, UInt16 *width, UInt16 *height );
|
||||
virtual int CompareTo( pfGUIListElement *rightSide );
|
||||
|
||||
virtual hsBool MouseClicked( UInt16 localX, UInt16 localY );
|
||||
|
||||
const wchar_t *GetTitle( void ) { return fText; }
|
||||
void SetTitle( const char *text );
|
||||
void SetTitle( const wchar_t *text );
|
||||
|
||||
UInt32 GetNumChildren( void ) const { return fChildren.GetCount(); }
|
||||
pfGUIListElement *GetChild( UInt32 i ) const { return fChildren[ i ]; }
|
||||
|
||||
void AddChild( pfGUIListElement *el );
|
||||
void RemoveChild( UInt32 idx );
|
||||
|
||||
virtual void SetCollapsed( hsBool c );
|
||||
|
||||
void ShowChildren( hsBool s );
|
||||
hsBool IsShowingChildren( void ) const { return fShowChildren; }
|
||||
};
|
||||
|
||||
//// pfGUIDropTargetProc /////////////////////////////////////////////////////
|
||||
// A little proc object you create if you want a control to be a potential
|
||||
// target for drag & drop operations. It has two functions: one takes a
|
||||
// listElement and returns whether it can accept that type, and the other
|
||||
// actually gets called when a listElement is "dropped" onto the associated
|
||||
// control. Any control can be a dropTarget; just attach the right proc
|
||||
// to it!
|
||||
// If you are dragging multiple elements, both CanEat() and Eat() will get
|
||||
// called for each element that is being dragged.
|
||||
|
||||
class pfGUIDropTargetProc
|
||||
{
|
||||
protected:
|
||||
|
||||
UInt32 fRefCnt;
|
||||
|
||||
public:
|
||||
|
||||
pfGUIDropTargetProc() { fRefCnt = 0; }
|
||||
|
||||
virtual hsBool CanEat( pfGUIListElement *element, pfGUIControlMod *source ) = 0;
|
||||
virtual void Eat( pfGUIListElement *element, pfGUIControlMod *source, pfGUIControlMod *parent ) = 0;
|
||||
|
||||
// ONLY THE GUI SYSTEM SHOULD CALL THESE
|
||||
void IncRef( void ) { fRefCnt++; }
|
||||
hsBool DecRef( void ) { fRefCnt--; return ( fRefCnt > 0 ) ? false : true; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIListElement_h
|
@ -0,0 +1,463 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIMenuItem Definition //
|
||||
// //
|
||||
// The type of button that knows how to party. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIMenuItem.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
#include "pfGUIPopUpMenu.h"
|
||||
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../plGImage/plDynamicTextMap.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIMenuItem::pfGUIMenuItem()
|
||||
{
|
||||
fName = nil;
|
||||
fSkin = nil;
|
||||
fReportingHover = false;
|
||||
fSkinBuffersUpdated = true;
|
||||
}
|
||||
|
||||
pfGUIMenuItem::~pfGUIMenuItem()
|
||||
{
|
||||
SetSkin( nil, kTop );
|
||||
delete [] fName;
|
||||
}
|
||||
|
||||
void pfGUIMenuItem::SetName( const char *name )
|
||||
{
|
||||
wchar_t *wName = hsStringToWString(name);
|
||||
SetName(wName);
|
||||
delete [] wName;
|
||||
}
|
||||
|
||||
void pfGUIMenuItem::SetName( const wchar_t *name )
|
||||
{
|
||||
delete [] fName;
|
||||
if (name != nil)
|
||||
{
|
||||
fName = TRACKED_NEW wchar_t[wcslen(name)+1];
|
||||
wcscpy(fName,name);
|
||||
}
|
||||
else
|
||||
fName = nil;
|
||||
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
//// SetSkin /////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIMenuItem::SetSkin( pfGUISkin *skin, HowToSkin s )
|
||||
{
|
||||
// Just a function wrapper for SendRef
|
||||
if( fSkin != nil )
|
||||
GetKey()->Release( fSkin->GetKey() );
|
||||
|
||||
if( skin != nil )
|
||||
hsgResMgr::ResMgr()->SendRef( skin->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefSkin ), plRefFlags::kActiveRef );
|
||||
|
||||
fHowToSkin = s;
|
||||
|
||||
fSkinBuffersUpdated = false;
|
||||
}
|
||||
|
||||
//// IPostSetUpDynTextMap ////////////////////////////////////////////////////
|
||||
// Draw our initial image on the dynTextMap
|
||||
|
||||
void pfGUIMenuItem::IPostSetUpDynTextMap( void )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//// IGetDesiredExtraDTMRoom /////////////////////////////////////////////////
|
||||
// Overridden so we can enlarge our DTMap by 3 vertically, to use the extra
|
||||
// space as basically a double buffer for our skinning
|
||||
|
||||
void pfGUIMenuItem::IGrowDTMDimsToDesiredSize( UInt16 &width, UInt16 &height )
|
||||
{
|
||||
height *= 3;
|
||||
}
|
||||
|
||||
//// IUpdateSkinBuffers //////////////////////////////////////////////////////
|
||||
// Redraws the double buffers for the two skin images we keep hidden in the
|
||||
// DTMap, so we don't have to re-composite them every time we draw the
|
||||
// control.
|
||||
|
||||
void pfGUIMenuItem::IUpdateSkinBuffers( void )
|
||||
{
|
||||
if( fSkinBuffersUpdated )
|
||||
return;
|
||||
if( fSkin == nil )
|
||||
return;
|
||||
if( fDynTextMap == nil )
|
||||
return;
|
||||
if( fSkin->GetTexture() == nil )
|
||||
return;
|
||||
|
||||
UInt16 y = fDynTextMap->GetVisibleHeight();
|
||||
|
||||
IUpdateSingleSkinBuffer( y, false );
|
||||
IUpdateSingleSkinBuffer( y << 1, true );
|
||||
|
||||
fSkinBuffersUpdated = true;
|
||||
}
|
||||
|
||||
//// IUpdateSingleSkinBuffer /////////////////////////////////////////////////
|
||||
// Broken down functionality for the above function
|
||||
|
||||
void pfGUIMenuItem::IUpdateSingleSkinBuffer( UInt16 y, hsBool sel )
|
||||
{
|
||||
hsAssert( fSkin != nil && fDynTextMap != nil, "Invalid pointers in IUpdateSingleSkinBuffer()" );
|
||||
|
||||
|
||||
// Note: add 1 to the visible height so we get enough overlap to take care of mipmapping issues
|
||||
UInt16 x = 0, totWidth = fDynTextMap->GetVisibleWidth();
|
||||
UInt16 totHeight = y + fDynTextMap->GetVisibleHeight();
|
||||
pfGUISkin::pfSRect element;
|
||||
|
||||
|
||||
totWidth -= fSkin->GetElement( pfGUISkin::kRightSpan ).fWidth;
|
||||
if( fHowToSkin == kTop )
|
||||
{
|
||||
// Draw up-left corner
|
||||
element = fSkin->GetElement( pfGUISkin::kUpLeftCorner );
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, element.fWidth, element.fHeight, plDynamicTextMap::kImgSprite );
|
||||
x += element.fWidth;
|
||||
|
||||
element = fSkin->GetElement( pfGUISkin::kTopSpan );
|
||||
for( ; x < totWidth; )
|
||||
{
|
||||
UInt16 wid = element.fWidth;
|
||||
if( x + wid > totWidth )
|
||||
wid = totWidth - x;
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, wid, element.fHeight, plDynamicTextMap::kImgSprite );
|
||||
x += wid;
|
||||
}
|
||||
|
||||
element = fSkin->GetElement( pfGUISkin::kUpRightCorner );
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, element.fWidth, element.fHeight, plDynamicTextMap::kImgSprite );
|
||||
|
||||
y += element.fHeight;
|
||||
}
|
||||
else if( fHowToSkin == kBottom )
|
||||
{
|
||||
// Clip some space for now
|
||||
totHeight -= fSkin->GetElement( pfGUISkin::kLowerLeftCorner ).fHeight;
|
||||
}
|
||||
|
||||
// Group drawing by skin elements for caching performance
|
||||
UInt16 startY = y;
|
||||
x = 0;
|
||||
element = fSkin->GetElement( pfGUISkin::kLeftSpan );
|
||||
for( ; y < totHeight; )
|
||||
{
|
||||
UInt16 ht = element.fHeight;
|
||||
if( y + ht > totHeight )
|
||||
ht = totHeight - y;
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, element.fWidth, ht, plDynamicTextMap::kImgSprite );
|
||||
y += ht;
|
||||
}
|
||||
|
||||
x += element.fWidth;
|
||||
if( sel )
|
||||
element = fSkin->GetElement( pfGUISkin::kSelectedFill );
|
||||
else
|
||||
element = fSkin->GetElement( pfGUISkin::kMiddleFill );
|
||||
for( ; x < totWidth; )
|
||||
{
|
||||
UInt16 wid = element.fWidth;
|
||||
if( x + wid > totWidth )
|
||||
wid = totWidth - x;
|
||||
|
||||
for( y = startY; y < totHeight; )
|
||||
{
|
||||
UInt16 ht = element.fHeight;
|
||||
if( y + ht > totHeight )
|
||||
ht = totHeight - y;
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, wid, ht, plDynamicTextMap::kImgSprite );
|
||||
y += ht;
|
||||
}
|
||||
|
||||
x += wid;
|
||||
}
|
||||
|
||||
element = fSkin->GetElement( pfGUISkin::kRightSpan );
|
||||
for( y = startY; y < totHeight; )
|
||||
{
|
||||
UInt16 ht = element.fHeight;
|
||||
if( y + ht > totHeight )
|
||||
ht = totHeight - y;
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, element.fWidth, ht, plDynamicTextMap::kImgSprite );
|
||||
y += ht;
|
||||
}
|
||||
|
||||
if( fHowToSkin == kBottom )
|
||||
{
|
||||
x = 0;
|
||||
|
||||
// Draw lower-left corner
|
||||
element = fSkin->GetElement( pfGUISkin::kLowerLeftCorner );
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, element.fWidth, element.fHeight, plDynamicTextMap::kImgSprite );
|
||||
x += element.fWidth;
|
||||
|
||||
element = fSkin->GetElement( pfGUISkin::kBottomSpan );
|
||||
for( ; x < totWidth; )
|
||||
{
|
||||
UInt16 wid = element.fWidth;
|
||||
if( x + wid > totWidth )
|
||||
wid = totWidth - x;
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, wid, element.fHeight, plDynamicTextMap::kImgSprite );
|
||||
x += wid;
|
||||
}
|
||||
|
||||
element = fSkin->GetElement( pfGUISkin::kLowerRightCorner );
|
||||
fDynTextMap->DrawClippedImage( x, y, fSkin->GetTexture(), element.fX, element.fY, element.fWidth, element.fHeight, plDynamicTextMap::kImgSprite );
|
||||
|
||||
y += element.fHeight;
|
||||
}
|
||||
}
|
||||
|
||||
//// IUpdate /////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIMenuItem::IUpdate( void )
|
||||
{
|
||||
if( fDynTextMap == nil )
|
||||
return;
|
||||
|
||||
if( fSkin != nil )
|
||||
{
|
||||
IUpdateSkinBuffers();
|
||||
|
||||
if( !fSkinBuffersUpdated )
|
||||
return;
|
||||
|
||||
// Copy now from our skin buffer, plus set our text color
|
||||
UInt16 y = fDynTextMap->GetVisibleHeight();
|
||||
|
||||
if( IsInteresting() )
|
||||
{
|
||||
fDynTextMap->DrawClippedImage( 0, 0, fDynTextMap, 0, y << 1, fDynTextMap->GetVisibleWidth(), y, plDynamicTextMap::kImgSprite );
|
||||
fDynTextMap->SetTextColor( GetColorScheme()->fSelForeColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
fDynTextMap->DrawClippedImage( 0, 0, fDynTextMap, 0, y, fDynTextMap->GetVisibleWidth(), y, plDynamicTextMap::kImgSprite );
|
||||
fDynTextMap->SetTextColor( GetColorScheme()->fForeColor );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( IsInteresting() )
|
||||
{
|
||||
fDynTextMap->ClearToColor( GetColorScheme()->fSelBackColor );
|
||||
fDynTextMap->SetTextColor( GetColorScheme()->fSelForeColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
fDynTextMap->ClearToColor( GetColorScheme()->fBackColor );
|
||||
fDynTextMap->SetTextColor( GetColorScheme()->fForeColor );
|
||||
}
|
||||
}
|
||||
|
||||
fDynTextMap->SetJustify( plDynamicTextMap::kLeftJustify );
|
||||
|
||||
if( fName != nil )
|
||||
{
|
||||
UInt16 ht;
|
||||
fDynTextMap->CalcStringWidth( fName, &ht );
|
||||
|
||||
Int16 x = 0, y = ( fDynTextMap->GetVisibleHeight() - ht ) >> 1;
|
||||
if( fHowToSkin == kTop && fSkin != nil )
|
||||
y += fSkin->GetElement( pfGUISkin::kTopSpan ).fHeight >> 1;
|
||||
else if( fHowToSkin == kBottom && fSkin != nil )
|
||||
y -= fSkin->GetElement( pfGUISkin::kTopSpan ).fHeight >> 1;
|
||||
|
||||
if( fSkin != nil )
|
||||
x += fSkin->GetBorderMargin();
|
||||
|
||||
if( fClicking )
|
||||
{
|
||||
x += 2;
|
||||
y += 2;
|
||||
}
|
||||
|
||||
fDynTextMap->DrawClippedString( x, y, fName, fDynTextMap->GetVisibleWidth(), fDynTextMap->GetVisibleHeight() );
|
||||
|
||||
if( HasFlag( kDrawSubMenuArrow ) )
|
||||
{
|
||||
if( fSkin != nil )
|
||||
{
|
||||
pfGUISkin::pfSRect element;
|
||||
|
||||
if( IsInteresting() )
|
||||
element = fSkin->GetElement( pfGUISkin::kSelectedSubMenuArrow );
|
||||
else
|
||||
element = fSkin->GetElement( pfGUISkin::kSubMenuArrow );
|
||||
|
||||
y += ( ht >> 1 ) - ( element.fHeight >> 1 );
|
||||
if( y < 0 || y + element.fHeight >= fDynTextMap->GetHeight() )
|
||||
y = 0;
|
||||
|
||||
fDynTextMap->DrawClippedImage( x + fDynTextMap->GetVisibleWidth() - 2 - element.fWidth
|
||||
- fSkin->GetElement( pfGUISkin::kRightSpan ).fWidth,
|
||||
y,
|
||||
fSkin->GetTexture(), element.fX, element.fY, element.fWidth, element.fHeight, plDynamicTextMap::kImgBlend );
|
||||
}
|
||||
else
|
||||
{
|
||||
fDynTextMap->SetJustify( plDynamicTextMap::kRightJustify );
|
||||
fDynTextMap->DrawString( x + fDynTextMap->GetVisibleWidth() - 2, y, ">>" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fDynTextMap->FlushToHost();
|
||||
}
|
||||
|
||||
void pfGUIMenuItem::PurgeDynaTextMapImage()
|
||||
{
|
||||
if ( fDynTextMap != nil )
|
||||
fDynTextMap->PurgeImage();
|
||||
}
|
||||
|
||||
//// GetTextExtents //////////////////////////////////////////////////////////
|
||||
// Calculate the size of the drawn text.
|
||||
|
||||
void pfGUIMenuItem::GetTextExtents( UInt16 &width, UInt16 &height )
|
||||
{
|
||||
if( fName == nil )
|
||||
width = height = 0;
|
||||
else
|
||||
width = fDynTextMap->CalcStringWidth( fName, &height );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIMenuItem::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return pfGUIButtonMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIMenuItem::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIButtonMod::Read( s, mgr );
|
||||
}
|
||||
|
||||
void pfGUIMenuItem::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIButtonMod::Write( s, mgr );
|
||||
}
|
||||
|
||||
//// HandleMouseDown/Up //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIMenuItem::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
pfGUIButtonMod::HandleMouseDown( mousePt, modifiers );
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
void pfGUIMenuItem::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
pfGUIButtonMod::HandleMouseUp( mousePt, modifiers );
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
void pfGUIMenuItem::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
/* if( !fClicking )
|
||||
return;
|
||||
|
||||
if( fDraggable == nil )
|
||||
return;
|
||||
|
||||
if( !fDraggable->IsVisible() )
|
||||
{
|
||||
// Are we outside ourselves?
|
||||
if( !PointInBounds( mousePt ) )
|
||||
{
|
||||
// Yes, start dragging
|
||||
StartDragging();
|
||||
|
||||
// Hand off our interest to the draggable
|
||||
fDialog->SetControlOfInterest( fDraggable );
|
||||
}
|
||||
}
|
||||
*/
|
||||
pfGUIButtonMod::HandleMouseDrag( mousePt, modifiers );
|
||||
}
|
||||
|
||||
void pfGUIMenuItem::HandleMouseHover( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
pfGUIButtonMod::HandleMouseHover( mousePt, modifiers );
|
||||
if( HasFlag( kReportHovers ) )
|
||||
{
|
||||
if( PointInBounds( mousePt ) )
|
||||
{
|
||||
if( !fReportingHover && ( fDialog->GetControlOfInterest() == nil ||
|
||||
fDialog->GetControlOfInterest() == this ) )
|
||||
{
|
||||
fReportingHover = true;
|
||||
HandleExtendedEvent( kMouseHover );
|
||||
fDialog->SetControlOfInterest( this );
|
||||
}
|
||||
}
|
||||
else if( fReportingHover )
|
||||
{
|
||||
fReportingHover = false;
|
||||
HandleExtendedEvent( kMouseExit );
|
||||
fDialog->SetControlOfInterest( nil );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// SetInteresting //////////////////////////////////////////////////////////
|
||||
// Overridden to play mouse over animation when we're interesting
|
||||
|
||||
void pfGUIMenuItem::SetInteresting( hsBool i )
|
||||
{
|
||||
pfGUIButtonMod::SetInteresting( i );
|
||||
IUpdate();
|
||||
|
||||
// Make sure we're not still thinking we're reporting hovers when we're not
|
||||
if( !i )
|
||||
fReportingHover = false;
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIMenuItem Header //
|
||||
// //
|
||||
// The type of button that knows how to party. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIMenuItem_h
|
||||
#define _pfGUIMenuItem_h
|
||||
|
||||
#include "pfGUIButtonMod.h"
|
||||
|
||||
class plMessage;
|
||||
|
||||
class pfGUISkin;
|
||||
class pfGUIMenuItem : public pfGUIButtonMod
|
||||
{
|
||||
public:
|
||||
enum HowToSkin
|
||||
{
|
||||
kTop,
|
||||
kMiddle,
|
||||
kBottom
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
wchar_t *fName;
|
||||
hsBool fReportingHover;
|
||||
|
||||
HowToSkin fHowToSkin;
|
||||
hsBool fSkinBuffersUpdated;
|
||||
|
||||
virtual void IGrowDTMDimsToDesiredSize( UInt16 &width, UInt16 &height );
|
||||
virtual void IPostSetUpDynTextMap( void );
|
||||
virtual void IUpdate( void );
|
||||
|
||||
void IUpdateSkinBuffers( void );
|
||||
void IUpdateSingleSkinBuffer( UInt16 y, hsBool sel );
|
||||
|
||||
public:
|
||||
|
||||
pfGUIMenuItem();
|
||||
virtual ~pfGUIMenuItem();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIMenuItem );
|
||||
GETINTERFACE_ANY( pfGUIMenuItem, pfGUIButtonMod );
|
||||
|
||||
enum ItemFlags
|
||||
{
|
||||
kDrawSubMenuArrow = kDerivedFlagsStart,
|
||||
kReportHovers
|
||||
};
|
||||
|
||||
// Extended event types
|
||||
enum ExtendedEvents
|
||||
{
|
||||
kMouseHover,
|
||||
kMouseExit
|
||||
};
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void SetInteresting( hsBool i );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseHover( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual void PurgeDynaTextMapImage();
|
||||
|
||||
|
||||
void SetName( const char *name );
|
||||
void SetName( const wchar_t *name );
|
||||
const wchar_t *GetName( void ) const { return fName; }
|
||||
|
||||
void GetTextExtents( UInt16 &width, UInt16 &height );
|
||||
|
||||
void SetSkin( pfGUISkin *skin, HowToSkin s );
|
||||
};
|
||||
|
||||
#endif // _pfGUIMenuItem_h
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,273 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIMultiLineEditCtrl Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIMultiLineEditCtrl_h
|
||||
#define _pfGUIMultiLineEditCtrl_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "hsTemplates.h"
|
||||
|
||||
#include "../plInputCore/plInputDevice.h"
|
||||
|
||||
class plMessage;
|
||||
class hsGMaterial;
|
||||
class plTextGenerator;
|
||||
class pfMLScrollProc;
|
||||
class pfGUIValueCtrl;
|
||||
|
||||
struct plUndoAction;
|
||||
|
||||
class pfGUIMultiLineEditProc
|
||||
{
|
||||
public:
|
||||
pfGUIMultiLineEditProc() {}
|
||||
virtual ~pfGUIMultiLineEditProc() {}
|
||||
|
||||
// we've hit the end of the control list (by moving the cursor)
|
||||
virtual OnEndOfControlList(Int32 cursorPos) {}
|
||||
|
||||
// we've hit the beginning of the control ist (by moving the cursor)
|
||||
virtual OnBeginningOfControlList(Int32 cursorPos) {}
|
||||
};
|
||||
|
||||
class pfGUIMultiLineEditCtrl : public pfGUIControlMod
|
||||
{
|
||||
public:
|
||||
enum Direction
|
||||
{
|
||||
kLineStart = 1,
|
||||
kLineEnd,
|
||||
kBufferStart,
|
||||
kBufferEnd,
|
||||
kOneBack,
|
||||
kOneForward,
|
||||
kOneWordBack,
|
||||
kOneWordForward,
|
||||
kOneLineUp,
|
||||
kOneLineDown,
|
||||
kPageUp,
|
||||
kPageDown
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
mutable hsTArray<wchar_t> fBuffer; // Because AcquireArray() isn't const
|
||||
|
||||
hsTArray<Int32> fLineStarts;
|
||||
UInt16 fLineHeight, fCurrCursorX, fCurrCursorY;
|
||||
Int32 fCursorPos, fLastCursorLine;
|
||||
hsBool fIgnoreNextKey, fReadyToRender;
|
||||
hsBounds3Ext fLastP2PArea;
|
||||
Int8 fLockCount;
|
||||
UInt8 fCalcedFontSize; // The font size that we calced our line height at
|
||||
|
||||
UInt8 fLastKeyModifiers;
|
||||
wchar_t fLastKeyPressed;
|
||||
|
||||
static wchar_t fColorCodeChar, fStyleCodeChar;
|
||||
static UInt32 fColorCodeSize, fStyleCodeSize;
|
||||
|
||||
wchar_t fLastDeadKey; // if the previous key was a dead key, its value goes here
|
||||
wchar_t fDeadKeyConverter[256][256]; // first index is the dead key, second index is the char to combine it with
|
||||
|
||||
void SetupDeadKeyConverter();
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual void IPostSetUpDynTextMap( void );
|
||||
virtual void IUpdate( void );
|
||||
void IUpdate( Int32 startLine, Int32 endLine );
|
||||
|
||||
friend class pfMLScrollProc;
|
||||
|
||||
pfGUIValueCtrl *fScrollControl;
|
||||
pfMLScrollProc *fScrollProc;
|
||||
Int32 fScrollPos;
|
||||
Int32 fBufferLimit;
|
||||
|
||||
pfGUIMultiLineEditCtrl *fNextCtrl; // used for linking multiple controls together to share a buffer
|
||||
pfGUIMultiLineEditCtrl *fPrevCtrl;
|
||||
|
||||
pfGUIMultiLineEditProc *fEventProc; // where we send events to
|
||||
|
||||
std::string fFontFace;
|
||||
hsColorRGBA fFontColor;
|
||||
UInt8 fFontSize;
|
||||
UInt8 fFontStyle;
|
||||
enum flagsSet
|
||||
{
|
||||
kFontFaceSet = 1,
|
||||
kFontColorSet = 2,
|
||||
kFontSizeSet = 4,
|
||||
kFontStyleSet = 8
|
||||
};
|
||||
UInt8 fFontFlagsSet;
|
||||
|
||||
int fTopMargin,fLeftMargin,fBottomMargin,fRightMargin;
|
||||
|
||||
void IMoveCursor( Direction dir );
|
||||
void IMoveCursorTo( Int32 position ); // Updates selection
|
||||
void ISetCursor( Int32 newPosition ); // Doesn't update selection
|
||||
|
||||
Int32 IRecalcLineStarts( Int32 startingLine, hsBool force, hsBool dontUpdate = false );
|
||||
void IRecalcFromCursor( hsBool forceUpdate = false );
|
||||
Int32 IFindCursorLine( Int32 cursorPos = -1 ) const;
|
||||
hsBool IStoreLineStart( UInt32 line, Int32 start );
|
||||
void IOffsetLineStarts( UInt32 position, Int32 offset, hsBool offsetSelectionEnd = false );
|
||||
Int32 IPointToPosition( Int16 x, Int16 y, hsBool searchOutsideBounds = false );
|
||||
Int32 ICalcNumVisibleLines( void ) const;
|
||||
|
||||
void IReadColorCode( Int32 &pos, hsColorRGBA &color ) const;
|
||||
void IReadStyleCode( Int32 &pos, UInt8 &fontStyle ) const;
|
||||
UInt32 IRenderLine( UInt16 x, UInt16 y, Int32 start, Int32 end, hsBool dontRender = false );
|
||||
hsBool IFindLastColorCode( Int32 pos, hsColorRGBA &color, hsBool ignoreFirstCharacter = false ) const;
|
||||
hsBool IFindLastStyleCode( Int32 pos, UInt8 &style, hsBool ignoreFirstCharacter = false ) const;
|
||||
|
||||
inline static bool IIsCodeChar( const wchar_t c );
|
||||
inline static bool IIsRenderable( const wchar_t c );
|
||||
inline static Int32 IOffsetToNextChar( wchar_t stringChar );
|
||||
inline Int32 IOffsetToNextCharFromPos( Int32 pos ) const;
|
||||
|
||||
void IActuallyInsertColor( Int32 pos, hsColorRGBA &color );
|
||||
void IActuallyInsertStyle( Int32 pos, UInt8 style );
|
||||
|
||||
void IUpdateScrollRange( void );
|
||||
|
||||
wchar_t *ICopyRange( Int32 start, Int32 end ) const;
|
||||
|
||||
Int32 ICharPosToBufferPos( Int32 charPos ) const;
|
||||
|
||||
void IUpdateBuffer();
|
||||
void IUpdateLineStarts();
|
||||
void ISetGlobalBuffer();
|
||||
void ISetLineStarts(hsTArray<Int32> lineStarts);
|
||||
|
||||
void IHitEndOfControlList(Int32 cursorPos);
|
||||
void IHitBeginningOfControlList(Int32 cursorPos);
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kRefScrollCtrl = kRefDerivedStart
|
||||
};
|
||||
|
||||
pfGUIMultiLineEditCtrl();
|
||||
virtual ~pfGUIMultiLineEditCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIMultiLineEditCtrl );
|
||||
GETINTERFACE_ANY( pfGUIMultiLineEditCtrl, pfGUIControlMod );
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual hsBool HandleKeyPress( char key, UInt8 modifiers );
|
||||
virtual hsBool HandleKeyEvent( pfGameGUIMgr::EventType event, plKeyDef key, UInt8 modifiers );
|
||||
|
||||
virtual void PurgeDynaTextMapImage();
|
||||
|
||||
// Extended event types
|
||||
enum ExtendedEvents
|
||||
{
|
||||
kValueChanging,
|
||||
kScrollPosChanged,
|
||||
kKeyPressedEvent
|
||||
};
|
||||
|
||||
void SetScrollPosition( Int32 topLine );
|
||||
void MoveCursor( Direction dir );
|
||||
|
||||
void InsertChar( char c );
|
||||
void InsertChar( wchar_t c);
|
||||
void InsertString( const char *string );
|
||||
void InsertString( const wchar_t *string );
|
||||
void InsertColor( hsColorRGBA &color );
|
||||
void InsertStyle( UInt8 fontStyle );
|
||||
void DeleteChar( void );
|
||||
void ClearBuffer( void );
|
||||
void SetBuffer( const char *asciiText );
|
||||
void SetBuffer( const wchar_t *asciiText );
|
||||
void SetBuffer( const UInt8 *codedText, UInt32 length );
|
||||
void SetBuffer( const UInt16 *codedText, UInt32 length );
|
||||
char *GetNonCodedBuffer( void ) const;
|
||||
wchar_t *GetNonCodedBufferW( void ) const;
|
||||
UInt8 *GetCodedBuffer( UInt32 &length ) const;
|
||||
UInt16 *GetCodedBufferW( UInt32 &length ) const;
|
||||
UInt32 GetBufferSize();
|
||||
|
||||
void SetBufferLimit(Int32 limit) { fBufferLimit = limit; }
|
||||
Int32 GetBufferLimit() { return fBufferLimit; }
|
||||
|
||||
void GetThisKeyPressed( char &key, UInt8 &modifiers ) const { key = (char)fLastKeyPressed; modifiers = fLastKeyModifiers; }
|
||||
|
||||
void Lock( void );
|
||||
void Unlock( void );
|
||||
hsBool IsLocked( void ) const { return ( fLockCount > 0 ) ? true : false; }
|
||||
|
||||
void SetScrollEnable( hsBool state );
|
||||
|
||||
void ForceUpdate() {/*IRecalcLineStarts(0,true);*/IUpdateLineStarts(); IUpdate();}
|
||||
|
||||
void SetNext( pfGUIMultiLineEditCtrl *newNext );
|
||||
void ClearNext();
|
||||
void SetPrev( pfGUIMultiLineEditCtrl *newPrev );
|
||||
void ClearPrev();
|
||||
void SetEventProc( pfGUIMultiLineEditProc *eventProc );
|
||||
void ClearEventProc();
|
||||
Int32 GetFirstVisibleLine();
|
||||
Int32 GetLastVisibleLine();
|
||||
Int32 GetNumVisibleLines() {return ICalcNumVisibleLines();}
|
||||
void SetGlobalStartLine(Int32 line);
|
||||
|
||||
void SetCursorToLoc(Int32 loc) {ISetCursor(loc);}
|
||||
|
||||
void SetMargins(int top, int left, int bottom, int right);
|
||||
|
||||
UInt8 GetFontSize() {return fFontSize;} // because we're too cool to use the color scheme crap
|
||||
|
||||
void SetFontFace(std::string fontFace);
|
||||
void SetFontColor(hsColorRGBA fontColor) {fFontColor = fontColor; fFontFlagsSet |= kFontColorSet;}
|
||||
void SetFontSize(UInt8 fontSize);
|
||||
void SetFontStyle(UInt8 fontStyle) {fFontStyle = fontStyle; fFontFlagsSet |= kFontStyleSet;}
|
||||
|
||||
hsBool ShowingBeginningOfBuffer();
|
||||
hsBool ShowingEndOfBuffer();
|
||||
|
||||
void DeleteLinesFromTop(int numLines); // cursor and scroll position might be off after this call, not valid on connected controls
|
||||
};
|
||||
|
||||
#endif // _pfGUIMultiLineEditCtrl_h
|
@ -0,0 +1,940 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIPopUpMenu Header //
|
||||
// //
|
||||
// Pop-up menus are really just dialogs that know how to create themselves //
|
||||
// and create buttons on themselves to simulate a menu (after all, that's //
|
||||
// all a menu really is anyway). //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIPopUpMenu.h"
|
||||
#include "pfGUIMenuItem.h"
|
||||
#include "pfGUIButtonMod.h"
|
||||
#include "pfGUIDialogHandlers.h"
|
||||
#include "pfGUIDialogNotifyProc.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
#include "pfGUICtrlGenerator.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
#include "../plSurface/hsGMaterial.h"
|
||||
#include "../plSurface/plLayer.h"
|
||||
#include "../plGImage/plDynamicTextMap.h"
|
||||
#include "../plMessage/plLayRefMsg.h"
|
||||
|
||||
#include "../pnSceneObject/plSceneObject.h"
|
||||
#include "../pnSceneObject/plDrawInterface.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
#include "../pnMessage/plIntRefMsg.h"
|
||||
#include "../pnMessage/plObjRefMsg.h"
|
||||
#include "../pnMessage/plNodeRefMsg.h"
|
||||
|
||||
#include "../plScene/plPostEffectMod.h"
|
||||
#include "../plScene/plSceneNode.h"
|
||||
#include "../pnMessage/plClientMsg.h"
|
||||
|
||||
#include "plViewTransform.h"
|
||||
#include "../plPipeline/plDebugText.h"
|
||||
|
||||
|
||||
class pfPopUpKeyGenerator
|
||||
{
|
||||
public:
|
||||
char fPrefix[ 128 ];
|
||||
UInt32 fKeyCount;
|
||||
plLocation fLoc;
|
||||
|
||||
pfPopUpKeyGenerator( const char *p, const plLocation &loc )
|
||||
{
|
||||
strcpy( fPrefix, p );
|
||||
fLoc = loc;
|
||||
}
|
||||
|
||||
plKey CreateKey( hsKeyedObject *ko )
|
||||
{
|
||||
char name[ 256 ];
|
||||
sprintf( name, "%s-%d", fPrefix, fKeyCount++ );
|
||||
|
||||
return hsgResMgr::ResMgr()->NewKey( name, ko, fLoc );
|
||||
}
|
||||
};
|
||||
|
||||
//// Router Proc So The Parent Can Handle Click Events ///////////////////////
|
||||
|
||||
class pfGUIMenuItemProc : public pfGUICtrlProcObject
|
||||
{
|
||||
protected:
|
||||
|
||||
pfGUIPopUpMenu *fParent;
|
||||
UInt32 fIndex;
|
||||
|
||||
public:
|
||||
|
||||
pfGUIMenuItemProc( pfGUIPopUpMenu *parent, UInt32 idx )
|
||||
{
|
||||
fParent = parent;
|
||||
fIndex = idx;
|
||||
}
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl )
|
||||
{
|
||||
fParent->IHandleMenuSomething( fIndex, ctrl );
|
||||
}
|
||||
|
||||
virtual void HandleExtendedEvent( pfGUIControlMod *ctrl, UInt32 event )
|
||||
{
|
||||
fParent->IHandleMenuSomething( fIndex, ctrl, (Int32)event );
|
||||
}
|
||||
};
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIPopUpMenu::pfGUIPopUpMenu()
|
||||
{
|
||||
fNeedsRebuilding = false;
|
||||
fParent = nil;
|
||||
fKeyGen = nil;
|
||||
fSubMenuOpen = -1;
|
||||
SetFlag( kModalOutsideMenus );
|
||||
fMargin = 4;
|
||||
fSkin = nil;
|
||||
fWaitingForSkin = false;
|
||||
|
||||
fParentNode = nil;
|
||||
fOriginX = fOriginY = 0.f;
|
||||
fOriginAnchor = nil;
|
||||
fOriginContext = nil;
|
||||
|
||||
fAlignment = kAlignDownRight;
|
||||
}
|
||||
|
||||
pfGUIPopUpMenu::~pfGUIPopUpMenu()
|
||||
{
|
||||
SetSkin( nil );
|
||||
|
||||
// if( fParentNode != nil )
|
||||
// fParentNode->GetKey()->UnRefObject();
|
||||
|
||||
ITearDownMenu();
|
||||
ClearItems();
|
||||
|
||||
delete fKeyGen;
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIPopUpMenu::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plGenRefMsg *ref = plGenRefMsg::ConvertNoRef( msg );
|
||||
if( ref != nil )
|
||||
{
|
||||
if( ref->fType == kRefSkin )
|
||||
{
|
||||
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
fSkin = pfGUISkin::ConvertNoRef( ref->GetRef() );
|
||||
fWaitingForSkin = false;
|
||||
}
|
||||
else
|
||||
fSkin = nil;
|
||||
|
||||
fNeedsRebuilding = true;
|
||||
if( IsVisible() )
|
||||
{
|
||||
// Rebuild NOW
|
||||
ITearDownMenu();
|
||||
IBuildMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if( ref->fType == kRefSubMenu )
|
||||
{
|
||||
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fMenuItems[ ref->fWhich ].fSubMenu = pfGUIPopUpMenu::ConvertNoRef( ref->GetRef() );
|
||||
else
|
||||
fMenuItems[ ref->fWhich ].fSubMenu = nil;
|
||||
return true;
|
||||
}
|
||||
else if( ref->fType == kRefOriginAnchor )
|
||||
{
|
||||
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fOriginAnchor = plSceneObject::ConvertNoRef( ref->GetRef() );
|
||||
else
|
||||
fOriginAnchor = nil;
|
||||
return true;
|
||||
}
|
||||
else if( ref->fType == kRefOriginContext )
|
||||
{
|
||||
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fOriginContext = pfGUIDialogMod::ConvertNoRef( ref->GetRef() );
|
||||
else
|
||||
fOriginContext = nil;
|
||||
return true;
|
||||
}
|
||||
else if( ref->fType == kRefParentNode )
|
||||
{
|
||||
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fParentNode = plSceneNode::ConvertNoRef( ref->GetRef() );
|
||||
else
|
||||
fParentNode = nil;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return pfGUIDialogMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIPopUpMenu::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIDialogMod::Read( s, mgr );
|
||||
|
||||
// In case we need it...
|
||||
fKeyGen = TRACKED_NEW pfPopUpKeyGenerator( GetName(), GetKey()->GetUoid().GetLocation() );
|
||||
|
||||
fOriginX = fOriginY = -1.f;
|
||||
|
||||
fMargin = s->ReadSwap16();
|
||||
|
||||
UInt32 i, count = s->ReadSwap32();
|
||||
fMenuItems.SetCountAndZero( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
char readTemp[ 256 ];
|
||||
s->Read( sizeof( readTemp ), readTemp );
|
||||
wchar_t *wReadTemp = hsStringToWString( readTemp );
|
||||
fMenuItems[ i ].fName = wReadTemp;
|
||||
delete [] wReadTemp;
|
||||
|
||||
fMenuItems[ i ].fHandler = pfGUICtrlProcWriteableObject::Read( s );
|
||||
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, i, kRefSubMenu ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefSkin ), plRefFlags::kActiveRef );
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefOriginAnchor ), plRefFlags::kPassiveRef );
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefOriginContext ), plRefFlags::kPassiveRef );
|
||||
|
||||
fAlignment = (Alignment)s->ReadByte();
|
||||
|
||||
fNeedsRebuilding = true;
|
||||
}
|
||||
|
||||
void pfGUIPopUpMenu::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIDialogMod::Write( s, mgr );
|
||||
|
||||
|
||||
s->WriteSwap16( fMargin );
|
||||
|
||||
s->WriteSwap32( fMenuItems.GetCount() );
|
||||
UInt32 i;
|
||||
for( i = 0; i < fMenuItems.GetCount(); i++ )
|
||||
{
|
||||
char writeTemp[ 256 ];
|
||||
char *sName = hsWStringToString( fMenuItems[ i ].fName.c_str() );
|
||||
strncpy( writeTemp, sName, sizeof( writeTemp ) );
|
||||
delete [] sName;
|
||||
s->Write( sizeof( writeTemp ), writeTemp );
|
||||
|
||||
// Write the handler out (if it's not a writeable, damn you)
|
||||
pfGUICtrlProcWriteableObject::Write( (pfGUICtrlProcWriteableObject *)fMenuItems[ i ].fHandler, s );
|
||||
|
||||
mgr->WriteKey( s, fMenuItems[ i ].fSubMenu );
|
||||
}
|
||||
|
||||
// Note: we force parentNode to nil here because we only use it when we dynamically
|
||||
// create nodes at runtime and need to unref and destroy them later. Since we're
|
||||
// reading from disk, we'll already have a sceneNode somewhere, so we don't need
|
||||
// this.
|
||||
fParentNode = nil;
|
||||
|
||||
mgr->WriteKey( s, fSkin );
|
||||
mgr->WriteKey( s, fOriginAnchor );
|
||||
mgr->WriteKey( s, fOriginContext );
|
||||
|
||||
s->WriteByte( (UInt8)fAlignment );
|
||||
}
|
||||
|
||||
void pfGUIPopUpMenu::SetOriginAnchor( plSceneObject *anchor, pfGUIDialogMod *context )
|
||||
{
|
||||
fOriginAnchor = anchor;
|
||||
fOriginContext = context;
|
||||
hsgResMgr::ResMgr()->AddViaNotify( fOriginAnchor->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefOriginAnchor ), plRefFlags::kPassiveRef );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( fOriginContext->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefOriginContext ), plRefFlags::kPassiveRef );
|
||||
}
|
||||
|
||||
//// SetEnabled //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIPopUpMenu::SetEnabled( hsBool e )
|
||||
{
|
||||
if( e && fNeedsRebuilding )
|
||||
{
|
||||
// Make sure our menu is rebuilt before enabling
|
||||
ITearDownMenu();
|
||||
IBuildMenu();
|
||||
}
|
||||
else if( !e )
|
||||
{
|
||||
if( fParent != nil )
|
||||
pfGUIPopUpMenu::ConvertNoRef( fParent )->fSubMenuOpen = -1;
|
||||
|
||||
// Hide our submenus if we have any open
|
||||
if( fSubMenuOpen != -1 )
|
||||
{
|
||||
fMenuItems[ fSubMenuOpen ].fSubMenu->Hide();
|
||||
fSubMenuOpen = -1;
|
||||
}
|
||||
}
|
||||
|
||||
pfGUIDialogMod::SetEnabled( e );
|
||||
}
|
||||
|
||||
void pfGUIPopUpMenu::Show( hsScalar x, hsScalar y )
|
||||
{
|
||||
fOriginX = x;
|
||||
fOriginY = y;
|
||||
pfGUIDialogMod::Show(); // C++ is kinda stupid if it can't find this naturally
|
||||
ISeekToOrigin();
|
||||
}
|
||||
|
||||
void pfGUIPopUpMenu::ISeekToOrigin( void )
|
||||
{
|
||||
#if 0
|
||||
UInt32 i;
|
||||
float x = 0.5f/*fOriginX*/, y = fOriginY;
|
||||
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ] != nil )
|
||||
{
|
||||
fControls[ i ]->SetObjectCenter( x, y );
|
||||
|
||||
// const hsBounds3 &bnds = fControls[ i ]->GetBounds();
|
||||
y += fMenuItems[ i ].fYOffsetToNext;//bnds.GetMaxs().fY - bnds.GetMins().fY;
|
||||
|
||||
/* hsMatrix44 p2l, l2p = GetTarget()->GetLocalToWorld();
|
||||
|
||||
hsPoint3 center, origin;
|
||||
ScreenToWorldPoint( fOriginX, fOriginY, 100.f, center );
|
||||
ScreenToWorldPoint( 0.f, 0.f, 100.f, origin );
|
||||
|
||||
center = origin - center;
|
||||
|
||||
center.fZ = 0.f;
|
||||
l2p.SetTranslate( ¢er );
|
||||
l2p.GetInverse( &p2l );
|
||||
|
||||
GetTarget()->SetTransform( l2p, p2l );
|
||||
*/ }
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//// IHandleMenuSomething ////////////////////////////////////////////////////
|
||||
// Handles a normal event from one of the item controls.
|
||||
|
||||
void pfGUIPopUpMenu::IHandleMenuSomething( UInt32 idx, pfGUIControlMod *ctrl, Int32 extended )
|
||||
{
|
||||
if( extended != -1 )
|
||||
{
|
||||
if( fSubMenuOpen != -1 && fSubMenuOpen != idx )
|
||||
{
|
||||
// Better close the submenu(s)
|
||||
fMenuItems[ fSubMenuOpen ].fSubMenu->Hide();
|
||||
fSubMenuOpen = -1;
|
||||
}
|
||||
|
||||
if( extended == pfGUIMenuItem::kMouseHover && fMenuItems[ idx ].fSubMenu != nil )
|
||||
{
|
||||
// Open new submenu
|
||||
const hsBounds3 &bnds = ctrl->GetBounds();
|
||||
fMenuItems[ idx ].fSubMenu->Show( bnds.GetMaxs().fX, bnds.GetMins().fY );
|
||||
fSubMenuOpen = idx;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( fMenuItems[ idx ].fHandler != nil )
|
||||
fMenuItems[ idx ].fHandler->DoSomething( ctrl );
|
||||
|
||||
// If item isn't a sub-menu, close this menu. Else add to list of menus to close
|
||||
// once the smallest submenu goes away
|
||||
if( fMenuItems[ idx ].fSubMenu == nil )
|
||||
{
|
||||
// Basically, we want to hide ourselves and as many up in the chain of command as
|
||||
// can be hidden
|
||||
pfGUIPopUpMenu *menu = this;
|
||||
while( menu != nil && !menu->HasFlag( kStayOpenAfterClick ) )
|
||||
{
|
||||
menu->Hide();
|
||||
menu = pfGUIPopUpMenu::ConvertNoRef( menu->fParent );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show relative to the corner of our current item
|
||||
const hsBounds3 &bnds = ctrl->GetBounds();
|
||||
fMenuItems[ idx ].fSubMenu->Show( bnds.GetMaxs().fX, bnds.GetMins().fY );
|
||||
fSubMenuOpen = idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// IBuildMenu //////////////////////////////////////////////////////////////
|
||||
// Given the list of menu items, builds our set of dynamic buttons
|
||||
|
||||
hsBool pfGUIPopUpMenu::IBuildMenu( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
if( fWaitingForSkin && fSkin == nil )
|
||||
return false; // Still waiting to get our skin before building
|
||||
|
||||
pfGUIColorScheme *scheme = TRACKED_NEW pfGUIColorScheme();
|
||||
scheme->fForeColor.Set( 0, 0, 0, 1 );
|
||||
scheme->fBackColor.Set( 1, 1, 1, 1 );
|
||||
|
||||
// If we don't have origin points, get them from translating our anchor
|
||||
if( fOriginX == -1 || fOriginY == -1 && fOriginAnchor != nil )
|
||||
{
|
||||
hsPoint3 scrnPt;
|
||||
const plDrawInterface *di = fOriginAnchor->GetDrawInterface();
|
||||
if( di != nil )
|
||||
{
|
||||
scrnPt = di->GetLocalBounds().GetCenter();
|
||||
scrnPt = fOriginAnchor->GetLocalToWorld() * scrnPt;
|
||||
}
|
||||
else
|
||||
scrnPt = fOriginAnchor->GetLocalToWorld().GetTranslate();
|
||||
if( fOriginContext != nil )
|
||||
scrnPt = fOriginContext->WorldToScreenPoint( scrnPt );
|
||||
else
|
||||
scrnPt = WorldToScreenPoint( scrnPt );
|
||||
|
||||
if( fOriginX == -1 )
|
||||
fOriginX = scrnPt.fX;
|
||||
if( fOriginY == -1 )
|
||||
fOriginY = scrnPt.fY;
|
||||
}
|
||||
|
||||
float x = fOriginX, y = fOriginY;
|
||||
float width = 0.f, height = 0.f;
|
||||
float topMargin = ( fSkin != nil ) ? fSkin->GetBorderMargin() : 0.f;
|
||||
|
||||
// First step: loop through and calculate the size of our menu
|
||||
// The PROBLEM is that we can't do that unless we have a friggin surface on
|
||||
// which to calculate the text extents! So sadly, we're going to have to create
|
||||
// a whole new DTMap and use it to calculate some stuff
|
||||
plDynamicTextMap *scratch = TRACKED_NEW plDynamicTextMap( 8, 8, false );
|
||||
scratch->SetFont( scheme->fFontFace, scheme->fFontSize, scheme->fFontFlags, true );
|
||||
for( i = 0; i < fMenuItems.GetCount(); i++ )
|
||||
{
|
||||
UInt16 thisW, thisH;
|
||||
thisW = scratch->CalcStringWidth( fMenuItems[ i ].fName.c_str(), &thisH );
|
||||
if( fMenuItems[ i ].fSubMenu != nil )
|
||||
{
|
||||
if( fSkin != nil )
|
||||
thisW += 4 + ( fSkin->GetElement( pfGUISkin::kSubMenuArrow ).fWidth << 1 );
|
||||
else
|
||||
thisW += scratch->CalcStringWidth( " >>", nil );
|
||||
}
|
||||
thisH += 2; // Give us at least one pixel on each side
|
||||
|
||||
int margin = fMargin;
|
||||
if( fSkin != nil )
|
||||
margin = fSkin->GetBorderMargin() << 1;
|
||||
|
||||
if( width < thisW + margin )
|
||||
width = (float)(thisW + margin);
|
||||
|
||||
if( fSkin != nil )
|
||||
margin = fSkin->GetItemMargin() << 1;
|
||||
|
||||
if( height < thisH + margin )
|
||||
height = (float)(thisH + margin);
|
||||
}
|
||||
delete scratch;
|
||||
|
||||
width += 4; // give us a little space, just in case
|
||||
|
||||
UInt32 scrnWidth, scrnHeight;
|
||||
// A cheat here, I know, but I'm lazy
|
||||
plDebugText::Instance().GetScreenSize( &scrnWidth, &scrnHeight );
|
||||
|
||||
// Use the same base res calc that dtMaps use
|
||||
if( !HasFlag( kScaleWithResolution ) )
|
||||
{
|
||||
// Just use what we were passed in
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scale with the resolution so that we take up the same % of screen space no matter what resolution
|
||||
// Assume a base "resolution" of 1024xX, where X is such that the ratio "1024/X = scrnWidth/scrnHt" holds
|
||||
const int kBaseScaleRes = 1024;
|
||||
scrnHeight = ( scrnHeight * kBaseScaleRes ) / scrnWidth;
|
||||
scrnWidth = kBaseScaleRes;
|
||||
}
|
||||
|
||||
width /= (float)scrnWidth;
|
||||
height /= (float)scrnHeight;
|
||||
topMargin /= (float)scrnHeight;
|
||||
|
||||
switch( fAlignment )
|
||||
{
|
||||
case kAlignUpLeft: x -= width; y -= height * fMenuItems.GetCount(); break;
|
||||
case kAlignUpRight: y -= height * fMenuItems.GetCount(); break;
|
||||
case kAlignDownLeft: x -= width; break;
|
||||
case kAlignDownRight: break;
|
||||
}
|
||||
|
||||
if( y + height * fMenuItems.GetCount() > 1.f )
|
||||
{
|
||||
// Make sure we don't go off the bottom
|
||||
y = 1.f - height * fMenuItems.GetCount();
|
||||
}
|
||||
// And the top (takes precedence)
|
||||
if( y < 0.f )
|
||||
y = 0.f;
|
||||
|
||||
// Control positions are in the lower left corner, so increment Y by 1 control height first
|
||||
y += height;// + topMargin;
|
||||
|
||||
hsTArray<pfGUIPopUpMenu *> buildList;
|
||||
|
||||
for( i = 0; i < fMenuItems.GetCount(); i++ )
|
||||
{
|
||||
hsGMaterial *mat = ICreateDynMaterial();
|
||||
|
||||
float thisMargin = ( i == 0 || i == fMenuItems.GetCount() - 1 ) ? topMargin : 0.f;
|
||||
float thisOffset = ( i == fMenuItems.GetCount() - 1 ) ? topMargin : 0.f;
|
||||
|
||||
pfGUIMenuItem *button = pfGUIMenuItem::ConvertNoRef( pfGUICtrlGenerator::Instance().CreateRectButton( this, fMenuItems[ i ].fName.c_str(), x, y + thisOffset, width, height + thisMargin, mat, true ) );
|
||||
if( button != nil )
|
||||
{
|
||||
button->SetColorScheme( scheme );
|
||||
button->SetName( fMenuItems[ i ].fName.c_str() );
|
||||
button->SetHandler( TRACKED_NEW pfGUIMenuItemProc( this, i ) );
|
||||
// make the tag ID the position in the menu list
|
||||
button->SetTagID(i);
|
||||
button->SetDynTextMap( mat->GetLayer( 0 ), plDynamicTextMap::ConvertNoRef( mat->GetLayer( 0 )->GetTexture() ) );
|
||||
button->SetFlag( pfGUIMenuItem::kReportHovers );
|
||||
button->SetSkin( fSkin, ( i == 0 ) ? pfGUIMenuItem::kTop : ( i == fMenuItems.GetCount() - 1 ) ? pfGUIMenuItem::kBottom : pfGUIMenuItem::kMiddle );
|
||||
if( fMenuItems[ i ].fSubMenu != nil )
|
||||
{
|
||||
button->SetFlag( pfGUIMenuItem::kDrawSubMenuArrow );
|
||||
buildList.Append( pfGUIPopUpMenu::ConvertNoRef( fMenuItems[ i ].fSubMenu ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Tiny bit of overlap to prevent gaps
|
||||
fMenuItems[ i ].fYOffsetToNext = height + thisOffset;
|
||||
y += height + thisOffset;// - ( 1.f / kBaseScaleResY );
|
||||
}
|
||||
|
||||
fNeedsRebuilding = false;
|
||||
|
||||
#if 0
|
||||
// Finally, go down our list of submenus and rebuild them, since they'll need to be rebuilt soon anyway,
|
||||
// and at least this way it's all in one pass
|
||||
|
||||
// Also, we need to bump the tag ID used, such as adding parent menuItem TagID * 100.. or something
|
||||
|
||||
// Disabled because right now we can't move menus, which is required for this to work
|
||||
for( i = 0; i < buildList.GetCount(); i++ )
|
||||
buildList[ i ]->IBuildMenu();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//// ITearDownMenu ///////////////////////////////////////////////////////////
|
||||
// Destroys all of our dynamic controls representing the menu
|
||||
|
||||
void pfGUIPopUpMenu::ITearDownMenu( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
{
|
||||
if( fControls[ i ] != nil )
|
||||
{
|
||||
// It's not enough to release the key, we have to have the sceneNode release the key, too.
|
||||
// Easy enough to do by just setting it's sn to nil
|
||||
if( fControls[ i ]->GetTarget() != nil )
|
||||
fControls[ i ]->GetTarget()->SetSceneNode( nil );
|
||||
|
||||
// Now release it from us
|
||||
GetKey()->Release( fControls[ i ]->GetKey() );
|
||||
}
|
||||
}
|
||||
|
||||
fNeedsRebuilding = true;
|
||||
}
|
||||
|
||||
//// HandleMouseEvent ////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIPopUpMenu::HandleMouseEvent( pfGameGUIMgr::EventType event, hsScalar mouseX, hsScalar mouseY,
|
||||
UInt8 modifiers )
|
||||
{
|
||||
hsBool r = pfGUIDialogMod::HandleMouseEvent( event, mouseX, mouseY, modifiers );
|
||||
if( r == false && event == pfGameGUIMgr::kMouseUp )
|
||||
{
|
||||
// We don't want to be active anymore!
|
||||
if( !HasFlag( kStayOpenAfterClick ) )
|
||||
{
|
||||
Hide();
|
||||
|
||||
// Now we pass the click to our parent. Why? Because it's possible that someone above us
|
||||
// will either a) also want to hide (cancel the entire menu selection) or b) select
|
||||
// another option
|
||||
if( fParent != nil )
|
||||
return fParent->HandleMouseEvent( event, mouseX, mouseY, modifiers );
|
||||
}
|
||||
}
|
||||
|
||||
return ( fParent != nil ) ? r : ( HasFlag( kModalOutsideMenus ) || ( fSubMenuOpen != -1 ) );
|
||||
}
|
||||
|
||||
//// ClearItems //////////////////////////////////////////////////////////////
|
||||
// Clears the list of template items
|
||||
|
||||
void pfGUIPopUpMenu::ClearItems( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fMenuItems.GetCount(); i++ )
|
||||
{
|
||||
if( fMenuItems[ i ].fHandler != nil )
|
||||
{
|
||||
if( fMenuItems[ i ].fHandler->DecRef() )
|
||||
delete fMenuItems[ i ].fHandler;
|
||||
}
|
||||
}
|
||||
|
||||
fMenuItems.Reset();
|
||||
|
||||
fNeedsRebuilding = true;
|
||||
}
|
||||
|
||||
//// AddItem /////////////////////////////////////////////////////////////////
|
||||
// Append a new item to the list of things to build the menu from
|
||||
|
||||
void pfGUIPopUpMenu::AddItem( const char *name, pfGUICtrlProcObject *handler, pfGUIPopUpMenu *subMenu )
|
||||
{
|
||||
wchar_t *wName = hsStringToWString(name);
|
||||
AddItem(wName,handler,subMenu);
|
||||
delete [] wName;
|
||||
}
|
||||
|
||||
void pfGUIPopUpMenu::AddItem( const wchar_t *name, pfGUICtrlProcObject *handler, pfGUIPopUpMenu *subMenu )
|
||||
{
|
||||
pfMenuItem newItem;
|
||||
|
||||
|
||||
newItem.fName = name;
|
||||
newItem.fHandler = handler;
|
||||
if( newItem.fHandler != nil )
|
||||
newItem.fHandler->IncRef();
|
||||
newItem.fSubMenu = subMenu;
|
||||
|
||||
if( subMenu != nil )
|
||||
subMenu->fParent = this;
|
||||
|
||||
fMenuItems.Append( newItem );
|
||||
|
||||
fNeedsRebuilding = true;
|
||||
}
|
||||
|
||||
//// ICreateDynMaterial //////////////////////////////////////////////////////
|
||||
// Creates the hsGMaterial tree for a single layer with a plDynamicTextMap.
|
||||
|
||||
hsGMaterial *pfGUIPopUpMenu::ICreateDynMaterial( void )
|
||||
{
|
||||
hsColorRGBA black, white;
|
||||
|
||||
|
||||
// Create the new dynTextMap
|
||||
plDynamicTextMap *textMap = TRACKED_NEW plDynamicTextMap();
|
||||
fKeyGen->CreateKey( textMap );
|
||||
|
||||
// Create the material
|
||||
hsGMaterial *material = TRACKED_NEW hsGMaterial;
|
||||
fKeyGen->CreateKey( material );
|
||||
|
||||
// Create the layer and attach
|
||||
plLayer *lay = material->MakeBaseLayer();
|
||||
white.Set( 1.f,1.f,1.f,1.f );
|
||||
black.Set( 0.f,0.f,0.f,1.f );
|
||||
|
||||
lay->SetRuntimeColor( black );
|
||||
lay->SetPreshadeColor( black );
|
||||
lay->SetAmbientColor( white );
|
||||
lay->SetClampFlags( hsGMatState::kClampTexture );
|
||||
|
||||
// Do sendRef here, since we're going to need it set pretty darned quick
|
||||
hsgResMgr::ResMgr()->SendRef( textMap->GetKey(), TRACKED_NEW plLayRefMsg( lay->GetKey(), plRefMsg::kOnCreate, 0, plLayRefMsg::kTexture ), plRefFlags::kActiveRef );
|
||||
|
||||
return material;
|
||||
|
||||
}
|
||||
|
||||
//// Build ///////////////////////////////////////////////////////////////////
|
||||
// Constructs a shiny new pop-up menu at runtime, complete with trimmings
|
||||
|
||||
#include "../plJPEG/plJPEG.h"
|
||||
|
||||
pfGUIPopUpMenu *pfGUIPopUpMenu::Build( const char *name, pfGUIDialogMod *parent, hsScalar x, hsScalar y, const plLocation &destLoc )
|
||||
{
|
||||
float fovX, fovY;
|
||||
|
||||
|
||||
// Create the menu and give it a key gen
|
||||
pfGUIPopUpMenu *menu = TRACKED_NEW pfGUIPopUpMenu();
|
||||
menu->fKeyGen = TRACKED_NEW pfPopUpKeyGenerator( name, destLoc );
|
||||
menu->fKeyGen->CreateKey( menu );
|
||||
|
||||
menu->fOriginX = x;
|
||||
menu->fOriginY = y;
|
||||
|
||||
// By default, share the same skin as the parent
|
||||
if( parent != nil && ( (pfGUIPopUpMenu *)parent )->fSkin != nil )
|
||||
{
|
||||
menu->fWaitingForSkin = true;
|
||||
hsgResMgr::ResMgr()->SendRef( ( (pfGUIPopUpMenu *)parent )->fSkin->GetKey(), TRACKED_NEW plGenRefMsg( menu->GetKey(), plRefMsg::kOnCreate, -1, pfGUIPopUpMenu::kRefSkin ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
// HACK for now: create us a temp skin to use
|
||||
/* static pfGUISkin *skin = nil;
|
||||
if( skin == nil )
|
||||
{
|
||||
plLocation loc;
|
||||
loc.Set( 0x1425 );
|
||||
plKey skinKey = hsgResMgr::ResMgr()->FindKey( plUoid( loc, pfGUISkin::Index(), "GUISkin01_GUISkin" ) );
|
||||
menu->fWaitingForSkin = true;
|
||||
hsgResMgr::ResMgr()->AddViaNotify( skinKey, TRACKED_NEW plGenRefMsg( menu->GetKey(), plRefMsg::kOnCreate, -1, pfGUIPopUpMenu::kRefSkin ), plRefFlags::kActiveRef );
|
||||
}
|
||||
*/
|
||||
|
||||
// Create the rendermod
|
||||
plPostEffectMod *renderMod = TRACKED_NEW plPostEffectMod;
|
||||
menu->fKeyGen->CreateKey( renderMod );
|
||||
|
||||
renderMod->SetHither( 0.5f );
|
||||
renderMod->SetYon( 200.f );
|
||||
|
||||
float scrnWidth = 20.f;
|
||||
|
||||
// fovX should be such that scrnWidth is the projected width at z=100
|
||||
fovX = atan( scrnWidth / ( 2.f * 100.f ) ) * 2.f;
|
||||
fovY = fovX;// * 3.f / 4.f;
|
||||
|
||||
renderMod->SetFovX( fovX * 180.f / hsScalarPI );
|
||||
renderMod->SetFovY( fovY * 180.f / hsScalarPI );
|
||||
|
||||
// Create the sceneNode to go with it
|
||||
menu->fParentNode= TRACKED_NEW plSceneNode;
|
||||
menu->fKeyGen->CreateKey( menu->fParentNode );
|
||||
// menu->fParentNode->GetKey()->RefObject();
|
||||
hsgResMgr::ResMgr()->SendRef( menu->fParentNode->GetKey(), TRACKED_NEW plGenRefMsg( menu->GetKey(), plRefMsg::kOnCreate, 0, kRefParentNode ), plRefFlags::kActiveRef );
|
||||
|
||||
hsgResMgr::ResMgr()->AddViaNotify( menu->fParentNode->GetKey(), TRACKED_NEW plGenRefMsg( renderMod->GetKey(), plRefMsg::kOnCreate, 0, plPostEffectMod::kNodeRef ), plRefFlags::kPassiveRef );
|
||||
|
||||
menu->SetRenderMod( renderMod );
|
||||
menu->SetName( name );
|
||||
|
||||
// Create the dummy scene object to hold the menu
|
||||
plSceneObject *newObj = TRACKED_NEW plSceneObject;
|
||||
menu->fKeyGen->CreateKey( newObj );
|
||||
|
||||
// *#&$(*@&#$ need a coordIface...
|
||||
plCoordinateInterface *newCI = TRACKED_NEW plCoordinateInterface;
|
||||
menu->fKeyGen->CreateKey( newCI );
|
||||
|
||||
hsMatrix44 l2w, w2l;
|
||||
l2w.Reset();
|
||||
l2w.GetInverse( &w2l );
|
||||
|
||||
// Using SendRef here because AddViaNotify will queue the messages up, which doesn't do us any good
|
||||
// if we need these refs right away
|
||||
hsgResMgr::ResMgr()->SendRef( newCI->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface ), plRefFlags::kActiveRef );
|
||||
hsgResMgr::ResMgr()->SendRef( renderMod->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kModifier ), plRefFlags::kActiveRef );
|
||||
newObj->SetSceneNode( menu->fParentNode->GetKey() );
|
||||
newObj->SetTransform( l2w, w2l );
|
||||
|
||||
hsgResMgr::ResMgr()->SendRef( menu->GetKey(), TRACKED_NEW plObjRefMsg( newObj->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kModifier ), plRefFlags::kActiveRef );
|
||||
|
||||
// Add the menu to the GUI mgr
|
||||
plGenRefMsg *refMsg = TRACKED_NEW plGenRefMsg( pfGameGUIMgr::GetInstance()->GetKey(),
|
||||
plRefMsg::kOnCreate, 0, pfGameGUIMgr::kDlgModRef );
|
||||
hsgResMgr::ResMgr()->AddViaNotify( menu->GetKey(), refMsg, plRefFlags::kActiveRef );
|
||||
|
||||
menu->ISeekToOrigin();
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
//// SetSkin /////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIPopUpMenu::SetSkin( pfGUISkin *skin )
|
||||
{
|
||||
// Just a function wrapper for SendRef
|
||||
if( fSkin != nil )
|
||||
GetKey()->Release( fSkin->GetKey() );
|
||||
|
||||
if( skin != nil )
|
||||
{
|
||||
hsgResMgr::ResMgr()->SendRef( skin->GetKey(), TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefSkin ), plRefFlags::kActiveRef );
|
||||
fWaitingForSkin = true;
|
||||
}
|
||||
else
|
||||
fWaitingForSkin = false;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// pfGUISkin Implementation ////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pfGUISkin::pfGUISkin()
|
||||
{
|
||||
fTexture = nil;
|
||||
memset( fElements, 0, sizeof( pfSRect ) * kNumElements );
|
||||
}
|
||||
|
||||
pfGUISkin::pfGUISkin( plMipmap *texture )
|
||||
{
|
||||
fTexture = texture;
|
||||
if( fTexture != nil )
|
||||
{
|
||||
hsAssert( fTexture->GetKey() != nil, "Creating a GUI skin via a mipmap with no key!" );
|
||||
fTexture->GetKey()->RefObject();
|
||||
}
|
||||
memset( fElements, 0, sizeof( pfSRect ) * kNumElements );
|
||||
}
|
||||
|
||||
pfGUISkin::~pfGUISkin()
|
||||
{
|
||||
SetTexture( nil );
|
||||
}
|
||||
|
||||
void pfGUISkin::SetTexture( plMipmap *tex )
|
||||
{
|
||||
if( fTexture != nil && fTexture->GetKey() != nil )
|
||||
fTexture->GetKey()->UnRefObject();
|
||||
|
||||
fTexture = tex;
|
||||
if( fTexture != nil )
|
||||
{
|
||||
hsAssert( fTexture->GetKey() != nil, "Creating a GUI skin via a mipmap with no key!" );
|
||||
fTexture->GetKey()->RefObject();
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUISkin::SetElement( UInt32 idx, UInt16 x, UInt16 y, UInt16 w, UInt16 h )
|
||||
{
|
||||
fElements[ idx ].fX = x;
|
||||
fElements[ idx ].fY = y;
|
||||
fElements[ idx ].fWidth = w;
|
||||
fElements[ idx ].fHeight = h;
|
||||
}
|
||||
|
||||
void pfGUISkin::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
hsKeyedObject::Read( s, mgr );
|
||||
|
||||
s->ReadSwap( &fItemMargin );
|
||||
s->ReadSwap( &fBorderMargin );
|
||||
|
||||
UInt32 i, count;
|
||||
s->ReadSwap( &count );
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
fElements[ i ].Read( s );
|
||||
|
||||
for( ; i < kNumElements; i++ )
|
||||
fElements[ i ].Empty();
|
||||
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefMipmap ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
void pfGUISkin::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
hsKeyedObject::Write( s, mgr );
|
||||
|
||||
s->WriteSwap( fItemMargin );
|
||||
s->WriteSwap( fBorderMargin );
|
||||
|
||||
UInt32 i = kNumElements;
|
||||
s->WriteSwap( i );
|
||||
|
||||
for( i = 0; i < kNumElements; i++ )
|
||||
fElements[ i ].Write( s );
|
||||
|
||||
mgr->WriteKey( s, fTexture );
|
||||
}
|
||||
|
||||
hsBool pfGUISkin::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plGenRefMsg *ref = plGenRefMsg::ConvertNoRef( msg );
|
||||
if( ref != nil )
|
||||
{
|
||||
if( ref->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
fTexture = plMipmap::ConvertNoRef( ref->GetRef() );
|
||||
else
|
||||
fTexture = nil;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return hsKeyedObject::MsgReceive( msg );
|
||||
}
|
||||
|
||||
void pfGUISkin::pfSRect::Read( hsStream *s )
|
||||
{
|
||||
s->ReadSwap( &fX );
|
||||
s->ReadSwap( &fY );
|
||||
s->ReadSwap( &fWidth );
|
||||
s->ReadSwap( &fHeight );
|
||||
}
|
||||
|
||||
void pfGUISkin::pfSRect::Write( hsStream *s )
|
||||
{
|
||||
s->WriteSwap( fX );
|
||||
s->WriteSwap( fY );
|
||||
s->WriteSwap( fWidth );
|
||||
s->WriteSwap( fHeight );
|
||||
}
|
@ -0,0 +1,225 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIPopUpMenu Header //
|
||||
// //
|
||||
// Pop-up menus are really just dialogs that know how to create themselves //
|
||||
// and create buttons on themselves to simulate a menu (after all, that's //
|
||||
// all a menu really is anyway). //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIPopUpMenu_h
|
||||
#define _pfGUIPopUpMenu_h
|
||||
|
||||
|
||||
#include "pfGUIDialogMod.h"
|
||||
#include "hsBounds.h"
|
||||
|
||||
class plMessage;
|
||||
class pfGUIButtonMod;
|
||||
class pfPopUpKeyGenerator;
|
||||
class pfGUICtrlProcObject;
|
||||
class hsGMaterial;
|
||||
class plSceneNode;
|
||||
class pfGUIMenuItemProc;
|
||||
class pfGUISkin;
|
||||
|
||||
class pfGUIPopUpMenu : public pfGUIDialogMod
|
||||
{
|
||||
public:
|
||||
|
||||
enum Alignment
|
||||
{
|
||||
kAlignUpLeft,
|
||||
kAlignUpRight,
|
||||
kAlignDownLeft,
|
||||
kAlignDownRight // Default
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
friend class pfGUIMenuItemProc;
|
||||
|
||||
pfGUIDialogMod *fParent; // Pop-up menus also have a sense of who owns them
|
||||
plSceneNode *fParentNode;
|
||||
|
||||
pfPopUpKeyGenerator *fKeyGen; // Generates keys for our dynamic objects
|
||||
|
||||
class pfMenuItem
|
||||
{
|
||||
// Simple wrapper class that tells us how to build our menu
|
||||
public:
|
||||
std::wstring fName;
|
||||
pfGUICtrlProcObject *fHandler;
|
||||
pfGUIPopUpMenu *fSubMenu;
|
||||
float fYOffsetToNext; // Filled in by IBuildMenu()
|
||||
|
||||
pfMenuItem& operator=(const int zero) { fName = L""; fHandler = nil; fSubMenu = nil; fYOffsetToNext = 0; return *this; }
|
||||
};
|
||||
|
||||
// Array of info to rebuild our menu from. Note that this is ONLY used when rebuilding
|
||||
hsBool fNeedsRebuilding, fWaitingForSkin;
|
||||
hsScalar fOriginX, fOriginY;
|
||||
UInt16 fMargin;
|
||||
hsTArray<pfMenuItem> fMenuItems;
|
||||
Int32 fSubMenuOpen;
|
||||
|
||||
pfGUISkin *fSkin;
|
||||
|
||||
plSceneObject *fOriginAnchor;
|
||||
pfGUIDialogMod *fOriginContext;
|
||||
|
||||
Alignment fAlignment;
|
||||
|
||||
|
||||
hsBool IBuildMenu( void );
|
||||
void ITearDownMenu( void );
|
||||
|
||||
hsGMaterial *ICreateDynMaterial( void );
|
||||
|
||||
void IHandleMenuSomething( UInt32 idx, pfGUIControlMod *ctrl, Int32 extended = -1 );
|
||||
|
||||
void ISeekToOrigin( void );
|
||||
|
||||
public:
|
||||
|
||||
pfGUIPopUpMenu();
|
||||
virtual ~pfGUIPopUpMenu();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIPopUpMenu );
|
||||
GETINTERFACE_ANY( pfGUIPopUpMenu, pfGUIDialogMod );
|
||||
|
||||
enum MenuFlags
|
||||
{
|
||||
kStayOpenAfterClick = kDerivedFlagsStart,
|
||||
kModalOutsideMenus,
|
||||
kOpenSubMenusOnHover,
|
||||
kScaleWithResolution
|
||||
};
|
||||
|
||||
enum Refs
|
||||
{
|
||||
kRefSkin = kRefDerviedStart,
|
||||
kRefSubMenu,
|
||||
kRefOriginAnchor,
|
||||
kRefOriginContext,
|
||||
kRefParentNode
|
||||
};
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void SetEnabled( hsBool e );
|
||||
virtual hsBool HandleMouseEvent( pfGameGUIMgr::EventType event, hsScalar mouseX, hsScalar mouseY, UInt8 modifiers );
|
||||
|
||||
void Show( hsScalar x, hsScalar y );
|
||||
|
||||
void SetOriginAnchor( plSceneObject *anchor, pfGUIDialogMod *context );
|
||||
void SetAlignment( Alignment a ) { fAlignment = a; }
|
||||
void ClearItems( void );
|
||||
void AddItem( const char *name, pfGUICtrlProcObject *handler, pfGUIPopUpMenu *subMenu = nil );
|
||||
void AddItem( const wchar_t *name, pfGUICtrlProcObject *handler, pfGUIPopUpMenu *subMenu = nil );
|
||||
void SetSkin( pfGUISkin *skin );
|
||||
|
||||
static pfGUIPopUpMenu *Build( const char *name, pfGUIDialogMod *parent, hsScalar x, hsScalar y, const plLocation &destLoc = plLocation::kGlobalFixedLoc );
|
||||
|
||||
};
|
||||
|
||||
// Skin definition. Here for now 'cause only the menus use it, but might move it later
|
||||
class plMipmap;
|
||||
class pfGUISkin : public hsKeyedObject
|
||||
{
|
||||
public:
|
||||
enum Elements
|
||||
{
|
||||
kUpLeftCorner = 0,
|
||||
kTopSpan,
|
||||
kUpRightCorner,
|
||||
kRightSpan,
|
||||
kLowerRightCorner,
|
||||
kBottomSpan,
|
||||
kLowerLeftCorner,
|
||||
kLeftSpan,
|
||||
kMiddleFill,
|
||||
kSelectedFill,
|
||||
kSubMenuArrow,
|
||||
kSelectedSubMenuArrow,
|
||||
kTreeButtonClosed,
|
||||
kTreeButtonOpen,
|
||||
kNumElements
|
||||
};
|
||||
|
||||
class pfSRect
|
||||
{
|
||||
public:
|
||||
UInt16 fX, fY, fWidth, fHeight;
|
||||
|
||||
void Empty( void ) { fX = fY = fWidth = fHeight = 0; }
|
||||
void Read( hsStream *s );
|
||||
void Write( hsStream *s );
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
plMipmap *fTexture;
|
||||
pfSRect fElements[ kNumElements ];
|
||||
UInt16 fItemMargin, fBorderMargin;
|
||||
|
||||
public:
|
||||
|
||||
pfGUISkin();
|
||||
pfGUISkin( plMipmap *texture );
|
||||
virtual ~pfGUISkin();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUISkin );
|
||||
GETINTERFACE_ANY( pfGUISkin, hsKeyedObject );
|
||||
|
||||
enum Refs
|
||||
{
|
||||
kRefMipmap
|
||||
};
|
||||
|
||||
virtual void Read( hsStream *s, hsResMgr *mgr );
|
||||
virtual void Write( hsStream *s, hsResMgr *mgr );
|
||||
virtual hsBool MsgReceive( plMessage *msg );
|
||||
|
||||
plMipmap *GetTexture( void ) const { return fTexture; }
|
||||
void SetTexture( plMipmap *tex );
|
||||
|
||||
const pfSRect &GetElement( UInt32 idx ) const { return fElements[ idx ]; }
|
||||
hsBool IsElementSet( UInt32 idx ) const { return ( fElements[ idx ].fWidth > 0 && fElements[ idx ].fHeight > 0 ); }
|
||||
void SetElement( UInt32 idx, UInt16 x, UInt16 y, UInt16 w, UInt16 h );
|
||||
|
||||
void SetMargins( UInt16 item, UInt16 border ) { fItemMargin = item; fBorderMargin = border; }
|
||||
UInt16 GetItemMargin( void ) const { return fItemMargin; }
|
||||
UInt16 GetBorderMargin( void ) const { return fBorderMargin; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIPopUpMenu_h
|
@ -0,0 +1,255 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIProgressCtrl Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIProgressCtrl.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plMessage/plTimerCallbackMsg.h"
|
||||
// #include "../plAvatar/plAGModifier.h"
|
||||
#include "../plAvatar/plAGMasterMod.h"
|
||||
#include "../plAvatar/plAGAnimInstance.h"
|
||||
#include "../plSurface/plLayerAnimation.h"
|
||||
|
||||
#include "../pnSceneObject/plSceneObject.h"
|
||||
#include "../pnSceneObject/plCoordinateInterface.h"
|
||||
#include "../pnTimer/plTimerCallbackManager.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIProgressCtrl::pfGUIProgressCtrl() : fStopSoundTimer(99)
|
||||
{
|
||||
fAnimTimesCalced = false;
|
||||
fAnimName = nil;
|
||||
fPlaySound = true;
|
||||
}
|
||||
|
||||
pfGUIProgressCtrl::~pfGUIProgressCtrl()
|
||||
{
|
||||
delete [] fAnimName;
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIProgressCtrl::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIValueCtrl::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIProgressCtrl::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plTimerCallbackMsg *timerMsg = plTimerCallbackMsg::ConvertNoRef(msg);
|
||||
if (timerMsg)
|
||||
{
|
||||
if (timerMsg->fID == fStopSoundTimer)
|
||||
{
|
||||
// we've finished animating, stop the sound that's playing
|
||||
StopSound(kAnimateSound);
|
||||
}
|
||||
}
|
||||
return pfGUIValueCtrl::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIProgressCtrl::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIValueCtrl::Read(s, mgr);
|
||||
|
||||
fAnimationKeys.Reset();
|
||||
UInt32 i, count = s->ReadSwap32();
|
||||
for( i = 0; i < count; i++ )
|
||||
fAnimationKeys.Append( mgr->ReadKey( s ) );
|
||||
fAnimName = s->ReadSafeString();
|
||||
|
||||
fAnimTimesCalced = false;
|
||||
}
|
||||
|
||||
void pfGUIProgressCtrl::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIValueCtrl::Write( s, mgr );
|
||||
|
||||
UInt32 i, count = fAnimationKeys.GetCount();
|
||||
s->WriteSwap32( count );
|
||||
for( i = 0; i < count; i++ )
|
||||
mgr->WriteKey( s, fAnimationKeys[ i ] );
|
||||
s->WriteSafeString( fAnimName );
|
||||
}
|
||||
|
||||
//// UpdateBounds ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIProgressCtrl::UpdateBounds( hsMatrix44 *invXformMatrix, hsBool force )
|
||||
{
|
||||
pfGUIValueCtrl::UpdateBounds( invXformMatrix, force );
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
fBoundsValid = false;
|
||||
}
|
||||
|
||||
//// SetAnimationKeys ////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIProgressCtrl::SetAnimationKeys( hsTArray<plKey> &keys, const char *name )
|
||||
{
|
||||
fAnimationKeys = keys;
|
||||
delete [] fAnimName;
|
||||
if( name != nil )
|
||||
{
|
||||
fAnimName = TRACKED_NEW char[ strlen( name ) + 1 ];
|
||||
strcpy( fAnimName, name );
|
||||
}
|
||||
else
|
||||
fAnimName = nil;
|
||||
}
|
||||
|
||||
//// ICalcAnimTimes //////////////////////////////////////////////////////////
|
||||
// Loops through and computes the max begin and end for our animations. If
|
||||
// none of them are loaded and we're not already calced, returns false.
|
||||
|
||||
hsBool pfGUIProgressCtrl::ICalcAnimTimes( void )
|
||||
{
|
||||
if( fAnimTimesCalced )
|
||||
return true;
|
||||
|
||||
hsScalar tBegin = 1e30, tEnd = -1e30;
|
||||
bool foundOne = false;
|
||||
|
||||
for( int i = 0; i < fAnimationKeys.GetCount(); i++ )
|
||||
{
|
||||
// Handle AGMasterMods
|
||||
plAGMasterMod *mod = plAGMasterMod::ConvertNoRef( fAnimationKeys[ i ]->ObjectIsLoaded() );
|
||||
if( mod != nil )
|
||||
{
|
||||
for( int j = 0; j < mod->GetNumAnimations(); j++ )
|
||||
{
|
||||
hsScalar begin = mod->GetAnimInstance( j )->GetTimeConvert()->GetBegin();
|
||||
hsScalar end = mod->GetAnimInstance( j )->GetTimeConvert()->GetEnd();
|
||||
if( begin < tBegin )
|
||||
tBegin = begin;
|
||||
if( end > tEnd )
|
||||
tEnd = end;
|
||||
}
|
||||
foundOne = true;
|
||||
}
|
||||
// Handle layer animations
|
||||
plLayerAnimation *layer = plLayerAnimation::ConvertNoRef( fAnimationKeys[ i ]->ObjectIsLoaded() );
|
||||
if( layer != nil )
|
||||
{
|
||||
hsScalar begin = layer->GetTimeConvert().GetBegin();
|
||||
hsScalar end = layer->GetTimeConvert().GetEnd();
|
||||
if( begin < tBegin )
|
||||
tBegin = begin;
|
||||
if( end > tEnd )
|
||||
tEnd = end;
|
||||
foundOne = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( foundOne )
|
||||
{
|
||||
fAnimBegin = tBegin;
|
||||
fAnimEnd = tEnd;
|
||||
|
||||
fAnimTimesCalced = true;
|
||||
}
|
||||
|
||||
return fAnimTimesCalced;
|
||||
}
|
||||
|
||||
//// SetCurrValue ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIProgressCtrl::SetCurrValue( hsScalar v )
|
||||
{
|
||||
int old = (int)fValue;
|
||||
|
||||
pfGUIValueCtrl::SetCurrValue( v );
|
||||
|
||||
// if( old == (int)fValue )
|
||||
// return;
|
||||
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
{
|
||||
ICalcAnimTimes();
|
||||
|
||||
hsScalar tLength = fAnimEnd - fAnimBegin;
|
||||
hsScalar newTime;
|
||||
|
||||
if( HasFlag( kReverseValues ) )
|
||||
newTime = ( ( fMax - fValue ) / ( fMax - fMin ) ) * tLength + fAnimBegin;
|
||||
else
|
||||
newTime = ( ( fValue - fMin ) / ( fMax - fMin ) ) * tLength + fAnimBegin;
|
||||
|
||||
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
|
||||
msg->SetCmd( plAnimCmdMsg::kGoToTime );
|
||||
msg->SetAnimName( fAnimName );
|
||||
msg->fTime = newTime;
|
||||
msg->AddReceivers( fAnimationKeys );
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIProgressCtrl::AnimateToPercentage( hsScalar percent )
|
||||
{
|
||||
// percent should be a value in range 0.0 to 1.0
|
||||
if (percent >= 0.0f && percent <= 1.0f)
|
||||
{
|
||||
pfGUIValueCtrl::SetCurrValue( (fMax - fMin) * percent + fMin );
|
||||
|
||||
if( fAnimationKeys.GetCount() > 0 )
|
||||
{
|
||||
plAnimCmdMsg *msg = TRACKED_NEW plAnimCmdMsg();
|
||||
msg->SetCmd( plAnimCmdMsg::kPlayToPercentage );
|
||||
msg->SetAnimName( fAnimName );
|
||||
msg->fTime = percent;
|
||||
msg->AddReceivers( fAnimationKeys );
|
||||
plgDispatch::MsgSend( msg );
|
||||
|
||||
if (fPlaySound)
|
||||
{
|
||||
// play the sound, looping
|
||||
PlaySound(kAnimateSound, true);
|
||||
|
||||
// setup a timer to call back when we finish animating
|
||||
hsScalar elapsedTime = (fAnimEnd - fAnimBegin) * percent;
|
||||
plTimerCallbackMsg *timerMsg = TRACKED_NEW plTimerCallbackMsg(GetKey(), fStopSoundTimer);
|
||||
plgTimerCallbackMgr::NewTimer(elapsedTime, timerMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIProgressCtrl Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIProgressCtrl_h
|
||||
#define _pfGUIProgressCtrl_h
|
||||
|
||||
#include "pfGUIValueCtrl.h"
|
||||
|
||||
class plMessage;
|
||||
class plAGMasterMod;
|
||||
|
||||
class pfGUIProgressCtrl : public pfGUIValueCtrl
|
||||
{
|
||||
protected:
|
||||
|
||||
hsTArray<plKey> fAnimationKeys;
|
||||
char *fAnimName;
|
||||
|
||||
// Computed once, once an anim is loaded that we can compute this with
|
||||
hsScalar fAnimBegin, fAnimEnd;
|
||||
hsBool fAnimTimesCalced;
|
||||
hsBool fPlaySound;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
hsBool ICalcAnimTimes( void );
|
||||
|
||||
const UInt32 fStopSoundTimer;
|
||||
|
||||
public:
|
||||
|
||||
pfGUIProgressCtrl();
|
||||
virtual ~pfGUIProgressCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIProgressCtrl );
|
||||
GETINTERFACE_ANY( pfGUIProgressCtrl, pfGUIValueCtrl );
|
||||
|
||||
|
||||
enum OurFlags
|
||||
{
|
||||
kReverseValues = kDerivedFlagsStart
|
||||
};
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void UpdateBounds( hsMatrix44 *invXformMatrix = nil, hsBool force = false );
|
||||
|
||||
virtual void SetCurrValue( hsScalar v );
|
||||
virtual void AnimateToPercentage( hsScalar percent );
|
||||
|
||||
enum SoundEvents
|
||||
{
|
||||
kAnimateSound
|
||||
};
|
||||
|
||||
void DontPlaySounds() { fPlaySound = false; }
|
||||
|
||||
// Export only
|
||||
void SetAnimationKeys( hsTArray<plKey> &keys, const char *name );
|
||||
};
|
||||
|
||||
#endif // _pfGUIProgressCtrl_h
|
@ -0,0 +1,257 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIRadioGroupCtrl Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIRadioGroupCtrl.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUICheckBoxCtrl.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
//// Wee Little Control Proc for our buttons /////////////////////////////////
|
||||
|
||||
class pfGroupProc : public pfGUICtrlProcObject
|
||||
{
|
||||
protected:
|
||||
|
||||
pfGUIRadioGroupCtrl *fParent;
|
||||
|
||||
public:
|
||||
|
||||
pfGroupProc( pfGUIRadioGroupCtrl *parent )
|
||||
{
|
||||
fParent = parent;
|
||||
}
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl )
|
||||
{
|
||||
Int32 newIdx;
|
||||
|
||||
|
||||
// So one of our controls got clicked. That means that we change our value
|
||||
// to the proper index
|
||||
|
||||
pfGUICheckBoxCtrl *check = pfGUICheckBoxCtrl::ConvertNoRef( ctrl );
|
||||
|
||||
// Are we unselecting? And do we allow this?
|
||||
if( !check->IsChecked() && !fParent->HasFlag( pfGUIRadioGroupCtrl::kAllowNoSelection ) )
|
||||
{
|
||||
// Boo on you. Re-check
|
||||
check->SetChecked( true );
|
||||
return;
|
||||
}
|
||||
|
||||
for( newIdx = 0; newIdx < fParent->fControls.GetCount(); newIdx++ )
|
||||
{
|
||||
if( fParent->fControls[ newIdx ] == check )
|
||||
break;
|
||||
}
|
||||
|
||||
if( newIdx == fParent->fControls.GetCount() )
|
||||
newIdx = -1;
|
||||
|
||||
if( newIdx != fParent->fValue )
|
||||
{
|
||||
if( fParent->fValue != -1 )
|
||||
fParent->fControls[ fParent->fValue ]->SetChecked( false );
|
||||
|
||||
fParent->fValue = newIdx;
|
||||
if( newIdx != -1 )
|
||||
fParent->fControls[ newIdx ]->SetChecked( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !check->IsChecked() && fParent->HasFlag( pfGUIRadioGroupCtrl::kAllowNoSelection ) )
|
||||
{
|
||||
// nobody is checked!
|
||||
fParent->fValue = -1;
|
||||
}
|
||||
}
|
||||
|
||||
fParent->DoSomething();
|
||||
}
|
||||
};
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIRadioGroupCtrl::pfGUIRadioGroupCtrl()
|
||||
{
|
||||
fButtonProc = TRACKED_NEW pfGroupProc( this );
|
||||
fButtonProc->IncRef();
|
||||
SetFlag( kIntangible );
|
||||
}
|
||||
|
||||
pfGUIRadioGroupCtrl::~pfGUIRadioGroupCtrl()
|
||||
{
|
||||
if( fButtonProc->DecRef() )
|
||||
delete fButtonProc;
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIRadioGroupCtrl::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIRadioGroupCtrl::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg );
|
||||
if( refMsg != nil )
|
||||
{
|
||||
if( refMsg->fType == kRefControl )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
fControls[ refMsg->fWhich ] = pfGUICheckBoxCtrl::ConvertNoRef( refMsg->GetRef() );
|
||||
fControls[ refMsg->fWhich ]->SetHandler( fButtonProc );
|
||||
if( fValue == refMsg->fWhich )
|
||||
fControls[ refMsg->fWhich ]->SetChecked( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
fControls[ refMsg->fWhich ] = nil;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIRadioGroupCtrl::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
|
||||
UInt32 i, count = s->ReadSwap32();
|
||||
fControls.SetCountAndZero( count );
|
||||
|
||||
for( i = 0; i < count; i++ )
|
||||
{
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, i, kRefControl ), plRefFlags::kActiveRef );
|
||||
}
|
||||
|
||||
fValue = fDefaultValue = s->ReadSwap16();
|
||||
if( fValue != -1 && fControls[ fValue ] != nil )
|
||||
fControls[ fValue ]->SetChecked( true );
|
||||
}
|
||||
|
||||
void pfGUIRadioGroupCtrl::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
|
||||
s->WriteSwap32( fControls.GetCount() );
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
mgr->WriteKey( s, fControls[ i ]->GetKey() );
|
||||
|
||||
s->WriteSwap16( (UInt16)fDefaultValue );
|
||||
}
|
||||
|
||||
//// SetValue ////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIRadioGroupCtrl::SetValue( Int32 value )
|
||||
{
|
||||
if( value != fValue && ( value != -1 || HasFlag( kAllowNoSelection ) ) )
|
||||
{
|
||||
if( fValue != -1 )
|
||||
fControls[ fValue ]->SetChecked( false );
|
||||
|
||||
fValue = value;
|
||||
if( value != -1 )
|
||||
fControls[ value ]->SetChecked( true );
|
||||
|
||||
DoSomething();
|
||||
}
|
||||
}
|
||||
|
||||
///// Setting to be trickled down to the underlings
|
||||
|
||||
void pfGUIRadioGroupCtrl::SetEnabled( hsBool e )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
fControls[ i ]->SetEnabled(e);
|
||||
}
|
||||
|
||||
void pfGUIRadioGroupCtrl::SetInteresting( hsBool e )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
fControls[ i ]->SetInteresting(e);
|
||||
}
|
||||
|
||||
void pfGUIRadioGroupCtrl::SetVisible( hsBool vis )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
fControls[ i ]->SetVisible(vis);
|
||||
}
|
||||
|
||||
void pfGUIRadioGroupCtrl::SetControlsFlag( int flag )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
fControls[ i ]->SetFlag(flag);
|
||||
}
|
||||
|
||||
|
||||
void pfGUIRadioGroupCtrl::ClearControlsFlag( int flag )
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fControls.GetCount(); i++ )
|
||||
fControls[ i ]->ClearFlag(flag);
|
||||
}
|
||||
|
||||
|
||||
//// Export Functions ////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIRadioGroupCtrl::ClearControlList( void )
|
||||
{
|
||||
fControls.Reset();
|
||||
fValue = -1;
|
||||
}
|
||||
|
||||
void pfGUIRadioGroupCtrl::AddControl( pfGUICheckBoxCtrl *ctrl )
|
||||
{
|
||||
fControls.Append( ctrl );
|
||||
}
|
||||
|
@ -0,0 +1,94 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIRadioGroupCtrl Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIRadioGroupCtrl_h
|
||||
#define _pfGUIRadioGroupCtrl_h
|
||||
|
||||
#include "pfGUIValueCtrl.h"
|
||||
#include "hsTemplates.h"
|
||||
|
||||
class plMessage;
|
||||
class pfGUICheckBoxCtrl;
|
||||
class pfGroupProc;
|
||||
|
||||
|
||||
class pfGUIRadioGroupCtrl : public pfGUIControlMod
|
||||
{
|
||||
friend class pfGroupProc;
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kRefControl = kRefDerivedStart
|
||||
};
|
||||
|
||||
hsTArray<pfGUICheckBoxCtrl *> fControls;
|
||||
pfGroupProc *fButtonProc;
|
||||
|
||||
Int32 fValue, fDefaultValue;
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
public:
|
||||
|
||||
pfGUIRadioGroupCtrl();
|
||||
virtual ~pfGUIRadioGroupCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIRadioGroupCtrl );
|
||||
GETINTERFACE_ANY( pfGUIRadioGroupCtrl, pfGUIControlMod );
|
||||
|
||||
enum OurFlags
|
||||
{
|
||||
kAllowNoSelection = kDerivedFlagsStart
|
||||
};
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
Int32 GetValue( void ) { return fValue; }
|
||||
void SetValue( Int32 value );
|
||||
|
||||
virtual void SetEnabled( hsBool e );
|
||||
virtual void SetInteresting( hsBool e );
|
||||
virtual void SetVisible( hsBool vis );
|
||||
virtual void SetControlsFlag( int flag );
|
||||
virtual void ClearControlsFlag( int flag );
|
||||
|
||||
/// Export ONLY
|
||||
void ClearControlList( void );
|
||||
void AddControl( pfGUICheckBoxCtrl *ctrl );
|
||||
void SetDefaultValue( Int32 value ) { fDefaultValue = value; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIRadioGroupCtrl_h
|
@ -0,0 +1,82 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUITagDefs.cpp //
|
||||
// List of Tag IDs for the GameGUIMgr //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUITagDefs.h"
|
||||
|
||||
//// Tag List ////////////////////////////////////////////////////////////////
|
||||
// Here's the actual list of tags. It's basically a list of konstants, but
|
||||
// they get translated into two things:
|
||||
// 1. An enum, to send as a UInt32 to the GetDialogFromTag() and
|
||||
// GetControlFromTag() functions.
|
||||
// 2. A string, which gets put in a dropdown box in the appropriate
|
||||
// MAX component, which sets the given control's tag ID to the
|
||||
// right konstant.
|
||||
|
||||
// Step 1: add your konstant to the end of the .h file list
|
||||
|
||||
// Step 2: Add the string here
|
||||
|
||||
pfGUITag gGUITags[] = {
|
||||
{ kKIMainDialog, "KI Main Dialog" },
|
||||
{ kKITestEditBox, "KI Test Control" },
|
||||
{ kKIEntryDlg, "KI Entry Dlg" },
|
||||
{ kKICloseButton, "KI Close Dlg Button" },
|
||||
{ kKITestControl2, "KI Test Control 2" },
|
||||
{ kKIAddButton, "KI Add Button" },
|
||||
{ kKIEditButton, "KI Edit Button" },
|
||||
{ kKIRemoveButton, "KI Remove Button" },
|
||||
{ kKIYesNoDlg, "KI Yes/No Dialog" },
|
||||
{ kKIYesBtn, "KI Yes Button" },
|
||||
{ kKINoBtn, "KI No Button" },
|
||||
{ kKIStaticText, "KI Static Text" },
|
||||
{ kKITestControl3, "KI Test Control 3" },
|
||||
{ kKIMiniDialog, "KI Mini Dialog" },
|
||||
{ kPlayerBook, "PB Dialog" },
|
||||
{ kPBLinkToBtn, "PB Link To Button" },
|
||||
{ kPBSaveLinkBtn, "PB Save Link Button" },
|
||||
{ kPBSaveSlotRadio, "PB Save Slot Radio" },
|
||||
{ kPBSaveSlotPrev1, "PB Save Slot Preview 1" },
|
||||
{ kPBSaveSlotPrev2, "PB Save Slot Preview 2" },
|
||||
{ kPBSaveSlotPrev3, "PB Save Slot Preview 3" },
|
||||
{ kPBSaveSlotPrev4, "PB Save Slot Preview 4" },
|
||||
{ kPBSaveSlotPrev5, "PB Save Slot Preview 5" },
|
||||
{ kPBSaveSlotPrev6, "PB Save Slot Preview 6" },
|
||||
{ kKICurrPlayerText, "KI Current Player Label" },
|
||||
{ kKIPlayerList, "KI Mini Friends List" },
|
||||
{ kKIChatModeBtn, "KI Toggle Chat Mode Btn" },
|
||||
{ kBlackBarDlg, "Black Bar Dialog" },
|
||||
{ kBlackBarKIButtons, "Black Bar KI Radio Group" },
|
||||
{ kKILogoutButton, "KI Logout Button" },
|
||||
|
||||
{ 0, "" } // Ending tag, MUST ALWAYS BE HERE
|
||||
};
|
@ -0,0 +1,88 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUITagDefs.cpp //
|
||||
// List of Tag IDs for the GameGUIMgr //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUITagDefs_h
|
||||
#define _pfGUITagDefs_h
|
||||
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
//// Tag List ////////////////////////////////////////////////////////////////
|
||||
// Here's the actual list of tags. It's basically a list of konstants, but
|
||||
// they get translated into two things:
|
||||
// 1. An enum, to send as a UInt32 to the GetDialogFromTag() and
|
||||
// GetControlFromTag() functions.
|
||||
// 2. A string, which gets put in a dropdown box in the appropriate
|
||||
// MAX component, which sets the given control's tag ID to the
|
||||
// right konstant.
|
||||
|
||||
|
||||
// Step 1: Add your konstant to the end of this list
|
||||
|
||||
enum
|
||||
{
|
||||
kKIMainDialog = 1,
|
||||
kKITestEditBox,
|
||||
kKIEntryDlg,
|
||||
kKICloseButton,
|
||||
kKITestControl2,
|
||||
kKIAddButton,
|
||||
kKIEditButton,
|
||||
kKIRemoveButton,
|
||||
kKIYesNoDlg,
|
||||
kKIYesBtn,
|
||||
kKINoBtn,
|
||||
kKIStaticText,
|
||||
kKITestControl3,
|
||||
kKIMiniDialog,
|
||||
kPlayerBook,
|
||||
kPBLinkToBtn,
|
||||
kPBSaveLinkBtn,
|
||||
kPBSaveSlotRadio,
|
||||
kPBSaveSlotPrev1,
|
||||
kPBSaveSlotPrev2,
|
||||
kPBSaveSlotPrev3,
|
||||
kPBSaveSlotPrev4,
|
||||
kPBSaveSlotPrev5,
|
||||
kPBSaveSlotPrev6,
|
||||
|
||||
kKICurrPlayerText = 30,
|
||||
kKIPlayerList = 31,
|
||||
kKIChatModeBtn = 32,
|
||||
|
||||
kBlackBarDlg = 33,
|
||||
kBlackBarKIButtons = 34,
|
||||
kKILogoutButton = 35,
|
||||
};
|
||||
|
||||
// Step 2: Add the string to the .cpp file
|
||||
|
||||
#endif
|
@ -0,0 +1,246 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUITextBoxMod Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "hsStlUtils.h"
|
||||
#include "pfGUITextBoxMod.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plAvatar/plAGModifier.h"
|
||||
#include "../plGImage/plDynamicTextMap.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
#include "../plResMgr/plLocalization.h"
|
||||
|
||||
#include "../pfLocalizationMgr/pfLocalizationMgr.h"
|
||||
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUITextBoxMod::pfGUITextBoxMod()
|
||||
{
|
||||
// SetFlag( kWantsInterest );
|
||||
SetFlag( kIntangible );
|
||||
fText = nil;
|
||||
fUseLocalizationPath = false;
|
||||
}
|
||||
|
||||
pfGUITextBoxMod::~pfGUITextBoxMod()
|
||||
{
|
||||
delete [] fText;
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUITextBoxMod::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIControlMod::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUITextBoxMod::MsgReceive( plMessage *msg )
|
||||
{
|
||||
return pfGUIControlMod::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// IPostSetUpDynTextMap ////////////////////////////////////////////////////
|
||||
|
||||
void pfGUITextBoxMod::IPostSetUpDynTextMap( void )
|
||||
{
|
||||
pfGUIColorScheme *scheme = GetColorScheme();
|
||||
|
||||
fDynTextMap->SetFont( scheme->fFontFace, scheme->fFontSize, scheme->fFontFlags,
|
||||
HasFlag( kXparentBgnd ) ? false : true );
|
||||
fDynTextMap->SetTextColor( scheme->fForeColor,
|
||||
( HasFlag( kXparentBgnd ) && scheme->fBackColor.a == 0.f ) ? true : false );
|
||||
}
|
||||
|
||||
//// IUpdate /////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUITextBoxMod::IUpdate( void )
|
||||
{
|
||||
if( fDynTextMap == nil || !fDynTextMap->IsValid() )
|
||||
return;
|
||||
|
||||
if( HasFlag( kCenterJustify ) )
|
||||
fDynTextMap->SetJustify( plDynamicTextMap::kCenter );
|
||||
else if( HasFlag( kRightJustify ) )
|
||||
fDynTextMap->SetJustify( plDynamicTextMap::kRightJustify );
|
||||
else
|
||||
fDynTextMap->SetJustify( plDynamicTextMap::kLeftJustify );
|
||||
|
||||
fDynTextMap->ClearToColor( GetColorScheme()->fBackColor );
|
||||
|
||||
std::wstring drawStr;
|
||||
if (fUseLocalizationPath && !fLocalizationPath.empty() && pfLocalizationMgr::InstanceValid())
|
||||
drawStr = pfLocalizationMgr::Instance().GetString(fLocalizationPath.c_str());
|
||||
else
|
||||
{
|
||||
if( fText != nil )
|
||||
{
|
||||
int lang = plLocalization::GetLanguage();
|
||||
std::vector<std::wstring> translations = plLocalization::StringToLocal(fText);
|
||||
if (translations[lang] == L"") // if the translations doesn't exist, draw English
|
||||
drawStr = translations[0].c_str();
|
||||
else
|
||||
drawStr = translations[lang].c_str();
|
||||
}
|
||||
}
|
||||
|
||||
if (!drawStr.empty())
|
||||
fDynTextMap->DrawWrappedString( 4, 4, drawStr.c_str(), fDynTextMap->GetVisibleWidth() - 8, fDynTextMap->GetVisibleHeight() - 8 );
|
||||
|
||||
fDynTextMap->FlushToHost();
|
||||
}
|
||||
|
||||
void pfGUITextBoxMod::PurgeDynaTextMapImage()
|
||||
{
|
||||
if ( fDynTextMap != nil )
|
||||
fDynTextMap->PurgeImage();
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUITextBoxMod::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
|
||||
UInt32 len = s->ReadSwap32();
|
||||
if( len > 0 )
|
||||
{
|
||||
char *text = TRACKED_NEW char[ len + 1 ];
|
||||
s->Read( len, text );
|
||||
text[ len ] = 0;
|
||||
|
||||
fText = hsStringToWString(text);
|
||||
delete [] text;
|
||||
}
|
||||
else
|
||||
fText = nil;
|
||||
|
||||
fUseLocalizationPath = (s->ReadBool() != 0);
|
||||
if (fUseLocalizationPath)
|
||||
{
|
||||
wchar_t* temp = s->ReadSafeWString();
|
||||
fLocalizationPath = temp;
|
||||
delete [] temp;
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUITextBoxMod::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
|
||||
if( fText == nil )
|
||||
s->WriteSwap32( 0 );
|
||||
else
|
||||
{
|
||||
char *text = hsWStringToString(fText);
|
||||
s->WriteSwap32( strlen( text ) );
|
||||
s->Write( strlen( text ), text );
|
||||
delete [] text;
|
||||
}
|
||||
|
||||
// Make sure we only write out to use localization path if the box is checked
|
||||
// and the path isn't empty
|
||||
bool useLoc = fUseLocalizationPath && !fLocalizationPath.empty();
|
||||
|
||||
s->WriteBool(useLoc);
|
||||
if (useLoc)
|
||||
s->WriteSafeWString(fLocalizationPath.c_str());
|
||||
}
|
||||
|
||||
//// HandleMouseDown/Up //////////////////////////////////////////////////////
|
||||
|
||||
void pfGUITextBoxMod::HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
}
|
||||
|
||||
void pfGUITextBoxMod::HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
}
|
||||
|
||||
void pfGUITextBoxMod::HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers )
|
||||
{
|
||||
}
|
||||
|
||||
//// SetText /////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUITextBoxMod::SetText( const char *text )
|
||||
{
|
||||
delete [] fText;
|
||||
if (text)
|
||||
{
|
||||
fText = hsStringToWString(text);
|
||||
}
|
||||
else
|
||||
fText = nil;
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
void pfGUITextBoxMod::SetText( const wchar_t *text )
|
||||
{
|
||||
delete [] fText;
|
||||
if (text)
|
||||
{
|
||||
fText = TRACKED_NEW wchar_t[wcslen(text)+1];
|
||||
wcscpy(fText,text);
|
||||
}
|
||||
else
|
||||
fText = nil;
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
void pfGUITextBoxMod::SetLocalizationPath(const wchar_t* path)
|
||||
{
|
||||
if (path)
|
||||
fLocalizationPath = path;
|
||||
}
|
||||
|
||||
void pfGUITextBoxMod::SetLocalizationPath(const char* path)
|
||||
{
|
||||
if (path)
|
||||
{
|
||||
wchar_t* wPath = hsStringToWString(path);
|
||||
fLocalizationPath = wPath;
|
||||
delete [] wPath;
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUITextBoxMod::SetUseLocalizationPath(bool use)
|
||||
{
|
||||
fUseLocalizationPath = use;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUITextBoxMod Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUITextBoxMod_h
|
||||
#define _pfGUITextBoxMod_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
class plMessage;
|
||||
class hsGMaterial;
|
||||
class plTextGenerator;
|
||||
|
||||
class pfGUITextBoxMod : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
wchar_t *fText;
|
||||
std::wstring fLocalizationPath;
|
||||
bool fUseLocalizationPath;
|
||||
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
|
||||
virtual void IUpdate( void );
|
||||
virtual void IPostSetUpDynTextMap( void );
|
||||
|
||||
public:
|
||||
|
||||
pfGUITextBoxMod();
|
||||
virtual ~pfGUITextBoxMod();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUITextBoxMod );
|
||||
GETINTERFACE_ANY( pfGUITextBoxMod, pfGUIControlMod );
|
||||
|
||||
enum OurFlags
|
||||
{
|
||||
kCenterJustify = kDerivedFlagsStart,
|
||||
kRightJustify
|
||||
};
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void HandleMouseDown( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseUp( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
virtual void HandleMouseDrag( hsPoint3 &mousePt, UInt8 modifiers );
|
||||
|
||||
virtual void PurgeDynaTextMapImage();
|
||||
|
||||
virtual const wchar_t* GetText() { return fText; }
|
||||
|
||||
// Export only
|
||||
void SetText( const char *text );
|
||||
void SetText( const wchar_t *text );
|
||||
|
||||
void SetLocalizationPath(const wchar_t* path);
|
||||
void SetLocalizationPath(const char* path);
|
||||
void SetUseLocalizationPath(bool use);
|
||||
|
||||
virtual void UpdateColorScheme() { IPostSetUpDynTextMap(); IUpdate(); }
|
||||
};
|
||||
|
||||
#endif // _pfGUITextBoxMod_h
|
@ -0,0 +1,225 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIUpDownPairMod Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIUpDownPairMod.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIButtonMod.h"
|
||||
#include "pfGUIControlHandlers.h"
|
||||
|
||||
#include "../pnMessage/plRefMsg.h"
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plAnimCmdMsg.h"
|
||||
#include "../plAvatar/plAGModifier.h"
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
//// Wee Little Control Proc for our buttons /////////////////////////////////
|
||||
|
||||
class pfUpDownBtnProc : public pfGUICtrlProcObject
|
||||
{
|
||||
protected:
|
||||
|
||||
pfGUIButtonMod *fUp, *fDown;
|
||||
pfGUIUpDownPairMod *fParent;
|
||||
|
||||
public:
|
||||
|
||||
pfUpDownBtnProc( pfGUIButtonMod *up, pfGUIButtonMod *down, pfGUIUpDownPairMod *parent )
|
||||
{
|
||||
fUp = up;
|
||||
fDown = down;
|
||||
fParent = parent;
|
||||
}
|
||||
|
||||
void SetUp( pfGUIButtonMod *up ) { fUp = up; }
|
||||
void SetDown( pfGUIButtonMod *down ) { fDown = down; }
|
||||
|
||||
virtual void DoSomething( pfGUIControlMod *ctrl )
|
||||
{
|
||||
if( (pfGUIButtonMod *)ctrl == fUp )
|
||||
{
|
||||
fParent->fValue += fParent->fStep;
|
||||
if( fParent->fValue > fParent->fMax )
|
||||
fParent->fValue = fParent->fMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
fParent->fValue -= fParent->fStep;
|
||||
if( fParent->fValue < fParent->fMin )
|
||||
fParent->fValue = fParent->fMin;
|
||||
}
|
||||
fParent->Update();
|
||||
fParent->DoSomething();
|
||||
}
|
||||
};
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIUpDownPairMod::pfGUIUpDownPairMod()
|
||||
{
|
||||
fUpControl = nil;
|
||||
fDownControl = nil;
|
||||
fValue = fMin = fMax = fStep = 0.f;
|
||||
|
||||
fButtonProc = TRACKED_NEW pfUpDownBtnProc( nil, nil, this );
|
||||
fButtonProc->IncRef();
|
||||
SetFlag( kIntangible );
|
||||
}
|
||||
|
||||
pfGUIUpDownPairMod::~pfGUIUpDownPairMod()
|
||||
{
|
||||
if( fButtonProc->DecRef() )
|
||||
delete fButtonProc;
|
||||
}
|
||||
|
||||
//// IEval ///////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIUpDownPairMod::IEval( double secs, hsScalar del, UInt32 dirty )
|
||||
{
|
||||
return pfGUIValueCtrl::IEval( secs, del, dirty );
|
||||
}
|
||||
|
||||
void pfGUIUpDownPairMod::IUpdate( void )
|
||||
{
|
||||
if (fEnabled)
|
||||
{
|
||||
if (fUpControl)
|
||||
{
|
||||
if ( fValue >= fMax)
|
||||
fUpControl->SetVisible(false);
|
||||
else
|
||||
fUpControl->SetVisible(true);
|
||||
}
|
||||
if (fDownControl)
|
||||
{
|
||||
if ( fValue <= fMin )
|
||||
fDownControl->SetVisible(false);
|
||||
else
|
||||
fDownControl->SetVisible(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fUpControl->SetVisible(false);
|
||||
fDownControl->SetVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void pfGUIUpDownPairMod::Update( void )
|
||||
{
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGUIUpDownPairMod::MsgReceive( plMessage *msg )
|
||||
{
|
||||
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( msg );
|
||||
if( refMsg != nil )
|
||||
{
|
||||
if( refMsg->fType == kRefUpControl )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
fUpControl = pfGUIButtonMod::ConvertNoRef( refMsg->GetRef() );
|
||||
fUpControl->SetHandler( fButtonProc );
|
||||
fButtonProc->SetUp( fUpControl );
|
||||
}
|
||||
else
|
||||
{
|
||||
fUpControl = nil;
|
||||
fButtonProc->SetUp( nil );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if( refMsg->fType == kRefDownControl )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest | plRefMsg::kOnReplace ) )
|
||||
{
|
||||
fDownControl = pfGUIButtonMod::ConvertNoRef( refMsg->GetRef() );
|
||||
fDownControl->SetHandler( fButtonProc );
|
||||
fButtonProc->SetDown( fDownControl );
|
||||
}
|
||||
else
|
||||
{
|
||||
fDownControl = nil;
|
||||
fButtonProc->SetDown( nil );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return pfGUIValueCtrl::MsgReceive( msg );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIUpDownPairMod::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIValueCtrl::Read(s, mgr);
|
||||
|
||||
fUpControl = nil;
|
||||
fDownControl = nil;
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefUpControl ), plRefFlags::kActiveRef );
|
||||
mgr->ReadKeyNotifyMe( s, TRACKED_NEW plGenRefMsg( GetKey(), plRefMsg::kOnCreate, -1, kRefDownControl ), plRefFlags::kActiveRef );
|
||||
|
||||
s->ReadSwap( &fMin );
|
||||
s->ReadSwap( &fMax );
|
||||
s->ReadSwap( &fStep );
|
||||
|
||||
fValue = fMin;
|
||||
}
|
||||
|
||||
void pfGUIUpDownPairMod::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIValueCtrl::Write( s, mgr );
|
||||
|
||||
mgr->WriteKey( s, fUpControl->GetKey() );
|
||||
mgr->WriteKey( s, fDownControl->GetKey() );
|
||||
|
||||
s->WriteSwap( fMin );
|
||||
s->WriteSwap( fMax );
|
||||
s->WriteSwap( fStep );
|
||||
}
|
||||
|
||||
|
||||
void pfGUIUpDownPairMod::SetRange( hsScalar min, hsScalar max )
|
||||
{
|
||||
pfGUIValueCtrl::SetRange( min, max );
|
||||
IUpdate();
|
||||
}
|
||||
|
||||
void pfGUIUpDownPairMod::SetCurrValue( hsScalar v )
|
||||
{
|
||||
pfGUIValueCtrl::SetCurrValue( v );
|
||||
IUpdate();
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIUpDownPairMod Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIUpDownPairMod_h
|
||||
#define _pfGUIUpDownPairMod_h
|
||||
|
||||
#include "pfGUIValueCtrl.h"
|
||||
|
||||
class plMessage;
|
||||
class pfGUIButtonMod;
|
||||
class pfUpDownBtnProc;
|
||||
|
||||
class pfGUIUpDownPairMod : public pfGUIValueCtrl
|
||||
{
|
||||
friend class pfUpDownBtnProc;
|
||||
|
||||
protected:
|
||||
|
||||
enum
|
||||
{
|
||||
kRefUpControl = kRefDerivedStart,
|
||||
kRefDownControl
|
||||
};
|
||||
|
||||
pfGUIButtonMod *fUpControl, *fDownControl;
|
||||
pfUpDownBtnProc *fButtonProc;
|
||||
|
||||
|
||||
virtual hsBool IEval( double secs, hsScalar del, UInt32 dirty ); // called only by owner object's Eval()
|
||||
virtual void IUpdate( void );
|
||||
|
||||
public:
|
||||
|
||||
pfGUIUpDownPairMod();
|
||||
virtual ~pfGUIUpDownPairMod();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIUpDownPairMod );
|
||||
GETINTERFACE_ANY( pfGUIUpDownPairMod, pfGUIValueCtrl );
|
||||
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
virtual void Update( void );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual void SetRange( hsScalar min, hsScalar max );
|
||||
virtual void SetCurrValue( hsScalar v );
|
||||
|
||||
/// Export ONLY
|
||||
|
||||
void SetControls( pfGUIButtonMod *up, pfGUIButtonMod *down ) { fUpControl = up; fDownControl = down; }
|
||||
};
|
||||
|
||||
#endif // _pfGUIUpDownPairMod_h
|
@ -0,0 +1,95 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIValueCtrl Definition //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "pfGUIValueCtrl.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
#include "plgDispatch.h"
|
||||
#include "hsResMgr.h"
|
||||
|
||||
|
||||
//// Constructor/Destructor //////////////////////////////////////////////////
|
||||
|
||||
pfGUIValueCtrl::pfGUIValueCtrl()
|
||||
{
|
||||
fValue = fMin = fMax = fStep = 0.f;
|
||||
}
|
||||
|
||||
pfGUIValueCtrl::~pfGUIValueCtrl()
|
||||
{
|
||||
}
|
||||
|
||||
//// SetCurrValue ////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIValueCtrl::SetCurrValue( hsScalar v )
|
||||
{
|
||||
fValue = v;
|
||||
if( fValue < fMin )
|
||||
fValue = fMin;
|
||||
else if( fValue > fMax )
|
||||
fValue = fMax;
|
||||
}
|
||||
|
||||
//// SetRange ////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIValueCtrl::SetRange( hsScalar min, hsScalar max )
|
||||
{
|
||||
fMin = min;
|
||||
fMax = max;
|
||||
if( fValue < fMin )
|
||||
SetCurrValue( fMin );
|
||||
else if( fValue > fMax )
|
||||
SetCurrValue( fMax );
|
||||
}
|
||||
|
||||
//// Read/Write //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGUIValueCtrl::Read( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Read(s, mgr);
|
||||
|
||||
s->ReadSwap( &fMin );
|
||||
s->ReadSwap( &fMax );
|
||||
s->ReadSwap( &fStep );
|
||||
|
||||
fValue = fMin;
|
||||
}
|
||||
|
||||
void pfGUIValueCtrl::Write( hsStream *s, hsResMgr *mgr )
|
||||
{
|
||||
pfGUIControlMod::Write( s, mgr );
|
||||
|
||||
s->WriteSwap( fMin );
|
||||
s->WriteSwap( fMax );
|
||||
s->WriteSwap( fStep );
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGUIValueCtrl Header //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGUIValueCtrl_h
|
||||
#define _pfGUIValueCtrl_h
|
||||
|
||||
#include "pfGUIControlMod.h"
|
||||
|
||||
|
||||
class pfGUIValueCtrl : public pfGUIControlMod
|
||||
{
|
||||
protected:
|
||||
|
||||
hsScalar fValue, fMin, fMax, fStep;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
pfGUIValueCtrl();
|
||||
virtual ~pfGUIValueCtrl();
|
||||
|
||||
CLASSNAME_REGISTER( pfGUIValueCtrl );
|
||||
GETINTERFACE_ANY( pfGUIValueCtrl, pfGUIControlMod );
|
||||
|
||||
virtual void Read( hsStream* s, hsResMgr* mgr );
|
||||
virtual void Write( hsStream* s, hsResMgr* mgr );
|
||||
|
||||
virtual hsScalar GetCurrValue( void ) { return fValue; }
|
||||
virtual void SetCurrValue( hsScalar v );
|
||||
|
||||
virtual hsScalar GetMin( void ) { return fMin; }
|
||||
virtual hsScalar GetMax( void ) { return fMax; }
|
||||
virtual hsScalar GetStep( void ) { return fStep; }
|
||||
|
||||
virtual void SetRange( hsScalar min, hsScalar max );
|
||||
virtual void SetStep( hsScalar step ) { fStep = step; }
|
||||
|
||||
};
|
||||
|
||||
#endif // _pfGUIValueCtrl_h
|
@ -0,0 +1,943 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGameGUIMgr //
|
||||
// //
|
||||
//// History /////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// 11.13.2001 mcn - Created //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "hsTimer.h"
|
||||
#include "hsTypes.h"
|
||||
#include "pfGameGUIMgr.h"
|
||||
#include "pfGUIDialogMod.h"
|
||||
#include "pfGUIDialogHandlers.h"
|
||||
#include "pfGUIDialogNotifyProc.h"
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "pfGUIPopUpMenu.h"
|
||||
|
||||
#include "../pfMessage/pfGameGUIMsg.h"
|
||||
#include "../plMessage/plInputEventMsg.h"
|
||||
#include "../plMessage/plInputIfaceMgrMsg.h"
|
||||
#include "../pnMessage/plClientMsg.h"
|
||||
#include "../pnNetCommon/plSynchedObject.h"
|
||||
#include "../plInputCore/plInputInterface.h"
|
||||
#include "../plInputCore/plInputDevice.h"
|
||||
#include "../plInputCore/plInputInterfaceMgr.h"
|
||||
#include "../pnInputCore/plKeyMap.h"
|
||||
#include "../pnKeyedObject/plFixedKey.h"
|
||||
#include "../pnSceneObject/plSceneObject.h" // So we can get the target sceneNode of a dialog
|
||||
#include "../plMessage/plConsoleMsg.h"
|
||||
#include "plgDispatch.h"
|
||||
|
||||
#include "../plResMgr/plKeyFinder.h"
|
||||
|
||||
#include "pfGUITagDefs.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// pfGameUIInputInterface Definition ///////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class pfGameUIInputInterface : public plInputInterface
|
||||
{
|
||||
protected:
|
||||
pfGameGUIMgr * const fGUIManager;
|
||||
|
||||
UInt8 fModifiers;
|
||||
UInt8 fButtonState;
|
||||
hsBool fHaveInterestingCursor;
|
||||
UInt32 fCurrentCursor;
|
||||
|
||||
virtual hsBool IHandleCtrlCmd( plCtrlCmd *cmd );
|
||||
virtual hsBool IControlCodeEnabled( ControlEventCode code );
|
||||
|
||||
public:
|
||||
|
||||
pfGameUIInputInterface( pfGameGUIMgr * const mgr );
|
||||
|
||||
virtual UInt32 GetPriorityLevel( void ) const { return kGUISystemPriority; }
|
||||
virtual hsBool InterpretInputEvent( plInputEventMsg *pMsg );
|
||||
virtual UInt32 GetCurrentCursorID( void ) const;
|
||||
virtual hsScalar GetCurrentCursorOpacity( void ) const;
|
||||
virtual hsBool HasInterestingCursorID( void ) const { return fHaveInterestingCursor; }
|
||||
virtual hsBool SwitchInterpretOrder( void ) const { return true; }
|
||||
|
||||
virtual void RestoreDefaultKeyMappings( void )
|
||||
{
|
||||
if( fControlMap != nil )
|
||||
{
|
||||
fControlMap->UnmapAllBindings();
|
||||
fControlMap->BindKey( KEY_BACKSPACE, B_CONTROL_EXIT_GUI_MODE, plKeyMap::kFirstAlways );
|
||||
fControlMap->BindKey( KEY_ESCAPE, B_CONTROL_EXIT_GUI_MODE, plKeyMap::kSecondAlways );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// pfGameGUIMgr Functions //////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pfGameGUIMgr *pfGameGUIMgr::fInstance = nil;
|
||||
|
||||
|
||||
//// Constructor & Destructor ////////////////////////////////////////////////
|
||||
|
||||
pfGameGUIMgr::pfGameGUIMgr()
|
||||
{
|
||||
fActivated = false;
|
||||
fInputCtlIndex = 0;
|
||||
fActiveDialogs = nil;
|
||||
|
||||
fInputConfig = nil;
|
||||
|
||||
fInstance = this;
|
||||
|
||||
fDefaultCursor = plInputInterface::kCursorUp;
|
||||
fCursorOpacity = 1.f;
|
||||
fAspectRatio = 0;
|
||||
}
|
||||
|
||||
pfGameGUIMgr::~pfGameGUIMgr()
|
||||
{
|
||||
int i;
|
||||
|
||||
// the GUIMgr is dead!
|
||||
fInstance = nil;
|
||||
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
UnloadDialog( fDialogs[ i ] );
|
||||
|
||||
for( i = 0; i < fDialogToSetKeyOf.GetCount(); i++ )
|
||||
delete fDialogToSetKeyOf[i];
|
||||
|
||||
if( fActivated )
|
||||
IActivateGUI( false );
|
||||
|
||||
delete fInputConfig;
|
||||
}
|
||||
|
||||
|
||||
//// Init ////////////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGameGUIMgr::Init( void )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//// Draw ////////////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGameGUIMgr::Draw( plPipeline *p )
|
||||
{
|
||||
}
|
||||
|
||||
//// MsgReceive //////////////////////////////////////////////////////////////
|
||||
|
||||
hsBool pfGameGUIMgr::MsgReceive( plMessage* pMsg )
|
||||
{
|
||||
pfGameGUIMsg *guiMsg = pfGameGUIMsg::ConvertNoRef( pMsg );
|
||||
if( guiMsg != nil )
|
||||
{
|
||||
if( guiMsg->GetCommand() == pfGameGUIMsg::kLoadDialog )
|
||||
LoadDialog( guiMsg->GetString(), nil, guiMsg->GetAge() );
|
||||
else if( guiMsg->GetCommand() == pfGameGUIMsg::kShowDialog )
|
||||
IShowDialog( guiMsg->GetString() );
|
||||
else if( guiMsg->GetCommand() == pfGameGUIMsg::kHideDialog )
|
||||
IHideDialog( guiMsg->GetString() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef( pMsg );
|
||||
if( refMsg != nil )
|
||||
{
|
||||
if( refMsg->fType == kDlgModRef )
|
||||
{
|
||||
if( refMsg->GetContext() & ( plRefMsg::kOnCreate | plRefMsg::kOnRequest ) )
|
||||
{
|
||||
IAddDlgToList( refMsg->GetRef() );
|
||||
}
|
||||
else if( refMsg->GetContext() & plRefMsg::kOnReplace )
|
||||
{
|
||||
IRemoveDlgFromList( refMsg->GetOldRef() );
|
||||
IAddDlgToList( refMsg->GetRef() );
|
||||
}
|
||||
else if( refMsg->GetContext() & ( plRefMsg::kOnRemove | plRefMsg::kOnDestroy ) )
|
||||
{
|
||||
IRemoveDlgFromList( refMsg->GetRef() );
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return hsKeyedObject::MsgReceive( pMsg );
|
||||
}
|
||||
|
||||
//// IAddDlgToList ///////////////////////////////////////////////////////////
|
||||
|
||||
void pfGameGUIMgr::IAddDlgToList( hsKeyedObject *obj )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
if( fDialogs.Find( (pfGUIDialogMod *)obj ) == fDialogs.kMissingIndex )
|
||||
{
|
||||
pfGUIDialogMod *mod = pfGUIDialogMod::ConvertNoRef( obj );
|
||||
if( mod != nil )
|
||||
{
|
||||
mod->UpdateAspectRatio(); // adding a new dialog, make sure the correct aspect ratio is set
|
||||
fDialogs.Append( mod );
|
||||
|
||||
|
||||
// check to see if it is the dialog we are waiting for to be loaded
|
||||
for ( i=0 ; i<fDialogToSetKeyOf.Count() ; i++ )
|
||||
{
|
||||
if ( hsStrEQ(fDialogToSetKeyOf[i]->GetName(), mod->GetName()) )
|
||||
{
|
||||
SetDialogToNotify(mod,fDialogToSetKeyOf[i]->GetKey());
|
||||
// now remove this entry... we did it
|
||||
delete fDialogToSetKeyOf[i];
|
||||
fDialogToSetKeyOf.Remove(i);
|
||||
// that's all the damage we can do for now...
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* // It's now officially "loaded"; take it off the pending list
|
||||
for( i = 0; i < fDlgsPendingLoad.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fDlgsPendingLoad[ i ]->GetName(), ( (pfGUIDialogMod *)obj )->GetName() ) == 0 )
|
||||
{
|
||||
// Here it is
|
||||
delete fDlgsPendingLoad[ i ];
|
||||
fDlgsPendingLoad.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//// IRemoveDlgFromList //////////////////////////////////////////////////////
|
||||
|
||||
void pfGameGUIMgr::IRemoveDlgFromList( hsKeyedObject *obj )
|
||||
{
|
||||
int idx = fDialogs.Find( (pfGUIDialogMod *)obj );
|
||||
if( idx != fDialogs.kMissingIndex )
|
||||
{
|
||||
pfGUIDialogMod *mod = pfGUIDialogMod::ConvertNoRef( obj );
|
||||
hsAssert( mod != nil, "Non-dialog sent to gameGUIMgr::IRemoveDlg()" );
|
||||
|
||||
if( mod != nil )
|
||||
{
|
||||
if( mod->IsEnabled() )
|
||||
{
|
||||
mod->SetEnabled( false );
|
||||
|
||||
mod->Unlink();
|
||||
if( fActiveDialogs == nil )
|
||||
IActivateGUI( false );
|
||||
}
|
||||
|
||||
// Needed?
|
||||
// GetKey()->Release( mod->GetKey() );
|
||||
fDialogs.Remove( idx );
|
||||
}
|
||||
}
|
||||
|
||||
// It's now officially "unloaded"; take it off the pending list
|
||||
/* int i;
|
||||
for( i = 0; i < fDlgsPendingUnload.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fDlgsPendingUnload[ i ]->GetName(), ( (pfGUIDialogMod *)obj )->GetName() ) == 0 )
|
||||
{
|
||||
// Here it is
|
||||
delete fDlgsPendingUnload[ i ];
|
||||
fDlgsPendingUnload.Remove( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//// LoadDialog //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGameGUIMgr::LoadDialog( const char *name, plKey recvrKey, const char *ageName )
|
||||
{
|
||||
// see if they want to set the receiver key once the dialog is loaded
|
||||
if ( recvrKey != nil )
|
||||
{
|
||||
// first see if we are loading a dialog that is already being loaded
|
||||
bool alreadyLoaded = false;
|
||||
int i;
|
||||
for ( i=0 ; i<fDialogToSetKeyOf.Count() ; i++ )
|
||||
{
|
||||
if ( hsStrEQ(fDialogToSetKeyOf[i]->GetName(), name) )
|
||||
{
|
||||
alreadyLoaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!alreadyLoaded)
|
||||
{
|
||||
pfDialogNameSetKey* pDNSK = TRACKED_NEW pfDialogNameSetKey(name,recvrKey);
|
||||
fDialogToSetKeyOf.Append(pDNSK);
|
||||
}
|
||||
}
|
||||
|
||||
hsStatusMessageF("\nLoading Dialog %s %s ... %f\n", name, ( ageName != nil ) ? ageName : "GUI", hsTimer::GetSeconds() );
|
||||
|
||||
plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY );
|
||||
|
||||
plClientMsg *msg = TRACKED_NEW plClientMsg( plClientMsg::kLoadRoomHold );
|
||||
msg->AddReceiver( clientKey );
|
||||
msg->AddRoomLoc(plKeyFinder::Instance().FindLocation(ageName ? ageName : "GUI", name));
|
||||
msg->Send();
|
||||
|
||||
// Now add this dialog to a list of pending loads (will remove it once it's fully loaded)
|
||||
// fDlgsPendingLoad.Append( TRACKED_NEW pfDialogNameSetKey( name, nil ) );
|
||||
}
|
||||
|
||||
//// IShowDialog /////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGameGUIMgr::IShowDialog( const char *name )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fDialogs[ i ]->GetName(), name ) == 0 )
|
||||
{
|
||||
ShowDialog( fDialogs[ i ] );
|
||||
fDialogs[i]->RefreshAllControls();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// IHideDialog /////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGameGUIMgr::IHideDialog( const char *name )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fDialogs[ i ]->GetName(), name ) == 0 )
|
||||
{
|
||||
HideDialog( fDialogs[ i ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// ShowDialog //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGameGUIMgr::ShowDialog( pfGUIDialogMod *dlg, bool resetClickables /* = true */ )
|
||||
{
|
||||
if ( resetClickables )
|
||||
plInputInterfaceMgr::GetInstance()->ResetClickableState();
|
||||
if( !dlg->IsEnabled() )
|
||||
{
|
||||
dlg->SetEnabled( true );
|
||||
|
||||
// Add to active list
|
||||
if( fActiveDialogs == nil )
|
||||
IActivateGUI( true );
|
||||
|
||||
dlg->LinkToList( &fActiveDialogs );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//// HideDialog //////////////////////////////////////////////////////////////
|
||||
|
||||
void pfGameGUIMgr::HideDialog( pfGUIDialogMod *dlg )
|
||||
{
|
||||
if( dlg->IsEnabled() )
|
||||
{
|
||||
dlg->SetEnabled( false );
|
||||
|
||||
dlg->Unlink();
|
||||
if( fActiveDialogs == nil )
|
||||
IActivateGUI( false );
|
||||
}
|
||||
}
|
||||
|
||||
//// UnloadDialog ////////////////////////////////////////////////////////////
|
||||
// Destroy the dialog and all the things associated with it. Fun fun.
|
||||
|
||||
void pfGameGUIMgr::UnloadDialog( const char *name )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fDialogs[ i ]->GetName(), name ) == 0 )
|
||||
{
|
||||
UnloadDialog( fDialogs[ i ] );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pfGameGUIMgr::UnloadDialog( pfGUIDialogMod *dlg )
|
||||
{
|
||||
// IRemoveDlgFromList( dlg );
|
||||
|
||||
// Add the name to our list of dialogs pending unload
|
||||
// fDlgsPendingUnload.Append( TRACKED_NEW pfDialogNameSetKey( dlg->GetName(), nil ) );
|
||||
|
||||
plKey sceneNodeKey = dlg->GetSceneNodeKey();
|
||||
if( sceneNodeKey == nil )
|
||||
{
|
||||
hsStatusMessageF( "Warning: Unable to grab sceneNodeKey to unload dialog %s; searching for it...", dlg->GetName() );
|
||||
sceneNodeKey = plKeyFinder::Instance().FindSceneNodeKey( dlg->GetKey()->GetUoid().GetLocation() );
|
||||
}
|
||||
|
||||
// if( dlg->GetTarget() )
|
||||
if( sceneNodeKey != nil )
|
||||
{
|
||||
plKey clientKey = hsgResMgr::ResMgr()->FindKey( kClient_KEY );
|
||||
|
||||
plClientMsg *msg = TRACKED_NEW plClientMsg( plClientMsg::kUnloadRoom );
|
||||
msg->AddReceiver( clientKey );
|
||||
// msg->SetProgressBarSuppression( true );
|
||||
msg->AddRoomLoc(sceneNodeKey->GetUoid().GetLocation());
|
||||
msg->Send();
|
||||
}
|
||||
// GetKey()->Release( dlg->GetKey() );
|
||||
}
|
||||
|
||||
//// IsDialogLoaded ////// see if the dialog is in our list of loaded dialogs
|
||||
|
||||
hsBool pfGameGUIMgr::IsDialogLoaded( const char *name )
|
||||
{
|
||||
// search through all the dialogs we've loaded
|
||||
int i;
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fDialogs[ i ]->GetName(), name ) == 0 )
|
||||
{
|
||||
// found 'em
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// nota
|
||||
return false;
|
||||
}
|
||||
|
||||
pfGUIPopUpMenu *pfGameGUIMgr::FindPopUpMenu( const char *name )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
{
|
||||
pfGUIPopUpMenu *menu = pfGUIPopUpMenu::ConvertNoRef( fDialogs[ i ] );
|
||||
if( menu != nil && stricmp( menu->GetName(), name ) == 0 )
|
||||
return menu;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
std::vector<plPostEffectMod*> pfGameGUIMgr::GetDlgRenderMods( void ) const
|
||||
{
|
||||
std::vector<plPostEffectMod*> retVal;
|
||||
pfGUIDialogMod* curDialog = fActiveDialogs;
|
||||
while (curDialog)
|
||||
{
|
||||
retVal.push_back(curDialog->GetRenderMod());
|
||||
curDialog = curDialog->GetNext();
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///// SetDialogToNotify - based on name
|
||||
// This will Set the handler to a Notify Handler that will send a GUINotifyMsg to the receiver
|
||||
//
|
||||
void pfGameGUIMgr::SetDialogToNotify(const char *name, plKey recvrKey)
|
||||
{
|
||||
int i;
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fDialogs[ i ]->GetName(), name ) == 0 )
|
||||
{
|
||||
SetDialogToNotify( fDialogs[ i ], recvrKey );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///// SetDialogToNotify - pfGUIDialogMod*
|
||||
// This will Set the handler to a Notify Handler that will send a GUINotifyMsg to the receiver
|
||||
//
|
||||
void pfGameGUIMgr::SetDialogToNotify(pfGUIDialogMod *dlg, plKey recvrKey)
|
||||
{
|
||||
pfGUIDialogNotifyProc* handler = TRACKED_NEW pfGUIDialogNotifyProc(recvrKey);
|
||||
dlg->SetHandler(handler);
|
||||
handler->OnInit();
|
||||
}
|
||||
|
||||
|
||||
//// IActivateGUI ////////////////////////////////////////////////////////////
|
||||
// "Activates" the GUI manager. This means enabling the drawing of GUI
|
||||
// elements on the screen as well as rerouting input to us.
|
||||
|
||||
void pfGameGUIMgr::IActivateGUI( hsBool activate )
|
||||
{
|
||||
if( fActivated == activate )
|
||||
return;
|
||||
|
||||
if( activate )
|
||||
{
|
||||
fInputConfig = TRACKED_NEW pfGameUIInputInterface( this );
|
||||
plInputIfaceMgrMsg *msg = TRACKED_NEW plInputIfaceMgrMsg( plInputIfaceMgrMsg::kAddInterface );
|
||||
msg->SetIFace( fInputConfig );
|
||||
plgDispatch::MsgSend( msg );
|
||||
}
|
||||
else
|
||||
{
|
||||
plInputIfaceMgrMsg *msg = TRACKED_NEW plInputIfaceMgrMsg( plInputIfaceMgrMsg::kRemoveInterface );
|
||||
msg->SetIFace( fInputConfig );
|
||||
plgDispatch::MsgSend( msg );
|
||||
|
||||
hsRefCnt_SafeUnRef( fInputConfig );
|
||||
fInputConfig = nil;
|
||||
}
|
||||
|
||||
fActivated = activate;
|
||||
}
|
||||
|
||||
//// IHandleMouse ////////////////////////////////////////////////////////////
|
||||
// Distributes mouse events to the dialogs currently active
|
||||
|
||||
hsBool pfGameGUIMgr::IHandleMouse( EventType event, hsScalar mouseX, hsScalar mouseY, UInt8 modifiers, UInt32 *desiredCursor )
|
||||
{
|
||||
pfGUIDialogMod *dlg;
|
||||
|
||||
|
||||
// Update interesting things first, no matter what, for ALL dialogs
|
||||
hsBool modalPresent = false;
|
||||
for( dlg = fActiveDialogs; dlg != nil; dlg = dlg->GetNext() )
|
||||
{
|
||||
dlg->UpdateInterestingThings( mouseX, mouseY, modifiers, modalPresent );
|
||||
if (dlg->HasFlag( pfGUIDialogMod::kModal ))
|
||||
modalPresent = true;
|
||||
}
|
||||
|
||||
for( dlg = fActiveDialogs; dlg != nil; dlg = dlg->GetNext() )
|
||||
{
|
||||
if( dlg->HandleMouseEvent( event, mouseX, mouseY, modifiers ) ||
|
||||
( dlg->HasFlag( pfGUIDialogMod::kModal ) && event != pfGameGUIMgr::kMouseUp ) )
|
||||
{
|
||||
// If this dialog handled it, also get the cursor it wants
|
||||
*desiredCursor = dlg->GetDesiredCursor();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//// IHandleKeyEvt ///////////////////////////////////////////////////////////
|
||||
// Distributes mouse events to the dialogs currently active
|
||||
|
||||
hsBool pfGameGUIMgr::IHandleKeyEvt( EventType event, plKeyDef key, UInt8 modifiers )
|
||||
{
|
||||
pfGUIDialogMod *dlg;
|
||||
|
||||
|
||||
for( dlg = fActiveDialogs; dlg != nil; dlg = dlg->GetNext() )
|
||||
{
|
||||
if( dlg->HandleKeyEvent( event, key, modifiers ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//// IHandleKeyPress /////////////////////////////////////////////////////////
|
||||
// Like IHandleKeyPress, but takes in a char for distributing actual
|
||||
// characters typed.
|
||||
|
||||
hsBool pfGameGUIMgr::IHandleKeyPress( char key, UInt8 modifiers )
|
||||
{
|
||||
pfGUIDialogMod *dlg;
|
||||
|
||||
|
||||
for( dlg = fActiveDialogs; dlg != nil; dlg = dlg->GetNext() )
|
||||
{
|
||||
if( dlg->HandleKeyPress( key, modifiers ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//// IModalBlocking //////////////////////////////////////////////////////////
|
||||
// Looks at the chain of active dialogs and determines if there's any modals
|
||||
// blocking input. Returns true if so.
|
||||
|
||||
hsBool pfGameGUIMgr::IModalBlocking( void )
|
||||
{
|
||||
return ( IGetTopModal() != nil ) ? true : false;
|
||||
}
|
||||
|
||||
//// IGetTopModal ////////////////////////////////////////////////////////////
|
||||
// Returns the topmost (visible) modal dialog, nil if none.
|
||||
|
||||
pfGUIDialogMod *pfGameGUIMgr::IGetTopModal( void ) const
|
||||
{
|
||||
pfGUIDialogMod *dlg;
|
||||
|
||||
|
||||
for( dlg = fActiveDialogs; dlg != nil; dlg = dlg->GetNext() )
|
||||
{
|
||||
if( dlg->HasFlag( pfGUIDialogMod::kModal ) )
|
||||
return dlg;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Control Config Class ////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pfGameUIInputInterface::pfGameUIInputInterface( pfGameGUIMgr * const mgr ) : plInputInterface(), fGUIManager( mgr )
|
||||
{
|
||||
fModifiers = pfGameGUIMgr::kNoModifiers;
|
||||
fButtonState = 0;
|
||||
fHaveInterestingCursor = false;
|
||||
SetEnabled( true ); // Always enabled
|
||||
fCurrentCursor = kCursorUp;
|
||||
|
||||
// Add our control codes to our control map. Do NOT add the key bindings yet.
|
||||
// Note: HERE is where you specify the actions for each command, i.e. net propagate and so forth.
|
||||
// This part basically declares us master of the bindings for these commands.
|
||||
|
||||
// IF YOU ARE LOOKING TO CHANGE THE DEFAULT KEY BINDINGS, DO NOT LOOK HERE. GO TO
|
||||
// RestoreDefaultKeyMappings()!!!!
|
||||
|
||||
fControlMap->AddCode( B_CONTROL_EXIT_GUI_MODE, kControlFlagNormal | kControlFlagNoRepeat );
|
||||
|
||||
// IF YOU ARE LOOKING TO CHANGE THE DEFAULT KEY BINDINGS, DO NOT LOOK HERE. GO TO
|
||||
// RestoreDefaultKeyMappings()!!!!
|
||||
}
|
||||
|
||||
hsBool pfGameUIInputInterface::IControlCodeEnabled( ControlEventCode code )
|
||||
{
|
||||
if( code == B_CONTROL_EXIT_GUI_MODE )
|
||||
{
|
||||
// Disable the exitGUIMode key binding if we don't have a modal dialog up or if
|
||||
// the cursor is inside an edit or multiline edit control
|
||||
if( !fGUIManager->IModalBlocking() )
|
||||
return false;
|
||||
|
||||
pfGUIDialogMod *dlg = fGUIManager->IGetTopModal();
|
||||
if( dlg != nil )
|
||||
{
|
||||
pfGUIControlMod *ctrl = dlg->GetFocus();
|
||||
if( ctrl != nil && ctrl->HasFlag( pfGUIControlMod::kTakesSpecialKeys ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true; // Enable all other codes
|
||||
}
|
||||
|
||||
hsBool pfGameUIInputInterface::IHandleCtrlCmd( plCtrlCmd *cmd )
|
||||
{
|
||||
if( cmd->fControlCode == B_CONTROL_EXIT_GUI_MODE )
|
||||
{
|
||||
if( cmd->fControlActivated )
|
||||
{
|
||||
pfGUIDialogMod *dlg = fGUIManager->IGetTopModal();
|
||||
if( dlg != nil && dlg->GetHandler() != nil )
|
||||
dlg->GetHandler()->OnControlEvent( pfGUIDialogProc::kExitMode );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
hsBool pfGameUIInputInterface::InterpretInputEvent( plInputEventMsg *pMsg )
|
||||
{
|
||||
hsBool handled = false;
|
||||
|
||||
|
||||
/// The in-game UI has to do far more complicated control handling, so we just overload this entirely
|
||||
plKeyEventMsg *pKeyMsg = plKeyEventMsg::ConvertNoRef( pMsg );
|
||||
if( pKeyMsg )
|
||||
{
|
||||
// By default, we don't want the modifier keys treated as "handled", 'cause
|
||||
// we want the other interfaces to get them as well (unless we have a modal
|
||||
// as the top dialog).
|
||||
if( pKeyMsg->GetKeyCode() == KEY_SHIFT )
|
||||
{
|
||||
if( pKeyMsg->GetKeyDown() )
|
||||
fModifiers |= pfGameGUIMgr::kShiftDown;
|
||||
else
|
||||
fModifiers &= ~pfGameGUIMgr::kShiftDown;
|
||||
}
|
||||
else if( pKeyMsg->GetKeyCode() == KEY_CTRL )
|
||||
{
|
||||
if( pKeyMsg->GetKeyDown() )
|
||||
fModifiers |= pfGameGUIMgr::kCtrlDown;
|
||||
else
|
||||
fModifiers &= ~pfGameGUIMgr::kCtrlDown;
|
||||
}
|
||||
else if( pKeyMsg->GetKeyCode() == KEY_CAPSLOCK )
|
||||
{
|
||||
if( pKeyMsg->GetKeyDown() )
|
||||
fModifiers |= pfGameGUIMgr::kCapsDown;
|
||||
else
|
||||
fModifiers &= ~pfGameGUIMgr::kCapsDown;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sometimes I can't explain why Mathew does some of the things he does.
|
||||
// I going to replace his modifier flags (which I don't know why he thought he had to have his own)
|
||||
// with the ones that are in the keymsg since they seem to be more accurate!
|
||||
fModifiers = 0;
|
||||
if ( pKeyMsg->GetShiftKeyDown() )
|
||||
fModifiers |= pfGameGUIMgr::kShiftDown;
|
||||
if ( pKeyMsg->GetCtrlKeyDown() )
|
||||
fModifiers |= pfGameGUIMgr::kCtrlDown;
|
||||
if ( pKeyMsg->GetCapsLockKeyDown() )
|
||||
fModifiers |= pfGameGUIMgr::kCapsDown;
|
||||
if( pKeyMsg->GetKeyDown() )
|
||||
{
|
||||
if( !pKeyMsg->GetRepeat() )
|
||||
handled = fGUIManager->IHandleKeyEvt( pfGameGUIMgr::kKeyDown, pKeyMsg->GetKeyCode(), fModifiers );
|
||||
else
|
||||
handled = fGUIManager->IHandleKeyEvt( pfGameGUIMgr::kKeyRepeat, pKeyMsg->GetKeyCode(), fModifiers );
|
||||
|
||||
handled |= fGUIManager->IHandleKeyPress( plKeyboardDevice::KeyEventToChar( pKeyMsg ), fModifiers );
|
||||
}
|
||||
else
|
||||
handled = fGUIManager->IHandleKeyEvt( pfGameGUIMgr::kKeyUp, pKeyMsg->GetKeyCode(), fModifiers );
|
||||
}
|
||||
|
||||
// We need to do early interception of a screenshot request, since they want
|
||||
// us to be able to take screen shots while in a modal GUI... whee
|
||||
// Also, this should only be run if the dialog didn't handle the command in
|
||||
// the first place (taking screenshots while the user is typing would be
|
||||
// awkward) and we must do it on key down because the key binding routines
|
||||
// also trigger on key-down and we don't want to be taking screen shots when
|
||||
// the user re-binds the screenshot command.
|
||||
// HACK HACK HACK
|
||||
if ((!handled) && (pKeyMsg->GetKeyDown()))
|
||||
{
|
||||
const plKeyBinding* keymap = plInputInterfaceMgr::GetInstance()->FindBindingByConsoleCmd("Game.KITakePicture");
|
||||
if (keymap)
|
||||
{
|
||||
unsigned keyFlags = 0;
|
||||
if (pKeyMsg->GetCtrlKeyDown())
|
||||
keyFlags |= plKeyCombo::kCtrl;
|
||||
if (pKeyMsg->GetShiftKeyDown())
|
||||
keyFlags |= plKeyCombo::kShift;
|
||||
plKeyCombo combo(pKeyMsg->GetKeyCode(), keyFlags);
|
||||
if ((keymap->GetKey1().IsSatisfiedBy(combo)) || (keymap->GetKey2().IsSatisfiedBy(combo)))
|
||||
{
|
||||
// tell the KI to take the shot
|
||||
plConsoleMsg * consoleMsg = NEWZERO(plConsoleMsg);
|
||||
consoleMsg->SetCmd(plConsoleMsg::kExecuteLine);
|
||||
consoleMsg->SetString("Game.KITakePicture");
|
||||
consoleMsg->Send(nil, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool modal = fGUIManager->IModalBlocking();
|
||||
return handled || modal; // we "handle" it if we are modal, even if it didn't do anything
|
||||
}
|
||||
|
||||
plMouseEventMsg *pMouseMsg = plMouseEventMsg::ConvertNoRef( pMsg );
|
||||
if( pMouseMsg && fManager->IsClickEnabled() )
|
||||
{
|
||||
if( pMouseMsg->GetButton() == kLeftButtonDown )
|
||||
{
|
||||
handled = fGUIManager->IHandleMouse( pfGameGUIMgr::kMouseDown, pMouseMsg->GetXPos(), pMouseMsg->GetYPos(), fModifiers, &fCurrentCursor );
|
||||
if (handled)
|
||||
fButtonState |= kLeftButtonDown;
|
||||
}
|
||||
else if( pMouseMsg->GetButton() == kLeftButtonUp )
|
||||
{
|
||||
handled = fGUIManager->IHandleMouse( pfGameGUIMgr::kMouseUp, pMouseMsg->GetXPos(), pMouseMsg->GetYPos(), fModifiers, &fCurrentCursor );
|
||||
if ((handled) || (fButtonState & kLeftButtonDown)) // even if we didn't handle the mouse up, if we think the button is still down, we should clear our flag
|
||||
fButtonState &= ~kLeftButtonDown;
|
||||
}
|
||||
else if( pMouseMsg->GetButton() == kLeftButtonDblClk )
|
||||
handled = fGUIManager->IHandleMouse( pfGameGUIMgr::kMouseDblClick, pMouseMsg->GetXPos(), pMouseMsg->GetYPos(), fModifiers, &fCurrentCursor );
|
||||
else if( fButtonState & kLeftButtonDown )
|
||||
handled = fGUIManager->IHandleMouse( pfGameGUIMgr::kMouseDrag, pMouseMsg->GetXPos(), pMouseMsg->GetYPos(), fModifiers, &fCurrentCursor );
|
||||
else
|
||||
handled = fGUIManager->IHandleMouse( pfGameGUIMgr::kMouseMove, pMouseMsg->GetXPos(), pMouseMsg->GetYPos(), fModifiers, &fCurrentCursor );
|
||||
|
||||
fHaveInterestingCursor = handled;
|
||||
return handled;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt32 pfGameUIInputInterface::GetCurrentCursorID( void ) const
|
||||
{
|
||||
if( fCurrentCursor == 0 )
|
||||
{
|
||||
if ( pfGameGUIMgr::GetInstance() )
|
||||
return pfGameGUIMgr::GetInstance()->GetDefaultCursor();
|
||||
else
|
||||
return kCursorUp;
|
||||
}
|
||||
|
||||
return fCurrentCursor;
|
||||
}
|
||||
|
||||
hsScalar pfGameUIInputInterface::GetCurrentCursorOpacity( void ) const
|
||||
{
|
||||
if ( pfGameGUIMgr::GetInstance() )
|
||||
return pfGameGUIMgr::GetInstance()->GetCursorOpacity();
|
||||
else
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Tag Stuff ///////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern pfGUITag gGUITags[]; // From pfGUITagDefs.cpp
|
||||
|
||||
//// GetDialogFromTag ////////////////////////////////////////////////////////
|
||||
|
||||
pfGUIDialogMod *pfGameGUIMgr::GetDialogFromTag( UInt32 tagID )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
{
|
||||
if( fDialogs[ i ]->GetTagID() == tagID )
|
||||
return fDialogs[ i ];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//// GetDialogFromString ////////////////////////////////////////////////////////
|
||||
|
||||
pfGUIDialogMod *pfGameGUIMgr::GetDialogFromString( const char *name )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i = 0; i < fDialogs.GetCount(); i++ )
|
||||
{
|
||||
if( stricmp( fDialogs[ i ]->GetName(), name ) == 0 )
|
||||
return fDialogs[ i ];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//// GetControlFromTag ///////////////////////////////////////////////////////
|
||||
|
||||
pfGUIControlMod *pfGameGUIMgr::GetControlFromTag( pfGUIDialogMod *dlg, UInt32 tagID )
|
||||
{
|
||||
return dlg->GetControlFromTag( tagID );
|
||||
}
|
||||
|
||||
//// GetNumTags //////////////////////////////////////////////////////////////
|
||||
|
||||
UInt32 pfGameGUIMgr::GetNumTags( void )
|
||||
{
|
||||
UInt32 count;
|
||||
|
||||
|
||||
for( count = 0; gGUITags[ count ].fID != 0; count++ );
|
||||
return count;
|
||||
}
|
||||
|
||||
//// GetTag //////////////////////////////////////////////////////////////////
|
||||
|
||||
pfGUITag *pfGameGUIMgr::GetTag( UInt32 tagIndex )
|
||||
{
|
||||
UInt32 count;
|
||||
|
||||
|
||||
for( count = 0; gGUITags[ count ].fID != 0; count++ );
|
||||
hsAssert( tagIndex < count, "Bad index to GetTag()" );
|
||||
|
||||
return &gGUITags[ tagIndex ];
|
||||
}
|
||||
|
||||
UInt32 pfGameGUIMgr::GetHighestTag( void )
|
||||
{
|
||||
UInt32 i, id = 1;
|
||||
|
||||
|
||||
for( i = 0; gGUITags[ i ].fID != 0; i++ )
|
||||
{
|
||||
if( id < gGUITags[ i ].fID )
|
||||
id = gGUITags[ i ].fID;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
void pfGameGUIMgr::SetAspectRatio(hsScalar aspectratio)
|
||||
{
|
||||
hsScalar oldAspectRatio = fAspectRatio;
|
||||
|
||||
// don't allow the aspectratio below 4:3
|
||||
hsScalar fourThree = 4.0f/3.0f;
|
||||
fAspectRatio = aspectratio < fourThree ? fourThree : aspectratio;
|
||||
|
||||
if (fAspectRatio != oldAspectRatio)
|
||||
{
|
||||
// need to tell dialogs to update
|
||||
int i;
|
||||
for (i = 0; i < fDialogs.GetCount(); i++)
|
||||
{
|
||||
if (fDialogs[i])
|
||||
fDialogs[i]->UpdateAspectRatio();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// pfGameGUIMgr Header //
|
||||
// A.K.A. "Ooh, we get a GUI!" //
|
||||
// //
|
||||
//// Description /////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// The in-game GUI manager. Handles reading, creation, and input for //
|
||||
// dialog boxes at runtime. //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _pfGameGUIMgr_h
|
||||
#define _pfGameGUIMgr_h
|
||||
|
||||
#include "hsTypes.h"
|
||||
#include "hsTemplates.h"
|
||||
#include "../pnInputCore/plKeyDef.h"
|
||||
#include "../pnKeyedObject/hsKeyedObject.h"
|
||||
#include <vector>
|
||||
|
||||
class plPipeline;
|
||||
class plMessage;
|
||||
class pfGUIDialogMod;
|
||||
class pfGUIControlMod;
|
||||
class pfGameUIInputInterface;
|
||||
class plPostEffectMod;
|
||||
|
||||
//// Tag Definitions /////////////////////////////////////////////////////////
|
||||
// Each dialog/control gets an optional tag ID number. This is the link
|
||||
// between MAX and C++. You attach a Tag component to a control or dialog
|
||||
// in MAX and assign it an ID (supplied by a list of konstants that are
|
||||
// hard-coded). Then, in code, you ask the gameGUIMgr for the dialog (or
|
||||
// control) with that ID, and pop, you get it back. Then you run with it.
|
||||
//
|
||||
// Easy, huh?
|
||||
|
||||
class pfGUITag
|
||||
{
|
||||
public:
|
||||
UInt32 fID;
|
||||
char fName[ 128 ];
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// This class just holds a name and the key to set the receiver to
|
||||
// after the dialog gets loaded.
|
||||
class pfDialogNameSetKey
|
||||
{
|
||||
private:
|
||||
char *fName;
|
||||
plKey fKey;
|
||||
public:
|
||||
pfDialogNameSetKey(const char *name, plKey key) { fName = hsStrcpy(name); fKey=key; }
|
||||
~pfDialogNameSetKey() { delete [] fName; }
|
||||
const char *GetName() { return fName; }
|
||||
plKey GetKey() { return fKey; }
|
||||
};
|
||||
|
||||
//// Manager Class Definition ////////////////////////////////////////////////
|
||||
|
||||
class pfGUIPopUpMenu;
|
||||
class pfGameGUIMgr : public hsKeyedObject
|
||||
{
|
||||
friend class pfGameUIInputInterface;
|
||||
|
||||
public:
|
||||
|
||||
enum EventType
|
||||
{
|
||||
kMouseDown,
|
||||
kMouseUp,
|
||||
kMouseMove,
|
||||
kMouseDrag,
|
||||
kKeyDown,
|
||||
kKeyUp,
|
||||
kKeyRepeat,
|
||||
kMouseDblClick
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kNoModifiers = 0,
|
||||
kShiftDown = 0x01,
|
||||
kCtrlDown = 0x02,
|
||||
kCapsDown = 0x04
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
static pfGameGUIMgr *fInstance;
|
||||
|
||||
protected:
|
||||
|
||||
hsTArray<pfGUIDialogMod *> fDialogs;
|
||||
pfGUIDialogMod *fActiveDialogs;
|
||||
|
||||
// These two lists help us manage when dialogs get told to load or unload versus when they actually *do*
|
||||
hsTArray<pfDialogNameSetKey *> fDlgsPendingLoad;
|
||||
hsTArray<pfDialogNameSetKey *> fDlgsPendingUnload;
|
||||
|
||||
hsBool fActivated;
|
||||
UInt32 fActiveDlgCount;
|
||||
|
||||
pfGameUIInputInterface *fInputConfig;
|
||||
UInt32 fInputCtlIndex;
|
||||
|
||||
UInt32 fDefaultCursor;
|
||||
hsScalar fCursorOpacity;
|
||||
hsScalar fAspectRatio;
|
||||
|
||||
// This is an array of the dialogs (by name) that need their
|
||||
// receiver key set once they are loaded.
|
||||
// This array shouldn't get more than one entry... but
|
||||
// it could be more....
|
||||
// LoadDialog adds an entry and MsgReceive removes it
|
||||
hsTArray<pfDialogNameSetKey *> fDialogToSetKeyOf;
|
||||
|
||||
void ILoadDialog( const char *name );
|
||||
void IShowDialog( const char *name );
|
||||
void IHideDialog( const char *name );
|
||||
|
||||
void IAddDlgToList( hsKeyedObject *obj );
|
||||
void IRemoveDlgFromList( hsKeyedObject *obj );
|
||||
|
||||
void IActivateGUI( hsBool activate );
|
||||
|
||||
hsBool IHandleMouse( EventType event, hsScalar mouseX, hsScalar mouseY, UInt8 modifiers, UInt32 *desiredCursor );
|
||||
hsBool IHandleKeyEvt( EventType event, plKeyDef key, UInt8 modifiers );
|
||||
hsBool IHandleKeyPress( char key, UInt8 modifiers );
|
||||
|
||||
hsBool IModalBlocking( void );
|
||||
|
||||
pfGUIDialogMod *IGetTopModal( void ) const;
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
kDlgModRef = 0
|
||||
};
|
||||
|
||||
|
||||
pfGameGUIMgr();
|
||||
~pfGameGUIMgr();
|
||||
|
||||
CLASSNAME_REGISTER( pfGameGUIMgr );
|
||||
GETINTERFACE_ANY( pfGameGUIMgr, hsKeyedObject );
|
||||
|
||||
void Draw( plPipeline *p );
|
||||
|
||||
hsBool Init( void );
|
||||
|
||||
virtual hsBool MsgReceive( plMessage* pMsg );
|
||||
|
||||
void LoadDialog( const char *name, plKey recvrKey=nil, const char *ageName = nil ); // AgeName = nil defaults to "GUI"
|
||||
void ShowDialog( const char *name ) { IShowDialog(name); }
|
||||
void HideDialog( const char *name ) { IHideDialog(name); }
|
||||
void UnloadDialog( const char *name );
|
||||
void UnloadDialog( pfGUIDialogMod *dlg );
|
||||
|
||||
void ShowDialog( pfGUIDialogMod *dlg, bool resetClickables=true );
|
||||
void HideDialog( pfGUIDialogMod *dlg );
|
||||
|
||||
hsBool IsDialogLoaded( const char *name );
|
||||
pfGUIDialogMod *GetDialogFromString( const char *name );
|
||||
|
||||
void SetDialogToNotify(const char *name, plKey recvrKey);
|
||||
void SetDialogToNotify(pfGUIDialogMod *dlg, plKey recvrKey);
|
||||
|
||||
void SetDefaultCursor(UInt32 defaultCursor) { fDefaultCursor = defaultCursor; }
|
||||
UInt32 GetDefaultCursor() { return fDefaultCursor; }
|
||||
void SetCursorOpacity(hsScalar opacity) { fCursorOpacity = opacity; }
|
||||
hsScalar GetCursorOpacity() { return fCursorOpacity; }
|
||||
|
||||
pfGUIPopUpMenu *FindPopUpMenu( const char *name );
|
||||
|
||||
std::vector<plPostEffectMod*> GetDlgRenderMods( void ) const;
|
||||
hsBool IsModalBlocking( void ) {return IModalBlocking();}
|
||||
|
||||
// Tag ID stuff
|
||||
pfGUIDialogMod *GetDialogFromTag( UInt32 tagID );
|
||||
pfGUIControlMod *GetControlFromTag( pfGUIDialogMod *dlg, UInt32 tagID );
|
||||
|
||||
static UInt32 GetNumTags( void );
|
||||
static pfGUITag *GetTag( UInt32 tagIndex );
|
||||
static UInt32 GetHighestTag( void );
|
||||
void SetAspectRatio(hsScalar aspectratio);
|
||||
hsScalar GetAspectRatio() { return fAspectRatio; }
|
||||
|
||||
static pfGameGUIMgr *GetInstance( void ) { return fInstance; }
|
||||
};
|
||||
|
||||
#endif //_pfGameGUIMgr_h
|
||||
|
@ -0,0 +1,77 @@
|
||||
/*==LICENSE==*
|
||||
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
|
||||
*==LICENSE==*/
|
||||
|
||||
#ifndef _pfGameGUIMgrCreatable_inc
|
||||
#define _pfGameGUIMgrCreatable_inc
|
||||
|
||||
#include "../pnFactory/plCreator.h"
|
||||
|
||||
#include "pfGameGUIMgr.h"
|
||||
|
||||
REGISTER_CREATABLE( pfGameGUIMgr );
|
||||
|
||||
#include "pfGUIDialogMod.h"
|
||||
#include "pfGUIControlMod.h"
|
||||
#include "pfGUIButtonMod.h"
|
||||
#include "pfGUIDraggableMod.h"
|
||||
#include "pfGUIListBoxMod.h"
|
||||
#include "pfGUITextBoxMod.h"
|
||||
#include "pfGUIEditBoxMod.h"
|
||||
#include "pfGUIUpDownPairMod.h"
|
||||
#include "pfGUIValueCtrl.h"
|
||||
#include "pfGUIKnobCtrl.h"
|
||||
#include "pfGUIDragBarCtrl.h"
|
||||
#include "pfGUICheckBoxCtrl.h"
|
||||
#include "pfGUIRadioGroupCtrl.h"
|
||||
#include "pfGUIDynDisplayCtrl.h"
|
||||
#include "pfGUIMultiLineEditCtrl.h"
|
||||
#include "pfGUIProgressCtrl.h"
|
||||
#include "pfGUIClickMapCtrl.h"
|
||||
#include "pfGUIPopUpMenu.h"
|
||||
#include "pfGUIMenuItem.h"
|
||||
|
||||
REGISTER_CREATABLE( pfGUIDialogMod );
|
||||
REGISTER_NONCREATABLE( pfGUIControlMod );
|
||||
REGISTER_CREATABLE( pfGUIButtonMod );
|
||||
REGISTER_CREATABLE( pfGUIDraggableMod );
|
||||
REGISTER_CREATABLE( pfGUIListBoxMod );
|
||||
REGISTER_CREATABLE( pfGUITextBoxMod );
|
||||
REGISTER_CREATABLE( pfGUIEditBoxMod );
|
||||
REGISTER_NONCREATABLE( pfGUIValueCtrl );
|
||||
REGISTER_CREATABLE( pfGUIUpDownPairMod );
|
||||
REGISTER_CREATABLE( pfGUIKnobCtrl );
|
||||
REGISTER_CREATABLE( pfGUIDragBarCtrl );
|
||||
REGISTER_CREATABLE( pfGUICheckBoxCtrl );
|
||||
REGISTER_CREATABLE( pfGUIRadioGroupCtrl );
|
||||
REGISTER_CREATABLE( pfGUIDynDisplayCtrl );
|
||||
REGISTER_CREATABLE( pfGUIMultiLineEditCtrl );
|
||||
REGISTER_CREATABLE( pfGUIProgressCtrl );
|
||||
REGISTER_CREATABLE( pfGUIClickMapCtrl );
|
||||
REGISTER_CREATABLE( pfGUIPopUpMenu );
|
||||
REGISTER_CREATABLE( pfGUIMenuItem );
|
||||
REGISTER_CREATABLE( pfGUISkin );
|
||||
|
||||
#endif // _pfGameGUIMgrCreatable_inc
|
Reference in New Issue
Block a user