mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-07 05:53:59 -07:00
Merge branch 'master' into ci/use-ninja-win
This commit is contained in:
commit
746f910c08
72 changed files with 965 additions and 723 deletions
|
|
@ -2,7 +2,6 @@
|
|||
# used by the ci to rename build artifacts
|
||||
# renames the file to [original name][SUFFIX].[original extension]
|
||||
# where SUFFIX is either available in the environment or as the first arg
|
||||
# if MAKE_ZIP is set instead a zip is made
|
||||
# expected to be run in the build directory unless BUILD_DIR is set
|
||||
# adds output to GITHUB_OUTPUT
|
||||
builddir="${BUILD_DIR:=.}"
|
||||
|
|
@ -22,8 +21,8 @@ set -e
|
|||
|
||||
# find file
|
||||
found="$(find "$builddir" -maxdepth 1 -type f -name "$findrx" -print -quit)"
|
||||
path="${found%/*}" # remove all after last /
|
||||
file="${found##*/}" # remove all before last /
|
||||
path="${found%/*}" # remove all including first "/" from right side
|
||||
file="${found##*/}" # remove all including last "/" from left side
|
||||
if [[ ! $file ]]; then
|
||||
echo "::error file=$0::could not find package"
|
||||
exit 1
|
||||
|
|
@ -35,21 +34,16 @@ if ! cd "$path"; then
|
|||
fi
|
||||
|
||||
# set filename
|
||||
name="${file%.*}" # remove all after last .
|
||||
new_name="$name$SUFFIX."
|
||||
if [[ $MAKE_ZIP ]]; then
|
||||
filename="${new_name}zip"
|
||||
echo "creating zip '$filename' from '$file'"
|
||||
zip "$filename" "$file"
|
||||
else
|
||||
extension="${file##*.}" # remove all before last .
|
||||
filename="$new_name$extension"
|
||||
echo "renaming '$file' to '$filename'"
|
||||
mv "$file" "$filename"
|
||||
fi
|
||||
name="${file%.*}" # remove all including first "." from right side
|
||||
new_name="$name$SUFFIX"
|
||||
extension="${file##*.}" # remove all including last "." from left side
|
||||
filename="$new_name.$extension"
|
||||
echo "renaming '$file' to '$filename'"
|
||||
mv "$file" "$filename"
|
||||
|
||||
cd "$oldpwd"
|
||||
relative_path="$path/$filename"
|
||||
ls -l "$relative_path"
|
||||
echo "path=$relative_path" >>"$GITHUB_OUTPUT"
|
||||
echo "name=$filename" >>"$GITHUB_OUTPUT"
|
||||
echo "name=$new_name" >>"$GITHUB_OUTPUT"
|
||||
echo "fullname=$filename" >>"$GITHUB_OUTPUT"
|
||||
|
|
|
|||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
|
|
@ -9,4 +9,4 @@ contact_links:
|
|||
about: For more information and guidance check our Translation FAQ on our wiki!
|
||||
- name: 📖 Code Documentation
|
||||
url: https://cockatrice.github.io/docs/
|
||||
about:
|
||||
about: Helpful source focusing on developers, but there are also references for users!
|
||||
|
|
|
|||
35
.github/workflows/desktop-build.yml
vendored
35
.github/workflows/desktop-build.yml
vendored
|
|
@ -220,27 +220,26 @@ jobs:
|
|||
if: matrix.package != 'skip'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{matrix.distro}}${{matrix.version}}-package
|
||||
path: ${{steps.build.outputs.path}}
|
||||
archive: false
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
id: upload_release
|
||||
if: needs.configure.outputs.tag != null && matrix.package != 'skip'
|
||||
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{needs.configure.outputs.tag}}
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
asset_name: ${{steps.build.outputs.fullname}}
|
||||
asset_path: ${{steps.build.outputs.path}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
|
||||
- name: Attest binary provenance
|
||||
id: attestation
|
||||
if: steps.upload_release.outcome == 'success'
|
||||
uses: actions/attest-build-provenance@v4
|
||||
uses: actions/attest@v4
|
||||
with:
|
||||
subject-name: ${{steps.build.outputs.name}}
|
||||
subject-path: ${{steps.build.outputs.path}}
|
||||
show-summary: false
|
||||
|
||||
|
|
@ -265,7 +264,6 @@ jobs:
|
|||
override_target: 13
|
||||
make_package: 1
|
||||
package_suffix: "-macOS13_Intel"
|
||||
artifact_name: macOS13_Intel-package
|
||||
qt_version: 6.10.*
|
||||
qt_arch: clang_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
|
|
@ -280,7 +278,6 @@ jobs:
|
|||
type: Release
|
||||
make_package: 1
|
||||
package_suffix: "-macOS14"
|
||||
artifact_name: macOS14-package
|
||||
qt_version: 6.10.*
|
||||
qt_arch: clang_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
|
|
@ -295,7 +292,6 @@ jobs:
|
|||
type: Release
|
||||
make_package: 1
|
||||
package_suffix: "-macOS15"
|
||||
artifact_name: macOS15-package
|
||||
qt_version: 6.10.*
|
||||
qt_arch: clang_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
|
|
@ -320,7 +316,6 @@ jobs:
|
|||
type: Release
|
||||
make_package: 1
|
||||
package_suffix: "-Win10"
|
||||
artifact_name: Windows10-installer
|
||||
qt_version: 6.10.*
|
||||
qt_arch: win64_msvc2022_64
|
||||
qt_modules: qtimageformats qtmultimedia qtwebsockets
|
||||
|
|
@ -464,7 +459,8 @@ jobs:
|
|||
key: ${{ steps.ccache_restore.outputs.cache-primary-key }}
|
||||
|
||||
- name: Sign app bundle
|
||||
if: matrix.os == 'macOS' && matrix.make_package && (github.ref == 'refs/heads/master' || needs.configure.outputs.tag != null)
|
||||
if: matrix.os == 'macOS' && matrix.make_package && needs.configure.outputs.tag != null
|
||||
id: sign_macos
|
||||
env:
|
||||
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
|
||||
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
|
||||
|
|
@ -476,7 +472,7 @@ jobs:
|
|||
fi
|
||||
|
||||
- name: Notarize app bundle
|
||||
if: matrix.os == 'macOS' && matrix.make_package && (github.ref == 'refs/heads/master' || needs.configure.outputs.tag != null)
|
||||
if: steps.sign_macos.outcome == 'success'
|
||||
env:
|
||||
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
|
|
@ -508,19 +504,19 @@ jobs:
|
|||
fi
|
||||
|
||||
- name: Upload artifact
|
||||
id: upload_artifact
|
||||
if: matrix.make_package
|
||||
id: upload_artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{matrix.artifact_name}}
|
||||
path: ${{steps.build.outputs.path}}
|
||||
archive: false
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload PDBs (Program Databases)
|
||||
if: matrix.os == 'Windows'
|
||||
if: matrix.os == 'Windows' && github.ref_type != 'tag'
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: Windows${{matrix.target}}-PDBs
|
||||
name: ${{steps.build.outputs.name}}-PDBs
|
||||
path: |
|
||||
build/cockatrice/**/*.pdb
|
||||
build/oracle/**/*.pdb
|
||||
|
|
@ -528,22 +524,21 @@ jobs:
|
|||
if-no-files-found: error
|
||||
|
||||
- name: Upload to release
|
||||
if: needs.configure.outputs.tag != null && matrix.make_package == '1'
|
||||
id: upload_release
|
||||
if: needs.configure.outputs.tag != null
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{github.token}}
|
||||
tag_name: ${{needs.configure.outputs.tag}}
|
||||
asset_name: ${{steps.build.outputs.name}}
|
||||
asset_name: ${{steps.build.outputs.fullname}}
|
||||
asset_path: ${{steps.build.outputs.path}}
|
||||
run: gh release upload "$tag_name" "$asset_path#$asset_name"
|
||||
|
||||
- name: Attest binary provenance
|
||||
id: attestation
|
||||
if: steps.upload_release.outcome == 'success'
|
||||
uses: actions/attest-build-provenance@v4
|
||||
id: attestation
|
||||
uses: actions/attest@v4
|
||||
with:
|
||||
subject-name: ${{steps.build.outputs.name}}
|
||||
subject-path: ${{steps.build.outputs.path}}
|
||||
show-summary: false
|
||||
|
||||
|
|
|
|||
9
.github/workflows/docker-release.yml
vendored
9
.github/workflows/docker-release.yml
vendored
|
|
@ -41,10 +41,10 @@ jobs:
|
|||
org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
uses: docker/setup-qemu-action@v4
|
||||
|
||||
- name: Set up Docker buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: github.ref_type == 'tag'
|
||||
|
|
@ -62,5 +62,6 @@ jobs:
|
|||
push: ${{ github.ref_type == 'tag' }}
|
||||
tags: ${{ steps.metadata.outputs.tags }}
|
||||
labels: ${{ steps.metadata.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
annotations: ${{ steps.metadata.outputs.annotations }}
|
||||
cache-from: type=gha,scope=servatrice
|
||||
cache-to: type=gha,mode=max,scope=servatrice
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ Var PortableMode
|
|||
!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Cockatrice.$\r$\n$\r$\nClick Next to continue."
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR/cockatrice.exe"
|
||||
!define MUI_FINISHPAGE_RUN_TEXT "Run 'Cockatrice' now"
|
||||
!define MUI_ICON "${NSIS_SOURCE_PATH}\cockatrice\resources\appicon.ico"
|
||||
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_LICENSE "${NSIS_SOURCE_PATH}\LICENSE"
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@
|
|||
#define INTERFACE_JSON_DECK_PARSER_H
|
||||
|
||||
#include "../../../interface/deck_loader/card_node_function.h"
|
||||
#include "../../../interface/deck_loader/deck_loader.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
|
||||
class IJsonDeckParser
|
||||
{
|
||||
|
|
@ -49,7 +50,7 @@ public:
|
|||
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
|
||||
}
|
||||
|
||||
deckList.loadFromStream_Plain(outStream, false);
|
||||
deckList.loadFromStream_Plain(outStream, false, CardNameNormalizer());
|
||||
deckList.forEachCard(CardNodeFunction::ResolveProviderId());
|
||||
|
||||
return deckList;
|
||||
|
|
@ -96,7 +97,7 @@ public:
|
|||
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
|
||||
}
|
||||
|
||||
deckList.loadFromStream_Plain(outStream, false);
|
||||
deckList.loadFromStream_Plain(outStream, false, CardNameNormalizer());
|
||||
deckList.forEachCard(CardNodeFunction::ResolveProviderId());
|
||||
|
||||
QJsonObject commandersObj = obj.value("commanders").toObject();
|
||||
|
|
|
|||
|
|
@ -1115,257 +1115,21 @@ void SettingsCache::setClientVersion(const QString &_clientVersion)
|
|||
|
||||
QStringList SettingsCache::getCountries() const
|
||||
{
|
||||
static QStringList countries = QStringList() << "ad"
|
||||
<< "ae"
|
||||
<< "af"
|
||||
<< "ag"
|
||||
<< "ai"
|
||||
<< "al"
|
||||
<< "am"
|
||||
<< "ao"
|
||||
<< "aq"
|
||||
<< "ar"
|
||||
<< "as"
|
||||
<< "at"
|
||||
<< "au"
|
||||
<< "aw"
|
||||
<< "ax"
|
||||
<< "az"
|
||||
<< "ba"
|
||||
<< "bb"
|
||||
<< "bd"
|
||||
<< "be"
|
||||
<< "bf"
|
||||
<< "bg"
|
||||
<< "bh"
|
||||
<< "bi"
|
||||
<< "bj"
|
||||
<< "bl"
|
||||
<< "bm"
|
||||
<< "bn"
|
||||
<< "bo"
|
||||
<< "bq"
|
||||
<< "br"
|
||||
<< "bs"
|
||||
<< "bt"
|
||||
<< "bv"
|
||||
<< "bw"
|
||||
<< "by"
|
||||
<< "bz"
|
||||
<< "ca"
|
||||
<< "cc"
|
||||
<< "cd"
|
||||
<< "cf"
|
||||
<< "cg"
|
||||
<< "ch"
|
||||
<< "ci"
|
||||
<< "ck"
|
||||
<< "cl"
|
||||
<< "cm"
|
||||
<< "cn"
|
||||
<< "co"
|
||||
<< "cr"
|
||||
<< "cu"
|
||||
<< "cv"
|
||||
<< "cw"
|
||||
<< "cx"
|
||||
<< "cy"
|
||||
<< "cz"
|
||||
<< "de"
|
||||
<< "dj"
|
||||
<< "dk"
|
||||
<< "dm"
|
||||
<< "do"
|
||||
<< "dz"
|
||||
<< "ec"
|
||||
<< "ee"
|
||||
<< "eg"
|
||||
<< "eh"
|
||||
<< "er"
|
||||
<< "es"
|
||||
<< "et"
|
||||
<< "eu"
|
||||
<< "fi"
|
||||
<< "fj"
|
||||
<< "fk"
|
||||
<< "fm"
|
||||
<< "fo"
|
||||
<< "fr"
|
||||
<< "ga"
|
||||
<< "gb"
|
||||
<< "gd"
|
||||
<< "ge"
|
||||
<< "gf"
|
||||
<< "gg"
|
||||
<< "gh"
|
||||
<< "gi"
|
||||
<< "gl"
|
||||
<< "gm"
|
||||
<< "gn"
|
||||
<< "gp"
|
||||
<< "gq"
|
||||
<< "gr"
|
||||
<< "gs"
|
||||
<< "gt"
|
||||
<< "gu"
|
||||
<< "gw"
|
||||
<< "gy"
|
||||
<< "hk"
|
||||
<< "hm"
|
||||
<< "hn"
|
||||
<< "hr"
|
||||
<< "ht"
|
||||
<< "hu"
|
||||
<< "id"
|
||||
<< "ie"
|
||||
<< "il"
|
||||
<< "im"
|
||||
<< "in"
|
||||
<< "io"
|
||||
<< "iq"
|
||||
<< "ir"
|
||||
<< "is"
|
||||
<< "it"
|
||||
<< "je"
|
||||
<< "jm"
|
||||
<< "jo"
|
||||
<< "jp"
|
||||
<< "ke"
|
||||
<< "kg"
|
||||
<< "kh"
|
||||
<< "ki"
|
||||
<< "km"
|
||||
<< "kn"
|
||||
<< "kp"
|
||||
<< "kr"
|
||||
<< "kw"
|
||||
<< "ky"
|
||||
<< "kz"
|
||||
<< "la"
|
||||
<< "lb"
|
||||
<< "lc"
|
||||
<< "li"
|
||||
<< "lk"
|
||||
<< "lr"
|
||||
<< "ls"
|
||||
<< "lt"
|
||||
<< "lu"
|
||||
<< "lv"
|
||||
<< "ly"
|
||||
<< "ma"
|
||||
<< "mc"
|
||||
<< "md"
|
||||
<< "me"
|
||||
<< "mf"
|
||||
<< "mg"
|
||||
<< "mh"
|
||||
<< "mk"
|
||||
<< "ml"
|
||||
<< "mm"
|
||||
<< "mn"
|
||||
<< "mo"
|
||||
<< "mp"
|
||||
<< "mq"
|
||||
<< "mr"
|
||||
<< "ms"
|
||||
<< "mt"
|
||||
<< "mu"
|
||||
<< "mv"
|
||||
<< "mw"
|
||||
<< "mx"
|
||||
<< "my"
|
||||
<< "mz"
|
||||
<< "na"
|
||||
<< "nc"
|
||||
<< "ne"
|
||||
<< "nf"
|
||||
<< "ng"
|
||||
<< "ni"
|
||||
<< "nl"
|
||||
<< "no"
|
||||
<< "np"
|
||||
<< "nr"
|
||||
<< "nu"
|
||||
<< "nz"
|
||||
<< "om"
|
||||
<< "pa"
|
||||
<< "pe"
|
||||
<< "pf"
|
||||
<< "pg"
|
||||
<< "ph"
|
||||
<< "pk"
|
||||
<< "pl"
|
||||
<< "pm"
|
||||
<< "pn"
|
||||
<< "pr"
|
||||
<< "ps"
|
||||
<< "pt"
|
||||
<< "pw"
|
||||
<< "py"
|
||||
<< "qa"
|
||||
<< "re"
|
||||
<< "ro"
|
||||
<< "rs"
|
||||
<< "ru"
|
||||
<< "rw"
|
||||
<< "sa"
|
||||
<< "sb"
|
||||
<< "sc"
|
||||
<< "sd"
|
||||
<< "se"
|
||||
<< "sg"
|
||||
<< "sh"
|
||||
<< "si"
|
||||
<< "sj"
|
||||
<< "sk"
|
||||
<< "sl"
|
||||
<< "sm"
|
||||
<< "sn"
|
||||
<< "so"
|
||||
<< "sr"
|
||||
<< "ss"
|
||||
<< "st"
|
||||
<< "sv"
|
||||
<< "sx"
|
||||
<< "sy"
|
||||
<< "sz"
|
||||
<< "tc"
|
||||
<< "td"
|
||||
<< "tf"
|
||||
<< "tg"
|
||||
<< "th"
|
||||
<< "tj"
|
||||
<< "tk"
|
||||
<< "tl"
|
||||
<< "tm"
|
||||
<< "tn"
|
||||
<< "to"
|
||||
<< "tr"
|
||||
<< "tt"
|
||||
<< "tv"
|
||||
<< "tw"
|
||||
<< "tz"
|
||||
<< "ua"
|
||||
<< "ug"
|
||||
<< "um"
|
||||
<< "us"
|
||||
<< "uy"
|
||||
<< "uz"
|
||||
<< "va"
|
||||
<< "vc"
|
||||
<< "ve"
|
||||
<< "vg"
|
||||
<< "vi"
|
||||
<< "vn"
|
||||
<< "vu"
|
||||
<< "wf"
|
||||
<< "ws"
|
||||
<< "xk"
|
||||
<< "ye"
|
||||
<< "yt"
|
||||
<< "za"
|
||||
<< "zm"
|
||||
<< "zw";
|
||||
static const QStringList countries = {
|
||||
"ad", "ae", "af", "ag", "ai", "al", "am", "ao", "aq", "ar", "as", "at", "au", "aw", "ax", "az", "ba", "bb",
|
||||
"bd", "be", "bf", "bg", "bh", "bi", "bj", "bl", "bm", "bn", "bo", "bq", "br", "bs", "bt", "bv", "bw", "by",
|
||||
"bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co", "cr", "cu", "cv", "cw", "cx",
|
||||
"cy", "cz", "de", "dj", "dk", "dm", "do", "dz", "ec", "ee", "eg", "eh", "er", "es", "et", "eu", "fi", "fj",
|
||||
"fk", "fm", "fo", "fr", "ga", "gb", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gm", "gn", "gp", "gq", "gr",
|
||||
"gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn", "hr", "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq",
|
||||
"ir", "is", "it", "je", "jm", "jo", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kp", "kr", "kw", "ky", "kz",
|
||||
"la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu", "lv", "ly", "ma", "mc", "md", "me", "mf", "mg", "mh",
|
||||
"mk", "ml", "mm", "mn", "mo", "mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz", "na", "nc",
|
||||
"ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", "nz", "om", "pa", "pe", "pf", "pg", "ph", "pk", "pl",
|
||||
"pm", "pn", "pr", "ps", "pt", "pw", "py", "qa", "re", "ro", "rs", "ru", "rw", "sa", "sb", "sc", "sd", "se",
|
||||
"sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "so", "sr", "ss", "st", "sv", "sx", "sy", "sz", "tc", "td",
|
||||
"tf", "tg", "th", "tj", "tk", "tl", "tm", "tn", "to", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "um", "us",
|
||||
"uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws", "xk", "ye", "yt", "za", "zm", "zw"};
|
||||
|
||||
return countries;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -598,11 +598,19 @@ private:
|
|||
{"Player/aMoveTopCardsToGraveyard", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard (Multiple)"),
|
||||
parseSequenceString("Alt+M"),
|
||||
ShortcutGroup::Move_top)},
|
||||
{"Player/aMoveTopCardsToGraveyardFaceDown",
|
||||
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard (Multiple), Face Down"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Move_top)},
|
||||
{"Player/aMoveTopCardToExile",
|
||||
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile"), parseSequenceString(""), ShortcutGroup::Move_top)},
|
||||
{"Player/aMoveTopCardsToExile", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile (Multiple)"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Move_top)},
|
||||
{"Player/aMoveTopCardsToExileFaceDown",
|
||||
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile (Multiple), Face Down"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Move_top)},
|
||||
{"Player/aMoveTopCardsUntil", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Stack Until Found"),
|
||||
parseSequenceString("Ctrl+Shift+Y"),
|
||||
ShortcutGroup::Move_top)},
|
||||
|
|
@ -620,11 +628,19 @@ private:
|
|||
{"Player/aMoveBottomCardsToGrave", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard (Multiple)"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Move_bottom)},
|
||||
{"Player/aMoveBottomCardsToGraveFaceDown",
|
||||
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Graveyard (Multiple), Face Down"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Move_bottom)},
|
||||
{"Player/aMoveBottomCardToExile",
|
||||
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile"), parseSequenceString(""), ShortcutGroup::Move_bottom)},
|
||||
{"Player/aMoveBottomCardsToExile", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile (Multiple)"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Move_bottom)},
|
||||
{"Player/aMoveBottomCardsToExileFaceDown",
|
||||
ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Exile (Multiple), Face Down"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Move_bottom)},
|
||||
{"Player/aMoveBottomCardToTop", ShortcutKey(QT_TRANSLATE_NOOP("shortcutsTab", "Top of Library"),
|
||||
parseSequenceString(""),
|
||||
ShortcutGroup::Move_bottom)},
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
#include "abstract_card_drag_item.h"
|
||||
|
||||
#include "../../client/settings/cache_settings.h"
|
||||
#include "../z_values.h"
|
||||
|
||||
#include <QCursor>
|
||||
#include <QDebug>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QPainter>
|
||||
|
||||
static const float CARD_WIDTH_HALF = CARD_WIDTH / 2;
|
||||
static const float CARD_HEIGHT_HALF = CARD_HEIGHT / 2;
|
||||
const QColor GHOST_MASK = QColor(255, 255, 255, 50);
|
||||
|
||||
AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
|
||||
|
|
@ -18,19 +17,19 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
|
|||
{
|
||||
if (parentDrag) {
|
||||
parentDrag->addChildDrag(this);
|
||||
setZValue(2000000007 + hotSpot.x() * 1000000 + hotSpot.y() * 1000 + 1000);
|
||||
setZValue(ZValues::childDragZValue(hotSpot.x(), hotSpot.y()));
|
||||
connect(parentDrag, &QObject::destroyed, this, &AbstractCardDragItem::deleteLater);
|
||||
} else {
|
||||
hotSpot = QPointF{qBound(0.0, hotSpot.x(), static_cast<qreal>(CARD_WIDTH - 1)),
|
||||
qBound(0.0, hotSpot.y(), static_cast<qreal>(CARD_HEIGHT - 1))};
|
||||
hotSpot = QPointF{qBound(0.0, hotSpot.x(), CardDimensions::WIDTH_F - 1),
|
||||
qBound(0.0, hotSpot.y(), CardDimensions::HEIGHT_F - 1)};
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
setZValue(2000000007);
|
||||
setZValue(ZValues::DRAG_ITEM);
|
||||
}
|
||||
if (item->getTapped())
|
||||
setTransform(QTransform()
|
||||
.translate(CARD_WIDTH_HALF, CARD_HEIGHT_HALF)
|
||||
.translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F)
|
||||
.rotate(90)
|
||||
.translate(-CARD_WIDTH_HALF, -CARD_HEIGHT_HALF));
|
||||
.translate(-CardDimensions::WIDTH_HALF_F, -CardDimensions::HEIGHT_HALF_F));
|
||||
|
||||
setCacheMode(DeviceCoordinateCache);
|
||||
|
||||
|
|
@ -47,7 +46,7 @@ AbstractCardDragItem::AbstractCardDragItem(AbstractCardItem *_item,
|
|||
QPainterPath AbstractCardDragItem::shape() const
|
||||
{
|
||||
QPainterPath shape;
|
||||
qreal cardCornerRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * CARD_WIDTH : 0.0;
|
||||
qreal cardCornerRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * CardDimensions::WIDTH_F : 0.0;
|
||||
shape.addRoundedRect(boundingRect(), cardCornerRadius, cardCornerRadius);
|
||||
return shape;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ public:
|
|||
AbstractCardDragItem(AbstractCardItem *_item, const QPointF &_hotSpot, AbstractCardDragItem *parentDrag = 0);
|
||||
[[nodiscard]] QRectF boundingRect() const override
|
||||
{
|
||||
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
|
||||
return QRectF(0, 0, CardDimensions::WIDTH_F, CardDimensions::HEIGHT_F);
|
||||
}
|
||||
[[nodiscard]] QPainterPath shape() const override;
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include "../../client/settings/cache_settings.h"
|
||||
#include "../../interface/card_picture_loader/card_picture_loader.h"
|
||||
#include "../game_scene.h"
|
||||
#include "../z_values.h"
|
||||
|
||||
#include <QCursor>
|
||||
#include <QGraphicsScene>
|
||||
|
|
@ -38,13 +39,13 @@ AbstractCardItem::~AbstractCardItem()
|
|||
|
||||
QRectF AbstractCardItem::boundingRect() const
|
||||
{
|
||||
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
|
||||
return QRectF(0, 0, CardDimensions::WIDTH_F, CardDimensions::HEIGHT_F);
|
||||
}
|
||||
|
||||
QPainterPath AbstractCardItem::shape() const
|
||||
{
|
||||
QPainterPath shape;
|
||||
qreal cardCornerRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * CARD_WIDTH : 0.0;
|
||||
qreal cardCornerRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * CardDimensions::WIDTH_F : 0.0;
|
||||
shape.addRoundedRect(boundingRect(), cardCornerRadius, cardCornerRadius);
|
||||
return shape;
|
||||
}
|
||||
|
|
@ -215,9 +216,9 @@ void AbstractCardItem::setHovered(bool _hovered)
|
|||
if (_hovered)
|
||||
processHoverEvent();
|
||||
isHovered = _hovered;
|
||||
setZValue(_hovered ? 2000000004 : realZValue);
|
||||
setZValue(_hovered ? ZValues::HOVERED_CARD : realZValue);
|
||||
setScale(_hovered && SettingsCache::instance().getScaleCards() ? 1.1 : 1);
|
||||
setTransformOriginPoint(_hovered ? CARD_WIDTH / 2 : 0, _hovered ? CARD_HEIGHT / 2 : 0);
|
||||
setTransformOriginPoint(_hovered ? CardDimensions::WIDTH_HALF_F : 0, _hovered ? CardDimensions::HEIGHT_HALF_F : 0);
|
||||
update();
|
||||
}
|
||||
|
||||
|
|
@ -273,9 +274,9 @@ void AbstractCardItem::setTapped(bool _tapped, bool canAnimate)
|
|||
else {
|
||||
tapAngle = tapped ? 90 : 0;
|
||||
setTransform(QTransform()
|
||||
.translate((float)CARD_WIDTH / 2, (float)CARD_HEIGHT / 2)
|
||||
.translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F)
|
||||
.rotate(tapAngle)
|
||||
.translate((float)-CARD_WIDTH / 2, (float)-CARD_HEIGHT / 2));
|
||||
.translate(-CardDimensions::WIDTH_HALF_F, -CardDimensions::HEIGHT_HALF_F));
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#define ABSTRACTCARDITEM_H
|
||||
|
||||
#include "../../game_graphics/board/graphics_item_type.h"
|
||||
#include "../card_dimensions.h"
|
||||
#include "arrow_target.h"
|
||||
|
||||
#include <libcockatrice/card/printing/exact_card.h>
|
||||
|
|
@ -15,9 +16,6 @@
|
|||
|
||||
class Player;
|
||||
|
||||
const int CARD_WIDTH = 72;
|
||||
const int CARD_HEIGHT = 102;
|
||||
|
||||
class AbstractCardItem : public ArrowTarget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "../player/player.h"
|
||||
#include "../player/player_actions.h"
|
||||
#include "../player/player_target.h"
|
||||
#include "../z_values.h"
|
||||
#include "../zones/card_zone.h"
|
||||
#include "card_item.h"
|
||||
|
||||
|
|
@ -18,12 +19,13 @@
|
|||
#include <libcockatrice/protocol/pb/command_create_arrow.pb.h>
|
||||
#include <libcockatrice/protocol/pb/command_delete_arrow.pb.h>
|
||||
#include <libcockatrice/utility/color.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
ArrowItem::ArrowItem(Player *_player, int _id, ArrowTarget *_startItem, ArrowTarget *_targetItem, const QColor &_color)
|
||||
: QGraphicsItem(), player(_player), id(_id), startItem(_startItem), targetItem(_targetItem), targetLocked(false),
|
||||
color(_color), fullColor(true)
|
||||
{
|
||||
setZValue(2000000005);
|
||||
setZValue(ZValues::ARROWS);
|
||||
|
||||
if (startItem)
|
||||
startItem->addArrowFrom(this);
|
||||
|
|
@ -238,16 +240,16 @@ void ArrowDragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|||
}
|
||||
|
||||
// if the card is in hand then we will move the card to stack or table as part of drawing the arrow
|
||||
if (startZone->getName() == "hand") {
|
||||
if (startZone->getName() == ZoneNames::HAND) {
|
||||
startCard->playCard(false);
|
||||
CardInfoPtr ci = startCard->getCard().getCardPtr();
|
||||
bool playToStack = SettingsCache::instance().getPlayToStack();
|
||||
if (ci &&
|
||||
((!playToStack && ci->getUiAttributes().tableRow == 3) ||
|
||||
(playToStack && ci->getUiAttributes().tableRow != 0 && startCard->getZone()->getName() != "stack")))
|
||||
cmd.set_start_zone("stack");
|
||||
if (ci && ((!playToStack && ci->getUiAttributes().tableRow == 3) ||
|
||||
(playToStack && ci->getUiAttributes().tableRow != 0 &&
|
||||
startCard->getZone()->getName() != ZoneNames::STACK)))
|
||||
cmd.set_start_zone(ZoneNames::STACK);
|
||||
else
|
||||
cmd.set_start_zone(playToStack ? "stack" : "table");
|
||||
cmd.set_start_zone(playToStack ? ZoneNames::STACK : ZoneNames::TABLE);
|
||||
}
|
||||
|
||||
if (deleteInPhase != 0) {
|
||||
|
|
@ -317,7 +319,7 @@ void ArrowAttachItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
void ArrowAttachItem::attachCards(CardItem *startCard, const CardItem *targetCard)
|
||||
{
|
||||
// do nothing if target is already attached to another card or is not in play
|
||||
if (targetCard->getAttachedTo() || targetCard->getZone()->getName() != "table") {
|
||||
if (targetCard->getAttachedTo() || targetCard->getZone()->getName() != ZoneNames::TABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -325,12 +327,12 @@ void ArrowAttachItem::attachCards(CardItem *startCard, const CardItem *targetCar
|
|||
CardZoneLogic *targetZone = targetCard->getZone();
|
||||
|
||||
// move card onto table first if attaching from some other zone
|
||||
if (startZone->getName() != "table") {
|
||||
if (startZone->getName() != ZoneNames::TABLE) {
|
||||
player->getPlayerActions()->playCardToTable(startCard, false);
|
||||
}
|
||||
|
||||
Command_AttachCard cmd;
|
||||
cmd.set_start_zone("table");
|
||||
cmd.set_start_zone(ZoneNames::TABLE);
|
||||
cmd.set_card_id(startCard->getId());
|
||||
cmd.set_target_player_id(targetZone->getPlayer()->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone(targetZone->getName().toStdString());
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@
|
|||
CardDragItem::CardDragItem(CardItem *_item,
|
||||
int _id,
|
||||
const QPointF &_hotSpot,
|
||||
bool _faceDown,
|
||||
bool _forceFaceDown,
|
||||
AbstractCardDragItem *parentDrag)
|
||||
: AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), faceDown(_faceDown), occupied(false), currentZone(0)
|
||||
: AbstractCardDragItem(_item, _hotSpot, parentDrag), id(_id), forceFaceDown(_forceFaceDown), occupied(false),
|
||||
currentZone(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class CardDragItem : public AbstractCardDragItem
|
|||
Q_OBJECT
|
||||
private:
|
||||
int id;
|
||||
bool faceDown;
|
||||
bool forceFaceDown;
|
||||
bool occupied;
|
||||
CardZone *currentZone;
|
||||
|
||||
|
|
@ -24,15 +24,15 @@ public:
|
|||
CardDragItem(CardItem *_item,
|
||||
int _id,
|
||||
const QPointF &_hotSpot,
|
||||
bool _faceDown,
|
||||
bool _forceFaceDown,
|
||||
AbstractCardDragItem *parentDrag = 0);
|
||||
int getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
bool getFaceDown() const
|
||||
bool isForceFaceDown() const
|
||||
{
|
||||
return faceDown;
|
||||
return forceFaceDown;
|
||||
}
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||
void updatePosition(const QPointF &cursorScenePos) override;
|
||||
|
|
|
|||
|
|
@ -212,10 +212,12 @@ void CardItem::setAttachedTo(CardItem *_attachedTo)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets the fields that should be reset after a zone transition
|
||||
*/
|
||||
void CardItem::resetState(bool keepAnnotations)
|
||||
{
|
||||
attacking = false;
|
||||
facedown = false;
|
||||
counters.clear();
|
||||
pt.clear();
|
||||
if (!keepAnnotations) {
|
||||
|
|
@ -251,10 +253,10 @@ void CardItem::processCardInfo(const ServerInfo_Card &_info)
|
|||
setDoesntUntap(_info.doesnt_untap());
|
||||
}
|
||||
|
||||
CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown)
|
||||
CardDragItem *CardItem::createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool forceFaceDown)
|
||||
{
|
||||
deleteDragItem();
|
||||
dragItem = new CardDragItem(this, _id, _pos, faceDown);
|
||||
dragItem = new CardDragItem(this, _id, _pos, forceFaceDown);
|
||||
dragItem->setVisible(false);
|
||||
scene()->addItem(dragItem);
|
||||
dragItem->updatePosition(_scenePos);
|
||||
|
|
@ -352,7 +354,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
|
||||
// Use the buttonDownPos to align the hot spot with the position when
|
||||
// the user originally clicked
|
||||
createDragItem(id, event->buttonDownPos(Qt::LeftButton), event->scenePos(), facedown || forceFaceDown);
|
||||
createDragItem(id, event->buttonDownPos(Qt::LeftButton), event->scenePos(), forceFaceDown);
|
||||
dragItem->grabMouse();
|
||||
|
||||
int childIndex = 0;
|
||||
|
|
@ -365,7 +367,7 @@ void CardItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
if (zone->getHasCardAttr())
|
||||
childPos = card->pos() - pos();
|
||||
else
|
||||
childPos = QPointF(childIndex * CARD_WIDTH / 2, 0);
|
||||
childPos = QPointF(childIndex * CardDimensions::WIDTH_HALF_F, 0);
|
||||
CardDragItem *drag =
|
||||
new CardDragItem(card, card->getId(), childPos, card->getFaceDown() || forceFaceDown, dragItem);
|
||||
drag->setPos(dragItem->pos() + childPos);
|
||||
|
|
@ -474,9 +476,9 @@ bool CardItem::animationEvent()
|
|||
}
|
||||
|
||||
setTransform(QTransform()
|
||||
.translate(CARD_WIDTH_HALF, CARD_HEIGHT_HALF)
|
||||
.translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F)
|
||||
.rotate(tapAngle)
|
||||
.translate(-CARD_WIDTH_HALF, -CARD_HEIGHT_HALF));
|
||||
.translate(-CardDimensions::WIDTH_HALF_F, -CardDimensions::HEIGHT_HALF_F));
|
||||
setHovered(false);
|
||||
update();
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ class QAction;
|
|||
class QColor;
|
||||
|
||||
const int MAX_COUNTERS_ON_CARD = 999;
|
||||
const float CARD_WIDTH_HALF = CARD_WIDTH / 2;
|
||||
const float CARD_HEIGHT_HALF = CARD_HEIGHT / 2;
|
||||
const int ROTATION_DEGREES_PER_FRAME = 10;
|
||||
|
||||
class CardItem : public AbstractCardItem
|
||||
|
|
@ -142,7 +140,7 @@ public:
|
|||
void processCardInfo(const ServerInfo_Card &_info);
|
||||
|
||||
bool animationEvent();
|
||||
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool faceDown);
|
||||
CardDragItem *createDragItem(int _id, const QPointF &_pos, const QPointF &_scenePos, bool forceFaceDown);
|
||||
void deleteDragItem();
|
||||
void drawArrow(const QColor &arrowColor);
|
||||
void drawAttachArrow();
|
||||
|
|
|
|||
29
cockatrice/src/game/card_dimensions.h
Normal file
29
cockatrice/src/game/card_dimensions.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef CARD_DIMENSIONS_H
|
||||
#define CARD_DIMENSIONS_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
/**
|
||||
* @file card_dimensions.h
|
||||
* @brief Canonical card dimension constants for layout and Z-value calculations.
|
||||
*
|
||||
* These values represent the logical pixel dimensions of a standard card graphic.
|
||||
* They are used throughout the game scene for layout, rendering, and Z-value computation.
|
||||
*/
|
||||
namespace CardDimensions
|
||||
{
|
||||
/// Card width in pixels
|
||||
constexpr int WIDTH = 72;
|
||||
/// Card height in pixels
|
||||
constexpr int HEIGHT = 102;
|
||||
|
||||
/// Pre-converted for floating-point contexts (Z-value calculations)
|
||||
constexpr qreal WIDTH_F = static_cast<qreal>(WIDTH);
|
||||
constexpr qreal HEIGHT_F = static_cast<qreal>(HEIGHT);
|
||||
|
||||
/// Half-dimensions for centering and rotation transforms
|
||||
constexpr qreal WIDTH_HALF_F = WIDTH_F / 2;
|
||||
constexpr qreal HEIGHT_HALF_F = HEIGHT_F / 2;
|
||||
} // namespace CardDimensions
|
||||
|
||||
#endif // CARD_DIMENSIONS_H
|
||||
|
|
@ -95,8 +95,9 @@ void DeckViewCard::paint(QPainter *painter, const QStyleOptionGraphicsItem *opti
|
|||
pen.setJoinStyle(Qt::MiterJoin);
|
||||
pen.setColor(originZone == DECK_ZONE_MAIN ? Qt::green : Qt::red);
|
||||
painter->setPen(pen);
|
||||
qreal cardRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * (CARD_WIDTH - 3) : 0.0;
|
||||
painter->drawRoundedRect(QRectF(1.5, 1.5, CARD_WIDTH - 3., CARD_HEIGHT - 3.), cardRadius, cardRadius);
|
||||
qreal cardRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * (CardDimensions::WIDTH_F - 3) : 0.0;
|
||||
painter->drawRoundedRect(QRectF(1.5, 1.5, CardDimensions::WIDTH_F - 3, CardDimensions::HEIGHT_F - 3), cardRadius,
|
||||
cardRadius);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +123,7 @@ void DeckViewCard::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
if (c == this)
|
||||
continue;
|
||||
++j;
|
||||
auto childPos = QPointF(j * CARD_WIDTH / 2, 0);
|
||||
auto childPos = QPointF(j * CardDimensions::WIDTH_HALF_F, 0);
|
||||
auto *drag = new DeckViewCardDragItem(c, childPos, dragItem);
|
||||
drag->setPos(dragItem->pos() + childPos);
|
||||
scene()->addItem(drag);
|
||||
|
|
@ -204,7 +205,7 @@ void DeckViewCardContainer::paint(QPainter *painter, const QStyleOptionGraphicsI
|
|||
painter->setPen(QColor(255, 255, 255, 100));
|
||||
painter->drawLine(QPointF(0, yUntilNow - paddingY / 2), QPointF(width, yUntilNow - paddingY / 2));
|
||||
}
|
||||
qreal thisRowHeight = CARD_HEIGHT * currentRowsAndCols[i].first;
|
||||
qreal thisRowHeight = CardDimensions::HEIGHT_F * currentRowsAndCols[i].first;
|
||||
QRectF textRect(0, yUntilNow, totalTextWidth, thisRowHeight);
|
||||
yUntilNow += thisRowHeight + paddingY;
|
||||
|
||||
|
|
@ -260,9 +261,9 @@ QSizeF DeckViewCardContainer::calculateBoundingRect(const QList<QPair<int, int>>
|
|||
|
||||
// Calculate space needed for cards
|
||||
for (int i = 0; i < rowsAndCols.size(); ++i) {
|
||||
totalHeight += CARD_HEIGHT * rowsAndCols[i].first + paddingY;
|
||||
if (CARD_WIDTH * rowsAndCols[i].second > totalWidth)
|
||||
totalWidth = CARD_WIDTH * rowsAndCols[i].second;
|
||||
totalHeight += CardDimensions::HEIGHT_F * rowsAndCols[i].first + paddingY;
|
||||
if (CardDimensions::WIDTH_F * rowsAndCols[i].second > totalWidth)
|
||||
totalWidth = CardDimensions::WIDTH_F * rowsAndCols[i].second;
|
||||
}
|
||||
|
||||
return QSizeF(getCardTypeTextWidth() + totalWidth, totalHeight + separatorY + paddingY);
|
||||
|
|
@ -289,9 +290,10 @@ void DeckViewCardContainer::rearrangeItems(const QList<QPair<int, int>> &rowsAnd
|
|||
std::sort(row.begin(), row.end(), DeckViewCardContainer::sortCardsByName);
|
||||
for (int j = 0; j < row.size(); ++j) {
|
||||
DeckViewCard *card = row[j];
|
||||
card->setPos(x + (j % tempCols) * CARD_WIDTH, yUntilNow + (j / tempCols) * CARD_HEIGHT);
|
||||
card->setPos(x + (j % tempCols) * CardDimensions::WIDTH_F,
|
||||
yUntilNow + (j / tempCols) * CardDimensions::HEIGHT_F);
|
||||
}
|
||||
yUntilNow += tempRows * CARD_HEIGHT + paddingY;
|
||||
yUntilNow += tempRows * CardDimensions::HEIGHT_F + paddingY;
|
||||
}
|
||||
|
||||
prepareGeometryChange();
|
||||
|
|
@ -392,7 +394,7 @@ void DeckViewScene::applySideboardPlan(const QList<MoveCard_ToZone> &plan)
|
|||
|
||||
void DeckViewScene::rearrangeItems()
|
||||
{
|
||||
const int spacing = CARD_HEIGHT / 3;
|
||||
const int spacing = CardDimensions::HEIGHT / 3;
|
||||
QList<DeckViewCardContainer *> contList = cardContainers.values();
|
||||
|
||||
// Initialize space requirements
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <QGraphicsView>
|
||||
#include <QSet>
|
||||
#include <QtMath>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
#include <numeric>
|
||||
|
||||
/**
|
||||
|
|
@ -410,9 +411,9 @@ void GameScene::toggleZoneView(Player *player, const QString &zoneName, int numb
|
|||
connect(item, &ZoneViewWidget::closePressed, this, &GameScene::removeZoneView);
|
||||
addItem(item);
|
||||
|
||||
if (zoneName == "grave")
|
||||
if (zoneName == ZoneNames::GRAVE)
|
||||
item->setPos(360, 100);
|
||||
else if (zoneName == "rfg")
|
||||
else if (zoneName == ZoneNames::EXILE)
|
||||
item->setPos(380, 120);
|
||||
else
|
||||
item->setPos(340, 80);
|
||||
|
|
|
|||
|
|
@ -10,16 +10,9 @@
|
|||
#include <../../client/settings/card_counter_settings.h>
|
||||
#include <libcockatrice/protocol/pb/context_move_card.pb.h>
|
||||
#include <libcockatrice/protocol/pb/context_mulligan.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
#include <utility>
|
||||
|
||||
static const QString TABLE_ZONE_NAME = "table";
|
||||
static const QString GRAVE_ZONE_NAME = "grave";
|
||||
static const QString EXILE_ZONE_NAME = "rfg";
|
||||
static const QString HAND_ZONE_NAME = "hand";
|
||||
static const QString DECK_ZONE_NAME = "deck";
|
||||
static const QString SIDEBOARD_ZONE_NAME = "sb";
|
||||
static const QString STACK_ZONE_NAME = "stack";
|
||||
|
||||
static QString sanitizeHtml(QString dirty)
|
||||
{
|
||||
return dirty.replace("&", "&").replace("<", "<").replace(">", ">").replace("\"", """);
|
||||
|
|
@ -37,15 +30,15 @@ MessageLogWidget::getFromStr(CardZoneLogic *zone, QString cardName, int position
|
|||
QString fromStr;
|
||||
QString zoneName = zone->getName();
|
||||
|
||||
if (zoneName == TABLE_ZONE_NAME) {
|
||||
if (zoneName == ZoneNames::TABLE) {
|
||||
fromStr = tr(" from play");
|
||||
} else if (zoneName == GRAVE_ZONE_NAME) {
|
||||
} else if (zoneName == ZoneNames::GRAVE) {
|
||||
fromStr = tr(" from their graveyard");
|
||||
} else if (zoneName == EXILE_ZONE_NAME) {
|
||||
} else if (zoneName == ZoneNames::EXILE) {
|
||||
fromStr = tr(" from exile");
|
||||
} else if (zoneName == HAND_ZONE_NAME) {
|
||||
} else if (zoneName == ZoneNames::HAND) {
|
||||
fromStr = tr(" from their hand");
|
||||
} else if (zoneName == DECK_ZONE_NAME) {
|
||||
} else if (zoneName == ZoneNames::DECK) {
|
||||
if (position == 0) {
|
||||
if (cardName.isEmpty()) {
|
||||
if (ownerChange) {
|
||||
|
|
@ -83,9 +76,9 @@ MessageLogWidget::getFromStr(CardZoneLogic *zone, QString cardName, int position
|
|||
fromStr = tr(" from their library");
|
||||
}
|
||||
}
|
||||
} else if (zoneName == SIDEBOARD_ZONE_NAME) {
|
||||
} else if (zoneName == ZoneNames::SIDEBOARD) {
|
||||
fromStr = tr(" from sideboard");
|
||||
} else if (zoneName == STACK_ZONE_NAME) {
|
||||
} else if (zoneName == ZoneNames::STACK) {
|
||||
fromStr = tr(" from the stack");
|
||||
} else {
|
||||
fromStr = tr(" from custom zone '%1'").arg(zoneName);
|
||||
|
|
@ -275,9 +268,9 @@ void MessageLogWidget::logMoveCard(Player *player,
|
|||
bool ownerChanged = startZone->getPlayer() != targetZone->getPlayer();
|
||||
|
||||
// do not log if moved within the same zone
|
||||
if ((startZoneName == TABLE_ZONE_NAME && targetZoneName == TABLE_ZONE_NAME && !ownerChanged) ||
|
||||
(startZoneName == HAND_ZONE_NAME && targetZoneName == HAND_ZONE_NAME) ||
|
||||
(startZoneName == EXILE_ZONE_NAME && targetZoneName == EXILE_ZONE_NAME)) {
|
||||
if ((startZoneName == ZoneNames::TABLE && targetZoneName == ZoneNames::TABLE && !ownerChanged) ||
|
||||
(startZoneName == ZoneNames::HAND && targetZoneName == ZoneNames::HAND) ||
|
||||
(startZoneName == ZoneNames::EXILE && targetZoneName == ZoneNames::EXILE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -306,20 +299,28 @@ void MessageLogWidget::logMoveCard(Player *player,
|
|||
|
||||
QString finalStr;
|
||||
std::optional<QString> fourthArg;
|
||||
if (targetZoneName == TABLE_ZONE_NAME) {
|
||||
if (targetZoneName == ZoneNames::TABLE) {
|
||||
soundEngine->playSound("play_card");
|
||||
if (card->getFaceDown()) {
|
||||
finalStr = tr("%1 puts %2 into play%3 face down.");
|
||||
} else {
|
||||
finalStr = tr("%1 puts %2 into play%3.");
|
||||
}
|
||||
} else if (targetZoneName == GRAVE_ZONE_NAME) {
|
||||
finalStr = tr("%1 puts %2%3 into their graveyard.");
|
||||
} else if (targetZoneName == EXILE_ZONE_NAME) {
|
||||
finalStr = tr("%1 exiles %2%3.");
|
||||
} else if (targetZoneName == HAND_ZONE_NAME) {
|
||||
} else if (targetZoneName == ZoneNames::GRAVE) {
|
||||
if (card->getFaceDown()) {
|
||||
finalStr = tr("%1 puts %2%3 into their graveyard face down.");
|
||||
} else {
|
||||
finalStr = tr("%1 puts %2%3 into their graveyard.");
|
||||
}
|
||||
} else if (targetZoneName == ZoneNames::EXILE) {
|
||||
if (card->getFaceDown()) {
|
||||
finalStr = tr("%1 exiles %2%3 face down.");
|
||||
} else {
|
||||
finalStr = tr("%1 exiles %2%3.");
|
||||
}
|
||||
} else if (targetZoneName == ZoneNames::HAND) {
|
||||
finalStr = tr("%1 moves %2%3 to their hand.");
|
||||
} else if (targetZoneName == DECK_ZONE_NAME) {
|
||||
} else if (targetZoneName == ZoneNames::DECK) {
|
||||
if (newX == -1) {
|
||||
finalStr = tr("%1 puts %2%3 into their library.");
|
||||
} else if (newX >= targetZone->getCards().size()) {
|
||||
|
|
@ -331,14 +332,22 @@ void MessageLogWidget::logMoveCard(Player *player,
|
|||
fourthArg = QString::number(newX);
|
||||
finalStr = tr("%1 puts %2%3 into their library %4 cards from the top.");
|
||||
}
|
||||
} else if (targetZoneName == SIDEBOARD_ZONE_NAME) {
|
||||
} else if (targetZoneName == ZoneNames::SIDEBOARD) {
|
||||
finalStr = tr("%1 moves %2%3 to sideboard.");
|
||||
} else if (targetZoneName == STACK_ZONE_NAME) {
|
||||
} else if (targetZoneName == ZoneNames::STACK) {
|
||||
soundEngine->playSound("play_card");
|
||||
finalStr = tr("%1 plays %2%3.");
|
||||
if (card->getFaceDown()) {
|
||||
finalStr = tr("%1 plays %2%3 face down.");
|
||||
} else {
|
||||
finalStr = tr("%1 plays %2%3.");
|
||||
}
|
||||
} else {
|
||||
fourthArg = targetZoneName;
|
||||
finalStr = tr("%1 moves %2%3 to custom zone '%4'.");
|
||||
if (card->getFaceDown()) {
|
||||
finalStr = tr("%1 moves %2%3 to custom zone '%4' face down.");
|
||||
} else {
|
||||
finalStr = tr("%1 moves %2%3 to custom zone '%4'.");
|
||||
}
|
||||
}
|
||||
|
||||
QString message = finalStr.arg(sanitizeHtml(player->getPlayerInfo()->getName()), cardStr, nameFrom.second);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <libcockatrice/protocol/pb/command_next_turn.pb.h>
|
||||
#include <libcockatrice/protocol/pb/command_set_active_phase.pb.h>
|
||||
#include <libcockatrice/protocol/pb/command_set_card_attr.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
PhaseButton::PhaseButton(const QString &_name, QGraphicsItem *parent, QAction *_doubleClickAction, bool _highlightable)
|
||||
: QObject(), QGraphicsItem(parent), name(_name), active(false), highlightable(_highlightable),
|
||||
|
|
@ -259,7 +260,7 @@ void PhasesToolbar::actNextTurn()
|
|||
void PhasesToolbar::actUntapAll()
|
||||
{
|
||||
Command_SetCardAttr cmd;
|
||||
cmd.set_zone("table");
|
||||
cmd.set_zone(ZoneNames::TABLE);
|
||||
cmd.set_attribute(AttrTapped);
|
||||
cmd.set_attr_value("0");
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/card/relation/card_relation.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive)
|
||||
: player(_player), card(_card), shortcutsActive(_shortcutsActive)
|
||||
|
|
@ -115,11 +116,12 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive
|
|||
} else if (writeableCard) {
|
||||
|
||||
if (card->getZone()) {
|
||||
if (card->getZone()->getName() == "table") {
|
||||
if (card->getZone()->getName() == ZoneNames::TABLE) {
|
||||
createTableMenu();
|
||||
} else if (card->getZone()->getName() == "stack") {
|
||||
} else if (card->getZone()->getName() == ZoneNames::STACK) {
|
||||
createStackMenu();
|
||||
} else if (card->getZone()->getName() == "rfg" || card->getZone()->getName() == "grave") {
|
||||
} else if (card->getZone()->getName() == ZoneNames::EXILE ||
|
||||
card->getZone()->getName() == ZoneNames::GRAVE) {
|
||||
createGraveyardOrExileMenu();
|
||||
} else {
|
||||
createHandOrCustomZoneMenu();
|
||||
|
|
@ -128,7 +130,7 @@ CardMenu::CardMenu(Player *_player, const CardItem *_card, bool _shortcutsActive
|
|||
addMenu(new MoveMenu(player));
|
||||
}
|
||||
} else {
|
||||
if (card->getZone() && card->getZone()->getName() != "hand") {
|
||||
if (card->getZone() && card->getZone()->getName() != ZoneNames::HAND) {
|
||||
addAction(aDrawArrow);
|
||||
addSeparator();
|
||||
addRelatedCardView();
|
||||
|
|
@ -285,7 +287,7 @@ void CardMenu::createHandOrCustomZoneMenu()
|
|||
addMenu(new MoveMenu(player));
|
||||
|
||||
// actions that are really wonky when done from deck or sideboard
|
||||
if (card->getZone()->getName() == "hand") {
|
||||
if (card->getZone()->getName() == ZoneNames::HAND) {
|
||||
addSeparator();
|
||||
addAction(aAttach);
|
||||
addAction(aDrawArrow);
|
||||
|
|
@ -298,7 +300,7 @@ void CardMenu::createHandOrCustomZoneMenu()
|
|||
}
|
||||
|
||||
addRelatedCardView();
|
||||
if (card->getZone()->getName() == "hand") {
|
||||
if (card->getZone()->getName() == ZoneNames::HAND) {
|
||||
addRelatedCardActions();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
GraveyardMenu::GraveyardMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
|
||||
{
|
||||
|
|
@ -39,16 +40,16 @@ void GraveyardMenu::createMoveActions()
|
|||
|
||||
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) {
|
||||
aMoveGraveToTopLibrary = new QAction(this);
|
||||
aMoveGraveToTopLibrary->setData(QList<QVariant>() << "deck" << 0);
|
||||
aMoveGraveToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0);
|
||||
|
||||
aMoveGraveToBottomLibrary = new QAction(this);
|
||||
aMoveGraveToBottomLibrary->setData(QList<QVariant>() << "deck" << -1);
|
||||
aMoveGraveToBottomLibrary->setData(QList<QVariant>() << ZoneNames::DECK << -1);
|
||||
|
||||
aMoveGraveToHand = new QAction(this);
|
||||
aMoveGraveToHand->setData(QList<QVariant>() << "hand" << 0);
|
||||
aMoveGraveToHand->setData(QList<QVariant>() << ZoneNames::HAND << 0);
|
||||
|
||||
aMoveGraveToRfg = new QAction(this);
|
||||
aMoveGraveToRfg->setData(QList<QVariant>() << "rfg" << 0);
|
||||
aMoveGraveToRfg->setData(QList<QVariant>() << ZoneNames::EXILE << 0);
|
||||
|
||||
connect(aMoveGraveToTopLibrary, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone);
|
||||
connect(aMoveGraveToBottomLibrary, &QAction::triggered, grave, &PileZoneLogic::moveAllToZone);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
HandMenu::HandMenu(Player *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player)
|
||||
{
|
||||
|
|
@ -76,13 +77,13 @@ HandMenu::HandMenu(Player *_player, PlayerActions *actions, QWidget *parent) : T
|
|||
|
||||
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) {
|
||||
aMoveHandToTopLibrary = new QAction(this);
|
||||
aMoveHandToTopLibrary->setData(QList<QVariant>() << "deck" << 0);
|
||||
aMoveHandToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0);
|
||||
aMoveHandToBottomLibrary = new QAction(this);
|
||||
aMoveHandToBottomLibrary->setData(QList<QVariant>() << "deck" << -1);
|
||||
aMoveHandToBottomLibrary->setData(QList<QVariant>() << ZoneNames::DECK << -1);
|
||||
aMoveHandToGrave = new QAction(this);
|
||||
aMoveHandToGrave->setData(QList<QVariant>() << "grave" << 0);
|
||||
aMoveHandToGrave->setData(QList<QVariant>() << ZoneNames::GRAVE << 0);
|
||||
aMoveHandToRfg = new QAction(this);
|
||||
aMoveHandToRfg->setData(QList<QVariant>() << "rfg" << 0);
|
||||
aMoveHandToRfg->setData(QList<QVariant>() << ZoneNames::EXILE << 0);
|
||||
|
||||
auto hand = player->getHandZone();
|
||||
|
||||
|
|
|
|||
|
|
@ -51,8 +51,10 @@ LibraryMenu::LibraryMenu(Player *_player, QWidget *parent) : TearOffMenu(parent)
|
|||
topLibraryMenu->addSeparator();
|
||||
topLibraryMenu->addAction(aMoveTopCardToGraveyard);
|
||||
topLibraryMenu->addAction(aMoveTopCardsToGraveyard);
|
||||
topLibraryMenu->addAction(aMoveTopCardsToGraveyardFaceDown);
|
||||
topLibraryMenu->addAction(aMoveTopCardToExile);
|
||||
topLibraryMenu->addAction(aMoveTopCardsToExile);
|
||||
topLibraryMenu->addAction(aMoveTopCardsToExileFaceDown);
|
||||
topLibraryMenu->addAction(aMoveTopCardsUntil);
|
||||
topLibraryMenu->addSeparator();
|
||||
topLibraryMenu->addAction(aShuffleTopCards);
|
||||
|
|
@ -66,8 +68,10 @@ LibraryMenu::LibraryMenu(Player *_player, QWidget *parent) : TearOffMenu(parent)
|
|||
bottomLibraryMenu->addSeparator();
|
||||
bottomLibraryMenu->addAction(aMoveBottomCardToGraveyard);
|
||||
bottomLibraryMenu->addAction(aMoveBottomCardsToGraveyard);
|
||||
bottomLibraryMenu->addAction(aMoveBottomCardsToGraveyardFaceDown);
|
||||
bottomLibraryMenu->addAction(aMoveBottomCardToExile);
|
||||
bottomLibraryMenu->addAction(aMoveBottomCardsToExile);
|
||||
bottomLibraryMenu->addAction(aMoveBottomCardsToExileFaceDown);
|
||||
bottomLibraryMenu->addSeparator();
|
||||
bottomLibraryMenu->addAction(aShuffleBottomCards);
|
||||
|
||||
|
|
@ -136,8 +140,14 @@ void LibraryMenu::createMoveActions()
|
|||
connect(aMoveTopCardToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToExile);
|
||||
aMoveTopCardsToGraveyard = new QAction(this);
|
||||
connect(aMoveTopCardsToGraveyard, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsToGrave);
|
||||
aMoveTopCardsToGraveyardFaceDown = new QAction(this);
|
||||
connect(aMoveTopCardsToGraveyardFaceDown, &QAction::triggered, playerActions,
|
||||
&PlayerActions::actMoveTopCardsToGraveFaceDown);
|
||||
aMoveTopCardsToExile = new QAction(this);
|
||||
connect(aMoveTopCardsToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsToExile);
|
||||
aMoveTopCardsToExileFaceDown = new QAction(this);
|
||||
connect(aMoveTopCardsToExileFaceDown, &QAction::triggered, playerActions,
|
||||
&PlayerActions::actMoveTopCardsToExileFaceDown);
|
||||
aMoveTopCardsUntil = new QAction(this);
|
||||
connect(aMoveTopCardsUntil, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsUntil);
|
||||
aMoveTopCardToBottom = new QAction(this);
|
||||
|
|
@ -156,8 +166,14 @@ void LibraryMenu::createMoveActions()
|
|||
aMoveBottomCardsToGraveyard = new QAction(this);
|
||||
connect(aMoveBottomCardsToGraveyard, &QAction::triggered, playerActions,
|
||||
&PlayerActions::actMoveBottomCardsToGrave);
|
||||
aMoveBottomCardsToGraveyardFaceDown = new QAction(this);
|
||||
connect(aMoveBottomCardsToGraveyardFaceDown, &QAction::triggered, playerActions,
|
||||
&PlayerActions::actMoveBottomCardsToGraveFaceDown);
|
||||
aMoveBottomCardsToExile = new QAction(this);
|
||||
connect(aMoveBottomCardsToExile, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardsToExile);
|
||||
aMoveBottomCardsToExileFaceDown = new QAction(this);
|
||||
connect(aMoveBottomCardsToExileFaceDown, &QAction::triggered, playerActions,
|
||||
&PlayerActions::actMoveBottomCardsToExileFaceDown);
|
||||
aMoveBottomCardToTop = new QAction(this);
|
||||
connect(aMoveBottomCardToTop, &QAction::triggered, playerActions, &PlayerActions::actMoveBottomCardToTop);
|
||||
}
|
||||
|
|
@ -216,7 +232,9 @@ void LibraryMenu::retranslateUi()
|
|||
aMoveTopCardToGraveyard->setText(tr("Move top card to grave&yard"));
|
||||
aMoveTopCardToExile->setText(tr("Move top card to e&xile"));
|
||||
aMoveTopCardsToGraveyard->setText(tr("Move top cards to &graveyard..."));
|
||||
aMoveTopCardsToGraveyardFaceDown->setText(tr("Move top cards to graveyard face down..."));
|
||||
aMoveTopCardsToExile->setText(tr("Move top cards to &exile..."));
|
||||
aMoveTopCardsToExileFaceDown->setText(tr("Move top cards to exile face down..."));
|
||||
aMoveTopCardsUntil->setText(tr("Put top cards on stack &until..."));
|
||||
aShuffleTopCards->setText(tr("Shuffle top cards..."));
|
||||
|
||||
|
|
@ -227,7 +245,9 @@ void LibraryMenu::retranslateUi()
|
|||
aMoveBottomCardToGraveyard->setText(tr("Move bottom card to grave&yard"));
|
||||
aMoveBottomCardToExile->setText(tr("Move bottom card to e&xile"));
|
||||
aMoveBottomCardsToGraveyard->setText(tr("Move bottom cards to &graveyard..."));
|
||||
aMoveBottomCardsToGraveyardFaceDown->setText(tr("Move bottom cards to graveyard face down..."));
|
||||
aMoveBottomCardsToExile->setText(tr("Move bottom cards to &exile..."));
|
||||
aMoveBottomCardsToExileFaceDown->setText(tr("Move bottom cards to exile face down..."));
|
||||
aMoveBottomCardToTop->setText(tr("Put bottom card on &top"));
|
||||
aShuffleBottomCards->setText(tr("Shuffle bottom cards..."));
|
||||
}
|
||||
|
|
@ -335,8 +355,10 @@ void LibraryMenu::setShortcutsActive()
|
|||
aMoveTopToPlayFaceDown->setShortcuts(shortcuts.getShortcut("Player/aMoveTopToPlayFaceDown"));
|
||||
aMoveTopCardToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardToGraveyard"));
|
||||
aMoveTopCardsToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardsToGraveyard"));
|
||||
aMoveTopCardsToGraveyardFaceDown->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardsToGraveyardFaceDown"));
|
||||
aMoveTopCardToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardToExile"));
|
||||
aMoveTopCardsToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardsToExile"));
|
||||
aMoveTopCardsToExileFaceDown->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardsToExileFaceDown"));
|
||||
aMoveTopCardsUntil->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardsUntil"));
|
||||
aMoveTopCardToBottom->setShortcuts(shortcuts.getShortcut("Player/aMoveTopCardToBottom"));
|
||||
aDrawBottomCard->setShortcuts(shortcuts.getShortcut("Player/aDrawBottomCard"));
|
||||
|
|
@ -345,8 +367,10 @@ void LibraryMenu::setShortcutsActive()
|
|||
aMoveBottomToPlayFaceDown->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomToPlayFaceDown"));
|
||||
aMoveBottomCardToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardToGrave"));
|
||||
aMoveBottomCardsToGraveyard->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardsToGrave"));
|
||||
aMoveBottomCardsToGraveyardFaceDown->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardsToGraveFaceDown"));
|
||||
aMoveBottomCardToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardToExile"));
|
||||
aMoveBottomCardsToExile->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardsToExile"));
|
||||
aMoveBottomCardsToExileFaceDown->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardsToExileFaceDown"));
|
||||
aMoveBottomCardToTop->setShortcuts(shortcuts.getShortcut("Player/aMoveBottomCardToTop"));
|
||||
}
|
||||
|
||||
|
|
@ -367,8 +391,10 @@ void LibraryMenu::setShortcutsInactive()
|
|||
aMoveTopToPlayFaceDown->setShortcut(QKeySequence());
|
||||
aMoveTopCardToGraveyard->setShortcut(QKeySequence());
|
||||
aMoveTopCardsToGraveyard->setShortcut(QKeySequence());
|
||||
aMoveTopCardsToGraveyardFaceDown->setShortcut(QKeySequence());
|
||||
aMoveTopCardToExile->setShortcut(QKeySequence());
|
||||
aMoveTopCardsToExile->setShortcut(QKeySequence());
|
||||
aMoveTopCardsToExileFaceDown->setShortcut(QKeySequence());
|
||||
aMoveTopCardsUntil->setShortcut(QKeySequence());
|
||||
aDrawBottomCard->setShortcut(QKeySequence());
|
||||
aDrawBottomCards->setShortcut(QKeySequence());
|
||||
|
|
@ -376,6 +402,8 @@ void LibraryMenu::setShortcutsInactive()
|
|||
aMoveBottomToPlayFaceDown->setShortcut(QKeySequence());
|
||||
aMoveBottomCardToGraveyard->setShortcut(QKeySequence());
|
||||
aMoveBottomCardsToGraveyard->setShortcut(QKeySequence());
|
||||
aMoveBottomCardsToGraveyardFaceDown->setShortcut(QKeySequence());
|
||||
aMoveBottomCardToExile->setShortcut(QKeySequence());
|
||||
aMoveBottomCardsToExile->setShortcut(QKeySequence());
|
||||
aMoveBottomCardsToExileFaceDown->setShortcut(QKeySequence());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,9 @@ public:
|
|||
QAction *aMoveTopCardToGraveyard = nullptr;
|
||||
QAction *aMoveTopCardToExile = nullptr;
|
||||
QAction *aMoveTopCardsToGraveyard = nullptr;
|
||||
QAction *aMoveTopCardsToGraveyardFaceDown = nullptr;
|
||||
QAction *aMoveTopCardsToExile = nullptr;
|
||||
QAction *aMoveTopCardsToExileFaceDown = nullptr;
|
||||
QAction *aMoveTopCardsUntil = nullptr;
|
||||
QAction *aShuffleTopCards = nullptr;
|
||||
|
||||
|
|
@ -100,7 +102,9 @@ public:
|
|||
QAction *aMoveBottomCardToGraveyard = nullptr;
|
||||
QAction *aMoveBottomCardToExile = nullptr;
|
||||
QAction *aMoveBottomCardsToGraveyard = nullptr;
|
||||
QAction *aMoveBottomCardsToGraveyardFaceDown = nullptr;
|
||||
QAction *aMoveBottomCardsToExile = nullptr;
|
||||
QAction *aMoveBottomCardsToExileFaceDown = nullptr;
|
||||
QAction *aShuffleBottomCards = nullptr;
|
||||
|
||||
int defaultNumberTopCards = 1;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "../player.h"
|
||||
#include "../player_actions.h"
|
||||
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
RfgMenu::RfgMenu(Player *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
|
||||
{
|
||||
createMoveActions();
|
||||
|
|
@ -30,13 +32,13 @@ void RfgMenu::createMoveActions()
|
|||
auto rfg = player->getRfgZone();
|
||||
|
||||
aMoveRfgToTopLibrary = new QAction(this);
|
||||
aMoveRfgToTopLibrary->setData(QList<QVariant>() << "deck" << 0);
|
||||
aMoveRfgToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0);
|
||||
aMoveRfgToBottomLibrary = new QAction(this);
|
||||
aMoveRfgToBottomLibrary->setData(QList<QVariant>() << "deck" << -1);
|
||||
aMoveRfgToBottomLibrary->setData(QList<QVariant>() << ZoneNames::DECK << -1);
|
||||
aMoveRfgToHand = new QAction(this);
|
||||
aMoveRfgToHand->setData(QList<QVariant>() << "hand" << 0);
|
||||
aMoveRfgToHand->setData(QList<QVariant>() << ZoneNames::HAND << 0);
|
||||
aMoveRfgToGrave = new QAction(this);
|
||||
aMoveRfgToGrave->setData(QList<QVariant>() << "grave" << 0);
|
||||
aMoveRfgToGrave->setData(QList<QVariant>() << ZoneNames::GRAVE << 0);
|
||||
|
||||
connect(aMoveRfgToTopLibrary, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone);
|
||||
connect(aMoveRfgToBottomLibrary, &QAction::triggered, rfg, &PileZoneLogic::moveAllToZone);
|
||||
|
|
|
|||
|
|
@ -61,15 +61,15 @@ void Player::forwardActionSignalsToEventHandler()
|
|||
|
||||
void Player::initializeZones()
|
||||
{
|
||||
addZone(new PileZoneLogic(this, "deck", false, true, false, this));
|
||||
addZone(new PileZoneLogic(this, "grave", false, false, true, this));
|
||||
addZone(new PileZoneLogic(this, "rfg", false, false, true, this));
|
||||
addZone(new PileZoneLogic(this, "sb", false, false, false, this));
|
||||
addZone(new TableZoneLogic(this, "table", true, false, true, this));
|
||||
addZone(new StackZoneLogic(this, "stack", true, false, true, this));
|
||||
addZone(new PileZoneLogic(this, ZoneNames::DECK, false, true, false, this));
|
||||
addZone(new PileZoneLogic(this, ZoneNames::GRAVE, false, false, true, this));
|
||||
addZone(new PileZoneLogic(this, ZoneNames::EXILE, false, false, true, this));
|
||||
addZone(new PileZoneLogic(this, ZoneNames::SIDEBOARD, false, false, false, this));
|
||||
addZone(new TableZoneLogic(this, ZoneNames::TABLE, true, false, true, this));
|
||||
addZone(new StackZoneLogic(this, ZoneNames::STACK, true, false, true, this));
|
||||
bool visibleHand = playerInfo->getLocalOrJudge() ||
|
||||
(game->getPlayerManager()->isSpectator() && game->getGameMetaInfo()->spectatorsOmniscient());
|
||||
addZone(new HandZoneLogic(this, "hand", false, false, visibleHand, this));
|
||||
addZone(new HandZoneLogic(this, ZoneNames::HAND, false, false, visibleHand, this));
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
|
|
@ -119,13 +119,13 @@ void Player::setZoneId(int _zoneId)
|
|||
void Player::processPlayerInfo(const ServerInfo_Player &info)
|
||||
{
|
||||
static QSet<QString> builtinZones{/* PileZones */
|
||||
"deck", "grave", "rfg", "sb",
|
||||
ZoneNames::DECK, ZoneNames::GRAVE, ZoneNames::EXILE, ZoneNames::SIDEBOARD,
|
||||
/* TableZone */
|
||||
"table",
|
||||
ZoneNames::TABLE,
|
||||
/* StackZone */
|
||||
"stack",
|
||||
ZoneNames::STACK,
|
||||
/* HandZone */
|
||||
"hand"};
|
||||
ZoneNames::HAND};
|
||||
clearCounters();
|
||||
clearArrows();
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include <libcockatrice/filters/filter_string.h>
|
||||
#include <libcockatrice/protocol/pb/card_attributes.pb.h>
|
||||
#include <libcockatrice/protocol/pb/game_event.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
inline Q_LOGGING_CATEGORY(PlayerLog, "player");
|
||||
|
||||
|
|
@ -155,37 +156,37 @@ public:
|
|||
|
||||
PileZoneLogic *getDeckZone()
|
||||
{
|
||||
return qobject_cast<PileZoneLogic *>(zones.value("deck"));
|
||||
return qobject_cast<PileZoneLogic *>(zones.value(ZoneNames::DECK));
|
||||
}
|
||||
|
||||
PileZoneLogic *getGraveZone()
|
||||
{
|
||||
return qobject_cast<PileZoneLogic *>(zones.value("grave"));
|
||||
return qobject_cast<PileZoneLogic *>(zones.value(ZoneNames::GRAVE));
|
||||
}
|
||||
|
||||
PileZoneLogic *getRfgZone()
|
||||
{
|
||||
return qobject_cast<PileZoneLogic *>(zones.value("rfg"));
|
||||
return qobject_cast<PileZoneLogic *>(zones.value(ZoneNames::EXILE));
|
||||
}
|
||||
|
||||
PileZoneLogic *getSideboardZone()
|
||||
{
|
||||
return qobject_cast<PileZoneLogic *>(zones.value("sb"));
|
||||
return qobject_cast<PileZoneLogic *>(zones.value(ZoneNames::SIDEBOARD));
|
||||
}
|
||||
|
||||
TableZoneLogic *getTableZone()
|
||||
{
|
||||
return qobject_cast<TableZoneLogic *>(zones.value("table"));
|
||||
return qobject_cast<TableZoneLogic *>(zones.value(ZoneNames::TABLE));
|
||||
}
|
||||
|
||||
StackZoneLogic *getStackZone()
|
||||
{
|
||||
return qobject_cast<StackZoneLogic *>(zones.value("stack"));
|
||||
return qobject_cast<StackZoneLogic *>(zones.value(ZoneNames::STACK));
|
||||
}
|
||||
|
||||
HandZoneLogic *getHandZone()
|
||||
{
|
||||
return qobject_cast<HandZoneLogic *>(zones.value("hand"));
|
||||
return qobject_cast<HandZoneLogic *>(zones.value(ZoneNames::HAND));
|
||||
}
|
||||
|
||||
AbstractCounter *addCounter(const ServerInfo_Counter &counter);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include <libcockatrice/protocol/pb/command_undo_draw.pb.h>
|
||||
#include <libcockatrice/protocol/pb/context_move_card.pb.h>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
// milliseconds in between triggers of the move top cards until action
|
||||
static constexpr int MOVE_TOP_CARD_UNTIL_INTERVAL = 100;
|
||||
|
|
@ -63,13 +64,13 @@ void PlayerActions::playCard(CardItem *card, bool faceDown)
|
|||
int tableRow = info.getUiAttributes().tableRow;
|
||||
bool playToStack = SettingsCache::instance().getPlayToStack();
|
||||
QString currentZone = card->getZone()->getName();
|
||||
if (currentZone == "stack" && tableRow == 3) {
|
||||
cmd.set_target_zone("grave");
|
||||
if (currentZone == ZoneNames::STACK && tableRow == 3) {
|
||||
cmd.set_target_zone(ZoneNames::GRAVE);
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
} else if (!faceDown &&
|
||||
((!playToStack && tableRow == 3) || ((playToStack && tableRow != 0) && currentZone != "stack"))) {
|
||||
cmd.set_target_zone("stack");
|
||||
} else if (!faceDown && ((!playToStack && tableRow == 3) ||
|
||||
((playToStack && tableRow != 0) && currentZone != ZoneNames::STACK))) {
|
||||
cmd.set_target_zone(ZoneNames::STACK);
|
||||
cmd.set_x(-1);
|
||||
cmd.set_y(0);
|
||||
} else {
|
||||
|
|
@ -81,7 +82,7 @@ void PlayerActions::playCard(CardItem *card, bool faceDown)
|
|||
}
|
||||
cardToMove->set_tapped(!faceDown && info.getUiAttributes().cipt);
|
||||
if (tableRow != 3)
|
||||
cmd.set_target_zone("table");
|
||||
cmd.set_target_zone(ZoneNames::TABLE);
|
||||
cmd.set_x(gridPoint.x());
|
||||
cmd.set_y(gridPoint.y());
|
||||
}
|
||||
|
|
@ -124,7 +125,7 @@ void PlayerActions::playCardToTable(const CardItem *card, bool faceDown)
|
|||
cardToMove->set_pt(info.getPowTough().toStdString());
|
||||
}
|
||||
cardToMove->set_tapped(!faceDown && info.getUiAttributes().cipt);
|
||||
cmd.set_target_zone("table");
|
||||
cmd.set_target_zone(ZoneNames::TABLE);
|
||||
cmd.set_x(gridPoint.x());
|
||||
cmd.set_y(gridPoint.y());
|
||||
sendGameCommand(cmd);
|
||||
|
|
@ -132,12 +133,12 @@ void PlayerActions::playCardToTable(const CardItem *card, bool faceDown)
|
|||
|
||||
void PlayerActions::actViewLibrary()
|
||||
{
|
||||
player->getGameScene()->toggleZoneView(player, "deck", -1);
|
||||
player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, -1);
|
||||
}
|
||||
|
||||
void PlayerActions::actViewHand()
|
||||
{
|
||||
player->getGameScene()->toggleZoneView(player, "hand", -1);
|
||||
player->getGameScene()->toggleZoneView(player, ZoneNames::HAND, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -181,7 +182,7 @@ void PlayerActions::actViewTopCards()
|
|||
deckSize, 1, &ok);
|
||||
if (ok) {
|
||||
defaultNumberTopCards = number;
|
||||
player->getGameScene()->toggleZoneView(player, "deck", number);
|
||||
player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, number);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -194,14 +195,14 @@ void PlayerActions::actViewBottomCards()
|
|||
deckSize, 1, &ok);
|
||||
if (ok) {
|
||||
defaultNumberBottomCards = number;
|
||||
player->getGameScene()->toggleZoneView(player, "deck", number, true);
|
||||
player->getGameScene()->toggleZoneView(player, ZoneNames::DECK, number, true);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerActions::actAlwaysRevealTopCard()
|
||||
{
|
||||
Command_ChangeZoneProperties cmd;
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_zone_name(ZoneNames::DECK);
|
||||
cmd.set_always_reveal_top_card(player->getPlayerMenu()->getLibraryMenu()->isAlwaysRevealTopCardChecked());
|
||||
|
||||
sendGameCommand(cmd);
|
||||
|
|
@ -210,7 +211,7 @@ void PlayerActions::actAlwaysRevealTopCard()
|
|||
void PlayerActions::actAlwaysLookAtTopCard()
|
||||
{
|
||||
Command_ChangeZoneProperties cmd;
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_zone_name(ZoneNames::DECK);
|
||||
cmd.set_always_look_at_top_card(player->getPlayerMenu()->getLibraryMenu()->isAlwaysLookAtTopCardChecked());
|
||||
|
||||
sendGameCommand(cmd);
|
||||
|
|
@ -223,17 +224,17 @@ void PlayerActions::actOpenDeckInDeckEditor()
|
|||
|
||||
void PlayerActions::actViewGraveyard()
|
||||
{
|
||||
player->getGameScene()->toggleZoneView(player, "grave", -1);
|
||||
player->getGameScene()->toggleZoneView(player, ZoneNames::GRAVE, -1);
|
||||
}
|
||||
|
||||
void PlayerActions::actViewRfg()
|
||||
{
|
||||
player->getGameScene()->toggleZoneView(player, "rfg", -1);
|
||||
player->getGameScene()->toggleZoneView(player, ZoneNames::EXILE, -1);
|
||||
}
|
||||
|
||||
void PlayerActions::actViewSideboard()
|
||||
{
|
||||
player->getGameScene()->toggleZoneView(player, "sb", -1);
|
||||
player->getGameScene()->toggleZoneView(player, ZoneNames::SIDEBOARD, -1);
|
||||
}
|
||||
|
||||
void PlayerActions::actShuffle()
|
||||
|
|
@ -263,7 +264,7 @@ void PlayerActions::actShuffleTop()
|
|||
defaultNumberTopCards = number;
|
||||
|
||||
Command_Shuffle cmd;
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_zone_name(ZoneNames::DECK);
|
||||
cmd.set_start(0);
|
||||
cmd.set_end(number - 1); // inclusive, the indexed card at end will be shuffled
|
||||
|
||||
|
|
@ -292,7 +293,7 @@ void PlayerActions::actShuffleBottom()
|
|||
defaultNumberBottomCards = number;
|
||||
|
||||
Command_Shuffle cmd;
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_zone_name(ZoneNames::DECK);
|
||||
cmd.set_start(-number);
|
||||
cmd.set_end(-1);
|
||||
|
||||
|
|
@ -376,7 +377,7 @@ void PlayerActions::actUndoDraw()
|
|||
|
||||
void PlayerActions::cmdSetTopCard(Command_MoveCard &cmd)
|
||||
{
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_start_zone(ZoneNames::DECK);
|
||||
auto *cardToMove = cmd.mutable_cards_to_move()->add_card();
|
||||
cardToMove->set_card_id(0);
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
|
|
@ -386,7 +387,7 @@ void PlayerActions::cmdSetBottomCard(Command_MoveCard &cmd)
|
|||
{
|
||||
CardZoneLogic *zone = player->getDeckZone();
|
||||
int lastCard = zone->getCards().size() - 1;
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_start_zone(ZoneNames::DECK);
|
||||
auto *cardToMove = cmd.mutable_cards_to_move()->add_card();
|
||||
cardToMove->set_card_id(lastCard);
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
|
|
@ -400,7 +401,7 @@ void PlayerActions::actMoveTopCardToGrave()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetTopCard(cmd);
|
||||
cmd.set_target_zone("grave");
|
||||
cmd.set_target_zone(ZoneNames::GRAVE);
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -415,7 +416,7 @@ void PlayerActions::actMoveTopCardToExile()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetTopCard(cmd);
|
||||
cmd.set_target_zone("rfg");
|
||||
cmd.set_target_zone(ZoneNames::EXILE);
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -424,37 +425,25 @@ void PlayerActions::actMoveTopCardToExile()
|
|||
|
||||
void PlayerActions::actMoveTopCardsToGrave()
|
||||
{
|
||||
const int maxCards = player->getDeckZone()->getCards().size();
|
||||
if (maxCards == 0) {
|
||||
return;
|
||||
}
|
||||
moveTopCardsTo(ZoneNames::GRAVE, tr("grave"), false);
|
||||
}
|
||||
|
||||
bool ok;
|
||||
int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Move top cards to grave"),
|
||||
tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberTopCards, 1,
|
||||
maxCards, 1, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
} else if (number > maxCards) {
|
||||
number = maxCards;
|
||||
}
|
||||
defaultNumberTopCards = number;
|
||||
|
||||
Command_MoveCard cmd;
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone("grave");
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
for (int i = number - 1; i >= 0; --i) {
|
||||
cmd.mutable_cards_to_move()->add_card()->set_card_id(i);
|
||||
}
|
||||
|
||||
sendGameCommand(cmd);
|
||||
void PlayerActions::actMoveTopCardsToGraveFaceDown()
|
||||
{
|
||||
moveTopCardsTo(ZoneNames::GRAVE, tr("grave"), true);
|
||||
}
|
||||
|
||||
void PlayerActions::actMoveTopCardsToExile()
|
||||
{
|
||||
moveTopCardsTo(ZoneNames::EXILE, tr("exile"), false);
|
||||
}
|
||||
|
||||
void PlayerActions::actMoveTopCardsToExileFaceDown()
|
||||
{
|
||||
moveTopCardsTo(ZoneNames::EXILE, tr("exile"), true);
|
||||
}
|
||||
|
||||
void PlayerActions::moveTopCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown)
|
||||
{
|
||||
const int maxCards = player->getDeckZone()->getCards().size();
|
||||
if (maxCards == 0) {
|
||||
|
|
@ -462,25 +451,31 @@ void PlayerActions::actMoveTopCardsToExile()
|
|||
}
|
||||
|
||||
bool ok;
|
||||
int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Move top cards to exile"),
|
||||
int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Move top cards to %1").arg(zoneDisplayName),
|
||||
tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberTopCards, 1,
|
||||
maxCards, 1, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
} else if (number > maxCards) {
|
||||
}
|
||||
|
||||
if (number > maxCards) {
|
||||
number = maxCards;
|
||||
}
|
||||
defaultNumberTopCards = number;
|
||||
|
||||
Command_MoveCard cmd;
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_start_zone(ZoneNames::DECK);
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone("rfg");
|
||||
cmd.set_target_zone(targetZone.toStdString());
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
for (int i = number - 1; i >= 0; --i) {
|
||||
cmd.mutable_cards_to_move()->add_card()->set_card_id(i);
|
||||
auto card = cmd.mutable_cards_to_move()->add_card();
|
||||
card->set_card_id(i);
|
||||
if (faceDown) {
|
||||
card->set_face_down(true);
|
||||
}
|
||||
}
|
||||
|
||||
sendGameCommand(cmd);
|
||||
|
|
@ -555,7 +550,7 @@ void PlayerActions::actMoveTopCardToBottom()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetTopCard(cmd);
|
||||
cmd.set_target_zone("deck");
|
||||
cmd.set_target_zone(ZoneNames::DECK);
|
||||
cmd.set_x(-1); // bottom of deck
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -570,7 +565,7 @@ void PlayerActions::actMoveTopCardToPlay()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetTopCard(cmd);
|
||||
cmd.set_target_zone("stack");
|
||||
cmd.set_target_zone(ZoneNames::STACK);
|
||||
cmd.set_x(-1);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -584,12 +579,12 @@ void PlayerActions::actMoveTopCardToPlayFaceDown()
|
|||
}
|
||||
|
||||
Command_MoveCard cmd;
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_start_zone(ZoneNames::DECK);
|
||||
CardToMove *cardToMove = cmd.mutable_cards_to_move()->add_card();
|
||||
cardToMove->set_card_id(0);
|
||||
cardToMove->set_face_down(true);
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone("table");
|
||||
cmd.set_target_zone(ZoneNames::TABLE);
|
||||
cmd.set_x(-1);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -604,7 +599,7 @@ void PlayerActions::actMoveBottomCardToGrave()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetBottomCard(cmd);
|
||||
cmd.set_target_zone("grave");
|
||||
cmd.set_target_zone(ZoneNames::GRAVE);
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -619,7 +614,7 @@ void PlayerActions::actMoveBottomCardToExile()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetBottomCard(cmd);
|
||||
cmd.set_target_zone("rfg");
|
||||
cmd.set_target_zone(ZoneNames::EXILE);
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -628,37 +623,25 @@ void PlayerActions::actMoveBottomCardToExile()
|
|||
|
||||
void PlayerActions::actMoveBottomCardsToGrave()
|
||||
{
|
||||
const int maxCards = player->getDeckZone()->getCards().size();
|
||||
if (maxCards == 0) {
|
||||
return;
|
||||
}
|
||||
moveBottomCardsTo(ZoneNames::GRAVE, tr("grave"), false);
|
||||
}
|
||||
|
||||
bool ok;
|
||||
int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Move bottom cards to grave"),
|
||||
tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1,
|
||||
maxCards, 1, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
} else if (number > maxCards) {
|
||||
number = maxCards;
|
||||
}
|
||||
defaultNumberBottomCards = number;
|
||||
|
||||
Command_MoveCard cmd;
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone("grave");
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
for (int i = maxCards - number; i < maxCards; ++i) {
|
||||
cmd.mutable_cards_to_move()->add_card()->set_card_id(i);
|
||||
}
|
||||
|
||||
sendGameCommand(cmd);
|
||||
void PlayerActions::actMoveBottomCardsToGraveFaceDown()
|
||||
{
|
||||
moveBottomCardsTo(ZoneNames::GRAVE, tr("grave"), true);
|
||||
}
|
||||
|
||||
void PlayerActions::actMoveBottomCardsToExile()
|
||||
{
|
||||
moveBottomCardsTo(ZoneNames::EXILE, tr("exile"), false);
|
||||
}
|
||||
|
||||
void PlayerActions::actMoveBottomCardsToExileFaceDown()
|
||||
{
|
||||
moveBottomCardsTo(ZoneNames::EXILE, tr("exile"), true);
|
||||
}
|
||||
|
||||
void PlayerActions::moveBottomCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown)
|
||||
{
|
||||
const int maxCards = player->getDeckZone()->getCards().size();
|
||||
if (maxCards == 0) {
|
||||
|
|
@ -666,25 +649,31 @@ void PlayerActions::actMoveBottomCardsToExile()
|
|||
}
|
||||
|
||||
bool ok;
|
||||
int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Move bottom cards to exile"),
|
||||
int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Move bottom cards to %1").arg(zoneDisplayName),
|
||||
tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1,
|
||||
maxCards, 1, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
} else if (number > maxCards) {
|
||||
}
|
||||
|
||||
if (number > maxCards) {
|
||||
number = maxCards;
|
||||
}
|
||||
defaultNumberBottomCards = number;
|
||||
|
||||
Command_MoveCard cmd;
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_start_zone(ZoneNames::DECK);
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone("rfg");
|
||||
cmd.set_target_zone(targetZone.toStdString());
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
for (int i = maxCards - number; i < maxCards; ++i) {
|
||||
cmd.mutable_cards_to_move()->add_card()->set_card_id(i);
|
||||
auto card = cmd.mutable_cards_to_move()->add_card();
|
||||
card->set_card_id(i);
|
||||
if (faceDown) {
|
||||
card->set_face_down(true);
|
||||
}
|
||||
}
|
||||
|
||||
sendGameCommand(cmd);
|
||||
|
|
@ -698,7 +687,7 @@ void PlayerActions::actMoveBottomCardToTop()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetBottomCard(cmd);
|
||||
cmd.set_target_zone("deck");
|
||||
cmd.set_target_zone(ZoneNames::DECK);
|
||||
cmd.set_x(0); // top of deck
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -768,7 +757,7 @@ void PlayerActions::actDrawBottomCard()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetBottomCard(cmd);
|
||||
cmd.set_target_zone("hand");
|
||||
cmd.set_target_zone(ZoneNames::HAND);
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -794,9 +783,9 @@ void PlayerActions::actDrawBottomCards()
|
|||
defaultNumberBottomCards = number;
|
||||
|
||||
Command_MoveCard cmd;
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_start_zone(ZoneNames::DECK);
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone("hand");
|
||||
cmd.set_target_zone(ZoneNames::HAND);
|
||||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -815,7 +804,7 @@ void PlayerActions::actMoveBottomCardToPlay()
|
|||
|
||||
Command_MoveCard cmd;
|
||||
cmdSetBottomCard(cmd);
|
||||
cmd.set_target_zone("stack");
|
||||
cmd.set_target_zone(ZoneNames::STACK);
|
||||
cmd.set_x(-1);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -832,13 +821,13 @@ void PlayerActions::actMoveBottomCardToPlayFaceDown()
|
|||
int lastCard = zone->getCards().size() - 1;
|
||||
|
||||
Command_MoveCard cmd;
|
||||
cmd.set_start_zone("deck");
|
||||
cmd.set_start_zone(ZoneNames::DECK);
|
||||
auto *cardToMove = cmd.mutable_cards_to_move()->add_card();
|
||||
cardToMove->set_card_id(lastCard);
|
||||
cardToMove->set_face_down(true);
|
||||
|
||||
cmd.set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd.set_target_zone("table");
|
||||
cmd.set_target_zone(ZoneNames::TABLE);
|
||||
cmd.set_x(-1);
|
||||
cmd.set_y(0);
|
||||
|
||||
|
|
@ -848,7 +837,7 @@ void PlayerActions::actMoveBottomCardToPlayFaceDown()
|
|||
void PlayerActions::actUntapAll()
|
||||
{
|
||||
Command_SetCardAttr cmd;
|
||||
cmd.set_zone("table");
|
||||
cmd.set_zone(ZoneNames::TABLE);
|
||||
cmd.set_attribute(AttrTapped);
|
||||
cmd.set_attr_value("0");
|
||||
|
||||
|
|
@ -898,7 +887,7 @@ void PlayerActions::actCreateAnotherToken()
|
|||
}
|
||||
|
||||
Command_CreateToken cmd;
|
||||
cmd.set_zone("table");
|
||||
cmd.set_zone(ZoneNames::TABLE);
|
||||
cmd.set_card_name(lastTokenInfo.name.toStdString());
|
||||
cmd.set_card_provider_id(lastTokenInfo.providerId.toStdString());
|
||||
cmd.set_color(lastTokenInfo.color.toStdString());
|
||||
|
|
@ -1079,7 +1068,7 @@ bool PlayerActions::createRelatedFromRelation(const CardItem *sourceCard, const
|
|||
|
||||
// move card onto table first if attaching from some other zone
|
||||
// we only do this for AttachTo because cross-zone TransformInto is already handled server-side
|
||||
if (attachType == CardRelationType::AttachTo && sourceCard->getZone()->getName() != "table") {
|
||||
if (attachType == CardRelationType::AttachTo && sourceCard->getZone()->getName() != ZoneNames::TABLE) {
|
||||
playCardToTable(sourceCard, false);
|
||||
}
|
||||
|
||||
|
|
@ -1105,7 +1094,7 @@ void PlayerActions::createCard(const CardItem *sourceCard,
|
|||
|
||||
// create the token for the related card
|
||||
Command_CreateToken cmd;
|
||||
cmd.set_zone("table");
|
||||
cmd.set_zone(ZoneNames::TABLE);
|
||||
cmd.set_card_name(cardInfo->getName().toStdString());
|
||||
switch (cardInfo->getColors().size()) {
|
||||
case 0:
|
||||
|
|
@ -1134,12 +1123,12 @@ void PlayerActions::createCard(const CardItem *sourceCard,
|
|||
|
||||
switch (attachType) {
|
||||
case CardRelationType::DoesNotAttach:
|
||||
cmd.set_target_zone("table");
|
||||
cmd.set_target_zone(ZoneNames::TABLE);
|
||||
cmd.set_card_provider_id(relatedCard.getPrinting().getUuid().toStdString());
|
||||
break;
|
||||
|
||||
case CardRelationType::AttachTo:
|
||||
cmd.set_target_zone("table"); // We currently only support creating tokens on the table
|
||||
cmd.set_target_zone(ZoneNames::TABLE); // We currently only support creating tokens on the table
|
||||
cmd.set_card_provider_id(relatedCard.getPrinting().getUuid().toStdString());
|
||||
cmd.set_target_card_id(sourceCard->getId());
|
||||
cmd.set_target_mode(Command_CreateToken::ATTACH_TO);
|
||||
|
|
@ -1147,7 +1136,7 @@ void PlayerActions::createCard(const CardItem *sourceCard,
|
|||
|
||||
case CardRelationType::TransformInto:
|
||||
// allow cards to directly transform on stack
|
||||
cmd.set_zone(sourceCard->getZone()->getName() == "stack" ? "stack" : "table");
|
||||
cmd.set_zone(sourceCard->getZone()->getName() == ZoneNames::STACK ? ZoneNames::STACK : ZoneNames::TABLE);
|
||||
// Transform card zone changes are handled server-side
|
||||
cmd.set_target_zone(sourceCard->getZone()->getName().toStdString());
|
||||
cmd.set_target_card_id(sourceCard->getId());
|
||||
|
|
@ -1262,7 +1251,7 @@ void PlayerActions::actMoveCardXCardsFromTop()
|
|||
cmd->set_start_zone(startZone.toStdString());
|
||||
cmd->mutable_cards_to_move()->CopyFrom(idList);
|
||||
cmd->set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd->set_target_zone("deck");
|
||||
cmd->set_target_zone(ZoneNames::DECK);
|
||||
cmd->set_x(number);
|
||||
cmd->set_y(0);
|
||||
commandList.append(cmd);
|
||||
|
|
@ -1651,7 +1640,7 @@ void PlayerActions::playSelectedCards(const bool faceDown)
|
|||
[](const auto &card1, const auto &card2) { return card1->getId() > card2->getId(); });
|
||||
|
||||
for (auto &card : selectedCards) {
|
||||
if (card && !isUnwritableRevealZone(card->getZone()) && card->getZone()->getName() != "table") {
|
||||
if (card && !isUnwritableRevealZone(card->getZone()) && card->getZone()->getName() != ZoneNames::TABLE) {
|
||||
playCard(card, faceDown);
|
||||
}
|
||||
}
|
||||
|
|
@ -1704,7 +1693,7 @@ void PlayerActions::actRevealHand(int revealToPlayerId)
|
|||
if (revealToPlayerId != -1) {
|
||||
cmd.set_player_id(revealToPlayerId);
|
||||
}
|
||||
cmd.set_zone_name("hand");
|
||||
cmd.set_zone_name(ZoneNames::HAND);
|
||||
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
|
@ -1715,7 +1704,7 @@ void PlayerActions::actRevealRandomHandCard(int revealToPlayerId)
|
|||
if (revealToPlayerId != -1) {
|
||||
cmd.set_player_id(revealToPlayerId);
|
||||
}
|
||||
cmd.set_zone_name("hand");
|
||||
cmd.set_zone_name(ZoneNames::HAND);
|
||||
cmd.add_card_id(RANDOM_CARD_FROM_ZONE);
|
||||
|
||||
sendGameCommand(cmd);
|
||||
|
|
@ -1727,7 +1716,7 @@ void PlayerActions::actRevealLibrary(int revealToPlayerId)
|
|||
if (revealToPlayerId != -1) {
|
||||
cmd.set_player_id(revealToPlayerId);
|
||||
}
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_zone_name(ZoneNames::DECK);
|
||||
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
|
@ -1738,7 +1727,7 @@ void PlayerActions::actLendLibrary(int lendToPlayerId)
|
|||
if (lendToPlayerId != -1) {
|
||||
cmd.set_player_id(lendToPlayerId);
|
||||
}
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_zone_name(ZoneNames::DECK);
|
||||
cmd.set_grant_write_access(true);
|
||||
|
||||
sendGameCommand(cmd);
|
||||
|
|
@ -1751,7 +1740,7 @@ void PlayerActions::actRevealTopCards(int revealToPlayerId, int amount)
|
|||
cmd.set_player_id(revealToPlayerId);
|
||||
}
|
||||
|
||||
cmd.set_zone_name("deck");
|
||||
cmd.set_zone_name(ZoneNames::DECK);
|
||||
cmd.set_top_cards(amount);
|
||||
// backward compatibility: servers before #1051 only permits to reveal the first card
|
||||
cmd.add_card_id(0);
|
||||
|
|
@ -1765,7 +1754,7 @@ void PlayerActions::actRevealRandomGraveyardCard(int revealToPlayerId)
|
|||
if (revealToPlayerId != -1) {
|
||||
cmd.set_player_id(revealToPlayerId);
|
||||
}
|
||||
cmd.set_zone_name("grave");
|
||||
cmd.set_zone_name(ZoneNames::GRAVE);
|
||||
cmd.add_card_id(RANDOM_CARD_FROM_ZONE);
|
||||
sendGameCommand(cmd);
|
||||
}
|
||||
|
|
@ -1828,7 +1817,7 @@ void PlayerActions::cardMenuAction()
|
|||
}
|
||||
case cmClone: {
|
||||
auto *cmd = new Command_CreateToken;
|
||||
cmd->set_zone("table");
|
||||
cmd->set_zone(ZoneNames::TABLE);
|
||||
cmd->set_card_name(card->getName().toStdString());
|
||||
cmd->set_card_provider_id(card->getProviderId().toStdString());
|
||||
cmd->set_color(card->getColor().toStdString());
|
||||
|
|
@ -1870,13 +1859,13 @@ void PlayerActions::cardMenuAction()
|
|||
cmd->set_start_zone(startZone.toStdString());
|
||||
cmd->mutable_cards_to_move()->CopyFrom(idList);
|
||||
cmd->set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd->set_target_zone("deck");
|
||||
cmd->set_target_zone(ZoneNames::DECK);
|
||||
cmd->set_x(0);
|
||||
cmd->set_y(0);
|
||||
|
||||
if (idList.card_size() > 1) {
|
||||
auto *scmd = new Command_Shuffle;
|
||||
scmd->set_zone_name("deck");
|
||||
scmd->set_zone_name(ZoneNames::DECK);
|
||||
scmd->set_start(0);
|
||||
scmd->set_end(idList.card_size() - 1); // inclusive, the indexed card at end will be shuffled
|
||||
// Server process events backwards, so...
|
||||
|
|
@ -1892,13 +1881,13 @@ void PlayerActions::cardMenuAction()
|
|||
cmd->set_start_zone(startZone.toStdString());
|
||||
cmd->mutable_cards_to_move()->CopyFrom(idList);
|
||||
cmd->set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd->set_target_zone("deck");
|
||||
cmd->set_target_zone(ZoneNames::DECK);
|
||||
cmd->set_x(-1);
|
||||
cmd->set_y(0);
|
||||
|
||||
if (idList.card_size() > 1) {
|
||||
auto *scmd = new Command_Shuffle;
|
||||
scmd->set_zone_name("deck");
|
||||
scmd->set_zone_name(ZoneNames::DECK);
|
||||
scmd->set_start(-idList.card_size());
|
||||
scmd->set_end(-1);
|
||||
// Server process events backwards, so...
|
||||
|
|
@ -1914,7 +1903,7 @@ void PlayerActions::cardMenuAction()
|
|||
cmd->set_start_zone(startZone.toStdString());
|
||||
cmd->mutable_cards_to_move()->CopyFrom(idList);
|
||||
cmd->set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd->set_target_zone("hand");
|
||||
cmd->set_target_zone(ZoneNames::HAND);
|
||||
cmd->set_x(0);
|
||||
cmd->set_y(0);
|
||||
commandList.append(cmd);
|
||||
|
|
@ -1926,7 +1915,7 @@ void PlayerActions::cardMenuAction()
|
|||
cmd->set_start_zone(startZone.toStdString());
|
||||
cmd->mutable_cards_to_move()->CopyFrom(idList);
|
||||
cmd->set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd->set_target_zone("grave");
|
||||
cmd->set_target_zone(ZoneNames::GRAVE);
|
||||
cmd->set_x(0);
|
||||
cmd->set_y(0);
|
||||
commandList.append(cmd);
|
||||
|
|
@ -1938,7 +1927,7 @@ void PlayerActions::cardMenuAction()
|
|||
cmd->set_start_zone(startZone.toStdString());
|
||||
cmd->mutable_cards_to_move()->CopyFrom(idList);
|
||||
cmd->set_target_player_id(player->getPlayerInfo()->getId());
|
||||
cmd->set_target_zone("rfg");
|
||||
cmd->set_target_zone(ZoneNames::EXILE);
|
||||
cmd->set_x(0);
|
||||
cmd->set_y(0);
|
||||
commandList.append(cmd);
|
||||
|
|
|
|||
|
|
@ -98,7 +98,9 @@ public slots:
|
|||
void actMoveTopCardToGrave();
|
||||
void actMoveTopCardToExile();
|
||||
void actMoveTopCardsToGrave();
|
||||
void actMoveTopCardsToGraveFaceDown();
|
||||
void actMoveTopCardsToExile();
|
||||
void actMoveTopCardsToExileFaceDown();
|
||||
void actMoveTopCardsUntil();
|
||||
void actMoveTopCardToBottom();
|
||||
void actDrawBottomCard();
|
||||
|
|
@ -108,7 +110,9 @@ public slots:
|
|||
void actMoveBottomCardToGrave();
|
||||
void actMoveBottomCardToExile();
|
||||
void actMoveBottomCardsToGrave();
|
||||
void actMoveBottomCardsToGraveFaceDown();
|
||||
void actMoveBottomCardsToExile();
|
||||
void actMoveBottomCardsToExileFaceDown();
|
||||
void actMoveBottomCardToTop();
|
||||
|
||||
void actSelectAll();
|
||||
|
|
@ -180,6 +184,9 @@ private:
|
|||
FilterString movingCardsUntilFilter;
|
||||
int movingCardsUntilCounter = 0;
|
||||
|
||||
void moveTopCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);
|
||||
void moveBottomCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);
|
||||
|
||||
void createCard(const CardItem *sourceCard,
|
||||
const QString &dbCardName,
|
||||
CardRelationType attach = CardRelationType::DoesNotAttach,
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <libcockatrice/protocol/pb/event_set_card_counter.pb.h>
|
||||
#include <libcockatrice/protocol/pb/event_set_counter.pb.h>
|
||||
#include <libcockatrice/protocol/pb/event_shuffle.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
PlayerEventHandler::PlayerEventHandler(Player *_player) : player(_player)
|
||||
{
|
||||
|
|
@ -321,8 +322,8 @@ void PlayerEventHandler::eventMoveCard(const Event_MoveCard &event, const GameEv
|
|||
}
|
||||
player->getPlayerMenu()->updateCardMenu(card);
|
||||
|
||||
if (player->getPlayerActions()->isMovingCardsUntil() && startZoneString == "deck" &&
|
||||
targetZone->getName() == "stack") {
|
||||
if (player->getPlayerActions()->isMovingCardsUntil() && startZoneString == ZoneNames::DECK &&
|
||||
targetZone->getName() == ZoneNames::STACK) {
|
||||
player->getPlayerActions()->moveOneCardUntil(card);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ PlayerGraphicsItem::PlayerGraphicsItem(Player *_player) : player(_player)
|
|||
playerArea = new PlayerArea(this);
|
||||
|
||||
playerTarget = new PlayerTarget(player, playerArea);
|
||||
qreal avatarMargin = (counterAreaWidth + CARD_HEIGHT + 15 - playerTarget->boundingRect().width()) / 2.0;
|
||||
qreal avatarMargin =
|
||||
(counterAreaWidth + CardDimensions::HEIGHT_F + 15 - playerTarget->boundingRect().width()) / 2.0;
|
||||
playerTarget->setPos(QPointF(avatarMargin, avatarMargin));
|
||||
|
||||
initializeZones();
|
||||
|
|
@ -55,8 +56,9 @@ void PlayerGraphicsItem::onPlayerActiveChanged(bool _active)
|
|||
void PlayerGraphicsItem::initializeZones()
|
||||
{
|
||||
deckZoneGraphicsItem = new PileZone(player->getDeckZone(), this);
|
||||
auto base = QPointF(counterAreaWidth + (CARD_HEIGHT - CARD_WIDTH + 15) / 2.0,
|
||||
10 + playerTarget->boundingRect().height() + 5 - (CARD_HEIGHT - CARD_WIDTH) / 2.0);
|
||||
auto base = QPointF(counterAreaWidth + (CardDimensions::HEIGHT_F - CardDimensions::WIDTH_F + 15) / 2.0,
|
||||
10 + playerTarget->boundingRect().height() + 5 -
|
||||
(CardDimensions::HEIGHT_F - CardDimensions::WIDTH_F) / 2.0);
|
||||
deckZoneGraphicsItem->setPos(base);
|
||||
|
||||
qreal h = deckZoneGraphicsItem->boundingRect().width() + 5;
|
||||
|
|
@ -95,7 +97,7 @@ QRectF PlayerGraphicsItem::boundingRect() const
|
|||
|
||||
qreal PlayerGraphicsItem::getMinimumWidth() const
|
||||
{
|
||||
qreal result = tableZoneGraphicsItem->getMinimumWidth() + CARD_HEIGHT + 15 + counterAreaWidth +
|
||||
qreal result = tableZoneGraphicsItem->getMinimumWidth() + CardDimensions::HEIGHT_F + 15 + counterAreaWidth +
|
||||
stackZoneGraphicsItem->boundingRect().width();
|
||||
if (!SettingsCache::instance().getHorizontalHand()) {
|
||||
result += handZoneGraphicsItem->boundingRect().width();
|
||||
|
|
@ -112,8 +114,8 @@ void PlayerGraphicsItem::paint(QPainter * /*painter*/,
|
|||
void PlayerGraphicsItem::processSceneSizeChange(int newPlayerWidth)
|
||||
{
|
||||
// Extend table (and hand, if horizontal) to accommodate the new player width.
|
||||
qreal tableWidth =
|
||||
newPlayerWidth - CARD_HEIGHT - 15 - counterAreaWidth - stackZoneGraphicsItem->boundingRect().width();
|
||||
qreal tableWidth = newPlayerWidth - CardDimensions::HEIGHT_F - 15 - counterAreaWidth -
|
||||
stackZoneGraphicsItem->boundingRect().width();
|
||||
if (!SettingsCache::instance().getHorizontalHand()) {
|
||||
tableWidth -= handZoneGraphicsItem->boundingRect().width();
|
||||
}
|
||||
|
|
@ -152,7 +154,7 @@ void PlayerGraphicsItem::rearrangeCounters()
|
|||
|
||||
void PlayerGraphicsItem::rearrangeZones()
|
||||
{
|
||||
auto base = QPointF(CARD_HEIGHT + counterAreaWidth + 15, 0);
|
||||
auto base = QPointF(CardDimensions::HEIGHT_F + counterAreaWidth + 15, 0);
|
||||
if (SettingsCache::instance().getHorizontalHand()) {
|
||||
if (mirrored) {
|
||||
if (player->getHandZone()->contentsKnown()) {
|
||||
|
|
@ -203,7 +205,7 @@ void PlayerGraphicsItem::rearrangeZones()
|
|||
void PlayerGraphicsItem::updateBoundingRect()
|
||||
{
|
||||
prepareGeometryChange();
|
||||
qreal width = CARD_HEIGHT + 15 + counterAreaWidth + stackZoneGraphicsItem->boundingRect().width();
|
||||
qreal width = CardDimensions::HEIGHT_F + 15 + counterAreaWidth + stackZoneGraphicsItem->boundingRect().width();
|
||||
if (SettingsCache::instance().getHorizontalHand()) {
|
||||
qreal handHeight =
|
||||
player->getPlayerInfo()->getHandVisible() ? handZoneGraphicsItem->boundingRect().height() : 0;
|
||||
|
|
@ -214,7 +216,7 @@ void PlayerGraphicsItem::updateBoundingRect()
|
|||
0, 0, width + handZoneGraphicsItem->boundingRect().width() + tableZoneGraphicsItem->boundingRect().width(),
|
||||
tableZoneGraphicsItem->boundingRect().height());
|
||||
}
|
||||
playerArea->setSize(CARD_HEIGHT + counterAreaWidth + 15, bRect.height());
|
||||
playerArea->setSize(CardDimensions::HEIGHT_F + counterAreaWidth + 15, bRect.height());
|
||||
|
||||
emit sizeChanged();
|
||||
}
|
||||
136
cockatrice/src/game/z_value_layer_manager.h
Normal file
136
cockatrice/src/game/z_value_layer_manager.h
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* @file z_value_layer_manager.h
|
||||
* @ingroup GameGraphics
|
||||
* @brief Semantic Z-value layer management for game scene rendering.
|
||||
*
|
||||
* This file provides a structured approach to Z-value allocation in the game scene.
|
||||
* Z-values in Qt determine stacking order - higher values render on top of lower values.
|
||||
*
|
||||
* ## Layer Architecture
|
||||
*
|
||||
* The game scene is organized into three conceptual layers:
|
||||
*
|
||||
* 1. **Zone Layer (0-999)**: Zone backgrounds, containers, and static elements
|
||||
* - Zone backgrounds (0.5-1.0)
|
||||
* - Cards within zones (1.0 base + index)
|
||||
*
|
||||
* 2. **Card Layer (1-40,000,000)**: Dynamic card rendering on the table zone
|
||||
* - Cards use formula: (actualY + CardDimensions::HEIGHT) * 100000 + (actualX + 1) * 100
|
||||
* - Maximum card Z-value: ~40,000,000 (with 3 rows, actualY <= ~289)
|
||||
*
|
||||
* 3. **Overlay Layer (2,000,000,000+)**: UI elements that must appear above all cards
|
||||
* - Hovered cards (+1)
|
||||
* - Arrows (+3)
|
||||
* - Zone views (+4)
|
||||
* - Drag items (+5, +6)
|
||||
* - Top UI elements (+7)
|
||||
*
|
||||
* ## Design Rationale
|
||||
*
|
||||
* The large gap between card Z-values (max ~40M) and overlay base (2B) provides
|
||||
* safety margin for future table zone expansions while ensuring overlays always
|
||||
* render above cards regardless of table position.
|
||||
*
|
||||
* ## Usage
|
||||
*
|
||||
* Prefer using the semantic constants from ZValues namespace:
|
||||
* @code
|
||||
* card->setZValue(ZValues::HOVERED_CARD);
|
||||
* arrow->setZValue(ZValues::ARROWS);
|
||||
* @endcode
|
||||
*
|
||||
* Use validation functions to verify card Z-values during development:
|
||||
* @code
|
||||
* Q_ASSERT(ZValueLayerManager::isValidCardZValue(cardZ));
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
#ifndef Z_VALUE_LAYER_MANAGER_H
|
||||
#define Z_VALUE_LAYER_MANAGER_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
/**
|
||||
* @namespace ZValueLayerManager
|
||||
* @brief Utilities for Z-value validation and layer management.
|
||||
*/
|
||||
namespace ZValueLayerManager
|
||||
{
|
||||
|
||||
/**
|
||||
* @enum Layer
|
||||
* @brief Semantic layer identifiers for Z-value allocation.
|
||||
*
|
||||
* These represent conceptual rendering layers, not actual Z-values.
|
||||
* Use the corresponding ZValues constants for actual rendering.
|
||||
*/
|
||||
enum class Layer
|
||||
{
|
||||
/// Zone-level elements like backgrounds and containers
|
||||
Zone,
|
||||
/// Cards rendered in zones (uses sequential Z-values)
|
||||
Card,
|
||||
/// Temporary UI elements like hovered cards and drag items
|
||||
Overlay
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Maximum Z-value a card can have on the table zone.
|
||||
*
|
||||
* Based on table zone formula: (actualY + CardDimensions::HEIGHT) * 100000 + (actualX + 1) * 100
|
||||
* With maximum 3 rows and CardDimensions::HEIGHT = 102, actualY <= ~289.
|
||||
* Maximum: (289 + 102) * 100000 + 100 * 100 = 39,110,000
|
||||
*
|
||||
* We use 40,000,000 as a safe upper bound with margin.
|
||||
*/
|
||||
constexpr qreal CARD_Z_VALUE_MAX = 40000000.0;
|
||||
|
||||
/**
|
||||
* @brief Base Z-value for overlay elements.
|
||||
*
|
||||
* Must exceed CARD_Z_VALUE_MAX to ensure overlays render above all cards.
|
||||
* The 50x margin (2B vs 40M) provides safety for future expansion.
|
||||
*/
|
||||
constexpr qreal OVERLAY_BASE = 2000000000.0;
|
||||
|
||||
/**
|
||||
* @brief Validates that a Z-value is within the valid card range.
|
||||
*
|
||||
* Cards should have Z-values between CARD_BASE (1.0) and CARD_Z_VALUE_MAX.
|
||||
* Values outside this range may interfere with overlay rendering.
|
||||
*
|
||||
* @param zValue The Z-value to validate
|
||||
* @return true if the Z-value is valid for a card
|
||||
*/
|
||||
[[nodiscard]] constexpr bool isValidCardZValue(qreal zValue)
|
||||
{
|
||||
return zValue >= 1.0 && zValue <= CARD_Z_VALUE_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Validates that a Z-value is in the overlay layer.
|
||||
*
|
||||
* Overlay elements should have Z-values at or above OVERLAY_BASE.
|
||||
*
|
||||
* @param zValue The Z-value to validate
|
||||
* @return true if the Z-value is valid for an overlay element
|
||||
*/
|
||||
[[nodiscard]] constexpr bool isOverlayZValue(qreal zValue)
|
||||
{
|
||||
return zValue >= OVERLAY_BASE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the Z-value for a specific overlay element.
|
||||
*
|
||||
* @param offset Offset from OVERLAY_BASE (0-7 for current elements)
|
||||
* @return The absolute Z-value for the overlay element
|
||||
*/
|
||||
[[nodiscard]] constexpr qreal overlayZValue(qreal offset)
|
||||
{
|
||||
return OVERLAY_BASE + offset;
|
||||
}
|
||||
|
||||
} // namespace ZValueLayerManager
|
||||
|
||||
#endif // Z_VALUE_LAYER_MANAGER_H
|
||||
83
cockatrice/src/game/z_values.h
Normal file
83
cockatrice/src/game/z_values.h
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#ifndef Z_VALUES_H
|
||||
#define Z_VALUES_H
|
||||
|
||||
#include "card_dimensions.h"
|
||||
#include "z_value_layer_manager.h"
|
||||
|
||||
/**
|
||||
* @file z_values.h
|
||||
* @ingroup GameGraphics
|
||||
* @brief Centralized Z-value constants for rendering layer order.
|
||||
*
|
||||
* Z-values in Qt determine stacking order. Higher values render on top.
|
||||
* These constants define the visual layering hierarchy for the game scene.
|
||||
*
|
||||
* ## Layer Architecture
|
||||
*
|
||||
* See z_value_layer_manager.h for detailed documentation on the three-layer
|
||||
* architecture (Zone, Card, Overlay) and the rationale for Z-value choices.
|
||||
*
|
||||
* ## Quick Reference
|
||||
*
|
||||
* | Layer | Z-Value Range | Purpose |
|
||||
* |----------|------------------|-----------------------------------|
|
||||
* | Zone | 0.5 - 1.0 | Zone backgrounds, containers |
|
||||
* | Card | 1.0 - 40,000,000 | Cards on table (position-based) |
|
||||
* | Overlay | 2,000,000,000+ | UI elements above all cards |
|
||||
*/
|
||||
|
||||
namespace ZValues
|
||||
{
|
||||
|
||||
// Expose base for callers that need it
|
||||
constexpr qreal OVERLAY_BASE = ZValueLayerManager::OVERLAY_BASE;
|
||||
|
||||
// Overlay layer Z-values for items that should appear above normal cards
|
||||
constexpr qreal HOVERED_CARD = ZValueLayerManager::overlayZValue(1.0);
|
||||
constexpr qreal ARROWS = ZValueLayerManager::overlayZValue(3.0);
|
||||
constexpr qreal ZONE_VIEW_WIDGET = ZValueLayerManager::overlayZValue(4.0);
|
||||
constexpr qreal DRAG_ITEM = ZValueLayerManager::overlayZValue(5.0);
|
||||
constexpr qreal DRAG_ITEM_CHILD = ZValueLayerManager::overlayZValue(6.0);
|
||||
constexpr qreal TOP_UI = ZValueLayerManager::overlayZValue(7.0);
|
||||
|
||||
/**
|
||||
* @brief Compute Z-value for child drag items based on hotspot position.
|
||||
*
|
||||
* When dragging multiple cards together, each child card needs a unique Z-value
|
||||
* to prevent Z-fighting (flickering/flashing). The Z-values are derived from
|
||||
* their position when grabbed to conserve original stacking. The formula encodes
|
||||
* 2D coordinates into a single value where X has higher weight, ensuring
|
||||
* deterministic visual stacking.
|
||||
*
|
||||
* @param hotSpotX The X coordinate of the grab position
|
||||
* @param hotSpotY The Y coordinate of the grab position
|
||||
* @return Unique Z-value for the child drag item
|
||||
*/
|
||||
[[nodiscard]] constexpr qreal childDragZValue(qreal hotSpotX, qreal hotSpotY)
|
||||
{
|
||||
return DRAG_ITEM_CHILD + hotSpotX * 1000000 + hotSpotY * 1000 + 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute Z-value for cards on the table zone based on position.
|
||||
*
|
||||
* Cards lower on the table (higher Y) render above cards higher up,
|
||||
* and cards to the right (higher X) render above cards to the left.
|
||||
* This creates natural visual stacking for overlapping cards.
|
||||
*
|
||||
* @param x The X coordinate of the card position
|
||||
* @param y The Y coordinate of the card position
|
||||
* @return Z-value for the card's table position
|
||||
*/
|
||||
[[nodiscard]] constexpr qreal tableCardZValue(qreal x, qreal y)
|
||||
{
|
||||
return (y + CardDimensions::HEIGHT_F) * 100000.0 + (x + 1) * 100.0;
|
||||
}
|
||||
|
||||
// Card layering (general architecture, not command-zone specific)
|
||||
constexpr qreal CARD_BASE = 1.0;
|
||||
constexpr qreal CARD_MAX = ZValueLayerManager::CARD_Z_VALUE_MAX;
|
||||
|
||||
} // namespace ZValues
|
||||
|
||||
#endif // Z_VALUES_H
|
||||
|
|
@ -56,7 +56,7 @@ void HandZone::handleDropEvent(const QList<CardDragItem *> &dragItems,
|
|||
QRectF HandZone::boundingRect() const
|
||||
{
|
||||
if (SettingsCache::instance().getHorizontalHand())
|
||||
return QRectF(0, 0, width, CARD_HEIGHT + 10);
|
||||
return QRectF(0, 0, width, CardDimensions::HEIGHT_F + 10);
|
||||
else
|
||||
return QRectF(0, 0, 100, zoneHeight);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include <QDebug>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/protocol/pb/command_move_card.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
/**
|
||||
* @param _player the player that the zone belongs to
|
||||
|
|
@ -43,8 +44,10 @@ void CardZoneLogic::addCard(CardItem *card, const bool reorganize, const int x,
|
|||
|
||||
for (auto *view : views) {
|
||||
if (qobject_cast<ZoneViewZoneLogic *>(view->getLogic())->prepareAddCard(x)) {
|
||||
view->getLogic()->addCard(new CardItem(player, nullptr, card->getCardRef(), card->getId()), reorganize, x,
|
||||
y);
|
||||
auto copy = new CardItem(player, nullptr, card->getCardRef(), card->getId());
|
||||
copy->setFaceDown(card->getFaceDown());
|
||||
|
||||
view->getLogic()->addCard(copy, reorganize, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,9 +175,9 @@ void CardZoneLogic::clearContents()
|
|||
QString CardZoneLogic::getTranslatedName(bool theirOwn, GrammaticalCase gc) const
|
||||
{
|
||||
QString ownerName = player->getPlayerInfo()->getName();
|
||||
if (name == "hand")
|
||||
if (name == ZoneNames::HAND)
|
||||
return (theirOwn ? tr("their hand", "nominative") : tr("%1's hand", "nominative").arg(ownerName));
|
||||
else if (name == "deck")
|
||||
else if (name == ZoneNames::DECK)
|
||||
switch (gc) {
|
||||
case CaseLookAtZone:
|
||||
return (theirOwn ? tr("their library", "look at zone")
|
||||
|
|
@ -190,11 +193,11 @@ QString CardZoneLogic::getTranslatedName(bool theirOwn, GrammaticalCase gc) cons
|
|||
default:
|
||||
return (theirOwn ? tr("their library", "nominative") : tr("%1's library", "nominative").arg(ownerName));
|
||||
}
|
||||
else if (name == "grave")
|
||||
else if (name == ZoneNames::GRAVE)
|
||||
return (theirOwn ? tr("their graveyard", "nominative") : tr("%1's graveyard", "nominative").arg(ownerName));
|
||||
else if (name == "rfg")
|
||||
else if (name == ZoneNames::EXILE)
|
||||
return (theirOwn ? tr("their exile", "nominative") : tr("%1's exile", "nominative").arg(ownerName));
|
||||
else if (name == "sb")
|
||||
else if (name == ZoneNames::SIDEBOARD)
|
||||
switch (gc) {
|
||||
case CaseLookAtZone:
|
||||
return (theirOwn ? tr("their sideboard", "look at zone")
|
||||
|
|
|
|||
|
|
@ -19,9 +19,9 @@ PileZone::PileZone(PileZoneLogic *_logic, QGraphicsItem *parent) : CardZone(_log
|
|||
setCursor(Qt::OpenHandCursor);
|
||||
|
||||
setTransform(QTransform()
|
||||
.translate((float)CARD_WIDTH / 2, (float)CARD_HEIGHT / 2)
|
||||
.translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F)
|
||||
.rotate(90)
|
||||
.translate((float)-CARD_WIDTH / 2, (float)-CARD_HEIGHT / 2));
|
||||
.translate(-CardDimensions::WIDTH_HALF_F, -CardDimensions::HEIGHT_HALF_F));
|
||||
|
||||
connect(&SettingsCache::instance(), &SettingsCache::roundCardCornersChanged, this, [this](bool _roundCardCorners) {
|
||||
Q_UNUSED(_roundCardCorners);
|
||||
|
|
@ -33,13 +33,13 @@ PileZone::PileZone(PileZoneLogic *_logic, QGraphicsItem *parent) : CardZone(_log
|
|||
|
||||
QRectF PileZone::boundingRect() const
|
||||
{
|
||||
return QRectF(0, 0, CARD_WIDTH, CARD_HEIGHT);
|
||||
return QRectF(0, 0, CardDimensions::WIDTH_F, CardDimensions::HEIGHT_F);
|
||||
}
|
||||
|
||||
QPainterPath PileZone::shape() const
|
||||
{
|
||||
QPainterPath shape;
|
||||
qreal cardCornerRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * CARD_WIDTH : 0.0;
|
||||
qreal cardCornerRadius = SettingsCache::instance().getRoundCardCorners() ? 0.05 * CardDimensions::WIDTH_F : 0.0;
|
||||
shape.addRoundedRect(boundingRect(), cardCornerRadius, cardCornerRadius);
|
||||
return shape;
|
||||
}
|
||||
|
|
@ -52,9 +52,9 @@ void PileZone::paint(QPainter *painter, const QStyleOptionGraphicsItem * /*optio
|
|||
getLogic()->getCards().at(0)->paintPicture(painter, getLogic()->getCards().at(0)->getTranslatedSize(painter),
|
||||
90);
|
||||
|
||||
painter->translate((float)CARD_WIDTH / 2, (float)CARD_HEIGHT / 2);
|
||||
painter->translate(CardDimensions::WIDTH_HALF_F, CardDimensions::HEIGHT_HALF_F);
|
||||
painter->rotate(-90);
|
||||
painter->translate((float)-CARD_WIDTH / 2, (float)-CARD_HEIGHT / 2);
|
||||
painter->translate(-CardDimensions::WIDTH_HALF_F, -CardDimensions::HEIGHT_HALF_F);
|
||||
paintNumberEllipse(getLogic()->getCards().size(), 28, Qt::white, -1, -1, painter);
|
||||
}
|
||||
|
||||
|
|
@ -68,8 +68,13 @@ void PileZone::handleDropEvent(const QList<CardDragItem *> &dragItems, CardZoneL
|
|||
cmd.set_x(0);
|
||||
cmd.set_y(0);
|
||||
|
||||
for (int i = 0; i < dragItems.size(); ++i)
|
||||
cmd.mutable_cards_to_move()->add_card()->set_card_id(dragItems[i]->getId());
|
||||
for (int i = 0; i < dragItems.size(); ++i) {
|
||||
auto cardToMove = cmd.mutable_cards_to_move()->add_card();
|
||||
cardToMove->set_card_id(dragItems[i]->getId());
|
||||
if (dragItems[i]->isForceFaceDown()) {
|
||||
cardToMove->set_face_down(true);
|
||||
}
|
||||
}
|
||||
|
||||
getLogic()->getPlayer()->getPlayerActions()->sendGameCommand(cmd);
|
||||
}
|
||||
|
|
@ -101,12 +106,12 @@ void PileZone::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
if (getLogic()->getCards().isEmpty())
|
||||
return;
|
||||
|
||||
bool faceDown = event->modifiers().testFlag(Qt::ShiftModifier);
|
||||
bool forceFaceDown = event->modifiers().testFlag(Qt::ShiftModifier);
|
||||
bool bottomCard = event->modifiers().testFlag(Qt::ControlModifier);
|
||||
CardItem *card = bottomCard ? getLogic()->getCards().last() : getLogic()->getCards().first();
|
||||
const int cardid =
|
||||
getLogic()->contentsKnown() ? card->getId() : (bottomCard ? getLogic()->getCards().size() - 1 : 0);
|
||||
CardDragItem *drag = card->createDragItem(cardid, event->pos(), event->scenePos(), faceDown);
|
||||
CardDragItem *drag = card->createDragItem(cardid, event->pos(), event->scenePos(), forceFaceDown);
|
||||
drag->grabMouse();
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,11 @@ void StackZone::handleDropEvent(const QList<CardDragItem *> &dragItems,
|
|||
|
||||
for (CardDragItem *item : dragItems) {
|
||||
if (item) {
|
||||
cmd.mutable_cards_to_move()->add_card()->set_card_id(item->getId());
|
||||
auto cardToMove = cmd.mutable_cards_to_move()->add_card();
|
||||
cardToMove->set_card_id(item->getId());
|
||||
if (item->isForceFaceDown()) {
|
||||
cardToMove->set_face_down(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "../board/card_item.h"
|
||||
#include "../player/player.h"
|
||||
#include "../player/player_actions.h"
|
||||
#include "../z_values.h"
|
||||
#include "logic/table_zone_logic.h"
|
||||
|
||||
#include <QGraphicsScene>
|
||||
|
|
@ -14,6 +15,7 @@
|
|||
#include <libcockatrice/card/card_info.h>
|
||||
#include <libcockatrice/protocol/pb/command_move_card.pb.h>
|
||||
#include <libcockatrice/protocol/pb/command_set_card_attr.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
const QColor TableZone::BACKGROUND_COLOR = QColor(100, 100, 100);
|
||||
const QColor TableZone::FADE_MASK = QColor(0, 0, 0, 80);
|
||||
|
|
@ -30,7 +32,7 @@ TableZone::TableZone(TableZoneLogic *_logic, QGraphicsItem *parent) : SelectZone
|
|||
|
||||
updateBg();
|
||||
|
||||
height = MARGIN_TOP + MARGIN_BOTTOM + TABLEROWS * CARD_HEIGHT + (TABLEROWS - 1) * PADDING_Y;
|
||||
height = MARGIN_TOP + MARGIN_BOTTOM + TABLEROWS * CardDimensions::HEIGHT + (TABLEROWS - 1) * PADDING_Y;
|
||||
width = MIN_WIDTH;
|
||||
currentMinimumWidth = width;
|
||||
|
||||
|
|
@ -105,7 +107,7 @@ void TableZone::paintLandDivider(QPainter *painter)
|
|||
{
|
||||
// Place the line 2 grid heights down then back it off just enough to allow
|
||||
// some space between a 3-card stack and the land area.
|
||||
qreal separatorY = MARGIN_TOP + 2 * (CARD_HEIGHT + PADDING_Y) - STACKED_CARD_OFFSET_Y / 2;
|
||||
qreal separatorY = MARGIN_TOP + 2 * (CardDimensions::HEIGHT + PADDING_Y) - STACKED_CARD_OFFSET_Y / 2;
|
||||
if (isInverted())
|
||||
separatorY = height - separatorY;
|
||||
painter->setPen(QColor(255, 255, 255, 40));
|
||||
|
|
@ -134,8 +136,10 @@ void TableZone::handleDropEventByGrid(const QList<CardDragItem *> &dragItems,
|
|||
for (const auto &item : dragItems) {
|
||||
CardToMove *ctm = cmd.mutable_cards_to_move()->add_card();
|
||||
ctm->set_card_id(item->getId());
|
||||
ctm->set_face_down(item->getFaceDown());
|
||||
if (startZone->getName() != getLogic()->getName() && !item->getFaceDown()) {
|
||||
if (item->isForceFaceDown()) {
|
||||
ctm->set_face_down(true);
|
||||
}
|
||||
if (startZone->getName() != getLogic()->getName() && !item->isForceFaceDown()) {
|
||||
const auto &card = item->getItem()->getCard();
|
||||
if (card) {
|
||||
ctm->set_pt(card.getInfo().getPowTough().toStdString());
|
||||
|
|
@ -167,7 +171,7 @@ void TableZone::reorganizeCards()
|
|||
actualY += 15;
|
||||
|
||||
getLogic()->getCards()[i]->setPos(actualX, actualY);
|
||||
getLogic()->getCards()[i]->setRealZValue((actualY + CARD_HEIGHT) * 100000 + (actualX + 1) * 100);
|
||||
getLogic()->getCards()[i]->setRealZValue(ZValues::tableCardZValue(actualX, actualY));
|
||||
|
||||
QListIterator<CardItem *> attachedCardIterator(getLogic()->getCards()[i]->getAttachedCards());
|
||||
int j = 0;
|
||||
|
|
@ -177,7 +181,7 @@ void TableZone::reorganizeCards()
|
|||
qreal childX = actualX - j * STACKED_CARD_OFFSET_X;
|
||||
qreal childY = y + 5;
|
||||
attachedCard->setPos(childX, childY);
|
||||
attachedCard->setRealZValue((childY + CARD_HEIGHT) * 100000 + (childX + 1) * 100);
|
||||
attachedCard->setRealZValue(ZValues::tableCardZValue(childX, childY));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -192,7 +196,7 @@ void TableZone::toggleTapped()
|
|||
|
||||
auto isCardOnTable = [](const QGraphicsItem *item) {
|
||||
if (auto card = qgraphicsitem_cast<const CardItem *>(item)) {
|
||||
return card->getZone()->getName() == "table";
|
||||
return card->getZone()->getName() == ZoneNames::TABLE;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
|
@ -229,7 +233,7 @@ void TableZone::resizeToContents()
|
|||
|
||||
// Minimum width is the rightmost card position plus enough room for
|
||||
// another card with padding, then margin.
|
||||
currentMinimumWidth = xMax + (2 * CARD_WIDTH) + PADDING_X + MARGIN_RIGHT;
|
||||
currentMinimumWidth = xMax + (2 * CardDimensions::WIDTH) + PADDING_X + MARGIN_RIGHT;
|
||||
|
||||
if (currentMinimumWidth < MIN_WIDTH)
|
||||
currentMinimumWidth = MIN_WIDTH;
|
||||
|
|
@ -279,10 +283,10 @@ void TableZone::computeCardStackWidths()
|
|||
const int key = getCardStackMapKey(gridPoint.x() / 3, gridPoint.y());
|
||||
const int stackCount = cardStackCount.value(key, 0);
|
||||
if (stackCount == 1)
|
||||
cardStackWidth.insert(key, CARD_WIDTH + getLogic()->getCards()[i]->getAttachedCards().size() *
|
||||
STACKED_CARD_OFFSET_X);
|
||||
cardStackWidth.insert(key, CardDimensions::WIDTH + getLogic()->getCards()[i]->getAttachedCards().size() *
|
||||
STACKED_CARD_OFFSET_X);
|
||||
else
|
||||
cardStackWidth.insert(key, CARD_WIDTH + (stackCount - 1) * STACKED_CARD_OFFSET_X);
|
||||
cardStackWidth.insert(key, CardDimensions::WIDTH + (stackCount - 1) * STACKED_CARD_OFFSET_X);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -296,7 +300,7 @@ QPointF TableZone::mapFromGrid(QPoint gridPoint) const
|
|||
// Add in width of card stack plus padding for each column
|
||||
for (int i = 0; i < gridPoint.x() / 3; ++i) {
|
||||
const int key = getCardStackMapKey(i, gridPoint.y());
|
||||
x += cardStackWidth.value(key, CARD_WIDTH) + PADDING_X;
|
||||
x += cardStackWidth.value(key, CardDimensions::WIDTH) + PADDING_X;
|
||||
}
|
||||
|
||||
if (isInverted())
|
||||
|
|
@ -307,7 +311,7 @@ QPointF TableZone::mapFromGrid(QPoint gridPoint) const
|
|||
|
||||
// Add in card size and padding for each row
|
||||
for (int i = 0; i < gridPoint.y(); ++i)
|
||||
y += CARD_HEIGHT + PADDING_Y;
|
||||
y += CardDimensions::HEIGHT + PADDING_Y;
|
||||
|
||||
return QPointF(x, y);
|
||||
}
|
||||
|
|
@ -321,7 +325,7 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const
|
|||
int y = mapPoint.y() - MARGIN_TOP;
|
||||
|
||||
// Below calculation effectively rounds to the nearest grid point.
|
||||
const int gridPointHeight = CARD_HEIGHT + PADDING_Y;
|
||||
const int gridPointHeight = CardDimensions::HEIGHT + PADDING_Y;
|
||||
int gridPointY = (y + PADDING_Y / 2) / gridPointHeight;
|
||||
|
||||
gridPointY = clampValidTableRow(gridPointY);
|
||||
|
|
@ -337,7 +341,7 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const
|
|||
|
||||
// Maximum value is a card width from the right margin, referenced to the
|
||||
// grid area.
|
||||
const int xMax = width - MARGIN_LEFT - MARGIN_RIGHT - CARD_WIDTH;
|
||||
const int xMax = width - MARGIN_LEFT - MARGIN_RIGHT - CardDimensions::WIDTH;
|
||||
|
||||
int xStack = 0;
|
||||
int xNextStack = 0;
|
||||
|
|
@ -345,7 +349,7 @@ QPoint TableZone::mapToGrid(const QPointF &mapPoint) const
|
|||
while ((xNextStack <= x) && (xNextStack <= xMax)) {
|
||||
xStack = xNextStack;
|
||||
const int key = getCardStackMapKey(nextStackCol, gridPointY);
|
||||
xNextStack += cardStackWidth.value(key, CARD_WIDTH) + PADDING_X;
|
||||
xNextStack += cardStackWidth.value(key, CardDimensions::WIDTH) + PADDING_X;
|
||||
nextStackCol++;
|
||||
}
|
||||
int stackCol = qMax(nextStackCol - 1, 0);
|
||||
|
|
|
|||
|
|
@ -41,12 +41,12 @@ private:
|
|||
/*
|
||||
Minimum width of the table zone including margins.
|
||||
*/
|
||||
static const int MIN_WIDTH = MARGIN_LEFT + (5 * CARD_WIDTH) + MARGIN_RIGHT;
|
||||
static const int MIN_WIDTH = MARGIN_LEFT + (5 * CardDimensions::WIDTH) + MARGIN_RIGHT;
|
||||
|
||||
/*
|
||||
Offset sizes when cards are stacked on each other in the grid
|
||||
*/
|
||||
static const int STACKED_CARD_OFFSET_X = CARD_WIDTH / 3;
|
||||
static const int STACKED_CARD_OFFSET_X = CardDimensions::WIDTH / 3;
|
||||
static const int STACKED_CARD_OFFSET_Y = PADDING_Y / 3;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -73,7 +73,10 @@ void ZoneViewZone::initializeCards(const QList<const ServerInfo_Card *> &cardLis
|
|||
for (int i = 0; i < cardList.size(); ++i) {
|
||||
auto card = cardList[i];
|
||||
CardRef cardRef = {QString::fromStdString(card->name()), QString::fromStdString(card->provider_id())};
|
||||
getLogic()->addCard(new CardItem(getLogic()->getPlayer(), this, cardRef, card->id()), false, i);
|
||||
auto copy = new CardItem(getLogic()->getPlayer(), this, cardRef, card->id());
|
||||
copy->setFaceDown(card->face_down());
|
||||
|
||||
getLogic()->addCard(copy, false, i);
|
||||
}
|
||||
reorganizeCards();
|
||||
} else if (!qobject_cast<ZoneViewZoneLogic *>(getLogic())->getOriginalZone()->contentsKnown()) {
|
||||
|
|
@ -91,8 +94,10 @@ void ZoneViewZone::initializeCards(const QList<const ServerInfo_Card *> &cardLis
|
|||
int number = numberCards == -1 ? c.size() : (numberCards < c.size() ? numberCards : c.size());
|
||||
for (int i = 0; i < number; i++) {
|
||||
CardItem *card = c.at(i);
|
||||
getLogic()->addCard(new CardItem(getLogic()->getPlayer(), this, card->getCardRef(), card->getId()), false,
|
||||
i);
|
||||
auto copy = new CardItem(getLogic()->getPlayer(), this, card->getCardRef(), card->getId());
|
||||
copy->setFaceDown(card->getFaceDown());
|
||||
|
||||
getLogic()->addCard(copy, false, i);
|
||||
}
|
||||
reorganizeCards();
|
||||
}
|
||||
|
|
@ -107,12 +112,15 @@ void ZoneViewZone::zoneDumpReceived(const Response &r)
|
|||
auto cardName = QString::fromStdString(cardInfo.name());
|
||||
auto cardProviderId = QString::fromStdString(cardInfo.provider_id());
|
||||
auto card = new CardItem(getLogic()->getPlayer(), this, {cardName, cardProviderId}, cardInfo.id(), getLogic());
|
||||
card->setFaceDown(cardInfo.face_down());
|
||||
getLogic()->rawInsertCard(card, i);
|
||||
}
|
||||
|
||||
qobject_cast<ZoneViewZoneLogic *>(getLogic())->updateCardIds(ZoneViewZoneLogic::INITIALIZE);
|
||||
reorganizeCards();
|
||||
emit getLogic()->cardCountChanged();
|
||||
// clang-format off
|
||||
emit getLogic()->cardCountChanged(); // emit keyword causes spurious spacing around ->
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
// Because of boundingRect(), this function must not be called before the zone was added to a scene.
|
||||
|
|
@ -160,8 +168,8 @@ void ZoneViewZone::reorganizeCards()
|
|||
// determine bounding rect
|
||||
qreal aleft = 0;
|
||||
qreal atop = 0;
|
||||
qreal awidth = gridSize.cols * CARD_WIDTH + (CARD_WIDTH / 2) + HORIZONTAL_PADDING;
|
||||
qreal aheight = (gridSize.rows * CARD_HEIGHT) / 3 + CARD_HEIGHT * 1.3;
|
||||
qreal awidth = gridSize.cols * CardDimensions::WIDTH_F + CardDimensions::WIDTH_HALF_F + HORIZONTAL_PADDING;
|
||||
qreal aheight = (gridSize.rows * CardDimensions::HEIGHT_F) / 3 + CardDimensions::HEIGHT_F * 1.3;
|
||||
optimumRect = QRectF(aleft, atop, awidth, aheight);
|
||||
|
||||
updateGeometry();
|
||||
|
|
@ -204,8 +212,8 @@ ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, Ca
|
|||
}
|
||||
|
||||
lastColumnProp = columnProp;
|
||||
qreal x = col * CARD_WIDTH;
|
||||
qreal y = row * CARD_HEIGHT / 3;
|
||||
qreal x = col * CardDimensions::WIDTH_F;
|
||||
qreal y = row * CardDimensions::HEIGHT_F / 3;
|
||||
c->setPos(HORIZONTAL_PADDING + x, VERTICAL_PADDING + y);
|
||||
c->setRealZValue(i);
|
||||
longestRow = qMax(row, longestRow);
|
||||
|
|
@ -232,8 +240,8 @@ ZoneViewZone::GridSize ZoneViewZone::positionCardsForDisplay(CardList &cards, Ca
|
|||
|
||||
for (int i = 0; i < cardCount; i++) {
|
||||
CardItem *c = cards.at(i);
|
||||
qreal x = (i / rows) * CARD_WIDTH;
|
||||
qreal y = (i % rows) * CARD_HEIGHT / 3;
|
||||
qreal x = (i / rows) * CardDimensions::WIDTH_F;
|
||||
qreal y = (i % rows) * CardDimensions::HEIGHT_F / 3;
|
||||
c->setPos(HORIZONTAL_PADDING + x, VERTICAL_PADDING + y);
|
||||
c->setRealZValue(i);
|
||||
}
|
||||
|
|
@ -279,8 +287,13 @@ void ZoneViewZone::handleDropEvent(const QList<CardDragItem *> &dragItems,
|
|||
cmd.set_y(0);
|
||||
cmd.set_is_reversed(qobject_cast<ZoneViewZoneLogic *>(getLogic())->getIsReversed());
|
||||
|
||||
for (int i = 0; i < dragItems.size(); ++i)
|
||||
cmd.mutable_cards_to_move()->add_card()->set_card_id(dragItems[i]->getId());
|
||||
for (int i = 0; i < dragItems.size(); ++i) {
|
||||
auto cardToMove = cmd.mutable_cards_to_move()->add_card();
|
||||
cardToMove->set_card_id(dragItems[i]->getId());
|
||||
if (dragItems[i]->isForceFaceDown()) {
|
||||
cardToMove->set_face_down(true);
|
||||
}
|
||||
}
|
||||
|
||||
getLogic()->getPlayer()->getPlayerActions()->sendGameCommand(cmd);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "../game_scene.h"
|
||||
#include "../player/player.h"
|
||||
#include "../player/player_actions.h"
|
||||
#include "../z_values.h"
|
||||
#include "view_zone.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
|
|
@ -47,7 +48,7 @@ ZoneViewWidget::ZoneViewWidget(Player *_player,
|
|||
{
|
||||
setAcceptHoverEvents(true);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setZValue(2000000006);
|
||||
setZValue(ZValues::ZONE_VIEW_WIDGET);
|
||||
setFlag(ItemIgnoresTransformations);
|
||||
|
||||
QGraphicsLinearLayout *vbox = new QGraphicsLinearLayout(Qt::Vertical);
|
||||
|
|
@ -71,7 +72,7 @@ ZoneViewWidget::ZoneViewWidget(Player *_player,
|
|||
|
||||
QGraphicsProxyWidget *searchEditProxy = new QGraphicsProxyWidget;
|
||||
searchEditProxy->setWidget(&searchEdit);
|
||||
searchEditProxy->setZValue(2000000007);
|
||||
searchEditProxy->setZValue(ZValues::DRAG_ITEM);
|
||||
vbox->addItem(searchEditProxy);
|
||||
|
||||
// top row
|
||||
|
|
@ -80,13 +81,13 @@ ZoneViewWidget::ZoneViewWidget(Player *_player,
|
|||
// groupBy options
|
||||
QGraphicsProxyWidget *groupBySelectorProxy = new QGraphicsProxyWidget;
|
||||
groupBySelectorProxy->setWidget(&groupBySelector);
|
||||
groupBySelectorProxy->setZValue(2000000008);
|
||||
groupBySelectorProxy->setZValue(ZValues::TOP_UI);
|
||||
hTopRow->addItem(groupBySelectorProxy);
|
||||
|
||||
// sortBy options
|
||||
QGraphicsProxyWidget *sortBySelectorProxy = new QGraphicsProxyWidget;
|
||||
sortBySelectorProxy->setWidget(&sortBySelector);
|
||||
sortBySelectorProxy->setZValue(2000000007);
|
||||
sortBySelectorProxy->setZValue(ZValues::DRAG_ITEM);
|
||||
hTopRow->addItem(sortBySelectorProxy);
|
||||
|
||||
vbox->addItem(hTopRow);
|
||||
|
|
@ -457,7 +458,7 @@ void ZoneViewWidget::resizeScrollbar(const qreal newZoneHeight)
|
|||
*/
|
||||
static qreal rowsToHeight(int rows)
|
||||
{
|
||||
const qreal cardsHeight = (rows + 1) * (CARD_HEIGHT / 3);
|
||||
const qreal cardsHeight = (rows + 1) * (CardDimensions::HEIGHT_F / 3);
|
||||
return cardsHeight + 5; // +5 padding to make the cutoff look nicer
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <QtConcurrentRun>
|
||||
#include <libcockatrice/card/database/card_database.h>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
||||
#include <libcockatrice/deck_list/deck_list.h>
|
||||
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
||||
|
||||
|
|
@ -42,7 +43,7 @@ DeckLoader::loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bo
|
|||
DeckList deckList;
|
||||
switch (fmt) {
|
||||
case DeckFileFormat::PlainText:
|
||||
result = deckList.loadFromFile_Plain(&file);
|
||||
result = deckList.loadFromFile_Plain(&file, CardNameNormalizer());
|
||||
break;
|
||||
case DeckFileFormat::Cockatrice: {
|
||||
result = deckList.loadFromFile_Native(&file);
|
||||
|
|
@ -50,7 +51,7 @@ DeckLoader::loadFromFile(const QString &fileName, DeckFileFormat::Format fmt, bo
|
|||
qCInfo(DeckLoaderLog) << "Failed to load " << fileName
|
||||
<< "as cockatrice format; retrying as plain format";
|
||||
file.seek(0);
|
||||
result = deckList.loadFromFile_Plain(&file);
|
||||
result = deckList.loadFromFile_Plain(&file, CardNameNormalizer());
|
||||
fmt = DeckFileFormat::PlainText;
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <QPixmapCache>
|
||||
#include <QStandardPaths>
|
||||
#include <QString>
|
||||
#include <QStyle>
|
||||
#include <QStyleFactory>
|
||||
#include <QStyleHints>
|
||||
#include <Qt>
|
||||
|
|
@ -89,6 +90,7 @@ struct PaletteColorInfo
|
|||
|
||||
ThemeManager::ThemeManager(QObject *parent) : QObject(parent)
|
||||
{
|
||||
defaultStyleName = qApp->style()->objectName();
|
||||
ensureThemeDirectoryExists();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
|
||||
connect(QGuiApplication::styleHints(), &QStyleHints::colorSchemeChanged, this, &ThemeManager::themeChangedSlot);
|
||||
|
|
@ -346,7 +348,7 @@ void ThemeManager::themeChangedSlot()
|
|||
qApp->setStyle(QStyleFactory::create("Fusion"));
|
||||
qApp->setPalette(createDarkGreenFusionPalette());
|
||||
} else {
|
||||
qApp->setStyle("");
|
||||
qApp->setStyle(defaultStyleName); // setting the style also sets the palette
|
||||
}
|
||||
|
||||
if (dirPath.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
QString defaultStyleName;
|
||||
std::array<QBrush, Role::MaxRole + 1> brushes;
|
||||
QStringMap availableThemes;
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
|
||||
CardInfoDisplayWidget::CardInfoDisplayWidget(const CardRef &cardRef, QWidget *parent, Qt::WindowFlags flags)
|
||||
: QFrame(parent, flags), aspectRatio((qreal)CARD_HEIGHT / (qreal)CARD_WIDTH)
|
||||
: QFrame(parent, flags), aspectRatio(CardDimensions::HEIGHT_F / CardDimensions::WIDTH_F)
|
||||
{
|
||||
setContentsMargins(3, 3, 3, 3);
|
||||
pic = new CardInfoPictureWidget();
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ CardInfoPictureArtCropWidget::CardInfoPictureArtCropWidget(QWidget *parent)
|
|||
hide();
|
||||
}
|
||||
|
||||
QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &targetSize)
|
||||
QPixmap CardInfoPictureArtCropWidget::getBackground()
|
||||
{
|
||||
// Load the full-resolution card image, not a pre-scaled one
|
||||
QPixmap fullResPixmap;
|
||||
|
|
@ -17,10 +17,8 @@ QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &target
|
|||
} else {
|
||||
CardPictureLoader::getCardBackPixmap(fullResPixmap, QSize(745, 1040));
|
||||
}
|
||||
|
||||
// Fail-safe if loading failed
|
||||
if (fullResPixmap.isNull()) {
|
||||
return QPixmap(targetSize);
|
||||
return QPixmap(); // return null qpixmap
|
||||
}
|
||||
|
||||
const QSize sz = fullResPixmap.size();
|
||||
|
|
@ -33,9 +31,7 @@ QPixmap CardInfoPictureArtCropWidget::getProcessedBackground(const QSize &target
|
|||
|
||||
foilRect = foilRect.intersected(fullResPixmap.rect()); // always clamp to source bounds
|
||||
|
||||
// Crop first, then scale for best quality
|
||||
// return full resolution image crop
|
||||
QPixmap cropped = fullResPixmap.copy(foilRect);
|
||||
QPixmap scaled = cropped.scaled(targetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
|
||||
return scaled;
|
||||
return cropped;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ class CardInfoPictureArtCropWidget : public CardInfoPictureWidget
|
|||
public:
|
||||
explicit CardInfoPictureArtCropWidget(QWidget *parent = nullptr);
|
||||
|
||||
// Returns a processed (cropped & scaled) version of the pixmap
|
||||
QPixmap getProcessedBackground(const QSize &targetSize);
|
||||
// Returns a cropped version of the pixmap
|
||||
QPixmap getBackground();
|
||||
};
|
||||
|
||||
#endif // CARD_INFO_PICTURE_ART_CROP_WIDGET_H
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ void DeckStateManager::undo(int steps)
|
|||
deckListModel->rebuildTree();
|
||||
|
||||
emit deckListModel->layoutChanged();
|
||||
emit deckReplaced();
|
||||
}
|
||||
|
||||
void DeckStateManager::redo(int steps)
|
||||
|
|
@ -338,6 +339,7 @@ void DeckStateManager::redo(int steps)
|
|||
deckListModel->rebuildTree();
|
||||
|
||||
emit deckListModel->layoutChanged();
|
||||
emit deckReplaced();
|
||||
}
|
||||
|
||||
void DeckStateManager::requestHistorySave(const QString &reason)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QTextStream>
|
||||
#include <QVBoxLayout>
|
||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
||||
|
||||
/**
|
||||
* Creates the main layout and connects the signals that are common to all versions of this window
|
||||
|
|
@ -81,7 +82,7 @@ bool AbstractDlgDeckTextEdit::loadIntoDeck(DeckList &deckList) const
|
|||
|
||||
QTextStream stream(&buffer);
|
||||
|
||||
if (deckList.loadFromStream_Plain(stream, true)) {
|
||||
if (deckList.loadFromStream_Plain(stream, true, CardNameNormalizer())) {
|
||||
if (loadSetNameAndNumberCheckBox->isChecked()) {
|
||||
deckList.forEachCard(CardNodeFunction::ResolveProviderId());
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <QJsonObject>
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkReply>
|
||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
||||
#include <version_string.h>
|
||||
|
||||
DlgLoadDeckFromWebsite::DlgLoadDeckFromWebsite(QWidget *parent) : QDialog(parent)
|
||||
|
|
@ -99,7 +100,7 @@ void DlgLoadDeckFromWebsite::accept()
|
|||
// Parse the plain text deck here
|
||||
DeckList deckList;
|
||||
QTextStream stream(&deckText);
|
||||
deckList.loadFromStream_Plain(stream, false);
|
||||
deckList.loadFromStream_Plain(stream, false, CardNameNormalizer());
|
||||
deckList.forEachCard(CardNodeFunction::ResolveProviderId());
|
||||
deck = deckList;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <QDialog>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QLoggingCategory>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ HomeWidget::HomeWidget(QWidget *parent, TabSupervisor *_tabSupervisor)
|
|||
&HomeWidget::onBackgroundShuffleFrequencyChanged);
|
||||
// Lambda is cleaner to read than overloading this
|
||||
connect(&SettingsCache::instance(), &SettingsCache::homeTabDisplayCardNameChanged, this, [this] { repaint(); });
|
||||
connect(&SettingsCache::instance(), &SettingsCache::themeChanged, this,
|
||||
&HomeWidget::updateButtonsToBackgroundColor);
|
||||
}
|
||||
|
||||
void HomeWidget::initializeBackgroundFromSource()
|
||||
|
|
@ -58,20 +60,24 @@ void HomeWidget::initializeBackgroundFromSource()
|
|||
|
||||
auto backgroundSourceType = BackgroundSources::fromId(SettingsCache::instance().getHomeTabBackgroundSource());
|
||||
|
||||
cardChangeTimer->stop();
|
||||
|
||||
switch (backgroundSourceType) {
|
||||
case BackgroundSources::Theme:
|
||||
cardChangeTimer->stop();
|
||||
background = QPixmap("theme:backgrounds/home");
|
||||
backgroundSourceDeck = DeckList();
|
||||
backgroundSourceCard->setCard(ExactCard());
|
||||
updateButtonsToBackgroundColor();
|
||||
update();
|
||||
break;
|
||||
case BackgroundSources::RandomCardArt:
|
||||
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
|
||||
backgroundSourceDeck = DeckList();
|
||||
updateRandomCard();
|
||||
onBackgroundShuffleFrequencyChanged();
|
||||
break;
|
||||
case BackgroundSources::DeckFileArt:
|
||||
loadBackgroundSourceDeck();
|
||||
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
|
||||
updateRandomCard();
|
||||
onBackgroundShuffleFrequencyChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -83,6 +89,20 @@ void HomeWidget::loadBackgroundSourceDeck()
|
|||
backgroundSourceDeck = deckOpt.has_value() ? deckOpt.value().deckList : DeckList();
|
||||
}
|
||||
|
||||
void HomeWidget::setRandomCard(ExactCard &newCard)
|
||||
{
|
||||
static constexpr int ATTEMPTS = 10;
|
||||
for (int i = 0; i < ATTEMPTS; ++i) {
|
||||
ExactCard tmpCard = CardDatabaseManager::query()->getRandomCard();
|
||||
if (tmpCard != backgroundSourceCard->getCard() && tmpCard.getCardPtr()->getProperty("layout") == "normal" &&
|
||||
tmpCard.getPrinting().getSet() != nullptr) {
|
||||
newCard = tmpCard;
|
||||
return;
|
||||
}
|
||||
}
|
||||
qWarning() << "failed to set random card image after" << ATTEMPTS << "attempts";
|
||||
}
|
||||
|
||||
void HomeWidget::updateRandomCard()
|
||||
{
|
||||
auto backgroundSourceType = BackgroundSources::fromId(SettingsCache::instance().getHomeTabBackgroundSource());
|
||||
|
|
@ -93,10 +113,7 @@ void HomeWidget::updateRandomCard()
|
|||
case BackgroundSources::Theme:
|
||||
break;
|
||||
case BackgroundSources::RandomCardArt:
|
||||
do {
|
||||
newCard = CardDatabaseManager::query()->getRandomCard();
|
||||
} while (newCard == backgroundSourceCard->getCard() &&
|
||||
newCard.getCardPtr()->getProperty("layout") != "normal");
|
||||
setRandomCard(newCard);
|
||||
break;
|
||||
case BackgroundSources::DeckFileArt:
|
||||
QList<CardRef> cardRefs = backgroundSourceDeck.getCardRefList();
|
||||
|
|
@ -124,25 +141,20 @@ void HomeWidget::updateRandomCard()
|
|||
|
||||
connect(newCard.getCardPtr().data(), &CardInfo::pixmapUpdated, this, &HomeWidget::updateBackgroundProperties);
|
||||
backgroundSourceCard->setCard(newCard);
|
||||
background = backgroundSourceCard->getProcessedBackground(size());
|
||||
|
||||
if (SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() <= 0) {
|
||||
cardChangeTimer->stop();
|
||||
}
|
||||
background = backgroundSourceCard->getBackground();
|
||||
}
|
||||
|
||||
void HomeWidget::onBackgroundShuffleFrequencyChanged()
|
||||
{
|
||||
cardChangeTimer->stop();
|
||||
if (SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() <= 0) {
|
||||
return;
|
||||
if (SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() > 0) {
|
||||
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
|
||||
}
|
||||
cardChangeTimer->start(SettingsCache::instance().getHomeTabBackgroundShuffleFrequency() * 1000);
|
||||
}
|
||||
|
||||
void HomeWidget::updateBackgroundProperties()
|
||||
{
|
||||
background = backgroundSourceCard->getProcessedBackground(size());
|
||||
background = backgroundSourceCard->getBackground();
|
||||
updateButtonsToBackgroundColor();
|
||||
update(); // Triggers repaint
|
||||
}
|
||||
|
|
@ -300,14 +312,17 @@ void HomeWidget::paintEvent(QPaintEvent *event)
|
|||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
background = background.scaled(size(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
if (!background.isNull()) {
|
||||
QSize widgetSize = size() * devicePixelRatio();
|
||||
QPixmap toDraw = background.scaled(widgetSize, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
|
||||
|
||||
// Draw already-scaled background centered
|
||||
QSize widgetSize = size();
|
||||
QSize bgSize = background.size();
|
||||
QPoint topLeft((widgetSize.width() - bgSize.width()) / 2, (widgetSize.height() - bgSize.height()) / 2);
|
||||
// Draw scaled background centered
|
||||
QSize bgSize = toDraw.size();
|
||||
QPoint topLeft((widgetSize.width() - bgSize.width()) / (devicePixelRatio() * 2), // undo scaling for painter
|
||||
(widgetSize.height() - bgSize.height()) / (devicePixelRatio() * 2));
|
||||
|
||||
painter.drawPixmap(topLeft, background);
|
||||
painter.drawPixmap(topLeft, toDraw);
|
||||
}
|
||||
|
||||
// Draw translucent black overlay with rounded corners
|
||||
QRectF overlayRect(5, 5, width() - 10, height() - 10);
|
||||
|
|
@ -321,8 +336,11 @@ void HomeWidget::paintEvent(QPaintEvent *event)
|
|||
QString cardName;
|
||||
ExactCard card = backgroundSourceCard->getCard();
|
||||
if (card) {
|
||||
cardName = card.getCardPtr()->getName() + " (" + card.getPrinting().getSet()->getCorrectedShortName() + ") " +
|
||||
card.getPrinting().getProperty("num");
|
||||
cardName = card.getCardPtr()->getName();
|
||||
if (card.getPrinting().getSet() != nullptr) {
|
||||
cardName += " (" + card.getPrinting().getSet()->getCorrectedShortName() + ") " +
|
||||
card.getPrinting().getProperty("num");
|
||||
}
|
||||
}
|
||||
|
||||
if (!cardName.isEmpty() && SettingsCache::instance().getHomeTabDisplayCardName()) {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ private:
|
|||
QPair<QColor, QColor> gradientColors;
|
||||
HomeStyledButton *connectButton;
|
||||
|
||||
void setRandomCard(ExactCard &newCard);
|
||||
void loadBackgroundSourceDeck();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "../../../../../deck_loader/card_node_function.h"
|
||||
#include "../../../../../deck_loader/deck_loader.h"
|
||||
#include "../../../../cards/card_info_picture_with_text_overlay_widget.h"
|
||||
#include "../../../../cards/card_size_widget.h"
|
||||
#include "../../../../cards/deck_card_zone_display_widget.h"
|
||||
#include "../../../../visual_deck_editor/visual_deck_display_options_widget.h"
|
||||
|
|
@ -10,7 +9,7 @@
|
|||
#include "../api_response/deck/archidekt_api_response_deck.h"
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <libcockatrice/card/database/card_database_manager.h>
|
||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
||||
|
||||
ArchidektApiResponseDeckDisplayWidget::ArchidektApiResponseDeckDisplayWidget(QWidget *parent,
|
||||
ArchidektApiResponseDeck _response,
|
||||
|
|
@ -80,7 +79,7 @@ ArchidektApiResponseDeckDisplayWidget::ArchidektApiResponseDeckDisplayWidget(QWi
|
|||
connect(model, &DeckListModel::modelReset, this, &ArchidektApiResponseDeckDisplayWidget::decklistModelReset);
|
||||
|
||||
auto decklist = QSharedPointer<DeckList>(new DeckList);
|
||||
decklist->loadFromStream_Plain(deckStream, false);
|
||||
decklist->loadFromStream_Plain(deckStream, false, CardNameNormalizer());
|
||||
model->setDeckList(decklist);
|
||||
|
||||
model->forEachCard(CardNodeFunction::ResolveProviderId());
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
#include "edhrec_deck_api_response.h"
|
||||
|
||||
#include "../../../../../../deck_loader/deck_loader.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
||||
|
||||
void EdhrecDeckApiResponse::fromJson(const QJsonArray &json)
|
||||
{
|
||||
|
|
@ -15,7 +14,7 @@ void EdhrecDeckApiResponse::fromJson(const QJsonArray &json)
|
|||
}
|
||||
|
||||
QTextStream stream(&deckList);
|
||||
deck.loadFromStream_Plain(stream, true);
|
||||
deck.loadFromStream_Plain(stream, true, CardNameNormalizer());
|
||||
}
|
||||
|
||||
void EdhrecDeckApiResponse::debugPrint() const
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ set(HEADERS
|
|||
libcockatrice/card/database/parser/card_database_parser.h
|
||||
libcockatrice/card/database/parser/cockatrice_xml_3.h
|
||||
libcockatrice/card/database/parser/cockatrice_xml_4.h
|
||||
libcockatrice/card/import/card_name_normalizer.h
|
||||
libcockatrice/card/printing/exact_card.h
|
||||
libcockatrice/card/printing/printing_info.h
|
||||
libcockatrice/card/set/card_set.h
|
||||
|
|
@ -36,6 +37,7 @@ add_library(
|
|||
libcockatrice/card/database/parser/card_database_parser.cpp
|
||||
libcockatrice/card/database/parser/cockatrice_xml_3.cpp
|
||||
libcockatrice/card/database/parser/cockatrice_xml_4.cpp
|
||||
libcockatrice/card/import/card_name_normalizer.cpp
|
||||
libcockatrice/card/printing/exact_card.cpp
|
||||
libcockatrice/card/printing/printing_info.cpp
|
||||
libcockatrice/card/relation/card_relation.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
#include "card_name_normalizer.h"
|
||||
|
||||
#include "../database/card_database_manager.h"
|
||||
#include "../printing/exact_card.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
/**
|
||||
* @brief Resolves the complete display name of a card.
|
||||
* @param cardName Base name.
|
||||
* @return Full display name, or the cardName unchanged if a display name is not found.
|
||||
*/
|
||||
static QString getCompleteCardName(const QString &cardName)
|
||||
{
|
||||
ExactCard temp = CardDatabaseManager::query()->guessCard({cardName});
|
||||
if (temp) {
|
||||
return temp.getName();
|
||||
}
|
||||
|
||||
return cardName;
|
||||
}
|
||||
|
||||
QString CardNameNormalizer::operator()(const QString &cardNameString) const
|
||||
{
|
||||
QString cardName = cardNameString;
|
||||
|
||||
// Regex for advanced card parsing
|
||||
static const QRegularExpression reSplitCard(R"( ?\/\/ ?)");
|
||||
static const QRegularExpression reBrace(R"( ?[\[\{][^\]\}]*[\]\}] ?)"); // not nested
|
||||
static const QRegularExpression reRoundBrace(R"(^\([^\)]*\) ?)"); // () are only matched at start of string
|
||||
static const QRegularExpression reDigitBrace(R"( ?\(\d*\) ?)"); // () are matched if containing digits
|
||||
static const QRegularExpression reBraceDigit(
|
||||
R"( ?\([\dA-Z]+\) *\d+$)"); // () are matched if containing setcode then a number
|
||||
static const QRegularExpression reDoubleFacedMarker(R"( ?\(Transform\) ?)");
|
||||
|
||||
static const QHash<QRegularExpression, QString> differences{{QRegularExpression("’"), "'"},
|
||||
{QRegularExpression("Æ"), "Ae"},
|
||||
{QRegularExpression("æ"), "ae"},
|
||||
{QRegularExpression(" ?[|/]+ ?"), " // "}};
|
||||
|
||||
// Handle advanced card types
|
||||
if (cardName.contains(reSplitCard)) {
|
||||
cardName = cardName.split(reSplitCard).join(" // ");
|
||||
}
|
||||
|
||||
if (cardName.contains(reDoubleFacedMarker)) {
|
||||
QStringList faces = cardName.split(reDoubleFacedMarker);
|
||||
cardName = faces.first().trimmed();
|
||||
}
|
||||
|
||||
// Remove unnecessary characters
|
||||
cardName.remove(reBrace);
|
||||
cardName.remove(reRoundBrace); // I'll be entirely honest here, these are split to accommodate just three cards
|
||||
cardName.remove(reDigitBrace); // from un-sets that have a word in between round braces at the end
|
||||
cardName.remove(reBraceDigit); // very specific format with the set code in () and collectors number after
|
||||
|
||||
// Normalize characters
|
||||
for (auto diff = differences.constBegin(); diff != differences.constEnd(); ++diff) {
|
||||
cardName.replace(diff.key(), diff.value());
|
||||
}
|
||||
|
||||
// Resolve complete card name
|
||||
cardName = getCompleteCardName(cardName);
|
||||
|
||||
return cardName;
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef COCKATRICE_CARD_NAME_NORMALIZER_H
|
||||
#define COCKATRICE_CARD_NAME_NORMALIZER_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* Functor that normalizes the raw card name parsed during a plaintext deck import into the card name that Cockatrice
|
||||
* uses.
|
||||
*/
|
||||
struct CardNameNormalizer
|
||||
{
|
||||
QString operator()(const QString &cardNameString) const;
|
||||
};
|
||||
|
||||
#endif // COCKATRICE_CARD_NAME_NORMALIZER_H
|
||||
|
|
@ -199,9 +199,12 @@ bool DeckList::saveToFile_Native(QIODevice *device) const
|
|||
*
|
||||
* @param in The text to load
|
||||
* @param preserveMetadata If true, don't clear the existing metadata
|
||||
* @param cardNameNormalizer Function that takes the parsed card name string in the text and
|
||||
* @return False if the input was empty, true otherwise.
|
||||
*/
|
||||
bool DeckList::loadFromStream_Plain(QTextStream &in, bool preserveMetadata)
|
||||
bool DeckList::loadFromStream_Plain(QTextStream &in,
|
||||
bool preserveMetadata,
|
||||
const std::function<QString(const QString &)> &cardNameNormalizer)
|
||||
{
|
||||
const QRegularExpression reCardLine(R"(^\s*[\w\[\(\{].*$)", QRegularExpression::UseUnicodePropertiesOption);
|
||||
const QRegularExpression reEmpty("^\\s*$");
|
||||
|
|
@ -213,23 +216,11 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, bool preserveMetadata)
|
|||
|
||||
// Regex for advanced card parsing
|
||||
const QRegularExpression reMultiplier(R"(^[xX\(\[]*(\d+)[xX\*\)\]]* ?(.+))");
|
||||
const QRegularExpression reSplitCard(R"( ?\/\/ ?)");
|
||||
const QRegularExpression reBrace(R"( ?[\[\{][^\]\}]*[\]\}] ?)"); // not nested
|
||||
const QRegularExpression reRoundBrace(R"(^\([^\)]*\) ?)"); // () are only matched at start of string
|
||||
const QRegularExpression reDigitBrace(R"( ?\(\d*\) ?)"); // () are matched if containing digits
|
||||
const QRegularExpression reBraceDigit(
|
||||
R"( ?\([\dA-Z]+\) *\d+$)"); // () are matched if containing setcode then a number
|
||||
const QRegularExpression reDoubleFacedMarker(R"( ?\(Transform\) ?)");
|
||||
|
||||
// Regex for extracting set code and collector number with attached symbols
|
||||
const QRegularExpression reHyphenFormat(R"(\((\w{3,})\)\s+(\w{3,})-(\d+[^\w\s]*))");
|
||||
const QRegularExpression reRegularFormat(R"(\((\w{3,})\)\s+(\d+[^\w\s]*))");
|
||||
|
||||
const QHash<QRegularExpression, QString> differences{{QRegularExpression("’"), QString("'")},
|
||||
{QRegularExpression("Æ"), QString("Ae")},
|
||||
{QRegularExpression("æ"), QString("ae")},
|
||||
{QRegularExpression(" ?[|/]+ ?"), QString(" // ")}};
|
||||
|
||||
cleanList(preserveMetadata);
|
||||
|
||||
auto inputs = in.readAll().trimmed().split('\n');
|
||||
|
|
@ -355,26 +346,8 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, bool preserveMetadata)
|
|||
cardName = match.captured(2);
|
||||
}
|
||||
|
||||
// Handle advanced card types
|
||||
if (cardName.contains(reSplitCard)) {
|
||||
cardName = cardName.split(reSplitCard).join(" // ");
|
||||
}
|
||||
|
||||
if (cardName.contains(reDoubleFacedMarker)) {
|
||||
QStringList faces = cardName.split(reDoubleFacedMarker);
|
||||
cardName = faces.first().trimmed();
|
||||
}
|
||||
|
||||
// Remove unnecessary characters
|
||||
cardName.remove(reBrace);
|
||||
cardName.remove(reRoundBrace); // I'll be entirely honest here, these are split to accommodate just three cards
|
||||
cardName.remove(reDigitBrace); // from un-sets that have a word in between round braces at the end
|
||||
cardName.remove(reBraceDigit); // very specific format with the set code in () and collectors number after
|
||||
|
||||
// Normalize names
|
||||
for (auto diff = differences.constBegin(); diff != differences.constEnd(); ++diff) {
|
||||
cardName.replace(diff.key(), diff.value());
|
||||
}
|
||||
// Normalize the card name
|
||||
cardName = cardNameNormalizer(cardName);
|
||||
|
||||
// Determine the zone (mainboard/sideboard)
|
||||
QString zoneName = sideboard ? DECK_ZONE_SIDE : DECK_ZONE_MAIN;
|
||||
|
|
@ -387,10 +360,10 @@ bool DeckList::loadFromStream_Plain(QTextStream &in, bool preserveMetadata)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DeckList::loadFromFile_Plain(QIODevice *device)
|
||||
bool DeckList::loadFromFile_Plain(QIODevice *device, const std::function<QString(const QString &)> &cardNameNormalizer)
|
||||
{
|
||||
QTextStream in(device);
|
||||
return loadFromStream_Plain(in, false);
|
||||
return loadFromStream_Plain(in, false, cardNameNormalizer);
|
||||
}
|
||||
|
||||
bool DeckList::saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards) const
|
||||
|
|
|
|||
|
|
@ -206,8 +206,10 @@ public:
|
|||
|
||||
/// @name Serialization (Plain text)
|
||||
///@{
|
||||
bool loadFromStream_Plain(QTextStream &stream, bool preserveMetadata);
|
||||
bool loadFromFile_Plain(QIODevice *device);
|
||||
bool loadFromStream_Plain(QTextStream &stream,
|
||||
bool preserveMetadata,
|
||||
const std::function<QString(const QString &)> &cardNameNormalizer);
|
||||
bool loadFromFile_Plain(QIODevice *device, const std::function<QString(const QString &)> &cardNameNormalizer);
|
||||
bool saveToStream_Plain(QTextStream &stream, bool prefixSideboardCards, bool slashTappedOutSplitCards) const;
|
||||
bool
|
||||
saveToFile_Plain(QIODevice *device, bool prefixSideboardCards = true, bool slashTappedOutSplitCards = false) const;
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ void DeckListModel::rebuildTree()
|
|||
}
|
||||
|
||||
endResetModel();
|
||||
|
||||
refreshCardFormatLegalities();
|
||||
}
|
||||
|
||||
int DeckListModel::rowCount(const QModelIndex &parent) const
|
||||
|
|
@ -649,7 +651,6 @@ void DeckListModel::setDeckList(const QSharedPointer<DeckList> &_deck)
|
|||
deckList = _deck;
|
||||
}
|
||||
rebuildTree();
|
||||
refreshCardFormatLegalities();
|
||||
emit deckReplaced();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
|
||||
#include <libcockatrice/rng/rng_abstract.h>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
Server_AbstractPlayer::Server_AbstractPlayer(Server_Game *_game,
|
||||
int _playerId,
|
||||
|
|
@ -190,14 +191,43 @@ shouldDestroyOnMove(const Server_Card *card, const Server_CardZone *startZone, c
|
|||
}
|
||||
|
||||
// Allow tokens on the stack
|
||||
if ((startZone->getName() == "table" || startZone->getName() == "stack") &&
|
||||
(targetZone->getName() == "table" || targetZone->getName() == "stack")) {
|
||||
if ((startZone->getName() == ZoneNames::TABLE || startZone->getName() == ZoneNames::STACK) &&
|
||||
(targetZone->getName() == ZoneNames::TABLE || targetZone->getName() == ZoneNames::STACK)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines whether the moved card should be face-down
|
||||
*/
|
||||
static bool
|
||||
shouldBeFaceDown(const MoveCardStruct &cardStruct, const Server_CardZone *startZone, const Server_CardZone *targetZone)
|
||||
{
|
||||
if (!targetZone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// being face-down only makes sense for public zones
|
||||
if (targetZone->getType() != ServerInfo_Zone::PublicZone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// face-down property in proto takes precedence
|
||||
if (cardStruct.cardToMove->has_face_down()) {
|
||||
return cardStruct.cardToMove->face_down();
|
||||
}
|
||||
|
||||
// Default to keep face-down the same if zone didn't change.
|
||||
// Compare using zone names because face-down is maintained when changing controllers.
|
||||
if (startZone && startZone->getName() == targetZone->getName()) {
|
||||
return cardStruct.card->getFaceDown();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Response::ResponseCode Server_AbstractPlayer::moveCard(GameEventStorage &ges,
|
||||
Server_CardZone *startzone,
|
||||
const QList<const CardToMove *> &_cards,
|
||||
|
|
@ -235,7 +265,7 @@ Response::ResponseCode Server_AbstractPlayer::moveCard(GameEventStorage &ges,
|
|||
}
|
||||
|
||||
// do not allow attached cards to move around on the table
|
||||
if (card->getParentCard() && targetzone->getName() == "table") {
|
||||
if (card->getParentCard() && targetzone->getName() == ZoneNames::TABLE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -257,10 +287,7 @@ Response::ResponseCode Server_AbstractPlayer::moveCard(GameEventStorage &ges,
|
|||
|
||||
for (auto cardStruct : cardsToMove) {
|
||||
Server_Card *card = cardStruct.card;
|
||||
const CardToMove *thisCardProperties = cardStruct.cardToMove;
|
||||
int originalPosition = cardStruct.position;
|
||||
bool faceDown = targetzone->hasCoords() &&
|
||||
(thisCardProperties->has_face_down() ? thisCardProperties->face_down() : card->getFaceDown());
|
||||
|
||||
bool sourceBeingLookedAt;
|
||||
int position = startzone->removeCard(card, sourceBeingLookedAt);
|
||||
|
|
@ -315,11 +342,13 @@ Response::ResponseCode Server_AbstractPlayer::moveCard(GameEventStorage &ges,
|
|||
++xIndex;
|
||||
int newX = isReversed ? targetzone->getCards().size() - xCoord + xIndex : xCoord + xIndex;
|
||||
|
||||
bool faceDown = shouldBeFaceDown(cardStruct, startzone, targetzone);
|
||||
|
||||
if (targetzone->hasCoords()) {
|
||||
newX = targetzone->getFreeGridColumn(newX, yCoord, card->getName(), faceDown);
|
||||
} else {
|
||||
yCoord = 0;
|
||||
card->resetState(targetzone->getName() == "stack");
|
||||
card->resetState(targetzone->getName() == ZoneNames::STACK);
|
||||
}
|
||||
|
||||
targetzone->insertCard(card, newX, yCoord);
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
#include <libcockatrice/protocol/pb/event_set_active_phase.pb.h>
|
||||
#include <libcockatrice/protocol/pb/event_set_active_player.pb.h>
|
||||
#include <libcockatrice/protocol/pb/game_replay.pb.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
Server_Game::Server_Game(const ServerInfo_User &_creatorInfo,
|
||||
int _gameId,
|
||||
|
|
@ -832,7 +833,7 @@ void Server_Game::returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPl
|
|||
QMutexLocker locker(&gameMutex);
|
||||
// Return cards to their rightful owners before conceding the game
|
||||
static const QRegularExpression ownerRegex{"Owner: ?([^\n]+)"};
|
||||
const auto &playerTable = player->getZones().value("table");
|
||||
const auto &playerTable = player->getZones().value(ZoneNames::TABLE);
|
||||
for (const auto &card : playerTable->getCards()) {
|
||||
if (card == nullptr) {
|
||||
continue;
|
||||
|
|
@ -858,7 +859,7 @@ void Server_Game::returnCardsFromPlayer(GameEventStorage &ges, Server_AbstractPl
|
|||
continue;
|
||||
}
|
||||
|
||||
const auto &targetZone = otherPlayer->getZones().value("table");
|
||||
const auto &targetZone = otherPlayer->getZones().value(ZoneNames::TABLE);
|
||||
|
||||
if (playerTable == nullptr || targetZone == nullptr) {
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include <libcockatrice/rng/rng_abstract.h>
|
||||
#include <libcockatrice/utility/color.h>
|
||||
#include <libcockatrice/utility/trice_limits.h>
|
||||
#include <libcockatrice/utility/zone_names.h>
|
||||
|
||||
Server_Player::Server_Player(Server_Game *_game,
|
||||
int _playerId,
|
||||
|
|
@ -80,15 +81,15 @@ void Server_Player::setupZones()
|
|||
// ------------------------------------------------------------------
|
||||
|
||||
// Create zones
|
||||
auto *deckZone = new Server_CardZone(this, "deck", false, ServerInfo_Zone::HiddenZone);
|
||||
auto *deckZone = new Server_CardZone(this, ZoneNames::DECK, false, ServerInfo_Zone::HiddenZone);
|
||||
addZone(deckZone);
|
||||
auto *sbZone = new Server_CardZone(this, "sb", false, ServerInfo_Zone::HiddenZone);
|
||||
auto *sbZone = new Server_CardZone(this, ZoneNames::SIDEBOARD, false, ServerInfo_Zone::HiddenZone);
|
||||
addZone(sbZone);
|
||||
addZone(new Server_CardZone(this, "table", true, ServerInfo_Zone::PublicZone));
|
||||
addZone(new Server_CardZone(this, "hand", false, ServerInfo_Zone::PrivateZone));
|
||||
addZone(new Server_CardZone(this, "stack", false, ServerInfo_Zone::PublicZone));
|
||||
addZone(new Server_CardZone(this, "grave", false, ServerInfo_Zone::PublicZone));
|
||||
addZone(new Server_CardZone(this, "rfg", false, ServerInfo_Zone::PublicZone));
|
||||
addZone(new Server_CardZone(this, ZoneNames::TABLE, true, ServerInfo_Zone::PublicZone));
|
||||
addZone(new Server_CardZone(this, ZoneNames::HAND, false, ServerInfo_Zone::PrivateZone));
|
||||
addZone(new Server_CardZone(this, ZoneNames::STACK, false, ServerInfo_Zone::PublicZone));
|
||||
addZone(new Server_CardZone(this, ZoneNames::GRAVE, false, ServerInfo_Zone::PublicZone));
|
||||
addZone(new Server_CardZone(this, ZoneNames::EXILE, false, ServerInfo_Zone::PublicZone));
|
||||
|
||||
addCounter(new Server_Counter(0, "life", makeColor(255, 255, 255), 25, game->getStartingLifeTotal()));
|
||||
addCounter(new Server_Counter(1, "w", makeColor(255, 255, 150), 20, 0));
|
||||
|
|
@ -164,8 +165,8 @@ void Server_Player::addCounter(Server_Counter *counter)
|
|||
|
||||
Response::ResponseCode Server_Player::drawCards(GameEventStorage &ges, int number)
|
||||
{
|
||||
Server_CardZone *deckZone = zones.value("deck");
|
||||
Server_CardZone *handZone = zones.value("hand");
|
||||
Server_CardZone *deckZone = zones.value(ZoneNames::DECK);
|
||||
Server_CardZone *handZone = zones.value(ZoneNames::HAND);
|
||||
if (deckZone->getCards().size() < number) {
|
||||
number = deckZone->getCards().size();
|
||||
}
|
||||
|
|
@ -210,7 +211,7 @@ void Server_Player::onCardBeingMoved(GameEventStorage &ges,
|
|||
// "Undo draw" should only remain valid if the just-drawn card stays within the user's hand (e.g., they only
|
||||
// reorder their hand). If a just-drawn card leaves the hand then remove cards before it from the list
|
||||
// (Ignore the case where the card is currently being un-drawn.)
|
||||
if (startzone->getName() == "hand" && targetzone->getName() != "hand" && !undoingDraw) {
|
||||
if (startzone->getName() == ZoneNames::HAND && targetzone->getName() != ZoneNames::HAND && !undoingDraw) {
|
||||
int index = lastDrawList.lastIndexOf(card->getId());
|
||||
if (index != -1) {
|
||||
lastDrawList.erase(lastDrawList.begin(), lastDrawList.begin() + index);
|
||||
|
|
@ -326,11 +327,11 @@ Server_Player::cmdShuffle(const Command_Shuffle &cmd, ResponseContainer & /*rc*/
|
|||
return Response::RespContextError;
|
||||
}
|
||||
|
||||
if (cmd.has_zone_name() && cmd.zone_name() != "deck") {
|
||||
if (cmd.has_zone_name() && cmd.zone_name() != ZoneNames::DECK) {
|
||||
return Response::RespFunctionNotAllowed;
|
||||
}
|
||||
|
||||
Server_CardZone *zone = zones.value("deck");
|
||||
Server_CardZone *zone = zones.value(ZoneNames::DECK);
|
||||
if (!zone) {
|
||||
return Response::RespNameNotFound;
|
||||
}
|
||||
|
|
@ -357,8 +358,8 @@ Server_Player::cmdMulligan(const Command_Mulligan &cmd, ResponseContainer & /*rc
|
|||
return Response::RespContextError;
|
||||
}
|
||||
|
||||
Server_CardZone *hand = zones.value("hand");
|
||||
Server_CardZone *_deck = zones.value("deck");
|
||||
Server_CardZone *hand = zones.value(ZoneNames::HAND);
|
||||
Server_CardZone *_deck = zones.value(ZoneNames::DECK);
|
||||
int number = cmd.number();
|
||||
|
||||
if (!hand->getCards().isEmpty()) {
|
||||
|
|
@ -414,8 +415,8 @@ Server_Player::cmdUndoDraw(const Command_UndoDraw & /*cmd*/, ResponseContainer &
|
|||
Response::ResponseCode retVal;
|
||||
auto *cardToMove = new CardToMove;
|
||||
cardToMove->set_card_id(lastDrawList.takeLast());
|
||||
retVal = moveCard(ges, zones.value("hand"), QList<const CardToMove *>() << cardToMove, zones.value("deck"), 0, 0,
|
||||
false, true);
|
||||
retVal = moveCard(ges, zones.value(ZoneNames::HAND), QList<const CardToMove *>() << cardToMove,
|
||||
zones.value(ZoneNames::DECK), 0, 0, false, true);
|
||||
delete cardToMove;
|
||||
|
||||
return retVal;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ message CardToMove {
|
|||
// Id of the card in its current zone
|
||||
optional sint32 card_id = 1 [default = -1];
|
||||
|
||||
// Places the card face down, hiding its name
|
||||
// If true, places the card face down, hiding its name.
|
||||
// If false, forcibly turns the card face up.
|
||||
// If not set, defers the resulting face down state to the server.
|
||||
optional bool face_down = 2;
|
||||
|
||||
// When moving add this value to the power/toughness field of the card
|
||||
|
|
|
|||
|
|
@ -10,8 +10,13 @@ set(UTILITY_SOURCES libcockatrice/utility/expression.cpp libcockatrice/utility/l
|
|||
)
|
||||
|
||||
set(UTILITY_HEADERS
|
||||
libcockatrice/utility/color.h libcockatrice/utility/expression.h libcockatrice/utility/levenshtein.h
|
||||
libcockatrice/utility/macros.h libcockatrice/utility/passwordhasher.h libcockatrice/utility/trice_limits.h
|
||||
libcockatrice/utility/color.h
|
||||
libcockatrice/utility/expression.h
|
||||
libcockatrice/utility/levenshtein.h
|
||||
libcockatrice/utility/macros.h
|
||||
libcockatrice/utility/passwordhasher.h
|
||||
libcockatrice/utility/trice_limits.h
|
||||
libcockatrice/utility/zone_names.h
|
||||
)
|
||||
|
||||
add_library(libcockatrice_utility STATIC ${UTILITY_SOURCES} ${UTILITY_HEADERS})
|
||||
|
|
|
|||
19
libcockatrice_utility/libcockatrice/utility/zone_names.h
Normal file
19
libcockatrice_utility/libcockatrice/utility/zone_names.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#ifndef ZONE_NAMES_H
|
||||
#define ZONE_NAMES_H
|
||||
|
||||
namespace ZoneNames
|
||||
{
|
||||
// Protocol-level zone identifiers shared between client and server.
|
||||
// These must match exactly across all components.
|
||||
|
||||
constexpr const char *TABLE = "table";
|
||||
constexpr const char *GRAVE = "grave";
|
||||
constexpr const char *EXILE = "rfg"; // "removed from game"
|
||||
constexpr const char *HAND = "hand";
|
||||
constexpr const char *DECK = "deck";
|
||||
constexpr const char *SIDEBOARD = "sb";
|
||||
constexpr const char *STACK = "stack";
|
||||
|
||||
} // namespace ZoneNames
|
||||
|
||||
#endif // ZONE_NAMES_H
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
add_definitions("-DCARDDB_DATADIR=\"${CMAKE_CURRENT_SOURCE_DIR}/data/\"")
|
||||
add_executable(loading_from_clipboard_test clipboard_testing.cpp loading_from_clipboard_test.cpp)
|
||||
add_executable(loading_from_clipboard_test ${VERSION_STRING_CPP} clipboard_testing.cpp loading_from_clipboard_test.cpp)
|
||||
|
||||
if(NOT GTEST_FOUND)
|
||||
add_dependencies(loading_from_clipboard_test gtest)
|
||||
|
|
@ -10,6 +10,7 @@ set(TEST_QT_MODULES ${COCKATRICE_QT_VERSION_NAME}::Concurrent ${COCKATRICE_QT_VE
|
|||
)
|
||||
|
||||
target_link_libraries(
|
||||
loading_from_clipboard_test libcockatrice_deck_list Threads::Threads ${GTEST_BOTH_LIBRARIES} ${TEST_QT_MODULES}
|
||||
loading_from_clipboard_test libcockatrice_deck_list libcockatrice_card Threads::Threads ${GTEST_BOTH_LIBRARIES}
|
||||
${TEST_QT_MODULES}
|
||||
)
|
||||
add_test(NAME loading_from_clipboard_test COMMAND loading_from_clipboard_test)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "clipboard_testing.h"
|
||||
|
||||
#include <QTextStream>
|
||||
#include <libcockatrice/card/import/card_name_normalizer.h>
|
||||
#include <libcockatrice/deck_list/tree/deck_list_card_node.h>
|
||||
|
||||
DeckList getDeckList(const QString &clipboard)
|
||||
|
|
@ -8,7 +9,7 @@ DeckList getDeckList(const QString &clipboard)
|
|||
DeckList deckList;
|
||||
QString cp(clipboard);
|
||||
QTextStream stream(&cp); // text stream requires local copy
|
||||
deckList.loadFromStream_Plain(stream, false);
|
||||
deckList.loadFromStream_Plain(stream, false, CardNameNormalizer());
|
||||
return deckList;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue