📄 geneditview.cpp
字号:
/****************************************************************************************/
/* GenEditView.cpp */
/* */
/* Author: Jim Mischel, Ken Baird, Jeff Lomax, John Moore */
/* Description: MFC view stuff... Alot of the editor UI functionality is here */
/* */
/* The contents of this file are subject to the Genesis3D Public License */
/* Version 1.01 (the "License"); you may not use this file except in */
/* compliance with the License. You may obtain a copy of the License at */
/* http://www.genesis3d.com */
/* */
/* Software distributed under the License is distributed on an "AS IS" */
/* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */
/* the License for the specific language governing rights and limitations */
/* under the License. */
/* */
/* The Original Code is Genesis3D, released March 25, 1999. */
/*Genesis3D Version 1.1 released November 15, 1999 */
/* Copyright (C) 1999 WildTangent, Inc. All Rights Reserved */
/* */
/* Modified by Tom Morris for GenEdit-Classic ver. 0.58, April 23, 2001 */
/****************************************************************************************/
#include "stdafx.h"
#include "Globals.h"
#include "KeyEditDlg.h"
#include "GenEditView.h"
#include <assert.h>
#include "units.h"
#include "face.h"
#include "ram.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define AXIS_X 0x1
#define AXIS_Y 0x2
#define AXIS_Z 0x4
#define MAX_PIXEL_DRAG_START_DIST (12.0f)
int CGenEditView::mCY_DRAG = 2 ;
int CGenEditView::mCX_DRAG = 2 ;
IMPLEMENT_DYNCREATE(CGenEditView, CView)
BEGIN_MESSAGE_MAP(CGenEditView, CView)
ON_MESSAGE(WM_USER_COMPILE_MSG, OnCompileMessage)
ON_MESSAGE(WM_USER_COMPILE_ERR, OnCompileError)
ON_MESSAGE(WM_USER_COMPILE_DONE, OnCompileDone)
//{{AFX_MSG_MAP(CGenEditView)
ON_WM_SIZE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_COMMAND(ID_TOOLS_CAMERA, OnToolsCamera)
ON_UPDATE_COMMAND_UI(ID_TOOLS_CAMERA, OnUpdateToolsCamera)
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_COMMAND(ID_AXIS_X, OnAxisX)
ON_UPDATE_COMMAND_UI(ID_AXIS_X, OnUpdateAxisX)
ON_COMMAND(ID_AXIS_Y, OnAxisY)
ON_UPDATE_COMMAND_UI(ID_AXIS_Y, OnUpdateAxisY)
ON_COMMAND(ID_AXIS_Z, OnAxisZ)
ON_UPDATE_COMMAND_UI(ID_AXIS_Z, OnUpdateAxisZ)
ON_COMMAND(ID_TOOLS_BRUSH_MOVEROTATEBRUSH, OnToolsBrushMoverotatebrush)
ON_UPDATE_COMMAND_UI(ID_TOOLS_BRUSH_MOVEROTATEBRUSH, OnUpdateToolsBrushMoverotatebrush)
ON_COMMAND(ID_TOOLS_BRUSH_SCALEBRUSH, OnToolsBrushScalebrush)
ON_UPDATE_COMMAND_UI(ID_TOOLS_BRUSH_SCALEBRUSH, OnUpdateToolsBrushScalebrush)
ON_COMMAND(ID_TOOLS_BRUSH_SHOWBRUSH, OnToolsBrushShowbrush)
ON_UPDATE_COMMAND_UI(ID_TOOLS_BRUSH_SHOWBRUSH, OnUpdateToolsBrushShowbrush)
ON_WM_ERASEBKGND()
ON_COMMAND(ID_TOOLS_BRUSH_SHEARBRUSH, OnToolsBrushShearbrush)
ON_UPDATE_COMMAND_UI(ID_TOOLS_BRUSH_SHEARBRUSH, OnUpdateToolsBrushShearbrush)
ON_UPDATE_COMMAND_UI(ID_GROUPS_MAKENEWGROUP, OnUpdateBrushGroupsMakenewgroup)
ON_UPDATE_COMMAND_UI(ID_BRUSH_GROUPS_ADDTOGROUP, OnUpdateBrushGroupsAddtogroup)
ON_COMMAND(ID_TOOLS_BRUSH_ROTATE90, OnToolsBrushRotate45)
ON_COMMAND(ID_TOOLS_BRUSH_MOVESELECTEDBRUSHES, OnToolsBrushMoveselectedbrushes)
ON_UPDATE_COMMAND_UI(ID_TOOLS_BRUSH_MOVESELECTEDBRUSHES, OnUpdateToolsBrushMoveselectedbrushes)
ON_COMMAND(ID_TOOLS_TEMPLATE, OnToolsTemplate)
ON_UPDATE_COMMAND_UI(ID_TOOLS_TEMPLATE, OnUpdateToolsTemplate)
ON_UPDATE_COMMAND_UI(ID_TOOLS_BRUSH_ROTATE90, OnUpdateToolsBrushRotate45)
ON_COMMAND(ID_BRUSH_REMOVESELECTEDFROMGROUP, OnBrushRemoveselectedfromgroup)
ON_UPDATE_COMMAND_UI(ID_BRUSH_REMOVESELECTEDFROMGROUP, OnUpdateBrushRemoveselectedfromgroup)
ON_COMMAND(ID_BRUSH_GROUPS_ADDTOGROUP, OnBrushGroupsAddtogroup)
ON_COMMAND(ID_DESELECTALL, OnDeselectall)
ON_UPDATE_COMMAND_UI(ID_DESELECTALL, OnUpdateDeselectall)
ON_COMMAND(ID_SELECTALL, OnSelectall)
ON_UPDATE_COMMAND_UI(ID_SELECTALL, OnUpdateSelectall)
ON_COMMAND(ID_TOOLS_SCALEWORLD, OnToolsScaleworld)
ON_COMMAND(ID_TOOLS_BRUSH_MAKENEWEST, OnToolsBrushMakenewest)
ON_COMMAND(ID_TOOLS_SETTEXTURESCALE, OnToolsSettexturescale)
ON_COMMAND(ID_TOOLS_NEXTBRUSH, OnToolsNextbrush)
ON_COMMAND(ID_TOOLS_PREVBRUSH, OnToolsPrevbrush)
ON_COMMAND(ID_TOOLS_ADDTOLEVEL, OnToolsAddtolevel)
ON_UPDATE_COMMAND_UI(ID_TOOLS_ADDTOLEVEL, OnUpdateToolsAddtolevel)
ON_COMMAND(ID_VIEW_ZOOMIN, OnViewZoomin)
ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMIN, OnUpdateViewZoomin)
ON_COMMAND(ID_VIEW_ZOOMOUT, OnViewZoomout)
ON_UPDATE_COMMAND_UI(ID_VIEW_ZOOMOUT, OnUpdateViewZoomout)
ON_COMMAND(ID_CENTERTHING, OnCenterthing)
ON_UPDATE_COMMAND_UI(ID_CENTERTHING, OnUpdateCenterthing)
ON_WM_CONTEXTMENU()
ON_COMMAND(ID_TOOLS_BRUSH_ROTATEBRUSH, OnToolsBrushRotatebrush)
ON_UPDATE_COMMAND_UI(ID_TOOLS_BRUSH_ROTATEBRUSH, OnUpdateToolsBrushRotatebrush)
ON_WM_MBUTTONUP()
ON_WM_MOUSEWHEEL() // posthoot
ON_WM_MBUTTONDOWN() // posthoot
ON_WM_MBUTTONUP() //posthoot
ON_COMMAND(IDC_BTN_REBUILD_COMMAND, OnButtonRebuildShow)// post 0.57
ON_COMMAND(IDC_BTN_REBUILD_HIDE, OnButtonRebuildHide)// post 0.57
ON_BN_CLICKED(IDC_BTN_VIEW_REBUILD, OnButtonRebuild)// post 0.57
//}}AFX_MSG_MAP
ON_COMMAND_RANGE( ID_VIEW_3DWIREFRAME, ID_VIEW_TEXTUREVIEW, OnViewType)
ON_UPDATE_COMMAND_UI_RANGE(ID_VIEW_3DWIREFRAME, ID_VIEW_TEXTUREVIEW, OnViewTypeCmdUi)
END_MESSAGE_MAP()
#define SIDE_LEFT 1
#define SIDE_RIGHT 2
#define SIDE_TOP 4
#define SIDE_BOTTOM 8
// post 0.57 notifies user of need to rebuild
// see pDoc::SelectRay for origin of message
void CGenEditView::OnButtonRebuildShow()
{
if (mViewType == ID_VIEW_TEXTUREVIEW)
{
if (m_btnRebuild)
{
if (!m_btnRebuild.IsWindowVisible())
{
m_btnRebuild.ShowWindow(SW_SHOW);
CGenEditDoc *pDoc = GetDocument();
pDoc->PlayResource("SND_QUICKBEEP");
}
}
}
}
// post 0.57 notifies user of need to rebuild
// see pDoc::OngbspnoWater for origin of message
void CGenEditView::OnButtonRebuildHide()
{
if (mViewType == ID_VIEW_TEXTUREVIEW)
{
if (m_btnRebuild)
{
if (m_btnRebuild.IsWindowVisible())
{
m_btnRebuild.ShowWindow(SW_HIDE);
}
}
}
}
// post 0.57
void CGenEditView::OnButtonRebuild()
{
if (mViewType == ID_VIEW_TEXTUREVIEW)
{
CGenEditDoc *pDoc = GetDocument ();
pDoc->UpdateAllViews( UAV_ALL3DVIEWS | REBUILD_QUICK, NULL, TRUE ); //post 0.57
if (m_btnRebuild.IsWindowVisible())
{
m_btnRebuild.ShowWindow(SW_HIDE);
}
CGlobals::g_iRebuildClickCount = 0;
}
}
void CGenEditView::OnUpdateCenterthing(CCmdUI* pCmdUI)
{
CGenEditDoc *pDoc = GetDocument ();
if ((pDoc->mModeTool == ID_TOOLS_TEMPLATE) &&
((mViewType == ID_VIEW_TOPVIEW) || (mViewType == ID_VIEW_SIDEVIEW) || (mViewType == ID_VIEW_FRONTVIEW)))
{
pCmdUI->Enable (TRUE);
}
else
{
pCmdUI->Enable (FALSE);
}
}
// Center the template brush or entity in the selected view.
// Doesn't work for 3d views...
void CGenEditView::OnCenterthing()
{
CGenEditDoc *pDoc = GetDocument ();
// only works on templates
if ((pDoc->mModeTool != ID_TOOLS_TEMPLATE) ||
((mViewType != ID_VIEW_TOPVIEW) && (mViewType != ID_VIEW_SIDEVIEW) && (mViewType != ID_VIEW_FRONTVIEW)))
{
return;
}
geVec3d NewWorldPos = Render_GetViewCenter (VCam);
// Get the current thing's position...
geVec3d CurrentThingPos;
if (pDoc->TempEnt)
{
CurrentThingPos = pDoc->mRegularEntity.mOrigin;
}
else
{
if (pDoc->CurBrush == NULL)
{
return;
}
Brush_Center (pDoc->CurBrush, &CurrentThingPos);
}
// Compute delta required to get thing to NewWorldPos.
// One dimension won't be changed (i.e. in the top view, the Y won't be modified)
geVec3d MoveDelta;
geVec3d_Subtract (&NewWorldPos, &CurrentThingPos, &MoveDelta);
switch (mViewType)
{
case ID_VIEW_TOPVIEW :
MoveDelta.Y = 0.0f;
break;
case ID_VIEW_SIDEVIEW :
MoveDelta.X = 0.0f;
break;
case ID_VIEW_FRONTVIEW :
MoveDelta.Z = 0.0f;
break;
default :
// don't do nothin!
assert (0);
}
// We've computed the delta, so move the thing...
pDoc->MoveTemplateBrush (&MoveDelta);
// Be very careful when speccing flags for UpdateAllViews()
// The wrong flags at the wrong time will totally screw things up
pDoc->UpdateAllViews( UAV_ALL3DVIEWS, NULL );
}
static geBoolean IsKeyDown (int Key)
{
int KeyState;
KeyState = ::GetAsyncKeyState (Key);
return (KeyState & 0x8000);
}
// Prevent axis movement. View space clipping.
void CGenEditView::LockAxisView (int *dx, int *dy)
{
CGenEditDoc *pDoc = GetDocument ();
int mLockAxis = pDoc->GetLockAxis ();
switch (mViewType)
{
case ID_VIEW_TOPVIEW :
if (mLockAxis & AXIS_X) *dx = 0;
if (mLockAxis & AXIS_Z) *dy = 0;
break;
case ID_VIEW_SIDEVIEW :
if (mLockAxis & AXIS_X) *dx = 0;
if (mLockAxis & AXIS_Y) *dy = 0;
break;
case ID_VIEW_FRONTVIEW :
if (mLockAxis & AXIS_Z) *dx = 0;
if (mLockAxis & AXIS_Y) *dy = 0;
break;
}
}
// Prevent axis movement. World space clipping.
void CGenEditView::LockAxis( geVec3d * pWP )
{
int mLockAxis ;
CGenEditDoc* pDoc = GetDocument();
mLockAxis = pDoc->GetLockAxis() ;
if( mLockAxis & AXIS_X ) pWP->X = 0.0f ;
if( mLockAxis & AXIS_Y ) pWP->Y = 0.0f ;
if( mLockAxis & AXIS_Z ) pWP->Z = 0.0f ;
}/* CGenEditView::LockAxis */
void CGenEditView::OnToolsBrushRotate45()
{
geVec3d rp;
static int i_reminder; // so this messagebox only shows up once
CGenEditDoc* pDoc = GetDocument();
// post 0.57
CString message = _T("If you choose this control while the Textured View is active,\n");
message += _T("rotation will NOT occur.\n\n");
message += _T("In order to get rotation in the view of your choice,\n");
message += _T("make sure your view is active (highlighted).\n\n");
message += _T("We recommend that you use the menu item for this control\n");
message += _T("on the right-click context menu while in the view of your choice.");
geVec3d_Clear (&rp);
switch (mViewType)
{
case ID_VIEW_TEXTUREVIEW: // post 0.57
if (i_reminder <1) // deliver the reminder once
{
AfxMessageBox(message);
i_reminder++;
}
break;
case ID_VIEW_TOPVIEW: // if textured view is highlighted, rotation will occur
rp.Y = -(M_PI/4.0f);// in the topo view
break;
case ID_VIEW_FRONTVIEW :
rp.Z = -(M_PI/4.0f);
break;
case ID_VIEW_SIDEVIEW:
rp.X = (M_PI/4.0f);
break;
default :
return;
}
if(GetModeTool()!=ID_GENERALSELECT)
{
pDoc->RotateTemplateBrush(&rp);
pDoc->UpdateSelected(); // calls UpdateMainControls()
// Be very careful when speccing flags for UpdateAllViews()
// The wrong flags at the wrong time will totally screw things up
pDoc->UpdateAllViews(UAV_ALL3DVIEWS, NULL);
}
else
{
pDoc->RotateSelectedBrushesDirect (&rp);
// Be very careful when speccing flags for UpdateAllViews()
// The wrong flags at the wrong time will totally screw things up
// Make sure REBUILD_QUICK is absolutely necessary.
pDoc->UpdateAllViews(UAV_ALL3DVIEWS | REBUILD_QUICK, NULL);
}
// post 0.57 send a message to display the Rebuild button on the textured view
int ModeTool = GetModeTool ();
int AdjustMode = GetAdjustMode ();
if ((ModeTool == ID_GENERALSELECT) && (AdjustMode == ADJUST_MODE_BRUSH))
{
if(!Level_RebuildBspAlways(pDoc->pLevel))
{
pDoc->mpMainFrame->SendMessageToDescendants(WM_COMMAND, IDC_BTN_REBUILD_COMMAND);
CGlobals::g_iRebuildClickCount = 0;
}
}
}
int CGenEditView::GetCursorBoxPos (const POINT *ptMousePos)
{
CGenEditDoc *pDoc;
const Box3d *pBrushBox;
POINT ptMin, ptMax;
int dx, dy;
int x, y;
int horiz, vert;
int lookup[4] = {1, 2, 2, 3};
/*
Split the box up into 3 sections vertically and 3 horizontally.
The center sections are 1/2 the width and height, and the end sections are
each 1/4 of width and height.
What we're creating is:
0 1 2 3 4
------------------------
| | | |
5 | 6 | 7 | 8 | 9
------------------------
| | | |
| | | |
10 | 11 | 12 | 13 | 14
| | | |
------------------------
| | | |
15 | 16 | 17 | 18 | 19
------------------------
20 21 22 23 24
Then we determine which of the sections the cursor is closest to,
and return that index.
*/
pDoc = GetDocument ();
pBrushBox = Brush_GetBoundingBox (pDoc->CurBrush);
// obtain screen coordinates for bounding box min and max points
ptMin = Render_OrthoWorldToView (VCam, &pBrushBox->Min);
ptMax = Render_OrthoWorldToView (VCam, &pBrushBox->Max);
// make sure the min and max points are correct...
if (ptMin.x > ptMax.x)
{
int temp;
temp = ptMin.x;
ptMin.x = ptMax.x;
ptMax.x = temp;
}
if (ptMin.y > ptMax.y)
{
int temp;
temp = ptMin.y;
ptMin.y = ptMax.y;
ptMax.y = temp;
}
// compute horizontal first
x = ptMousePos->x - ptMin.x;
dx = (ptMax.x - ptMin.x);
if (dx == 0) horiz = 0; else horiz = (4*x) / dx;
if (horiz < 0) horiz = 0;
else if (horiz > 3) horiz = 4;
else horiz = lookup[horiz];
// and vertical
y = ptMousePos->y - ptMin.y;
dy = (ptMax.y - ptMin.y);
if (dy == 0) vert = 0; else vert = (4*y)/dy;
if (vert < 0) vert = 0;
else if (vert > 3) vert = 3;
else vert = lookup[vert];
// return index...
return (vert * 5) + horiz;
}
void CGenEditView::SetEditCursor (int Tool, const POINT *pMousePos)
{
//for sizing stuff
static const char *SizeCursors[25]=
{
IDC_SIZENWSE, IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW, IDC_SIZENESW,
IDC_SIZENWSE, IDC_SIZENWSE, IDC_SIZENS, IDC_SIZENESW, IDC_SIZENESW,
IDC_SIZEWE, IDC_SIZEWE, IDC_NO, IDC_SIZEWE, IDC_SIZEWE,
IDC_SIZENESW, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, IDC_SIZENWSE,
IDC_SIZENESW, IDC_SIZENESW, IDC_SIZENS, IDC_SIZENWSE, IDC_SIZENWSE
};
static const char *ShearCursors[25]=
{
IDC_NO, IDC_SIZEWE, IDC_SIZEWE, IDC_SIZEWE, IDC_NO,
IDC_SIZENS, IDC_NO, IDC_SIZEWE, IDC_NO, IDC_SIZENS,
IDC_SIZENS, IDC_SIZENS, IDC_NO, IDC_SIZENS, IDC_SIZENS,
IDC_SIZENS, IDC_NO, IDC_SIZEWE, IDC_NO, IDC_SIZENS,
IDC_NO, IDC_SIZEWE, IDC_SIZEWE, IDC_SIZEWE, IDC_NO
};
const char *WhichCursor = NULL;
int CursorIndex;
assert ((Tool == ID_TOOLS_BRUSH_SCALEBRUSH) || (Tool == ID_TOOLS_BRUSH_SHEARBRUSH));
// Determine where the cursor is on the box surrounding the selected brush,
// and set the appropriate cursor.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -