#include #include #include "QF/quakeio.h" #include "QF/script.h" #include "QF/sys.h" #include "Map.h" #include "Entity.h" #include "TexturePalette.h" #include "SetBrush.h" #include "XYView.h" #include "CameraView.h" #include "QuakeEd.h" #include "Things.h" #include "InspectorControl.h" #include "Project.h" id map_i; @implementation Map /* =============================================================================== FILE METHODS =============================================================================== */ - init { [super init]; map_i = self; minz = 0; maxz = 80; oldselection = [[NSMutableArray alloc] init]; return self; } - saveSelected { int i, c; id o, w; [oldselection removeAllObjects]; w = [self objectAtIndex: 0]; c = [w count]; sb_newowner = oldselection; for (i=0 ; i -2048) minz = m; return self; } - (float)currentMaxZ { float grid; [self currentMinZ]; // grid align grid = [xyview_i gridsize]; maxz = grid * rint(maxz/grid); if (maxz <= minz) maxz = minz + grid; return maxz; } - setCurrentMaxZ: (float)m { if (m < 2048) maxz = m; return self; } - (void) removeObject: o { [super removeObject: o]; if (o == currentEntity) { // select the world [self setCurrentEntity: [self objectAtIndex: 0]]; } return; } - writeStats { /*XXX FILE *f; extern int c_updateall; struct timeval tp; struct timezone tzp; gettimeofday(&tp, &tzp); f = fopen (FN_DEVLOG, "a"); fprintf (f,"%i %i\n", (int)tp.tv_sec, c_updateall); c_updateall = 0; fclose (f); */ return self; } - (int)numSelected { int i, c; int num; num = 0; c = [currentEntity count]; for (i=0 ; i=0 ; i--) { ent = [self objectAtIndex: i]; c2 = [ent count]; for (j=0 ; jbesttime) continue; bestent = ent; besttime = time; bestbrush = brush; bestface = face; } if (i == 1 && ef && bestbrush) break; // found an entity, so don't check the world } if (besttime == 99999) { Sys_Printf ("trace missed"); return self; } if ( [bestbrush regioned] ) { Sys_Printf ("WANRING: clicked on regioned brush"); return self; } if (bestent != currentEntity) { [self makeSelectedPerform: @selector(deselect)]; [self setCurrentEntity: bestent]; } [quakeed_i disableFlushWindow]; if ( ![bestbrush selected] ) { if ( [map_i numSelected] == 0) { // don't grab texture if others are selected td = [bestbrush texturedefForFace: bestface]; [texturepalette_i setTextureDef: td]; } [bestbrush setSelected: YES]; Sys_Printf ("selected entity %i brush %i face %i", (int) [self indexOfObject:bestent], (int) [bestent indexOfObject: bestbrush], bestface); } else { [bestbrush setSelected: NO]; Sys_Printf ("deselected entity %i brush %i face %i", (int) [self indexOfObject:bestent], (int) [bestent indexOfObject: bestbrush], bestface); } [quakeed_i enableFlushWindow]; [quakeed_i updateAll]; return self; } /* ================= grabRay checks only the selected brushes Returns the brush hit, or nil if missed. ================= */ - grabRay: (vec3_t)p1 : (vec3_t)p2 { int i, j, c, c2; id ent; id brush, bestbrush; int face; float time, besttime; bestbrush = nil; besttime = 99999; c = [self count]; for (i=0 ; ibesttime) continue; besttime = time; bestbrush = brush; } } if (besttime == 99999) return nil; return bestbrush; } /* ================= getTextureRay ================= */ - getTextureRay: (vec3_t)p1 : (vec3_t)p2 { int i, j, c, c2; id ent, bestent; id brush, bestbrush; int face, bestface; float time, besttime; texturedef_t *td; vec3_t mins, maxs; bestbrush = nil; bestent = nil; besttime = 99999; bestface = -1; c = [self count]; for (i=0 ; ibesttime) continue; bestent = ent; bestface = face; besttime = time; bestbrush = brush; } } if (besttime == 99999) return nil; if ( ![bestent modifiable]) { Sys_Printf ("can't modify spawned entities"); return self; } td = [bestbrush texturedefForFace: bestface]; [texturepalette_i setTextureDef: td]; Sys_Printf ("grabbed texturedef and sizes"); [bestbrush getMins: mins maxs: maxs]; minz = mins[2]; maxz = maxs[2]; return bestbrush; } /* ================= setTextureRay ================= */ - setTextureRay: (vec3_t)p1 : (vec3_t)p2 : (BOOL)allsides; { int i, j, c, c2; id ent, bestent; id brush, bestbrush; int face, bestface; float time, besttime; texturedef_t td; bestent = nil; bestface = -1; bestbrush = nil; besttime = 99999; c = [self count]; for (i=0 ; ibesttime) continue; bestent = ent; besttime = time; bestbrush = brush; bestface = face; } } if (besttime == 99999) { Sys_Printf ("trace missed"); return self; } if ( ![bestent modifiable]) { Sys_Printf ("can't modify spawned entities"); return self; } if ( [bestbrush regioned] ) { Sys_Printf ("WANRING: clicked on regioned brush"); return self; } [texturepalette_i getTextureDef: &td]; [quakeed_i disableFlushWindow]; if (allsides) { [bestbrush setTexturedef: &td]; Sys_Printf ("textured entity %i brush %i", (int) [self indexOfObject:bestent], (int) [bestent indexOfObject: bestbrush]); } else { [bestbrush setTexturedef: &td forFace: bestface]; Sys_Printf ("deselected entity %i brush %i face %i", (int) [self indexOfObject:bestent], (int) [bestent indexOfObject: bestbrush], bestface); } [quakeed_i enableFlushWindow]; [quakeed_i updateAll]; return self; } /* ============================================================================== OPERATIONS ON SELECTIONS ============================================================================== */ - makeSelectedPerform: (SEL)sel { int i,j, c, c2; id ent, brush; int total; total = 0; c = [self count]; for (i=c-1 ; i>=0 ; i--) { ent = [self objectAtIndex: i]; c2 = [ent count]; for (j = c2-1 ; j >=0 ; j--) { brush = [ent objectAtIndex: j]; if (! [brush selected] ) continue; if ([brush regioned]) continue; total++; [brush performSelector:sel]; } } // if (!total) // Sys_Printf ("nothing selected"); return self; } - makeUnselectedPerform: (SEL)sel { int i,j, c, c2; id ent, brush; c = [self count]; for (i=c-1 ; i>=0 ; i--) { ent = [self objectAtIndex: i]; c2 = [ent count]; for (j = c2-1 ; j >=0 ; j--) { brush = [ent objectAtIndex: j]; if ( [brush selected] ) continue; if ([brush regioned]) continue; [brush performSelector:sel]; } } return self; } - makeAllPerform: (SEL)sel { int i,j, c, c2; id ent, brush; c = [self count]; for (i=c-1 ; i>=0 ; i--) { ent = [self objectAtIndex: i]; c2 = [ent count]; for (j = c2-1 ; j >=0 ; j--) { brush = [ent objectAtIndex: j]; if ([brush regioned]) continue; [brush performSelector:sel]; } } return self; } - makeGlobalPerform: (SEL)sel // in and out of region { int i,j, c, c2; id ent, brush; c = [self count]; for (i=c-1 ; i>=0 ; i--) { ent = [self objectAtIndex: i]; c2 = [ent count]; for (j = c2-1 ; j >=0 ; j--) { brush = [ent objectAtIndex: j]; [brush performSelector:sel]; } } return self; } void sel_identity (void) { sel_x[0]=1; sel_x[1]=0; sel_x[2]=0; sel_y[0]=0; sel_y[1]=1; sel_y[2]=0; sel_z[0]=0; sel_z[1]=0; sel_z[2]=1; } - transformSelection { if ( ![currentEntity modifiable]) { Sys_Printf ("can't modify spawned entities"); return self; } // find an origin to apply the transformation to sb_mins[0] = sb_mins[1] = sb_mins[2] = 99999; sb_maxs[0] = sb_maxs[1] = sb_maxs[2] = -99999; [self makeSelectedPerform: @selector(addToBBox)]; sel_org[0] = [xyview_i snapToGrid: (sb_mins[0] + sb_maxs[0])/2]; sel_org[1] = [xyview_i snapToGrid: (sb_mins[1] + sb_maxs[1])/2]; sel_org[2] = [xyview_i snapToGrid: (sb_mins[2] + sb_maxs[2])/2]; // do it! [self makeSelectedPerform: @selector(transform)]; [quakeed_i updateAll]; return self; } void swapvectors (vec3_t a, vec3_t b) { vec3_t temp; VectorCopy (a, temp); VectorCopy (b, a); VectorSubtract (vec3_origin, temp, b); } /* =============================================================================== UI operations =============================================================================== */ - rotate_x: sender { sel_identity (); swapvectors(sel_y, sel_z); [self transformSelection]; return self; } - rotate_y: sender { sel_identity (); swapvectors(sel_x, sel_z); [self transformSelection]; return self; } - rotate_z: sender { sel_identity (); swapvectors(sel_x, sel_y); [self transformSelection]; return self; } - flip_x: sender { sel_identity (); sel_x[0] = -1; [self transformSelection]; [map_i makeSelectedPerform: @selector(flipNormals)]; return self; } - flip_y: sender { sel_identity (); sel_y[1] = -1; [self transformSelection]; [map_i makeSelectedPerform: @selector(flipNormals)]; return self; } - flip_z: sender { sel_identity (); sel_z[2] = -1; [self transformSelection]; [map_i makeSelectedPerform: @selector(flipNormals)]; return self; } - cloneSelection: sender { int i,j , c, originalElements; id o, b; id new; sb_translate[0] = sb_translate[1] = [xyview_i gridsize]; sb_translate[2] = 0; // copy individual brushes in the world entity o = [self objectAtIndex: 0]; c = [o count]; for (i=0 ; i