890 lines
23 KiB
C++
890 lines
23 KiB
C++
|
|
#include "stdafx.h"
|
|
#include "resource.h"
|
|
#include "GsPreviewCtrl.h"
|
|
#include "acgsmanager.h"
|
|
#include "EarThwormDef.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define WM_VIEWDBLCLKSEL (WM_USER + 0x1200)
|
|
|
|
BOOL IsKeyPressed(int vk)
|
|
{
|
|
SHORT nState = ::GetKeyState(vk);
|
|
return ((nState & 256) != 0);
|
|
}
|
|
|
|
double g_nWalkDistStep = 1000.0, g_nWalkAngleStep = 5.0*PI / 180;;
|
|
#define RXASSERT ASSERT
|
|
|
|
double GetLatitude(AcGePoint3d ptCam, AcGePoint3d ptTar)
|
|
{
|
|
double nDist = ptTar.distanceTo(ptCam);
|
|
if (nDist < 1.e-6)
|
|
return 0.0;
|
|
|
|
if (ptTar.distanceTo(ptCam) < 1.e-5)
|
|
{
|
|
return ((ptTar.z > ptCam.z) ? PI / 2 : -PI / 2);
|
|
}
|
|
return asin((ptTar.z - ptCam.z) / nDist);
|
|
}
|
|
|
|
|
|
double GetLongitude(AcGePoint3d ptCam, AcGePoint3d ptTar) // 0 ~ 2*PI
|
|
{
|
|
if (ptTar.distanceTo(ptCam) < 1.e-6)
|
|
return 0.0;
|
|
return ads_angle(asDblArray(ptCam), asDblArray(ptTar));
|
|
}
|
|
|
|
IMPLEMENT_DYNAMIC(CGsPreviewCtrl, CStatic)
|
|
|
|
CGsPreviewCtrl::CGsPreviewCtrl(int nOrbitFlag) : CStatic(), mOrbitFlag(nOrbitFlag),
|
|
mpManager(NULL), mpFactory(NULL), mpDevice(NULL), mpView(NULL),
|
|
mpModel(NULL), mbModelCreated(false), mbPanning(false), mbOrbiting(false),
|
|
mDistStep(g_nWalkDistStep), mAngStep(g_nWalkAngleStep)
|
|
{
|
|
|
|
}
|
|
|
|
BOOL CGsPreviewCtrl::DestroyWindow()
|
|
{
|
|
clearAll();
|
|
return CStatic::DestroyWindow();
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CGsPreviewCtrl, CStatic)
|
|
//{{AFX_MSG_MAP(CGsPreviewCtrl)
|
|
ON_WM_PAINT()
|
|
ON_WM_SIZE()
|
|
ON_WM_MOUSEWHEEL()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_MBUTTONDOWN()
|
|
ON_WM_MBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_NCHITTEST()
|
|
ON_WM_SETFOCUS()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
//}}AFX_MSG_MAP
|
|
ON_WM_SETCURSOR()
|
|
END_MESSAGE_MAP()
|
|
|
|
void CGsPreviewCtrl::OnPaint()
|
|
{
|
|
CPaintDC dc(this);
|
|
//update the gs view
|
|
if (mpView)
|
|
{
|
|
mpView->invalidate();
|
|
mpView->update();
|
|
}
|
|
}
|
|
|
|
// Erase view and delete model
|
|
void CGsPreviewCtrl::erasePreview()
|
|
{
|
|
if (mpView)
|
|
mpView->eraseAll();
|
|
if (mpManager && mpModel) {
|
|
mpManager->destroyAutoCADModel(mpModel);
|
|
mpModel = NULL;
|
|
}
|
|
}
|
|
|
|
void CGsPreviewCtrl::setModel(AcGsModel* pModel)
|
|
{
|
|
erasePreview();
|
|
mpModel = pModel;
|
|
mbModelCreated = false;
|
|
}
|
|
|
|
void CGsPreviewCtrl::clearAll()
|
|
{
|
|
if (mpView) {
|
|
mpView->eraseAll();
|
|
}
|
|
if (mpDevice) {
|
|
bool b = mpDevice->erase(mpView);
|
|
RXASSERT(b);
|
|
}
|
|
|
|
if (mpFactory) {
|
|
if (mpView) {
|
|
mpFactory->deleteView(mpView);
|
|
mpView = NULL;
|
|
}
|
|
if (mpGhostModel) {
|
|
mpFactory->deleteModel(mpGhostModel);
|
|
mpGhostModel = NULL;
|
|
}
|
|
mpFactory = NULL;
|
|
}
|
|
|
|
if (mpManager) {
|
|
if (mpModel) {
|
|
if (mbModelCreated)
|
|
mpManager->destroyAutoCADModel(mpModel);
|
|
mpModel = NULL;
|
|
}
|
|
|
|
if (mpDevice) {
|
|
mpManager->destroyAutoCADDevice(mpDevice);
|
|
mpDevice = NULL;
|
|
}
|
|
mpManager = NULL;
|
|
}
|
|
}
|
|
|
|
BOOL CGsPreviewCtrl::GetCurrentViewInfo(const AcDbExtents& exts, AcGePoint3d & ptPosition, AcGePoint3d & ptTarget,
|
|
AcGeVector3d& vecUpVector, double& dFieldWidth, double& dFieldHeight)
|
|
{
|
|
// get the view port information - see parameter list
|
|
double dHeight = 0.0, dWidth = 0.0, dViewTwist = 0.0;
|
|
AcGePoint3d ptTargetView;
|
|
AcGeVector3d vecViewDir;
|
|
GetActiveViewPortInfo(dHeight, dWidth, ptTargetView, vecViewDir, dViewTwist, TRUE);
|
|
|
|
// we are only interested in the directions of the view, not the sizes, so we normalise.
|
|
vecViewDir.normalize();
|
|
|
|
// Our view coordinate space consists of z direction
|
|
// get a perp vector off the z direction
|
|
// Make sure its normalised
|
|
AcGeVector3d vecViewXDir = vecViewDir.perpVector().normal();
|
|
// correct the x angle by applying the twist
|
|
vecViewXDir = vecViewXDir.rotateBy(dViewTwist, -vecViewDir);
|
|
// now we can work out y, this is of course perp to the x and z directions. No need to normalise this,
|
|
// as we know that x and z are of unit length, and perpendicular, so their cross product must be on unit length
|
|
vecUpVector = vecViewDir.crossProduct(vecViewXDir);
|
|
|
|
// Calculate the extents in WCS
|
|
AcGePoint3d ptExtMax = exts.maxPoint();
|
|
AcGePoint3d ptExtMin = exts.minPoint();
|
|
|
|
// find a nice point around which to transform the view. We'll use the same point as the center of the view.
|
|
ptTarget = ptExtMin + 0.5 * (ptExtMax - ptExtMin);
|
|
|
|
ptPosition = ptTarget + vecViewDir;
|
|
|
|
// create a transform from WCS to View space
|
|
// this represents the transformation from WCS to the view space. (Actually not quite since
|
|
// we are keeping the fixed point as the center of the box for convenience )
|
|
AcGeMatrix3d matView;
|
|
matView = AcGeMatrix3d::alignCoordSys(ptTarget, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis,
|
|
ptTarget, vecViewXDir, vecUpVector, vecViewDir).inverse();
|
|
|
|
AcDbExtents extWcsExtents(ptExtMin, ptExtMax);
|
|
// now we have the view Extents
|
|
AcDbExtents extViewExtents = extWcsExtents;
|
|
// transforms the extents in WCS->view space
|
|
extViewExtents.transformBy(matView);
|
|
|
|
// get the extents of the AutoCAD view
|
|
dFieldWidth = fabs(extViewExtents.maxPoint().x - extViewExtents.minPoint().x);
|
|
dFieldHeight = fabs(extViewExtents.maxPoint().y - extViewExtents.minPoint().y);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CGsPreviewCtrl::InitFromCurrentView2D(const AcDbExtents& exts,bool bRestTarget)
|
|
{
|
|
struct resbuf rb;
|
|
acedGetVar(_T("CVPORT"), &rb);
|
|
int iCurView = rb.resval.rint;
|
|
acedGetVar(_T("TILEMODE"), &rb);
|
|
int iTileMode = rb.resval.rint;
|
|
|
|
#ifndef ZWCAD
|
|
#if ARX < 20
|
|
AcGsView::RenderMode eShadeMode;
|
|
if (iTileMode == 0 && iCurView == 1)
|
|
eShadeMode = AcGsView::k2DOptimized;
|
|
else
|
|
eShadeMode = AcGsView::k2DOptimized;
|
|
mpView->setMode(eShadeMode);
|
|
#else
|
|
AcGiVisualStyle style;
|
|
if (iTileMode == 0 && iCurView == 1)
|
|
style.setType(AcGiVisualStyle::k2DWireframe);
|
|
else
|
|
style.setType(AcGiVisualStyle::k2DWireframe);
|
|
mpView->setVisualStyle(style);
|
|
#endif
|
|
#else
|
|
#if defined(R24)
|
|
AcGsView::RenderMode eShadeMode;
|
|
if (iTileMode == 0 && iCurView == 1)
|
|
eShadeMode = AcGsView::k2DOptimized;
|
|
else
|
|
eShadeMode = AcGsView::k2DOptimized;
|
|
mpView->setMode(eShadeMode);
|
|
#else
|
|
AcGiVisualStyle style;
|
|
if (iTileMode == 0 && iCurView == 1)
|
|
style.setType(AcGiVisualStyle::k2DWireframe);
|
|
else
|
|
style.setType(AcGiVisualStyle::k2DWireframe);
|
|
mpView->setVisualStyle(style);
|
|
#endif
|
|
#endif
|
|
|
|
AcGeVector3d vecUpVector;
|
|
AcGePoint3d ptPosition, ptTarget;
|
|
double dFieldWidth, dFieldHeight;
|
|
GetCurrentViewInfo(exts, ptPosition, ptTarget, vecUpVector, dFieldWidth, dFieldHeight);
|
|
|
|
if (!vecUpVector.isParallelTo(AcGeVector3d::kYAxis))
|
|
{
|
|
vecUpVector = AcGeVector3d::kYAxis;//???显示Y方向看
|
|
}
|
|
|
|
if (bRestTarget)
|
|
ptTarget.set(0,0,0);
|
|
|
|
ptPosition.set(0,0,0);
|
|
|
|
mpView->setView(ptPosition, ptTarget, vecUpVector, dFieldWidth, dFieldHeight);
|
|
|
|
mpView->zoomExtents(exts.minPoint(),exts.maxPoint());
|
|
|
|
mpView->zoom(1.1);
|
|
|
|
mpView->invalidate();
|
|
}
|
|
|
|
void CGsPreviewCtrl::InitFromCurrentView3D(const AcDbExtents& exts, bool bRestTarget)
|
|
{
|
|
struct resbuf rb;
|
|
acedGetVar(_T("CVPORT"), &rb);
|
|
int iCurView = rb.resval.rint;
|
|
acedGetVar(_T("TILEMODE"), &rb);
|
|
int iTileMode = rb.resval.rint;
|
|
|
|
#ifndef ZWCAD
|
|
#if ARX < 20
|
|
mpView->setMode(AcGsView::kGouraudShaded);
|
|
#else
|
|
mpView->setVisualStyle(AcGiVisualStyle::kGouraud);
|
|
#endif
|
|
#else
|
|
#if defined(R24)
|
|
mpView->setMode(AcGsView::kGouraudShaded);
|
|
#else
|
|
mpView->setVisualStyle(AcGiVisualStyle::kGouraud);
|
|
#endif
|
|
#endif
|
|
|
|
AcGePoint3d extMax(500, 500, 500);// = pDb->extmax();
|
|
AcGePoint3d extMin(-500, -500, -500);// = pDb->extmin();
|
|
|
|
//AcGePoint3d extMax = pDb->extmax();
|
|
//AcGePoint3d extMin = pDb->extmin();
|
|
|
|
// get the view port information - see parameter list
|
|
ads_real height = 0.0, width = 0.0, viewTwist = 0.0;
|
|
AcGePoint3d targetView;
|
|
AcGeVector3d viewDir;
|
|
GetActiveViewPortInfo(height, width, targetView, viewDir, viewTwist, true);
|
|
|
|
viewDir.set(-1, -1, 1);
|
|
viewDir = viewDir.normal();
|
|
|
|
|
|
AcGeVector3d viewXDir = viewDir.perpVector().normal();
|
|
viewXDir = viewXDir.rotateBy(viewTwist, -viewDir);
|
|
AcGeVector3d viewYDir = viewDir.crossProduct(viewXDir);
|
|
|
|
AcGePoint3d boxCenter = extMin + 0.5 * (extMax - extMin);
|
|
|
|
AcGeMatrix3d viewMat = AcGeMatrix3d::alignCoordSys(boxCenter, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis,
|
|
boxCenter, viewXDir, viewYDir, viewDir).inverse();
|
|
|
|
AcDbExtents wcsExtents(extMin, extMax);
|
|
AcDbExtents viewExtents = wcsExtents;
|
|
viewExtents.transformBy(viewMat);
|
|
|
|
double xMax = fabs(viewExtents.maxPoint().x - viewExtents.minPoint().x);
|
|
double yMax = fabs(viewExtents.maxPoint().y - viewExtents.minPoint().y);
|
|
|
|
AcGePoint3d eye = boxCenter + viewDir;
|
|
|
|
mpView->setView(eye, boxCenter, viewYDir, xMax, yMax);
|
|
|
|
//if (mpView != NULL)
|
|
//{
|
|
// mpView->invalidate();
|
|
// mpView->update();
|
|
//}
|
|
|
|
}
|
|
|
|
BOOL CGsPreviewCtrl::GetActiveViewPortInfo(double &dHeight, double &dWidth, AcGePoint3d &ptTarget,
|
|
AcGeVector3d &vecViewDir, double &dViewTwist, BOOL bGetViewCenter)
|
|
{
|
|
// get the working db
|
|
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
|
|
// if not ok
|
|
if (pDb == NULL)
|
|
return FALSE;
|
|
|
|
// lock document
|
|
//AcApDocument* pDoc = acDocManager->curDocument();
|
|
//acDocManager->lockDocument(pDoc);
|
|
|
|
// make sure the active view port is uptodate
|
|
//acedVports2VportTableRecords();
|
|
|
|
// unlock document
|
|
//acDocManager->unlockDocument(pDoc);
|
|
|
|
// open the view port records
|
|
AcDbViewportTable *pVTable = NULL;
|
|
Acad::ErrorStatus es = pDb->getViewportTable(pVTable, AcDb::kForRead);
|
|
// if we opened them ok
|
|
if (es == Acad::eOk)
|
|
{
|
|
AcDbViewportTableRecord *pViewPortRec = NULL;
|
|
es = pVTable->getAt(_T("*Active"), pViewPortRec, AcDb::kForRead);
|
|
if (es == Acad::eOk)
|
|
{
|
|
// get the height of the view
|
|
dHeight = pViewPortRec->height();
|
|
// get the width
|
|
dWidth = pViewPortRec->width();
|
|
// if the user wants the center of the viewport used
|
|
if (bGetViewCenter)
|
|
{
|
|
struct resbuf rb;
|
|
memset(&rb, 0, sizeof(struct resbuf));
|
|
// get the system var VIEWCTR
|
|
acedGetVar(_T("VIEWCTR"), &rb);
|
|
// set that as the target
|
|
ptTarget = AcGePoint3d(rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
|
|
}
|
|
else
|
|
{
|
|
// we want the viewports camera target setting
|
|
// get the target of the view
|
|
ptTarget = pViewPortRec->target();
|
|
}
|
|
|
|
// get the view direction
|
|
vecViewDir = pViewPortRec->viewDirection();
|
|
// get the view twist of the viewport
|
|
dViewTwist = pViewPortRec->viewTwist();
|
|
}
|
|
// close after use
|
|
pVTable->close();
|
|
pViewPortRec->close();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CGsPreviewCtrl::GetCurrentViewInfo(AcGePoint3d & ptPosition, AcGePoint3d & ptTarget,
|
|
AcGeVector3d& vecUpVector, double& dFieldWidth, double& dFieldHeight)
|
|
{
|
|
// get the view port information - see parameter list
|
|
double dHeight = 0.0, dWidth = 0.0, dViewTwist = 0.0;
|
|
AcGePoint3d ptTargetView;
|
|
AcGeVector3d vecViewDir;
|
|
GetActiveViewPortInfo(dHeight, dWidth, ptTargetView, vecViewDir, dViewTwist, TRUE);
|
|
|
|
// we are only interested in the directions of the view, not the sizes, so we normalise.
|
|
vecViewDir.normalize();
|
|
|
|
// Our view coordinate space consists of z direction
|
|
// get a perp vector off the z direction
|
|
// Make sure its normalised
|
|
AcGeVector3d vecViewXDir = vecViewDir.perpVector().normal();
|
|
// correct the x angle by applying the twist
|
|
vecViewXDir = vecViewXDir.rotateBy(dViewTwist, -vecViewDir);
|
|
// now we can work out y, this is of course perp to the x and z directions. No need to normalise this,
|
|
// as we know that x and z are of unit length, and perpendicular, so their cross product must be on unit length
|
|
vecUpVector = vecViewDir.crossProduct(vecViewXDir);
|
|
|
|
// the current editor drawing
|
|
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
|
|
// Calculate the extents in WCS
|
|
AcGePoint3d ptExtMax = pDb->extmax();
|
|
AcGePoint3d ptExtMin = pDb->extmin();
|
|
|
|
// find a nice point around which to transform the view. We'll use the same point as the center of the view.
|
|
ptTarget = ptExtMin + 0.5 * (ptExtMax - ptExtMin);
|
|
|
|
ptPosition = ptTarget + vecViewDir;
|
|
|
|
// create a transform from WCS to View space
|
|
// this represents the transformation from WCS to the view space. (Actually not quite since
|
|
// we are keeping the fixed point as the center of the box for convenience )
|
|
AcGeMatrix3d matView;
|
|
matView = AcGeMatrix3d::alignCoordSys(ptTarget, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis,
|
|
ptTarget, vecViewXDir, vecUpVector, vecViewDir).inverse();
|
|
|
|
AcDbExtents extWcsExtents(ptExtMin, ptExtMax);
|
|
// now we have the view Extents
|
|
AcDbExtents extViewExtents = extWcsExtents;
|
|
// transforms the extents in WCS->view space
|
|
extViewExtents.transformBy(matView);
|
|
|
|
// get the extents of the AutoCAD view
|
|
dFieldWidth = fabs(extViewExtents.maxPoint().x - extViewExtents.minPoint().x);
|
|
dFieldHeight = fabs(extViewExtents.maxPoint().y - extViewExtents.minPoint().y);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CGsPreviewCtrl::init(bool bCreateModel)
|
|
{
|
|
//Load our special cursors
|
|
{
|
|
CAcModuleResourceOverride vTemp;
|
|
CWinApp *pApp = AfxGetApp();
|
|
mhPanCursor = pApp->LoadCursor(IDI_PAN);
|
|
mhCrossCursor = pApp->LoadCursor(IDI_CROSS);
|
|
mhOrbitCursor = pApp->LoadCursor(IDI_ORBIT);
|
|
mhEditCursor = pApp->LoadCursor(IDC_CURSOREDIT);
|
|
}
|
|
|
|
//Instantiate view, a device and a model object
|
|
CRect rect;
|
|
if (!mpManager) {
|
|
mpManager = acgsGetGsManager();
|
|
RXASSERT(mpManager);
|
|
#if (ARX >= 20)
|
|
AcGsKernelDescriptor desc;
|
|
desc.addRequirement(AcGsKernelDescriptor::k3DDrawing);
|
|
mpFactory = AcGsManager::acquireGraphicsKernel(desc);
|
|
if (!mpFactory) return;
|
|
#else
|
|
mpFactory = mpManager->getGSClassFactory();
|
|
#endif
|
|
RXASSERT(mpFactory);
|
|
//a device with standard autocad color palette
|
|
#if (ARX >= 20)
|
|
//mpDevice = mpFactory->createOffScreenDevice();
|
|
mpDevice = mpManager->createAutoCADDevice(*mpFactory, m_hWnd);
|
|
#else
|
|
mpDevice = mpManager->createAutoCADDevice(m_hWnd);
|
|
#endif
|
|
RXASSERT(mpDevice);
|
|
|
|
GetClientRect(&rect);
|
|
mpDevice->onSize(rect.Width(), rect.Height());
|
|
//a simple view
|
|
mpView = mpFactory->createView();
|
|
RXASSERT(mpView);
|
|
if (bCreateModel)
|
|
{
|
|
RXASSERT(mpModel == NULL);
|
|
//a model with open/close protocol
|
|
#if (ARX >= 20)
|
|
mpModel = mpManager->createAutoCADModel(*mpFactory);
|
|
#else
|
|
mpModel = mpManager->createAutoCADModel();
|
|
#endif
|
|
RXASSERT(mpModel);
|
|
mbModelCreated = true;
|
|
}
|
|
//another model without open/close for the orbit gadget
|
|
mpGhostModel = mpFactory->createModel(AcGsModel::kDirect, 0, 0, 0);
|
|
if (mOrbitFlag) {
|
|
/*
|
|
mpView->add(&mOrbitGadget,mpGhostModel);
|
|
mOrbitGadget.setGsView(mpView);
|
|
*/
|
|
}
|
|
mpDevice->add(mpView);
|
|
mpView->setView(AcGePoint3d(0.0, 0.0, 1.0),
|
|
AcGePoint3d(0.0, 0.0, 0.0),
|
|
AcGeVector3d(0.0, 0.0, 1.0),
|
|
1.0, 1.0);
|
|
}
|
|
}
|
|
|
|
BOOL CGsPreviewCtrl::Add(AcDbEntity* pEnt)
|
|
{
|
|
if (mpView != NULL)
|
|
{
|
|
mpView->add(pEnt, mpModel);
|
|
mpView->invalidate();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CGsPreviewCtrl::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CRect rect;
|
|
if (mpDevice) {
|
|
GetClientRect(&rect);
|
|
mpDevice->onSize(rect.Width(), rect.Height());
|
|
}
|
|
}
|
|
|
|
BOOL CGsPreviewCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
|
|
{
|
|
if (!(mOrbitFlag&OBF_ZOOM))
|
|
return CStatic::OnMouseWheel(nFlags, zDelta, pt);
|
|
if (mpView)
|
|
{
|
|
if (mpView->isPerspective())
|
|
{
|
|
AcGePoint3d ptTar = mpView->target();
|
|
AcGePoint3d ptCam = mpView->position();
|
|
AcGeVector3d vtView = ptTar - ptCam;
|
|
vtView.normalize();
|
|
double nScale = mDistStep;
|
|
if (zDelta < 0)
|
|
nScale = -nScale;
|
|
vtView *= nScale;
|
|
ptCam += vtView;
|
|
ptTar += vtView;
|
|
|
|
mpView->setView(ptCam, ptTar, AcGeVector3d(0, 0, 1), mpView->fieldWidth(),
|
|
mpView->fieldHeight(), AcGsView::kPerspective);
|
|
//mpView->setTarget(ptTar);
|
|
//mpView->setCamera(ptCam);
|
|
}
|
|
else
|
|
{
|
|
if (zDelta < 0)
|
|
mpView->zoom(0.9);
|
|
else
|
|
mpView->zoom(1.1);
|
|
}
|
|
//Invalidate();//闪的利害
|
|
RedrawWindow();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CGsPreviewCtrl::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
SetFocus();
|
|
|
|
if ((mOrbitFlag & OBF_COTE))
|
|
{
|
|
CRect rc;
|
|
GetClientRect(&rc);
|
|
|
|
CPoint pt = point;
|
|
AcGePoint3d ptGe1(pt.x, (rc.Height() - pt.y), 0.0);
|
|
ptGe1.transformBy(mpView->worldToDeviceMatrix().inverse());
|
|
|
|
GetParent()->SendMessage(WM_VIEW_LBUTTONDOWN, 0, (LPARAM)&ptGe1);
|
|
|
|
::SetCursor(mhEditCursor);
|
|
return;
|
|
}
|
|
|
|
if (!(mOrbitFlag & OBF_ORBIT))
|
|
{
|
|
CStatic::OnLButtonDown(nFlags, point);
|
|
return;
|
|
}
|
|
|
|
//start orbit
|
|
mbOrbiting = true;
|
|
SetCapture();
|
|
//set up the proper cursor
|
|
//::SetClassLong(m_hWnd,GCL_HCURSOR,NULL);
|
|
::SetCursor(mhOrbitCursor);
|
|
//store the start point
|
|
mStartPt = point;
|
|
|
|
ClientToScreen(&point);
|
|
GetParent()->ScreenToClient(&point);
|
|
GetParent()->SendMessage(WM_LBUTTONDOWN, nFlags, MAKELPARAM(point.x, point.y));
|
|
}
|
|
|
|
void CGsPreviewCtrl::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if ((mOrbitFlag & OBF_COTE))
|
|
{
|
|
::SetCursor(mhEditCursor);
|
|
ReleaseCapture();
|
|
return;
|
|
}
|
|
|
|
if (!(mOrbitFlag&OBF_ORBIT)) {
|
|
CStatic::OnLButtonUp(nFlags, point);
|
|
return;
|
|
}
|
|
|
|
//end orbit
|
|
mbOrbiting = false;
|
|
//::SetClassLong(m_hWnd,GCL_HCURSOR,(long)mhCrossCursor);
|
|
::SetCursor(mhCrossCursor);
|
|
ReleaseCapture();
|
|
}
|
|
|
|
void CGsPreviewCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
ClientToScreen(&point);
|
|
GetParent()->ScreenToClient(&point);
|
|
GetParent()->SendMessage(WM_LBUTTONDBLCLK,nFlags,MAKELPARAM(point.x,point.y));
|
|
GetParent()->SendMessage(WM_VIEWDBLCLKSEL,0,0);
|
|
}
|
|
|
|
void CGsPreviewCtrl::OnMButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
if (!(mOrbitFlag&OBF_PAN)) {
|
|
CStatic::OnMButtonDown(nFlags, point);
|
|
return;
|
|
}
|
|
|
|
//start pan
|
|
mbPanning = true;
|
|
SetCapture();
|
|
//set up the proper cursor
|
|
//::SetClassLong(m_hWnd,GCL_HCURSOR,NULL);
|
|
::SetCursor(mhPanCursor);
|
|
//store the start point
|
|
mStartPt = point;
|
|
|
|
|
|
}
|
|
|
|
void CGsPreviewCtrl::OnMButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (!(mOrbitFlag&OBF_PAN)) {
|
|
CStatic::OnMButtonUp(nFlags, point);
|
|
return;
|
|
}
|
|
|
|
//end pan
|
|
ReleaseCapture();
|
|
mbPanning = false;
|
|
//::SetClassLong(m_hWnd,GCL_HCURSOR,(long)mhCrossCursor);
|
|
::SetCursor(mhCrossCursor);
|
|
}
|
|
void CGsPreviewCtrl::Invalidate(BOOL bErase)
|
|
{
|
|
#if(ARX<17)
|
|
CStatic::Invalidate(bErase);
|
|
#else
|
|
{
|
|
CWnd*pParent = GetParent();
|
|
if (pParent != NULL)//2008+vista发现刷新问题,暂用此方法解决
|
|
{
|
|
CRect rect;
|
|
GetWindowRect(rect);
|
|
pParent->ScreenToClient(rect);
|
|
pParent->InvalidateRect(rect, bErase);
|
|
}
|
|
else
|
|
{
|
|
CStatic::Invalidate(bErase);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
void CGsPreviewCtrl::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (mpView && mbPanning && (mOrbitFlag&OBF_PAN))
|
|
{
|
|
//transform the point from device coordinates to
|
|
//world coordinates
|
|
AcGeVector3d pan_vec(-(point.x - mStartPt.x), point.y - mStartPt.y, 0);
|
|
pan_vec.transformBy(mpView->viewingMatrix() * mpView->worldToDeviceMatrix().inverse());
|
|
mpView->dolly(pan_vec);
|
|
//Invalidate();
|
|
RedrawWindow();
|
|
mStartPt = point;
|
|
}
|
|
else if (mpView && mbOrbiting && (mOrbitFlag&OBF_ORBIT))
|
|
{
|
|
AcGeVector3d vtMov(mStartPt.x - point.x, point.y - mStartPt.y, 0.0);
|
|
AcGePoint3d ptCam = mpView->position();
|
|
AcGePoint3d ptTar = mpView->target();
|
|
AcGeVector3d vtUp = mpView->upVector();
|
|
vtUp = AcGeVector3d(0, 0, 1);
|
|
CRect rect;
|
|
GetClientRect(rect);
|
|
double nRotX = -vtMov.y / rect.Height()*PI / 2;
|
|
double nRotY = -vtMov.x / rect.Width()*PI / 2;
|
|
|
|
AcGeVector3d vtZ = ptCam - ptTar;
|
|
AcGePlane plan(ptCam, vtZ);
|
|
AcGePoint3d ptUp = ptCam + vtUp*10000.0;
|
|
AcGePoint3d ptUp1 = ptUp.orthoProject(plan);
|
|
if (ptCam.distanceTo(ptUp1) < 0.1)
|
|
return;
|
|
AcGeVector3d vtY = ptUp1 - ptCam;
|
|
AcGeVector3d vtX = vtY.crossProduct(vtZ);
|
|
vtX.normalize();
|
|
vtY.normalize();
|
|
vtZ.normalize();
|
|
|
|
AcGeVector3d vtView = ptTar - ptCam;
|
|
|
|
vtView.rotateBy(nRotX, vtX);
|
|
vtY.rotateBy(nRotX, vtX);
|
|
vtView.rotateBy(nRotY, vtY);
|
|
ptTar = ptCam + vtView;
|
|
mpView->setView(ptCam, ptTar, vtUp, mpView->fieldWidth(), mpView->fieldHeight(),
|
|
mpView->isPerspective() ? AcGsView::kPerspective : AcGsView::kParallel);
|
|
|
|
//Invalidate();
|
|
RedrawWindow();
|
|
mStartPt = point;
|
|
}
|
|
else
|
|
{
|
|
CStatic::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
}
|
|
|
|
#if ARX<17
|
|
UINT CGsPreviewCtrl::OnNcHitTest(CPoint point)
|
|
#else
|
|
LRESULT CGsPreviewCtrl::OnNcHitTest(CPoint point)
|
|
#endif
|
|
{
|
|
return HTCLIENT;
|
|
}
|
|
|
|
|
|
void CGsPreviewCtrl::OnSetFocus(CWnd* pOldWnd)
|
|
{
|
|
if (mOrbitFlag && mhCrossCursor)
|
|
{
|
|
::SetCursor(mhCrossCursor);
|
|
}
|
|
}
|
|
|
|
void CGsPreviewCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
BOOL bShift = IsKeyPressed(VK_SHIFT);
|
|
BOOL bCtrl = IsKeyPressed(VK_CONTROL);
|
|
if (!mpView) return;
|
|
|
|
AcGePoint3d ptCam = mpView->position();
|
|
AcGePoint3d ptTar = mpView->target();
|
|
AcGeVector3d vtView = ptTar - ptCam;
|
|
vtView.normalize();
|
|
AcGeVector3d vtUp(0, 0, 1);
|
|
if (nChar == VK_LEFT || nChar == VK_RIGHT)
|
|
{
|
|
double nFactor = 1.0;
|
|
if (nChar == VK_RIGHT)
|
|
nFactor = -1.0;
|
|
if (!bShift && !bCtrl)
|
|
{ //左右移
|
|
double nStepLen = mDistStep*nRepCnt;
|
|
double longitude = GetLongitude(ptCam, ptTar);
|
|
AcGeMatrix3d mat;
|
|
|
|
AcGePoint3d ptTmp(nStepLen*cos(longitude + PI / 2.0*nFactor),
|
|
nStepLen*sin(longitude + PI / 2.0*nFactor), 0.0);
|
|
mat.setToTranslation(ptTmp.asVector());
|
|
|
|
ptCam.transformBy(mat);
|
|
ptTar.transformBy(mat);
|
|
}
|
|
else if (bCtrl)
|
|
{ //左右转 PI/2
|
|
double val = GetLongitude(ptCam, ptTar) + PI / 2.0 * nFactor;
|
|
double nElev = ptTar.z;
|
|
ads_polar(asDblArray(ptCam), val, ptCam.distanceTo(ptTar), asDblArray(ptTar));
|
|
ptTar.z = nElev;
|
|
}
|
|
else if (bShift) { //左右转
|
|
double val = GetLongitude(ptCam, ptTar) + mAngStep*nRepCnt*nFactor;
|
|
double nElev = ptTar.z;
|
|
ads_polar(asDblArray(ptCam), val, ptCam.distanceTo(ptTar), asDblArray(ptTar));
|
|
ptTar.z = nElev;
|
|
}
|
|
}
|
|
else if (nChar == VK_UP || nChar == VK_DOWN)
|
|
{
|
|
double nFactor = 1.0;
|
|
if (nChar == VK_DOWN)
|
|
nFactor = -1.0;
|
|
if (!bShift && !bCtrl) { //前进或后退
|
|
AcGeMatrix3d mat;
|
|
double nStepLen = mDistStep*nRepCnt*nFactor;
|
|
double longitude = GetLongitude(ptCam, ptTar);
|
|
|
|
AcGePoint3d ptT(nStepLen*cos(longitude), nStepLen*sin(longitude), 0);
|
|
mat.setToTranslation(ptT.asVector());
|
|
|
|
ptCam.transformBy(mat);
|
|
ptTar.transformBy(mat);
|
|
}
|
|
else if (bCtrl) { //上下移动
|
|
ptCam.z += mDistStep*nRepCnt*nFactor;
|
|
ptTar.z += mDistStep*nRepCnt*nFactor;
|
|
}
|
|
else if (bShift) { //上下转动
|
|
double val = GetLatitude(ptCam, ptTar) + mAngStep*nRepCnt*nFactor;
|
|
double nElevDiff = ptCam.distanceTo(ptTar)*tan(val);
|
|
ptTar.z = ptCam.z + nElevDiff;
|
|
}
|
|
}
|
|
else {
|
|
CStatic::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
return;
|
|
}
|
|
mpView->setView(ptCam, ptTar, vtUp, mpView->fieldWidth(), mpView->fieldHeight(),
|
|
mpView->isPerspective() ? AcGsView::kPerspective : AcGsView::kParallel);
|
|
//Invalidate();
|
|
RedrawWindow();
|
|
}
|
|
|
|
|
|
|
|
BOOL CGsPreviewCtrl::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
// TODO: Add your specialized code here and/or call the base class
|
|
if (pMsg->message == WM_KEYDOWN) {
|
|
INT_PTR vk = pMsg->wParam;
|
|
if (vk == VK_LEFT || vk == VK_RIGHT || vk == VK_DOWN || vk == VK_UP) {
|
|
int nRepCnt = LOWORD(pMsg->lParam);
|
|
OnKeyDown((UINT)vk, nRepCnt, 0);
|
|
return TRUE;
|
|
}
|
|
}
|
|
return CStatic::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
|
|
BOOL CGsPreviewCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
if ((mOrbitFlag & OBF_COTE))
|
|
{
|
|
SetCursor(mhEditCursor);
|
|
return FALSE;
|
|
}
|
|
return CStatic::OnSetCursor(pWnd, nHitTest, message);
|
|
}
|
|
|
|
void CGsPreviewCtrl::RefreshView()
|
|
{
|
|
if (mpView != NULL)
|
|
{
|
|
mpView->invalidate();
|
|
mpView->update();
|
|
}
|
|
}
|
|
|
|
void CGsPreviewCtrl::OnZoomExtents(AcDbDatabase* pDb)
|
|
{
|
|
AcDbExtents viewExtents(pDb->extmin(), pDb->extmax());
|
|
AcGeMatrix3d viewMatrix;
|
|
viewExtents.transformBy(viewMatrix);
|
|
|
|
//mpView->zoomExtents(viewExtents.minPoint(),viewExtents.maxPoint());
|
|
RefreshView();
|
|
}
|