mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-12 08:11:10 +02:00
Added axis movement.
This commit is contained in:
@@ -52,6 +52,12 @@ extern brush_t* Brush_CreateFaceExtrusion(brush_t* sourceBrush, face_t* sourceFa
|
||||
extern void Select_ShiftTexture(float x, float y);
|
||||
extern void Select_ScaleTexture(float x, float y);
|
||||
extern void Select_RotateTexture(float amt, bool absolute);
|
||||
extern void Select_Move(idVec3 delta, bool bSnap);
|
||||
extern void Select_Ray(idVec3 origin, idVec3 dir, int flags);
|
||||
extern void Select_Deselect(bool bDeselectFaces);
|
||||
extern void Select_RotateAxis(int axis, float deg, bool bPaint, bool bMouse);
|
||||
extern void Select_InitializeRotation();
|
||||
extern void Select_FinalizeRotation();
|
||||
|
||||
/*
|
||||
========================
|
||||
@@ -1931,6 +1937,582 @@ static void CamWnd_FaceExtrudeDrawPreview(CCamWnd* cam) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
========================
|
||||
Camera selection axis gizmo
|
||||
|
||||
A selected object now gets a small world-axis handle in the camera view.
|
||||
Hover an axis and left-drag to translate along that axis. Holding Shift while
|
||||
starting the drag converts the same handle into yaw-only rotation around the Z
|
||||
axis; no pitch/roll rotation handles are exposed here.
|
||||
========================
|
||||
*/
|
||||
#define CAMWND_GIZMO_AXIS_NONE -1
|
||||
#define CAMWND_GIZMO_AXIS_X 0
|
||||
#define CAMWND_GIZMO_AXIS_Y 1
|
||||
#define CAMWND_GIZMO_AXIS_Z 2
|
||||
#define CAMWND_GIZMO_HIT_PIXELS 9.0f
|
||||
#define CAMWND_GIZMO_DRAW_PIXELS 96.0f
|
||||
#define CAMWND_GIZMO_ROTATE_AXIS 2
|
||||
|
||||
struct camWndGizmoState_t {
|
||||
bool active;
|
||||
bool rotating;
|
||||
int hoverAxis;
|
||||
int activeAxis;
|
||||
CCamWnd* cam;
|
||||
CPoint startPoint;
|
||||
CPoint lastPoint;
|
||||
idVec3 startCenter;
|
||||
idVec3 axisDir;
|
||||
float axisLength;
|
||||
float startScalar;
|
||||
float lastScalar;
|
||||
float rotationAmount;
|
||||
};
|
||||
|
||||
static camWndGizmoState_t s_camWndGizmoState;
|
||||
|
||||
static bool CamWnd_GizmoSelectionBounds(idVec3& mins, idVec3& maxs) {
|
||||
if (selected_brushes.next == NULL || selected_brushes.next == &selected_brushes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mins[0] = mins[1] = mins[2] = 999999.0f;
|
||||
maxs[0] = maxs[1] = maxs[2] = -999999.0f;
|
||||
bool haveBounds = false;
|
||||
|
||||
for (brush_t* brush = selected_brushes.next; brush != &selected_brushes; brush = brush->next) {
|
||||
if (brush == NULL) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (brush->mins[i] < mins[i]) {
|
||||
mins[i] = brush->mins[i];
|
||||
}
|
||||
if (brush->maxs[i] > maxs[i]) {
|
||||
maxs[i] = brush->maxs[i];
|
||||
}
|
||||
}
|
||||
haveBounds = true;
|
||||
}
|
||||
|
||||
return haveBounds;
|
||||
}
|
||||
|
||||
static bool CamWnd_GizmoSelectionCenter(idVec3& center, idVec3* outMins = NULL, idVec3* outMaxs = NULL) {
|
||||
idVec3 mins;
|
||||
idVec3 maxs;
|
||||
if (!CamWnd_GizmoSelectionBounds(mins, maxs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
center[0] = (mins[0] + maxs[0]) * 0.5f;
|
||||
center[1] = (mins[1] + maxs[1]) * 0.5f;
|
||||
center[2] = (mins[2] + maxs[2]) * 0.5f;
|
||||
|
||||
center += g_qeglobals.d_select_translate;
|
||||
if (outMins) {
|
||||
*outMins = mins;
|
||||
}
|
||||
if (outMaxs) {
|
||||
*outMaxs = maxs;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static idVec3 CamWnd_GizmoAxisVector(int axis) {
|
||||
idVec3 v;
|
||||
v[0] = v[1] = v[2] = 0.0f;
|
||||
if (axis >= 0 && axis < 3) {
|
||||
v[axis] = 1.0f;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static float CamWnd_GizmoGridSize() {
|
||||
float gridSize = (float)g_qeglobals.d_gridsize;
|
||||
if (gridSize <= 0.0f) {
|
||||
gridSize = 1.0f;
|
||||
}
|
||||
return gridSize;
|
||||
}
|
||||
|
||||
static float CamWnd_GizmoSnapScalar(float scalar) {
|
||||
if (g_PrefsDlg.m_bNoClamp) {
|
||||
return scalar;
|
||||
}
|
||||
const float gridSize = CamWnd_GizmoGridSize();
|
||||
return floor(scalar / gridSize + 0.5f) * gridSize;
|
||||
}
|
||||
|
||||
static float CamWnd_GizmoWorldPerPixel(CCamWnd* cam, const idVec3& center) {
|
||||
if (cam == NULL) {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
camera_t& camera = cam->Camera();
|
||||
idVec3 toCenter = center - camera.origin;
|
||||
float depth = DotProduct(toCenter, camera.vpn);
|
||||
if (depth < 8.0f) {
|
||||
depth = toCenter.Length();
|
||||
if (depth < 8.0f) {
|
||||
depth = 8.0f;
|
||||
}
|
||||
}
|
||||
|
||||
float halfWidth = (float)camera.width * 0.5f;
|
||||
if (halfWidth < 1.0f) {
|
||||
halfWidth = 1.0f;
|
||||
}
|
||||
return depth / halfWidth;
|
||||
}
|
||||
|
||||
static float CamWnd_GizmoAxisLength(CCamWnd* cam, const idVec3& center, const idVec3& mins, const idVec3& maxs) {
|
||||
idVec3 size = maxs - mins;
|
||||
float selectionSize = size.Length() * 0.55f;
|
||||
float cameraSize = CamWnd_GizmoWorldPerPixel(cam, center) * CAMWND_GIZMO_DRAW_PIXELS;
|
||||
float length = cameraSize;
|
||||
|
||||
if (length < selectionSize) {
|
||||
length = selectionSize;
|
||||
}
|
||||
if (length < 32.0f) {
|
||||
length = 32.0f;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
static bool CamWnd_GizmoProjectPoint(CCamWnd* cam, const idVec3& point, CPoint& out) {
|
||||
if (cam == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
camera_t& camera = cam->Camera();
|
||||
idVec3 local = point - camera.origin;
|
||||
float depth = DotProduct(local, camera.vpn);
|
||||
if (depth <= 1.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float halfWidth = (float)camera.width * 0.5f;
|
||||
if (halfWidth <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float r = DotProduct(local, camera.vright) / depth;
|
||||
float u = DotProduct(local, camera.vup) / depth;
|
||||
float sx = (float)camera.width * 0.5f + r * halfWidth;
|
||||
float syBottom = (float)camera.height * 0.5f + u * halfWidth;
|
||||
|
||||
CRect rect;
|
||||
cam->GetClientRect(rect);
|
||||
out.x = (int)(sx + 0.5f);
|
||||
out.y = rect.bottom - 1 - (int)(syBottom + 0.5f);
|
||||
return true;
|
||||
}
|
||||
|
||||
static float CamWnd_GizmoDistanceToSegment(const CPoint& point, const CPoint& a, const CPoint& b, float& tOut) {
|
||||
float px = (float)point.x;
|
||||
float py = (float)point.y;
|
||||
float ax = (float)a.x;
|
||||
float ay = (float)a.y;
|
||||
float bx = (float)b.x;
|
||||
float by = (float)b.y;
|
||||
float dx = bx - ax;
|
||||
float dy = by - ay;
|
||||
float lenSqr = dx * dx + dy * dy;
|
||||
|
||||
if (lenSqr <= 0.0001f) {
|
||||
tOut = 0.0f;
|
||||
float ex = px - ax;
|
||||
float ey = py - ay;
|
||||
return sqrt(ex * ex + ey * ey);
|
||||
}
|
||||
|
||||
float t = ((px - ax) * dx + (py - ay) * dy) / lenSqr;
|
||||
if (t < 0.0f) {
|
||||
t = 0.0f;
|
||||
}
|
||||
else if (t > 1.0f) {
|
||||
t = 1.0f;
|
||||
}
|
||||
tOut = t;
|
||||
|
||||
float cx = ax + dx * t;
|
||||
float cy = ay + dy * t;
|
||||
float ex = px - cx;
|
||||
float ey = py - cy;
|
||||
return sqrt(ex * ex + ey * ey);
|
||||
}
|
||||
|
||||
static int CamWnd_GizmoHitTest(CCamWnd* cam, const CPoint& point, float* bestDistance = NULL) {
|
||||
idVec3 center;
|
||||
idVec3 mins;
|
||||
idVec3 maxs;
|
||||
if (!CamWnd_GizmoSelectionCenter(center, &mins, &maxs)) {
|
||||
if (bestDistance) {
|
||||
*bestDistance = -1.0f;
|
||||
}
|
||||
return CAMWND_GIZMO_AXIS_NONE;
|
||||
}
|
||||
|
||||
const float axisLength = CamWnd_GizmoAxisLength(cam, center, mins, maxs);
|
||||
float best = CAMWND_GIZMO_HIT_PIXELS;
|
||||
int bestAxis = CAMWND_GIZMO_AXIS_NONE;
|
||||
|
||||
CPoint start;
|
||||
if (!CamWnd_GizmoProjectPoint(cam, center, start)) {
|
||||
if (bestDistance) {
|
||||
*bestDistance = -1.0f;
|
||||
}
|
||||
return CAMWND_GIZMO_AXIS_NONE;
|
||||
}
|
||||
|
||||
for (int axis = 0; axis < 3; axis++) {
|
||||
idVec3 axisDir = CamWnd_GizmoAxisVector(axis);
|
||||
CPoint end;
|
||||
if (!CamWnd_GizmoProjectPoint(cam, center + axisDir * axisLength, end)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float segmentT = 0.0f;
|
||||
float dist = CamWnd_GizmoDistanceToSegment(point, start, end, segmentT);
|
||||
if (dist <= best && segmentT >= 0.08f) {
|
||||
best = dist;
|
||||
bestAxis = axis;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestDistance) {
|
||||
*bestDistance = (bestAxis == CAMWND_GIZMO_AXIS_NONE) ? -1.0f : best;
|
||||
}
|
||||
return bestAxis;
|
||||
}
|
||||
|
||||
static bool CamWnd_GizmoAxisScalarFromRay(CCamWnd* cam, const CPoint& point, const idVec3& lineOrigin, const idVec3& lineDir, float& scalar) {
|
||||
idVec3 rayDir;
|
||||
CamWnd_FaceExtrudeBuildRay(cam, point, rayDir);
|
||||
|
||||
const idVec3 rayOrigin = cam->Camera().origin;
|
||||
const float b = DotProduct(rayDir, lineDir);
|
||||
const float denom = 1.0f - b * b;
|
||||
if (denom < 0.0001f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idVec3 w = rayOrigin - lineOrigin;
|
||||
const float d = DotProduct(rayDir, w);
|
||||
const float e = DotProduct(lineDir, w);
|
||||
const float t = (e - b * d) / denom;
|
||||
const float rayT = b * t - d;
|
||||
if (rayT < 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scalar = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CamWnd_GizmoScreenDeltaScalar(CCamWnd* cam, const CPoint& point, float& scalar) {
|
||||
CPoint start;
|
||||
CPoint end;
|
||||
if (!CamWnd_GizmoProjectPoint(cam, s_camWndGizmoState.startCenter, start) ||
|
||||
!CamWnd_GizmoProjectPoint(cam, s_camWndGizmoState.startCenter + s_camWndGizmoState.axisDir * s_camWndGizmoState.axisLength, end)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float dx = (float)(end.x - start.x);
|
||||
float dy = (float)(end.y - start.y);
|
||||
float len = sqrt(dx * dx + dy * dy);
|
||||
if (len < 0.001f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dx /= len;
|
||||
dy /= len;
|
||||
float mouseDx = (float)(point.x - s_camWndGizmoState.startPoint.x);
|
||||
float mouseDy = (float)(point.y - s_camWndGizmoState.startPoint.y);
|
||||
scalar = (mouseDx * dx + mouseDy * dy) * (s_camWndGizmoState.axisLength / len);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CamWnd_GizmoBegin(CCamWnd* cam, const CPoint& point, UINT nFlags) {
|
||||
if (cam == NULL || !cam->GetSafeHwnd() || (nFlags & MK_CONTROL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int axis = CamWnd_GizmoHitTest(cam, point);
|
||||
if (axis == CAMWND_GIZMO_AXIS_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idVec3 center;
|
||||
idVec3 mins;
|
||||
idVec3 maxs;
|
||||
if (!CamWnd_GizmoSelectionCenter(center, &mins, &maxs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(&s_camWndGizmoState, 0, sizeof(s_camWndGizmoState));
|
||||
s_camWndGizmoState.active = true;
|
||||
s_camWndGizmoState.rotating = ((nFlags & MK_SHIFT) != 0) || ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0);
|
||||
s_camWndGizmoState.hoverAxis = axis;
|
||||
s_camWndGizmoState.activeAxis = s_camWndGizmoState.rotating ? CAMWND_GIZMO_AXIS_Z : axis;
|
||||
s_camWndGizmoState.cam = cam;
|
||||
s_camWndGizmoState.startPoint = point;
|
||||
s_camWndGizmoState.lastPoint = point;
|
||||
s_camWndGizmoState.startCenter = center;
|
||||
s_camWndGizmoState.axisDir = CamWnd_GizmoAxisVector(s_camWndGizmoState.rotating ? CAMWND_GIZMO_AXIS_Z : axis);
|
||||
s_camWndGizmoState.axisLength = CamWnd_GizmoAxisLength(cam, center, mins, maxs);
|
||||
s_camWndGizmoState.startScalar = 0.0f;
|
||||
s_camWndGizmoState.lastScalar = 0.0f;
|
||||
s_camWndGizmoState.rotationAmount = 0.0f;
|
||||
|
||||
CamWnd_GizmoAxisScalarFromRay(cam, point, center, s_camWndGizmoState.axisDir, s_camWndGizmoState.startScalar);
|
||||
|
||||
if (s_camWndGizmoState.rotating) {
|
||||
Select_InitializeRotation();
|
||||
}
|
||||
|
||||
cam->SetFocus();
|
||||
cam->SetCapture();
|
||||
SetCursor(LoadCursor(NULL, s_camWndGizmoState.rotating ? IDC_CROSS : IDC_SIZEALL));
|
||||
Sys_Status(s_camWndGizmoState.rotating ? "Shift-drag gizmo: yaw rotate selected object.\n" : "Drag gizmo axis to move selected object.\n");
|
||||
Sys_UpdateWindows(W_CAMERA | W_XY | W_Z);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CamWnd_GizmoIsActive(CCamWnd* cam) {
|
||||
return s_camWndGizmoState.active && s_camWndGizmoState.cam == cam;
|
||||
}
|
||||
|
||||
static void CamWnd_GizmoEnd(CCamWnd* cam, bool commit) {
|
||||
if (!CamWnd_GizmoIsActive(cam)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (::GetCapture() == cam->GetSafeHwnd()) {
|
||||
::ReleaseCapture();
|
||||
}
|
||||
|
||||
if (s_camWndGizmoState.rotating) {
|
||||
Select_FinalizeRotation();
|
||||
}
|
||||
|
||||
|
||||
if (!commit) {
|
||||
Sys_Status("camera gizmo drag ended.\n");
|
||||
}
|
||||
g_pParentWnd->SetStatusText(3, "");
|
||||
const int lastHoverAxis = s_camWndGizmoState.hoverAxis;
|
||||
memset(&s_camWndGizmoState, 0, sizeof(s_camWndGizmoState));
|
||||
s_camWndGizmoState.hoverAxis = lastHoverAxis;
|
||||
Sys_UpdateWindows(W_ALL);
|
||||
}
|
||||
|
||||
static bool CamWnd_GizmoMouseMove(CCamWnd* cam, const CPoint& point, UINT nFlags) {
|
||||
if (CamWnd_GizmoIsActive(cam)) {
|
||||
if (s_camWndGizmoState.rotating) {
|
||||
const int dx = point.x - s_camWndGizmoState.lastPoint.x;
|
||||
const int dy = point.y - s_camWndGizmoState.lastPoint.y;
|
||||
float deltaAngle = (float)dx * 0.5f;
|
||||
if (idMath::Fabs(deltaAngle) < idMath::Fabs((float)dy) * 0.15f) {
|
||||
deltaAngle = (float)-dy * 0.5f;
|
||||
}
|
||||
if (deltaAngle != 0.0f) {
|
||||
Select_RotateAxis(CAMWND_GIZMO_ROTATE_AXIS, deltaAngle, false, false);
|
||||
cam->MarkWorldDirty();
|
||||
s_camWndGizmoState.rotationAmount += deltaAngle;
|
||||
CString strStatus;
|
||||
strStatus.Format("Yaw rotation: %.1f", s_camWndGizmoState.rotationAmount);
|
||||
g_pParentWnd->SetStatusText(3, strStatus);
|
||||
Sys_UpdateWindows(W_CAMERA | W_XY | W_Z);
|
||||
}
|
||||
}
|
||||
else {
|
||||
float currentScalar = 0.0f;
|
||||
float moveScalar = 0.0f;
|
||||
if (CamWnd_GizmoAxisScalarFromRay(cam, point, s_camWndGizmoState.startCenter, s_camWndGizmoState.axisDir, currentScalar)) {
|
||||
moveScalar = currentScalar - s_camWndGizmoState.startScalar;
|
||||
}
|
||||
else if (!CamWnd_GizmoScreenDeltaScalar(cam, point, moveScalar)) {
|
||||
moveScalar = 0.0f;
|
||||
}
|
||||
|
||||
moveScalar = CamWnd_GizmoSnapScalar(moveScalar);
|
||||
float deltaScalar = moveScalar - s_camWndGizmoState.lastScalar;
|
||||
if (deltaScalar != 0.0f) {
|
||||
idVec3 delta = s_camWndGizmoState.axisDir * deltaScalar;
|
||||
Select_Move(delta, true);
|
||||
cam->MarkWorldDirty();
|
||||
s_camWndGizmoState.lastScalar = moveScalar;
|
||||
CString strStatus;
|
||||
strStatus.Format("Axis move: %.1f", moveScalar);
|
||||
g_pParentWnd->SetStatusText(3, strStatus);
|
||||
Sys_UpdateWindows(W_CAMERA | W_XY | W_Z);
|
||||
}
|
||||
}
|
||||
|
||||
s_camWndGizmoState.lastPoint = point;
|
||||
SetCursor(LoadCursor(NULL, s_camWndGizmoState.rotating ? IDC_CROSS : IDC_SIZEALL));
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((nFlags & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON)) == 0) {
|
||||
int oldHover = s_camWndGizmoState.hoverAxis;
|
||||
s_camWndGizmoState.hoverAxis = CamWnd_GizmoHitTest(cam, point);
|
||||
if (s_camWndGizmoState.hoverAxis != CAMWND_GIZMO_AXIS_NONE) {
|
||||
SetCursor(LoadCursor(NULL, (GetAsyncKeyState(VK_SHIFT) & 0x8000) ? IDC_CROSS : IDC_SIZEALL));
|
||||
}
|
||||
if (oldHover != s_camWndGizmoState.hoverAxis) {
|
||||
Sys_UpdateWindows(W_CAMERA);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CamWnd_GizmoSelectObjectClick(CCamWnd* cam, const CPoint& point, UINT nFlags) {
|
||||
if (cam == NULL || !cam->GetSafeHwnd()) {
|
||||
return false;
|
||||
}
|
||||
if (nFlags & (MK_CONTROL | MK_SHIFT)) {
|
||||
return false;
|
||||
}
|
||||
if (GetAsyncKeyState(VK_MENU) & 0x8000) {
|
||||
return false;
|
||||
}
|
||||
|
||||
idVec3 dir;
|
||||
CamWnd_FaceExtrudeBuildRay(cam, point, dir);
|
||||
qertrace_t trace = Test_Ray(cam->Camera().origin, dir, 0);
|
||||
if (trace.brush == NULL || trace.dist <= 0.0f || trace.dist >= HUGE_DISTANCE) {
|
||||
return false;
|
||||
}
|
||||
if (CamWnd_MenuFilterBrush(cam, trace.brush) || Map_IsBrushFiltered(trace.brush)) {
|
||||
return false;
|
||||
}
|
||||
if (trace.brush->owner != NULL && !Outliner_IsEntityVisible(trace.brush->owner)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the click hit something outside the current selection, make it the new
|
||||
// selection and let the axis draw immediately. Clicks on an already-selected
|
||||
// object still fall through to the original drag code for compatibility.
|
||||
if (!trace.selected || selected_brushes.next == &selected_brushes) {
|
||||
Select_Deselect(true);
|
||||
Select_Ray(cam->Camera().origin, dir, 0);
|
||||
s_camWndGizmoState.hoverAxis = CAMWND_GIZMO_AXIS_NONE;
|
||||
Sys_UpdateWindows(W_ALL);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void CamWnd_GizmoColorForAxis(int axis, bool active) {
|
||||
if (active) {
|
||||
glColor3f(1.0f, 1.0f, 0.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (axis) {
|
||||
case CAMWND_GIZMO_AXIS_X:
|
||||
glColor3f(1.0f, 0.1f, 0.1f);
|
||||
break;
|
||||
case CAMWND_GIZMO_AXIS_Y:
|
||||
glColor3f(0.1f, 1.0f, 0.1f);
|
||||
break;
|
||||
case CAMWND_GIZMO_AXIS_Z:
|
||||
glColor3f(0.25f, 0.45f, 1.0f);
|
||||
break;
|
||||
default:
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static idVec3 CamWnd_GizmoCross(const idVec3& a, const idVec3& b) {
|
||||
idVec3 out;
|
||||
out[0] = a[1] * b[2] - a[2] * b[1];
|
||||
out[1] = a[2] * b[0] - a[0] * b[2];
|
||||
out[2] = a[0] * b[1] - a[1] * b[0];
|
||||
return out;
|
||||
}
|
||||
|
||||
static void CamWnd_GizmoDrawAxisTip(const idVec3& axisEnd, const idVec3& axisDir, float tipSize) {
|
||||
idVec3 side1 = CamWnd_GizmoCross(axisDir, idVec3(0.0f, 0.0f, 1.0f));
|
||||
if (side1.LengthSqr() < 0.001f) {
|
||||
side1 = CamWnd_GizmoCross(axisDir, idVec3(0.0f, 1.0f, 0.0f));
|
||||
}
|
||||
side1.Normalize();
|
||||
idVec3 side2 = CamWnd_GizmoCross(axisDir, side1);
|
||||
side2.Normalize();
|
||||
|
||||
const idVec3 base = axisEnd - axisDir * tipSize;
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(axisEnd.ToFloatPtr());
|
||||
glVertex3fv((base + side1 * (tipSize * 0.45f)).ToFloatPtr());
|
||||
glVertex3fv(axisEnd.ToFloatPtr());
|
||||
glVertex3fv((base - side1 * (tipSize * 0.45f)).ToFloatPtr());
|
||||
glVertex3fv(axisEnd.ToFloatPtr());
|
||||
glVertex3fv((base + side2 * (tipSize * 0.45f)).ToFloatPtr());
|
||||
glVertex3fv(axisEnd.ToFloatPtr());
|
||||
glVertex3fv((base - side2 * (tipSize * 0.45f)).ToFloatPtr());
|
||||
glEnd();
|
||||
}
|
||||
|
||||
static void CamWnd_GizmoDraw(CCamWnd* cam) {
|
||||
idVec3 center;
|
||||
idVec3 mins;
|
||||
idVec3 maxs;
|
||||
if (!CamWnd_GizmoSelectionCenter(center, &mins, &maxs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
float axisLength = CamWnd_GizmoAxisLength(cam, center, mins, maxs);
|
||||
float tipSize = axisLength * 0.12f;
|
||||
if (tipSize < 8.0f) {
|
||||
tipSize = 8.0f;
|
||||
}
|
||||
else if (tipSize > 32.0f) {
|
||||
tipSize = 32.0f;
|
||||
}
|
||||
|
||||
glPushAttrib(GL_CURRENT_BIT);
|
||||
globalImages->BindNull();
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glLineWidth(3.0f);
|
||||
|
||||
for (int axis = 0; axis < 3; axis++) {
|
||||
idVec3 axisDir = CamWnd_GizmoAxisVector(axis);
|
||||
idVec3 axisEnd = center + axisDir * axisLength;
|
||||
bool active = (CamWnd_GizmoIsActive(cam) && s_camWndGizmoState.activeAxis == axis) ||
|
||||
(!s_camWndGizmoState.active && s_camWndGizmoState.hoverAxis == axis);
|
||||
|
||||
CamWnd_GizmoColorForAxis(axis, active);
|
||||
glBegin(GL_LINES);
|
||||
glVertex3fv(center.ToFloatPtr());
|
||||
glVertex3fv(axisEnd.ToFloatPtr());
|
||||
glEnd();
|
||||
CamWnd_GizmoDrawAxisTip(axisEnd, axisDir, tipSize);
|
||||
}
|
||||
|
||||
glPointSize(6.0f);
|
||||
glColor3f(1.0f, 1.0f, 1.0f);
|
||||
glBegin(GL_POINTS);
|
||||
glVertex3fv(center.ToFloatPtr());
|
||||
glEnd();
|
||||
|
||||
glPopAttrib();
|
||||
}
|
||||
|
||||
static COLORREF CamWnd_LerpColor(COLORREF a, COLORREF b, float t) {
|
||||
const int ar = GetRValue(a);
|
||||
const int ag = GetGValue(a);
|
||||
@@ -2154,6 +2736,7 @@ INT_PTR WINAPI CamWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
CCamWnd* cam = DYNAMIC_DOWNCAST(CCamWnd, wnd);
|
||||
if (cam) {
|
||||
CamWnd_FaceExtrudeEnd(cam, false);
|
||||
CamWnd_GizmoEnd(cam, false);
|
||||
CameraNav_Stop(cam);
|
||||
}
|
||||
SendMessage(hWnd, WM_NCACTIVATE, FALSE, 0);
|
||||
@@ -2274,6 +2857,7 @@ void CCamWnd::SetXYFriend(CXYWnd* pWnd) {
|
||||
*/
|
||||
void CCamWnd::OnDestroy() {
|
||||
CamWnd_FaceExtrudeEnd(this, false);
|
||||
CamWnd_GizmoEnd(this, false);
|
||||
CamWnd_DestroyMenuBar(this);
|
||||
CWnd::OnDestroy();
|
||||
}
|
||||
@@ -2306,6 +2890,11 @@ void CCamWnd::OnMouseMove(UINT nFlags, CPoint point) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CamWnd_GizmoMouseMove(this, point, nFlags)) {
|
||||
m_ptLastCursor = point;
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetCapture() == this && (GetAsyncKeyState(VK_MENU) & 0x8000)) {
|
||||
// Alt-drag texture manipulation. The old condition excluded shift/control
|
||||
// before checking them, so alt+shift and alt+control never reached the
|
||||
@@ -2348,6 +2937,12 @@ void CCamWnd::OnLButtonDown(UINT nFlags, CPoint point) {
|
||||
if ((nFlags & MK_CONTROL) && (nFlags & MK_SHIFT) && CamWnd_FaceExtrudeBegin(this, point)) {
|
||||
return;
|
||||
}
|
||||
if (CamWnd_GizmoBegin(this, point, nFlags)) {
|
||||
return;
|
||||
}
|
||||
if (CamWnd_GizmoSelectObjectClick(this, point, nFlags)) {
|
||||
return;
|
||||
}
|
||||
OriginalMouseDown(nFlags, point);
|
||||
}
|
||||
|
||||
@@ -2356,6 +2951,11 @@ void CCamWnd::OnLButtonDown(UINT nFlags, CPoint point) {
|
||||
=======================================================================================================================
|
||||
*/
|
||||
void CCamWnd::OnLButtonUp(UINT nFlags, CPoint point) {
|
||||
if (CamWnd_GizmoIsActive(this)) {
|
||||
CamWnd_GizmoMouseMove(this, point, nFlags);
|
||||
CamWnd_GizmoEnd(this, true);
|
||||
return;
|
||||
}
|
||||
if (CamWnd_FaceExtrudeIsActive(this)) {
|
||||
CamWnd_FaceExtrudeMouseMove(this, point);
|
||||
CamWnd_FaceExtrudeEnd(this, true);
|
||||
@@ -3256,6 +3856,7 @@ void CCamWnd::Cam_Draw() {
|
||||
|
||||
CamWnd_DrawMoveSelectedBrushSides(this);
|
||||
CamWnd_FaceExtrudeDrawPreview(this);
|
||||
CamWnd_GizmoDraw(this);
|
||||
|
||||
// edge / vertex flags
|
||||
if (g_qeglobals.d_select_mode == sel_vertex) {
|
||||
|
||||
Reference in New Issue
Block a user