mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-16 00:01:53 +02:00
Added rotation and fixed decal placement bugs.
This commit is contained in:
@@ -120,6 +120,9 @@ struct cameraNavState_t {
|
||||
static cameraNavConfig_t s_cameraNavConfig;
|
||||
static cameraNavState_t s_cameraNavState;
|
||||
static void CameraNav_GetIniPath(char* path, int pathSize);
|
||||
static bool s_camWndDecalPreviewValid = false;
|
||||
static HWND s_camWndDecalPreviewOwner = NULL;
|
||||
static renderWorldDecal_t s_camWndDecalPreview;
|
||||
|
||||
static bool CamWnd_DecalPlacementEnabled() {
|
||||
char iniPath[MAX_PATH];
|
||||
@@ -135,13 +138,31 @@ static float CamWnd_DecalFloat(const char* key, const char* defaultValue) {
|
||||
return (float)atof(value);
|
||||
}
|
||||
|
||||
static void CamWnd_DecalMaterial(idStr& material) {
|
||||
static float s_camWndDecalPreviewRotation = 0.0f;
|
||||
|
||||
static void CamWnd_RotateDecalBasis(renderWorldDecal_t& decal, float degrees) {
|
||||
const float radians = degrees * idMath::M_DEG2RAD;
|
||||
const float s = sin(radians);
|
||||
const float c = cos(radians);
|
||||
const idVec3 oldU = decal.axisU;
|
||||
const idVec3 oldV = decal.axisV;
|
||||
decal.axisU = oldU * c + oldV * s;
|
||||
decal.axisV = oldV * c - oldU * s;
|
||||
}
|
||||
|
||||
static bool CamWnd_DecalMaterial(idStr& material) {
|
||||
const char* selected = g_qeglobals.d_texturewin.texdef.name;
|
||||
if (selected && selected[0] && selected[0] != '(') {
|
||||
material = selected;
|
||||
return;
|
||||
if (!selected || !selected[0] || selected[0] == '(') {
|
||||
return false;
|
||||
}
|
||||
material = "textures/decals/default";
|
||||
|
||||
const idMaterial* mat = declManager->FindMaterial(selected, false);
|
||||
if (!mat || mat->TestMaterialFlag(MF_DEFAULTED)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
material = selected;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CamWnd_DecalColorFromSelectedMaterial(const idStr& material, idVec4& color) {
|
||||
@@ -1074,6 +1095,10 @@ static const char* CAMWND_PROP_DECAL_EDITING = "QER_CamWnd_DecalEditing";
|
||||
#define CAMWND_MENU_CMD_SHOW_TRIGGER_BRUSHES 62108
|
||||
#define CAMWND_MENU_CMD_CUBIC_CLIPPING 62109
|
||||
#define CAMWND_MENU_CMD_DECAL_EDITING 62110
|
||||
#define CAMWND_MENU_CMD_DECAL_SCALE_UP 62111
|
||||
#define CAMWND_MENU_CMD_DECAL_SCALE_DOWN 62112
|
||||
#define CAMWND_MENU_CMD_DECAL_ROTATE_CCW 62113
|
||||
#define CAMWND_MENU_CMD_DECAL_ROTATE_CW 62114
|
||||
|
||||
#define CAMWND_FILTER_HIDE_WORLD 0x00000001
|
||||
#define CAMWND_FILTER_HIDE_PATCHES 0x00000002
|
||||
@@ -1232,6 +1257,8 @@ static void CamWnd_ToggleRealtimeLighting(CCamWnd* cam) {
|
||||
CamWnd_SetRealtimeLighting(cam, !CamWnd_RealtimeLightingEnabled(cam));
|
||||
}
|
||||
|
||||
static void CamWnd_ClearDecalPreview(CCamWnd* cam);
|
||||
|
||||
static bool CamWnd_DecalEditingEnabled(CCamWnd* cam) {
|
||||
if (!cam || !cam->GetSafeHwnd()) {
|
||||
return false;
|
||||
@@ -1243,6 +1270,9 @@ static void CamWnd_SetDecalEditing(CCamWnd* cam, bool enabled) {
|
||||
if (!cam || !cam->GetSafeHwnd()) {
|
||||
return;
|
||||
}
|
||||
if (!enabled) {
|
||||
CamWnd_ClearDecalPreview(cam);
|
||||
}
|
||||
CamWnd_SetIntProp(cam->GetSafeHwnd(), CAMWND_PROP_DECAL_EDITING, enabled ? 1 : 0);
|
||||
CamWnd_RequestRedraw(cam);
|
||||
}
|
||||
@@ -1251,6 +1281,74 @@ static void CamWnd_ToggleDecalEditing(CCamWnd* cam) {
|
||||
CamWnd_SetDecalEditing(cam, !CamWnd_DecalEditingEnabled(cam));
|
||||
}
|
||||
|
||||
static void CamWnd_ClearDecalPreview(CCamWnd* cam = NULL) {
|
||||
const bool wasValid = s_camWndDecalPreviewValid;
|
||||
if (!cam || s_camWndDecalPreviewOwner == cam->GetSafeHwnd()) {
|
||||
s_camWndDecalPreviewValid = false;
|
||||
s_camWndDecalPreviewOwner = NULL;
|
||||
if (wasValid && cam && cam->GetSafeHwnd()) {
|
||||
cam->InvalidateRect(NULL, FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_ScaleSelectedDecal(CCamWnd* cam, float scale) {
|
||||
if (Map_ScaleSelectedDecal(scale)) {
|
||||
CamWnd_RequestRedraw(cam);
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_RotateStencil(CCamWnd* cam, float degrees) {
|
||||
if (Map_GetSelectedDecal() >= 0) {
|
||||
if (Map_RotateSelectedDecal(degrees)) {
|
||||
CamWnd_RequestRedraw(cam);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
s_camWndDecalPreviewRotation += degrees;
|
||||
if (s_camWndDecalPreviewRotation >= 360.0f || s_camWndDecalPreviewRotation <= -360.0f) {
|
||||
s_camWndDecalPreviewRotation = fmod(s_camWndDecalPreviewRotation, 360.0f);
|
||||
}
|
||||
CamWnd_ClearDecalPreview(cam);
|
||||
if (cam && cam->GetSafeHwnd()) {
|
||||
CamWnd_RequestRedraw(cam);
|
||||
}
|
||||
}
|
||||
|
||||
static bool CamWnd_HandleDecalTransformChar(CCamWnd* cam, UINT nChar) {
|
||||
if (!CamWnd_DecalEditingEnabled(cam)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (nChar) {
|
||||
case '+':
|
||||
case '=':
|
||||
if (Map_GetSelectedDecal() >= 0) {
|
||||
CamWnd_ScaleSelectedDecal(cam, 1.25f);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
case '_':
|
||||
if (Map_GetSelectedDecal() >= 0) {
|
||||
CamWnd_ScaleSelectedDecal(cam, 0.8f);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 'q':
|
||||
case 'Q':
|
||||
CamWnd_RotateStencil(cam, -15.0f);
|
||||
return true;
|
||||
case 'e':
|
||||
case 'E':
|
||||
CamWnd_RotateStencil(cam, 15.0f);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void CamWnd_ToggleFilterBit(CCamWnd* cam, int bit) {
|
||||
int mask = CamWnd_GetFilterMask(cam);
|
||||
mask ^= bit;
|
||||
@@ -1286,6 +1384,18 @@ static void CamWnd_HandleMenuCommand(CCamWnd* cam, int command) {
|
||||
case CAMWND_MENU_CMD_DECAL_EDITING:
|
||||
CamWnd_ToggleDecalEditing(cam);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_DECAL_SCALE_UP:
|
||||
CamWnd_ScaleSelectedDecal(cam, 1.25f);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_DECAL_SCALE_DOWN:
|
||||
CamWnd_ScaleSelectedDecal(cam, 0.8f);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_DECAL_ROTATE_CCW:
|
||||
CamWnd_RotateStencil(cam, -15.0f);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_DECAL_ROTATE_CW:
|
||||
CamWnd_RotateStencil(cam, 15.0f);
|
||||
break;
|
||||
case CAMWND_MENU_CMD_SHOW_WORLD:
|
||||
CamWnd_ToggleFilterBit(cam, CAMWND_FILTER_HIDE_WORLD);
|
||||
break;
|
||||
@@ -1356,6 +1466,14 @@ static void CamWnd_ShowDecalsMenu(HWND hWnd, CCamWnd* cam) {
|
||||
|
||||
menu = CreatePopupMenu();
|
||||
AppendMenu(menu, MF_STRING | (CamWnd_DecalEditingEnabled(cam) ? MF_CHECKED : 0), CAMWND_MENU_CMD_DECAL_EDITING, "Enable decal editing");
|
||||
AppendMenu(menu, MF_SEPARATOR, 0, NULL);
|
||||
UINT scaleFlags = MF_STRING | (Map_GetSelectedDecal() >= 0 ? 0 : MF_GRAYED);
|
||||
AppendMenu(menu, scaleFlags, CAMWND_MENU_CMD_DECAL_SCALE_UP, "Scale selected up (+)");
|
||||
AppendMenu(menu, scaleFlags, CAMWND_MENU_CMD_DECAL_SCALE_DOWN, "Scale selected down (-)");
|
||||
AppendMenu(menu, MF_SEPARATOR, 0, NULL);
|
||||
UINT rotateFlags = MF_STRING | (CamWnd_DecalEditingEnabled(cam) ? 0 : MF_GRAYED);
|
||||
AppendMenu(menu, rotateFlags, CAMWND_MENU_CMD_DECAL_ROTATE_CCW, "Rotate stencil left (Q)");
|
||||
AppendMenu(menu, rotateFlags, CAMWND_MENU_CMD_DECAL_ROTATE_CW, "Rotate stencil right (E)");
|
||||
|
||||
command = TrackPopupMenu(menu, TPM_RETURNCMD | TPM_LEFTALIGN | TPM_TOPALIGN, pt.x, pt.y, 0, hWnd, NULL);
|
||||
DestroyMenu(menu);
|
||||
@@ -1816,29 +1934,24 @@ 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) {
|
||||
static bool CamWnd_BuildDecalAtPoint(CCamWnd* cam, const CPoint& point, renderWorldDecal_t& decal, const char** hitSource) {
|
||||
if (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";
|
||||
const char* localHitSource = "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";
|
||||
localHitSource = "brush";
|
||||
hitDist = trace.dist;
|
||||
hitPoint = cam->Camera().origin + dir * trace.dist;
|
||||
hitNormal = trace.face->plane.Normal();
|
||||
@@ -1850,7 +1963,7 @@ static bool CamWnd_DecalClick(CCamWnd* cam, const CPoint& point, UINT nFlags) {
|
||||
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";
|
||||
localHitSource = "render";
|
||||
hitDist = modelDist;
|
||||
hitPoint = modelTrace.point;
|
||||
hitNormal = modelTrace.normal;
|
||||
@@ -1859,11 +1972,12 @@ static bool CamWnd_DecalClick(CCamWnd* cam, const CPoint& point, UINT nFlags) {
|
||||
}
|
||||
|
||||
if (hitDist <= 0.0f || hitDist >= HUGE_DISTANCE || hitNormal.LengthSqr() < 0.0001f) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
renderWorldDecal_t decal;
|
||||
CamWnd_DecalMaterial(decal.material);
|
||||
if (!CamWnd_DecalMaterial(decal.material)) {
|
||||
return false;
|
||||
}
|
||||
CamWnd_DecalColorFromSelectedMaterial(decal.material, decal.color);
|
||||
decal.origin = hitPoint;
|
||||
decal.normal = hitNormal;
|
||||
@@ -1875,9 +1989,147 @@ static bool CamWnd_DecalClick(CCamWnd* cam, const CPoint& point, UINT nFlags) {
|
||||
decal.axisU = decal.normal.Cross(cam->Camera().vright);
|
||||
}
|
||||
decal.axisV = decal.normal.Cross(decal.axisU);
|
||||
CamWnd_RotateDecalBasis(decal, s_camWndDecalPreviewRotation);
|
||||
decal.size = CamWnd_DecalFloat("size", "64");
|
||||
decal.depth = CamWnd_DecalFloat("depth", "8");
|
||||
decal.opacity = CamWnd_DecalFloat("opacity", "1");
|
||||
if (hitSource) {
|
||||
*hitSource = localHitSource;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CamWnd_UpdateDecalPreview(CCamWnd* cam, const CPoint& point) {
|
||||
if (!CamWnd_DecalEditingEnabled(cam) || cam == NULL || !cam->GetSafeHwnd()) {
|
||||
CamWnd_ClearDecalPreview(cam);
|
||||
return;
|
||||
}
|
||||
if (Map_GetSelectedDecal() >= 0) {
|
||||
CamWnd_ClearDecalPreview(cam);
|
||||
return;
|
||||
}
|
||||
|
||||
renderWorldDecal_t preview;
|
||||
if (!CamWnd_BuildDecalAtPoint(cam, point, preview, NULL)) {
|
||||
CamWnd_ClearDecalPreview(cam);
|
||||
return;
|
||||
}
|
||||
|
||||
s_camWndDecalPreview = preview;
|
||||
s_camWndDecalPreviewOwner = cam->GetSafeHwnd();
|
||||
s_camWndDecalPreviewValid = true;
|
||||
cam->InvalidateRect(NULL, FALSE);
|
||||
}
|
||||
|
||||
static bool CamWnd_HasDecalPreview(CCamWnd* cam) {
|
||||
return cam && cam->GetSafeHwnd() && s_camWndDecalPreviewValid && s_camWndDecalPreviewOwner == cam->GetSafeHwnd();
|
||||
}
|
||||
|
||||
static void CamWnd_SubmitWorldDecalsWithPreview(CCamWnd* cam) {
|
||||
if (!g_qeglobals.rw) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CamWnd_HasDecalPreview(cam)) {
|
||||
g_qeglobals.rw->SubmitWorldDecalsToScreenSpace();
|
||||
return;
|
||||
}
|
||||
|
||||
const int previewIndex = g_qeglobals.rw->AddWorldDecal(s_camWndDecalPreview);
|
||||
g_qeglobals.rw->SubmitWorldDecalsToScreenSpace();
|
||||
if (previewIndex >= 0) {
|
||||
g_qeglobals.rw->RemoveWorldDecal(previewIndex);
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_DecalCorners(const renderWorldDecal_t& decal, idVec3 corners[4]) {
|
||||
const idVec3 axisU = decal.axisU * (decal.size * 0.5f);
|
||||
const idVec3 axisV = decal.axisV * (decal.size * 0.5f);
|
||||
corners[0] = decal.origin - axisU - axisV;
|
||||
corners[1] = decal.origin + axisU - axisV;
|
||||
corners[2] = decal.origin + axisU + axisV;
|
||||
corners[3] = decal.origin - axisU + axisV;
|
||||
}
|
||||
|
||||
static void CamWnd_DrawDecalOutlineGL(const renderWorldDecal_t& decal, const idVec4& color, float lineWidth) {
|
||||
idVec3 corners[4];
|
||||
CamWnd_DecalCorners(decal, corners);
|
||||
|
||||
const GLboolean depthEnabled = glIsEnabled(GL_DEPTH_TEST);
|
||||
glPushAttrib(GL_CURRENT_BIT);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
globalImages->BindNull();
|
||||
glLineWidth(lineWidth);
|
||||
glColor4f(color.x, color.y, color.z, color.w);
|
||||
glBegin(GL_LINE_LOOP);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
glVertex3fv(corners[i].ToFloatPtr());
|
||||
}
|
||||
glEnd();
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(decal.origin.ToFloatPtr());
|
||||
idVec3 normalEnd = decal.origin + decal.normal * idMath::ClampFloat(4.0f, 32.0f, decal.size * 0.2f);
|
||||
glVertex3fv(normalEnd.ToFloatPtr());
|
||||
glEnd();
|
||||
glLineWidth(1.0f);
|
||||
if (depthEnabled) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
static void CamWnd_DrawDecalSelectionOverlayGL(CCamWnd* cam) {
|
||||
if (!cam || !g_qeglobals.rw || !CamWnd_DecalEditingEnabled(cam)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int selected = Map_GetSelectedDecal();
|
||||
if (selected >= 0) {
|
||||
const renderWorldDecal_t* decal = g_qeglobals.rw->GetWorldDecal(selected);
|
||||
if (decal) {
|
||||
CamWnd_DrawDecalOutlineGL(*decal, idVec4(1.0f, 0.85f, 0.05f, 1.0f), 3.0f);
|
||||
}
|
||||
}
|
||||
if (CamWnd_HasDecalPreview(cam)) {
|
||||
CamWnd_DrawDecalOutlineGL(s_camWndDecalPreview, idVec4(0.1f, 0.8f, 1.0f, 1.0f), 1.5f);
|
||||
}
|
||||
}
|
||||
|
||||
static void CamWnd_DebugDecalOutline(const renderWorldDecal_t& decal, const idVec4& color) {
|
||||
if (!g_qeglobals.rw) {
|
||||
return;
|
||||
}
|
||||
|
||||
idVec3 corners[4];
|
||||
CamWnd_DecalCorners(decal, corners);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
g_qeglobals.rw->DebugLine(color, corners[i], corners[(i + 1) & 3], 0, false);
|
||||
}
|
||||
g_qeglobals.rw->DebugLine(color, decal.origin, decal.origin + decal.normal * idMath::ClampFloat(4.0f, 32.0f, decal.size * 0.2f), 0, false);
|
||||
}
|
||||
|
||||
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) {
|
||||
const int selected = Map_SelectDecalByRay(cam->Camera().origin, dir);
|
||||
if (selected >= 0) {
|
||||
CamWnd_ClearDecalPreview(cam);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
renderWorldDecal_t decal;
|
||||
const char* hitSource = "none";
|
||||
if (!CamWnd_BuildDecalAtPoint(cam, point, decal, &hitSource)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -2913,6 +3165,7 @@ CCamWnd::~CCamWnd() {
|
||||
BEGIN_MESSAGE_MAP(CCamWnd, CWnd)
|
||||
//{{AFX_MSG_MAP(CCamWnd)
|
||||
ON_WM_KEYDOWN()
|
||||
ON_WM_CHAR()
|
||||
ON_WM_PAINT()
|
||||
ON_WM_DESTROY()
|
||||
ON_WM_CLOSE()
|
||||
@@ -3024,6 +3277,10 @@ void CCamWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
|
||||
CamWnd_FaceExtrudeEnd(this, false);
|
||||
return;
|
||||
}
|
||||
if (nChar == VK_ESCAPE && CamWnd_DecalEditingEnabled(this) && Map_GetSelectedDecal() >= 0) {
|
||||
Map_ClearSelectedDecal();
|
||||
return;
|
||||
}
|
||||
if (nChar == VK_DELETE && CamWnd_DecalEditingEnabled(this) && Map_GetSelectedDecal() >= 0) {
|
||||
Map_DeleteSelectedDecal();
|
||||
return;
|
||||
@@ -3034,6 +3291,17 @@ void CCamWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) {
|
||||
g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
|
||||
}
|
||||
|
||||
/*
|
||||
=======================================================================================================================
|
||||
=======================================================================================================================
|
||||
*/
|
||||
void CCamWnd::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) {
|
||||
if (CamWnd_HandleDecalTransformChar(this, nChar)) {
|
||||
return;
|
||||
}
|
||||
CWnd::OnChar(nChar, nRepCnt, nFlags);
|
||||
}
|
||||
|
||||
brush_t* g_pSplitList = NULL;
|
||||
|
||||
/*
|
||||
@@ -3075,6 +3343,7 @@ void CCamWnd::SetXYFriend(CXYWnd* pWnd) {
|
||||
void CCamWnd::OnDestroy() {
|
||||
CamWnd_FaceExtrudeEnd(this, false);
|
||||
CamWnd_GizmoEnd(this, false);
|
||||
CamWnd_ClearDecalPreview(this);
|
||||
CamWnd_DestroyMenuBar(this);
|
||||
CWnd::OnDestroy();
|
||||
}
|
||||
@@ -3097,6 +3366,10 @@ void CCamWnd::OnMouseMove(UINT nFlags, CPoint point) {
|
||||
CRect r;
|
||||
GetClientRect(r);
|
||||
|
||||
if (GetCapture() != this) {
|
||||
CamWnd_UpdateDecalPreview(this, point);
|
||||
}
|
||||
|
||||
if (CamWnd_FaceExtrudeMouseMove(this, point)) {
|
||||
m_ptLastCursor = point;
|
||||
return;
|
||||
@@ -4265,8 +4538,16 @@ void CCamWnd::Cam_Draw() {
|
||||
}
|
||||
|
||||
CamWnd_DrawMoveSelectedBrushSides(brushFilter);
|
||||
if (!renderMode && g_qeglobals.rw && CamWnd_DecalEditingEnabled(this)) {
|
||||
g_qeglobals.rw->SubmitWorldDecalsToScreenSpace();
|
||||
if (!renderMode && g_qeglobals.rw) {
|
||||
if (CamWnd_DecalEditingEnabled(this)) {
|
||||
CamWnd_UpdateDecalPreview(this, m_ptLastCursor);
|
||||
CamWnd_SubmitWorldDecalsWithPreview(this);
|
||||
CamWnd_DrawDecalSelectionOverlayGL(this);
|
||||
}
|
||||
else {
|
||||
CamWnd_ClearDecalPreview(this);
|
||||
g_qeglobals.rw->SubmitWorldDecalsToScreenSpace();
|
||||
}
|
||||
}
|
||||
CamWnd_FaceExtrudeDrawPreview(this);
|
||||
CamWnd_GizmoDraw(this);
|
||||
@@ -5866,14 +6147,28 @@ void CCamWnd::Cam_Render() {
|
||||
}
|
||||
Cam_SetGlobalFogFromWorldspawn(refdef);
|
||||
|
||||
if (CamWnd_DecalEditingEnabled(this)) {
|
||||
CamWnd_UpdateDecalPreview(this, m_ptLastCursor);
|
||||
}
|
||||
|
||||
int previewDecalIndex = -1;
|
||||
if (g_qeglobals.rw && CamWnd_HasDecalPreview(this)) {
|
||||
previewDecalIndex = g_qeglobals.rw->AddWorldDecal(s_camWndDecalPreview);
|
||||
}
|
||||
|
||||
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);
|
||||
const bool selected = (i == Map_GetSelectedDecal());
|
||||
const bool preview = (i == previewDecalIndex);
|
||||
idVec4 color = selected ? 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);
|
||||
if (selected || preview) {
|
||||
CamWnd_DebugDecalOutline(*decal, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5884,6 +6179,10 @@ void CCamWnd::Cam_Render() {
|
||||
renderSystem->EndFrame(&frontEnd, &backEnd, false);
|
||||
//common->Printf( "front:%i back:%i\n", frontEnd, backEnd );
|
||||
|
||||
if (g_qeglobals.rw && previewDecalIndex >= 0) {
|
||||
g_qeglobals.rw->RemoveWorldDecal(previewDecalIndex);
|
||||
}
|
||||
|
||||
//glPopAttrib();
|
||||
//DrawEntityData();
|
||||
|
||||
|
||||
@@ -180,6 +180,7 @@ protected:
|
||||
void OriginalMouseUp(UINT nFlags, CPoint point);
|
||||
//{{AFX_MSG(CCamWnd)
|
||||
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
|
||||
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
|
||||
afx_msg void OnPaint();
|
||||
afx_msg void OnDestroy();
|
||||
afx_msg void OnClose();
|
||||
|
||||
@@ -132,6 +132,15 @@ int Map_GetSelectedDecal(void) {
|
||||
return s_selectedWorldDecal;
|
||||
}
|
||||
|
||||
void Map_ClearSelectedDecal(void) {
|
||||
if (s_selectedWorldDecal < 0) {
|
||||
return;
|
||||
}
|
||||
s_selectedWorldDecal = -1;
|
||||
Sys_UpdateWindows(W_CAMERA);
|
||||
Sys_Status("Deselected decal\n", 0);
|
||||
}
|
||||
|
||||
void Map_DeleteSelectedDecal(void) {
|
||||
if (!g_qeglobals.rw || s_selectedWorldDecal < 0) {
|
||||
return;
|
||||
@@ -142,6 +151,64 @@ void Map_DeleteSelectedDecal(void) {
|
||||
Sys_UpdateWindows(W_ALL);
|
||||
}
|
||||
|
||||
bool Map_ScaleSelectedDecal(float scale) {
|
||||
if (!g_qeglobals.rw || s_selectedWorldDecal < 0 || scale <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const renderWorldDecal_t* existing = g_qeglobals.rw->GetWorldDecal(s_selectedWorldDecal);
|
||||
if (!existing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
renderWorldDecal_t decal = *existing;
|
||||
decal.size *= scale;
|
||||
if (decal.size < 1.0f) {
|
||||
decal.size = 1.0f;
|
||||
}
|
||||
else if (decal.size > 4096.0f) {
|
||||
decal.size = 4096.0f;
|
||||
}
|
||||
|
||||
if (!g_qeglobals.rw->UpdateWorldDecal(s_selectedWorldDecal, decal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mapModified = 1;
|
||||
Sys_UpdateWindows(W_CAMERA);
|
||||
Sys_Status(va("Scaled decal to %.2f\n", decal.size), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Map_RotateSelectedDecal(float degrees) {
|
||||
if (!g_qeglobals.rw || s_selectedWorldDecal < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const renderWorldDecal_t* existing = g_qeglobals.rw->GetWorldDecal(s_selectedWorldDecal);
|
||||
if (!existing) {
|
||||
return false;
|
||||
}
|
||||
|
||||
renderWorldDecal_t decal = *existing;
|
||||
const float radians = degrees * idMath::M_DEG2RAD;
|
||||
const float s = sin(radians);
|
||||
const float c = cos(radians);
|
||||
const idVec3 oldU = decal.axisU;
|
||||
const idVec3 oldV = decal.axisV;
|
||||
decal.axisU = oldU * c + oldV * s;
|
||||
decal.axisV = oldV * c - oldU * s;
|
||||
|
||||
if (!g_qeglobals.rw->UpdateWorldDecal(s_selectedWorldDecal, decal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mapModified = 1;
|
||||
Sys_UpdateWindows(W_CAMERA);
|
||||
Sys_Status(va("Rotated decal %.1f degrees\n", degrees), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int Map_SelectDecalByRay(const idVec3& origin, const idVec3& dir) {
|
||||
if (!g_qeglobals.rw) {
|
||||
return -1;
|
||||
@@ -154,25 +221,43 @@ int Map_SelectDecalByRay(const idVec3& origin, const idVec3& dir) {
|
||||
if (!decal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const float halfSize = decal->size * 0.5f;
|
||||
const float tolerance = idMath::ClampFloat(4.0f, 24.0f, decal->size * 0.125f);
|
||||
const float depthTolerance = (decal->depth > 1.0f ? decal->depth : 1.0f) + tolerance;
|
||||
float denom = dir * decal->normal;
|
||||
if (fabs(denom) < 0.0001f) {
|
||||
continue;
|
||||
if (fabs(denom) >= 0.0001f) {
|
||||
float t = ((decal->origin - origin) * decal->normal) / denom;
|
||||
if (t > 0.0f && t < bestT) {
|
||||
idVec3 hit = origin + dir * t;
|
||||
idVec3 rel = hit - decal->origin;
|
||||
float u = rel * decal->axisU;
|
||||
float v = rel * decal->axisV;
|
||||
if (fabs(u) <= halfSize + tolerance && fabs(v) <= halfSize + tolerance) {
|
||||
bestT = t;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
float centerT = (decal->origin - origin) * dir;
|
||||
if (centerT > 0.0f && centerT < bestT) {
|
||||
idVec3 closest = origin + dir * centerT;
|
||||
idVec3 rel = closest - decal->origin;
|
||||
float planeDist = fabs(rel * decal->normal);
|
||||
float u = rel * decal->axisU;
|
||||
float v = rel * decal->axisV;
|
||||
if (planeDist <= depthTolerance && fabs(u) <= halfSize + tolerance && fabs(v) <= halfSize + tolerance) {
|
||||
bestT = centerT;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
s_selectedWorldDecal = bestIndex;
|
||||
Sys_UpdateWindows(W_CAMERA);
|
||||
if (bestIndex >= 0) {
|
||||
Sys_Status(va("Selected decal %i\n", bestIndex), 0);
|
||||
}
|
||||
return bestIndex;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,9 @@ void Map_LoadDecals(const char *filename);
|
||||
void Map_SaveDecals(const char *filename);
|
||||
int Map_AddDecal(const renderWorldDecal_t& decal);
|
||||
void Map_DeleteSelectedDecal(void);
|
||||
bool Map_ScaleSelectedDecal(float scale);
|
||||
bool Map_RotateSelectedDecal(float degrees);
|
||||
void Map_ClearSelectedDecal(void);
|
||||
int Map_SelectDecalByRay(const idVec3& origin, const idVec3& dir);
|
||||
int Map_GetSelectedDecal(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user