Clipboard.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "clipboard.h"
  19. #include <istdplug.h>
  20. #include "utilapi.h"
  21. //----------------------------------------------------------------------------
  22. // Node_Key
  23. //----------------------------------------------------------------------------
  24. class Node_Key
  25. {
  26. public:
  27. Node_Key ( int nr_frames, const char * name, Node_Key * next );
  28. ~Node_Key ();
  29. void set_position ( int frame, Point3 pos )
  30. {
  31. if ( frame >= 0 && frame < nr_frames_ )
  32. position_ [frame] = pos;
  33. }
  34. void set_orientation ( int frame, Quat facing )
  35. {
  36. if ( frame >= 0 && frame < nr_frames_ )
  37. orientation_ [frame] = facing;
  38. }
  39. const Point3 & position ( int frame )
  40. {
  41. if ( frame < 0 || frame >= nr_frames_ )
  42. frame = 0;
  43. return position_ [frame];
  44. }
  45. const Quat & orientation ( int frame )
  46. {
  47. if ( frame < 0 || frame >= nr_frames_ )
  48. frame = 0;
  49. return orientation_ [frame];
  50. }
  51. const char * name () { return name_; }
  52. int nr_frames () { return nr_frames_; }
  53. Node_Key * next () { return next_; }
  54. private:
  55. char * name_;
  56. int nr_frames_;
  57. Point3 * position_;
  58. Quat * orientation_;
  59. Node_Key * next_;
  60. };
  61. //----------------------------------------------------------------------------
  62. // Node_Key::Node_Key
  63. //----------------------------------------------------------------------------
  64. Node_Key::Node_Key
  65. (
  66. int nr_frames,
  67. const char * name,
  68. Node_Key * next
  69. ):
  70. nr_frames_ (nr_frames),
  71. next_ (next)
  72. {
  73. position_ = new Point3 [ nr_frames ];
  74. orientation_ = new Quat [ nr_frames ];
  75. name_ = new char [ strlen (name) + 1 ];
  76. strcpy ( name_, name );
  77. }
  78. //----------------------------------------------------------------------------
  79. // Node_Key::~Node_Key
  80. //----------------------------------------------------------------------------
  81. Node_Key::~Node_Key ()
  82. {
  83. delete [] position_;
  84. delete [] orientation_;
  85. delete [] name_;
  86. }
  87. //----------------------------------------------------------------------------
  88. // Pose
  89. //----------------------------------------------------------------------------
  90. const MAX_NAME = 64;
  91. class Pose
  92. {
  93. public:
  94. Pose ( Interface * ip, const char * new_name, int first_frame, int last_frame );
  95. ~Pose ()
  96. {
  97. delete_keys ();
  98. }
  99. const char * name () const { return name_; }
  100. void Add_Objects_To_List ( HWND hWnd );
  101. void Paste_Keys ( Interface * ip );
  102. Pose * next;
  103. private:
  104. void delete_keys ();
  105. Node_Key * first_key;
  106. char name_ [ MAX_NAME ];
  107. int ticks_per_frame_;
  108. };
  109. //----------------------------------------------------------------------------
  110. // Clipboard_Class
  111. //----------------------------------------------------------------------------
  112. class Clipboard_Class : public UtilityObj
  113. {
  114. public:
  115. Clipboard_Class ();
  116. ~Clipboard_Class ();
  117. void BeginEditParams(Interface *ip,IUtil *iu);
  118. void EndEditParams(Interface *ip,IUtil *iu);
  119. void SelectionSetChanged ( Interface * ip, IUtil * iu );
  120. void DeleteThis() {}
  121. void Init(HWND hWnd);
  122. void Destroy(HWND hWnd);
  123. void Close () { iu->CloseUtility (); }
  124. void Create ( HWND );
  125. void Paste ( HWND );
  126. void Delete ( HWND );
  127. BOOL Is_Empty () const { return first_pose == NULL; }
  128. void Update_Object_List ( HWND hWnd );
  129. private:
  130. void Update_Pose_List ( HWND hWnd );
  131. IUtil * iu;
  132. Interface *ip;
  133. HWND hPanel;
  134. Pose * first_pose;
  135. };
  136. //----------------------------------------------------------------------------
  137. // the_clipboard
  138. //----------------------------------------------------------------------------
  139. static Clipboard_Class the_clipboard;
  140. //----------------------------------------------------------------------------
  141. // Static data used for communicating to/from the name dialog.
  142. //----------------------------------------------------------------------------
  143. static char pose_name [ MAX_NAME ];
  144. static int first_frame;
  145. static int last_frame;
  146. static int current_frame;
  147. //----------------------------------------------------------------------------
  148. // Clipboard_Desc_Class
  149. //----------------------------------------------------------------------------
  150. class Clipboard_Desc_Class:public ClassDesc
  151. {
  152. public:
  153. int IsPublic() {return 1;}
  154. void * Create(BOOL) {return &the_clipboard;}
  155. const TCHAR * ClassName() {return _T("Key Clipboard");}
  156. SClass_ID SuperClassID() {return UTILITY_CLASS_ID;}
  157. Class_ID ClassID() {return Class_ID(0x5eb13907, 0x1d931bb4);}
  158. const TCHAR* Category() {return _T("Westwood Tools");}
  159. };
  160. //----------------------------------------------------------------------------
  161. // clipboard_desc
  162. //----------------------------------------------------------------------------
  163. static Clipboard_Desc_Class clipboard_desc;
  164. //----------------------------------------------------------------------------
  165. // ClipboardDesc
  166. //----------------------------------------------------------------------------
  167. ClassDesc* ClipboardDesc() {return &clipboard_desc;}
  168. //----------------------------------------------------------------------------
  169. // ClipboardDlgProc
  170. //----------------------------------------------------------------------------
  171. static BOOL CALLBACK ClipboardDlgProc
  172. (
  173. HWND hWnd,
  174. UINT msg,
  175. WPARAM wParam,
  176. LPARAM lParam
  177. )
  178. {
  179. switch (msg)
  180. {
  181. case WM_INITDIALOG:
  182. the_clipboard.Init(hWnd);
  183. break;
  184. case WM_DESTROY:
  185. the_clipboard.Destroy(hWnd);
  186. break;
  187. case WM_COMMAND:
  188. switch (LOWORD(wParam))
  189. {
  190. case ID_CLOSE:
  191. the_clipboard.Close ();
  192. break;
  193. case ID_CREATE:
  194. the_clipboard.Create ( hWnd );
  195. break;
  196. case ID_PASTE:
  197. the_clipboard.Paste ( hWnd );
  198. break;
  199. case ID_DELETE:
  200. the_clipboard.Delete ( hWnd );
  201. break;
  202. case IDC_POSE_LIST:
  203. if ( HIWORD(wParam) == CBN_SELCHANGE )
  204. the_clipboard.Update_Object_List ( hWnd );
  205. break;
  206. }
  207. break;
  208. default:
  209. return FALSE;
  210. }
  211. return TRUE;
  212. }
  213. //----------------------------------------------------------------------------
  214. // Pose_Name_Message_Handler
  215. //----------------------------------------------------------------------------
  216. static BOOL CALLBACK Pose_Name_Message_Handler
  217. (
  218. HWND hWnd,
  219. UINT msg,
  220. WPARAM wParam,
  221. LPARAM lParam
  222. )
  223. {
  224. static ISpinnerControl * first_frame_spin;
  225. static ISpinnerControl * last_frame_spin;
  226. switch (msg)
  227. {
  228. case WM_INITDIALOG:
  229. CenterWindow ( hWnd, GetParent (hWnd) );
  230. SetFocus ( GetDlgItem (hWnd, IDC_NAME) );
  231. first_frame_spin = SetupIntSpinner
  232. (
  233. hWnd,
  234. IDC_FIRST_FRAME_SPIN,
  235. IDC_FIRST_FRAME_EDIT,
  236. first_frame,
  237. last_frame,
  238. current_frame
  239. );
  240. first_frame_spin->SetResetValue ( current_frame );
  241. last_frame_spin = SetupIntSpinner
  242. (
  243. hWnd,
  244. IDC_LAST_FRAME_SPIN,
  245. IDC_LAST_FRAME_EDIT,
  246. first_frame,
  247. last_frame,
  248. current_frame
  249. );
  250. last_frame_spin->SetResetValue ( current_frame );
  251. return TRUE;
  252. case WM_COMMAND:
  253. switch (LOWORD(wParam))
  254. {
  255. case IDOK:
  256. if ( SendDlgItemMessage ( hWnd, IDC_NAME, WM_GETTEXTLENGTH, 0, 0 ) == 0 )
  257. EndDialog ( hWnd, 0 );
  258. SendDlgItemMessage ( hWnd, IDC_NAME, WM_GETTEXT, MAX_NAME,
  259. (LPARAM) pose_name );
  260. first_frame = first_frame_spin->GetIVal ();
  261. last_frame = last_frame_spin->GetIVal ();
  262. EndDialog ( hWnd, 1 );
  263. break;
  264. case IDCANCEL:
  265. EndDialog ( hWnd, 0 );
  266. break;
  267. }
  268. return TRUE;
  269. case CC_SPINNER_CHANGE:
  270. // Do checking on the range spinners to make sure the low value never
  271. // exceeds the high value.
  272. switch ( LOWORD(wParam) )
  273. {
  274. case IDC_FIRST_FRAME_SPIN:
  275. if ( first_frame_spin->GetIVal () > last_frame_spin->GetIVal () )
  276. {
  277. last_frame_spin->SetValue ( first_frame_spin->GetIVal (),
  278. FALSE );
  279. }
  280. break;
  281. case IDC_LAST_FRAME_SPIN:
  282. if ( last_frame_spin->GetIVal () < first_frame_spin->GetIVal () )
  283. {
  284. first_frame_spin->SetValue ( last_frame_spin->GetIVal (),
  285. FALSE );
  286. }
  287. break;
  288. }
  289. return TRUE;
  290. }
  291. return FALSE;
  292. }
  293. //----------------------------------------------------------------------------
  294. // Clipboard_Class::Clipboard_Class
  295. //----------------------------------------------------------------------------
  296. Clipboard_Class::Clipboard_Class()
  297. {
  298. iu = NULL;
  299. ip = NULL;
  300. hPanel = NULL;
  301. first_pose = NULL;
  302. }
  303. //----------------------------------------------------------------------------
  304. // Clipboard_Class::~Clipboard_Class
  305. //----------------------------------------------------------------------------
  306. Clipboard_Class::~Clipboard_Class ()
  307. {
  308. while ( first_pose != NULL )
  309. {
  310. Pose * delete_p = first_pose;
  311. first_pose = first_pose->next;
  312. delete delete_p;
  313. }
  314. }
  315. //----------------------------------------------------------------------------
  316. // Clipboard_Class::BeginEditParams
  317. //----------------------------------------------------------------------------
  318. void Clipboard_Class::BeginEditParams(Interface *ip,IUtil *iu)
  319. {
  320. this->iu = iu;
  321. this->ip = ip;
  322. hPanel = ip->AddRollupPage
  323. (
  324. hInstance,
  325. MAKEINTRESOURCE(IDD_CLIPBOARD_PANEL),
  326. ClipboardDlgProc,
  327. _T("Key Clipboard"),
  328. 0
  329. );
  330. }
  331. //----------------------------------------------------------------------------
  332. // Clipboard_Class::EndEditParams
  333. //----------------------------------------------------------------------------
  334. void Clipboard_Class::EndEditParams ( Interface *ip, IUtil *iu )
  335. {
  336. this->iu = NULL;
  337. this->ip = NULL;
  338. ip->DeleteRollupPage(hPanel);
  339. hPanel = NULL;
  340. }
  341. //----------------------------------------------------------------------------
  342. // Clipboard_Class::SelectionSetChanged
  343. //----------------------------------------------------------------------------
  344. void Clipboard_Class::SelectionSetChanged ( Interface * ip, IUtil * iu )
  345. {
  346. if ( ip->GetSelNodeCount () == 0 )
  347. {
  348. EnableWindow ( GetDlgItem ( hPanel, ID_CREATE ), FALSE );
  349. }
  350. else
  351. {
  352. EnableWindow ( GetDlgItem ( hPanel, ID_CREATE ), TRUE );
  353. }
  354. }
  355. //----------------------------------------------------------------------------
  356. // Clipboard_Class::Init
  357. //----------------------------------------------------------------------------
  358. void Clipboard_Class::Init ( HWND hWnd )
  359. {
  360. Update_Pose_List ( hWnd );
  361. SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_SETCURSEL, 0, 0 );
  362. Update_Object_List ( hWnd );
  363. if ( ip->GetSelNodeCount () == 0 )
  364. {
  365. EnableWindow ( GetDlgItem ( hWnd, ID_CREATE ), FALSE );
  366. }
  367. else
  368. {
  369. EnableWindow ( GetDlgItem ( hWnd, ID_CREATE ), TRUE );
  370. }
  371. if ( Is_Empty () )
  372. {
  373. EnableWindow ( GetDlgItem ( hWnd, ID_PASTE ), FALSE );
  374. EnableWindow ( GetDlgItem ( hWnd, ID_DELETE ), FALSE );
  375. }
  376. else
  377. {
  378. EnableWindow ( GetDlgItem ( hWnd, ID_PASTE ), TRUE );
  379. EnableWindow ( GetDlgItem ( hWnd, ID_DELETE ), TRUE );
  380. }
  381. }
  382. //----------------------------------------------------------------------------
  383. // Clipboard_Class::Destroy
  384. //----------------------------------------------------------------------------
  385. void Clipboard_Class::Destroy(HWND hWnd) {}
  386. //----------------------------------------------------------------------------
  387. // Clipboard_Class::Create
  388. //----------------------------------------------------------------------------
  389. void Clipboard_Class::Create ( HWND hWnd )
  390. {
  391. // Set up the data that will appear in the name dialog.
  392. const int ticks_per_frame = GetTicksPerFrame ();
  393. first_frame = ip->GetAnimRange ().Start () / ticks_per_frame;
  394. last_frame = ip->GetAnimRange ().End () / ticks_per_frame;
  395. current_frame = ip->GetTime () / ticks_per_frame;
  396. // Put up the name dialog.
  397. int rv = DialogBoxParam
  398. (
  399. hInstance,
  400. MAKEINTRESOURCE ( IDD_POSE_NAME ),
  401. hWnd,
  402. Pose_Name_Message_Handler,
  403. 0
  404. );
  405. if ( rv == 0 )
  406. return;
  407. Pose * new_pose = new Pose ( ip, pose_name, first_frame, last_frame );
  408. new_pose->next = first_pose;
  409. first_pose = new_pose;
  410. Update_Pose_List ( hWnd );
  411. SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_SETCURSEL, 0, 0 );
  412. Update_Object_List ( hWnd );
  413. EnableWindow ( GetDlgItem ( hWnd, ID_PASTE ), TRUE );
  414. EnableWindow ( GetDlgItem ( hWnd, ID_DELETE ), TRUE );
  415. }
  416. //----------------------------------------------------------------------------
  417. // Clipboard_Class::Paste
  418. //----------------------------------------------------------------------------
  419. void Clipboard_Class::Paste ( HWND hWnd )
  420. {
  421. SetCursor ( LoadCursor (NULL, IDC_WAIT) );
  422. int sel = SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_GETCURSEL, 0, 0 );
  423. if ( sel == CB_ERR )
  424. return;
  425. // Find the selected pose.
  426. Pose * p = first_pose;
  427. while ( sel > 0 && p != NULL )
  428. {
  429. p = p->next;
  430. -- sel;
  431. }
  432. if ( p == NULL )
  433. return;
  434. p->Paste_Keys ( ip );
  435. SetCursor ( LoadCursor (NULL, IDC_ARROW) );
  436. }
  437. //----------------------------------------------------------------------------
  438. // Clipboard_Class::Delete
  439. //----------------------------------------------------------------------------
  440. void Clipboard_Class::Delete ( HWND hWnd )
  441. {
  442. int sel = SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_GETCURSEL, 0, 0 );
  443. if ( sel != CB_ERR )
  444. {
  445. // Delete the pose's name from the list box.
  446. SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_DELETESTRING, sel, 0 );
  447. SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_SETCURSEL, 0, 0 );
  448. // Find the selected pose and delete it.
  449. Pose ** pointer_to_p = & first_pose;
  450. Pose * p = first_pose;
  451. while ( sel > 0 && p != NULL )
  452. {
  453. pointer_to_p = & p->next;
  454. p = p->next;
  455. -- sel;
  456. }
  457. if ( p != NULL )
  458. {
  459. *pointer_to_p = p->next;
  460. delete p;
  461. }
  462. Update_Object_List ( hWnd );
  463. }
  464. if ( Is_Empty () )
  465. {
  466. EnableWindow ( GetDlgItem ( hWnd, ID_PASTE ), FALSE );
  467. EnableWindow ( GetDlgItem ( hWnd, ID_DELETE ), FALSE );
  468. }
  469. }
  470. //----------------------------------------------------------------------------
  471. // Clipboard_Class::Update_Pose_List
  472. //----------------------------------------------------------------------------
  473. void Clipboard_Class::Update_Pose_List ( HWND hWnd )
  474. {
  475. // Delete any strings in the combo box.
  476. SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_RESETCONTENT, 0, 0 );
  477. // Rebuild the combo box.
  478. for ( Pose * p = first_pose; p != NULL; p = p->next )
  479. {
  480. SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_ADDSTRING, 0,
  481. (LPARAM) (LPCTSTR) p->name () );
  482. }
  483. }
  484. //----------------------------------------------------------------------------
  485. // Clipboard_Class::Update_Object_List
  486. //----------------------------------------------------------------------------
  487. void Clipboard_Class::Update_Object_List ( HWND hWnd )
  488. {
  489. // Delete any strings in the combo box.
  490. SendDlgItemMessage ( hWnd, IDC_OBJECT_LIST, LB_RESETCONTENT, 0, 0 );
  491. // Add strings from the objects in the currently selected pose.
  492. int sel = SendDlgItemMessage ( hWnd, IDC_POSE_LIST, CB_GETCURSEL, 0, 0 );
  493. if ( sel != CB_ERR )
  494. {
  495. Pose * p = first_pose;
  496. while ( sel > 0 && p != NULL )
  497. {
  498. p = p->next;
  499. -- sel;
  500. }
  501. if ( p != NULL )
  502. {
  503. p->Add_Objects_To_List ( hWnd );
  504. }
  505. }
  506. }
  507. //----------------------------------------------------------------------------
  508. // Pose::Pose
  509. //----------------------------------------------------------------------------
  510. Pose::Pose ( Interface * ip, const char * name, int first_frame, int last_frame ):
  511. first_key (NULL),
  512. next (NULL),
  513. ticks_per_frame_ (GetTicksPerFrame ())
  514. {
  515. int number_of_nodes = ip->GetSelNodeCount ();
  516. int nr_frames = (last_frame - first_frame) + 1;
  517. TimeValue start_time = first_frame * ticks_per_frame_;
  518. char frame_count [ 16 ];
  519. sprintf ( frame_count, " (%d)", nr_frames );
  520. strncpy ( name_, name, MAX_NAME - 6 );
  521. strncat ( name_, frame_count, 5 );
  522. name_ [MAX_NAME - 1] = '\0';
  523. for ( int i = 0; i < number_of_nodes; ++ i )
  524. {
  525. // Get the inode.
  526. INode * inode = ip->GetSelNode ( i );
  527. Control * tm_controller = inode->GetTMController ();
  528. if ( tm_controller == NULL )
  529. continue;
  530. Node_Key * new_key = new Node_Key
  531. (
  532. nr_frames,
  533. inode->GetName (),
  534. first_key
  535. );
  536. first_key = new_key;
  537. // Store the position and rotation keys.
  538. Point3 node_position ( 0.0, 0.0, 0.0 );
  539. Quat node_orientation ( 0.0, 0.0, 0.0, 1.0 );
  540. for ( int frame = 0; frame < nr_frames; ++ frame )
  541. {
  542. TimeValue key_time = frame * ticks_per_frame_ + start_time;
  543. Control * c;
  544. // Copy rotation keys.
  545. c = tm_controller->GetRotationController ();
  546. if ( c != NULL )
  547. c->GetValue ( key_time, & node_orientation, FOREVER );
  548. else
  549. node_orientation = Quat (0.0, 0.0, 0.0, 1.0);
  550. // Copy position keys.
  551. c = tm_controller->GetPositionController ();
  552. if ( c != NULL )
  553. c->GetValue ( key_time, & node_position, FOREVER );
  554. else
  555. node_position = Point3 (0.0, 0.0, 0.0);
  556. new_key->set_position ( frame, node_position );
  557. new_key->set_orientation ( frame, node_orientation );
  558. }
  559. }
  560. }
  561. //----------------------------------------------------------------------------
  562. // Pose::Paste_Keys
  563. //----------------------------------------------------------------------------
  564. void Pose::Paste_Keys ( Interface * ip )
  565. {
  566. TimeValue current_time = ip->GetTime ();
  567. theHold.Begin ();
  568. SuspendAnimate ();
  569. AnimateOn ();
  570. Node_Key * p = first_key;
  571. while ( p != NULL )
  572. {
  573. INode * inode = ip->GetINodeByName ( p->name () );
  574. if ( inode != NULL )
  575. {
  576. Control * tm_controller = inode->GetTMController ();
  577. if ( tm_controller != NULL )
  578. {
  579. for ( int frame = 0; frame < p->nr_frames (); ++ frame )
  580. {
  581. TimeValue key_time = current_time + frame * ticks_per_frame_;
  582. Control * c;
  583. // Paste rotation keys.
  584. c = tm_controller->GetRotationController ();
  585. if ( c != NULL )
  586. {
  587. c->EnableORTs (FALSE);
  588. Quat orientation = p->orientation (frame);
  589. c->SetValue ( key_time, & orientation );
  590. c->EnableORTs (TRUE);
  591. }
  592. // Paste position keys.
  593. c = tm_controller->GetPositionController ();
  594. if ( c != NULL )
  595. {
  596. c->EnableORTs (FALSE);
  597. Point3 position = p->position (frame);
  598. c->SetValue ( key_time, & position );
  599. c->EnableORTs (TRUE);
  600. }
  601. }
  602. }
  603. }
  604. p = p->next ();
  605. }
  606. ResumeAnimate ();
  607. TSTR undostr;
  608. undostr.printf ( "Paste Keys" );
  609. theHold.Accept ( undostr );
  610. ip->RedrawViews ( current_time );
  611. }
  612. //----------------------------------------------------------------------------
  613. // Pose::delete_keys
  614. //----------------------------------------------------------------------------
  615. void Pose::delete_keys ()
  616. {
  617. while ( first_key != NULL )
  618. {
  619. Node_Key * delete_p = first_key;
  620. first_key = first_key->next ();
  621. delete delete_p;
  622. }
  623. }
  624. //----------------------------------------------------------------------------
  625. // Pose::Add_Objects_To_List
  626. //----------------------------------------------------------------------------
  627. void Pose::Add_Objects_To_List ( HWND hWnd )
  628. {
  629. for ( Node_Key * k = first_key; k != NULL; k = k->next () )
  630. {
  631. SendDlgItemMessage ( hWnd, IDC_OBJECT_LIST, LB_ADDSTRING, 0,
  632. (LPARAM) (LPCTSTR) k->name () );
  633. }
  634. }