1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
17 #ifndef R2_DISPLAYER_VISUAL_H
18 #define R2_DISPLAYER_VISUAL_H
21 #include "displayer_base.h"
24 #include "nel/misc/vector.h"
25 #include "nel/misc/vectord.h"
26 #include "nel/misc/rgba.h"
35 // ***********************************************************************************************************************
36 // Interface for object selection in the scene
37 struct ISelectableObject
39 enum TSelectionType
{ LocalSelectBox
= 0, WorldSelectBox
, GroundProjected
};
40 // Intersection & selection testing
41 virtual bool isSelectable() const = 0;
42 virtual bool getLastClip() const { return false; }
43 // the object is projected on the scene, and so intersection test
44 // ask if current intersection with mouse ray in in the projection of the object (must call isInProjection)
45 virtual const NLMISC::CMatrix
&getInvertedMatrix() const { return NLMISC::CMatrix::Identity
; }
46 virtual TSelectionType
getSelectionType() const { return LocalSelectBox
; }
47 virtual bool isInProjection(const NLMISC::CVector2f
&/* pos */) const { return false; }
48 virtual bool isInProjectionBorder(const NLMISC::CVector2f
&/* pos */) const { return false; }
49 virtual NLMISC::CAABBox
getSelectBox() const { return NLMISC::CAABBox(); }
50 virtual float preciseIntersectionTest(const NLMISC::CVector
&/* worldRayStart */, const NLMISC::CVector
&/* worldRayDir */) const { return FLT_MAX
; }
51 virtual CInstance
*getInstanceInEditor() const = 0;
54 // ***********************************************************************************************************************
55 // Decoration in a CGroupMap that expose this interface (through dynamic_cast) are representation of CInstance in the island map
56 struct IDisplayerUIHandle
58 virtual CInstance
&getDisplayedInstance() = 0;
59 // test that the given position intesersect the displayer (default is true, because this is call
60 // only if bounding rect test succeeded)
61 virtual bool contains(sint32
/* mouseXInWindow */, sint32
/* mouseYInWindow */) const { return true; }
62 // special test : is it an edge of a zone ?
63 virtual bool isEdge() const { return false; }
64 // for edge, give the edge index in its parent zone
65 virtual uint
getEdgeIndex() const { nlassert(0); return 0; }
69 // ***********************************************************************************************************************
70 // Displays an object of the editor in the 3D scene / in the worldmap
71 class CDisplayerVisual
: public CDisplayerBase
, public ISelectableObject
74 typedef NLMISC::CSmartPtr
<CDisplayerVisual
> TSmartPtr
;
75 typedef NLMISC::CRefPtr
<CDisplayerVisual
> TRefPtr
;
82 FlagBadPos
, // a 'stop' icon is displayed on entity when it is on a bad landscape position
83 // may happen whn a group is moved as a whole
89 // Current display mode. Display mode is retrieved from the lua property 'DisplayMode', and is thus
90 // saved with the object
93 DisplayModeVisible
= 0, // the object is visible
94 DisplayModeHidden
= 1, // the object is not visible (not in scene / not in the minimap)
95 DisplayModeFrozen
= 2, // the object can't be selected, but is visible
96 DisplayModeLocked
= 3, // the object can be selected, but not moved / rotated
97 DisplayModeArray
= 4, // The instance is in an array being created by the 'array' tool
102 virtual ~CDisplayerVisual();
104 // Init parameters from script
105 virtual bool init(const CLuaObject
¶meters
);
112 /** Default behaviour when act is changed is to check whether
113 * the object is visible in current act by calling "isVisibleInCurrentAct"
114 * If not visible then "setActive(false)" will be called to remove the displayed object from the view.
115 * Modification messages (if any ...) should then be ignored by derivers until onCreate is called again
117 virtual void onPreActChanged();
118 virtual void onActChanged();
119 virtual void onContinentChanged();
120 virtual void onPreRender() {}
121 virtual void onPostRender();
122 /** NB : derivers should not usually react to the 'onPostCreate' or 'onErase' methods
123 * because default behavior of these is to call 'setActive' as necessary when the user select
124 * an act in which the displayed instance is visible in the scenario.
126 virtual void onPostCreate();
127 // for derivers : see 'onPostCreate' remarks
128 virtual void onErase();
129 virtual void onFocus(bool focused
);
130 virtual void onSelect(bool selected
);
131 /** Derivers note : 'onAttrModifier' takes care of updating position of the displayer,
132 * hence derivers should call their parent version before updating real position in the 3D scene
134 virtual void onAttrModified(const std::string
&attrName
, sint32 attrIndex
);
135 /** Default behavior of 'onPostHrcMove' is to force to recompute the world pos
136 * Because object may have been made son of an new object with another world pos
138 virtual void onPostHrcMove();
144 // get display mode, taking possible inheritance in account
145 virtual TDisplayMode
getActualDisplayMode() const;
146 // get display mode, (not taking possible inheritance in account), sint32 for lua export
147 sint32
getDisplayMode() const { return _DisplayMode
; }
148 // set display moed (sint32 for lua export)
149 virtual void setDisplayMode(sint32 mode
);
151 // return true if the object is currently visible *in current act* (mean it is not and'ed with the getActive() flag)
152 bool getActualVisibility() const { return getActualDisplayMode() != DisplayModeHidden
; }
154 // Set one display flag for the displayer (selected, highlighted ...)
155 void setDisplayFlag(TDisplayFlags flag
, bool on
);
156 bool getDisplayFlag(TDisplayFlags flag
) const;
157 // Get parent visual displayer if one exists
158 CDisplayerVisual
*getParent();
159 const CDisplayerVisual
*getParent() const;
160 /** Eval a point at which the displayed object may be linked to when displaying groups
161 * Must be expressed in world coordinates
163 virtual NLMISC::CVector
evalLinkPoint(bool /* leader */ = false) { return getWorldPos().asVector(); }
164 // Eval enter point (useful for zones)
165 virtual bool evalEnterPoint(const NLMISC::CVector
&startPoint
, NLMISC::CVector
&result
);
166 // Eval exit point (for objects such as roads), default resume to evalEnterPoint
167 virtual NLMISC::CVector
evalExitPoint();
168 // From ISelectableObject
169 virtual CInstance
*getInstanceInEditor() const { return getDisplayedInstance(); }
170 // Snap the displayed object to the ground (if supported)
171 virtual void snapToGround() {}
172 // Make this displayer blink
174 int luaBlink(CLuaState
&ls
);
175 /** See if instance may be dropped on an invalid pacs pos after a move
176 * May have sens for entity such as region which are just projected over the scene
177 * and don't depend on PACS for their display
179 virtual bool isInvalidPacsPosAcceptable() const { return false; }
181 /** For the move tool : test if all parts of the object are accessible (e.g not on an unreachable part of the map)
182 * NB : this is a display, flag, not updated if the current displayer is not active !!
184 virtual bool isAccessible() { return true; }
186 // test if the current shape for this displayer is valid (may be false for self-intersecting polys)
187 virtual bool isValidShape() const { return true; }
189 // test if this displayer is a group displayer
190 virtual bool isGroup() const { return false; }
192 // from ISelectableObject
193 virtual bool isSelectable() const;
195 NLMISC::CRGBA
getDisplayModeColorInScene() const;
196 NLMISC::CRGBA
getDisplayModeColorInMap() const;
198 // called by parent when the display mode has changed, so sons may want to update their display if their inherit it
199 virtual void onParentDisplayModeChanged() {}
204 // TODO nico : should really move the position into "CInstance", or better, find a way to derive CWorldObject
205 // in C++ rather than in lua. Position is a property of the object, not a display property!! Should not be the responsability
206 // of the displayer to maintain this ...
209 // Get 3D position relative to parent.
210 NLMISC::CVectorD
getPos() const { return _Pos
; }
211 // Get world 2D position
212 NLMISC::CVector2f
getWorldPos2f() const { return NLMISC::CVector2f((float) _WorldPos
.x
, (float) _WorldPos
.y
); }
213 // Get world 3D position
214 NLMISC::CVectorD
getWorldPos() const { return _WorldPos
; }
215 // Test if this object should inherit its parent pos
216 bool inheritPos() const;
217 // Eval all sub-positions in world as CVector2f (default is to clear the vector)
218 virtual void getSonsWorldPos2f(std::vector
<NLMISC::CVector2f
> &result
);
219 virtual void getSons(std::vector
<CDisplayerVisual
*> &sons
) const;
220 virtual uint
getNumSons() const { return 0; }
221 virtual CDisplayerVisual
*getSon(uint
/* index */) const { nlassert(0); return NULL
; }
222 virtual bool isCompound() const { return false; }
224 virtual float getAngle() const { nlassert(0); return 0.f
; }
230 REFLECT_EXPORT_START(R2::CDisplayerVisual
, R2::CDisplayerBase
)
231 REFLECT_LUA_METHOD("blink", luaBlink
);
232 REFLECT_SINT32("DisplayMode", getDisplayMode
, setDisplayMode
);
235 // signal that this entity start / stops to be rotated
236 virtual void setRotateInProgress(bool rotateInProgress
);
237 bool getRotateInProgress() const { return _RotateInProgress
; }
238 virtual void setMoveInProgress(bool moveInProgress
);
239 bool getMoveInProgress() const { return _MoveInProgress
; }
242 uint32 _DisplayFlags
; // a combination of the TDisplayFlags flags
243 sint64 _BlinkStartDate
;
245 NLMISC::CVectorD _Pos
;
246 CGroupInScene
*_IconInScene
; // a "stop" icon showing that the object has an invalid position
247 bool _IconInSceneCreationFailed
;
248 bool _RotateInProgress
;
249 bool _MoveInProgress
;
250 bool _InheritDisplayMode
;
252 TDisplayMode _DisplayMode
;
253 // Caching of current parent pointer
255 CDisplayerVisual
*_LastParent
;
257 NLMISC::CVectorD _WorldPos
;
259 // update world position for the objet tree rooted at this object
260 void updateWorldPosRecurse();
262 void updateLocalPos();
263 //void updateDisplayMode();
265 NLMISC::CRGBA
getBlinkColor(NLMISC::CRGBA defaultColor
, NLMISC::CRGBA blinkColor
= NLMISC::CRGBA(192, 192, 192)) const;
267 // See if the z need to be reevaluated. May happen after a tp or when the camera moves (used by shapes)
268 // Calling this will update the invalidity flag
269 bool testNeedZEval();
270 void updateValidPosFlag();
276 virtual void setActive(bool active
) = 0;
277 virtual bool getActive() const = 0;
278 virtual bool isActiveInCurrentAct() const;
280 virtual void evalIconInScenePos(NLMISC::CVector
&dest
) const;
282 /** Protected : Called by parent when its world pos has changed.
283 * Default behaviour is to add instance relative pos to parent world pos
285 virtual void updateWorldPos();