From 784ac996d3ac3c6b121c2d4503342b839c13d82a Mon Sep 17 00:00:00 2001 From: Bruno Herbelin Date: Thu, 29 Dec 2022 00:39:51 +0100 Subject: [PATCH] First operational implementation of Displays View --- CMakeLists.txt | 2 +- rsc/mesh/icon_tv.ply | 580 +++++++++++++++++++++++++ src/Decorations.cpp | 22 +- src/Decorations.h | 4 +- src/DisplaysView.cpp | 886 ++++++++++++++------------------------- src/DisplaysView.h | 46 +- src/GeometryView.cpp | 2 +- src/LayerView.cpp | 2 +- src/MixingView.cpp | 2 +- src/RenderingManager.cpp | 151 ++++--- src/RenderingManager.h | 15 +- src/Settings.cpp | 4 +- src/Settings.h | 4 +- src/TextureView.cpp | 2 +- src/defines.h | 1 + 15 files changed, 1073 insertions(+), 650 deletions(-) create mode 100644 rsc/mesh/icon_tv.ply diff --git a/CMakeLists.txt b/CMakeLists.txt index b1ddaec..ed74e46 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -563,7 +563,7 @@ set(VMIX_RSC_FILES ./rsc/mesh/icon_crop.ply ./rsc/mesh/icon_eye.ply ./rsc/mesh/icon_eye_slash.ply - ./rsc/mesh/icon_vector_square_slash.ply + ./rsc/mesh/icon_tv.ply ./rsc/mesh/icon_cube.ply ./rsc/mesh/icon_sequence.ply ./rsc/mesh/icon_receive.ply diff --git a/rsc/mesh/icon_tv.ply b/rsc/mesh/icon_tv.ply new file mode 100644 index 0000000..bf593b2 --- /dev/null +++ b/rsc/mesh/icon_tv.ply @@ -0,0 +1,580 @@ +ply +format ascii 1.0 +comment Created by Blender 3.2.2 - www.blender.org +element vertex 285 +property float x +property float y +property float z +element face 285 +property list uchar uint vertex_indices +end_header +-0.169188 -0.075740 0.000000 +-0.169243 -0.070732 0.000000 +-0.169243 -0.074063 0.000000 +-0.169243 -0.061524 0.000000 +-0.169243 -0.047614 0.000000 +-0.169243 -0.030177 0.000000 +-0.169243 -0.010389 0.000000 +-0.169243 0.010574 0.000000 +-0.169243 0.031537 0.000000 +-0.169243 0.051325 0.000000 +-0.169243 0.068762 0.000000 +-0.169243 0.082672 0.000000 +-0.169243 0.091880 0.000000 +-0.169243 0.095211 0.000000 +-0.169188 0.096888 0.000000 +-0.169023 -0.077400 0.000000 +-0.169023 0.098548 0.000000 +-0.168751 -0.079040 0.000000 +-0.168751 0.100187 0.000000 +-0.168373 -0.080652 0.000000 +-0.168373 0.101800 0.000000 +-0.167892 -0.082234 0.000000 +-0.167892 0.103382 0.000000 +-0.167310 -0.083780 0.000000 +-0.167310 0.104927 0.000000 +-0.166629 -0.085284 0.000000 +-0.166629 0.106432 0.000000 +-0.165850 -0.086742 0.000000 +-0.165850 0.107890 0.000000 +-0.164976 -0.088150 0.000000 +-0.164976 0.109298 0.000000 +-0.164010 0.110649 0.000000 +-0.164010 -0.089501 0.000000 +-0.162952 0.111940 0.000000 +-0.162952 -0.090792 0.000000 +-0.161805 0.113165 0.000000 +-0.161805 -0.092017 0.000000 +-0.160580 0.114312 0.000000 +-0.160580 -0.093164 0.000000 +-0.159289 0.115369 0.000000 +-0.159289 -0.094221 0.000000 +-0.157937 0.116336 0.000000 +-0.157937 -0.095188 0.000000 +-0.156529 0.117209 0.000000 +-0.156529 -0.096062 0.000000 +-0.155070 0.117988 0.000000 +-0.155070 -0.096840 0.000000 +-0.153566 0.118669 0.000000 +-0.153566 -0.097521 0.000000 +-0.152020 0.119251 0.000000 +-0.152020 -0.098103 0.000000 +-0.150438 0.119732 0.000000 +-0.150438 -0.098584 0.000000 +-0.149867 0.100208 0.000000 +-0.148825 0.120109 0.000000 +-0.148825 -0.098962 0.000000 +-0.149867 -0.079856 0.000000 +0.150125 0.100208 0.000000 +0.150125 -0.079856 0.000000 +-0.147185 0.120382 0.000000 +-0.147185 -0.099234 0.000000 +-0.145524 0.120546 0.000000 +-0.145524 -0.099399 0.000000 +-0.143847 0.120602 0.000000 +-0.143847 -0.099454 0.000000 +0.143979 0.120602 0.000000 +-0.141348 -0.099454 0.000000 +-0.134441 -0.099454 0.000000 +-0.124006 -0.099454 0.000000 +-0.110926 -0.099454 0.000000 +-0.118432 -0.126889 0.000000 +-0.118451 -0.126468 0.000000 +-0.118451 -0.126625 0.000000 +-0.118451 -0.126034 0.000000 +-0.118451 -0.125379 0.000000 +-0.118451 -0.124557 0.000000 +-0.118451 -0.123624 0.000000 +-0.118451 -0.122636 0.000000 +-0.118451 -0.121647 0.000000 +-0.118451 -0.120715 0.000000 +-0.118451 -0.119893 0.000000 +-0.118451 -0.119237 0.000000 +-0.118451 -0.118803 0.000000 +-0.118451 -0.118646 0.000000 +-0.118432 -0.118382 0.000000 +-0.118377 -0.127150 0.000000 +-0.118377 -0.118122 0.000000 +-0.118286 -0.127407 0.000000 +-0.118286 -0.117864 0.000000 +-0.118160 -0.127661 0.000000 +-0.118160 -0.117611 0.000000 +-0.118000 -0.127909 0.000000 +-0.118000 -0.117362 0.000000 +-0.117806 -0.128152 0.000000 +-0.117806 -0.117119 0.000000 +-0.117579 -0.128388 0.000000 +-0.117579 -0.116883 0.000000 +-0.117319 -0.128618 0.000000 +-0.117319 -0.116654 0.000000 +-0.117028 -0.128839 0.000000 +-0.117028 -0.116433 0.000000 +-0.116706 -0.129051 0.000000 +-0.116706 -0.116220 0.000000 +-0.116353 -0.129254 0.000000 +-0.116353 -0.116017 0.000000 +-0.115971 -0.129446 0.000000 +-0.115971 -0.115825 0.000000 +-0.115563 -0.129627 0.000000 +-0.115563 -0.115645 0.000000 +-0.115132 -0.129793 0.000000 +-0.115132 -0.115479 0.000000 +-0.114682 -0.129945 0.000000 +-0.114682 -0.115327 0.000000 +-0.114212 -0.130082 0.000000 +-0.114212 -0.115189 0.000000 +-0.113726 -0.130204 0.000000 +-0.113726 -0.115067 0.000000 +-0.113225 -0.130311 0.000000 +-0.113225 -0.114960 0.000000 +-0.112709 -0.130403 0.000000 +-0.112709 -0.114869 0.000000 +-0.112182 -0.130478 0.000000 +-0.112182 -0.114793 0.000000 +-0.111644 -0.130538 0.000000 +-0.111644 -0.114734 0.000000 +-0.111098 -0.130580 0.000000 +-0.111098 -0.114691 0.000000 +-0.110544 -0.130606 0.000000 +-0.110544 -0.114665 0.000000 +-0.096082 -0.099454 0.000000 +-0.109985 -0.130615 0.000000 +-0.109985 -0.114656 0.000000 +-0.105654 -0.130615 0.000000 +-0.016865 -0.114656 0.000000 +-0.093681 -0.130615 0.000000 +-0.080356 -0.099454 0.000000 +-0.075594 -0.130615 0.000000 +-0.064630 -0.099454 0.000000 +-0.052921 -0.130615 0.000000 +-0.049786 -0.099454 0.000000 +-0.027192 -0.130615 0.000000 +-0.036706 -0.099454 0.000000 +-0.026271 -0.099454 0.000000 +0.000066 -0.130615 0.000000 +-0.019363 -0.099454 0.000000 +-0.016865 -0.099454 0.000000 +0.016997 -0.099454 0.000000 +0.027324 -0.130615 0.000000 +0.016997 -0.114656 0.000000 +0.143979 -0.099454 0.000000 +0.018829 -0.114656 0.000000 +0.023895 -0.114656 0.000000 +0.031547 -0.114656 0.000000 +0.053054 -0.130615 0.000000 +0.041139 -0.114656 0.000000 +0.052025 -0.114656 0.000000 +0.063557 -0.114656 0.000000 +0.075726 -0.130615 0.000000 +0.075089 -0.114656 0.000000 +0.085975 -0.114656 0.000000 +0.093813 -0.130615 0.000000 +0.095567 -0.114656 0.000000 +0.105786 -0.130615 0.000000 +0.103219 -0.114656 0.000000 +0.108285 -0.114656 0.000000 +0.110117 -0.130615 0.000000 +0.110117 -0.114656 0.000000 +0.110676 -0.114665 0.000000 +0.110676 -0.130606 0.000000 +0.111230 -0.114691 0.000000 +0.111230 -0.130580 0.000000 +0.111776 -0.114734 0.000000 +0.111776 -0.130538 0.000000 +0.112314 -0.114793 0.000000 +0.112314 -0.130478 0.000000 +0.112842 -0.114869 0.000000 +0.112842 -0.130403 0.000000 +0.113357 -0.114960 0.000000 +0.113357 -0.130311 0.000000 +0.113858 -0.115067 0.000000 +0.113858 -0.130204 0.000000 +0.114345 -0.115189 0.000000 +0.114345 -0.130082 0.000000 +0.114814 -0.115327 0.000000 +0.114814 -0.129945 0.000000 +0.115264 -0.115479 0.000000 +0.115264 -0.129793 0.000000 +0.115695 -0.115645 0.000000 +0.115695 -0.129627 0.000000 +0.116103 -0.115825 0.000000 +0.116103 -0.129446 0.000000 +0.116485 -0.116017 0.000000 +0.116485 -0.129254 0.000000 +0.116838 -0.116220 0.000000 +0.116838 -0.129051 0.000000 +0.117160 -0.116433 0.000000 +0.117160 -0.128839 0.000000 +0.117452 -0.116654 0.000000 +0.117452 -0.128618 0.000000 +0.117711 -0.116883 0.000000 +0.117711 -0.128388 0.000000 +0.117938 -0.117119 0.000000 +0.117938 -0.128152 0.000000 +0.118132 -0.117362 0.000000 +0.118132 -0.127909 0.000000 +0.118293 -0.117611 0.000000 +0.118293 -0.127661 0.000000 +0.118419 -0.117864 0.000000 +0.118419 -0.127407 0.000000 +0.118509 -0.118122 0.000000 +0.118509 -0.127150 0.000000 +0.118564 -0.118383 0.000000 +0.118564 -0.126889 0.000000 +0.118583 -0.118646 0.000000 +0.118583 -0.126625 0.000000 +0.118583 -0.126468 0.000000 +0.118583 -0.126034 0.000000 +0.118583 -0.125379 0.000000 +0.118583 -0.124557 0.000000 +0.118583 -0.123624 0.000000 +0.118583 -0.122636 0.000000 +0.118583 -0.121647 0.000000 +0.118583 -0.120715 0.000000 +0.118583 -0.119893 0.000000 +0.118583 -0.119237 0.000000 +0.118583 -0.118803 0.000000 +0.145656 0.120546 0.000000 +0.145656 -0.099399 0.000000 +0.147317 0.120382 0.000000 +0.147317 -0.099234 0.000000 +0.148957 0.120109 0.000000 +0.148957 -0.098962 0.000000 +0.150570 0.119732 0.000000 +0.150570 -0.098584 0.000000 +0.152152 0.119251 0.000000 +0.152152 -0.098103 0.000000 +0.153698 0.118669 0.000000 +0.153698 -0.097521 0.000000 +0.155203 0.117988 0.000000 +0.155203 -0.096840 0.000000 +0.156661 0.117209 0.000000 +0.156661 -0.096062 0.000000 +0.158069 0.116336 0.000000 +0.158069 -0.095188 0.000000 +0.159421 0.115369 0.000000 +0.159421 -0.094221 0.000000 +0.160712 0.114312 0.000000 +0.160712 -0.093164 0.000000 +0.161937 0.113165 0.000000 +0.161937 -0.092017 0.000000 +0.163084 0.111940 0.000000 +0.163084 -0.090792 0.000000 +0.164142 0.110649 0.000000 +0.164142 -0.089501 0.000000 +0.165109 0.109298 0.000000 +0.165109 -0.088150 0.000000 +0.165982 0.107890 0.000000 +0.165982 -0.086742 0.000000 +0.166761 0.106432 0.000000 +0.166761 -0.085284 0.000000 +0.167442 0.104927 0.000000 +0.167442 -0.083780 0.000000 +0.168025 0.103382 0.000000 +0.168025 -0.082234 0.000000 +0.168505 0.101800 0.000000 +0.168505 -0.080652 0.000000 +0.168883 0.100187 0.000000 +0.168883 -0.079040 0.000000 +0.169155 0.098548 0.000000 +0.169155 -0.077400 0.000000 +0.169320 0.096888 0.000000 +0.169320 -0.075740 0.000000 +0.169376 0.095211 0.000000 +0.169376 -0.074063 0.000000 +0.169376 0.091880 0.000000 +0.169376 -0.070732 0.000000 +0.169376 -0.061524 0.000000 +0.169376 -0.047614 0.000000 +0.169376 -0.030177 0.000000 +0.169376 -0.010389 0.000000 +0.169376 0.010574 0.000000 +0.169376 0.031537 0.000000 +0.169376 0.051325 0.000000 +0.169376 0.068762 0.000000 +0.169376 0.082672 0.000000 +3 0 1 2 +3 0 3 1 +3 0 4 3 +3 0 5 4 +3 0 6 5 +3 0 7 6 +3 0 8 7 +3 0 9 8 +3 0 10 9 +3 0 11 10 +3 0 12 11 +3 0 13 12 +3 0 14 13 +3 15 14 0 +3 15 16 14 +3 17 16 15 +3 17 18 16 +3 19 18 17 +3 19 20 18 +3 21 20 19 +3 21 22 20 +3 23 22 21 +3 23 24 22 +3 25 24 23 +3 25 26 24 +3 27 26 25 +3 27 28 26 +3 29 28 27 +3 29 30 28 +3 29 31 30 +3 32 31 29 +3 32 33 31 +3 34 33 32 +3 34 35 33 +3 36 35 34 +3 36 37 35 +3 38 37 36 +3 38 39 37 +3 40 39 38 +3 40 41 39 +3 42 41 40 +3 42 43 41 +3 44 43 42 +3 44 45 43 +3 46 45 44 +3 46 47 45 +3 48 47 46 +3 48 49 47 +3 50 49 48 +3 50 51 49 +3 52 51 50 +3 52 53 51 +3 53 54 51 +3 55 56 52 +3 56 53 52 +3 57 54 53 +3 55 58 56 +3 57 59 54 +3 60 58 55 +3 57 61 59 +3 62 58 60 +3 57 63 61 +3 64 58 62 +3 57 65 63 +3 66 58 64 +3 67 58 66 +3 68 58 67 +3 69 58 68 +3 70 71 72 +3 70 73 71 +3 70 74 73 +3 70 75 74 +3 70 76 75 +3 70 77 76 +3 70 78 77 +3 70 79 78 +3 70 80 79 +3 70 81 80 +3 70 82 81 +3 70 83 82 +3 70 84 83 +3 85 84 70 +3 85 86 84 +3 87 86 85 +3 87 88 86 +3 89 88 87 +3 89 90 88 +3 91 90 89 +3 91 92 90 +3 93 92 91 +3 93 94 92 +3 95 94 93 +3 95 96 94 +3 97 96 95 +3 97 98 96 +3 99 98 97 +3 99 100 98 +3 101 100 99 +3 101 102 100 +3 103 102 101 +3 103 104 102 +3 105 104 103 +3 105 106 104 +3 107 106 105 +3 107 108 106 +3 109 108 107 +3 109 110 108 +3 111 110 109 +3 111 112 110 +3 113 112 111 +3 113 114 112 +3 115 114 113 +3 115 116 114 +3 117 116 115 +3 117 118 116 +3 119 118 117 +3 119 120 118 +3 121 120 119 +3 121 122 120 +3 123 122 121 +3 123 124 122 +3 125 124 123 +3 125 126 124 +3 127 126 125 +3 127 128 126 +3 129 58 69 +3 130 128 127 +3 130 131 128 +3 132 131 130 +3 132 133 131 +3 134 133 132 +3 135 58 129 +3 136 133 134 +3 137 58 135 +3 138 133 136 +3 139 58 137 +3 140 133 138 +3 141 58 139 +3 142 58 141 +3 143 133 140 +3 144 58 142 +3 145 58 144 +3 143 145 133 +3 143 146 145 +3 146 58 145 +3 147 148 143 +3 148 146 143 +3 149 58 146 +3 147 150 148 +3 147 151 150 +3 147 152 151 +3 153 152 147 +3 153 154 152 +3 153 155 154 +3 153 156 155 +3 157 156 153 +3 157 158 156 +3 157 159 158 +3 160 159 157 +3 160 161 159 +3 162 161 160 +3 162 163 161 +3 162 164 163 +3 165 164 162 +3 165 166 164 +3 165 167 166 +3 168 167 165 +3 168 169 167 +3 170 169 168 +3 170 171 169 +3 172 171 170 +3 172 173 171 +3 174 173 172 +3 174 175 173 +3 176 175 174 +3 176 177 175 +3 178 177 176 +3 178 179 177 +3 180 179 178 +3 180 181 179 +3 182 181 180 +3 182 183 181 +3 184 183 182 +3 184 185 183 +3 186 185 184 +3 186 187 185 +3 188 187 186 +3 188 189 187 +3 190 189 188 +3 190 191 189 +3 192 191 190 +3 192 193 191 +3 194 193 192 +3 194 195 193 +3 196 195 194 +3 196 197 195 +3 198 197 196 +3 198 199 197 +3 200 199 198 +3 200 201 199 +3 202 201 200 +3 202 203 201 +3 204 203 202 +3 204 205 203 +3 206 205 204 +3 206 207 205 +3 208 207 206 +3 208 209 207 +3 210 209 208 +3 210 211 209 +3 212 211 210 +3 212 213 211 +3 214 213 212 +3 215 213 214 +3 216 213 215 +3 217 213 216 +3 218 213 217 +3 219 213 218 +3 220 213 219 +3 221 213 220 +3 222 213 221 +3 223 213 222 +3 224 213 223 +3 225 213 224 +3 57 226 65 +3 227 58 149 +3 57 228 226 +3 229 58 227 +3 57 230 228 +3 231 58 229 +3 57 232 230 +3 233 58 231 +3 233 57 58 +3 233 232 57 +3 233 234 232 +3 235 234 233 +3 235 236 234 +3 237 236 235 +3 237 238 236 +3 239 238 237 +3 239 240 238 +3 241 240 239 +3 241 242 240 +3 243 242 241 +3 243 244 242 +3 245 244 243 +3 245 246 244 +3 247 246 245 +3 247 248 246 +3 249 248 247 +3 249 250 248 +3 251 250 249 +3 251 252 250 +3 253 252 251 +3 253 254 252 +3 255 254 253 +3 255 256 254 +3 257 256 255 +3 257 258 256 +3 259 258 257 +3 259 260 258 +3 261 260 259 +3 261 262 260 +3 263 262 261 +3 263 264 262 +3 265 264 263 +3 265 266 264 +3 267 266 265 +3 267 268 266 +3 269 268 267 +3 269 270 268 +3 271 270 269 +3 271 272 270 +3 273 272 271 +3 273 274 272 +3 275 274 273 +3 276 274 275 +3 277 274 276 +3 278 274 277 +3 279 274 278 +3 280 274 279 +3 281 274 280 +3 282 274 281 +3 283 274 282 +3 284 274 283 diff --git a/src/Decorations.cpp b/src/Decorations.cpp index d816998..a372ea0 100644 --- a/src/Decorations.cpp +++ b/src/Decorations.cpp @@ -220,6 +220,7 @@ Handles::Handles(Type type) : Node(), type_(type) static Mesh *handle_menu = new Mesh("mesh/border_handles_menu.ply"); static Mesh *handle_lock = new Mesh("mesh/border_handles_lock.ply"); static Mesh *handle_unlock = new Mesh("mesh/border_handles_lock_open.ply"); + static Mesh *handle_eyeslash = new Mesh("mesh/icon_eye_slash.ply"); static Mesh *handle_shadow = new Mesh("mesh/border_handles_shadow.ply", "images/soft_shadow.dds"); if ( type_ == Handles::ROTATE ) { @@ -240,6 +241,9 @@ Handles::Handles(Type type) : Node(), type_(type) else if ( type_ == Handles::UNLOCKED ) { handle_ = handle_unlock; } + else if ( type_ == Handles::EYESLASHED ) { + handle_ = handle_eyeslash; + } else { handle_ = handle_corner; } @@ -371,7 +375,7 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection) // 1. Fixed displacement by (0.12,0.12) along the rotation.. ctm = GlmToolkit::transform(glm::vec4(0.f), rot, mirror); glm::vec4 pos = ctm * glm::vec4(mirror.x * 0.12f, mirror.x * 0.12f, 0.f, 1.f); - // 2. ..from the bottom right corner (1,-1) + // 2. ..from the bottom left corner (-1,-1) vec = ( modelview * glm::vec4(-1.f, -1.f, 0.f, 1.f) ) + pos; ctm = GlmToolkit::transform(vec, rot, mirror); // 3. draw @@ -402,6 +406,18 @@ void Handles::draw(glm::mat4 modelview, glm::mat4 projection) shadow_->draw( ctm, projection ); handle_->draw( ctm, projection ); } + else if ( type_ == Handles::EYESLASHED ){ + // one icon in bottom right corner + // 1. Fixed displacement by (0.12,0.12) along the rotation.. + ctm = GlmToolkit::transform(glm::vec4(0.f), rot, mirror); + glm::vec4 pos = ctm * glm::vec4(mirror.x * 0.15f, mirror.x * 0.15f, 0.f, 1.f); + // 2. ..from the bottom left corner (-1,-1) + vec = ( modelview * glm::vec4(-1.f, -1.f, 0.f, 1.f) ) + pos; + ctm = GlmToolkit::transform(vec, rot, mirror); + // 3. draw + shadow_->draw( ctm, projection ); + handle_->draw( ctm, projection ); + } } } @@ -459,8 +475,8 @@ Symbol::Symbol(Type t, glm::vec3 pos) : Node(), type_(t) shadows[EYE] = shadow; icons[EYESLASH] = new Mesh("mesh/icon_eye_slash.ply"); shadows[EYESLASH] = shadow; - icons[VECTORSLASH] = new Mesh("mesh/icon_vector_square_slash.ply"); - shadows[VECTORSLASH] = shadow; + icons[TELEVISION] = new Mesh("mesh/icon_tv.ply"); + shadows[TELEVISION] = shadow; icons[ARROWS] = new Mesh("mesh/icon_rightarrow.ply"); shadows[ARROWS] = shadow; icons[ROTATION] = new Mesh("mesh/border_handles_rotation.ply"); diff --git a/src/Decorations.h b/src/Decorations.h index 08393e4..a8c61bf 100644 --- a/src/Decorations.h +++ b/src/Decorations.h @@ -36,7 +36,7 @@ protected: class Handles : public Node { public: - typedef enum { RESIZE = 0, RESIZE_H, RESIZE_V, ROTATE, SCALE, CROP, MENU, LOCKED, UNLOCKED } Type; + typedef enum { RESIZE = 0, RESIZE_H, RESIZE_V, ROTATE, SCALE, CROP, MENU, LOCKED, UNLOCKED, EYESLASHED } Type; Handles(Type type); ~Handles(); @@ -61,7 +61,7 @@ class Symbol : public Node { public: typedef enum { CIRCLE_POINT = 0, SQUARE_POINT, IMAGE, SEQUENCE, VIDEO, SESSION, CLONE, RENDER, GROUP, PATTERN, CAMERA, CUBE, SHARE, RECEIVE, - DOTS, BUSY, LOCK, UNLOCK, EYE, EYESLASH, VECTORSLASH, ARROWS, ROTATION, CROP, CIRCLE, SQUARE, CLOCK, CLOCK_H, GRID, CROSS, EMPTY } Type; + DOTS, BUSY, LOCK, UNLOCK, EYE, EYESLASH, TELEVISION, ARROWS, ROTATION, CROP, CIRCLE, SQUARE, CLOCK, CLOCK_H, GRID, CROSS, EMPTY } Type; Symbol(Type t, glm::vec3 pos = glm::vec3(0.f)); ~Symbol(); diff --git a/src/DisplaysView.cpp b/src/DisplaysView.cpp index cb1740c..001902a 100644 --- a/src/DisplaysView.cpp +++ b/src/DisplaysView.cpp @@ -47,97 +47,72 @@ DisplaysView::DisplaysView() : View(DISPLAYS) { scene.root()->scale_ = glm::vec3(DISPLAYS_DEFAULT_SCALE, DISPLAYS_DEFAULT_SCALE, 1.0f); // read default settings - if ( Settings::application.views[mode_].name.empty() ) + if ( Settings::application.views[mode_].name.empty() ) { // no settings found: store application default saveSettings(); + } else restoreSettings(); Settings::application.views[mode_].name = "Displays"; - // Geometry Scene foreground + // stored status of output_ + output_status_ = new Group; + + // Geometry Scene workspace + output_ = new Group; + scene.ws()->attach(output_); output_surface_ = new Surface; - output_surface_->visible_ = false; - scene.fg()->attach(output_surface_); -// Frame *border = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); -// border->color = glm::vec4( COLOR_FRAME, 1.f ); -// scene.fg()->attach(border); + output_->attach(output_surface_); + output_render_ = new Surface; + output_->attach(output_render_); -// // User interface foreground -// // -// // point to show POSITION -// overlay_position_ = new Symbol(Symbol::SQUARE_POINT); -// overlay_position_->scale_ = glm::vec3(0.5f, 0.5f, 1.f); -// scene.fg()->attach(overlay_position_); -// overlay_position_->visible_ = false; -// // cross to show the axis for POSITION -// overlay_position_cross_ = new Symbol(Symbol::GRID); -// overlay_position_cross_->scale_ = glm::vec3(0.5f, 0.5f, 1.f); -// scene.fg()->attach(overlay_position_cross_); -// overlay_position_cross_->visible_ = false; -// // 'clock' : tic marks every 10 degrees for ROTATION -// // with dark background -// overlay_rotation_clock_ = new Group; -// overlay_rotation_clock_tic_ = new Symbol(Symbol::CLOCK); -// overlay_rotation_clock_->attach(overlay_rotation_clock_tic_); -// Symbol *s = new Symbol(Symbol::CIRCLE_POINT); -// s->color = glm::vec4(0.f, 0.f, 0.f, 0.1f); -// s->scale_ = glm::vec3(28.f, 28.f, 1.f); -// s->translation_.z = -0.1; -// overlay_rotation_clock_->attach(s); -// overlay_rotation_clock_->scale_ = glm::vec3(0.25f, 0.25f, 1.f); -// scene.fg()->attach(overlay_rotation_clock_); -// overlay_rotation_clock_->visible_ = false; -// // circle to show fixed-size ROTATION -// overlay_rotation_clock_hand_ = new Symbol(Symbol::CLOCK_H); -// overlay_rotation_clock_hand_->scale_ = glm::vec3(0.25f, 0.25f, 1.f); -// scene.fg()->attach(overlay_rotation_clock_hand_); -// overlay_rotation_clock_hand_->visible_ = false; -// overlay_rotation_fix_ = new Symbol(Symbol::SQUARE); -// overlay_rotation_fix_->scale_ = glm::vec3(0.25f, 0.25f, 1.f); -// scene.fg()->attach(overlay_rotation_fix_); -// overlay_rotation_fix_->visible_ = false; -// // circle to show the center of ROTATION -// overlay_rotation_ = new Symbol(Symbol::CIRCLE); -// overlay_rotation_->scale_ = glm::vec3(0.25f, 0.25f, 1.f); -// scene.fg()->attach(overlay_rotation_); -// overlay_rotation_->visible_ = false; -// // 'grid' : tic marks every 0.1 step for SCALING -// // with dark background -// Group *g = new Group; -// s = new Symbol(Symbol::GRID); -// s->scale_ = glm::vec3(1.655f, 1.655f, 1.f); -// g->attach(s); -// s = new Symbol(Symbol::SQUARE_POINT); -// s->color = glm::vec4(0.f, 0.f, 0.f, 0.1f); -// s->scale_ = glm::vec3(17.f, 17.f, 1.f); -// s->translation_.z = -0.1; -// g->attach(s); -// overlay_scaling_grid_ = g; -// overlay_scaling_grid_->scale_ = glm::vec3(0.3f, 0.3f, 1.f); -// scene.fg()->attach(overlay_scaling_grid_); -// overlay_scaling_grid_->visible_ = false; -// // cross in the square for proportional SCALING -// overlay_scaling_cross_ = new Symbol(Symbol::CROSS); -// overlay_scaling_cross_->scale_ = glm::vec3(0.3f, 0.3f, 1.f); -// scene.fg()->attach(overlay_scaling_cross_); -// overlay_scaling_cross_->visible_ = false; -// // square to show the center of SCALING -// overlay_scaling_ = new Symbol(Symbol::SQUARE); -// overlay_scaling_->scale_ = glm::vec3(0.3f, 0.3f, 1.f); -// scene.fg()->attach(overlay_scaling_); -// overlay_scaling_->visible_ = false; + output_visible_ = new Handles(Handles::EYESLASHED); + output_visible_->visible_ = false; + output_visible_->color = glm::vec4( COLOR_FRAME, 1.f ); + output_->attach(output_visible_); -// border = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); -// border->color = glm::vec4( COLOR_HIGHLIGHT_SOURCE, 0.2f ); -// overlay_crop_ = border; -// scene.fg()->attach(overlay_crop_); -// overlay_crop_->visible_ = false; + // overlays for selected and not selected + output_overlays_ = new Switch; + output_->attach(output_overlays_); + + // output_overlays_ [0] is for not active output frame + Frame *frame = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); + frame->color = glm::vec4( COLOR_FRAME, 1.f ); + output_overlays_->attach(frame); + + // output_overlays_ [1] is for active frame + Group *g = new Group; + output_overlays_->attach(g); + // Overlay menu icon + output_menu_ = new Handles(Handles::MENU); + output_menu_->color = glm::vec4( COLOR_FRAME, 1.f ); + g->attach(output_menu_); + // selected frame + frame = new Frame(Frame::SHARP, Frame::LARGE, Frame::NONE); + frame->color = glm::vec4( COLOR_FRAME, 1.f ); + g->attach(frame); + + // Overlay has two modes : window or fullscreen + output_mode_ = new Switch; + g->attach(output_mode_); + + // output_mode_ [0] is for WINDOWED + output_handles_ = new Handles(Handles::RESIZE); + output_handles_->color = glm::vec4( COLOR_FRAME, 1.f ); + output_mode_->attach(output_handles_); + + // output_mode_ [1] is for FULLSCREEN + output_fullscreen_ = new Symbol(Symbol::TELEVISION); + output_fullscreen_->scale_ = glm::vec3(2.f, 2.f, 1.f); + output_fullscreen_->color = glm::vec4( COLOR_FRAME, 1.f ); + output_mode_->attach(output_fullscreen_); + + // default behavior : selected output in windowed mode + show_output_menu_ = false; + output_selected_=true; + output_overlays_->setActive(1); + output_mode_->setActive(0); - // will be init later - overlay_selection_scale_ = nullptr; - overlay_selection_rotate_ = nullptr; - overlay_selection_stored_status_ = nullptr; - overlay_selection_active_ = false; } void DisplaysView::update(float dt) @@ -148,25 +123,17 @@ void DisplaysView::update(float dt) if (View::need_deep_update_ > 0) { // update rendering of render frame - FrameBuffer *output = Mixer::manager().session()->frame(); - if (output){ -// float aspect_ratio = output->aspectRatio(); -// for (NodeSet::iterator node = scene.bg()->begin(); node != scene.bg()->end(); ++node) { -// (*node)->scale_.x = aspect_ratio; -// } -// for (NodeSet::iterator node = scene.fg()->begin(); node != scene.fg()->end(); ++node) { -// (*node)->scale_.x = aspect_ratio; -// } -// output_surface_->setTextureIndex( output->texture() ); - } + FrameBuffer *render = Mixer::manager().session()->frame(); + if (render) + output_render_->setTextureIndex( render->texture() ); - // prevent invalid scaling - float s = CLAMP(scene.root()->scale_.x, DISPLAYS_MIN_SCALE, DISPLAYS_MAX_SCALE); - scene.root()->scale_.x = s; - scene.root()->scale_.y = s; + +// // prevent invalid scaling +// float s = CLAMP(scene.root()->scale_.x, DISPLAYS_MIN_SCALE, DISPLAYS_MAX_SCALE); +// scene.root()->scale_.x = s; +// scene.root()->scale_.y = s; } - } @@ -175,27 +142,45 @@ void DisplaysView::recenter () { // clear background display of monitors scene.clearBackground(); + scene.clearForeground(); // fill scene background with the frames to show monitors + int index = 1; std::map _monitors = Rendering::manager().monitors(); for (auto monitor_iter = _monitors.begin(); - monitor_iter != _monitors.end(); ++monitor_iter) { + monitor_iter != _monitors.end(); ++monitor_iter, ++index) { - Group *m = new Group; + // get coordinates of monitor in Display units glm::vec4 rect = DISPLAYS_UNIT * glm::vec4(monitor_iter->second); + + // add a background black surface with glow shadow + Group *m = new Group; m->scale_ = glm::vec3( 0.5f * rect.p, 0.5f * rect.q, 1.f ); m->translation_ = glm::vec3( rect.x + m->scale_.x, -rect.y - m->scale_.y, 0.f ); + Surface *surf = new Surface( new Shader); + surf->shader()->color = glm::vec4( 0.1f, 0.1f, 0.1f, 1.f ); - Surface *surf = new Surface; m->attach(surf); - - Frame *frame = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); - frame->color = glm::vec4( COLOR_MONITOR, 1.f ); + Frame *frame = new Frame(Frame::SHARP, Frame::THIN, Frame::GLOW); + frame->color = glm::vec4(COLOR_MONITOR, 1.f); m->attach(frame); - + Glyph *label = new Glyph(4); + label->setChar( std::to_string(index).back() ); + label->color = glm::vec4( COLOR_MONITOR, 1.f ); + label->translation_.y = 0.02f ; + label->scale_.y = 0.4f / rect.p; + m->attach(label); scene.bg()->attach( m ); -// g_printerr("- display %f,%f %f,%f\n", rect.x, rect.y, rect.w, rect.z); + // add a foreground color frame + Group *f = new Group; + f->copyTransform(m); + frame = new Frame(Frame::SHARP, Frame::THIN, Frame::NONE); + frame->color = glm::vec4( COLOR_MONITOR, 0.4f ); + f->attach(frame); + scene.fg()->attach(f); + +// g_printerr("- display %f,%f %f,%f\n", rect.x, rect.y, rect.p, rect.q); // g_printerr(" %f,%f %f,%f\n", m->translation_.x, m->translation_.y, // m->scale_.x, m->scale_.y); } @@ -231,269 +216,183 @@ int DisplaysView::size () void DisplaysView::draw() { -// std::vector surfaces; -// std::vector overlays; - // g_printerr("DisplaysView::draw()\n"); + output_render_->visible_ = !Settings::application.render.disabled; + output_visible_->visible_ = Settings::application.render.disabled; + + + if ( Settings::application.windows[1].fullscreen ) { + output_mode_->setActive( 1 ); + + glm::ivec4 rect = Rendering::manager().monitors()[Settings::application.windows[1].monitor]; + + output_->scale_.x = rect.p * 0.5f * DISPLAYS_UNIT; + output_->scale_.y = rect.q * 0.5f * DISPLAYS_UNIT; + output_->translation_.x = rect.x * DISPLAYS_UNIT + output_->scale_.x; + output_->translation_.y = -rect.y * DISPLAYS_UNIT - output_->scale_.y; + + } + else { + output_mode_->setActive( 0 ); + + if (!current_action_ongoing_) { + + // TODO Mutex for multithread access with changed flag + + output_->scale_.x = Settings::application.windows[1].w * 0.5f * DISPLAYS_UNIT; + output_->scale_.y = Settings::application.windows[1].h * 0.5f * DISPLAYS_UNIT; + output_->translation_.x = Settings::application.windows[1].x * DISPLAYS_UNIT + output_->scale_.x; + output_->translation_.y = -Settings::application.windows[1].y * DISPLAYS_UNIT - output_->scale_.y; + + } + } + + + if (Settings::application.windows[1].scaled) { + output_render_->scale_ = glm::vec3(1.f, 1.f, 1.f); + } + else { + FrameBuffer *output = Mixer::manager().session()->frame(); + if (output){ + float out_ar = output_->scale_.x / output_->scale_.y; + if (output->aspectRatio() < out_ar) + output_render_->scale_ = glm::vec3(output->aspectRatio() / out_ar, 1.f, 1.f); + else + output_render_->scale_ = glm::vec3(1.f, out_ar / output->aspectRatio(), 1.f); + } + } View::draw(); -// // 0. prepare projection for draw visitors -// glm::mat4 projection = Rendering::manager().Projection(); + // display popup menu + if (show_output_menu_) { + ImGui::OpenPopup( "DisplaysOutputContextMenu" ); + show_output_menu_ = false; + } + if (ImGui::BeginPopup("DisplaysOutputContextMenu")) { -//// // 1. Draw surface of sources in the current workspace -//// DrawVisitor draw_surfaces(surfaces, projection); -//// scene.accept(draw_surfaces); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(COLOR_FRAME_LIGHT, 1.f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(COLOR_MENU_HOVERED, 0.5f)); -//// for( auto it = surfaces.begin(); it!=surfaces.end(); ++it) { -//// delete *it; -//// } + if (ImGui::MenuItem( ICON_FA_EYE_SLASH " Disable", nullptr, &Settings::application.render.disabled )){ -//// // 2. Draw scene rendering on top (which includes rendering of all visible sources) -//// DrawVisitor draw_rendering(output_surface_, projection, true); -//// scene.accept(draw_rendering); + } + if (ImGui::MenuItem( ICON_FA_EXPAND_ARROWS_ALT " Scaled", nullptr, &Settings::application.windows[1].scaled )){ -// // 3. Draw frames and icons of sources in the current workspace -// DrawVisitor draw_overlays(overlays, projection); -// scene.accept(draw_overlays); + } + ImGui::Separator(); + bool _windowed = !Settings::application.windows[1].fullscreen; + if (ImGui::MenuItem( ICON_FA_WINDOW_RESTORE " Windowed", nullptr, &_windowed)){ + Rendering::manager().outputWindow().exitFullscreen(); + } + int index = 1; + std::map _monitors = Rendering::manager().monitors(); + for (auto monitor_iter = _monitors.begin(); + monitor_iter != _monitors.end(); ++monitor_iter, ++index) { -// // 4. Draw control overlays of current source on top (if selectable) -// if (s!=nullptr && canSelect(s)) { -// s->setMode(Source::CURRENT); -// DrawVisitor dv(s->overlays_[mode_], projection); -// scene.accept(dv); -// } - -// // 5. Finally, draw overlays of view -// DrawVisitor draw_foreground(scene.fg(), projection); -// scene.accept(draw_foreground); - -// display interface - // Locate window at upper left corner -// glm::vec2 P = glm::vec2(-output_surface_->scale_.x - 0.02f, output_surface_->scale_.y + 0.01 ); -// P = Rendering::manager().project(glm::vec3(P, 0.f), scene.root()->transform_, false); -// // Set window position depending on icons size -// ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); -// ImGui::SetNextWindowPos(ImVec2(P.x, P.y - 1.5f * ImGui::GetFrameHeight() ), ImGuiCond_Always); -// if (ImGui::Begin("##DisplaysViewOptions", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBackground -// | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings -// | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoBringToFrontOnFocus )) -// { -// // style grey -// ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(COLOR_FRAME_LIGHT, 1.f)); // 1 -// ImGui::PushStyleColor(ImGuiCol_PopupBg, ImVec4(0.14f, 0.14f, 0.14f, 0.9f)); -// ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.36f, 0.36f, 0.36f, 0.9f)); -// ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.36f, 0.36f, 0.36f, 0.5f)); -// ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.14f, 0.14f, 0.14f, 0.00f)); -// ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.14f, 0.14f, 0.14f, 0.46f)); -// ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.14f, 0.14f, 0.14f, 0.00f)); -// ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.14f, 0.14f, 0.14f, 0.46f)); // 8 - -// static std::vector< std::pair > icons_ws = { {10,16}, {11,16}, {12,16} }; -// static std::vector< std::string > labels_ws = { "Background", "Workspace", "Foreground" }; -// if ( ImGuiToolkit::ComboIcon (icons_ws, labels_ws, &Settings::application.current_workspace) ){ -// ++View::need_deep_update_; -// } - -// ImGui::PopStyleColor(8); // 14 colors -// ImGui::End(); -// } -// ImGui::PopFont(); - -// // display popup menu -// if (show_context_menu_ == MENU_SOURCE) { -// ImGui::OpenPopup( "DisplaysOutputContextMenu" ); -// show_context_menu_ = MENU_NONE; -// } -// if (ImGui::BeginPopup("DisplaysOutputContextMenu")) { -//// if (s != nullptr) { -//// if (ImGui::Selectable( ICON_FA_EXPAND " Fit" )){ -//// s->group(mode_)->scale_ = glm::vec3(output_surface_->scale_.x/ s->frame()->aspectRatio(), 1.f, 1.f); -//// s->group(mode_)->rotation_.z = 0; -//// s->group(mode_)->translation_ = glm::vec3(0.f); -//// s->touch(); -//// Action::manager().store(s->name() + std::string(": Geometry Fit")); -//// } -//// if (ImGui::Selectable( ICON_FA_VECTOR_SQUARE " Reset" )){ -//// s->group(mode_)->scale_ = glm::vec3(1.f); -//// s->group(mode_)->rotation_.z = 0; -//// s->group(mode_)->crop_ = glm::vec3(1.f); -//// s->group(mode_)->translation_ = glm::vec3(0.f); -//// s->touch(); -//// Action::manager().store(s->name() + std::string(": Geometry Reset")); -//// } -//// if (ImGui::Selectable( ICON_FA_CROSSHAIRS " Reset position" )){ -//// s->group(mode_)->translation_ = glm::vec3(0.f); -//// s->touch(); -//// Action::manager().store(s->name() + std::string(": Reset position")); -//// } -//// if (ImGui::Selectable( ICON_FA_COMPASS " Reset rotation" )){ -//// s->group(mode_)->rotation_.z = 0; -//// s->touch(); -//// Action::manager().store(s->name() + std::string(": Reset rotation")); -//// } -//// if (ImGui::Selectable( ICON_FA_EXPAND_ALT " Reset aspect ratio" )){ -//// s->group(mode_)->scale_.x = s->group(mode_)->scale_.y; -//// s->group(mode_)->scale_.x *= s->group(mode_)->crop_.x / s->group(mode_)->crop_.y; -//// s->touch(); -//// Action::manager().store(s->name() + std::string(": Reset aspect ratio")); -//// } -//// } -// ImGui::EndPopup(); -// } + bool _fullscreen = Settings::application.windows[1].fullscreen && + Settings::application.windows[1].monitor == monitor_iter->first; + std::string menutext = std::string( ICON_FA_TV " Fullscreen ") + std::to_string(index); + if (ImGui::MenuItem( menutext.c_str(), nullptr, _fullscreen )){ + Rendering::manager().outputWindow().setFullscreen( monitor_iter->first ); + } + } + ImGui::PopStyleColor(2); + ImGui::EndPopup(); + } } - std::pair DisplaysView::pick(glm::vec2 P) { - // prepare empty return value - std::pair pick = { nullptr, glm::vec2(0.f) }; + // get picking from generic View + std::pair pick = View::pick(P); - // unproject mouse coordinate into scene coordinates - glm::vec3 scene_point_ = Rendering::manager().unProject(P); + // ignore pick on render surface: it's the same as output surface + if (pick.first == output_render_) + pick.first = output_surface_; -// // picking visitor traverses the scene -// PickingVisitor pv(scene_point_); -// scene.accept(pv); + if (pick.first == output_menu_) + show_output_menu_ = true; -// // picking visitor found nodes? -// if ( !pv.empty() ) { -// // keep current source active if it is clicked -// Source *current = Mixer::manager().currentSource(); -// if (current != nullptr) { -// if (current->workspace() != Settings::application.current_workspace){ -// current = nullptr; -// } -// else { -// // find if the current source was picked -// auto itp = pv.rbegin(); -// for (; itp != pv.rend(); ++itp){ -// // test if source contains this node -// Source::hasNode is_in_source((*itp).first ); -// if ( is_in_source( current ) ){ -// // a node in the current source was clicked ! -// pick = *itp; -// break; -// } -// } -// // not found: the current source was not clicked -// if (itp == pv.rend()) { -// current = nullptr; -// } -// // picking on the menu handle: show context menu -// else if ( pick.first == current->handles_[mode_][Handles::MENU] ) { -// openContextMenu(MENU_SOURCE); -// } -// // pick on the lock icon; unlock source -// else if ( UserInterface::manager().ctrlModifier() && pick.first == current->lock_ ) { -// lock(current, false); -// pick = { current->locker_, pick.second }; -//// pick = { nullptr, glm::vec2(0.f) }; -// } -// // pick on the open lock icon; lock source and cancel pick -// else if ( UserInterface::manager().ctrlModifier() && pick.first == current->unlock_ ) { -// lock(current, true); -// pick = { nullptr, glm::vec2(0.f) }; -// } -// // pick a locked source ; cancel pick -// else if ( !UserInterface::manager().ctrlModifier() && current->locked() ) { -// pick = { nullptr, glm::vec2(0.f) }; -// } -// } -// } -// // the clicked source changed (not the current source) -// if (current == nullptr) { - -// if (UserInterface::manager().ctrlModifier()) { - -// // default to failed pick -// pick = { nullptr, glm::vec2(0.f) }; - -// // loop over all nodes picked to detect clic on locks -// for (auto itp = pv.rbegin(); itp != pv.rend(); ++itp){ -// // get if a source was picked -// Source *s = Mixer::manager().findSource((*itp).first); -// // lock icon of a source (not current) is picked : unlock -// if ( s!=nullptr && (*itp).first == s->lock_) { -// lock(s, false); -// pick = { s->locker_, (*itp).second }; -// break; -// } -// } -// } -// // no lock icon picked, find what else was picked -// if ( pick.first == nullptr) { - -// // loop over all nodes picked -// for (auto itp = pv.rbegin(); itp != pv.rend(); ++itp){ -// // get if a source was picked -// Source *s = Mixer::manager().findSource((*itp).first); -// // accept picked sources in current workspaces -// if ( s!=nullptr && s->workspace() == Settings::application.current_workspace) { -// // a non-locked source is picked (anywhere) -// if ( !s->locked() ) { -// // not in an active selection? don't pick this one! -// if ( !UserInterface::manager().ctrlModifier() && -// Mixer::selection().size() > 1 && -// !Mixer::selection().contains(s)) -// continue; -// // yeah, pick this one (NB: locker_ is just a node in Geometry that is detected) -// pick = { s->locker_, (*itp).second }; -// break; -// } - -// } -// // not a source picked -// else { -// // picked on selection handles -// if ( (*itp).first == overlay_selection_scale_ || (*itp).first == overlay_selection_rotate_ ) { -// pick = (*itp); -// // initiate selection manipulation -// if (overlay_selection_stored_status_) { -// overlay_selection_stored_status_->copyTransform(overlay_selection_); -// overlay_selection_active_ = true; -// } -// break; -// } -// else if ( overlay_selection_icon_ != nullptr && (*itp).first == overlay_selection_icon_ ) { -// pick = (*itp); -// openContextMenu(MENU_SELECTION); -// break; -// } -// } -// } -// } -// } -// } + // activate / deactivate output frame + output_selected_ = (pick.first == output_surface_) || + (pick.first == output_handles_) || + (pick.first == output_fullscreen_) || + (pick.first == output_menu_); + output_overlays_->setActive(output_selected_ ? 1 : 0); return pick; } -bool DisplaysView::canSelect(Source *s) { +bool DisplaysView::canSelect(Source *) { - return ( s!=nullptr && View::canSelect(s) && s->ready() && s->active() && s->workspace() == Settings::application.current_workspace); + return false; +} + +void DisplaysView::select(glm::vec2 A, glm::vec2 B) +{ + // unproject mouse coordinate into scene coordinates + glm::vec3 scene_point_A = Rendering::manager().unProject(A); + glm::vec3 scene_point_B = Rendering::manager().unProject(B); + + // picking visitor traverses the scene + PickingVisitor pv(scene_point_A, scene_point_B, true); + scene.accept(pv); + + output_selected_ = !pv.empty(); + output_overlays_->setActive(output_selected_ ? 0 : 1); + +} + +void DisplaysView::initiate() +{ + // initiate pending action + if (!current_action_ongoing_) { + + // store status + output_status_->copyTransform(output_); + + // initiated + current_action_ = ""; + current_action_ongoing_ = true; + } +} + +void DisplaysView::terminate(bool force) +{ + // terminate pending action + if (current_action_ongoing_ || force) { + + Rendering::manager().outputWindow().setCoordinates( outputCoordinates() ); + + + // reset indicators + output_handles_->overlayActiveCorner(glm::vec2(0.f, 0.f)); + + // terminated + current_action_ = ""; + current_action_ongoing_ = false; + } } -void DisplaysView::applySelectionTransform(glm::mat4 M) +glm::ivec4 DisplaysView::outputCoordinates() const { -// for (auto sit = Mixer::selection().begin(); sit != Mixer::selection().end(); ++sit){ -// // recompute all from matrix transform -// glm::mat4 transform = M * (*sit)->stored_status_->transform_; -// glm::vec3 tra, rot, sca; -// GlmToolkit::inverse_transform(transform, tra, rot, sca); -// (*sit)->group(mode_)->translation_ = tra; -// (*sit)->group(mode_)->scale_ = sca; -// (*sit)->group(mode_)->rotation_ = rot; -// // will have to be updated -// (*sit)->touch(); -// } + glm::ivec4 rect; + + rect.x = (output_->translation_.x - output_->scale_.x) / DISPLAYS_UNIT; + rect.y = (output_->translation_.y + output_->scale_.y) / - DISPLAYS_UNIT; + rect.p = 2.f * output_->scale_.x / DISPLAYS_UNIT; + rect.q = 2.f * output_->scale_.y / DISPLAYS_UNIT; + + return rect; } View::Cursor DisplaysView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair pick) { + std::ostringstream info; View::Cursor ret = Cursor(); // grab coordinates in scene-View reference frame @@ -501,167 +400,119 @@ View::Cursor DisplaysView::grab (Source *s, glm::vec2 from, glm::vec2 to, std::p glm::vec3 scene_to = Rendering::manager().unProject(to, scene.root()->transform_); glm::vec3 scene_translation = scene_to - scene_from; - // No source is given + // No source should be given if (!s) { + // grab surface to move + if ( pick.first == output_surface_ ){ -// // possibly grabing the selection overlay handles -// if (overlay_selection_ && overlay_selection_active_ ) { + // apply translation + output_->translation_ = output_status_->translation_ + scene_translation; + glm::ivec4 r = outputCoordinates(); -// // rotation center to selection position -// glm::mat4 T = glm::translate(glm::identity(), overlay_selection_stored_status_->translation_); -// glm::vec4 selection_from = glm::inverse(T) * glm::vec4( scene_from, 1.f ); -// glm::vec4 selection_to = glm::inverse(T) * glm::vec4( scene_to, 1.f ); + // discretized translation with ALT + if (UserInterface::manager().altModifier()) { + r.x = ROUND(r.x, 0.01f); + r.y = ROUND(r.y, 0.01f); + output_->translation_.x = (r.x * DISPLAYS_UNIT) + output_->scale_.x; + output_->translation_.y = (r.y * - DISPLAYS_UNIT) - output_->scale_.y; + } -// // calculate scaling of selection -// float factor = glm::length( glm::vec2( selection_to ) ) / glm::length( glm::vec2( selection_from ) ); -// glm::mat4 S = glm::scale(glm::identity(), glm::vec3(factor, factor, 1.f)); + // Show move cursor + output_handles_->overlayActiveCorner(glm::vec2(-1.f, 1.f)); + ret.type = Cursor_ResizeAll; + info << "Position " << r.x << ", " << r.y << " px"; -// // if interaction with selection SCALING handle -// if (pick.first == overlay_selection_scale_) { + // apply to settings + Settings::application.windows[2].x = r.x; + Settings::application.windows[2].y = r.y; + } + // grab handle to resize + else if ( pick.first == output_handles_ ){ -// // show manipulation overlay -// overlay_scaling_cross_->visible_ = true; -// overlay_scaling_grid_->visible_ = false; -// overlay_scaling_->visible_ = true; -// overlay_scaling_->translation_.x = overlay_selection_stored_status_->translation_.x; -// overlay_scaling_->translation_.y = overlay_selection_stored_status_->translation_.y; -// overlay_scaling_->rotation_.z = overlay_selection_stored_status_->rotation_.z; -// overlay_scaling_->update(0); -// overlay_scaling_cross_->copyTransform(overlay_scaling_); -// overlay_scaling_->color = overlay_selection_icon_->color; -// overlay_scaling_cross_->color = overlay_selection_icon_->color; + // which corner was picked ? + glm::vec2 corner = glm::round(pick.second); + // inform on which corner should be overlayed (opposite) + output_handles_->overlayActiveCorner(-corner); -// // apply to selection overlay -// glm::vec4 vec = S * glm::vec4( overlay_selection_stored_status_->scale_, 0.f ); -// overlay_selection_->scale_ = glm::vec3(vec); + // transform from source center to corner + glm::mat4 T = GlmToolkit::transform(glm::vec3(corner.x, corner.y, 0.f), glm::vec3(0.f, 0.f, 0.f), + glm::vec3(1.f, 1.f, 1.f)); -// // apply to selection sources -// // NB: complete transform matrix (right to left) : move to center, scale and move back -// glm::mat4 M = T * S * glm::inverse(T); -// applySelectionTransform(M); + // transformation from scene to corner: + glm::mat4 scene_to_corner_transform = T * glm::inverse(output_status_->transform_); + glm::mat4 corner_to_scene_transform = glm::inverse(scene_to_corner_transform); -// // store action in history -// current_action_ = "Scale selection"; -// ret.type = Cursor_ResizeNWSE; -// } -// // if interaction with selection ROTATION handle -// else if (pick.first == overlay_selection_rotate_) { + // compute cursor movement in corner reference frame + glm::vec4 corner_from = scene_to_corner_transform * glm::vec4( scene_from, 1.f ); + glm::vec4 corner_to = scene_to_corner_transform * glm::vec4( scene_to, 1.f ); -// // show manipulation overlay -// overlay_rotation_->visible_ = true; -// overlay_rotation_->translation_.x = overlay_selection_stored_status_->translation_.x; -// overlay_rotation_->translation_.y = overlay_selection_stored_status_->translation_.y; -// overlay_rotation_->update(0); -// overlay_rotation_->color = overlay_selection_icon_->color; -// overlay_rotation_fix_->visible_ = false; -// overlay_rotation_fix_->copyTransform(overlay_rotation_); -// overlay_rotation_fix_->color = overlay_selection_icon_->color; + // operation of scaling in corner reference frame + glm::vec3 corner_scaling = glm::vec3(corner_to) / glm::vec3(corner_from); + glm::ivec4 rect; -// // cancel out scaling with SHIFT modifier key -// if (UserInterface::manager().shiftModifier()) { -// overlay_rotation_fix_->visible_ = true; -// float scale_factor = glm::length( glm::vec2( overlay_selection_->scale_ ) ) / glm::length( glm::vec2( overlay_selection_stored_status_->scale_ ) ); -// S = glm::scale(glm::identity(), glm::vec3(scale_factor, scale_factor, 1.f)); -// } + // RESIZE CORNER + // proportional SCALING with SHIFT + if (UserInterface::manager().shiftModifier()) { + // calculate proportional scaling factor + float factor = glm::length( glm::vec2( corner_to ) ) / glm::length( glm::vec2( corner_from ) ); + // scale node + output_->scale_ = output_status_->scale_ * glm::vec3(factor, factor, 1.f); + } + // non-proportional CORNER RESIZE (normal case) + else { + // scale node + output_->scale_ = output_status_->scale_ * corner_scaling; + } -// // compute rotation angle -// float angle = glm::orientedAngle( glm::normalize(glm::vec2(selection_from)), glm::normalize(glm::vec2(selection_to))); + // discretized scaling with ALT + if (UserInterface::manager().altModifier()) { + // calculate ratio of scaling modulo the output resolution + glm::vec3 outputsize = output_->scale_ / DISPLAYS_UNIT; + glm::vec3 framesize = Mixer::manager().session()->frame()->resolution(); + glm::vec3 ra = outputsize / framesize; + ra.x = ROUND(ra.x, 20.f); + ra.y = ROUND(ra.y, 20.f); + outputsize = ra * framesize; + output_->scale_.x = outputsize.x * DISPLAYS_UNIT; + output_->scale_.y = outputsize.y * DISPLAYS_UNIT; + } + // update corner scaling to apply to center coordinates + corner_scaling = output_->scale_ / output_status_->scale_; -// // apply to selection overlay -// glm::vec4 vec = S * glm::vec4( overlay_selection_stored_status_->scale_, 0.f ); -// overlay_selection_->scale_ = glm::vec3(vec); -// overlay_selection_->rotation_.z = overlay_selection_stored_status_->rotation_.z + angle; + // TRANSLATION CORNER + // convert source position in corner reference frame + glm::vec4 center = scene_to_corner_transform * glm::vec4( output_status_->translation_, 1.f); + // transform source center (in corner reference frame) + center = glm::scale(glm::identity(), corner_scaling) * center; + // convert center back into scene reference frame + center = corner_to_scene_transform * center; + // apply to node + output_->translation_ = glm::vec3(center); -// // POST-CORRECTION ; discretized rotation with ALT -// if (UserInterface::manager().altModifier()) { -// int degrees = int( glm::degrees(overlay_selection_->rotation_.z) ); -// degrees = (degrees / 10) * 10; -// overlay_selection_->rotation_.z = glm::radians( float(degrees) ); -// angle = overlay_selection_->rotation_.z - overlay_selection_stored_status_->rotation_.z; -// overlay_rotation_clock_->visible_ = true; -// overlay_rotation_clock_->copyTransform(overlay_rotation_); -// overlay_rotation_clock_tic_->color = overlay_selection_icon_->color; -// } + // show cursor depending on diagonal (corner picked) + T = glm::rotate(glm::identity(), output_status_->rotation_.z, glm::vec3(0.f, 0.f, 1.f)); + T = glm::scale(T, output_status_->scale_); + corner = T * glm::vec4( corner, 0.f, 0.f ); + ret.type = corner.x * corner.y > 0.f ? Cursor_ResizeNESW : Cursor_ResizeNWSE; -// // apply to selection sources -// // NB: complete transform matrix (right to left) : move to center, rotate, scale and move back -// glm::mat4 R = glm::rotate(glm::identity(), angle, glm::vec3(0.f, 0.f, 1.f) ); -// glm::mat4 M = T * S * R * glm::inverse(T); -// applySelectionTransform(M); + rect = outputCoordinates(); + info << "Dimensions " << rect.p << " x " << rect.q << " px"; -// // store action in history -// current_action_ = "Scale and rotate selection"; -// ret.type = Cursor_Hand; -// } + // apply to settings + Settings::application.windows[2].x = rect.x; + Settings::application.windows[2].y = rect.y; + Settings::application.windows[2].w = rect.p; + Settings::application.windows[2].h = rect.q; + } -// } - - // update cursor - return ret; } -// Group *sourceNode = s->group(mode_); // groups_[View::GEOMETRY] - -// // make sure matrix transform of stored status is updated -// s->stored_status_->update(0); -// // grab coordinates in source-root reference frame -// glm::vec4 source_from = glm::inverse(s->stored_status_->transform_) * glm::vec4( scene_from, 1.f ); -// glm::vec4 source_to = glm::inverse(s->stored_status_->transform_) * glm::vec4( scene_to, 1.f ); -// glm::vec3 source_scaling = glm::vec3(source_to) / glm::vec3(source_from); - - // which manipulation to perform? - std::ostringstream info; - - // store action in history - current_action_ = s->name() + ": " + info.str(); - // update cursor ret.info = info.str(); + return ret; } -void DisplaysView::terminate(bool force) -{ - View::terminate(force); - -// // hide all view overlays -// overlay_position_->visible_ = false; -// overlay_position_cross_->visible_ = false; -// overlay_rotation_clock_->visible_ = false; -// overlay_rotation_clock_hand_->visible_ = false; -// overlay_rotation_fix_->visible_ = false; -// overlay_rotation_->visible_ = false; -// overlay_scaling_grid_->visible_ = false; -// overlay_scaling_cross_->visible_ = false; -// overlay_scaling_->visible_ = false; -// overlay_crop_->visible_ = false; - -// // restore possible color change after selection operation -// overlay_rotation_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f); -// overlay_rotation_fix_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f); -// overlay_rotation_clock_tic_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f); -// overlay_scaling_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f); -// overlay_scaling_cross_->color = glm::vec4(1.f, 1.f, 1.f, 0.8f); - - // restore of all handles overlays -// glm::vec2 c(0.f, 0.f); -// for (auto sit = Mixer::manager().session()->begin(); -// sit != Mixer::manager().session()->end(); ++sit){ - -// (*sit)->handles_[mode_][Handles::RESIZE]->overlayActiveCorner(c); -// (*sit)->handles_[mode_][Handles::RESIZE_H]->overlayActiveCorner(c); -// (*sit)->handles_[mode_][Handles::RESIZE_V]->overlayActiveCorner(c); -// (*sit)->handles_[mode_][Handles::RESIZE]->visible_ = true; -// (*sit)->handles_[mode_][Handles::RESIZE_H]->visible_ = true; -// (*sit)->handles_[mode_][Handles::RESIZE_V]->visible_ = true; -// (*sit)->handles_[mode_][Handles::SCALE]->visible_ = true; -// (*sit)->handles_[mode_][Handles::ROTATE]->visible_ = true; -// (*sit)->handles_[mode_][Handles::CROP]->visible_ = true; -// (*sit)->handles_[mode_][Handles::MENU]->visible_ = true; -// } - - overlay_selection_active_ = false; -} void DisplaysView::arrow (glm::vec2 movement) { @@ -672,92 +523,5 @@ void DisplaysView::arrow (glm::vec2 movement) glm::vec3 gl_Position_to = Rendering::manager().unProject(movement, scene.root()->transform_); glm::vec3 gl_delta = gl_Position_to - gl_Position_from; -// bool first = true; -// glm::vec3 delta_translation(0.f); -// for (auto it = Mixer::selection().begin(); it != Mixer::selection().end(); ++it) { - -// // individual move with SHIFT -// if ( !Source::isCurrent(*it) && UserInterface::manager().shiftModifier() ) -// continue; - -// Group *sourceNode = (*it)->group(mode_); -// glm::vec3 dest_translation(0.f); - -// if (first) { -// // dest starts at current -// dest_translation = sourceNode->translation_; - -// // + ALT : discrete displacement -// if (UserInterface::manager().altModifier()) { -// if (accumulator > 100.f) { -// dest_translation += glm::sign(gl_delta) * 0.11f; -// dest_translation.x = ROUND(dest_translation.x, 10.f); -// dest_translation.y = ROUND(dest_translation.y, 10.f); -// accumulator = 0.f; -// } -// else -// break; -// } -// else { -// // normal case: dest += delta -// dest_translation += gl_delta * ARROWS_MOVEMENT_FACTOR * dt_; -// accumulator = 0.f; -// } - -// // store action in history -// std::ostringstream info; -// info << "Position " << std::fixed << std::setprecision(3) << sourceNode->translation_.x; -// info << ", " << sourceNode->translation_.y ; -// current_action_ = (*it)->name() + ": " + info.str(); - -// // delta for others to follow -// delta_translation = dest_translation - sourceNode->translation_; -// } -// else { -// // dest = current + delta from first -// dest_translation = sourceNode->translation_ + delta_translation; -// } - -// // apply & request update -// sourceNode->translation_ = dest_translation; -// (*it)->touch(); - -// first = false; -// } -} - -void DisplaysView::updateSelectionOverlay() -{ - View::updateSelectionOverlay(); - -// // create first -// if (overlay_selection_scale_ == nullptr) { - -// overlay_selection_stored_status_ = new Group; -// overlay_selection_scale_ = new Handles(Handles::SCALE); -// overlay_selection_->attach(overlay_selection_scale_); -// overlay_selection_rotate_ = new Handles(Handles::ROTATE); -// overlay_selection_->attach(overlay_selection_rotate_); -// } - -// if (overlay_selection_->visible_) { - -// if ( !overlay_selection_active_) { - -// // calculate ORIENTED bbox on selection -// GlmToolkit::OrientedBoundingBox selection_box = BoundingBoxVisitor::OBB(Mixer::selection().getCopy(), this); - -// // apply transform -// overlay_selection_->rotation_ = selection_box.orientation; -// overlay_selection_->scale_ = selection_box.aabb.scale(); -// glm::mat4 rot = glm::rotate(glm::identity(), selection_box.orientation.z, glm::vec3(0.f, 0.f, 1.f) ); -// glm::vec4 vec = rot * glm::vec4(selection_box.aabb.center(), 1.f); -// overlay_selection_->translation_ = glm::vec3(vec); -// } - -// // cosmetics -// overlay_selection_scale_->color = overlay_selection_icon_->color; -// overlay_selection_rotate_->color = overlay_selection_icon_->color; -// } } diff --git a/src/DisplaysView.h b/src/DisplaysView.h index e05ea42..f37d411 100644 --- a/src/DisplaysView.h +++ b/src/DisplaysView.h @@ -16,34 +16,44 @@ public: void resize (int) override; int size () override; bool canSelect(Source *) override; + void select(glm::vec2 A, glm::vec2 B) override; void recenter () override; std::pair pick(glm::vec2 P) override; + void initiate () override; + void terminate (bool force = false) override; Cursor grab (Source *s, glm::vec2 from, glm::vec2 to, std::pair pick) override; - void terminate(bool force) override; void arrow (glm::vec2) override; + glm::ivec4 outputCoordinates() const; + private: + + Group *output_; + Group *output_status_; Surface *output_surface_; - Node *overlay_position_; - Node *overlay_position_cross_; - Symbol *overlay_rotation_; - Symbol *overlay_rotation_fix_; - Group *overlay_rotation_clock_; - Symbol *overlay_rotation_clock_tic_; - Node *overlay_rotation_clock_hand_; - Symbol *overlay_scaling_; - Symbol *overlay_scaling_cross_; - Node *overlay_scaling_grid_; - Node *overlay_crop_; + Surface *output_render_; + Switch *output_overlays_; + Switch *output_mode_; + Handles *output_handles_; + Handles *output_menu_; + Handles *output_visible_; + Symbol *output_fullscreen_; - void updateSelectionOverlay() override; - bool overlay_selection_active_; - Group *overlay_selection_stored_status_; - Handles *overlay_selection_scale_; - Handles *overlay_selection_rotate_; + bool output_selected_; + bool show_output_menu_; - void applySelectionTransform(glm::mat4 M); +// Node *overlay_position_; +// Node *overlay_position_cross_; +// Symbol *overlay_rotation_; +// Symbol *overlay_rotation_fix_; +// Group *overlay_rotation_clock_; +// Symbol *overlay_rotation_clock_tic_; +// Node *overlay_rotation_clock_hand_; +// Symbol *overlay_scaling_; +// Symbol *overlay_scaling_cross_; +// Node *overlay_scaling_grid_; +// Node *overlay_crop_; }; diff --git a/src/GeometryView.cpp b/src/GeometryView.cpp index 2f71385..51828ba 100644 --- a/src/GeometryView.cpp +++ b/src/GeometryView.cpp @@ -330,7 +330,7 @@ void GeometryView::draw() // colored context menu ImGui::PushStyleColor(ImGuiCol_Text, ImGuiToolkit::HighlightColor()); - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.36f, 0.36f, 0.36f, 0.44f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(COLOR_MENU_HOVERED, 0.5f)); // batch manipulation of sources in Geometry view if (ImGui::Selectable( ICON_FA_EXPAND " Fit all" )){ diff --git a/src/LayerView.cpp b/src/LayerView.cpp index ccb5ef4..bf0d1c6 100644 --- a/src/LayerView.cpp +++ b/src/LayerView.cpp @@ -116,7 +116,7 @@ void LayerView::draw() // colored context menu ImGui::PushStyleColor(ImGuiCol_Text, ImGuiToolkit::HighlightColor()); - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.36f, 0.36f, 0.36f, 0.44f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(COLOR_MENU_HOVERED, 0.5f)); // special action of Mixing view if (candidate_flatten_group){ diff --git a/src/MixingView.cpp b/src/MixingView.cpp index 9a9a436..ccd7341 100644 --- a/src/MixingView.cpp +++ b/src/MixingView.cpp @@ -169,7 +169,7 @@ void MixingView::draw() // colored context menu ImGui::PushStyleColor(ImGuiCol_Text, ImGuiToolkit::HighlightColor()); - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.36f, 0.36f, 0.36f, 0.44f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(COLOR_MENU_HOVERED, 0.5f)); // special action of Mixing view: link or unlink SourceList selected = Mixer::selection().getCopy(); diff --git a/src/RenderingManager.cpp b/src/RenderingManager.cpp index f7f8099..5c115d1 100644 --- a/src/RenderingManager.cpp +++ b/src/RenderingManager.cpp @@ -160,17 +160,25 @@ static void WindowMoveCallback( GLFWwindow *w, int x, int y) } } -static void WindowToggleFullscreen( GLFWwindow *w, int button, int action, int) +static void OutputWindowEvent( GLFWwindow *w, int button, int action, int) { + // detect mouse press if (button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) { static double seconds = 0.f; // detect double clic if ( glfwGetTime() - seconds < 0.2f ) { - // toggle fullscreen - GLFW_window_[w]->toggleFullscreen(); + + // exit fullscreen if its the case + if (glfwGetWindowMonitor(w) != nullptr) + Rendering::manager().outputWindow().exitFullscreen(); + + // show main window in DISPLAYS view to + // indicate how to manipulate output window + Mixer::manager().setView(View::DISPLAYS); + Rendering::manager().mainWindow().show(); } - // for next clic detection + // for next double clic detection seconds = glfwGetTime(); } } @@ -184,7 +192,7 @@ static void WindowCloseCallback( GLFWwindow* w ) void Rendering::MonitorConnect(GLFWmonitor* monitor, int event) { // reset list of monitors - Rendering::manager().monitors_.clear(); + Rendering::manager().monitors_geometry_.clear(); // list monitors with GLFW int count_monitors = 0; @@ -198,10 +206,9 @@ void Rendering::MonitorConnect(GLFWmonitor* monitor, int event) const GLFWvidmode *vm = glfwGetVideoMode(monitors[i]); std::string n = glfwGetMonitorName(monitors[i]); // add - Rendering::manager().monitors_[n] = glm::ivec4(x, y, vm->width, vm->height); + Rendering::manager().monitors_geometry_[n] = glm::ivec4(x, y, vm->width, vm->height); } - // TODO : find appropriate // inform Displays View that monitors changed Mixer::manager().view(View::DISPLAYS)->recenter(); @@ -386,7 +393,7 @@ bool Rendering::init() output_.init(1, main_.window()); output_.setIcon("images/vimix_256x256.png"); // special callbacks for user input in output window - glfwSetMouseButtonCallback( output_.window(), WindowToggleFullscreen); + glfwSetMouseButtonCallback( output_.window(), OutputWindowEvent); // // Monitors configuration @@ -431,8 +438,8 @@ void Rendering::draw() glfwPollEvents(); // change windows fullscreen mode if requested - main_.toggleFullscreen_(); - output_.toggleFullscreen_(); + main_.changeFullscreen_(); + output_.changeFullscreen_(); // change main window title if requested if (!main_new_title_.empty()) { @@ -667,7 +674,7 @@ WindowSurface::WindowSurface(Shader *s) : Primitive(s) RenderingWindow::RenderingWindow() : window_(nullptr), master_(nullptr), - index_(-1), dpi_scale_(1.f), textureid_(0), fbo_(0), surface_(nullptr), request_toggle_fullscreen_(false) + index_(-1), dpi_scale_(1.f), textureid_(0), fbo_(0), surface_(nullptr), request_change_fullscreen_(false) { } @@ -703,19 +710,15 @@ void RenderingWindow::setIcon(const std::string &resource) } } -bool RenderingWindow::isFullscreen () -{ -// return (glfwGetWindowMonitor(window_) != nullptr); - return Settings::application.windows[index_].fullscreen; -} - GLFWmonitor *RenderingWindow::monitor() { - // pick at the coordinates given or at pos of window - int x = 1, y = 1; - if (window_ != nullptr) + // get monitor at the center of the window + int x = 0, y = 0, w = 2, h = 2; + if (window_ != nullptr) { + glfwGetWindowSize(window_, &w, &h); glfwGetWindowPos(window_, &x, &y); - return Rendering::manager().monitorAt(x, y); + } + return Rendering::manager().monitorAt(x + w/2, y + h/2); } void RenderingWindow::setFullscreen_(GLFWmonitor *mo) @@ -723,9 +726,6 @@ void RenderingWindow::setFullscreen_(GLFWmonitor *mo) if (window_ == nullptr) return; - // done request - request_toggle_fullscreen_ = false; - // disable fullscreen mode if (mo == nullptr) { // store fullscreen mode @@ -746,8 +746,9 @@ void RenderingWindow::setFullscreen_(GLFWmonitor *mo) // set to fullscreen mode const GLFWvidmode * mode = glfwGetVideoMode(mo); - glfwSetInputMode( window_, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); glfwSetWindowMonitor( window_, mo, 0, 0, mode->width, mode->height, mode->refreshRate); + + glfwSetInputMode( window_, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); } // Enable vsync on output window only (i.e. not 0 if has a master) @@ -756,36 +757,63 @@ void RenderingWindow::setFullscreen_(GLFWmonitor *mo) } -void RenderingWindow::exitFullscreen() +bool RenderingWindow::isFullscreen () { - if (isFullscreen()) { - // exit fullscreen - request_toggle_fullscreen_ = true; - } +// return (glfwGetWindowMonitor(window_) != nullptr); + return Settings::application.windows[index_].fullscreen; } -void RenderingWindow::toggleFullscreen() +void RenderingWindow::exitFullscreen () { - request_toggle_fullscreen_ = true; + // exit fullscreen + request_change_fullscreen_ = isFullscreen(); } -void RenderingWindow::toggleFullscreen_() +void RenderingWindow::toggleFullscreen () { - if (request_toggle_fullscreen_) { + request_change_fullscreen_ = true; +} + +void RenderingWindow::setFullscreen (std::string monitorname) +{ + Settings::application.windows[index_].monitor = monitorname; + request_change_fullscreen_ = true; +} + +void RenderingWindow::changeFullscreen_() +{ + // change upon request + if (request_change_fullscreen_) { + + // done request + request_change_fullscreen_ = false; + + GLFWmonitor *mo = Rendering::manager().monitorNamed( Settings::application.windows[index_].monitor ); // if in fullscreen mode - if (glfwGetWindowMonitor(window_) != nullptr) { - // exit fullscreen - setFullscreen_(nullptr); + if (isFullscreen ()) { + + // changing fullscreen monitor + if ( glfwGetWindowMonitor(window_) != mo) + setFullscreen_(mo); + else + // exit fullscreen + setFullscreen_(nullptr); } // not in fullscreen mode else { - // enter fullscreen in monitor where the window is - setFullscreen_(monitor()); + // enter fullscreen + setFullscreen_(mo); } } } +void RenderingWindow::setCoordinates(glm::ivec4 rect) +{ + glfwSetWindowPos( window_, rect.x, rect.y); + glfwSetWindowSize( window_, rect.p, rect.q); +} + int RenderingWindow::width() { return window_attributes_.viewport.x; @@ -886,6 +914,11 @@ bool RenderingWindow::init(int index, GLFWwindow *share) // if not main window if ( master_ != NULL ) { + + // special window type + glfwSetWindowAttrib( window_, GLFW_DECORATED, GLFW_FALSE); + glfwSetWindowAttrib( window_, GLFW_RESIZABLE, GLFW_FALSE); + // Enable vsync on output window glfwSwapInterval(Settings::application.render.vsync); // no need for multisampling @@ -983,19 +1016,28 @@ void RenderingWindow::draw(FrameBuffer *fb) // calculate scaling factor of frame buffer inside window int rx, ry, rw, rh; float renderingAspectRatio = fb->aspectRatio(); - if (aspectRatio() < renderingAspectRatio) { - int nh = (int)( float(window_attributes_.viewport.x) / renderingAspectRatio); + + if (Settings::application.windows[index_].scaled) { rx = 0; - ry = (window_attributes_.viewport.y - nh) / 2; - rw = window_attributes_.viewport.x; - rh = (window_attributes_.viewport.y + nh) / 2; - } else { - int nw = (int)( float(window_attributes_.viewport.y) * renderingAspectRatio ); - rx = (window_attributes_.viewport.x - nw) / 2; ry = 0; - rw = (window_attributes_.viewport.x + nw) / 2; + rw = window_attributes_.viewport.x; rh = window_attributes_.viewport.y; } + else { + if (aspectRatio() < renderingAspectRatio) { + int nh = (int)( float(window_attributes_.viewport.x) / renderingAspectRatio); + rx = 0; + ry = (window_attributes_.viewport.y - nh) / 2; + rw = window_attributes_.viewport.x; + rh = (window_attributes_.viewport.y + nh) / 2; + } else { + int nw = (int)( float(window_attributes_.viewport.y) * renderingAspectRatio ); + rx = (window_attributes_.viewport.x - nw) / 2; + ry = 0; + rw = (window_attributes_.viewport.x + nw) / 2; + rh = window_attributes_.viewport.y; + } + } // select fbo texture read target glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_); @@ -1020,11 +1062,14 @@ void RenderingWindow::draw(FrameBuffer *fb) // calculate scaling factor of frame buffer inside window float windowAspectRatio = aspectRatio(); float renderingAspectRatio = fb->aspectRatio(); - glm::vec3 scale; - if (windowAspectRatio < renderingAspectRatio) - scale = glm::vec3(1.f, windowAspectRatio / renderingAspectRatio, 1.f); - else - scale = glm::vec3(renderingAspectRatio / windowAspectRatio, 1.f, 1.f); + glm::vec3 scale = glm::vec3(1.f, 1.f, 1.f); + + if (!Settings::application.windows[index_].scaled) { + if (windowAspectRatio < renderingAspectRatio) + scale = glm::vec3(1.f, windowAspectRatio / renderingAspectRatio, 1.f); + else + scale = glm::vec3(renderingAspectRatio / windowAspectRatio, 1.f, 1.f); + } // make sure previous shader in another glcontext is disabled ShadingProgram::enduse(); diff --git a/src/RenderingManager.h b/src/RenderingManager.h index 115af0b..c2a4f5d 100644 --- a/src/RenderingManager.h +++ b/src/RenderingManager.h @@ -38,8 +38,8 @@ class RenderingWindow uint fbo_; class WindowSurface *surface_; - bool request_toggle_fullscreen_; - void toggleFullscreen_ (); + bool request_change_fullscreen_; + void changeFullscreen_ (); void setFullscreen_(GLFWmonitor *mo); public: @@ -65,9 +65,13 @@ public: // fullscreen bool isFullscreen (); - void exitFullscreen(); + void exitFullscreen (); + void setFullscreen (std::string monitorname); void toggleFullscreen (); + // set geometry + void setCoordinates(glm::ivec4 rect); + // get width of rendering area int width(); // get height of rendering area @@ -143,8 +147,7 @@ public: glm::vec2 project(glm::vec3 scene_coordinate, glm::mat4 modelview = glm::mat4(1.f), bool to_framebuffer = true); // get hold on the monitors - void monitorsUpdate(); - inline std::map monitors() { return monitors_; } + inline std::map monitors() { return monitors_geometry_; } // get which monitor contains this point GLFWmonitor *monitorAt(int x, int y); // get which monitor has this name @@ -174,7 +177,7 @@ private: RenderingWindow output_; // monitors - std::map monitors_; + std::map monitors_geometry_; static void MonitorConnect(GLFWmonitor* monitor, int event); // file drop callback diff --git a/src/Settings.cpp b/src/Settings.cpp index 40216cb..00aa356 100644 --- a/src/Settings.cpp +++ b/src/Settings.cpp @@ -105,8 +105,9 @@ void Settings::Save(uint64_t runtime) window->SetAttribute("x", w.x); window->SetAttribute("y", w.y); window->SetAttribute("w", w.w); - window->SetAttribute("h", w.h); + window->SetAttribute("h", w.h); window->SetAttribute("f", w.fullscreen); + window->SetAttribute("s", w.scaled); window->SetAttribute("m", w.monitor.c_str()); windowsNode->InsertEndChild(window); } @@ -502,6 +503,7 @@ void Settings::Load() windowNode->QueryIntAttribute("w", &w.w); windowNode->QueryIntAttribute("h", &w.h); windowNode->QueryBoolAttribute("f", &w.fullscreen); + windowNode->QueryBoolAttribute("s", &w.scaled); const char *text = windowNode->Attribute("m"); if (text) w.monitor = std::string(text); diff --git a/src/Settings.h b/src/Settings.h index 00408c1..83706ad 100644 --- a/src/Settings.h +++ b/src/Settings.h @@ -60,9 +60,10 @@ struct WindowConfig std::string name; int x,y,w,h; bool fullscreen; + bool scaled; std::string monitor; - WindowConfig() : name(""), x(15), y(15), w(1280), h(720), fullscreen(false), monitor("") { } + WindowConfig() : name(""), x(15), y(15), w(1280), h(720), fullscreen(false), scaled(false), monitor("") { } }; @@ -336,6 +337,7 @@ struct Application windows[0].w = 1600; windows[0].h = 900; windows[1].name = "Output " APP_TITLE; + windows[2].name = "Fullscreen " APP_TITLE; } }; diff --git a/src/TextureView.cpp b/src/TextureView.cpp index 3fb485d..e700501 100644 --- a/src/TextureView.cpp +++ b/src/TextureView.cpp @@ -871,7 +871,7 @@ void TextureView::draw() } if (ImGui::BeginPopup("AppearanceSourceContextMenu")) { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(COLOR_APPEARANCE_SOURCE, 1.f)); - ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.36f, 0.36f, 0.36f, 0.44f)); + ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(COLOR_MENU_HOVERED, 0.5f)); Source *s = Mixer::manager().currentSource(); if (s != nullptr) { diff --git a/src/defines.h b/src/defines.h index 8e8c1c4..f051b2b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -109,6 +109,7 @@ #define COLOR_SLIDER_CIRCLE 0.11f, 0.11f, 0.11f #define COLOR_STASH_CIRCLE 0.06f, 0.06f, 0.06f #define COLOR_MONITOR 0.2f, 0.85f, 0.85f +#define COLOR_MENU_HOVERED 0.3f, 0.3f, 0.3f #define OSC_PORT_RECV_DEFAULT 7000 #define OSC_PORT_SEND_DEFAULT 7001