00001 //------------------------------------------------------------------------ 00002 //C++ 00003 // ________ ____ ___ 00004 // | \ / | / / 00005 // +---+ \/ |/ / 00006 // +--+| |\ /| < 00007 // | || | \ / | |\ \ 00008 // | | \/ | | \ \ 00009 // \_____| |__| \__\ 00010 // Copyright 2002 00011 // Joe Michael Kniss 00012 // "All Your Base are Belong to Us" 00013 //------------------------------------------------------------------------- 00014 00015 #ifndef __RENDERABLE_002_DOT_H 00016 #define __RENDERABLE_002_DOT_H 00017 00018 #include <list> 00019 #include <vector> 00020 #include <eventGutz.h> 00021 #include <smartptr.h> 00022 #include <graphicsGutz.h> 00023 00024 //////////////////////////////////////////////////////////////////////////// 00025 /// a unique identifier for this species of object, needed 00026 /// mostly for GL style picking, since we need to know what 00027 /// kind of object was picked, so we can forward mouse/key 00028 /// events to it 00029 const unsigned int RENDERABLE_NAME = 80081355; 00030 //////////////////////////////////////////////////////////////////////////// 00031 00032 //////////////////////////////////////////////////////////////////////////// 00033 /// Renderable. 00034 /// 00035 /// This is the base class, and a new effect/renderer should sub-class from it. 00036 /// 00037 /// Please note: this object contains a gutz::Manip smart pointer, when it 00038 /// is constructed (by default) it creates a new manipulator (_manip). USE IT! 00039 /// It is generally assumed that you might want to interact with your object 00040 /// this is why we create one for you. If you just want to interact with 00041 /// your object with the least amout of effort, call setManipEventsDefault() 00042 /// and follow the notes on GL picking (below). If you don't override the 00043 /// mouse() and move() functions then events are automatically forwarded to your 00044 /// Manip. Apply your manip (using OpenGL) like this: 00045 /// \code 00046 /// glPushMatrix(); 00047 /// { 00048 /// glMultMatrixf(_manip->getWorldTransform().m); 00049 /// /* ... draw stuff ...*/ 00050 /// } 00051 /// glPopMatrix(); 00052 /// \endcode 00053 /// I usually add the "{}" around a glPush/Pop to keep the code neat and the state 00054 /// clear. Don't forget, if you want interaction using openGL, you have to push 00055 /// 2 specific unsigned int "names" on the gl-name-stack. 00056 /// 00057 /// NOTE on GL picking (gl interaction): \n 00058 /// There are 2 strict rules for GL style picking of renderables. \n 00059 /// 1) push the #RENDERABLE_NAME on the gl name stack first \n 00060 /// 2) push your (Renderable*) pointer onto the stack as an unsigned int \n 00061 /// Like this: 00062 /// \code 00063 /// glPushName(RENDERABLE_NAME); 00064 /// glPushName((unsigned int)(Renderable *)this); 00065 /// \endcode 00066 /// Item 2 is actually a little tricky. You should ALWAYS cast to 00067 /// Renderable* before casting to unsigned int. 00068 /// This is VERY important if the type you are setting up is polymorphic; 00069 /// the "this" pointer may be incorrect when we cast to "Renderable*" in 00070 /// the UI. If you cast to "Renderable*" first, any ambiguity is resolved 00071 /// and you get the right position in the class for the cast-back in the UI 00072 /// 00073 /// There is a third rule, but it is obvious:\n 00074 /// 3) Pop all names that you pushed onto the stack back off when you are 00075 /// done rendering. \n 00076 /// Like this: 00077 /// \code 00078 /// glPopName(); 00079 /// glPopName(); /// plus one pop for each additional name you added 00080 /// \endcode 00081 /// After you are done with items 1 & 2, you can push as much onto the 00082 /// stack as you like (within reason), just be sure you pop it all back off 00083 /// (item 3). \n 00084 /// 00085 /// Here is what your draw function might look like if you are using OpenGL, 00086 /// you want interaction, and you are using the _manip for the transformation: 00087 /// \code 00088 /// void draw(const gutz::RenderEvent &re) 00089 /// { 00090 /// glPushName(RENDERABLE_NAME); 00091 /// glPushName((unsigned int)(Renderable *)this); 00092 /// glPushMatrix(); 00093 /// { 00094 /// glMultMatrixf(_manip->getWorldTransform().m); 00095 /// /* ... draw your geometry ...*/ 00096 /// } 00097 /// glPopMatrix(); 00098 /// glPopName(); ///DONT FORGET THESE!!! 00099 /// glPopName(); 00100 /// } 00101 /// \endcode 00102 /// 00103 /// Why is this object "Counted", see gutz::Counted and gutz::SmartPtr for 00104 /// details on what this means. \n 00105 /// This object really needs to be counted, since it is usualy the primary 00106 /// interface to renderable objects for any framework that uses them. 00107 /// This may be problematic in situations with polymorphisim in the 00108 /// hierarchy's derivation. Oh well, need to deal with this somehow, I think 00109 /// that this kind of baddness will be rare if you can sepparate the 00110 /// appearance from the behavior/data associated with a renderable object. \n 00111 /// NOTE: Please be carefull, you need to make very sure that if a 00112 /// renderable pushes its name on the glName stack for GL style picking, 00113 /// it better have a smartptr to it somewhere, or the object that created 00114 /// it needs to do the reference counting, since the user interface is 00115 /// probably going to keep a smartptr to it too. This can lead to trouble 00116 /// if the user interface's smart pointer calls delete on the object because 00117 /// it has no references, or the objects owner deletes it. This is the 00118 /// classic smart pointer problem; bad things occur when we create objects 00119 /// on the stack, or we create objects that have automatic deletion, like 00120 /// non-smart pointer member variables. See gutz::SmartPtr & gutz::Counted 00121 /// 00122 /// See also: gutz::RenderEvent, gutz::MouseEvent, gutz::MouseMoveEvent 00123 ///////////////////////////////////////////////////////////////////////////// 00124 00125 class Renderable : public gutz::Counted { 00126 public: 00127 ~Renderable(){}; 00128 00129 /////////////////////////////////////////////////////////////////////////// 00130 ///@name DRAW! 00131 /// This is the draw function. Calling it renders the object. Pure virtual, 00132 /// you must override this function in a subclass. 00133 ///@{ 00134 virtual void draw(const gutz::RenderEvent &rs) = 0; 00135 ///@} 00136 /////////////////////////////////////////////////////////////////////////// 00137 00138 /////////////////////////////////////////////////////////////////////////// 00139 ///@name Draw on/off. 00140 ///@{ 00141 bool isOn() const { return _on; } 00142 void setOn(bool yes) { _on = yes; } 00143 ///@} 00144 /////////////////////////////////////////////////////////////////////////// 00145 00146 /////////////////////////////////////////////////////////////////////////// 00147 ///@name Delete. 00148 /// Does this object need to be removed from a render list? 00149 /// This means that the object is finished and anyone with a smart pointer 00150 /// to it needs to delete the smart pointer and stop using the renderable. 00151 ///@{ 00152 bool needsDelete() const { return _deleteMe; } 00153 void setDelete(bool yes) { _deleteMe = yes; if(yes) setOn(false); } 00154 ///@} 00155 /////////////////////////////////////////////////////////////////////////// 00156 00157 /////////////////////////////////////////////////////////////////////////// 00158 ///@name Interaction Functions 00159 /// Return true if the event was for you. By default interaction is 00160 /// forwarded to your protected manipulator (_manip). To use it 00161 /// just apply it in your draw function. However, if you don't 00162 /// add any events or call setManipEventsDefault(), you won't have 00163 /// any interaction. Override these functions in your base class 00164 /// to implement custom behaviors. 00165 //@{ 00166 virtual bool key(unsigned char k, int x, int y) { return false; } 00167 virtual bool mouse(const gutz::MouseEvent &me) { return _manip->mouse(me); } 00168 virtual bool move(const gutz::MouseMoveEvent &mme) { return _manip->move(mme); } 00169 //@} 00170 /////////////////////////////////////////////////////////////////////////// 00171 00172 /////////////////////////////////////////////////////////////////////////// 00173 ///@name Selected 00174 /// Is this object currently selected? 00175 ///@{ 00176 virtual void setSelected(bool yes) {_selected = yes;} 00177 bool isSelected() const {return _selected;} 00178 ///@} 00179 /////////////////////////////////////////////////////////////////////////// 00180 00181 /////////////////////////////////////////////////////////////////////////// 00182 ///@name Manipulator Interface 00183 ///@{ 00184 gutz::Manip *getManip() const { return _manip.getPtr(); } 00185 void setManip(gutz::Manip *const m) { _manip = m; } 00186 /// you have to call this to enable default interaction, OR 00187 /// customize the manipulators events yourself. 00188 void setManipEventsDefault() 00189 { 00190 _manip->mapEvent(gutz::GUTZ_LEFT_MOUSE, new gutz::RotateManipEvent(1.0f)); 00191 _manip->mapEvent(gutz::GUTZ_MIDDLE_MOUSE, new gutz::TransZManipEvent(1.0f)); 00192 _manip->mapEvent(gutz::GUTZ_RIGHT_MOUSE, new gutz::TransXYManipEvent(1.0f)); 00193 #if 0 00194 _manip->mapEvent(gutz::OBJ_CENT_ROT, gutz::GUTZ_LEFT_MOUSE, 1.0f); 00195 _manip->mapEvent(gutz::OBJ_STRANS_XY, gutz::GUTZ_RIGHT_MOUSE, 1.0f); 00196 _manip->mapEvent(gutz::OBJ_STRANS_XZ, gutz::GUTZ_MIDDLE_MOUSE, 1.0f); 00197 #endif 00198 } 00199 ///@} 00200 /////////////////////////////////////////////////////////////////////////// 00201 00202 protected: 00203 /////////////////////////////////////////////////////////////////////////// 00204 /// since this is a base class/interface it cannot be publicly 00205 /// created. Only derived classes can construct this guy. 00206 Renderable() 00207 : _on(true), 00208 _selected(false), 00209 _deleteMe(false), 00210 _manip(new gutz::Manip()) 00211 {} 00212 /////////////////////////////////////////////////////////////////////////// 00213 00214 /////////////////////////////////////////////////////////////////////////// 00215 ///@name copy/assign 00216 ///@{ 00217 Renderable(const Renderable &r) 00218 : _on(r._on), 00219 _selected(false), 00220 _manip(new gutz::Manip()) 00221 { 00222 if(r._manip) 00223 *_manip = *(r._manip); 00224 } 00225 Renderable &operator=(const Renderable &r) 00226 { 00227 _on = r._on; 00228 if(r._manip) 00229 *_manip = *(r._manip); 00230 return *this; 00231 } 00232 ///@} 00233 /////////////////////////////////////////////////////////////////////////// 00234 00235 bool _on; ///<is this renderable currently "render-able"? 00236 bool _selected; ///<is this renderable selected? 00237 bool _deleteMe; ///<does this object need to be deleted? 00238 00239 /// You get a manipulator free, no charge 00240 gutz::ManipSP _manip; 00241 00242 private: 00243 }; 00244 00245 typedef gutz::SmartPtr<Renderable> RenderableSP; 00246 00247 /////////////////////////////////////////////////////////////////////////// 00248 ///@name Lists/Vectors of renderables typedefined, for ease of use 00249 //@{ 00250 00251 typedef std::list<RenderableSP> RenderableList; 00252 typedef std::list<RenderableSP>::iterator RenderableListIter; 00253 00254 typedef std::vector<RenderableSP> RenderableVec; 00255 typedef std::vector<RenderableSP>::iterator RenderableVecIter; 00256 //@} 00257 /////////////////////////////////////////////////////////////////////////// 00258 00259 00260 #endif 00261