1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
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/>.
21 #include "nel/misc/time_nl.h"
22 #include "nel/misc/path.h"
23 #include "nel/misc/command.h"
24 #include "nel/misc/file.h"
25 #include "nel/3d/u_camera.h"
26 #include "nel/gui/action_handler.h"
27 #include "client_cfg.h"
33 using namespace NLMISC
;
35 using namespace NLGUI
;
37 // TODO nico : that stuff was coded in a hurry, but could be good to add it to NL3D with a better packaging later...
40 //extern UCamera MainCam;
44 // state ofthe recorder
62 void serial(NLMISC::IStream
&f
)
71 bool operator<(const CSample
&lhs
, const CSample
&rhs
)
73 return lhs
.Date
< rhs
.Date
;
77 typedef std::vector
<CSample
> TTrack
;
81 static TState State
= Idle
; // current state of the camera recorder
82 static TTime TimeOrigin
= 0; // time origin for record or playback
87 bool isRecordingCamera()
89 return State
== Recording
;
93 void updateCameraRecorder()
103 sample
.Date
= CTime::getLocalTime() - TimeOrigin
;
104 //sample.Matrix = MainCam.getMatrix();
105 sample
.Pos
= View
.viewPos();
106 sample
.Heading
= View
.view();
110 Track
.push_back(sample
);
112 else if (sample
.Date
> Track
.back().Date
)
114 // push a new sample only if more recent
115 Track
.push_back(sample
);
126 TTime date
= CTime::getLocalTime() - TimeOrigin
;
129 TTrack::const_iterator it
= std::lower_bound(Track
.begin(), Track
.end(), compVal
);
130 if (it
== Track
.end())
132 //MainCam.setMatrix(Track.back().Matrix);
133 View
.viewPos(Track
.back().Pos
);
134 View
.view(Track
.back().Heading
);
138 if (it
== Track
.begin())
140 //MainCam.setMatrix(Track.back().Matrix);
141 View
.viewPos(Track
.front().Pos
);
142 View
.view(Track
.front().Heading
);
145 const CSample
&s0
= *(it
- 1);
146 const CSample
&s1
= *it
;
147 float lambda
= float(date
- s0
.Date
) / float(s1
.Date
- s0
.Date
);
152 if (ClientCfg
.CameraRecorderBlend
)
154 pos
= lambda
* s1
.Pos
+ (1.f
- lambda
) * s0
.Pos
;
155 heading
= (lambda
* s1
.Heading
+ (1.f
- lambda
) * s0
.Heading
).normed();
160 heading
= s0
.Heading
;
168 CVector pos = lambda * s1.Matrix.getPos() + (1.f - lambda) * s0.Matrix.getPos();
169 CVector I = lambda * s1.Matrix.getI() + (1.f - lambda) * s0.Matrix.getI();
171 CVector J = lambda * s1.Matrix.getJ() + (1.f - lambda) * s0.Matrix.getJ();
172 J = (J - (J * I) * I).normed();
177 UTransform::TTransformMode oldMode = MainCam.getTransformMode();
178 MainCam.setTransformMode(UTransformable::DirectMatrix);
179 MainCam.setMatrix(mat);
180 MainCam.setTransformMode(oldMode);
187 // ***************************************************************************
188 class CAHToggleCameraRecorder
: public IActionHandler
190 virtual void execute (CCtrlBase
* /* pCaller */, const string
&/* Params */)
192 if (State
== Recording
)
198 TimeOrigin
= CTime::getLocalTime();
202 // ***************************************************************************
203 REGISTER_ACTION_HANDLER (CAHToggleCameraRecorder
, "toggle_camera_recorder");
205 // ***************************************************************************
206 class CAHCameraRecorderPlayback
: public IActionHandler
208 virtual void execute (CCtrlBase
* /* pCaller */, const string
&/* Params */)
210 if (State
== PlayBack
)
216 TimeOrigin
= CTime::getLocalTime();
219 // ***************************************************************************
220 REGISTER_ACTION_HANDLER (CAHCameraRecorderPlayback
, "camera_recorder_playback");
222 // ***************************************************************************
223 class CAHSaveCameraRecord
: public IActionHandler
225 virtual void execute (CCtrlBase
* /* pCaller */, const string
&/* Params */)
229 std::string filename
= ClientCfg
.CameraRecorderPrefix
+ ".cr";
230 if (!ClientCfg
.CameraRecorderPath
.empty())
232 filename
= ClientCfg
.CameraRecorderPath
+ "/" + filename
;
234 filename
= CFile::findNewFile(filename
);
235 if (!filename
.empty())
243 nlwarning("Couldn't compute camera recorder next filename");
246 catch(const EStream
&e
)
252 // ***************************************************************************
253 REGISTER_ACTION_HANDLER (CAHSaveCameraRecord
, "save_camera_record");
256 // ***************************************************************************
257 NLMISC_COMMAND(loadCamRec
, "Load a camera path record file (.cr)", "<filename>")
261 std::string filename
= args
[0];
262 string::size_type pos
= args
[0].find_last_of ('.');
263 if (pos
== string::npos
)
268 std::string searchFilename
= filename
;
269 if (!ClientCfg
.CameraRecorderPath
.empty())
271 searchFilename
= ClientCfg
.CameraRecorderPath
+ "/" + searchFilename
;
273 if (CFile::fileExists(searchFilename
))
275 path
= searchFilename
;
279 path
= CPath::lookup(filename
, false, true);
290 catch(const EStream
&e
)