Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / client / src / rosace.cpp
blob75b896255b0f5f5b9ae3952530b5fcbb82376654
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "stdpch.h"
22 //////////////
23 // INCLUDES //
24 //////////////
25 // Misc.
26 #include "nel/misc/common.h"
27 // 3D Interface.
28 #include "nel/3d/u_driver.h"
29 // Client.
30 #include "rosace.h"
31 #include "math.h"
34 ///////////
35 // USING //
36 ///////////
37 using namespace NLMISC;
38 using namespace NL3D;
39 using namespace std;
42 /////////////
43 // Externs //
44 /////////////
45 extern UDriver *Driver;
48 ///////////////
49 // FUNCTIONS //
50 ///////////////
51 //////////////////////
52 // CRosaceComponent //
53 //////////////////////
54 //-----------------------------------------------
55 // CRosaceComponent :
56 // Constructor.
57 //-----------------------------------------------
58 CRosaceComponent::CRosaceComponent()
60 // No callback function at the beginning.
61 _Callback = 0;
62 // No texture at the beginning.
63 _Texture = 0;
64 _X = 0.5f;
65 _Y = 0.5f;
66 _W = 0.05f;
67 _H = 0.05f;
68 }// CRosaceComponent //
70 //-----------------------------------------------
71 // display :
72 // Display the component.
73 //-----------------------------------------------
74 void CRosaceComponent::display(bool selected)
76 // If there is a texture to display.
77 if(_Texture)
79 if(selected)
80 Driver->drawBitmap(_X, _Y, _W, _H, *_Texture, true, CRGBA(255, 0, 0, 255));
81 else
82 Driver->drawBitmap(_X, _Y, _W, _H, *_Texture, true, CRGBA(255, 255, 255, 255));
84 }// display //
86 //-----------------------------------------------
87 // execute :
88 // Execute the callback associated to the component.
89 //-----------------------------------------------
90 void CRosaceComponent::execute()
92 // If there is a callback -> execute it.
93 if(_Callback)
94 _Callback();
95 }// execute //
97 //-----------------------------------------------
98 // texture :
99 // Set the texture for the component.
100 //-----------------------------------------------
101 void CRosaceComponent::texture(const string &filename)
103 _Texture = Driver->createTextureFile(filename);
104 }// texture //
106 //-----------------------------------------------
107 // inside :
108 // Return true if the position (x,y) is inside the rosace.
109 //-----------------------------------------------
110 bool CRosaceComponent::inside(float x, float y)
112 if(x>=_X && x<_X+_W && y>=_Y && y<_Y+_H)
113 return true;
114 return false;
115 }// inside //
120 /////////////////
121 // CRosacePage //
122 /////////////////
123 //-----------------------------------------------
124 // CRosacePage :
125 // Constructor.
126 //-----------------------------------------------
127 CRosacePage::CRosacePage()
129 _OldX = 0.5f;
130 _OldY = 0.5f;
131 _Selected = -1;
132 _Components.clear();
133 }// CRosacePage //
135 //-----------------------------------------------
136 // CRosacePage :
137 // Constructor. Create some components at the beginning.
138 //-----------------------------------------------
139 CRosacePage::CRosacePage(sint nb)
141 _Selected = -1;
142 _Components.clear();
143 _Components.resize(nb);
144 generate();
145 }// CRosaceContext //
147 //-----------------------------------------------
148 // display :
149 // Display all the components in the page.
150 //-----------------------------------------------
151 void CRosacePage::display()
153 for(uint i = 0; i<size(); ++i)
155 if(_Selected == (sint)i)
156 _Components[i].display(true);
157 else
158 _Components[i].display(false);
160 }// display //
162 //-----------------------------------------------
163 // execute :
164 // Execute the callback associated to the selected component.
165 //-----------------------------------------------
166 void CRosacePage::execute()
168 // If there is no component selected -> return.
169 if(_Selected<0 || _Selected>=(sint)size())
170 return;
171 // Else execute the callback associated to the selected component.
172 _Components[_Selected].execute();
173 }// execute //
175 //-----------------------------------------------
176 // next :
177 // Select the next valide component.
178 //-----------------------------------------------
179 void CRosacePage::next()
181 _Selected++;
182 if(!valide())
184 _Selected = 0;
185 if(!valide())
186 _Selected = -1;
188 }// next //
190 //-----------------------------------------------
191 // previous :
192 // Select the previous valide component.
193 //-----------------------------------------------
194 void CRosacePage::previous()
196 _Selected--;
197 // If the selected component is not valide selected the last 1 (-1 is no component).
198 if(!valide())
199 _Selected = (sint)size()-1;
200 }// previous //
202 //-----------------------------------------------
203 // generate :
204 // Generate the rosace (all components).
205 //-----------------------------------------------
206 void CRosacePage::generate()
208 float _W = 0.05f;
209 float _H = 0.05f;
211 double ang = 2*Pi/(float)size();
212 double r1 = _W/(2*sin(ang/2)); // r = opp/tan @
213 double r2 = _H/(2*sin(ang/2));
214 for(uint i=0; i<size(); ++i)
216 double x = r1*cos(i*ang);
217 double y = r2*sin(i*ang);
218 _Components[i].setPos((float)(0.5f+x-_W/2), (float)(0.5f+y-_H/2));
220 }// generate //
222 //-----------------------------------------------
223 // update :
224 // Update the page.
225 //-----------------------------------------------
226 void CRosacePage::update(float x, float y, TMode mode)
228 switch(mode)
230 case CursorMode:
231 cursorMode(x, y);
232 break;
234 case CursorAngleMode:
235 cursorAngleMode(x, y);
236 break;
238 case RelativeMode:
239 relativeMode(x, y);
240 break;
242 case DirectMode:
243 directMode(x, y);
244 break;
245 case NbRosaceMode:
246 nlwarning("Rosace Mode reached.");
247 break;
248 default:
249 break;
251 }// update //
253 //-----------------------------------------------
254 // select :
255 // ...
256 //-----------------------------------------------
257 void CRosacePage::select(double ang)
259 double angTmp = 2*Pi/(float)size();
260 if(ang>=0)
262 ang = ang+angTmp/2;
263 _Selected = (sint)(ang/angTmp);
265 else
267 ang = -ang+angTmp/2;
268 _Selected = size()-(sint)(ang/angTmp);
271 if(_Selected >= (sint)size() || _Selected<0)
272 _Selected = 0;
273 }// select //
275 //-----------------------------------------------
276 // cursorMode :
277 // Select the component under the position (x,y) or unselect all if nothing at this position.
278 //-----------------------------------------------
279 void CRosacePage::cursorMode(float x , float y)
281 for(uint i=0; i<size(); ++i)
283 if(_Components[i].inside(x, y))
285 _Selected = i;
286 return;
290 // Unselect all.
291 _Selected = -1;
292 }// cursorMode //
294 //-----------------------------------------------
295 // cursorAngleMode :
296 // Select elements of the rosace according to the angle generated by mouse position and screen center.
297 //-----------------------------------------------
298 void CRosacePage::cursorAngleMode(float x , float y)
300 // If the mouse is near center -> unselect all.
301 if(x>=0.5f-0.01f && x<0.5f+0.01f && y>=0.5f-0.01f && y<0.5f+0.01f)
302 _Selected = -1;
303 // Select the right element of the rosace according to the angle.
304 else
306 uint32 width, height;
307 Driver->getWindowSize(width, height);
309 double x1, y1;
310 x1 = (double)width/2.0;
311 x1 = (x*(double)width) - x1;
313 y1 = (double)height/2.0;
314 y1 = (y*(double)height) - y1;
316 select(atan2(y1, x1));
318 }// CursorAngleMode //
320 //-----------------------------------------------
321 // directMode :
322 // ...
323 //-----------------------------------------------
324 void CRosacePage::directMode(float x , float y)
326 float difX = x-_OldX;
327 float difY = y-_OldY;
329 if(fabs(difX)<0.01f && fabs(difY)<0.01f)
330 return;
332 uint32 width, height;
333 Driver->getWindowSize(width, height);
335 double x1 = (difX*(double)width);
336 double y1 = (difY*(double)height);
338 select(atan2(y1, x1));
340 // Backup the x and y.
341 _OldX = x;
342 _OldY = y;
343 }//directMode //
345 //-----------------------------------------------
346 // relativeMode :
347 // ...
348 //-----------------------------------------------
349 void CRosacePage::relativeMode(float x, float /* y */)
351 float difX = x-_OldX;
352 if(fabs(difX)<0.01f)
353 return;
355 if(difX>0)
356 next();
357 else
358 previous();
360 // Backup the x and y.
361 _OldX = x;
362 }// relativeMode //
367 ///////////////////
368 // CRosaceContext//
369 ///////////////////
370 //-----------------------------------------------
371 // CRosaceContext :
372 // Constructor.
373 //-----------------------------------------------
374 CRosaceContext::CRosaceContext()
376 _Selected = 0;
377 _Pages.clear();
378 }// CRosacePage //
380 //-----------------------------------------------
381 // CRosaceContext :
382 // Constructor. Create some pages at the beginning.
383 //-----------------------------------------------
384 CRosaceContext::CRosaceContext(sint nb)
386 _Selected = 0;
387 _Pages.clear();
388 _Pages.resize(nb);
389 }// CRosacePage //
391 //-----------------------------------------------
392 // display :
393 // Display all the pages in the context.
394 //-----------------------------------------------
395 void CRosaceContext::display()
397 // If there is no page selected -> return.
398 if(!valide())
399 return;
400 // Else display the right page.
401 _Pages[_Selected].display();
402 }// display //
404 //-----------------------------------------------
405 // execute :
406 // Execute the callback associated to the selected component in the selected page.
407 //-----------------------------------------------
408 void CRosaceContext::execute()
410 // If there is no page selected -> return.
411 if(!valide())
412 return;
413 // Else execute the callback associated to the selected component.
414 _Pages[_Selected].execute();
415 }// execute //
417 //-----------------------------------------------
418 // add :
419 // Add a page.
420 //-----------------------------------------------
421 void CRosaceContext::add(const CRosacePage &page)
423 _Pages.push_back(page);
424 }// add //
426 //-----------------------------------------------
427 // update :
428 // Update the context.
429 //-----------------------------------------------
430 void CRosaceContext::update(float x, float y, CRosacePage::TMode mode)
432 // If there is no page selected -> return.
433 if(!valide())
434 return;
435 // Update the selected page.
436 _Pages[_Selected].update(x, y, mode);
437 }// update //
439 //-----------------------------------------------
440 // next :
441 // Select the next valide page.
442 //-----------------------------------------------
443 void CRosaceContext::next()
445 _Selected++;
446 if(!valide())
448 _Selected = 0;
449 if(!valide())
450 _Selected = -1;
452 }// next //
454 //-----------------------------------------------
455 // previous :
456 // Select the previous valide page.
457 //-----------------------------------------------
458 void CRosaceContext::previous()
460 _Selected--;
461 // If the selected component is not valide selected the last 1 (-1 is no component).
462 if(!valide())
463 _Selected = (sint)size()-1;
464 }// previous //
469 /////////////
470 // CRosace //
471 /////////////
472 //-----------------------------------------------
473 // CRosace :
474 // Constructor.
475 //-----------------------------------------------
476 CRosace::CRosace()
478 init();
479 }// CRosace //
481 //-----------------------------------------------
482 // ~CRosace :
483 // Destructor.
484 //-----------------------------------------------
485 CRosace::~CRosace()
487 }// ~CRosace //
489 //-----------------------------------------------
490 // init :
491 // Initialize the rosace.
492 //-----------------------------------------------
493 void CRosace::init()
495 _Mode = CRosacePage::CursorAngleMode;
496 _Selected.clear();
497 }// init //
499 //-----------------------------------------------
500 // add :
501 // Add a page. ("" is not valide name).
502 //-----------------------------------------------
503 void CRosace::add(const string &name, const CRosaceContext &context)
505 // If the name is not empty.
506 if(!name.empty())
507 _Contexts.insert(TContexts::value_type (name, context));
508 }// add //
510 //-----------------------------------------------
511 // valide :
512 // Is the current context valide.
513 //-----------------------------------------------
514 bool CRosace::valide()
516 // Check if the Selected context is valide.
517 TContexts::iterator it = _Contexts.find(_Selected);
518 if(it != _Contexts.end())
519 return true;
520 return false;
521 }// valide //
523 //-----------------------------------------------
524 // display :
525 // Display the rosace.
526 //-----------------------------------------------
527 void CRosace::display()
529 if(valide())
530 _Contexts[_Selected].display();
531 }// display //
533 //-----------------------------------------------
534 // update :
535 // ...
536 //-----------------------------------------------
537 void CRosace::update(float x, float y)
539 if(valide())
540 _Contexts[_Selected].update(x, y, _Mode);
541 }// update //
543 //-----------------------------------------------
544 // execute :
545 // Execute the callback function corresponding to the selected component.
546 //-----------------------------------------------
547 void CRosace::execute()
549 if(valide())
550 _Contexts[_Selected].execute();
551 }// execute //
553 //-----------------------------------------------
554 // swap :
555 // Swap to next rosace page.
556 //-----------------------------------------------
557 void CRosace::swap()
559 if(valide())
560 _Contexts[_Selected].next();
561 }// swap //