diff options
Diffstat (limited to 'svx/source/engine3d/scene3d.cxx')
-rw-r--r-- | svx/source/engine3d/scene3d.cxx | 871 |
1 files changed, 871 insertions, 0 deletions
diff --git a/svx/source/engine3d/scene3d.cxx b/svx/source/engine3d/scene3d.cxx new file mode 100644 index 000000000000..22ef5777f730 --- /dev/null +++ b/svx/source/engine3d/scene3d.cxx @@ -0,0 +1,871 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: scene3d.cxx,v $ + * $Revision: 1.34.18.1 $ + * + * 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 "svdstr.hrc" +#include "svdglob.hxx" +#include "svditer.hxx" + +#if defined( UNX ) || defined( ICC ) +#include <stdlib.h> +#endif +#include "globl3d.hxx" +#include <svx/svdpage.hxx> +#include <svtools/style.hxx> +#include <svx/scene3d.hxx> +#include <svx/e3dundo.hxx> +#include <svx/svdtrans.hxx> +#include <svx/svxids.hrc> +#include <svx/colritem.hxx> +#include <svx/e3ditem.hxx> +#include <svx/xlntrit.hxx> +#include <svx/xfltrit.hxx> +#include <svx/svx3ditems.hxx> +#include <svtools/whiter.hxx> +#include <svx/xflftrit.hxx> +#include <svx/sdr/properties/e3dsceneproperties.hxx> +#include <svx/sdr/contact/viewcontactofe3dscene.hxx> +#include <svx/svddrag.hxx> +#include <helperminimaldepth3d.hxx> +#include <algorithm> +#include <drawinglayer/geometry/viewinformation3d.hxx> +#include <basegfx/polygon/b2dpolypolygontools.hxx> +#include <svx/e3dsceneupdater.hxx> + +#define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue() + +////////////////////////////////////////////////////////////////////////////// +// #110988# + +class ImpRemap3DDepth +{ + sal_uInt32 mnOrdNum; + double mfMinimalDepth; + + // bitfield + unsigned mbIsScene : 1; + +public: + ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth); + ImpRemap3DDepth(sal_uInt32 nOrdNum); + ~ImpRemap3DDepth(); + + // for ::std::sort + bool operator<(const ImpRemap3DDepth& rComp) const; + + sal_uInt32 GetOrdNum() const { return mnOrdNum; } + sal_Bool IsScene() const { return mbIsScene; } +}; + +ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth) +: mnOrdNum(nOrdNum), + mfMinimalDepth(fMinimalDepth), + mbIsScene(sal_False) +{ +} + +ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum) +: mnOrdNum(nOrdNum), + mbIsScene(sal_True) +{ +} + +ImpRemap3DDepth::~ImpRemap3DDepth() +{ +} + +bool ImpRemap3DDepth::operator<(const ImpRemap3DDepth& rComp) const +{ + if(IsScene()) + { + return sal_False; + } + else + { + if(rComp.IsScene()) + { + return sal_True; + } + else + { + return mfMinimalDepth < rComp.mfMinimalDepth; + } + } +} + +// typedefs for a vector of ImpRemap3DDepths +typedef ::std::vector< ImpRemap3DDepth > ImpRemap3DDepthVector; + +////////////////////////////////////////////////////////////////////////////// +// #110988# + +class Imp3DDepthRemapper +{ + ImpRemap3DDepthVector maVector; + +public: + Imp3DDepthRemapper(E3dScene& rScene); + ~Imp3DDepthRemapper(); + + sal_uInt32 RemapOrdNum(sal_uInt32 nOrdNum) const; +}; + +Imp3DDepthRemapper::Imp3DDepthRemapper(E3dScene& rScene) +{ + // only called when rScene.GetSubList() and nObjCount > 1L + SdrObjList* pList = rScene.GetSubList(); + const sal_uInt32 nObjCount(pList->GetObjCount()); + + for(sal_uInt32 a(0L); a < nObjCount; a++) + { + SdrObject* pCandidate = pList->GetObj(a); + + if(pCandidate) + { + if(pCandidate->ISA(E3dCompoundObject)) + { + // single 3d object, calc depth + const double fMinimalDepth(getMinimalDepthInViewCoordinates(static_cast< const E3dCompoundObject& >(*pCandidate))); + ImpRemap3DDepth aEntry(a, fMinimalDepth); + maVector.push_back(aEntry); + } + else + { + // scene, use standard entry for scene + ImpRemap3DDepth aEntry(a); + maVector.push_back(aEntry); + } + } + } + + // now, we need to sort the maVector by it's members minimal depth. The + // smaller, the nearer to the viewer. + ::std::sort(maVector.begin(), maVector.end()); +} + +Imp3DDepthRemapper::~Imp3DDepthRemapper() +{ +} + +sal_uInt32 Imp3DDepthRemapper::RemapOrdNum(sal_uInt32 nOrdNum) const +{ + if(nOrdNum < maVector.size()) + { + nOrdNum = maVector[(maVector.size() - 1) - nOrdNum].GetOrdNum(); + } + + return nOrdNum; +} + +////////////////////////////////////////////////////////////////////////////// +// BaseProperties section + +sdr::properties::BaseProperties* E3dScene::CreateObjectSpecificProperties() +{ + return new sdr::properties::E3dSceneProperties(*this); +} + +////////////////////////////////////////////////////////////////////////////// +// #110094# DrawContact section + +sdr::contact::ViewContact* E3dScene::CreateObjectSpecificViewContact() +{ + return new sdr::contact::ViewContactOfE3dScene(*this); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TYPEINIT1(E3dScene, E3dObject); + +/************************************************************************* +|* +|* E3dScene-Konstruktor +|* +\************************************************************************/ + +E3dScene::E3dScene() +: E3dObject(), + aCamera(basegfx::B3DPoint(0.0, 0.0, 4.0), basegfx::B3DPoint()), + mp3DDepthRemapper(0L), + bDrawOnlySelected(false) +{ + // Defaults setzen + E3dDefaultAttributes aDefault; + SetDefaultAttributes(aDefault); +} + +E3dScene::E3dScene(E3dDefaultAttributes& rDefault) +: E3dObject(), + aCamera(basegfx::B3DPoint(0.0, 0.0, 4.0), basegfx::B3DPoint()), + mp3DDepthRemapper(0L), + bDrawOnlySelected(false) +{ + // Defaults setzen + SetDefaultAttributes(rDefault); +} + +void E3dScene::SetDefaultAttributes(E3dDefaultAttributes& /*rDefault*/) +{ + // Fuer OS/2 die FP-Exceptions abschalten +#if defined(OS2) +#define SC_FPEXCEPTIONS_ON() _control87( MCW_EM, 0 ) +#define SC_FPEXCEPTIONS_OFF() _control87( MCW_EM, MCW_EM ) + SC_FPEXCEPTIONS_OFF(); +#endif + + // Fuer WIN95/NT die FP-Exceptions abschalten +#if defined(WNT) || defined(WIN) +#define SC_FPEXCEPTIONS_ON() _control87( _MCW_EM, 0 ) +#define SC_FPEXCEPTIONS_OFF() _control87( _MCW_EM, _MCW_EM ) + SC_FPEXCEPTIONS_OFF(); +#endif + + // Defaults setzen + aCamera.SetViewWindow(-2, -2, 4, 4); + aCameraSet.SetDeviceRectangle(-2, 2, -2, 2); + aCamera.SetDeviceWindow(Rectangle(0, 0, 10, 10)); + Rectangle aRect(0, 0, 10, 10); + aCameraSet.SetViewportRectangle(aRect); + + // set defaults for Camera from ItemPool + aCamera.SetProjection(GetPerspective()); + basegfx::B3DPoint aActualPosition(aCamera.GetPosition()); + double fNew = GetDistance(); + + if(fabs(fNew - aActualPosition.getZ()) > 1.0) + { + aCamera.SetPosition( basegfx::B3DPoint( aActualPosition.getX(), aActualPosition.getY(), fNew) ); + } + + fNew = GetFocalLength() / 100.0; + aCamera.SetFocalLength(fNew); +} + +/************************************************************************* +|* +|* Destruktor +|* +\************************************************************************/ + +E3dScene::~E3dScene() +{ + // #110988# + ImpCleanup3DDepthMapper(); +} + +basegfx::B2DPolyPolygon E3dScene::TakeXorPoly() const +{ + const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(GetViewContact()); + const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D()); + const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe()); + + basegfx::B2DPolyPolygon aRetval(basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon, + aViewInfo3D.getObjectToView())); + aRetval.transform(rVCScene.getObjectTransformation()); + + return aRetval; +} + +// #110988# +void E3dScene::ImpCleanup3DDepthMapper() +{ + if(mp3DDepthRemapper) + { + delete mp3DDepthRemapper; + mp3DDepthRemapper = 0L; + } +} + +// #110988# +sal_uInt32 E3dScene::RemapOrdNum(sal_uInt32 nNewOrdNum) const +{ + if(!mp3DDepthRemapper) + { + const sal_uInt32 nObjCount(GetSubList() ? GetSubList()->GetObjCount() : 0L); + + if(nObjCount > 1L) + { + ((E3dScene*)this)->mp3DDepthRemapper = new Imp3DDepthRemapper((E3dScene&)(*this)); + } + } + + if(mp3DDepthRemapper) + { + return mp3DDepthRemapper->RemapOrdNum(nNewOrdNum); + } + + return nNewOrdNum; +} + +/************************************************************************* +|* +|* Identifier zurueckgeben +|* +\************************************************************************/ + +UINT16 E3dScene::GetObjIdentifier() const +{ + return E3D_SCENE_ID; +} + +/************************************************************************* +|* +|* SetSnapRect +|* +\************************************************************************/ + +void E3dScene::NbcSetSnapRect(const Rectangle& rRect) +{ + SetRectsDirty(); + E3dObject::NbcSetSnapRect(rRect); + aCamera.SetDeviceWindow(rRect); + aCameraSet.SetViewportRectangle((Rectangle&)rRect); + + // #110988# + ImpCleanup3DDepthMapper(); +} + +/************************************************************************* +|* +|* Objekt verschieben +|* +\************************************************************************/ + +void E3dScene::NbcMove(const Size& rSize) +{ + Rectangle aNewSnapRect = GetSnapRect(); + MoveRect(aNewSnapRect, rSize); + NbcSetSnapRect(aNewSnapRect); +} + +/************************************************************************* +|* +|* Objekt Resizen +|* +\************************************************************************/ + +void E3dScene::NbcResize(const Point& rRef, const Fraction& rXFact, + const Fraction& rYFact) +{ + Rectangle aNewSnapRect = GetSnapRect(); + ResizeRect(aNewSnapRect, rRef, rXFact, rYFact); + NbcSetSnapRect(aNewSnapRect); +} + +/************************************************************************* +|* +|* Neue Kamera setzen, und dabei die Szene und ggf. das BoundVolume +|* als geaendert markieren +|* +\************************************************************************/ + +void E3dScene::SetCamera(const Camera3D& rNewCamera) +{ + // Alte Kamera setzen + aCamera = rNewCamera; + ((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera(); + + SetRectsDirty(); + + // Neue Kamera aus alter fuellen + Camera3D& rCam = (Camera3D&)GetCamera(); + + // Ratio abschalten + if(rCam.GetAspectMapping() == AS_NO_MAPPING) + GetCameraSet().SetRatio(0.0); + + // Abbildungsgeometrie setzen + basegfx::B3DPoint aVRP(rCam.GetViewPoint()); + basegfx::B3DVector aVPN(aVRP - rCam.GetVRP()); + basegfx::B3DVector aVUV(rCam.GetVUV()); + + // #91047# use SetViewportValues() to set VRP, VPN and VUV as vectors, too. + // Else these values would not be exported/imported correctly. + GetCameraSet().SetViewportValues(aVRP, aVPN, aVUV); + + // Perspektive setzen + GetCameraSet().SetPerspective(rCam.GetProjection() == PR_PERSPECTIVE); + GetCameraSet().SetViewportRectangle((Rectangle&)rCam.GetDeviceWindow()); + + // #110988# + ImpCleanup3DDepthMapper(); +} + +/************************************************************************* +|* +|* 3D-Objekt einfuegen +|* +\************************************************************************/ + +void E3dScene::NewObjectInserted(const E3dObject* p3DObj) +{ + E3dObject::NewObjectInserted(p3DObj); + + if ( p3DObj == this ) + return; + + // #110988# + ImpCleanup3DDepthMapper(); +} + +/************************************************************************* +|* +|* Parent ueber Aenderung eines Childs informieren +|* +\************************************************************************/ + +void E3dScene::StructureChanged() +{ + E3dObject::StructureChanged(); + SetRectsDirty(); + + // #110988# + ImpCleanup3DDepthMapper(); +} + +/************************************************************************* +|* +|* Uebergeordnetes Szenenobjekt bestimmen +|* +\************************************************************************/ + +E3dScene* E3dScene::GetScene() const +{ + if(GetParentObj()) + return GetParentObj()->GetScene(); + else + return (E3dScene*)this; +} + +void E3dScene::removeAllNonSelectedObjects() +{ + E3DModifySceneSnapRectUpdater aUpdater(this); + + for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++) + { + SdrObject* pObj = maSubList.GetObj(a); + + if(pObj) + { + bool bRemoveObject(false); + + if(pObj->ISA(E3dScene)) + { + E3dScene* pScene = (E3dScene*)pObj; + + // iterate over this sub-scene + pScene->removeAllNonSelectedObjects(); + + // check object count. Empty scenes can be deleted + const sal_uInt32 nObjCount(pScene->GetSubList() ? pScene->GetSubList()->GetObjCount() : 0); + + if(!nObjCount) + { + // all objects removed, scene can be removed, too + bRemoveObject = true; + } + } + else if(pObj->ISA(E3dCompoundObject)) + { + E3dCompoundObject* pCompound = (E3dCompoundObject*)pObj; + + if(!pCompound->GetSelected()) + { + bRemoveObject = true; + } + } + + if(bRemoveObject) + { + maSubList.NbcRemoveObject(pObj->GetOrdNum()); + a--; + SdrObject::Free(pObj); + } + } + } +} + +/************************************************************************* +|* +|* Zuweisungsoperator +|* +\************************************************************************/ + +void E3dScene::operator=(const SdrObject& rObj) +{ + E3dObject::operator=(rObj); + + const E3dScene& r3DObj = (const E3dScene&) rObj; + aCamera = r3DObj.aCamera; + + // neu ab 377: + aCameraSet = r3DObj.aCameraSet; + ((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera(); + + // SetSnapRect(r3DObj.GetSnapRect()); + InvalidateBoundVolume(); + RebuildLists(); + SetRectsDirty(); + + // #110988# + ImpCleanup3DDepthMapper(); + + // #i101941# + // After a Scene as model object is cloned, the used + // ViewContactOfE3dScene is created and partially used + // to calculate Bound/SnapRects, but - since quite some + // values are buffered at the VC - not really well + // initialized. It would be possible to always watch for + // preconditions of buffered data, but this would be expensive + // and would create a lot of short living data structures. + // It is currently better to flush that data, e.g. by using + // ActionChanged at the VC which will for this class + // flush that cached data and initalize it's valid reconstruction + GetViewContact().ActionChanged(); +} + +/************************************************************************* +|* +|* Licht- und Labelobjektlisten neu aufbauen (nach Laden, Zuweisung) +|* +\************************************************************************/ + +void E3dScene::RebuildLists() +{ + // zuerst loeschen + SdrLayerID nCurrLayerID = GetLayer(); + + SdrObjListIter a3DIterator(maSubList, IM_FLAT); + + // dann alle Objekte in der Szene pruefen + while ( a3DIterator.IsMore() ) + { + E3dObject* p3DObj = (E3dObject*) a3DIterator.Next(); + p3DObj->NbcSetLayer(nCurrLayerID); + NewObjectInserted(p3DObj); + } +} + +/************************************************************************* +|* +|* erstelle neues GeoData-Objekt +|* +\************************************************************************/ + +SdrObjGeoData *E3dScene::NewGeoData() const +{ + return new E3DSceneGeoData; +} + +/************************************************************************* +|* +|* uebergebe aktuelle werte an das GeoData-Objekt +|* +\************************************************************************/ + +void E3dScene::SaveGeoData(SdrObjGeoData& rGeo) const +{ + E3dObject::SaveGeoData (rGeo); + + ((E3DSceneGeoData &) rGeo).aCamera = aCamera; +} + +/************************************************************************* +|* +|* uebernehme werte aus dem GeoData-Objekt +|* +\************************************************************************/ + +void E3dScene::RestGeoData(const SdrObjGeoData& rGeo) +{ + // #i94832# removed E3DModifySceneSnapRectUpdater here. + // It should not be needed, is already part of E3dObject::RestGeoData + E3dObject::RestGeoData (rGeo); + SetCamera (((E3DSceneGeoData &) rGeo).aCamera); +} + +/************************************************************************* +|* +|* Am StyleSheet wurde etwas geaendert, also Scene aendern +|* +\************************************************************************/ + +void E3dScene::Notify(SfxBroadcaster &rBC, const SfxHint &rHint) +{ + SetRectsDirty(); + E3dObject::Notify(rBC, rHint); +} + +/************************************************************************* +|* +\************************************************************************/ + +void E3dScene::RotateScene (const Point& rRef, long /*nWink*/, double sn, double cs) +{ + Point UpperLeft, LowerRight, Center, NewCenter; + + UpperLeft = aOutRect.TopLeft(); + LowerRight = aOutRect.BottomRight(); + + long dxOutRectHalf = labs(UpperLeft.X() - LowerRight.X()); + dxOutRectHalf /= 2; + long dyOutRectHalf = labs(UpperLeft.Y() - LowerRight.Y()); + dyOutRectHalf /= 2; + + Rectangle RectQuelle(aOutRect), RectZiel(aOutRect); + + // Nur der Mittelpunkt wird bewegt. Die Ecken werden von NbcMove bewegt. + // Fuer das Drehen wird von mir ein kartesisches Koordinatensystem verwendet in dem der Drehpunkt + // der Nullpunkt ist und die Y- Achse nach oben ansteigt, die X-Achse nach rechts. + // Dies muss bei den Y-Werten beachtet werden. (Auf dem Blatt zeigt die Y-Achse nach unten + Center.X() = (UpperLeft.X() + dxOutRectHalf) - rRef.X(); + Center.Y() = -((UpperLeft.Y() + dyOutRectHalf) - rRef.Y()); + // Ein paar Spezialfaelle zuerst abhandeln (n*90 Grad n ganzzahlig) + if (sn==1.0 && cs==0.0) { // 90deg + NewCenter.X() = -Center.Y(); + NewCenter.Y() = -Center.X(); + } else if (sn==0.0 && cs==-1.0) { // 180deg + NewCenter.X() = -Center.X(); + NewCenter.Y() = -Center.Y(); + } else if (sn==-1.0 && cs==0.0) { // 270deg + NewCenter.X() = Center.Y(); + NewCenter.Y() = -Center.X(); + } + else // Hier wird um einen beliebigen Winkel in mathematisch positiver Richtung gedreht! + { // xneu = x * cos(alpha) - y * sin(alpha) + // yneu = x * sin(alpha) + y * cos(alpha) + // Unten Rechts wird nicht gedreht: die Seiten von RectQuelle muessen parallel + // zu den Koordinatenachsen bleiben. + NewCenter.X() = (long) (Center.X() * cs - Center.Y() * sn); + NewCenter.Y() = (long) (Center.X() * sn + Center.Y() * cs); + } + + Size Differenz; + Point DiffPoint = (NewCenter - Center); + Differenz.Width() = DiffPoint.X(); + Differenz.Height() = -DiffPoint.Y(); // Man beachte dass die Y-Achse nach unten positiv gezaehlt wird. + NbcMove (Differenz); // fuehrt die eigentliche Koordinatentransformation durch. +} + +/************************************************************************* +|* +|* Get the name of the object (singular) +|* +\************************************************************************/ + +void E3dScene::TakeObjNameSingul(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNameSingulScene3d); + + 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 E3dScene::TakeObjNamePlural(XubString& rName) const +{ + rName=ImpGetResStr(STR_ObjNamePluralScene3d); +} + +/************************************************************************* +|* +|* Die NbcRotate-Routine ueberlaedt die des SdrObject. Die Idee ist die Scene +|* drehen zu koennen und relativ zur Lage der Scene dann auch die Objekte +|* in der Scene +|* +\************************************************************************/ + +void E3dScene::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix) +{ + if(maTransformation != rMatrix) + { + // call parent + E3dObject::NbcSetTransform(rMatrix); + } +} + +void E3dScene::SetTransform(const basegfx::B3DHomMatrix& rMatrix) +{ + if(rMatrix != maTransformation) + { + // call parent + E3dObject::SetTransform(rMatrix); + } +} + +void E3dScene::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(TRUE); + + // So dass war die Szene, ab jetzt kommen die Objekte in der Szene + // 3D-Objekte gibt es nur ein einziges das kann zwar mehrere Flaechen haben aber die Flaechen + // muessen ja nicht zusammenhaengend sein + // es ermoeglicht den Zugriff auf Kindobjekte + // Ich gehe also die gesamte Liste durch und rotiere um die Z-Achse die durch den + // Mittelpunkt von aOutRect geht (Satz von Steiner), also RotateZ + + RotateScene (rRef, nWink, sn, cs); // Rotiert die Szene + double fWinkelInRad = nWink/100 * F_PI180; + + basegfx::B3DHomMatrix aRotation; + aRotation.rotate(0.0, 0.0, fWinkelInRad); + NbcSetTransform(aRotation * 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(FALSE); // ab jetzt sind sie wieder relativ zum BoundRect (also dem aOutRect definiert) + SetRectsDirty(); +} + +/************************************************************************* +|* +|* SnapRect berechnen +|* +\************************************************************************/ + +void E3dScene::RecalcSnapRect() +{ + E3dScene* pScene = GetScene(); + + if(pScene == this) + { + // Szene wird als 2D-Objekt benutzt, nimm SnapRect aus der + // 2D Bildschrimdarstellung + Camera3D& rCam = (Camera3D&)pScene->GetCamera(); + maSnapRect = rCam.GetDeviceWindow(); + } + else + { + // Szene ist selbst Mitglied einer anderen Szene, hole das + // SnapRect als zusammengesetztes Objekt + E3dObject::RecalcSnapRect(); + } +} + +/************************************************************************* +|* +|* Aufbrechen +|* +\************************************************************************/ + +BOOL E3dScene::IsBreakObjPossible() +{ + // Szene ist aufzubrechen, wenn alle Mitglieder aufzubrechen sind + SdrObjListIter a3DIterator(maSubList, IM_DEEPWITHGROUPS); + + while ( a3DIterator.IsMore() ) + { + E3dObject* pObj = (E3dObject*) a3DIterator.Next(); + DBG_ASSERT(pObj->ISA(E3dObject), "AW: In Szenen sind nur 3D-Objekte erlaubt!"); + if(!pObj->IsBreakObjPossible()) + return FALSE; + } + + return TRUE; +} + +basegfx::B3DVector E3dScene::GetShadowPlaneDirection() const +{ + double fWink = (double)GetShadowSlant() * F_PI180; + basegfx::B3DVector aShadowPlaneDir(0.0, sin(fWink), cos(fWink)); + aShadowPlaneDir.normalize(); + return aShadowPlaneDir; +} + +void E3dScene::SetShadowPlaneDirection(const basegfx::B3DVector& rVec) +{ + UINT16 nSceneShadowSlant = (UINT16)((atan2(rVec.getY(), rVec.getZ()) / F_PI180) + 0.5); + GetProperties().SetObjectItemDirect(Svx3DShadowSlantItem(nSceneShadowSlant)); +} + +basegfx::B2DPolyPolygon E3dScene::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const +{ + return TakeXorPoly(); +} + +FASTBOOL E3dScene::BegCreate(SdrDragStat& rStat) +{ + rStat.SetOrtho4Possible(); + Rectangle aRect1(rStat.GetStart(), rStat.GetNow()); + aRect1.Justify(); + rStat.SetActionRect(aRect1); + NbcSetSnapRect(aRect1); + return TRUE; +} + +FASTBOOL E3dScene::MovCreate(SdrDragStat& rStat) +{ + Rectangle aRect1; + rStat.TakeCreateRect(aRect1); + aRect1.Justify(); + rStat.SetActionRect(aRect1); + NbcSetSnapRect(aRect1); + SetBoundRectDirty(); + bSnapRectDirty=TRUE; + return TRUE; +} + +FASTBOOL E3dScene::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd) +{ + Rectangle aRect1; + rStat.TakeCreateRect(aRect1); + aRect1.Justify(); + NbcSetSnapRect(aRect1); + SetRectsDirty(); + return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2); +} + +FASTBOOL E3dScene::BckCreate(SdrDragStat& /*rStat*/) +{ + return FALSE; +} + +void E3dScene::BrkCreate(SdrDragStat& /*rStat*/) +{ +} + +// eof |