Files
libreoffice/svx/source/engine3d/dragmt3d.cxx

880 lines
27 KiB
C++
Raw Normal View History

2000-09-18 16:07:07 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 16:07:07 +00:00
*
* $RCSfile: dragmt3d.cxx,v $
2000-09-18 16:07:07 +00:00
*
* $Revision: 1.7 $
2000-09-18 16:07:07 +00:00
*
* last change: $Author: rt $ $Date: 2006-07-25 12:51:14 $
2000-09-18 16:07:07 +00:00
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
2000-09-18 16:07:07 +00:00
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
2000-09-18 16:07:07 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
2000-09-18 16:07:07 +00:00
*
* This library 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
* Lesser General Public License for more details.
2000-09-18 16:07:07 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
2000-09-18 16:07:07 +00:00
*
************************************************************************/
// MIB 6.11.97: Die Reihenfolge der Includes mag verwundern, aber in dieser
// Reihenfolge geht das durch den SCO GCC, in anderen nicht. Also bitte nicht
// an der Reihenfolge drehen, wenn es nicht noetig ist. Das gleiche gilt
// natuerlich auch fuer das hinzufuegen von Includes. Danke.
#ifndef _SHL_HXX //autogen
#include <tools/shl.hxx>
#endif
#ifndef _SVDPAGV_HXX //autogen
#include "svdpagv.hxx"
#endif
#ifndef _SVX_DIALMGR_HXX //autogen
#include <dialmgr.hxx>
#endif
#ifndef _XOUTX_HXX //autogen
#include <xoutx.hxx>
#endif
#ifndef _SVDDRGMT_HXX //autogen
#include <svddrgmt.hxx>
#endif
#ifndef _SVDTRANS_HXX
#include "svdtrans.hxx"
#endif
#ifndef _POLY3D_HXX
#include "poly3d.hxx"
#endif
#ifndef _SVX_MATRIX3D_HXX
#include "matrix3d.hxx"
#endif
#ifndef _E3D_OBJ3D_HXX
#include "obj3d.hxx"
#endif
#ifndef _E3D_POLYSC3D_HXX
#include "polysc3d.hxx"
#endif
#ifndef _E3D_UNDO_HXX
#include "e3dundo.hxx"
#endif
#ifndef _E3D_DRAGMT3D_HXX
#include "dragmt3d.hxx"
#endif
#ifndef _SVX_DIALOGS_HRC
#include "dialogs.hrc"
#endif
TYPEINIT1(E3dDragMethod, SdrDragMethod);
/*************************************************************************
|*
|* Parameter fuer Interaktion eines 3D-Objektes
|*
\************************************************************************/
SV_IMPL_PTRARR(E3dDragMethodUnitGroup, E3dDragMethodUnit*);
/*************************************************************************
|*
|* Timing-Qualitaeten
|*
\************************************************************************/
#define E3D_GOOD_TIME Time(0,0)
#define E3D_BAD_TIME Time(0,0,1)
#define E3D_WANTED_TIME Time(0,0,0,25)
#define E3D_WAITTIME_TIL_REDRAW (5)
/*************************************************************************
|*
|* Konstruktor aller 3D-DragMethoden
|*
\************************************************************************/
E3dDragMethod::E3dDragMethod (
SdrDragView &_rView,
2000-09-18 16:07:07 +00:00
const SdrMarkList& rMark,
//BFS01E3dDragDetail eDetail,
2000-09-18 16:07:07 +00:00
E3dDragConstraint eConstr,
BOOL bFull)
: SdrDragMethod(_rView),
2000-09-18 16:07:07 +00:00
eConstraint(eConstr),
//BFS01eDragDetail(eDetail),
2000-09-18 16:07:07 +00:00
bMoveFull(bFull),
bMovedAtAll(FALSE)
{
// Fuer alle in der selektion befindlichen 3D-Objekte
// eine Unit anlegen
long nCnt = rMark.GetMarkCount();
for(long nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = rMark.GetMark(nObjs)->GetMarkedSdrObj();
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dObject))
{
E3dObject* p3DObj = (E3dObject*)pObj;
E3dDragMethodUnit* pNewUnit = new E3dDragMethodUnit;
DBG_ASSERT(pNewUnit, "AW: Kein Speicher");
// Neue Unit einrichten
pNewUnit->p3DObj = p3DObj;
// Transformationen holen
pNewUnit->aInitTransform = pNewUnit->aTransform = p3DObj->GetTransform();
if(p3DObj->GetParentObj())
pNewUnit->aDisplayTransform = p3DObj->GetParentObj()->GetFullTransform();
pNewUnit->aInvDisplayTransform = pNewUnit->aDisplayTransform;
pNewUnit->aInvDisplayTransform.Invert();
// SnapRects der beteiligten Objekte invalidieren, um eine
// Neuberechnung beim Setzen der Marker zu erzwingen
p3DObj->SetRectsDirty();
if(bMoveFull)
{
// Timings merken
pNewUnit->nOrigQuality = p3DObj->GetScene()->GetDisplayQuality();
}
else
{
// Drahtgitterdarstellung fuer Parent-Koodinaten erzeugen
pNewUnit->aWireframePoly.SetPointCount(0);
p3DObj->CreateWireframe(pNewUnit->aWireframePoly, NULL /*BFS01, eDragDetail*/);
2000-09-18 16:07:07 +00:00
pNewUnit->aWireframePoly.Transform(pNewUnit->aTransform);
}
// FullBound ermitteln
aFullBound.Union(p3DObj->GetSnapRect());
// Unit einfuegen
aGrp.Insert((const E3dDragMethodUnit*&)pNewUnit, aGrp.Count());
}
}
// Link auf den Timer setzen
aCallbackTimer.SetTimeoutHdl( LINK( this, E3dDragMethod, TimerInterruptHdl) );
}
/*************************************************************************
|*
\************************************************************************/
IMPL_LINK(E3dDragMethod, TimerInterruptHdl, void*, EMPTYARG)
{
// Alle beteiligten Szenen neu zeichnen
UINT16 nCnt = aGrp.Count();
E3dScene* pScene = NULL;
UINT32 nNewTime(0);
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
if(aGrp[nOb]->p3DObj->GetScene() != pScene)
{
pScene = aGrp[nOb]->p3DObj->GetScene();
INT32 nOldQual = pScene->GetDisplayQuality();
if(nOldQual != 255)
{
if(nOldQual == 0)
nOldQual = 30;
else if(nOldQual <= 64)
nOldQual = 64;
else
nOldQual = 255;
pScene->SetDisplayQuality((UINT8)nOldQual);
pScene->SetChanged();
pScene->BroadcastObjectChange();
2000-09-18 16:07:07 +00:00
if(nOldQual != 255)
{
Time aLast = pScene->GetLastPaintTime();
if(nOldQual == 30)
nNewTime = aLast.GetTime() * (50 * E3D_WAITTIME_TIL_REDRAW);
else
nNewTime = aLast.GetTime() * (200 * E3D_WAITTIME_TIL_REDRAW);
}
}
}
}
if(nNewTime)
{
// Timer reset
aCallbackTimer.SetTimeout(nNewTime);
aCallbackTimer.Start();
}
return 0L;
}
/*************************************************************************
|*
\************************************************************************/
void E3dDragMethod::TakeComment(XubString& /*rStr*/) const
2000-09-18 16:07:07 +00:00
{
}
/*************************************************************************
|*
|* Erstelle das Drahtgittermodel fuer alle Aktionen
|*
\************************************************************************/
FASTBOOL E3dDragMethod::Beg()
{
if(eConstraint == E3DDRAG_CONSTR_Z)
{
UINT16 nCnt = aGrp.Count();
DragStat().Ref1() = aFullBound.Center();
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
aGrp[nOb]->nStartAngle = GetAngle(DragStat().GetStart() - DragStat().GetRef1());
aGrp[nOb]->nLastAngle = 0;
}
}
else
{
aLastPos = DragStat().GetStart();
}
if(!bMoveFull)
{
Show();
}
return TRUE;
}
/*************************************************************************
|*
|* Schluss
|*
\************************************************************************/
FASTBOOL E3dDragMethod::End(FASTBOOL /*bCopy*/)
2000-09-18 16:07:07 +00:00
{
UINT16 nCnt = aGrp.Count();
if(bMoveFull)
{
// Timer stoppen
aCallbackTimer.Stop();
if(bMovedAtAll)
{
// Original-Qualitaet restaurieren
for(UINT16 nOb=0;nOb<nCnt;nOb++)
aGrp[nOb]->p3DObj->GetScene()->SetDisplayQuality(aGrp[nOb]->nOrigQuality);
}
}
else
{
// WireFrame ausblenden
Hide();
}
// Alle Transformationen anwenden und UnDo's anlegen
if(bMovedAtAll)
{
rView.BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_ROTATE));
UINT16 nOb;
for(nOb=0;nOb<nCnt;nOb++)
{
aGrp[nOb]->p3DObj->SetTransform(aGrp[nOb]->aTransform);
rView.AddUndo(new E3dRotateUndoAction(aGrp[nOb]->p3DObj->GetModel(),
aGrp[nOb]->p3DObj, aGrp[nOb]->aInitTransform,
aGrp[nOb]->aTransform));
}
rView.EndUndo();
// An allen beteiligten Szenen SnapRect neu setzen und
// BoundVolume der Kamera neu bestimmen, da sich die Geometrie
// tatsaechlich geaendert haben kann
E3dScene* pScene = NULL;
for(nOb=0;nOb<nCnt;nOb++)
{
if(aGrp[nOb]->p3DObj->GetScene() != pScene)
{
pScene = aGrp[nOb]->p3DObj->GetScene();
pScene->CorrectSceneDimensions();
}
}
}
return TRUE;
}
/*************************************************************************
|*
|* Abbruch
|*
\************************************************************************/
void E3dDragMethod::Brk()
{
if(bMoveFull)
{
// Timer stoppen
aCallbackTimer.Stop();
if(bMovedAtAll)
{
UINT16 nCnt = aGrp.Count();
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
// Transformation restaurieren
aGrp[nOb]->p3DObj->SetTransform(aGrp[nOb]->aInitTransform);
aGrp[nOb]->p3DObj->GetScene()->FitSnapRectToBoundVol();
// Original-Qualitaet restaurieren
aGrp[nOb]->p3DObj->GetScene()->SetDisplayQuality(aGrp[nOb]->nOrigQuality);
}
}
}
else
{
// WireFrame ausblenden
Hide();
}
}
/*************************************************************************
|*
|* Gemeinsames Mov()
|*
\************************************************************************/
void E3dDragMethod::Mov(const Point& /*rPnt*/)
2000-09-18 16:07:07 +00:00
{
bMovedAtAll = TRUE;
if(bMoveFull)
{
UINT32 nNewTime = 0L;
// Darstellungsqualitaet bestimmen
UINT16 nCnt = aGrp.Count();
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
E3dScene* pScene = aGrp[nOb]->p3DObj->GetScene();
if(pScene)
{
Time aLast = pScene->GetLastPaintTime();
if(aLast.GetTime())
{
INT32 nActQual = pScene->GetDisplayQuality();
// nur weiter ueberlegen, wenn die Qualitaet ueber null liegt
if(nActQual)
{
INT32 nNewQual = nActQual + (E3D_WANTED_TIME.GetTime() - aLast.GetTime());
if(nNewQual < 0L)
nNewQual = 0L;
if(nNewQual > 255L)
nNewQual = 255L;
pScene->SetDisplayQuality((UINT8)nNewQual);
}
}
UINT32 nTime = aLast.GetTime() * (25 * E3D_WAITTIME_TIL_REDRAW);
nNewTime = (nTime > nNewTime) ? nTime : nNewTime;
}
}
// Timer reset
aCallbackTimer.SetTimeout(nNewTime);
aCallbackTimer.Start();
}
}
/*************************************************************************
|*
|* Zeichne das Drahtgittermodel
|*
\************************************************************************/
void E3dDragMethod::DrawXor(XOutputDevice& rXOut, FASTBOOL /*bFull*/) const
2000-09-18 16:07:07 +00:00
{
UINT16 nPVCnt = rView.GetPageViewCount();
XPolygon aLine(2);
UINT16 nCnt = aGrp.Count();
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
B3dCamera& rCameraSet = aGrp[nOb]->p3DObj->GetScene()->GetCameraSet();
for (UINT16 a=0;a<nPVCnt;a++)
{
SdrPageView* pPV = rView.GetPageViewPvNum(a);
if(pPV->HasMarkedObjPageView())
2000-09-18 16:07:07 +00:00
{
rXOut.SetOffset(pPV->GetOffset());
UINT16 nPntCnt = aGrp[nOb]->aWireframePoly.GetPointCount();
if(nPntCnt > 1)
{
for(UINT16 b=0;b < nPntCnt;b += 2)
{
Vector3D aPnt1 = aGrp[nOb]->aDisplayTransform * aGrp[nOb]->aWireframePoly[b];
aPnt1 = rCameraSet.WorldToViewCoor(aPnt1);
aLine[0].X() = (long)(aPnt1.X() + 0.5);
aLine[0].Y() = (long)(aPnt1.Y() + 0.5);
Vector3D aPnt2 = aGrp[nOb]->aDisplayTransform * aGrp[nOb]->aWireframePoly[b+1];
aPnt2 = rCameraSet.WorldToViewCoor(aPnt2);
aLine[1].X() = (long)(aPnt2.X() + 0.5);
aLine[1].Y() = (long)(aPnt2.Y() + 0.5);
rXOut.DrawXPolyLine(aLine);
}
}
}
}
}
}
/*************************************************************************
E3dDragRotate
*************************************************************************/
TYPEINIT1(E3dDragRotate, E3dDragMethod);
E3dDragRotate::E3dDragRotate(SdrDragView &_rView,
2000-09-18 16:07:07 +00:00
const SdrMarkList& rMark,
//BFS01E3dDragDetail eDetail,
2000-09-18 16:07:07 +00:00
E3dDragConstraint eConstr,
BOOL bFull)
: E3dDragMethod(_rView, rMark/*BFS01, eDetail*/, eConstr, bFull)
2000-09-18 16:07:07 +00:00
{
// Zentrum aller selektierten Objekte in Augkoordinaten holen
UINT16 nCnt = aGrp.Count();
E3dScene *pScene = NULL;
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
Vector3D aObjCenter = aGrp[nOb]->p3DObj->GetCenter();
B3dCamera& rCameraSet = aGrp[nOb]->p3DObj->GetScene()->GetCameraSet();
aObjCenter *= aGrp[nOb]->aInitTransform;
aObjCenter *= aGrp[nOb]->aDisplayTransform;
aObjCenter = rCameraSet.WorldToEyeCoor(aObjCenter);
aGlobalCenter += aObjCenter;
if(aGrp[nOb]->p3DObj->ISA(E3dScene))
pScene = (E3dScene*)aGrp[nOb]->p3DObj;
}
// Teilen durch Anzahl
if(nCnt > 1)
aGlobalCenter /= (double)nCnt;
// Gruppe schon gesetzt? Sonst gruppe irgendeines Objektes
// (erstes) holen
if(!pScene && nCnt)
{
if(aGrp[0]->p3DObj)
pScene = aGrp[0]->p3DObj->GetScene();
}
if(pScene)
{
// 2D-Koordinaten des Controls Rotationszentrum holen
Point aRotCenter2D = Ref1();
// In Augkoordinaten transformieren
Vector3D aRotCenter(aRotCenter2D.X(), aRotCenter2D.Y(), 0.0);
aRotCenter = pScene->GetCameraSet().ViewToEyeCoor(aRotCenter);
// X,Y des RotCenter und Tiefe der gemeinsamen Objektmitte aus
// Rotationspunkt im Raum benutzen
aGlobalCenter.X() = aRotCenter.X();
aGlobalCenter.Y() = aRotCenter.Y();
}
}
/*************************************************************************
|*
|* Das Objekt wird bewegt, bestimme die Winkel
|*
\************************************************************************/
void E3dDragRotate::Mov(const Point& rPnt)
{
// call parent
E3dDragMethod::Mov(rPnt);
if(DragStat().CheckMinMoved(rPnt))
{
// Modifier holen
UINT16 nModifier = 0;
if(rView.ISA(E3dView))
{
const MouseEvent& rLastMouse = ((E3dView&)rView).GetMouseEvent();
nModifier = rLastMouse.GetModifier();
}
// Alle Objekte rotieren
UINT16 nCnt = aGrp.Count();
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
// Rotationswinkel bestimmen
double fWAngle, fHAngle;
if(eConstraint == E3DDRAG_CONSTR_Z)
{
fWAngle = NormAngle360(GetAngle(rPnt - DragStat().GetRef1()) -
aGrp[nOb]->nStartAngle) - aGrp[nOb]->nLastAngle;
aGrp[nOb]->nLastAngle = (long)fWAngle + aGrp[nOb]->nLastAngle;
fWAngle /= 100.0;
fHAngle = 0.0;
}
else
{
fWAngle = 90.0 * (double)(rPnt.X() - aLastPos.X())
/ (double)aFullBound.GetWidth();
fHAngle = 90.0 * (double)(rPnt.Y() - aLastPos.Y())
/ (double)aFullBound.GetHeight();
}
long nSnap = 0;
if(!rView.IsRotateAllowed(FALSE))
nSnap = 90;
if(nSnap != 0)
{
fWAngle = (double)(((long) fWAngle + nSnap/2) / nSnap * nSnap);
fHAngle = (double)(((long) fHAngle + nSnap/2) / nSnap * nSnap);
}
// nach radiant
fWAngle *= F_PI180;
fHAngle *= F_PI180;
// Transformation bestimmen
Matrix4D aRotMat;
if(eConstraint & E3DDRAG_CONSTR_Y)
{
if(nModifier & KEY_MOD2)
aRotMat.RotateZ(fWAngle);
else
aRotMat.RotateY(fWAngle);
}
else if(eConstraint & E3DDRAG_CONSTR_Z)
{
if(nModifier & KEY_MOD2)
aRotMat.RotateY(fWAngle);
else
aRotMat.RotateZ(fWAngle);
}
if(eConstraint & E3DDRAG_CONSTR_X)
{
aRotMat.RotateX(fHAngle);
}
// Transformation in Eye-Koordinaten, dort rotieren
// und zurueck
B3dCamera& rCameraSet = aGrp[nOb]->p3DObj->GetScene()->GetCameraSet();
Matrix4D aTransMat = aGrp[nOb]->aDisplayTransform;
aTransMat *= rCameraSet.GetOrientation();
aTransMat.Translate(-aGlobalCenter);
aTransMat *= aRotMat;
aTransMat.Translate(aGlobalCenter);
aTransMat *= rCameraSet.GetInvOrientation();
aTransMat *= aGrp[nOb]->aInvDisplayTransform;
// ...und anwenden
aGrp[nOb]->aTransform *= aTransMat;
if(bMoveFull)
{
aGrp[nOb]->p3DObj->NbcSetTransform(aGrp[nOb]->aTransform);
aGrp[nOb]->p3DObj->GetScene()->FitSnapRectToBoundVol();
}
else
{
Hide();
aGrp[nOb]->aWireframePoly.Transform(aTransMat);
Show();
}
}
aLastPos = rPnt;
DragStat().NextMove(rPnt);
}
}
/*************************************************************************
|*
\************************************************************************/
Pointer E3dDragRotate::GetPointer() const
{
return Pointer(POINTER_ROTATE);
}
/*************************************************************************
|*
|* E3dDragMove
|* Diese DragMethod wird nur bei Translationen innerhalb von 3D-Scenen
|* benoetigt. Wird eine 3D-Scene selbst verschoben, so wird diese DragMethod
|* nicht verwendet.
|*
\************************************************************************/
TYPEINIT1(E3dDragMove, E3dDragMethod);
E3dDragMove::E3dDragMove(SdrDragView &_rView,
2000-09-18 16:07:07 +00:00
const SdrMarkList& rMark,
//BFS01E3dDragDetail eDetail,
2000-09-18 16:07:07 +00:00
SdrHdlKind eDrgHdl,
E3dDragConstraint eConstr,
BOOL bFull)
: E3dDragMethod(_rView, rMark, /*BFS01eDetail,*/ eConstr, bFull),
2000-09-18 16:07:07 +00:00
eWhatDragHdl(eDrgHdl)
{
switch(eWhatDragHdl)
{
case HDL_LEFT:
aScaleFixPos = aFullBound.RightCenter();
break;
case HDL_RIGHT:
aScaleFixPos = aFullBound.LeftCenter();
break;
case HDL_UPPER:
aScaleFixPos = aFullBound.BottomCenter();
break;
case HDL_LOWER:
aScaleFixPos = aFullBound.TopCenter();
break;
case HDL_UPLFT:
aScaleFixPos = aFullBound.BottomRight();
break;
case HDL_UPRGT:
aScaleFixPos = aFullBound.BottomLeft();
break;
case HDL_LWLFT:
aScaleFixPos = aFullBound.TopRight();
break;
case HDL_LWRGT:
aScaleFixPos = aFullBound.TopLeft();
break;
default:
// Bewegen des Objektes, HDL_MOVE
break;
}
// Override wenn IsResizeAtCenter()
if(rView.IsResizeAtCenter())
{
eWhatDragHdl = HDL_USER;
aScaleFixPos = aFullBound.Center();
}
}
/*************************************************************************
|*
|* Das Objekt wird bewegt, bestimme die Translation
|*
\************************************************************************/
void E3dDragMove::Mov(const Point& rPnt)
{
// call parent
E3dDragMethod::Mov(rPnt);
if(DragStat().CheckMinMoved(rPnt))
{
if(eWhatDragHdl == HDL_MOVE)
{
// Translation
// Bewegungsvektor bestimmen
Vector3D aGlobalMoveHead((double)(rPnt.X() - aLastPos.X()),
(double)(rPnt.Y() - aLastPos.Y()), 32768.0);
Vector3D aGlobalMoveTail(0.0, 0.0, 32768.0);
UINT16 nCnt = aGrp.Count();
// Modifier holen
UINT16 nModifier = 0;
if(rView.ISA(E3dView))
{
const MouseEvent& rLastMouse = ((E3dView&)rView).GetMouseEvent();
nModifier = rLastMouse.GetModifier();
}
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
B3dCamera& rCameraSet = aGrp[nOb]->p3DObj->GetScene()->GetCameraSet();
// Bewegungsvektor von View-Koordinaten nach Aug-Koordinaten
Vector3D aMoveHead = rCameraSet.ViewToEyeCoor(aGlobalMoveHead);
Vector3D aMoveTail = rCameraSet.ViewToEyeCoor(aGlobalMoveTail);
// Eventuell Bewegung von XY-Ebene auf XZ-Ebene umschalten
if(nModifier & KEY_MOD2)
{
double fZwi = aMoveHead.Y();
aMoveHead.Y() = aMoveHead.Z();
aMoveHead.Z() = fZwi;
fZwi = aMoveTail.Y();
aMoveTail.Y() = aMoveTail.Z();
aMoveTail.Z() = fZwi;
}
// Bewegungsvektor von Aug-Koordinaten nach Parent-Koordinaten
aMoveHead = rCameraSet.EyeToWorldCoor(aMoveHead);
aMoveHead *= aGrp[nOb]->aInvDisplayTransform;
aMoveTail = rCameraSet.EyeToWorldCoor(aMoveTail);
aMoveTail *= aGrp[nOb]->aInvDisplayTransform;
// Transformation bestimmen
Matrix4D aTransMat;
aTransMat.Translate(aMoveHead - aMoveTail);
// ...und anwenden
aGrp[nOb]->aTransform *= aTransMat;
if(bMoveFull)
{
aGrp[nOb]->p3DObj->NbcSetTransform(aGrp[nOb]->aTransform);
aGrp[nOb]->p3DObj->GetScene()->FitSnapRectToBoundVol();
}
else
{
Hide();
aGrp[nOb]->aWireframePoly.Transform(aTransMat);
Show();
}
}
}
else
{
// Skalierung
// Skalierungsvektor bestimmen
Point aStartPos = DragStat().GetStart();
Vector3D aGlobalScaleStart((double)(aStartPos.X()), (double)(aStartPos.Y()), 32768.0);
Vector3D aGlobalScaleNext((double)(rPnt.X()), (double)(rPnt.Y()), 32768.0);
Vector3D aGlobalScaleFixPos((double)(aScaleFixPos.X()), (double)(aScaleFixPos.Y()), 32768.0);
UINT16 nCnt = aGrp.Count();
for(UINT16 nOb=0;nOb<nCnt;nOb++)
{
B3dCamera& rCameraSet = aGrp[nOb]->p3DObj->GetScene()->GetCameraSet();
Vector3D aObjectCenter = aGrp[nOb]->p3DObj->GetCenter();
aGlobalScaleStart.Z() = aObjectCenter.Z();
aGlobalScaleNext.Z() = aObjectCenter.Z();
aGlobalScaleFixPos.Z() = aObjectCenter.Z();
// Skalierungsvektor von View-Koordinaten nach Aug-Koordinaten
Vector3D aScStart = rCameraSet.ViewToEyeCoor(aGlobalScaleStart);
Vector3D aScNext = rCameraSet.ViewToEyeCoor(aGlobalScaleNext);
Vector3D aScFixPos = rCameraSet.ViewToEyeCoor(aGlobalScaleFixPos);
// Einschraenkungen?
switch(eWhatDragHdl)
{
case HDL_LEFT:
case HDL_RIGHT:
// Einschraenken auf X -> Y gleichsetzen
aScNext.Y() = aScFixPos.Y();
break;
case HDL_UPPER:
case HDL_LOWER:
// Einschraenken auf Y -> X gleichsetzen
aScNext.X() = aScFixPos.X();
break;
default:
break;
2000-09-18 16:07:07 +00:00
}
// ScaleVector in Augkoordinaten bestimmen
Vector3D aScaleVec = aScStart - aScFixPos;
aScaleVec.Z() = 1.0;
if(aScaleVec.X() != 0.0)
aScaleVec.X() = (aScNext.X() - aScFixPos.X()) / aScaleVec.X();
else
aScaleVec.X() = 1.0;
if(aScaleVec.Y() != 0.0)
aScaleVec.Y() = (aScNext.Y() - aScFixPos.Y()) / aScaleVec.Y();
else
aScaleVec.Y() = 1.0;
// Mit SHIFT-Taste?
if(rView.IsOrtho())
{
if(fabs(aScaleVec.X()) > fabs(aScaleVec.Y()))
{
// X ist am groessten
aScaleVec.Y() = aScaleVec.X();
}
else
{
// Y ist am groessten
aScaleVec.X() = aScaleVec.Y();
}
}
// Transformation bestimmen
Matrix4D aNewTrans = aGrp[nOb]->aInitTransform;
aNewTrans *= aGrp[nOb]->aDisplayTransform;
aNewTrans *= rCameraSet.GetOrientation();
aNewTrans.Translate(-aScFixPos);
aNewTrans.Scale(aScaleVec);
aNewTrans.Translate(aScFixPos);
aNewTrans *= rCameraSet.GetInvOrientation();
aNewTrans *= aGrp[nOb]->aInvDisplayTransform;
// ...und anwenden
aGrp[nOb]->aTransform = aNewTrans;
if(bMoveFull)
{
aGrp[nOb]->p3DObj->NbcSetTransform(aGrp[nOb]->aTransform);
aGrp[nOb]->p3DObj->GetScene()->FitSnapRectToBoundVol();
}
else
{
Hide();
aGrp[nOb]->aWireframePoly.SetPointCount(0);
aGrp[nOb]->p3DObj->CreateWireframe(aGrp[nOb]->aWireframePoly, NULL/*BFS01, eDragDetail*/);
2000-09-18 16:07:07 +00:00
aGrp[nOb]->aWireframePoly.Transform(aGrp[nOb]->aTransform);
Show();
}
}
}
aLastPos = rPnt;
DragStat().NextMove(rPnt);
}
}
/*************************************************************************
|*
\************************************************************************/
Pointer E3dDragMove::GetPointer() const
{
return Pointer(POINTER_MOVE);
}