merge the formfield patch from ooo-build
[ooovba.git] / svx / source / sdr / contact / viewcontactofe3dscene.cxx
blobcf5768910f4a0bbf206a8b09178856c726a16bdf
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: viewcontactofe3dscene.cxx,v $
10 * $Revision: 1.10.18.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <svx/sdr/contact/viewcontactofe3dscene.hxx>
34 #include <svx/polysc3d.hxx>
35 #include <svx/sdr/contact/displayinfo.hxx>
36 #include <svx/sdr/contact/viewobjectcontact.hxx>
37 #include <basegfx/polygon/b2dpolygontools.hxx>
38 #include <basegfx/color/bcolor.hxx>
39 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
40 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
41 #include <svx/sdr/contact/viewobjectcontactofe3dscene.hxx>
42 #include <basegfx/matrix/b2dhommatrix.hxx>
43 #include <basegfx/range/b3drange.hxx>
44 #include <drawinglayer/attribute/sdrattribute3d.hxx>
45 #include <drawinglayer/primitive3d/baseprimitive3d.hxx>
46 #include <svx/sdr/contact/viewcontactofe3d.hxx>
47 #include <drawinglayer/primitive2d/sceneprimitive2d.hxx>
48 #include <drawinglayer/primitive3d/transformprimitive3d.hxx>
50 //////////////////////////////////////////////////////////////////////////////
52 using namespace com::sun::star;
54 //////////////////////////////////////////////////////////////////////////////
56 namespace
58 // pActiveVC is only true if ghosted is still activated and maybe needs to be switched off in this path
59 void createSubPrimitive3DVector(
60 const sdr::contact::ViewContact& rCandidate,
61 drawinglayer::primitive3d::Primitive3DSequence& o_rAllTarget,
62 drawinglayer::primitive3d::Primitive3DSequence* o_pVisibleTarget,
63 const SetOfByte* pVisibleLayerSet,
64 const bool bTestSelectedVisibility)
66 const sdr::contact::ViewContactOfE3dScene* pViewContactOfE3dScene = dynamic_cast< const sdr::contact::ViewContactOfE3dScene* >(&rCandidate);
68 if(pViewContactOfE3dScene)
70 const sal_uInt32 nChildrenCount(rCandidate.GetObjectCount());
72 if(nChildrenCount)
74 // provide new collection sequences
75 drawinglayer::primitive3d::Primitive3DSequence aNewAllTarget;
76 drawinglayer::primitive3d::Primitive3DSequence aNewVisibleTarget;
78 // add children recursively
79 for(sal_uInt32 a(0L); a < nChildrenCount; a++)
81 createSubPrimitive3DVector(
82 rCandidate.GetViewContact(a),
83 aNewAllTarget,
84 o_pVisibleTarget ? &aNewVisibleTarget : 0,
85 pVisibleLayerSet,
86 bTestSelectedVisibility);
89 // create transform primitive for the created content combining content and transformtion
90 const drawinglayer::primitive3d::Primitive3DReference xReference(new drawinglayer::primitive3d::TransformPrimitive3D(
91 pViewContactOfE3dScene->GetE3dScene().GetTransform(),
92 aNewAllTarget));
94 // add created content to all target
95 drawinglayer::primitive3d::appendPrimitive3DReferenceToPrimitive3DSequence(o_rAllTarget, xReference);
97 // add created content to visibiel target if exists
98 if(o_pVisibleTarget)
100 drawinglayer::primitive3d::appendPrimitive3DReferenceToPrimitive3DSequence(*o_pVisibleTarget, xReference);
104 else
106 // access view independent representation of rCandidate
107 const sdr::contact::ViewContactOfE3d* pViewContactOfE3d = dynamic_cast< const sdr::contact::ViewContactOfE3d* >(&rCandidate);
109 if(pViewContactOfE3d)
111 drawinglayer::primitive3d::Primitive3DSequence xPrimitive3DSeq(pViewContactOfE3d->getViewIndependentPrimitive3DSequence());
113 if(xPrimitive3DSeq.hasElements())
115 // add to all target vector
116 drawinglayer::primitive3d::appendPrimitive3DSequenceToPrimitive3DSequence(o_rAllTarget, xPrimitive3DSeq);
118 if(o_pVisibleTarget)
120 // test visibility. Primitive is visible when both tests are true (AND)
121 bool bVisible(true);
123 if(pVisibleLayerSet)
125 // test layer visibility
126 const E3dObject& rE3dObject = pViewContactOfE3d->GetE3dObject();
127 const SdrLayerID aLayerID(rE3dObject.GetLayer());
129 bVisible = pVisibleLayerSet->IsSet(aLayerID);
132 if(bVisible && bTestSelectedVisibility)
134 // test selected visibility (see 3D View's DrawMarkedObj implementation)
135 const E3dObject& rE3dObject = pViewContactOfE3d->GetE3dObject();
137 bVisible = rE3dObject.GetSelected();
140 if(bVisible && o_pVisibleTarget)
142 // add to visible target vector
143 drawinglayer::primitive3d::appendPrimitive3DSequenceToPrimitive3DSequence(*o_pVisibleTarget, xPrimitive3DSeq);
150 } // end of anonymous namespace
152 //////////////////////////////////////////////////////////////////////////////
154 namespace sdr
156 namespace contact
158 // Create a Object-Specific ViewObjectContact, set ViewContact and
159 // ObjectContact. Always needs to return something.
160 ViewObjectContact& ViewContactOfE3dScene::CreateObjectSpecificViewObjectContact(ObjectContact& rObjectContact)
162 ViewObjectContact* pRetval = new ViewObjectContactOfE3dScene(rObjectContact, *this);
163 DBG_ASSERT(pRetval, "ViewContactOfE3dScene::CreateObjectSpecificViewObjectContact() failed (!)");
165 return *pRetval;
168 ViewContactOfE3dScene::ViewContactOfE3dScene(E3dScene& rScene)
169 : ViewContactOfSdrObj(rScene),
170 mpViewInformation3D(0),
171 mpObjectTransformation(0),
172 mpSdrSceneAttribute(0),
173 mpSdrLightingAttribute(0)
177 ViewContactOfE3dScene::~ViewContactOfE3dScene()
179 delete mpViewInformation3D;
180 delete mpObjectTransformation;
181 delete mpSdrSceneAttribute;
182 delete mpSdrLightingAttribute;
185 void ViewContactOfE3dScene::createViewInformation3D(const basegfx::B3DRange& rContentRange)
187 basegfx::B3DHomMatrix aTransformation;
188 basegfx::B3DHomMatrix aOrientation;
189 basegfx::B3DHomMatrix aProjection;
190 basegfx::B3DHomMatrix aDeviceToView;
192 // create transformation (scene as group's transformation)
193 // For historical reasons, the outmost scene's transformation is handles as part of the
194 // view transformation. This means that the BoundRect of the contained 3D Objects is
195 // without that transformation and makes it necessary to NOT add the first scene to the
196 // Primitive3DSequence of contained objects.
198 aTransformation = GetE3dScene().GetTransform();
201 // create orientation (world to camera coordinate system)
203 // calculate orientation from VRP, VPN and VUV
204 const B3dCamera& rSceneCamera = GetE3dScene().GetCameraSet();
205 const basegfx::B3DPoint aVRP(rSceneCamera.GetVRP());
206 const basegfx::B3DVector aVPN(rSceneCamera.GetVRP());
207 const basegfx::B3DVector aVUV(rSceneCamera.GetVUV());
209 aOrientation.orientation(aVRP, aVPN, aVUV);
212 // create projection (camera coordinate system to relative 2d where X,Y and Z are [0.0 .. 1.0])
214 const basegfx::B3DHomMatrix aWorldToCamera(aOrientation * aTransformation);
215 basegfx::B3DRange aCameraRange(rContentRange);
216 aCameraRange.transform(aWorldToCamera);
218 // remember Z-Values, but change orientation
219 const double fMinZ(-aCameraRange.getMaxZ());
220 const double fMaxZ(-aCameraRange.getMinZ());
222 // construct temorary matrix from world to device. Use unit values here to measure expansion
223 basegfx::B3DHomMatrix aWorldToDevice(aWorldToCamera);
224 const drawinglayer::attribute::SdrSceneAttribute& rSdrSceneAttribute = getSdrSceneAttribute();
226 if(::com::sun::star::drawing::ProjectionMode_PERSPECTIVE == rSdrSceneAttribute.getProjectionMode())
228 aWorldToDevice.frustum(-1.0, 1.0, -1.0, 1.0, fMinZ, fMaxZ);
230 else
232 aWorldToDevice.ortho(-1.0, 1.0, -1.0, 1.0, fMinZ, fMaxZ);
235 // create B3DRange in device. This will create the real used ranges
236 // in camera space. Do not use the Z-Values, though.
237 basegfx::B3DRange aDeviceRange(rContentRange);
238 aDeviceRange.transform(aWorldToDevice);
240 // set projection
241 if(::com::sun::star::drawing::ProjectionMode_PERSPECTIVE == rSdrSceneAttribute.getProjectionMode())
243 aProjection.frustum(
244 aDeviceRange.getMinX(), aDeviceRange.getMaxX(),
245 aDeviceRange.getMinY(), aDeviceRange.getMaxY(),
246 fMinZ, fMaxZ);
248 else
250 aProjection.ortho(
251 aDeviceRange.getMinX(), aDeviceRange.getMaxX(),
252 aDeviceRange.getMinY(), aDeviceRange.getMaxY(),
253 fMinZ, fMaxZ);
257 // create device to view transform
259 // create standard deviceToView projection for geometry
260 // input is [-1.0 .. 1.0] in X,Y and Z. bring to [0.0 .. 1.0]. Also
261 // necessary to flip Y due to screen orientation
262 // Z is not needed, but will also be brought to [0.0 .. 1.0]
263 aDeviceToView.scale(0.5, -0.5, 0.5);
264 aDeviceToView.translate(0.5, 0.5, 0.5);
267 const uno::Sequence< beans::PropertyValue > aEmptyProperties;
268 mpViewInformation3D = new drawinglayer::geometry::ViewInformation3D(aTransformation, aOrientation, aProjection, aDeviceToView, 0.0, aEmptyProperties);
271 void ViewContactOfE3dScene::createObjectTransformation()
273 // create 2d Object Transformation from relative point in 2d scene to world
274 mpObjectTransformation = new basegfx::B2DHomMatrix;
275 const Rectangle& rRectangle = GetE3dScene().GetSnapRect();
277 mpObjectTransformation->set(0, 0, rRectangle.getWidth());
278 mpObjectTransformation->set(1, 1, rRectangle.getHeight());
279 mpObjectTransformation->set(0, 2, rRectangle.Left());
280 mpObjectTransformation->set(1, 2, rRectangle.Top());
283 void ViewContactOfE3dScene::createSdrSceneAttribute()
285 const SfxItemSet& rItemSet = GetE3dScene().GetMergedItemSet();
286 mpSdrSceneAttribute = drawinglayer::primitive2d::createNewSdrSceneAttribute(rItemSet);
289 void ViewContactOfE3dScene::createSdrLightingAttribute()
291 const SfxItemSet& rItemSet = GetE3dScene().GetMergedItemSet();
292 mpSdrLightingAttribute = drawinglayer::primitive2d::createNewSdrLightingAttribute(rItemSet);
295 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfE3dScene::createScenePrimitive2DSequence(const SetOfByte* pLayerVisibility) const
297 drawinglayer::primitive2d::Primitive2DSequence xRetval;
298 const sal_uInt32 nChildrenCount(GetObjectCount());
300 if(nChildrenCount)
302 // create 3d scene primitive with visible content tested against rLayerVisibility
303 drawinglayer::primitive3d::Primitive3DSequence aAllSequence;
304 drawinglayer::primitive3d::Primitive3DSequence aVisibleSequence;
305 const bool bTestLayerVisibility(0 != pLayerVisibility);
306 const bool bTestSelectedVisibility(GetE3dScene().GetDrawOnlySelected());
307 const bool bTestVisibility(bTestLayerVisibility || bTestSelectedVisibility);
309 // add children recursively. Do NOT start with (*this), this would create
310 // a 3D transformPrimitive for the start scene. While this is theoretically not
311 // a bad thing, for historical reasons the transformation of the outmost scene
312 // is seen as part of the ViewTransformation (see text in createViewInformation3D)
313 for(sal_uInt32 a(0L); a < nChildrenCount; a++)
315 createSubPrimitive3DVector(
316 GetViewContact(a),
317 aAllSequence,
318 bTestLayerVisibility ? &aVisibleSequence : 0,
319 bTestLayerVisibility ? pLayerVisibility : 0,
320 bTestSelectedVisibility);
323 const sal_uInt32 nAllSize(aAllSequence.hasElements() ? aAllSequence.getLength() : 0);
324 const sal_uInt32 nVisibleSize(aVisibleSequence.hasElements() ? aVisibleSequence.getLength() : 0);
326 if((bTestVisibility && nVisibleSize) || nAllSize)
328 // for getting the 3D range using getB3DRangeFromPrimitive3DSequence a ViewInformation3D
329 // needs to be given for evtl. decompositions. At the same time createViewInformation3D
330 // currently is based on creating the target-ViewInformation3D using a given range. To
331 // get the true range, use a neutral ViewInformation3D here. This leaves all matrices
332 // on identity and the time on 0.0.
333 const uno::Sequence< beans::PropertyValue > aEmptyProperties;
334 const drawinglayer::geometry::ViewInformation3D aNeutralViewInformation3D(aEmptyProperties);
335 const basegfx::B3DRange aContentRange(drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(aAllSequence, aNeutralViewInformation3D));
337 // create 2d primitive 3dscene with generated sub-list from collector
338 const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::ScenePrimitive2D(
339 bTestVisibility ? aVisibleSequence : aAllSequence,
340 getSdrSceneAttribute(),
341 getSdrLightingAttribute(),
342 getObjectTransformation(),
343 getViewInformation3D(aContentRange)));
344 xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
348 return xRetval;
351 drawinglayer::primitive2d::Primitive2DSequence ViewContactOfE3dScene::createViewIndependentPrimitive2DSequence() const
353 drawinglayer::primitive2d::Primitive2DSequence xRetval;
355 if(GetObjectCount())
357 // create a default ScenePrimitive2D (without visibility test of members)
358 xRetval = createScenePrimitive2DSequence(0);
361 if(xRetval.hasElements())
363 return xRetval;
365 else
367 // create a gray placeholder hairline polygon in object size as empty 3D scene marker. Use object size
368 // model information directly, NOT getBoundRect()/getSnapRect() since these will
369 // be using the geometry data we get just asked for. AFAIK for empty 3D Scenes, the model data
370 // is SdrObject::aOutRect which i can access directly using GetLastBoundRect() here
371 const Rectangle aEmptySceneGeometry(GetE3dScene().GetLastBoundRect());
372 const basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(basegfx::B2DRange(
373 aEmptySceneGeometry.Left(), aEmptySceneGeometry.Top(),
374 aEmptySceneGeometry.Right(), aEmptySceneGeometry.Bottom())));
375 const double fGrayTone(0xc0 / 255.0);
376 const basegfx::BColor aGrayTone(fGrayTone, fGrayTone, fGrayTone);
377 const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::PolygonHairlinePrimitive2D(aOutline, aGrayTone));
379 // The replacement object may also get a text like 'empty 3D Scene' here later
380 return drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
384 void ViewContactOfE3dScene::ActionChanged()
386 // call parent
387 ViewContactOfSdrObj::ActionChanged();
389 // mark locally cached values as invalid
390 delete mpViewInformation3D;
391 mpViewInformation3D = 0;
393 delete mpObjectTransformation;
394 mpObjectTransformation = 0;
396 delete mpSdrSceneAttribute;
397 mpSdrSceneAttribute = 0;
399 delete mpSdrLightingAttribute;
400 mpSdrLightingAttribute = 0;
403 const drawinglayer::geometry::ViewInformation3D& ViewContactOfE3dScene::getViewInformation3D() const
405 if(!mpViewInformation3D)
407 // this version will create the content range on demand locally and thus is less
408 // performant than the other one. Since the information is buffered the planned
409 // behaviour is that the version with the given range is used initially.
410 basegfx::B3DRange aContentRange(getAllContentRange3D());
412 if(aContentRange.isEmpty())
414 // empty scene, no 3d action should be necessary. Prepare some
415 // fallback size
416 OSL_ENSURE(false, "No need to get ViewInformation3D from an empty scene (!)");
417 aContentRange.expand(basegfx::B3DPoint(-100.0, -100.0, -100.0));
418 aContentRange.expand(basegfx::B3DPoint( 100.0, 100.0, 100.0));
421 const_cast < ViewContactOfE3dScene* >(this)->createViewInformation3D(aContentRange);
424 return *mpViewInformation3D;
427 const drawinglayer::geometry::ViewInformation3D& ViewContactOfE3dScene::getViewInformation3D(const basegfx::B3DRange& rContentRange) const
429 if(!mpViewInformation3D)
431 const_cast < ViewContactOfE3dScene* >(this)->createViewInformation3D(rContentRange);
434 return *mpViewInformation3D;
437 const basegfx::B2DHomMatrix& ViewContactOfE3dScene::getObjectTransformation() const
439 if(!mpObjectTransformation)
441 const_cast < ViewContactOfE3dScene* >(this)->createObjectTransformation();
444 return *mpObjectTransformation;
447 const drawinglayer::attribute::SdrSceneAttribute& ViewContactOfE3dScene::getSdrSceneAttribute() const
449 if(!mpSdrSceneAttribute)
451 const_cast < ViewContactOfE3dScene* >(this)->createSdrSceneAttribute();
454 return *mpSdrSceneAttribute;
457 const drawinglayer::attribute::SdrLightingAttribute& ViewContactOfE3dScene::getSdrLightingAttribute() const
459 if(!mpSdrLightingAttribute)
461 const_cast < ViewContactOfE3dScene* >(this)->createSdrLightingAttribute();
464 return *mpSdrLightingAttribute;
467 drawinglayer::primitive3d::Primitive3DSequence ViewContactOfE3dScene::getAllPrimitive3DSequence() const
469 drawinglayer::primitive3d::Primitive3DSequence aAllPrimitive3DSequence;
470 const sal_uInt32 nChildrenCount(GetObjectCount());
472 // add children recursively. Do NOT start with (*this), this would create
473 // a 3D transformPrimitive for the start scene. While this is theoretically not
474 // a bad thing, for historical reasons the transformation of the outmost scene
475 // is seen as part of the ViewTransformation (see text in createViewInformation3D)
476 for(sal_uInt32 a(0L); a < nChildrenCount; a++)
478 createSubPrimitive3DVector(GetViewContact(a), aAllPrimitive3DSequence, 0, 0, false);
481 return aAllPrimitive3DSequence;
484 basegfx::B3DRange ViewContactOfE3dScene::getAllContentRange3D() const
486 const drawinglayer::primitive3d::Primitive3DSequence xAllSequence(getAllPrimitive3DSequence());
487 basegfx::B3DRange aAllContentRange3D;
489 if(xAllSequence.hasElements())
491 // for getting the 3D range using getB3DRangeFromPrimitive3DSequence a ViewInformation3D
492 // needs to be given for evtl. decompositions. Use a neutral ViewInformation3D here. This
493 // leaves all matrices on identity and the time on 0.0.
494 const uno::Sequence< beans::PropertyValue > aEmptyProperties;
495 const drawinglayer::geometry::ViewInformation3D aNeutralViewInformation3D(aEmptyProperties);
497 aAllContentRange3D = drawinglayer::primitive3d::getB3DRangeFromPrimitive3DSequence(xAllSequence, aNeutralViewInformation3D);
500 return aAllContentRange3D;
502 } // end of namespace contact
503 } // end of namespace sdr
505 //////////////////////////////////////////////////////////////////////////////
506 // eof