/*==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 . 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; }