| 1 | /* |
|---|
| 2 | ================================================================================= |
|---|
| 3 | This file is part of Cafu, the open-source game engine and graphics engine |
|---|
| 4 | for multiplayer, cross-platform, real-time 3D action. |
|---|
| 5 | Copyright (C) 2002-2012 Carsten Fuchs Software. |
|---|
| 6 | |
|---|
| 7 | Cafu is free software: you can redistribute it and/or modify it under the terms |
|---|
| 8 | of the GNU General Public License as published by the Free Software Foundation, |
|---|
| 9 | either version 3 of the License, or (at your option) any later version. |
|---|
| 10 | |
|---|
| 11 | Cafu is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
|---|
| 12 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
|---|
| 13 | PURPOSE. See the GNU General Public License for more details. |
|---|
| 14 | |
|---|
| 15 | You should have received a copy of the GNU General Public License |
|---|
| 16 | along with Cafu. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 17 | |
|---|
| 18 | For support and more information about Cafu, visit us at <http://www.cafu.de>. |
|---|
| 19 | ================================================================================= |
|---|
| 20 | */ |
|---|
| 21 | |
|---|
| 22 | #ifndef CAFU_MAP_ELEMENT_HPP_INCLUDED |
|---|
| 23 | #define CAFU_MAP_ELEMENT_HPP_INCLUDED |
|---|
| 24 | |
|---|
| 25 | #include "Group.hpp" |
|---|
| 26 | |
|---|
| 27 | #include "Math3D/Angles.hpp" |
|---|
| 28 | #include "Math3D/BoundingBox.hpp" |
|---|
| 29 | #include "Templates/Array.hpp" |
|---|
| 30 | #include "TypeSys.hpp" |
|---|
| 31 | |
|---|
| 32 | #include "wx/string.h" |
|---|
| 33 | |
|---|
| 34 | #include <ostream> |
|---|
| 35 | |
|---|
| 36 | |
|---|
| 37 | class MapElementT; |
|---|
| 38 | class Renderer2DT; |
|---|
| 39 | class Renderer3DT; |
|---|
| 40 | class TextParserT; |
|---|
| 41 | class ViewWindow2DT; |
|---|
| 42 | class MatrixT; |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | /// The TypeInfoTs of all MapElementT derived classes must register with this TypeInfoManT instance. |
|---|
| 46 | cf::TypeSys::TypeInfoManT& GetMapElemTIM(); |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | class MapElementT |
|---|
| 50 | { |
|---|
| 51 | public: |
|---|
| 52 | |
|---|
| 53 | /// The default constructor. |
|---|
| 54 | MapElementT(const wxColour& Color); |
|---|
| 55 | |
|---|
| 56 | /// The copy constructor for copying a map element. |
|---|
| 57 | /// |
|---|
| 58 | /// @param Elem The element to copy-construct this element from. |
|---|
| 59 | /// |
|---|
| 60 | /// Contrary to Elem, the new MapElementT instance is: |
|---|
| 61 | /// - never selected (no matter if Elem was selected), |
|---|
| 62 | /// - not in a group (and thus visible). |
|---|
| 63 | /// It is up to the caller to assign selection state and group membership if desired. |
|---|
| 64 | /// The new element is always constructed with a deep-copy (that is, the children of Elem are copied recursively). |
|---|
| 65 | MapElementT(const MapElementT& Elem); |
|---|
| 66 | |
|---|
| 67 | /// The virtual destructor. |
|---|
| 68 | virtual ~MapElementT() { } |
|---|
| 69 | |
|---|
| 70 | |
|---|
| 71 | /// The virtual copy constructor. |
|---|
| 72 | /// Creates a copy of this element that is of the *same* class as the original, even when called |
|---|
| 73 | /// via a base class pointer (the caller doesn't even need to know the exact derived class). |
|---|
| 74 | virtual MapElementT* Clone() const=0; |
|---|
| 75 | |
|---|
| 76 | /// Assigns the given element to this element. |
|---|
| 77 | /// |
|---|
| 78 | /// @param Elem The element that is to be assigned to this element. |
|---|
| 79 | /// |
|---|
| 80 | /// Elem must be of the exact same type as this element (e.g. as obtained by the Clone() method), |
|---|
| 81 | /// or else the assignment will silently succeed only partially (or not at all), |
|---|
| 82 | /// without explicit notice of the failure (except for built-in debug asserts). |
|---|
| 83 | /// |
|---|
| 84 | /// Why did we not override operator = instead? |
|---|
| 85 | /// Having a virtual assignment operator is highly confusing and typically doesn't work as expected. |
|---|
| 86 | /// See http://www.icu-project.org/docs/papers/cpp_report/the_assignment_operator_revisited.html for details. |
|---|
| 87 | /// Among the many problems, note that the different semantics between this method (it just does a "best try") |
|---|
| 88 | /// and a true assignment operator (which makes the left object computationally equivalent to the right) |
|---|
| 89 | /// is the biggest one. |
|---|
| 90 | virtual void Assign(const MapElementT* Elem); |
|---|
| 91 | |
|---|
| 92 | |
|---|
| 93 | virtual void Load_cmap(TextParserT& TP, MapDocumentT& MapDoc); |
|---|
| 94 | virtual void Save_cmap(std::ostream& OutFile, unsigned long ElemNr, const MapDocumentT& MapDoc) const; |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | /// Returns whether this element is currently selected in the map document. |
|---|
| 98 | bool IsSelected() const { return m_IsSelected; } |
|---|
| 99 | |
|---|
| 100 | /// Sets the selection state of this element. As this should always be in sync with the map document, |
|---|
| 101 | /// the map document is the only legitimate caller of this method (but there are some exceptions). |
|---|
| 102 | void SetSelected(bool Selected=true) { m_IsSelected=Selected; } |
|---|
| 103 | |
|---|
| 104 | |
|---|
| 105 | /// This method returns the "inherent" color of this map element. |
|---|
| 106 | /// The returned color should be used for rendering the map element whenever no better |
|---|
| 107 | /// (e.g. texture-mapped) alternative is available. |
|---|
| 108 | /// |
|---|
| 109 | /// @param ConsiderGroup Whether the map elements group color should be taken into account. |
|---|
| 110 | /// @returns the "inherent" color of this map element. |
|---|
| 111 | /// When the map element is in a group and ConsiderGroup is true, the group color is returned. |
|---|
| 112 | /// When the map element is an entity, the color of the entity class is returned. |
|---|
| 113 | /// Otherwise (the element is a primitive), when the map element is part of an entity, the entity color |
|---|
| 114 | /// is returned. Finally (it's a map primitive that is in the world), its native color is returned. |
|---|
| 115 | virtual wxColour GetColor(bool ConsiderGroup=true) const; |
|---|
| 116 | |
|---|
| 117 | /// Returns whether this map element is (entirely or partially) translucent. |
|---|
| 118 | /// Translucent map elements are typically implemented with "alpha blending" and require rendering in back-to-front order. |
|---|
| 119 | /// @see EditorMaterialI::IsTranslucent() |
|---|
| 120 | virtual bool IsTranslucent() const { return false; } |
|---|
| 121 | |
|---|
| 122 | virtual wxString GetDescription() const { return ""; } |
|---|
| 123 | |
|---|
| 124 | |
|---|
| 125 | GroupT* GetGroup() const { return m_Group; } ///< Returns NULL when this map element is in no group, or the pionter to the group it is a member of otherwise. |
|---|
| 126 | void SetGroup(GroupT* Group) { m_Group=Group; } ///< Sets the group this element is a member of (use NULL for "no group"). |
|---|
| 127 | bool IsVisible() const { return !m_Group || m_Group->IsVisible; } ///< Returns whether this map element is visible (in the 2D, 3D and other views). Note that the visibility does not depend on the visibility of the parent entity - in CaWE, map elements are mostly independent of their parents (and thus entities can also be "half visible" if the user wishes so). |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | /// This is periodically called in order to have the element advance its internal clock by t seconds. |
|---|
| 131 | /// The typical use case is with elements that represent models for updating the current frame in their animation sequence. |
|---|
| 132 | virtual void AdvanceTime(float t) { } |
|---|
| 133 | |
|---|
| 134 | virtual void Render2D(Renderer2DT& Renderer) const { } |
|---|
| 135 | virtual void Render3D(Renderer3DT& Renderer) const { } |
|---|
| 136 | |
|---|
| 137 | /// Returns the spatial bounding-box of this map element. |
|---|
| 138 | virtual BoundingBox3fT GetBB() const=0; |
|---|
| 139 | |
|---|
| 140 | /// Traces a ray against this map element, and returns whether it was hit. |
|---|
| 141 | /// The ray for the trace is defined by RayOrigin + RayDir*Fraction, where Fraction is a scalar >= 0. |
|---|
| 142 | /// If a hit was detected, the Fraction is returned. Hit brushes return the number of the hit face as well. |
|---|
| 143 | /// This method has been implemented mainly for "picking", that is, left-click selection in the 3D views |
|---|
| 144 | /// (it makes sure that also objects that "clip nothing" in the engine can be picked), but it can also be used for any other purpose. |
|---|
| 145 | /// |
|---|
| 146 | /// @param RayOrigin The point in world space where the ray starts. |
|---|
| 147 | /// @param RayDir A unit vector in world space that describes the direction the ray extends to. |
|---|
| 148 | /// @param Fraction On hit, the scalar along RayDir at which the hit occurred is returned here. |
|---|
| 149 | /// @param FaceNr If this map element is a brush and it was hit, the number of the hit face is returned here. |
|---|
| 150 | /// |
|---|
| 151 | /// @returns true if the ray hit this map element, false otherwise. Additional hit data (i.e. Fraction and FaceNr) |
|---|
| 152 | /// is returned via reference paramaters. |
|---|
| 153 | virtual bool TraceRay(const Vector3fT& RayOrigin, const Vector3fT& RayDir, float& Fraction, unsigned long& FaceNr) const; |
|---|
| 154 | |
|---|
| 155 | /// This method determines if this map element is intersected/affected by the specified disc in ViewWin. |
|---|
| 156 | /// The disc for the test is defined by the given center pixel and the given radius. |
|---|
| 157 | /// For example, the caller can learn by the result of this method whether the map element should respond to a mouse-click |
|---|
| 158 | /// at the same pixel. Therefore, this method can be considered as the 2D analogue of the TraceRay() method. |
|---|
| 159 | virtual bool TracePixel(const wxPoint& Pixel, int Radius, const ViewWindow2DT& ViewWin) const; |
|---|
| 160 | |
|---|
| 161 | /// Translates this element by the given vector. |
|---|
| 162 | /// @param Delta The offset by which to translate the element. |
|---|
| 163 | virtual void TrafoMove(const Vector3fT& Delta) { } |
|---|
| 164 | |
|---|
| 165 | /// Rotates this element about the given reference point. |
|---|
| 166 | /// @param RefPoint The reference point (origin) for the rotation. |
|---|
| 167 | /// @param Angles The rotation angles for the three axes. |
|---|
| 168 | virtual void TrafoRotate(const Vector3fT& RefPoint, const cf::math::AnglesfT& Angles) { } |
|---|
| 169 | |
|---|
| 170 | /// Scales this element about the given reference point. |
|---|
| 171 | /// @param RefPoint The reference point (origin) for the scale. |
|---|
| 172 | /// @param Scale The scale factors for the three axes. |
|---|
| 173 | /// @throws DivisionByZeroE, e.g. when Scale is too small and the element becomes degenerate (e.g. a brush with too small faces). |
|---|
| 174 | virtual void TrafoScale(const Vector3fT& RefPoint, const Vector3fT& Scale) { } |
|---|
| 175 | |
|---|
| 176 | /// Mirrors this element along the given mirror plane. |
|---|
| 177 | /// @param NormalAxis The number of the axis along which the normal vector of the mirror plane points: 0, 1 or 2 for the x-, y- or z-axis respectively. |
|---|
| 178 | /// @param Dist The position of the mirror plane along its normal vector, where it intersects the NormalAxis. |
|---|
| 179 | /// Note that the mirroring is not necessarily "perfect", because for some elements like models or plants, |
|---|
| 180 | /// only their point of origin can be mirrored, but not their mesh. |
|---|
| 181 | virtual void TrafoMirror(unsigned int NormalAxis, float Dist) { } |
|---|
| 182 | |
|---|
| 183 | /// Why does this method not replace all the other Trafo*() methods? |
|---|
| 184 | /// This method is the most generic, allowing transformations that e.g. are non-orthogonal (like shears or non-uniform scales). |
|---|
| 185 | /// This in turn conflicts with map primitives that can only store and deal with a restricted fixed set of transformations, |
|---|
| 186 | /// e.g. an origin, a rotation and a uniform scale. These values cannot properly be re-computed from a general matrix with |
|---|
| 187 | /// non-orthogonal basis vectors. |
|---|
| 188 | virtual void Transform(const MatrixT& Matrix) { } |
|---|
| 189 | |
|---|
| 190 | |
|---|
| 191 | unsigned int GetFrameCount() const { return m_FrameCount; } |
|---|
| 192 | void SetFrameCount(unsigned int FrameCount) { m_FrameCount=FrameCount; } |
|---|
| 193 | |
|---|
| 194 | |
|---|
| 195 | // The TypeSys related declarations for this class. |
|---|
| 196 | virtual const cf::TypeSys::TypeInfoT* GetType() const { return &TypeInfo; } |
|---|
| 197 | static void* CreateInstance(const cf::TypeSys::CreateParamsT& Params); |
|---|
| 198 | static const cf::TypeSys::TypeInfoT TypeInfo; |
|---|
| 199 | |
|---|
| 200 | |
|---|
| 201 | protected: |
|---|
| 202 | |
|---|
| 203 | bool m_IsSelected; ///< Is this element currently selected in the map document? |
|---|
| 204 | wxColour m_Color; ///< The color of this element. |
|---|
| 205 | GroupT* m_Group; ///< The group this element is in, NULL if in no group. |
|---|
| 206 | unsigned int m_FrameCount; ///< The number of the frame in which this element was last rendered in a 3D view, used in order to avoid processing/rendering it twice. |
|---|
| 207 | }; |
|---|
| 208 | |
|---|
| 209 | #endif |
|---|