aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lightmapviewer/ImageViewer.qml
blob: 058b867c1c317a792cad7629e78aebef1f3c1f61 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
import QtQuick

import LightmapFile 1.0

Rectangle {
    id: scrollView
    clip: true
    color: "black"

    property real lastMouseX: 0
    property real lastMouseY: 0

    function clamp() {
        // If the image is smaller than the scroll view, center it
        if (image.width <= scrollView.width) {
            imageCenterX = 0
        } else {
            const maxOffsetX = (image.width - scrollView.width) / 2
            imageCenterX = Math.max(-maxOffsetX,
                                    Math.min(imageCenterX,
                                             maxOffsetX))
        }

        if (image.height <= scrollView.height) {
            imageCenterY = 0
        } else {
            const maxOffsetY = (image.height - scrollView.height) / 2
            imageCenterY = Math.max(-maxOffsetY,
                                    Math.min(imageCenterY,
                                             maxOffsetY))
        }
    }

    onWidthChanged: clamp()
    onHeightChanged: clamp()

    Connections {
        target: window
        function onSelectedEntryChanged() {
            if (imageLoader.item === scrollView) {
                imageZoom = 1
                imageCenterX = 0
                imageCenterY = 0
            }
        }
    }

    MouseArea {
        id: mouseArea
        property bool dragging: false
        anchors.fill: parent
        onPressed: mouse => {
                       scrollView.lastMouseX = mouse.x
                       scrollView.lastMouseY = mouse.y
                       dragging = true
                   }
        onReleased: mouse => {
                        dragging = false
                    }

        onPositionChanged: mouse => {
                               var dx = mouse.x - scrollView.lastMouseX
                               var dy = mouse.y - scrollView.lastMouseY

                               scrollView.lastMouseX = mouse.x
                               scrollView.lastMouseY = mouse.y

                               imageCenterX += dx
                               imageCenterY += dy

                               clamp()
                           }
        cursorShape: mouseArea.dragging ? Qt.ClosedHandCursor : Qt.ArrowCursor

        onWheel: event => {
                     const oldZoom = imageZoom
                     const zoomDelta = event.angleDelta.y / 256
                     const newZoom = Math.max(
                         1, Math.min(32, oldZoom + zoomDelta))

                     if (newZoom === oldZoom)
                     return

                     // Adjust center offset so the same point remains at the center
                     const scaleFactor = newZoom / oldZoom
                     imageCenterX *= scaleFactor
                     imageCenterY *= scaleFactor

                     imageZoom = newZoom
                     clamp()

                     event.accepted = true
                 }
    }

    Image {
        id: baseGrid
        anchors.fill: scrollView
        source: "grid.png"
        fillMode: Image.Tile
        opacity: 0.75
    }

    Rectangle {
        width: image.width + (border.width * 2)
        height: image.height + (border.width * 2)
        x: image.x - border.width
        y: image.y - border.width
        color: "white" // This is the border color

        border.width: 0
        border.color: "white"
        opacity: 0.25
        visible: window.isImage(window.selectedEntry)
    }

    Image {
        id: image
        x: Math.round(parent.width / 2 - width / 2) + imageCenterX
        y: Math.round(parent.height / 2 - height / 2) + imageCenterY
        source: window.isImage(
                    window.selectedEntry) ? `image://lightmaps/key=${selectedEntry.key}&tag=${selectedEntry.tag}&file=${LightmapFile.source}&alpha=${alphaSwitch.checked}` : ""
        onWidthChanged: clamp()
        onHeightChanged: clamp()
        fillMode: Image.PreserveAspectFit
        smooth: false
        antialiasing: false

        // Let the image scale visibly
        width: sourceSize.width * imageZoom
        height: sourceSize.height * imageZoom
    }
}