Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/engine3d/dragmt3d.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
21
#include <dragmt3d.hxx>
22
#include <o3tl/numeric.hxx>
23
#include <svx/svdpagv.hxx>
24
#include <svx/dialmgr.hxx>
25
#include <svx/svddrgmt.hxx>
26
#include <svx/svdtrans.hxx>
27
#include <svx/obj3d.hxx>
28
#include <svx/e3dundo.hxx>
29
#include <svx/strings.hrc>
30
#include <svx/sdr/overlay/overlaypolypolygon.hxx>
31
#include <svx/sdr/overlay/overlaymanager.hxx>
32
#include <basegfx/polygon/b2dpolypolygontools.hxx>
33
#include <svx/sdr/contact/viewcontactofe3dscene.hxx>
34
#include <drawinglayer/geometry/viewinformation3d.hxx>
35
#include <svx/e3dsceneupdater.hxx>
36
#include <svx/view3d.hxx>
37
#include <vcl/ptrstyle.hxx>
38
#include <comphelper/lok.hxx>
39
40
41
E3dDragMethod::E3dDragMethod (
42
    SdrDragView &_rView,
43
    const SdrMarkList& rMark,
44
    E3dDragConstraint eConstr,
45
    bool bFull)
46
0
:   SdrDragMethod(_rView),
47
0
    meConstraint(eConstr),
48
0
    mbMoveFull(bFull),
49
0
    mbMovedAtAll(false)
50
0
{
51
    // Create a unit for all the 3D objects present in the selection
52
0
    const size_t nCnt(rMark.GetMarkCount());
53
54
0
    if(mbMoveFull)
55
0
    {
56
        // for non-visible 3D objects fallback to wireframe interaction
57
0
        for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
58
0
        {
59
0
            E3dObject* pE3dObj = DynCastE3dObject(rMark.GetMark(nObjs)->GetMarkedSdrObj());
60
61
0
            if(pE3dObj)
62
0
            {
63
0
                if(!pE3dObj->HasFillStyle() && !pE3dObj->HasLineStyle())
64
0
                {
65
0
                    mbMoveFull = false;
66
0
                    break;
67
0
                }
68
0
            }
69
0
        }
70
0
    }
71
72
0
    for(size_t nObjs = 0; nObjs < nCnt; ++nObjs)
73
0
    {
74
0
        E3dObject* pE3dObj = DynCastE3dObject(rMark.GetMark(nObjs)->GetMarkedSdrObj());
75
76
0
        if(pE3dObj)
77
0
        {
78
            // fill new interaction unit
79
0
            E3dDragMethodUnit aNewUnit(*pE3dObj);
80
81
            // get transformations
82
0
            aNewUnit.maInitTransform = aNewUnit.maTransform = pE3dObj->GetTransform();
83
84
0
            if(nullptr != pE3dObj->getParentE3dSceneFromE3dObject())
85
0
            {
86
                // get transform between object and world, normally scene transform
87
0
                aNewUnit.maInvDisplayTransform = aNewUnit.maDisplayTransform = pE3dObj->getParentE3dSceneFromE3dObject()->GetFullTransform();
88
0
                aNewUnit.maInvDisplayTransform.invert();
89
0
            }
90
91
0
            if(!mbMoveFull)
92
0
            {
93
                // create wireframe visualisation for parent coordinate system
94
0
                aNewUnit.maWireframePoly.clear();
95
0
                aNewUnit.maWireframePoly = pE3dObj->CreateWireframe();
96
0
                aNewUnit.maWireframePoly.transform(aNewUnit.maTransform);
97
0
            }
98
99
            // Determine FullBound
100
0
            maFullBound.Union(pE3dObj->GetSnapRect());
101
102
            // Insert Unit
103
0
            maGrp.push_back(aNewUnit);
104
0
        }
105
0
    }
106
0
}
107
108
OUString E3dDragMethod::GetSdrDragComment() const
109
0
{
110
0
    return OUString();
111
0
}
112
113
// Create the wireframe model for all actions
114
115
bool E3dDragMethod::BeginSdrDrag()
116
0
{
117
0
    if(E3dDragConstraint::Z == meConstraint)
118
0
    {
119
0
        const sal_uInt32 nCnt(maGrp.size());
120
0
        DragStat().SetRef1( maFullBound.Center() );
121
122
0
        for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
123
0
        {
124
0
            E3dDragMethodUnit& rCandidate = maGrp[nOb];
125
0
            rCandidate.mnStartAngle = GetAngle(DragStat().GetStart() - DragStat().GetRef1());
126
0
            rCandidate.mnLastAngle = 0_deg100;
127
0
        }
128
0
    }
129
0
    else
130
0
    {
131
0
        maLastPos = DragStat().GetStart();
132
0
    }
133
134
0
    if(!mbMoveFull)
135
0
    {
136
0
        Show();
137
0
    }
138
139
0
    return true;
140
0
}
141
142
bool E3dDragMethod::EndSdrDrag(bool /*bCopy*/)
143
0
{
144
0
    const sal_uInt32 nCnt(maGrp.size());
145
146
0
    if(!mbMoveFull)
147
0
    {
148
        // Hide wireframe
149
0
        Hide();
150
0
    }
151
152
    // Apply all transformations and create undo's
153
0
    if(mbMovedAtAll)
154
0
    {
155
0
        const bool bUndo = getSdrDragView().IsUndoEnabled();
156
0
        if( bUndo )
157
0
            getSdrDragView().BegUndo(SvxResId(RID_SVX_3D_UNDO_ROTATE));
158
0
        sal_uInt32 nOb(0);
159
160
0
        for(nOb=0;nOb<nCnt;nOb++)
161
0
        {
162
0
            E3dDragMethodUnit& rCandidate = maGrp[nOb];
163
0
            E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
164
0
            rCandidate.mr3DObj.SetTransform(rCandidate.maTransform);
165
0
            if( bUndo )
166
0
            {
167
0
                getSdrDragView().AddUndo(
168
0
                    std::make_unique<E3dRotateUndoAction>(
169
0
                        rCandidate.mr3DObj,
170
0
                        rCandidate.maInitTransform,
171
0
                        rCandidate.maTransform));
172
0
            }
173
0
        }
174
0
        if( bUndo )
175
0
            getSdrDragView().EndUndo();
176
0
    }
177
178
0
    return true;
179
0
}
180
181
void E3dDragMethod::CancelSdrDrag()
182
0
{
183
0
    if(mbMoveFull)
184
0
    {
185
0
        if(mbMovedAtAll)
186
0
        {
187
0
            const sal_uInt32 nCnt(maGrp.size());
188
189
0
            for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
190
0
            {
191
                // Restore transformation
192
0
                E3dDragMethodUnit& rCandidate = maGrp[nOb];
193
0
                E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
194
0
                rCandidate.mr3DObj.SetTransform(rCandidate.maInitTransform);
195
0
            }
196
0
        }
197
0
    }
198
0
    else
199
0
    {
200
        // Hide WireFrame
201
0
        Hide();
202
0
    }
203
0
}
204
205
// Common MoveSdrDrag()
206
207
void E3dDragMethod::MoveSdrDrag(const Point& /*rPnt*/)
208
0
{
209
0
    mbMovedAtAll = true;
210
0
}
211
212
// Draw the wire frame model
213
214
// for migration from XOR to overlay
215
void E3dDragMethod::CreateOverlayGeometry(
216
    sdr::overlay::OverlayManager& rOverlayManager,
217
    const sdr::contact::ObjectContact& rObjectContact, bool /* bIsGeometrySizeValid */)
218
0
{
219
    // We do client-side object manipulation with the Kit API
220
0
    if (comphelper::LibreOfficeKit::isActive())
221
0
        return;
222
223
0
    const sal_uInt32 nCnt(maGrp.size());
224
0
    basegfx::B2DPolyPolygon aResult;
225
226
0
    for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
227
0
    {
228
0
        E3dDragMethodUnit& rCandidate = maGrp[nOb];
229
0
        SdrPageView* pPV = getSdrDragView().GetSdrPageView();
230
231
0
        if(pPV && pPV->HasMarkedObjPageView())
232
0
        {
233
0
            const basegfx::B3DPolyPolygon aCandidate(rCandidate.maWireframePoly);
234
0
            const sal_uInt32 nPlyCnt(aCandidate.count());
235
236
0
            if(nPlyCnt)
237
0
            {
238
0
                const E3dScene* pScene(rCandidate.mr3DObj.getRootE3dSceneFromE3dObject());
239
240
0
                if(nullptr != pScene)
241
0
                {
242
0
                    const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
243
0
                    const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
244
0
                    const basegfx::B3DHomMatrix aWorldToView(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection() * aViewInfo3D.getOrientation());
245
0
                    const basegfx::B3DHomMatrix aTransform(aWorldToView * rCandidate.maDisplayTransform);
246
247
                    // transform to relative scene coordinates
248
0
                    basegfx::B2DPolyPolygon aPolyPolygon(basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(aCandidate, aTransform));
249
250
                    // transform to 2D view coordinates
251
0
                    aPolyPolygon.transform(rVCScene.getObjectTransformation());
252
253
0
                    aResult.append(aPolyPolygon);
254
0
                }
255
0
            }
256
0
        }
257
0
    }
258
259
0
    if(aResult.count())
260
0
    {
261
0
        std::unique_ptr<sdr::overlay::OverlayPolyPolygonStripedAndFilled> pNew(
262
0
            new sdr::overlay::OverlayPolyPolygonStripedAndFilled(
263
0
                std::move(aResult)));
264
265
0
        insertNewlyCreatedOverlayObjectForSdrDragMethod(
266
0
            std::move(pNew),
267
0
            rObjectContact,
268
0
            rOverlayManager);
269
0
    }
270
0
}
271
272
273
E3dDragRotate::E3dDragRotate(SdrDragView &_rView,
274
    const SdrMarkList& rMark,
275
    E3dDragConstraint eConstr,
276
    bool bFull)
277
0
:   E3dDragMethod(_rView, rMark, eConstr, bFull)
278
0
{
279
    // Get center of all selected objects in eye coordinates
280
0
    const sal_uInt32 nCnt(maGrp.size());
281
282
0
    if(!nCnt)
283
0
        return;
284
285
0
    const E3dScene* pScene(maGrp[0].mr3DObj.getRootE3dSceneFromE3dObject());
286
287
0
    if(nullptr == pScene)
288
0
        return;
289
290
0
    const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
291
0
    const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
292
293
0
    for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
294
0
    {
295
0
        E3dDragMethodUnit& rCandidate = maGrp[nOb];
296
0
        basegfx::B3DPoint aObjCenter = rCandidate.mr3DObj.GetBoundVolume().getCenter();
297
0
        const basegfx::B3DHomMatrix aTransform(aViewInfo3D.getOrientation() * rCandidate.maDisplayTransform * rCandidate.maInitTransform);
298
299
0
        aObjCenter = aTransform * aObjCenter;
300
0
        maGlobalCenter += aObjCenter;
301
0
    }
302
303
    // Divide by the number
304
0
    if(nCnt > 1)
305
0
    {
306
0
        maGlobalCenter /= static_cast<double>(nCnt);
307
0
    }
308
309
    // get rotate center and transform to 3D eye coordinates
310
0
    basegfx::B2DPoint aRotCenter2D(Ref1().X(), Ref1().Y());
311
312
    // from world to relative scene using inverse getObjectTransformation()
313
0
    basegfx::B2DHomMatrix aInverseObjectTransform(rVCScene.getObjectTransformation());
314
0
    aInverseObjectTransform.invert();
315
0
    aRotCenter2D = aInverseObjectTransform * aRotCenter2D;
316
317
    // from 3D view to 3D eye
318
0
    basegfx::B3DPoint aRotCenter3D(aRotCenter2D.getX(), aRotCenter2D.getY(), 0.0);
319
0
    basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
320
0
    aInverseViewToEye.invert();
321
0
    aRotCenter3D = aInverseViewToEye * aRotCenter3D;
322
323
// Use X,Y of the RotCenter and depth of the common object centre
324
// as rotation point in the space
325
0
    maGlobalCenter.setX(aRotCenter3D.getX());
326
0
    maGlobalCenter.setY(aRotCenter3D.getY());
327
0
}
328
329
330
//The object is moved, determine the angle
331
332
void E3dDragRotate::MoveSdrDrag(const Point& rPnt)
333
0
{
334
    // call parent
335
0
    E3dDragMethod::MoveSdrDrag(rPnt);
336
337
0
    if(!DragStat().CheckMinMoved(rPnt))
338
0
        return;
339
340
    // Get modifier
341
0
    sal_uInt16 nModifier = 0;
342
0
    if(auto pDragView = dynamic_cast<const E3dView*>(&getSdrDragView()))
343
0
    {
344
0
        const MouseEvent& rLastMouse = pDragView->GetMouseEvent();
345
0
        nModifier = rLastMouse.GetModifier();
346
0
    }
347
348
    // Rotate all objects
349
0
    const sal_uInt32 nCnt(maGrp.size());
350
351
0
    for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
352
0
    {
353
        // Determine rotation angle
354
0
        double fWAngle, fHAngle;
355
0
        E3dDragMethodUnit& rCandidate = maGrp[nOb];
356
357
0
        if(E3dDragConstraint::Z == meConstraint)
358
0
        {
359
0
            Degree100 lastAngle = NormAngle36000(GetAngle(rPnt - DragStat().GetRef1()) -
360
0
                rCandidate.mnStartAngle) - rCandidate.mnLastAngle;
361
0
            rCandidate.mnLastAngle = lastAngle + rCandidate.mnLastAngle;
362
0
            fWAngle = toDegrees(lastAngle);
363
0
            fHAngle = 0.0;
364
0
        }
365
0
        else
366
0
        {
367
0
            if ((maFullBound.GetWidth() == 0) || (maFullBound.GetHeight() == 0))
368
0
                throw o3tl::divide_by_zero();
369
0
            fWAngle = 90.0 * static_cast<double>(rPnt.X() - maLastPos.X())
370
0
                / static_cast<double>(maFullBound.GetWidth());
371
0
            fHAngle = 90.0 * static_cast<double>(rPnt.Y() - maLastPos.Y())
372
0
                / static_cast<double>(maFullBound.GetHeight());
373
0
        }
374
0
        tools::Long nSnap = 0;
375
376
0
        if(!getSdrDragView().IsRotateAllowed())
377
0
            nSnap = 90;
378
379
0
        if(nSnap != 0)
380
0
        {
381
0
            fWAngle = static_cast<double>((static_cast<tools::Long>(fWAngle) + nSnap/2) / nSnap * nSnap);
382
0
            fHAngle = static_cast<double>((static_cast<tools::Long>(fHAngle) + nSnap/2) / nSnap * nSnap);
383
0
        }
384
385
        // to radians
386
0
        fWAngle = basegfx::deg2rad(fWAngle);
387
0
        fHAngle = basegfx::deg2rad(fHAngle);
388
389
        // Determine transformation
390
0
        basegfx::B3DHomMatrix aRotMat;
391
0
        if(E3dDragConstraint::Y & meConstraint)
392
0
        {
393
0
            if(nModifier & KEY_MOD2)
394
0
                aRotMat.rotate(0.0, 0.0, fWAngle);
395
0
            else
396
0
                aRotMat.rotate(0.0, fWAngle, 0.0);
397
0
        }
398
0
        else if(E3dDragConstraint::Z & meConstraint)
399
0
        {
400
0
            if(nModifier & KEY_MOD2)
401
0
                aRotMat.rotate(0.0, fWAngle, 0.0);
402
0
            else
403
0
                aRotMat.rotate(0.0, 0.0, fWAngle);
404
0
        }
405
0
        if(E3dDragConstraint::X & meConstraint)
406
0
        {
407
0
            aRotMat.rotate(fHAngle, 0.0, 0.0);
408
0
        }
409
410
0
        const E3dScene* pScene(rCandidate.mr3DObj.getRootE3dSceneFromE3dObject());
411
412
0
        if(nullptr != pScene)
413
0
        {
414
            // Transformation in eye coordinates, there rotate then and back
415
0
            const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
416
0
            const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
417
0
            basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
418
0
            aInverseOrientation.invert();
419
420
0
            basegfx::B3DHomMatrix aTransMat(rCandidate.maDisplayTransform);
421
0
            aTransMat *= aViewInfo3D.getOrientation();
422
0
            aTransMat.translate(-maGlobalCenter.getX(), -maGlobalCenter.getY(), -maGlobalCenter.getZ());
423
0
            aTransMat *= aRotMat;
424
0
            aTransMat.translate(maGlobalCenter.getX(), maGlobalCenter.getY(), maGlobalCenter.getZ());
425
0
            aTransMat *= aInverseOrientation;
426
0
            aTransMat *= rCandidate.maInvDisplayTransform;
427
428
            // ...and apply
429
0
            rCandidate.maTransform *= aTransMat;
430
431
0
            if(mbMoveFull)
432
0
            {
433
0
                E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
434
0
                rCandidate.mr3DObj.SetTransform(rCandidate.maTransform);
435
0
            }
436
0
            else
437
0
            {
438
0
                Hide();
439
0
                rCandidate.maWireframePoly.transform(aTransMat);
440
0
                Show();
441
0
            }
442
0
        }
443
0
    }
444
0
    maLastPos = rPnt;
445
0
    DragStat().NextMove(rPnt);
446
0
}
447
448
PointerStyle E3dDragRotate::GetSdrDragPointer() const
449
0
{
450
0
    return PointerStyle::Rotate;
451
0
}
452
453
// E3dDragMove. This drag method is only required for translations inside
454
// 3D scenes. If a 3D-scene itself moved, then this drag method will drag
455
// not be used.
456
457
458
E3dDragMove::E3dDragMove(SdrDragView &_rView,
459
    const SdrMarkList& rMark,
460
    SdrHdlKind eDrgHdl,
461
    E3dDragConstraint eConstr,
462
    bool bFull)
463
0
:   E3dDragMethod(_rView, rMark, eConstr, bFull),
464
0
    meWhatDragHdl(eDrgHdl)
465
0
{
466
0
    switch(meWhatDragHdl)
467
0
    {
468
0
        case SdrHdlKind::Left:
469
0
            maScaleFixPos = maFullBound.RightCenter();
470
0
            break;
471
0
        case SdrHdlKind::Right:
472
0
            maScaleFixPos = maFullBound.LeftCenter();
473
0
            break;
474
0
        case SdrHdlKind::Upper:
475
0
            maScaleFixPos = maFullBound.BottomCenter();
476
0
            break;
477
0
        case SdrHdlKind::Lower:
478
0
            maScaleFixPos = maFullBound.TopCenter();
479
0
            break;
480
0
        case SdrHdlKind::UpperLeft:
481
0
            maScaleFixPos = maFullBound.BottomRight();
482
0
            break;
483
0
        case SdrHdlKind::UpperRight:
484
0
            maScaleFixPos = maFullBound.BottomLeft();
485
0
            break;
486
0
        case SdrHdlKind::LowerLeft:
487
0
            maScaleFixPos = maFullBound.TopRight();
488
0
            break;
489
0
        case SdrHdlKind::LowerRight:
490
0
            maScaleFixPos = maFullBound.TopLeft();
491
0
            break;
492
0
        default:
493
            // Moving the object, SdrHdlKind::Move
494
0
            break;
495
0
    }
496
497
    // Override when IsResizeAtCenter()
498
0
    if(getSdrDragView().IsResizeAtCenter())
499
0
    {
500
0
        meWhatDragHdl = SdrHdlKind::User;
501
0
        maScaleFixPos = maFullBound.Center();
502
0
    }
503
0
}
504
505
// The object is moved, determine the translations
506
507
void E3dDragMove::MoveSdrDrag(const Point& rPnt)
508
0
{
509
    // call parent
510
0
    E3dDragMethod::MoveSdrDrag(rPnt);
511
512
0
    if(!DragStat().CheckMinMoved(rPnt))
513
0
        return;
514
515
0
    if(SdrHdlKind::Move == meWhatDragHdl)
516
0
    {
517
        // Translation
518
        // Determine the motion vector
519
0
        const sal_uInt32 nCnt(maGrp.size());
520
521
        // Get modifier
522
0
        sal_uInt16 nModifier(0);
523
524
0
        if(auto pDragView = dynamic_cast<const E3dView*>(&getSdrDragView()))
525
0
        {
526
0
            const MouseEvent& rLastMouse = pDragView->GetMouseEvent();
527
0
            nModifier = rLastMouse.GetModifier();
528
0
        }
529
530
0
        for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
531
0
        {
532
0
            E3dDragMethodUnit& rCandidate = maGrp[nOb];
533
0
            const E3dScene* pScene(rCandidate.mr3DObj.getRootE3dSceneFromE3dObject());
534
535
0
            if(nullptr != pScene)
536
0
            {
537
0
                const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
538
0
                const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
539
540
                // move coor from 2d world to 3d Eye
541
0
                basegfx::B2DPoint aGlobalMoveHead2D(static_cast<double>(rPnt.X() - maLastPos.X()), static_cast<double>(rPnt.Y() - maLastPos.Y()));
542
0
                basegfx::B2DPoint aGlobalMoveTail2D(0.0, 0.0);
543
0
                basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
544
545
0
                aInverseSceneTransform.invert();
546
0
                aGlobalMoveHead2D = aInverseSceneTransform * aGlobalMoveHead2D;
547
0
                aGlobalMoveTail2D = aInverseSceneTransform * aGlobalMoveTail2D;
548
549
0
                basegfx::B3DPoint aMoveHead3D(aGlobalMoveHead2D.getX(), aGlobalMoveHead2D.getY(), 0.5);
550
0
                basegfx::B3DPoint aMoveTail3D(aGlobalMoveTail2D.getX(), aGlobalMoveTail2D.getY(), 0.5);
551
0
                basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
552
0
                aInverseViewToEye.invert();
553
554
0
                aMoveHead3D = aInverseViewToEye * aMoveHead3D;
555
0
                aMoveTail3D = aInverseViewToEye * aMoveTail3D;
556
557
                // eventually switch movement from XY to XZ plane
558
0
                if(nModifier & KEY_MOD2)
559
0
                {
560
0
                    double fZwi = aMoveHead3D.getY();
561
0
                    aMoveHead3D.setY(aMoveHead3D.getZ());
562
0
                    aMoveHead3D.setZ(fZwi);
563
564
0
                    fZwi = aMoveTail3D.getY();
565
0
                    aMoveTail3D.setY(aMoveTail3D.getZ());
566
0
                    aMoveTail3D.setZ(fZwi);
567
0
                }
568
569
                // Motion vector from eye coordinates to parent coordinates
570
0
                basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
571
0
                aInverseOrientation.invert();
572
0
                basegfx::B3DHomMatrix aCompleteTrans(rCandidate.maInvDisplayTransform * aInverseOrientation);
573
574
0
                aMoveHead3D = aCompleteTrans * aMoveHead3D;
575
0
                aMoveTail3D = aCompleteTrans* aMoveTail3D;
576
577
                // build transformation
578
0
                basegfx::B3DHomMatrix aTransMat;
579
0
                basegfx::B3DPoint aTranslate(aMoveHead3D - aMoveTail3D);
580
0
                aTransMat.translate(aTranslate.getX(), aTranslate.getY(), aTranslate.getZ());
581
582
                // ...and apply
583
0
                rCandidate.maTransform *= aTransMat;
584
585
0
                if(mbMoveFull)
586
0
                {
587
0
                    E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
588
0
                    rCandidate.mr3DObj.SetTransform(rCandidate.maTransform);
589
0
                }
590
0
                else
591
0
                {
592
0
                    Hide();
593
0
                    rCandidate.maWireframePoly.transform(aTransMat);
594
0
                    Show();
595
0
                }
596
0
            }
597
0
        }
598
0
    }
599
0
    else
600
0
    {
601
        // Scaling
602
        // Determine scaling vector
603
0
        Point aStartPos = DragStat().GetStart();
604
0
        const sal_uInt32 nCnt(maGrp.size());
605
606
0
        for(sal_uInt32 nOb(0); nOb < nCnt; nOb++)
607
0
        {
608
0
            E3dDragMethodUnit& rCandidate = maGrp[nOb];
609
0
            const basegfx::B3DPoint aObjectCenter(rCandidate.mr3DObj.GetBoundVolume().getCenter());
610
0
            const E3dScene* pScene(rCandidate.mr3DObj.getRootE3dSceneFromE3dObject());
611
612
0
            if(nullptr != pScene)
613
0
            {
614
                // transform from 2D world view to 3D eye
615
0
                const sdr::contact::ViewContactOfE3dScene& rVCScene = static_cast< sdr::contact::ViewContactOfE3dScene& >(pScene->GetViewContact());
616
0
                const drawinglayer::geometry::ViewInformation3D& aViewInfo3D(rVCScene.getViewInformation3D());
617
618
0
                basegfx::B2DPoint aGlobalScaleStart2D(static_cast<double>(aStartPos.X()), static_cast<double>(aStartPos.Y()));
619
0
                basegfx::B2DPoint aGlobalScaleNext2D(static_cast<double>(rPnt.X()), static_cast<double>(rPnt.Y()));
620
0
                basegfx::B2DPoint aGlobalScaleFixPos2D(static_cast<double>(maScaleFixPos.X()), static_cast<double>(maScaleFixPos.Y()));
621
0
                basegfx::B2DHomMatrix aInverseSceneTransform(rVCScene.getObjectTransformation());
622
623
0
                aInverseSceneTransform.invert();
624
0
                aGlobalScaleStart2D = aInverseSceneTransform * aGlobalScaleStart2D;
625
0
                aGlobalScaleNext2D = aInverseSceneTransform * aGlobalScaleNext2D;
626
0
                aGlobalScaleFixPos2D = aInverseSceneTransform * aGlobalScaleFixPos2D;
627
628
0
                basegfx::B3DPoint aGlobalScaleStart3D(aGlobalScaleStart2D.getX(), aGlobalScaleStart2D.getY(), aObjectCenter.getZ());
629
0
                basegfx::B3DPoint aGlobalScaleNext3D(aGlobalScaleNext2D.getX(), aGlobalScaleNext2D.getY(), aObjectCenter.getZ());
630
0
                basegfx::B3DPoint aGlobalScaleFixPos3D(aGlobalScaleFixPos2D.getX(), aGlobalScaleFixPos2D.getY(), aObjectCenter.getZ());
631
0
                basegfx::B3DHomMatrix aInverseViewToEye(aViewInfo3D.getDeviceToView() * aViewInfo3D.getProjection());
632
633
0
                aInverseViewToEye.invert();
634
0
                basegfx::B3DPoint aScStart(aInverseViewToEye * aGlobalScaleStart3D);
635
0
                basegfx::B3DPoint aScNext(aInverseViewToEye * aGlobalScaleNext3D);
636
0
                basegfx::B3DPoint aScFixPos(aInverseViewToEye * aGlobalScaleFixPos3D);
637
638
                // constraints?
639
0
                switch(meWhatDragHdl)
640
0
                {
641
0
                    case SdrHdlKind::Left:
642
0
                    case SdrHdlKind::Right:
643
                        // to constrain on X -> Y equal
644
0
                        aScNext.setY(aScFixPos.getY());
645
0
                        break;
646
0
                    case SdrHdlKind::Upper:
647
0
                    case SdrHdlKind::Lower:
648
                        // constrain to Y -> X equal
649
0
                        aScNext.setX(aScFixPos.getX());
650
0
                        break;
651
0
                    default:
652
0
                        break;
653
0
                }
654
655
                // get scale vector in eye coordinates
656
0
                basegfx::B3DPoint aScaleVec(aScStart - aScFixPos);
657
0
                aScaleVec.setZ(1.0);
658
659
0
                if(aScaleVec.getX() != 0.0)
660
0
                {
661
0
                    aScaleVec.setX((aScNext.getX() - aScFixPos.getX()) / aScaleVec.getX());
662
0
                }
663
0
                else
664
0
                {
665
0
                    aScaleVec.setX(1.0);
666
0
                }
667
668
0
                if(aScaleVec.getY() != 0.0)
669
0
                {
670
0
                    aScaleVec.setY((aScNext.getY() - aScFixPos.getY()) / aScaleVec.getY());
671
0
                }
672
0
                else
673
0
                {
674
0
                    aScaleVec.setY(1.0);
675
0
                }
676
677
                // SHIFT-key used?
678
0
                if(getSdrDragView().IsOrtho())
679
0
                {
680
0
                    if(fabs(aScaleVec.getX()) > fabs(aScaleVec.getY()))
681
0
                    {
682
                        // X is biggest
683
0
                        aScaleVec.setY(aScaleVec.getX());
684
0
                    }
685
0
                    else
686
0
                    {
687
                        // Y is biggest
688
0
                        aScaleVec.setX(aScaleVec.getY());
689
0
                    }
690
0
                }
691
692
                // build transformation
693
0
                basegfx::B3DHomMatrix aInverseOrientation(aViewInfo3D.getOrientation());
694
0
                aInverseOrientation.invert();
695
696
0
                basegfx::B3DHomMatrix aNewTrans = rCandidate.maInitTransform;
697
0
                aNewTrans *= rCandidate.maDisplayTransform;
698
0
                aNewTrans *= aViewInfo3D.getOrientation();
699
0
                aNewTrans.translate(-aScFixPos.getX(), -aScFixPos.getY(), -aScFixPos.getZ());
700
0
                aNewTrans.scale(aScaleVec.getX(), aScaleVec.getY(), aScaleVec.getZ());
701
0
                aNewTrans.translate(aScFixPos.getX(), aScFixPos.getY(), aScFixPos.getZ());
702
0
                aNewTrans *= aInverseOrientation;
703
0
                aNewTrans *= rCandidate.maInvDisplayTransform;
704
705
                // ...and apply
706
0
                rCandidate.maTransform = std::move(aNewTrans);
707
708
0
                if(mbMoveFull)
709
0
                {
710
0
                    E3DModifySceneSnapRectUpdater aUpdater(&rCandidate.mr3DObj);
711
0
                    rCandidate.mr3DObj.SetTransform(rCandidate.maTransform);
712
0
                }
713
0
                else
714
0
                {
715
0
                    Hide();
716
0
                    rCandidate.maWireframePoly.clear();
717
0
                    rCandidate.maWireframePoly = rCandidate.mr3DObj.CreateWireframe();
718
0
                    rCandidate.maWireframePoly.transform(rCandidate.maTransform);
719
0
                    Show();
720
0
                }
721
0
            }
722
0
        }
723
0
    }
724
0
    maLastPos = rPnt;
725
0
    DragStat().NextMove(rPnt);
726
0
}
727
728
PointerStyle E3dDragMove::GetSdrDragPointer() const
729
0
{
730
0
    return PointerStyle::Move;
731
0
}
732
733
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */