xref: /aoo42x/main/svx/source/engine3d/scene3d.cxx (revision 437a6594)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include "svx/svdstr.hrc"
28 #include "svx/svdglob.hxx"
29 #include "svx/svditer.hxx"
30 
31 #if defined( UNX ) || defined( ICC )
32 #include <stdlib.h>
33 #endif
34 #include "svx/globl3d.hxx"
35 #include <svx/svdpage.hxx>
36 #include <svl/style.hxx>
37 #include <svx/scene3d.hxx>
38 #include <svx/e3dundo.hxx>
39 #include <svx/svdtrans.hxx>
40 #include <svx/svxids.hrc>
41 #include <editeng/colritem.hxx>
42 #include <svx/e3ditem.hxx>
43 #include <svx/xlntrit.hxx>
44 #include <svx/xfltrit.hxx>
45 #include <svx/svx3ditems.hxx>
46 #include <svl/whiter.hxx>
47 #include <svx/xflftrit.hxx>
48 #include <svx/sdr/properties/e3dsceneproperties.hxx>
49 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
50 #include <svx/svddrag.hxx>
51 #include <helperminimaldepth3d.hxx>
52 #include <algorithm>
53 #include <drawinglayer/geometry/viewinformation3d.hxx>
54 #include <basegfx/polygon/b2dpolypolygontools.hxx>
55 #include <svx/e3dsceneupdater.hxx>
56 #include <svx/svdmodel.hxx>
57 
58 #define ITEMVALUE(ItemSet,Id,Cast)	((const Cast&)(ItemSet).Get(Id)).GetValue()
59 
60 //////////////////////////////////////////////////////////////////////////////
61 // #110988#
62 
63 class ImpRemap3DDepth
64 {
65 	sal_uInt32					mnOrdNum;
66 	double						mfMinimalDepth;
67 
68 	// bitfield
69 	unsigned					mbIsScene : 1;
70 
71 public:
72 	ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth);
73 	ImpRemap3DDepth(sal_uInt32 nOrdNum);
74 	~ImpRemap3DDepth();
75 
76 	// for ::std::sort
77 	bool operator<(const ImpRemap3DDepth& rComp) const;
78 
GetOrdNum() const79 	sal_uInt32 GetOrdNum() const { return mnOrdNum; }
IsScene() const80 	sal_Bool IsScene() const { return mbIsScene; }
81 };
82 
ImpRemap3DDepth(sal_uInt32 nOrdNum,double fMinimalDepth)83 ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum, double fMinimalDepth)
84 :	mnOrdNum(nOrdNum),
85 	mfMinimalDepth(fMinimalDepth),
86 	mbIsScene(sal_False)
87 {
88 }
89 
ImpRemap3DDepth(sal_uInt32 nOrdNum)90 ImpRemap3DDepth::ImpRemap3DDepth(sal_uInt32 nOrdNum)
91 :	mnOrdNum(nOrdNum),
92 	mbIsScene(sal_True)
93 {
94 }
95 
~ImpRemap3DDepth()96 ImpRemap3DDepth::~ImpRemap3DDepth()
97 {
98 }
99 
operator <(const ImpRemap3DDepth & rComp) const100 bool ImpRemap3DDepth::operator<(const ImpRemap3DDepth& rComp) const
101 {
102 	if(IsScene())
103 	{
104 		return sal_False;
105 	}
106 	else
107 	{
108 		if(rComp.IsScene())
109 		{
110 			return sal_True;
111 		}
112 		else
113 		{
114 			return mfMinimalDepth < rComp.mfMinimalDepth;
115 		}
116 	}
117 }
118 
119 // typedefs for a vector of ImpRemap3DDepths
120 typedef ::std::vector< ImpRemap3DDepth > ImpRemap3DDepthVector;
121 
122 //////////////////////////////////////////////////////////////////////////////
123 // #110988#
124 
125 class Imp3DDepthRemapper
126 {
127 	ImpRemap3DDepthVector		maVector;
128 
129 public:
130 	Imp3DDepthRemapper(E3dScene& rScene);
131 	~Imp3DDepthRemapper();
132 
133 	sal_uInt32 RemapOrdNum(sal_uInt32 nOrdNum) const;
134 };
135 
Imp3DDepthRemapper(E3dScene & rScene)136 Imp3DDepthRemapper::Imp3DDepthRemapper(E3dScene& rScene)
137 {
138 	// only called when rScene.GetSubList() and nObjCount > 1L
139 	SdrObjList* pList = rScene.GetSubList();
140 	const sal_uInt32 nObjCount(pList->GetObjCount());
141 
142 	for(sal_uInt32 a(0L); a < nObjCount; a++)
143 	{
144 		SdrObject* pCandidate = pList->GetObj(a);
145 
146 		if(pCandidate)
147 		{
148 			if(pCandidate->ISA(E3dCompoundObject))
149 			{
150 				// single 3d object, calc depth
151                 const double fMinimalDepth(getMinimalDepthInViewCoordinates(static_cast< const E3dCompoundObject& >(*pCandidate)));
152 				ImpRemap3DDepth aEntry(a, fMinimalDepth);
153 				maVector.push_back(aEntry);
154 			}
155 			else
156 			{
157 				// scene, use standard entry for scene
158 				ImpRemap3DDepth aEntry(a);
159 				maVector.push_back(aEntry);
160 			}
161 		}
162 	}
163 
164 	// now, we need to sort the maVector by it's members minimal depth. The
165 	// smaller, the nearer to the viewer.
166 	::std::sort(maVector.begin(), maVector.end());
167 }
168 
~Imp3DDepthRemapper()169 Imp3DDepthRemapper::~Imp3DDepthRemapper()
170 {
171 }
172 
RemapOrdNum(sal_uInt32 nOrdNum) const173 sal_uInt32 Imp3DDepthRemapper::RemapOrdNum(sal_uInt32 nOrdNum) const
174 {
175 	if(nOrdNum < maVector.size())
176 	{
177 		nOrdNum = maVector[(maVector.size() - 1) - nOrdNum].GetOrdNum();
178 	}
179 
180 	return nOrdNum;
181 }
182 
183 //////////////////////////////////////////////////////////////////////////////
184 // BaseProperties section
185 
CreateObjectSpecificProperties()186 sdr::properties::BaseProperties* E3dScene::CreateObjectSpecificProperties()
187 {
188 	return new sdr::properties::E3dSceneProperties(*this);
189 }
190 
191 //////////////////////////////////////////////////////////////////////////////
192 // #110094# DrawContact section
193 
CreateObjectSpecificViewContact()194 sdr::contact::ViewContact* E3dScene::CreateObjectSpecificViewContact()
195 {
196 	return new sdr::contact::ViewContactOfE3dScene(*this);
197 }
198 
199 ////////////////////////////////////////////////////////////////////////////////////////////////////
200 
201 TYPEINIT1(E3dScene, E3dObject);
202 
203 /*************************************************************************
204 |*
205 |* E3dScene-Konstruktor
206 |*
207 \************************************************************************/
208 
E3dScene()209 E3dScene::E3dScene()
210 :	E3dObject(),
211 	aCamera(basegfx::B3DPoint(0.0, 0.0, 4.0), basegfx::B3DPoint()),
212 	mp3DDepthRemapper(0L),
213 	bDrawOnlySelected(false)
214 {
215 	// Defaults setzen
216 	E3dDefaultAttributes aDefault;
217 	SetDefaultAttributes(aDefault);
218 }
219 
E3dScene(E3dDefaultAttributes & rDefault)220 E3dScene::E3dScene(E3dDefaultAttributes& rDefault)
221 :	E3dObject(),
222 	aCamera(basegfx::B3DPoint(0.0, 0.0, 4.0), basegfx::B3DPoint()),
223 	mp3DDepthRemapper(0L),
224 	bDrawOnlySelected(false)
225 {
226 	// Defaults setzen
227 	SetDefaultAttributes(rDefault);
228 }
229 
SetDefaultAttributes(E3dDefaultAttributes &)230 void E3dScene::SetDefaultAttributes(E3dDefaultAttributes& /*rDefault*/)
231 {
232 	// Fuer OS/2 die FP-Exceptions abschalten
233 #if defined(OS2)
234 #define SC_FPEXCEPTIONS_ON()	_control87( MCW_EM, 0 )
235 #define SC_FPEXCEPTIONS_OFF()	_control87( MCW_EM, MCW_EM )
236 	SC_FPEXCEPTIONS_OFF();
237 #endif
238 
239 	// Fuer WIN95/NT die FP-Exceptions abschalten
240 #if defined(WNT)
241 #define SC_FPEXCEPTIONS_ON()	_control87( _MCW_EM, 0 )
242 #define SC_FPEXCEPTIONS_OFF()	_control87( _MCW_EM, _MCW_EM )
243 	SC_FPEXCEPTIONS_OFF();
244 #endif
245 
246 	// Defaults setzen
247 	aCamera.SetViewWindow(-2, -2, 4, 4);
248 	aCameraSet.SetDeviceRectangle(-2, 2, -2, 2);
249 	aCamera.SetDeviceWindow(Rectangle(0, 0, 10, 10));
250 	Rectangle aRect(0, 0, 10, 10);
251 	aCameraSet.SetViewportRectangle(aRect);
252 
253 	// set defaults for Camera from ItemPool
254 	aCamera.SetProjection(GetPerspective());
255 	basegfx::B3DPoint aActualPosition(aCamera.GetPosition());
256 	double fNew = GetDistance();
257 
258 	if(fabs(fNew - aActualPosition.getZ()) > 1.0)
259 	{
260 		aCamera.SetPosition( basegfx::B3DPoint( aActualPosition.getX(), aActualPosition.getY(), fNew) );
261 	}
262 
263 	fNew = GetFocalLength() / 100.0;
264 	aCamera.SetFocalLength(fNew);
265 }
266 
267 /*************************************************************************
268 |*
269 |* Destruktor
270 |*
271 \************************************************************************/
272 
~E3dScene()273 E3dScene::~E3dScene()
274 {
275 	// #110988#
276 	ImpCleanup3DDepthMapper();
277 }
278 
TakeXorPoly() const279 basegfx::B2DPolyPolygon E3dScene::TakeXorPoly() const
280 {
281 	const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(GetViewContact());
282 	const drawinglayer::geometry::ViewInformation3D aViewInfo3D(rVCScene.getViewInformation3D());
283 	const basegfx::B3DPolyPolygon aCubePolyPolygon(CreateWireframe());
284 
285 	basegfx::B2DPolyPolygon aRetval(basegfx::tools::createB2DPolyPolygonFromB3DPolyPolygon(aCubePolyPolygon,
286 		aViewInfo3D.getObjectToView()));
287 	aRetval.transform(rVCScene.getObjectTransformation());
288 
289 	return aRetval;
290 }
291 
292 // #110988#
ImpCleanup3DDepthMapper()293 void E3dScene::ImpCleanup3DDepthMapper()
294 {
295 	if(mp3DDepthRemapper)
296 	{
297 		delete mp3DDepthRemapper;
298 		mp3DDepthRemapper = 0L;
299 	}
300 }
301 
302 // #110988#
RemapOrdNum(sal_uInt32 nNewOrdNum) const303 sal_uInt32 E3dScene::RemapOrdNum(sal_uInt32 nNewOrdNum) const
304 {
305 	if(!mp3DDepthRemapper)
306 	{
307 		const sal_uInt32 nObjCount(GetSubList() ? GetSubList()->GetObjCount() : 0L);
308 
309 		if(nObjCount > 1L)
310 		{
311 			((E3dScene*)this)->mp3DDepthRemapper = new Imp3DDepthRemapper((E3dScene&)(*this));
312 		}
313 	}
314 
315 	if(mp3DDepthRemapper)
316 	{
317 		return mp3DDepthRemapper->RemapOrdNum(nNewOrdNum);
318 	}
319 
320 	return nNewOrdNum;
321 }
322 
323 /*************************************************************************
324 |*
325 |* Identifier zurueckgeben
326 |*
327 \************************************************************************/
328 
GetObjIdentifier() const329 sal_uInt16 E3dScene::GetObjIdentifier() const
330 {
331 	return E3D_SCENE_ID;
332 }
333 
SetBoundRectDirty()334 void E3dScene::SetBoundRectDirty()
335 {
336 	E3dScene* pScene = GetScene();
337 
338 	if(pScene == this)
339 	{
340 	    // avoid resetting aOutRect which in case of a 3D scene used as 2d object
341 		// is model data,not re-creatable view data
342 	}
343 	else
344 	{
345 		// if not the outmost scene it is used as group in 3d, call parent
346 		E3dObject::SetBoundRectDirty();
347 	}
348 }
349 
350 /*************************************************************************
351 |*
352 |* SetSnapRect
353 |*
354 \************************************************************************/
355 
NbcSetSnapRect(const Rectangle & rRect)356 void E3dScene::NbcSetSnapRect(const Rectangle& rRect)
357 {
358 	SetRectsDirty();
359 	E3dObject::NbcSetSnapRect(rRect);
360 	aCamera.SetDeviceWindow(rRect);
361 	aCameraSet.SetViewportRectangle((Rectangle&)rRect);
362 
363 	// #110988#
364 	ImpCleanup3DDepthMapper();
365 }
366 
367 /*************************************************************************
368 |*
369 |* Objekt verschieben
370 |*
371 \************************************************************************/
372 
NbcMove(const Size & rSize)373 void E3dScene::NbcMove(const Size& rSize)
374 {
375 	Rectangle aNewSnapRect = GetSnapRect();
376 	MoveRect(aNewSnapRect, rSize);
377 	NbcSetSnapRect(aNewSnapRect);
378 }
379 
380 /*************************************************************************
381 |*
382 |* Objekt Resizen
383 |*
384 \************************************************************************/
385 
NbcResize(const Point & rRef,const Fraction & rXFact,const Fraction & rYFact)386 void E3dScene::NbcResize(const Point& rRef, const Fraction& rXFact,
387 											const Fraction& rYFact)
388 {
389 	Rectangle aNewSnapRect = GetSnapRect();
390 	ResizeRect(aNewSnapRect, rRef, rXFact, rYFact);
391 	NbcSetSnapRect(aNewSnapRect);
392 }
393 
394 /*************************************************************************
395 |*
396 |* Neue Kamera setzen, und dabei die Szene und ggf. das BoundVolume
397 |* als geaendert markieren
398 |*
399 \************************************************************************/
400 
SetCamera(const Camera3D & rNewCamera)401 void E3dScene::SetCamera(const Camera3D& rNewCamera)
402 {
403 	// Alte Kamera setzen
404 	aCamera = rNewCamera;
405 	((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera();
406 
407 	SetRectsDirty();
408 
409 	// Neue Kamera aus alter fuellen
410 	Camera3D& rCam = (Camera3D&)GetCamera();
411 
412 	// Ratio abschalten
413 	if(rCam.GetAspectMapping() == AS_NO_MAPPING)
414 		GetCameraSet().SetRatio(0.0);
415 
416 	// Abbildungsgeometrie setzen
417 	basegfx::B3DPoint aVRP(rCam.GetViewPoint());
418 	basegfx::B3DVector aVPN(aVRP - rCam.GetVRP());
419 	basegfx::B3DVector aVUV(rCam.GetVUV());
420 
421 	// #91047# use SetViewportValues() to set VRP, VPN and VUV as vectors, too.
422 	// Else these values would not be exported/imported correctly.
423 	GetCameraSet().SetViewportValues(aVRP, aVPN, aVUV);
424 
425 	// Perspektive setzen
426 	GetCameraSet().SetPerspective(rCam.GetProjection() == PR_PERSPECTIVE);
427 	GetCameraSet().SetViewportRectangle((Rectangle&)rCam.GetDeviceWindow());
428 
429 	// #110988#
430 	ImpCleanup3DDepthMapper();
431 }
432 
433 /*************************************************************************
434 |*
435 |* 3D-Objekt einfuegen
436 |*
437 \************************************************************************/
438 
NewObjectInserted(const E3dObject * p3DObj)439 void E3dScene::NewObjectInserted(const E3dObject* p3DObj)
440 {
441 	E3dObject::NewObjectInserted(p3DObj);
442 
443 	if ( p3DObj == this )
444 		return;
445 
446 	// #110988#
447 	ImpCleanup3DDepthMapper();
448 }
449 
450 /*************************************************************************
451 |*
452 |* Parent ueber Aenderung eines Childs informieren
453 |*
454 \************************************************************************/
455 
StructureChanged()456 void E3dScene::StructureChanged()
457 {
458 	E3dObject::StructureChanged();
459 
460     if(!GetModel() || !GetModel()->isLocked())
461     {
462         // #123539# optimization for 3D chart object generation: do not reset
463         // already calculated scene projection data every time an object gets
464         // initialized
465         SetRectsDirty();
466     }
467 
468 	// #110988#
469 	ImpCleanup3DDepthMapper();
470 }
471 
472 /*************************************************************************
473 |*
474 |* Uebergeordnetes Szenenobjekt bestimmen
475 |*
476 \************************************************************************/
477 
GetScene() const478 E3dScene* E3dScene::GetScene() const
479 {
480 	if(GetParentObj())
481 		return GetParentObj()->GetScene();
482 	else
483 		return (E3dScene*)this;
484 }
485 
removeAllNonSelectedObjects()486 void E3dScene::removeAllNonSelectedObjects()
487 {
488 	E3DModifySceneSnapRectUpdater aUpdater(this);
489 
490     for(sal_uInt32 a(0); a < maSubList.GetObjCount(); a++)
491     {
492 		SdrObject* pObj = maSubList.GetObj(a);
493 
494         if(pObj)
495 		{
496             bool bRemoveObject(false);
497 
498             if(pObj->ISA(E3dScene))
499             {
500                 E3dScene* pScene = (E3dScene*)pObj;
501 
502                 // iterate over this sub-scene
503                 pScene->removeAllNonSelectedObjects();
504 
505                 // check object count. Empty scenes can be deleted
506                 const sal_uInt32 nObjCount(pScene->GetSubList() ? pScene->GetSubList()->GetObjCount() : 0);
507 
508                 if(!nObjCount)
509 			    {
510                     // all objects removed, scene can be removed, too
511                     bRemoveObject = true;
512 			    }
513 			}
514             else if(pObj->ISA(E3dCompoundObject))
515 			{
516                 E3dCompoundObject* pCompound = (E3dCompoundObject*)pObj;
517 
518 			    if(!pCompound->GetSelected())
519 				{
520                     bRemoveObject = true;
521 				}
522 			}
523 
524             if(bRemoveObject)
525 			{
526 			    maSubList.NbcRemoveObject(pObj->GetOrdNum());
527 			    a--;
528                 SdrObject::Free(pObj);
529             }
530         }
531     }
532 }
533 
534 /*************************************************************************
535 |*
536 |* Zuweisungsoperator
537 |*
538 \************************************************************************/
539 
operator =(const SdrObject & rObj)540 void E3dScene::operator=(const SdrObject& rObj)
541 {
542 	E3dObject::operator=(rObj);
543 
544 	const E3dScene& r3DObj = (const E3dScene&) rObj;
545 	aCamera			 = r3DObj.aCamera;
546 
547 	// neu ab 377:
548 	aCameraSet = r3DObj.aCameraSet;
549 	((sdr::properties::E3dSceneProperties&)GetProperties()).SetSceneItemsFromCamera();
550 
551     // SetSnapRect(r3DObj.GetSnapRect());
552 	InvalidateBoundVolume();
553 	RebuildLists();
554 	SetRectsDirty();
555 
556 	// #110988#
557 	ImpCleanup3DDepthMapper();
558 
559     // #i101941#
560     // After a Scene as model object is cloned, the used
561     // ViewContactOfE3dScene is created and partially used
562     // to calculate Bound/SnapRects, but - since quite some
563     // values are buffered at the VC - not really well
564     // initialized. It would be possible to always watch for
565     // preconditions of buffered data, but this would be expensive
566     // and would create a lot of short living data structures.
567     // It is currently better to flush that data, e.g. by using
568     // ActionChanged at the VC which will for this class
569     // flush that cached data and initialize its valid reconstruction
570     GetViewContact().ActionChanged();
571 }
572 
573 /*************************************************************************
574 |*
575 |* Licht- und Labelobjektlisten neu aufbauen (nach Laden, Zuweisung)
576 |*
577 \************************************************************************/
578 
RebuildLists()579 void E3dScene::RebuildLists()
580 {
581 	// zuerst loeschen
582 	SdrLayerID nCurrLayerID = GetLayer();
583 
584 	SdrObjListIter a3DIterator(maSubList, IM_FLAT);
585 
586 	// dann alle Objekte in der Szene pruefen
587 	while ( a3DIterator.IsMore() )
588 	{
589 		E3dObject* p3DObj = (E3dObject*) a3DIterator.Next();
590 		p3DObj->NbcSetLayer(nCurrLayerID);
591 		NewObjectInserted(p3DObj);
592 	}
593 }
594 
595 /*************************************************************************
596 |*
597 |* erstelle neues GeoData-Objekt
598 |*
599 \************************************************************************/
600 
NewGeoData() const601 SdrObjGeoData *E3dScene::NewGeoData() const
602 {
603 	return new E3DSceneGeoData;
604 }
605 
606 /*************************************************************************
607 |*
608 |* uebergebe aktuelle werte an das GeoData-Objekt
609 |*
610 \************************************************************************/
611 
SaveGeoData(SdrObjGeoData & rGeo) const612 void E3dScene::SaveGeoData(SdrObjGeoData& rGeo) const
613 {
614 	E3dObject::SaveGeoData (rGeo);
615 
616 	((E3DSceneGeoData &) rGeo).aCamera = aCamera;
617 }
618 
619 /*************************************************************************
620 |*
621 |* uebernehme werte aus dem GeoData-Objekt
622 |*
623 \************************************************************************/
624 
RestGeoData(const SdrObjGeoData & rGeo)625 void E3dScene::RestGeoData(const SdrObjGeoData& rGeo)
626 {
627 	// #i94832# removed E3DModifySceneSnapRectUpdater here.
628     // It should not be needed, is already part of E3dObject::RestGeoData
629 	E3dObject::RestGeoData (rGeo);
630 	SetCamera (((E3DSceneGeoData &) rGeo).aCamera);
631 }
632 
633 /*************************************************************************
634 |*
635 |* Am StyleSheet wurde etwas geaendert, also Scene aendern
636 |*
637 \************************************************************************/
638 
Notify(SfxBroadcaster & rBC,const SfxHint & rHint)639 void E3dScene::Notify(SfxBroadcaster &rBC, const SfxHint  &rHint)
640 {
641 	SetRectsDirty();
642 	E3dObject::Notify(rBC, rHint);
643 }
644 
645 /*************************************************************************
646 |*
647 \************************************************************************/
648 
RotateScene(const Point & rRef,long,double sn,double cs)649 void E3dScene::RotateScene (const Point& rRef, long /*nWink*/, double sn, double cs)
650 {
651 	Point UpperLeft, LowerRight, Center, NewCenter;
652 
653 	UpperLeft = aOutRect.TopLeft();
654 	LowerRight = aOutRect.BottomRight();
655 
656 	long dxOutRectHalf = labs(UpperLeft.X() - LowerRight.X());
657 	dxOutRectHalf /= 2;
658 	long dyOutRectHalf = labs(UpperLeft.Y() - LowerRight.Y());
659 	dyOutRectHalf /= 2;
660 
661 	Rectangle RectQuelle(aOutRect), RectZiel(aOutRect);
662 
663 	   // Nur der Mittelpunkt wird bewegt. Die Ecken werden von NbcMove bewegt.
664 	   // Fuer das Drehen wird von mir ein kartesisches Koordinatensystem verwendet in dem der Drehpunkt
665 	   // der Nullpunkt ist und die Y- Achse nach oben ansteigt, die X-Achse nach rechts.
666 	   // Dies muss bei den Y-Werten beachtet werden. (Auf dem Blatt zeigt die Y-Achse nach unten
667 	Center.X() = (UpperLeft.X() + dxOutRectHalf) - rRef.X();
668 	Center.Y() = -((UpperLeft.Y() + dyOutRectHalf) - rRef.Y());
669 				  // Ein paar Spezialfaelle zuerst abhandeln (n*90 Grad n ganzzahlig)
670     if (sn==1.0 && cs==0.0) { // 90deg
671 		NewCenter.X() = -Center.Y();
672 		NewCenter.Y() = -Center.X();
673     } else if (sn==0.0 && cs==-1.0) { // 180deg
674 		NewCenter.X() = -Center.X();
675 		NewCenter.Y() = -Center.Y();
676     } else if (sn==-1.0 && cs==0.0) { // 270deg
677 		NewCenter.X() =  Center.Y();
678 		NewCenter.Y() = -Center.X();
679 	}
680 	else          // Hier wird um einen beliebigen Winkel in mathematisch positiver Richtung gedreht!
681 	{             // xneu = x * cos(alpha) - y * sin(alpha)
682 				  // yneu = x * sin(alpha) + y * cos(alpha)
683 				  // Unten Rechts wird nicht gedreht: die Seiten von RectQuelle muessen parallel
684 				  // zu den Koordinatenachsen bleiben.
685 		NewCenter.X() = (long) (Center.X() * cs - Center.Y() * sn);
686 		NewCenter.Y() = (long) (Center.X() * sn + Center.Y() * cs);
687 	}
688 
689 	Size Differenz;
690 	Point DiffPoint = (NewCenter - Center);
691 	Differenz.Width() = DiffPoint.X();
692 	Differenz.Height() = -DiffPoint.Y();  // Man beachte dass die Y-Achse nach unten positiv gezaehlt wird.
693 	NbcMove (Differenz);  // fuehrt die eigentliche Koordinatentransformation durch.
694 }
695 
696 /*************************************************************************
697 |*
698 |* Get the name of the object (singular)
699 |*
700 \************************************************************************/
701 
TakeObjNameSingul(XubString & rName) const702 void E3dScene::TakeObjNameSingul(XubString& rName) const
703 {
704 	rName=ImpGetResStr(STR_ObjNameSingulScene3d);
705 
706 	String aName( GetName() );
707 	if(aName.Len())
708 	{
709 		rName += sal_Unicode(' ');
710 		rName += sal_Unicode('\'');
711 		rName += aName;
712 		rName += sal_Unicode('\'');
713 	}
714 }
715 
716 /*************************************************************************
717 |*
718 |* Get the name of the object (plural)
719 |*
720 \************************************************************************/
721 
TakeObjNamePlural(XubString & rName) const722 void E3dScene::TakeObjNamePlural(XubString& rName) const
723 {
724 	rName=ImpGetResStr(STR_ObjNamePluralScene3d);
725 }
726 
727 /*************************************************************************
728 |*
729 |* Die NbcRotate-Routine ueberlaedt die des SdrObject. Die Idee ist die Scene
730 |* drehen zu koennen und relativ zur Lage der Scene dann auch die Objekte
731 |* in der Scene
732 |*
733 \************************************************************************/
734 
NbcSetTransform(const basegfx::B3DHomMatrix & rMatrix)735 void E3dScene::NbcSetTransform(const basegfx::B3DHomMatrix& rMatrix)
736 {
737     if(maTransformation != rMatrix)
738     {
739 		// call parent
740 		E3dObject::NbcSetTransform(rMatrix);
741 	}
742 }
743 
SetTransform(const basegfx::B3DHomMatrix & rMatrix)744 void E3dScene::SetTransform(const basegfx::B3DHomMatrix& rMatrix)
745 {
746     if(rMatrix != maTransformation)
747     {
748 		// call parent
749 		E3dObject::SetTransform(rMatrix);
750 	}
751 }
752 
NbcRotate(const Point & rRef,long nWink,double sn,double cs)753 void E3dScene::NbcRotate(const Point& rRef, long nWink, double sn, double cs)
754 {
755 	// Also derzeit sind die Klebepunkte relativ zum aOutRect der Szene definiert. Vor dem Drehen
756 	// werden die Klebepunkte relativ zur Seite definiert. Sie nehmen an der Drehung der Szene noch nicht Teil
757 	// dafuer gibt es den
758 	SetGlueReallyAbsolute(sal_True);
759 
760 	// So dass war die Szene, ab jetzt kommen die Objekte in der Szene
761     // 3D-Objekte gibt es nur ein einziges das kann zwar mehrere Flaechen haben aber die Flaechen
762 	// muessen ja nicht zusammenhaengend sein
763 	// es ermoeglicht den Zugriff auf Kindobjekte
764 	// Ich gehe also die gesamte Liste durch und rotiere um die Z-Achse die durch den
765 	// Mittelpunkt von aOutRect geht (Satz von Steiner), also RotateZ
766 
767 	RotateScene (rRef, nWink, sn, cs);  // Rotiert die Szene
768 	double fWinkelInRad = nWink/100 * F_PI180;
769 
770 	basegfx::B3DHomMatrix aRotation;
771 	aRotation.rotate(0.0, 0.0, fWinkelInRad);
772 	NbcSetTransform(aRotation * GetTransform());
773 
774 	SetRectsDirty();    // Veranlasst eine Neuberechnung aller BoundRects
775 	NbcRotateGluePoints(rRef,nWink,sn,cs);  // Rotiert die Klebepunkte (die haben noch Koordinaten relativ
776 											// zum Urpsung des Blattes
777 	SetGlueReallyAbsolute(sal_False);  // ab jetzt sind sie wieder relativ zum BoundRect (also dem aOutRect definiert)
778 	SetRectsDirty();
779 }
780 
781 /*************************************************************************
782 |*
783 |* SnapRect berechnen
784 |*
785 \************************************************************************/
786 
RecalcSnapRect()787 void E3dScene::RecalcSnapRect()
788 {
789 	E3dScene* pScene = GetScene();
790 
791 	if(pScene == this)
792 	{
793 		// Szene wird als 2D-Objekt benutzt, nimm SnapRect aus der
794 		// 2D Bildschrimdarstellung
795 		Camera3D& rCam = (Camera3D&)pScene->GetCamera();
796 		maSnapRect = rCam.GetDeviceWindow();
797 	}
798 	else
799 	{
800 		// Szene ist selbst Mitglied einer anderen Szene, hole das
801 		// SnapRect als zusammengesetztes Objekt
802 		E3dObject::RecalcSnapRect();
803 	}
804 }
805 
806 /*************************************************************************
807 |*
808 |* Aufbrechen
809 |*
810 \************************************************************************/
811 
IsBreakObjPossible()812 sal_Bool E3dScene::IsBreakObjPossible()
813 {
814 	// Szene ist aufzubrechen, wenn alle Mitglieder aufzubrechen sind
815 	SdrObjListIter a3DIterator(maSubList, IM_DEEPWITHGROUPS);
816 
817 	while ( a3DIterator.IsMore() )
818 	{
819 		E3dObject* pObj = (E3dObject*) a3DIterator.Next();
820 		DBG_ASSERT(pObj->ISA(E3dObject), "AW: In Szenen sind nur 3D-Objekte erlaubt!");
821 		if(!pObj->IsBreakObjPossible())
822 			return sal_False;
823 	}
824 
825 	return sal_True;
826 }
827 
GetShadowPlaneDirection() const828 basegfx::B3DVector E3dScene::GetShadowPlaneDirection() const
829 {
830 	double fWink = (double)GetShadowSlant() * F_PI180;
831 	basegfx::B3DVector aShadowPlaneDir(0.0, sin(fWink), cos(fWink));
832 	aShadowPlaneDir.normalize();
833 	return aShadowPlaneDir;
834 }
835 
SetShadowPlaneDirection(const basegfx::B3DVector & rVec)836 void E3dScene::SetShadowPlaneDirection(const basegfx::B3DVector& rVec)
837 {
838 	sal_uInt16 nSceneShadowSlant = (sal_uInt16)((atan2(rVec.getY(), rVec.getZ()) / F_PI180) + 0.5);
839 	GetProperties().SetObjectItemDirect(Svx3DShadowSlantItem(nSceneShadowSlant));
840 }
841 
TakeCreatePoly(const SdrDragStat &) const842 basegfx::B2DPolyPolygon E3dScene::TakeCreatePoly(const SdrDragStat& /*rDrag*/) const
843 {
844 	return TakeXorPoly();
845 }
846 
BegCreate(SdrDragStat & rStat)847 FASTBOOL E3dScene::BegCreate(SdrDragStat& rStat)
848 {
849 	rStat.SetOrtho4Possible();
850 	Rectangle aRect1(rStat.GetStart(), rStat.GetNow());
851 	aRect1.Justify();
852 	rStat.SetActionRect(aRect1);
853 	NbcSetSnapRect(aRect1);
854 	return sal_True;
855 }
856 
MovCreate(SdrDragStat & rStat)857 FASTBOOL E3dScene::MovCreate(SdrDragStat& rStat)
858 {
859 	Rectangle aRect1;
860 	rStat.TakeCreateRect(aRect1);
861 	aRect1.Justify();
862 	rStat.SetActionRect(aRect1);
863 	NbcSetSnapRect(aRect1);
864 	SetBoundRectDirty();
865 	bSnapRectDirty=sal_True;
866 	return sal_True;
867 }
868 
EndCreate(SdrDragStat & rStat,SdrCreateCmd eCmd)869 FASTBOOL E3dScene::EndCreate(SdrDragStat& rStat, SdrCreateCmd eCmd)
870 {
871 	Rectangle aRect1;
872 	rStat.TakeCreateRect(aRect1);
873 	aRect1.Justify();
874 	NbcSetSnapRect(aRect1);
875 	SetRectsDirty();
876 	return (eCmd==SDRCREATE_FORCEEND || rStat.GetPointAnz()>=2);
877 }
878 
BckCreate(SdrDragStat &)879 FASTBOOL E3dScene::BckCreate(SdrDragStat& /*rStat*/)
880 {
881 	return sal_False;
882 }
883 
BrkCreate(SdrDragStat &)884 void E3dScene::BrkCreate(SdrDragStat& /*rStat*/)
885 {
886 }
887 
888 // eof
889