/**************************************************************
 *
 * 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 "svx/svditer.hxx"

#if defined( UNX ) || defined( ICC )
#include <stdlib.h>
#endif
#include "svx/globl3d.hxx"
#include <svx/svdpage.hxx>
#include <svl/style.hxx>
#include <svx/scene3d.hxx>
#include <svx/e3dundo.hxx>
#include <svx/svdtrans.hxx>
#include <svx/svxids.hrc>
#include <editeng/colritem.hxx>
#include <svx/e3ditem.hxx>
#include <svx/xlntrit.hxx>
#include <svx/xfltrit.hxx>
#include <svx/svx3ditems.hxx>
#include <svl/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>
#include <svx/svdmodel.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)
#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
|*
\************************************************************************/

sal_uInt16 E3dScene::GetObjIdentifier() const
{
	return E3D_SCENE_ID;
}

void E3dScene::SetBoundRectDirty()
{
	E3dScene* pScene = GetScene();

	if(pScene == this)
	{
	    // avoid resetting aOutRect which in case of a 3D scene used as 2d object
		// is model data,not re-creatable view data
	}
	else
	{
		// if not the outmost scene it is used as group in 3d, call parent
		E3dObject::SetBoundRectDirty();
	}
}

/*************************************************************************
|*
|* 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();

    if(!GetModel() || !GetModel()->isLocked())
    {
        // #123539# optimization for 3D chart object generation: do not reset
        // already calculated scene projection data every time an object gets
        // initialized
        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 initialize its 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(sal_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(sal_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
|*
\************************************************************************/

sal_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 sal_False;
	}

	return sal_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)
{
	sal_uInt16 nSceneShadowSlant = (sal_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 sal_True;
}

FASTBOOL E3dScene::MovCreate(SdrDragStat& rStat)
{
	Rectangle aRect1;
	rStat.TakeCreateRect(aRect1);
	aRect1.Justify();
	rStat.SetActionRect(aRect1);
	NbcSetSnapRect(aRect1);
	SetBoundRectDirty();
	bSnapRectDirty=sal_True;
	return sal_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 sal_False;
}

void E3dScene::BrkCreate(SdrDragStat& /*rStat*/)
{
}

// eof
