You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

566 lines
21 KiB

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import NERvGear 1.0 as NVG
import NERvGear.Controls 1.0
import NERvGear.Templates 1.0 as T
import NERvGear.Preferences 1.0 as P
WidgetTemplate {
id: widget
title: qsTr("Ordinal Scale Top UI widget")
editing: styleDialog.active
version: "1.0.1"
defaultValues: {
"Curve": "true",
"Line Color": "#fffcf9",
"Line Width": 38,
"Shadow Color": "#e0e0e0",
"Shadow Size": 0.5,
"Battle UI": false,
"Circle Color": "#fffcf9",
"Clock Visible": true,
"Full Clock": true,
"Font Color": "#f5f5f5",
"Font Size": 44,
"Font Name": 0,
"Font Weight": 0,
"Text Vertical Offset": 16
}
onUpdated: {
widget.settings.styles = Object.assign(defaultValues, widget.settings.styles);
}
onConfigsChanged: {
line.requestPaint();
c0.requestPaint();
c1.requestPaint();
c2.requestPaint();
c3.requestPaint();
c4.requestPaint();
c5.requestPaint();
}
readonly property var configs: widget.settings.styles
property real thour: 0
property real t12hour: 0
property real tmin: -1
readonly property var fonts: Qt.fontFamilies()
readonly property var fontweight: [Font.Light, Font.Normal, Font.Bold]
readonly property var sfontweight: [qsTr("Light"), qsTr("Normal"), qsTr("Bold")]
readonly property real size: 155
readonly property real h: Math.min(widget.width, widget.height)
readonly property real w: widget.width
readonly property real r: (w**2+h**2)/4/h
action: T.Action {
id: thiz
title: qsTr("Top Line Action")
description: title
execute: function () {
return new Promise(function (resolve, reject) {
if (!styleDialog.active) {
let cfg = widget.settings.styles;
cfg["Battle UI"] = !cfg["Battle UI"];
widget.settings.styles = cfg;
}
resolve();
});
}
preference: P.SelectPreference {
label: qsTr("Command")
model: [ qsTr("Toggle UI") ]
defaultValue: 0
load: function () {}
save: function () {}
}
}
Timer {
interval: 250
running: text_clock.visible
repeat: true
onTriggered: {
var now = new Date();
if (tmin !== now.getMinutes()) {
tmin = now.getMinutes();
thour = now.getHours();
t12hour = thour > 12 ? thour - 12 : thour;
}
}
}
Text {
id: text_clock
anchors.top: parent.top
anchors.topMargin: widget.height/200*configs["Text Vertical Offset"]
anchors.horizontalCenter: parent.horizontalCenter
style: Text.Outline
styleColor: "transparent"
color: configs["Font Color"]
text: configs["Full Clock"] ? ("0"+thour).slice(-2) + ":" + ("0"+tmin).slice(-2) : ("0"+t12hour).slice(-2) + ":" + ("0"+tmin).slice(-2)
font.pointSize: widget.height/200*configs["Font Size"]
font.family: fonts[configs["Font Name"]]
font.weight: fontweight[configs["Font Weight"]]
visible: widget.NVG.View.exposed && !configs["Battle UI"] && configs["Clock Visible"]
}
Item {
id: circle
anchors.centerIn: parent
anchors.verticalCenterOffset: -2.5
scale: widget.height/size/1.25
visible: widget.NVG.View.exposed && configs["Battle UI"]
Canvas {
id: c1
anchors.centerIn: parent
width: size
height: size
contextType: "2d"
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.04 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.38-configs["Shadow Size"]/2, -Math.PI/6, -Math.PI/6+Math.PI*2/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
rotation: -140
SequentialAnimation on rotation {
running: circle.visible
loops: Animation.Infinite
RotationAnimation {
duration: 1250
easing.type: Easing.InOutCubic
from: -140
to: 220
}
RotationAnimation {
duration: 1250
easing.type: Easing.InOutCubic
from: 220
to: -140
direction: RotationAnimation.Counterclockwise
}
}
}
Canvas {
id: c2
anchors.centerIn: parent
width: size
height: size
contextType: "2d"
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.08 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.30-configs["Shadow Size"]/2, -Math.PI/6, -Math.PI/24+Math.PI*2/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
rotation: 20
NumberAnimation on rotation {
duration: 2800
easing.type: Easing.Linear
from: 20
to: 380
loops: Animation.Infinite
running: circle.visible
}
}
Canvas {
id: c3
anchors.centerIn: parent
width: size
height: size
contextType: "2d"
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.03 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.23-configs["Shadow Size"]/2, -Math.PI/6, Math.PI/12+Math.PI*2/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
rotation: 90
NumberAnimation on rotation {
duration: 2000
easing.type: Easing.Linear
from: 90
to: -270
loops: Animation.Infinite
running: circle.visible
}
}
Canvas {
id: c4
anchors.centerIn: parent
width: size
height: size
contextType: "2d"
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.06 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.17-configs["Shadow Size"]/2, -Math.PI/6, Math.PI/4+Math.PI*2/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
rotation: -70
SequentialAnimation on rotation {
running: circle.visible
loops: Animation.Infinite
RotationAnimation {
duration: 1150
easing.type: Easing.InOutCubic
from: -70
to: 290
}
RotationAnimation {
duration: 1150
easing.type: Easing.InOutCubic
from: 290
to: -70
direction: RotationAnimation.Counterclockwise
}
}
}
Canvas {
id: c5
anchors.centerIn: parent
width: size
height: size
contextType: "2d"
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.1 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.05-configs["Shadow Size"]/2, 0, -Math.PI*2 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
}
Canvas {
id: c0
anchors.centerIn: parent
width: size
height: size
contextType: "2d"
onPaint: {
context.reset();
context.clearRect(0,0,size,size);
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = size*0.16 - configs["Shadow Size"];
context.beginPath();
context.arc(size/2, size/2, size*0.38-configs["Shadow Size"]/2, 0, -Math.PI/3 , true);
context.strokeStyle = configs["Circle Color"];
context.stroke();
}
NumberAnimation on rotation {
duration: 1500
easing.type: Easing.Linear
from: 0
to: 360
loops: Animation.Infinite
running: circle.visible
}
}
}
Canvas {
id: line
anchors.centerIn: parent
width: widget.width
height: widget.height
contextType: "2d"
onPaint: {
context.reset();
context.clearRect(0,0,width,height);
context.shadowBlur = configs["Shadow Size"];
context.shadowColor = configs["Shadow Color"];
context.lineWidth = Math.max(0.08*configs["Line Width"], 0.1);
context.strokeStyle = configs["Line Color"];
let deg = Math.asin(w/2/r)*0.95;
context.beginPath();
if (configs["Curve"]) {
if (circle.visible) {
context.arc(w/2, -r+h/2, r, deg+Math.PI/2, Math.PI/2+circle.scale*size/1.22/r, true);
context.stroke();
context.beginPath();
context.arc(w/2, -r+h/2, r, -deg+Math.PI/2, Math.PI/2-circle.scale*size/1.22/r, false);
context.stroke();
} else {
context.arc(w/2, -r+h/2, r, deg+Math.PI/2, -deg+Math.PI/2, true);
context.stroke();
}
} else {
if (circle.visible) {
context.moveTo(0, height/2);
context.lineTo(width/2-circle.scale*size/1.22, height/2);
context.stroke();
context.beginPath();
context.moveTo(width/2+circle.scale*size/1.22, height/2);
context.lineTo(width, height/2);
context.stroke();
} else {
context.moveTo(0, height/2);
context.lineTo(width, height/2);
context.stroke();
}
}
}
}
menu: Menu {
Action {
text: qsTr("Settings") + "..."
onTriggered: styleDialog.active = true
}
}
Loader {
id: styleDialog
active: false
sourceComponent: NVG.Window {
id: window
title: qsTr("Settings")
visible: true
minimumWidth: 380
minimumHeight: 500
width: minimumWidth
height: minimumHeight
transientParent: widget.NVG.View.window
property var configuration
Page {
id: cfg_page
anchors.fill: parent
header: TitleBar {
text: qsTr("UI Settings")
standardButtons: Dialog.Save | Dialog.Reset
onAccepted: {
configuration = rootPreference.save();
widget.settings.styles = configuration;
styleDialog.active = false;
}
onReset: {
rootPreference.load();
let cfg = rootPreference.save();
widget.settings.styles = cfg;
}
}
ColumnLayout {
id: root
anchors.fill: parent
anchors.margins: 16
anchors.topMargin: 0
Flickable {
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
contentWidth: preferenceLayout.implicitWidth
contentHeight: preferenceLayout.implicitHeight
ColumnLayout {
id: preferenceLayout
width: root.width
P.PreferenceGroup {
id: rootPreference
Layout.fillWidth: true
label: qsTr("Configuration")
onPreferenceEdited: {
widget.settings.styles = rootPreference.save();
}
P.SwitchPreference {
name: "Curve"
label: qsTr("Curve")
defaultValue: defaultValues["Curve"]
}
P.ColorPreference {
name: "Line Color"
label: qsTr("Line Color")
defaultValue: defaultValues["Line Color"]
}
P.SliderPreference {
name: "Line Width"
label: qsTr("Line Width")
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Line Width"]
displayValue: value + "%"
}
P.ColorPreference {
name: "Shadow Color"
label: qsTr("Shadow Color")
defaultValue: defaultValues["Shadow Color"]
}
P.SliderPreference {
name: "Shadow Size"
label: qsTr("Shadow Size")
from: 0
to: 3
stepSize: 0.1
defaultValue: defaultValues["Shadow Size"]
displayValue: Math.round(value*10)/10 + "px"
}
P.Separator {}
P.SwitchPreference {
id: _cfg_battle_ui
name: "Battle UI"
label: qsTr("Battle UI")
defaultValue: defaultValues["Battle UI"]
}
P.ColorPreference {
name: "Circle Color"
label: qsTr("Circle Color")
visible: _cfg_battle_ui.value
defaultValue: defaultValues["Circle Color"]
}
P.Separator {}
P.SwitchPreference {
id: _cfg_clock_visible
name: "Clock Visible"
label: qsTr("Clock Visible")
visible: !_cfg_battle_ui.value
enabled: visible
defaultValue: defaultValues["Clock Visible"]
}
P.SwitchPreference {
name: "Full Clock"
label: qsTr("24 Hour Clock")
visible: !_cfg_battle_ui.value
enabled: visible && _cfg_clock_visible.value
defaultValue: defaultValues["Full Clock"]
}
P.ColorPreference {
name: "Font Color"
label: qsTr("Font Color")
visible: !_cfg_battle_ui.value
enabled: visible && _cfg_clock_visible.value
defaultValue: defaultValues["Font Color"]
}
P.SliderPreference {
name: "Font Size"
label: qsTr("Font Size")
visible: !_cfg_battle_ui.value
enabled: visible && _cfg_clock_visible.value
from: 1
to: 100
stepSize: 1
defaultValue: defaultValues["Font Size"]
displayValue: value + "%"
}
P.SelectPreference {
name: "Font Name"
label: qsTr("Font Style")
visible: !_cfg_battle_ui.value
enabled: visible && _cfg_clock_visible.value
icon.name: "solid:\uf1fc"
defaultValue: defaultValues["Font Name"]
model: fonts
}
P.SelectPreference {
name: "Font Weight"
label: qsTr("Font Weight")
visible: !_cfg_battle_ui.value
enabled: visible && _cfg_clock_visible.value
icon.name: "solid:\uf1fc"
defaultValue: defaultValues["Font Weight"]
model: sfontweight
}
P.SliderPreference {
name: "Text Vertical Offset"
label: qsTr("Text Vertical Offset")
visible: !_cfg_battle_ui.value
enabled: visible && _cfg_clock_visible.value
from: -100
to: 100
stepSize: 1
defaultValue: defaultValues["Text Vertical Offset"]
displayValue: value + "%"
}
Component.onCompleted: {
if(!widget.settings.styles) {
configuration = rootPreference.save();
widget.settings.styles = configuration;
}
rootPreference.load(widget.settings.styles);
configuration = widget.settings.styles;
}
}
}
}
}
}
onClosing: {
widget.settings.styles = configuration;
styleDialog.active = false;
}
}
}
}