mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-15 07:40:44 +02:00
Added screensapce decal system and stamp placement system in Radiant.
This commit is contained in:
@@ -31,6 +31,7 @@ If you have questions concerning this license or the applicable additional terms
|
||||
|
||||
#include "qe3.h"
|
||||
#include "Radiant.h"
|
||||
#include "EditorMap.h"
|
||||
#include "XYWnd.h"
|
||||
#include "CamWnd.h"
|
||||
#include "OutlinerDlg.h"
|
||||
@@ -118,6 +119,52 @@ struct cameraNavState_t {
|
||||
|
||||
static cameraNavConfig_t s_cameraNavConfig;
|
||||
static cameraNavState_t s_cameraNavState;
|
||||
static void CameraNav_GetIniPath(char* path, int pathSize);
|
||||
|
||||
static bool CamWnd_DecalPlacementEnabled() {
|
||||
char iniPath[MAX_PATH];
|
||||
CameraNav_GetIniPath(iniPath, sizeof(iniPath));
|
||||
return GetPrivateProfileInt("decals", "enabled", 0, iniPath) != 0;
|
||||
}
|
||||
|
||||
static float CamWnd_DecalFloat(const char* key, const char* defaultValue) {
|
||||
char iniPath[MAX_PATH];
|
||||
char value[64];
|
||||
CameraNav_GetIniPath(iniPath, sizeof(iniPath));
|
||||
GetPrivateProfileString("decals", key, defaultValue, value, sizeof(value), iniPath);
|
||||
return (float)atof(value);
|
||||
}
|
||||
|
||||
static void CamWnd_DecalMaterial(idStr& material) {
|
||||
const char* selected = g_qeglobals.d_texturewin.texdef.name;
|
||||
if (selected && selected[0] && selected[0] != '(') {
|
||||
material = selected;
|
||||
return;
|
||||
}
|
||||
material = "textures/decals/default";
|
||||
}
|
||||
|
||||
static void CamWnd_DecalColorFromSelectedMaterial(const idStr& material, idVec4& color) {
|
||||
color.Set(
|
||||
CamWnd_DecalFloat("red", "1"),
|
||||
CamWnd_DecalFloat("green", "1"),
|
||||
CamWnd_DecalFloat("blue", "1"),
|
||||
CamWnd_DecalFloat("alpha", "1"));
|
||||
|
||||
const idMaterial* mat = declManager->FindMaterial(material.c_str());
|
||||
if (mat) {
|
||||
#ifndef QUAKE4
|
||||
decalInfo_t decalInfo = mat->GetDecalInfo();
|
||||
color.x *= decalInfo.start[0];
|
||||
color.y *= decalInfo.start[1];
|
||||
color.z *= decalInfo.start[2];
|
||||
color.w *= decalInfo.start[3];
|
||||
#endif
|
||||
if (mat->GetEditorImage()) {
|
||||
mat->GetEditorImage()->Bind();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CameraNav_GetIniPath(char* path, int pathSize) {
|
||||
if (pathSize <= 0) {
|
||||
@@ -1010,6 +1057,7 @@ static const char* CAMWND_PROP_RENDER_MODE = "QER_CamWnd_RenderMode";
|
||||
static const char* CAMWND_PROP_REBUILD_MODE = "QER_CamWnd_RebuildMode";
|
||||
static const char* CAMWND_PROP_ENTITY_MODE = "QER_CamWnd_EntityMode";
|
||||
static const char* CAMWND_PROP_FILTER_MASK = "QER_CamWnd_FilterMask";
|
||||
static const char* CAMWND_PROP_DECAL_EDITING = "QER_CamWnd_DecalEditing";
|
||||
|
||||
#define CAMWND_CAPTION_HEIGHT 30
|
||||
#define CAMWND_MENU_HEIGHT 22
|
||||
@@ -1025,6 +1073,7 @@ static const char* CAMWND_PROP_FILTER_MASK = "QER_CamWnd_FilterMask";
|
||||
#define CAMWND_MENU_CMD_SHOW_TARGET_LINES 62107
|
||||
#define CAMWND_MENU_CMD_SHOW_TRIGGER_BRUSHES 62108
|
||||
#define CAMWND_MENU_CMD_CUBIC_CLIPPING 62109
|
||||
#define CAMWND_MENU_CMD_DECAL_EDITING 62110
|
||||
|
||||
#define CAMWND_FILTER_HIDE_WORLD 0x00000001
|
||||
#define CAMWND_FILTER_HIDE_PATCHES 0x00000002
|
||||
@@ -1120,15 +1169,19 @@ static void CamWnd_GetMenuItemRect(HWND hWnd, int item, RECT& rect) {
|
||||
rect.left = 4;
|
||||
rect.right = 86;
|
||||
}
|
||||
else {
|
||||
else if (item == 1) {
|
||||
rect.left = 86;
|
||||
rect.right = 156;
|
||||
}
|
||||
else {
|
||||
rect.left = 156;
|
||||
rect.right = 236;
|
||||
}
|
||||
}
|
||||
|
||||
static int CamWnd_MenuHitTest(HWND hWnd, int x, int y) {
|
||||
RECT rect;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
CamWnd_GetMenuItemRect(hWnd, i, rect);
|
||||
if (x >= rect.left && x < rect.right && y >= rect.top && y < rect.bottom) {
|
||||
return i;
|
||||
@@ -1179,6 +1232,25 @@ static void CamWnd_ToggleRealtimeLighting(CCamWnd* cam) {
|
||||
CamWnd_SetRealtimeLighting(cam, !CamWnd_RealtimeLightingEnabled(cam));
|
||||
}
|
||||
|
||||
static bool CamWnd_DecalEditingEnabled(CCamWnd* cam) {
|
||||
if (!cam || !cam->GetSafeHwnd()) {
|
||||
return false;
|
||||
}
|
||||
return CamWnd_GetIntProp(cam->GetSafeHwnd(), CAMWND_PROP_DECAL_EDITING, CamWnd_DecalPlacementEnabled() ? 1 : 0) != 0;
|
||||
}
|
||||
|
||||
static void CamWnd_SetDecalEditing(CCamWnd* cam, bool enabled) {
|
||||
if (!cam || !cam->GetSafeHwnd()) {
|
||||
return;
|
||||
}
|
||||
CamWnd_SetIntProp(cam->GetSafeHwnd(), CAMWND_PROP_DECAL_EDITING, enabled ? 1 : 0);
|
||||
CamWnd_RequestRedraw(cam);
|
||||
}
|
||||
|
||||
static void CamWnd_ToggleDecalEditing(CCamWnd* cam) {
|
||||
CamWnd_SetDecalEditing(cam, !CamWnd_DecalEditingEnabled(cam));
|
||||
}
|
||||
|
||||
static void CamWnd_ToggleFilterBit(CCamWnd* cam, int bit) {
|
||||
int mask = CamWnd_GetFilterMask(cam);
|
||||
mask ^= bit;
|
||||
@@ -1211,6 +1283,9 @@ static void CamWnd_HandleMenuCommand(CCamWnd* cam, int command) {
|
||||
case CAMWND_MENU_CMD_CUBIC_CLIPPING:
|
||||
CamWnd_ToggleCubicClipping(cam);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_DECAL_EDITING:
|
||||
CamWnd_ToggleDecalEditing(cam);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_SHOW_WORLD:
|
||||
CamWnd_ToggleFilterBit(cam, CAMWND_FILTER_HIDE_WORLD);
|
||||
break;
|
||||
@@ -1268,6 +1343,28 @@ static void CamWnd_ShowLightingMenu(HWND hWnd, CCamWnd* cam) {
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_ShowDecalsMenu(HWND hWnd, CCamWnd* cam) {
|
||||
RECT itemRect;
|
||||
POINT pt;
|
||||
HMENU menu;
|
||||
int command;
|
||||
|
||||
CamWnd_GetMenuItemRect(hWnd, 2, itemRect);
|
||||
pt.x = itemRect.left;
|
||||
pt.y = itemRect.bottom;
|
||||
ClientToScreen(hWnd, &pt);
|
||||
|
||||
menu = CreatePopupMenu();
|
||||
AppendMenu(menu, MF_STRING | (CamWnd_DecalEditingEnabled(cam) ? MF_CHECKED : 0), CAMWND_MENU_CMD_DECAL_EDITING, "Enable decal editing");
|
||||
|
||||
command = TrackPopupMenu(menu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y, 0, hWnd, NULL);
|
||||
DestroyMenu(menu);
|
||||
|
||||
if (command) {
|
||||
CamWnd_HandleMenuCommand(cam, command);
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_ShowFiltersMenu(HWND hWnd, CCamWnd* cam) {
|
||||
RECT itemRect;
|
||||
POINT pt;
|
||||
@@ -1313,6 +1410,9 @@ static void CamWnd_ShowTopMenu(HWND hWnd, int item) {
|
||||
else if (item == 1) {
|
||||
CamWnd_ShowFiltersMenu(hWnd, cam);
|
||||
}
|
||||
else if (item == 2) {
|
||||
CamWnd_ShowDecalsMenu(hWnd, cam);
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_RegisterMenuBarClass() {
|
||||
@@ -1397,6 +1497,7 @@ static void CamWnd_DestroyMenuBar(CCamWnd* cam) {
|
||||
RemoveProp(cam->GetSafeHwnd(), CAMWND_PROP_REBUILD_MODE);
|
||||
RemoveProp(cam->GetSafeHwnd(), CAMWND_PROP_ENTITY_MODE);
|
||||
RemoveProp(cam->GetSafeHwnd(), CAMWND_PROP_FILTER_MASK);
|
||||
RemoveProp(cam->GetSafeHwnd(), CAMWND_PROP_DECAL_EDITING);
|
||||
}
|
||||
|
||||
static bool CamWnd_PointInMenuBar(CCamWnd* cam, const CPoint& point) {
|
||||
@@ -1703,9 +1804,11 @@ static void CamWnd_FaceExtrudeBuildRay(CCamWnd* cam, const CPoint& point, idVec3
|
||||
float u = 0.0f;
|
||||
float r = 0.0f;
|
||||
if (camera.width > 0) {
|
||||
u = (float)(y - camera.height / 2) / (camera.width / 2);
|
||||
r = (float)(x - camera.width / 2) / (camera.width / 2);
|
||||
}
|
||||
if (camera.width > 0) {
|
||||
u = (float)(y - camera.height / 2) / (camera.width / 2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
dir[i] = camera.vpn[i] + camera.vright[i] * r + camera.vup[i] * u;
|
||||
@@ -1713,6 +1816,75 @@ static void CamWnd_FaceExtrudeBuildRay(CCamWnd* cam, const CPoint& point, idVec3
|
||||
dir.Normalize();
|
||||
}
|
||||
|
||||
static bool CamWnd_DecalClick(CCamWnd* cam, const CPoint& point, UINT nFlags) {
|
||||
if (!CamWnd_DecalEditingEnabled(cam) || cam == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idVec3 dir;
|
||||
CamWnd_FaceExtrudeBuildRay(cam, point, dir);
|
||||
|
||||
if (nFlags & MK_SHIFT) {
|
||||
Map_SelectDecalByRay(cam->Camera().origin, dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
idVec3 hitPoint;
|
||||
idVec3 hitNormal;
|
||||
float hitDist = HUGE_DISTANCE;
|
||||
bool hitBrush = false;
|
||||
const char* hitSource = "none";
|
||||
|
||||
qertrace_t trace = Test_Ray(cam->Camera().origin, dir, 0);
|
||||
if (trace.brush != NULL && trace.face != NULL && trace.dist > 0.0f && trace.dist < hitDist) {
|
||||
hitBrush = true;
|
||||
hitSource = "brush";
|
||||
hitDist = trace.dist;
|
||||
hitPoint = cam->Camera().origin + dir * trace.dist;
|
||||
hitNormal = trace.face->plane.Normal();
|
||||
}
|
||||
|
||||
if (g_qeglobals.rw) {
|
||||
modelTrace_t modelTrace;
|
||||
idVec3 end = cam->Camera().origin + dir * HUGE_DISTANCE;
|
||||
if (g_qeglobals.rw->Trace(modelTrace, cam->Camera().origin, end, 0.0f, false, false)) {
|
||||
float modelDist = (modelTrace.point - cam->Camera().origin) * dir;
|
||||
if (!hitBrush && modelDist > 0.0f && modelDist < hitDist) {
|
||||
hitSource = "render";
|
||||
hitDist = modelDist;
|
||||
hitPoint = modelTrace.point;
|
||||
hitNormal = modelTrace.normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hitDist <= 0.0f || hitDist >= HUGE_DISTANCE || hitNormal.LengthSqr() < 0.0001f) {
|
||||
return true;
|
||||
}
|
||||
|
||||
renderWorldDecal_t decal;
|
||||
CamWnd_DecalMaterial(decal.material);
|
||||
CamWnd_DecalColorFromSelectedMaterial(decal.material, decal.color);
|
||||
decal.origin = hitPoint;
|
||||
decal.normal = hitNormal;
|
||||
if ((decal.normal * dir) > 0.0f) {
|
||||
decal.normal = -decal.normal;
|
||||
}
|
||||
decal.axisU = decal.normal.Cross(cam->Camera().vup);
|
||||
if (decal.axisU.LengthSqr() < 0.0001f) {
|
||||
decal.axisU = decal.normal.Cross(cam->Camera().vright);
|
||||
}
|
||||
decal.axisV = decal.normal.Cross(decal.axisU);
|
||||
decal.size = CamWnd_DecalFloat("size", "64");
|
||||
decal.depth = CamWnd_DecalFloat("depth", "8");
|
||||
decal.opacity = CamWnd_DecalFloat("opacity", "1");
|
||||
|
||||
Map_AddDecal(decal);
|
||||
Sys_Status(va("Placed decal using %s on %s at %.2f %.2f %.2f\n", decal.material.c_str(), hitSource, decal.origin.x, decal.origin.y, decal.origin.z), 0);
|
||||
Sys_UpdateWindows(W_CAMERA);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CamWnd_FaceExtrudeBrushAllowed(CCamWnd* cam, brush_t* brush) {
|
||||
if (brush == NULL || brush->owner == NULL || brush->owner->eclass == NULL) {
|
||||
return false;
|
||||
@@ -2665,6 +2837,9 @@ static LRESULT CALLBACK CamWnd_MenuBarProc(HWND hWnd, UINT uMsg, WPARAM wParam,
|
||||
CamWnd_GetMenuItemRect(hWnd, 1, itemRect);
|
||||
RoundRect(hDC, itemRect.left + 3, itemRect.top + 2, itemRect.right - 3, itemRect.bottom - 2, 6, 6);
|
||||
DrawText(hDC, "Filters", -1, &itemRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
||||
CamWnd_GetMenuItemRect(hWnd, 2, itemRect);
|
||||
RoundRect(hDC, itemRect.left + 3, itemRect.top + 2, itemRect.right - 3, itemRect.bottom - 2, 6, 6);
|
||||
DrawText(hDC, "Decals", -1, &itemRect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
|
||||
::SelectObject(hDC, oldPen);
|
||||
::SelectObject(hDC, oldBrush);
|
||||
::DeleteObject(borderPen);
|
||||
@@ -2849,6 +3024,10 @@ void CCamWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
|
||||
CamWnd_FaceExtrudeEnd(this, false);
|
||||
return;
|
||||
}
|
||||
if (nChar == VK_DELETE && CamWnd_DecalEditingEnabled(this) && Map_GetSelectedDecal() >= 0) {
|
||||
Map_DeleteSelectedDecal();
|
||||
return;
|
||||
}
|
||||
if (CameraNav_HandleKeyDown(this, nChar)) {
|
||||
return;
|
||||
}
|
||||
@@ -2975,6 +3154,9 @@ void CCamWnd::OnLButtonDown(UINT nFlags, CPoint point) {
|
||||
if ((nFlags & MK_CONTROL) && (nFlags & MK_SHIFT) && CamWnd_FaceExtrudeBegin(this, point)) {
|
||||
return;
|
||||
}
|
||||
if (CamWnd_DecalClick(this, point, nFlags)) {
|
||||
return;
|
||||
}
|
||||
if (CamWnd_GizmoBegin(this, point, nFlags)) {
|
||||
return;
|
||||
}
|
||||
@@ -3857,7 +4039,6 @@ static void CamWnd_DrawMoveSelectedBrushSides(const camWndBrushFilterContext_t&
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
|
||||
extern void glLabeledPoint(idVec4& color, idVec3& point, float size, const char* label);
|
||||
void DrawAxial(face_t* selFace) {
|
||||
if (g_bAxialMode) {
|
||||
@@ -4084,6 +4265,9 @@ void CCamWnd::Cam_Draw() {
|
||||
}
|
||||
|
||||
CamWnd_DrawMoveSelectedBrushSides(brushFilter);
|
||||
if (!renderMode && g_qeglobals.rw && CamWnd_DecalEditingEnabled(this)) {
|
||||
g_qeglobals.rw->SubmitWorldDecalsToScreenSpace();
|
||||
}
|
||||
CamWnd_FaceExtrudeDrawPreview(this);
|
||||
CamWnd_GizmoDraw(this);
|
||||
|
||||
@@ -4141,7 +4325,7 @@ void CCamWnd::Cam_Draw() {
|
||||
CameraNav_DrawOverlay(this);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glFinish();
|
||||
//glFinish();
|
||||
QE_CheckOpenGLForErrors();
|
||||
|
||||
if (!renderMode) {
|
||||
@@ -5682,6 +5866,17 @@ void CCamWnd::Cam_Render() {
|
||||
}
|
||||
Cam_SetGlobalFogFromWorldspawn(refdef);
|
||||
|
||||
if (g_qeglobals.rw && CamWnd_DecalEditingEnabled(this)) {
|
||||
for (int i = 0; i < g_qeglobals.rw->NumWorldDecals(); ++i) {
|
||||
const renderWorldDecal_t* decal = g_qeglobals.rw->GetWorldDecal(i);
|
||||
if (!decal) {
|
||||
continue;
|
||||
}
|
||||
idVec4 color = (i == Map_GetSelectedDecal()) ? idVec4(1.0f, 0.85f, 0.1f, 1.0f) : idVec4(0.1f, 0.8f, 1.0f, 1.0f);
|
||||
g_qeglobals.rw->DebugCircle(color, decal->origin, decal->normal, decal->size * 0.5f, 32, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
g_qeglobals.rw->RenderScene(&refdef);
|
||||
|
||||
int frontEnd, backEnd;
|
||||
|
||||
@@ -82,6 +82,209 @@ void Map_SaveBetween(void) {
|
||||
|
||||
}
|
||||
|
||||
static int s_selectedWorldDecal = -1;
|
||||
|
||||
static idStr Map_DecalFileName(const char* filename) {
|
||||
idStr decalFile = filename ? filename : currentmap;
|
||||
decalFile.StripFileExtension();
|
||||
decalFile.SetFileExtension(".stamp");
|
||||
return decalFile;
|
||||
}
|
||||
|
||||
static void Map_NormalizeDecal(renderWorldDecal_t& decal) {
|
||||
if (decal.normal.LengthSqr() < 0.0001f) {
|
||||
decal.normal.Set(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
decal.normal.Normalize();
|
||||
decal.axisU -= decal.normal * (decal.axisU * decal.normal);
|
||||
if (decal.axisU.LengthSqr() < 0.0001f) {
|
||||
decal.axisU = decal.normal.Cross(idVec3(0.0f, 0.0f, 1.0f));
|
||||
if (decal.axisU.LengthSqr() < 0.0001f) {
|
||||
decal.axisU = decal.normal.Cross(idVec3(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
}
|
||||
decal.axisU.Normalize();
|
||||
decal.axisV = decal.normal.Cross(decal.axisU);
|
||||
decal.axisV.Normalize();
|
||||
if (decal.size <= 0.0f) {
|
||||
decal.size = 64.0f;
|
||||
}
|
||||
if (decal.depth <= 0.0f) {
|
||||
decal.depth = 8.0f;
|
||||
}
|
||||
if (decal.opacity <= 0.0f) {
|
||||
decal.opacity = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
int Map_AddDecal(const renderWorldDecal_t& inDecal) {
|
||||
if (!g_qeglobals.rw) {
|
||||
return -1;
|
||||
}
|
||||
renderWorldDecal_t decal = inDecal;
|
||||
Map_NormalizeDecal(decal);
|
||||
s_selectedWorldDecal = g_qeglobals.rw->AddWorldDecal(decal);
|
||||
mapModified = 1;
|
||||
return s_selectedWorldDecal;
|
||||
}
|
||||
|
||||
int Map_GetSelectedDecal(void) {
|
||||
return s_selectedWorldDecal;
|
||||
}
|
||||
|
||||
void Map_DeleteSelectedDecal(void) {
|
||||
if (!g_qeglobals.rw || s_selectedWorldDecal < 0) {
|
||||
return;
|
||||
}
|
||||
g_qeglobals.rw->RemoveWorldDecal(s_selectedWorldDecal);
|
||||
s_selectedWorldDecal = -1;
|
||||
mapModified = 1;
|
||||
Sys_UpdateWindows(W_ALL);
|
||||
}
|
||||
|
||||
int Map_SelectDecalByRay(const idVec3& origin, const idVec3& dir) {
|
||||
if (!g_qeglobals.rw) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float bestT = 1e30f;
|
||||
int bestIndex = -1;
|
||||
for (int i = 0; i < g_qeglobals.rw->NumWorldDecals(); ++i) {
|
||||
const renderWorldDecal_t* decal = g_qeglobals.rw->GetWorldDecal(i);
|
||||
if (!decal) {
|
||||
continue;
|
||||
}
|
||||
float denom = dir * decal->normal;
|
||||
if (fabs(denom) < 0.0001f) {
|
||||
continue;
|
||||
}
|
||||
float t = ((decal->origin - origin) * decal->normal) / denom;
|
||||
if (t <= 0.0f || t >= bestT) {
|
||||
continue;
|
||||
}
|
||||
idVec3 hit = origin + dir * t;
|
||||
idVec3 rel = hit - decal->origin;
|
||||
float u = rel * decal->axisU;
|
||||
float v = rel * decal->axisV;
|
||||
if (fabs(u) <= decal->size * 0.5f && fabs(v) <= decal->size * 0.5f) {
|
||||
bestT = t;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
s_selectedWorldDecal = bestIndex;
|
||||
Sys_UpdateWindows(W_CAMERA);
|
||||
return bestIndex;
|
||||
}
|
||||
|
||||
void Map_SaveDecals(const char* filename) {
|
||||
if (!g_qeglobals.rw) {
|
||||
return;
|
||||
}
|
||||
|
||||
idStr decalFile = Map_DecalFileName(filename);
|
||||
const bool osPath = strstr(decalFile.c_str(), ":") != NULL;
|
||||
idFile* file = osPath ? fileSystem->OpenExplicitFileWrite(decalFile.c_str()) : fileSystem->OpenFileWrite(decalFile.c_str());
|
||||
if (!file) {
|
||||
common->Warning("Map_SaveDecals: couldn't write %s", decalFile.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
file->WriteFloatString("worldDecals 1 {\n");
|
||||
for (int i = 0; i < g_qeglobals.rw->NumWorldDecals(); ++i) {
|
||||
const renderWorldDecal_t* d = g_qeglobals.rw->GetWorldDecal(i);
|
||||
if (!d) {
|
||||
continue;
|
||||
}
|
||||
file->WriteFloatString("\tdecal {\n");
|
||||
file->WriteFloatString("\t\tmaterial \"%s\"\n", d->material.c_str());
|
||||
file->WriteFloatString("\t\torigin ( %f %f %f )\n", d->origin.x, d->origin.y, d->origin.z);
|
||||
file->WriteFloatString("\t\tnormal ( %f %f %f )\n", d->normal.x, d->normal.y, d->normal.z);
|
||||
file->WriteFloatString("\t\taxisU ( %f %f %f )\n", d->axisU.x, d->axisU.y, d->axisU.z);
|
||||
file->WriteFloatString("\t\taxisV ( %f %f %f )\n", d->axisV.x, d->axisV.y, d->axisV.z);
|
||||
file->WriteFloatString("\t\tsize %f\n", d->size);
|
||||
file->WriteFloatString("\t\tdepth %f\n", d->depth);
|
||||
file->WriteFloatString("\t\topacity %f\n", d->opacity);
|
||||
file->WriteFloatString("\t\tcolor ( %f %f %f %f )\n", d->color.x, d->color.y, d->color.z, d->color.w);
|
||||
file->WriteFloatString("\t}\n");
|
||||
}
|
||||
file->WriteFloatString("}\n");
|
||||
fileSystem->CloseFile(file);
|
||||
}
|
||||
|
||||
void Map_LoadDecals(const char* filename) {
|
||||
if (!g_qeglobals.rw) {
|
||||
return;
|
||||
}
|
||||
g_qeglobals.rw->ClearWorldDecals();
|
||||
s_selectedWorldDecal = -1;
|
||||
|
||||
idStr decalFile = Map_DecalFileName(filename);
|
||||
const bool osPath = strstr(decalFile.c_str(), ":") != NULL;
|
||||
idLexer src(LEXFL_NOSTRINGCONCAT | LEXFL_NODOLLARPRECOMPILE | LEXFL_ALLOWPATHNAMES);
|
||||
src.LoadFile(decalFile.c_str(), osPath);
|
||||
if (!src.IsLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
idToken token;
|
||||
if (!src.ReadToken(&token) || token.Icmp("worldDecals")) {
|
||||
return;
|
||||
}
|
||||
src.ReadToken(&token);
|
||||
if (token != "{") {
|
||||
src.ExpectTokenString("{");
|
||||
}
|
||||
|
||||
while (src.ReadToken(&token)) {
|
||||
if (token == "}") {
|
||||
break;
|
||||
}
|
||||
if (token.Icmp("decal")) {
|
||||
break;
|
||||
}
|
||||
renderWorldDecal_t decal;
|
||||
decal.material = "textures/decals/default";
|
||||
decal.origin.Zero();
|
||||
decal.normal.Set(0.0f, 0.0f, 1.0f);
|
||||
decal.axisU.Set(1.0f, 0.0f, 0.0f);
|
||||
decal.axisV.Set(0.0f, 1.0f, 0.0f);
|
||||
decal.size = 64.0f;
|
||||
decal.depth = 8.0f;
|
||||
decal.opacity = 1.0f;
|
||||
decal.color.Set(0.05f, 0.05f, 0.05f, 1.0f);
|
||||
|
||||
src.ExpectTokenString("{");
|
||||
while (src.ReadToken(&token)) {
|
||||
if (token == "}") {
|
||||
break;
|
||||
}
|
||||
if (!token.Icmp("material")) {
|
||||
src.ExpectAnyToken(&token);
|
||||
decal.material = token;
|
||||
} else if (!token.Icmp("origin")) {
|
||||
src.Parse1DMatrix(3, decal.origin.ToFloatPtr());
|
||||
} else if (!token.Icmp("normal")) {
|
||||
src.Parse1DMatrix(3, decal.normal.ToFloatPtr());
|
||||
} else if (!token.Icmp("axisU")) {
|
||||
src.Parse1DMatrix(3, decal.axisU.ToFloatPtr());
|
||||
} else if (!token.Icmp("axisV")) {
|
||||
src.Parse1DMatrix(3, decal.axisV.ToFloatPtr());
|
||||
} else if (!token.Icmp("size")) {
|
||||
decal.size = src.ParseFloat();
|
||||
} else if (!token.Icmp("depth")) {
|
||||
decal.depth = src.ParseFloat();
|
||||
} else if (!token.Icmp("opacity")) {
|
||||
decal.opacity = src.ParseFloat();
|
||||
} else if (!token.Icmp("color")) {
|
||||
src.Parse1DMatrix(4, decal.color.ToFloatPtr());
|
||||
}
|
||||
}
|
||||
Map_AddDecal(decal);
|
||||
}
|
||||
s_selectedWorldDecal = -1;
|
||||
mapModified = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================================================================
|
||||
=======================================================================================================================
|
||||
@@ -546,6 +749,7 @@ void Map_LoadFile(const char *filename) {
|
||||
if (g_pParentWnd->GetCamera()->GetRenderMode()) {
|
||||
g_pParentWnd->GetCamera()->BuildRendererState();
|
||||
}
|
||||
Map_LoadDecals(filename);
|
||||
|
||||
Sys_EndWait();
|
||||
Sys_UpdateWindows(W_ALL);
|
||||
@@ -790,6 +994,9 @@ bool Map_SaveFile(const char *filename, bool use_region, bool autosave) {
|
||||
sprintf(status, "Writing file %s.%s...", mapFile.c_str(), mapExt.c_str());
|
||||
dlg.SetText(status);
|
||||
map.Write(mapFile, mapExt, !(autosave || localFile));
|
||||
if (!use_region) {
|
||||
Map_SaveDecals(filename);
|
||||
}
|
||||
mapModified = 0;
|
||||
|
||||
if (use_region) {
|
||||
@@ -821,6 +1028,9 @@ void Map_New(void) {
|
||||
world_entity->brushes.onext = world_entity->brushes.oprev = &world_entity->brushes;
|
||||
SetKeyValue(world_entity, "classname", "worldspawn");
|
||||
world_entity->eclass = Eclass_ForName("worldspawn", true);
|
||||
if (g_qeglobals.rw) {
|
||||
g_qeglobals.rw->ClearWorldDecals();
|
||||
}
|
||||
|
||||
g_pParentWnd->GetCamera()->Camera().angles[YAW] = 0;
|
||||
g_pParentWnd->GetCamera()->Camera().angles[PITCH] = 0;
|
||||
|
||||
@@ -26,6 +26,11 @@ If you have questions concerning this license or the applicable additional terms
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef __EDITORMAP_H__
|
||||
#define __EDITORMAP_H__
|
||||
|
||||
#include "../../renderer/RenderWorld.h"
|
||||
|
||||
extern char currentmap[1024];
|
||||
|
||||
// head/tail of doubly linked lists
|
||||
@@ -52,6 +57,12 @@ void Map_LoadFile (const char *filename);
|
||||
bool Map_SaveFile (const char *filename, bool use_region, bool autosave = false);
|
||||
void Map_New (void);
|
||||
void Map_BuildBrushData(void);
|
||||
void Map_LoadDecals(const char *filename);
|
||||
void Map_SaveDecals(const char *filename);
|
||||
int Map_AddDecal(const renderWorldDecal_t& decal);
|
||||
void Map_DeleteSelectedDecal(void);
|
||||
int Map_SelectDecalByRay(const idVec3& origin, const idVec3& dir);
|
||||
int Map_GetSelectedDecal(void);
|
||||
|
||||
void Map_RegionOff (void);
|
||||
void Map_RegionXY (void);
|
||||
@@ -65,3 +76,5 @@ void Map_ImportBuffer (char* buf, bool renameEntities = true);
|
||||
int Map_GetUniqueEntityID(const char *prefix, const char *eclass);
|
||||
|
||||
idMapPrimitive *BrushToMapPrimitive( const brush_t *b, const idVec3 &origin );
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user