mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-16 00:01:53 +02:00
Editor: Added ability to hide/unhide utility brushes and target lines.
Tweaked path tracing so lighting is more realistic.
This commit is contained in:
@@ -1012,12 +1012,16 @@ static const char* CAMWND_PROP_FILTER_MASK = "QER_CamWnd_FilterMask";
|
||||
#define CAMWND_MENU_CMD_SHOW_ENTITIES 62104
|
||||
#define CAMWND_MENU_CMD_SHOW_LIGHTS 62105
|
||||
#define CAMWND_MENU_CMD_RESET_FILTERS 62106
|
||||
#define CAMWND_MENU_CMD_SHOW_TARGET_LINES 62107
|
||||
#define CAMWND_MENU_CMD_SHOW_TRIGGER_BRUSHES 62108
|
||||
|
||||
#define CAMWND_FILTER_HIDE_WORLD 0x00000001
|
||||
#define CAMWND_FILTER_HIDE_PATCHES 0x00000002
|
||||
#define CAMWND_FILTER_HIDE_MODELS 0x00000004
|
||||
#define CAMWND_FILTER_HIDE_ENTITIES 0x00000008
|
||||
#define CAMWND_FILTER_HIDE_LIGHTS 0x00000010
|
||||
#define CAMWND_FILTER_HIDE_TARGET_LINES 0x00000020
|
||||
#define CAMWND_FILTER_HIDE_TRIGGER_BRUSHES 0x00000040
|
||||
|
||||
static LRESULT CALLBACK CamWnd_MenuBarProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
@@ -1186,6 +1190,12 @@ static void CamWnd_HandleMenuCommand(CCamWnd* cam, int command) {
|
||||
case CAMWND_MENU_CMD_SHOW_LIGHTS:
|
||||
CamWnd_ToggleFilterBit(cam, CAMWND_FILTER_HIDE_LIGHTS);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_SHOW_TARGET_LINES:
|
||||
CamWnd_ToggleFilterBit(cam, CAMWND_FILTER_HIDE_TARGET_LINES);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_SHOW_TRIGGER_BRUSHES:
|
||||
CamWnd_ToggleFilterBit(cam, CAMWND_FILTER_HIDE_TRIGGER_BRUSHES);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_RESET_FILTERS:
|
||||
CamWnd_ResetFilters(cam);
|
||||
break;
|
||||
@@ -1241,6 +1251,9 @@ static void CamWnd_ShowFiltersMenu(HWND hWnd, CCamWnd* cam) {
|
||||
CamWnd_AppendVisibleFilterItem(menu, mask, CAMWND_FILTER_HIDE_ENTITIES, CAMWND_MENU_CMD_SHOW_ENTITIES, "Show entities");
|
||||
CamWnd_AppendVisibleFilterItem(menu, mask, CAMWND_FILTER_HIDE_LIGHTS, CAMWND_MENU_CMD_SHOW_LIGHTS, "Show lights");
|
||||
AppendMenu(menu, MF_SEPARATOR, 0, NULL);
|
||||
CamWnd_AppendVisibleFilterItem(menu, mask, CAMWND_FILTER_HIDE_TARGET_LINES, CAMWND_MENU_CMD_SHOW_TARGET_LINES, "Show actor/link lines");
|
||||
CamWnd_AppendVisibleFilterItem(menu, mask, CAMWND_FILTER_HIDE_TRIGGER_BRUSHES, CAMWND_MENU_CMD_SHOW_TRIGGER_BRUSHES, "Show trigger/utility brushes");
|
||||
AppendMenu(menu, MF_SEPARATOR, 0, NULL);
|
||||
AppendMenu(menu, MF_STRING, CAMWND_MENU_CMD_RESET_FILTERS, "Reset filters");
|
||||
|
||||
command = TrackPopupMenu(menu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y, 0, hWnd, NULL);
|
||||
@@ -1370,6 +1383,154 @@ static void CamWnd_UpdateRuntimeState(CCamWnd* cam, bool renderMode, bool rebuil
|
||||
}
|
||||
}
|
||||
|
||||
static bool CamWnd_StringStartsWithNoCase(const char* text, const char* prefix) {
|
||||
if (text == NULL || prefix == NULL || prefix[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
return idStr::Icmpn(text, prefix, (int)strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
static bool CamWnd_StringContainsNoCase(const char* text, const char* needle) {
|
||||
if (text == NULL || needle == NULL || needle[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int needleLen = (int)strlen(needle);
|
||||
for (const char* scan = text; *scan; scan++) {
|
||||
if (idStr::Icmpn(scan, needle, needleLen) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CamWnd_MaterialPathHasSegment(const char* materialName, const char* segment) {
|
||||
if (materialName == NULL || segment == NULL || segment[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int segmentLen = (int)strlen(segment);
|
||||
for (const char* scan = materialName; *scan; scan++) {
|
||||
const bool segmentStart = (scan == materialName || scan[-1] == '/' || scan[-1] == '\\');
|
||||
if (!segmentStart) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (idStr::Icmpn(scan, segment, segmentLen) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char end = scan[segmentLen];
|
||||
if (end == '\0' || end == '/' || end == '\\') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CamWnd_IsUtilityMaterial(const idMaterial* material) {
|
||||
if (material == NULL || material->GetName() == NULL || material->GetName()[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* materialName = material->GetName();
|
||||
|
||||
// Nodraw is the important case here and may appear outside textures/common
|
||||
// in some projects, so match it anywhere in the material name.
|
||||
if (CamWnd_StringContainsNoCase(materialName, "nodraw")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// The broader names below are only treated as utility when they live in a
|
||||
// common/editor tool-material folder. This avoids hiding ordinary art
|
||||
// materials that happen to contain words like "clip" or "portal".
|
||||
if (!CamWnd_MaterialPathHasSegment(materialName, "common") &&
|
||||
!CamWnd_MaterialPathHasSegment(materialName, "editor")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* const utilityTokens[] = {
|
||||
"caulk",
|
||||
"trigger",
|
||||
"clip",
|
||||
"playerclip",
|
||||
"monsterclip",
|
||||
"moveclip",
|
||||
"missileclip",
|
||||
"aas",
|
||||
"ladder",
|
||||
"origin",
|
||||
"portal",
|
||||
"visportal",
|
||||
"hint",
|
||||
"skip",
|
||||
"collision"
|
||||
};
|
||||
|
||||
for (int i = 0; i < (int)(sizeof(utilityTokens) / sizeof(utilityTokens[0])); i++) {
|
||||
if (CamWnd_StringContainsNoCase(materialName, utilityTokens[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CamWnd_BrushUsesOnlyUtilityMaterials(brush_t* brush) {
|
||||
if (brush == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (brush->pPatch) {
|
||||
return CamWnd_IsUtilityMaterial(brush->pPatch->d_texture);
|
||||
}
|
||||
|
||||
bool foundMaterial = false;
|
||||
for (face_t* face = brush->brush_faces; face; face = face->next) {
|
||||
if (face->face_winding == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (face->d_texture == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foundMaterial = true;
|
||||
if (!CamWnd_IsUtilityMaterial(face->d_texture)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return foundMaterial;
|
||||
}
|
||||
|
||||
static bool CamWnd_IsTriggerLikeBrushEntity(brush_t* brush) {
|
||||
if (brush == NULL || brush->owner == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* className = ValueForKey(brush->owner, "classname");
|
||||
if (className == NULL || className[0] == '\0') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// These brush entities are editor/gameplay volumes rather than visible map
|
||||
// geometry, so let the camera filter hide them independently from normal
|
||||
// func_* brush models such as doors, movers, and func_static.
|
||||
return CamWnd_StringStartsWithNoCase(className, "trigger") ||
|
||||
CamWnd_StringStartsWithNoCase(className, "func_trigger") ||
|
||||
CamWnd_StringStartsWithNoCase(className, "func_clip") ||
|
||||
CamWnd_StringStartsWithNoCase(className, "func_playerclip") ||
|
||||
CamWnd_StringStartsWithNoCase(className, "func_monsterclip") ||
|
||||
CamWnd_StringStartsWithNoCase(className, "clip") ||
|
||||
CamWnd_StringStartsWithNoCase(className, "playerclip") ||
|
||||
CamWnd_StringStartsWithNoCase(className, "monsterclip");
|
||||
}
|
||||
|
||||
static bool CamWnd_TargetLinesVisible(CCamWnd* cam) {
|
||||
return (CamWnd_GetFilterMask(cam) & CAMWND_FILTER_HIDE_TARGET_LINES) == 0;
|
||||
}
|
||||
|
||||
static bool CamWnd_MenuFilterBrush(CCamWnd* cam, brush_t* brush) {
|
||||
if (!brush) {
|
||||
return false;
|
||||
@@ -1394,8 +1555,13 @@ static bool CamWnd_MenuFilterBrush(CCamWnd* cam, brush_t* brush) {
|
||||
const bool isModel = (brush->modelHandle > 0) || (hasOwner && brush->owner->eclass->entityModel) || brush->entityModel;
|
||||
const bool isBrushModel = hasOwner && IsBModel(brush);
|
||||
const bool isFixedEntity = hasOwner && brush->owner->eclass->fixedsize;
|
||||
const bool isTriggerLikeBrushEntity = CamWnd_IsTriggerLikeBrushEntity(brush);
|
||||
const bool isUtilityMaterialBrush = CamWnd_BrushUsesOnlyUtilityMaterials(brush);
|
||||
const bool isEntity = isLight || isModel || isBrushModel || isFixedEntity;
|
||||
|
||||
if ((mask & CAMWND_FILTER_HIDE_TRIGGER_BRUSHES) && (isTriggerLikeBrushEntity || isUtilityMaterialBrush)) {
|
||||
return true;
|
||||
}
|
||||
if ((mask & CAMWND_FILTER_HIDE_LIGHTS) && isLight) {
|
||||
return true;
|
||||
}
|
||||
@@ -2641,7 +2807,9 @@ void CCamWnd::Cam_Draw() {
|
||||
// draw pointfile
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
CamWnd_DrawVisiblePathLines();
|
||||
if (CamWnd_TargetLinesVisible(this)) {
|
||||
CamWnd_DrawVisiblePathLines();
|
||||
}
|
||||
|
||||
if (g_qeglobals.d_pointfile_display_list) {
|
||||
Pointfile_Draw();
|
||||
|
||||
Reference in New Issue
Block a user