/src/libreoffice/svx/source/engine3d/e3dsceneupdater.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <svx/e3dsceneupdater.hxx> |
21 | | #include <drawinglayer/geometry/viewinformation3d.hxx> |
22 | | #include <svx/obj3d.hxx> |
23 | | #include <svx/scene3d.hxx> |
24 | | #include <svx/sdr/contact/viewcontactofe3dscene.hxx> |
25 | | |
26 | | |
27 | | E3DModifySceneSnapRectUpdater::E3DModifySceneSnapRectUpdater(const SdrObject* pObject) |
28 | 0 | : mpScene(nullptr) |
29 | 0 | { |
30 | | // Secure old 3D transformation stack before modification |
31 | 0 | const E3dObject* pE3dObject = DynCastE3dObject(pObject); |
32 | 0 | if(!pE3dObject) |
33 | 0 | return; |
34 | | |
35 | 0 | mpScene = pE3dObject->getRootE3dSceneFromE3dObject(); |
36 | |
|
37 | 0 | if(nullptr == mpScene || mpScene->getRootE3dSceneFromE3dObject() != mpScene) |
38 | 0 | return; |
39 | | |
40 | | // if there is a scene and it's the outmost scene, get current 3D range |
41 | 0 | const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(mpScene->GetViewContact()); |
42 | 0 | const basegfx::B3DRange aAllContentRange(rVCScene.getAllContentRange3D()); |
43 | |
|
44 | 0 | if(aAllContentRange.isEmpty()) |
45 | 0 | { |
46 | | // no content, nothing to do |
47 | 0 | mpScene = nullptr; |
48 | 0 | } |
49 | 0 | else |
50 | 0 | { |
51 | | // secure current 3D transformation stack |
52 | 0 | mpViewInformation3D = rVCScene.getViewInformation3D(aAllContentRange); |
53 | 0 | } |
54 | 0 | } |
55 | | |
56 | | E3DModifySceneSnapRectUpdater::~E3DModifySceneSnapRectUpdater() |
57 | 0 | { |
58 | 0 | if(!(mpScene && mpViewInformation3D)) |
59 | 0 | return; |
60 | | |
61 | | // after changing parts of the scene, use the secured last 3d transformation stack and the new content |
62 | | // range to calculate a new, eventually expanded or shrunk, 2D geometry for the scene and apply it. |
63 | | // Get new content range |
64 | 0 | const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(mpScene->GetViewContact()); |
65 | 0 | basegfx::B3DRange aAllContentRange(rVCScene.getAllContentRange3D()); |
66 | | |
67 | | // only change when there is still content; else let scene stay at old SnapRect |
68 | 0 | if(aAllContentRange.isEmpty()) |
69 | 0 | return; |
70 | | |
71 | | // check if object transform of scene has changed |
72 | 0 | if(mpViewInformation3D->getObjectTransformation() != mpScene->GetTransform()) |
73 | 0 | { |
74 | | // If Yes, it needs to be updated since it's - for historical reasons - |
75 | | // part of the basic 3d transformation stack of the scene |
76 | 0 | mpViewInformation3D = drawinglayer::geometry::ViewInformation3D( |
77 | 0 | mpScene->GetTransform(), // replace object transformation with new local transform |
78 | 0 | mpViewInformation3D->getOrientation(), |
79 | 0 | mpViewInformation3D->getProjection(), |
80 | 0 | mpViewInformation3D->getDeviceToView(), |
81 | 0 | mpViewInformation3D->getViewTime(), |
82 | 0 | mpViewInformation3D->getExtendedInformationSequence()); |
83 | 0 | } |
84 | | |
85 | | // transform content range to scene-relative coordinates using old 3d transformation stack |
86 | 0 | aAllContentRange.transform(mpViewInformation3D->getObjectToView()); |
87 | | |
88 | | // build 2d relative content range |
89 | 0 | basegfx::B2DRange aSnapRange( |
90 | 0 | aAllContentRange.getMinX(), aAllContentRange.getMinY(), |
91 | 0 | aAllContentRange.getMaxX(), aAllContentRange.getMaxY()); |
92 | | |
93 | | // transform to 2D world coordinates using scene's 2D transformation |
94 | 0 | aSnapRange.transform(rVCScene.getObjectTransformation()); |
95 | | |
96 | | // snap to (old) integer |
97 | 0 | const tools::Rectangle aNewSnapRect( |
98 | 0 | sal_Int32(floor(aSnapRange.getMinX())), sal_Int32(floor(aSnapRange.getMinY())), |
99 | 0 | sal_Int32(ceil(aSnapRange.getMaxX())), sal_Int32(ceil(aSnapRange.getMaxY()))); |
100 | | |
101 | | // set as new SnapRect and invalidate bound volume |
102 | 0 | if(mpScene->GetSnapRect() != aNewSnapRect) |
103 | 0 | { |
104 | 0 | mpScene->SetSnapRect(aNewSnapRect); |
105 | 0 | mpScene->InvalidateBoundVolume(); |
106 | 0 | } |
107 | 0 | } |
108 | | |
109 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |