mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-16 08:10:32 +02:00
Numerous performance fixes.
This commit is contained in:
@@ -36,6 +36,7 @@ If you have questions concerning this license or the applicable additional terms
|
||||
#include "OutlinerDlg.h"
|
||||
#include "splines.h"
|
||||
#include <GL/glu.h>
|
||||
#include <vector>
|
||||
|
||||
#include "../../renderer/tr_local.h"
|
||||
#include "../../models/model_local.h" // for idRenderModelMD5
|
||||
@@ -1564,24 +1565,38 @@ static bool CamWnd_IsTriggerLikeBrushEntity(brush_t* brush) {
|
||||
CamWnd_StringStartsWithNoCase(className, "monsterclip");
|
||||
}
|
||||
|
||||
static bool CamWnd_TargetLinesVisible(CCamWnd* cam) {
|
||||
return (CamWnd_GetFilterMask(cam) & CAMWND_FILTER_HIDE_TARGET_LINES) == 0;
|
||||
struct camWndBrushFilterContext_t {
|
||||
CCamWnd* cam;
|
||||
int mask;
|
||||
bool hasHiddenEntities;
|
||||
};
|
||||
|
||||
static camWndBrushFilterContext_t CamWnd_MakeBrushFilterContext(CCamWnd* cam) {
|
||||
camWndBrushFilterContext_t ctx;
|
||||
ctx.cam = cam;
|
||||
ctx.mask = CamWnd_GetFilterMask(cam);
|
||||
ctx.hasHiddenEntities = Outliner_HasHiddenEntities();
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static bool CamWnd_MenuFilterBrush(CCamWnd* cam, brush_t* brush) {
|
||||
static bool CamWnd_TargetLinesVisible(const camWndBrushFilterContext_t& filter) {
|
||||
return (filter.mask & CAMWND_FILTER_HIDE_TARGET_LINES) == 0;
|
||||
}
|
||||
|
||||
static bool CamWnd_MenuFilterBrush(const camWndBrushFilterContext_t& filter, brush_t* brush) {
|
||||
if (!brush) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (brush->owner != NULL && !Outliner_IsEntityVisible(brush->owner)) {
|
||||
if (filter.hasHiddenEntities && brush->owner != NULL && !Outliner_IsEntityVisible(brush->owner)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!cam) {
|
||||
if (!filter.cam) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int mask = CamWnd_GetFilterMask(cam);
|
||||
const int mask = filter.mask;
|
||||
if (mask == 0) {
|
||||
return false;
|
||||
}
|
||||
@@ -1618,6 +1633,11 @@ static bool CamWnd_MenuFilterBrush(CCamWnd* cam, brush_t* brush) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CamWnd_MenuFilterBrush(CCamWnd* cam, brush_t* brush) {
|
||||
const camWndBrushFilterContext_t filter = CamWnd_MakeBrushFilterContext(cam);
|
||||
return CamWnd_MenuFilterBrush(filter, brush);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
@@ -3556,6 +3576,7 @@ void setGLMode(int mode) {
|
||||
break;
|
||||
|
||||
case cd_texture:
|
||||
case cd_light:
|
||||
glCullFace(GL_FRONT);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glShadeModel(GL_FLAT);
|
||||
@@ -3577,6 +3598,215 @@ void setGLMode(int mode) {
|
||||
}
|
||||
}
|
||||
|
||||
struct camWndWorldFaceBatch_t {
|
||||
const idMaterial* material;
|
||||
std::vector<face_t*> faces;
|
||||
};
|
||||
|
||||
static bool CamWnd_IsFastWorldBrush(brush_t* brush) {
|
||||
if (brush == NULL || brush->hiddenBrush) {
|
||||
return false;
|
||||
}
|
||||
if (brush->pPatch || brush->modelHandle > 0 || brush->entityModel || brush->forceWireFrame) {
|
||||
return false;
|
||||
}
|
||||
if (brush->owner == NULL || brush->owner != world_entity || brush->owner->curve != NULL) {
|
||||
return false;
|
||||
}
|
||||
if (brush->owner->eclass == NULL || !(brush->owner->eclass->nShowFlags & ECLASS_WORLDSPAWN)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CamWnd_CanFastDrawWorldMode(int drawMode) {
|
||||
return drawMode == cd_solid || drawMode == cd_texture || drawMode == cd_light;
|
||||
}
|
||||
|
||||
static bool CamWnd_ShouldDrawFastFace(face_t* face) {
|
||||
if (face == NULL || face->face_winding == NULL || face->face_winding->GetNumPoints() < 3) {
|
||||
return false;
|
||||
}
|
||||
if ((g_qeglobals.d_savedinfo.exclude & EXCLUDE_CAULK) && strstr(face->texdef.name, "caulk")) {
|
||||
return false;
|
||||
}
|
||||
if ((g_qeglobals.d_savedinfo.exclude & EXCLUDE_VISPORTALS) && strstr(face->texdef.name, "visportal")) {
|
||||
return false;
|
||||
}
|
||||
if ((g_qeglobals.d_savedinfo.exclude & EXCLUDE_NODRAW) && strstr(face->texdef.name, "nodraw")) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static camWndWorldFaceBatch_t* CamWnd_FindWorldFaceBatch(std::vector<camWndWorldFaceBatch_t>& batches, const idMaterial* material) {
|
||||
for (size_t i = 0; i < batches.size(); i++) {
|
||||
if (batches[i].material == material) {
|
||||
return &batches[i];
|
||||
}
|
||||
}
|
||||
|
||||
camWndWorldFaceBatch_t batch;
|
||||
batch.material = material;
|
||||
batch.faces.reserve(128);
|
||||
batches.push_back(batch);
|
||||
return &batches.back();
|
||||
}
|
||||
|
||||
static void CamWnd_AddFastWorldBrush(std::vector<camWndWorldFaceBatch_t>& batches, brush_t* brush, int drawMode) {
|
||||
const bool textured = (drawMode == cd_texture || drawMode == cd_light);
|
||||
|
||||
for (face_t* face = brush->brush_faces; face; face = face->next) {
|
||||
if (!CamWnd_ShouldDrawFastFace(face)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const idMaterial* material = textured ? face->d_texture : NULL;
|
||||
CamWnd_FindWorldFaceBatch(batches, material)->faces.push_back(face);
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_EmitFastWorldFaceBatches(const std::vector<camWndWorldFaceBatch_t>& batches, int drawMode) {
|
||||
const bool textured = (drawMode == cd_texture || drawMode == cd_light);
|
||||
|
||||
for (size_t batchIndex = 0; batchIndex < batches.size(); batchIndex++) {
|
||||
const camWndWorldFaceBatch_t& batch = batches[batchIndex];
|
||||
if (batch.faces.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (textured && batch.material != NULL) {
|
||||
batch.material->GetEditorImage()->Bind();
|
||||
}
|
||||
else {
|
||||
globalImages->BindNull();
|
||||
}
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (size_t faceIndex = 0; faceIndex < batch.faces.size(); faceIndex++) {
|
||||
face_t* face = batch.faces[faceIndex];
|
||||
idWinding* w = face->face_winding;
|
||||
const int numPoints = w->GetNumPoints();
|
||||
const float alpha = face->d_texture ? face->d_texture->GetEditorAlpha() : 1.0f;
|
||||
|
||||
glColor4f(face->d_color.x, face->d_color.y, face->d_color.z, alpha);
|
||||
|
||||
for (int i = 2; i < numPoints; i++) {
|
||||
if (textured) {
|
||||
glTexCoord2fv(&(*w)[0][3]);
|
||||
}
|
||||
glVertex3fv((*w)[0].ToFloatPtr());
|
||||
|
||||
if (textured) {
|
||||
glTexCoord2fv(&(*w)[i - 1][3]);
|
||||
}
|
||||
glVertex3fv((*w)[i - 1].ToFloatPtr());
|
||||
|
||||
if (textured) {
|
||||
glTexCoord2fv(&(*w)[i][3]);
|
||||
}
|
||||
glVertex3fv((*w)[i].ToFloatPtr());
|
||||
}
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
globalImages->BindNull();
|
||||
}
|
||||
|
||||
static void CamWnd_DrawActiveBrushes(CCamWnd* cam, bool renderMode, bool entityMode, const camWndBrushFilterContext_t& filter) {
|
||||
std::vector<camWndWorldFaceBatch_t> batches;
|
||||
std::vector<brush_t*> slowBrushes;
|
||||
batches.reserve(64);
|
||||
slowBrushes.reserve(64);
|
||||
|
||||
for (brush_t* brush = active_brushes.next; brush != &active_brushes; brush = brush->next) {
|
||||
if (cam->CullBrush(brush, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FilterBrush(brush)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CamWnd_MenuFilterBrush(filter, brush)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (renderMode) {
|
||||
if (!(entityMode && brush->owner->eclass->fixedsize)) {
|
||||
continue;
|
||||
}
|
||||
slowBrushes.push_back(brush);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CamWnd_CanFastDrawWorldMode(cam->Camera().draw_mode) && CamWnd_IsFastWorldBrush(brush)) {
|
||||
CamWnd_AddFastWorldBrush(batches, brush, cam->Camera().draw_mode);
|
||||
}
|
||||
else {
|
||||
slowBrushes.push_back(brush);
|
||||
}
|
||||
}
|
||||
|
||||
if (!batches.empty()) {
|
||||
setGLMode(cam->Camera().draw_mode);
|
||||
CamWnd_EmitFastWorldFaceBatches(batches, cam->Camera().draw_mode);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < slowBrushes.size(); i++) {
|
||||
setGLMode(cam->Camera().draw_mode);
|
||||
Brush_Draw(slowBrushes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_DrawRadiantLightFrustum(const renderLight_t& lightParms, const idVec3& color) {
|
||||
idPlane planes[6];
|
||||
R_RenderLightFrustum(lightParms, planes);
|
||||
srfTriangles_t* tri = R_PolytopeSurface(6, planes, NULL);
|
||||
if (tri == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
glColor3fv(color.ToFloatPtr());
|
||||
for (int i = 0; i < tri->numIndexes; i += 3) {
|
||||
glBegin(GL_LINE_LOOP);
|
||||
glVertex3fv(tri->verts[tri->indexes[i]].xyz.ToFloatPtr());
|
||||
glVertex3fv(tri->verts[tri->indexes[i + 1]].xyz.ToFloatPtr());
|
||||
glVertex3fv(tri->verts[tri->indexes[i + 2]].xyz.ToFloatPtr());
|
||||
glEnd();
|
||||
}
|
||||
|
||||
R_FreeStaticTriSurf(tri);
|
||||
}
|
||||
|
||||
static void CamWnd_DrawRadiantLightFrustums(CCamWnd* cam) {
|
||||
if (cam == NULL || !cam->GetRenderMode() || !(cam->GetEntityMode() || g_bShowLightVolumes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glLineWidth(1.0f);
|
||||
globalImages->BindNull();
|
||||
|
||||
for (entity_t* ent = entities.next; ent != &entities; ent = ent->next) {
|
||||
if (ent->eclass == NULL || !(ent->eclass->nShowFlags & ECLASS_LIGHT) || ent->epairs.GetBool("start_off")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
idDict spawnArgs = ent->epairs;
|
||||
renderLight_t lightParms;
|
||||
gameEdit->ParseSpawnArgsToRenderLight(&spawnArgs, &lightParms);
|
||||
|
||||
CamWnd_DrawRadiantLightFrustum(lightParms, idVec3(1.0f, 0.0f, 1.0f));
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
static bool CamWnd_FaceHasAllPlanePointsSelected(face_t* face) {
|
||||
if (face == NULL || face->face_winding == NULL) {
|
||||
return false;
|
||||
@@ -3590,13 +3820,13 @@ static bool CamWnd_FaceHasAllPlanePointsSelected(face_t* face) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CamWnd_DrawMoveSelectedBrushSidesForList(CCamWnd* cam, brush_t* list) {
|
||||
static void CamWnd_DrawMoveSelectedBrushSidesForList(const camWndBrushFilterContext_t& filter, brush_t* list) {
|
||||
if (list == NULL || list->next == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (brush_t* brush = list->next; brush != list; brush = brush->next) {
|
||||
if (CamWnd_MenuFilterBrush(cam, brush)) {
|
||||
if (CamWnd_MenuFilterBrush(filter, brush)) {
|
||||
continue;
|
||||
}
|
||||
if (brush->pPatch || brush->modelHandle > 0 || brush->entityModel) {
|
||||
@@ -3611,7 +3841,7 @@ static void CamWnd_DrawMoveSelectedBrushSidesForList(CCamWnd* cam, brush_t* list
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_DrawMoveSelectedBrushSides(CCamWnd* cam) {
|
||||
static void CamWnd_DrawMoveSelectedBrushSides(const camWndBrushFilterContext_t& filter) {
|
||||
glPushAttrib(GL_CURRENT_BIT);
|
||||
globalImages->BindNull();
|
||||
glDisable(GL_LIGHTING);
|
||||
@@ -3621,8 +3851,8 @@ static void CamWnd_DrawMoveSelectedBrushSides(CCamWnd* cam) {
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.25f);
|
||||
|
||||
CamWnd_DrawMoveSelectedBrushSidesForList(cam, &active_brushes);
|
||||
CamWnd_DrawMoveSelectedBrushSidesForList(cam, &selected_brushes);
|
||||
CamWnd_DrawMoveSelectedBrushSidesForList(filter, &active_brushes);
|
||||
CamWnd_DrawMoveSelectedBrushSidesForList(filter, &selected_brushes);
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
@@ -3756,29 +3986,10 @@ void CCamWnd::Cam_Draw() {
|
||||
|
||||
Cam_BuildMatrix();
|
||||
|
||||
for (brush = active_brushes.next; brush != &active_brushes; brush = brush->next) {
|
||||
const camWndBrushFilterContext_t brushFilter = CamWnd_MakeBrushFilterContext(this);
|
||||
|
||||
if (CullBrush(brush, false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FilterBrush(brush)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CamWnd_MenuFilterBrush(this, brush)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (renderMode) {
|
||||
if (!(entityMode && brush->owner->eclass->fixedsize)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
setGLMode(m_Camera.draw_mode);
|
||||
Brush_Draw(brush);
|
||||
}
|
||||
CamWnd_DrawActiveBrushes(this, renderMode, entityMode, brushFilter);
|
||||
CamWnd_DrawRadiantLightFrustums(this);
|
||||
|
||||
|
||||
//glDepthMask ( 1 ); // Ok, write now
|
||||
@@ -3791,7 +4002,7 @@ void CCamWnd::Cam_Draw() {
|
||||
if (!renderMode) {
|
||||
// draw normally
|
||||
for (brush = pList->next; brush != pList; brush = brush->next) {
|
||||
if (CamWnd_MenuFilterBrush(this, brush)) {
|
||||
if (CamWnd_MenuFilterBrush(brushFilter, brush)) {
|
||||
continue;
|
||||
}
|
||||
if (brush->pPatch) {
|
||||
@@ -3812,7 +4023,7 @@ void CCamWnd::Cam_Draw() {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
globalImages->BindNull();
|
||||
for (brush = pList->next; brush != pList; brush = brush->next) {
|
||||
if (CamWnd_MenuFilterBrush(this, brush)) {
|
||||
if (CamWnd_MenuFilterBrush(brushFilter, brush)) {
|
||||
continue;
|
||||
}
|
||||
if (brush->pPatch || brush->modelHandle > 0) {
|
||||
@@ -3860,7 +4071,7 @@ void CCamWnd::Cam_Draw() {
|
||||
|
||||
glColor4f(1.0f, 0.0f, 0.0f, 0.25f);
|
||||
for (brush = pList->next; brush != pList; brush = brush->next) {
|
||||
if (CamWnd_MenuFilterBrush(this, brush)) {
|
||||
if (CamWnd_MenuFilterBrush(brushFilter, brush)) {
|
||||
continue;
|
||||
}
|
||||
if (brush->pPatch || brush->modelHandle > 0) {
|
||||
@@ -3872,7 +4083,7 @@ void CCamWnd::Cam_Draw() {
|
||||
}
|
||||
}
|
||||
|
||||
CamWnd_DrawMoveSelectedBrushSides(this);
|
||||
CamWnd_DrawMoveSelectedBrushSides(brushFilter);
|
||||
CamWnd_FaceExtrudeDrawPreview(this);
|
||||
CamWnd_GizmoDraw(this);
|
||||
|
||||
@@ -3913,7 +4124,7 @@ void CCamWnd::Cam_Draw() {
|
||||
// draw pointfile
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
if (CamWnd_TargetLinesVisible(this)) {
|
||||
if (CamWnd_TargetLinesVisible(brushFilter)) {
|
||||
CamWnd_DrawVisiblePathLines();
|
||||
}
|
||||
|
||||
@@ -4196,12 +4407,12 @@ static unsigned int EditorHashBrushGeometry(brush_t* brush, const idVec3& origin
|
||||
return hash;
|
||||
}
|
||||
|
||||
static unsigned int EditorHashBModelGeometry(CCamWnd* cam, entity_t* ent) {
|
||||
static unsigned int EditorHashBModelGeometry(entity_t* ent, const camWndBrushFilterContext_t& filter) {
|
||||
unsigned int hash = EDITOR_RENDER_HASH_INIT;
|
||||
hash = EditorHashString(hash, ValueForKey(ent, "name"));
|
||||
|
||||
for (brush_t* brush = ent->brushes.onext; brush != &ent->brushes; brush = brush->onext) {
|
||||
if (FilterBrush(brush) || CamWnd_MenuFilterBrush(cam, brush) || Map_IsBrushFiltered(brush)) {
|
||||
if (FilterBrush(brush) || CamWnd_MenuFilterBrush(filter, brush) || Map_IsBrushFiltered(brush)) {
|
||||
continue;
|
||||
}
|
||||
const unsigned int brushHash = EditorHashBrushGeometry(brush, ent->origin);
|
||||
@@ -4255,12 +4466,12 @@ static idRenderModel* EditorBuildSingleBrushModel(brush_t* brush, const idVec3&
|
||||
return model;
|
||||
}
|
||||
|
||||
static idRenderModel* EditorBuildBModel(CCamWnd* cam, entity_t* ent, const char* name) {
|
||||
static idRenderModel* EditorBuildBModel(entity_t* ent, const char* name, const camWndBrushFilterContext_t& filter) {
|
||||
idTriList tris(1024);
|
||||
idMatList mats(1024);
|
||||
|
||||
for (brush_t* brush = ent->brushes.onext; brush != &ent->brushes; brush = brush->onext) {
|
||||
if (FilterBrush(brush) || CamWnd_MenuFilterBrush(cam, brush) || Map_IsBrushFiltered(brush)) {
|
||||
if (FilterBrush(brush) || CamWnd_MenuFilterBrush(filter, brush) || Map_IsBrushFiltered(brush)) {
|
||||
continue;
|
||||
}
|
||||
Brush_ToTris(brush, &tris, &mats, false, true);
|
||||
@@ -4600,6 +4811,7 @@ void CCamWnd::BuildEntityRenderState(entity_t* ent, bool update) {
|
||||
idDict spawnArgs;
|
||||
const char* name = NULL;
|
||||
editorRenderEntityState_t* entityState = EditorTouchEntityState(ent);
|
||||
const camWndBrushFilterContext_t brushFilter = CamWnd_MakeBrushFilterContext(this);
|
||||
|
||||
// The old code used update=false as "tear down and recreate". The
|
||||
// incremental path keeps the handles and uses UpdateEntityDef /
|
||||
@@ -4611,7 +4823,7 @@ void CCamWnd::BuildEntityRenderState(entity_t* ent, bool update) {
|
||||
// If the entity is no longer renderable, remove only this entity's defs.
|
||||
if (ent->brushes.onext == &ent->brushes ||
|
||||
FilterBrush(ent->brushes.onext) ||
|
||||
CamWnd_MenuFilterBrush(this, ent->brushes.onext) ||
|
||||
CamWnd_MenuFilterBrush(brushFilter, ent->brushes.onext) ||
|
||||
CullBrush(ent->brushes.onext, true) ||
|
||||
Map_IsBrushFiltered(ent->brushes.onext)) {
|
||||
EditorFreeEntityModelDef(entityState, ent);
|
||||
@@ -4636,7 +4848,7 @@ void CCamWnd::BuildEntityRenderState(entity_t* ent, bool update) {
|
||||
// Brush model entity. Rebuild the renderModel only when the
|
||||
// entity-local brush geometry/materials changed. Plain movement
|
||||
// is handled by UpdateEntityDef below.
|
||||
const unsigned int geometryHash = EditorHashBModelGeometry(this, ent);
|
||||
const unsigned int geometryHash = EditorHashBModelGeometry(ent, brushFilter);
|
||||
editorRenderBModelState_t* bmodelState = EditorTouchBModelState(ent);
|
||||
idRenderModel* oldModel = NULL;
|
||||
|
||||
@@ -4646,7 +4858,7 @@ void CCamWnd::BuildEntityRenderState(entity_t* ent, bool update) {
|
||||
idStr::Icmp(bmodelState->modelName.c_str(), name) != 0);
|
||||
|
||||
if (geometryChanged) {
|
||||
idRenderModel* newModel = EditorBuildBModel(this, ent, name);
|
||||
idRenderModel* newModel = EditorBuildBModel(ent, name, brushFilter);
|
||||
if (newModel) {
|
||||
oldModel = bmodelState->model;
|
||||
bmodelState->model = newModel;
|
||||
@@ -5348,6 +5560,7 @@ void CCamWnd::DrawEntityData() {
|
||||
idVec3 color(0, 1, 0);
|
||||
glColor3fv(color.ToFloatPtr());
|
||||
|
||||
const camWndBrushFilterContext_t brushFilter = CamWnd_MakeBrushFilterContext(this);
|
||||
brush_t* brushList = &active_brushes;
|
||||
int pass = 0;
|
||||
while (brushList) {
|
||||
@@ -5361,7 +5574,7 @@ void CCamWnd::DrawEntityData() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CamWnd_MenuFilterBrush(this, brush)) {
|
||||
if (CamWnd_MenuFilterBrush(brushFilter, brush)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -5474,97 +5474,140 @@ bool FilterBrush(brush_t *pb) {
|
||||
the lines can be visible when neither end is. Called for both camera view and xy view.
|
||||
=======================================================================================================================
|
||||
*/
|
||||
void DrawPathLines(void) {
|
||||
int i, k;
|
||||
idVec3 mid, mid1;
|
||||
entity_t *se, *te;
|
||||
brush_t *sb, *tb;
|
||||
const char *psz;
|
||||
idVec3 dir, s1, s2;
|
||||
float len, f;
|
||||
int arrows;
|
||||
int num_entities;
|
||||
const char *ent_target[MAX_MAP_ENTITIES];
|
||||
entity_t *ent_entity[MAX_MAP_ENTITIES];
|
||||
struct pathLineNamedEntity_t {
|
||||
const char* name;
|
||||
entity_t* entity;
|
||||
brush_t* brush;
|
||||
};
|
||||
|
||||
static bool DrawPathLines_IsTargetKey(const char* key) {
|
||||
if (key == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (idStr::Cmp(key, "target") == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (idStr::Cmpn(key, "target", 6) != 0 || key[6] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const char* c = key + 6; *c != '\0'; c++) {
|
||||
if (*c < '0' || *c > '9') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static brush_t* DrawPathLines_FirstBrush(entity_t* ent) {
|
||||
if (ent == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
brush_t* brush = ent->brushes.onext;
|
||||
return (brush != &ent->brushes) ? brush : NULL;
|
||||
}
|
||||
|
||||
static void DrawPathLines_AppendNamedEntity(idList<pathLineNamedEntity_t>& namedEntities, idHashIndex& nameHash, entity_t* ent) {
|
||||
const char* name = ValueForKey(ent, "name");
|
||||
if (name == NULL || name[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
brush_t* brush = DrawPathLines_FirstBrush(ent);
|
||||
if (brush == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pathLineNamedEntity_t named;
|
||||
named.name = name;
|
||||
named.entity = ent;
|
||||
named.brush = brush;
|
||||
|
||||
const int index = namedEntities.Append(named);
|
||||
nameHash.Add(nameHash.GenerateKey(name, true), index);
|
||||
}
|
||||
|
||||
static void DrawPathLines_DrawConnection(const pathLineNamedEntity_t& namedTarget, entity_t* source, brush_t* sourceBrush) {
|
||||
if (namedTarget.entity == NULL || namedTarget.entity->eclass == NULL || source == NULL || sourceBrush == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 mid = namedTarget.brush->owner->origin;
|
||||
idVec3 mid1 = sourceBrush->owner->origin;
|
||||
idVec3 dir, s1, s2;
|
||||
|
||||
VectorSubtract(mid1, mid, dir);
|
||||
const float len = dir.Normalize();
|
||||
s1[0] = -dir[1] * 8 + dir[0] * 8;
|
||||
s2[0] = dir[1] * 8 + dir[0] * 8;
|
||||
s1[1] = dir[0] * 8 + dir[1] * 8;
|
||||
s2[1] = -dir[0] * 8 + dir[1] * 8;
|
||||
|
||||
glColor3f(namedTarget.entity->eclass->color[0], namedTarget.entity->eclass->color[1], namedTarget.entity->eclass->color[2]);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(mid.ToFloatPtr());
|
||||
glVertex3fv(mid1.ToFloatPtr());
|
||||
|
||||
const int arrows = (int)(len / 256) + 1;
|
||||
for (int i = 0; i < arrows; i++) {
|
||||
const float f = len * (i + 0.5f) / arrows;
|
||||
|
||||
mid1 = mid + (f * dir);
|
||||
|
||||
glVertex3fv(mid1.ToFloatPtr());
|
||||
glVertex3f(mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
|
||||
glVertex3fv(mid1.ToFloatPtr());
|
||||
glVertex3f(mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void DrawPathLines(void) {
|
||||
if (g_qeglobals.d_savedinfo.exclude & EXCLUDE_PATHS) {
|
||||
return;
|
||||
}
|
||||
|
||||
num_entities = 0;
|
||||
for (te = entities.next; te != &entities && num_entities != MAX_MAP_ENTITIES; te = te->next) {
|
||||
for (int i = 0; i < 2048; i++) {
|
||||
if (i == 0) {
|
||||
ent_target[num_entities] = ValueForKey(te, "target");
|
||||
} else {
|
||||
ent_target[num_entities] = ValueForKey(te, va("target%i", i));
|
||||
}
|
||||
if (ent_target[num_entities][0]) {
|
||||
ent_entity[num_entities] = te;
|
||||
num_entities++;
|
||||
} else if (i > 16) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
idList<pathLineNamedEntity_t> namedEntities;
|
||||
idHashIndex nameHash(1024, 1024);
|
||||
namedEntities.SetGranularity(256);
|
||||
|
||||
for (entity_t* ent = entities.next; ent != &entities; ent = ent->next) {
|
||||
DrawPathLines_AppendNamedEntity(namedEntities, nameHash, ent);
|
||||
}
|
||||
|
||||
for (se = entities.next; se != &entities; se = se->next) {
|
||||
psz = ValueForKey(se, "name");
|
||||
|
||||
if (psz == NULL || psz[0] == '\0') {
|
||||
for (entity_t* source = entities.next; source != &entities; source = source->next) {
|
||||
brush_t* sourceBrush = DrawPathLines_FirstBrush(source);
|
||||
if (sourceBrush == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sb = se->brushes.onext;
|
||||
if (sb == &se->brushes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (k = 0; k < num_entities; k++) {
|
||||
if (strcmp(ent_target[k], psz)) {
|
||||
const int numKeys = source->epairs.GetNumKeyVals();
|
||||
for (int keyIndex = 0; keyIndex < numKeys; keyIndex++) {
|
||||
const idKeyValue* kv = source->epairs.GetKeyVal(keyIndex);
|
||||
if (kv == NULL || !DrawPathLines_IsTargetKey(kv->GetKey().c_str())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
te = ent_entity[k];
|
||||
tb = te->brushes.onext;
|
||||
if (tb == &te->brushes) {
|
||||
const char* targetName = kv->GetValue().c_str();
|
||||
if (targetName == NULL || targetName[0] == '\0') {
|
||||
continue;
|
||||
}
|
||||
|
||||
mid = sb->owner->origin;
|
||||
mid1 = tb->owner->origin;
|
||||
|
||||
VectorSubtract(mid1, mid, dir);
|
||||
len = dir.Normalize();
|
||||
s1[0] = -dir[1] * 8 + dir[0] * 8;
|
||||
s2[0] = dir[1] * 8 + dir[0] * 8;
|
||||
s1[1] = dir[0] * 8 + dir[1] * 8;
|
||||
s2[1] = -dir[0] * 8 + dir[1] * 8;
|
||||
|
||||
glColor3f(se->eclass->color[0], se->eclass->color[1], se->eclass->color[2]);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(mid.ToFloatPtr());
|
||||
glVertex3fv(mid1.ToFloatPtr());
|
||||
|
||||
arrows = (int)(len / 256) + 1;
|
||||
|
||||
for (i = 0; i < arrows; i++) {
|
||||
f = len * (i + 0.5) / arrows;
|
||||
|
||||
mid1 = mid + (f * dir);
|
||||
|
||||
glVertex3fv(mid1.ToFloatPtr());
|
||||
glVertex3f(mid1[0] + s1[0], mid1[1] + s1[1], mid1[2]);
|
||||
glVertex3fv(mid1.ToFloatPtr());
|
||||
glVertex3f(mid1[0] + s2[0], mid1[1] + s2[1], mid1[2]);
|
||||
const int hashKey = nameHash.GenerateKey(targetName, true);
|
||||
for (int index = nameHash.First(hashKey); index != -1; index = nameHash.Next(index)) {
|
||||
const pathLineNamedEntity_t& namedTarget = namedEntities[index];
|
||||
if (strcmp(namedTarget.name, targetName) == 0) {
|
||||
DrawPathLines_DrawConnection(namedTarget, source, sourceBrush);
|
||||
}
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user