/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svx.hxx" #include "svx/svdstr.hrc" #include "svx/svdglob.hxx" #include #include #include #include #include "svx/svditer.hxx" #include "svx/globl3d.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "svdoimp.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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