Merge branch '138-toggle-free-look-with-hotkey' into main/gingo-test
[ryzomcore.git] / ryzom / client / src / r2 / tool.h
blob122b85782053cc0b0fc841bac65e376ca2628b0b
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
7 //
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #ifndef R2_TOOL_H
22 #define R2_TOOL_H
25 #include "nel/misc/smart_ptr.h"
26 #include "nel/misc/array_2d.h"
28 #include "nel/gui/interface_element.h"
29 #include "game_share/scenario_entry_points.h"
32 class CInterfaceManager;
34 namespace NLGUI
36 class CEventDescriptor;
37 class CLuaObject;
38 class CGroupContainer;
41 class CGroupMap;
43 namespace NLMISC
45 class CVector;
48 namespace DMS
50 class CDynamicMapClient;
53 namespace R2
56 extern const uint32 DEFAULT_ENTITY_MIN_OPACITY;
59 struct IDisplayerUIHandle;
60 class CEditor;
61 class CInstance;
62 class CDynamicMapClient;
64 /** Base class for manipulation tools found in the R2 editor
65 * There's only one tool at a moment and mouse/keyboard events are routed to that tool
67 * \author Nicolas Vizerie
68 * \author Nevrax France
69 * \date 5/2005
71 class CTool : public CReflectableRefPtrTarget, public NLMISC::IClassable
73 public:
74 class CWorldViewRay
76 public:
77 NLMISC::CVector Origin;
78 NLMISC::CVector Dir;
79 NLMISC::CVector Right;
80 NLMISC::CVector Up;
81 bool OnMiniMap;
82 bool Valid;
83 public:
84 CWorldViewRay()
86 Origin = NLMISC::CVector::Null;
87 Dir = NLMISC::CVector::Null;
88 Right = NLMISC::CVector::Null;
89 Up = NLMISC::CVector::Null;
90 OnMiniMap = false;
91 Valid = false;
95 //\TODO nico find a better place for this
96 enum TRayIntersectionType { NoIntersection, ValidPacsPos, InvalidPacsPos };
98 typedef NLMISC::CSmartPtr<CTool> TSmartPtr;
100 CTool();
101 virtual ~CTool() {}
103 // Init parameters from script
104 virtual bool init(const CLuaObject &/* parameters */) { return true; }
105 /** Get this tool name in the ui. This name is used to identify the tool in the ui (used by the r2.ToolUI:setActiveToolUIByName function defined in r2ed_ui.lua)
106 * May return "" if there's no ui associated with that tool
108 virtual const char *getToolUIName() const = 0;
109 virtual bool isCreationTool() const = 0;
110 virtual bool isPickTool() const {return false; }
113 // This update is called at each frame for the current tool just before rendering
114 virtual void updateBeforeRender() {}
115 // This update is called at each frame for the current tool just after rendering
116 virtual void updateAfterRender() = 0;
118 //////////////////////////
119 // EVENTS HANDLING //
120 //////////////////////////
122 /** Entry point for events handling.
123 * Methods where defined below for convenience for the most common events
124 * like 'onMouseLeftButtonDown' or 'onMouseRightButtonUp'.
125 * Default behaviour of this member function is to forward the event to these event handling methods.
127 * A deriver may handle events not listed below by redefining this method,
128 * possibly calling its parent version for events he is not interested in.
130 * \return true if the event has been handled by the tool
132 virtual bool handleEvent (const NLGUI::CEventDescriptor &eventDesc);
134 virtual void onFocusGained() {} // the app window gained the focus (there's no 'focus lost' event here because it reset current tool, so 'CTooll::cancel' will be called instead)
135 // IMPORTANT : Reacting to this should be unnecessary, as lost focus reset the current tool,
136 // defaulting to the 'SelectMove' tool, that handle this event correctly.
137 virtual bool onMouseLeftButtonDown() { return false; }
138 virtual bool onMouseLeftButtonUp() { releaseMouse(); return false; }
139 virtual bool onMouseRightButtonDown() { return false; }
140 virtual bool onMouseRightButtonUp() { return false; }
141 virtual bool onMouseMove() { return false; }
143 // call when this tool is just being activated
144 virtual void onActivate() {}
145 // special messages for shortcut keys
146 virtual bool onDeleteCmd() { return false; }
148 * Unlike the other onMousexxx method, these are actually called AFTER the camera event handling
149 * has been done. Doing the same in onMouseRightButtonUp or onMouseRightButtonDown
150 * instead would require that the user test if mouse button was not released after a camera
151 * move (in which case the click should not be handled of course)
153 * Usually the onMousexxxButtonUp are ususeful when working in pair with the associated 'mouse button down' event.
154 * Such events usually provoke a mouse capture (example : selectMoveTool)
156 virtual bool onMouseLeftButtonClicked() { return false; }
157 /** NB : if the onMouseRightButtonClicked isn't handled by the tool then
158 * editor will show the context menu
160 virtual bool onMouseRightButtonClicked();
161 // Called by editor just before a new tool is made current
162 virtual void cancel() = 0;
165 // when returning true -> ignore next click causing unselect
166 virtual bool getPreviousToolClickEndFlag(bool /* clear */ = true) { return false; }
169 // double click handling :
170 // 'startDoubleClickCheck' should be called when the 'onMouseLeftButtonClicked' msg is handled
171 // then checkDoubleClick' should be call on any subsequent onMouseLeftButtonDown. If
172 // the result is true then double click should be handled
173 void startDoubleClickCheck();
174 bool checkDoubleClick();
176 // test if one of the 'shift' keys is down
177 static bool isShiftDown();
179 // test if one of the 'ctrl' keys is down
180 static bool isCtrlDown();
182 //////////////////////
183 // HELPER FUNCTIONS //
184 //////////////////////
186 /** check which instance is under the mouse, possibly fading player in / out
187 * \param miniMapHandle if not NULL, pointer will be filled with the minimap ui element that is under the mouse
188 * \return NULL if there's no instance under the mouse
190 static CInstance *checkInstanceUnderMouse(IDisplayerUIHandle **miniMapHandle = NULL);
192 // helper : handle mouse over instance: highlight them when mouse is over & change mouse cursor accordingly
193 static void handleMouseOverInstance(const char *cursorDefault,
194 const char *cursorOverUnselectedInstance,
195 const char *cursorOverSelectedInstance);
197 // handle player under cursor (fade in / fade out)
198 static void handleMouseOverPlayer(bool over);
200 /** Default right button down handling :
201 * If an entity is highlighted,
202 * then select it and pop its menu
203 * \return true if the event was handled
205 bool defaultRightButtonDownHandling();
207 /** Capture the mouse
208 * - The ui won't receive events from the mouse
209 * - Maintaining the left button down doesn't trigger camera rotation any more.
210 * Useful for tools such as 'select', 'move' ...
212 static void captureMouse();
213 static void releaseMouse();
214 static bool isMouseCaptured();
216 // shortcut to get the ui
217 static CInterfaceManager &getUI();
218 // Get mouse position
219 static void getMousePos(sint32 &x, sint32 &y) ;
220 // Get if mouse are clicked down and position of last down click
221 static void getMouseDown(bool &down, sint32 &x, sint32 &y);
222 // Get if mouse are middle clicked down and position of last down click
223 static void getMouseMiddleDown(bool &down, sint32 &x, sint32 &y);
224 // Get if mouse are right clicked down and position of last down click
225 static void getMouseRightDown(bool &down, sint32 &x, sint32 &y);
226 // Get mouse x position
227 static sint32 getMouseX();
228 // Get mouse y position
229 static sint32 getMouseY();
230 // Set the current mouse cursor
231 static void setMouseCursor(const std::string &cursorTexture);
232 /** Compute a view vector (with its direction z set to 1) from coordinate of the mouse on screen
233 * If the mouse is on the island map, then a vector looking down from heights will be returned
235 static void computeWorldViewRay(sint32 posX, sint32 posY, CWorldViewRay &dest);
236 // specific test for the world map
237 static TRayIntersectionType computeWorldMapIntersection(float x, float y, NLMISC::CVector &inter);
239 // get current screen size
240 static void getScreenSize(uint32 &scrW, uint32 &scrH);
241 // get current screen width
242 static uint32 getScreenWidth();
243 // get current screen height
244 static uint32 getScreenHeight();
245 // see if a point is in screen
246 static bool isInScreen(sint32 x, sint32 y);
247 // test whether the mouse is over the user interface
248 static bool isMouseOnUI();
249 // retriever ptr on world map in the ui
250 static CGroupMap *getWorldMap();
251 // test whether the mouse is over the map
252 static CGroupMap *isMouseOnWorldMap();
253 // test whether the mouse is over a container
254 static CGroupContainer *isMouseOnContainer();
255 /** Compute collision of a segment with the landscape
256 * \param inter If return type is different from 'NoIntersection', then 'inter' is filled with the collision position
258 static TRayIntersectionType computeLandscapeRayIntersection(const CWorldViewRay &worldViewRay, NLMISC::CVector &inter);
259 // Get pacs type at the given position, with the given threshold.
260 static TRayIntersectionType getPacsType(const NLMISC::CVector &pos, float threshold, NLPACS::UGlobalPosition &destPos);
262 // set context help for the current tool
263 static void setContextHelp(const ucstring &contextHelp);
265 // shortcut to get the interface to the server
266 CDynamicMapClient &getDMC();
268 /** handle world map auto-panning feature, should be called whenever auto-pan should be done
269 * dx & dy are filled with delta of the map for this frame
271 void handleWorldMapAutoPan(sint32 &dx, sint32 &dy);
273 // lua exports
274 int luaIsPickTool(CLuaState &ls);
276 REFLECT_EXPORT_START(R2::CTool, CReflectable)
277 REFLECT_LUA_METHOD("isPickTool", luaIsPickTool);
278 REFLECT_EXPORT_END
280 static NLMISC::CRGBA getInvalidPosColor();
282 /** For derivers : additionnal checking can be done on the pos to choose
283 * Pos must at least be a valid pacs pos
284 * Default will check with a radius of 0.5 meter
286 static bool isValid2DPos(const NLMISC::CVector2f &pos);
288 private:
289 sint64 _DoubleClickStartTime;
290 sint32 _DoubleClickX;
291 sint32 _DoubleClickY;
292 uint64 _AutoPanLastHandlingFrame;
293 sint64 _AutoPanDelay;
294 sint64 _NumPans;
295 static bool _MouseCaptured;
296 static NLMISC::CRefPtr<NLMISC::CCDBNodeLeaf> _UserCharFade;
297 private:
298 /** compute the nearest valid surface at a given position from the island heightmap
299 * (heightmap must not be empty or an assertion is raised)
300 * \return true if a valid surface was found
302 static bool computeNearestValidSurfaceFromHeightMap(float x, float y, NLMISC::CVector &inter);
303 // trace a ray though the scene, using precise camera collision first, island packed collisions then.
304 static bool raytrace(const NLMISC::CVector &segmentStart, const NLMISC::CVector &dir, NLMISC::CVector &inter);
305 static bool isIslandValidPos(const NLMISC::CArray2D<sint16> &heightMap, const CScenarioEntryPoints::CCompleteIsland &islandDesc, float x, float y);
308 } // R2
310 #endif