convert line ends
[canaan.git] / prj / cam / src / editor / linkdraw.cpp
blob1a768c562870c1549c99ed415910dd750ce346ff
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
6 ////////////////////////////////////////////////////////////////////////////////
7 // $Header: r:/t2repos/thief2/src/editor/linkdraw.cpp,v 1.7 2000/02/11 14:27:44 bfarquha Exp $
8 //
9 // Link-drawing system
12 #include <lg.h>
13 #include <string.h>
15 #include <appagg.h>
16 #include <comtools.h>
18 #include <dlist.h>
19 #include <relation.h>
20 #include <lnkquery.h>
21 #include <linkbase.h>
22 #include <linkman.h>
24 #include <wrtype.h>
25 #include <objpos.h>
27 #include <ged_line.h>
28 #include <linkdraw.h>
30 #include <editbr_.h>
31 #include <editbr.h>
32 #include <brlist.h>
33 #include <brinfo.h>
35 // Must be last header
36 #include <dbmem.h>
39 class cLinkDraw;
41 typedef cDList<cLinkDraw, 0> cLinkDrawList;
42 typedef cDListNode<cLinkDraw, 0> cLinkDrawNode;
44 struct sColor
46 int r, g, b;
47 sColor(int rr = 0, int gg = 0, int bb = 0) : r(rr),g(gg),b(bb) {};
50 class cLinkDraw : public cLinkDrawNode
52 public:
53 char name[64];
54 sColor color;
58 static cLinkDrawList LinkDrawList;
60 ////////////////////////////////////////////////////////////////////////////////
62 void InitDrawnRelations()
64 // Hey, we might want to do something here someday...
67 ////////////////////////////////////////
69 void TermDrawnRelations()
71 cLinkDraw *pLinkDraw;
73 pLinkDraw = LinkDrawList.GetFirst();
74 while (pLinkDraw != NULL)
76 delete LinkDrawList.Remove(pLinkDraw);
77 pLinkDraw = LinkDrawList.GetFirst();
81 ////////////////////////////////////////
83 void ResetDrawnRelations()
85 TermDrawnRelations();
86 InitDrawnRelations();
89 ////////////////////////////////////////////////////////////////////////////////
91 static cLinkDraw *GetLinkDrawNode(const char *name)
93 cLinkDraw *pLinkDraw;
95 pLinkDraw = LinkDrawList.GetFirst();
96 while (pLinkDraw != NULL)
98 if (!strcmp(name, pLinkDraw->name))
99 return pLinkDraw;
101 pLinkDraw = pLinkDraw->GetNext();
104 return NULL;
107 ////////////////////////////////////////
109 void AddDrawnRelation(const char *name, ubyte r, ubyte g, ubyte b)
111 cLinkDraw *pLinkDraw;
113 if (GetLinkDrawNode(name) == NULL)
115 pLinkDraw = new cLinkDraw;
117 strncpy(pLinkDraw->name, name, 64);
118 pLinkDraw->color = sColor(r,g,b);
120 LinkDrawList.Append(pLinkDraw);
124 ////////////////////////////////////////
126 void AddDrawnRelationID(RelationID relationID, ubyte r, ubyte g, ubyte b)
128 AutoAppIPtr_(LinkManager, pLinkMan);
130 IRelation *rel = pLinkMan->GetRelation(relationID);
132 if (rel != NULL)
133 AddDrawnRelation(rel->Describe()->name, r, g, b);
134 else
135 Warning(("AddDrawnRelationID: Relation id %d not found!\n", relationID));
137 SafeRelease(rel);
140 ////////////////////////////////////////
142 void RemoveDrawnRelation(const char *name)
144 cLinkDraw *pLinkDraw;
146 if ((pLinkDraw = GetLinkDrawNode(name)) != NULL)
147 delete LinkDrawList.Remove(pLinkDraw);
150 ////////////////////////////////////////
152 void RemoveDrawnRelationID(RelationID relationID)
154 AutoAppIPtr_(LinkManager, pLinkMan);
156 IRelation *rel = pLinkMan->GetRelation(relationID);
158 if (rel != NULL)
159 RemoveDrawnRelation(rel->Describe()->name);
160 else
161 Warning(("RemoveDrawnRelationID: Relation id %d not found!\n", relationID));
163 SafeRelease(rel);
166 ////////////////////////////////////////////////////////////////////////////////
168 // from brrend.c:
169 extern "C"
171 bool pointOBBIntersect(editBrush *point, editBrush *brush);
174 // Determine if link originates inside brush.
175 static BOOL LinkOriginatesInBrush(sLink *pLink, editBrush *us)
177 editBrush point;
178 point.pos = ObjPosGet(pLink->source)->loc.vec;
179 return pointOBBIntersect(&point, us);
183 int g_nLinkDrawSourceId = 0;
184 int g_nLinkDrawSplitId = 0;
187 // Is this id a child of g_nLinkDrawSplitId?
188 // *** We're assuming there are no circular patrols that don't include startid
189 // To do this right, we'd need to mark previously visited nodes, but that's probably overkill
190 // given our problem space. Still, let's at least not crash:
192 static int nCrashDetector;
194 static BOOL IsChild(ObjID startid, ObjID id, IRelation *pRelation, int nLoopCount = 0)
196 if (startid==id) // We've gone circular, or are just beginning.
198 if (nLoopCount)
200 nCrashDetector--;
201 return FALSE;
203 else
204 nLoopCount++;
207 if (nCrashDetector > 40)
208 return FALSE;
210 nCrashDetector++;
212 ILinkQuery *query = pRelation->Query(LINKOBJ_WILDCARD, id);
214 for (; !query->Done(); query->Next())
216 sLink link;
217 query->Link(&link);
218 if (link.source == g_nLinkDrawSplitId)
220 SafeRelease(query);
221 return TRUE;
223 else if (IsChild(startid, link.source, pRelation, nLoopCount))
225 SafeRelease(query);
226 return TRUE;
230 SafeRelease(query);
231 nCrashDetector--;
232 return FALSE;
236 // Is this id a parent of g_nLinkDrawSplitId?
237 // *** We're assuming there are no circular patrols that don't include startid
238 // To do this right, we'd need to mark previously visited nodes, but that's probably overkill
239 // given our problem space.
240 static BOOL IsParent(ObjID startid, ObjID id, IRelation *pRelation, int nLoopCount = 0)
242 if (startid==id) // We've gone circular, or are just beginning.
244 if (nLoopCount)
246 nCrashDetector--;
247 return FALSE;
249 else
250 nLoopCount++;
253 if (nCrashDetector > 40)
254 return FALSE;
256 nCrashDetector++;
258 ILinkQuery *query = pRelation->Query(id, LINKOBJ_WILDCARD);
260 for (; !query->Done(); query->Next())
262 sLink link;
263 query->Link(&link);
264 if (link.dest == g_nLinkDrawSplitId)
266 SafeRelease(query);
267 return TRUE;
269 else if (IsParent(startid, link.dest, pRelation, nLoopCount))
271 SafeRelease(query);
272 return TRUE;
276 SafeRelease(query);
277 nCrashDetector--;
278 return FALSE;
282 // This is SLOW, but then again, it doesn't need to be fast.
283 // See if this Obj is anywhere on branching relation.
284 static BOOL ObjIsOnSplitPath(ObjID id, IRelation *pRelation)
286 if (id==g_nLinkDrawSplitId)
287 return TRUE;
289 nCrashDetector = 0;
290 if (IsParent(id, id, pRelation))
291 return TRUE;
293 nCrashDetector = 0;
294 if (IsChild(id, id, pRelation))
295 return TRUE;
297 return FALSE;
301 // Go through and see if any brushes are me-only. If so, only draw links that originate within this brush.
302 static BOOL LinkIsDrawable(sLink *pLink, IRelation *pRelation)
304 editBrush *us;
305 int hIter;
306 BOOL bFoundBrush = FALSE;
308 if ((g_nLinkDrawSourceId > 0) && (pLink->source != g_nLinkDrawSourceId))
309 return FALSE;
311 if ((g_nLinkDrawSplitId > 0) && !ObjIsOnSplitPath(pLink->source, pRelation))
312 return FALSE;
314 us=blistIterStart(&hIter);
315 while ((us!=NULL) && !bFoundBrush)
317 if ((brushGetType(us)==brType_HOTREGION) && brHot_IsMEONLY(us))
319 bFoundBrush = TRUE;
320 blistIterDone(hIter);
322 else
323 us=blistIterNext(hIter);
326 return !bFoundBrush || LinkOriginatesInBrush(pLink, us);
331 void DrawRelations()
333 AutoAppIPtr_(LinkManager, pLinkMan);
334 cLinkDraw *pLinkDraw;
336 gedDeleteChannelLines(1<<LINE_CH_LINKS);
338 ged_line_load_channel = LINE_CH_LINKS;
339 ged_line_view_channels |= (1<<LINE_CH_LINKS);
341 pLinkDraw = LinkDrawList.GetFirst();
342 while (pLinkDraw != NULL)
344 IRelation *pRelation = pLinkMan->GetRelationNamed(pLinkDraw->name);
346 if (pRelation != NULL)
348 ILinkQuery *query = pRelation->Query(LINKOBJ_WILDCARD, LINKOBJ_WILDCARD);
350 for (; !query->Done(); query->Next())
352 sLink link;
353 query->Link(&link);
355 if (LinkIsDrawable(&link, pRelation))
356 gedLineAddRGB(&ObjPosGet(link.source)->loc.vec, &ObjPosGet(link.dest)->loc.vec, LINE_FLG_DIR, pLinkDraw->color.r, pLinkDraw->color.g, pLinkDraw->color.b);
359 SafeRelease(query);
361 else
362 Warning(("DrawRelations: relation %s not found!\n", pLinkDraw->name));
364 SafeRelease(pRelation);
366 pLinkDraw = pLinkDraw->GetNext();
370 ////////////////////////////////////////////////////////////////////////////////
372 BOOL ObjHasDrawnLinks(ObjID objID)
374 AutoAppIPtr_(LinkManager, pLinkMan);
375 cLinkDraw *pLinkDraw;
376 ILinkQuery *query;
378 pLinkDraw = LinkDrawList.GetFirst();
379 while (pLinkDraw != NULL)
381 IRelation *pRelation = pLinkMan->GetRelationNamed(pLinkDraw->name);
383 if (pRelation != NULL)
385 query = pRelation->Query(objID, LINKOBJ_WILDCARD);
387 if (!query->Done())
389 SafeRelease(query);
390 SafeRelease(pRelation);
392 return TRUE;
395 SafeRelease(query);
397 query = pRelation->Query(LINKOBJ_WILDCARD, objID);
399 if (!query->Done())
401 SafeRelease(query);
402 SafeRelease(pRelation);
404 return TRUE;
407 SafeRelease(query);
409 else
410 Warning(("DrawRelations: relation %s not found!\n", pLinkDraw->name));
412 SafeRelease(pRelation);
414 pLinkDraw = pLinkDraw->GetNext();
417 return FALSE;