00001
00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024
00025
00026 #include "std_afx.h"
00027
00028 #define OBJECT_VIEWER_EXPORT __declspec( dllexport )
00029
00030 #include "object_viewer.h"
00031 #include <3d/nelu.h>
00032 #include <3d/mesh.h>
00033 #include <3d/transform_shape.h>
00034 #include <3d/mesh_instance.h>
00035 #include <3d/skeleton_model.h>
00036 #include <nel/misc/file.h>
00037 #include <nel/misc/path.h>
00038 #include <nel/misc/time_nl.h>
00039
00040 #include "editable_range.h"
00041 #include "located_properties.h"
00042 #include "color_button.h"
00043
00044 #ifdef _DEBUG
00045 #define new DEBUG_NEW
00046 #undef THIS_FILE
00047 static char THIS_FILE[] = __FILE__;
00048 #endif
00049
00050 using namespace NL3D;
00051 using namespace NLMISC;
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00081
00082
00083 BEGIN_MESSAGE_MAP(CObject_viewerApp, CWinApp)
00084
00085
00086
00087
00088 END_MESSAGE_MAP()
00089
00091
00092
00093 CObject_viewerApp::CObject_viewerApp()
00094 {
00095
00096
00097 }
00098
00100
00101
00102 CObject_viewerApp theApp;
00103
00104
00105
00106 CObjectViewer::CObjectViewer ()
00107 {
00108 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00109 _SlotDlg=NULL;
00110 _AnimationSetDlg=NULL;
00111 _AnimationDlg=NULL;
00112 _SceneDlg=NULL;
00113 _ParticleDlg = NULL ;
00114
00115
00116 _ChannelMixer.setAnimationSet (&_AnimationSet);
00117
00118
00119 _HotSpotColor.R=255;
00120 _HotSpotColor.G=255;
00121 _HotSpotColor.B=0;
00122 _HotSpotColor.A=255;
00123
00124
00125 _HotSpotSize=10.f;
00126 }
00127
00128
00129
00130 CObjectViewer::~CObjectViewer ()
00131 {
00132 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00133 if (_SlotDlg)
00134 delete _SlotDlg;
00135 if (_AnimationSetDlg)
00136 delete _AnimationSetDlg;
00137 if (_AnimationDlg)
00138 delete _AnimationDlg;
00139 if (_SceneDlg)
00140 delete _SceneDlg;
00141 if (_ParticleDlg)
00142 delete _ParticleDlg ;
00143 }
00144
00145
00146
00147 void CObjectViewer::initUI ()
00148 {
00149 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00150
00151
00152 CViewport viewport;
00153
00154
00155 CNELU::init (640, 480, viewport);
00156
00157
00158 CWnd driverWnd;
00159 driverWnd.Attach((HWND)CNELU::Driver->getDisplay());
00160 getRegisterWindowState (&driverWnd, REGKEY_OBJ_VIEW_OPENGL_WND, true);
00161
00162
00163 CFrustum frustrum;
00164 frustrum.initPerspective( 75.f*(float)Pi/180.f, 1.33f, 0.1f, 1000.f);
00165 CNELU::Camera->setFrustum (frustrum);
00166
00167
00168
00169
00170
00171
00172 _AnimationDlg=new CAnimationDlg (this, &driverWnd);
00173 _AnimationDlg->Create (IDD_ANIMATION);
00174 getRegisterWindowState (_AnimationDlg, REGKEY_OBJ_VIEW_ANIMATION_DLG, false);
00175
00176
00177 _AnimationSetDlg=new CAnimationSetDlg (this, &driverWnd);
00178 _AnimationSetDlg->Create (IDD_ANIMATION_SET);
00179 getRegisterWindowState (_AnimationSetDlg, REGKEY_OBJ_VIEW_ANIMATION_SET_DLG, false);
00180
00181
00182 _SlotDlg=new CMainDlg (this, &driverWnd);
00183 _SlotDlg->init (&_AnimationSet);
00184 _SlotDlg->Create (IDD_MAIN_DLG);
00185 getRegisterWindowState (_SlotDlg, REGKEY_OBJ_VIEW_SLOT_DLG, false);
00186
00187
00188 _SceneDlg=new CSceneDlg (this, &driverWnd);
00189 _SceneDlg->Create (IDD_SCENE);
00190 _SceneDlg->ShowWindow (TRUE);
00191 getRegisterWindowState (_SceneDlg, REGKEY_OBJ_VIEW_SCENE_DLG, false);
00192
00193
00194 _ParticleDlg=new CParticleDlg (&driverWnd, _SceneDlg);
00195 _ParticleDlg->Create (IDD_PARTICLE);
00196 getRegisterWindowState (_ParticleDlg, REGKEY_OBJ_PARTICLE_DLG, false);
00197
00198
00199
00200
00201
00202
00203 setAnimTime (0.f, 100.f);
00204
00205
00206 CNELU::EventServer.addListener (EventDestroyWindowId, this);
00207
00208
00209 _MouseListener.addToServer(CNELU::EventServer);
00210
00211
00212 driverWnd.Detach ();
00213
00214 CNELU::Driver->activate ();
00215 }
00216
00217
00218
00219 void CObjectViewer::operator ()(const CEvent& event)
00220 {
00221
00222 if (event==EventDestroyWindowId)
00223 {
00224 }
00225 }
00226
00227
00228
00229 void CObjectViewer::go ()
00230 {
00231 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00232
00233 do
00234 {
00235 CNELU::Driver->activate ();
00236
00237
00238 _AnimationDlg->handle ();
00239
00240
00241 _SlotDlg->getSlot ();
00242
00243
00244 _SlotDlg->Playlist.setupMixer (_ChannelMixer, _AnimationDlg->getTime());
00245
00246
00247 CNELU::Scene.animate( NLMISC::CTime::ticksToSecond( NLMISC::CTime::getPerformanceTime() ) );
00248
00249
00250 _ChannelMixer.eval (false);
00251
00252
00253 _SceneDlg->UpdateData();
00254
00255
00256
00257
00258
00259
00260 CNELU::clearBuffers(CRGBA(0,0,0));
00261
00262
00263 CNELU::Scene.render();
00264
00265
00266 if (_SceneDlg->ObjectMode)
00267 {
00268 float radius=_HotSpotSize/2.f;
00269 CNELU::Driver->setupModelMatrix (CMatrix::Identity);
00270 CDRU::drawLine (_MouseListener.getHotSpot()+CVector (radius, 0, 0), _MouseListener.getHotSpot()+CVector (-radius, 0, 0), _HotSpotColor, *CNELU::Driver);
00271 CDRU::drawLine (_MouseListener.getHotSpot()+CVector (0, radius, 0), _MouseListener.getHotSpot()+CVector (0, -radius, 0), _HotSpotColor, *CNELU::Driver);
00272 CDRU::drawLine (_MouseListener.getHotSpot()+CVector (0, 0, radius), _MouseListener.getHotSpot()+CVector (0, 0, -radius), _HotSpotColor, *CNELU::Driver);
00273 }
00274
00275
00276 CNELU::swapBuffers();
00277
00278
00279 if (_SceneDlg->ObjectMode)
00280 _MouseListener.setMouseMode (CEvent3dMouseListener::edit3d);
00281 else
00282 {
00283 _MouseListener.setMouseMode (CEvent3dMouseListener::firstPerson);
00284 _MouseListener.setSpeed (_SceneDlg->MoveSpeed);
00285 }
00286
00287
00288
00289 CNELU::EventServer.pump();
00290
00291 if (!_SceneDlg->MoveElement)
00292 {
00293
00294 CNELU::Camera->setTransformMode (ITransformable::DirectMatrix);
00295 CNELU::Camera->setMatrix (_MouseListener.getViewMatrix());
00296 }
00297 else
00298 {
00299
00300 _ParticleDlg->moveElement(_MouseListener.getModelMatrix()) ;
00301 }
00302
00303
00304 MSG msg;
00305 while ( PeekMessage(&msg, NULL,0,0,PM_REMOVE) )
00306 {
00307 TranslateMessage(&msg);
00308 DispatchMessage(&msg);
00309 }
00310 }
00311 while (!CNELU::AsyncListener.isKeyPushed(KeyESCAPE)&&CNELU::Driver->isActive());
00312 }
00313
00314
00315
00316 void CObjectViewer::releaseUI ()
00317 {
00318 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00319
00320 if (CNELU::Driver->isActive())
00321 {
00322
00323 if (CNELU::Driver->getDisplay())
00324 {
00325 CWnd driverWnd;
00326 driverWnd.Attach((HWND)CNELU::Driver->getDisplay());
00327 setRegisterWindowState (&driverWnd, REGKEY_OBJ_VIEW_OPENGL_WND);
00328 driverWnd.Detach ();
00329 }
00330 }
00331
00332
00333 _MouseListener.removeFromServer (CNELU::EventServer);
00334
00335
00336 CNELU::EventServer.removeListener (EventDestroyWindowId, this);
00337
00338
00339 CNELU::release();
00340 }
00341
00342
00343
00344 void setRegisterWindowState (const CWnd *pWnd, const char* keyName)
00345 {
00346 HKEY hKey;
00347 if (RegCreateKey(HKEY_CURRENT_USER, keyName, &hKey)==ERROR_SUCCESS)
00348 {
00349 RECT rect;
00350 pWnd->GetWindowRect (&rect);
00351 RegSetValueEx(hKey, "Left", 0, REG_DWORD, (LPBYTE)&rect.left, 4);
00352 RegSetValueEx(hKey, "Right", 0, REG_DWORD, (LPBYTE)&rect.right, 4);
00353 RegSetValueEx(hKey, "Top", 0, REG_DWORD, (LPBYTE)&rect.top, 4);
00354 RegSetValueEx(hKey, "Bottom", 0, REG_DWORD, (LPBYTE)&rect.bottom, 4);
00355 }
00356 }
00357
00358
00359
00360 void getRegisterWindowState (CWnd *pWnd, const char* keyName, bool resize)
00361 {
00362 HKEY hKey;
00363 if (RegOpenKeyEx(HKEY_CURRENT_USER, keyName, 0, KEY_READ, &hKey)==ERROR_SUCCESS)
00364 {
00365 DWORD len=4;
00366 DWORD type;
00367 RECT rect;
00368 RegQueryValueEx (hKey, "Left", 0, &type, (LPBYTE)&rect.left, &len);
00369 RegQueryValueEx (hKey, "Right", 0, &type, (LPBYTE)&rect.right, &len);
00370 RegQueryValueEx (hKey, "Top", 0, &type, (LPBYTE)&rect.top, &len);
00371 RegQueryValueEx (hKey, "Bottom", 0, &type, (LPBYTE)&rect.bottom, &len);
00372
00373
00374 pWnd->SetWindowPos (NULL, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, SWP_NOOWNERZORDER|SWP_NOZORDER|
00375 (resize?0:SWP_NOSIZE));
00376 }
00377 }
00378
00379
00380
00381 void CObjectViewer::setAnimTime (float animStart, float animEnd)
00382 {
00383
00384 _SlotDlg->setAnimTime (animStart, animEnd);
00385 _AnimationDlg->setAnimTime (animStart, animEnd);
00386 }
00387
00388
00389
00390
00391 void CObjectViewer::resetSlots ()
00392 {
00393
00394 _AnimationSet.reset ();
00395
00396
00397 for (uint i=0; i<NL3D::CChannelMixer::NumAnimationSlot; i++)
00398 _SlotDlg->Slots[i].setAnimation (0xffffffff, NULL, NULL);
00399 }
00400
00401
00402
00403 void CObjectViewer::reinitChannels ()
00404 {
00405
00406 _ChannelMixer.resetChannels ();
00407
00408
00409 for (uint i=0; i<_ListTransformShape.size(); i++)
00410 _ListTransformShape[i]->registerToChannelMixer (&_ChannelMixer, _ListShapeBaseName[i]);
00411 }
00412
00413
00414
00415 float CObjectViewer::getFrameRate ()
00416 {
00417 return _AnimationDlg->Speed;
00418 }
00419
00420
00421
00422 void CObjectViewer::serial (NLMISC::IStream& f)
00423 {
00424
00425 f.serialCheck ((uint32)'VJBO');
00426 f.serialCheck ((uint32)'GFC_');
00427
00428
00429 int ver=f.serialVersion (0);
00430
00431
00432 _AnimationDlg->UpdateData ();
00433 _SceneDlg->UpdateData ();
00434
00435
00436 f.serial (_AnimationDlg->Start);
00437 f.serial (_AnimationDlg->End);
00438 f.serial (_AnimationDlg->Speed);
00439 bool loop=_AnimationDlg->Loop!=0;
00440 f.serial (loop);
00441 _AnimationDlg->Loop=loop;
00442 bool euler=_SceneDlg->Euler!=0;
00443 f.serial (euler);
00444 _SceneDlg->Euler=euler;
00445 sint32 ui=_AnimationDlg->UICurrentFrame;
00446 f.serial (ui);
00447 _AnimationDlg->UICurrentFrame=ui;
00448 f.serial (_AnimationDlg->CurrentFrame);
00449
00450
00451 _AnimationDlg->UpdateData (FALSE);
00452 _SceneDlg->UpdateData (FALSE);
00453
00454
00455 for (uint i=0; i<NL3D::CChannelMixer::NumAnimationSlot; i++)
00456 {
00457
00458 _SlotDlg->Slots[i].UpdateData();
00459
00460
00461 bool slotState=_SlotDlg->Slots[i].enable!=0;
00462 f.serial (slotState);
00463 _SlotDlg->Slots[i].enable=slotState;
00464
00465
00466 _SlotDlg->Slots[i].UpdateData(FALSE);
00467 }
00468
00469
00470
00471 CMatrix mt=_MouseListener.getViewMatrix();
00472 f.serial (mt);
00473 _MouseListener.setMatrix (mt);
00474
00475
00476 std::vector<CMeshDesc> meshArray=_ListMeshes;
00477
00478
00479 f.serialCont (meshArray);
00480
00481
00482 if (f.isReading ())
00483 {
00484
00485 for (uint s=0; s<meshArray.size(); s++)
00486 loadMesh (meshArray[s].MeshName.c_str(), meshArray[s].SkeletonName.c_str());
00487 }
00488
00489
00490 std::vector<std::string> stringArray=_AnimationSetDlg->_ListAnimation;
00491
00492
00493 f.serialCont (stringArray);
00494
00495
00496 if (f.isReading ())
00497 {
00498
00499 for (uint s=0; s<stringArray.size(); s++)
00500 _AnimationSetDlg->loadAnimation (stringArray[s].c_str());
00501 }
00502
00503
00504 stringArray=_AnimationSetDlg->_ListSkeleton;
00505
00506
00507 f.serialCont (stringArray);
00508
00509
00510 if (f.isReading ())
00511 {
00512
00513 for (uint s=0; s<stringArray.size(); s++)
00514 _AnimationSetDlg->loadSkeleton (stringArray[s].c_str());
00515 }
00516
00517
00518 if (f.isReading ())
00519 {
00520
00521 f.serial (_SlotDlg->Playlist);
00522
00523
00524 _SlotDlg->setSlot ();
00525 }
00526 else
00527 {
00528
00529 _SlotDlg->getSlot ();
00530
00531
00532 f.serial (_SlotDlg->Playlist);
00533 }
00534
00535
00536 if (f.isReading ())
00537 {
00538
00539 setAnimTime (_AnimationDlg->Start, _AnimationDlg->End);
00540
00541
00542 reinitChannels ();
00543 }
00544 }
00545
00546
00547
00548 bool CObjectViewer::loadMesh (const char* meshFilename, const char* skeleton)
00549 {
00550 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00551
00552
00553 char drive[256];
00554 char dir[256];
00555 char path[256];
00556
00557
00558 _splitpath (meshFilename, drive, dir, NULL, NULL);
00559 _makepath (path, drive, dir, NULL, NULL);
00560 CPath::addSearchPath (path);
00561
00562
00563 if (skeleton)
00564 {
00565 _splitpath (skeleton, drive, dir, NULL, NULL);
00566 _makepath (path, drive, dir, NULL, NULL);
00567 CPath::addSearchPath (path);
00568 }
00569
00570
00571 IShape *shapeMesh=NULL;
00572 IShape *shapeSkel=NULL;
00573
00574
00575 CIFile file;
00576 if (file.open (meshFilename))
00577 {
00578
00579 CShapeStream streamShape;
00580 try
00581 {
00582
00583 streamShape.serial (file);
00584
00585
00586 shapeMesh=streamShape.getShapePointer();
00587 }
00588 catch (Exception& e)
00589 {
00590 _SceneDlg->MessageBox (e.what(), "NeL object viewer", MB_OK|MB_ICONEXCLAMATION);
00591 return false;
00592 }
00593 }
00594 else
00595 {
00596
00597 char msg[512];
00598 _snprintf (msg, 512, "Can't open the file %s for reading.", meshFilename);
00599 _SceneDlg->MessageBox (msg, "NeL object viewer", MB_OK|MB_ICONEXCLAMATION);
00600 return false;
00601 }
00602
00603
00604 if (skeleton&&(strcmp (skeleton, "")!=0))
00605 {
00606
00607 bool skelError=false;
00608
00609 if (skeleton)
00610 {
00611
00612 if (file.open (skeleton))
00613 {
00614
00615 CShapeStream streamShape;
00616 try
00617 {
00618
00619 streamShape.serial (file);
00620
00621
00622 shapeSkel=streamShape.getShapePointer();
00623 }
00624 catch (Exception& e)
00625 {
00626 _SceneDlg->MessageBox (e.what(), "NeL object viewer", MB_OK|MB_ICONEXCLAMATION);
00627
00628
00629 skelError=true;
00630 }
00631 }
00632 else
00633 {
00634
00635 char msg[512];
00636 _snprintf (msg, 512, "Can't open the file %s for reading.", meshFilename);
00637 _SceneDlg->MessageBox (msg, "NeL object viewer", MB_OK|MB_ICONEXCLAMATION);
00638
00639
00640 skelError=true;
00641 }
00642 }
00643
00644
00645 if (skelError)
00646 {
00647 if (shapeMesh)
00648 delete shapeMesh;
00649 shapeMesh=NULL;
00650 return false;
00651 }
00652 }
00653
00654
00655 NL3D::CSkeletonModel *transformSkel=NULL;
00656 if (shapeSkel)
00657 transformSkel=addSkel (shapeSkel, skeleton, "");
00658
00659
00660 if (shapeMesh)
00661 addMesh (shapeMesh, meshFilename, "", transformSkel);
00662
00663
00664 _ListMeshes.push_back (CMeshDesc (meshFilename, skeleton));
00665
00666 return true;
00667 }
00668
00669
00670
00671 void CObjectViewer::resetCamera ()
00672 {
00673 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00674
00675 _SceneDlg->OnResetCamera();
00676 }
00677
00678
00679
00680 CTransformShape *CObjectViewer::addMesh (NL3D::IShape* pMeshShape, const char* meshName, const char *meshBaseName, CSkeletonModel* pSkel)
00681 {
00682 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00683
00684
00685
00686
00687 CNELU::ShapeBank->add (meshName, CSmartPtr<IShape> (pMeshShape));
00688
00689
00690 _ListShapeBaseName.push_back (meshBaseName);
00691
00692
00693 CTransformShape *pTrShape=CNELU::Scene.createInstance (meshName);
00694 nlassert (pTrShape);
00695
00696
00697 if (_SceneDlg->Euler)
00698 pTrShape->setTransformMode (ITransformable::RotEuler);
00699 else
00700 pTrShape->setTransformMode (ITransformable::RotQuat);
00701
00702
00703 _ListTransformShape.push_back (pTrShape);
00704
00705
00706
00707
00708 CMeshInstance *meshInstance=dynamic_cast<CMeshInstance*>(pTrShape);
00709
00710
00711 if (pSkel)
00712 pSkel->bindSkin (meshInstance);
00713
00714
00715 return pTrShape;
00716 }
00717
00718
00719
00720 CSkeletonModel *CObjectViewer::addSkel (NL3D::IShape* pSkelShape, const char* skelName, const char *skelBaseName)
00721 {
00722 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00723
00724
00725
00726
00727 CNELU::ShapeBank->add (skelName, CSmartPtr<IShape> (pSkelShape));
00728
00729
00730 CTransformShape *pTrShape=CNELU::Scene.createInstance (skelName);
00731 nlassert (pTrShape);
00732
00733
00734 CSkeletonModel *skelModel=dynamic_cast<CSkeletonModel*>(pTrShape);
00735
00736
00737 if (skelModel)
00738 {
00739
00740 if (_SceneDlg->Euler)
00741 pTrShape->setTransformMode (ITransformable::RotEuler);
00742 else
00743 pTrShape->setTransformMode (ITransformable::RotQuat);
00744
00745
00746 _ListShapeBaseName.push_back (skelBaseName);
00747
00748
00749 _ListTransformShape.push_back (skelModel);
00750 }
00751
00752
00753 return skelModel;
00754 }
00755
00756
00757
00758 IObjectViewer* IObjectViewer::getInterface (int version)
00759 {
00760 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00761
00762
00763 if (version!=OBJECT_VIEWER_VERSION)
00764 {
00765 MessageBox (NULL, "Bad version of object_viewer.dll.", "NeL object viewer", MB_ICONEXCLAMATION|MB_OK);
00766 return NULL;
00767 }
00768 else
00769 return new CObjectViewer;
00770 }
00771
00772
00773
00774 void IObjectViewer::releaseInterface (IObjectViewer* view)
00775 {
00776 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00777
00778 delete view;
00779 }
00780
00781
00782
00783 void CObjectViewer::setSingleAnimation (NL3D::CAnimation* pAnim, const char* name)
00784 {
00785 AFX_MANAGE_STATE(AfxGetStaticModuleState());
00786
00787
00788 _AnimationSetDlg->UpdateData (TRUE);
00789 _AnimationSetDlg->addAnimation (pAnim, name);
00790 _AnimationSetDlg->UpdateData (FALSE);
00791
00792
00793 setAnimTime (pAnim->getBeginTime()*_AnimationDlg->Speed, pAnim->getEndTime()*_AnimationDlg->Speed);
00794
00795
00796 _SlotDlg->UpdateData ();
00797 _SlotDlg->Slots[0].setAnimation (_AnimationSet.getAnimationIdByName(name), pAnim, name);
00798 _SlotDlg->Slots[0].StartBlend=1.f;
00799 _SlotDlg->Slots[0].EndBlend=1.f;
00800 _SlotDlg->Slots[0].Offset=0;
00801 _SlotDlg->Slots[0].enable=TRUE;
00802 _SlotDlg->UpdateData (FALSE);
00803
00804
00805 reinitChannels ();
00806 }
00807
00808
00809
00810 void CObjectViewer::setAutoAnimation (NL3D::CAnimation* pAnim)
00811 {
00812 CNELU::Scene.setAutoAnim (pAnim);
00813 }
00814
00815
00816
00817 void CObjectViewer::setAmbientColor (const NLMISC::CRGBA& color)
00818 {
00819 CNELU::Driver->setAmbientColor (color);
00820 }
00821
00822
00823
00824 void CObjectViewer::setLight (unsigned char id, const NL3D::CLight& light)
00825 {
00826 CNELU::Driver->enableLight (id);
00827 CNELU::Driver->setLight (id, light);
00828 }
00829
00830