mirror of
https://github.com/dhewm/dhewm3.git
synced 2024-12-15 15:20:56 +00:00
763 lines
18 KiB
C++
763 lines
18 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 GPL Source Code
|
|
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
|
|
|
|
Doom 3 Source Code is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 Source Code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "../../idlib/precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#include "qe3.h"
|
|
#include "splines.h"
|
|
|
|
/* drag either multiple brushes, or select plane points from a single brush. */
|
|
bool g_moveOnly = false;
|
|
bool drag_ok;
|
|
idVec3 drag_xvec;
|
|
idVec3 drag_yvec;
|
|
|
|
static int buttonstate;
|
|
int pressx, pressy;
|
|
static idVec3 pressdelta;
|
|
static idVec3 vPressStart;
|
|
static int buttonx, buttony;
|
|
|
|
// int num_move_points; float *move_points[1024];
|
|
int lastx, lasty;
|
|
|
|
bool drag_first;
|
|
|
|
/*
|
|
================
|
|
AxializeVector
|
|
================
|
|
*/
|
|
static void AxializeVector( idVec3 &v ) {
|
|
idVec3 a;
|
|
float o;
|
|
int i;
|
|
|
|
if (!v[0] && !v[1]) {
|
|
return;
|
|
}
|
|
|
|
if (!v[1] && !v[2]) {
|
|
return;
|
|
}
|
|
|
|
if (!v[0] && !v[2]) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
a[i] = idMath::Fabs(v[i]);
|
|
}
|
|
|
|
if (a[0] > a[1] && a[0] > a[2]) {
|
|
i = 0;
|
|
}
|
|
else if (a[1] > a[0] && a[1] > a[2]) {
|
|
i = 1;
|
|
}
|
|
else {
|
|
i = 2;
|
|
}
|
|
|
|
o = v[i];
|
|
VectorCopy(vec3_origin, v);
|
|
if (o < 0) {
|
|
v[i] = -1;
|
|
}
|
|
else {
|
|
v[i] = 1;
|
|
}
|
|
}
|
|
|
|
extern bool UpdateActiveDragPoint(const idVec3 &move);
|
|
extern void SetActiveDrag(CDragPoint *p);
|
|
|
|
/*
|
|
================
|
|
Draw_Setup
|
|
================
|
|
*/
|
|
static void Drag_Setup( int x, int y, int buttons,
|
|
const idVec3 &xaxis, const idVec3 &yaxis, const idVec3 &origin, const idVec3 &dir ) {
|
|
qertrace_t t;
|
|
face_t *f;
|
|
|
|
drag_first = true;
|
|
|
|
VectorCopy(vec3_origin, pressdelta);
|
|
pressx = x;
|
|
pressy = y;
|
|
|
|
VectorCopy(xaxis, drag_xvec);
|
|
AxializeVector(drag_xvec);
|
|
VectorCopy(yaxis, drag_yvec);
|
|
AxializeVector(drag_yvec);
|
|
|
|
if (g_qeglobals.d_select_mode == sel_addpoint) {
|
|
if (g_qeglobals.selectObject) {
|
|
g_qeglobals.selectObject->addPoint(origin);
|
|
}
|
|
else {
|
|
g_qeglobals.d_select_mode = sel_brush;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (g_qeglobals.d_select_mode == sel_editpoint) {
|
|
|
|
g_Inspectors->entityDlg.SelectCurvePointByRay( origin, dir, buttons );
|
|
|
|
if ( g_qeglobals.d_num_move_points ) {
|
|
drag_ok = true;
|
|
}
|
|
|
|
Sys_UpdateWindows(W_ALL);
|
|
|
|
return;
|
|
}
|
|
|
|
if (g_qeglobals.d_select_mode == sel_curvepoint) {
|
|
SelectCurvePointByRay(origin, dir, buttons);
|
|
|
|
if (g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_area) {
|
|
drag_ok = true;
|
|
}
|
|
|
|
Sys_UpdateWindows(W_ALL);
|
|
|
|
Undo_Start("drag curve point");
|
|
Undo_AddBrushList(&selected_brushes);
|
|
|
|
return;
|
|
}
|
|
else {
|
|
g_qeglobals.d_num_move_points = 0;
|
|
}
|
|
|
|
if (selected_brushes.next == &selected_brushes) {
|
|
//
|
|
// in this case a new brush is created when the dragging takes place in the XYWnd,
|
|
// An useless undo is created when the dragging takes place in the CamWnd
|
|
//
|
|
Undo_Start("create brush");
|
|
|
|
Sys_Status("No selection to drag\n", 0);
|
|
return;
|
|
}
|
|
|
|
if (g_qeglobals.d_select_mode == sel_vertex) {
|
|
|
|
if ( radiant_entityMode.GetBool() ) {
|
|
return;
|
|
}
|
|
|
|
SelectVertexByRay(origin, dir);
|
|
if (g_qeglobals.d_num_move_points) {
|
|
drag_ok = true;
|
|
Undo_Start("drag vertex");
|
|
Undo_AddBrushList(&selected_brushes);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (g_qeglobals.d_select_mode == sel_edge) {
|
|
|
|
if ( radiant_entityMode.GetBool() ) {
|
|
return;
|
|
}
|
|
|
|
SelectEdgeByRay(origin, dir);
|
|
if (g_qeglobals.d_num_move_points) {
|
|
drag_ok = true;
|
|
Undo_Start("drag edge");
|
|
Undo_AddBrushList(&selected_brushes);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// check for direct hit first
|
|
t = Test_Ray(origin, dir, true);
|
|
SetActiveDrag(t.point);
|
|
if (t.point) {
|
|
drag_ok = true;
|
|
|
|
// point was hit
|
|
return;
|
|
}
|
|
|
|
if (t.selected) {
|
|
drag_ok = true;
|
|
|
|
Undo_Start("drag selection");
|
|
Undo_AddBrushList(&selected_brushes);
|
|
|
|
if (buttons == (MK_LBUTTON | MK_CONTROL)) {
|
|
Sys_Status("Shear dragging face\n");
|
|
Brush_SelectFaceForDragging(t.brush, t.face, true);
|
|
}
|
|
else if (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT)) {
|
|
Sys_Status("Sticky dragging brush\n");
|
|
for (f = t.brush->brush_faces; f; f = f->next) {
|
|
Brush_SelectFaceForDragging(t.brush, f, false);
|
|
}
|
|
}
|
|
else {
|
|
Sys_Status("Dragging entire selection\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge) {
|
|
return;
|
|
}
|
|
|
|
if ( radiant_entityMode.GetBool() ) {
|
|
return;
|
|
}
|
|
|
|
// check for side hit multiple brushes selected?
|
|
if (selected_brushes.next->next != &selected_brushes) {
|
|
// yes, special handling
|
|
bool bOK = ( g_PrefsDlg.m_bALTEdge ) ? ( ::GetAsyncKeyState( VK_MENU ) != 0 ) : true;
|
|
if (bOK) {
|
|
for (brush_t * pBrush = selected_brushes.next; pBrush != &selected_brushes; pBrush = pBrush->next) {
|
|
if (buttons & MK_CONTROL) {
|
|
Brush_SideSelect(pBrush, origin, dir, true);
|
|
}
|
|
else {
|
|
Brush_SideSelect(pBrush, origin, dir, false);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Sys_Status("press ALT to drag multiple edges\n");
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
// single select.. trying to drag fixed entities handle themselves and just move
|
|
if (buttons & MK_CONTROL) {
|
|
Brush_SideSelect(selected_brushes.next, origin, dir, true);
|
|
}
|
|
else {
|
|
Brush_SideSelect(selected_brushes.next, origin, dir, false);
|
|
}
|
|
}
|
|
|
|
Sys_Status("Side stretch\n");
|
|
drag_ok = true;
|
|
|
|
Undo_Start("side stretch");
|
|
Undo_AddBrushList(&selected_brushes);
|
|
}
|
|
|
|
extern void Face_GetScale_BrushPrimit(face_t *face, float *s, float *t, float *rot);
|
|
|
|
/*
|
|
================
|
|
Drag_Begin
|
|
================
|
|
*/
|
|
void Drag_Begin( int x, int y, int buttons,
|
|
const idVec3 &xaxis, const idVec3 &yaxis, const idVec3 &origin, const idVec3 &dir ) {
|
|
qertrace_t t;
|
|
|
|
drag_ok = false;
|
|
VectorCopy(vec3_origin, pressdelta);
|
|
VectorCopy(vec3_origin, vPressStart);
|
|
|
|
drag_first = true;
|
|
|
|
// shift LBUTTON = select entire brush
|
|
if (buttons == (MK_LBUTTON | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint) {
|
|
int nFlag = ( ::GetAsyncKeyState( VK_MENU ) != 0 ) ? SF_CYCLE : 0;
|
|
if (dir[0] == 0 || dir[1] == 0 || dir[2] == 0) { // extremely low chance of this happening from camera
|
|
Select_Ray(origin, dir, nFlag | SF_ENTITIES_FIRST); // hack for XY
|
|
}
|
|
else {
|
|
Select_Ray(origin, dir, nFlag);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// ctrl-shift LBUTTON = select single face
|
|
if (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint) {
|
|
if ( radiant_entityMode.GetBool() ) {
|
|
return;
|
|
}
|
|
|
|
// _D3XP disabled
|
|
//Select_Deselect( ( ::GetAsyncKeyState( VK_MENU ) == 0 ) );
|
|
Select_Ray(origin, dir, SF_SINGLEFACE);
|
|
return;
|
|
}
|
|
|
|
// LBUTTON + all other modifiers = manipulate selection
|
|
if (buttons & MK_LBUTTON) {
|
|
Drag_Setup(x, y, buttons, xaxis, yaxis, origin, dir);
|
|
return;
|
|
}
|
|
|
|
if ( radiant_entityMode.GetBool() ) {
|
|
return;
|
|
}
|
|
|
|
int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON;
|
|
|
|
// middle button = grab texture
|
|
if (buttons == nMouseButton) {
|
|
t = Test_Ray(origin, dir, false);
|
|
if (t.face) {
|
|
g_qeglobals.d_new_brush_bottom = t.brush->mins;
|
|
g_qeglobals.d_new_brush_top = t.brush->maxs;
|
|
|
|
// use a local brushprimit_texdef fitted to a default 2x2 texture
|
|
brushprimit_texdef_t bp_local;
|
|
if (t.brush && t.brush->pPatch) {
|
|
texdef_t localtd;
|
|
memset(&bp_local.coords, 0, sizeof(bp_local.coords));
|
|
bp_local.coords[0][0] = 1.0f;
|
|
bp_local.coords[1][1] = 1.0f;
|
|
localtd.SetName(t.brush->pPatch->d_texture->GetName());
|
|
Texture_SetTexture(&localtd, &bp_local, false, true);
|
|
Select_CopyPatchTextureCoords ( t.brush->pPatch );
|
|
} else {
|
|
Select_ProjectFaceOntoPatch( t.face );
|
|
ConvertTexMatWithQTexture(&t.face->brushprimit_texdef, t.face->d_texture, &bp_local, NULL);
|
|
Texture_SetTexture(&t.face->texdef, &bp_local, false, true);
|
|
}
|
|
UpdateSurfaceDialog();
|
|
UpdatePatchInspector();
|
|
UpdateLightInspector();
|
|
}
|
|
else {
|
|
Sys_Status("Did not select a texture\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// ctrl-middle button = set entire brush to texture
|
|
if (buttons == (nMouseButton | MK_CONTROL)) {
|
|
t = Test_Ray(origin, dir, false);
|
|
if (t.brush) {
|
|
if (t.brush->brush_faces->texdef.name[0] == '(') {
|
|
Sys_Status("Can't change an entity texture\n");
|
|
}
|
|
else {
|
|
Brush_SetTexture
|
|
(
|
|
t.brush,
|
|
&g_qeglobals.d_texturewin.texdef,
|
|
&g_qeglobals.d_texturewin.brushprimit_texdef,
|
|
false
|
|
);
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
}
|
|
else {
|
|
Sys_Status("Didn't hit a btrush\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// ctrl-shift-middle button = set single face to texture
|
|
if (buttons == (nMouseButton | MK_SHIFT | MK_CONTROL)) {
|
|
t = Test_Ray(origin, dir, false);
|
|
if (t.brush) {
|
|
if (t.brush->brush_faces->texdef.name[0] == '(') {
|
|
Sys_Status("Can't change an entity texture\n");
|
|
}
|
|
else {
|
|
SetFaceTexdef
|
|
(
|
|
t.brush,
|
|
t.face,
|
|
&g_qeglobals.d_texturewin.texdef,
|
|
&g_qeglobals.d_texturewin.brushprimit_texdef
|
|
);
|
|
Brush_Build(t.brush);
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
}
|
|
else {
|
|
Sys_Status("Didn't hit a btrush\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (buttons == (nMouseButton | MK_SHIFT)) {
|
|
Sys_Status("Set brush face texture info\n");
|
|
t = Test_Ray(origin, dir, false);
|
|
if (t.brush && !t.brush->owner->eclass->fixedsize) {
|
|
/*
|
|
if (t.brush->brush_faces->texdef.name[0] == '(') {
|
|
if (t.brush->owner->eclass->nShowFlags & ECLASS_LIGHT) {
|
|
CString strBuff;
|
|
idMaterial *pTex = declManager->FindMaterial(g_qeglobals.d_texturewin.texdef.name);
|
|
if (pTex) {
|
|
idVec3 vColor = pTex->getColor();
|
|
|
|
float fLargest = 0.0f;
|
|
for (int i = 0; i < 3; i++) {
|
|
if (vColor[i] > fLargest) {
|
|
fLargest = vColor[i];
|
|
}
|
|
}
|
|
|
|
if (fLargest == 0.0f) {
|
|
vColor[0] = vColor[1] = vColor[2] = 1.0f;
|
|
}
|
|
else {
|
|
float fScale = 1.0f / fLargest;
|
|
for (int i = 0; i < 3; i++) {
|
|
vColor[i] *= fScale;
|
|
}
|
|
}
|
|
|
|
strBuff.Format("%f %f %f", pTex->getColor().x, pTex->getColor().y, pTex->getColor().z);
|
|
SetKeyValue(t.brush->owner, "_color", strBuff.GetBuffer(0));
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
}
|
|
else {
|
|
Sys_Status("Can't select an entity brush face\n");
|
|
}
|
|
}
|
|
|
|
else {
|
|
*/
|
|
// strcpy(t.face->texdef.name,g_qeglobals.d_texturewin.texdef.name);
|
|
t.face->texdef.SetName(g_qeglobals.d_texturewin.texdef.name);
|
|
Brush_Build(t.brush);
|
|
Sys_UpdateWindows(W_ALL);
|
|
// }
|
|
}
|
|
else {
|
|
Sys_Status("Didn't hit a brush\n");
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
void Brush_GetBounds(brush_t *b, idVec3 &mins, idVec3 &maxs) {
|
|
int i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
mins[i] = 999999;
|
|
maxs[i] = -999999;
|
|
}
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
if (b->mins[i] < mins[i]) {
|
|
mins[i] = b->mins[i];
|
|
}
|
|
|
|
if (b->maxs[i] > maxs[i]) {
|
|
maxs[i] = b->maxs[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
================
|
|
MoveSelection
|
|
================
|
|
*/
|
|
static void MoveSelection( const idVec3 &orgMove ) {
|
|
int i, success;
|
|
brush_t *b;
|
|
CString strStatus;
|
|
idVec3 vTemp, vTemp2, end, move;
|
|
|
|
move = orgMove;
|
|
|
|
if (!move[0] && !move[1] && !move[2]) {
|
|
return;
|
|
}
|
|
|
|
move[0] = (g_nScaleHow & SCALE_X) ? 0 : move[0];
|
|
move[1] = (g_nScaleHow & SCALE_Y) ? 0 : move[1];
|
|
move[2] = (g_nScaleHow & SCALE_Z) ? 0 : move[2];
|
|
|
|
if (g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode) {
|
|
float fDeg = -move[2];
|
|
float fAdj = move[2];
|
|
int axis = 0;
|
|
if (g_pParentWnd->ActiveXY()->GetViewType() == XY) {
|
|
fDeg = -move[1];
|
|
fAdj = move[1];
|
|
axis = 2;
|
|
}
|
|
else if (g_pParentWnd->ActiveXY()->GetViewType() == XZ) {
|
|
fDeg = move[2];
|
|
fAdj = move[2];
|
|
axis = 1;
|
|
}
|
|
|
|
g_pParentWnd->ActiveXY()->Rotation()[g_qeglobals.rotateAxis] += fAdj;
|
|
strStatus.Format
|
|
(
|
|
"%s x:: %.1f y:: %.1f z:: %.1f",
|
|
(g_bPatchBendMode) ? "Bend angle" : "Rotation",
|
|
g_pParentWnd->ActiveXY()->Rotation()[0],
|
|
g_pParentWnd->ActiveXY()->Rotation()[1],
|
|
g_pParentWnd->ActiveXY()->Rotation()[2]
|
|
);
|
|
g_pParentWnd->SetStatusText(2, strStatus);
|
|
|
|
if (g_bPatchBendMode) {
|
|
Patch_SelectBendNormal();
|
|
Select_RotateAxis(axis, fDeg * 2, false, true);
|
|
Patch_SelectBendAxis();
|
|
Select_RotateAxis(axis, fDeg, false, true);
|
|
}
|
|
else {
|
|
Select_RotateAxis(g_qeglobals.rotateAxis, fDeg, false, true);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (g_pParentWnd->ActiveXY()->ScaleMode()) {
|
|
idVec3 v;
|
|
v[0] = v[1] = v[2] = 1.0f;
|
|
for (int i = 0; i < 3; i++) {
|
|
if ( move[i] > 0.0f ) {
|
|
v[i] = 1.1f;
|
|
} else if ( move[i] < 0.0f ) {
|
|
v[i] = 0.9f;
|
|
}
|
|
}
|
|
|
|
Select_Scale(v.x, v.y, v.z);
|
|
Sys_UpdateWindows(W_ALL);
|
|
return;
|
|
}
|
|
|
|
idVec3 vDistance;
|
|
VectorSubtract(pressdelta, vPressStart, vDistance);
|
|
strStatus.Format("Distance x: %.3f y: %.3f z: %.3f", vDistance[0], vDistance[1], vDistance[2]);
|
|
g_pParentWnd->SetStatusText(3, strStatus);
|
|
|
|
// dragging only a part of the selection
|
|
if (UpdateActiveDragPoint(move)) {
|
|
UpdateLightInspector();
|
|
return;
|
|
}
|
|
|
|
//
|
|
// this is fairly crappy way to deal with curvepoint and area selection but it
|
|
// touches the smallest amount of code this way
|
|
//
|
|
if (g_qeglobals.d_num_move_points || g_qeglobals.d_num_move_planes || g_qeglobals.d_select_mode == sel_area) {
|
|
// area selection
|
|
if (g_qeglobals.d_select_mode == sel_area) {
|
|
VectorAdd(g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR);
|
|
return;
|
|
}
|
|
|
|
// curve point selection
|
|
if (g_qeglobals.d_select_mode == sel_curvepoint) {
|
|
Patch_UpdateSelected(move);
|
|
return;
|
|
}
|
|
|
|
// vertex selection
|
|
if (g_qeglobals.d_select_mode == sel_vertex) {
|
|
success = true;
|
|
for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
|
|
success &= Brush_MoveVertex(selected_brushes.next, *g_qeglobals.d_move_points[0], move, end, true);
|
|
}
|
|
|
|
// if (success)
|
|
VectorCopy(end, *g_qeglobals.d_move_points[0]);
|
|
return;
|
|
}
|
|
|
|
// all other selection types
|
|
for (i = 0; i < g_qeglobals.d_num_move_points; i++) {
|
|
VectorAdd(*g_qeglobals.d_move_points[i], move, *g_qeglobals.d_move_points[i]);
|
|
}
|
|
|
|
if ( g_qeglobals.d_select_mode == sel_editpoint ) {
|
|
g_Inspectors->entityDlg.UpdateEntityCurve();
|
|
}
|
|
|
|
//
|
|
// VectorScale(move, .5, move); for (i=0 ; i<g_qeglobals.d_num_move_points2 ; i++)
|
|
// VectorAdd (g_qeglobals.d_move_points2[i], move, g_qeglobals.d_move_points2[i]);
|
|
//
|
|
for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
|
|
VectorCopy(b->maxs, vTemp);
|
|
VectorSubtract(vTemp, b->mins, vTemp);
|
|
Brush_Build(b);
|
|
for (i = 0; i < 3; i++) {
|
|
if
|
|
(
|
|
b->mins[i] > b->maxs[i] ||
|
|
b->maxs[i] - b->mins[i] > MAX_WORLD_SIZE ||
|
|
b->maxs[i] - b->mins[i] == 0.0f
|
|
) {
|
|
break; // dragged backwards or messed up
|
|
}
|
|
}
|
|
|
|
if (i != 3) {
|
|
break;
|
|
}
|
|
|
|
if (b->pPatch) {
|
|
VectorCopy(b->maxs, vTemp2);
|
|
VectorSubtract(vTemp2, b->mins, vTemp2);
|
|
VectorSubtract(vTemp2, vTemp, vTemp2);
|
|
|
|
// if (!Patch_DragScale(b->nPatchID, vTemp2, move))
|
|
if (!Patch_DragScale(b->pPatch, vTemp2, move)) {
|
|
b = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if any of the brushes were crushed out of existance calcel the entire move
|
|
if (b != &selected_brushes) {
|
|
Sys_Status("Brush dragged backwards, move canceled\n");
|
|
for (i = 0; i < g_qeglobals.d_num_move_points; i++) {
|
|
VectorSubtract(*g_qeglobals.d_move_points[i], move, *g_qeglobals.d_move_points[i]);
|
|
}
|
|
|
|
for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
|
|
Brush_Build(b);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
//
|
|
// reset face originals from vertex edit mode this is dirty, but unfortunately
|
|
// necessary because Brush_Build can remove windings
|
|
//
|
|
for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
|
|
Brush_ResetFaceOriginals(b);
|
|
}
|
|
|
|
Select_Move(move);
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
Drag_MouseMoved
|
|
================
|
|
*/
|
|
void Drag_MouseMoved(int x, int y, int buttons) {
|
|
idVec3 move, delta;
|
|
int i;
|
|
|
|
if (!buttons || !drag_ok) {
|
|
drag_ok = false;
|
|
return;
|
|
}
|
|
|
|
// clear along one axis
|
|
if (buttons & MK_SHIFT) {
|
|
drag_first = false;
|
|
if (abs(x - pressx) > abs(y - pressy)) {
|
|
y = pressy;
|
|
}
|
|
else {
|
|
x = pressx;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
move[i] = drag_xvec[i] * (x - pressx) + drag_yvec[i] * (y - pressy);
|
|
if (!g_PrefsDlg.m_bNoClamp) {
|
|
move[i] = floor(move[i] / g_qeglobals.d_gridsize + 0.5) * g_qeglobals.d_gridsize;
|
|
}
|
|
}
|
|
|
|
VectorSubtract(move, pressdelta, delta);
|
|
VectorCopy(move, pressdelta);
|
|
|
|
if (buttons & MK_CONTROL && g_pParentWnd->ActiveXY()->RotateMode()) {
|
|
for (i = 0; i < 3; i++) {
|
|
if (delta[i] != 0) {
|
|
if (delta[i] > 0) {
|
|
delta[i] = 15;
|
|
}
|
|
else {
|
|
delta[i] = -15;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MoveSelection(delta);
|
|
}
|
|
|
|
/*
|
|
================
|
|
Drag_MouseUp
|
|
================
|
|
*/
|
|
void Drag_MouseUp(int nButtons) {
|
|
Sys_Status("drag completed.", 0);
|
|
|
|
if (g_qeglobals.d_select_mode == sel_area) {
|
|
Patch_SelectAreaPoints();
|
|
g_qeglobals.d_select_mode = sel_curvepoint;
|
|
Sys_UpdateWindows(W_ALL);
|
|
}
|
|
|
|
if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2]) {
|
|
Select_Move(g_qeglobals.d_select_translate);
|
|
VectorCopy(vec3_origin, g_qeglobals.d_select_translate);
|
|
Sys_UpdateWindows(W_CAMERA);
|
|
}
|
|
|
|
g_pParentWnd->SetStatusText(3, "");
|
|
|
|
/*
|
|
if (g_pParentWnd->GetCamera()->UpdateRenderEntities()) {
|
|
Sys_UpdateWindows(W_CAMERA);
|
|
}
|
|
*/
|
|
|
|
Undo_EndBrushList(&selected_brushes);
|
|
Undo_End();
|
|
}
|