more patches: targetname/killtarget handling fixes
[divverent/nexuiz.git] / misc / gtkradiant / singlepatches / gtkradiant-targetname.diff
1 Index: radiant/map.cpp
2 ===================================================================
3 --- radiant/map.cpp     (revision 304)
4 +++ radiant/map.cpp     (working copy)
5 @@ -270,6 +270,100 @@
6    ents->RemoveAll();
7  }
8  
9 +void Map_DoTargetFix(entity_t *e, const char *target, int num_ents, CPtrArray *ents, GPtrArray *new_ents)
10 +{
11 +       int j;
12 +       int id;
13 +       char newtarget[128];
14 +       entity_t *e_target;
15 +
16 +       qboolean targetnameFound = FALSE;
17 +       qboolean targetFound = FALSE;
18 +       qboolean colliding = FALSE;
19 +
20 +       if(!target)
21 +               return;
22 +       if(!*target)
23 +               return;
24 +
25 +       target = g_strdup(target);
26 +
27 +       // check the current map entities for an actual collision
28 +       for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
29 +       {
30 +               if(
31 +                       !strcmp(target, ValueForKey(e_target, "target"))
32 +                       ||
33 +                       !strcmp(target, ValueForKey(e_target, "killtarget"))
34 +               )
35 +               {
36 +                       // make sure the collision is not between two imported entities
37 +                       for(j=0; j<(int)new_ents->len; j++)
38 +                       {
39 +                               if(e_target == g_ptr_array_index(new_ents, j))
40 +                               {
41 +                                       targetFound = true;
42 +                                       goto no_collision_yet_1;
43 +                               }
44 +                       }
45 +                       colliding = TRUE;
46 +no_collision_yet_1:
47 +                       ;
48 +               }
49 +               if(
50 +                       !strcmp(target, ValueForKey(e_target, "targetname"))
51 +               )
52 +               {
53 +                       // make sure the collision is not between two imported entities
54 +                       for(j=0; j<(int)new_ents->len; j++)
55 +                       {
56 +                               if(e_target == g_ptr_array_index(new_ents, j))
57 +                               {
58 +                                       targetnameFound = true;
59 +                                       goto no_collision_yet_2;
60 +                               }
61 +                       }
62 +                       colliding = TRUE;
63 +no_collision_yet_2:
64 +                       ;
65 +               }
66 +       }
67 +
68 +       // find the matching targeted entity(s)
69 +       if(colliding && targetFound && targetnameFound)
70 +       {
71 +               // We got a collision
72 +               // first look for a non-conflicting target name
73 +               id = GetUniqueTargetId(1);
74 +               sprintf(newtarget, "t%i", id);
75 +
76 +               for(j=num_ents-1; j>0; j--)
77 +               {
78 +                       e_target = (entity_t*)ents->GetAt(j);
79 +                       if(e_target != NULL)
80 +                       {
81 +                               const char *targetname = ValueForKey(e_target, "targetname");
82 +                               if( (targetname != NULL) && (strcmp(target, targetname) == 0) ) 
83 +                               {
84 +                                       SetKeyValue(e_target, "targetname", newtarget);
85 +                               }
86 +                               targetname = ValueForKey(e_target, "target");
87 +                               if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
88 +                               {
89 +                                       SetKeyValue(e_target, "target", newtarget);
90 +                               }
91 +                               targetname = ValueForKey(e_target, "killtarget");
92 +                               if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
93 +                               {
94 +                                       SetKeyValue(e_target, "killtarget", newtarget);
95 +                               }
96 +                       }
97 +               }
98 +       }
99 +
100 +       g_free(target);
101 +}
102 +
103  /*!\todo Possibly make the import Undo-friendly by calling Undo_End for new brushes and ents */
104  void Map_ImportEntities(CPtrArray *ents, bool bAddSelected = false)
105  {
106 @@ -466,60 +560,27 @@
107      }
108      else
109      {
110 -      // fix target/targetname collisions
111 -      if ((g_PrefsDlg.m_bDoTargetFix) && (strcmp(ValueForKey(e, "target"), "") != 0))
112 -      {
113 -        GPtrArray *t_ents = g_ptr_array_new();
114 -        entity_t *e_target;
115 -        const char *target = ValueForKey(e, "target");
116 -        qboolean bCollision=FALSE;
117 +      // keep a list of ents added to avoid testing collisions against them
118 +      g_ptr_array_add(new_ents, (gpointer)e);
119  
120 -        // check the current map entities for an actual collision
121 -        for (e_target = entities.next; e_target != &entities; e_target = e_target->next)
122 -        {
123 -          if(!strcmp(target, ValueForKey(e_target, "target")))
124 -          {
125 -            bCollision = TRUE;
126 -            // make sure the collision is not between two imported entities
127 -            for(j=0; j<(int)new_ents->len; j++)
128 -            {
129 -              if(e_target == g_ptr_array_index(new_ents, j))
130 -                bCollision = FALSE;
131 -            }
132 -          }
133 -        }
134 -
135 -        // find the matching targeted entity(s)
136 -        if(bCollision)
137 -        {
138 -          for(j=num_ents-1; j>0; j--)
139 -          {
140 -            e_target = (entity_t*)ents->GetAt(j);
141 -            if(e_target != NULL && e_target != e)
142 -            {
143 -              const char *targetname = ValueForKey(e_target, "targetname");
144 -              if( (targetname != NULL) && (strcmp(target, targetname) == 0) )
145 -                g_ptr_array_add(t_ents, (gpointer)e_target);
146 -            }
147 -          }
148 -          if(t_ents->len > 0)
149 -          {
150 -            // link the first to get a unique target/targetname
151 -            Entity_Connect(e, (entity_t*)g_ptr_array_index(t_ents,0));
152 -            // set the targetname of the rest of them manually
153 -            for(j = 1; j < (int)t_ents->len; j++)
154 -              SetKeyValue( (entity_t*)g_ptr_array_index(t_ents, j), "targetname", ValueForKey(e, "target") );
155 -          }
156 -          g_ptr_array_free(t_ents, FALSE);
157 -        }
158 -      }
159 -
160        // add the entity to the end of the entity list
161        Entity_AddToList(e, &entities);
162        g_qeglobals.d_num_entities++;
163  
164 -      // keep a list of ents added to avoid testing collisions against them
165 -      g_ptr_array_add(new_ents, (gpointer)e);
166 +      // fix target/targetname collisions
167 +      if (g_PrefsDlg.m_bDoTargetFix)
168 +         {
169 +                 const char *target;
170 +
171 +                 target = ValueForKey(e, "target");
172 +                 Map_DoTargetFix(e, target, num_ents, ents, new_ents);
173 +
174 +                 target = ValueForKey(e, "killtarget");
175 +                 Map_DoTargetFix(e, target, num_ents, ents, new_ents);
176 +
177 +                 target = ValueForKey(e, "targetname");
178 +                 Map_DoTargetFix(e, target, num_ents, ents, new_ents);
179 +         }
180      }
181    }
182    g_ptr_array_free(new_ents, FALSE);
183 Index: radiant/drag.cpp
184 ===================================================================
185 --- radiant/drag.cpp    (revision 304)
186 +++ radiant/drag.cpp    (working copy)
187 @@ -255,54 +255,6 @@
188  
189  entity_t *peLink;
190  
191 -void UpdateTarget(vec3_t origin, vec3_t dir)
192 -{
193 -       trace_t t;
194 -       entity_t *pe;
195 -       int i;
196 -       char sz[128];
197 -
198 -       t = Test_Ray (origin, dir, 0);
199 -
200 -       if (!t.brush)
201 -               return;
202 -
203 -       pe = t.brush->owner;
204 -
205 -       if (pe == NULL)
206 -               return;
207 -
208 -       // is this the first?
209 -       if (peLink != NULL)
210 -       {
211 -
212 -               // Get the target id from out current target
213 -               // if there is no id, make one
214 -
215 -               i = IntForKey(pe, "target");
216 -               if (i <= 0)
217 -               {
218 -                       i = GetUniqueTargetId(1);
219 -                       sprintf(sz, "%d", i);
220 -
221 -                       SetKeyValue(pe, "target", sz);
222 -               }
223 -
224 -               // set the target # into our src
225 -
226 -               sprintf(sz, "%d", i);
227 -               SetKeyValue(peLink, "targetname", sz);
228 -
229 -               Sys_UpdateWindows(W_ENTITY);
230 -
231 -       }
232 -
233 -       // promote the target to the src
234 -
235 -       peLink = pe;
236 -
237 -}
238 -
239  /*
240  ===========
241  Drag_Begin
242 Index: radiant/xywindow.cpp
243 ===================================================================
244 --- radiant/xywindow.cpp        (revision 304)
245 +++ radiant/xywindow.cpp        (working copy)
246 @@ -270,16 +270,17 @@
247  void DrawPathLines (void)
248  {
249    int       i, j, k;
250 -  vec3_t    mid, mid1;
251 +  vec3_t    mid, mid1, v;
252    entity_t *se, *te;
253    brush_t   *sb, *tb;
254    const char    *psz;
255 -  vec3_t    dir, s1, s2;
256 +  vec3_t    dir, s1, s2, dirortho;
257    vec_t len, f;
258    int       arrows;
259    int           num_entities;
260    const char        *ent_target[MAX_MAP_ENTITIES];
261    entity_t  *ent_entity[MAX_MAP_ENTITIES];
262 +  int lines;
263  
264    if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS)
265    {
266 @@ -295,6 +296,12 @@
267        ent_entity[num_entities] = te;
268        num_entities++;
269      }
270 +    ent_target[num_entities] = ValueForKey (te, "killtarget");
271 +    if (ent_target[num_entities][0])
272 +    {
273 +      ent_entity[num_entities] = te;
274 +      num_entities++;
275 +    }
276    }
277  
278    for (se = entities.next ; se != &entities ; se = se->next)
279 @@ -308,6 +315,9 @@
280      if (sb == &se->brushes)
281        continue;
282  
283 +       for (i=0 ; i<3 ; i++)
284 +               mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
285 +
286      for (k=0 ; k<num_entities ; k++)
287      {
288        if (strcmp (ent_target[k], psz))
289 @@ -318,14 +328,20 @@
290        if (tb == &te->brushes)
291          continue;
292  
293 -      for (i=0 ; i<3 ; i++)
294 -        mid[i] = (sb->mins[i] + sb->maxs[i])*0.5;
295 +         lines = 0;
296 +         if(!strcmp(ValueForKey(te, "target"), psz))
297 +                 lines += 1;
298 +         if(!strcmp(ValueForKey(te, "killtarget"), psz))
299 +                 lines += 2;
300  
301        for (i=0 ; i<3 ; i++)
302          mid1[i] = (tb->mins[i] + tb->maxs[i])*0.5;
303  
304        VectorSubtract (mid1, mid, dir);
305        len = VectorNormalize (dir, dir);
306 +         dirortho[0] = -dir[1];
307 +         dirortho[1] = dir[0];
308 +         dirortho[2] = 0;
309        s1[0] = -dir[1]*8 + dir[0]*8;
310        s2[0] = dir[1]*8 + dir[0]*8;
311        s1[1] = dir[0]*8 + dir[1]*8;
312 @@ -334,8 +350,13 @@
313        qglColor3f (se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
314  
315        qglBegin(GL_LINES);
316 -      qglVertex3fv(mid);
317 -      qglVertex3fv(mid1);
318 +         for(i = -lines + 1; i < lines; i += 2)
319 +         {
320 +                 VectorMA(mid, i, dirortho, v);
321 +                 qglVertex3fv(v);
322 +                 VectorMA(mid1, i, dirortho, v);
323 +                 qglVertex3fv(v);
324 +         }
325  
326        arrows = (int)(len / 256) + 1;
327  
328 Index: radiant/targetname.cpp
329 ===================================================================
330 --- radiant/targetname.cpp      (revision 304)
331 +++ radiant/targetname.cpp      (working copy)
332 @@ -24,11 +24,11 @@
333  /*!
334  connects two entities creating a unique target/targetname value 
335  */
336 -void Entity_Connect(entity_t *e1, entity_t *e2)
337 +void Entity_Connect(entity_t *e1, entity_t *e2, bool kill)
338  {
339    const char *maptarget;
340    char newtarget[16];
341 -  int maxtarget=0;  // highest t# value in the map
342 +  int id=0;  // highest t# value in the map
343    entity_t *e;      // map entities
344  
345    if (e1 == e2)
346 @@ -39,47 +39,54 @@
347                 return;
348         }
349  
350 -  for (e=entities.next ; e != &entities ; e=e->next)
351 -  {
352 -    maptarget = ValueForKey (e, "target");
353 -    if (maptarget && maptarget[0])
354 -    {
355 -      int targetnum = atoi(maptarget+1);
356 -      if (targetnum > maxtarget)
357 -        maxtarget = targetnum;
358 -    }
359 -  }
360 -  sprintf (newtarget, "t%i", maxtarget+1);
361 +       id = GetUniqueTargetId(1);
362 +       sprintf (newtarget, "t%i", id);
363    
364  #ifdef _DEBUG
365    Sys_Printf("Connecting entities with new target/targetname: %s\n", newtarget);
366  #endif  
367    
368 -       SetKeyValue (e1, "target", newtarget);
369 +       if(kill)
370 +               SetKeyValue (e1, "killtarget", newtarget);
371 +       else
372 +               SetKeyValue (e1, "target", newtarget);
373         SetKeyValue (e2, "targetname", newtarget);
374  }
375  
376 +static int TargetIdForKey(entity_t *pe, const char *key)
377 +{
378 +       const char *p = ValueForKey(pe, key);
379 +       if(!p)
380 +               return 0;
381 +       if(!*p)
382 +               return 0;
383 +       return atoi(p + 1);
384 +}
385 +
386  int GetUniqueTargetId(int iHint)
387  {
388 -       int iMin, iMax, i;
389 +       int iMax, i;
390         bool fFound;
391         entity_t *pe;
392         
393         fFound = FALSE;
394         pe = entities.next;
395 -       iMin = 0; 
396         iMax = 0;
397         
398         for (; pe != NULL && pe != &entities ; pe = pe->next)
399         {
400 -               i = IntForKey(pe, "target");
401 -               if (i)
402 -               {
403 -                       iMin = MIN(i, iMin);
404 -                       iMax = MAX(i, iMax);
405 -                       if (i == iHint)
406 -                               fFound = TRUE;
407 -               }
408 +               i = TargetIdForKey(pe, "target");
409 +               iMax = MAX(i, iMax);
410 +               if (i == iHint)
411 +                       fFound = TRUE;
412 +               i = TargetIdForKey(pe, "targetname");
413 +               iMax = MAX(i, iMax);
414 +               if (i == iHint)
415 +                       fFound = TRUE;
416 +               i = TargetIdForKey(pe, "killtarget");
417 +               iMax = MAX(i, iMax);
418 +               if (i == iHint)
419 +                       fFound = TRUE;
420         }
421  
422         if (fFound)
423 Index: radiant/qe3.cpp
424 ===================================================================
425 --- radiant/qe3.cpp     (revision 304)
426 +++ radiant/qe3.cpp     (working copy)
427 @@ -704,7 +704,7 @@
428  from the first selected to the secon
429  ===============
430  */
431 -void ConnectEntities (void)
432 +void ConnectEntities (bool kill)
433  {
434         entity_t        *e1, *e2;
435         const char              *target;
436 @@ -734,7 +734,7 @@
437                 return;
438         }
439  
440 -  target = ValueForKey (e1, "target");
441 +  target = ValueForKey (e1, kill ? "killtarget" : "target");
442    if (target && target[0])
443      newtarg = g_strdup(target);
444    else
445 @@ -743,12 +743,12 @@
446      if(target && target[0])
447        newtarg = g_strdup(target);
448      else
449 -      Entity_Connect(e1, e2);
450 +      Entity_Connect(e1, e2, kill);
451    }
452  
453    if(newtarg != NULL)
454    {
455 -    SetKeyValue(e1, "target", newtarg);
456 +    SetKeyValue(e1, kill ? "killtarget" : "target", newtarg);
457      SetKeyValue(e2, "targetname", newtarg);
458      g_free(newtarg);
459    }
460 Index: radiant/qe3.h
461 ===================================================================
462 --- radiant/qe3.h       (revision 304)
463 +++ radiant/qe3.h       (working copy)
464 @@ -229,7 +229,7 @@
465  void SelectEdgeByRay (vec3_t org, vec3_t dir);
466  void SelectVertexByRay (vec3_t org, vec3_t dir);
467  
468 -void ConnectEntities (void);
469 +void ConnectEntities (bool kill = false);
470  
471  extern int     update_bits;
472  
473 @@ -878,7 +878,7 @@
474  
475  // SPoG
476  // targetname.cpp
477 -void Entity_Connect(entity_t *e1, entity_t *e2);
478 +void Entity_Connect(entity_t *e1, entity_t *e2, bool kill = false);
479  int GetUniqueTargetId(int iHint);
480  
481  // xywindow.cpp