/* * Descent 3 * Copyright (C) 2024 Parallax Software * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/editor/drawworld.cpp $ * $Revision: 1.1.1.1 $ * $Date: 2003-08-26 03:57:37 $ * $Author: kevinb $ * * Code to draw wireframe world for editor * * $Log: not supported by cvs2svn $ * * 36 4/22/99 5:17p Matt * Changed the and & or fields in the grCodes struct to cc_and & cc_or, * since the former names didn't work with some compilers. * * 35 3/01/99 2:58p Dan * Set lighting type before wireframe search, because sometimes it was set * wrong & the search wouldn't work. (MattT on Dan's machine) * * 34 2/28/99 6:18p Matt * Commented-out Int3() * * 33 2/13/99 6:29p Matt * Always check current room when searching, because if the render radius * is low it was getting checked. * * 32 2/03/99 1:10p Matt * Changed the paletted room current faces to be stored in a separate * array, instead of in the room structure. * * 31 12/01/98 11:17p Matt * Added menu option to disable drawing objects in the wireframe view * * 30 10/04/98 1:25p Matt * * 29 9/04/98 12:29p Matt * Added marked edge & vertex in the editor * * 28 9/01/98 12:04p Matt * Ripped out multi-face portal code * * 27 5/20/98 3:48p Matt * Added suport for variable-depth face selection in wireframe view. * * 26 5/14/98 12:56p Jason * changes to help lower memory usage * * 25 2/16/98 1:08p Matt * Draw the current vertex in the wireframe view * * 24 1/29/98 5:50p Matt * Changed old camera object type to be viewer object (for editor), and * now camera objects will just be for game cameras. * * 23 1/12/98 3:34p Jason * sped up indoor rendering by clipping faces against portals * * 22 12/19/97 5:23p Samir * Clear before frame in Wireframe. * * 21 12/19/97 12:26p Samir * Replaced g3_StartFrame with StartEditorFrame * * 20 10/15/97 5:20p Jason * did a HUGE overhaul of the bitmap system * * 19 9/29/97 12:09p Jason * added functionality to doorway system * * 18 9/22/97 5:21p Matt * Got box selection working for room engine * * 17 9/17/97 1:01p Matt * Ripped out segment code * * 16 9/17/97 11:34a Matt * Ripped out segment code * * 15 9/11/97 7:08p Matt * Added code to draw floating trigger faces * * 14 9/09/97 3:58p Matt * Ripped out segment engine renderer * * 13 9/06/97 3:16p Matt * Added current portal system * * 12 9/04/97 4:39p Matt * Added includes needed as a result of removing includes from d3edit.h * * 11 8/29/97 5:35p Matt * Massive changes: ripped out segment code, make current & selection * rooms draw special, made facing & nonfacing edges draw in different * colors. * * 10 8/22/97 9:31a Matt * Terrain portals now draw in blue. * * 9 8/20/97 10:39a Matt * If a frame hasn't been previously rendered when the findroomface * function is called, handle it gracefully. * * 8 8/18/97 6:59p Matt * Implemented Place Room/Attach room system * * 7 8/05/97 10:48a Matt * Draw marked face * * 6 7/29/97 12:16p Matt * Made wireframe seach work for rooms & faces * * 5 7/24/97 6:11p Matt * Created symbolic constant for default zoom, and used it every place * that specifies zoom * * 4 7/22/97 7:07p Matt * Cleaned up D3EditState, moving some vars in and some out, and renaming * and changing a few others * * 3 7/16/97 4:18p Matt * Changes to work with changed 3d draw functions * * 22 5/21/97 12:29p Jason * added the ability to draw terrain dots in mine view * * 21 5/15/97 3:27a Jason * implemented terrain magnification * * 20 5/13/97 7:47p Matt * Added code to compress mine before saving. * Cleaned up code dealing with num vertices & segments. * * 19 5/12/97 11:41a Jason * made game work (default) to 16bit no mip maps mode * Saves us alot of memory * * 18 5/01/97 6:06p Matt * Deleted commented-out code * * 17 4/30/97 3:15p Jason * changes to support both 8bit and 16bit rendering in software * * 16 4/10/97 4:39p Jason * Made selection manager stuff work with terrain topographical map * * 15 4/01/97 10:51p Matt * Draw viewer based on object type * * 14 4/01/97 5:18p Matt * Draw objects as spheres in wireframe view * * 13 3/20/97 11:55a Jason * changes for terrain editing/drawing * * 12 3/17/97 11:59a Matt * Added code to draw warning segments * * 11 3/17/97 11:10a Jason * added wireframe terrain view * * 10 2/28/97 6:38p Matt * Fixed box selection bug, & added supprt for two box selection modes * * 9 2/28/97 4:00p Matt * Added code to handle the list of selected segments * * 8 2/28/97 9:33a Matt * Improved code that checked for segments by writing a pixel and reading * that pixel after rendering. * * 7 2/26/97 5:59p Matt * Renamed 3d lib structs for D3 naming convention * * 6 2/24/97 5:57p Matt * Restored code to draw marked seg in different color * * 5 2/24/97 12:23p Matt * Changed the name of some segment struct elements * * 4 2/19/97 5:37p Matt * Added code to set curseg from clicking in wireframe window * * 3 2/07/97 6:02p Matt * Enabled code that draws current seg, side, & edge * * $NoKeywords: $ */ #include "drawworld.h" #include #include "3d.h" #include "descent.h" #include "d3edit.h" #include "selectedroom.h" #include "terrain.h" #include "object.h" #include "erooms.h" #include "group.h" #include "renderer.h" int Draw_all_rooms = 1; // the viewport we're currently drawing to grViewport *Draw_viewport; // Colors for rooms/edges #define FACING_COLOR GR_RGB(198, 198, 198) #define NOTFACING_COLOR GR_RGB(125, 125, 125) // GR_RGB( 158, 158, 158) #define PLACED_COLOR GR_RGB(255, 0, 255) #define SELECTED_COLOR GR_RGB(255, 166, 0) #define TERR_PORTAL_COLOR GR_RGB(0, 0, 255) #define CURROOM_COLOR GR_RGB(255, 255, 255) #define CURFACE_COLOR GR_RGB(255, 255, 0) #define CUREDGE_COLOR GR_RGB(0, 255, 0) #define MARKEDFACE_COLOR GR_RGB(0, 255, 255) #define MARKEDEDGE_COLOR GR_RGB(0, 150, 150) #define CURPORTAL_COLOR GR_RGB(200, 150, 255) #define FLOAT_TRIG_COLOR GR_RGB(255, 100, 100) // Unused for now #define FOUND_COLOR GR_RGB(0, 121, 182) #define WARNING_COLOR GR_RGB(255, 0, 0) #define MARKEDROOM_COLOR GR_RGB(0, 255, 0) // Colors for objects #define ROBOT_COLOR GR_RGB(255, 0, 0) // a robot #define PLAYER_COLOR GR_RGB(0, 255, 0) // a player object #define VIEWER_COLOR GR_RGB(100, 0, 100) // a viewer #define POWERUP_COLOR GR_RGB(0, 0, 255) // a powerup #define MISCOBJ_COLOR GR_RGB(0, 100, 100) // some other object #define CAMERA_COLOR GR_RGB(255, 255, 0) // a camera // vars for WireframeFindRoomFace() static int Search_mode = 0; // if 1, searching for point, if 2, searching for box static int Search_x, Search_y; static int Search_find_mode; static float Search_min_dist = 0.0; static int Search_left, Search_top, Search_right, Search_bot; static int Search_roomnum, Search_facenum; static vector Search_viewer; // used to determine closest room static int Found_roomnum; static int Found_facenum; static float Found_dist; static grViewport *last_vp; static vector last_viewer_position; static vector last_viewer_target; static matrix last_view_orient; static int last_start_seg; static int last_start_room; static float last_rad; static float last_zoom; extern vector *TS_View_position; extern matrix *TS_View_matrix; extern matrix View_matrix; void PreRotateTerrain(); void Terrain_start_frame(vector *eye, matrix *view_orient); void DrawTerrainPoints(vector *view_pos, matrix *view_orient) { g3Point terr_point; int i; Terrain_start_frame(view_pos, &View_matrix); for (i = 0; i < TERRAIN_DEPTH * TERRAIN_WIDTH; i++) { GetPreRotatedPoint(&terr_point, i % TERRAIN_WIDTH, i / TERRAIN_WIDTH, Terrain_seg[i].ypos); terr_point.p3_flags = 0; g3_CodePoint(&terr_point); if (!terr_point.p3_codes) { g3_ProjectPoint(&terr_point); Draw_viewport->setpixel(GR_RGB(255, 255, 255), terr_point.p3_sx, terr_point.p3_sy); } } } // edge types - lower number types have precedence #define ET_EMPTY 255 // this entry in array is empty #define ET_FACING 0 // this edge on a facing face #define ET_NOTFACING 1 // this edge on a non-facing face #define N_EDGE_TYPES 2 // how many edge types there are struct seg_edge { union { struct { int16_t v0, v1; }; int32_t vv; }; uint16_t type; }; #define MAX_EDGES (MAX_VERTS_PER_ROOM * 2) seg_edge edge_list[MAX_EDGES]; int16_t used_list[MAX_EDGES]; // which entries in edge_list have been used int n_used; int edge_list_size; // set each frame #define HASH(a, b) ((a * 5 + b) % edge_list_size) #define swap(a, b) \ do { \ int t; \ t = (a); \ (a) = (b); \ (b) = t; \ } while (0) // finds edge, filling in edge_ptr. if found old edge, returns index, else return -1 int FindEdge(int v0, int v1, seg_edge **edge_ptr) { int32_t vv; int16_t hash, oldhash; int ret; vv = (v1 << 16) + v0; oldhash = hash = HASH(v0, v1); ret = -1; while (ret == -1) { if (edge_list[hash].type == ET_EMPTY) ret = 0; else if (edge_list[hash].vv == vv) ret = 1; else { if (++hash == edge_list_size) hash = 0; if (hash == oldhash) Error("Edge list full!"); } } *edge_ptr = &edge_list[hash]; if (ret == 0) return -1; else return hash; } // adds an edge to the edge list void AddEdge(int v0, int v1, uint8_t type) { int found; seg_edge *e; // mprintf(0, "Verts = %2i %2i, type = %i ", v0, v1, type); if (v0 > v1) swap(v0, v1); found = FindEdge(v0, v1, &e); if (found == -1) { e->v0 = v0; e->v1 = v1; e->type = type; used_list[n_used] = e - edge_list; n_used++; } else { if (type < e->type) e->type = type; } } // If searching for a point, see if this room draws at the search x,y position, and if so, // if it's the closest to the viewer. If searching for a box, see if any of the room points are // inside the box. void CheckRoom(room *rp) { uint8_t codes_and = 0xff; int vn; // Rotate all the points for (vn = 0; vn < rp->num_verts; vn++) codes_and &= g3_RotatePoint((g3Point *)&World_point_buffer[vn], &rp->verts[vn]); if (!codes_and) { // all off screen? if (Search_mode == 1) { // searching for a point int fn; ddgr_color oldcolor; face *fp; rend_SetLighting(LS_NONE); rend_SetTextureType(TT_FLAT); for (fn = 0, fp = rp->faces; fn < rp->num_faces; fn++, fp++) { g3Point *vert_list[MAX_VERTS_PER_FACE]; codes_and = 0xff; for (vn = 0; vn < fp->num_verts; vn++) { vert_list[vn] = (g3Point *)&World_point_buffer[fp->face_verts[vn]]; codes_and &= vert_list[vn]->p3_codes; } if (!codes_and) { Draw_viewport->setpixel(GR_RGB(0, 0, 0), Search_x, Search_y); oldcolor = Draw_viewport->getpixel(Search_x, Search_y); // will be different in 15/16-bit color rend_SetFlatColor(GR_RGB(255, 255, 255)); g3_CheckAndDrawPoly(fp->num_verts, vert_list, 0, NULL, NULL); if (Draw_viewport->getpixel(Search_x, Search_y) != oldcolor) { vector t; float dist; ComputeCenterPointOnFace(&t, rp, fn); dist = vm_VectorDistance(&t, &Search_viewer); if (Search_find_mode == FM_SPECIFIC) { if ((ROOMNUM(rp) == Search_roomnum) && (fn == Search_facenum)) { Found_roomnum = ROOMNUM(rp); Found_facenum = fn; Found_dist = dist; } } else if ((Found_roomnum == -1 || dist < Found_dist) && (dist > Search_min_dist)) { Found_roomnum = ROOMNUM(rp); Found_facenum = fn; Found_dist = dist; } } } } } else if (Search_mode == 2) { // searching in a box int v; for (v = 0; v < rp->num_verts; v++) { int x, y; g3_ProjectPoint((g3Point *)&World_point_buffer[v]); x = Round(World_point_buffer[v].p3_sx); y = Round(World_point_buffer[v].p3_sy); if ((x >= Search_left) && (y >= Search_top) && (x <= Search_right) && (y <= Search_bot)) { if ((D3EditState.box_selection_mode == ACROSS_EDGE) || (v == rp->num_verts - 1)) { AddRoomToSelectedList(ROOMNUM(rp)); Found_roomnum++; // doubles as a counter break; // no need to check rest of verts } } else // this point not in window if (D3EditState.box_selection_mode == IN_WINDOW) // seg not entirely in window break; //..so stop checking this room } } else Int3(); // unknown Search_mode } } void DrawLine(ddgr_color color, int pnum0, int pnum1) { g3Point pnt1, pnt2; pnt1 = *((g3Point *)&World_point_buffer[pnum0]); pnt2 = *((g3Point *)&World_point_buffer[pnum1]); g3_DrawLine(color, &pnt1, &pnt2); } void DrawEdges(int room_color = -1); void DrawEdges(int room_color) { int i, type; seg_edge *e; ddgr_color edge_colors[] = {FACING_COLOR, NOTFACING_COLOR}; for (type = N_EDGE_TYPES - 1; type >= 0; type--) { for (i = 0; i < n_used; i++) { e = &edge_list[used_list[i]]; if (e->type == type) DrawLine((room_color == -1) ? edge_colors[type] : room_color, e->v0, e->v1); } } } void DrawAllRooms(vector *view_target, float rad); void DrawRoom(room *rp, int room_type = -1); // Finds the closest room:face to the viewer at a given x,y screen position in the wireframe view // Parameters: vp - the viewport we're checking. Must be the same viewport as the last wireframe view rendered // x,y - the screen coordinates clicked on // roomnum,facenum - pointers to variables to be filled in // find_mode - see values in header file // Returns: true if found a room/face bool WireframeFindRoomFace(grViewport *vp, int x, int y, int *roomnum, int *facenum, int find_mode) { if (last_vp == NULL) return 0; if (vp != last_vp) { // Int3(); return 0; } Draw_viewport = vp; vp->clear(); StartEditorFrame(vp, &last_viewer_position, &last_view_orient, last_zoom); Search_mode = 1; Search_find_mode = find_mode; Search_x = x; Search_y = y; Search_viewer = last_viewer_position; Search_min_dist = (find_mode == FM_NEXT) ? Found_dist : 0.0; Search_roomnum = *roomnum; Search_facenum = *facenum; Found_roomnum = -1; Found_facenum = -1; if (Editor_view_mode == VM_ROOM) { ASSERT(D3EditState.current_room != -1); CheckRoom(&Rooms[D3EditState.current_room]); } else { DrawAllRooms(&last_viewer_target, last_rad); CheckRoom(Curroomp); } EndEditorFrame(); Search_mode = 0; if (Found_roomnum != -1) { *roomnum = Found_roomnum; *facenum = Found_facenum; return 1; } else return 0; } // Adds all the rooms that have a vertex inside of a given screen box to the selected list // Parameters: vp - the viewport we're checking. Must be the same viewport as the last wireframe view rendered // left,top,right,bot - the screen coordinates of the box // Returns: the number of rooms found int SelectRoomsInBox(grViewport *vp, int left, int top, int right, int bot) { // TEMP: The caller doesn't know the viewport, so we set it here vp = last_vp; if (vp != last_vp) { Int3(); return -1; } Draw_viewport = vp; vp->clear(); StartEditorFrame(vp, &last_viewer_position, &last_view_orient, last_zoom); Search_mode = 2; Search_left = left; Search_top = top; Search_right = right; Search_bot = bot; Search_viewer = last_viewer_position; Found_roomnum = 0; // we use this as a counter DrawAllRooms(&last_viewer_target, last_rad); EndEditorFrame(); Search_mode = 0; return Found_roomnum; } // Resets the edge list void ResetEdgeList(int size) { int i; edge_list_size = __min(size, MAX_EDGES); // make maybe smaller than max for (i = 0; i < edge_list_size; i++) { edge_list[i].type = ET_EMPTY; } n_used = 0; } // Draw a room void DrawRoom(room *rp, int room_color) { int fn, vn; face *fp; int edge_type; ResetEdgeList(MAX_EDGES); // Rotate all the points for (vn = 0; vn < rp->num_verts; vn++) g3_RotatePoint((g3Point *)&World_point_buffer[vn], &rp->verts[vn]); for (fn = 0, fp = rp->faces; fn < rp->num_faces; fn++, fp++) { if (fp->flags & FF_FLOATING_TRIG) { for (vn = 0; vn < fp->num_verts; vn++) DrawLine(FLOAT_TRIG_COLOR, fp->face_verts[vn], fp->face_verts[(vn + 1) % fp->num_verts]); DrawLine(FLOAT_TRIG_COLOR, fp->face_verts[0], fp->face_verts[2]); DrawLine(FLOAT_TRIG_COLOR, fp->face_verts[1], fp->face_verts[3]); } else if (fp->portal_num == -1) { bool facing = g3_CheckNormalFacing(&rp->verts[fp->face_verts[0]], &fp->normal); for (vn = 0; vn < fp->num_verts; vn++) { if (facing) edge_type = ET_NOTFACING; else edge_type = ET_FACING; AddEdge(fp->face_verts[vn], fp->face_verts[(vn + 1) % fp->num_verts], edge_type); } } } DrawEdges(room_color); // Now draw the terrain portals for (int p = 0; p < rp->num_portals; p++) { portal *pp = &rp->portals[p]; if (pp->croom == -1) { // terrain portal fp = &rp->faces[pp->portal_face]; for (vn = 0; vn < fp->num_verts; vn++) DrawLine(TERR_PORTAL_COLOR, fp->face_verts[vn], fp->face_verts[(vn + 1) % fp->num_verts]); } } } // Draw a room rotated and placed in space void DrawRoomRotated(room *rp, vector *rotpoint, matrix *rotmat, vector *placepoint, int room_color) { int fn, vn; face *fp; ResetEdgeList(MAX_EDGES); // Rotate all the points for (vn = 0; vn < rp->num_verts; vn++) { vector tv; tv = (rp->verts[vn] - *rotpoint) * *rotmat + *placepoint; g3_RotatePoint((g3Point *)&World_point_buffer[vn], &tv); } for (fn = 0, fp = rp->faces; fn < rp->num_faces; fn++, fp++) for (vn = 0; vn < fp->num_verts; vn++) AddEdge(fp->face_verts[vn], fp->face_verts[(vn + 1) % fp->num_verts], ET_FACING); DrawEdges(room_color); } void DrawRoomFace(ddgr_color color, room *rp, int facenum) { face *fp = &rp->faces[facenum]; g3Codes cc; int i; // Rotate the points in this face cc.cc_and = 0xff; cc.cc_or = 0; for (i = 0; i < fp->num_verts; i++) { int vertnum = fp->face_verts[i]; g3_RotatePoint((g3Point *)&World_point_buffer[vertnum], &rp->verts[vertnum]); cc.cc_and &= World_point_buffer[vertnum].p3_codes; cc.cc_or |= World_point_buffer[vertnum].p3_codes; } if (!cc.cc_and) // if not all off screen for (i = 0; i < fp->num_verts; i++) DrawLine(color, fp->face_verts[i], fp->face_verts[(i + 1) % fp->num_verts]); } void DrawFaceEdge(ddgr_color color, room *rp, int facenum, int edgenum) { face *fp = &rp->faces[facenum]; int v0, v1; v0 = fp->face_verts[edgenum]; v1 = fp->face_verts[(edgenum + 1) % fp->num_verts]; g3_RotatePoint((g3Point *)&World_point_buffer[v0], &rp->verts[v0]); g3_RotatePoint((g3Point *)&World_point_buffer[v1], &rp->verts[v1]); if (!(World_point_buffer[v0].p3_codes & World_point_buffer[v1].p3_codes)) DrawLine(color, v0, v1); } // Draw the objects in a room as spheres void DrawRoomObjects(room *rp) { int objnum; if (!D3EditState.objects_in_wireframe) return; for (objnum = rp->objects; objnum != -1; objnum = Objects[objnum].next) { object *obj = &Objects[objnum]; g3Point sphere_point; ddgr_color color; switch (obj->type) { case OBJ_POWERUP: color = POWERUP_COLOR; break; case OBJ_ROBOT: color = ROBOT_COLOR; break; case OBJ_PLAYER: color = PLAYER_COLOR; break; case OBJ_VIEWER: color = VIEWER_COLOR; break; case OBJ_CAMERA: color = CAMERA_COLOR; break; default: color = MISCOBJ_COLOR; break; } if (obj->type == OBJ_DOOR) // don't draw doors continue; g3_RotatePoint(&sphere_point, &obj->pos); g3_DrawSphere(color, &sphere_point, obj->size); } } void DrawAllRooms(vector *view_target, float rad) { int r; room *rp; for (r = 0, rp = Rooms; r <= Highest_room_index; r++, rp++) { if (rp->used && (vm_VectorDistance(&rp->verts[0], view_target) < rad)) { if (Search_mode) CheckRoom(rp); else { DrawRoom(rp); DrawRoomObjects(rp); } } } } #define CROSS_WIDTH 8.0 #define CROSS_HEIGHT 8.0 void DrawVertBox(vector *v, ddgr_color color) { // Draw a box at the marked vert g3Point p0; uint8_t c0 = g3_RotatePoint(&p0, v); if (!c0) { // on screen? g3_ProjectPoint(&p0); rend_SetFlatColor(color); rend_DrawLine(p0.p3_sx - CROSS_WIDTH, p0.p3_sy, p0.p3_sx, p0.p3_sy - CROSS_HEIGHT); rend_DrawLine(p0.p3_sx, p0.p3_sy - CROSS_HEIGHT, p0.p3_sx + CROSS_WIDTH, p0.p3_sy); rend_DrawLine(p0.p3_sx + CROSS_WIDTH, p0.p3_sy, p0.p3_sx, p0.p3_sy + CROSS_HEIGHT); rend_DrawLine(p0.p3_sx, p0.p3_sy + CROSS_HEIGHT, p0.p3_sx - CROSS_WIDTH, p0.p3_sy); } } void DrawWorld(grViewport *vp, vector *view_target, matrix *view_orient, float view_dist, int start_room, float rad) { vector viewer_position; float zoom = D3_DEFAULT_ZOOM; ASSERT(Curroomp != NULL); viewer_position = *view_target - (view_orient->fvec * view_dist); // save for possible use by find function last_vp = vp; last_viewer_position = viewer_position; last_viewer_target = *view_target; last_view_orient = *view_orient; last_start_room = start_room; last_rad = rad; last_zoom = zoom; Draw_viewport = vp; vp->clear(); StartEditorFrame(vp, &viewer_position, view_orient, zoom); if (Editor_view_mode == VM_ROOM) { ASSERT(D3EditState.current_room != -1); if (Search_mode) CheckRoom(&Rooms[D3EditState.current_room]); else { room *rp = &Rooms[D3EditState.current_room]; DrawRoom(rp); ASSERT(D3EditState.current_room >= FIRST_PALETTE_ROOM); if (Current_faces[D3EditState.current_room - FIRST_PALETTE_ROOM] != -1) DrawRoomFace(CURFACE_COLOR, rp, Current_faces[D3EditState.current_room - FIRST_PALETTE_ROOM]); } } else { if (D3EditState.terrain_dots) DrawTerrainPoints(&viewer_position, view_orient); // Draw all rooms or only connected rooms. if (Draw_all_rooms) { int r; room *rp; for (r = 0, rp = Rooms; r <= Highest_room_index; r++, rp++) { if (rp->used && (vm_VectorDistance(&rp->verts[0], view_target) < rad)) { if (rp != Curroomp) { int color = -1; if (IsRoomSelected(r)) color = SELECTED_COLOR; DrawRoom(rp, color); } DrawRoomObjects(rp); } } } else Error("No support yet for Draw_all_rooms==0"); //??DrawMine(mine_ptr,depth); if (Placed_room != -1) if (Rooms[Placed_room].used) DrawRoomRotated(&Rooms[Placed_room], &Placed_room_origin, &Placed_room_rotmat, &Placed_room_attachpoint, PLACED_COLOR); if (Placed_group) for (int r = 0; r < Placed_group->nrooms; r++) DrawRoomRotated(&Placed_group->rooms[r], &Placed_room_origin, &Placed_room_rotmat, &Placed_room_attachpoint, PLACED_COLOR); //@@DrawWarningSegments(); //@@draw_group_segments(); //@@draw_found_segments(); //@@DrawSelectedSegments(); //@@draw_special_segments(); // Highlight marked room side. if (Markedroomp) { DrawRoomFace(MARKEDFACE_COLOR, Markedroomp, Markedface); DrawFaceEdge(MARKEDEDGE_COLOR, Markedroomp, Markedface, Markededge); DrawVertBox(&Markedroomp->verts[Markedroomp->faces[Markedface].face_verts[Markedvert]], MARKEDEDGE_COLOR); } // Draw current room, face, & edge DrawRoom(Curroomp, CURROOM_COLOR); if (Curportal != -1) DrawRoomFace(CURPORTAL_COLOR, Curroomp, Curroomp->portals[Curportal].portal_face); DrawRoomFace(CURFACE_COLOR, Curroomp, Curface); DrawFaceEdge(CUREDGE_COLOR, Curroomp, Curface, Curedge); DrawVertBox(&Curroomp->verts[Curroomp->faces[Curface].face_verts[Curvert]], CUREDGE_COLOR); } EndEditorFrame(); }