//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #ifndef CHOREOVIEW_H #define CHOREOVIEW_H #ifdef _WIN32 #pragma once #endif #include #include #include "mxBitmapButton.h" #include "utlvector.h" #include "ChoreoWidget.h" #include "ichoreoeventcallback.h" #include "faceposertoolwindow.h" #include "ChoreoEvent.h" #include "mathlib/mathlib.h" #include "SoundEmitterSystem/isoundemittersystembase.h" #define IDC_CV_CC_LANGUAGESTART 5300 #define IDC_STOPSCENE 5000 #define IDC_PLAYSCENE 5001 #define IDC_PAUSESCENE 5002 #define IDC_CHOREOVSCROLL 5003 #define IDC_CHOREOHSCROLL 5004 #define IDC_ADDACTOR 5005 #define IDC_DELETEACTOR 5006 #define IDC_MOVEACTORUP 5007 #define IDC_MOVEACTORDOWN 5008 #define IDC_EDITACTOR 5009 #define IDC_EDITEVENT 5010 #define IDC_DELETEEVENT 5011 #define IDC_ADDEVENT_EXPRESSION 5012 #define IDC_ADDEVENT_GESTURE 5013 #define IDC_ADDEVENT_LOOKAT 5014 #define IDC_ADDEVENT_MOVETO 5015 #define IDC_ADDEVENT_SPEAK 5016 #define IDC_ADDEVENT_FACE 5017 #define IDC_ADDEVENT_FIRETRIGGER 5018 #define IDC_ADDEVENT_SEQUENCE 5019 #define IDC_ADDEVENT_GENERIC 5020 #define IDC_CV_CHANGESCALE 5021 #define IDC_EDITGLOBALEVENT 5022 #define IDC_DELETEGLOBALEVENT 5023 #define IDC_ADDEVENT_PAUSE 5024 #define IDC_ADDCHANNEL 5025 #define IDC_EDITCHANNEL 5026 #define IDC_DELETECHANNEL 5027 #define IDC_MOVECHANNELUP 5028 #define IDC_MOVECHANNELDOWN 5029 #define IDC_CHANNELOPEN 5030 #define IDC_CHANNELCLOSE 5031 #define IDC_CBACTORACTIVE 5032 #define IDC_DELETERELATIVETAG 5033 #define IDC_ADDTIMINGTAG 5034 #define IDC_SELECTALL 5035 #define IDC_DESELECTALL 5036 #define IDC_MOVETOBACK 5037 #define IDC_UNDO 5038 #define IDC_REDO 5039 #define IDC_EXPRESSIONTOOL 5040 #define IDC_ASSOCIATEBSP 5041 #define IDC_ADDEVENT_FLEXANIMATION 5042 #define IDC_COPYEVENTS 5043 #define IDC_PASTEEVENTS 5044 #define IDC_IMPORTEVENTS 5045 #define IDC_EXPORTEVENTS 5046 #define IDC_ADDEVENT_SUBSCENE 5047 #define IDC_PLAYSCENE_BACKWARD 5048 #define IDC_ASSOCIATEMODEL 5049 #define IDC_CHOREO_PLAYBACKRATE 5050 #define IDC_CV_CHECKSEQLENGTHS 5051 #define IDC_CV_PROCESSSEQUENCES 5052 #define IDC_GESTURETOOL 5053 #define IDC_ADDEVENT_LOOP 5054 #define IDC_CV_TOGGLERAMPONLY 5055 #define IDC_ADDEVENT_INTERRUPT 5056 #define IDC_ADDEVENT_STOPPOINT 5067 #define SCENE_ACTION_UNKNOWN 0 #define SCENE_ACTION_CANCEL 1 #define SCENE_ACTION_RESUME 2 #define SCENE_ANIMLAYER_SEQUENCE 0 #define SCENE_ANIMLAYER_GESTURE 1 #define IDC_ADDEVENT_NULLGESTURE 5068 #define IDC_SELECTEVENTS_ALL_BEFORE 5069 #define IDC_SELECTEVENTS_ALL_AFTER 5070 #define IDC_SELECTEVENTS_ACTIVE_BEFORE 5071 #define IDC_SELECTEVENTS_ACTIVE_AFTER 5072 #define IDC_SELECTEVENTS_CHANNEL_BEFORE 5073 #define IDC_SELECTEVENTS_CHANNEL_AFTER 5074 #define IDC_INSERT_TIME 5075 #define IDC_DELETE_TIME 5076 #define IDC_EXPORT_VCD 5077 #define IDC_IMPORT_VCD 5078 #define IDC_ADDEVENT_PERMITRESPONSES 5079 #define IDC_CV_CC_SHOW 5080 #define IDC_CV_COMBINESPEAKEVENTS 5081 #define IDC_CV_REMOVESPEAKEVENTFROMGROUP 5082 #define IDC_CV_CHANGECLOSECAPTIONTOKEN 5083 #define IDC_CV_TOGGLECLOSECAPTIONS 5084 #define IDC_CV_ALIGN_LEFT 5085 #define IDC_CV_ALIGN_RIGHT 5086 #define IDC_CV_SAMESIZE_SMALLEST 5087 #define IDC_CV_SAMESIZE_LARGEST 5088 #define IDC_CV_ALLEVENTS_CHANNEL 5089 #define IDC_CV_ALLEVENTS_ACTOR 5090 #define IDC_CV_ENABLEEVENTS 5091 #define IDC_CV_DISABLEEVENTS 5092 #define IDC_ADDEVENT_CAMERA 5093 ///////////////////////////////////////////////////////////////////////////// // CChoreoView window class CChoreoScene; class CChoreoEvent; class CChoreoActor; class CChoreoChannel; class CChoreoActorWidget; class CChoreoChannelWidget; class CChoreoEventWidget; class CChoreoGlobalEventWidget; class CChoreoWidgetDrawHelper; class PhonemeEditor; class CExpression; class CExpClass; class StudioModel; //----------------------------------------------------------------------------- // Purpose: The main view of the choreography data for a scene //----------------------------------------------------------------------------- class CChoreoView : public mxWindow, public IFacePoserToolWindow, public IChoreoEventCallback { // Construction public: CChoreoView( mxWindow *parent, int x, int y, int w, int h, int id ); virtual ~CChoreoView(); virtual void OnModelChanged(); virtual void OnDelete(); virtual bool CanClose(); void InvalidateTrackLookup( void ); // Implements IChoreoEventCallback virtual void StartEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); virtual void EndEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); virtual void ProcessEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); virtual bool CheckEvent( float currenttime, CChoreoScene *scene, CChoreoEvent *event ); void SetChoreoFile( char const *filename ); char const *GetChoreoFile( void ) const; // Scene load/unload void LoadSceneFromFile( const char *filename ); CChoreoScene *LoadScene( char const *filename ); void UnloadScene( void ); // UI void New( void ); void Save( void ); void SaveAs( void ); void Load( void ); void LoadNext( void ); bool Close( void ); // Drag/drop from expression thumbnail bool CreateExpressionEvent( int mx, int my, CExpClass *cl, CExpression *exp ); bool CreateAnimationEvent( int mx, int my, char const *animationname ); void SelectAll( void ); void DeselectAll( void ); struct SelectionParams_t { enum { SP_CHANNEL = 0, SP_ACTIVE, SP_ALL }; float time; bool forward; int type; }; void SelectEvents( SelectionParams_t& params ); // Channel/actor right click menu void NewChannel( void ); void DeleteChannel( CChoreoChannel *channel ); void MoveChannelUp( CChoreoChannel *channel ); void MoveChannelDown( CChoreoChannel *channel ); void EditChannel( CChoreoChannel *channel ); void AddEvent( int type, int subtype = 0, char const *defaultparameters = NULL ); // Actor right click menu void NewActor( void ); void DeleteActor( CChoreoActor *actor ); void MoveActorUp( CChoreoActor *actor ); void MoveActorDown( CChoreoActor *actor ); void EditActor( CChoreoActor *actor ); // Event menu void EditEvent( CChoreoEvent *event ); void DeleteSelectedEvents( void ); void EnableSelectedEvents( bool state ); void DeleteEventRelativeTag( CChoreoEvent *event, int tagnum ); void AddEventRelativeTag( void ); CChoreoEventWidget *FindWidgetForEvent( CChoreoEvent *event ); CChoreoChannelWidget *FindChannelForEvent( CChoreoEvent *event ); void MoveEventToBack( CChoreoEvent *event ); void OnExpressionTool( void ); void OnGestureTool( void ); // Global event ( pause ) menu void EditGlobalEvent( CChoreoEvent *event ); void DeleteGlobalEvent( CChoreoEvent *event ); void AddGlobalEvent( CChoreoEvent::EVENTTYPE type ); void AssociateBSP( void ); void AssociateModel( void ); void AssociateModelToActor( CChoreoActor *actor, int modelindex ); // UI Layout void CreateSceneWidgets( void ); void DeleteSceneWidgets( void ); void LayoutScene( void ); void InvalidateLayout( void ); void ForceScrollBarsToRecompute( bool resetthumb ); // Layout data that children should obey int GetLabelWidth( void ); int GetStartRow( void ); int GetRowHeight( void ); int GetFontSize( void ); int GetEndRow( void ); // Simulation void PlayScene( bool forward ); void PauseScene( void ); bool IsPlayingScene( void ); void ResetTargetSettings( void ); void UpdateCurrentSettings( void ); virtual void Think( float dt ); virtual bool IsScrubbing( void ) const; virtual bool IsProcessing( void ); bool ShouldProcessSpeak( void ); void SceneThink( float time ); void PauseThink( void ); void FinishSimulation( void ); void StopScene(); float GetStartTime( void ); float GetEndTime( void ); void SetStartTime( float time ); void ProcessExpression( CChoreoScene *scene, CChoreoEvent *event ); void ProcessFlexAnimation( CChoreoScene *scene, CChoreoEvent *event ); void ProcessLookat( CChoreoScene *scene, CChoreoEvent *event ); bool GetTarget( CChoreoScene *scene, CChoreoEvent *event, Vector &vecTarget, QAngle &vecAngle ); void ProcessFace( CChoreoScene *scene, CChoreoEvent *event ); void ProcessGesture( CChoreoScene *scene, CChoreoEvent *event ); void ProcessSequence( CChoreoScene *scene, CChoreoEvent *event ); void ProcessMoveto( CChoreoScene *scene, CChoreoEvent *event ); int GetMovetoSequence( CChoreoScene *scene, CChoreoEvent *event, StudioModel *model ); void ProcessSubscene( CChoreoScene *scene, CChoreoEvent *event ); void ProcessPause( CChoreoScene *scene, CChoreoEvent *event ); void ProcessSpeak( CChoreoScene *scene, CChoreoEvent *event ); void ProcessLoop( CChoreoScene *scene, CChoreoEvent *event ); void ProcessInterrupt( CChoreoScene *scene, CChoreoEvent *event ); void ProcessPermitResponses( CChoreoScene *scene, CChoreoEvent *event ); float GetPixelsPerSecond( void ); // mxWindow overrides virtual void redraw(); virtual bool PaintBackground( void ); virtual int handleEvent( mxEvent *event ); // Draw helpers void DrawSceneABTicks( CChoreoWidgetDrawHelper& drawHelper ); void DrawTimeLine( CChoreoWidgetDrawHelper& drawHelper, RECT& rc, float left, float right ); void DrawBackground( CChoreoWidgetDrawHelper& drawHelper, RECT& rc ); void DrawRelativeTagLines( CChoreoWidgetDrawHelper& drawHelper, RECT& rc ); // Remap click position to/from time value float GetTimeValueForMouse( int mx, bool clip = false ); int GetPixelForTimeValue( float time, bool *clipped = NULL ); float GetTimeDeltaForMouseDelta( int mx, int origmx ); // Readjust slider void MoveTimeSliderToPos( int x ); // Dirty flag for file save prompting bool GetDirty( void ); void SetDirty( bool dirty, bool clearundo = true ); void ShowContextMenu( int mx, int my ); // Caller must first translate mouse into screen coordinates bool IsMouseOverTimeline( int mx, int my ); CChoreoActorWidget *GetActorUnderCursorPos( int mx, int my ); CChoreoChannelWidget *GetChannelUnderCursorPos( int mx, int my ); CChoreoEventWidget *GetEventUnderCursorPos( int mx, int my ); CChoreoGlobalEventWidget *GetGlobalEventUnderCursorPos( int mx, int my ); int GetTagUnderCursorPos( CChoreoEventWidget *event, int mx, int my ); CEventAbsoluteTag *GetAbsoluteTagUnderCursorPos( CChoreoEventWidget *event, int mx, int my ); void GetObjectsUnderMouse( int mx, int my, CChoreoActorWidget **actor, CChoreoChannelWidget **channel, CChoreoEventWidget **event, CChoreoGlobalEventWidget **globalevent, int* clickedTag, CEventAbsoluteTag **absolutetag, int *clickedCCButton ); void OnDoubleClicked( void ); void ApplyBounds( int& mx, int& my ); void CalcBounds( int movetype ); void MouseStartDrag( mxEvent *event, int mx, int my ); void MouseContinueDrag( mxEvent *event, int mx, int my ); void MouseFinishDrag( mxEvent *event, int mx, int my ); void MouseMove( int mx, int my ); //void StartDraggingGlobalEvent( int mx, int my ); void StartDraggingEvent( int mx, int my ); //void FinishDraggingGlobalEvent( int mx, int my ); void FinishDraggingEvent( mxEvent *event, int mx, int my ); // Draw focus rect while mouse dragging is going on void DrawFocusRect( void ); int ComputeEventDragType( int mx, int my ); void SetCurrentWaveFile( const char *filename, CChoreoEvent *event ); void RecomputeWaves(); typedef void (CChoreoView::*CVMEMBERFUNC)( CChoreoWidget *widget, CChoreoWidget *param1 ); void TraverseWidgets( CVMEMBERFUNC pfn, CChoreoWidget *param1 ); int CountSelectedEvents( void ); int CountSelectedGlobalEvents( void ); int GetSelectedEvents( CUtlVector< CChoreoEvent * >& events ); int GetSelectedEventWidgets( CUtlVector< CChoreoEventWidget * >& events ); int GetEarliestEventIndex( CUtlVector< CChoreoEventWidget * >& events ); int GetLatestEventIndex( CUtlVector< CChoreoEventWidget * >& events ); // Traversal functions void Deselect( CChoreoWidget *widget, CChoreoWidget *param1 ); void Select( CChoreoWidget *widget, CChoreoWidget *param1 ); void SelectInActor( CChoreoWidget *widget, CChoreoWidget *param1 ); void SelectInChannel( CChoreoWidget *widget, CChoreoWidget *param1 ); void SelectAllEvents( CChoreoWidget *widget, CChoreoWidget *param1 ); void SelectAllEventsInActor( CChoreoActorWidget *actor ); void SelectAllEventsInChannel( CChoreoChannelWidget *channel ); // Adjust scroll bars void RepositionVSlider( void ); void RepositionHSlider( void ); void UpdateStatusArea( int mx, int my ); void ClearStatusArea( void ); void RedrawStatusArea( CChoreoWidgetDrawHelper& drawHelper, RECT& rcStatus ); void GetUndoLevels( int& current, int& number ); // Undo/Redo void Undo( void ); void Redo( void ); bool CanUndo(); bool CanRedo(); // Do push before changes void PushUndo( const char *description ); // Do this push after changes, must match pushundo 1for1 void PushRedo( const char *description ); void WipeUndo( void ); void WipeRedo( void ); const char *GetUndoDescription( void ); const char *GetRedoDescription( void ); CChoreoScene *GetScene( void ); void ReportSceneClearToTools( void ); void CopyEvents( void ); void PasteEvents( void ); void ImportEvents( void ); void ExportEvents( void ); void ExportVCD(); void ImportVCD(); void ExportVCDFile( char const *filename ); void ImportVCDFile( char const *filename ); bool CanPaste( void ); bool IsMouseOverScrubHandle( mxEvent *event ); bool IsMouseOverScrubArea( mxEvent *event ); void GetScrubHandleRect( RECT& rcHandle, bool clipped = false ); void GetScrubAreaRect( RECT& rcArea ); void DrawScrubHandle( CChoreoWidgetDrawHelper& drawHelper ); void DrawScrubHandle( void ); void ScrubThink( float dt, bool scrubbing, IFacePoserToolWindow *invoker ); void ClampTimeToSelectionInterval( float& timeval ); void SetScrubTime( float t ); void SetScrubTargetTime( float t ); void OnCheckSequenceLengths( void ); bool IsRampOnly( void ) const; void SetTimeZoom( const char *tool, int tz, bool preserveFocus ); int GetTimeZoom( const char *tool ); template< class T > void SetPreservedTimeZoom( T *other, int tz ); template< class T > int HandleZoomKey( T *other, int keyCode ); void OnInsertTime(); void OnDeleteTime(); bool GetShowCloseCaptionData( void ) const; bool ValidateCombinedSoundCheckSum( CChoreoEvent *e ); void OnPlaceNextSpeakEvent(); void SetScrubUnitSeconds( bool bUseSeconds); private: void CheckInsertTime( CChoreoEvent *e, float dt, float starttime, float endtime ); void CheckDeleteTime( CChoreoEvent *d, float dt, float starttime, float endtime, bool& deleteEvent ); bool FixupSequenceDurations( CChoreoScene *scene, bool checkonly ); bool CheckSequenceLength( CChoreoEvent *e, bool checkonly ); bool CheckGestureLength( CChoreoEvent *e, bool checkonly ); bool DefaultGestureLength( CChoreoEvent *e, bool checkonly ); bool AutoaddGestureKeys( CChoreoEvent *e, bool checkonly ); void InvalidateTrackLookup_R( CChoreoScene *scene ); void ShowButtons( bool show ); // Compute full size of data in pixels, for setting up scroll bars int ComputeVPixelsNeeded( void ); int ComputeHPixelsNeeded( void ); void PositionControls(); void OnChangeScale(); float FindNextEventTime( CChoreoEvent::EVENTTYPE type, CChoreoChannel *channel, CChoreoEvent *e, bool forward ); bool ShouldSelectEvent( SelectionParams_t ¶ms, CChoreoEvent *event ); bool IsMouseOverSceneEndTime( int mx ); void StartDraggingSceneEndTime( int mx, int my ); void FinishDraggingSceneEndTime( mxEvent *event, int mx, int my ); void SetShowCloseCaptionData( bool show ); void OnToggleCloseCaptionTags(); void OnCombineSpeakEvents(); void OnRemoveSpeakEventFromGroup(); void OnChangeCloseCaptionToken( CChoreoEvent *e ); bool AreSelectedEventsCombinable(); bool AreSelectedEventsInSpeakGroup(); void OnToggleCloseCaptionsForEvent(); bool GenerateCombinedFile( char const *outfilename, const char *cctoken, gender_t gender, CUtlRBTree< CChoreoEvent * >& sorted ); bool ValidateCombinedFileCheckSum( char const *outfilename, char const *cctoken, gender_t gender, CUtlRBTree< CChoreoEvent * >& sorted ); void RememberSelectedEvents( CUtlVector< CChoreoEvent * >& list ); void ReselectEvents( CUtlVector< CChoreoEvent * >& list ); void OnAlign( bool left ); void OnMakeSameSize( bool smallest ); bool IsMouseOverEventEdge( CChoreoEventWidget *ew, bool bLeftEdge, int mx, int my ); bool IsMouseOverEvent( CChoreoEventWidget *ew, int mx, int my ); typedef struct { bool active; float time; } SCENEAB; void PlaceABPoint( int mx ); void ClearABPoints( void ); SCENEAB m_rgABPoints[ 2 ]; int m_nCurrentABPoint; bool m_bForward; // The underlying scene we are editing CChoreoScene *m_pScene; enum { MAX_ACTORS = 32 }; typedef struct { bool expanded; } ACTORSTATE; ACTORSTATE m_ActorExpanded[ MAX_ACTORS ]; // The scene's ui actors CUtlVector < CChoreoActorWidget * > m_SceneActors; // The scenes segment markers CUtlVector < CChoreoGlobalEventWidget * > m_SceneGlobalEvents; // How many pixels per second we are showing in the UI float m_flPixelsPerSecond; // Do we need to move controls? bool m_bLayoutIsValid; // Starting row of first actor int m_nStartRow; // How wide the actor/channel name area is int m_nLabelWidth; // Height between channel/actor names int m_nRowHeight; // Font size for drawing event labels int m_nFontSize; // Height/width of scroll bars int m_nScrollbarHeight; // Height off info area for flyover info / help int m_nInfoHeight; // Simulation info float m_flStartTime; float m_flEndTime; float m_flFrameTime; bool m_bSimulating; bool m_bPaused; float m_flLastSpeedScale; bool m_bResetSpeedScale; bool m_bAutomated; int m_nAutomatedAction; float m_flAutomationDelay; float m_flAutomationTime; // Some rectangles for the UI RECT m_rcTitles; RECT m_rcTimeLine; // Play/pause buttons for simulation mxBitmapButton *m_btnPlay; mxBitmapButton *m_btnPause; mxBitmapButton *m_btnStop; mxSlider *m_pPlaybackRate; float m_flPlaybackRate; // The scroll bars mxScrollbar *m_pVertScrollBar; mxScrollbar *m_pHorzScrollBar; int m_nLastHPixelsNeeded; int m_nLastVPixelsNeeded; // Current sb values int m_nTopOffset; float m_flLeftOffset; // Need save? bool m_bDirty; // Currently loaded scene file char m_szChoreoFile[ 256 ]; CChoreoActorWidget *m_pClickedActor; CChoreoChannelWidget *m_pClickedChannel; CChoreoEventWidget *m_pClickedEvent; CChoreoGlobalEventWidget *m_pClickedGlobalEvent; // Relative to the clicked event int m_nClickedTag; CEventAbsoluteTag *m_pClickedAbsoluteTag; int m_nSelectedEvents; int m_nClickedX, m_nClickedY; int m_nClickedChannelCloseCaptionButton; // For mouse dragging // How close to right or left edge the mouse has to be before the wider/shorten // cursor shows up enum { DRAG_EVENT_EDGE_TOLERANCE = 5, }; // When dragging, what time of action is being performed enum { DRAGTYPE_NONE = 0, DRAGTYPE_EVENT_MOVE, DRAGTYPE_EVENT_STARTTIME, DRAGTYPE_EVENT_STARTTIME_RESCALE, DRAGTYPE_EVENT_ENDTIME, DRAGTYPE_EVENT_ENDTIME_RESCALE, DRAGTYPE_EVENTTAG_MOVE, DRAGTYPE_EVENTABSTAG_MOVE, DRAGTYPE_SCRUBBER, DRAGTYPE_SCENE_ENDTIME, DRAGTYPE_RESCALELEFT, DRAGTYPE_RESCALERIGHT, }; float m_flScrub; int m_bScrubSeconds; float m_flScrubTarget; bool m_bDragging; int m_xStart; int m_yStart; bool m_bUseBounds; int m_nMinX; int m_nMaxX; struct CFocusRect { RECT m_rcOrig; RECT m_rcFocus; }; CUtlVector < CFocusRect > m_FocusRects; int m_nDragType; HCURSOR m_hPrevCursor; struct FLYOVER { CChoreoActorWidget *a; CChoreoChannelWidget *c; CChoreoEventWidget *e; CChoreoGlobalEventWidget *ge; int tag; CEventAbsoluteTag *at; int ccbutton; }; FLYOVER m_Flyover; bool m_bCanDraw; struct CVUndo { CChoreoScene *undo; CChoreoScene *redo; char *udescription; char *rdescription; }; CUtlVector< CVUndo * > m_UndoStack; int m_nUndoLevel; bool m_bRedoPending; bool m_bProcessSequences; float m_flLastMouseClickTime; bool m_bSuppressLayout; bool m_bRampOnly; float m_flScrubberTimeOffset; bool m_bShowCloseCaptionData; bool m_bForceProcess; // cached version of the local directory when a scene is loaded CUtlVector< CUtlString > m_nextFileList; }; extern CChoreoView *g_pChoreoView; template< class T > void CChoreoView::SetPreservedTimeZoom( T *other, int tz ) { POINT pt; ::GetCursorPos( &pt ); ::ScreenToClient( (HWND)other->getHandle(), &pt ); // Now figure out time under cursor at old zoom scale float t = other->GetTimeValueForMouse( pt.x, true ); // Call CChoreoView's version SetTimeZoom( other->GetToolName(), tz, false ); // Now figure out tie under pt.x float newT = other->GetTimeValueForMouse( pt.x, true ); if ( newT != t ) { // We need to scroll over a bit float pps = other->GetPixelsPerSecond(); float movePixels = pps * ( newT - t ); float newOffset = other->m_flLeftOffset - movePixels; if ( newOffset < 0.0f ) { newOffset = 0; } float ed = other->GetEventEndTime(); float flLastPixel = ed * pps; if ( newOffset + other->w2() > flLastPixel ) { newOffset = flLastPixel - other->w2(); } other->m_flLeftOffset = newOffset; other->m_pHorzScrollBar->setValue( (int)( other->m_flLeftOffset ) ); } other->RepositionHSlider(); } template< class T > int CChoreoView::HandleZoomKey( T *other, int keyCode ) { int iret = 1; switch ( keyCode ) { default: { iret = 0; } break; case VK_HOME: { other->MoveTimeSliderToPos( 0 ); } break; case VK_END: { float maxtime = other->GetEventEndTime(); int pixels = max( 0, (int)( maxtime * other->GetPixelsPerSecond() ) - other->w2() ); other->MoveTimeSliderToPos( pixels ); } break; case VK_PRIOR: // PgUp { int window = other->w2(); other->m_flLeftOffset = max( other->m_flLeftOffset - (float)window, 0.0f ); other->MoveTimeSliderToPos( (int)other->m_flLeftOffset ); } break; case VK_NEXT: // PgDown { int window = other->w2(); float maxtime = other->GetEventEndTime(); int pixels = max( 0, (int)( maxtime * other->GetPixelsPerSecond() ) - other->w2() ); other->m_flLeftOffset = min( other->m_flLeftOffset + (float)window, (float)pixels ); other->MoveTimeSliderToPos( (int)other->m_flLeftOffset ); } break; } return iret; } float SnapTime( float input, float granularity ); class StudioModel; StudioModel *FindAssociatedModel( CChoreoScene *scene, CChoreoActor *a ); #endif // CHOREOVIEW_H