2023-04-09 05:35:35 +00:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
2022-09-14 05:01:10 +00:00
|
|
|
import QtQuick
|
|
|
|
import Qt5Compat.GraphicalEffects
|
2022-03-23 11:40:28 +00:00
|
|
|
import "../skin-bank.js" as SkinBank
|
|
|
|
|
|
|
|
/* Layout of card:
|
|
|
|
* +--------+
|
|
|
|
* num -|5 |
|
|
|
|
* suit-|s |
|
|
|
|
* | img |
|
|
|
|
* | |
|
|
|
|
* |footnote|
|
|
|
|
* +--------+
|
|
|
|
*/
|
|
|
|
|
|
|
|
Item {
|
2022-04-30 07:27:56 +00:00
|
|
|
id: root
|
|
|
|
width: 93
|
|
|
|
height: 130
|
|
|
|
|
|
|
|
// properties for the view
|
|
|
|
property string suit: "club"
|
|
|
|
property int number: 7
|
|
|
|
property string name: "slash"
|
2023-02-15 11:54:35 +00:00
|
|
|
property string extension: ""
|
|
|
|
property string virt_name: ""
|
2022-04-30 07:27:56 +00:00
|
|
|
property string subtype: ""
|
|
|
|
property string color: "" // only use when suit is empty
|
|
|
|
property string footnote: "" // footnote, e.g. "A use card to B"
|
2023-01-29 10:11:41 +00:00
|
|
|
property bool footnoteVisible: false
|
2022-04-30 07:27:56 +00:00
|
|
|
property bool known: true // if false it only show a card back
|
|
|
|
property bool enabled: true // if false the card will be grey
|
|
|
|
property alias card: cardItem
|
|
|
|
property alias glow: glowItem
|
|
|
|
|
|
|
|
function getColor() {
|
|
|
|
if (suit != "")
|
|
|
|
return (suit == "heart" || suit == "diamond") ? "red" : "black";
|
|
|
|
else return color;
|
|
|
|
}
|
|
|
|
|
|
|
|
// properties for animation and game system
|
|
|
|
property int cid: 0
|
|
|
|
property bool selectable: true
|
|
|
|
property bool selected: false
|
|
|
|
property bool draggable: false
|
|
|
|
property bool autoBack: true
|
|
|
|
property int origX: 0
|
|
|
|
property int origY: 0
|
|
|
|
property real origOpacity: 1
|
2023-03-18 07:34:42 +00:00
|
|
|
// property bool isClicked: false
|
2022-04-30 07:27:56 +00:00
|
|
|
property bool moveAborted: false
|
|
|
|
property alias goBackAnim: goBackAnimation
|
|
|
|
property int goBackDuration: 500
|
2023-01-29 10:11:41 +00:00
|
|
|
property bool busy: false // whether there is a running emotion on the card
|
2022-04-30 07:27:56 +00:00
|
|
|
|
|
|
|
signal toggleDiscards()
|
|
|
|
signal clicked()
|
2023-02-15 11:54:35 +00:00
|
|
|
signal rightClicked()
|
2022-04-30 07:27:56 +00:00
|
|
|
signal doubleClicked()
|
|
|
|
signal thrown()
|
|
|
|
signal released()
|
|
|
|
signal entered()
|
|
|
|
signal exited()
|
|
|
|
signal moveFinished()
|
|
|
|
signal generalChanged() // For choose general freely
|
|
|
|
signal hoverChanged(bool enter)
|
|
|
|
|
|
|
|
RectangularGlow {
|
|
|
|
id: glowItem
|
|
|
|
anchors.fill: parent
|
|
|
|
glowRadius: 8
|
|
|
|
spread: 0
|
|
|
|
color: "#88FFFFFF"
|
|
|
|
cornerRadius: 8
|
|
|
|
visible: false
|
|
|
|
}
|
|
|
|
|
|
|
|
Image {
|
|
|
|
id: cardItem
|
2023-02-15 11:54:35 +00:00
|
|
|
source: known ? SkinBank.getCardPicture(cid)
|
2022-04-30 07:27:56 +00:00
|
|
|
: (SkinBank.CARD_DIR + "card-back")
|
|
|
|
anchors.fill: parent
|
|
|
|
fillMode: Image.PreserveAspectCrop
|
|
|
|
}
|
|
|
|
|
|
|
|
Image {
|
|
|
|
id: suitItem
|
|
|
|
visible: known
|
|
|
|
source: suit != "" ? SkinBank.CARD_SUIT_DIR + suit : ""
|
|
|
|
x: 3
|
|
|
|
y: 19
|
|
|
|
width: 21
|
|
|
|
height: 17
|
|
|
|
}
|
|
|
|
|
|
|
|
Image {
|
|
|
|
id: numberItem
|
|
|
|
visible: known
|
|
|
|
source: (suit != "" && number > 0) ? SkinBank.CARD_DIR
|
|
|
|
+ "number/" + root.getColor() + "/" + number : ""
|
|
|
|
x: 0
|
|
|
|
y: 0
|
|
|
|
width: 27
|
|
|
|
height: 28
|
|
|
|
}
|
|
|
|
|
|
|
|
Image {
|
|
|
|
id: colorItem
|
|
|
|
visible: known && suit == ""
|
|
|
|
source: (visible && color != "") ? SkinBank.CARD_SUIT_DIR + "/" + color : ""
|
|
|
|
x: 1
|
|
|
|
}
|
|
|
|
|
2023-02-15 11:54:35 +00:00
|
|
|
Rectangle {
|
|
|
|
visible: root.virt_name !== ""
|
|
|
|
width: parent.width
|
|
|
|
height: 14
|
|
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
|
|
Text {
|
|
|
|
anchors.centerIn: parent
|
|
|
|
text: Backend.translate(root.virt_name)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
GlowText {
|
|
|
|
id: footnoteItem
|
|
|
|
text: footnote
|
|
|
|
x: 6
|
|
|
|
y: parent.height - height - 6
|
|
|
|
width: root.width - x * 2
|
|
|
|
color: "#E4D5A0"
|
|
|
|
visible: footnoteVisible
|
|
|
|
wrapMode: Text.WrapAnywhere
|
|
|
|
horizontalAlignment: Text.AlignHCenter
|
2022-05-01 10:37:13 +00:00
|
|
|
font.family: fontLibian.name
|
2022-04-30 07:27:56 +00:00
|
|
|
font.pixelSize: 14
|
|
|
|
glow.color: "black"
|
|
|
|
glow.spread: 1
|
|
|
|
glow.radius: 1
|
2022-09-14 05:01:10 +00:00
|
|
|
//glow.samples: 12
|
2022-04-30 07:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
visible: !root.selectable
|
|
|
|
anchors.fill: parent
|
|
|
|
color: Qt.rgba(0, 0, 0, 0.5)
|
|
|
|
opacity: 0.7
|
|
|
|
}
|
|
|
|
|
2023-03-18 07:34:42 +00:00
|
|
|
TapHandler {
|
|
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.NoButton
|
2023-03-18 15:37:21 +00:00
|
|
|
gesturePolicy: TapHandler.WithinBounds
|
2023-03-18 07:34:42 +00:00
|
|
|
|
|
|
|
onTapped: (p, btn) => {
|
|
|
|
if (btn === Qt.LeftButton || btn === Qt.NoButton) {
|
|
|
|
selected = selectable ? !selected : false;
|
|
|
|
parent.clicked();
|
|
|
|
} else if (btn === Qt.RightButton) {
|
|
|
|
parent.rightClicked();
|
|
|
|
}
|
|
|
|
}
|
2022-04-30 07:27:56 +00:00
|
|
|
|
2023-03-18 07:34:42 +00:00
|
|
|
onLongPressed: {
|
|
|
|
parent.rightClicked();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DragHandler {
|
|
|
|
enabled: draggable
|
2023-04-09 03:44:19 +00:00
|
|
|
grabPermissions: PointHandler.TakeOverForbidden
|
2023-03-18 07:34:42 +00:00
|
|
|
xAxis.enabled: true
|
|
|
|
yAxis.enabled: true
|
|
|
|
|
|
|
|
onGrabChanged: (transtition, point) => {
|
|
|
|
if (transtition !== PointerDevice.UngrabExclusive) return;
|
2022-04-30 07:27:56 +00:00
|
|
|
parent.released();
|
|
|
|
if (autoBack)
|
|
|
|
goBackAnimation.start();
|
2022-03-23 11:40:28 +00:00
|
|
|
}
|
2023-03-18 07:34:42 +00:00
|
|
|
}
|
2022-03-23 11:40:28 +00:00
|
|
|
|
2023-03-18 07:34:42 +00:00
|
|
|
HoverHandler {
|
|
|
|
id: hover
|
|
|
|
onHoveredChanged: {
|
|
|
|
if (!draggable) return;
|
|
|
|
if (hovered) {
|
2022-04-30 07:27:56 +00:00
|
|
|
glow.visible = true;
|
|
|
|
root.z++;
|
2023-03-18 07:34:42 +00:00
|
|
|
} else {
|
2022-04-30 07:27:56 +00:00
|
|
|
glow.visible = false;
|
|
|
|
root.z--;
|
|
|
|
}
|
2022-03-23 11:40:28 +00:00
|
|
|
}
|
2022-04-30 07:27:56 +00:00
|
|
|
}
|
2022-03-23 11:40:28 +00:00
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
ParallelAnimation {
|
|
|
|
id: goBackAnimation
|
2022-03-23 11:40:28 +00:00
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
PropertyAnimation {
|
|
|
|
target: root
|
|
|
|
property: "x"
|
|
|
|
to: origX
|
|
|
|
easing.type: Easing.OutQuad
|
|
|
|
duration: goBackDuration
|
2022-03-23 11:40:28 +00:00
|
|
|
}
|
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
PropertyAnimation {
|
|
|
|
target: root
|
|
|
|
property: "y"
|
|
|
|
to: origY
|
|
|
|
easing.type: Easing.OutQuad
|
|
|
|
duration: goBackDuration
|
2022-03-30 06:14:40 +00:00
|
|
|
}
|
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
SequentialAnimation {
|
|
|
|
PropertyAnimation {
|
|
|
|
target: root
|
|
|
|
property: "opacity"
|
|
|
|
to: 1
|
|
|
|
easing.type: Easing.OutQuad
|
|
|
|
duration: goBackDuration * 0.8
|
|
|
|
}
|
|
|
|
|
|
|
|
PropertyAnimation {
|
|
|
|
target: root
|
|
|
|
property: "opacity"
|
|
|
|
to: origOpacity
|
|
|
|
easing.type: Easing.OutQuad
|
|
|
|
duration: goBackDuration * 0.2
|
|
|
|
}
|
2022-03-23 11:40:28 +00:00
|
|
|
}
|
|
|
|
|
2022-04-30 07:27:56 +00:00
|
|
|
onStopped: {
|
|
|
|
if (!moveAborted)
|
|
|
|
root.moveFinished();
|
2022-03-23 11:40:28 +00:00
|
|
|
}
|
2022-04-30 07:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function setData(data)
|
|
|
|
{
|
|
|
|
cid = data.cid;
|
|
|
|
name = data.name;
|
|
|
|
suit = data.suit;
|
|
|
|
number = data.number;
|
|
|
|
color = data.color;
|
2023-02-15 13:20:40 +00:00
|
|
|
subtype = data.subtype ? data.subtype : "";
|
|
|
|
virt_name = data.virt_name ? data.virt_name : "";
|
2022-04-30 07:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function toData()
|
|
|
|
{
|
|
|
|
let data = {
|
|
|
|
cid: cid,
|
|
|
|
name: name,
|
|
|
|
suit: suit,
|
|
|
|
number: number,
|
2023-02-15 13:20:40 +00:00
|
|
|
color: color,
|
|
|
|
subtype: subtype,
|
|
|
|
virt_name: virt_name,
|
2022-04-30 07:27:56 +00:00
|
|
|
};
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
function goBack(animated)
|
|
|
|
{
|
|
|
|
if (animated) {
|
|
|
|
moveAborted = true;
|
|
|
|
goBackAnimation.stop();
|
|
|
|
moveAborted = false;
|
|
|
|
goBackAnimation.start();
|
|
|
|
} else {
|
|
|
|
x = origX;
|
|
|
|
y = origY;
|
|
|
|
opacity = origOpacity;
|
2022-03-23 11:40:28 +00:00
|
|
|
}
|
2022-04-30 07:27:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function destroyOnStop()
|
|
|
|
{
|
|
|
|
root.moveFinished.connect(function(){
|
|
|
|
root.destroy();
|
|
|
|
});
|
|
|
|
}
|
2022-03-23 11:40:28 +00:00
|
|
|
}
|