1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #undef OBJECT_VIEWER_EXPORT
23 #define OBJECT_VIEWER_EXPORT __declspec( dllexport )
28 #include "object_viewer.h"
30 #include "nel/3d/nelu.h"
31 #include "nel/3d/mesh.h"
32 #include "nel/3d/mesh_mrm.h"
33 #include "nel/3d/mesh_mrm_skinned.h"
34 #include "nel/3d/transform_shape.h"
35 #include "nel/3d/mesh_instance.h"
36 #include "nel/3d/text_context.h"
37 #include "nel/3d/skeleton_model.h"
38 #include "nel/3d/init_3d.h"
39 #include "nel/3d/scene_group.h"
40 #include "nel/3d/animation_playlist.h"
41 #include "nel/3d/track_keyframer.h"
42 #include "nel/3d/register_3d.h"
43 #include "nel/3d/seg_remanence.h"
45 #include "nel/misc/common.h"
46 #include "nel/misc/file.h"
47 #include "nel/misc/path.h"
48 #include "nel/misc/time_nl.h"
49 #include "nel/misc/config_file.h"
51 #include "nel/sound/u_audio_mixer.h"
52 #include "nel/3d/water_pool_manager.h"
53 #include "nel/3d/landscape_model.h"
54 #include "nel/3d/visual_collision_manager.h"
55 #include "nel/3d/visual_collision_entity.h"
56 #include "nel/3d/ps_util.h"
59 #include "nel/pacs/global_retriever.h"
63 #include "select_movie_size.h"
64 #include "editable_range.h"
65 #include "range_manager.h"
66 #include "located_properties.h"
67 #include "color_button.h"
68 #include "particle_dlg.h"
70 #include "main_frame.h"
71 #include "sound_system.h"
72 #include "scheme_manager.h"
73 #include "day_night_dlg.h"
74 #include "water_pool_editor.h"
75 #include "vegetable_dlg.h"
76 #include "dialog_progress.h"
77 #include "select_string.h"
78 #include "global_wind_dlg.h"
79 #include "sound_anim_dlg.h"
80 #include "light_group_factor.h"
81 #include "choose_bg_color_dlg.h"
82 #include "choose_sun_color_dlg.h"
83 #include "choose_frame_delay.h"
84 #include "skeleton_scale_dlg.h"
86 #include "tune_mrm_dlg.h"
91 using namespace NLMISC
;
92 using namespace NLSOUND
;
93 using namespace NLPACS
;
99 static std::string SPath
;
101 uint SkeletonUsedForSound
= 0xFFFFFFFF;
102 CSoundContext SoundContext
;
108 // If this DLL is dynamically linked against the MFC
109 // DLLs, any functions exported from this DLL which
110 // call into MFC must have the AFX_MANAGE_STATE macro
111 // added at the very beginning of the function.
115 // extern "C" BOOL PASCAL EXPORT ExportedFunction()
117 // AFX_MANAGE_STATE(AfxGetStaticModuleState());
118 // // normal function body here
121 // It is very important that this macro appear in each
122 // function, prior to any calls into MFC. This means that
123 // it must appear as the first statement within the
124 // function, even before any object variable declarations
125 // as their constructors may generate calls into the MFC
128 // Please see MFC Technical Notes 33 and 58 for additional
132 /////////////////////////////////////////////////////////////////////////////
135 BEGIN_MESSAGE_MAP(CObject_viewerApp
, CWinApp
)
136 //{{AFX_MSG_MAP(CObject_viewerApp)
140 /////////////////////////////////////////////////////////////////////////////
141 // CObject_viewerApp construction
143 CObject_viewerApp::CObject_viewerApp()
145 // TODO: add construction code here,
146 // Place all significant initialization in InitInstance
149 /////////////////////////////////////////////////////////////////////////////
150 // The one and only CObject_viewerApp object
152 CObject_viewerApp theApp
;
155 bool CObjectViewer::_InstanceRunning
= false;
157 // ***************************************************************************
159 class CObjView
: public CView
166 virtual ~CObjView() {}
167 virtual void OnDraw (CDC
*) {}
168 afx_msg BOOL
OnEraseBkgnd(CDC
* pDC
)
172 virtual LRESULT
WindowProc(UINT message
, WPARAM wParam
, LPARAM lParam
)
174 if ((CNELU::Driver
) && MainFrame
)
175 MainFrame
->DriverWindowProc (CNELU::Driver
, m_hWnd
, message
, wParam
, lParam
);
177 return CView::WindowProc(message
, wParam
, lParam
);
179 DECLARE_DYNCREATE(CObjView
)
180 CMainFrame
*MainFrame
;
183 // ***************************************************************************
185 IMPLEMENT_DYNCREATE(CObjView
, CView
)
188 // ***************************************************************************
190 void animateCNELUScene (CCloudScape
*cs
, uint64 deltaTime
= 0)
193 static sint64 firstTime
= NLMISC::CTime::getLocalTime();
194 static sint64 lastTime
= NLMISC::CTime::getLocalTime();
197 deltaTime
= NLMISC::CTime::getLocalTime() - lastTime
;
199 lastTime
+= deltaTime
;
200 float fdelta
= 0.001f
* (float) (lastTime
- firstTime
);
201 CNELU::Scene
->animate ( fdelta
);
202 cs
->anim (fdelta
, CNELU::Scene
->getCam());
205 // ***************************************************************************
207 CObjectViewer::CObjectViewer ()
209 AFX_MANAGE_STATE(AfxGetStaticModuleState());
215 // vl: is it really useful? i moved it from ov.exe init
216 CScene::registerBasics ();
222 _AnimationSetDlg
=NULL
;
225 _FontGenerator
= NULL
;
226 _VegetableLandscape
= NULL
;
227 _VegetableCollisionManager
= NULL
;
228 _VegetableCollisionEntity
= NULL
;
229 _CameraFocal
= 75.f
; // default value for the focal
230 _SelectedObject
= 0xffffffff;
231 _LightGroupDlg
= NULL
;
232 _ChooseFrameDelayDlg
= NULL
;
233 _ChooseBGColorDlg
= NULL
;
235 _WaterPoolDlg
= NULL
;
236 _SoundAnimDlg
= NULL
;
237 _VegetableDlg
= NULL
;
238 _GlobalWindDlg
= NULL
;
239 _SkeletonScaleDlg
= NULL
;
243 // no frame delay is the default
252 _BackGroundColor
= CRGBA::Black
;
257 _Wpm
= &NL3D::GetWaterPoolManager();
259 _GlobalRetriever
= NULL
;
260 _ObjectLightTest
= NULL
;
262 _CharacterScalePos
= 1;
268 _FogColor
= NLMISC::CRGBA::Black
;
270 _FXUserMatrix
.identity();
272 _FXMatrixVisible
= false;
273 _FXUserMatrixVisible
= false;
274 _SceneMatrixVisible
= false;
275 _OcclusionTestMeshsVisible
= false;
279 // ***************************************************************************
280 std::string
CObjectViewer::getModulePath() const
282 // Get the configuration file path (located in same directory as module)
283 HMODULE hModule
= AfxGetInstanceHandle();
284 nlassert(hModule
); // shouldn't be null now anymore in any case
285 nlassert(hModule
!= GetModuleHandle(NULL
)); // if this is dll, the module handle can't be same as exe
286 TCHAR sModulePath
[256];
287 int res
= GetModuleFileName(hModule
, sModulePath
, 256); nlassert(res
);
288 nldebug("Object viewer module path is '%s'", sModulePath
);
290 SPath
= NLMISC::CFile::getPath(tStrToUtf8(sModulePath
));
292 return SPath
+ "object_viewer.cfg";
296 // ***************************************************************************
297 void CObjectViewer::loadDriverName()
299 // Load the config file
301 cf
.load (getModulePath());
302 CConfigFile::CVar
*var
= cf
.getVarPtr("driver");
303 _Direct3d
= var
&& (var
->asString() == "direct3d");
306 // ***************************************************************************
307 void CObjectViewer::loadConfigFile()
309 // Load object_viewer.ini
312 // Load the config file
314 cf
.load (getModulePath());
319 CConfigFile::CVar
&search_pathes
= cf
.getVar ("search_pathes");
320 for (uint i
=0; i
<(uint
)search_pathes
.size(); i
++)
321 CPath::addSearchPath (search_pathes
.asString(i
));
323 catch(const EUnknownVar
&)
328 // Add recusrive search pathes
329 CConfigFile::CVar
&recursive_search_pathes
= cf
.getVar ("recursive_search_pathes");
330 for (uint i
=0; i
<(uint
)recursive_search_pathes
.size(); i
++)
331 CPath::addSearchPath (recursive_search_pathes
.asString(i
), true, false);
333 catch(const EUnknownVar
&)
336 // Add extension remapping
339 CConfigFile::CVar
&extensions_remapping
= cf
.getVar ("extensions_remapping");
340 if (extensions_remapping
.size()%2 != 0)
342 nlwarning ("extensions_remapping must have a multiple of 2 entries (ex: extensions_remapping={\"dds\",\"tga\"};)");
346 for (uint i
=0; i
<(uint
)extensions_remapping
.size(); i
+=2)
347 CPath::remapExtension(extensions_remapping
.asString(i
), extensions_remapping
.asString(i
+1), true);
350 catch (const EUnknownVar
&)
354 // debug, display path
357 // set the sound banks and sample banks
360 /* CConfigFile::CVar &var = cf.getVar("sound_path");
361 string soundPath = var.asString();
363 var = cf.getVar("soundbanks");
364 for (uint i=0; i<(uint)var.size(); i++)
366 string dir = soundPath;
367 dir.append("/").append(var.asString(i).c_str());
368 CSoundSystem::addSoundBank(dir);
372 CConfigFile::CVar
&var
= cf
.getVar("sample_path");
373 string
samplePath(var
.asString());
374 CSoundSystem::setSamplePath(samplePath
);
378 CConfigFile::CVar
&var
= cf
.getVar("packed_sheet_path");
379 string
packedSheetPath(var
.asString());
380 CSoundSystem::setPackedSheetPath(packedSheetPath
);
383 /*CConfigFile::CVar var = cf.getVar("samplebanks");
384 for (uint i=0; i<(uint)var.size(); i++)
385 CSoundSystem::addSampleBank(var.asString(i).c_str());*/
387 catch (const EUnknownVar
&)
389 //::MessageBox(NULL, "warning : 'sample_path' or 'packed_sheet_path' variable not defined.\nSound will not work properly.", "Objectviewer.cfg", MB_OK|MB_ICONEXCLAMATION);
392 // load the camera focal
395 CConfigFile::CVar
&camera_focal
= cf
.getVar("camera_focal");
396 _CameraFocal
= camera_focal
.asFloat();
398 catch (const EUnknownVar
&)
403 // load Scene light setup.
406 CConfigFile::CVar
&var
= cf
.getVar("scene_light_enabled");
407 _SceneLightEnabled
= var
.asInt() !=0 ;
409 catch (const EUnknownVar
&)
411 _SceneLightEnabled
= false;
415 CConfigFile::CVar
&var
= cf
.getVar("scene_light_sun_ambiant");
416 _SceneLightSunAmbiant
.R
= var
.asInt(0);
417 _SceneLightSunAmbiant
.G
= var
.asInt(1);
418 _SceneLightSunAmbiant
.B
= var
.asInt(2);
420 catch (const EUnknownVar
&)
422 _SceneLightSunAmbiant
= NLMISC::CRGBA::Black
;
426 CConfigFile::CVar
&var
= cf
.getVar("scene_light_sun_diffuse");
427 _SceneLightSunDiffuse
.R
= var
.asInt(0);
428 _SceneLightSunDiffuse
.G
= var
.asInt(1);
429 _SceneLightSunDiffuse
.B
= var
.asInt(2);
431 catch (const EUnknownVar
&)
433 _SceneLightSunDiffuse
= NLMISC::CRGBA::White
;
437 CConfigFile::CVar
&var
= cf
.getVar("scene_light_sun_specular");
438 _SceneLightSunSpecular
.R
= var
.asInt(0);
439 _SceneLightSunSpecular
.G
= var
.asInt(1);
440 _SceneLightSunSpecular
.B
= var
.asInt(2);
442 catch (const EUnknownVar
&)
444 _SceneLightSunSpecular
= NLMISC::CRGBA::White
;
448 CConfigFile::CVar
&var
= cf
.getVar("scene_light_sun_dir");
449 _SceneLightSunDir
.x
= var
.asFloat(0);
450 _SceneLightSunDir
.y
= var
.asFloat(1);
451 _SceneLightSunDir
.z
= var
.asFloat(2);
452 _SceneLightSunDir
.normalize();
454 catch (const EUnknownVar
&)
456 _SceneLightSunDir
.set(0, 1, -1);
457 _SceneLightSunDir
.normalize();
461 CConfigFile::CVar
&var
= cf
.getVar("object_light_test");
462 _ObjectLightTestShape
= var
.asString();
464 catch (const EUnknownVar
&)
468 // Load vegetable Landscape cfg.
469 loadVegetableLandscapeCfg(cf
);
471 // load automatfic animations
474 CConfigFile::CVar
&var
= cf
.getVar("automatic_animation_path");
475 CUniquePtr
<CAnimationSet
> as(new CAnimationSet
);
477 bool loadingOk
= as
->loadFromFiles(var
.asString(),true ,"anim",true);
481 //::MessageBox(NULL, "Warning : Unable to load all automatic animation", "Error", MB_OK | MB_ICONEXCLAMATION);
482 nlwarning("Unable to load all automatic animation");
484 CNELU::Scene
->setAutomaticAnimationSet(as
.release());
486 catch (const EUnknownVar
&)
488 //::MessageBox(NULL, "No automatic animation path specified, please set 'automatic_animation_path'", "warning", MB_OK);
489 nlwarning("No automatic animation path specified");
492 // load CharacterScalePos
495 CConfigFile::CVar
&var
= cf
.getVar("character_scale_pos");
496 _CharacterScalePos
= var
.asFloat();
498 catch (const EUnknownVar
&)
503 CConfigFile::CVar
*var
= cf
.getVarPtr("fog");
505 _Fog
= var
->asInt() != 0;
506 var
= cf
.getVarPtr("fog_start");
508 _FogStart
= var
->asFloat();
509 var
= cf
.getVarPtr("fog_end");
511 _FogEnd
= var
->asFloat();
512 var
= cf
.getVarPtr("fog_color");
514 _FogColor
= CRGBA ((uint8
)(var
->asInt(0)), (uint8
)(var
->asInt(1)), (uint8
)(var
->asInt(2)));
518 if (var
= cf
.getVarPtr("cloud_count"))
519 _CSS
.NbCloud
= var
->asInt();
520 if (var
= cf
.getVarPtr("cloud_diffuse"))
522 _CSS
.Diffuse
.R
= var
->asInt(0);
523 _CSS
.Diffuse
.G
= var
->asInt(1);
524 _CSS
.Diffuse
.B
= var
->asInt(2);
526 if (var
= cf
.getVarPtr("cloud_ambient"))
528 _CSS
.Ambient
.R
= var
->asInt(0);
529 _CSS
.Ambient
.G
= var
->asInt(1);
530 _CSS
.Ambient
.B
= var
->asInt(2);
532 if (var
= cf
.getVarPtr("cloud_speed"))
533 _CSS
.CloudSpeed
= var
->asFloat();
534 if (var
= cf
.getVarPtr("cloud_update_period"))
535 _CSS
.TimeToChange
= var
->asFloat();
536 if (var
= cf
.getVarPtr("cloud_wind_speed"))
537 _CSS
.WindSpeed
= var
->asFloat();
539 catch (const Exception
& e
)
541 ::MessageBox(NULL
, nlUtf8ToTStr(e
.what()), _T("Objectviewer.cfg"), MB_OK
| MB_ICONEXCLAMATION
);
546 // ***************************************************************************
547 // properly remove a single window
548 static void removeWindow(CWnd
*wnd
)
551 wnd
->DestroyWindow();
555 // ***************************************************************************
556 CObjectViewer::~CObjectViewer ()
558 AFX_MANAGE_STATE(AfxGetStaticModuleState());
559 removeWindow(_MainFrame
);
560 removeWindow(_SlotDlg
);
561 removeWindow(_AnimationSetDlg
);
562 removeWindow(_AnimationDlg
);
563 removeWindow(_DayNightDlg
);
564 removeWindow(_WaterPoolDlg
);
565 removeWindow(_SoundAnimDlg
);
566 removeWindow(_LightGroupDlg
);
567 removeWindow(_ChooseBGColorDlg
);
568 removeWindow(_VegetableDlg
);
569 removeWindow(_GlobalWindDlg
);
570 removeWindow(_SkeletonScaleDlg
);
571 removeWindow(_TuneMRMDlg
);
572 delete _FontGenerator
;
575 // ***************************************************************************
577 void CObjectViewer::initCamera ()
581 uint32 width
, height
;
582 CNELU::Driver
->getWindowSize (width
, height
);
583 frustrum
.initPerspective( _CameraFocal
*(float)Pi
/180.f
, height
!= 0 ? (float)width
/(float)height
: 0.f
, 0.1f
, 1000.f
);
584 CNELU::Camera
->setFrustum (frustrum
);
588 for (i
=0; i
<_Cameras
.size (); i
++)
590 frustrum
.initPerspective( _ListInstance
[_Cameras
[i
]]->Camera
->getFov(), height
!= 0 ? (float)width
/(float)height
: 0.f
, 0.1f
, 1000.f
);
591 _ListInstance
[_Cameras
[i
]]->Camera
->setFrustum (frustrum
);
595 // ***************************************************************************
598 CFontGenerator
*newCFontGenerator(const std::string
&fontFileName
);
601 // ***************************************************************************
603 bool CObjectViewer::initUI (HWND parent
)
605 AFX_MANAGE_STATE(AfxGetStaticModuleState());
607 // initialize NeL context if needed
608 if (!NLMISC::INelContext::isContextInitialised())
610 new NLMISC::CApplicationContext();
611 nldebug("NeL Object Viewer: initUI");
615 _FontManager
.setMaxMemory(2000000);
618 uint dSize
= ::GetWindowsDirectory(NULL
, 0);
621 TCHAR
*wd
= new TCHAR
[dSize
];
622 nlverify(::GetWindowsDirectory(wd
, dSize
));
623 _FontPath
= tStrToUtf8(wd
) + "\\fonts\\arial.ttf";
626 // The font generator
627 _FontGenerator
= NL3D::newCFontGenerator ( _FontPath
);
633 HICON hIcon
= (HICON
)LoadImage(theApp
.m_hInstance
, MAKEINTRESOURCE(IDI_APP_ICON
), IMAGE_ICON
,
636 // load name of the driver from the config file
639 // Create a doomy driver
640 IDriver
*driver
= _Direct3d
?CDRU::createD3DDriver():CDRU::createGlDriver();
644 CWnd
*parentWndPtr
=NULL
;
647 parentWnd
.Attach (parent
);
648 parentWndPtr
=&parentWnd
;
651 // Create the main frame
652 _MainFrame
= new CMainFrame (this, (winProc
) driver
->getWindowProc());
655 _MainFrame
->registerValue (true);
658 _MainFrame
->CFrameWnd::Create (AfxRegisterWndClass(0, 0, NULL
, hIcon
),
659 _T("NeL object viewer"), 0x00cfc000, /*WS_OVERLAPPEDWINDOW,*/ CFrameWnd::rectDefault
, parentWndPtr
,
660 MAKEINTRESOURCE(IDR_OBJECT_VIEWER_MENU
), 0x00000300 /*WS_EX_ACCEPTFILES*/ /*|WS_EX_CLIENTEDGE*/);
665 // Delete doomy driver
669 getRegisterWindowState (_MainFrame
, REGKEY_OBJ_VIEW_OPENGL_WND
, true);
670 _MainFrame
->ActivateFrame ();
671 _MainFrame
->ShowWindow (SW_SHOW
);
672 _MainFrame
->UpdateWindow();
674 // Context to open a view
675 CCreateContext context
;
676 context
.m_pCurrentDoc
=NULL
;
677 context
.m_pCurrentFrame
=_MainFrame
;
678 context
.m_pLastView
=NULL
;
679 context
.m_pNewDocTemplate
=NULL
;
680 context
.m_pNewViewClass
=RUNTIME_CLASS(CObjView
);
683 CObjView
*view
= (CObjView
*)_MainFrame
->CreateView (&context
);
684 view
->ShowWindow (SW_SHOW
);
685 _MainFrame
->SetActiveView(view
);
686 view
= (CObjView
*)_MainFrame
->GetActiveView();
687 view
->MainFrame
= _MainFrame
;
689 _MainFrame
->ShowWindow (SW_SHOW
);
692 GetClientRect(view
->m_hWnd
, &viewportRect
);
695 if (!CNELU::init (viewportRect
.right
, viewportRect
.bottom
, viewport
, 32, true, view
->m_hWnd
, false, _Direct3d
))
699 //CNELU::init (640, 480, viewport, 32, true, _MainFrame->m_hWnd);
700 CNELU::Scene
->setPolygonBalancingMode(CScene::PolygonBalancingClamp
);
702 // load the config file
706 CNELU::Driver
->enableFog (_Fog
);
707 CNELU::Driver
->setupFog (_FogStart
, _FogEnd
, _FogColor
);
710 CSoundSystem::initSoundSystem ();
713 _SceneRoot
= (CTransform
*)CNELU::Scene
->createModel(NL3D::TransformId
);
715 // Init default lighting seutp.
716 setupSceneLightingSystem(_SceneLightEnabled
, _SceneLightSunDir
, _SceneLightSunAmbiant
, _SceneLightSunDiffuse
, _SceneLightSunSpecular
);
721 _MainFrame
->OnResetCamera();
723 // Create animation set dialog
724 _AnimationSetDlg
=new CAnimationSetDlg (this, _MainFrame
);
725 _AnimationSetDlg
->Create (IDD_ANIMATION_SET
);
726 getRegisterWindowState (_AnimationSetDlg
, REGKEY_OBJ_VIEW_ANIMATION_SET_DLG
, false);
728 // Create animation set dialog
729 _AnimationDlg
=new CAnimationDlg (this, _MainFrame
);
730 _AnimationDlg
->Create (IDD_ANIMATION
);
731 getRegisterWindowState (_AnimationDlg
, REGKEY_OBJ_VIEW_ANIMATION_DLG
, false);
733 // Create the main dialog
734 _SlotDlg
=new CMainDlg (this, _MainFrame
);
735 _SlotDlg
->Create (IDD_MAIN_DLG
);
736 getRegisterWindowState (_SlotDlg
, REGKEY_OBJ_VIEW_SLOT_DLG
, false);
738 // Create particle dialog
739 _ParticleDlg
=new CParticleDlg (this, _MainFrame
, _MainFrame
, _AnimationDlg
);
740 _ParticleDlg
->Create (IDD_PARTICLE
);
741 getRegisterWindowState (_ParticleDlg
, REGKEY_OBJ_PARTICLE_DLG
, false);
743 // Create water pool editor dialog
744 _WaterPoolDlg
= new CWaterPoolEditor(_Wpm
, _MainFrame
);
745 _WaterPoolDlg
->Create (IDD_WATER_POOL
);
746 getRegisterWindowState (_WaterPoolDlg
, REGKEY_OBJ_WATERPOOL_DLG
, false);
748 // Create day night dialog
749 _DayNightDlg
= new CDayNightDlg (this, _MainFrame
);
750 _DayNightDlg
->Create (IDD_DAYNIGHT
);
751 getRegisterWindowState (_DayNightDlg
, REGKEY_OBJ_DAYNIGHT_DLG
, false);
753 // Create vegetable dialog
754 _VegetableDlg
=new CVegetableDlg (this, _MainFrame
);
755 _VegetableDlg
->Create (IDD_VEGETABLE_DLG
);
756 getRegisterWindowState (_VegetableDlg
, REGKEY_OBJ_VIEW_VEGETABLE_DLG
, false);
758 // Create global wind dialog
759 _GlobalWindDlg
= new CGlobalWindDlg (this, _MainFrame
);
760 _GlobalWindDlg
->Create(IDD_GLOBAL_WIND
);
761 getRegisterWindowState (_GlobalWindDlg
, REGKEY_OBJ_GLOBAL_WIND_DLG
, false);
763 // Create sound animation editor dialog
764 _SoundAnimDlg
= new CSoundAnimDlg(this, _AnimationDlg
, _MainFrame
);
765 _SoundAnimDlg
->Create (IDD_SOUND_ANIM_DLG
, _MainFrame
);
766 getRegisterWindowState (_SoundAnimDlg
, REGKEY_OBJ_SOUND_ANIM_DLG
, false);
768 // Create light group editor dialog
769 _LightGroupDlg
= new CLightGroupFactor(_MainFrame
);
770 _LightGroupDlg
->Create (IDD_LIGHT_GROUP_FACTOR
, _MainFrame
);
771 getRegisterWindowState (_LightGroupDlg
, REGKEY_OBJ_LIGHT_GROUP_DLG
, false);
773 // Create frame delay window
774 _ChooseFrameDelayDlg
= new CChooseFrameDelay(this, _MainFrame
);
775 _ChooseFrameDelayDlg
->Create(IDD_CHOOSE_FRAME_DELAY
, _MainFrame
);
776 getRegisterWindowState (_ChooseFrameDelayDlg
, REGKEY_CHOOSE_FRAME_DELAY_DLG
, false);
778 // Set backgroupnd color
779 setBackGroundColor(_MainFrame
->BgColor
);
781 // Create bg color window (must create after the background color has been set)
782 _ChooseBGColorDlg
= new CChooseBGColorDlg(this, _MainFrame
);
783 _ChooseBGColorDlg
->Create(IDD_CHOOSE_BG_COLOR
, _MainFrame
);
784 getRegisterWindowState (_ChooseBGColorDlg
, REGKEY_CHOOSE_BG_COLOR_DLG
, false);
786 // Create bg color window (must create after the background color has been set)
787 _ChooseSunColorDlg
= new CChooseSunColorDlg(CNELU::Scene
, _MainFrame
);
788 _ChooseSunColorDlg
->Create(IDD_CHOOSE_SUN_COLOR
, _MainFrame
);
789 getRegisterWindowState (_ChooseSunColorDlg
, REGKEY_CHOOSE_SUN_COLOR_DLG
, false);
791 // Create skeleton scale dlg
792 _SkeletonScaleDlg
= new CSkeletonScaleDlg(this, _MainFrame
);
793 _SkeletonScaleDlg
->Create(IDD_SKELETON_SCALE_DLG
, _MainFrame
);
794 getRegisterWindowState (_SkeletonScaleDlg
, REGKEY_SKELETON_SCALE_DLG
, false);
796 // Create tune mrm dlg
797 _TuneMRMDlg
= new CTuneMrmDlg(this, CNELU::Scene
, _MainFrame
);
798 _TuneMRMDlg
->Create(IDD_TUNE_MRM_DLG
, _MainFrame
);
799 getRegisterWindowState (_TuneMRMDlg
, REGKEY_TUNE_MRM_DLG
, false);
802 _MainFrame
->update ();
806 setAnimTime (0.f
, 100.f
);
808 // Add mouse listener to event server
809 _MouseListener
.addToServer(CNELU::EventServer
);
811 CNELU::Driver
->activate ();
813 // Enable sum of vram
814 CNELU::Driver
->enableUsedTextureMemorySum ();
816 // load the scheme bank if one is present
818 std::string path
= SPath
+ "default.scb";
823 iF
.serial(SchemeManager
);
825 catch (const NLMISC::EStream
&e
)
827 std::string msg
= toString("Unable to load the default scheme bank file : %s", e
.what());
828 ::MessageBox(NULL
, nlUtf8ToTStr(msg
), _T("Object Viewer"), MB_ICONEXCLAMATION
);
833 // try to load a default config file for the viewer (for anitmation and particle edition setup)
834 path
= SPath
+ "default.ovcgf";
842 catch (const Exception
& e
)
844 std::string msg
= toString("Error while loading default.ovcgf : %s", e
.what());
845 ::MessageBox(NULL
, nlUtf8ToTStr(msg
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
849 // Create the cloud scape
850 _CS
= new CCloudScape(CNELU::Driver
);
856 // ***************************************************************************
858 void CObjectViewer::addTransformation (CMatrix
¤t
, CAnimation
*anim
, float begin
, float end
, ITrack
*posTrack
, ITrack
*rotquatTrack
,
859 ITrack
*nextPosTrack
, ITrack
*nextRotquatTrack
, bool removeLast
)
862 if (_AnimationDlg
->Inplace
)
869 // Remove the start of the animation
870 CQuat
rotEnd (0,0,0,1);
871 CVector
posEnd (0,0,0);
874 // Interpolate the rotation
875 rotquatTrack
->interpolate (end
, rotEnd
);
879 // Interpolate the position
880 posTrack
->interpolate (end
, posEnd
);
883 // Add the final rotation and position
890 if (_AnimationDlg
->IncPos
)
897 CQuat
rotStart (0,0,0,1);
898 CVector
posStart (0,0,0);
899 if (nextRotquatTrack
)
901 // Interpolate the rotation
902 nextRotquatTrack
->interpolate (begin
, rotStart
);
906 // Interpolate the position
907 nextPosTrack
->interpolate (begin
, posStart
);
909 // Remove the init rotation and position of the next animation
911 tmp
.setRot (rotStart
);
912 tmp
.setPos (posStart
);
917 CVector I
= current
.getI ();
918 CVector J
= current
.getJ ();
926 tmp
.setRot (I
, J
, K
);
927 tmp
.setPos (current
.getPos ());
933 // ***************************************************************************
935 void CObjectViewer::setupPlaylist (float time
)
937 // Update animation dlg
941 for (i
=0; i
<_ListInstance
.size(); i
++)
943 // Empty with playlist
945 for (j
=0; j
<CChannelMixer::NumAnimationSlot
; j
++)
948 _ListInstance
[i
]->Playlist
.setAnimation (j
, CAnimationPlaylist::empty
);
951 // With channel mixer ?
952 if (_AnimationSetDlg
->UseMixer
)
955 _ListInstance
[i
]->setAnimationPlaylist (getFrameRate ());
958 _ListInstance
[i
]->Playlist
.setupMixer (_ListInstance
[i
]->ChannelMixer
, _AnimationDlg
->getTime());
962 // Some animation in the list ?
963 if (_ListInstance
[i
]->Saved
.PlayList
.size()>0)
966 uint choosedIndex
= 0xffffffff;
976 CAnimation
*anim
= NULL
;
977 ITrack
*posTrack
= NULL
;
978 ITrack
*rotquatTrack
= NULL
;
980 // Try channel animationset
981 anim
= _ListInstance
[i
]->AnimationSet
.getAnimation (_ListInstance
[i
]->AnimationSet
.getAnimationIdByName (_ListInstance
[i
]->Saved
.PlayList
[0]));
984 posTrack
= (ITrack
*)anim
->getTrackByName ("pos");
985 rotquatTrack
= (ITrack
*)anim
->getTrackByName ("rotquat");
987 there
= posTrack
|| rotquatTrack
;
991 float endTime
=anim
->getEndTime()-anim
->getBeginTime();
996 // Get animation used in the list
997 while (time
>=endTime
)
1001 if (index
<_ListInstance
[i
]->Saved
.PlayList
.size())
1003 // Pointer on the animation
1004 CAnimation
*newAnim
=_ListInstance
[i
]->AnimationSet
.getAnimation (_ListInstance
[i
]->AnimationSet
.getAnimationIdByName(_ListInstance
[i
]->Saved
.PlayList
[index
]));
1005 ITrack
*newPosTrack
= (ITrack
*)newAnim
->getTrackByName ("pos");
1006 ITrack
*newRotquatTrack
= (ITrack
*)newAnim
->getTrackByName ("rotquat");
1008 // Add the transformation
1009 addTransformation (current
, anim
, newAnim
->getBeginTime(), anim
->getEndTime(), posTrack
, rotquatTrack
, newPosTrack
, newRotquatTrack
, true);
1011 // Pointer on the animation
1013 posTrack
= newPosTrack
;
1014 rotquatTrack
= newRotquatTrack
;
1017 startTime
= endTime
;
1018 endTime
= startTime
+ anim
->getEndTime()-anim
->getBeginTime();
1023 // Add the transformation
1024 addTransformation (current
, anim
, 0, anim
->getEndTime(), posTrack
, rotquatTrack
, NULL
, NULL
, false);
1031 if (index
>=_ListInstance
[i
]->Saved
.PlayList
.size())
1037 choosedIndex
= _ListInstance
[i
]->AnimationSet
.getAnimationIdByName (_ListInstance
[i
]->Saved
.PlayList
[index
]);
1038 anim
=_ListInstance
[i
]->AnimationSet
.getAnimation (choosedIndex
);
1040 // End time for last anim
1041 startTime
= anim
->getEndTime () - time
;
1047 // Add the transformation
1048 addTransformation (current
, anim
, 0, anim
->getBeginTime() + time
- startTime
, posTrack
, rotquatTrack
, NULL
, NULL
, false);
1051 choosedIndex
= _ListInstance
[i
]->AnimationSet
.getAnimationIdByName (_ListInstance
[i
]->Saved
.PlayList
[index
]);
1053 // Get the animation
1054 anim
=_ListInstance
[i
]->AnimationSet
.getAnimation (choosedIndex
);
1057 startTime
-= anim
->getBeginTime ();
1061 _ListInstance
[i
]->Playlist
.setTimeOrigin (0, startTime
);
1062 _ListInstance
[i
]->Playlist
.setWrapMode (0, CAnimationPlaylist::Clamp
);
1063 _ListInstance
[i
]->Playlist
.setStartWeight (0, 1, 0);
1064 _ListInstance
[i
]->Playlist
.setEndWeight (0, 1, 1);
1065 _ListInstance
[i
]->Playlist
.setAnimation (0, choosedIndex
);
1067 // Setup the channel
1068 _ListInstance
[i
]->Playlist
.setupMixer (_ListInstance
[i
]->ChannelMixer
, _AnimationDlg
->getTime());
1070 // Setup the pos and rot for this shape
1073 CVector pos
= current
.getPos();
1074 // Get a skeleton model
1075 CSkeletonModel
*skelModel
=dynamic_cast<CSkeletonModel
*>(_ListInstance
[i
]->TransformShape
);
1076 // If a skeleton model
1079 // scale animated pos value with the CFG scale
1080 pos
*= _CharacterScalePos
;
1083 if (_ListInstance
[i
]->TransformShape
)
1085 _ListInstance
[i
]->TransformShape
->setPos (pos
);
1086 _ListInstance
[i
]->TransformShape
->setRotQuat (current
.getRot());
1088 if (_ListInstance
[i
]->Camera
)
1090 _ListInstance
[i
]->Camera
->setPos (pos
);
1091 _ListInstance
[i
]->Camera
->setRotQuat (current
.getRot());
1097 if (_ListInstance
[i
]->TransformShape
)
1099 CMeshBase
*meshBase
= dynamic_cast<CMeshBase
*> ((IShape
*)_ListInstance
[i
]->TransformShape
->Shape
);
1102 _ListInstance
[i
]->TransformShape
->setPos (meshBase
->getDefaultPos ()->getDefaultValue ());
1103 _ListInstance
[i
]->TransformShape
->setRotQuat (meshBase
->getDefaultRotQuat ()->getDefaultValue ());
1104 _ListInstance
[i
]->TransformShape
->setScale (meshBase
->getDefaultScale ()->getDefaultValue ());
1108 /*_ListInstance[i]->TransformShape->setPos (CVector::Null);
1109 _ListInstance[i]->TransformShape->setRotQuat (CQuat::Identity);
1110 _ListInstance[i]->TransformShape->setScale (1, 1, 1);*/
1113 if (_ListInstance
[i
]->Camera
)
1115 _ListInstance
[i
]->Camera
->setPos (_ListInstance
[i
]->Camera
->getDefaultPos ()->getDefaultValue ());
1116 _ListInstance
[i
]->Camera
->setTargetPos (_ListInstance
[i
]->Camera
->getDefaultTargetPos ()->getDefaultValue ());
1124 // tool funct : this if a window has another window as a parent (recursive)
1125 // if parent == true, this return true
1126 static bool isParentWnd(HWND parent
, HWND son
)
1128 if (parent
== son
) return true;
1129 HWND directParent
= GetParent (son
);
1130 if (!directParent
) return false;
1131 if (directParent
== parent
) return true;
1132 return isParentWnd(parent
, directParent
);
1136 // ***************************************************************************
1137 void CObjectViewer::go ()
1139 nlassert(!_InstanceRunning
); // this shouldn't be called if an instance of the viewer is running.
1140 AFX_MANAGE_STATE(AfxGetStaticModuleState());
1142 _InstanceRunning
= true;
1143 CGraph
graph("ms", 10, 10, 200, 100, CRGBA(64, 64, 64), 20, 200);
1148 if (isParentWnd(_MainFrame
->m_hWnd
, GetForegroundWindow()))
1150 CNELU::Driver
->activate ();
1153 _AnimationDlg
->handle ();
1155 // Handle sound animation
1156 _SoundAnimDlg
->handle ();
1158 // Handle sound animation
1159 _LightGroupDlg
->handle ();
1161 // Setup the channel mixer
1162 _AnimationSetDlg
->UpdateData ();
1164 // Setup the play list
1165 setupPlaylist (_AnimationDlg
->getTime());
1167 // Eval sound tracks
1168 evalSoundTrack (_AnimationDlg
->getLastTime(), _AnimationDlg
->getTime());
1170 // Animate the automatic animation in the scene
1171 //CNELU::Scene->animate( (float) + NLMISC::CTime::ticksToSecond( NLMISC::CTime::getPerformanceTime() ) );
1174 // Eval channel mixer for transform
1175 for (uint i
=0; i
<_ListInstance
.size(); i
++)
1177 _ListInstance
[i
]->ChannelMixer
.eval (false);
1179 animateCNELUScene (_CS
);
1181 // Clear the buffers
1182 CNELU::clearBuffers(_BackGroundColor
);
1185 //if (_CS) _CS->setDebugQuad(true);
1187 // call of callback list
1189 std::vector
<IMainLoopCallBack
*> copyVect(_CallBackList
.begin(), _CallBackList
.end());
1190 for (std::vector
<IMainLoopCallBack
*>::iterator it
= _CallBackList
.begin(); it
!= _CallBackList
.end(); ++it
)
1192 (*it
)->goPreRender();
1196 if (_CS
) _CS
->render ();
1199 CNELU::Scene
->render();
1201 // call of callback list
1203 std::vector
<IMainLoopCallBack
*> copyVect(_CallBackList
.begin(), _CallBackList
.end());
1204 for (std::vector
<IMainLoopCallBack
*>::iterator it
= _CallBackList
.begin(); it
!= _CallBackList
.end(); ++it
)
1206 (*it
)->goPostRender();
1210 if (_OcclusionTestMeshsVisible
)
1212 CNELU::Scene
->renderOcclusionTestMeshs();
1215 // Profile polygon count
1216 CPrimitiveProfile in
, out
;
1217 CNELU::Driver
->profileRenderedPrimitives (in
, out
);
1220 if (_MainFrame
->MoveMode
== CMainFrame::ObjectMode
)
1222 float radius
=_HotSpotSize
/2.f
;
1223 CNELU::Driver
->setupModelMatrix (CMatrix::Identity
);
1224 CDRU::drawLine (_MouseListener
.getHotSpot()+CVector (radius
, 0, 0), _MouseListener
.getHotSpot()+CVector (-radius
, 0, 0), _HotSpotColor
, *CNELU::Driver
);
1225 CDRU::drawLine (_MouseListener
.getHotSpot()+CVector (0, radius
, 0), _MouseListener
.getHotSpot()+CVector (0, -radius
, 0), _HotSpotColor
, *CNELU::Driver
);
1226 CDRU::drawLine (_MouseListener
.getHotSpot()+CVector (0, 0, radius
), _MouseListener
.getHotSpot()+CVector (0, 0, -radius
), _HotSpotColor
, *CNELU::Driver
);
1230 if (CNELU::AsyncListener
.isKeyPushed(KeyF3
))
1232 // Change render mode
1233 switch (CNELU::Driver
->getPolygonMode())
1235 case IDriver::Filled
:
1236 CNELU::Driver
->setPolygonMode (IDriver::Line
);
1239 CNELU::Driver
->setPolygonMode (IDriver::Point
);
1241 case IDriver::Point
:
1242 CNELU::Driver
->setPolygonMode (IDriver::Filled
);
1247 // draw various matrix
1248 if (_FXMatrixVisible
) drawFXMatrix();
1249 if (_FXUserMatrixVisible
) drawFXUserMatrix();
1250 if (_SceneMatrixVisible
) drawSceneMatrix();
1252 // draw Skeleton Scale Dlg selection
1253 if(_SkeletonScaleDlg
)
1254 _SkeletonScaleDlg
->drawSelection();
1257 bool keyWndOk
= false;
1258 if (CNELU::AsyncListener
.isKeyPushed(Key1
))
1259 _MainFrame
->OnWindowAnimation(), keyWndOk
= true;
1260 if (CNELU::AsyncListener
.isKeyPushed(Key2
))
1261 _MainFrame
->OnWindowAnimationset(), keyWndOk
= true;
1262 if (CNELU::AsyncListener
.isKeyPushed(Key3
))
1263 _MainFrame
->OnWindowMixersslots(), keyWndOk
= true;
1264 if (CNELU::AsyncListener
.isKeyPushed(Key4
))
1265 _MainFrame
->OnWindowParticles(), keyWndOk
= true;
1266 if (CNELU::AsyncListener
.isKeyPushed(Key5
))
1267 _MainFrame
->OnWindowDayNight(), keyWndOk
= true;
1268 if (CNELU::AsyncListener
.isKeyPushed(Key6
))
1269 _MainFrame
->OnWindowWaterPool(), keyWndOk
= true;
1270 if (CNELU::AsyncListener
.isKeyPushed(Key7
))
1271 _MainFrame
->OnWindowVegetable(), keyWndOk
= true;
1272 if (CNELU::AsyncListener
.isKeyPushed(Key8
))
1273 _MainFrame
->OnWindowGlobalwind(), keyWndOk
= true;
1274 if (CNELU::AsyncListener
.isKeyPushed(Key9
))
1275 _MainFrame
->OnWindowSoundAnim(), keyWndOk
= true;
1276 if (CNELU::AsyncListener
.isKeyPushed(KeyO
))
1277 _MainFrame
->OnFileOpen(), keyWndOk
= true;
1280 if (CNELU::AsyncListener
.isKeyPushed(KeyR
))
1281 _MainFrame
->OnReloadTextures();
1283 // If some window activated, reset the focus to the main wnd.
1285 _MainFrame
->SetActiveWindow();
1288 static sint64 lastTime
=NLMISC::CTime::getPerformanceTime ();
1289 sint64 newTime
=NLMISC::CTime::getPerformanceTime ();
1290 sint64 timeDiff
= newTime
- lastTime
;
1291 float fps
= timeDiff
> 0 ? (float)(1.0 / NLMISC::CTime::ticksToSecond (newTime
-lastTime
)) : 1000.0f
;
1293 uint nbPlayingSources
, nbSources
;
1294 if (CSoundSystem::getAudioMixer())
1296 nbPlayingSources
= CSoundSystem::getAudioMixer()->getUsedTracksCount();
1297 nbSources
= CSoundSystem::getAudioMixer()->getPlayingSourcesCount();
1301 nbPlayingSources
= nbSources
= NULL
;
1304 // Display std info.
1305 std::string msgBar
= toString("%s - Nb tri: %u - Texture used (MiB): %5.2f - Texture allocated (MiB): %5.2f - Distance: %5.0f - Sounds: %u/%u - Fps: %03.1f",
1306 _Direct3d
? "Direct3d":"OpenGL",
1307 in
.NLines
+in
.NPoints
+in
.NQuads
*2+in
.NTriangles
+in
.NTriangleStrips
,
1308 (float)CNELU::Driver
->getUsedTextureMemory () / (float)(1024*1024),
1309 (float)CNELU::Driver
->profileAllocatedTextureMemory () / (float)(1024*1024),
1310 (_SceneCenter
-CNELU::Camera
->getMatrix().getPos()).norm(),
1317 _MainFrame
->StatusBar
.SetWindowText(nlUtf8ToTStr(msgBar
));
1319 // Display Vegetable info.
1320 if(_VegetableDlg
!=NULL
)
1322 if(_VegetableLandscape
!= NULL
)
1324 CString vegetMsgBar
;
1325 vegetMsgBar
.Format(_T("%u"), _VegetableLandscape
->Landscape
.getNumVegetableFaceRendered());
1326 _VegetableDlg
->StaticPolyCount
.SetWindowText(vegetMsgBar
);
1330 _VegetableDlg
->StaticPolyCount
.SetWindowText(_T("0"));
1334 // graph disabled for now..
1335 // graph.addValue(CNELU::Scene->getEllapsedTime() * 1000.f);
1336 // graph.renderGraph();
1339 CNELU::swapBuffers();
1341 // Select the good camera
1342 if (_MainFrame
->MoveMode
== CMainFrame::CameraMode
)
1344 sint cameraId
= getCurrentCamera ();
1347 CInstanceInfo
*info
= getInstance(getCameraInstance (cameraId
));
1348 nlassert (info
->Camera
);
1349 CNELU::Scene
->setCam (info
->Camera
);
1354 CNELU::Scene
->setCam (CNELU::Camera
);
1357 if (_MainFrame
->MoveMode
== CMainFrame::ObjectMode
)
1359 _MouseListener
.setMouseMode (CEvent3dMouseListener::edit3d
);
1363 _MouseListener
.setMouseMode (CEvent3dMouseListener::firstPerson
);
1364 _MouseListener
.setSpeed (_MainFrame
->MoveSpeed
);
1369 // Reset camera aspect ratio
1372 if (_MainFrame
->isMoveElement())
1374 // for now we apply a transform on the selected object in the particle system
1375 _ParticleDlg
->moveElement(_MouseListener
.getModelMatrix());
1377 else if (_MainFrame
->isMoveFX())
1379 _ParticleDlg
->setPSWorldMatrix(_MouseListener
.getModelMatrix());
1381 else if (_MainFrame
->isMoveFXUserMatrix())
1383 setFXUserMatrix(_MouseListener
.getModelMatrix());
1385 else if (_MainFrame
->isMoveObjectLightTest())
1387 _ObjectLightTestMatrix
= _MouseListener
.getModelMatrix();
1389 else if (_MainFrame
->isMoveSceneRoot())
1391 _SceneRoot
->setTransformMode (ITransformable::DirectMatrix
);
1392 _SceneRoot
->setMatrix (_MouseListener
.getModelMatrix());
1396 nlassert(_MainFrame
->isMoveCamera());
1398 // New matrix from camera
1399 CNELU::Camera
->setTransformMode (ITransformable::DirectMatrix
);
1400 CNELU::Camera
->setMatrix (_MouseListener
.getViewMatrix());
1402 // Vegetable: manage collision snapping if wanted and possible
1403 if(_VegetableSnapToGround
&& _VegetableLandscape
)
1405 // get matrix from camera.
1406 CMatrix matrix
= CNELU::Camera
->getMatrix();
1408 CVector pos
= matrix
.getPos();
1409 // if succes to snap to ground
1410 if(_VegetableCollisionEntity
->snapToGround(pos
))
1412 pos
.z
+= _VegetableSnapHeight
;
1414 // reset the moveListener and the camera.
1415 _MouseListener
.setMatrix(matrix
);
1416 CNELU::Camera
->setMatrix(matrix
);
1422 // Update lighting test Dynamic object position
1423 if(_ObjectLightTest
&& _GlobalRetriever
)
1425 // Get the position of the object snapped.
1426 UGlobalPosition gPos
= _GlobalRetriever
->retrievePosition(_ObjectLightTestMatrix
.getPos());
1427 CVector pos
= _GlobalRetriever
->getGlobalPosition(gPos
);
1428 _ObjectLightTest
->setPos(pos
);
1429 _ObjectLightTest
->setRotQuat(_ObjectLightTestMatrix
.getRot());
1431 // Update the matrix and the mouseListener.
1432 if (_MainFrame
->isMoveObjectLightTest())
1434 _ObjectLightTestMatrix
.setPos(pos
);
1435 _MouseListener
.setModelMatrix(_ObjectLightTestMatrix
);
1438 // Update the logicInfo so lighting is well computed.
1439 _ObjectLightTestLogicInfo
.GPos
= gPos
;
1442 // Pump message from the server
1443 CNELU::EventServer
.pump();
1445 // Pump others message for the windows
1447 while ( PeekMessage(&msg
, NULL
,0,0,PM_REMOVE
) )
1449 TranslateMessage(&msg
);
1450 DispatchMessage(&msg
);
1453 CSoundSystem::setListenerMatrix(_MouseListener
.getViewMatrix());
1454 CSoundSystem::poll();
1458 // simulate frame delay
1461 NLMISC::nlSleep(_FrameDelay
);
1466 _LastTime
=_AnimationDlg
->getTime();
1471 // Traditionnal message loop
1473 while (GetMessage( &msg
, NULL
, 0, 0) == TRUE
)
1475 ::TranslateMessage(&msg
);
1476 ::DispatchMessage(&msg
);
1477 if (!IsWindow (_MainFrame
->m_hWnd
))
1480 // Get the foreground window
1481 if (isParentWnd(_MainFrame
->m_hWnd
, GetForegroundWindow()))
1486 while (!CNELU::AsyncListener
.isKeyPushed(KeyESCAPE
)&&CNELU::Driver
->isActive());
1487 _InstanceRunning
= false;
1490 // ***************************************************************************
1492 void CObjectViewer::releaseUI ()
1494 AFX_MANAGE_STATE(AfxGetStaticModuleState());
1496 // Release particles
1497 removeWindow(_ChooseFrameDelayDlg
);
1498 removeWindow(_ParticleDlg
);
1501 CSoundSystem::releaseSoundSystem();
1503 if (CNELU::Driver
->isActive())
1505 // register window position
1506 if (CNELU::Driver
->getDisplay())
1508 setRegisterWindowState (_MainFrame
, REGKEY_OBJ_VIEW_OPENGL_WND
);
1515 _MainFrame
->registerValue (false);
1516 // Remove the main frame
1517 if (::IsWindow(*_MainFrame
))
1519 _MainFrame
->DestroyWindow();
1525 // Release the emitter from the server
1526 _MouseListener
.removeFromServer (CNELU::EventServer
);
1530 // remove first possibly created collisions objects.
1531 if(_VegetableCollisionEntity
)
1533 _VegetableCollisionManager
->deleteEntity(_VegetableCollisionEntity
);
1534 _VegetableCollisionEntity
= NULL
;
1536 if(_VegetableCollisionManager
)
1538 delete _VegetableCollisionManager
;
1539 _VegetableCollisionManager
= NULL
;
1543 if(_VegetableLandscape
)
1545 CNELU::Scene
->deleteModel(_VegetableLandscape
);
1546 _VegetableLandscape
= NULL
;
1551 // Release all instances and all Igs.
1552 removeAllInstancesFromScene();
1556 // Create the cloud scape
1561 CNELU::Scene
->deleteModel(_SceneRoot
);
1564 // release other 3D.
1570 // ***************************************************************************
1572 void setRegisterWindowState (const CWnd
*pWnd
, const TCHAR
* keyName
)
1575 if (RegCreateKey(HKEY_CURRENT_USER
, keyName
, &hKey
)==ERROR_SUCCESS
)
1578 pWnd
->GetWindowRect (&rect
);
1579 RegSetValueEx(hKey
, _T("Left"), 0, REG_DWORD
, (LPBYTE
)&rect
.left
, 4);
1580 RegSetValueEx(hKey
, _T("Right"), 0, REG_DWORD
, (LPBYTE
)&rect
.right
, 4);
1581 RegSetValueEx(hKey
, _T("Top"), 0, REG_DWORD
, (LPBYTE
)&rect
.top
, 4);
1582 RegSetValueEx(hKey
, _T("Bottom"), 0, REG_DWORD
, (LPBYTE
)&rect
.bottom
, 4);
1586 // ***************************************************************************
1588 void getRegisterWindowState (CWnd
*pWnd
, const TCHAR
* keyName
, bool resize
)
1591 if (RegOpenKeyEx(HKEY_CURRENT_USER
, keyName
, 0, KEY_READ
, &hKey
)==ERROR_SUCCESS
)
1596 RegQueryValueEx (hKey
, _T("Left"), 0, &type
, (LPBYTE
)&rect
.left
, &len
);
1597 RegQueryValueEx (hKey
, _T("Right"), 0, &type
, (LPBYTE
)&rect
.right
, &len
);
1598 RegQueryValueEx (hKey
, _T("Top"), 0, &type
, (LPBYTE
)&rect
.top
, &len
);
1599 RegQueryValueEx (hKey
, _T("Bottom"), 0, &type
, (LPBYTE
)&rect
.bottom
, &len
);
1602 pWnd
->SetWindowPos (NULL
, rect
.left
, rect
.top
, rect
.right
-rect
.left
, rect
.bottom
-rect
.top
, SWP_NOOWNERZORDER
|SWP_NOZORDER
|
1603 (resize
?0:SWP_NOSIZE
));
1607 // ***************************************************************************
1609 void CObjectViewer::setAnimTime (float animStart
, float animEnd
)
1611 // Dispatch the command
1612 _SlotDlg
->setAnimTime (animStart
, animEnd
);
1613 _AnimationDlg
->setAnimTime (animStart
, animEnd
);
1614 _SoundAnimDlg
->setAnimTime (animStart
, animEnd
);
1617 // ***************************************************************************
1620 void CObjectViewer::resetSlots (uint instance
)
1622 // Reset the animation set
1623 _ListInstance
[instance
]->AnimationSet
.reset ();
1625 // Set no animation in slot UI
1626 for (uint j
=0; j
<NL3D::CChannelMixer::NumAnimationSlot
; j
++)
1627 _ListInstance
[instance
]->Saved
.SlotInfo
[j
].Animation
.clear();
1629 // Reset the animation list
1630 _ListInstance
[instance
]->Saved
.AnimationFileName
.clear ();
1632 // Reset the play list
1633 _ListInstance
[instance
]->Saved
.PlayList
.clear ();
1635 // Reset the skeleton list
1636 _ListInstance
[instance
]->Saved
.SWTFileName
.clear ();
1639 _AnimationSetDlg
->refresh (TRUE
);
1640 _SlotDlg
->refresh (TRUE
);
1641 _SoundAnimDlg
->refresh (TRUE
);
1644 // ***************************************************************************
1646 void CObjectViewer::reinitChannels ()
1648 // Add all the instance in the channel mixer
1649 for (uint i
=0; i
<_ListInstance
.size(); i
++)
1651 // Reset the channels
1652 _ListInstance
[i
]->ChannelMixer
.resetChannels ();
1654 // Setup animation set
1655 _ListInstance
[i
]->ChannelMixer
.setAnimationSet (&(_ListInstance
[i
]->AnimationSet
));
1657 // Register the transform (but not if it has automatic animation, as a channel mixer has been created for us)
1658 bool autoAnim
= false;
1659 if (dynamic_cast<CMeshBaseInstance
*>(_ListInstance
[i
]->TransformShape
))
1661 CMeshBase
*mb
= NLMISC::safe_cast
<CMeshBase
*>( (IShape
*) static_cast<CMeshBaseInstance
*>(_ListInstance
[i
]->TransformShape
)->Shape
);
1662 autoAnim
= mb
->getAutoAnim();
1667 if (_ListInstance
[i
]->TransformShape
)
1668 _ListInstance
[i
]->TransformShape
->registerToChannelMixer (&(_ListInstance
[i
]->ChannelMixer
), "");
1669 if (_ListInstance
[i
]->Camera
)
1670 _ListInstance
[i
]->Camera
->registerToChannelMixer (&(_ListInstance
[i
]->ChannelMixer
), "");
1674 // Enable / disable channels
1678 // ***************************************************************************
1680 void CObjectViewer::enableChannels ()
1682 // Disable some channels
1683 _AnimationSetDlg
->UpdateData ();
1684 bool enable
= (_AnimationSetDlg
->UseMixer
== 1);
1686 // Add all the instance in the channel mixer
1687 for (uint i
=0; i
<_ListInstance
.size(); i
++)
1689 // Get the pos and rot channel id
1690 uint posId
= _ListInstance
[i
]->AnimationSet
.getChannelIdByName ("pos");
1691 uint rotQuatId
= _ListInstance
[i
]->AnimationSet
.getChannelIdByName ("rotquat");
1692 uint rotEulerId
= _ListInstance
[i
]->AnimationSet
.getChannelIdByName ("roteuler");
1694 if (posId
!= CAnimationSet::NotFound
)
1695 _ListInstance
[i
]->ChannelMixer
.enableChannel (posId
, enable
);
1696 if (rotQuatId
!= CAnimationSet::NotFound
)
1697 _ListInstance
[i
]->ChannelMixer
.enableChannel (rotQuatId
, enable
);
1698 if (rotEulerId
!= CAnimationSet::NotFound
)
1699 _ListInstance
[i
]->ChannelMixer
.enableChannel (rotEulerId
, enable
);
1703 // ***************************************************************************
1705 float CObjectViewer::getFrameRate ()
1707 return _AnimationDlg
->Speed
;
1710 // ***************************************************************************
1712 string
getFilename (const string
&file
)
1714 // if the direct file exist, return it
1715 if (NLMISC::CFile::fileExists(file
))
1718 string path
= NLMISC::CFile::getFilename(file
);
1719 path
= CPath::lookup (path
, false, false, false);
1725 // ***************************************************************************
1727 void CObjectViewer::serial (NLMISC::IStream
& f
)
1729 // version 4: include particle workspace infos
1730 // serial "OBJV_CFG"
1731 f
.serialCheck (NELID("VJBO"));
1732 f
.serialCheck (NELID("GFC_"));
1734 // serial the version
1735 int ver
=f
.serialVersion (4);
1738 f
.serial(ParticleWorkspaceFilename
);
1742 // Read the configuration file
1747 ParticleWorkspaceFilename
.clear();
1750 uint firstInstance
= (uint
)_ListInstance
.size();
1753 std::vector
<CInstanceSave
> readed
;
1754 f
.serialCont (readed
);
1757 for (uint i
=0; i
<readed
.size(); i
++)
1762 uint instance
= 0xffffffff;
1764 if (readed
[i
].Camera
)
1766 instance
= addCamera (readed
[i
].CameraInfo
, readed
[i
].ShapeFilename
.c_str());
1772 string path
= getFilename (readed
[i
].ShapeFilename
);
1773 if (input
.open (path
))
1776 CShapeStream serialShape
;
1777 serialShape
.serial (input
);
1780 if (readed
[i
].IsSkeleton
)
1783 instance
= addSkel (serialShape
.getShapePointer(), readed
[i
].ShapeFilename
.c_str());
1784 SkeletonUsedForSound
= instance
;
1789 if (readed
[i
].SkeletonId
!= 0xffffffff)
1790 instance
= addMesh (serialShape
.getShapePointer(), readed
[i
].ShapeFilename
.c_str(), readed
[i
].SkeletonId
+ firstInstance
, (readed
[i
].BindBoneName
.empty())?NULL
:readed
[i
].BindBoneName
.c_str());
1792 instance
= addMesh (serialShape
.getShapePointer(), readed
[i
].ShapeFilename
.c_str(), 0xffffffff, (readed
[i
].BindBoneName
.empty())?NULL
:readed
[i
].BindBoneName
.c_str());
1798 std::string message
= toString("File not found %s", readed
[i
].ShapeFilename
.c_str());
1799 _MainFrame
->MessageBox(nlUtf8ToTStr(message
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
1806 // Check instance number
1807 nlassert (instance
== (firstInstance
+i
));
1810 for (uint anim
=0; anim
<readed
[i
].AnimationFileName
.size(); anim
++)
1812 string path
= getFilename (readed
[i
].AnimationFileName
[anim
]);
1813 loadAnimation (path
.c_str(), instance
);
1817 for (uint swt
=0; swt
<readed
[i
].SWTFileName
.size(); swt
++)
1819 string path
= getFilename (readed
[i
].SWTFileName
[swt
]);
1820 loadSWT (path
.c_str(), instance
);
1824 _ListInstance
[instance
]->Saved
.PlayList
= readed
[i
].PlayList
;
1826 // Set the slot information
1827 for (uint slot
=0; slot
<NL3D::CChannelMixer::NumAnimationSlot
; slot
++)
1828 _ListInstance
[instance
]->Saved
.SlotInfo
[slot
] = readed
[i
].SlotInfo
[slot
];
1830 catch (const Exception
&e
)
1833 std::string message
= toString("Error loading shape %s: %s", readed
[i
].ShapeFilename
.c_str(), e
.what());
1834 _MainFrame
->MessageBox(nlUtf8ToTStr(message
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
1844 // Read the selection
1846 f
.serial (selection
);
1847 if (selection
+firstInstance
< _ListInstance
.size())
1849 _SelectedObject
= selection
+firstInstance
;
1852 // Invalidate dialogs
1853 _AnimationSetDlg
->refresh (TRUE
);
1854 _SlotDlg
->refresh (TRUE
);
1855 _SoundAnimDlg
->refresh (TRUE
);
1859 // Build information
1860 std::vector
<CInstanceSave
> readed (_ListInstance
.size());
1861 for (uint instance
=0; instance
<_ListInstance
.size(); instance
++)
1863 // Copy the save information
1864 readed
[instance
] = _ListInstance
[instance
]->Saved
;
1867 // Save the configuration
1868 f
.serialCont (readed
);
1870 // Write the selection
1871 f
.serial (_SelectedObject
);
1876 // ***************************************************************************
1878 bool CObjectViewer::loadInstanceGroup(const std::string
&igFilename
)
1880 //AFX_MANAGE_STATE(AfxGetStaticModuleState());
1882 // Add search path for the mesh
1883 CPath::addSearchPath (NLMISC::CFile::getPath(igFilename
));
1887 if (file
.open (igFilename
))
1890 NL3D::CInstanceGroup
*ig
= new NL3D::CInstanceGroup
;
1898 addInstanceGroup(ig
);
1900 catch (const Exception
& e
)
1904 _MainFrame
->MessageBox(nlUtf8ToTStr(e
.what()), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
1911 std::string msg
= toString("Can't open the file %s for reading.", igFilename
.c_str());
1912 _MainFrame
->MessageBox(nlUtf8ToTStr(msg
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
1923 // ***************************************************************************
1925 bool CObjectViewer::loadMesh (std::vector
<std::string
> &meshFilename
, const std::string
&skeleton
)
1927 AFX_MANAGE_STATE(AfxGetStaticModuleState());
1931 // Add search path for the skeleton
1932 if (skeleton
.empty())
1934 CPath::addSearchPath (NLMISC::CFile::getPath(skeleton
));
1941 IShape
*shapeSkel
=NULL
;
1942 uint skelIndex
= 0xffffffff;
1943 NL3D::CSkeletonModel
*transformSkel
=NULL
;
1946 bool skelError
=false;
1949 if (!skeleton
.empty())
1953 if (file
.open (skeleton
))
1956 CShapeStream streamShape
;
1960 streamShape
.serial (file
);
1963 shapeSkel
=streamShape
.getShapePointer();
1965 catch (const Exception
& e
)
1967 _MainFrame
->MessageBox(nlUtf8ToTStr(e
.what()), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
1976 std::string msg
= NLMISC::toString("Can't open the file %s for reading.", skeleton
.c_str());
1977 _MainFrame
->MessageBox(nlUtf8ToTStr(msg
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
1989 bool skelUsed
= false;
1991 // Index of the shape
1992 uint lastShape
= 0xffffffff;
1995 for (uint i
=0; i
<meshFilename
.size(); i
++)
1998 const std::string fileName
= meshFilename
[i
];
2000 // Add search path for the mesh
2001 CPath::addSearchPath (NLMISC::CFile::getPath(fileName
));
2004 IShape
*shapeMesh
=NULL
;
2006 if (file
.open (fileName
))
2009 CShapeStream streamShape
;
2013 streamShape
.serial (file
);
2016 shapeMesh
=streamShape
.getShapePointer();
2018 catch (const Exception
& e
)
2020 _MainFrame
->MessageBox(nlUtf8ToTStr(e
.what()), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
2027 std::string msg
= NLMISC::toString("Can't open the file %s for reading.", fileName
.c_str());
2028 _MainFrame
->MessageBox(nlUtf8ToTStr(msg
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
2032 // Add the skel shape
2033 if (shapeSkel
&&(!skelUsed
))
2036 skelIndex
= addSkel (shapeSkel
, skeleton
);
2037 if (skelIndex
!= 0xffffffff)
2040 transformSkel
= dynamic_cast<CSkeletonModel
*>(_ListInstance
[skelIndex
]->TransformShape
);
2041 nlassert (transformSkel
);
2045 // Add the skel shape
2048 // Get the object name
2049 lastShape
= addMesh (shapeMesh
, fileName
, skelIndex
);
2054 if ((!skelUsed
)&&shapeSkel
)
2060 // Select the skeleton
2061 if (skelIndex
!= 0xffffffff)
2062 _SelectedObject
= skelIndex
;
2063 else if (lastShape
!= 0xffffffff)
2064 _SelectedObject
= lastShape
;
2067 _AnimationSetDlg
->refresh (TRUE
);
2068 _SlotDlg
->refresh (TRUE
);
2069 _SoundAnimDlg
->refresh (TRUE
);
2074 // ***************************************************************************
2076 void CObjectViewer::resetCamera ()
2078 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2080 _MainFrame
->OnResetCamera();
2083 // ***************************************************************************
2085 uint
CObjectViewer::addMesh (NL3D::IShape
* pMeshShape
, const std::string
&meshName
, uint skelIndex
, const char* bindSkelName
, bool createInstance
)
2087 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2089 // *** Add the shape
2091 // Store the shape pointer
2092 if (CNELU::ShapeBank
->getPresentState(meshName
)!=CShapeBank::NotPresent
)
2097 CNELU::ShapeBank
->add (meshName
, CSmartPtr
<IShape
> (pMeshShape
));
2099 // Must create the instance?
2102 // Create a model and add it to the scene
2103 CTransformShape
*pTrShape
=CNELU::Scene
->createInstance (meshName
);
2104 nlassert (pTrShape
);
2106 // link to the root for manipulation
2107 _SceneRoot
->hrcLinkSon(pTrShape
);
2109 // Get the real shape used by the instance.
2110 pMeshShape
= pTrShape
->Shape
;
2112 // Set the rot model
2113 if (_MainFrame
->Euler
)
2114 pTrShape
->setTransformMode (ITransformable::RotEuler
);
2116 pTrShape
->setTransformMode (ITransformable::RotQuat
);
2118 // Store the transform shape pointer
2119 CInstanceInfo
*iInfo
= new CInstanceInfo
;
2120 iInfo
->TransformShape
= pTrShape
;
2122 // Store the name of the shape
2123 iInfo
->MustDelete
= true;
2124 iInfo
->Saved
.ShapeFilename
= meshName
;
2125 iInfo
->Saved
.SkeletonId
= skelIndex
;
2126 _ListInstance
.push_back (iInfo
);
2128 // *** Bind to the skeleton
2130 // Get a mesh instance
2131 CMeshBaseInstance
*meshInstance
=dynamic_cast<CMeshBaseInstance
*>(pTrShape
);
2134 if (skelIndex
!= 0xffffffff)
2137 NL3D::CSkeletonModel
*transformSkel
= dynamic_cast<CSkeletonModel
*>(_ListInstance
[skelIndex
]->TransformShape
);
2138 nlassert (transformSkel
);
2140 // It is a skinned mesh ?
2141 CMesh
*mesh
= dynamic_cast<CMesh
*>(pMeshShape
);
2142 CMeshMRM
*meshMrm
= dynamic_cast<CMeshMRM
*>(pMeshShape
);
2143 CMeshMRMSkinned
*meshMrmSkinned
= dynamic_cast<CMeshMRMSkinned
*>(pMeshShape
);
2144 if ( (mesh
&& mesh
->getMeshGeom().isSkinned()) ||
2145 (meshMrm
&& meshMrm
->getMeshGeom().isSkinned()) ||
2149 transformSkel
->bindSkin (meshInstance
);
2154 uint bindBone
= 0xffffffff;
2155 std::string boneName
;
2157 // Name is passed, look for bone
2160 // Make a list of bones
2162 for (bone
=0; bone
<transformSkel
->Bones
.size(); bone
++)
2164 if (transformSkel
->Bones
[bone
].getBoneName() == bindSkelName
)
2167 boneName
= bindSkelName
;
2173 // Found ? No, look for a bind bone
2174 if (bindBone
== 0xffffffff)
2176 // Make a list of bones
2177 vector
<string
> listBones
;
2179 for (bone
=0; bone
<transformSkel
->Bones
.size(); bone
++)
2180 listBones
.push_back (transformSkel
->Bones
[bone
].getBoneName());
2182 // Get name of the mesh
2183 std::string nameMesh
= NLMISC::CFile::getFilenameWithoutExtension(meshName
);
2186 std::string message
= "Select a bone to stick " + string (nameMesh
);
2187 CSelectString
dialogSelect (listBones
, message
.c_str(), _MainFrame
, false);
2188 if (dialogSelect
.DoModal ()==IDOK
)
2190 // Select your bones
2191 bindBone
= dialogSelect
.Selection
;
2192 boneName
= listBones
[dialogSelect
.Selection
];
2197 if (bindBone
!= 0xffffffff)
2199 transformSkel
->stickObject (pTrShape
, bindBone
);
2200 /*meshInstance->setPos (CVector::Null);
2201 meshInstance->setRotQuat (CQuat::Identity);
2202 meshInstance->setScale (1, 1, 1);*/
2205 // Set the bone name
2206 iInfo
->Saved
.BindBoneName
= boneName
;
2210 // Return the instance index
2211 return (uint
)_ListInstance
.size()-1;
2218 // ***************************************************************************
2219 bool CObjectViewer::chooseBone(const std::string
&caption
, NL3D::CSkeletonModel
*&skel
, uint
&boneIndex
, std::string
*skelName
/*= NULL*/, std::string
*boneName
/*= NULL*/)
2221 for(uint k
= 0; k
< _ListInstance
.size(); ++k
)
2223 NL3D::CSkeletonModel
*transformSkel
= dynamic_cast<CSkeletonModel
*>(_ListInstance
[k
]->TransformShape
);
2226 // Make a list of bones
2227 vector
<string
> listBones
;
2229 for (bone
=0; bone
<transformSkel
->Bones
.size(); bone
++)
2231 listBones
.push_back (transformSkel
->Bones
[bone
].getBoneName());
2233 CSelectString
dialogSelect (listBones
, caption
.c_str(), _MainFrame
, false);
2234 if (dialogSelect
.DoModal ()==IDOK
)
2236 boneIndex
= dialogSelect
.Selection
;
2237 skel
= transformSkel
;
2240 *skelName
= _ListInstance
[k
]->Saved
.ShapeFilename
;
2244 *boneName
= safe_cast
<NL3D::CSkeletonModel
*>(_ListInstance
[k
]->TransformShape
)->Bones
[boneIndex
].getBoneName();
2254 // ***************************************************************************
2255 bool CObjectViewer::isSkeletonPresent() const
2257 for(uint k
= 0; k
< _ListInstance
.size(); ++k
)
2259 NL3D::CSkeletonModel
*transformSkel
= dynamic_cast<CSkeletonModel
*>(_ListInstance
[k
]->TransformShape
);
2260 if (transformSkel
) return true;
2265 // ***************************************************************************
2267 uint
CObjectViewer::addCamera (const NL3D::CCameraInfo
&cameraInfo
, const std::string
&cameraName
)
2269 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2271 // *** Add the shape
2273 // link to the root for manipulation
2274 CCamera
*pCamera
= (CCamera
*)CNELU::Scene
->createModel (CameraId
);
2275 _SceneRoot
->hrcLinkSon(pCamera
);
2278 pCamera
->build (cameraInfo
);
2280 // Store the transform shape pointer
2281 CInstanceInfo
*iInfo
= new CInstanceInfo
;
2282 iInfo
->Camera
= pCamera
;
2284 // Store the name of the shape
2285 iInfo
->MustDelete
= true;
2286 iInfo
->Saved
.ShapeFilename
= cameraName
;
2287 iInfo
->Saved
.SkeletonId
= 0xffffffff;
2288 iInfo
->Saved
.CameraInfo
= cameraInfo
;
2289 iInfo
->Saved
.Camera
= true;
2290 _ListInstance
.push_back (iInfo
);
2291 _Cameras
.push_back ((uint
)_ListInstance
.size()-1);
2296 // Return the instance index
2297 return (uint
)_ListInstance
.size()-1;
2300 // ***************************************************************************
2302 uint
CObjectViewer::addSkel (NL3D::IShape
* pSkelShape
, const std::string
&skelName
)
2304 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2306 // *** Add the shape
2308 // Store the shape pointer
2309 if (CNELU::ShapeBank
->getPresentState(skelName
)!=CShapeBank::NotPresent
)
2314 CNELU::ShapeBank
->add (skelName
, CSmartPtr
<IShape
> (pSkelShape
));
2316 // Create a model and add it to the scene
2317 CTransformShape
*pTrShape
=CNELU::Scene
->createInstance (skelName
);
2318 nlassert (pTrShape
);
2320 // link to the root for manipulation
2321 _SceneRoot
->hrcLinkSon(pTrShape
);
2323 // Get the real shape used by the instance.
2324 pSkelShape
= pTrShape
->Shape
;
2326 // Get a skeleton model
2327 CSkeletonModel
*skelModel
=dynamic_cast<CSkeletonModel
*>(pTrShape
);
2332 // Set the rot model
2333 if (_MainFrame
->Euler
)
2334 pTrShape
->setTransformMode (ITransformable::RotEuler
);
2336 pTrShape
->setTransformMode (ITransformable::RotQuat
);
2338 // Store the transform shape pointer
2339 CInstanceInfo
*iInfo
= new CInstanceInfo
;
2340 iInfo
->TransformShape
= skelModel
;
2342 // Store the name of the shape
2343 iInfo
->MustDelete
= true;
2344 iInfo
->Saved
.ShapeFilename
= skelName
;
2345 iInfo
->Saved
.IsSkeleton
= true;
2346 iInfo
->Saved
.SkeletonId
= 0xffffffff;
2347 _ListInstance
.push_back (iInfo
);
2349 // set this skeleton for Skeleton Scale edition
2350 _SkeletonScaleDlg
->setSkeletonToEdit(skelModel
, skelName
);
2352 // Return the instance
2353 return (uint
)_ListInstance
.size()-1;
2358 // ***************************************************************************
2360 IObjectViewer
* IObjectViewer::getInterface (int version
)
2362 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2364 // Check version number
2365 if (version
!=OBJECT_VIEWER_VERSION
)
2367 MessageBox (NULL
, _T("Bad version of object_viewer.dll."), _T("NeL object viewer"), MB_ICONEXCLAMATION
|MB_OK
);
2371 return new CObjectViewer
;
2374 // ***************************************************************************
2376 void IObjectViewer::releaseInterface (IObjectViewer
* view
)
2378 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2383 // ***************************************************************************
2385 void CObjectViewer::setSingleAnimation (NL3D::CAnimation
* pAnim
, const std::string
&name
, uint instance
)
2387 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2389 if (instance
< _ListInstance
.size())
2392 _SelectedObject
= instance
;
2394 // Add the animation
2395 addAnimation (pAnim
, name
+ ".anim", name
, instance
);
2397 // Add the animation to the animationSet
2398 _AnimationSetDlg
->UpdateData (TRUE
);
2399 _AnimationSetDlg
->UseMixer
= 1;
2400 _AnimationSetDlg
->UpdateData (FALSE
);
2402 // Set the animation in the first slot
2403 _ListInstance
[instance
]->Saved
.SlotInfo
[0].Animation
= name
;
2404 _ListInstance
[instance
]->Saved
.SlotInfo
[0].Skeleton
.clear();
2405 _ListInstance
[instance
]->Saved
.SlotInfo
[0].Offset
= 0;
2406 _ListInstance
[instance
]->Saved
.SlotInfo
[0].StartTime
= (int)(pAnim
->getBeginTime()*_AnimationDlg
->Speed
);
2407 _ListInstance
[instance
]->Saved
.SlotInfo
[0].EndTime
= (int)(pAnim
->getEndTime()*_AnimationDlg
->Speed
);
2408 _ListInstance
[instance
]->Saved
.SlotInfo
[0].StartBlend
= 1.f
;
2409 _ListInstance
[instance
]->Saved
.SlotInfo
[0].EndBlend
= 1.f
;
2410 _ListInstance
[instance
]->Saved
.SlotInfo
[0].Enable
= true;
2411 for (uint i
=1; i
<CChannelMixer::NumAnimationSlot
; i
++)
2412 _ListInstance
[instance
]->Saved
.SlotInfo
[i
].Enable
= false;
2414 // Update dialog box
2415 _AnimationSetDlg
->refresh (TRUE
);
2416 _SlotDlg
->refresh (TRUE
);
2417 _SoundAnimDlg
->refresh(TRUE
);
2424 // ***************************************************************************
2426 void CObjectViewer::setAutoAnimation (NL3D::CAnimationSet
* pAnimSet
)
2428 CNELU::Scene
->setAutomaticAnimationSet (pAnimSet
);
2431 // ***************************************************************************
2433 void CObjectViewer::setAmbientColor (const NLMISC::CRGBA
& color
)
2435 CNELU::Driver
->setAmbientColor (color
);
2437 // Setup also Scene lighting system here, even if not used.
2438 CNELU::Scene
->setAmbientGlobal(color
);
2441 // ***************************************************************************
2443 void CObjectViewer::setLight (unsigned char id
, const NL3D::CLight
& light
)
2445 CNELU::Driver
->enableLight (id
);
2446 CNELU::Driver
->setLight (id
, light
);
2449 // ***************************************************************************
2452 /** add an object that will be notified each time a frame is processed
2453 * \see removeMainLoopCallBack()
2455 void CObjectViewer::registerMainLoopCallBack(IMainLoopCallBack
*i
)
2457 // nlassert(std::find(_CallBackList.begin(), _CallBackList.end(), i) == _CallBackList.begin()); // the object was register twice !!
2458 _CallBackList
.push_back(i
);
2461 /// remove an object that was registered with registerMainLoopCallBack()
2462 void CObjectViewer::removeMainLoopCallBack(IMainLoopCallBack
*i
)
2464 std::vector
<IMainLoopCallBack
*>::iterator it
= std::find(_CallBackList
.begin(), _CallBackList
.end(), i
);
2465 nlassert(it
!= _CallBackList
.end()); // this object wasn't registered
2466 _CallBackList
.erase(it
);
2469 // ***************************************************************************
2470 void CObjectViewer::activateTextureSet(uint index
)
2472 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2474 std::vector
<CInstanceInfo
*>::iterator it
;
2475 for (it
= _ListInstance
.begin(); it
!= _ListInstance
.end(); ++it
)
2477 NL3D::CTransformShape
*trShape
= (*it
)->TransformShape
;
2478 if (dynamic_cast<NL3D::CMeshBaseInstance
*>(trShape
))
2480 static_cast<NL3D::CMeshBaseInstance
*>(trShape
)->selectTextureSet(index
);
2485 // ***************************************************************************
2486 void CObjectViewer::shuffleTextureSet()
2488 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2490 std::vector
<CInstanceInfo
*>::iterator it
;
2491 for (it
= _ListInstance
.begin(); it
!= _ListInstance
.end(); ++it
)
2493 NL3D::CTransformShape
*trShape
= (*it
)->TransformShape
;
2494 if (dynamic_cast<NL3D::CMeshBaseInstance
*>(trShape
))
2496 static_cast<NL3D::CMeshBaseInstance
*>(trShape
)->selectTextureSet(rand() % 8);
2502 // ***************************************************************************
2504 void CObjectViewer::removeAllInstancesFromScene()
2506 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2508 // Remove all stand alone TransformShapes.
2509 for(uint instance
=0; instance
<_ListInstance
.size(); instance
++)
2511 delete _ListInstance
[instance
];
2514 // Remove all stand alone TransformShapes.
2515 _ListInstance
.clear();
2517 _CurrentCamera
= -1;
2518 _SelectedObject
= 0xffffffff;
2520 // Remove added/loaded igs and their instances.
2521 for(uint igId
=0; igId
<_ListIG
.size(); igId
++)
2523 // remove instances.
2524 _ListIG
[igId
]->removeFromScene(*CNELU::Scene
);
2526 delete _ListIG
[igId
];
2530 // clear dynamic lighting test
2531 _GlobalRetriever
= NULL
;
2532 CNELU::Scene
->deleteInstance(_ObjectLightTest
);
2533 _ObjectLightTest
= NULL
;
2536 CNELU::ShapeBank
->reset();
2538 // Invalidate dialogs
2539 if (CNELU::Driver
->isActive())
2541 _AnimationSetDlg
->refresh (TRUE
);
2542 _SlotDlg
->refresh (TRUE
);
2543 _SoundAnimDlg
->refresh (TRUE
);
2546 // remove any skeleton edited
2547 if(_InstanceRunning
)
2548 _SkeletonScaleDlg
->setSkeletonToEdit(NULL
, "");
2552 // ***************************************************************************
2553 void CObjectViewer::enableFXs(bool enabled
)
2556 for(uint instance
=0; instance
<_ListInstance
.size(); instance
++)
2558 NL3D::CSegRemanence
*sr
= dynamic_cast<NL3D::CSegRemanence
*>(_ListInstance
[instance
]->TransformShape
);
2561 if (enabled
) sr
->start();
2565 // remanences in igs
2566 for(uint igId
= 0; igId
< _ListIG
.size(); ++igId
)
2568 for(uint k
= 0; k
< _ListIG
[igId
]->_Instances
.size(); ++k
)
2570 NL3D::CSegRemanence
*sr
= dynamic_cast<NL3D::CSegRemanence
*>(_ListIG
[igId
]->_Instances
[k
]);
2573 if (enabled
) sr
->start();
2580 // ***************************************************************************
2582 void CObjectViewer::evalSoundTrack (float lastTime
, float currentTime
)
2585 for (uint i
= 0; i
< _ListInstance
.size(); i
++)
2587 // Some animation in the list ?
2588 if (!_ListInstance
[i
]->Saved
.PlayList
.empty())
2591 float startTime
= 0;
2594 // Get start time of the animation that starts before the current time
2595 for (uint index
= 0; index
< _ListInstance
[i
]->Saved
.PlayList
.size(); index
++)
2597 // Pointer on the animation
2598 string
& name
= _ListInstance
[i
]->Saved
.PlayList
[index
];
2599 CAnimation
*anim
= _ListInstance
[i
]->AnimationSet
.getAnimation (_ListInstance
[i
]->AnimationSet
.getAnimationIdByName(name
));
2602 startTime
= endTime
;
2603 endTime
= startTime
+ anim
->getEndTime()-anim
->getBeginTime();
2605 if ((startTime
<= currentTime
) && (currentTime
< endTime
))
2607 // setup the sound context
2609 DWORD tab
[] = {IDC_ARG0
, IDC_ARG1
, IDC_ARG2
, IDC_ARG3
, };
2611 for (uint i
= 0; i
< 4; i
++)
2613 CEdit
*edit
= (CEdit
*) _SoundAnimDlg
->GetDlgItem(tab
[i
]);
2616 edit
->GetLine(0, str
, 1024);
2617 SoundContext
.Args
[i
] = _ttoi (str
);
2620 // get the position of the skel if a skel is available
2621 if (SkeletonUsedForSound
!= 0xFFFFFFFF)
2623 const CMatrix
&m
= _ListInstance
[SkeletonUsedForSound
]->TransformShape
->getMatrix();
2624 SoundContext
.Position
= m
.getPos();
2628 SoundContext
.Position
= CVector::Null
;
2631 CSoundSystem::playAnimation(name
, lastTime
- startTime
, currentTime
- startTime
, SoundContext
);
2638 // ***************************************************************************
2641 void CObjectViewer::evalSoundTrack (float lastTime, float currentTime)
2643 if (lastTime!=currentTime)
2646 for (uint instance=0; instance<_ListInstance.size(); instance++)
2648 // For each channel of the mixer
2649 for (uint slot=0; slot<CChannelMixer::NumAnimationSlot; slot++)
2652 uint animId=_ListInstance[instance]->Playlist.getAnimation (slot);
2655 if (animId!=CAnimationPlaylist::empty)
2657 // Get the animation
2658 CAnimation *anim=_ListInstance[instance]->AnimationSet.getAnimation (animId);
2661 // Get the sound track
2662 uint trackId=anim->getIdTrackByName ("NoteTrack");
2663 if (trackId!=CAnimation::NotFound)
2666 ITrack *track=anim->getTrack (trackId);
2670 UTrackKeyframer *soundTrackKF = dynamic_cast<UTrackKeyframer *>(track);
2674 std::vector<TAnimationTime> result;
2676 // Get local begin and endTime
2677 TAnimationTime localLastTime = _ListInstance[instance]->Playlist.getLocalTime (slot, lastTime, _ListInstance[instance]->AnimationSet);
2678 TAnimationTime localCurrentTime = _ListInstance[instance]->Playlist.getLocalTime (slot, currentTime, _ListInstance[instance]->AnimationSet);
2681 if (localLastTime<=localCurrentTime)
2683 // Get keys in this interval
2684 soundTrackKF->getKeysInRange(localLastTime, localCurrentTime, result);
2688 // Get begin and last time
2689 TAnimationTime beginTime=track->getBeginTime ();
2690 TAnimationTime endTime=track->getEndTime ();
2692 // Time must have been clamped
2693 nlassert (localCurrentTime<=endTime);
2694 nlassert (localLastTime>=beginTime);
2696 // Get keys to the end
2697 soundTrackKF->getKeysInRange(localCurrentTime, endTime, result);
2699 // Get keys at the beginning
2700 soundTrackKF->getKeysInRange(beginTime, localLastTime, result);
2704 NLSOUND::UAudioMixer *audioMixer = CSoundSystem::getAudioMixer ();
2707 vector<TAnimationTime>::iterator itResult;
2708 for( itResult = result.begin(); itResult != result.end(); ++itResult )
2711 double keyTime = *itResult;
2712 nlinfo("keyTime = %f result size : %d",*itResult,result.size());
2714 if( !track->interpolate( *itResult, soundName) )
2716 nlwarning("The key at offset %f is not a string",*itResult);
2720 // if there are step sounds
2721 if( soundName == "step" )
2723 // need to spawn a sound linked to the anim
2724 string dummySound = "PAShommecourseappartdur1a";
2725 USource *source = audioMixer->createSource (dummySound.c_str() , true );
2728 source->setPos (CVector::Null);
2730 nlinfo ("launching dummy sound %s for the step event", dummySound.c_str());
2734 nlwarning ("sound not found for the step event: '%s'", dummySound.c_str());
2737 else if (soundName.find ("snd_") != string::npos)
2739 // need to spawn a sound linked to the anim
2740 USource *source = audioMixer->createSource ( soundName.c_str(), true );
2743 source->setPos (CVector::Null);
2745 nlinfo ("launching sound for anim event from notetrack '%s'", soundName.c_str());
2749 nlwarning ("sound not found: '%s'", soundName.c_str());
2754 nlwarning ("unknown notetrack event: '%s'", soundName.c_str());
2769 // ***************************************************************************
2770 uint
CObjectViewer::addInstanceGroup(NL3D::CInstanceGroup
*ig
)
2773 uint first
= (uint
)_ListInstance
.size();
2775 // Add all models to the scene
2776 ig
->addToScene(*CNELU::Scene
, CNELU::Driver
);
2777 // Unfreeze all objects from HRC.
2780 // link the root of the IG to our root, for scene rotation
2781 ig
->linkRoot(*CNELU::Scene
, _SceneRoot
);
2783 // Keep a reference on them, but they'll be destroyed by IG.
2784 for (uint k
= 0; k
< ig
->getNumInstance(); ++k
)
2786 CInstanceInfo
*iInfo
= new CInstanceInfo
;
2787 iInfo
->TransformShape
= ig
->_Instances
[k
];
2788 iInfo
->Saved
.ShapeFilename
= ig
->_InstancesInfos
[k
].Name
;
2789 iInfo
->MustDelete
= false;
2790 _ListInstance
.push_back (iInfo
);
2793 // Add the ig to the list.
2794 _ListIG
.push_back(ig
);
2796 // Return first instance
2800 // ***************************************************************************
2801 void CObjectViewer::setupSceneLightingSystem(bool enable
, const NLMISC::CVector
&sunDir
, NLMISC::CRGBA sunAmbiant
, NLMISC::CRGBA sunDiffuse
, NLMISC::CRGBA sunSpecular
)
2803 CNELU::Scene
->enableLightingSystem(enable
);
2806 CNELU::Scene
->setSunAmbient(sunAmbiant
);
2807 CNELU::Scene
->setSunDiffuse(sunDiffuse
);
2808 CNELU::Scene
->setSunSpecular(sunSpecular
);
2809 CNELU::Scene
->setSunDirection(sunDir
);
2813 // ***************************************************************************
2814 void CObjectViewer::enableDynamicObjectLightingTest(NLPACS::CGlobalRetriever
*globalRetriever
, NL3D::CInstanceGroup
*ig
)
2816 AFX_MANAGE_STATE(AfxGetStaticModuleState());
2818 // first delete the instance
2819 if(_ObjectLightTest
)
2821 CNELU::Scene
->deleteInstance(_ObjectLightTest
);
2822 _ObjectLightTest
= NULL
;
2825 _GlobalRetriever
= globalRetriever
;
2828 if(_GlobalRetriever
)
2832 // this mesh is the dynamic one to move around.
2833 _ObjectLightTest
= CNELU::Scene
->createInstance(_ObjectLightTestShape
);
2834 if(_ObjectLightTest
!=NULL
)
2836 // link to the root for manipulation
2837 _SceneRoot
->hrcLinkSon(_ObjectLightTest
);
2839 // setup the matrix.
2840 _ObjectLightTestMatrix
= _ObjectLightTest
->getMatrix();
2841 // setup the logic info.
2842 _ObjectLightTestLogicInfo
.GlobalRetriever
= _GlobalRetriever
;
2843 _ObjectLightTestLogicInfo
.Ig
= ig
;
2844 // Default the GPos to uninitialized
2845 _ObjectLightTestLogicInfo
.GPos
.InstanceId
= -1;
2846 _ObjectLightTest
->setLogicInfo(&_ObjectLightTestLogicInfo
);
2850 if (!_ObjectLightTestShape
.empty())
2852 string str
= string("Path not found for Light Test Shape: ") + _ObjectLightTestShape
;
2853 ::MessageBox(NULL
, nlUtf8ToTStr(str
.c_str()), _T("Dynamic Object Light Test"), MB_OK
| MB_ICONEXCLAMATION
);
2856 _ObjectLightTest
= NULL
;
2857 _GlobalRetriever
= NULL
;
2863 // ***************************************************************************
2864 void CObjectViewer::COVLogicInfo::getStaticLightSetup(NLMISC::CRGBA sunAmbient
, std::vector
<CPointLightInfluence
> &pointLightList
, uint8
&sunContribution
, CRGBA
&ambient
)
2866 Ig
->getStaticLightSetup(sunAmbient
, GlobalRetriever
->getLocalRetrieverId(GPos
),
2867 GPos
.LocalPosition
.Surface
,
2868 GPos
.LocalPosition
.Estimation
,
2869 pointLightList
, sunContribution
, ambient
);
2873 // ***************************************************************************
2874 // ***************************************************************************
2875 // Vegetable Landscape Part.
2876 // ***************************************************************************
2877 // ***************************************************************************
2880 // ***************************************************************************
2881 void CObjectViewer::loadVegetableLandscapeCfg(NLMISC::CConfigFile
&cf
)
2883 // vegetable display is true by default.
2884 _VegetableEnabled
= true;
2885 _VegetableSnapToGround
= true;
2888 // Load landscape setup
2893 CConfigFile::CVar
&tileBank
= cf
.getVar("veget_tile_bank");
2894 _VegetableLandscapeTileBank
= tileBank
.asString();
2895 CConfigFile::CVar
&tileFarBank
= cf
.getVar("veget_tile_far_bank");
2896 _VegetableLandscapeTileFarBank
= tileFarBank
.asString();
2898 _VegetableLandscapeZoneNames
.clear();
2899 CConfigFile::CVar
&zones
= cf
.getVar("veget_landscape_zones");
2900 for (uint i
=0; i
<(uint
)zones
.size(); i
++)
2901 _VegetableLandscapeZoneNames
.push_back(zones
.asString(i
).c_str());
2903 catch (const EUnknownVar
&)
2905 _VegetableLandscapeTileBank
.clear();
2906 _VegetableLandscapeTileFarBank
.clear();
2907 _VegetableLandscapeZoneNames
.clear();
2911 // Load Landscape params.
2916 CConfigFile::CVar
&thre
= cf
.getVar("veget_landscape_threshold");
2917 _VegetableLandscapeThreshold
= thre
.asFloat();
2918 // clamp to avoid divide/0.
2919 _VegetableLandscapeThreshold
= max(_VegetableLandscapeThreshold
, 0.001f
);
2921 catch (const EUnknownVar
&)
2923 _VegetableLandscapeThreshold
= 0.003f
;
2928 CConfigFile::CVar
&tileNear
= cf
.getVar("veget_landscape_tile_near");
2929 _VegetableLandscapeTileNear
= tileNear
.asFloat();
2931 catch (const EUnknownVar
&)
2933 _VegetableLandscapeTileNear
= 50;
2938 CConfigFile::CVar
&color
= cf
.getVar("veget_landscape_ambient");
2939 _VegetableLandscapeAmbient
.R
= color
.asInt(0);
2940 _VegetableLandscapeAmbient
.G
= color
.asInt(1);
2941 _VegetableLandscapeAmbient
.B
= color
.asInt(2);
2943 catch (const EUnknownVar
&)
2945 _VegetableLandscapeAmbient
.set(80, 80, 80);
2950 CConfigFile::CVar
&color
= cf
.getVar("veget_landscape_diffuse");
2951 _VegetableLandscapeDiffuse
.R
= color
.asInt(0);
2952 _VegetableLandscapeDiffuse
.G
= color
.asInt(1);
2953 _VegetableLandscapeDiffuse
.B
= color
.asInt(2);
2955 catch (const EUnknownVar
&)
2957 _VegetableLandscapeDiffuse
.set(255, 255, 255);
2962 CConfigFile::CVar
&var
= cf
.getVar("veget_landscape_snap_height");
2963 _VegetableSnapHeight
= var
.asFloat();
2965 catch (const EUnknownVar
&)
2967 _VegetableSnapHeight
= 1.70f
;
2971 // Load Vegetable params.
2974 // vegetable texture
2977 CConfigFile::CVar
&var
= cf
.getVar("veget_texture");
2978 _VegetableTexture
= var
.asString();
2980 catch (const EUnknownVar
&)
2982 _VegetableTexture
.clear();
2985 // vegetable ambient
2988 CConfigFile::CVar
&color
= cf
.getVar("veget_ambient");
2989 _VegetableAmbient
.R
= color
.asInt(0);
2990 _VegetableAmbient
.G
= color
.asInt(1);
2991 _VegetableAmbient
.B
= color
.asInt(2);
2993 catch (const EUnknownVar
&)
2995 _VegetableAmbient
.set(80, 80, 80);
2997 // vegetable diffuse
3000 CConfigFile::CVar
&color
= cf
.getVar("veget_diffuse");
3001 // setup to behave correclty ie as maxLightFactor:
3002 sint R
= color
.asInt(0) - _VegetableAmbient
.R
; clamp(R
, 0, 255); _VegetableDiffuse
.R
= R
;
3003 sint G
= color
.asInt(1) - _VegetableAmbient
.G
; clamp(G
, 0, 255); _VegetableDiffuse
.G
= G
;
3004 sint B
= color
.asInt(2) - _VegetableAmbient
.B
; clamp(B
, 0, 255); _VegetableDiffuse
.B
= B
;
3006 catch (const EUnknownVar
&)
3008 sint R
= 255 - _VegetableAmbient
.R
; clamp(R
, 0, 255); _VegetableDiffuse
.R
= R
;
3009 sint G
= 255 - _VegetableAmbient
.G
; clamp(G
, 0, 255); _VegetableDiffuse
.G
= G
;
3010 sint B
= 255 - _VegetableAmbient
.B
; clamp(B
, 0, 255); _VegetableDiffuse
.B
= B
;
3012 // vegetable lightDir
3015 CConfigFile::CVar
&var
= cf
.getVar("veget_light_dir");
3016 _VegetableLightDir
.x
= var
.asFloat(0);
3017 _VegetableLightDir
.y
= var
.asFloat(1);
3018 _VegetableLightDir
.z
= var
.asFloat(2);
3019 _VegetableLightDir
.normalize();
3021 catch (const EUnknownVar
&)
3023 _VegetableLightDir
.set(0, 1, -1);
3024 _VegetableLightDir
.normalize();
3030 CConfigFile::CVar
&var
= cf
.getVar("veget_wind_dir");
3031 _VegetableWindDir
.x
= var
.asFloat(0);
3032 _VegetableWindDir
.y
= var
.asFloat(1);
3033 _VegetableWindDir
.z
= var
.asFloat(2);
3035 catch (const EUnknownVar
&)
3037 _VegetableWindDir
.x
= 0.5f
;
3038 _VegetableWindDir
.y
= 0.5f
;
3039 _VegetableWindDir
.z
= 0;
3044 CConfigFile::CVar
&var
= cf
.getVar("veget_wind_freq");
3045 _VegetableWindFreq
= var
.asFloat();
3047 catch (const EUnknownVar
&)
3049 _VegetableWindFreq
= 0.5;
3054 CConfigFile::CVar
&var
= cf
.getVar("veget_wind_power");
3055 _VegetableWindPower
= var
.asFloat();
3057 catch (const EUnknownVar
&)
3059 _VegetableWindPower
= 1;
3064 CConfigFile::CVar
&var
= cf
.getVar("veget_wind_bend_min");
3065 _VegetableWindBendMin
= var
.asFloat();
3067 catch (const EUnknownVar
&)
3069 _VegetableWindBendMin
= 0;
3076 // ***************************************************************************
3077 bool CObjectViewer::createVegetableLandscape()
3079 // If not already done.
3080 if(!_VegetableLandscape
)
3082 // create the landscape.
3083 _VegetableLandscape
= static_cast<CLandscapeModel
*>(CNELU::Scene
->createModel(LandscapeModelId
));
3085 // Create a Progress Dialog.
3086 CDialogProgress dlgProgress
;
3087 dlgProgress
.Create(CDialogProgress::IDD
, _MainFrame
);
3088 dlgProgress
.ShowWindow(true);
3092 if(_VegetableLandscapeTileBank
.empty())
3094 throw Exception("Landscape CFG not fully defined");
3097 // Load The Bank files (copied from CLandscapeUser :) ).
3100 dlgProgress
.ProgressText
.SetWindowText(_T("Loading TileBanks..."));
3101 dlgProgress
.ProgressBar
.SetPos(0);
3103 CIFile
bankFile(CPath::lookup(_VegetableLandscapeTileBank
));
3104 _VegetableLandscape
->Landscape
.TileBank
.serial(bankFile
);
3105 _VegetableLandscape
->Landscape
.TileBank
.makeAllPathRelative();
3106 _VegetableLandscape
->Landscape
.TileBank
.makeAllExtensionDDS();
3107 _VegetableLandscape
->Landscape
.TileBank
.setAbsPath ("");
3110 dlgProgress
.ProgressBar
.SetPos(50);
3112 CIFile
farbankFile(CPath::lookup(_VegetableLandscapeTileFarBank
));
3113 _VegetableLandscape
->Landscape
.TileFarBank
.serial(farbankFile
);
3114 if ( ! _VegetableLandscape
->Landscape
.initTileBanks() )
3116 nlwarning( "You need to recompute bank.farbank for the far textures" );
3119 farbankFile
.close();
3127 dlgProgress
.ProgressText
.SetWindowText(_T("Loading Tiles..."));
3128 dlgProgress
.ProgressBar
.SetPos(0);
3130 // count nbText to load.
3132 sint nbTextTotal
= 0;
3133 for (ts
=0; ts
<_VegetableLandscape
->Landscape
.TileBank
.getTileSetCount (); ts
++)
3135 CTileSet
*tileSet
=_VegetableLandscape
->Landscape
.TileBank
.getTileSet (ts
);
3136 nbTextTotal
+= tileSet
->getNumTile128();
3137 nbTextTotal
+= tileSet
->getNumTile256();
3138 nbTextTotal
+= CTileSet::count
;
3143 for (ts
=0; ts
<_VegetableLandscape
->Landscape
.TileBank
.getTileSetCount (); ts
++)
3145 CTileSet
*tileSet
=_VegetableLandscape
->Landscape
.TileBank
.getTileSet (ts
);
3147 for (tl
=0; tl
<tileSet
->getNumTile128(); tl
++, nbTextDone
++)
3149 _VegetableLandscape
->Landscape
.flushTiles (CNELU::Driver
, (uint16
)tileSet
->getTile128(tl
), 1);
3150 dlgProgress
.ProgressBar
.SetPos(nbTextDone
*100/nbTextTotal
);
3152 for (tl
=0; tl
<tileSet
->getNumTile256(); tl
++, nbTextDone
++)
3154 _VegetableLandscape
->Landscape
.flushTiles (CNELU::Driver
, (uint16
)tileSet
->getTile256(tl
), 1);
3155 dlgProgress
.ProgressBar
.SetPos(nbTextDone
*100/nbTextTotal
);
3157 for (tl
=0; tl
<CTileSet::count
; tl
++, nbTextDone
++)
3159 _VegetableLandscape
->Landscape
.flushTiles (CNELU::Driver
, (uint16
)tileSet
->getTransition(tl
)->getTile (), 1);
3160 dlgProgress
.ProgressBar
.SetPos(nbTextDone
*100/nbTextTotal
);
3168 _VegetableLandscape
->Landscape
.setThreshold(_VegetableLandscapeThreshold
);
3169 _VegetableLandscape
->Landscape
.setTileNear(_VegetableLandscapeTileNear
);
3170 _VegetableLandscape
->Landscape
.setupStaticLight(_VegetableLandscapeDiffuse
, _VegetableLandscapeAmbient
, 1);
3171 _VegetableLandscape
->Landscape
.loadVegetableTexture(_VegetableTexture
);
3172 _VegetableLandscape
->Landscape
.setupVegetableLighting(_VegetableAmbient
, _VegetableDiffuse
, _VegetableLightDir
);
3173 _VegetableLandscape
->Landscape
.setVegetableWind(_VegetableWindDir
, _VegetableWindFreq
, _VegetableWindPower
, _VegetableWindBendMin
);
3178 // landscape recentering.
3179 bool zoneLoaded
= false;
3180 CAABBox landscapeBBox
;
3182 dlgProgress
.ProgressText
.SetWindowText(_T("Loading Zones..."));
3183 dlgProgress
.ProgressBar
.SetPos(0);
3184 uint nbZones
= (uint
)_VegetableLandscapeZoneNames
.size();
3185 for(uint i
=0; i
<nbZones
;i
++)
3188 CIFile
zoneFile(CPath::lookup(_VegetableLandscapeZoneNames
[i
]));
3191 zoneFile
.serial(zone
);
3192 // append to landscape
3193 _VegetableLandscape
->Landscape
.addZone(zone
);
3195 dlgProgress
.ProgressBar
.SetPos(i
*100/nbZones
);
3201 landscapeBBox
.setCenter(zone
.getZoneBB().getCenter());
3204 landscapeBBox
.extend(zone
.getZoneBB().getCenter());
3207 // After All zone loaded, recenter the mouse listener on the landscape.
3211 _MouseListener
.setHotSpot(landscapeBBox
.getCenter());
3212 matrix
.setPos(landscapeBBox
.getCenter());
3213 matrix
.rotateX(-(float)Pi
/4);
3214 matrix
.translate(CVector(0,-1000,0));
3215 _MouseListener
.setMatrix(matrix
);
3218 // Create collisions objects.
3219 _VegetableCollisionManager
= new CVisualCollisionManager
;
3220 _VegetableCollisionManager
->setLandscape(&_VegetableLandscape
->Landscape
);
3221 _VegetableCollisionEntity
= _VegetableCollisionManager
->createEntity();
3223 catch (const Exception
&e
)
3225 // close the progress dialog
3226 dlgProgress
.DestroyWindow();
3228 MessageBox(_MainFrame
->m_hWnd
, nlUtf8ToTStr(e
.what()), _T("Failed to Load landscape"), MB_OK
| MB_APPLMODAL
);
3230 // remove first possibly created collisions objects.
3231 if(_VegetableCollisionEntity
)
3233 _VegetableCollisionManager
->deleteEntity(_VegetableCollisionEntity
);
3234 _VegetableCollisionEntity
= NULL
;
3236 if(_VegetableCollisionManager
)
3238 delete _VegetableCollisionManager
;
3239 _VegetableCollisionManager
= NULL
;
3242 // remove the landscape
3243 CNELU::Scene
->deleteModel(_VegetableLandscape
);
3244 _VegetableLandscape
= NULL
;
3249 // close the progress dialog
3250 dlgProgress
.DestroyWindow();
3257 // ***************************************************************************
3258 void CObjectViewer::showVegetableLandscape()
3260 if(_VegetableLandscape
)
3262 _VegetableLandscape
->show();
3266 // ***************************************************************************
3267 void CObjectViewer::hideVegetableLandscape()
3269 if(_VegetableLandscape
)
3271 _VegetableLandscape
->hide();
3276 // ***************************************************************************
3277 void CObjectViewer::enableLandscapeVegetable(bool enable
)
3280 _VegetableEnabled
= enable
;
3283 if(_VegetableLandscape
)
3285 _VegetableLandscape
->Landscape
.enableVegetable(_VegetableEnabled
);
3290 // ***************************************************************************
3291 void CObjectViewer::refreshVegetableLandscape(const NL3D::CTileVegetableDesc
&tvdesc
)
3293 // if landscape is displayed.
3294 if(_VegetableLandscape
)
3296 // first disable the vegetable, to delete any vegetation
3297 _VegetableLandscape
->Landscape
.enableVegetable(false);
3299 // Then change all the tileSet of all the TileBanks.
3300 for (sint ts
=0; ts
<_VegetableLandscape
->Landscape
.TileBank
.getTileSetCount (); ts
++)
3302 CTileSet
*tileSet
=_VegetableLandscape
->Landscape
.TileBank
.getTileSet (ts
);
3303 // change the vegetableTileDesc of this tileSet.
3304 tileSet
->setTileVegetableDesc(tvdesc
);
3307 // re-Enable the vegetable (if wanted).
3308 _VegetableLandscape
->Landscape
.enableVegetable(_VegetableEnabled
);
3313 // ***************************************************************************
3314 void CObjectViewer::setVegetableWindPower(float w
)
3316 _VegetableWindPower
= w
;
3317 if(_VegetableLandscape
)
3318 _VegetableLandscape
->Landscape
.setVegetableWind(_VegetableWindDir
, _VegetableWindFreq
, _VegetableWindPower
, _VegetableWindBendMin
);
3320 // ***************************************************************************
3321 void CObjectViewer::setVegetableWindBendStart(float w
)
3323 _VegetableWindBendMin
= w
;
3324 if(_VegetableLandscape
)
3325 _VegetableLandscape
->Landscape
.setVegetableWind(_VegetableWindDir
, _VegetableWindFreq
, _VegetableWindPower
, _VegetableWindBendMin
);
3327 // ***************************************************************************
3328 void CObjectViewer::setVegetableWindFrequency(float w
)
3330 _VegetableWindFreq
= w
;
3331 if(_VegetableLandscape
)
3332 _VegetableLandscape
->Landscape
.setVegetableWind(_VegetableWindDir
, _VegetableWindFreq
, _VegetableWindPower
, _VegetableWindBendMin
);
3336 // ***************************************************************************
3337 void CObjectViewer::snapToGroundVegetableLandscape(bool enable
)
3340 _VegetableSnapToGround
= enable
;
3343 // ***************************************************************************
3344 CInstanceInfo::CInstanceInfo ()
3346 TransformShape
= NULL
;
3351 // ***************************************************************************
3352 CInstanceInfo::~CInstanceInfo ()
3357 CNELU::Scene
->deleteInstance (TransformShape
);
3359 CNELU::Scene
->deleteModel (Camera
);
3363 // ***************************************************************************
3364 CSlotInfo::CSlotInfo ()
3374 SkeletonInverted
= false;
3378 // ***************************************************************************
3379 void CSlotInfo::serial (NLMISC::IStream
&f
)
3381 f
.serialVersion (0);
3382 f
.serial (Animation
);
3383 f
.serial (Skeleton
);
3385 f
.serial (StartTime
);
3387 f
.serial (StartBlend
);
3388 f
.serial (EndBlend
);
3389 f
.serial (Smoothness
);
3390 f
.serial (SpeedFactor
);
3391 f
.serial (ClampMode
);
3392 f
.serial (SkeletonInverted
);
3396 // ***************************************************************************
3397 uint
CObjectViewer::getEditedObject ()
3399 return _SelectedObject
;
3402 // ***************************************************************************
3403 void CObjectViewer::setEditedObject (uint selected
)
3405 _SelectedObject
=selected
;
3408 // ***************************************************************************
3409 CInstanceInfo
*CObjectViewer::getInstance (uint instance
)
3411 return _ListInstance
[instance
];
3414 // ***************************************************************************
3415 uint
CObjectViewer::getNumInstance () const
3417 return (uint
)_ListInstance
.size ();
3420 // ***************************************************************************
3421 void CInstanceInfo::setAnimationPlaylist (float frameRate
)
3423 for (uint id
=0; id
<NL3D::CChannelMixer::NumAnimationSlot
; id
++)
3425 if (Saved
.SlotInfo
[id
].Enable
)
3427 // Set the animation
3428 uint animId
= AnimationSet
.getAnimationIdByName (Saved
.SlotInfo
[id
].Animation
);
3429 if (animId
== CAnimationSet::NotFound
)
3430 Playlist
.setAnimation (id
, CAnimationPlaylist::empty
);
3432 Playlist
.setAnimation (id
, animId
);
3434 // Set the skeleton weight
3435 uint skelId
= AnimationSet
.getSkeletonWeightIdByName (Saved
.SlotInfo
[id
].Skeleton
);
3436 if (skelId
== CAnimationSet::NotFound
)
3437 Playlist
.setSkeletonWeight (id
, CAnimationPlaylist::empty
, false);
3439 Playlist
.setSkeletonWeight (id
, skelId
, Saved
.SlotInfo
[id
].SkeletonInverted
);
3441 // Set others values
3442 Playlist
.setTimeOrigin (id
, Saved
.SlotInfo
[id
].Offset
/frameRate
);
3443 Playlist
.setSpeedFactor (id
, Saved
.SlotInfo
[id
].SpeedFactor
);
3444 Playlist
.setStartWeight (id
, Saved
.SlotInfo
[id
].StartBlend
, Saved
.SlotInfo
[id
].StartTime
/frameRate
);
3445 Playlist
.setEndWeight (id
, Saved
.SlotInfo
[id
].EndBlend
, Saved
.SlotInfo
[id
].EndTime
/frameRate
);
3446 Playlist
.setWeightSmoothness (id
, Saved
.SlotInfo
[id
].Smoothness
);
3448 // Switch between wrap modes
3449 switch (Saved
.SlotInfo
[id
].ClampMode
)
3452 Playlist
.setWrapMode (id
, CAnimationPlaylist::Clamp
);
3455 Playlist
.setWrapMode (id
, CAnimationPlaylist::Repeat
);
3458 Playlist
.setWrapMode (id
, CAnimationPlaylist::Disable
);
3465 // ***************************************************************************
3466 CInstanceSave::CInstanceSave ()
3468 SkeletonId
= 0xffffffff;
3473 // ***************************************************************************
3474 void CInstanceSave::serial (NLMISC::IStream
&f
)
3477 sint ver
= f
.serialVersion (1);
3479 // Play list of this object
3480 f
.serialCont (PlayList
);
3482 // Slot info for this object
3483 nlassert (NL3D::CChannelMixer::NumAnimationSlot
== 8);
3484 for (uint slot
=0; slot
<8; slot
++)
3485 // Serial the slot information
3486 f
.serial (SlotInfo
[slot
]);
3489 f
.serial (ShapeFilename
);
3492 f
.serial (SkeletonId
);
3495 f
.serial (BindBoneName
);
3498 f
.serial (IsSkeleton
);
3500 // Animation input file
3501 f
.serialCont (AnimationFileName
);
3503 // Skeleton weight input file
3504 f
.serialCont (SWTFileName
);
3510 f
.serial (CameraInfo
);
3512 else if (f
.isReading ())
3516 // ***************************************************************************
3517 void CObjectViewer::refreshAnimationListeners()
3519 _SoundAnimDlg
->refresh (TRUE
);
3522 // ***************************************************************************
3523 void CObjectViewer::addAnimation(NL3D::CAnimation
* anim
, const std::string
&filename
, const std::string
&name
, uint instance
)
3526 uint id
= _ListInstance
[instance
]->AnimationSet
.addAnimation (name
.c_str(), anim
);
3527 _ListInstance
[instance
]->Saved
.AnimationFileName
.push_back (filename
);
3529 // Rebuild the animationSet
3530 _ListInstance
[instance
]->AnimationSet
.build ();
3531 if(CNELU::Driver
&& CNELU::ShapeBank
)
3533 _ListInstance
[instance
]->AnimationSet
.preloadSSSShapes(*CNELU::Driver
, *CNELU::ShapeBank
);
3536 _SoundAnimDlg
->refresh (TRUE
);
3539 // ***************************************************************************
3540 void CObjectViewer::loadAnimation(const std::string
&fileName
, uint instance
)
3544 if (file
.open (fileName
))
3546 // Get the animation name
3547 std::string name
= NLMISC::CFile::getFilenameWithoutExtension(fileName
);
3549 // Make an animation
3550 CAnimation
*anim
=new CAnimation
;
3553 anim
->serial (file
);
3555 // Add the animation
3556 addAnimation (anim
, fileName
, name
, instance
);
3561 std::string msg
= NLMISC::toString("Can't open the file %s for reading.", fileName
.c_str());
3562 _MainFrame
->MessageBox(nlUtf8ToTStr(msg
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
3566 // ***************************************************************************
3567 void CObjectViewer::loadSWT (const std::string
&fileName
, uint instance
)
3571 if (file
.open (fileName
))
3573 // Get the animation name
3574 std::string name
= NLMISC::CFile::getFilenameWithoutExtension(fileName
);
3576 // Get the skeleton pointer
3577 CSkeletonWeight
* skel
=new CSkeletonWeight
;
3580 skel
->serial (file
);
3583 _ListInstance
[instance
]->AnimationSet
.addSkeletonWeight (name
.c_str(), skel
);
3585 // Add the filename in the list
3586 _ListInstance
[instance
]->Saved
.SWTFileName
.push_back (fileName
);
3591 std::string msg
= NLMISC::toString("Can't open the file %s for reading.", fileName
.c_str());
3592 _MainFrame
->MessageBox(nlUtf8ToTStr(msg
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
3596 // ***************************************************************************
3597 CMainDlg
*CObjectViewer::getSlotDlg ()
3602 // ***************************************************************************
3603 void CObjectViewer::reloadTextures ()
3605 // For each instances
3606 uint numInstance
= getNumInstance ();
3608 for (instance
=0; instance
<numInstance
; instance
++)
3611 CInstanceInfo
*info
= getInstance (instance
);
3613 // For each material
3614 if (info
->TransformShape
)
3616 uint numMaterial
= info
->TransformShape
->getNumMaterial ();
3618 for (mat
=0; mat
<numMaterial
; mat
++)
3621 CMaterial
*material
= info
->TransformShape
->getMaterial (mat
);
3625 for (tex
=0; tex
<IDRV_MAT_MAXTEXTURES
; tex
++)
3627 ITexture
*texture
= material
->getTexture (tex
);
3632 CNELU::Driver
->invalidateShareTexture (*texture
);
3640 // ***************************************************************************
3641 // ***************************************************************************
3642 // Global wind part.
3643 // ***************************************************************************
3644 // ***************************************************************************
3647 // ***************************************************************************
3648 void CObjectViewer::setGlobalWindPower(float w
)
3653 _MainFrame
->GlobalWindPower
= w
;
3654 CNELU::Scene
->setGlobalWindPower(w
);
3659 // ***************************************************************************
3660 float CObjectViewer::getGlobalWindPower() const
3663 return _MainFrame
->GlobalWindPower
;
3669 void CObjectViewer::shootScene()
3671 static const TCHAR BASED_CODE szFilter
[] = _T("PNG Files (*.png)|*.png|Targa Files (*.tga)|*.tga|Jpeg Files (*.jpg)|*.jpg|All Files (*.*)|*.*||");
3672 CFileDialog
fileDlg ( FALSE
, _T(".tga"), _T("*.tga"), OFN_HIDEREADONLY
|OFN_OVERWRITEPROMPT
, szFilter
);
3673 if (fileDlg
.DoModal () == IDOK
)
3676 CSelectMovieSize movieSize
;
3677 if (movieSize
.DoModal () == IDOK
)
3679 // Resize the window
3681 _MainFrame
->GetWindowRect (&window
);
3684 CNELU::Driver
->getWindowSize (width
, height
);
3685 window
.right
+= movieSize
.Width
- width
;
3686 window
.bottom
+= movieSize
.Height
- height
;
3687 _MainFrame
->SetWindowPos (NULL
, 0, 0, window
.right
-window
.left
, window
.bottom
-window
.top
, SWP_NOMOVE
|SWP_NOZORDER
);
3691 CNELU::swapBuffers();
3692 CNELU::Driver
->setupViewport (CViewport ());
3695 string filename
= NLMISC::CFile::getFilenameWithoutExtension(tStrToUtf8(fileDlg
.GetPathName()));
3696 string extension
= NLMISC::CFile::getExtension (tStrToUtf8(fileDlg
.GetPathName()));
3698 // The file name without extension
3699 bool jpeg
= toLowerAscii (extension
) == "jpg";
3701 // Activate the driver
3702 CNELU::Driver
->activate ();
3705 NLMISC::CBitmap shoot
;
3709 for (i
=(sint
)_AnimationDlg
->Start
; i
<=(sint
)_AnimationDlg
->End
; i
++)
3712 _AnimationDlg
->setCurrentFrame ((float)i
);
3714 // Setup the play list
3715 setupPlaylist (_AnimationDlg
->getTime());
3717 // Animate the automatic animation in the scene
3718 animateCNELUScene (_CS
, (uint64
)(1000.f
/ _AnimationDlg
->Speed
));
3720 // Eval channel mixer for transform
3721 for (uint j
=0; j
<_ListInstance
.size(); j
++)
3722 _ListInstance
[j
]->ChannelMixer
.eval (false);
3724 // Clear the buffers
3725 CNELU::clearBuffers (_BackGroundColor
);
3727 // call of callback list
3729 std::vector
<IMainLoopCallBack
*> copyVect(_CallBackList
.begin(), _CallBackList
.end());
3730 for (std::vector
<IMainLoopCallBack
*>::iterator it
= _CallBackList
.begin(); it
!= _CallBackList
.end(); ++it
)
3732 (*it
)->goPreRender();
3736 if (_CS
) _CS
->render ();
3739 CNELU::Scene
->render();
3741 // call of callback list
3743 std::vector
<IMainLoopCallBack
*> copyVect(_CallBackList
.begin(), _CallBackList
.end());
3744 for (std::vector
<IMainLoopCallBack
*>::iterator it
= _CallBackList
.begin(); it
!= _CallBackList
.end(); ++it
)
3746 (*it
)->goPostRender();
3753 CNELU::swapBuffers();
3756 CNELU::Driver
->getBuffer (shoot
);
3761 smprintf (num
, 12, "%04d", i
);
3762 string filenamefinal
= filename
+num
+string (".")+extension
;
3765 NLMISC::COFile output
;
3766 if (output
.open (filenamefinal
))
3769 shoot
.writeJPG ( output
, 255 );
3771 shoot
.writeTGA ( output
, 32 );
3775 std::string message
= toString("Can't open the file %s for writing.", filenamefinal
.c_str());
3776 _MainFrame
->MessageBox(nlUtf8ToTStr(message
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
3780 catch (const Exception
&e
)
3782 std::string message
= toString("Error during writing of the file %s: %s", filenamefinal
.c_str(), e
.what());
3783 _MainFrame
->MessageBox(nlUtf8ToTStr(message
), _T("NeL object viewer"), MB_OK
| MB_ICONEXCLAMATION
);
3791 void CObjectViewer::drawFXUserMatrix()
3794 static std::string fxUserMatrixStr
;
3795 static bool stringRetrieved
= false;
3796 if (!stringRetrieved
)
3798 CString fxUserMatrix
;
3799 fxUserMatrix
.LoadString(IDS_FX_USER_MATRIX
);
3800 fxUserMatrixStr
= tStrToUtf8(fxUserMatrix
);
3801 stringRetrieved
= true;
3803 nlassert(_ParticleDlg
);
3804 drawNamedMatrix(getFXUserMatrix(), fxUserMatrixStr
, NLMISC::CRGBA::Red
, 0.2f
, 10.f
);
3807 void CObjectViewer::drawFXMatrix()
3809 static std::string fxStr
;
3810 static bool stringRetrieved
= false;
3811 if (!stringRetrieved
)
3814 fx
.LoadString(IDS_FX_MATRIX
);
3815 fxStr
= tStrToUtf8(fx
);
3816 stringRetrieved
= true;
3818 drawNamedMatrix(_ParticleDlg
->getPSWorldMatrix(), fxStr
, NLMISC::CRGBA::Blue
, -0.2f
, 10.f
);
3821 void CObjectViewer::drawSceneMatrix()
3823 static std::string sceneMatrixStr
;
3824 static bool stringRetrieved
= false;
3825 if (!stringRetrieved
)
3827 CString sceneMatrix
;
3828 sceneMatrix
.LoadString(IDS_SCENE_MATRIX
);
3829 sceneMatrixStr
= tStrToUtf8(sceneMatrix
);
3830 stringRetrieved
= true;
3832 drawNamedMatrix(_SceneRoot
->getMatrix(), sceneMatrixStr
, NLMISC::CRGBA::White
, 0.f
, 10.f
);
3836 void CObjectViewer::drawNamedMatrix(const NLMISC::CMatrix
&matrix
, const std::string
&name
, NLMISC::CRGBA color
, float textZOffset
, float testSize
)
3838 CPSUtil::displayBasis(CNELU::Driver
, matrix
, NLMISC::CMatrix::Identity
, 1.f
, *_FontGenerator
, _FontManager
);
3839 CPSUtil::print(CNELU::Driver
, name
, *_FontGenerator
, _FontManager
, matrix
.getPos() + NLMISC::CVector(0.f
, 0.f
, textZOffset
), testSize
, color
);
3844 sint
CObjectViewer::getCurrentCamera () const
3846 return _CurrentCamera
;
3849 void CObjectViewer::setCurrentCamera (sint currentCamera
)
3851 nlassert ((currentCamera
== -1) ||(currentCamera
< (sint
)_Cameras
.size ()));
3852 _CurrentCamera
= currentCamera
;
3855 uint
CObjectViewer::getCameraInstance (uint cameraId
) const
3857 return _Cameras
[cameraId
];
3860 uint
CObjectViewer::getNumCamera () const
3862 return (uint
)_Cameras
.size ();
3865 int localizedMessageBox(HWND parentWindow
, int messageStringID
, int captionStringID
, UINT nType
)
3869 caption
.LoadString(captionStringID
);
3870 mess
.LoadString(messageStringID
);
3871 return MessageBox(parentWindow
, (LPCTSTR
) mess
, (LPCTSTR
) caption
, nType
);
3872 // TODO : replace older call to ::MessageBox in the object viewer with that function
3875 int localizedMessageBox(HWND parentWindow
, const TCHAR
*message
, int captionStringID
, UINT nType
)
3878 caption
.LoadString(captionStringID
);
3879 return MessageBox(parentWindow
, message
, (LPCTSTR
) caption
, nType
);
3882 CString
getStrRsc(uint stringID
)
3885 str
.LoadString(stringID
);
3889 bool browseFolder(const CString
&caption
, CString
&destFolder
, HWND parent
)
3891 TCHAR chosenPath
[MAX_PATH
];
3894 bi
.hwndOwner
= parent
;
3896 bi
.pszDisplayName
= chosenPath
;
3897 bi
.lpszTitle
= (LPCTSTR
) caption
;
3898 bi
.ulFlags
= BIF_DONTGOBELOWDOMAIN
| BIF_EDITBOX
;
3902 PIDLIST_ABSOLUTE result
= SHBrowseForFolder(&bi
);
3903 if (result
!= NULL
&& SHGetPathFromIDList(result
, chosenPath
))
3905 destFolder
= chosenPath
;