From 5ff9585c3db701dcc6f4251be0b0344482502b6c Mon Sep 17 00:00:00 2001
From: Jampi0n <27952849+Jampi0n@users.noreply.github.com>
Date: Wed, 22 Jun 2022 19:26:04 +0200
Subject: [PATCH 1/4] Add transparency toggle
---
src/DDSPreview.py | 94 +++++++++++++++++++++++++++++---------------
src/DDSPreview_en.ts | 29 ++++++++++----
2 files changed, 84 insertions(+), 39 deletions(-)
diff --git a/src/DDSPreview.py b/src/DDSPreview.py
index 96e8398..73338bd 100644
--- a/src/DDSPreview.py
+++ b/src/DDSPreview.py
@@ -151,9 +151,11 @@
glVersionProfile.setVersion(2, 1)
class DDSWidget(QOpenGLWidget):
- def __init__(self, ddsFile, debugContext = False, parent = None, f = Qt.WindowFlags()):
+ def __init__(self, ddsPreview, ddsFile, debugContext = False, parent = None, f = Qt.WindowFlags()):
super(DDSWidget, self).__init__(parent, f)
-
+
+ self.ddsPreview = ddsPreview
+
self.ddsFile = ddsFile
self.clean = True
@@ -166,8 +168,6 @@ def __init__(self, ddsFile, debugContext = False, parent = None, f = Qt.WindowFl
self.vbo = None
self.vao = None
- self.backgroundColour = None
-
if debugContext:
format = QSurfaceFormat()
format.setOption(QSurfaceFormat.DebugContext)
@@ -252,9 +252,10 @@ def paintGL(self):
# Draw checkerboard so transparency is obvious
self.transparecyProgram.bind()
-
- if self.backgroundColour and self.backgroundColour.isValid():
- self.transparecyProgram.setUniformValue("backgroundColour", self.backgroundColour)
+
+ backgroundColour = self.ddsPreview.getBackgroundColour()
+ if backgroundColour and backgroundColour.isValid():
+ self.transparecyProgram.setUniformValue("backgroundColour", backgroundColour)
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
@@ -264,9 +265,12 @@ def paintGL(self):
if self.texture:
self.texture.bind()
-
- gl.glEnable(gl.GL_BLEND)
- gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
+
+ if self.ddsPreview.getTransparency():
+ gl.glEnable(gl.GL_BLEND)
+ gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
+ else:
+ gl.glDisable(gl.GL_BLEND)
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
@@ -291,12 +295,6 @@ def cleanup(self):
self.doneCurrent()
self.clean = True
- def setBackgroundColour(self, colour):
- self.backgroundColour = colour
-
- def getBackgroundColour(self):
- return self.backgroundColour
-
def __tr(self, str):
return QCoreApplication.translate("DDSWidget", str)
@@ -311,6 +309,12 @@ def init(self, organizer):
self.__organizer = organizer
return True
+ def pluginSetting(self, name):
+ return self.__organizer.pluginSetting(self.name(), name)
+
+ def setPluginSetting(self, name, value):
+ self.__organizer.setPluginSetting(self.name(), name, value)
+
def name(self):
return "DDS Preview Plugin"
@@ -328,7 +332,8 @@ def settings(self):
mobase.PluginSetting("background r", self.__tr("Red channel of background colour"), 0),
mobase.PluginSetting("background g", self.__tr("Green channel of background colour"), 0),
mobase.PluginSetting("background b", self.__tr("Blue channel of background colour"), 0),
- mobase.PluginSetting("background a", self.__tr("Alpha channel of background colour"), 0)]
+ mobase.PluginSetting("background a", self.__tr("Alpha channel of background colour"), 0),
+ mobase.PluginSetting("transparency", self.__tr("If enabled, transparency will be displayed."), True)]
def supportedExtensions(self):
return ["dds"]
@@ -342,12 +347,13 @@ def genFilePreview(self, fileName, maxSize):
# Label grows before button
layout.setColumnStretch(0, 1)
layout.addWidget(self.__makeLabel(ddsFile), 1, 0, 1, 1)
-
- ddsWidget = DDSWidget(ddsFile, self.__organizer.pluginSetting(self.name(), "log gl errors"))
- layout.addWidget(ddsWidget, 0, 0, 1, 2)
-
- layout.addWidget(self.__makeColourButton(ddsWidget), 1, 1, 1, 1)
-
+
+ ddsWidget = DDSWidget(self, ddsFile, self.__organizer.pluginSetting(self.name(), "log gl errors"))
+ layout.addWidget(ddsWidget, 0, 0, 1, 3)
+
+ layout.addWidget(self.__makeColourButton(ddsWidget), 1, 2, 1, 1)
+ layout.addWidget(self.__makeToggleTransparencyButton(ddsWidget), 1, 1, 1, 1)
+
widget = QWidget()
widget.setLayout(layout)
return widget
@@ -363,20 +369,44 @@ def __makeLabel(self, ddsFile):
def __makeColourButton(self, ddsWidget):
button = QPushButton(self.__tr("Pick background colour"))
- savedColour = QColor(self.__organizer.pluginSetting(self.name(), "background r"), self.__organizer.pluginSetting(self.name(), "background g"), self.__organizer.pluginSetting(self.name(), "background b"), self.__organizer.pluginSetting(self.name(), "background a"))
- ddsWidget.setBackgroundColour(savedColour)
-
+
def pickColour(unused):
- newColour = QColorDialog.getColor(ddsWidget.getBackgroundColour(), button, "Background colour", QColorDialog.ShowAlphaChannel)
+ newColour = QColorDialog.getColor(self.getBackgroundColour(), button, "Background colour", QColorDialog.ShowAlphaChannel)
if newColour.isValid():
- ddsWidget.setBackgroundColour(newColour)
- self.__organizer.setPluginSetting(self.name(), "background r", newColour.red())
- self.__organizer.setPluginSetting(self.name(), "background g", newColour.green())
- self.__organizer.setPluginSetting(self.name(), "background b", newColour.blue())
- self.__organizer.setPluginSetting(self.name(), "background a", newColour.alpha())
+ self.setPluginSetting("background r", newColour.red())
+ self.setPluginSetting("background g", newColour.green())
+ self.setPluginSetting("background b", newColour.blue())
+ self.setPluginSetting("background a", newColour.alpha())
+ ddsWidget.update()
button.clicked.connect(pickColour)
return button
+
+ def __makeToggleTransparencyButton(self, ddsWidget):
+ def getButtonText():
+ if self.getTransparency():
+ return self.__tr("Disable Transparency")
+ else:
+ return self.__tr("Enable Transparency")
+
+ button = QPushButton(getButtonText())
+ # Since every conflicting mod gets its own button, the text needs to be updated when the page is changed.
+ button.showEvent = lambda _: button.setText(getButtonText())
+
+ def toggleTransparency(unused):
+ transparency = not self.getTransparency()
+ self.setPluginSetting("transparency", transparency)
+ ddsWidget.update()
+ button.setText(getButtonText())
+
+ button.clicked.connect(toggleTransparency)
+ return button
+
+ def getBackgroundColour(self):
+ return QColor(self.pluginSetting("background r"), self.pluginSetting("background g"), self.pluginSetting("background b"), self.pluginSetting("background a"))
+
+ def getTransparency(self):
+ return self.pluginSetting("transparency")
def createPlugin():
return DDSPreview()
\ No newline at end of file
diff --git a/src/DDSPreview_en.ts b/src/DDSPreview_en.ts
index b2b0a09..bd025ca 100644
--- a/src/DDSPreview_en.ts
+++ b/src/DDSPreview_en.ts
@@ -71,40 +71,55 @@
DDSPreview
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
DDSWidget
From 14ec98b0cc5479eef6427aa4d3fd03ba72a1757a Mon Sep 17 00:00:00 2001
From: Jampi0n <27952849+Jampi0n@users.noreply.github.com>
Date: Mon, 27 Jun 2022 18:23:20 +0200
Subject: [PATCH 2/4] Select which color channels are displayed
---
src/DDSPreview.py | 133 +++++++++++++++++++++++++++++++------------
src/DDSPreview_en.ts | 32 +++++------
2 files changed, 110 insertions(+), 55 deletions(-)
diff --git a/src/DDSPreview.py b/src/DDSPreview.py
index 73338bd..37e9d82 100644
--- a/src/DDSPreview.py
+++ b/src/DDSPreview.py
@@ -1,10 +1,11 @@
import struct
import sys
import threading
+import enum
from PyQt5.QtCore import QCoreApplication, qDebug, Qt
-from PyQt5.QtGui import QColor, QOpenGLBuffer, QOpenGLContext, QOpenGLDebugLogger, QOpenGLShader, QOpenGLShaderProgram, QOpenGLTexture, QOpenGLVersionProfile, QOpenGLVertexArrayObject, QSurfaceFormat
-from PyQt5.QtWidgets import QCheckBox, QDialog, QGridLayout, QLabel, QOpenGLWidget, QPushButton, QWidget
+from PyQt5.QtGui import QColor, QOpenGLBuffer, QOpenGLContext, QOpenGLDebugLogger, QOpenGLShader, QOpenGLShaderProgram, QOpenGLVersionProfile, QOpenGLVertexArrayObject, QSurfaceFormat
+from PyQt5.QtWidgets import QColorDialog, QGridLayout, QLabel, QOpenGLWidget, QPushButton, QWidget, QComboBox
from DDS.DDSFile import DDSFile
@@ -146,17 +147,51 @@
]
+class ColourChannels(enum.Enum):
+ RGBA = "Colour and Alpha"
+ RGB = "Colour"
+ A = "Alpha"
+ R = "Red"
+ G = "Green"
+ B = "Blue"
+
+
+class DDSOptions:
+ def __init__(self, colour: QColor = QColor(0, 0, 0, 0), channels: ColourChannels = ColourChannels.RGBA):
+ self.backgroundColour = None
+ self.channels = None
+ self.setBackgroundColour(colour)
+ self.setChannels(channels)
+
+ def setBackgroundColour(self, colour: QColor):
+ if isinstance(colour, QColor) and colour.isValid():
+ self.backgroundColour = colour
+ else:
+ raise TypeError(str(colour) + " is not a valid QColor object.")
+
+ def getBackgroundColour(self) -> QColor:
+ return self.backgroundColour
+
+ def setChannels(self, channels: ColourChannels):
+ if isinstance(channels, ColourChannels):
+ self.channels = channels
+ else:
+ raise TypeError(str(channels) + " is not a valid ColourChannels object.")
+
+ def getChannels(self) -> ColourChannels:
+ return self.channels
+
glVersionProfile = QOpenGLVersionProfile()
glVersionProfile.setVersion(2, 1)
class DDSWidget(QOpenGLWidget):
- def __init__(self, ddsPreview, ddsFile, debugContext = False, parent = None, f = Qt.WindowFlags()):
+ def __init__(self, ddsFile, ddsOptions = DDSOptions(), debugContext = False, parent = None, f = Qt.WindowFlags()):
super(DDSWidget, self).__init__(parent, f)
- self.ddsPreview = ddsPreview
-
self.ddsFile = ddsFile
+
+ self.ddsOptions = ddsOptions
self.clean = True
@@ -253,7 +288,7 @@ def paintGL(self):
# Draw checkerboard so transparency is obvious
self.transparecyProgram.bind()
- backgroundColour = self.ddsPreview.getBackgroundColour()
+ backgroundColour = self.ddsOptions.getBackgroundColour()
if backgroundColour and backgroundColour.isValid():
self.transparecyProgram.setUniformValue("backgroundColour", backgroundColour)
@@ -266,11 +301,35 @@ def paintGL(self):
if self.texture:
self.texture.bind()
- if self.ddsPreview.getTransparency():
- gl.glEnable(gl.GL_BLEND)
- gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
+ gl.glEnable(gl.GL_BLEND)
+ gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
+
+ def drawColour(alpha):
+ gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_R, gl.GL_RED)
+ gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_G, gl.GL_GREEN)
+ gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_B, gl.GL_BLUE)
+ gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_A, alpha)
+
+ def drawGrayscale(channel):
+ gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_R, channel)
+ gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_G, channel)
+ gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_B, channel)
+ gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_A, gl.GL_ONE)
+
+ if self.ddsOptions.getChannels() == ColourChannels.RGBA:
+ drawColour(gl.GL_ALPHA)
+ elif self.ddsOptions.getChannels() == ColourChannels.RGB:
+ drawColour(gl.GL_ONE)
+ elif self.ddsOptions.getChannels() == ColourChannels.R:
+ drawGrayscale(gl.GL_RED)
+ elif self.ddsOptions.getChannels() == ColourChannels.G:
+ drawGrayscale(gl.GL_GREEN)
+ elif self.ddsOptions.getChannels() == ColourChannels.B:
+ drawGrayscale(gl.GL_BLUE)
+ elif self.ddsOptions.getChannels() == ColourChannels.A:
+ drawGrayscale(gl.GL_ALPHA)
else:
- gl.glDisable(gl.GL_BLEND)
+ drawGrayscale(gl.GL_ZERO)
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
@@ -304,9 +363,16 @@ class DDSPreview(mobase.IPluginPreview):
def __init__(self):
super().__init__()
self.__organizer = None
+ self.options = None
def init(self, organizer):
self.__organizer = organizer
+ savedColour = QColor(self.pluginSetting("background r"), self.pluginSetting("background g"), self.pluginSetting("background b"), self.pluginSetting("background a"))
+ try:
+ savedChannels = ColourChannels[self.pluginSetting("channels")]
+ except KeyError:
+ savedChannels = ColourChannels.RGBA
+ self.options = DDSOptions(savedColour, savedChannels)
return True
def pluginSetting(self, name):
@@ -333,7 +399,7 @@ def settings(self):
mobase.PluginSetting("background g", self.__tr("Green channel of background colour"), 0),
mobase.PluginSetting("background b", self.__tr("Blue channel of background colour"), 0),
mobase.PluginSetting("background a", self.__tr("Alpha channel of background colour"), 0),
- mobase.PluginSetting("transparency", self.__tr("If enabled, transparency will be displayed."), True)]
+ mobase.PluginSetting("channels", self.__tr("The colour channels that are displayed."), ColourChannels.RGBA.name)]
def supportedExtensions(self):
return ["dds"]
@@ -348,11 +414,11 @@ def genFilePreview(self, fileName, maxSize):
layout.setColumnStretch(0, 1)
layout.addWidget(self.__makeLabel(ddsFile), 1, 0, 1, 1)
- ddsWidget = DDSWidget(self, ddsFile, self.__organizer.pluginSetting(self.name(), "log gl errors"))
+ ddsWidget = DDSWidget(ddsFile, self.options, self.__organizer.pluginSetting(self.name(), "log gl errors"))
layout.addWidget(ddsWidget, 0, 0, 1, 3)
layout.addWidget(self.__makeColourButton(ddsWidget), 1, 2, 1, 1)
- layout.addWidget(self.__makeToggleTransparencyButton(ddsWidget), 1, 1, 1, 1)
+ layout.addWidget(self.__makeChannelsButton(ddsWidget), 1, 1, 1, 1)
widget = QWidget()
widget.setLayout(layout)
@@ -371,42 +437,35 @@ def __makeColourButton(self, ddsWidget):
button = QPushButton(self.__tr("Pick background colour"))
def pickColour(unused):
- newColour = QColorDialog.getColor(self.getBackgroundColour(), button, "Background colour", QColorDialog.ShowAlphaChannel)
+ newColour = QColorDialog.getColor(self.options.getBackgroundColour(), button, "Background colour", QColorDialog.ShowAlphaChannel)
if newColour.isValid():
self.setPluginSetting("background r", newColour.red())
self.setPluginSetting("background g", newColour.green())
self.setPluginSetting("background b", newColour.blue())
self.setPluginSetting("background a", newColour.alpha())
+ self.options.setBackgroundColour(newColour)
ddsWidget.update()
button.clicked.connect(pickColour)
return button
- def __makeToggleTransparencyButton(self, ddsWidget):
- def getButtonText():
- if self.getTransparency():
- return self.__tr("Disable Transparency")
- else:
- return self.__tr("Enable Transparency")
-
- button = QPushButton(getButtonText())
- # Since every conflicting mod gets its own button, the text needs to be updated when the page is changed.
- button.showEvent = lambda _: button.setText(getButtonText())
-
- def toggleTransparency(unused):
- transparency = not self.getTransparency()
- self.setPluginSetting("transparency", transparency)
+ def __makeChannelsButton(self, ddsWidget):
+ listwidget = QComboBox()
+ channelKeys = [e.name for e in ColourChannels]
+ channelNames = [e.value for e in ColourChannels]
+
+ listwidget.addItems(channelNames)
+ listwidget.setCurrentText(self.options.channels.value)
+ listwidget.setToolTip(self.__tr("Change which channels are displayed."))
+
+ listwidget.showEvent = lambda _: listwidget.setCurrentText(self.options.channels.value)
+ def onChanged(newIndex):
+ self.options.channels = ColourChannels[channelKeys[newIndex]]
+ self.setPluginSetting("channels", self.options.channels.name)
ddsWidget.update()
- button.setText(getButtonText())
-
- button.clicked.connect(toggleTransparency)
- return button
-
- def getBackgroundColour(self):
- return QColor(self.pluginSetting("background r"), self.pluginSetting("background g"), self.pluginSetting("background b"), self.pluginSetting("background a"))
- def getTransparency(self):
- return self.pluginSetting("transparency")
+ listwidget.currentIndexChanged.connect(onChanged)
+ return listwidget
def createPlugin():
return DDSPreview()
\ No newline at end of file
diff --git a/src/DDSPreview_en.ts b/src/DDSPreview_en.ts
index bd025ca..27d14c5 100644
--- a/src/DDSPreview_en.ts
+++ b/src/DDSPreview_en.ts
@@ -1,5 +1,6 @@
-
+
+
DDSFile
@@ -71,60 +72,55 @@
DDSPreview
-
+
-
+
-
+
-
+
-
+
-
+
-
-
-
-
-
-
+
-
-
+
+
-
-
+
+
DDSWidget
-
+
From 024072841e1045a2df464fe7da8873af5350b528 Mon Sep 17 00:00:00 2001
From: Jampi0n <27952849+Jampi0n@users.noreply.github.com>
Date: Thu, 30 Jun 2022 12:29:03 +0200
Subject: [PATCH 3/4] Implement channels inside the shaders
---
src/DDSPreview.py | 173 +++++++++++++++++++++++++++++++---------------
1 file changed, 118 insertions(+), 55 deletions(-)
diff --git a/src/DDSPreview.py b/src/DDSPreview.py
index 37e9d82..860dd6b 100644
--- a/src/DDSPreview.py
+++ b/src/DDSPreview.py
@@ -2,9 +2,10 @@
import sys
import threading
import enum
+from typing import Iterable
from PyQt5.QtCore import QCoreApplication, qDebug, Qt
-from PyQt5.QtGui import QColor, QOpenGLBuffer, QOpenGLContext, QOpenGLDebugLogger, QOpenGLShader, QOpenGLShaderProgram, QOpenGLVersionProfile, QOpenGLVertexArrayObject, QSurfaceFormat
+from PyQt5.QtGui import QColor, QOpenGLBuffer, QOpenGLContext, QOpenGLDebugLogger, QOpenGLShader, QOpenGLShaderProgram, QOpenGLVersionProfile, QOpenGLVertexArrayObject, QSurfaceFormat, QMatrix4x4, QVector4D
from PyQt5.QtWidgets import QColorDialog, QGridLayout, QLabel, QOpenGLWidget, QPushButton, QWidget, QComboBox
from DDS.DDSFile import DDSFile
@@ -54,12 +55,14 @@
#version 150
uniform sampler2D aTexture;
+uniform mat4 channelMatrix;
+uniform vec4 channelOffset;
in vec2 texCoord;
void main()
{
- gl_FragData[0] = texture(aTexture, texCoord);
+ gl_FragData[0] = channelMatrix * texture(aTexture, texCoord) + channelOffset;
}
"""
@@ -67,13 +70,15 @@
#version 150
uniform usampler2D aTexture;
+uniform mat4 channelMatrix;
+uniform vec4 channelOffset;
in vec2 texCoord;
void main()
{
// autofilled alpha is 1, so if we have a scaling factor, we need separate ones for luminance and alpha
- gl_FragData[0] = texture(aTexture, texCoord);
+ gl_FragData[0] = channelMatrix * texture(aTexture, texCoord) + channelOffset;
}
"""
@@ -81,13 +86,15 @@
#version 150
uniform isampler2D aTexture;
+uniform mat4 channelMatrix;
+uniform vec4 channelOffset;
in vec2 texCoord;
void main()
{
// autofilled alpha is 1, so if we have a scaling factor and offset, we need separate ones for luminance and alpha
- gl_FragData[0] = texture(aTexture, texCoord);
+ gl_FragData[0] = channelMatrix * texture(aTexture, texCoord) + channelOffset;
}
"""
@@ -95,6 +102,8 @@
#version 150
uniform samplerCube aTexture;
+uniform mat4 channelMatrix;
+uniform vec4 channelOffset;
in vec2 texCoord;
@@ -104,7 +113,7 @@
{
float theta = -2.0 * PI * texCoord.x;
float phi = PI * texCoord.y;
- gl_FragData[0] = texture(aTexture, vec3(sin(theta) * sin(phi), cos(theta) * sin(phi), cos(phi)));
+ gl_FragData[0] = channelMatrix * texture(aTexture, vec3(sin(theta) * sin(phi), cos(theta) * sin(phi), cos(phi))) + channelOffset;
}
"""
@@ -146,22 +155,17 @@
1.0, -1.0, 0.5, 1.0, 1.0, 1.0,
]
-
-class ColourChannels(enum.Enum):
- RGBA = "Colour and Alpha"
- RGB = "Colour"
- A = "Alpha"
- R = "Red"
- G = "Green"
- B = "Blue"
-
-
class DDSOptions:
- def __init__(self, colour: QColor = QColor(0, 0, 0, 0), channels: ColourChannels = ColourChannels.RGBA):
+ def __init__(self, colour: QColor = QColor(0, 0, 0, 0), channelMatrix: QMatrix4x4 = QMatrix4x4(), channelOffset: QVector4D = QVector4D()):
+ # QMatrix4x4 with no arguments is the identity matrix, so no channel transformations
+ # declare member variables with None values
self.backgroundColour = None
- self.channels = None
+ self.channelMatrix = None
+ self.channelOffset = None
+ # initialize member variables with error checks
self.setBackgroundColour(colour)
- self.setChannels(channels)
+ self.setChannelMatrix(channelMatrix)
+ self.setChannelOffset(channelOffset)
def setBackgroundColour(self, colour: QColor):
if isinstance(colour, QColor) and colour.isValid():
@@ -172,14 +176,44 @@ def setBackgroundColour(self, colour: QColor):
def getBackgroundColour(self) -> QColor:
return self.backgroundColour
- def setChannels(self, channels: ColourChannels):
- if isinstance(channels, ColourChannels):
- self.channels = channels
+ def getChannelMatrix(self) -> QMatrix4x4:
+ return self.channelMatrix
+
+ def setChannelMatrix(self, matrix):
+
+ def flattenList(lst: Iterable):
+ tmp = []
+ for e in lst:
+ if isinstance(e, Iterable):
+ tmp += flattenList(e)
+ elif isinstance(e, (int, float)):
+ tmp += [float(e)]
+ else:
+ raise ValueError("Can only set a matrix with numbers.")
+ return tmp
+
+ if isinstance(matrix, Iterable):
+ flattened = flattenList(matrix)
+ if len(flattened) != 16:
+ raise ValueError("Must provide exactly 16 values.")
+ matrix = QMatrix4x4(flattened)
+
+ if isinstance(matrix, QMatrix4x4):
+ self.channelMatrix = matrix
else:
- raise TypeError(str(channels) + " is not a valid ColourChannels object.")
+ raise ValueError("Can only set a matrix with numbers.")
+
+ def getChannelOffset(self) -> QVector4D:
+ return self.channelOffset
+
+ def setChannelOffset(self, vector):
+ if isinstance(vector, Iterable):
+ vector = list(vector)
+ if len(vector) != 4:
+ raise ValueError("Must provide exactly 4 values.")
+ vector = QVector4D(vector[0], vector[1], vector[2], vector[3])
+ self.channelOffset = vector
- def getChannels(self) -> ColourChannels:
- return self.channels
glVersionProfile = QOpenGLVersionProfile()
@@ -304,32 +338,8 @@ def paintGL(self):
gl.glEnable(gl.GL_BLEND)
gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
- def drawColour(alpha):
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_R, gl.GL_RED)
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_G, gl.GL_GREEN)
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_B, gl.GL_BLUE)
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_A, alpha)
-
- def drawGrayscale(channel):
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_R, channel)
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_G, channel)
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_B, channel)
- gl.glTexParameteri(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_SWIZZLE_A, gl.GL_ONE)
-
- if self.ddsOptions.getChannels() == ColourChannels.RGBA:
- drawColour(gl.GL_ALPHA)
- elif self.ddsOptions.getChannels() == ColourChannels.RGB:
- drawColour(gl.GL_ONE)
- elif self.ddsOptions.getChannels() == ColourChannels.R:
- drawGrayscale(gl.GL_RED)
- elif self.ddsOptions.getChannels() == ColourChannels.G:
- drawGrayscale(gl.GL_GREEN)
- elif self.ddsOptions.getChannels() == ColourChannels.B:
- drawGrayscale(gl.GL_BLUE)
- elif self.ddsOptions.getChannels() == ColourChannels.A:
- drawGrayscale(gl.GL_ALPHA)
- else:
- drawGrayscale(gl.GL_ZERO)
+ self.program.setUniformValue("channelMatrix", self.ddsOptions.getChannelMatrix())
+ self.program.setUniformValue("channelOffset", self.ddsOptions.getChannelOffset())
gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
@@ -358,12 +368,63 @@ def __tr(self, str):
return QCoreApplication.translate("DDSWidget", str)
+class ColourChannels(enum.Enum):
+ RGBA = "Colour and Alpha"
+ RGB = "Colour"
+ A = "Alpha"
+ R = "Red"
+ G = "Green"
+ B = "Blue"
+
+
+class DDSChannelManager:
+ def __init__(self, channels: ColourChannels):
+ self.channels = channels
+
+ def setChannels(self, options: DDSOptions, channels: ColourChannels):
+ self.channels = channels
+ def drawColour(alpha: bool):
+ colorMatrix = QMatrix4x4()
+ colorOffset = QVector4D()
+ if not alpha:
+ colorMatrix[3, 3] = 0
+ colorOffset.setW(1.0)
+ options.setChannelMatrix(colorMatrix)
+ options.setChannelOffset(colorOffset)
+
+ def drawGrayscale(channel: ColourChannels):
+ colorOffset = QVector4D(0, 0, 0, 1)
+ channelVector = [0, 0, 0, 0]
+ if channels == ColourChannels.R:
+ channelVector[0] = 1
+ elif channel == ColourChannels.G:
+ channelVector[1] = 1
+ elif channel == ColourChannels.B:
+ channelVector[2] = 1
+ elif channels == ColourChannels.A:
+ channelVector[3] = 1
+ else:
+ raise ValueError("channel must be a single color channel.")
+ alphaVector = [0, 0, 0, 0]
+ colorMatrix = channelVector * 3 + alphaVector
+ options.setChannelMatrix(colorMatrix)
+ options.setChannelOffset(colorOffset)
+
+ if channels == ColourChannels.RGBA:
+ drawColour(True)
+ elif channels == ColourChannels.RGB:
+ drawColour(False)
+ else:
+ drawGrayscale(channels)
+
+
class DDSPreview(mobase.IPluginPreview):
def __init__(self):
super().__init__()
self.__organizer = None
self.options = None
+ self.channelManager = None
def init(self, organizer):
self.__organizer = organizer
@@ -372,7 +433,9 @@ def init(self, organizer):
savedChannels = ColourChannels[self.pluginSetting("channels")]
except KeyError:
savedChannels = ColourChannels.RGBA
- self.options = DDSOptions(savedColour, savedChannels)
+ self.options = DDSOptions(savedColour)
+ self.channelManager = DDSChannelManager(savedChannels)
+ self.channelManager.setChannels(self.options, savedChannels)
return True
def pluginSetting(self, name):
@@ -455,13 +518,13 @@ def __makeChannelsButton(self, ddsWidget):
channelNames = [e.value for e in ColourChannels]
listwidget.addItems(channelNames)
- listwidget.setCurrentText(self.options.channels.value)
+ listwidget.setCurrentText(self.channelManager.channels.value)
listwidget.setToolTip(self.__tr("Change which channels are displayed."))
- listwidget.showEvent = lambda _: listwidget.setCurrentText(self.options.channels.value)
+ listwidget.showEvent = lambda _: listwidget.setCurrentText(self.channelManager.channels.value)
def onChanged(newIndex):
- self.options.channels = ColourChannels[channelKeys[newIndex]]
- self.setPluginSetting("channels", self.options.channels.name)
+ self.channelManager.setChannels(self.options, ColourChannels[channelKeys[newIndex]])
+ self.setPluginSetting("channels", self.channelManager.channels.name)
ddsWidget.update()
listwidget.currentIndexChanged.connect(onChanged)
From a9a1bfe14f74314145bd6a4d15459346e876761d Mon Sep 17 00:00:00 2001
From: Jampi0n <27952849+Jampi0n@users.noreply.github.com>
Date: Fri, 1 Jul 2022 10:57:33 +0200
Subject: [PATCH 4/4] Simplify set matrix and vector functions
---
src/DDSPreview.py | 31 ++-----------------------------
src/DDSPreview_en.ts | 20 ++++++++++----------
2 files changed, 12 insertions(+), 39 deletions(-)
diff --git a/src/DDSPreview.py b/src/DDSPreview.py
index 860dd6b..ed25d89 100644
--- a/src/DDSPreview.py
+++ b/src/DDSPreview.py
@@ -180,40 +180,13 @@ def getChannelMatrix(self) -> QMatrix4x4:
return self.channelMatrix
def setChannelMatrix(self, matrix):
-
- def flattenList(lst: Iterable):
- tmp = []
- for e in lst:
- if isinstance(e, Iterable):
- tmp += flattenList(e)
- elif isinstance(e, (int, float)):
- tmp += [float(e)]
- else:
- raise ValueError("Can only set a matrix with numbers.")
- return tmp
-
- if isinstance(matrix, Iterable):
- flattened = flattenList(matrix)
- if len(flattened) != 16:
- raise ValueError("Must provide exactly 16 values.")
- matrix = QMatrix4x4(flattened)
-
- if isinstance(matrix, QMatrix4x4):
- self.channelMatrix = matrix
- else:
- raise ValueError("Can only set a matrix with numbers.")
+ self.channelMatrix = QMatrix4x4(matrix)
def getChannelOffset(self) -> QVector4D:
return self.channelOffset
def setChannelOffset(self, vector):
- if isinstance(vector, Iterable):
- vector = list(vector)
- if len(vector) != 4:
- raise ValueError("Must provide exactly 4 values.")
- vector = QVector4D(vector[0], vector[1], vector[2], vector[3])
- self.channelOffset = vector
-
+ self.channelOffset = QVector4D(vector)
glVersionProfile = QOpenGLVersionProfile()
diff --git a/src/DDSPreview_en.ts b/src/DDSPreview_en.ts
index 27d14c5..6f47bc7 100644
--- a/src/DDSPreview_en.ts
+++ b/src/DDSPreview_en.ts
@@ -72,47 +72,47 @@
DDSPreview
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -120,7 +120,7 @@
DDSWidget
-
+