656 lines
14 KiB
QML
656 lines
14 KiB
QML
import QtQuick
|
|
import QtQuick.Controls
|
|
import QtQuick.Layouts
|
|
import QtMultimedia
|
|
import "Common"
|
|
import "RoomElement"
|
|
import "RoomLogic.js" as Logic
|
|
import "skin-bank.js" as SkinBank
|
|
|
|
|
|
Item {
|
|
id: roomScene
|
|
|
|
property int playerNum: 0
|
|
property var dashboardModel
|
|
|
|
property bool isOwner: false
|
|
property bool isStarted: false
|
|
|
|
property alias popupBox: popupBox
|
|
property alias manualBox: manualBox
|
|
property alias bigAnim: bigAnim
|
|
property alias promptText: prompt.text
|
|
property alias okCancel: okCancel
|
|
property alias okButton: okButton
|
|
property alias cancelButton: cancelButton
|
|
property alias dynamicCardArea: dynamicCardArea
|
|
property alias tableCards: tablePile.cards
|
|
|
|
property var selected_targets: []
|
|
property string responding_card
|
|
property bool respond_play: false
|
|
property var extra_data: ({})
|
|
|
|
Image {
|
|
source: config.roomBg
|
|
anchors.fill: parent
|
|
fillMode: Image.PreserveAspectCrop
|
|
}
|
|
|
|
MediaPlayer {
|
|
id: bgm
|
|
source: config.bgmFile
|
|
|
|
// loops: MediaPlayer.Infinite
|
|
onPlaybackStateChanged: {
|
|
if (playbackState == MediaPlayer.StoppedState && roomScene.isStarted)
|
|
play();
|
|
}
|
|
audioOutput: AudioOutput {}
|
|
}
|
|
|
|
onIsStartedChanged: {
|
|
if (isStarted) {
|
|
bgm.play();
|
|
} else {
|
|
// bgm.stop();
|
|
}
|
|
}
|
|
|
|
// tmp
|
|
Button {
|
|
text: "quit"
|
|
anchors.top: parent.top
|
|
anchors.right: parent.right
|
|
onClicked: {
|
|
// ClientInstance.clearPlayers();
|
|
ClientInstance.notifyServer("QuitRoom", "[]");
|
|
}
|
|
}
|
|
Button {
|
|
text: "add robot"
|
|
visible: dashboardModel.isOwner && !isStarted
|
|
anchors.centerIn: parent
|
|
onClicked: {
|
|
ClientInstance.notifyServer("AddRobot", "[]");
|
|
}
|
|
}
|
|
|
|
states: [
|
|
State { name: "notactive" }, // Normal status
|
|
State { name: "playing" }, // Playing cards in playing phase
|
|
State { name: "responding" }, // all requests need to operate dashboard
|
|
State { name: "replying" } // requests only operate a popup window
|
|
]
|
|
state: "notactive"
|
|
transitions: [
|
|
Transition {
|
|
from: "*"; to: "notactive"
|
|
ScriptAction {
|
|
script: {
|
|
promptText = "";
|
|
progress.visible = false;
|
|
okCancel.visible = false;
|
|
endPhaseButton.visible = false;
|
|
respond_play = false;
|
|
extra_data = {};
|
|
|
|
if (dashboard.pending_skill !== "")
|
|
dashboard.stopPending();
|
|
dashboard.disableAllCards();
|
|
dashboard.disableSkills();
|
|
dashboard.retractAllPiles();
|
|
selected_targets = [];
|
|
|
|
if (popupBox.item != null) {
|
|
popupBox.item.finished();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
Transition {
|
|
from: "*"; to: "playing"
|
|
ScriptAction {
|
|
script: {
|
|
dashboard.enableCards();
|
|
dashboard.enableSkills();
|
|
progress.visible = true;
|
|
okCancel.visible = true;
|
|
endPhaseButton.visible = true;
|
|
respond_play = false;
|
|
}
|
|
}
|
|
},
|
|
|
|
Transition {
|
|
from: "*"; to: "responding"
|
|
ScriptAction {
|
|
script: {
|
|
dashboard.enableCards(responding_card);
|
|
dashboard.enableSkills(responding_card);
|
|
progress.visible = true;
|
|
okCancel.visible = true;
|
|
}
|
|
}
|
|
},
|
|
|
|
Transition {
|
|
from: "*"; to: "replying"
|
|
ScriptAction {
|
|
script: {
|
|
dashboard.disableAllCards();
|
|
dashboard.disableSkills();
|
|
progress.visible = true;
|
|
respond_play = false;
|
|
roomScene.okCancel.visible = false;
|
|
roomScene.okButton.enabled = false;
|
|
roomScene.cancelButton.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
]
|
|
|
|
/* Layout:
|
|
* +---------------------+
|
|
* | Photos, get more |
|
|
* | in arrangePhotos() |
|
|
* | tablePile |
|
|
* | progress,prompt,btn |
|
|
* +---------------------+
|
|
* | dashboard |
|
|
* +---------------------+
|
|
*/
|
|
|
|
ListModel {
|
|
id: photoModel
|
|
}
|
|
|
|
Item {
|
|
id: roomArea
|
|
width: roomScene.width
|
|
height: roomScene.height - dashboard.height + 20
|
|
|
|
Repeater {
|
|
id: photos
|
|
model: photoModel
|
|
Photo {
|
|
playerid: model.id
|
|
general: model.general
|
|
screenName: model.screenName
|
|
role: model.role
|
|
kingdom: model.kingdom
|
|
netstate: model.netstate
|
|
maxHp: model.maxHp
|
|
hp: model.hp
|
|
seatNumber: model.seatNumber
|
|
dead: model.dead
|
|
dying: model.dying
|
|
faceup: model.faceup
|
|
chained: model.chained
|
|
drank: model.drank
|
|
isOwner: model.isOwner
|
|
|
|
onSelectedChanged: {
|
|
Logic.updateSelectedTargets(playerid, selected);
|
|
}
|
|
}
|
|
}
|
|
|
|
onWidthChanged: Logic.arrangePhotos();
|
|
onHeightChanged: Logic.arrangePhotos();
|
|
|
|
InvisibleCardArea {
|
|
id: drawPile
|
|
x: parent.width / 2
|
|
y: roomScene.height / 2
|
|
}
|
|
|
|
TablePile {
|
|
id: tablePile
|
|
width: parent.width * 0.6
|
|
height: 150
|
|
x: parent.width * 0.2
|
|
y: parent.height * 0.6 + 10
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: dashboardBtn
|
|
width: childrenRect.width
|
|
height: childrenRect.height
|
|
anchors.bottom: parent.bottom
|
|
ColumnLayout {
|
|
MetroButton {
|
|
text: Backend.translate("Trust")
|
|
}
|
|
MetroButton {
|
|
text: Backend.translate("Sort Cards")
|
|
}
|
|
MetroButton {
|
|
text: Backend.translate("Chat")
|
|
onClicked: roomDrawer.open();
|
|
}
|
|
}
|
|
}
|
|
|
|
Dashboard {
|
|
id: dashboard
|
|
width: roomScene.width - dashboardBtn.width
|
|
anchors.top: roomArea.bottom
|
|
anchors.left: dashboardBtn.right
|
|
|
|
self.playerid: dashboardModel.id
|
|
self.general: dashboardModel.general
|
|
self.screenName: dashboardModel.screenName
|
|
self.role: dashboardModel.role
|
|
self.kingdom: dashboardModel.kingdom
|
|
self.netstate: dashboardModel.netstate
|
|
self.maxHp: dashboardModel.maxHp
|
|
self.hp: dashboardModel.hp
|
|
self.seatNumber: dashboardModel.seatNumber
|
|
self.dead: dashboardModel.dead
|
|
self.dying: dashboardModel.dying
|
|
self.faceup: dashboardModel.faceup
|
|
self.chained: dashboardModel.chained
|
|
self.drank: dashboardModel.drank
|
|
self.isOwner: dashboardModel.isOwner
|
|
|
|
onSelectedChanged: {
|
|
Logic.updateSelectedTargets(self.playerid, selected);
|
|
}
|
|
|
|
onCardSelected: function(card) {
|
|
Logic.enableTargets(card);
|
|
}
|
|
}
|
|
|
|
GlowText {
|
|
text: Backend.translate("Observing ...")
|
|
visible: config.observing
|
|
color: "#4B83CD"
|
|
font.family: fontLi2.name
|
|
font.pixelSize: 48
|
|
}
|
|
|
|
Item {
|
|
id: controls
|
|
anchors.bottom: dashboard.top
|
|
anchors.bottomMargin: -60
|
|
width: roomScene.width
|
|
|
|
Text {
|
|
id: prompt
|
|
visible: progress.visible
|
|
anchors.top: progress.top
|
|
anchors.topMargin: -2
|
|
color: "white"
|
|
z: 1
|
|
anchors.horizontalCenter: progress.horizontalCenter
|
|
}
|
|
|
|
ProgressBar {
|
|
id: progress
|
|
width: parent.width * 0.6
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
anchors.bottom: okCancel.top
|
|
anchors.bottomMargin: 4
|
|
from: 0.0
|
|
to: 100.0
|
|
|
|
visible: false
|
|
|
|
background: Rectangle {
|
|
implicitWidth: 200
|
|
implicitHeight: 14
|
|
color: "black"
|
|
radius: 3
|
|
}
|
|
|
|
contentItem: Item {
|
|
implicitWidth: 200
|
|
implicitHeight: 12
|
|
|
|
Rectangle {
|
|
width: progress.visualPosition * parent.width
|
|
height: parent.height
|
|
radius: 2
|
|
color: "red"
|
|
}
|
|
}
|
|
|
|
NumberAnimation on value {
|
|
running: progress.visible
|
|
from: 100.0
|
|
to: 0.0
|
|
duration: config.roomTimeout * 1000
|
|
|
|
onFinished: {
|
|
roomScene.state = "notactive"
|
|
}
|
|
}
|
|
}
|
|
|
|
Row {
|
|
id: okCancel
|
|
anchors.bottom: parent.bottom
|
|
anchors.horizontalCenter: progress.horizontalCenter
|
|
spacing: 20
|
|
visible: false
|
|
|
|
Button {
|
|
id: okButton
|
|
text: Backend.translate("OK")
|
|
onClicked: Logic.doOkButton();
|
|
}
|
|
|
|
Button {
|
|
id: cancelButton
|
|
text: Backend.translate("Cancel")
|
|
onClicked: Logic.doCancelButton();
|
|
}
|
|
}
|
|
|
|
Button {
|
|
id: endPhaseButton
|
|
text: Backend.translate("End")
|
|
anchors.bottom: parent.bottom
|
|
anchors.bottomMargin: 40
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: 30
|
|
visible: false;
|
|
onClicked: Logic.replyToServer("");
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: popupBox
|
|
z: 999
|
|
onSourceChanged: {
|
|
if (item === null)
|
|
return;
|
|
item.finished.connect(function(){
|
|
source = "";
|
|
});
|
|
item.widthChanged.connect(function(){
|
|
popupBox.moveToCenter();
|
|
});
|
|
item.heightChanged.connect(function(){
|
|
popupBox.moveToCenter();
|
|
});
|
|
moveToCenter();
|
|
}
|
|
|
|
function moveToCenter()
|
|
{
|
|
item.x = Math.round((roomArea.width - item.width) / 2);
|
|
item.y = Math.round(roomArea.height * 0.67 - item.height / 2);
|
|
}
|
|
}
|
|
|
|
// manualBox: same as popupBox, but must be closed manually
|
|
Loader {
|
|
id: manualBox
|
|
z: 999
|
|
onSourceChanged: {
|
|
if (item === null)
|
|
return;
|
|
item.finished.connect(() => source = "");
|
|
item.widthChanged.connect(() => manualBox.moveToCenter());
|
|
item.heightChanged.connect(() => manualBox.moveToCenter());
|
|
moveToCenter();
|
|
}
|
|
|
|
function moveToCenter()
|
|
{
|
|
item.x = Math.round((roomArea.width - item.width) / 2);
|
|
item.y = Math.round(roomArea.height * 0.67 - item.height / 2);
|
|
}
|
|
}
|
|
|
|
Loader {
|
|
id: bigAnim
|
|
anchors.fill: parent
|
|
z: 999
|
|
}
|
|
|
|
function activateSkill(skill_name, pressed) {
|
|
if (pressed) {
|
|
dashboard.startPending(skill_name);
|
|
cancelButton.enabled = true;
|
|
} else {
|
|
Logic.doCancelButton();
|
|
}
|
|
}
|
|
|
|
Drawer {
|
|
id: roomDrawer
|
|
width: parent.width * 0.3 / mainWindow.scale
|
|
height: parent.height / mainWindow.scale
|
|
dim: false
|
|
clip: true
|
|
dragMargin: 0
|
|
scale: mainWindow.scale
|
|
transformOrigin: Item.TopLeft
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
|
|
SwipeView {
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
interactive: false
|
|
currentIndex: drawerBar.currentIndex
|
|
Item {
|
|
LogEdit {
|
|
id: log
|
|
anchors.fill: parent
|
|
}
|
|
}
|
|
Item {
|
|
ChatBox {
|
|
id: chat
|
|
anchors.fill: parent
|
|
}
|
|
}
|
|
}
|
|
|
|
TabBar {
|
|
id: drawerBar
|
|
width: roomDrawer.width
|
|
TabButton {
|
|
width: roomDrawer.width / 2
|
|
text: Backend.translate("Log")
|
|
}
|
|
TabButton {
|
|
width: roomDrawer.width / 2
|
|
text: Backend.translate("Chat")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Drawer {
|
|
id: cheatDrawer
|
|
edge: Qt.RightEdge
|
|
width: parent.width * 0.4 / mainWindow.scale
|
|
height: parent.height / mainWindow.scale
|
|
dim: false
|
|
clip: true
|
|
dragMargin: 0
|
|
scale: mainWindow.scale
|
|
transformOrigin: Item.TopRight
|
|
|
|
Loader {
|
|
id: cheatLoader
|
|
anchors.fill: parent
|
|
onSourceChanged: {
|
|
if (item === null)
|
|
return;
|
|
item.finish.connect(() => {
|
|
cheatDrawer.close();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: dynamicCardArea
|
|
anchors.fill: parent
|
|
}
|
|
|
|
Rectangle {
|
|
id: easyChat
|
|
width: parent.width
|
|
height: 28
|
|
anchors.bottom: parent.bottom
|
|
visible: false
|
|
color: "#040403"
|
|
radius: 3
|
|
border.width: 1
|
|
border.color: "#A6967A"
|
|
|
|
TextInput {
|
|
id: easyChatEdit
|
|
anchors.fill: parent
|
|
anchors.margins: 6
|
|
color: "white"
|
|
clip: true
|
|
font.pixelSize: 14
|
|
|
|
onAccepted: {
|
|
if (text != "") {
|
|
ClientInstance.notifyServer(
|
|
"Chat",
|
|
JSON.stringify({
|
|
type: 0,
|
|
msg: text
|
|
})
|
|
);
|
|
text = "";
|
|
easyChat.visible = false;
|
|
easyChatEdit.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Shortcut {
|
|
sequence: "T"
|
|
onActivated: {
|
|
easyChat.visible = true;
|
|
easyChatEdit.enabled = true;
|
|
easyChatEdit.forceActiveFocus();
|
|
}
|
|
}
|
|
|
|
Shortcut {
|
|
sequence: "D"
|
|
property bool show_distance: false
|
|
onActivated: {
|
|
show_distance = !show_distance;
|
|
showDistance(show_distance);
|
|
}
|
|
}
|
|
|
|
Shortcut {
|
|
sequence: "Esc"
|
|
onActivated: {
|
|
easyChat.visible = false;
|
|
easyChatEdit.enabled = false;
|
|
}
|
|
}
|
|
|
|
Shortcut {
|
|
sequence: "Return"
|
|
enabled: okButton.enabled
|
|
onActivated: Logic.doOkButton();
|
|
}
|
|
|
|
Shortcut {
|
|
sequence: "Space"
|
|
enabled: cancelButton.enabled
|
|
onActivated: Logic.doCancelButton();
|
|
}
|
|
|
|
function addToChat(pid, raw, msg) {
|
|
chat.append(msg);
|
|
let photo = Logic.getPhotoOrSelf(pid);
|
|
if (photo === undefined)
|
|
return;
|
|
photo.chat(raw.msg);
|
|
}
|
|
|
|
function addToLog(msg) {
|
|
log.append(msg);
|
|
}
|
|
|
|
function showDistance(show) {
|
|
for (let i = 0; i < photoModel.count; i++) {
|
|
let item = photos.itemAt(i);
|
|
if (show) {
|
|
let dis = Backend.callLuaFunction("DistanceTo",[Self.id, item.playerid]);
|
|
item.distance = parseInt(dis);
|
|
} else {
|
|
item.distance = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
function startCheat(source, data) {
|
|
cheatLoader.source = source;
|
|
cheatLoader.item.extra_data = data;
|
|
cheatDrawer.open();
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
toast.show(Backend.translate("$EnterRoom"));
|
|
|
|
dashboardModel = {
|
|
id: Self.id,
|
|
general: Self.avatar,
|
|
screenName: Self.screenName,
|
|
role: "unknown",
|
|
kingdom: "qun",
|
|
netstate: "online",
|
|
maxHp: 0,
|
|
hp: 0,
|
|
seatNumber: 1,
|
|
dead: false,
|
|
dying: false,
|
|
faceup: true,
|
|
chained: false,
|
|
drank: 0,
|
|
isOwner: false
|
|
}
|
|
|
|
playerNum = config.roomCapacity;
|
|
|
|
let i;
|
|
for (i = 1; i < playerNum; i++) {
|
|
photoModel.append({
|
|
id: -1,
|
|
index: i - 1, // For animating seat swap
|
|
general: "",
|
|
screenName: "",
|
|
role: "unknown",
|
|
kingdom: "qun",
|
|
netstate: "online",
|
|
maxHp: 0,
|
|
hp: 0,
|
|
seatNumber: i + 1,
|
|
dead: false,
|
|
dying: false,
|
|
faceup: true,
|
|
chained: false,
|
|
drank: 0,
|
|
isOwner: false
|
|
});
|
|
}
|
|
|
|
Logic.arrangePhotos();
|
|
}
|
|
}
|
|
|