diff options
Diffstat (limited to 'svx/source/engine3d/obj3d.cxx')
-rw-r--r-- | svx/source/engine3d/obj3d.cxx | 1280 |
1 files changed, 1280 insertions, 0 deletions
diff --git a/svx/source/engine3d/obj3d.cxx b/svx/source/engine3d/obj3d.cxx new file mode 100644 index 000000000000..64f43790513d --- /dev/null +++ b/svx/source/engine3d/obj3d.cxx @@ -0,0 +1,1280 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" + +#include "svx/svdstr.hrc" +#include "svx/svdglob.hxx" +#include <svx/svdview.hxx> +#include <svx/svdattr.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdmodel.hxx> +#include "svx/svditer.hxx" +#include "svx/globl3d.hxx" +#include <svx/camera3d.hxx> +#include <svx/scene3d.hxx> +#include <svx/polysc3d.hxx> +#include <svx/cube3d.hxx> +#include <svx/lathe3d.hxx> +#include <svx/sphere3d.hxx> +#include <svx/extrud3d.hxx> +#include <svx/obj3d.hxx> +#include <svx/xtable.hxx> +#include <svx/xflclit.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <svx/xlnclit.hxx> +#include <svl/metitem.hxx> +#include <svx/xtable.hxx> +#include <svx/xfillit.hxx> +#include <svx/xlnwtit.hxx> +#include <vcl/virdev.hxx> +#include <tools/poly.hxx> +#include <tools/b3dtrans.hxx> +#include <svx/svxids.hrc> +#include <editeng/colritem.hxx> +#include <svx/e3ditem.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xfltrit.hxx> +#include <svx/svdpagv.hxx> +#include <vcl/gradient.hxx> +#include <vcl/metaact.hxx> +#include <svx/svx3ditems.hxx> +#include <svl/whiter.hxx> +#include <svtools/colorcfg.hxx> +#include <editeng/eeitem.hxx> +#include <svx/xgrscit.hxx> +#include "svdoimp.hxx" +#include <svx/sdr/properties/e3dproperties.hxx> +#include <svx/sdr/properties/e3dcompoundproperties.hxx> +#include <basegfx/polygon/b3dpolypolygontools.hxx> +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/vector/b3dvector.hxx> +#include <svx/xlndsit.hxx> +#include <basegfx/matrix/b3dhommatrix.hxx> +#include <basegfx/polygon/b3dpolygon.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <basegfx/polygon/b3dpolygontools.hxx> +#include <svx/helperhittest3d.hxx> +#include <svx/sdr/contact/viewcontactofe3d.hxx> +#include <drawinglayer/geometry/viewinformation3d.hxx> +#include <com/sun/star/uno/Sequence.h> +#include <svx/sdr/contact/viewcontactofe3dscene.hxx> +#include <basegfx/polygon/b3dpolypolygontools.hxx> +#include <svx/e3dsceneupdater.hxx> + +#define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue() + +////////////////////////////////////////////////////////////////////////////// + +using namespace com::sun::star; + +/************************************************************************* +|* +|* Liste fuer 3D-Objekte +|* +\************************************************************************/ + +TYPEINIT1(E3dObjList, SdrObjList); + +E3dObjList::E3dObjList(SdrModel* pNewModel, SdrPage* pNewPage, E3dObjList* pNewUpList) +: SdrObjList(pNewModel, pNewPage, pNewUpList) +{ +} + +E3dObjList::E3dObjList(const E3dObjList& rSrcList) +: SdrObjList(rSrcList) +{ +} + +E3dObjList::~E3dObjList() +{ +} + +void E3dObjList::NbcInsertObject(SdrObject* pObj, sal_uIntPtr nPos, const SdrInsertReason* pReason) +{ + // Owner holen + DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "AW: Einfuegen 3DObject in Parent != 3DObject"); + + // Ist es ueberhaupt ein 3D-Objekt? + if(pObj && pObj->ISA(E3dObject)) + { + // Normales 3D Objekt, einfuegen mittels + // call parent + SdrObjList::NbcInsertObject(pObj, nPos, pReason); + } + else + { + // Kein 3D Objekt, fuege in Seite statt in Szene ein... + GetOwnerObj()->GetPage()->InsertObject(pObj, nPos); + } +} + +void E3dObjList::InsertObject(SdrObject* pObj, sal_uIntPtr nPos, const SdrInsertReason* pReason) +{ + OSL_ENSURE(GetOwnerObj()->ISA(E3dObject), "Insert 3DObject in non-3D Parent"); + //E3DModifySceneSnapRectUpdater aUpdater(GetOwnerObj()); + + // call parent + SdrObjList::InsertObject(pObj, nPos, pReason); + + E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene(); + if(pScene) + { + pScene->Cleanup3DDepthMapper(); + } +} + +SdrObject* E3dObjList::NbcRemoveObject(sal_uIntPtr nObjNum) +{ + DBG_ASSERT(GetOwnerObj()->ISA(E3dObject), "AW: Entfernen 3DObject aus Parent != 3DObject"); + //E3DModifySceneSnapRectUpdater aUpdater(GetOwnerObj()); + + // call parent + SdrObject* pRetval = SdrObjList::NbcRemoveObject(nObjNum); + + E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene(); + if(pScene) + { + pScene->Cleanup3DDepthMapper(); + } + + return pRetval; +} + +SdrObject* E3dObjList::RemoveObject(sal_uIntPtr nObjNum) +{ + OSL_ENSURE(GetOwnerObj()->ISA(E3dObject), "3DObject is removed from non-3D Parent"); + //E3DModifySceneSnapRectUpdater aUpdater(GetOwnerObj()); + + // call parent + SdrObject* pRetval = SdrObjList::RemoveObject(nObjNum); + + E3dScene* pScene = ((E3dObject*)GetOwnerObj())->GetScene(); + if(pScene) + { + pScene->Cleanup3DDepthMapper(); + } + + return pRetval; +} + +/************************************************************************* +|* +|* Konstruktor +|* +\************************************************************************/ + +////////////////////////////////////////////////////////////////////////////// + +sdr::properties::BaseProperties* E3dObject::CreateObjectSpecificProperties() +{ + return new sdr::properties::E3dProperties(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(E3dObject, SdrAttrObj); + +E3dObject::E3dObject() +: maSubList(), + maLocalBoundVol(), + maTransformation(), + maFullTransform(), + mbTfHasChanged(true), + mbIsSelected(false) +{ + bIs3DObj = true; + maSubList.SetOwnerObj(this); + maSubList.SetListKind(SDROBJLIST_GROUPOBJ); + bClosedObj = true; +} + +/************************************************************************* +|* +|* Destruktor +|* +\************************************************************************/ + +E3dObject::~E3dObject() +{ +} + +/************************************************************************* +|* +|* Selektions-Flag setzen +|* +\************************************************************************/ + +void E3dObject::SetSelected(bool bNew) +{ + if((bool)mbIsSelected != bNew) + { + mbIsSelected = bNew; + } + + for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) + { + E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); + + if(pCandidate) + { + pCandidate->SetSelected(bNew); + } + } +} + +/************************************************************************* +|* +|* Aufbrechen, default-Implementierungen +|* +\************************************************************************/ + +sal_Bool E3dObject::IsBreakObjPossible() +{ + return sal_False; +} + +SdrAttrObj* E3dObject::GetBreakObj() +{ + return 0L; +} + +/************************************************************************* +|* +|* SetRectsDirty muss ueber die lokale SdrSubList gehen +|* +\************************************************************************/ + +void E3dObject::SetRectsDirty(sal_Bool bNotMyself) +{ + // call parent + SdrAttrObj::SetRectsDirty(bNotMyself); + + for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) + { + E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); + + if(pCandidate) + { + pCandidate->SetRectsDirty(bNotMyself); + } + } +} + +/************************************************************************* +|* +|* Inventor zurueckgeben +|* +\************************************************************************/ + +sal_uInt32 E3dObject::GetObjInventor() const +{ + return E3dInventor; +} + +/************************************************************************* +|* +|* Identifier zurueckgeben +|* +\************************************************************************/ + +sal_uInt16 E3dObject::GetObjIdentifier() const +{ + return E3D_OBJECT_ID; +} + +/************************************************************************* +|* +|* Faehigkeiten des Objektes feststellen +|* +\************************************************************************/ + +void E3dObject::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const +{ + rInfo.bResizeFreeAllowed = sal_True; + rInfo.bResizePropAllowed = sal_True; + rInfo.bRotateFreeAllowed = sal_True; + rInfo.bRotate90Allowed = sal_True; + rInfo.bMirrorFreeAllowed = sal_False; + rInfo.bMirror45Allowed = sal_False; + rInfo.bMirror90Allowed = sal_False; + rInfo.bShearAllowed = sal_False; + rInfo.bEdgeRadiusAllowed = sal_False; + rInfo.bCanConvToPath = sal_False; + + // no transparence for 3d objects + rInfo.bTransparenceAllowed = sal_False; + + // gradient depends on fillstyle + // BM *** check if SetItem is NULL *** + XFillStyle eFillStyle = ((XFillStyleItem&)(GetMergedItem(XATTR_FILLSTYLE))).GetValue(); + rInfo.bGradientAllowed = (eFillStyle == XFILL_GRADIENT); + + // Umwandeln von 3D-Koerpern in Gruppe von Polygonen: + // + // Erst mal nicht moeglich, da die Erzeugung einer Gruppe von + // 2D-Polygonen notwendig waere, die tiefensortiert werden muessten, + // also bei Durchdringugnen auch gegeneinander geschnitten werden + // muessten. Auch die Texturkoorinaten waeren ein ungeloestes + // Problem. + rInfo.bCanConvToPoly = sal_False; + rInfo.bCanConvToContour = sal_False; + rInfo.bCanConvToPathLineToArea = sal_False; + rInfo.bCanConvToPolyLineToArea = sal_False; +} + +/************************************************************************* +|* +|* Layer setzen +|* +\************************************************************************/ + +void E3dObject::NbcSetLayer(SdrLayerID nLayer) +{ + SdrAttrObj::NbcSetLayer(nLayer); + + for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) + { + E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); + + if(pCandidate) + { + pCandidate->NbcSetLayer(nLayer); + } + } +} + +/************************************************************************* +|* +|* ObjList auch an SubList setzen +|* +\************************************************************************/ + +void E3dObject::SetObjList(SdrObjList* pNewObjList) +{ + SdrObject::SetObjList(pNewObjList); + maSubList.SetUpList(pNewObjList); +} + +/************************************************************************* +|* +|* Layer setzen +|* +\************************************************************************/ + +void E3dObject::SetPage(SdrPage* pNewPage) +{ + SdrAttrObj::SetPage(pNewPage); + maSubList.SetPage(pNewPage); +} + +/************************************************************************* +|* +|* Layer setzen +|* +\************************************************************************/ + +void E3dObject::SetModel(SdrModel* pNewModel) +{ + SdrAttrObj::SetModel(pNewModel); + maSubList.SetModel(pNewModel); +} + +/************************************************************************* +|* +|* resize object, used from old 2d interfaces, e.g. in Move/Scale dialog +|* (F4) +|* +\************************************************************************/ +void E3dObject::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +{ + // Bewegung in X,Y im Augkoordinatensystem + E3dScene* pScene = GetScene(); + + if(pScene) + { + // transform pos from 2D world to 3D eye + const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact()); + const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D()); + basegfx::B2DPoint aScaleCenter2D((double)rRef.X(), (double)rRef.Y()); + basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation()); + + aInverseSceneTransform.invert(); + aScaleCenter2D = aInverseSceneTransform * aScaleCenter2D; + + basegfx::B3DPoint aScaleCenter3D(aScaleCenter2D.getX(), aScaleCenter2D.getY(), 0.5); + basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection()); + + aInverseViewToEye.invert(); + aScaleCenter3D = aInverseViewToEye * aScaleCenter3D; + + // scale-faktoren holen + double fScaleX(xFact); + double fScaleY(yFact); + + // build transform + basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation()); + aInverseOrientation.invert(); + basegfx::B3DHomMatrix mFullTransform(GetFullTransform()); + basegfx::B3DHomMatrix mTrans(mFullTransform); + + mTrans *= aViewInfo3D.getOrientation(); + mTrans.translate(-aScaleCenter3D.getX(), -aScaleCenter3D.getY(), -aScaleCenter3D.getZ()); + mTrans.scale(fScaleX, fScaleY, 1.0); + mTrans.translate(aScaleCenter3D.getX(), aScaleCenter3D.getY(), aScaleCenter3D.getZ()); + mTrans *= aInverseOrientation; + mFullTransform.invert(); + mTrans *= mFullTransform; + + // anwenden + basegfx::B3DHomMatrix mObjTrans(GetTransform()); + mObjTrans *= mTrans; + + E3DModifySceneSnapRectUpdater aUpdater(this); + SetTransform(mObjTrans); + } +} + +/************************************************************************* +|* +|* Objekt verschieben in 2D, wird bei Cursortasten benoetigt +|* +\************************************************************************/ +void E3dObject::NbcMove(const Size& rSize) +{ + // Bewegung in X,Y im Augkoordinatensystem + E3dScene* pScene = GetScene(); + + if(pScene) + { + // Abmessungen der Szene in 3D und 2D als Vergleich + Rectangle aRect = pScene->GetSnapRect(); + + // Transformation Weltkoordinaten bis eine VOR Objektkoordinaten holen + basegfx::B3DHomMatrix mInvDispTransform; + if(GetParentObj()) + { + mInvDispTransform = GetParentObj()->GetFullTransform(); + mInvDispTransform.invert(); + } + + // BoundVolume from 3d world to 3d eye + const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact()); + const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D()); + basegfx::B3DRange aEyeVol(pScene->GetBoundVolume()); + aEyeVol.transform(aViewInfo3D.getOrientation()); + + // build relative movement vector in eye coordinates + basegfx::B3DPoint aMove( + (double)rSize.Width() * aEyeVol.getWidth() / (double)aRect.GetWidth(), + (double)-rSize.Height() * aEyeVol.getHeight() / (double)aRect.GetHeight(), + 0.0); + basegfx::B3DPoint aPos(0.0, 0.0, 0.0); + + // movement vektor to local coordinates of objects' parent + basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation()); + aInverseOrientation.invert(); + basegfx::B3DHomMatrix aCompleteTrans(mInvDispTransform * aInverseOrientation); + + aMove = aCompleteTrans * aMove; + aPos = aCompleteTrans * aPos; + + // build transformation and apply + basegfx::B3DHomMatrix aTranslate; + aTranslate.translate(aMove.getX() - aPos.getX(), aMove.getY() - aPos.getY(), aMove.getZ() - aPos.getZ()); + + E3DModifySceneSnapRectUpdater aUpdater(pScene); + SetTransform(aTranslate * GetTransform()); + } +} + +/************************************************************************* +|* +|* liefere die Sublist, aber nur dann, wenn darin Objekte enthalten sind ! +|* +\************************************************************************/ + +SdrObjList* E3dObject::GetSubList() const +{ + return &(const_cast< E3dObjList& >(maSubList)); +} + +/************************************************************************* +|* +|* SnapRect berechnen +|* +\************************************************************************/ + +void E3dObject::RecalcSnapRect() +{ + maSnapRect = Rectangle(); + + for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) + { + E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); + + if(pCandidate) + { + maSnapRect.Union(pCandidate->GetSnapRect()); + } + } +} + +/************************************************************************* +|* +|* Einfuegen eines 3D-Objekts an den Parent weitermelden, damit dieser +|* ggf. eine Sonderbehandlung fuer spezielle Objekte durchfuehren kann +|* (z.B. Light/Label in E3dScene) +|* +\************************************************************************/ + +void E3dObject::NewObjectInserted(const E3dObject* p3DObj) +{ + if(GetParentObj()) + GetParentObj()->NewObjectInserted(p3DObj); +} + +/************************************************************************* +|* +|* Parent ueber Aenderung der Struktur (z.B. durch Transformation) +|* informieren; dabei wird das Objekt, in welchem die Aenderung +|* aufgetreten ist, uebergeben +|* +\************************************************************************/ + +void E3dObject::StructureChanged() +{ + if ( GetParentObj() ) + { + GetParentObj()->InvalidateBoundVolume(); + GetParentObj()->StructureChanged(); + } +} + +/************************************************************************* +|* +|* 3D-Objekt einfuegen +|* +\************************************************************************/ + +void E3dObject::Insert3DObj(E3dObject* p3DObj) +{ + DBG_ASSERT(p3DObj, "Insert3DObj mit NULL-Zeiger!"); + SdrPage* pPg = pPage; + maSubList.InsertObject(p3DObj); + pPage = pPg; + InvalidateBoundVolume(); + NewObjectInserted(p3DObj); + StructureChanged(); +} + +void E3dObject::Remove3DObj(E3dObject* p3DObj) +{ + DBG_ASSERT(p3DObj, "Remove3DObj mit NULL-Zeiger!"); + + if(p3DObj->GetParentObj() == this) + { + SdrPage* pPg = pPage; + maSubList.RemoveObject(p3DObj->GetOrdNum()); + pPage = pPg; + + InvalidateBoundVolume(); + StructureChanged(); + } +} + +/************************************************************************* +|* +|* Parent holen +|* +\************************************************************************/ + +E3dObject* E3dObject::GetParentObj() const +{ + E3dObject* pRetval = NULL; + + if(GetObjList() + && GetObjList()->GetOwnerObj() + && GetObjList()->GetOwnerObj()->ISA(E3dObject)) + pRetval = ((E3dObject*)GetObjList()->GetOwnerObj()); + return pRetval; +} + +/************************************************************************* +|* +|* Uebergeordnetes Szenenobjekt bestimmen +|* +\************************************************************************/ + +E3dScene* E3dObject::GetScene() const +{ + if(GetParentObj()) + return GetParentObj()->GetScene(); + return NULL; +} + +/************************************************************************* +|* +|* umschliessendes Volumen inklusive aller Kindobjekte berechnen +|* +\************************************************************************/ + +basegfx::B3DRange E3dObject::RecalcBoundVolume() const +{ + basegfx::B3DRange aRetval; + const sal_uInt32 nObjCnt(maSubList.GetObjCount()); + + if(nObjCnt) + { + for(sal_uInt32 a(0); a < nObjCnt; a++) + { + const E3dObject* p3DObject = dynamic_cast< const E3dObject* >(maSubList.GetObj(a)); + + if(p3DObject) + { + basegfx::B3DRange aLocalRange(p3DObject->GetBoundVolume()); + aLocalRange.transform(p3DObject->GetTransform()); + aRetval.expand(aLocalRange); + } + } + } + else + { + // single 3D object + const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact()); + + if(pVCOfE3D) + { + // BoundVolume is without 3D object transformation, use correct sequence + const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getVIP3DSWithoutObjectTransform()); + + if(xLocalSequence.hasElements()) + { + const uno::Sequence< beans::PropertyValue > aEmptyParameters; + const drawinglayer::geometry::ViewInformation3D aLocalViewInformation3D(aEmptyParameters); + + aRetval = drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence( + xLocalSequence, aLocalViewInformation3D); + } + } + } + + return aRetval; +} + +/************************************************************************* +|* +|* umschliessendes Volumen zurueckgeben und ggf. neu berechnen +|* +\************************************************************************/ + +const basegfx::B3DRange& E3dObject::GetBoundVolume() const +{ + if(maLocalBoundVol.isEmpty()) + { + const_cast< E3dObject* >(this)->maLocalBoundVol = RecalcBoundVolume(); + } + + return maLocalBoundVol; +} + +void E3dObject::InvalidateBoundVolume() +{ + maLocalBoundVol.reset(); +} + +/************************************************************************* +|* +|* Aederung des BoundVolumes an alle Kindobjekte weitergeben +|* +\************************************************************************/ + +void E3dObject::SetBoundVolInvalid() +{ + InvalidateBoundVolume(); + + for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) + { + E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); + + if(pCandidate) + { + pCandidate->SetBoundVolInvalid(); + } + } +} + +/************************************************************************* +|* +|* Aederung der Transformation an alle Kindobjekte weitergeben +|* +\************************************************************************/ + +void E3dObject::SetTransformChanged() +{ + InvalidateBoundVolume(); + mbTfHasChanged = true; + + for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) + { + E3dObject* pCandidate = dynamic_cast< E3dObject* >(maSubList.GetObj(a)); + + if(pCandidate) + { + pCandidate->SetTransformChanged(); + } + } +} + +/************************************************************************* +|* +|* hierarchische Transformation ueber alle Parents bestimmen, in +|* maFullTransform ablegen und diese zurueckgeben +|* +\************************************************************************/ + +const basegfx::B3DHomMatrix& E3dObject::GetFullTransform() const +{ + if(mbTfHasChanged) + { + basegfx::B3DHomMatrix aNewFullTransformation(maTransformation); + + if ( GetParentObj() ) + { + aNewFullTransformation = GetParentObj()->GetFullTransform() * aNewFullTransformation; + } + + const_cast< E3dObject* >(this)->maFullTransform = aNewFullTransformation; + const_cast< E3dObject* >(this)->mbTfHasChanged = false; + } + + return maFullTransform; +} + +/************************************************************************* +|* +|* Transformationsmatrix abfragen +|* +\************************************************************************/ + +const basegfx::B3DHomMatrix& E3dObject::GetTransform() const +{ + return maTransformation; +} + +/************************************************************************* +|* +|* Transformationsmatrix setzen +|* +\************************************************************************/ + +void E3dObject::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix) +{ + if(maTransformation != rMatrix) + { + maTransformation = rMatrix; + SetTransformChanged(); + StructureChanged(); + } +} + +/************************************************************************* +|* +|* Transformationsmatrix setzen mit Repaint-Broadcast +|* +\************************************************************************/ + +void E3dObject::SetTransform(const basegfx::B3DHomMatrix& rMatrix) +{ + if(rMatrix != maTransformation) + { + // #110094#-14 SendRepaintBroadcast(); + NbcSetTransform(rMatrix); + SetChanged(); + BroadcastObjectChange(); + if (pUserCall != NULL) pUserCall->Changed(*this, SDRUSERCALL_RESIZE, Rectangle()); + } +} + +/************************************************************************* +|* +|* Linien fuer die Wireframe-Darstellung des Objekts dem uebergebenen +|* basegfx::B3DPolygon hinzufuegen +|* +\************************************************************************/ + +basegfx::B3DPolyPolygon E3dObject::CreateWireframe() const +{ + const basegfx::B3DRange aBoundVolume(GetBoundVolume()); + return basegfx::tools::createCubePolyPolygonFromB3DRange(aBoundVolume); +} + +/************************************************************************* +|* +|* Get the name of the object (singular) +|* +\************************************************************************/ + +void E3dObject::TakeObjNameSingul(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNameSingulObj3d); + + String aName( GetName() ); + if(aName.Len()) + { + rName += sal_Unicode(' '); + rName += sal_Unicode('\''); + rName += aName; + rName += sal_Unicode('\''); + } +} + +/************************************************************************* +|* +|* Get the name of the object (plural) +|* +\************************************************************************/ + +void E3dObject::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralObj3d); +} + +/************************************************************************* +|* +|* Zuweisungsoperator +|* +\************************************************************************/ + +void E3dObject::operator=(const SdrObject& rObj) +{ + SdrObject::operator=(rObj); + + const E3dObject& r3DObj = (const E3dObject&) rObj; + if (r3DObj.GetSubList()) + { + maSubList.CopyObjects(*r3DObj.GetSubList()); + } + + // BoundVol kann uebernommen werden, da die Childs auch kopiert werden + maLocalBoundVol = r3DObj.maLocalBoundVol; + maTransformation = r3DObj.maTransformation; + + // Da sich der Parent geaendert haben kann, Gesamttransformation beim + // naechsten Mal auf jeden Fall neu bestimmen + SetTransformChanged(); + + // Selektionsstatus kopieren + mbIsSelected = r3DObj.mbIsSelected; +} + +/************************************************************************* +|* +|* erstelle neues GeoData-Objekt +|* +\************************************************************************/ + +SdrObjGeoData *E3dObject::NewGeoData() const +{ + // Theoretisch duerfen auch nur Szenen ihre GeoDatas erstellen und verwalten !! + // AW: Dies stimmt nicht mehr, diese Stelle ist mit der neuen Engine OK! + return new E3DObjGeoData; +} + +/************************************************************************* +|* +|* uebergebe aktuelle werte an das GeoData-Objekt +|* +\************************************************************************/ + +void E3dObject::SaveGeoData(SdrObjGeoData& rGeo) const +{ + SdrAttrObj::SaveGeoData (rGeo); + + ((E3DObjGeoData &) rGeo).maLocalBoundVol = maLocalBoundVol; + ((E3DObjGeoData &) rGeo).maTransformation = maTransformation; +} + +/************************************************************************* +|* +|* uebernehme werte aus dem GeoData-Objekt +|* +\************************************************************************/ + +void E3dObject::RestGeoData(const SdrObjGeoData& rGeo) +{ + maLocalBoundVol = ((E3DObjGeoData &) rGeo).maLocalBoundVol; + E3DModifySceneSnapRectUpdater aUpdater(this); + NbcSetTransform(((E3DObjGeoData &) rGeo).maTransformation); + SdrAttrObj::RestGeoData (rGeo); +} + +/************************************************************************* +|* +|* Rotation eines 3d-Koerpers +|* +\************************************************************************/ +// 2D-rotation eines 3D-Koerpers, normalerweise macht das die Szene selbst +// Ist aber eine korrekte Implementierung, denn alles was passiert ist eine +// Rotation um die Achse die senkrecht auf dem Bildschirm steht und zwar +// unabhaengig davon, wie die Szene bisher gedreht worden ist. + +void E3dObject::NbcRotate(const Point& rRef, long nWink, double sn, double cs) +{ + // Also derzeit sind die Klebepunkte relativ zum aOutRect der Szene definiert. Vor dem Drehen + // werden die Klebepunkte relativ zur Seite definiert. Sie nehmen an der Drehung der Szene noch nicht Teil + // dafuer gibt es den + SetGlueReallyAbsolute(sal_True); + + // SendRepaintBroadcast(); + double fWinkelInRad = nWink/100 * F_PI180; + + basegfx::B3DHomMatrix aRotateZ; + aRotateZ.rotate(0.0, 0.0, fWinkelInRad); + NbcSetTransform(aRotateZ * GetTransform()); + + SetRectsDirty(); // Veranlasst eine Neuberechnung aller BoundRects + NbcRotateGluePoints(rRef,nWink,sn,cs); // Rotiert die Klebepunkte (die haben noch Koordinaten relativ + // zum Urpsung des Blattes + SetGlueReallyAbsolute(sal_False); // ab jetzt sind sie wieder relativ zum BoundRect (also dem aOutRect definiert) +} + +/*************************************************************************/ + +////////////////////////////////////////////////////////////////////////////// + +sdr::properties::BaseProperties* E3dCompoundObject::CreateObjectSpecificProperties() +{ + return new sdr::properties::E3dCompoundProperties(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(E3dCompoundObject, E3dObject); + +/************************************************************************* +|* +|* Konstruktor +|* +\************************************************************************/ + +E3dCompoundObject::E3dCompoundObject() +: E3dObject(), + aMaterialAmbientColor(), + bCreateNormals(false), + bCreateTexture(false) +{ + // Defaults setzen + E3dDefaultAttributes aDefault; + SetDefaultAttributes(aDefault); +} + +E3dCompoundObject::E3dCompoundObject(E3dDefaultAttributes& rDefault) +: E3dObject(), + aMaterialAmbientColor(), + bCreateNormals(false), + bCreateTexture(false) +{ + // Defaults setzen + SetDefaultAttributes(rDefault); +} + +void E3dCompoundObject::SetDefaultAttributes(E3dDefaultAttributes& rDefault) +{ + // Defaults setzen + aMaterialAmbientColor = rDefault.GetDefaultAmbientColor(); + + bCreateNormals = rDefault.GetDefaultCreateNormals(); + bCreateTexture = rDefault.GetDefaultCreateTexture(); +} + +/************************************************************************* +|* +|* Destruktor +|* +\************************************************************************/ + +E3dCompoundObject::~E3dCompoundObject () +{ +} + +/************************************************************************* +|* +|* Drag-Polygon zurueckgeben +|* +\************************************************************************/ + +basegfx::B2DPolyPolygon E3dCompoundObject::TakeXorPoly() const +{ + basegfx::B2DPolyPolygon aRetval; + const uno::Sequence< beans::PropertyValue > aEmptyParameters; + drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); + E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this); + + if(pRootScene) + { + const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); + const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe()); + aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon, + aViewInfo3D.getObjectToView() * GetTransform()); + aRetval.transform(rVCScene.getObjectTransformation()); + } + + return aRetval; +} + +/************************************************************************* +|* +|* Anzahl der Handles zurueckgeben +|* +\************************************************************************/ + +sal_uInt32 E3dCompoundObject::GetHdlCount() const +{ + // 8 Eckpunkte + 1 E3dVolumeMarker (= Wireframe-Darstellung) + return 9L; +} + +/************************************************************************* +|* +|* Handle-Liste fuellen +|* +\************************************************************************/ + +void E3dCompoundObject::AddToHdlList(SdrHdlList& rHdlList) const +{ + const uno::Sequence< beans::PropertyValue > aEmptyParameters; + drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); + E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this); + + if(pRootScene) + { + const basegfx::B3DRange aBoundVolume(GetBoundVolume()); + + if(!aBoundVolume.isEmpty()) + { + const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); + + for(sal_uInt32 a(0); a < 8; a++) + { + basegfx::B3DPoint aPos3D; + + switch(a) + { + case 0 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break; + case 1 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break; + case 2 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break; + case 3 : aPos3D.setX(aBoundVolume.getMinX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break; + case 4 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMinZ()); break; + case 5 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMinY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break; + case 6 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMinZ()); break; + case 7 : aPos3D.setX(aBoundVolume.getMaxX()); aPos3D.setY(aBoundVolume.getMaxY()); aPos3D.setZ(aBoundVolume.getMaxZ()); break; + } + + // to 3d view coor + aPos3D *= aViewInfo3D.getObjectToView() * GetTransform(); + + // create 2d relative scene + basegfx::B2DPoint aPos2D(aPos3D.getX(), aPos3D.getY()); + + // to 2d world coor + aPos2D *= rVCScene.getObjectTransformation(); + + rHdlList.AddHdl(new SdrHdl(Point(basegfx::fround(aPos2D.getX()), basegfx::fround(aPos2D.getY())), HDL_BWGT)); + } + } + } + + const basegfx::B2DPolyPolygon aPolyPolygon(TakeXorPoly()); + + if(aPolyPolygon.count()) + { + E3dVolumeMarker* pVolMarker = new E3dVolumeMarker(aPolyPolygon); + rHdlList.AddHdl(pVolMarker); + } +} + +/************************************************************************* +|* +|* Identifier zurueckgeben +|* +\************************************************************************/ + +sal_uInt16 E3dCompoundObject::GetObjIdentifier() const +{ + return E3D_COMPOUNDOBJ_ID; +} + +/************************************************************************* +|* +|* SnapRect berechnen +|* +\************************************************************************/ + +void E3dCompoundObject::RecalcSnapRect() +{ + const uno::Sequence< beans::PropertyValue > aEmptyParameters; + drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); + E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this); + maSnapRect = Rectangle(); + + if(pRootScene) + { + // get VC of 3D candidate + const sdr::contact::ViewContactOfE3d* pVCOfE3D = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&GetViewContact()); + + if(pVCOfE3D) + { + // get 3D primitive sequence + const drawinglayer::primitive3d::Primitive3DSequence xLocalSequence(pVCOfE3D->getViewIndependentPrimitive3DSequence()); + + if(xLocalSequence.hasElements()) + { + // get BoundVolume + basegfx::B3DRange aBoundVolume(drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence( + xLocalSequence, aViewInfo3D)); + + // transform bound volume to relative scene coordinates + aBoundVolume.transform(aViewInfo3D.getObjectToView()); + + // build 2d relative scene range + basegfx::B2DRange aSnapRange( + aBoundVolume.getMinX(), aBoundVolume.getMinY(), + aBoundVolume.getMaxX(), aBoundVolume.getMaxY()); + + // transform to 2D world coordiantes + const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); + aSnapRange.transform(rVCScene.getObjectTransformation()); + + // snap to integer + maSnapRect = Rectangle( + sal_Int32(floor(aSnapRange.getMinX())), sal_Int32(floor(aSnapRange.getMinY())), + sal_Int32(ceil(aSnapRange.getMaxX())), sal_Int32(ceil(aSnapRange.getMaxY()))); + } + } + } +} + +/************************************************************************* +|* +|* Copy-Operator +|* +\************************************************************************/ + +void E3dCompoundObject::operator=(const SdrObject& rObj) +{ + // erstmal alle Childs kopieren + E3dObject::operator=(rObj); + + // weitere Parameter kopieren + const E3dCompoundObject& r3DObj = (const E3dCompoundObject&) rObj; + + bCreateNormals = r3DObj.bCreateNormals; + bCreateTexture = r3DObj.bCreateTexture; + aMaterialAmbientColor = r3DObj.aMaterialAmbientColor; +} + +/************************************************************************* +|* +|* Parameter Geometrieerzeugung setzen +|* +\************************************************************************/ + +void E3dCompoundObject::SetCreateNormals(sal_Bool bNew) +{ + if(bCreateNormals != bNew) + { + bCreateNormals = bNew; + ActionChanged(); + } +} + +void E3dCompoundObject::SetCreateTexture(sal_Bool bNew) +{ + if(bCreateTexture != bNew) + { + bCreateTexture = bNew; + ActionChanged(); + } +} + +/************************************************************************* +|* +|* Material des Objektes +|* +\************************************************************************/ + +void E3dCompoundObject::SetMaterialAmbientColor(const Color& rColor) +{ + if(aMaterialAmbientColor != rColor) + { + aMaterialAmbientColor = rColor; + } +} + +/************************************************************************* +|* +|* convert given basegfx::B3DPolyPolygon to screen coor +|* +\************************************************************************/ + +basegfx::B2DPolyPolygon E3dCompoundObject::TransformToScreenCoor(const basegfx::B3DPolyPolygon& rCandidate) +{ + const uno::Sequence< beans::PropertyValue > aEmptyParameters; + drawinglayer::geometry::ViewInformation3D aViewInfo3D(aEmptyParameters); + E3dScene* pRootScene = fillViewInformation3DForCompoundObject(aViewInfo3D, *this); + basegfx::B2DPolyPolygon aRetval; + + if(pRootScene) + { + aRetval = basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(rCandidate, + aViewInfo3D.getObjectToView() * GetTransform()); + const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pRootScene->GetViewContact()); + aRetval.transform(rVCScene.getObjectTransformation()); + } + + return aRetval; +} + +sal_Bool E3dCompoundObject::IsAOrdNumRemapCandidate(E3dScene*& prScene) const +{ + if(GetObjList() + && GetObjList()->GetOwnerObj() + && GetObjList()->GetOwnerObj()->ISA(E3dScene)) + { + prScene = (E3dScene*)GetObjList()->GetOwnerObj(); + return sal_True; + } + + return sal_False; +} + +////////////////////////////////////////////////////////////////////////////// +// eof |