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

2142 lines
71 KiB
C++
Raw Normal View History

2000-09-18 16:07:07 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 16:07:07 +00:00
*
* $RCSfile: view3d.cxx,v $
2000-09-18 16:07:07 +00:00
*
* $Revision: 1.29 $
2000-09-18 16:07:07 +00:00
*
* last change: $Author: hr $ $Date: 2007-06-27 18:06:11 $
2000-09-18 16:07:07 +00:00
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
2000-09-18 16:07:07 +00:00
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
2000-09-18 16:07:07 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
2000-09-18 16:07:07 +00:00
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
2000-09-18 16:07:07 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
2000-09-18 16:07:07 +00:00
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_svx.hxx"
2000-09-18 16:07:07 +00:00
#ifndef _SV_WRKWIN_HXX
#include <vcl/wrkwin.hxx>
#endif
2000-11-10 14:24:49 +00:00
#ifndef INCLUDED_SVTOOLS_OPTIONS3D_HXX
#include <svtools/options3d.hxx>
#endif
2000-09-18 16:07:07 +00:00
#ifndef _SVDOGRP_HXX
#include <svx/svdogrp.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVDOPATH_HXX
#include <svx/svdopath.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SHL_HXX
#include <tools/shl.hxx>
#endif
#ifndef _SVDITER_HXX
#include "svditer.hxx"
#endif
#ifndef _SVDPOOL_HXX
#include <svx/svdpool.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVDORECT_HXX
#include <svx/svdorect.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVDMODEL_HXX
#include <svx/svdmodel.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVDPAGV_HXX
#include <svx/svdpagv.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _XOUTX_HXX
#include <svx/xoutx.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVX_SVXIDS_HRC
#include <svx/svxids.hrc>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVX_COLRITEM_HXX
#include <svx/colritem.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _XTABLE_HXX
#include <svx/xtable.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVDVIEW_HXX
#include <svx/svdview.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVX_DIALOGS_HRC
#include <svx/dialogs.hrc>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVX_DIALMGR_HXX
#include <svx/dialmgr.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _E3D_GLOBL3D_HXX
#include "globl3d.hxx"
#endif
#ifndef _E3D_OBJ3D_HXX
#include <svx/obj3d.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _E3D_LATHE3D_HXX
#include <svx/lathe3d.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _E3D_SPHERE3D_HXX
#include <svx/sphere3d.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _E3D_EXTRUD3D_HXX
#include <svx/extrud3d.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _E3D_CUBE3D_HXX
#include <svx/cube3d.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _E3D_POLYSC3D_HXX
#include <svx/polysc3d.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _E3D_DRAGMT3D_HXX
#include "dragmt3d.hxx"
#endif
#ifndef _E3D_VIEW3D_HXX
#include <svx/view3d.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVDUNDO_HXX
#include <svx/svdundo.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVX_XFLCLIT_HXX
#include <svx/xflclit.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVX_XLNCLIT_HXX
#include <svx/xlnclit.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVDOGRAF_HXX
#include <svx/svdograf.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVX_XBTMPIT_HXX
#include <svx/xbtmpit.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _SVX_XFLBMTIT_HXX
#include <svx/xflbmtit.hxx>
2000-09-18 16:07:07 +00:00
#endif
#ifndef _BGFX_RANGE_B2DRANGE_HXX
#include <basegfx/range/b2drange.hxx>
#endif
#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX
#include <basegfx/polygon/b2dpolygontools.hxx>
#endif
#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#endif
#include <svx/xlnwtit.hxx>
2000-09-18 16:07:07 +00:00
#ifndef _SDR_OVERLAY_OVERLAYPOLYPOLYGON_HXX
#include <svx/sdr/overlay/overlaypolypolygon.hxx>
#endif
#ifndef _SDR_OVERLAY_OVERLAYMANAGER_HXX
#include <svx/sdr/overlay/overlaymanager.hxx>
#endif
#ifndef _SDRPAINTWINDOW_HXX
#include <sdrpaintwindow.hxx>
#endif
2000-09-18 16:07:07 +00:00
#define ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue()
TYPEINIT1(E3dView, SdrView);
////////////////////////////////////////////////////////////////////////////////////////////////////
// Migrate Marking
2000-09-18 16:07:07 +00:00
class Impl3DMirrorConstructOverlay
{
// The OverlayObjects
::sdr::overlay::OverlayObjectList maObjects;
2000-09-18 16:07:07 +00:00
// the view
const E3dView& mrView;
2000-09-18 16:07:07 +00:00
// the unmirrored polygons and their count
sal_uInt32 mnCount;
basegfx::B2DPolyPolygon* mpPolygons;
2000-09-18 16:07:07 +00:00
public:
Impl3DMirrorConstructOverlay(const E3dView& rView);
~Impl3DMirrorConstructOverlay();
2000-09-18 16:07:07 +00:00
void SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB);
};
2000-09-18 16:07:07 +00:00
Impl3DMirrorConstructOverlay::Impl3DMirrorConstructOverlay(const E3dView& rView)
: mrView(rView)
2000-09-18 16:07:07 +00:00
{
const SdrMarkList& rMarkList = mrView.GetMarkedObjectList();
mnCount = rMarkList.GetMarkCount();
mpPolygons = new basegfx::B2DPolyPolygon[mnCount];
for(sal_uInt32 a(0L); a < mnCount; a++)
{
SdrMark *pMark = rMarkList.GetMark(a);
SdrObject *pObj = pMark->GetMarkedSdrObj();
mpPolygons[mnCount - (a + 1L)] = pObj->TakeXorPoly(sal_False);
}
2000-09-18 16:07:07 +00:00
}
Impl3DMirrorConstructOverlay::~Impl3DMirrorConstructOverlay()
{
// The OverlayObjects are cleared using the destructor of OverlayObjectList.
// That destructor calls clear() at the list which removes all objects from the
// OverlayManager and deletes them.
delete[] mpPolygons;
}
2000-09-18 16:07:07 +00:00
void Impl3DMirrorConstructOverlay::SetMirrorAxis(Point aMirrorAxisA, Point aMirrorAxisB)
2000-09-18 16:07:07 +00:00
{
// get rid of old overlay objects
maObjects.clear();
// create new ones
for(sal_uInt32 a(0L); a < mrView.PaintWindowCount(); a++)
{
SdrPaintWindow* pCandidate = mrView.GetPaintWindow(a);
::sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager();
if(pTargetOverlay)
{
for(sal_uInt32 b(0L); b < mnCount; b++)
{
basegfx::B2DPolyPolygon aPolyPolygon(mpPolygons[b]);
// translate and rotate polygon so that given edge is on x axis, them mirror in y and translate back
const basegfx::B2DVector aEdge(aMirrorAxisB.X() - aMirrorAxisA.X(), aMirrorAxisB.Y() - aMirrorAxisA.Y());
basegfx::B2DHomMatrix aMatrixTransform;
aMatrixTransform.translate(-aMirrorAxisA.X(), -aMirrorAxisA.Y());
aMatrixTransform.rotate(-atan2(aEdge.getY(), aEdge.getX()));
aMatrixTransform.scale(1.0, -1.0);
aMatrixTransform.rotate(atan2(aEdge.getY(), aEdge.getX()));
aMatrixTransform.translate(aMirrorAxisA.X(), aMirrorAxisA.Y());
// apply to polygon
aPolyPolygon.transform(aMatrixTransform);
::sdr::overlay::OverlayPolyPolygonStriped* pNew = new ::sdr::overlay::OverlayPolyPolygonStriped(aPolyPolygon);
pTargetOverlay->add(*pNew);
maObjects.append(*pNew);
}
}
}
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* Konstruktor 1
2000-09-18 16:07:07 +00:00
|*
\************************************************************************/
E3dView::E3dView(SdrModel* pModel, OutputDevice* pOut) :
SdrView(pModel, pOut)
2000-09-18 16:07:07 +00:00
{
InitView ();
}
/*************************************************************************
|*
|* DrawMarkedObj ueberladen, da eventuell nur einzelne 3D-Objekte
|* gezeichnet werden sollen
|*
\************************************************************************/
void E3dView::DrawMarkedObj(OutputDevice& rOut, const Point& rOfs) const
{
// Existieren 3D-Objekte, deren Szenen nicht selektiert sind?
BOOL bSpecialHandling = FALSE;
E3dScene *pScene = NULL;
long nCnt = GetMarkedObjectCount();
2000-09-18 16:07:07 +00:00
for(long nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dCompoundObject))
{
// zugehoerige Szene
pScene = ((E3dCompoundObject*)pObj)->GetScene();
if(pScene && !IsObjMarked(pScene))
bSpecialHandling = TRUE;
}
// Alle SelectionFlags zuruecksetzen
if(pObj && pObj->ISA(E3dObject))
{
pScene = ((E3dObject*)pObj)->GetScene();
if(pScene)
pScene->SetSelected(FALSE);
}
}
if(bSpecialHandling)
{
// SelectionFlag bei allen zu 3D Objekten gehoerigen
// Szenen und deren Objekten auf nicht selektiert setzen
long nObjs;
for(nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dCompoundObject))
{
// zugehoerige Szene
pScene = ((E3dCompoundObject*)pObj)->GetScene();
if(pScene)
pScene->SetSelected(FALSE);
}
}
// bei allen direkt selektierten Objekten auf selektiert setzen
SdrMark* pM = NULL;
for(nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dObject))
{
// Objekt markieren
E3dObject* p3DObj = (E3dObject*)pObj;
p3DObj->SetSelected(TRUE);
pScene = p3DObj->GetScene();
pM = GetSdrMarkByIndex(nObjs);
2000-09-18 16:07:07 +00:00
}
}
if(pScene)
{
// code from parent
SortMarkedObjects();
2000-09-18 16:07:07 +00:00
pXOut->SetOutDev(&rOut);
SdrPaintInfoRec aInfoRec;
aInfoRec.nPaintMode|=SDRPAINTMODE_ANILIKEPRN;
Point aOfs(-rOfs.X(), -rOfs.Y());
// aOfs += pM->GetPageView()->GetOffset();
2000-09-18 16:07:07 +00:00
if(aOfs != pXOut->GetOffset())
pXOut->SetOffset(aOfs);
pScene->SetDrawOnlySelected(TRUE);
pScene->SingleObjectPainter(*pXOut,aInfoRec); // #110094#-17
2000-09-18 16:07:07 +00:00
pScene->SetDrawOnlySelected(FALSE);
pXOut->SetOffset(Point(0,0));
}
// SelectionFlag zuruecksetzen
for(nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dCompoundObject))
{
// zugehoerige Szene
pScene = ((E3dCompoundObject*)pObj)->GetScene();
if(pScene)
pScene->SetSelected(FALSE);
}
}
}
else
{
// call parent
SdrExchangeView::DrawMarkedObj(rOut, rOfs);
}
}
/*************************************************************************
|*
|* Model holen ueberladen, da bei einzelnen 3D Objekten noch eine Szene
|* untergeschoben werden muss
|*
\************************************************************************/
SdrModel* E3dView::GetMarkedObjModel() const
{
// Existieren 3D-Objekte, deren Szenen nicht selektiert sind?
BOOL bSpecialHandling = FALSE;
E3dScene *pScene = NULL;
long nCnt = GetMarkedObjectCount();
2000-09-18 16:07:07 +00:00
for(long nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dCompoundObject))
{
// zugehoerige Szene
pScene = ((E3dCompoundObject*)pObj)->GetScene();
if(pScene && !IsObjMarked(pScene))
bSpecialHandling = TRUE;
}
// Alle SelectionFlags zuruecksetzen
if(pObj && pObj->ISA(E3dObject))
{
pScene = ((E3dObject*)pObj)->GetScene();
if(pScene)
pScene->SetSelected(FALSE);
}
}
SdrModel* pNewModel = 0L;
if(bSpecialHandling)
{
// SelectionFlag bei allen zu 3D Objekten gehoerigen
// Szenen und deren Objekten auf nicht selektiert setzen
long nObjs;
for(nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dCompoundObject))
{
// zugehoerige Szene
pScene = ((E3dCompoundObject*)pObj)->GetScene();
if(pScene)
pScene->SetSelected(FALSE);
}
}
// bei allen direkt selektierten Objekten auf selektiert setzen
for(nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dObject))
{
// Objekt markieren
E3dObject* p3DObj = (E3dObject*)pObj;
p3DObj->SetSelected(TRUE);
}
}
// Neue MarkList generieren, die die betroffenen
// Szenen als markierte Objekte enthaelt
SdrMarkList aOldML(GetMarkedObjectList()); // alte Marklist merken
2000-09-18 16:07:07 +00:00
SdrMarkList aNewML; // neue leere Marklist
SdrMarkList& rCurrentMarkList = ((E3dView*)this)->GetMarkedObjectListWriteAccess();
rCurrentMarkList = aNewML; // ((E3dView*)this)->maMarkedObjectList = aNewML;
2000-09-18 16:07:07 +00:00
for(nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = aOldML.GetMark(nObjs)->GetMarkedSdrObj();
2000-09-18 16:07:07 +00:00
if(pObj)
{
if(pObj->ISA(E3dCompoundObject))
{
// zugehoerige Szene holen
pScene = ((E3dCompoundObject*)pObj)->GetScene();
if(pScene)
pObj = pScene;
}
// Keine Objekte doppelt markieren
// (dies koennten nur Szenen sein)
if(!IsObjMarked(pObj))
{
if(GetSdrPageView())
{
((E3dView*)this)->MarkObj(pObj, GetSdrPageView(), FALSE, TRUE);
2000-09-18 16:07:07 +00:00
}
}
}
}
// call parent
pNewModel = SdrView::GetMarkedObjModel();
// Alle Szenen im kopierten Model in Ihren Ausdehnungen Korrigieren
// und IsSelected zuruecksetzen
if(pNewModel)
{
for(UINT16 nPg=0; nPg < pNewModel->GetPageCount(); nPg++)
{
const SdrPage* pSrcPg=pNewModel->GetPage(nPg);
UINT32 nObAnz=pSrcPg->GetObjCount();
// Unterobjekte von Szenen einfuegen
for(UINT32 nOb=0; nOb<nObAnz; nOb++)
{
const SdrObject* pSrcOb=pSrcPg->GetObj(nOb);
if(pSrcOb->ISA(E3dScene))
{
pScene = (E3dScene*)pSrcOb;
pScene->CorrectSceneDimensions();
pScene->SetSelected(FALSE);
}
}
}
}
// Alte Liste wieder setzen
// ((E3dView*)this)->maMarkedObjectList= aOldML;
rCurrentMarkList = aOldML;
2000-09-18 16:07:07 +00:00
// SelectionFlag zuruecksetzen
for(nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dCompoundObject))
{
// zugehoerige Szene
pScene = ((E3dCompoundObject*)pObj)->GetScene();
if(pScene)
pScene->SetSelected(FALSE);
}
}
}
else
{
// call parent
pNewModel = SdrView::GetMarkedObjModel();
}
// model zurueckgeben
return pNewModel;
}
/*************************************************************************
|*
|* Bei Paste muss - falls in eine Scene eingefuegt wird - die
|* Objekte der Szene eingefuegt werden, die Szene selbst aber nicht
|*
\************************************************************************/
BOOL E3dView::Paste(const SdrModel& rMod, const Point& rPos, SdrObjList* pLst, UINT32 nOptions)
2000-09-18 16:07:07 +00:00
{
BOOL bRetval = FALSE;
// Liste holen
Point aPos(rPos);
SdrObjList* pDstList = pLst;
ImpGetPasteObjList(aPos, pDstList);
if(!pDstList)
2000-09-18 16:07:07 +00:00
return FALSE;
// Owner der Liste holen
SdrObject* pOwner = pDstList->GetOwnerObj();
2000-09-18 16:07:07 +00:00
if(pOwner && pOwner->ISA(E3dScene))
{
E3dScene* pDstScene = (E3dScene*)pOwner;
BOOL bDstInserted(FALSE);
2000-09-18 16:07:07 +00:00
BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXCHANGE_PASTE));
// Alle Objekte aus E3dScenes kopieren und direkt einfuegen
for(sal_uInt16 nPg(0); nPg < rMod.GetPageCount(); nPg++)
2000-09-18 16:07:07 +00:00
{
const SdrPage* pSrcPg=rMod.GetPage(nPg);
sal_uInt32 nObAnz(pSrcPg->GetObjCount());
2000-09-18 16:07:07 +00:00
// calculate offset for paste
Rectangle aR = pSrcPg->GetAllObjBoundRect();
Point aDist(aPos - aR.Center());
2000-09-18 16:07:07 +00:00
// Unterobjekte von Szenen einfuegen
for(sal_uInt32 nOb(0); nOb < nObAnz; nOb++)
2000-09-18 16:07:07 +00:00
{
const SdrObject* pSrcOb = pSrcPg->GetObj(nOb);
2000-09-18 16:07:07 +00:00
if(pSrcOb->ISA(E3dScene))
{
E3dScene* pSrcScene = (E3dScene*)pSrcOb;
bDstInserted = ImpCloneAll3DObjectsToDestScene(pSrcScene, pDstScene, aDist);
2000-09-18 16:07:07 +00:00
}
}
}
EndUndo();
// DestScene anpassen
if(bDstInserted)
{
pDstScene->SetRectsDirty();
pDstScene->CorrectSceneDimensions();
bRetval = TRUE;
2000-09-18 16:07:07 +00:00
}
}
else
{
// call parent
bRetval = SdrView::Paste(rMod, rPos, pLst, nOptions);
}
// und Rueckgabewert liefern
return bRetval;
}
// #83403# Service routine used from local Clone() and from SdrCreateView::EndCreateObj(...)
BOOL E3dView::ImpCloneAll3DObjectsToDestScene(E3dScene* pSrcScene, E3dScene* pDstScene, Point aOffset)
{
BOOL bRetval(FALSE);
if(pSrcScene && pDstScene)
{
B3dCamera& rCameraSetDst = pDstScene->GetCameraSet();
B3dCamera& rCameraSetSrc = pSrcScene->GetCameraSet();
for(sal_uInt32 i(0); i < pSrcScene->GetSubList()->GetObjCount(); i++)
{
SdrObject* pObj = pSrcScene->GetSubList()->GetObj(i);
if(pObj && pObj->ISA(E3dCompoundObject))
{
// Kopieren
// E3dObject* pNew = (E3dObject*)pObj->Clone(pDstScene->GetPage(), pDstScene->GetModel());
// #116235#
E3dObject* pNew = (E3dObject*)pObj->Clone();
if(pNew)
{
// #116235#
pNew->SetModel(pDstScene->GetModel());
pNew->SetPage(pDstScene->GetPage());
// Neues Objekt in Szene einfuegen
pNew->NbcSetLayer(pObj->GetLayer());
pNew->NbcSetStyleSheet(pObj->GetStyleSheet(), sal_True);
pDstScene->Insert3DObj(pNew);
bRetval = TRUE;
// Transformation ObjectToEye Src
basegfx::B3DHomMatrix aMatSrc;
aMatSrc = ((E3dCompoundObject*)pObj)->GetFullTransform();
aMatSrc *= rCameraSetSrc.GetOrientation();
// Tanslation und scale von source
basegfx::B3DRange aDevVolSrc(rCameraSetSrc.GetDeviceVolume());
// auf Augkoordinaten umstellen
aDevVolSrc = basegfx::B3DRange(
aDevVolSrc.getMinX(), aDevVolSrc.getMinY(), -aDevVolSrc.getMaxZ(),
aDevVolSrc.getMaxX(), aDevVolSrc.getMaxY(), -aDevVolSrc.getMinZ());
basegfx::B3DPoint aProjScaleSrc(
2.0 / aDevVolSrc.getWidth(),
2.0 / aDevVolSrc.getHeight(),
2.0 / aDevVolSrc.getDepth());
basegfx::B3DPoint aProjTransSrc(
-1.0 * ((aDevVolSrc.getMaxX() + aDevVolSrc.getMinX()) / aDevVolSrc.getWidth()),
-1.0 * ((aDevVolSrc.getMaxY() + aDevVolSrc.getMinY()) / aDevVolSrc.getHeight()),
-1.0 * ((aDevVolSrc.getMaxZ() + aDevVolSrc.getMinZ()) / aDevVolSrc.getDepth()));
basegfx::B3DPoint aViewScaleSrc(rCameraSetSrc.GetScale());
aViewScaleSrc.setZ(1.0);
// Tanslation und scale von dest
basegfx::B3DRange aDevVolDst(rCameraSetDst.GetDeviceVolume());
// auf Augkoordinaten umstellen
aDevVolDst = basegfx::B3DRange(
aDevVolDst.getMinX(), aDevVolDst.getMinY(), -aDevVolDst.getMaxZ(),
aDevVolDst.getMaxX(), aDevVolDst.getMaxY(), -aDevVolDst.getMinZ());
basegfx::B3DPoint aProjScaleDst(
2.0 / aDevVolDst.getWidth(),
2.0 / aDevVolDst.getHeight(),
2.0 / aDevVolDst.getDepth());
basegfx::B3DPoint aProjTransDst(
-1.0 * ((aDevVolDst.getMaxX() + aDevVolDst.getMinX()) / aDevVolDst.getWidth()),
-1.0 * ((aDevVolDst.getMaxY() + aDevVolDst.getMinY()) / aDevVolDst.getHeight()),
-1.0 * ((aDevVolDst.getMaxZ() + aDevVolDst.getMinZ()) / aDevVolDst.getDepth()));
basegfx::B3DPoint aViewScaleDst(rCameraSetDst.GetScale());
aViewScaleDst.setZ(1.0);
// Groesse des Objektes in Augkoordinaten Src
basegfx::B3DRange aObjVolSrc(((E3dCompoundObject*)pObj)->GetBoundVolume().GetTransformVolume(aMatSrc));
// Vorlaeufige Groesse in Augkoordinaten Dst
basegfx::B3DHomMatrix aMatZwi = aMatSrc;
aMatZwi.scale(aProjScaleSrc.getX(), aProjScaleSrc.getY(), aProjScaleSrc.getZ());
aMatZwi.translate(aProjTransSrc.getX(), aProjTransSrc.getY(), aProjTransSrc.getZ());
aMatZwi.scale(aViewScaleSrc.getX(), aViewScaleSrc.getY(), aViewScaleSrc.getZ());
basegfx::B3DHomMatrix aMatDst;
aMatDst.scale(aProjScaleDst.getX(), aProjScaleDst.getY(), aProjScaleDst.getZ());
aMatDst.translate(aProjTransDst.getX(), aProjTransDst.getY(), aProjTransDst.getZ());
aMatDst.scale(aViewScaleDst.getX(), aViewScaleDst.getY(), aViewScaleDst.getZ());
aMatDst.invert();
aMatZwi *= aMatDst;
basegfx::B3DRange aObjVolDst(((E3dCompoundObject*)pObj)->GetBoundVolume().GetTransformVolume(aMatZwi));
// Beide verhaeltnistiefen berechnen und mitteln
double fDepthOne = (aObjVolSrc.getDepth() * aObjVolDst.getWidth()) / aObjVolSrc.getWidth();
double fDepthTwo = (aObjVolSrc.getDepth() * aObjVolDst.getHeight()) / aObjVolSrc.getHeight();
double fWantedDepth = (fDepthOne + fDepthTwo) / 2.0;
// Faktor zum Tiefe anpassen bilden
double fFactor = fWantedDepth / aObjVolDst.getDepth();
basegfx::B3DPoint aDepthScale(1.0, 1.0, fFactor);
// Endgueltige Transformation bilden
aMatSrc.scale(aProjScaleSrc.getX(), aProjScaleSrc.getY(), aProjScaleSrc.getZ());
aMatSrc.translate(aProjTransSrc.getX(), aProjTransSrc.getY(), aProjTransSrc.getZ());
aMatSrc.scale(aViewScaleSrc.getX(), aViewScaleSrc.getY(), aViewScaleSrc.getZ());
aMatSrc.scale(aDepthScale.getX(), aDepthScale.getY(), aDepthScale.getZ());
aMatDst = pDstScene->GetFullTransform();
aMatDst *= rCameraSetDst.GetOrientation();
aMatDst.scale(aProjScaleDst.getX(), aProjScaleDst.getY(), aProjScaleDst.getZ());
aMatDst.translate(aProjTransDst.getX(), aProjTransDst.getY(), aProjTransDst.getZ());
aMatDst.scale(aViewScaleDst.getX(), aViewScaleDst.getY(), aViewScaleDst.getZ());
aMatDst.invert();
aMatSrc *= aMatDst;
// Neue Objekttransformation setzen
pNew->SetTransform(aMatSrc);
// force new camera and SnapRect on scene, geometry may have really
// changed
pDstScene->CorrectSceneDimensions();
// #83403# translate in view coor
{
// screen position of center of old object
basegfx::B3DHomMatrix aSrcFullTrans = ((E3dCompoundObject*)pObj)->GetFullTransform();
rCameraSetSrc.SetObjectTrans(aSrcFullTrans);
basegfx::B3DPoint aSrcCenter(((E3dCompoundObject*)pObj)->GetCenter());
aSrcCenter = rCameraSetSrc.ObjectToViewCoor(aSrcCenter);
if(aOffset.X() != 0 || aOffset.Y() != 0)
{
aSrcCenter += basegfx::B3DPoint((double)aOffset.X(), (double)aOffset.Y(), 0.0);
}
// to have a valid Z-Coor in dst system, calc current center of dst object
basegfx::B3DHomMatrix aDstFullTrans = pNew->GetFullTransform();
rCameraSetDst.SetObjectTrans(aDstFullTrans);
basegfx::B3DPoint aDstCenter(pNew->GetCenter());
aDstCenter = rCameraSetDst.ObjectToEyeCoor(aDstCenter);
// convert aSrcCenter to a eye position of dst scene
basegfx::B3DPoint aNewDstCenter(rCameraSetDst.ViewToEyeCoor(aSrcCenter));
aNewDstCenter.setZ(aDstCenter.getZ());
// transform back to object coor
aNewDstCenter = rCameraSetDst.EyeToObjectCoor(aNewDstCenter);
// get transform vector
basegfx::B3DPoint aTransformCorrection(aNewDstCenter - pNew->GetCenter());
basegfx::B3DHomMatrix aTransCorrMat;
aTransCorrMat.translate(aTransformCorrection.getX(), aTransformCorrection.getY(), aTransformCorrection.getZ());
// treanslate new object, add translate in front of obj transform
pNew->SetTransform(pNew->GetTransform() * aTransCorrMat); // #112587#
// force new camera and SnapRect on scene, geometry may have really
// changed
pDstScene->CorrectSceneDimensions();
//Rectangle aOldPosSize = pObj->GetSnapRect();
//if(aOffset.X() != 0 || aOffset.Y() != 0)
// aOldPosSize.Move(aOffset.X(), aOffset.Y());
//Rectangle aNewPosSize = pNew->GetSnapRect();
}
// Undo anlegen
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pNew));
}
}
}
}
return bRetval;
}
2000-09-18 16:07:07 +00:00
/*************************************************************************
|*
|* 3D-Konvertierung moeglich?
|*
\************************************************************************/
BOOL E3dView::IsConvertTo3DObjPossible() const
{
BOOL bAny3D(FALSE);
BOOL bGroupSelected(FALSE);
BOOL bRetval(TRUE);
for(sal_uInt32 a=0;!bAny3D && a<GetMarkedObjectCount();a++)
2000-09-18 16:07:07 +00:00
{
SdrObject *pObj = GetMarkedObjectByIndex(a);
2000-09-18 16:07:07 +00:00
if(pObj)
{
ImpIsConvertTo3DPossible(pObj, bAny3D, bGroupSelected);
}
}
bRetval = !bAny3D
&& (
IsConvertToPolyObjPossible(FALSE)
|| IsConvertToPathObjPossible(FALSE)
|| IsImportMtfPossible());
return bRetval;
}
void E3dView::ImpIsConvertTo3DPossible(SdrObject* pObj, BOOL& rAny3D,
BOOL& rGroupSelected) const
{
if(pObj)
{
if(pObj->ISA(E3dObject))
{
rAny3D = TRUE;
}
else
{
if(pObj->IsGroupObject())
{
SdrObjListIter aIter(*pObj, IM_DEEPNOGROUPS);
while(aIter.IsMore())
{
SdrObject* pNewObj = aIter.Next();
ImpIsConvertTo3DPossible(pNewObj, rAny3D, rGroupSelected);
}
rGroupSelected = TRUE;
}
}
}
}
/*************************************************************************
|*
|* 3D-Konvertierung zu Extrude ausfuehren
|*
\************************************************************************/
#ifndef _EEITEM_HXX
#include <svx/eeitem.hxx>
#endif
2000-09-18 16:07:07 +00:00
void E3dView::ImpChangeSomeAttributesFor3DConversion(SdrObject* pObj)
{
if(pObj->ISA(SdrTextObj))
{
const SfxItemSet& rSet = pObj->GetMergedItemSet();
const SvxColorItem& rTextColorItem = (const SvxColorItem&)rSet.Get(EE_CHAR_COLOR);
2000-09-18 16:07:07 +00:00
if(rTextColorItem.GetValue() == RGB_Color(COL_BLACK))
{
// Bei schwarzen Textobjekten wird die Farbe auf grau gesetzt
if(pObj->GetPage())
{
// #84864# if black is only default attribute from
// pattern set it hard so that it is used in undo.
pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_BLACK), EE_CHAR_COLOR));
// add undo now
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
}
pObj->SetMergedItem(SvxColorItem(RGB_Color(COL_GRAY), EE_CHAR_COLOR));
2000-09-18 16:07:07 +00:00
}
}
}
void E3dView::ImpChangeSomeAttributesFor3DConversion2(SdrObject* pObj)
{
if(pObj->ISA(SdrPathObj))
{
const SfxItemSet& rSet = pObj->GetMergedItemSet();
sal_Int32 nLineWidth = ((const XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue();
XLineStyle eLineStyle = (XLineStyle)((const XLineStyleItem&)rSet.Get(XATTR_LINESTYLE)).GetValue();
XFillStyle eFillStyle = ITEMVALUE(rSet, XATTR_FILLSTYLE, XFillStyleItem);
if(((SdrPathObj*)pObj)->IsClosed()
&& eLineStyle == XLINE_SOLID
&& !nLineWidth
&& eFillStyle != XFILL_NONE)
2000-09-18 16:07:07 +00:00
{
if(pObj->GetPage())
AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoAttrObject(*pObj, false, false));
pObj->SetMergedItem(XLineStyleItem(XLINE_NONE));
pObj->SetMergedItem(XLineWidthItem(0L));
2000-09-18 16:07:07 +00:00
}
}
}
void E3dView::ImpCreateSingle3DObjectFlat(E3dScene* pScene, SdrObject* pObj, BOOL bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
2000-09-18 16:07:07 +00:00
{
// Einzelnes PathObject, dieses umwanden
SdrPathObj* pPath = PTR_CAST(SdrPathObj, pObj);
if(pPath)
{
E3dDefaultAttributes aDefault = Get3DDefaultAttributes();
if(bExtrude)
aDefault.SetDefaultExtrudeCharacterMode(TRUE);
else
aDefault.SetDefaultLatheCharacterMode(TRUE);
// ItemSet des Ursprungsobjektes holen
SfxItemSet aSet(pObj->GetMergedItemSet());
2000-09-18 16:07:07 +00:00
XFillStyle eFillStyle = ITEMVALUE(aSet, XATTR_FILLSTYLE, XFillStyleItem);
// Linienstil ausschalten
aSet.Put(XLineStyleItem(XLINE_NONE));
// Feststellen, ob ein FILL_Attribut gesetzt ist.
if(!pPath->IsClosed() || eFillStyle == XFILL_NONE)
{
// Das SdrPathObj ist nicht gefuellt, lasse die
// vordere und hintere Flaeche weg. Ausserdem ist
// eine beidseitige Darstellung notwendig.
aDefault.SetDefaultExtrudeCloseFront(FALSE);
aDefault.SetDefaultExtrudeCloseBack(FALSE);
aSet.Put(Svx3DDoubleSidedItem(TRUE));
2000-09-18 16:07:07 +00:00
// Fuellattribut setzen
aSet.Put(XFillStyleItem(XFILL_SOLID));
// Fuellfarbe muss auf Linienfarbe, da das Objekt vorher
// nur eine Linie war
Color aColorLine = ((const XLineColorItem&)(aSet.Get(XATTR_LINECOLOR))).GetColorValue();
2000-09-18 16:07:07 +00:00
aSet.Put(XFillColorItem(String(), aColorLine));
}
// Neues Extrude-Objekt erzeugen
E3dObject* p3DObj = NULL;
if(bExtrude)
{
p3DObj = new E3dExtrudeObj(aDefault, pPath->GetPathPoly(), fDepth);
}
else
{
basegfx::B2DPolyPolygon aPolyPoly2D(pPath->GetPathPoly());
aPolyPoly2D.transform(rLatheMat);
p3DObj = new E3dLatheObj(aDefault, aPolyPoly2D);
2000-09-18 16:07:07 +00:00
}
// Attribute setzen
if(p3DObj)
{
p3DObj->NbcSetLayer(pObj->GetLayer());
p3DObj->SetMergedItemSet(aSet);
p3DObj->NbcSetStyleSheet(pObj->GetStyleSheet(), sal_True);
2000-09-18 16:07:07 +00:00
// Neues 3D-Objekt einfuegen
pScene->Insert3DObj(p3DObj);
}
}
}
void E3dView::ImpCreate3DObject(E3dScene* pScene, SdrObject* pObj, BOOL bExtrude, double fDepth, basegfx::B2DHomMatrix& rLatheMat)
2000-09-18 16:07:07 +00:00
{
if(pObj)
{
// change text color attribute for not so dark colors
if(pObj->IsGroupObject())
{
SdrObjListIter aIter(*pObj, IM_DEEPWITHGROUPS);
while(aIter.IsMore())
{
SdrObject* pGroupMember = aIter.Next();
ImpChangeSomeAttributesFor3DConversion(pGroupMember);
}
}
else
ImpChangeSomeAttributesFor3DConversion(pObj);
// convert completely to path objects
SdrObject* pNewObj1 = pObj->ConvertToPolyObj(FALSE, FALSE);
if(pNewObj1)
2000-09-18 16:07:07 +00:00
{
// change text color attribute for not so dark colors
if(pNewObj1->IsGroupObject())
2000-09-18 16:07:07 +00:00
{
SdrObjListIter aIter(*pNewObj1, IM_DEEPWITHGROUPS);
while(aIter.IsMore())
{
SdrObject* pGroupMember = aIter.Next();
ImpChangeSomeAttributesFor3DConversion2(pGroupMember);
}
2000-09-18 16:07:07 +00:00
}
else
ImpChangeSomeAttributesFor3DConversion2(pNewObj1);
2000-09-18 16:07:07 +00:00
// convert completely to path objects
SdrObject* pNewObj2 = pObj->ConvertToContourObj(pNewObj1, TRUE);
2000-09-18 16:07:07 +00:00
if(pNewObj2)
2000-09-18 16:07:07 +00:00
{
// add all to flat scene
if(pNewObj2->IsGroupObject())
{
SdrObjListIter aIter(*pNewObj2, IM_DEEPWITHGROUPS);
while(aIter.IsMore())
{
SdrObject* pGroupMember = aIter.Next();
ImpCreateSingle3DObjectFlat(pScene, pGroupMember, bExtrude, fDepth, rLatheMat);
}
}
else
ImpCreateSingle3DObjectFlat(pScene, pNewObj2, bExtrude, fDepth, rLatheMat);
2000-09-18 16:07:07 +00:00
// delete zwi object
if(pNewObj2 != pObj && pNewObj2 != pNewObj1 && pNewObj2)
delete pNewObj2;
}
2000-09-18 16:07:07 +00:00
// delete zwi object
if(pNewObj1 != pObj && pNewObj1)
delete pNewObj1;
}
2000-09-18 16:07:07 +00:00
}
}
/*************************************************************************
|*
|* 3D-Konvertierung zu Extrude steuern
|*
\************************************************************************/
void E3dView::ConvertMarkedObjTo3D(BOOL bExtrude, basegfx::B2DPoint aPnt1, basegfx::B2DPoint aPnt2)
2000-09-18 16:07:07 +00:00
{
if(AreObjectsMarked())
2000-09-18 16:07:07 +00:00
{
// Undo anlegen
if(bExtrude)
BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_EXTRUDE));
else
BegUndo(SVX_RESSTR(RID_SVX_3D_UNDO_LATHE));
// Neue Szene fuer zu erzeugende 3D-Objekte anlegen
E3dScene* pScene = new E3dPolyScene(Get3DDefaultAttributes());
// Rechteck bestimmen und evtl. korrigieren
Rectangle aRect = GetAllMarkedRect();
if(aRect.GetWidth() <= 1)
aRect.SetSize(Size(500, aRect.GetHeight()));
if(aRect.GetHeight() <= 1)
aRect.SetSize(Size(aRect.GetWidth(), 500));
// Tiefe relativ zur Groesse der Selektion bestimmen
double fDepth = 0.0;
double fRot3D = 0.0;
basegfx::B2DHomMatrix aLatheMat;
2000-09-18 16:07:07 +00:00
if(bExtrude)
{
double fW = (double)aRect.GetWidth();
double fH = (double)aRect.GetHeight();
fDepth = sqrt(fW*fW + fH*fH) / 6.0;
}
if(!bExtrude)
{
// Transformation fuer Polygone Rotationskoerper erstellen
if(aPnt1 != aPnt2)
{
// Rotation um Kontrollpunkt1 mit eigestelltem Winkel
// fuer 3D Koordinaten
basegfx::B2DPoint aDiff(aPnt1 - aPnt2);
fRot3D = atan2(aDiff.getY(), aDiff.getX()) - F_PI2;
2000-09-18 16:07:07 +00:00
if(fabs(fRot3D) < SMALL_DVALUE)
fRot3D = 0.0;
if(fRot3D != 0.0)
{
aLatheMat.translate(-aPnt2.getX(), -aPnt2.getY());
aLatheMat.rotate(-fRot3D);
aLatheMat.translate(aPnt2.getX(), aPnt2.getY());
2000-09-18 16:07:07 +00:00
}
}
if(aPnt2.getX() != 0.0)
2000-09-18 16:07:07 +00:00
{
// Translation auf Y=0 - Achse
aLatheMat.translate(-aPnt2.getX(), 0.0);
2000-09-18 16:07:07 +00:00
}
else
{
aLatheMat.translate((double)-aRect.Left(), 0.0);
2000-09-18 16:07:07 +00:00
}
// Inverse Matrix bilden, um die Zielausdehnung zu bestimmen
basegfx::B2DHomMatrix aInvLatheMat(aLatheMat);
aInvLatheMat.invert();
2000-09-18 16:07:07 +00:00
// SnapRect Ausdehnung mittels Spiegelung an der Rotationsachse
// erweitern
for(UINT32 a=0;a<GetMarkedObjectCount();a++)
2000-09-18 16:07:07 +00:00
{
SdrMark* pMark = GetSdrMarkByIndex(a);
SdrObject* pObj = pMark->GetMarkedSdrObj();
2000-09-18 16:07:07 +00:00
Rectangle aTurnRect = pObj->GetSnapRect();
basegfx::B2DPoint aRot;
2000-09-18 16:07:07 +00:00
Point aRotPnt;
aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Top());
2000-09-18 16:07:07 +00:00
aRot *= aLatheMat;
aRot.setX(-aRot.getX());
2000-09-18 16:07:07 +00:00
aRot *= aInvLatheMat;
aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
2000-09-18 16:07:07 +00:00
aRect.Union(Rectangle(aRotPnt, aRotPnt));
aRot = basegfx::B2DPoint(aTurnRect.Left(), -aTurnRect.Bottom());
2000-09-18 16:07:07 +00:00
aRot *= aLatheMat;
aRot.setX(-aRot.getX());
2000-09-18 16:07:07 +00:00
aRot *= aInvLatheMat;
aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
2000-09-18 16:07:07 +00:00
aRect.Union(Rectangle(aRotPnt, aRotPnt));
aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Top());
2000-09-18 16:07:07 +00:00
aRot *= aLatheMat;
aRot.setX(-aRot.getX());
2000-09-18 16:07:07 +00:00
aRot *= aInvLatheMat;
aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
2000-09-18 16:07:07 +00:00
aRect.Union(Rectangle(aRotPnt, aRotPnt));
aRot = basegfx::B2DPoint(aTurnRect.Right(), -aTurnRect.Bottom());
2000-09-18 16:07:07 +00:00
aRot *= aLatheMat;
aRot.setX(-aRot.getX());
2000-09-18 16:07:07 +00:00
aRot *= aInvLatheMat;
aRotPnt = Point((long)(aRot.getX() + 0.5), (long)(-aRot.getY() - 0.5));
2000-09-18 16:07:07 +00:00
aRect.Union(Rectangle(aRotPnt, aRotPnt));
}
}
// Ueber die Selektion gehen und in 3D wandeln, komplett mit
// Umwandeln in SdrPathObject, auch Schriften
for(UINT32 a=0;a<GetMarkedObjectCount();a++)
2000-09-18 16:07:07 +00:00
{
SdrMark* pMark = GetSdrMarkByIndex(a);
SdrObject* pObj = pMark->GetMarkedSdrObj();
2000-09-18 16:07:07 +00:00
ImpCreate3DObject(pScene, pObj, bExtrude, fDepth, aLatheMat);
}
if(pScene->GetSubList() && pScene->GetSubList()->GetObjCount() != 0)
{
// Alle angelegten Objekte Tiefenarrangieren
if(bExtrude)
DoDepthArrange(pScene, fDepth);
// 3D-Objekte auf die Mitte des Gesamtrechtecks zentrieren
basegfx::B3DPoint aCenter(pScene->GetCenter());
basegfx::B3DHomMatrix aMatrix;
2000-09-18 16:07:07 +00:00
aMatrix.translate(-aCenter.getX(), -aCenter.getY(), -aCenter.getZ());
pScene->SetTransform(aMatrix * pScene->GetTransform()); // #112587#
2000-09-18 16:07:07 +00:00
// Szene initialisieren
pScene->NbcSetSnapRect(aRect);
Volume3D aBoundVol = pScene->GetBoundVolume();
InitScene(pScene, (double)aRect.GetWidth(), (double)aRect.GetHeight(), aBoundVol.getDepth());
2000-09-18 16:07:07 +00:00
// Transformationen initialisieren, damit bei RecalcSnapRect()
// richtig gerechnet wird
pScene->InitTransformationSet();
// Szene anstelle des ersten selektierten Objektes einfuegen
// und alle alten Objekte weghauen
SdrObject* pRepObj = GetMarkedObjectByIndex(0);
SdrPageView* pPV = GetSdrPageViewOfMarkedByIndex(0);
2000-09-18 16:07:07 +00:00
MarkObj(pRepObj, pPV, TRUE);
ReplaceObjectAtView(pRepObj, *pPV, pScene, FALSE);
2000-09-18 16:07:07 +00:00
DeleteMarked();
MarkObj(pScene, pPV);
// Rotationskoerper um Rotationsachse drehen
if(!bExtrude && fRot3D != 0.0)
{
pScene->RotateZ(fRot3D);
}
// Default-Rotation setzen
double XRotateDefault = 20;
pScene->RotateX(DEG2RAD(XRotateDefault));
// SnapRects der Objekte ungueltig
pScene->CorrectSceneDimensions();
pScene->SetSnapRect(aRect);
}
else
{
// Es wurden keine 3D Objekte erzeugt, schmeiss alles weg
delete pScene;
}
// Undo abschliessen
EndUndo();
}
}
/*************************************************************************
|*
|* Alle enthaltenen Extrude-Objekte Tiefenarrangieren
|*
\************************************************************************/
struct E3dDepthNeighbour
{
E3dDepthNeighbour* pNext;
E3dExtrudeObj* pObj;
E3dDepthNeighbour() { pNext = NULL; pObj = NULL; }
};
struct E3dDepthLayer
{
E3dDepthLayer* pDown;
E3dDepthNeighbour* pNext;
E3dDepthLayer() { pDown = NULL; pNext = NULL; }
~E3dDepthLayer() { while(pNext) { E3dDepthNeighbour* pSucc = pNext->pNext; delete pNext; pNext = pSucc; }}
};
bool ImpDoesOverlap(const basegfx::B2DPolygon& rPolygonA, const basegfx::B2DPolygon& rPolygonB)
{
bool bRetval(false);
const basegfx::B2DRange aRangeA(basegfx::tools::getRange(rPolygonA));
const basegfx::B2DRange aRangeB(basegfx::tools::getRange(rPolygonB));
if(aRangeA.overlaps(aRangeB))
{
// A in B ?
if(basegfx::tools::isInside(rPolygonA, rPolygonB))
return true;
// B in A ?
if(basegfx::tools::isInside(rPolygonB, rPolygonA))
return true;
// A and B the same ?
if(basegfx::tools::isInside(rPolygonB, rPolygonA, true))
return true;
}
return bRetval;
}
bool ImpDoesOverlap(const basegfx::B2DPolyPolygon& rPolyPolygonA, const basegfx::B2DPolyPolygon& rPolyPolygonB)
{
bool bRetval(false);
const basegfx::B2DRange aRangeA(basegfx::tools::getRange(rPolyPolygonA));
const basegfx::B2DRange aRangeB(basegfx::tools::getRange(rPolyPolygonB));
if(aRangeA.overlaps(aRangeB))
{
const sal_uInt32 nCntA(rPolyPolygonA.count());
const sal_uInt32 nCntB(rPolyPolygonB.count());
for(sal_uInt32 a(0L); !bRetval && a < nCntA; a++)
{
const basegfx::B2DPolygon aPolygonA(rPolyPolygonA.getB2DPolygon(a));
if(aPolygonA.isClosed())
{
for(sal_uInt32 b(0L); !bRetval && b < nCntB; b++)
{
const basegfx::B2DPolygon aPolygonB(rPolyPolygonB.getB2DPolygon(b));
if(aPolygonB.isClosed())
{
bRetval = ImpDoesOverlap(aPolygonA, aPolygonB);
}
}
}
}
}
return bRetval;
}
2000-09-18 16:07:07 +00:00
void E3dView::DoDepthArrange(E3dScene* pScene, double fDepth)
{
if(pScene && pScene->GetSubList() && pScene->GetSubList()->GetObjCount() > 1)
{
SdrObjList* pSubList = pScene->GetSubList();
SdrObjListIter aIter(*pSubList, IM_FLAT);
E3dDepthLayer* pBaseLayer = NULL;
E3dDepthLayer* pLayer = NULL;
INT32 nNumLayers = 0;
//SfxItemPool& rPool = pMod->GetItemPool();
2000-09-18 16:07:07 +00:00
while(aIter.IsMore())
{
E3dObject* pSubObj = (E3dObject*)aIter.Next();
if(pSubObj && pSubObj->ISA(E3dExtrudeObj))
{
E3dExtrudeObj* pExtrudeObj = (E3dExtrudeObj*)pSubObj;
const basegfx::B2DPolyPolygon aExtrudePoly(pExtrudeObj->GetExtrudePolygon());
2000-09-18 16:07:07 +00:00
const SfxItemSet& rLocalSet = pExtrudeObj->GetMergedItemSet();
XFillStyle eLocalFillStyle = ITEMVALUE(rLocalSet, XATTR_FILLSTYLE, XFillStyleItem);
Color aLocalColor = ((const XFillColorItem&)(rLocalSet.Get(XATTR_FILLCOLOR))).GetColorValue();
2000-09-18 16:07:07 +00:00
// ExtrudeObj einordnen
if(pLayer)
{
// Gibt es eine Ueberschneidung mit einem Objekt dieses
// Layers?
BOOL bOverlap(FALSE);
E3dDepthNeighbour* pAct = pLayer->pNext;
while(!bOverlap && pAct)
{
// ueberlappen sich pAct->pObj und pExtrudeObj ?
const basegfx::B2DPolyPolygon aActPoly(pAct->pObj->GetExtrudePolygon());
bOverlap = ImpDoesOverlap(aExtrudePoly, aActPoly);
2000-09-18 16:07:07 +00:00
if(bOverlap)
{
// second ciriteria: is another fillstyle or color used?
const SfxItemSet& rCompareSet = pAct->pObj->GetMergedItemSet();
2000-09-18 16:07:07 +00:00
XFillStyle eCompareFillStyle = ITEMVALUE(rCompareSet, XATTR_FILLSTYLE, XFillStyleItem);
2000-09-18 16:07:07 +00:00
if(eLocalFillStyle == eCompareFillStyle)
{
if(eLocalFillStyle == XFILL_SOLID)
{
Color aCompareColor = ((const XFillColorItem&)(rCompareSet.Get(XATTR_FILLCOLOR))).GetColorValue();
2000-09-18 16:07:07 +00:00
if(aCompareColor == aLocalColor)
{
bOverlap = FALSE;
}
}
else if(eLocalFillStyle == XFILL_NONE)
{
bOverlap = FALSE;
}
}
}
pAct = pAct->pNext;
}
if(bOverlap)
{
// ja, beginne einen neuen Layer
pLayer->pDown = new E3dDepthLayer;
pLayer = pLayer->pDown;
nNumLayers++;
pLayer->pNext = new E3dDepthNeighbour;
pLayer->pNext->pObj = pExtrudeObj;
}
else
{
// nein, Objekt kann in aktuellen Layer
E3dDepthNeighbour* pNewNext = new E3dDepthNeighbour;
pNewNext->pObj = pExtrudeObj;
pNewNext->pNext = pLayer->pNext;
pLayer->pNext = pNewNext;
}
}
else
{
// erster Layer ueberhaupt
pBaseLayer = new E3dDepthLayer;
pLayer = pBaseLayer;
nNumLayers++;
pLayer->pNext = new E3dDepthNeighbour;
pLayer->pNext->pObj = pExtrudeObj;
}
}
}
// Anzahl Layer steht fest
if(nNumLayers > 1)
{
// Arrangement ist notwendig
double fMinDepth = fDepth * 0.8;
double fStep = (fDepth - fMinDepth) / (double)nNumLayers;
pLayer = pBaseLayer;
while(pLayer)
{
// an pLayer entlangspazieren
E3dDepthNeighbour* pAct = pLayer->pNext;
while(pAct)
{
// Anpassen
pAct->pObj->SetMergedItem(SfxUInt32Item(SDRATTR_3DOBJ_DEPTH, sal_uInt32(fMinDepth + 0.5)));
2000-09-18 16:07:07 +00:00
// Naechster Eintrag
pAct = pAct->pNext;
}
// naechster Layer
pLayer = pLayer->pDown;
fMinDepth += fStep;
}
}
// angelegte Strukturen aufraeumen
while(pBaseLayer)
{
pLayer = pBaseLayer->pDown;
delete pBaseLayer;
pBaseLayer = pLayer;
}
}
}
/*************************************************************************
|*
|* Drag beginnen, vorher ggf. Drag-Methode fuer 3D-Objekte erzeugen
|*
\************************************************************************/
BOOL E3dView::BegDragObj(const Point& rPnt, OutputDevice* pOut,
SdrHdl* pHdl, short nMinMov,
SdrDragMethod* pForcedMeth)
{
if(Is3DRotationCreationActive() && GetMarkedObjectCount())
2000-09-18 16:07:07 +00:00
{
// bestimme alle selektierten Polygone und gebe die gespiegelte Hilfsfigur aus
mpMirrorOverlay->SetMirrorAxis(aRef1, aRef2);
2000-09-18 16:07:07 +00:00
}
else
{
BOOL bOwnActionNecessary;
if (pHdl == NULL)
{
bOwnActionNecessary = TRUE;
}
else if (pHdl->IsVertexHdl() || pHdl->IsCornerHdl())
{
bOwnActionNecessary = TRUE;
}
else
{
bOwnActionNecessary = FALSE;
}
if(bOwnActionNecessary && GetMarkedObjectCount() >= 1)
2000-09-18 16:07:07 +00:00
{
E3dDragConstraint eConstraint = E3DDRAG_CONSTR_XYZ;
BOOL bThereAreRootScenes = FALSE;
BOOL bThereAre3DObjects = FALSE;
long nCnt = GetMarkedObjectCount();
2000-09-18 16:07:07 +00:00
for(long nObjs = 0;nObjs < nCnt;nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj)
{
if(pObj->ISA(E3dScene) && ((E3dScene*)pObj)->GetScene() == pObj)
bThereAreRootScenes = TRUE;
if(pObj->ISA(E3dObject))
bThereAre3DObjects = TRUE;
}
}
if( bThereAre3DObjects )
{
eDragHdl = ( pHdl == NULL ? HDL_MOVE : pHdl->GetKind() );
switch ( eDragMode )
{
case SDRDRAG_ROTATE:
case SDRDRAG_SHEAR:
{
switch ( eDragHdl )
{
case HDL_LEFT:
case HDL_RIGHT:
{
eConstraint = E3DDRAG_CONSTR_X;
}
break;
case HDL_UPPER:
case HDL_LOWER:
{
eConstraint = E3DDRAG_CONSTR_Y;
}
break;
case HDL_UPLFT:
case HDL_UPRGT:
case HDL_LWLFT:
case HDL_LWRGT:
{
eConstraint = E3DDRAG_CONSTR_Z;
}
break;
default: break;
2000-09-18 16:07:07 +00:00
}
// die nicht erlaubten Rotationen ausmaskieren
eConstraint = E3dDragConstraint(eConstraint& eDragConstraint);
pForcedMeth = new E3dDragRotate(*this, GetMarkedObjectList(), eConstraint,
2000-11-10 14:24:49 +00:00
SvtOptions3D().IsShowFull() );
2000-09-18 16:07:07 +00:00
}
break;
case SDRDRAG_MOVE:
{
if(!bThereAreRootScenes)
{
pForcedMeth = new E3dDragMove(*this, GetMarkedObjectList(), eDragHdl, eConstraint,
2000-11-10 14:24:49 +00:00
SvtOptions3D().IsShowFull() );
2000-09-18 16:07:07 +00:00
}
}
break;
// spaeter mal
case SDRDRAG_MIRROR:
case SDRDRAG_CROOK:
case SDRDRAG_DISTORT:
case SDRDRAG_TRANSPARENCE:
case SDRDRAG_GRADIENT:
default:
{
}
break;
}
}
}
}
return SdrView::BegDragObj(rPnt, pOut, pHdl, nMinMov, pForcedMeth);
}
/*************************************************************************
|*
|* Pruefen, obj 3D-Szene markiert ist
|*
\************************************************************************/
BOOL E3dView::HasMarkedScene()
{
return (GetMarkedScene() != NULL);
}
/*************************************************************************
|*
|* Pruefen, obj 3D-Szene markiert ist
|*
\************************************************************************/
E3dScene* E3dView::GetMarkedScene()
{
ULONG nCnt = GetMarkedObjectCount();
2000-09-18 16:07:07 +00:00
for ( ULONG i = 0; i < nCnt; i++ )
if ( GetMarkedObjectByIndex(i)->ISA(E3dScene) )
return (E3dScene*) GetMarkedObjectByIndex(i);
2000-09-18 16:07:07 +00:00
return NULL;
}
/*************************************************************************
|*
|* aktuelles 3D-Zeichenobjekt setzen, dafuer Szene erzeugen
|*
\************************************************************************/
E3dScene* E3dView::SetCurrent3DObj(E3dObject* p3DObj)
2000-09-18 16:07:07 +00:00
{
DBG_ASSERT(p3DObj != NULL, "Nana, wer steckt denn hier 'nen NULL-Zeiger rein?");
E3dScene* pScene = NULL;
// get transformed BoundVolume of the object
Volume3D aVolume;
const Volume3D& rObjVol = p3DObj->GetBoundVolume();
const basegfx::B3DHomMatrix& rObjTrans = p3DObj->GetTransform();
aVolume.expand(rObjVol.GetTransformVolume(rObjTrans));
double fW(aVolume.getWidth());
double fH(aVolume.getHeight());
2000-09-18 16:07:07 +00:00
Rectangle aRect(0,0, (long) fW, (long) fH);
pScene = new E3dPolyScene(Get3DDefaultAttributes());
InitScene(pScene, fW, fH, aVolume.getMaxZ() + ((fW + fH) / 4.0));
2000-09-18 16:07:07 +00:00
pScene->Insert3DObj(p3DObj);
pScene->NbcSetSnapRect(aRect);
return pScene;
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* neu erzeugte Szene initialisieren
|*
\************************************************************************/
void E3dView::InitScene(E3dScene* pScene, double fW, double fH, double fCamZ)
{
Camera3D aCam(pScene->GetCamera());
aCam.SetAutoAdjustProjection(FALSE);
aCam.SetViewWindow(- fW / 2, - fH / 2, fW, fH);
basegfx::B3DPoint aLookAt;
double fDefaultCamPosZ = GetDefaultCamPosZ();
basegfx::B3DPoint aCamPos(0.0, 0.0, fCamZ < fDefaultCamPosZ ? fDefaultCamPosZ : fCamZ);
2000-09-18 16:07:07 +00:00
aCam.SetPosAndLookAt(aCamPos, aLookAt);
aCam.SetFocalLength(GetDefaultCamFocal());
aCam.SetDefaults(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ), aLookAt, GetDefaultCamFocal());
2000-09-18 16:07:07 +00:00
pScene->SetCamera(aCam);
}
/*************************************************************************
|*
|* startsequenz fuer die erstellung eines 3D-Rotationskoerpers
|*
\************************************************************************/
void E3dView::Start3DCreation()
2000-09-18 16:07:07 +00:00
{
if (GetMarkedObjectCount())
2000-09-18 16:07:07 +00:00
{
// irgendwelche Markierungen ermitteln und ausschalten
//HMHBOOL bVis = IsMarkHdlShown();
2000-09-18 16:07:07 +00:00
//HMHif (bVis) HideMarkHdl();
2000-09-18 16:07:07 +00:00
// bestimme die koordinaten fuer JOEs Mirrorachse
// entgegen der normalen Achse wird diese an die linke Seite des Objektes
// positioniert
long nOutMin = 0;
long nOutMax = 0;
long nMinLen = 0;
long nObjDst = 0;
long nOutHgt = 0;
OutputDevice* pOut = GetFirstOutputDevice(); //GetWin(0);
2000-09-18 16:07:07 +00:00
// erstmal Darstellungsgrenzen bestimmen
if (pOut != NULL)
{
nMinLen = pOut->PixelToLogic(Size(0,50)).Height();
nObjDst = pOut->PixelToLogic(Size(0,20)).Height();
long nDst = pOut->PixelToLogic(Size(0,10)).Height();
nOutMin = -pOut->GetMapMode().GetOrigin().Y();
nOutMax = pOut->GetOutputSize().Height() - 1 + nOutMin;
nOutMin += nDst;
nOutMax -= nDst;
if (nOutMax - nOutMin < nDst)
{
nOutMin += nOutMax + 1;
nOutMin /= 2;
nOutMin -= (nDst + 1) / 2;
nOutMax = nOutMin + nDst;
}
nOutHgt = nOutMax - nOutMin;
long nTemp = nOutHgt / 4;
if (nTemp > nMinLen) nMinLen = nTemp;
}
// und dann die Markierungen oben und unten an das Objekt heften
basegfx::B2DRange aR;
for(sal_uInt32 nMark(0L); nMark < GetMarkedObjectCount(); nMark++)
2000-09-18 16:07:07 +00:00
{
SdrObject* pMark = GetMarkedObjectByIndex(nMark);
basegfx::B2DPolyPolygon aXPP(pMark->TakeXorPoly(FALSE));
aR.expand(basegfx::tools::getRange(aXPP));
2000-09-18 16:07:07 +00:00
}
basegfx::B2DPoint aCenter(aR.getCenter());
long nMarkHgt = FRound(aR.getHeight()) - 1;
2000-09-18 16:07:07 +00:00
long nHgt = nMarkHgt + nObjDst * 2;
if (nHgt < nMinLen) nHgt = nMinLen;
long nY1 = FRound(aCenter.getY()) - (nHgt + 1) / 2;
2000-09-18 16:07:07 +00:00
long nY2 = nY1 + nHgt;
if (pOut && (nMinLen > nOutHgt)) nMinLen = nOutHgt;
if (pOut)
{
if (nY1 < nOutMin)
{
nY1 = nOutMin;
if (nY2 < nY1 + nMinLen) nY2 = nY1 + nMinLen;
}
if (nY2 > nOutMax)
{
nY2 = nOutMax;
if (nY1 > nY2 - nMinLen) nY1 = nY2 - nMinLen;
}
}
aRef1.X() = FRound(aR.getMinX()); // Initial Achse um 2/100mm nach links
2000-09-18 16:07:07 +00:00
aRef1.Y() = nY1;
aRef2.X() = aRef1.X();
aRef2.Y() = nY2;
// Markierungen einschalten
SetMarkHandles();
//HMHif (bVis) ShowMarkHdl();
if (AreObjectsMarked()) MarkListHasChanged();
2000-09-18 16:07:07 +00:00
// SpiegelPolygone SOFORT zeigen
const SdrHdlList &aHdlList = GetHdlList();
mpMirrorOverlay = new Impl3DMirrorConstructOverlay(*this);
mpMirrorOverlay->SetMirrorAxis(aHdlList.GetHdl(HDL_REF1)->GetPos(), aHdlList.GetHdl(HDL_REF2)->GetPos());
//CreateMirrorPolygons ();
//ShowMirrorPolygons (aHdlList.GetHdl (HDL_REF1)->GetPos (),
// aHdlList.GetHdl (HDL_REF2)->GetPos ());
2000-09-18 16:07:07 +00:00
}
}
/*************************************************************************
|*
|* was passiert bei einer Mausbewegung, wenn das Objekt erstellt wird ?
|*
\************************************************************************/
void E3dView::MovAction(const Point& rPnt)
{
if(Is3DRotationCreationActive())
2000-09-18 16:07:07 +00:00
{
SdrHdl* pHdl = GetDragHdl();
if (pHdl)
{
SdrHdlKind eHdlKind = pHdl->GetKind();
// reagiere nur bei einer spiegelachse
if ((eHdlKind == HDL_REF1) ||
(eHdlKind == HDL_REF2) ||
(eHdlKind == HDL_MIRX))
{
const SdrHdlList &aHdlList = GetHdlList ();
// loesche das gespiegelte Polygon, spiegele das Original und zeichne es neu
//ShowMirrored ();
2000-09-18 16:07:07 +00:00
SdrView::MovAction (rPnt);
mpMirrorOverlay->SetMirrorAxis(
aHdlList.GetHdl (HDL_REF1)->GetPos(),
aHdlList.GetHdl (HDL_REF2)->GetPos());
2000-09-18 16:07:07 +00:00
}
}
else
{
SdrView::MovAction (rPnt);
}
}
else
{
SdrView::MovAction (rPnt);
}
}
/*************************************************************************
|*
|* Schluss. Objekt und evtl. Unterobjekte ueber ImpCreate3DLathe erstellen
|* [FG] Mit dem Parameterwert TRUE (SDefault: FALSE) wird einfach ein
|* Rotationskoerper erzeugt, ohne den Benutzer die Lage der
|* Achse fetlegen zu lassen. Es reicht dieser Aufruf, falls
|* ein Objekt selektiert ist. (keine Initialisierung noetig)
|*
\************************************************************************/
void E3dView::End3DCreation(BOOL bUseDefaultValuesForMirrorAxes)
{
ResetCreationActive();
if(AreObjectsMarked())
2000-09-18 16:07:07 +00:00
{
if(bUseDefaultValuesForMirrorAxes)
{
Rectangle aRect = GetAllMarkedRect();
if(aRect.GetWidth() <= 1)
aRect.SetSize(Size(500, aRect.GetHeight()));
if(aRect.GetHeight() <= 1)
aRect.SetSize(Size(aRect.GetWidth(), 500));
basegfx::B2DPoint aPnt1(aRect.Left(), -aRect.Top());
basegfx::B2DPoint aPnt2(aRect.Left(), -aRect.Bottom());
2000-09-18 16:07:07 +00:00
ConvertMarkedObjTo3D(FALSE, aPnt1, aPnt2);
}
else
{
// Hilfsfigur ausschalten
// bestimme aus den Handlepositionen und den Versatz der Punkte
const SdrHdlList &aHdlList = GetHdlList();
Point aMirrorRef1 = aHdlList.GetHdl(HDL_REF1)->GetPos();
Point aMirrorRef2 = aHdlList.GetHdl(HDL_REF2)->GetPos();
basegfx::B2DPoint aPnt1(aMirrorRef1.X(), -aMirrorRef1.Y());
basegfx::B2DPoint aPnt2(aMirrorRef2.X(), -aMirrorRef2.Y());
2000-09-18 16:07:07 +00:00
ConvertMarkedObjTo3D(FALSE, aPnt1, aPnt2);
}
}
}
/*************************************************************************
|*
|* Destruktor
|*
\************************************************************************/
E3dView::~E3dView ()
{
}
/*************************************************************************
|*
|* beende das erzeugen und loesche die polygone
|*
\************************************************************************/
void E3dView::ResetCreationActive ()
{
if(mpMirrorOverlay)
{
delete mpMirrorOverlay;
mpMirrorOverlay = 0L;
}
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* Klasse initialisieren
|*
\************************************************************************/
void E3dView::InitView ()
{
eDragConstraint = E3DDRAG_CONSTR_XYZ;
fDefaultScaleX =
fDefaultScaleY =
fDefaultScaleZ = 1.0;
fDefaultRotateX =
fDefaultRotateY =
fDefaultRotateZ = 0.0;
fDefaultExtrusionDeepth = 1000; // old: 2000;
fDefaultLightIntensity = 0.8; // old: 0.6;
fDefaultAmbientIntensity = 0.4;
nHDefaultSegments = 12;
nVDefaultSegments = 12;
aDefaultLightColor = RGB_Color(COL_WHITE);
aDefaultAmbientColor = RGB_Color(COL_BLACK);
bDoubleSided = FALSE;
mpMirrorOverlay = 0L;
2000-09-18 16:07:07 +00:00
}
/*************************************************************************
|*
|* Koennen die selektierten Objekte aufgebrochen werden?
|*
\************************************************************************/
BOOL E3dView::IsBreak3DObjPossible() const
{
ULONG nCount = GetMarkedObjectCount();
2000-09-18 16:07:07 +00:00
if (nCount > 0)
{
ULONG i = 0;
while (i < nCount)
{
SdrObject* pObj = GetMarkedObjectByIndex(i);
2000-09-18 16:07:07 +00:00
if (pObj && pObj->ISA(E3dObject))
{
if(!(((E3dObject*)pObj)->IsBreakObjPossible()))
return FALSE;
}
else
{
return FALSE;
}
i++;
}
}
else
{
return FALSE;
}
return TRUE;
}
/*************************************************************************
|*
|* Selektierte Lathe-Objekte aufbrechen
|*
\************************************************************************/
void E3dView::Break3DObj()
{
if(IsBreak3DObjPossible())
{
// ALLE selektierten Objekte werden gewandelt
UINT32 nCount = GetMarkedObjectCount();
2000-09-18 16:07:07 +00:00
BegUndo(String(SVX_RESSTR(RID_SVX_3D_UNDO_BREAK_LATHE)));
for(UINT32 a=0;a<nCount;a++)
{
E3dObject* pObj = (E3dObject*)GetMarkedObjectByIndex(a);
2000-09-18 16:07:07 +00:00
BreakSingle3DObj(pObj);
}
DeleteMarked();
EndUndo();
}
}
void E3dView::BreakSingle3DObj(E3dObject* pObj)
{
if(pObj->ISA(E3dScene))
{
SdrObjList* pSubList = pObj->GetSubList();
SdrObjListIter aIter(*pSubList, IM_FLAT);
while(aIter.IsMore())
{
E3dObject* pSubObj = (E3dObject*)aIter.Next();
BreakSingle3DObj(pSubObj);
}
}
else
{
SdrAttrObj* pNewObj = pObj->GetBreakObj();
if(pNewObj)
{
InsertObjectAtView(pNewObj, *GetSdrPageView(), SDRINSERT_DONTMARK);
pNewObj->SetChanged();
pNewObj->BroadcastObjectChange();
2000-09-18 16:07:07 +00:00
}
}
}
/*************************************************************************
|*
|* Szenen mischen
|*
\************************************************************************/
void E3dView::MergeScenes ()
{
ULONG nCount = GetMarkedObjectCount();
2000-09-18 16:07:07 +00:00
if (nCount > 0)
{
ULONG nObj = 0;
SdrObject *pObj = GetMarkedObjectByIndex(nObj);
2000-09-18 16:07:07 +00:00
E3dScene *pScene = new E3dPolyScene(Get3DDefaultAttributes());
Volume3D aBoundVol;
Rectangle aAllBoundRect (GetMarkedObjBoundRect ());
Point aCenter (aAllBoundRect.Center());
while (pObj)
{
if (pObj->ISA(E3dScene))
{
/**********************************************************
* Es ist eine 3D-Scene oder 3D-PolyScene
**********************************************************/
SdrObjList* pSubList = ((E3dObject*) pObj)->GetSubList();
SdrObjListIter aIter(*pSubList, IM_FLAT);
while (aIter.IsMore())
{
/******************************************************
* LatheObjekte suchen
******************************************************/
SdrObject* pSubObj = aIter.Next();
E3dObject *pNewObj = 0;
switch (pSubObj->GetObjIdentifier())
{
case E3D_OBJECT_ID:
pNewObj = new E3dObject;
*(E3dObject*)pNewObj = *(E3dObject*)pSubObj;
break;
case E3D_CUBEOBJ_ID :
pNewObj = new E3dCubeObj;
*(E3dCubeObj*)pNewObj = *(E3dCubeObj*)pSubObj;
break;
case E3D_SPHEREOBJ_ID:
pNewObj = new E3dSphereObj;
*(E3dSphereObj*)pNewObj = *(E3dSphereObj*)pSubObj;
break;
case E3D_POINTOBJ_ID:
pNewObj = new E3dPointObj;
*(E3dPointObj*)pNewObj = *(E3dPointObj*)pSubObj;
break;
case E3D_EXTRUDEOBJ_ID:
pNewObj = new E3dExtrudeObj;
*(E3dExtrudeObj*)pNewObj = *(E3dExtrudeObj*)pSubObj;
break;
case E3D_LATHEOBJ_ID:
pNewObj = new E3dLatheObj;
*(E3dLatheObj*)pNewObj = *(E3dLatheObj*)pSubObj;
break;
case E3D_LABELOBJ_ID:
pNewObj = new E3dLabelObj;
*(E3dLabelObj*)pNewObj = *(E3dLabelObj*)pSubObj;
break;
case E3D_COMPOUNDOBJ_ID:
pNewObj = new E3dCompoundObject;
*(E3dCompoundObject*)pNewObj = *(E3dCompoundObject*)pSubObj;
break;
}
Rectangle aBoundRect = pSubObj->GetCurrentBoundRect();
2000-09-18 16:07:07 +00:00
basegfx::B3DHomMatrix aMatrix;
aMatrix.translate(aBoundRect.Left() - aCenter.getX(), aCenter.getY(), 0.0);
pNewObj->SetTransform(aMatrix * pNewObj->GetTransform()); // #112587#
2000-09-18 16:07:07 +00:00
if (pNewObj) aBoundVol.expand(pNewObj->GetBoundVolume());
2000-09-18 16:07:07 +00:00
pScene->Insert3DObj (pNewObj);
}
}
nObj++;
if (nObj < nCount)
{
pObj = GetMarkedObjectByIndex(nObj);
2000-09-18 16:07:07 +00:00
}
else
{
pObj = NULL;
}
}
double fW = aAllBoundRect.GetWidth();
double fH = aAllBoundRect.GetHeight();
Rectangle aRect(0,0, (long) fW, (long) fH);
InitScene(pScene, fW, fH, aBoundVol.getMaxZ() + + ((fW + fH) / 4.0));
2000-09-18 16:07:07 +00:00
pScene->FitSnapRectToBoundVol();
pScene->NbcSetSnapRect(aRect);
Camera3D &aCamera = (Camera3D&) pScene->GetCamera ();
basegfx::B3DPoint aMinVec(aBoundVol.getMinimum());
basegfx::B3DPoint aMaxVec(aBoundVol.getMaximum());
double fDeepth(fabs(aMaxVec.getZ() - aMinVec.getZ()));
2000-09-18 16:07:07 +00:00
aCamera.SetPRP(basegfx::B3DPoint(0.0, 0.0, 1000.0));
double fDefaultCamPosZ(GetDefaultCamPosZ());
aCamera.SetPosition(basegfx::B3DPoint(0.0, 0.0, fDefaultCamPosZ + fDeepth / 2.0));
aCamera.SetFocalLength(GetDefaultCamFocal());
2000-09-18 16:07:07 +00:00
pScene->SetCamera (aCamera);
// SnapRects der Objekte ungueltig
pScene->SetRectsDirty();
// Transformationen initialisieren, damit bei RecalcSnapRect()
// richtig gerechnet wird
pScene->InitTransformationSet();
InsertObjectAtView(pScene, *(GetSdrPageViewOfMarkedByIndex(0)));
2000-09-18 16:07:07 +00:00
// SnapRects der Objekte ungueltig
pScene->SetRectsDirty();
}
}
/*************************************************************************
|*
|* Possibilities, hauptsaechlich gruppieren/ungruppieren
|*
\************************************************************************/
void E3dView::CheckPossibilities()
{
// call parent
SdrView::CheckPossibilities();
// Weitere Flags bewerten
if(bGroupPossible || bUnGroupPossible || bGrpEnterPossible)
{
INT32 nMarkCnt = GetMarkedObjectCount();
2000-09-18 16:07:07 +00:00
BOOL bCoumpound = FALSE;
BOOL b3DObject = FALSE;
for(INT32 nObjs = 0L; (nObjs < nMarkCnt) && !bCoumpound; nObjs++)
{
SdrObject *pObj = GetMarkedObjectByIndex(nObjs);
2000-09-18 16:07:07 +00:00
if(pObj && pObj->ISA(E3dCompoundObject))
bCoumpound = TRUE;
if(pObj && pObj->ISA(E3dObject))
b3DObject = TRUE;
}
// Bisher: Es sind ZWEI oder mehr beliebiger Objekte selektiert.
// Nachsehen, ob CompoundObjects beteiligt sind. Falls ja,
// das Gruppieren verbieten.
if(bGroupPossible && bCoumpound)
bGroupPossible = FALSE;
if(bUnGroupPossible && b3DObject)
bUnGroupPossible = FALSE;
if(bGrpEnterPossible && bCoumpound)
bGrpEnterPossible = FALSE;
}
}
// eof