DRAG.CPP (19546B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 #include "stdafx.h" 23 #include "qe3.h" 24 25 /* 26 27 drag either multiple brushes, or select plane points from 28 a single brush. 29 30 */ 31 32 qboolean drag_ok; 33 vec3_t drag_xvec; 34 vec3_t drag_yvec; 35 36 static int buttonstate; 37 int pressx, pressy; 38 static vec3_t pressdelta; 39 static vec3_t vPressStart; 40 static int buttonx, buttony; 41 42 43 //int num_move_points; 44 //float *move_points[1024]; 45 46 int lastx, lasty; 47 48 qboolean drag_first; 49 50 51 void AxializeVector (vec3_t v) 52 { 53 vec3_t a; 54 float o; 55 int i; 56 57 if (!v[0] && !v[1]) 58 return; 59 if (!v[1] && !v[2]) 60 return; 61 if (!v[0] && !v[2]) 62 return; 63 64 for (i=0 ; i<3 ; i++) 65 a[i] = fabs(v[i]); 66 if (a[0] > a[1] && a[0] > a[2]) 67 i = 0; 68 else if (a[1] > a[0] && a[1] > a[2]) 69 i = 1; 70 else 71 i = 2; 72 73 o = v[i]; 74 VectorCopy (vec3_origin, v); 75 if (o<0) 76 v[i] = -1; 77 else 78 v[i] = 1; 79 80 } 81 82 83 /* 84 =========== 85 Drag_Setup 86 =========== 87 */ 88 void Drag_Setup (int x, int y, int buttons, 89 vec3_t xaxis, vec3_t yaxis, 90 vec3_t origin, vec3_t dir) 91 { 92 trace_t t; 93 face_t *f; 94 95 drag_first = true; 96 97 VectorCopy (vec3_origin, pressdelta); 98 pressx = x; 99 pressy = y; 100 101 VectorCopy (xaxis, drag_xvec); 102 AxializeVector (drag_xvec); 103 VectorCopy (yaxis, drag_yvec); 104 AxializeVector (drag_yvec); 105 106 if (g_qeglobals.d_select_mode == sel_addpoint) { 107 if (g_qeglobals.selectObject) { 108 g_qeglobals.selectObject->addPoint(origin[0], origin[1], origin[2]); 109 } else { 110 clearSelection(); 111 } 112 return; 113 } 114 115 if (g_qeglobals.d_select_mode == sel_editpoint) { 116 117 if (g_qeglobals.selectObject) { 118 if (g_qeglobals.selectObject->selectPointByRay(origin[0], origin[1], origin[2], dir[0], dir[1], dir[2], !(buttons == MK_SHIFT)) >= 0) { 119 drag_ok = true; 120 } 121 return; 122 } else { 123 clearSelection(); 124 } 125 Sys_UpdateWindows(W_ALL); 126 Undo_Start("drag object point"); 127 128 return; 129 } 130 131 132 extern void SelectCurvePointByRay (vec3_t org, vec3_t dir, int buttons); 133 if (g_qeglobals.d_select_mode == sel_curvepoint) 134 { 135 //if ((buttons == MK_LBUTTON)) 136 // g_qeglobals.d_num_move_points = 0; 137 138 SelectCurvePointByRay (origin, dir, buttons); 139 140 if (g_qeglobals.d_num_move_points || g_qeglobals.d_select_mode == sel_area) 141 { 142 drag_ok = true; 143 } 144 145 Sys_UpdateWindows(W_ALL); 146 147 Undo_Start("drag curve point"); 148 Undo_AddBrushList(&selected_brushes); 149 150 return; 151 } 152 else if (g_qeglobals.d_select_mode == sel_terrainpoint) 153 { 154 Terrain_SelectPointByRay( origin, dir, buttons ); 155 156 if (g_qeglobals.d_numterrapoints || g_qeglobals.d_select_mode == sel_area) 157 { 158 drag_ok = true; 159 } 160 161 Sys_UpdateWindows(W_ALL); 162 163 Undo_Start("drag terrain point"); 164 Undo_AddBrushList(&selected_brushes); 165 return; 166 } 167 else if (g_qeglobals.d_select_mode == sel_terraintexture) 168 { 169 Terrain_SelectPointByRay( origin, dir, buttons ); 170 171 if (g_qeglobals.d_numterrapoints || g_qeglobals.d_select_mode == sel_area) 172 { 173 drag_ok = true; 174 } 175 176 Sys_UpdateWindows(W_ALL); 177 178 Undo_Start("drag terrain point"); 179 Undo_AddBrushList(&selected_brushes); 180 return; 181 } 182 else 183 { 184 g_qeglobals.d_num_move_points = 0; 185 } 186 187 if (selected_brushes.next == &selected_brushes) 188 { 189 //in this case a new brush is created when the dragging 190 //takes place in the XYWnd, An useless undo is created 191 //when the dragging takes place in the CamWnd 192 Undo_Start("create brush"); 193 194 Sys_Status("No selection to drag\n", 0); 195 return; 196 } 197 198 199 if (g_qeglobals.d_select_mode == sel_vertex) 200 { 201 SelectVertexByRay (origin, dir); 202 if (g_qeglobals.d_num_move_points) 203 { 204 drag_ok = true; 205 Undo_Start("drag vertex"); 206 Undo_AddBrushList(&selected_brushes); 207 return; 208 } 209 } 210 211 if (g_qeglobals.d_select_mode == sel_edge) 212 { 213 SelectEdgeByRay (origin, dir); 214 if (g_qeglobals.d_num_move_points) 215 { 216 drag_ok = true; 217 Undo_Start("drag edge"); 218 Undo_AddBrushList(&selected_brushes); 219 return; 220 } 221 } 222 223 224 // 225 // check for direct hit first 226 // 227 t = Test_Ray (origin, dir, true); 228 if (t.selected) 229 { 230 drag_ok = true; 231 232 Undo_Start("drag selection"); 233 Undo_AddBrushList(&selected_brushes); 234 235 if (buttons == (MK_LBUTTON|MK_CONTROL) ) 236 { 237 Sys_Printf ("Shear dragging face\n"); 238 Brush_SelectFaceForDragging (t.brush, t.face, true); 239 } 240 else if (buttons == (MK_LBUTTON|MK_CONTROL|MK_SHIFT) ) 241 { 242 Sys_Printf ("Sticky dragging brush\n"); 243 for (f=t.brush->brush_faces ; f ; f=f->next) 244 Brush_SelectFaceForDragging (t.brush, f, false); 245 } 246 else 247 Sys_Printf ("Dragging entire selection\n"); 248 249 return; 250 } 251 252 if (g_qeglobals.d_select_mode == sel_vertex || g_qeglobals.d_select_mode == sel_edge) 253 return; 254 255 // 256 // check for side hit 257 // 258 // multiple brushes selected? 259 if (selected_brushes.next->next != &selected_brushes) 260 { 261 // yes, special handling 262 bool bOK = (g_PrefsDlg.m_bALTEdge) ? (static_cast<bool>(::GetAsyncKeyState(VK_MENU))) : true; 263 if (bOK) 264 { 265 for (brush_t* pBrush = selected_brushes.next ; pBrush != &selected_brushes ; pBrush = pBrush->next) 266 { 267 if (buttons & MK_CONTROL) 268 Brush_SideSelect (pBrush, origin, dir, true); 269 else 270 Brush_SideSelect (pBrush, origin, dir, false); 271 } 272 } 273 else 274 { 275 Sys_Printf ("press ALT to drag multiple edges\n"); 276 return; 277 } 278 } 279 else 280 { 281 // single select.. trying to drag fixed entities handle themselves and just move 282 if (buttons & MK_CONTROL) 283 Brush_SideSelect (selected_brushes.next, origin, dir, true); 284 else 285 Brush_SideSelect (selected_brushes.next, origin, dir, false); 286 } 287 288 Sys_Printf ("Side stretch\n"); 289 drag_ok = true; 290 291 Undo_Start("side stretch"); 292 Undo_AddBrushList(&selected_brushes); 293 } 294 295 entity_t *peLink; 296 297 void UpdateTarget(vec3_t origin, vec3_t dir) 298 { 299 trace_t t; 300 entity_t *pe; 301 int i; 302 char sz[128]; 303 304 t = Test_Ray (origin, dir, 0); 305 306 if (!t.brush) 307 return; 308 309 pe = t.brush->owner; 310 311 if (pe == NULL) 312 return; 313 314 // is this the first? 315 if (peLink != NULL) 316 { 317 318 // Get the target id from out current target 319 // if there is no id, make one 320 321 i = IntForKey(pe, "target"); 322 if (i <= 0) 323 { 324 i = GetUniqueTargetId(1); 325 sprintf(sz, "%d", i); 326 327 SetKeyValue(pe, "target", sz); 328 } 329 330 // set the target # into our src 331 332 sprintf(sz, "%d", i); 333 SetKeyValue(peLink, "targetname", sz); 334 335 Sys_UpdateWindows(W_ENTITY); 336 337 } 338 339 // promote the target to the src 340 341 peLink = pe; 342 343 } 344 345 /* 346 =========== 347 Drag_Begin 348 //++timo test three button mouse and three button emulation here ? 349 =========== 350 */ 351 void Drag_Begin (int x, int y, int buttons, 352 vec3_t xaxis, vec3_t yaxis, 353 vec3_t origin, vec3_t dir) 354 { 355 trace_t t; 356 bool altdown; 357 358 drag_ok = false; 359 VectorCopy (vec3_origin, pressdelta); 360 VectorCopy (vec3_origin, vPressStart); 361 drag_first = true; 362 peLink = NULL; 363 364 altdown = static_cast<bool>(::GetAsyncKeyState(VK_MENU)); 365 366 // shift-LBUTTON = select entire brush 367 if (buttons == (MK_LBUTTON | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint && 368 g_qeglobals.d_select_mode != sel_terrainpoint && g_qeglobals.d_select_mode != sel_terraintexture) 369 { 370 int nFlag = altdown ? SF_CYCLE : 0; 371 if (dir[0] == 0 || dir[1] == 0 || dir[2] == 0) // extremely low chance of this happening from camera 372 Select_Ray (origin, dir, nFlag | SF_ENTITIES_FIRST); // hack for XY 373 else 374 Select_Ray (origin, dir, nFlag); 375 return; 376 } 377 378 // ctrl-alt-LBUTTON = multiple brush select without selecting whole entities 379 if (buttons == (MK_LBUTTON | MK_CONTROL) && altdown && g_qeglobals.d_select_mode != sel_curvepoint && 380 g_qeglobals.d_select_mode != sel_terrainpoint && g_qeglobals.d_select_mode != sel_terraintexture) 381 { 382 if (dir[0] == 0 || dir[1] == 0 || dir[2] == 0) // extremely low chance of this happening from camera 383 Select_Ray (origin, dir, SF_ENTITIES_FIRST); // hack for XY 384 else 385 Select_Ray (origin, dir, 0); 386 return; 387 } 388 389 // ctrl-shift-LBUTTON = select single face 390 if (buttons == (MK_LBUTTON | MK_CONTROL | MK_SHIFT) && g_qeglobals.d_select_mode != sel_curvepoint && 391 g_qeglobals.d_select_mode != sel_terrainpoint && g_qeglobals.d_select_mode != sel_terraintexture) 392 { 393 Select_Deselect (!static_cast<bool>(::GetAsyncKeyState(VK_MENU))); 394 Select_Ray (origin, dir, SF_SINGLEFACE); 395 return; 396 } 397 398 399 // LBUTTON + all other modifiers = manipulate selection 400 if (buttons & MK_LBUTTON) 401 { 402 // 403 Drag_Setup (x, y, buttons, xaxis, yaxis, origin, dir); 404 return; 405 } 406 407 int nMouseButton = g_PrefsDlg.m_nMouseButtons == 2 ? MK_RBUTTON : MK_MBUTTON; 408 // middle button = grab texture 409 if (buttons == nMouseButton) 410 { 411 t = Test_Ray (origin, dir, false); 412 if (t.face) 413 { 414 g_qeglobals.d_new_brush_bottom_z = t.brush->mins[2]; 415 g_qeglobals.d_new_brush_top_z = t.brush->maxs[2]; 416 // use a local brushprimit_texdef fitted to a default 2x2 texture 417 brushprimit_texdef_t bp_local; 418 ConvertTexMatWithQTexture( &t.face->brushprimit_texdef, t.face->d_texture, &bp_local, NULL ); 419 Texture_SetTexture ( &t.face->texdef, &bp_local, false, GETPLUGINTEXDEF(t.face)); 420 UpdateSurfaceDialog(); 421 UpdatePatchInspector(); 422 } 423 else 424 Sys_Printf ("Did not select a texture\n"); 425 return; 426 } 427 428 // ctrl-middle button = set entire brush to texture 429 if (buttons == (nMouseButton|MK_CONTROL) ) 430 { 431 t = Test_Ray (origin, dir, false); 432 if (t.brush) 433 { 434 if (t.brush->brush_faces->texdef.name[0] == '(') 435 Sys_Printf ("Can't change an entity texture\n"); 436 else 437 { 438 Brush_SetTexture (t.brush, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef, false, static_cast<IPluginTexdef *>( g_qeglobals.d_texturewin.pTexdef ) ); 439 Sys_UpdateWindows (W_ALL); 440 } 441 } 442 else 443 Sys_Printf ("Didn't hit a btrush\n"); 444 return; 445 } 446 447 // ctrl-shift-middle button = set single face to texture 448 if (buttons == (nMouseButton|MK_SHIFT|MK_CONTROL) ) 449 { 450 t = Test_Ray (origin, dir, false); 451 if (t.brush) 452 { 453 if (t.brush->brush_faces->texdef.name[0] == '(') 454 Sys_Printf ("Can't change an entity texture\n"); 455 else 456 { 457 SetFaceTexdef (t.brush, t.face, &g_qeglobals.d_texturewin.texdef, &g_qeglobals.d_texturewin.brushprimit_texdef); 458 Brush_Build( t.brush ); 459 Sys_UpdateWindows (W_ALL); 460 } 461 } 462 else 463 Sys_Printf ("Didn't hit a btrush\n"); 464 return; 465 } 466 467 if (buttons == (nMouseButton | MK_SHIFT)) 468 { 469 Sys_Printf("Set brush face texture info\n"); 470 t = Test_Ray (origin, dir, false); 471 if (t.brush) 472 { 473 if (t.brush->brush_faces->texdef.name[0] == '(') 474 { 475 if (t.brush->owner->eclass->nShowFlags & ECLASS_LIGHT) 476 { 477 CString strBuff; 478 qtexture_t* pTex = Texture_ForName(g_qeglobals.d_texturewin.texdef.name); 479 if (pTex) 480 { 481 vec3_t vColor; 482 VectorCopy(pTex->color, vColor); 483 484 float fLargest = 0.0f; 485 for (int i = 0; i < 3; i++) 486 { 487 if (vColor[i] > fLargest) 488 fLargest = vColor[i]; 489 } 490 491 if (fLargest == 0.0f) 492 { 493 vColor[0] = vColor[1] = vColor[2] = 1.0f; 494 } 495 else 496 { 497 float fScale = 1.0f / fLargest; 498 for (int i = 0; i < 3; i++) 499 { 500 vColor[i] *= fScale; 501 } 502 } 503 strBuff.Format("%f %f %f",pTex->color[0], pTex->color[1], pTex->color[2]); 504 SetKeyValue(t.brush->owner, "_color", strBuff.GetBuffer(0)); 505 Sys_UpdateWindows (W_ALL); 506 } 507 } 508 else 509 { 510 Sys_Printf ("Can't select an entity brush face\n"); 511 } 512 } 513 else 514 { 515 //strcpy(t.face->texdef.name,g_qeglobals.d_texturewin.texdef.name); 516 t.face->texdef.SetName(g_qeglobals.d_texturewin.texdef.name); 517 Brush_Build(t.brush); 518 Sys_UpdateWindows (W_ALL); 519 } 520 } 521 else 522 Sys_Printf ("Didn't hit a brush\n"); 523 return; 524 } 525 526 } 527 528 529 // 530 //=========== 531 //MoveSelection 532 //=========== 533 // 534 void MoveSelection (vec3_t move) 535 { 536 int i, success; 537 brush_t *b; 538 CString strStatus; 539 vec3_t vTemp, vTemp2, end; 540 541 if (!move[0] && !move[1] && !move[2]) 542 return; 543 544 move[0] = (g_nScaleHow & SCALE_X) ? 0 : move[0]; 545 move[1] = (g_nScaleHow & SCALE_Y) ? 0 : move[1]; 546 move[2] = (g_nScaleHow & SCALE_Z) ? 0 : move[2]; 547 548 if (g_pParentWnd->ActiveXY()->RotateMode() || g_bPatchBendMode) 549 { 550 float fDeg = -move[2]; 551 float fAdj = move[2]; 552 int nAxis = 0; 553 if (g_pParentWnd->ActiveXY()->GetViewType() == XY) 554 { 555 fDeg = -move[1]; 556 fAdj = move[1]; 557 nAxis = 2; 558 } 559 else 560 if (g_pParentWnd->ActiveXY()->GetViewType() == XZ) 561 { 562 fDeg = move[2]; 563 fAdj = move[2]; 564 nAxis = 1; 565 } 566 else 567 nAxis = 0; 568 569 g_pParentWnd->ActiveXY()->Rotation()[nAxis] += fAdj; 570 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]); 571 g_pParentWnd->SetStatusText(2, strStatus); 572 573 if (g_bPatchBendMode) 574 { 575 Patch_SelectBendNormal(); 576 Select_RotateAxis(nAxis, fDeg*2, false, true); 577 Patch_SelectBendAxis(); 578 Select_RotateAxis(nAxis, fDeg, false, true); 579 } 580 else 581 { 582 Select_RotateAxis(nAxis, fDeg, false, true); 583 } 584 return; 585 } 586 587 if (g_pParentWnd->ActiveXY()->ScaleMode()) 588 { 589 vec3_t v; 590 v[0] = v[1] = v[2] = 1.0; 591 if (move[1] > 0) 592 { 593 v[0] = 1.1; 594 v[1] = 1.1; 595 v[2] = 1.1; 596 } 597 else 598 if (move[1] < 0) 599 { 600 v[0] = 0.9; 601 v[1] = 0.9; 602 v[2] = 0.9; 603 } 604 605 Select_Scale((g_nScaleHow & SCALE_X) ? 1.0 : v[0], 606 (g_nScaleHow & SCALE_Y) ? 1.0 : v[1], 607 (g_nScaleHow & SCALE_Z) ? 1.0 : v[2]); 608 Sys_UpdateWindows (W_ALL); 609 return; 610 } 611 612 613 vec3_t vDistance; 614 VectorSubtract(pressdelta, vPressStart, vDistance); 615 strStatus.Format("Distance x: %.1f y: %.1f z: %.1f", vDistance[0], vDistance[1], vDistance[2]); 616 g_pParentWnd->SetStatusText(3, strStatus); 617 618 // 619 // dragging only a part of the selection 620 // 621 //point object selection 622 if (g_qeglobals.d_select_mode == sel_editpoint) { 623 if (g_qeglobals.selectObject) { 624 g_qeglobals.selectObject->updateSelection(move[0], move[1], move[2]); 625 } 626 return; 627 } 628 629 630 // this is fairly crappy way to deal with curvepoint and area selection 631 // but it touches the smallest amount of code this way 632 // 633 if (g_qeglobals.d_num_move_points || g_qeglobals.d_numterrapoints || g_qeglobals.d_select_mode == sel_area) 634 { 635 //area selection 636 if (g_qeglobals.d_select_mode == sel_area) 637 { 638 VectorAdd(g_qeglobals.d_vAreaBR, move, g_qeglobals.d_vAreaBR); 639 return; 640 } 641 //curve point selection 642 if (g_qeglobals.d_select_mode == sel_curvepoint) 643 { 644 Patch_UpdateSelected(move); 645 return; 646 } 647 //terrain point selection 648 if ( ( g_qeglobals.d_select_mode == sel_terrainpoint ) || ( g_qeglobals.d_select_mode == sel_terraintexture ) ) 649 { 650 Terrain_UpdateSelected(move); 651 return; 652 } 653 654 //vertex selection 655 if (g_qeglobals.d_select_mode == sel_vertex) 656 { 657 success = true; 658 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) 659 { 660 success &= Brush_MoveVertex(b, g_qeglobals.d_move_points[0], move, end, true); 661 } 662 if (success) 663 VectorCopy(end, g_qeglobals.d_move_points[0]); 664 return; 665 } 666 //all other selection types 667 for (i=0 ; i<g_qeglobals.d_num_move_points ; i++) 668 VectorAdd (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]); 669 //VectorScale(move, .5, move); 670 //for (i=0 ; i<g_qeglobals.d_num_move_points2 ; i++) 671 // VectorAdd (g_qeglobals.d_move_points2[i], move, g_qeglobals.d_move_points2[i]); 672 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) 673 { 674 VectorCopy(b->maxs, vTemp); 675 VectorSubtract(vTemp, b->mins, vTemp); 676 Brush_Build( b ); 677 for (i=0 ; i<3 ; i++) 678 if (b->mins[i] > b->maxs[i] 679 || b->maxs[i] - b->mins[i] > MAX_BRUSH_SIZE) 680 break; // dragged backwards or fucked up 681 if (i != 3) 682 break; 683 if (b->patchBrush) 684 { 685 VectorCopy(b->maxs, vTemp2); 686 VectorSubtract(vTemp2, b->mins, vTemp2); 687 VectorSubtract(vTemp2, vTemp, vTemp2); 688 //if (!Patch_DragScale(b->nPatchID, vTemp2, move)) 689 if (!Patch_DragScale(b->pPatch, vTemp2, move)) 690 { 691 b = NULL; 692 break; 693 } 694 } 695 696 if (b->terrainBrush) 697 { 698 VectorCopy(b->maxs, vTemp2); 699 VectorSubtract(vTemp2, b->mins, vTemp2); 700 VectorSubtract(vTemp2, vTemp, vTemp2); 701 if (!Terrain_DragScale(b->pTerrain, vTemp2, move)) 702 { 703 b = NULL; 704 break; 705 } 706 } 707 } 708 // if any of the brushes were crushed out of existance 709 // calcel the entire move 710 if (b != &selected_brushes) 711 { 712 Sys_Printf ("Brush dragged backwards, move canceled\n"); 713 for (i=0 ; i<g_qeglobals.d_num_move_points ; i++) 714 VectorSubtract (g_qeglobals.d_move_points[i], move, g_qeglobals.d_move_points[i]); 715 716 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next) 717 Brush_Build( b ); 718 } 719 720 } 721 else 722 { 723 // reset face originals from vertex edit mode 724 // this is dirty, but unfortunately necessary because Brush_Build 725 // can remove windings 726 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) 727 { 728 Brush_ResetFaceOriginals(b); 729 } 730 // 731 // if there are lots of brushes selected, just translate instead 732 // of rebuilding the brushes 733 // 734 if (drag_yvec[2] == 0 && selected_brushes.next->next != &selected_brushes) 735 { 736 Select_Move (move); 737 //VectorAdd (g_qeglobals.d_select_translate, move, g_qeglobals.d_select_translate); 738 } 739 else 740 { 741 Select_Move (move); 742 } 743 } 744 } 745 746 /* 747 =========== 748 Drag_MouseMoved 749 =========== 750 */ 751 void Drag_MouseMoved (int x, int y, int buttons) 752 { 753 vec3_t move, delta; 754 int i; 755 756 if (!buttons) 757 { 758 drag_ok = false; 759 return; 760 } 761 if (!drag_ok) 762 return; 763 764 // clear along one axis 765 if (buttons & MK_SHIFT) 766 { 767 drag_first = false; 768 if (abs(x-pressx) > abs(y-pressy)) 769 y = pressy; 770 else 771 x = pressx; 772 } 773 774 775 for (i=0 ; i<3 ; i++) 776 { 777 move[i] = drag_xvec[i]*(x - pressx) + drag_yvec[i]*(y - pressy); 778 if (!g_PrefsDlg.m_bNoClamp) 779 { 780 move[i] = floor(move[i]/g_qeglobals.d_gridsize+0.5)*g_qeglobals.d_gridsize; 781 } 782 } 783 784 VectorSubtract (move, pressdelta, delta); 785 VectorCopy (move, pressdelta); 786 787 MoveSelection (delta); 788 789 } 790 791 /* 792 =========== 793 Drag_MouseUp 794 =========== 795 */ 796 void Drag_MouseUp (int nButtons) 797 { 798 Sys_Status ("drag completed.", 0); 799 800 if (g_qeglobals.d_select_mode == sel_area) 801 { 802 if ( OnlyTerrainSelected() ) 803 { 804 Terrain_SelectAreaPoints(); 805 g_qeglobals.d_select_mode = sel_terrainpoint; 806 Sys_UpdateWindows (W_ALL); 807 } 808 else 809 { 810 Patch_SelectAreaPoints(); 811 g_qeglobals.d_select_mode = sel_curvepoint; 812 Sys_UpdateWindows (W_ALL); 813 } 814 } 815 816 if (g_qeglobals.d_select_translate[0] || g_qeglobals.d_select_translate[1] || g_qeglobals.d_select_translate[2]) 817 { 818 Select_Move (g_qeglobals.d_select_translate); 819 VectorCopy (vec3_origin, g_qeglobals.d_select_translate); 820 Sys_UpdateWindows (W_CAMERA); 821 } 822 823 g_pParentWnd->SetStatusText(3, ""); 824 825 // 826 Undo_EndBrushList(&selected_brushes); 827 Undo_End(); 828 }