| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815 |
- /*
- ** Command & Conquer Renegade(tm)
- ** Copyright 2025 Electronic Arts 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/>.
- */
- #include "clipboard.h"
- #include <istdplug.h>
- #include "utilapi.h"
- //----------------------------------------------------------------------------
- // Node_Key
- //----------------------------------------------------------------------------
- class Node_Key
- {
- public:
- Node_Key ( int nr_frames, const char * name, Node_Key * next );
- ~Node_Key ();
- void set_position ( int frame, Point3 pos )
- {
- if ( frame >= 0 && frame < nr_frames_ )
- position_ [frame] = pos;
- }
- void set_orientation ( int frame, Quat facing )
- {
- if ( frame >= 0 && frame < nr_frames_ )
- orientation_ [frame] = facing;
- }
- const Point3 & position ( int frame )
- {
- if ( frame < 0 || frame >= nr_frames_ )
- frame = 0;
- return position_ [frame];
- }
- const Quat & orientation ( int frame )
- {
- if ( frame < 0 || frame >= nr_frames_ )
- frame = 0;
- return orientation_ [frame];
- }
- const char * name () { return name_; }
- int nr_frames () { return nr_frames_; }
- Node_Key * next () { return next_; }
- private:
- char * name_;
- int nr_frames_;
- Point3 * position_;
- Quat * orientation_;
- Node_Key * next_;
- };
- //----------------------------------------------------------------------------
- // Node_Key::Node_Key
- //----------------------------------------------------------------------------
- Node_Key::Node_Key
- (
- int nr_frames,
- const char * name,
- Node_Key * next
- ):
- nr_frames_ (nr_frames),
- next_ (next)
- {
- position_ = new Point3 [ nr_frames ];
- orientation_ = new Quat [ nr_frames ];
- name_ = new char [ strlen (name) + 1 ];
- strcpy ( name_, name );
- }
- //----------------------------------------------------------------------------
- // Node_Key::~Node_Key
- //----------------------------------------------------------------------------
- Node_Key::~Node_Key ()
- {
- delete [] position_;
- delete [] orientation_;
- delete [] name_;
- }
- //----------------------------------------------------------------------------
- // Pose
- //----------------------------------------------------------------------------
- const MAX_NAME = 64;
- class Pose
- {
- public:
- Pose ( Interface * ip, const char * new_name, int first_frame, int last_frame );
- ~Pose ()
- {
- delete_keys ();
- }
- const char * name () const { return name_; }
- void Add_Objects_To_List ( HWND hWnd );
- void Paste_Keys ( Interface * ip );
- Pose * next;
- private:
- void delete_keys ();
- Node_Key * first_key;
- char name_ [ MAX_NAME ];
- int ticks_per_frame_;
- };
- //----------------------------------------------------------------------------
- // Clipboard_Class
- //----------------------------------------------------------------------------
- class Clipboard_Class : public UtilityObj
- {
- public:
- Clipboard_Class ();
- ~Clipboard_Class ();
- void BeginEditParams(Interface *ip,IUtil *iu);
- void EndEditParams(Interface *ip,IUtil *iu);
- void SelectionSetChanged ( Interface * ip, IUtil * iu );
- void DeleteThis() {}
- void Init(HWND hWnd);
- void Destroy(HWND hWnd);
- void Close () { iu->CloseUtility (); }
- void Create ( HWND );
- void Paste ( HWND );
- void Delete ( HWND );
- BOOL Is_Empty () const { return first_pose == NULL; }
- void Update_Object_List ( HWND hWnd );
- private:
- void Update_Pose_List ( HWND hWnd );
- IUtil * iu;
- Interface *ip;
- HWND hPanel;
- Pose * first_pose;
- };
- //----------------------------------------------------------------------------
- // the_clipboard
- //----------------------------------------------------------------------------
- static Clipboard_Class the_clipboard;
- //----------------------------------------------------------------------------
- // Static data used for communicating to/from the name dialog.
- //----------------------------------------------------------------------------
- static char pose_name [ MAX_NAME ];
- static int first_frame;
- static int last_frame;
- static int current_frame;
- //----------------------------------------------------------------------------
- // Clipboard_Desc_Class
- //----------------------------------------------------------------------------
- class Clipboard_Desc_Class:public ClassDesc
- {
- public:
- int IsPublic() {return 1;}
- void * Create(BOOL) {return &the_clipboard;}
- const TCHAR * ClassName() {return _T("Key Clipboard");}
- SClass_ID SuperClassID() {return UTILITY_CLASS_ID;}
- Class_ID ClassID() {return Class_ID(0x5eb13907, 0x1d931bb4);}
- const TCHAR* Category() {return _T("Westwood Tools");}
- };
- //----------------------------------------------------------------------------
- // clipboard_desc
- //----------------------------------------------------------------------------
- static Clipboard_Desc_Class clipboard_desc;
- //----------------------------------------------------------------------------
- // ClipboardDesc
- //----------------------------------------------------------------------------
- ClassDesc* ClipboardDesc() {return &clipboard_desc;}
- //----------------------------------------------------------------------------
- // ClipboardDlgProc
- //----------------------------------------------------------------------------
- static BOOL CALLBACK ClipboardDlgProc
- (
- HWND hWnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- switch (msg)
- {
- case WM_INITDIALOG:
- the_clipboard.Init(hWnd);
- break;
-
- case WM_DESTROY:
- the_clipboard.Destroy(hWnd);
- break;
- case WM_COMMAND:
- switch (LOWORD(wParam))
- {
- case ID_CLOSE:
- the_clipboard.Close ();
- break;
- case ID_CREATE:
- the_clipboard.Create ( hWnd );
- break;
- case ID_PASTE:
- the_clipboard.Paste ( hWnd );
- break;
- case ID_DELETE:
- the_clipboard.Delete ( hWnd );
- break;
- case IDC_POSE_LIST:
- if ( HIWORD(wParam) == CBN_SELCHANGE )
- the_clipboard.Update_Object_List ( hWnd );
- break;
- }
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- //----------------------------------------------------------------------------
- // Pose_Name_Message_Handler
- //----------------------------------------------------------------------------
- static BOOL CALLBACK Pose_Name_Message_Handler
- (
- HWND hWnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam
- )
- {
- static ISpinnerControl * first_frame_spin;
- static ISpinnerControl * last_frame_spin;
- switch (msg)
- {
- case WM_INITDIALOG:
- CenterWindow ( hWnd, GetParent (hWnd) );
- SetFocus ( GetDlgItem (hWnd, IDC_NAME) );
- first_frame_spin = SetupIntSpinner
- (
- hWnd,
- IDC_FIRST_FRAME_SPIN,
- IDC_FIRST_FRAME_EDIT,
- first_frame,
- last_frame,
- current_frame
- );
- first_frame_spin->SetResetValue ( current_frame );
- last_frame_spin = SetupIntSpinner
- (
- hWnd,
- IDC_LAST_FRAME_SPIN,
- IDC_LAST_FRAME_EDIT,
- first_frame,
- last_frame,
- current_frame
- );
- last_frame_spin->SetResetValue ( current_frame );
- return TRUE;
-
- case WM_COMMAND:
- switch (LOWORD(wParam))
- {
- case IDOK:
- if ( SendDlgItemMessage ( hWnd, IDC_NAME, WM_GETTEXTLENGTH, 0, 0 ) == 0 )
- EndDialog ( hWnd, 0 );
- SendDlgItemMessage ( hWnd, IDC_NAME, WM_GETTEXT, MAX_NAME,
- (LPARAM) pose_name );
- first_frame = first_frame_spin->GetIVal ();
- last_frame = last_frame_spin->GetIVal ();
- EndDialog ( hWnd, 1 );
- break;
- case IDCANCEL:
- EndDialog ( hWnd, 0 );
- break;
- }
- return TRUE;
- case CC_SPINNER_CHANGE:
- // Do checking on the range spinners to make sure the low value never
- // exceeds the high value.
- switch ( LOWORD(wParam) )
- {
- case IDC_FIRST_FRAME_SPIN:
- if ( first_frame_spin->GetIVal () > last_frame_spin->GetIVal () )
- {
- last_frame_spin->SetValue ( first_frame_spin->GetIVal (),
- FALSE );
- }
- break;
- case IDC_LAST_FRAME_SPIN:
- if ( last_frame_spin->GetIVal () < first_frame_spin->GetIVal () )
- {
- first_frame_spin->SetValue ( last_frame_spin->GetIVal (),
- FALSE );
- }
- break;
- }
- return TRUE;
- }
- return FALSE;
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::Clipboard_Class
- //----------------------------------------------------------------------------
- Clipboard_Class::Clipboard_Class()
- {
- iu = NULL;
- ip = NULL;
- hPanel = NULL;
- first_pose = NULL;
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::~Clipboard_Class
- //----------------------------------------------------------------------------
- Clipboard_Class::~Clipboard_Class ()
- {
- while ( first_pose != NULL )
- {
- Pose * delete_p = first_pose;
- first_pose = first_pose->next;
- delete delete_p;
- }
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::BeginEditParams
- //----------------------------------------------------------------------------
- void Clipboard_Class::BeginEditParams(Interface *ip,IUtil *iu)
- {
- this->iu = iu;
- this->ip = ip;
- hPanel = ip->AddRollupPage
- (
- hInstance,
- MAKEINTRESOURCE(IDD_CLIPBOARD_PANEL),
- ClipboardDlgProc,
- _T("Key Clipboard"),
- 0
- );
- }
-
- //----------------------------------------------------------------------------
- // Clipboard_Class::EndEditParams
- //----------------------------------------------------------------------------
- void Clipboard_Class::EndEditParams ( Interface *ip, IUtil *iu )
- {
- this->iu = NULL;
- this->ip = NULL;
- ip->DeleteRollupPage(hPanel);
- hPanel = NULL;
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::SelectionSetChanged
- //----------------------------------------------------------------------------
- void Clipboard_Class::SelectionSetChanged ( Interface * ip, IUtil * iu )
- {
- if ( ip->GetSelNodeCount () == 0 )
- {
- EnableWindow ( GetDlgItem ( hPanel, ID_CREATE ), FALSE );
- }
- else
- {
- EnableWindow ( GetDlgItem ( hPanel, ID_CREATE ), TRUE );
- }
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::Init
- //----------------------------------------------------------------------------
- void Clipboard_Class::Init ( HWND hWnd )
- {
- Update_Pose_List ( hWnd );
- SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_SETCURSEL, 0, 0 );
- Update_Object_List ( hWnd );
- if ( ip->GetSelNodeCount () == 0 )
- {
- EnableWindow ( GetDlgItem ( hWnd, ID_CREATE ), FALSE );
- }
- else
- {
- EnableWindow ( GetDlgItem ( hWnd, ID_CREATE ), TRUE );
- }
- if ( Is_Empty () )
- {
- EnableWindow ( GetDlgItem ( hWnd, ID_PASTE ), FALSE );
- EnableWindow ( GetDlgItem ( hWnd, ID_DELETE ), FALSE );
- }
- else
- {
- EnableWindow ( GetDlgItem ( hWnd, ID_PASTE ), TRUE );
- EnableWindow ( GetDlgItem ( hWnd, ID_DELETE ), TRUE );
- }
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::Destroy
- //----------------------------------------------------------------------------
- void Clipboard_Class::Destroy(HWND hWnd) {}
- //----------------------------------------------------------------------------
- // Clipboard_Class::Create
- //----------------------------------------------------------------------------
- void Clipboard_Class::Create ( HWND hWnd )
- {
- // Set up the data that will appear in the name dialog.
- const int ticks_per_frame = GetTicksPerFrame ();
- first_frame = ip->GetAnimRange ().Start () / ticks_per_frame;
- last_frame = ip->GetAnimRange ().End () / ticks_per_frame;
- current_frame = ip->GetTime () / ticks_per_frame;
- // Put up the name dialog.
- int rv = DialogBoxParam
- (
- hInstance,
- MAKEINTRESOURCE ( IDD_POSE_NAME ),
- hWnd,
- Pose_Name_Message_Handler,
- 0
- );
- if ( rv == 0 )
- return;
- Pose * new_pose = new Pose ( ip, pose_name, first_frame, last_frame );
- new_pose->next = first_pose;
- first_pose = new_pose;
- Update_Pose_List ( hWnd );
- SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_SETCURSEL, 0, 0 );
- Update_Object_List ( hWnd );
- EnableWindow ( GetDlgItem ( hWnd, ID_PASTE ), TRUE );
- EnableWindow ( GetDlgItem ( hWnd, ID_DELETE ), TRUE );
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::Paste
- //----------------------------------------------------------------------------
- void Clipboard_Class::Paste ( HWND hWnd )
- {
- SetCursor ( LoadCursor (NULL, IDC_WAIT) );
- int sel = SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_GETCURSEL, 0, 0 );
- if ( sel == CB_ERR )
- return;
- // Find the selected pose.
- Pose * p = first_pose;
- while ( sel > 0 && p != NULL )
- {
- p = p->next;
- -- sel;
- }
- if ( p == NULL )
- return;
- p->Paste_Keys ( ip );
- SetCursor ( LoadCursor (NULL, IDC_ARROW) );
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::Delete
- //----------------------------------------------------------------------------
- void Clipboard_Class::Delete ( HWND hWnd )
- {
- int sel = SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_GETCURSEL, 0, 0 );
- if ( sel != CB_ERR )
- {
- // Delete the pose's name from the list box.
- SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_DELETESTRING, sel, 0 );
- SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_SETCURSEL, 0, 0 );
- // Find the selected pose and delete it.
- Pose ** pointer_to_p = & first_pose;
- Pose * p = first_pose;
- while ( sel > 0 && p != NULL )
- {
- pointer_to_p = & p->next;
- p = p->next;
- -- sel;
- }
- if ( p != NULL )
- {
- *pointer_to_p = p->next;
- delete p;
- }
- Update_Object_List ( hWnd );
- }
- if ( Is_Empty () )
- {
- EnableWindow ( GetDlgItem ( hWnd, ID_PASTE ), FALSE );
- EnableWindow ( GetDlgItem ( hWnd, ID_DELETE ), FALSE );
- }
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::Update_Pose_List
- //----------------------------------------------------------------------------
- void Clipboard_Class::Update_Pose_List ( HWND hWnd )
- {
- // Delete any strings in the combo box.
- SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_RESETCONTENT, 0, 0 );
- // Rebuild the combo box.
- for ( Pose * p = first_pose; p != NULL; p = p->next )
- {
- SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_ADDSTRING, 0,
- (LPARAM) (LPCTSTR) p->name () );
- }
- }
- //----------------------------------------------------------------------------
- // Clipboard_Class::Update_Object_List
- //----------------------------------------------------------------------------
- void Clipboard_Class::Update_Object_List ( HWND hWnd )
- {
- // Delete any strings in the combo box.
- SendDlgItemMessage ( hWnd, IDC_OBJECT_LIST, LB_RESETCONTENT, 0, 0 );
- // Add strings from the objects in the currently selected pose.
- int sel = SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_GETCURSEL, 0, 0 );
- if ( sel != CB_ERR )
- {
- Pose * p = first_pose;
- while ( sel > 0 && p != NULL )
- {
- p = p->next;
- -- sel;
- }
- if ( p != NULL )
- {
- p->Add_Objects_To_List ( hWnd );
- }
- }
- }
- //----------------------------------------------------------------------------
- // Pose::Pose
- //----------------------------------------------------------------------------
- Pose::Pose ( Interface * ip, const char * name, int first_frame, int last_frame ):
- first_key (NULL),
- next (NULL),
- ticks_per_frame_ (GetTicksPerFrame ())
- {
- int number_of_nodes = ip->GetSelNodeCount ();
- int nr_frames = (last_frame - first_frame) + 1;
- TimeValue start_time = first_frame * ticks_per_frame_;
- char frame_count [ 16 ];
- sprintf ( frame_count, " (%d)", nr_frames );
- strncpy ( name_, name, MAX_NAME - 6 );
- strncat ( name_, frame_count, 5 );
- name_ [MAX_NAME - 1] = '\0';
- for ( int i = 0; i < number_of_nodes; ++ i )
- {
- // Get the inode.
- INode * inode = ip->GetSelNode ( i );
- Control * tm_controller = inode->GetTMController ();
- if ( tm_controller == NULL )
- continue;
- Node_Key * new_key = new Node_Key
- (
- nr_frames,
- inode->GetName (),
- first_key
- );
- first_key = new_key;
- // Store the position and rotation keys.
- Point3 node_position ( 0.0, 0.0, 0.0 );
- Quat node_orientation ( 0.0, 0.0, 0.0, 1.0 );
- for ( int frame = 0; frame < nr_frames; ++ frame )
- {
- TimeValue key_time = frame * ticks_per_frame_ + start_time;
- Control * c;
- // Copy rotation keys.
- c = tm_controller->GetRotationController ();
- if ( c != NULL )
- c->GetValue ( key_time, & node_orientation, FOREVER );
- else
- node_orientation = Quat (0.0, 0.0, 0.0, 1.0);
- // Copy position keys.
- c = tm_controller->GetPositionController ();
- if ( c != NULL )
- c->GetValue ( key_time, & node_position, FOREVER );
- else
- node_position = Point3 (0.0, 0.0, 0.0);
- new_key->set_position ( frame, node_position );
- new_key->set_orientation ( frame, node_orientation );
- }
- }
- }
- //----------------------------------------------------------------------------
- // Pose::Paste_Keys
- //----------------------------------------------------------------------------
- void Pose::Paste_Keys ( Interface * ip )
- {
- TimeValue current_time = ip->GetTime ();
- theHold.Begin ();
- SuspendAnimate ();
- AnimateOn ();
- Node_Key * p = first_key;
- while ( p != NULL )
- {
- INode * inode = ip->GetINodeByName ( p->name () );
- if ( inode != NULL )
- {
- Control * tm_controller = inode->GetTMController ();
- if ( tm_controller != NULL )
- {
- for ( int frame = 0; frame < p->nr_frames (); ++ frame )
- {
- TimeValue key_time = current_time + frame * ticks_per_frame_;
- Control * c;
- // Paste rotation keys.
- c = tm_controller->GetRotationController ();
- if ( c != NULL )
- {
- c->EnableORTs (FALSE);
- Quat orientation = p->orientation (frame);
- c->SetValue ( key_time, & orientation );
- c->EnableORTs (TRUE);
- }
- // Paste position keys.
- c = tm_controller->GetPositionController ();
- if ( c != NULL )
- {
- c->EnableORTs (FALSE);
- Point3 position = p->position (frame);
- c->SetValue ( key_time, & position );
- c->EnableORTs (TRUE);
- }
- }
- }
- }
- p = p->next ();
- }
- ResumeAnimate ();
- TSTR undostr;
- undostr.printf ( "Paste Keys" );
- theHold.Accept ( undostr );
- ip->RedrawViews ( current_time );
- }
- //----------------------------------------------------------------------------
- // Pose::delete_keys
- //----------------------------------------------------------------------------
- void Pose::delete_keys ()
- {
- while ( first_key != NULL )
- {
- Node_Key * delete_p = first_key;
- first_key = first_key->next ();
- delete delete_p;
- }
- }
- //----------------------------------------------------------------------------
- // Pose::Add_Objects_To_List
- //----------------------------------------------------------------------------
- void Pose::Add_Objects_To_List ( HWND hWnd )
- {
- for ( Node_Key * k = first_key; k != NULL; k = k->next () )
- {
- SendDlgItemMessage ( hWnd, IDC_OBJECT_LIST, LB_ADDSTRING, 0,
- (LPARAM) (LPCTSTR) k->name () );
- }
- }
|