diff --git a/app/SettingComponent.qml b/app/CheckableSlider.qml similarity index 86% rename from app/SettingComponent.qml rename to app/CheckableSlider.qml index abeb827..c6044bc 100644 --- a/app/SettingComponent.qml +++ b/app/CheckableSlider.qml @@ -56,6 +56,14 @@ RowLayout { } Text{ id: textfield - text: Math.round(((value - min_value) / (max_value - min_value)) * 100) + "%" + property string unformattedText: Math.round(((value - min_value) / (max_value - min_value)) * 100) + text: formatNumber(unformattedText) + } + function formatNumber(num) { + var n = "" + num; + while (n.length < 3) { + n = " " + n; + } + return n + "%"; } } diff --git a/app/ColorButton.qml b/app/ColorButton.qml index 1b966df..248924c 100644 --- a/app/ColorButton.qml +++ b/app/ColorButton.qml @@ -22,7 +22,8 @@ import QtQuick 2.2 import QtQuick.Dialogs 1.1 Item { - property color button_color; + property color button_color + property string name ColorDialog { id: colorDialog @@ -35,25 +36,22 @@ Item { onAccepted: button_color = color; } Rectangle{ - radius: 10 anchors.fill: parent + radius: 10 color: button_color - - Text{ - id: text_color - anchors.centerIn: parent - z: 1.1 - text: button_color - } - - Rectangle{ - anchors.centerIn: parent - width: text_color.width * 1.4 - height: text_color.height * 1.4 - radius: 10 - border.color: "black" - border.width: 2 + border.color: "black" + Glossy {} + Rectangle { + anchors.fill: parent + anchors.margins: parent.height * 0.25 + radius: parent.radius color: "white" + opacity: 0.5 + } + Text{ + anchors.centerIn: parent + z: parent.z + 1 + text: name + ": " + button_color } } MouseArea{ diff --git a/app/FontPixels.qml b/app/FontPixels.qml new file mode 100644 index 0000000..455346d --- /dev/null +++ b/app/FontPixels.qml @@ -0,0 +1,51 @@ +import QtQuick 2.0 + +Item{ + property int selectedFontIndex + property int selectedScalingIndex + property alias fontlist: fontlist + property var _font: fontlist.get(selectedFontIndex) + property var _scaling: fontScalingList[selectedScalingIndex] + property var source: _font.source + property var fontScalingList: [0.75, 1.0, 1.25, 1.50, 1.75, 2.0, 2.25, 2.5] + property int pixelSize: _font.pixelSize * _scaling + property int lineSpacing: (_font.pixelSize / _font.virtualCharHeight) * _font.lineSpacing + property size virtualCharSize: Qt.size(_font.virtualCharWidth, + _font.virtualCharHeight) + + ListModel{ + id: fontlist + ListElement{ + text: "Commodore PET (1977)" + source: "fonts/1977-commodore-pet/COMMODORE_PET.ttf" + lineSpacing: 2 + virtualCharWidth: 8 + virtualCharHeight: 8 + pixelSize: 32 + } + ListElement{ + text: "Apple ][ (1977)" + source: "fonts/1977-apple2/PrintChar21.ttf" + lineSpacing: 2 + virtualCharWidth: 7 + virtualCharHeight: 8 + pixelSize: 32 + } + ListElement{ + text: "Atari 400-800 (1979)" + source: "fonts/1979-atari-400-800/ATARI400800_original.TTF" + lineSpacing: 3 + virtualCharWidth: 8 + virtualCharHeight: 8 + pixelSize: 32 + } + ListElement{ + text: "Commodore 64 (1982)" + source: "fonts/1982-commodore64/C64_User_Mono_v1.0-STYLE.ttf" + lineSpacing: 3 + virtualCharWidth: 8 + virtualCharHeight: 8 + pixelSize: 32 + } + } +} diff --git a/app/FontScanlines.qml b/app/FontScanlines.qml new file mode 100644 index 0000000..7ab57c7 --- /dev/null +++ b/app/FontScanlines.qml @@ -0,0 +1,59 @@ +import QtQuick 2.0 + +Item{ + property int selectedFontIndex + property int selectedScalingIndex + property alias fontlist: fontlist + property var _font: fontlist.get(selectedFontIndex) + property var _scaling: fontScalingList[selectedScalingIndex] + property var source: _font.source + property var fontScalingList: [0.75, 1.0, 1.25, 1.50, 1.75, 2.0, 2.25, 2.50] + property int pixelSize: _font.pixelSize * _scaling + property int lineSpacing: (_font.pixelSize / _font.virtualCharHeight) * _font.lineSpacing + property size virtualCharSize: Qt.size(_font.virtualCharWidth, + _font.virtualCharHeight) + + ListModel{ + id: fontlist + ListElement{ + text: "Commodore PET 2Y (1977)" + source: "fonts/1977-commodore-pet/COMMODORE_PET_2y.ttf" + lineSpacing: 2 + virtualCharWidth: 4 + virtualCharHeight: 8 + pixelSize: 32 + } + ListElement{ + text: "Commodore PET (1977)" + source: "fonts/1977-commodore-pet/COMMODORE_PET.ttf" + lineSpacing: 2 + virtualCharWidth: 8 + virtualCharHeight: 8 + pixelSize: 32 + } + ListElement{ + text: "Apple ][ (1977)" + source: "fonts/1977-apple2/PrintChar21.ttf" + lineSpacing: 2 + virtualCharWidth: 8 + virtualCharHeight: 8 + pixelSize: 32 + } + ListElement{ + text: "Atari 400-800 (1979)" + source: "fonts/1979-atari-400-800/ATARI400800_original.TTF" + lineSpacing: 3 + virtualCharWidth: 8 + virtualCharHeight: 8 + pixelSize: 32 + } + ListElement{ + text: "Commodore 64 (1982)" + source: "fonts/1982-commodore64/C64_User_Mono_v1.0-STYLE.ttf" + lineSpacing: 3 + virtualCharWidth: 8 + virtualCharHeight: 8 + pixelSize: 32 + } + } +} diff --git a/app/Fonts.qml b/app/Fonts.qml new file mode 100644 index 0000000..5e85aa2 --- /dev/null +++ b/app/Fonts.qml @@ -0,0 +1,67 @@ +import QtQuick 2.0 + +Item{ + property int selectedFontIndex + property int selectedScalingIndex + property alias fontlist: fontlist + property var source: fontlist.get(selectedFontIndex).source + property var _font: fontlist.get(selectedFontIndex) + property var _scaling: fontScalingList[selectedScalingIndex] + property var fontScalingList: [0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.1, 2.2, 2.3, 2.4, 2.5] + property int pixelSize: _font.pixelSize * _scaling + property int lineSpacing: pixelSize * _font.lineSpacing + + //In this configuration lineSpacing is proportional to pixelSize. + + ListModel{ + id: fontlist + ListElement{ + text: "Terminus (Modern)" + source: "fonts/modern-terminus/TerminusTTF-Bold-4.38.2.ttf" + lineSpacing: 0.2 + pixelSize: 35 + } + ListElement{ + text: "Commodore PET (1977)" + source: "fonts/1977-commodore-pet/COMMODORE_PET.ttf" + lineSpacing: 0.2 + pixelSize: 24 + } + ListElement{ + text: "Commodore PET 2Y (1977)" + source: "fonts/1977-commodore-pet/COMMODORE_PET_2y.ttf" + lineSpacing: 0.2 + pixelSize: 32 + } + ListElement{ + text: "Apple ][ (1977)" + source: "fonts/1977-apple2/PrintChar21.ttf" + lineSpacing: 0.2 + pixelSize: 24 + } + ListElement{ + text: "Atari 400-800 (1979)" + source: "fonts/1979-atari-400-800/ATARI400800_original.TTF" + lineSpacing: 0.3 + pixelSize: 24 + } + ListElement{ + text: "Commodore 64 (1982)" + source: "fonts/1982-commodore64/C64_User_Mono_v1.0-STYLE.ttf" + lineSpacing: 0.3 + pixelSize: 24 + } + ListElement{ + text: "Atari ST (1985)" + source: "fonts/1985-atari-st/AtariST8x16SystemFont.ttf" + lineSpacing: 0.2 + pixelSize: 32 + } + ListElement{ + text: "IBM DOS (1985)" + source: "fonts/1985-ibm-pc-vga/Perfect DOS VGA 437.ttf" + lineSpacing: 0.2 + pixelSize: 32 + } + } +} diff --git a/app/Glossy.qml b/app/Glossy.qml new file mode 100644 index 0000000..3ac9c14 --- /dev/null +++ b/app/Glossy.qml @@ -0,0 +1,21 @@ +import QtQuick 2.2 + +Rectangle { + anchors.centerIn: parent + width: parent.width - parent.border.width + height: parent.height - parent.border.width + radius:parent.radius - parent.border.width/2 + smooth: true + + border.width: parent.border.width/2 + border.color: "#22FFFFFF" + + gradient: Gradient { + GradientStop { position: 0; color: "#88FFFFFF" } + GradientStop { position: .1; color: "#55FFFFFF" } + GradientStop { position: .5; color: "#33FFFFFF" } + GradientStop { position: .501; color: "#11000000" } + GradientStop { position: .8; color: "#11FFFFFF" } + GradientStop { position: 1; color: "#55FFFFFF" } + } +} diff --git a/app/SettingsEffectsTab.qml b/app/SettingsEffectsTab.qml new file mode 100644 index 0000000..a6e398a --- /dev/null +++ b/app/SettingsEffectsTab.qml @@ -0,0 +1,53 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 + +Tab{ + GroupBox{ + title: qsTr("Effects") + anchors.fill: parent + ColumnLayout{ + anchors.fill: parent + CheckableSlider{ + name: qsTr("Bloom") + onValueChanged: shadersettings.bloom_strength = value + _value: shadersettings.bloom_strength + } + CheckableSlider{ + name: qsTr("Motion Blur") + onValueChanged: shadersettings.motion_blur = value + _value: shadersettings.motion_blur + } + CheckableSlider{ + name: qsTr("Noise") + onValueChanged: shadersettings.noise_strength = value + _value: shadersettings.noise_strength + } + CheckableSlider{ + name: qsTr("Jitter") + onValueChanged: shadersettings.jitter = value + _value: shadersettings.jitter + } + CheckableSlider{ + name: qsTr("Glow") + onValueChanged: shadersettings.glowing_line_strength = value; + _value: shadersettings.glowing_line_strength + } + CheckableSlider{ + name: qsTr("Screen distortion") + onValueChanged: shadersettings.screen_distortion = value; + _value: shadersettings.screen_distortion; + } + CheckableSlider{ + name: qsTr("Brightness flickering") + onValueChanged: shadersettings.brightness_flickering= value; + _value: shadersettings.brightness_flickering; + } + CheckableSlider{ + name: qsTr("Horizontal flickering") + onValueChanged: shadersettings.horizontal_sincronization = value; + _value: shadersettings.horizontal_sincronization; + } + } + } +} diff --git a/app/SettingsGeneralTab.qml b/app/SettingsGeneralTab.qml new file mode 100644 index 0000000..fe40028 --- /dev/null +++ b/app/SettingsGeneralTab.qml @@ -0,0 +1,110 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 + +Tab{ + ColumnLayout{ + anchors.fill: parent + GroupBox{ + Layout.fillWidth: true + title: qsTr("Profile") + ColumnLayout{ + anchors.fill: parent + ComboBox{ + id: profilesbox + Layout.fillWidth: true + model: shadersettings.profiles_list + currentIndex: shadersettings.profiles_index + } + RowLayout{ + Layout.fillWidth: true + Button{ + Layout.fillWidth: true + text: qsTr("Load") + onClicked: { + shadersettings.profiles_index = profilesbox.currentIndex + shadersettings.loadCurrentProfile(); + shadersettings.handleFontChanged(); + } + } + Button{ + Layout.fillWidth: true + text: qsTr("Store current") + onClicked: insertname.show() + } + Button{ + Layout.fillWidth: true + text: qsTr("Remove Selected") + enabled: !shadersettings.profiles_list.get(profilesbox.currentIndex).builtin + onClicked: { + shadersettings.profiles_list.remove(profilesbox.currentIndex) + profilesbox.currentIndex = profilesbox.currentIndex - 1 + } + } + } + InsertNameDialog{ + id: insertname + onNameSelected: shadersettings.addNewCustomProfile(name) + } + } + } + GroupBox{ + title: qsTr("Lights") + Layout.fillWidth: true + GridLayout{ + anchors.fill: parent + columns: 2 + Text{ text: qsTr("Brightness") } + SimpleSlider{ + onValueChanged: shadersettings.brightness = value + value: shadersettings.brightness + } + Text{ text: qsTr("Contrast") } + SimpleSlider{ + onValueChanged: shadersettings.contrast = value + value: shadersettings.contrast + } + Text{ text: qsTr("Ambient") } + SimpleSlider{ + onValueChanged: shadersettings.ambient_light = value; + value: shadersettings.ambient_light + } + } + } + GroupBox{ + title: qsTr("Performace") + Layout.fillWidth: true + Layout.columnSpan: 2 + anchors.left: parent.left + anchors.right: parent.right + GridLayout{ + anchors.fill: parent + rows: 2 + columns: 3 + Text{text: qsTr("Animation FPS")} + Slider{ + Layout.fillWidth: true + id: slider + stepSize: 1 + maximumValue: 60 + minimumValue: 0 + onValueChanged: shadersettings.fps = value; + value: shadersettings.fps + } + Text{text: slider.value} + Text{text: qsTr("Texture quality")} + Slider{ + Layout.fillWidth: true + id: txtslider + stepSize: 0.01 + maximumValue: 1 + minimumValue: 0 + onValueChanged: shadersettings.window_scaling = value; + value: shadersettings.window_scaling + updateValueWhileDragging: false + } + Text{text: Math.round(txtslider.__handlePos * 100) + "%"} + } + } + } +} diff --git a/app/SettingsTerminalTab.qml b/app/SettingsTerminalTab.qml new file mode 100644 index 0000000..b09476d --- /dev/null +++ b/app/SettingsTerminalTab.qml @@ -0,0 +1,114 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.1 +import QtQuick.Layouts 1.1 + +Tab{ + ColumnLayout{ + anchors.fill: parent + GroupBox{ + title: qsTr("Rasterization Mode") + Layout.fillWidth: true + ComboBox { + id: rasterizationBox + property string selectedElement: model[currentIndex] + anchors.fill: parent + model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels")] + currentIndex: shadersettings.rasterization + onCurrentIndexChanged: { + scalingChanger.enabled = false; + shadersettings.rasterization = currentIndex + fontChanger.updateIndex(); + scalingChanger.updateIndex(); + scalingChanger.enabled = true; + } + } + } + GroupBox{ + title: qsTr("Font") + " (" + rasterizationBox.selectedElement + ")" + Layout.fillWidth: true + GridLayout{ + anchors.fill: parent + columns: 2 + Text{ text: qsTr("Name") } + ComboBox{ + id: fontChanger + Layout.fillWidth: true + model: shadersettings.fontlist + currentIndex: updateIndex() + onActivated: { + shadersettings.fontIndexes[shadersettings.rasterization] = index; + shadersettings.handleFontChanged(); + } + function updateIndex(){ + currentIndex = shadersettings.fontIndexes[shadersettings.rasterization]; + } + } + Text{ text: qsTr("Scaling") } + RowLayout{ + Layout.fillWidth: true + Slider{ + id: scalingChanger + Layout.fillWidth: true + minimumValue: 0 + maximumValue: shadersettings.fontScalingList.length - 1 + stepSize: 1 + tickmarksEnabled: true + value: updateIndex() + onValueChanged: { + if(!enabled) return; //Ugly and hacky solution. Look for a better solution. + shadersettings.fontScalingIndexes[shadersettings.rasterization] = value; + shadersettings.handleFontChanged(); + } + function updateIndex(){ + value = shadersettings.fontScalingIndexes[shadersettings.rasterization]; + } + } + Text{ + text: shadersettings.fontScalingList[scalingChanger.value].toFixed(2) + } + } + } + } + GroupBox{ + title: qsTr("Colors") + Layout.fillWidth: true + RowLayout{ + anchors.fill: parent + ColorButton{ + name: qsTr("Font") + height: 50 + Layout.fillWidth: true + onButton_colorChanged: shadersettings._font_color = button_color + button_color: shadersettings._font_color + } + ColorButton{ + name: qsTr("Background") + height: 50 + Layout.fillWidth: true + onButton_colorChanged: shadersettings._background_color = button_color + button_color: shadersettings._background_color + } + } + } + GroupBox{ + title: qsTr("Frame") + Layout.fillWidth: true + RowLayout{ + anchors.fill: parent + ComboBox{ + id: framescombobox + Layout.fillWidth: true + model: shadersettings.frames_list + currentIndex: shadersettings.frames_index + onCurrentIndexChanged: shadersettings.frames_index = currentIndex + } + CheckBox{ + checked: shadersettings.frame_reflections + text: qsTr("Reflections") + onCheckedChanged: shadersettings.frame_reflections = checked + enabled: framescombobox.model.get(framescombobox.currentIndex).reflections + } + } + } + } +} diff --git a/app/SettingsWindow.qml b/app/SettingsWindow.qml index 08fdf6f..db23dff 100644 --- a/app/SettingsWindow.qml +++ b/app/SettingsWindow.qml @@ -28,276 +28,29 @@ Window { id: settings_window title: qsTr("Settings") width: 640 - height: 480 + height: 420 + + property int tabmargins: 15 modality: Qt.ApplicationModal TabView{ anchors.fill: parent anchors.margins: 10 - Tab{ - title: qsTr("Appearance") + SettingsGeneralTab{ + title: qsTr("General") anchors.fill: parent - anchors.margins: 15 - GridLayout{ - anchors.fill: parent - columns: 2 - GroupBox{ - anchors.left: parent.left - anchors.right: parent.right - Layout.columnSpan: 2 - title: qsTr("Profile") - RowLayout{ - anchors.fill: parent - ComboBox{ - id: profilesbox - Layout.fillWidth: true - model: shadersettings.profiles_list - currentIndex: shadersettings.profiles_index - } - Button{ - text: "Load" - onClicked: shadersettings.profiles_index = profilesbox.currentIndex - } - Button{ - text: "Add" - onClicked: insertname.show() - } - Button{ - text: "Remove" - enabled: !shadersettings.profiles_list.get(profilesbox.currentIndex).builtin - onClicked: { - shadersettings.profiles_list.remove(profilesbox.currentIndex) - profilesbox.currentIndex = profilesbox.currentIndex - 1 - } - } - InsertNameDialog{ - id: insertname - onNameSelected: shadersettings.addNewCustomProfile(name) - } - } - } - - GroupBox{ - id: fontbox - title: qsTr("Font") - Layout.fillHeight: true - Layout.fillWidth: true - GridLayout{ - anchors.fill: parent - columns: 2 - Text{text: qsTr("Font style:")} - ComboBox{ - Layout.fillWidth: true - model: shadersettings.fonts_list - currentIndex: shadersettings.font_index - onCurrentIndexChanged: shadersettings.font_index = currentIndex - } - Text{text: qsTr("Font scaling:")} - ComboBox{ - Layout.fillWidth: true - model: shadersettings._font_scalings - currentIndex: shadersettings.font_scaling_index - onCurrentIndexChanged: shadersettings.font_scaling_index = currentIndex - } - Item{Layout.fillHeight: true} - ColorButton{ - height: 50 - Layout.fillWidth: true - Layout.columnSpan: 2 - onButton_colorChanged: shadersettings._font_color = button_color; - button_color: shadersettings._font_color; - } - } - } - GroupBox{ - title: qsTr("Background") - Layout.fillHeight: true - Layout.fillWidth: true - GridLayout{ - anchors.fill: parent - columns: 2 - Text{text: "Frame texture"} - ComboBox{ - id: framescombobox - Layout.fillWidth: true - model: shadersettings.frames_list - currentIndex: shadersettings.frames_index - onCurrentIndexChanged: shadersettings.frames_index = currentIndex - } - CheckBox{ - Layout.columnSpan: 2 - Layout.fillWidth: true - checked: shadersettings.frame_reflections - text: qsTr("Frame reflections") - onCheckedChanged: shadersettings.frame_reflections = checked - enabled: framescombobox.model.get(framescombobox.currentIndex).reflections - } - - Item{Layout.fillHeight: true} - ColorButton{ - height: 50 - Layout.fillWidth: true - Layout.columnSpan: 2 - - onButton_colorChanged: shadersettings._background_color= button_color - button_color: shadersettings._background_color; - } - } - } - GroupBox{ - title: qsTr("Lights") - Layout.fillWidth: true - Layout.columnSpan: 2 - anchors.left: parent.left - anchors.right: parent.right - GridLayout{ - Layout.columnSpan: 2 - columns: 2 - rows: 2 - anchors.left: parent.left - anchors.right: parent.right - Text{text: qsTr("Contrast")} - SimpleSlider{ - onValueChanged: shadersettings.contrast = value - value: shadersettings.contrast - } - Text{text: qsTr("Brightness")} - SimpleSlider{ - onValueChanged: shadersettings.brightness = value - value: shadersettings.brightness - } - } - } - GroupBox{ - title: qsTr("Performace") - Layout.fillWidth: true - Layout.columnSpan: 2 - anchors.left: parent.left - anchors.right: parent.right - GridLayout{ - columns: 3 - Layout.columnSpan: 2 - anchors {left: parent.left; right: parent.right} - Text{text: "Animation FPS"} - Slider{ - Layout.fillWidth: true - id: slider - stepSize: 1 - maximumValue: 60 - minimumValue: 0 - onValueChanged: shadersettings.fps = value; - value: shadersettings.fps - } - Text{text: slider.value} - Text{text: "Texture quality"} - Slider{ - Layout.fillWidth: true - id: txtslider - stepSize: 0.01 - maximumValue: 1 - minimumValue: 0 - onValueChanged: shadersettings.window_scaling = value; - value: shadersettings.window_scaling - updateValueWhileDragging: false - } - Text{text: Math.round(txtslider.value * 100) + "%"} - } - } - } + anchors.margins: tabmargins } - - Tab{ - title: qsTr("Eye-candy") + SettingsTerminalTab{ + title: qsTr("Terminal") anchors.fill: parent - anchors.margins: 15 - - ColumnLayout{ - anchors.fill: parent - GroupBox{ - title: qsTr("Rasterization") - anchors.left: parent.left - anchors.right: parent.right - ColumnLayout{ - anchors.left: parent.left - anchors.right: parent.right - RowLayout{ - anchors.left: parent.left - anchors.right: parent.right - ExclusiveGroup { id: rasterizationgroup } - RadioButton { - text: qsTr("No Rasterization") - exclusiveGroup: rasterizationgroup - checked: shadersettings.rasterization === shadersettings.no_rasterization - onCheckedChanged: if(checked) - shadersettings.rasterization = shadersettings.no_rasterization - } - RadioButton { - text: qsTr("Scanlines") - exclusiveGroup: rasterizationgroup - checked: shadersettings.rasterization === shadersettings.scanline_rasterization - onCheckedChanged: if(checked) - shadersettings.rasterization = shadersettings.scanline_rasterization - } - RadioButton { - text: qsTr("Pixels") - exclusiveGroup: rasterizationgroup - checked: shadersettings.rasterization === shadersettings.pixel_rasterization - onCheckedChanged: if(checked) - shadersettings.rasterization = shadersettings.pixel_rasterization - } - } - } - } - GroupBox{ - title: qsTr("Effects") - anchors.left: parent.left - anchors.right: parent.right - ColumnLayout{ - anchors.fill: parent - SettingComponent{ - name: "Bloom" - onValueChanged: shadersettings.bloom_strength = value - _value: shadersettings.bloom_strength - } - SettingComponent{ - name: "Motion Blur" - onValueChanged: shadersettings.motion_blur = value - _value: shadersettings.motion_blur - } - SettingComponent{ - name: "Noise" - onValueChanged: shadersettings.noise_strength = value - _value: shadersettings.noise_strength - } - SettingComponent{ - name: "Glow" - onValueChanged: shadersettings.glowing_line_strength = value; - _value: shadersettings.glowing_line_strength - } - SettingComponent{ - name: "Ambient light" - onValueChanged: shadersettings.ambient_light = value; - _value: shadersettings.ambient_light - } - SettingComponent{ - name: "Screen distortion" - onValueChanged: shadersettings.screen_distortion = value; - _value: shadersettings.screen_distortion; - } - SettingComponent{ - name: "Brightness flickering" - onValueChanged: shadersettings.brightness_flickering= value; - _value: shadersettings.brightness_flickering; - } - SettingComponent{ - name: "Horizontal flickering" - onValueChanged: shadersettings.horizontal_sincronization = value; - _value: shadersettings.horizontal_sincronization; - } - } - } - } + anchors.margins: tabmargins + } + SettingsEffectsTab{ + title: qsTr("Effects") + anchors.fill: parent + anchors.margins: tabmargins } } } diff --git a/app/ShaderManager.qml b/app/ShaderManager.qml index 2c3a413..a61c4eb 100644 --- a/app/ShaderManager.qml +++ b/app/ShaderManager.qml @@ -26,12 +26,15 @@ ShaderEffect { property color background_color: shadersettings.background_color property variant source: terminal.theSource property variant bloomSource: terminal.bloomSource - property variant scanlineSource: terminal.scanlineSource + property variant rasterizationSource: terminal.rasterizationSource + property variant noiseSource: terminal.staticNoiseSource property size txt_Size: Qt.size(frame.sourceRect.width, frame.sourceRect.height) property real bloom: shadersettings.bloom_strength property int rasterization: shadersettings.rasterization + property real jitter: shadersettings.jitter * 0.007 + property real noise_strength: shadersettings.noise_strength property real screen_distorsion: shadersettings.screen_distortion property real glowing_line_strength: shadersettings.glowing_line_strength @@ -51,6 +54,8 @@ ShaderEffect { property real time: timetimer.time property variant randomFunctionSource: randfuncsource + blending: false + function str(num){ return num.toFixed(8); } @@ -96,15 +101,15 @@ ShaderEffect { varying highp vec2 qt_TexCoord0; uniform highp vec4 font_color; - uniform highp vec4 background_color;" + - - (rasterization != shadersettings.no_rasterization ? " - uniform highp sampler2D scanlineSource;" : "") + + uniform highp vec4 background_color; + uniform highp sampler2D rasterizationSource;" + (bloom !== 0 ? " uniform highp sampler2D bloomSource;" : "") + (noise_strength !== 0 ? " uniform highp float noise_strength;" : "") + + (noise_strength !== 0 || jitter !== 0 ? " + uniform lowp sampler2D noiseSource;" : "") + (screen_distorsion !== 0 ? " uniform highp float screen_distorsion;" : "")+ (glowing_line_strength !== 0 ? " @@ -114,22 +119,6 @@ ShaderEffect { (horizontal_sincronization !== 0 ? " varying lowp float horizontal_distortion;" : "") + - " - highp float rand(vec2 co) - { - highp float a = 12.9898; - highp float b = 78.233; - highp float c = 43758.5453; - highp float dt= dot(co.xy ,vec2(a,b)); - highp float sn= mod(dt,3.14); - return fract(sin(sn) * c); - } - - float stepNoise(vec2 p){ - vec2 newP = p * txt_Size * 0.5; - return rand(floor(newP) + fract(time / 100.0)); - }" + - (glowing_line_strength !== 0 ? " float randomPass(vec2 coords){ return fract(smoothstep(-0.2, 0.0, coords.y - 3.0 * fract(time * 0.0001))) * glowing_line_strength; @@ -161,10 +150,17 @@ ShaderEffect { noise += horizontal_distortion;" : "") : "") + - "float color = texture2D(source, coords).r;" + + (jitter !== 0 ? " + vec2 offset = vec2(texture2D(noiseSource, coords + fract(time / 57.0)).a, + texture2D(noiseSource, coords + fract(time / 251.0)).a) - 0.5; + vec2 txt_coords = coords + offset * "+str(jitter)+";" + : "vec2 txt_coords = coords;") + + + "float color = texture2D(source, txt_coords).a;" + (noise_strength !== 0 ? " - color += stepNoise(coords) * noise * (1.0 - distance * distance * 2.0);" : "") + + float noiseVal = texture2D(noiseSource, qt_TexCoord0 + vec2(fract(time / 51.0), fract(time / 237.0))).a; + color += noiseVal * noise * (1.0 - distance * 1.3);" : "") + (glowing_line_strength !== 0 ? " color += randomPass(coords) * glowing_line_strength;" : "") + @@ -174,9 +170,7 @@ ShaderEffect { "vec3 finalColor = mix(background_color, font_color, color).rgb;" + "finalColor = mix(finalColor * 1.1, vec3(0.0), 1.2 * distance * distance);" + - - (rasterization != shadersettings.no_rasterization ? " - finalColor *= texture2D(scanlineSource, coords).r;" : "") + + "finalColor *= texture2D(rasterizationSource, coords).a;" + (brightness_flickering !== 0 ? " finalColor *= brightness;" : "") + diff --git a/app/ShaderSettings.qml b/app/ShaderSettings.qml index 3908e53..dc6b2fe 100644 --- a/app/ShaderSettings.qml +++ b/app/ShaderSettings.qml @@ -25,7 +25,7 @@ Item{ property real ambient_light: 0.2 property real contrast: 0.85 - property real brightness: 0.75 + property real brightness: 0.5 //On resize shows an overlay with the current size property bool show_terminal_size: true @@ -50,18 +50,20 @@ Item{ //Probably there is a better way to cast string to colors. property string _background_color: "#000000" - property string _font_color: "#ff9400" + property string _font_color: "#ff8100" property color font_color: mix(strToColor(_font_color), strToColor(_background_color), 0.7 + (contrast * 0.3)) property color background_color: mix(strToColor(_background_color), strToColor(_font_color), 0.7 + (contrast * 0.3)) property real noise_strength: 0.1 - property real screen_distortion: 0.15 - property real glowing_line_strength: 0.4 - property real motion_blur: 0.65 - property real bloom_strength: 0.6 + property real screen_distortion: 0.1 + property real glowing_line_strength: 0.2 + property real motion_blur: 0.40 + property real bloom_strength: 0.65 - property real horizontal_sincronization: 0.1 - property real brightness_flickering: 0.12 + property real jitter: 0.18 + + property real horizontal_sincronization: 0.08 + property real brightness_flickering: 0.1 readonly property int no_rasterization: 0 readonly property int scanline_rasterization: 1 @@ -69,46 +71,6 @@ Item{ property int rasterization: no_rasterization - property string frame_source: frames_list.get(frames_index).source - property int frames_index: 1 - property var frames_list: framelist - - signal terminalFontChanged - - property var _font_scalings: [0.5, 0.75, 1.0, 1.25, 1.50, 1.75, 2.0] - property var font: currentfont - property int font_index: 0 - property var fonts_list: fontlist - - property bool frame_reflections: true - property real frame_reflection_strength: ((frame_reflections && framelist.get(frames_index).reflections) ? 1.0 : 0.0) * 0.15 - - property alias profiles_list: profileslist - property int profiles_index: 0 - onProfiles_indexChanged: loadProfile(profiles_index); - - onFont_indexChanged: handleFontChanged(); - onFont_scaling_indexChanged: handleFontChanged(); - - function handleFontChanged(){ - var f = fontlist.get(font_index); - var metrics = f.metrics.get(font_scaling_index); - currentfont.source = f.source; - currentfont.pixelSize = metrics.pixelSize; - currentfont.lineSpacing = f.lineSpacing; - currentfont.virtualResolution = Qt.size(metrics.virtualWidth, - metrics.virtualHeight); - terminalFontChanged(); - } - - FontLoader{ - property int pixelSize - property real lineSpacing - property size virtualResolution - id: currentfont - source: fontlist.get(font_index).source - } - ListModel{ id: framelist ListElement{text: "No frame"; source: "./frames/NoFrame.qml"; reflections: false} @@ -116,102 +78,53 @@ Item{ ListElement{text: "Rough black frame"; source: "./frames/BlackRoughFrame.qml"; reflections: true} } - property int font_scaling_index: 0 - ListModel{ - id: fontlist - ListElement{ - text: "Terminus (Modern)" - source: "fonts/modern-terminus/TerminusTTF-Bold-4.38.2.ttf" - lineSpacing: 2 - metrics: [ - ListElement{pixelSize: 18; virtualWidth: 0; virtualHeight: 6}, - ListElement{pixelSize: 24; virtualWidth: 0; virtualHeight: 8}, - ListElement{pixelSize: 35; virtualWidth: 5; virtualHeight: 12}, - ListElement{pixelSize: 43; virtualWidth: 6; virtualHeight: 11}, - ListElement{pixelSize: 54; virtualWidth: 7; virtualHeight: 11}, - ListElement{pixelSize: 64; virtualWidth: 8; virtualHeight: 11}, - ListElement{pixelSize: 75; virtualWidth: 8; virtualHeight: 11}] - } - ListElement{ - text: "Commodore PET (1977)" - source: "fonts/1977-commodore-pet/COMMODORE_PET.ttf" - lineSpacing: 2 - metrics: [ - ListElement{pixelSize: 11; virtualWidth: 0; virtualHeight: 0}, - ListElement{pixelSize: 17; virtualWidth: 0; virtualHeight: 6}, - ListElement{pixelSize: 24; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 32; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 40; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 48; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 56; virtualWidth: 8; virtualHeight: 8}] - } - ListElement{ - text: "Apple ][ (1977)" - source: "fonts/1977-apple2/PrintChar21.ttf" - lineSpacing: 2 - metrics: [ - ListElement{pixelSize: 11; virtualWidth: 0; virtualHeight: 0}, - ListElement{pixelSize: 17; virtualWidth: 0; virtualHeight: 6}, - ListElement{pixelSize: 24; virtualWidth: 7; virtualHeight: 8}, - ListElement{pixelSize: 32; virtualWidth: 7; virtualHeight: 8}, - ListElement{pixelSize: 40; virtualWidth: 7; virtualHeight: 8}, - ListElement{pixelSize: 48; virtualWidth: 7; virtualHeight: 8}, - ListElement{pixelSize: 56; virtualWidth: 7; virtualHeight: 8}] - } - ListElement{ - text: "Atari 400-800 (1979)" - source: "fonts/1979-atari-400-800/ATARI400800_original.TTF" - lineSpacing: 3 - metrics: [ - ListElement{pixelSize: 11; virtualWidth: 0; virtualHeight: 0}, - ListElement{pixelSize: 17; virtualWidth: 0; virtualHeight: 6}, - ListElement{pixelSize: 24; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 32; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 40; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 48; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 56; virtualWidth: 8; virtualHeight: 8}] - } - ListElement{ - text: "Commodore 64 (1982)" - source: "fonts/1982-commodore64/C64_User_Mono_v1.0-STYLE.ttf" - lineSpacing: 3 - metrics: [ - ListElement{pixelSize: 11; virtualWidth: 0; virtualHeight: 0}, - ListElement{pixelSize: 17; virtualWidth: 0; virtualHeight: 6}, - ListElement{pixelSize: 24; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 32; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 40; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 48; virtualWidth: 8; virtualHeight: 8}, - ListElement{pixelSize: 56; virtualWidth: 8; virtualHeight: 8}] - } - ListElement{ - text: "Atari ST (1985)" - source: "fonts/1985-atari-st/AtariST8x16SystemFont.ttf" - lineSpacing: 2 - metrics: [ - ListElement{pixelSize: 16; virtualWidth: 0; virtualHeight: 0}, - ListElement{pixelSize: 23; virtualWidth: 0; virtualHeight: 7}, - ListElement{pixelSize: 32; virtualWidth: 4; virtualHeight: 8}, - ListElement{pixelSize: 40; virtualWidth: 4; virtualHeight: 8}, - ListElement{pixelSize: 48; virtualWidth: 4; virtualHeight: 8}, - ListElement{pixelSize: 56; virtualWidth: 4; virtualHeight: 8}, - ListElement{pixelSize: 64; virtualWidth: 8; virtualHeight: 16}] - } - ListElement{ - text: "IBM DOS (1985)" - source: "fonts/1985-ibm-pc-vga/Perfect DOS VGA 437.ttf" - lineSpacing: 2 - metrics: [ - ListElement{pixelSize: 18; virtualWidth: 0; virtualHeight: 0}, - ListElement{pixelSize: 25; virtualWidth: 0; virtualHeight: 0}, - ListElement{pixelSize: 32; virtualWidth: 6; virtualHeight: 8}, - ListElement{pixelSize: 36; virtualWidth: 6; virtualHeight: 12}, - ListElement{pixelSize: 48; virtualWidth: 9; virtualHeight: 16}, - ListElement{pixelSize: 56; virtualWidth: 9; virtualHeight: 16}, - ListElement{pixelSize: 64; virtualWidth: 9; virtualHeight: 16}] - } + property string frame_source: frames_list.get(frames_index).source + property int frames_index: 1 + property var frames_list: framelist + + + signal terminalFontChanged(string fontSource, int pixelSize, int lineSpacing, size virtualCharSize) + + Loader{ + id: fontManager + + states: [ + State { when: rasterization == no_rasterization + PropertyChanges {target: fontManager; source: "Fonts.qml" } }, + State { when: rasterization == scanline_rasterization + PropertyChanges {target: fontManager; source: "FontScanlines.qml" } }, + State { when: rasterization == pixel_rasterization; + PropertyChanges {target: fontManager; source: "FontPixels.qml" } } + ] + + onLoaded: handleFontChanged() } + property var fontlist: fontManager.item.fontlist + property var fontScalingList: fontManager.item.fontScalingList + + property var fontIndexes: [0,0,0] + property var fontScalingIndexes: [5,1,1] + + function handleFontChanged(){ + if(!fontManager.item) return; + fontManager.item.selectedFontIndex = fontIndexes[rasterization]; + fontManager.item.selectedScalingIndex = fontScalingIndexes[rasterization]; + + var fontSource = fontManager.item.source; + var pixelSize = fontManager.item.pixelSize; + var lineSpacing = fontManager.item.lineSpacing; + var virtualCharSize = fontManager.item.virtualCharSize; + + terminalFontChanged(fontSource, pixelSize, lineSpacing, virtualCharSize); + } + + property bool frame_reflections: true + property real frame_reflection_strength: ((frame_reflections && framelist.get(frames_index).reflections) ? 1.0 : 0.0) * 0.15 + + property alias profiles_list: profileslist + property int profiles_index: 0 + Storage{id: storage} function composeSettingsString(){ @@ -222,7 +135,8 @@ Item{ brightness: brightness, contrast: contrast, ambient_light: ambient_light, - font_scaling_index: font_scaling_index, + fontScalingIndexes: fontScalingIndexes, + fontIndexes: fontIndexes } return JSON.stringify(settings); } @@ -237,10 +151,11 @@ Item{ screen_distortion: screen_distortion, glowing_line_strength: glowing_line_strength, frames_index: frames_index, - font_index: font_index, motion_blur: motion_blur, bloom_strength: bloom_strength, - rasterization: rasterization + rasterization: rasterization, + jitter: jitter, + fontIndex: fontIndexes[rasterization] } return JSON.stringify(settings); } @@ -265,7 +180,8 @@ Item{ storage.setSetting("_CURRENT_SETTINGS", settingsString); storage.setSetting("_CURRENT_PROFILE", profileString); - console.log("Storing settings :" + settingsString + profileString); + console.log("Storing settings: " + settingsString); + console.log("Storing profile: " + profileString); } function loadSettingsString(settingsString){ @@ -276,12 +192,13 @@ Item{ contrast = settings.contrast !== undefined ? settings.contrast : contrast; brightness = settings.brightness !== undefined ? settings.brightness : brightness - show_terminal_size = settings.show_terminal_size ? settings.show_terminal_size : show_terminal_size + show_terminal_size = settings.show_terminal_size !== undefined ? settings.show_terminal_size : show_terminal_size fps = settings.fps !== undefined ? settings.fps: fps - window_scaling = settings.window_scaling ? settings.window_scaling : window_scaling + window_scaling = settings.window_scaling !== undefined ? settings.window_scaling : window_scaling - font_scaling_index = settings.font_scaling_index !== undefined ? settings.font_scaling_index: font_scaling_index; + fontIndexes = settings.fontIndexes !== undefined ? settings.fontIndexes : fontIndexes + fontScalingIndexes = settings.fontScalingIndexes !== undefined ? settings.fontScalingIndexes : fontScalingIndexes } function loadProfileString(profileString){ @@ -301,9 +218,11 @@ Item{ frames_index = settings.frames_index !== undefined ? settings.frames_index : frames_index; - font_index = settings.font_index !== undefined ? settings.font_index : font_index; - rasterization = settings.rasterization !== undefined ? settings.rasterization : rasterization; + + jitter = settings.jitter !== undefined ? settings.jitter : jitter; + + fontIndexes[rasterization] = settings.fontIndex !== undefined ? settings.fontIndex : fontIndexes[rasterization]; } function storeCustomProfiles(){ @@ -335,6 +254,10 @@ Item{ return JSON.stringify(customProfiles); } + function loadCurrentProfile(){ + loadProfile(profiles_index); + } + function loadProfile(index){ var profile = profileslist.get(index); loadProfileString(profile.obj_string); @@ -358,18 +281,38 @@ Item{ ListModel{ id: profileslist ListElement{ - text: "Default" - obj_string: '{"background_color":"#000000","bloom_strength":0.6,"brightness_flickering":0.12,"font_color":"#ff9400","font_index":0,"frames_index":1,"glowing_line_strength":0.4,"horizontal_sincronization":0.1,"motion_blur":0.65,"noise_strength":0.1,"rasterization":1,"screen_distortion":0.15}' + text: "Default Amber" + obj_string: '{"background_color":"#000000","bloom_strength":0.65,"brightness_flickering":0.1,"fontIndex":0,"font_color":"#ff8100","frames_index":1,"glowing_line_strength":0.2,"horizontal_sincronization":0.08,"jitter":0.18,"motion_blur":0.45,"noise_strength":0.1,"rasterization":0,"screen_distortion":0.1}' builtin: true } ListElement{ - text: "Commodore 64" - obj_string: '{"ambient_light":0.2,"background_color":"#5048b2","font_color":"#8bcad1","font_index":2,"font_scaling":1,"frames_index":1,"glowing_line_strength":0.2,"noise_strength":0.05,"scanlines":0.0,"screen_distortion":0.1,"brightness_flickering":0.03}' + text: "Default Green" + obj_string: '{"background_color":"#000000","bloom_strength":0.4,"brightness_flickering":0.1,"fontIndex":0,"font_color":"#0ccc68","frames_index":1,"glowing_line_strength":0.2,"horizontal_sincronization":0.08,"jitter":0.18,"motion_blur":0.45,"noise_strength":0.1,"rasterization":0,"screen_distortion":0.1}' + builtin: true + } + ListElement{ + text: "Default Scanlines" + obj_string: '{"background_color":"#000000","bloom_strength":0.4,"brightness_flickering":0.1,"fontIndex":0,"font_color":"#00ff5b","frames_index":1,"glowing_line_strength":0.2,"horizontal_sincronization":0.07,"jitter":0.11,"motion_blur":0.4,"noise_strength":0.05,"rasterization":1,"screen_distortion":0.1}' + builtin: true + } + ListElement{ + text: "Default Pixelated" + obj_string: '{"background_color":"#000000","bloom_strength":0.65,"brightness_flickering":0.1,"fontIndex":0,"font_color":"#ff8100","frames_index":1,"glowing_line_strength":0.2,"horizontal_sincronization":0.1,"jitter":0,"motion_blur":0.45,"noise_strength":0.14,"rasterization":2,"screen_distortion":0.05}' + builtin: true + } + ListElement{ + text: "Apple ][" + obj_string: '{"background_color":"#000000","bloom_strength":0.5,"brightness_flickering":0.2,"fontIndex":2,"font_color":"#2fff91","frames_index":1,"glowing_line_strength":0.22,"horizontal_sincronization":0.08,"jitter":0.1,"motion_blur":0.65,"noise_strength":0.08,"rasterization":1,"screen_distortion":0.18}' + builtin: true + } + ListElement{ + text: "Vintage" + obj_string: '{"background_color":"#000000","bloom_strength":0.4,"brightness_flickering":0.54,"fontIndex":0,"font_color":"#00ff3e","frames_index":2,"glowing_line_strength":0.3,"horizontal_sincronization":0.2,"jitter":0.4,"motion_blur":0.75,"noise_strength":0.2,"rasterization":1,"screen_distortion":0.1}' builtin: true } ListElement{ text: "IBM Dos" - obj_string: '{"ambient_light":0.4,"background_color":"#000000","font_color":"#ffffff","font_index":3,"font_scaling":1,"frames_index":1,"glowing_line_strength":0,"noise_strength":0,"scanlines":0.0,"screen_distortion":0.05,"brightness_flickering":0.00}' + obj_string: '{"background_color":"#000000","bloom_strength":0.4,"brightness_flickering":0.07,"fontIndex":7,"font_color":"#ffffff","frames_index":1,"glowing_line_strength":0.13,"horizontal_sincronization":0,"jitter":0.08,"motion_blur":0.3,"noise_strength":0.03,"rasterization":0,"screen_distortion":0.1}' builtin: true } } diff --git a/app/SimpleSlider.qml b/app/SimpleSlider.qml index cabc9d8..f362e06 100644 --- a/app/SimpleSlider.qml +++ b/app/SimpleSlider.qml @@ -23,21 +23,28 @@ import QtQuick.Controls 1.1 import QtQuick.Layouts 1.1 RowLayout { - property string name - property double value: 0.0 - property double stepSize: 0.01 + property alias value: slider.value + property alias stepSize: slider.stepSize + property alias minimumValue: slider.minimumValue + property alias maximumValue: slider.maximumValue + property real maxMultiplier: 100 id: setting_component spacing: 10 Slider{ id: slider stepSize: parent.stepSize - onValueChanged: setting_component.value = slider.value; Layout.fillWidth: true - value: setting_component.value } Text{ id: textfield - text: Math.round(value * 100) + "%" + text: formatNumber(Math.round(value * maxMultiplier)) + } + function formatNumber(num) { + var n = "" + num; + while (n.length < 3) { + n = " " + n; + } + return n + "%"; } } diff --git a/app/Terminal.qml b/app/Terminal.qml index fb6a7ad..8e5d572 100644 --- a/app/Terminal.qml +++ b/app/Terminal.qml @@ -28,7 +28,14 @@ Item{ id: terminalContainer property variant theSource: finalSource property variant bloomSource: bloomSourceLoader.item - property variant scanlineSource: scanlineSourceLoader.item + property variant rasterizationSource: rasterizationEffectSource + property variant staticNoiseSource: staticNoiseSource + + property alias kterminal: kterminal + + signal sizeChanged + onWidthChanged: sizeChanged() + onHeightChanged: sizeChanged() //The blur effect has to take into account the framerate property real fpsAttenuation: 60 / shadersettings.fps @@ -37,9 +44,8 @@ Item{ property real _minBlurCoefficient: 0.75 property real _maxBlurCoefficient: 0.95 - property real scanlineWidth: 1 - property real scanlineHeight: 1 - property size virtual_resolution: Qt.size(width / scanlineWidth, height / scanlineHeight) + property size virtualPxSize: Qt.size(1,1) + property size virtual_resolution: Qt.size(width / virtualPxSize.width, height / virtualPxSize.height) property real deltay: 0.5 / virtual_resolution.height property real deltax: 0.5 / virtual_resolution.width @@ -50,8 +56,6 @@ Item{ property size terminalSize: kterminal.terminalSize property size paintedTextSize - onPaintedTextSizeChanged: console.log(paintedTextSize) - //Force reload of the blursource when settings change onMBlurChanged: restartBlurredSource() @@ -67,12 +71,9 @@ Item{ kterminal.copyClipboard(); } - KTerminal { id: kterminal anchors.fill: parent - font.pixelSize: shadersettings.font.pixelSize - font.family: shadersettings.font.name colorScheme: "MyWhiteOnBlack" @@ -85,38 +86,38 @@ Item{ } } + FontLoader{ id: fontLoader } Text{id: fontMetrics; text: "B"; visible: false} - function handleFontChange(){ - var scaling_factor = shadersettings.window_scaling; - var font_size = shadersettings.font.pixelSize * scaling_factor; - font.pixelSize = font_size; - font.family = shadersettings.font.name; + function getPaintedSize(pixelSize){ + fontMetrics.font.family = fontLoader.name; + fontMetrics.font.pixelSize = pixelSize; + return Qt.size(fontMetrics.paintedWidth, fontMetrics.paintedHeight); + } + function isValid(size){ + return size.width >= 0 && size.height >= 0; + } - fontMetrics.font = font; + function handleFontChange(fontSource, pixelSize, lineSpacing, virtualCharSize){ + fontLoader.source = fontSource; + font.pixelSize = pixelSize * shadersettings.window_scaling; + font.family = fontLoader.name; - var vertical_density = shadersettings.font.virtualResolution.height; - var horizontal_density = shadersettings.font.virtualResolution.width; + var paintedSize = getPaintedSize(pixelSize); + var charSize = isValid(virtualCharSize) + ? virtualCharSize + : Qt.size(paintedSize.width / 2, paintedSize.height / 2); - var scanline_height = fontMetrics.paintedHeight / vertical_density; - var scanline_width = fontMetrics.paintedWidth / horizontal_density; + var virtualPxSize = Qt.size(paintedSize.width / charSize.width, + paintedSize.height / charSize.height) - var scanline_spacing = shadersettings.font.lineSpacing; - var line_spacing = Math.round(scanline_spacing * scanline_height); + terminalContainer.virtualPxSize = virtualPxSize; -// console.log("Font height: " + fontMetrics.paintedHeight) -// console.log("Scanline Height: " + scanline_height) -// console.log("Line Spacing: " + line_spacing) - - terminalContainer.scanlineHeight = scanline_height; - terminalContainer.scanlineWidth = scanline_width; - - setLineSpacing(line_spacing); + setLineSpacing(lineSpacing); restartBlurredSource(); } Component.onCompleted: { shadersettings.terminalFontChanged.connect(handleFontChange); - handleFontChange(); forceActiveFocus(); } } @@ -161,10 +162,19 @@ Item{ } } + //Frame displacement properties + property real dtop: frame.item.displacementTop + property real dleft:frame.item.displacementLeft + property real dright: frame.item.displacementRight + property real dbottom: frame.item.displacementBottom + function correctDistortion(x, y){ x = x / width; y = y / height; + x = (-dleft + x * (width + dleft + dright)) / width + y = (-dtop + y * (height + dtop + dbottom)) / height + var cc = Qt.size(0.5 - x, 0.5 - y); var distortion = (cc.height * cc.height + cc.width * cc.width) * shadersettings.screen_distortion; @@ -203,6 +213,7 @@ Item{ id: finalSource sourceItem: blurredterminal sourceRect: frame.sourceRect + format: ShaderEffectSource.Alpha } ShaderEffect { id: blurredterminal @@ -212,7 +223,7 @@ Item{ property size virtual_resolution: parent.virtual_resolution property size delta: Qt.size((mScanlines == shadersettings.pixel_rasterization ? deltax : 0), mScanlines != shadersettings.no_rasterization ? deltay : 0) - z: 2 + blending: false fragmentShader: "uniform lowp float qt_Opacity;" + @@ -234,16 +245,16 @@ Item{ (mScanlines == shadersettings.pixel_rasterization ? " coords.x = floor(virtual_resolution.x * coords.x) / virtual_resolution.x;" : "") : "") + - - "float color = texture2D(source, coords + delta).r * 256.0;" + + "coords = coords + delta;" + + "float color = texture2D(source, coords).r * 256.0;" + (mBlur !== 0 ? - "float blurredSourceColor = texture2D(blurredSource, qt_TexCoord0).r * 256.0;" + + "float blurredSourceColor = texture2D(blurredSource, coords).a * 256.0;" + "blurredSourceColor = blurredSourceColor - blurredSourceColor * " + (1.0 - motionBlurCoefficient) * fpsAttenuation+ ";" + "color = step(1.0, color) * color + step(color, 1.0) * blurredSourceColor;" : "") + - "gl_FragColor = vec4(vec3(floor(color) / 256.0), 1.0);" + + "gl_FragColor.a = floor(color) / 256.0;" + "}" } ////////////////////////////////////////////////////////////////////// @@ -271,40 +282,89 @@ Item{ smooth: false } } - //Scanlines - Loader{ - id: scanlineEffectLoader - active: mScanlines != shadersettings.no_rasterization + + //Rasterization mask + ShaderEffect { + id: staticNoiseEffect anchors.fill: parent - sourceComponent: ShaderEffect { - property size virtual_resolution: terminalContainer.virtual_resolution + property size virtual_resolution: terminalContainer.virtual_resolution - fragmentShader: - "uniform lowp float qt_Opacity;" + + blending: false - "varying highp vec2 qt_TexCoord0; + fragmentShader: + "uniform lowp float qt_Opacity; + varying highp vec2 qt_TexCoord0; + uniform highp vec2 virtual_resolution;" + + + "highp float noise(vec2 co) + { + highp float a = 12.9898; + highp float b = 78.233; + highp float c = 43758.5453; + highp float dt= dot(co.xy ,vec2(a,b)); + highp float sn= mod(dt,3.14); + return fract(sin(sn) * c); + } + + vec2 sw(vec2 p) {return vec2( floor(p.x) , floor(p.y) );} + vec2 se(vec2 p) {return vec2( ceil(p.x) , floor(p.y) );} + vec2 nw(vec2 p) {return vec2( floor(p.x) , ceil(p.y) );} + vec2 ne(vec2 p) {return vec2( ceil(p.x) , ceil(p.y) );} + + float smoothNoise(vec2 p) { + vec2 inter = smoothstep(0., 1., fract(p)); + float s = mix(noise(sw(p)), noise(se(p)), inter.x); + float n = mix(noise(nw(p)), noise(ne(p)), inter.x); + return mix(s, n, inter.y); + }" + + + "void main() {" + + "gl_FragColor.a = smoothNoise(qt_TexCoord0 * virtual_resolution);" + + "}" + } + ShaderEffectSource{ + id: staticNoiseSource + sourceItem: staticNoiseEffect + textureSize: Qt.size(parent.width, parent.height) + wrapMode: ShaderEffectSource.Repeat + smooth: true + hideSource: true + format: ShaderEffectSource.Alpha + } + + //Rasterization mask + ShaderEffect { + id: rasterizationEffect + anchors.fill: parent + property size virtual_resolution: terminalContainer.virtual_resolution + + blending: false + + fragmentShader: + "uniform lowp float qt_Opacity;" + + + "varying highp vec2 qt_TexCoord0; uniform highp vec2 virtual_resolution; float getScanlineIntensity(vec2 coords) { - float result = abs(sin(coords.y * virtual_resolution.y * "+Math.PI+"));" + - (mScanlines == shadersettings.pixel_rasterization ? - "result *= abs(sin(coords.x * virtual_resolution.x * "+Math.PI+"));" : "") + " + float result = 1.0;" + + (mScanlines != shadersettings.no_rasterization ? + "result *= abs(sin(coords.y * virtual_resolution.y * "+Math.PI+"));" : "") + + (mScanlines == shadersettings.pixel_rasterization ? + "result *= abs(sin(coords.x * virtual_resolution.x * "+Math.PI+"));" : "") + " return result; }" + - "void main() {" + - "gl_FragColor = vec4(getScanlineIntensity(qt_TexCoord0));" + - "}" - } + "void main() {" + + "gl_FragColor.a = getScanlineIntensity(qt_TexCoord0);" + + "}" } - Loader{ - id: scanlineSourceLoader - active: mScanlines != shadersettings.no_rasterization - sourceComponent: ShaderEffectSource{ - sourceItem: scanlineEffectLoader.item - sourceRect: frame.sourceRect - hideSource: true - smooth: true - } + ShaderEffectSource{ + id: rasterizationEffectSource + sourceItem: rasterizationEffect + sourceRect: frame.sourceRect + hideSource: true + smooth: true + format: ShaderEffectSource.Alpha } } diff --git a/app/app.qmlproject.user b/app/app.qmlproject.user index 8ca1b8a..24e654f 100644 --- a/app/app.qmlproject.user +++ b/app/app.qmlproject.user @@ -1,6 +1,6 @@ - + ProjectExplorer.Project.ActiveTarget diff --git a/app/main.qml b/app/main.qml index 41d49d7..8b6ed88 100644 --- a/app/main.qml +++ b/app/main.qml @@ -159,4 +159,5 @@ ApplicationWindow{ terminalSize: terminal.terminalSize } } + Component.onCompleted: shadersettings.handleFontChanged(); } diff --git a/konsole-qml-plugin/src/TerminalDisplay.cpp b/konsole-qml-plugin/src/TerminalDisplay.cpp index ae5391a..e350b8c 100644 --- a/konsole-qml-plugin/src/TerminalDisplay.cpp +++ b/konsole-qml-plugin/src/TerminalDisplay.cpp @@ -416,6 +416,9 @@ void KTerminalDisplay::setVTFont(const QFont& f) // Disabling kerning saves some computation when rendering text. font.setKerning(false); + // Konsole cannot handle non-integer font metrics + font.setStyleStrategy(QFont::StyleStrategy(font.styleStrategy() | QFont::ForceIntegerMetrics)); + //QWidget::setFont(font); m_font = font; fontChange(font);