00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Cristin Barghiel 00008 * Side Effects Software Inc. 00009 * 477 Richmond Street West 00010 * Toronto, Ontario 00011 * Canada M5V 3E7 00012 * 416-504-9876 00013 * 00014 * NAME: Domain pasting Library (C++) 00015 * 00016 * COMMENTS: Specialized frame collection. Based on a tree structure. 00017 * 00018 */ 00019 00020 #ifndef __GP_FrameHierarchy_h__ 00021 #define __GP_FrameHierarchy_h__ 00022 00023 #include "GP_API.h" 00024 #include <iostream.h> 00025 #include "GP_CorrectionFrame.h" 00026 00027 class UT_IStream; 00028 class GP_Domain; 00029 class GP_DomainDAG; 00030 class GP_NodeTree; 00031 00032 class GP_API GP_FrameHierarchyFlags 00033 { 00034 public: 00035 GP_FrameHierarchyFlags() 00036 { 00037 dirty = 0; 00038 modified = 0; 00039 } 00040 unsigned dirty :1, // xform changed 00041 modified :1; // visited by update method 00042 }; 00043 00044 class GP_API GP_FrameHierarchy 00045 { 00046 public: 00047 // Class c-tors and d-tor. 00048 GP_FrameHierarchy(void); 00049 GP_FrameHierarchy(const GP_XformHandle &rootxform); 00050 GP_FrameHierarchy(const GP_FrameHierarchy &h); // shallow! 00051 virtual ~GP_FrameHierarchy(void); 00052 00053 // Insert the root node, which will replace the existing root. Return 0 if 00054 // successful and -1 otherwise. 00055 int insertRoot(GP_CorrectionFrame &root); 00056 00057 // Insert child into this hierarchy and return 0 if OK, -1 if failure. 00058 // The child must not belong to another hierarchy at this point. Checking 00059 // for duplicates is OFF by default. 00060 int insert(GP_FrameHierarchy &child, int check = 0, 00061 int wcorrection = 1); 00062 00063 // Remove child, update the hierarchy the child's world xform. The child 00064 // becomes stand-alone. The method returns the child if OK and 0 otherwise. 00065 GP_FrameHierarchy *remove(GP_FrameHierarchy &child); 00066 00067 // Same as removal, only the child's anchor is not updated. Useful for 00068 // imminent re-attachment. 00069 GP_FrameHierarchy *detach(GP_FrameHierarchy &child); 00070 00071 // Remove child w/o updating the child's state -- just cut him off. 00072 // The method returns the child if OK and 0 otherwise. 00073 GP_FrameHierarchy *discard(GP_FrameHierarchy &child); 00074 00075 // Isolate ourselves by removing ourselves from the tree of hierarchies 00076 // and letting our parent and all of our children know. We also reset 00077 // myDAG to zero. 00078 void isolate(void); 00079 00080 // Move child to the given hierarchy, making all the necessary updates. 00081 // Return 0 if OK and -1 otherwise. The child should be ours initially. 00082 int move(GP_FrameHierarchy &child, GP_FrameHierarchy &to) 00083 { 00084 return detach(child) ? to.insert(child) : -1; 00085 } 00086 00087 // Update this collection starting at the given frame or at the root 00088 // if the frame is nil. We assume the frame is in the collection. 00089 void update(const GP_Frame * = 0) 00090 { 00091 if (myAnchor->myFlags.dirty) 00092 myAnchor->traverseUpdateWorld(0); 00093 } 00094 00095 // Hierarchy traversal method (depth-first): 00096 void apply(void (f)(GP_FrameHierarchy*,void*), void *data); 00097 00098 // I/O functions returning 0 if OK and -1 otherwise. They operate ONLY 00099 // on the root. 00100 int save(ostream &os, int binary = 0) const; 00101 bool load(UT_IStream &is); 00102 00103 // Copy just our root from the source's root: 00104 void copyFrom(const GP_FrameHierarchy &src); 00105 00106 // Copy the links of the frames stored in destnodes. Returns a pointer to 00107 // the root frame in destnodes. 00108 GP_FrameHierarchy *copyLinks(GP_NodeTree &destnodes) const; 00109 00110 // Search the whole hierarchy (not just immediate children), or just the 00111 // children: 00112 int contains(const GP_FrameHierarchy &descendent) const; 00113 int hasChild(const GP_FrameHierarchy &child ) const 00114 { 00115 int f = 0; 00116 GP_FrameHierarchy *h = myChildren; 00117 00118 while (h && !(f = (h==&child))) h = h->mySibling; 00119 return f; 00120 } 00121 00122 // Find out if we have any children or a parent: 00123 int hasParent () const { return myParent ? 1 : 0; } 00124 int hasChildren() const { return myChildren ? 1 : 0; } 00125 00126 // Access some of the internal hierarchies we know about: 00127 GP_FrameHierarchy *anchor (void) const { return myAnchor; } 00128 GP_FrameHierarchy *parent (void) const { return myParent; } 00129 GP_FrameHierarchy *sibling (void) const { return mySibling; } 00130 GP_FrameHierarchy *children(void) const { return myChildren; } 00131 00132 // Const reference to the root. 00133 const GP_CorrectionFrame &root() const { return myRoot; } 00134 00135 // Query or set the "modified" flag. If true, it means that either us 00136 // or our ancestors had changed at one point in time. It does not mean 00137 // we're still dirty. Use the dirty() method for that. 00138 int modified(void) const { return myFlags.modified; } 00139 void modified(int m) { myFlags.modified = m; } 00140 00141 // Query or set the domain information stored in this node: 00142 GP_Domain *domain(void) const { return myDomain; } 00143 void domain(GP_Domain *d) { myDomain = d; } 00144 00145 // Query or set the domain DAG information stored in this node. 00146 // This is to be used only by the anchor! 00147 GP_DomainDAG *dag(void) const { return myDAG; } 00148 void dag(GP_DomainDAG *d) { myDAG = d; } 00149 00150 // Some frame's transformation has changed. Let us know. 00151 int isDirty(void) const { return myFlags.dirty; } 00152 void dirty(void) 00153 { 00154 myFlags.dirty = 1; 00155 myAnchor->myFlags.dirty = 1; // very important! 00156 } 00157 00158 00159 protected: 00160 private: 00161 GP_CorrectionFrame myRoot; // root node. kids are hierarchies 00162 00163 GP_FrameHierarchy *myAnchor; // root-most hierar. we're in. never 0. 00164 GP_FrameHierarchy *myParent; // parent "node" 00165 GP_FrameHierarchy *mySibling; // sibling "node" 00166 GP_FrameHierarchy *myChildren; // hierarchy of children 00167 00168 GP_Domain *myDomain; // domain associated with frame 00169 GP_DomainDAG *myDAG; // this ptr is set only for the ANCHOR! 00170 00171 GP_FrameHierarchyFlags myFlags; 00172 00173 00174 // Special internal c-tor. 00175 GP_FrameHierarchy(const GP_FrameHierarchy &hierarchy, 00176 const GP_CorrectionFrame &root); 00177 00178 // Traverse the hierarchy from us to all the descendents and update 00179 // everyone's world transforms, then clear everyone's dirty flags. 00180 void traverseUpdateWorld(int history = 0); 00181 00182 // Link an immediate child to us. Really meant ot be used internally. 00183 void attach(GP_FrameHierarchy &child) 00184 { 00185 child.myParent = this; 00186 child.mySibling = myChildren; 00187 myChildren = &child; 00188 } 00189 00190 // Set the anchor to us and all our descendents: 00191 void anchor(GP_FrameHierarchy *a) 00192 { 00193 myAnchor = a; 00194 GP_FrameHierarchy *h = myChildren; 00195 while (h) 00196 { 00197 h->anchor(a); 00198 h = h->mySibling; 00199 } 00200 } 00201 00202 // Tell a frame if it's in this list or not: 00203 void link (GP_Frame &frame) { frame.hierarchy(this); } 00204 void unlink(GP_Frame &frame) { frame.hierarchy( 0 ); } 00205 }; 00206 00207 #endif
1.5.9