Compare commits

...

18 commits

Author SHA1 Message Date
tooomm
cc4f21b369
stricter check for file in app bundle path 2026-06-14 00:54:33 +02:00
tooomm
3978c7e642 move keychain setup and cert import back into build step 2026-06-14 00:22:29 +02:00
tooomm
80705afafe Update desktop-build.yml 2026-06-13 23:43:10 +02:00
tooomm
8c7b201022
Merge branch 'master' into tooomm-ci_sign_mac 2026-06-13 22:15:52 +02:00
kongwu
f28ede7ae3
[UserContextMenu] Add confirmation dialog before kicking a player (#6987)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
2026-06-13 02:42:55 -07:00
BruebachL
7aaacbf347
[Update][NSIS] Use single string shell invocation (#6986)
Some checks failed
Build Desktop / Configure (push) Has been cancelled
Build Docker Image / amd64 & arm64 (push) Has been cancelled
Build Desktop / Debian 13 (push) Has been cancelled
Build Desktop / Debian 12 (push) Has been cancelled
Build Desktop / Fedora 44 (push) Has been cancelled
Build Desktop / Fedora 43 (push) Has been cancelled
Build Desktop / Servatrice_Debian 12 (push) Has been cancelled
Build Desktop / Ubuntu 26.04 (push) Has been cancelled
Build Desktop / Ubuntu 24.04 (push) Has been cancelled
Build Desktop / Arch (push) Has been cancelled
Build Desktop / macOS 14 (push) Has been cancelled
Build Desktop / macOS 15 (push) Has been cancelled
Build Desktop / macOS 13 Intel (push) Has been cancelled
Build Desktop / macOS 15 Debug (push) Has been cancelled
Build Desktop / Windows 10 (push) Has been cancelled
Took 18 minutes


Took 2 minutes

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2026-06-11 21:17:28 +02:00
tooomm
694adc9e64
Use Visual Studio 2026 (#6985)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
2026-06-11 10:45:17 +02:00
BruebachL
b17d879da8
[Game][Graphics][Player] Add named zone lookup-map to player graphics. (#6984)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
Took 16 minutes

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2026-06-10 10:58:28 +02:00
ebbit1q
6be9cec6e2
do not save a const reference to the user data in the info dialog (#6974)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
* do not save a const reference to the user data in the info dialog

* cmake format
2026-06-09 23:35:00 -07:00
kongwu
6d0a423dcf
[Messages] Add option to ignore private messages from non-buddy users (#6966)
* [Messages] Add option to ignore private messages from non-buddy users

* [Messages] Exclude Moderator/Admin from non-buddy ignore filter

Moderator and Admin messages should not be filtered out when the
'Ignore private messages from non-buddies' setting is enabled, to
ensure that important warnings from server staff reach users.
2026-06-09 20:49:29 -07:00
kongwu
f72c82d0f9
[DeckEditor] Replace mainboard/sideboard with tokensboard for tokens (#6971)
* [DeckEditor] Replace mainboard/sideboard with tokensboard for token cards (#6546)

* [PrintingSelector] Replace std::tuple with ZoneCounts struct for readability (#6546)
2026-06-09 20:46:43 -07:00
BruebachL
da4ba222c0
[Game] Move graphics out of game and into game_graphics (#6928)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
* [Game][Player] Pull out graphics_items out of player_logic

Took 25 seconds


Took 9 minutes

* [Game] Move graphics files into game_graphics

Took 1 minute

Took 2 minutes

Took 23 seconds

Took 1 minute

Took 2 seconds

* Include.

Took 4 minutes

Took 3 minutes

Took 4 minutes

Took 1 minute

Took 3 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2026-06-09 09:51:13 +02:00
BruebachL
cbfd286908
[Game][Player] Move dialog creation out of player_actions and into player_dialogs (#6946)
Some checks are pending
Build Desktop / Configure (push) Waiting to run
Build Desktop / Debian 13 (push) Blocked by required conditions
Build Desktop / Debian 12 (push) Blocked by required conditions
Build Desktop / Fedora 44 (push) Blocked by required conditions
Build Desktop / Fedora 43 (push) Blocked by required conditions
Build Desktop / Servatrice_Debian 12 (push) Blocked by required conditions
Build Desktop / Ubuntu 26.04 (push) Blocked by required conditions
Build Desktop / Ubuntu 24.04 (push) Blocked by required conditions
Build Desktop / Arch (push) Blocked by required conditions
Build Desktop / macOS 14 (push) Blocked by required conditions
Build Desktop / macOS 15 (push) Blocked by required conditions
Build Desktop / macOS 13 Intel (push) Blocked by required conditions
Build Desktop / macOS 15 Debug (push) Blocked by required conditions
Build Desktop / Windows 10 (push) Blocked by required conditions
Build Docker Image / amd64 & arm64 (push) Waiting to run
* [Game][Player] Split Player into PlayerLogic/PlayerGraphicsItem

Took 4 minutes

Took 48 seconds

Took 2 minutes

* Drop early return.

Took 1 hour 13 minutes


Took 2 minutes

Took 1 minute

Took 24 seconds

* [Game][Player] Split Player into PlayerLogic/PlayerGraphicsItem

Took 4 minutes

Took 58 seconds

* [Game][Menus] Make Menus accept PlayerGraphicsItem instead of PlayerLogic

Took 7 minutes

Took 4 minutes

Took 9 seconds

Took 2 minutes


Took 5 minutes

Took 58 seconds

* [Game][Player] Split Player into PlayerLogic/PlayerGraphicsItem

Took 4 minutes

Took 2 minutes

* [Game][Menus] Make Menus accept PlayerGraphicsItem instead of PlayerLogic

Took 7 minutes


Took 1 minute

Took 57 seconds

* [Game][Player] Move dialog creation out of player_actions and into player_dialogs

Took 3 minutes

Took 1 second

* Fix typo.

Took 5 minutes

* Addressed comments.

Took 16 minutes

Took 11 seconds

* Reintroduce clearCardsToDelete check.

Took 3 minutes

* Capture cards before semaphore.

Took 1 minute

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2026-06-09 08:22:59 +02:00
BruebachL
487bb84b6f
[Game][Menus] Make Menus accept PlayerGraphicsItem instead of PlayerLogic (#6945)
* [Game][Player] Split Player into PlayerLogic/PlayerGraphicsItem

Took 4 minutes

Took 58 seconds


Took 2 minutes

* [Game][Menus] Make Menus accept PlayerGraphicsItem instead of PlayerLogic

Took 7 minutes

Took 4 minutes

Took 9 seconds

Took 2 minutes


Took 5 minutes

Took 58 seconds

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2026-06-09 08:07:06 +02:00
BruebachL
9e03f82616
[Game][Player] Split Player into PlayerLogic/PlayerGraphicsItem (#6944)
* [Game][Player] Split Player into PlayerLogic/PlayerGraphicsItem

Took 4 minutes

Took 48 seconds

* Drop early return.

Took 1 hour 13 minutes


Took 2 minutes

Took 1 minute

* Delete player view.

Took 37 seconds

* Restore card counter color in menu.

Took 5 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
2026-06-09 08:05:39 +02:00
Christo
e674a39b87
Fix #6952: prevent deck loss when saving to a full disk (#6978)
* Fix #6952: prevent deck loss when saving to a full disk

DeckLoader::saveToFile() opened the target with QFile in WriteOnly mode,
which truncates the existing file to 0 bytes the moment it is opened. The
serializers (DeckList::saveToFile_Native/_Plain) always return true and the
result of flush() was ignored, so a write that failed part-way -- e.g.
because the disk was full -- left a 0-byte file behind yet was still
reported (and logged) as a successful save. The same truncate-then-write
pattern in updateLastLoadedTimestamp() could destroy a deck on load.

Switch both paths to QSaveFile, which writes to a temporary file and only
atomically replaces the target if commit() succeeds. On any write or flush
failure commit() returns false, the original deck is left untouched, and
the failure is logged instead of being reported as success.

* Use QSaveFile in convertToCockatriceFormat() too

convertToCockatriceFormat() had the same data-loss pattern: QFile WriteOnly
truncated the .cod, saveToFile_Native() always returns true, and the original
file was then removed unconditionally -- so a full disk during conversion wrote
a 0-byte .cod and then deleted the source deck.

Switch to QSaveFile (write + atomic commit), remove the original only after a
successful commit, and move the format check ahead of the file open so an
already-Cockatrice or unsupported deck never truncates or deletes anything.

Raised in review by ZeldaZach.
2026-06-09 07:54:01 +02:00
tooomm
6f7c5d7788 move cert import too 2026-06-06 22:33:56 +02:00
tooomm
e353f4968b split sign+notarize into own script 2026-06-06 22:33:56 +02:00
143 changed files with 1857 additions and 1037 deletions

77
.ci/sign_macos_bundle.sh Executable file
View file

@ -0,0 +1,77 @@
#!/bin/bash
# This script is to be used by the ci environment.
# Signs and notarizes a macOS app bundle
# Requires: $1 - path to the app bundle
# Environment variables:
# - MACOS_CERTIFICATE_NAME: Name of the certificate for signing (optional, skips signing if not set)
# - MACOS_CI_KEYCHAIN_PWD: Password for the CI keychain (required if MACOS_CERTIFICATE_NAME is set)
# - MACOS_NOTARIZATION_APPLE_ID: Apple ID for notarization (optional, skips notarization if not set)
# - MACOS_NOTARIZATION_PWD: Password for notarization (required if MACOS_NOTARIZATION_APPLE_ID is set)
# - MACOS_NOTARIZATION_TEAM_ID: Team ID for notarization (required if MACOS_NOTARIZATION_APPLE_ID is set)
# exitcode: 1 for failure, 2 for invalid arguments
set -e
# Check input arguments
if [[ $# -lt 1 ]]; then
echo "::error file=$0::No argument passed to the script - provide <path_to_app_bundle>"
exit 2
fi
APP_BUNDLE_PATH="$1"
# Verify that app bundle exists
if [[ ! -f "$APP_BUNDLE_PATH" ]]; then
echo "::error file=$0::App bundle not found at: $APP_BUNDLE_PATH"
exit 1
fi
# Sign app bundle
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]; then
echo "::group::Sign app bundle"
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
/usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose "$APP_BUNDLE_PATH"
echo "::endgroup::"
else
echo "::error file=$0::MACOS_CERTIFICATE_NAME not set. Can not sign app bundle."
exit 1
fi
# Notarize app bundle
if [[ -n "$MACOS_NOTARIZATION_APPLE_ID" ]]; then
echo "::group::Notarize app bundle"
# Store the notarization credentials so that we can prevent a UI password dialog from blocking the CI
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$MACOS_NOTARIZATION_APPLE_ID" --team-id "$MACOS_NOTARIZATION_TEAM_ID" --password "$MACOS_NOTARIZATION_PWD"
# We can't notarize an app bundle directly, but we need to compress it as an archive.
# Therefore, we create a zip file containing our app bundle, so that we can send it to the notarization service
echo ""
echo "Creating temp notarization archive..."
ditto -c -k --keepParent "$APP_BUNDLE_PATH" "notarization.zip"
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App characteristics.
# Visit the Notarization docs for more information and strategies on how to optimize it if you're curious.
echo ""
xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait
echo "::endgroup::"
echo "::group::Staple app"
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
# validated by macOS even when an internet connection is not available.
echo "Attach staple"
xcrun stapler staple "$APP_BUNDLE_PATH"
echo "::endgroup::"
else
echo "::error file=$0::MACOS_NOTARIZATION_APPLE_ID not set. Can not notarize app bundle."
exit 1
fi
echo "::group::Cleanup"
# Cleanup keychain and files to avoid leaking credentials
echo "Deleting keychain"
security delete-keychain build.keychain
rm -f certificate.p12 notarization.zip
echo "::endgroup::"

View file

@ -7,6 +7,17 @@ permissions:
id-token: write # needed for signing certificate in attestation id-token: write # needed for signing certificate in attestation
on: on:
pull_request:
paths:
- '*/**' # matches all files not in root
- '!**.md'
- '!.github/**'
- '!.tx/**'
- '!doc/**'
- '.github/workflows/desktop-build.yml'
- 'CMakeLists.txt'
- 'vcpkg.json'
- 'vcpkg' # needed to match submodule bumps (gitlink)
push: push:
branches: branches:
- master - master
@ -22,30 +33,19 @@ on:
- 'vcpkg' # needed to match submodule bumps (gitlink) - 'vcpkg' # needed to match submodule bumps (gitlink)
tags: tags:
- '*' - '*'
pull_request:
paths:
- '*/**' # matches all files not in root
- '!**.md'
- '!.github/**'
- '!.tx/**'
- '!doc/**'
- '.github/workflows/desktop-build.yml'
- 'CMakeLists.txt'
- 'vcpkg.json'
- 'vcpkg' # needed to match submodule bumps (gitlink)
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on release) # Cancel earlier, unfinished runs of this workflow on the same branch (unless on release)
concurrency: concurrency:
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
cancel-in-progress: ${{ github.ref_type != 'tag' }} cancel-in-progress: ${{ github.ref_type != 'tag' }}
group: "${{ github.workflow }} @ ${{ github.ref_name }}"
jobs: jobs:
configure: configure:
name: Configure name: Configure
runs-on: ubuntu-slim runs-on: ubuntu-slim
outputs: outputs:
tag: ${{ steps.configure.outputs.tag }}
sha: ${{ steps.configure.outputs.sha }} sha: ${{ steps.configure.outputs.sha }}
tag: ${{ steps.configure.outputs.tag }}
steps: steps:
- name: "Configure" - name: "Configure"
@ -54,7 +54,7 @@ jobs:
run: | run: |
tag_regex='^refs/tags/' tag_regex='^refs/tags/'
if [[ $GITHUB_EVENT_NAME == pull-request ]]; then # pull request if [[ $GITHUB_EVENT_NAME == pull-request ]]; then # pull request
sha="${{github.event.pull_request.head.sha}}" sha="${{ github.event.pull_request.head.sha }}"
elif [[ $GITHUB_REF =~ $tag_regex ]]; then # release elif [[ $GITHUB_REF =~ $tag_regex ]]; then # release
sha="$GITHUB_SHA" sha="$GITHUB_SHA"
tag="${GITHUB_REF/refs\/tags\//}" tag="${GITHUB_REF/refs\/tags\//}"
@ -71,8 +71,8 @@ jobs:
fetch-depth: 0 # fetch all history for all branches and tags fetch-depth: 0 # fetch all history for all branches and tags
- name: "Prepare release parameters" - name: "Prepare release parameters"
id: prepare
if: steps.configure.outputs.tag != null if: steps.configure.outputs.tag != null
id: prepare
shell: bash shell: bash
env: env:
TAG: ${{ steps.configure.outputs.tag }} TAG: ${{ steps.configure.outputs.tag }}
@ -83,12 +83,12 @@ jobs:
id: create_release id: create_release
shell: bash shell: bash
env: env:
body_path: ${{ steps.prepare.outputs.body_path }}
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
prerelease: ${{ steps.prepare.outputs.is_beta }}
release_name: ${{ steps.prepare.outputs.title }}
tag_name: ${{ steps.configure.outputs.tag }} tag_name: ${{ steps.configure.outputs.tag }}
target: ${{ steps.configure.outputs.sha }} target: ${{ steps.configure.outputs.sha }}
release_name: ${{ steps.prepare.outputs.title }}
body_path: ${{ steps.prepare.outputs.body_path }}
prerelease: ${{ steps.prepare.outputs.is_beta }}
run: | run: |
args=() args=()
[[ $prerelease == yes ]] && args+=(--prerelease) [[ $prerelease == yes ]] && args+=(--prerelease)
@ -188,13 +188,13 @@ jobs:
--cmake-generator "$CMAKE_GENERATOR" --cmake-generator "$CMAKE_GENERATOR"
- name: "Build release package" - name: "Build release package"
id: build
if: matrix.package != 'skip' if: matrix.package != 'skip'
id: build
shell: bash shell: bash
env: env:
SUFFIX: '-${{ matrix.distro }}${{ matrix.version }}'
package: '${{ matrix.package }}' package: '${{ matrix.package }}'
server_only: '${{ matrix.server_only }}' server_only: '${{ matrix.server_only }}'
SUFFIX: '-${{ matrix.distro }}${{ matrix.version }}'
run: | run: |
source .ci/docker.sh source .ci/docker.sh
args=() args=()
@ -225,8 +225,8 @@ jobs:
path: ${{ env.CACHE }} path: ${{ env.CACHE }}
- name: "Upload artifact" - name: "Upload artifact"
id: upload_artifact
if: matrix.package != 'skip' if: matrix.package != 'skip'
id: upload_artifact
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
archive: false archive: false
@ -234,8 +234,8 @@ jobs:
path: ${{ steps.build.outputs.path }} path: ${{ steps.build.outputs.path }}
- name: "Upload to release" - name: "Upload to release"
id: upload_release
if: matrix.package != 'skip' && needs.configure.outputs.tag != null if: matrix.package != 'skip' && needs.configure.outputs.tag != null
id: upload_release
shell: bash shell: bash
env: env:
asset_name: ${{ steps.build.outputs.fullname }} asset_name: ${{ steps.build.outputs.fullname }}
@ -245,8 +245,8 @@ jobs:
run: gh release upload "$tag_name" "$asset_path#$asset_name" run: gh release upload "$tag_name" "$asset_path#$asset_name"
- name: "Attest binary provenance" - name: "Attest binary provenance"
id: attestation
if: steps.upload_release.outcome == 'success' if: steps.upload_release.outcome == 'success'
id: attestation
uses: actions/attest@v4 uses: actions/attest@v4
with: with:
show-summary: false show-summary: false
@ -268,7 +268,6 @@ jobs:
target: 13 target: 13
runner: macos-15-intel runner: macos-15-intel
ccache_eviction_age: 7d
cmake_generator: Ninja cmake_generator: Ninja
make_package: 1 make_package: 1
override_target: 13 override_target: 13
@ -285,7 +284,6 @@ jobs:
target: 14 target: 14
runner: macos-14 runner: macos-14
ccache_eviction_age: 7d
cmake_generator: Ninja cmake_generator: Ninja
make_package: 1 make_package: 1
package_suffix: "-macOS14" package_suffix: "-macOS14"
@ -301,7 +299,6 @@ jobs:
target: 15 target: 15
runner: macos-15 runner: macos-15
ccache_eviction_age: 7d
cmake_generator: Ninja cmake_generator: Ninja
make_package: 1 make_package: 1
package_suffix: "-macOS15" package_suffix: "-macOS15"
@ -317,7 +314,6 @@ jobs:
target: 15 target: 15
runner: macos-15 runner: macos-15
ccache_eviction_age: 7d
cmake_generator: Ninja cmake_generator: Ninja
qt_version: 6.11.0 qt_version: 6.11.0
qt_arch: clang_64 qt_arch: clang_64
@ -331,7 +327,7 @@ jobs:
target: 10 target: 10
runner: windows-2025 runner: windows-2025
cmake_generator: "Visual Studio 17 2022" cmake_generator: "Visual Studio 18 2026"
cmake_generator_platform: x64 cmake_generator_platform: x64
make_package: 1 make_package: 1
package_suffix: "-Win10" package_suffix: "-Win10"
@ -346,6 +342,7 @@ jobs:
timeout-minutes: 100 timeout-minutes: 100
env: env:
CCACHE_DIR: ${{ github.workspace }}/.cache/ CCACHE_DIR: ${{ github.workspace }}/.cache/
CCACHE_EVICTION_AGE: 7d
CCACHE_SIZE: 550M # space of all repo is 10Gi: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy CCACHE_SIZE: 550M # space of all repo is 10Gi: https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
steps: steps:
@ -443,8 +440,7 @@ jobs:
id: build id: build
shell: bash shell: bash
env: env:
BUILDTYPE: '${{ matrix.type }}' BUILDTYPE: ${{ matrix.type }}
CCACHE_EVICTION_AGE: ${{ matrix.ccache_eviction_age }}
CMAKE_GENERATOR: ${{ matrix.cmake_generator }} CMAKE_GENERATOR: ${{ matrix.cmake_generator }}
CMAKE_GENERATOR_PLATFORM: ${{ matrix.cmake_generator_platform }} CMAKE_GENERATOR_PLATFORM: ${{ matrix.cmake_generator_platform }}
DEVELOPER_DIR: '/Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer' DEVELOPER_DIR: '/Applications/Xcode_${{ matrix.xcode }}.app/Contents/Developer'
@ -452,8 +448,8 @@ jobs:
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }} MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
MAKE_PACKAGE: '${{ matrix.make_package }}' MAKE_PACKAGE: ${{ matrix.make_package }}
PACKAGE_SUFFIX: '${{ matrix.package_suffix }}' PACKAGE_SUFFIX: ${{ matrix.package_suffix }}
TARGET_MACOS_VERSION: ${{ matrix.override_target }} TARGET_MACOS_VERSION: ${{ matrix.override_target }}
USE_CCACHE: ${{ matrix.use_ccache }} USE_CCACHE: ${{ matrix.use_ccache }}
VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite' VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite'
@ -478,50 +474,17 @@ jobs:
key: ${{ steps.ccache_restore.outputs.cache-primary-key }} key: ${{ steps.ccache_restore.outputs.cache-primary-key }}
path: ${{ env.CCACHE_DIR }} path: ${{ env.CCACHE_DIR }}
- name: "[macOS] Sign app bundle" - name: "[macOS] Sign & notarize app bundle"
if: matrix.os == 'macOS' && matrix.make_package && needs.configure.outputs.tag != null # if: matrix.os == 'macOS' && matrix.make_package && needs.configure.outputs.tag != null
id: sign_macos if: matrix.os == 'macOS'
shell: bash
env: env:
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
run: |
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]
then
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
/usr/bin/codesign --sign="$MACOS_CERTIFICATE_NAME" --entitlements=".ci/macos.entitlements" --options=runtime --force --deep --timestamp --verbose "${{ steps.build.outputs.path }}"
fi
- name: "[macOS] Notarize app bundle"
if: matrix.os == 'macOS' && steps.sign_macos.outcome == 'success'
env:
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }} MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
run: | run: .ci/sign_macos_bundle.sh "${{ steps.build.outputs.path }}"
if [[ -n "$MACOS_NOTARIZATION_APPLE_ID" ]]
then
# Store the notarization credentials so that we can prevent a UI password dialog from blocking the CI
echo "Create keychain profile"
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$MACOS_NOTARIZATION_APPLE_ID" --team-id "$MACOS_NOTARIZATION_TEAM_ID" --password "$MACOS_NOTARIZATION_PWD"
# We can't notarize an app bundle directly, but we need to compress it as an archive.
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
# notarization service
echo "Creating temp notarization archive"
ditto -c -k --keepParent "${{ steps.build.outputs.path }}" "notarization.zip"
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
# characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
# you're curious
echo "Notarize app"
xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait
# Finally, we need to "attach the staple" to our executable, which will allow our app to be
# validated by macOS even when an internet connection is not available.
echo "Attach staple"
xcrun stapler staple "${{ steps.build.outputs.path }}"
fi
- name: "Upload artifact" - name: "Upload artifact"
if: matrix.make_package if: matrix.make_package

View file

@ -57,56 +57,57 @@ set(cockatrice_SOURCES
src/filters/syntax_help.cpp src/filters/syntax_help.cpp
src/game/abstract_game.cpp src/game/abstract_game.cpp
src/game/arrow_registry.cpp src/game/arrow_registry.cpp
src/game/board/abstract_card_drag_item.cpp src/game_graphics/board/abstract_card_drag_item.cpp
src/game/board/abstract_card_item.cpp src/game_graphics/board/abstract_card_item.cpp
src/game/board/abstract_counter.cpp src/game_graphics/board/abstract_counter.cpp
src/game/board/arrow_data.cpp src/game/board/arrow_data.cpp
src/game/board/arrow_item.cpp src/game_graphics/board/arrow_item.cpp
src/game/board/arrow_target.cpp src/game_graphics/board/arrow_target.cpp
src/game/board/card_drag_item.cpp src/game_graphics/board/card_drag_item.cpp
src/game/board/card_item.cpp src/game_graphics/board/card_item.cpp
src/game/board/card_list.cpp src/game/board/card_list.cpp
src/game/board/card_state.cpp src/game/board/card_state.cpp
src/game/board/counter_general.cpp src/game_graphics/board/counter_general.cpp
src/game/board/counter_state.cpp src/game/board/counter_state.cpp
src/game/board/translate_counter_name.cpp src/game_graphics/board/translate_counter_name.cpp
src/game/deckview/deck_view.cpp src/game_graphics/deckview/deck_view.cpp
src/game/deckview/deck_view_container.cpp src/game_graphics/deckview/deck_view_container.cpp
src/game/deckview/tabbed_deck_view_container.cpp src/game_graphics/deckview/tabbed_deck_view_container.cpp
src/game/dialogs/dlg_create_token.cpp src/game_graphics/dialogs/dlg_create_token.cpp
src/game/dialogs/dlg_move_top_cards_until.cpp src/game_graphics/dialogs/dlg_move_top_cards_until.cpp
src/game/dialogs/dlg_roll_dice.cpp src/game_graphics/dialogs/dlg_roll_dice.cpp
src/game/game.cpp src/game/game.cpp
src/game/game_event_handler.cpp src/game/game_event_handler.cpp
src/game/game_meta_info.cpp src/game/game_meta_info.cpp
src/game/game_scene.cpp src/game_graphics/game_scene.cpp
src/game/game_state.cpp src/game/game_state.cpp
src/game/game_view.cpp src/game_graphics/game_view.cpp
src/game/hand_counter.cpp src/game_graphics/hand_counter.cpp
src/game/log/message_log_widget.cpp src/game_graphics/log/message_log_widget.cpp
src/game/phase.cpp src/game/phase.cpp
src/game/phases_toolbar.cpp src/game_graphics/phases_toolbar.cpp
src/game/player/menu/card_menu.cpp src/game_graphics/player/menu/card_menu.cpp
src/game/player/menu/custom_zone_menu.cpp src/game_graphics/player/menu/custom_zone_menu.cpp
src/game/player/menu/grave_menu.cpp src/game_graphics/player/menu/grave_menu.cpp
src/game/player/menu/hand_menu.cpp src/game_graphics/player/menu/hand_menu.cpp
src/game/player/menu/library_menu.cpp src/game_graphics/player/menu/library_menu.cpp
src/game/player/menu/move_menu.cpp src/game_graphics/player/menu/move_menu.cpp
src/game/player/menu/player_menu.cpp src/game_graphics/player/menu/player_menu.cpp
src/game/player/menu/pt_menu.cpp src/game_graphics/player/menu/pt_menu.cpp
src/game/player/menu/rfg_menu.cpp src/game_graphics/player/menu/rfg_menu.cpp
src/game/player/menu/say_menu.cpp src/game_graphics/player/menu/say_menu.cpp
src/game/player/menu/sideboard_menu.cpp src/game_graphics/player/menu/sideboard_menu.cpp
src/game/player/menu/utility_menu.cpp src/game_graphics/player/menu/utility_menu.cpp
src/game/player/player_actions.cpp src/game/player/player_actions.cpp
src/game/player/player_area.cpp src/game_graphics/player/player_area.cpp
src/game_graphics/player/player_dialogs.cpp
src/game/player/player_event_handler.cpp src/game/player/player_event_handler.cpp
src/game/player/player_graphics_item.cpp src/game_graphics/player/player_graphics_item.cpp
src/game/player/player_info.cpp src/game/player/player_info.cpp
src/game/player/player_list_widget.cpp src/game_graphics/player/player_list_widget.cpp
src/game/player/player_logic.cpp src/game/player/player_logic.cpp
src/game/player/player_manager.cpp src/game/player/player_manager.cpp
src/game/player/player_target.cpp src/game_graphics/player/player_target.cpp
src/game/replay.cpp src/game/replay.cpp
src/game/zones/card_zone_logic.cpp src/game/zones/card_zone_logic.cpp
src/game/zones/hand_zone_logic.cpp src/game/zones/hand_zone_logic.cpp

View file

@ -388,6 +388,7 @@ SettingsCache::SettingsCache()
ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool(); ignoreUnregisteredUsers = settings->value("chat/ignore_unregistered", false).toBool();
ignoreUnregisteredUserMessages = settings->value("chat/ignore_unregistered_messages", false).toBool(); ignoreUnregisteredUserMessages = settings->value("chat/ignore_unregistered_messages", false).toBool();
ignoreNonBuddyUserMessages = settings->value("chat/ignore_nonbuddy_messages", false).toBool();
scaleCards = settings->value("cards/scaleCards", true).toBool(); scaleCards = settings->value("cards/scaleCards", true).toBool();
verticalCardOverlapPercent = settings->value("cards/verticalCardOverlapPercent", 33).toInt(); verticalCardOverlapPercent = settings->value("cards/verticalCardOverlapPercent", 33).toInt();
@ -1117,6 +1118,12 @@ void SettingsCache::setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T _ignore
settings->setValue("chat/ignore_unregistered_messages", ignoreUnregisteredUserMessages); settings->setValue("chat/ignore_unregistered_messages", ignoreUnregisteredUserMessages);
} }
void SettingsCache::setIgnoreNonBuddyUserMessages(QT_STATE_CHANGED_T _ignoreNonBuddyUserMessages)
{
ignoreNonBuddyUserMessages = static_cast<bool>(_ignoreNonBuddyUserMessages);
settings->setValue("chat/ignore_nonbuddy_messages", ignoreNonBuddyUserMessages);
}
void SettingsCache::setPixmapCacheSize(const int _pixmapCacheSize) void SettingsCache::setPixmapCacheSize(const int _pixmapCacheSize)
{ {
pixmapCacheSize = _pixmapCacheSize; pixmapCacheSize = _pixmapCacheSize;

View file

@ -183,6 +183,7 @@ signals:
void soundThemeChanged(); void soundThemeChanged();
void ignoreUnregisteredUsersChanged(); void ignoreUnregisteredUsersChanged();
void ignoreUnregisteredUserMessagesChanged(); void ignoreUnregisteredUserMessagesChanged();
void ignoreNonBuddyUserMessagesChanged();
void pixmapCacheSizeChanged(int newSizeInMBs); void pixmapCacheSizeChanged(int newSizeInMBs);
void networkCacheSizeChanged(int newSizeInMBs); void networkCacheSizeChanged(int newSizeInMBs);
void redirectCacheTtlChanged(int newTtl); void redirectCacheTtlChanged(int newTtl);
@ -294,6 +295,7 @@ private:
QString soundThemeName; QString soundThemeName;
bool ignoreUnregisteredUsers; bool ignoreUnregisteredUsers;
bool ignoreUnregisteredUserMessages; bool ignoreUnregisteredUserMessages;
bool ignoreNonBuddyUserMessages;
QString picUrl; QString picUrl;
QString picUrlFallback; QString picUrlFallback;
QString clientID; QString clientID;
@ -788,6 +790,10 @@ public:
{ {
return ignoreUnregisteredUserMessages; return ignoreUnregisteredUserMessages;
} }
[[nodiscard]] bool getIgnoreNonBuddyUserMessages() const
{
return ignoreNonBuddyUserMessages;
}
[[nodiscard]] int getPixmapCacheSize() const [[nodiscard]] int getPixmapCacheSize() const
{ {
return pixmapCacheSize; return pixmapCacheSize;
@ -1111,6 +1117,7 @@ public slots:
void setSoundThemeName(const QString &_soundThemeName); void setSoundThemeName(const QString &_soundThemeName);
void setIgnoreUnregisteredUsers(QT_STATE_CHANGED_T _ignoreUnregisteredUsers); void setIgnoreUnregisteredUsers(QT_STATE_CHANGED_T _ignoreUnregisteredUsers);
void setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T _ignoreUnregisteredUserMessages); void setIgnoreUnregisteredUserMessages(QT_STATE_CHANGED_T _ignoreUnregisteredUserMessages);
void setIgnoreNonBuddyUserMessages(QT_STATE_CHANGED_T _ignoreNonBuddyUserMessages);
void setPixmapCacheSize(const int _pixmapCacheSize); void setPixmapCacheSize(const int _pixmapCacheSize);
void setCardImageCacheMethod(CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod); void setCardImageCacheMethod(CardPictureLoaderCacheMethod::CacheMethod _cardImageCachingMethod);
void setNetworkCacheSizeInMB(const int _networkCacheSize); void setNetworkCacheSizeInMB(const int _networkCacheSize);

View file

@ -3,7 +3,7 @@
#include "../interface/widgets/tabs/tab_game.h" #include "../interface/widgets/tabs/tab_game.h"
#include "player/player_logic.h" #include "player/player_logic.h"
AbstractGame::AbstractGame(TabGame *_tab) : QObject(_tab), tab(_tab) AbstractGame::AbstractGame(QObject *_parent) : QObject(_parent)
{ {
gameMetaInfo = new GameMetaInfo(this); gameMetaInfo = new GameMetaInfo(this);
gameEventHandler = new GameEventHandler(this); gameEventHandler = new GameEventHandler(this);

View file

@ -16,26 +16,19 @@
#include <libcockatrice/protocol/pb/game_replay.pb.h> #include <libcockatrice/protocol/pb/game_replay.pb.h>
class CardItem; class CardItem;
class TabGame;
class AbstractGame : public QObject class AbstractGame : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AbstractGame(TabGame *tab); explicit AbstractGame(QObject *parent);
TabGame *tab;
GameMetaInfo *gameMetaInfo; GameMetaInfo *gameMetaInfo;
GameState *gameState; GameState *gameState;
GameEventHandler *gameEventHandler; GameEventHandler *gameEventHandler;
PlayerManager *playerManager; PlayerManager *playerManager;
CardItem *activeCard; CardItem *activeCard;
TabGame *getTab() const
{
return tab;
}
GameMetaInfo *getGameMetaInfo() GameMetaInfo *getGameMetaInfo()
{ {
return gameMetaInfo; return gameMetaInfo;

View file

@ -1,6 +1,6 @@
#include "arrow_registry.h" #include "arrow_registry.h"
#include "board/arrow_item.h" #include "../game_graphics/board/arrow_item.h"
void ArrowRegistry::insert(QSharedPointer<ArrowData> data, ArrowItem *arrow) void ArrowRegistry::insert(QSharedPointer<ArrowData> data, ArrowItem *arrow)
{ {

View file

@ -1,6 +1,6 @@
#include "card_list.h" #include "card_list.h"
#include "card_item.h" #include "../../game_graphics/board/card_item.h"
#include <QDebug> #include <QDebug>
#include <algorithm> #include <algorithm>

View file

@ -4,16 +4,16 @@
#include <libcockatrice/protocol/pb/event_game_joined.pb.h> #include <libcockatrice/protocol/pb/event_game_joined.pb.h>
Game::Game(TabGame *_tab, Game::Game(QObject *_parent,
bool isLocalGame,
QList<AbstractClient *> &_clients, QList<AbstractClient *> &_clients,
const Event_GameJoined &event, const Event_GameJoined &event,
const QMap<int, QString> &_roomGameTypes) const QMap<int, QString> &_roomGameTypes)
: AbstractGame(_tab) : AbstractGame(_parent)
{ {
gameMetaInfo->setFromProto(event.game_info()); gameMetaInfo->setFromProto(event.game_info());
gameMetaInfo->setRoomGameTypes(_roomGameTypes); gameMetaInfo->setRoomGameTypes(_roomGameTypes);
gameState = new GameState(this, 0, event.host_id(), tab->getTabSupervisor()->getIsLocalGame(), _clients, false, gameState = new GameState(this, 0, event.host_id(), isLocalGame, _clients, false, event.resuming(), -1, false);
event.resuming(), -1, false);
connect(gameMetaInfo, &GameMetaInfo::startedChanged, gameState, &GameState::onStartedChanged); connect(gameMetaInfo, &GameMetaInfo::startedChanged, gameState, &GameState::onStartedChanged);
playerManager = new PlayerManager(this, event.player_id(), event.judge(), event.spectator()); playerManager = new PlayerManager(this, event.player_id(), event.judge(), event.spectator());
gameMetaInfo->setStarted(false); gameMetaInfo->setStarted(false);

View file

@ -16,7 +16,8 @@ class Game : public AbstractGame
Q_OBJECT Q_OBJECT
public: public:
Game(TabGame *tab, Game(QObject *parent,
bool isLocalGame,
QList<AbstractClient *> &_clients, QList<AbstractClient *> &_clients,
const Event_GameJoined &event, const Event_GameJoined &event,
const QMap<int, QString> &_roomGameTypes); const QMap<int, QString> &_roomGameTypes);

View file

@ -1,8 +1,8 @@
#include "game_event_handler.h" #include "game_event_handler.h"
#include "../game_graphics/log/message_log_widget.h"
#include "../interface/widgets/tabs/tab_game.h" #include "../interface/widgets/tabs/tab_game.h"
#include "abstract_game.h" #include "abstract_game.h"
#include "log/message_log_widget.h"
#include <libcockatrice/network/client/abstract/abstract_client.h> #include <libcockatrice/network/client/abstract/abstract_client.h>
#include <libcockatrice/protocol/get_pb_extension.h> #include <libcockatrice/protocol/get_pb_extension.h>

File diff suppressed because it is too large Load diff

View file

@ -7,8 +7,11 @@
#ifndef COCKATRICE_PLAYER_ACTIONS_H #ifndef COCKATRICE_PLAYER_ACTIONS_H
#define COCKATRICE_PLAYER_ACTIONS_H #define COCKATRICE_PLAYER_ACTIONS_H
#include "../dialogs/dlg_create_token.h"
#include "../dialogs/dlg_move_top_cards_until.h" #include "../../game_graphics/board/card_item.h"
#include "../../game_graphics/dialogs/dlg_create_token.h"
#include "../../game_graphics/dialogs/dlg_move_top_cards_until.h"
#include "../../game_graphics/player/card_menu_action_type.h"
#include "event_processing_options.h" #include "event_processing_options.h"
#include "player_logic.h" #include "player_logic.h"
@ -25,7 +28,6 @@ class Message;
} }
} // namespace google } // namespace google
class CardItem;
class Command_MoveCard; class Command_MoveCard;
class GameEventContext; class GameEventContext;
class PendingCommand; class PendingCommand;
@ -56,30 +58,75 @@ public:
return movingCardsUntil; return movingCardsUntil;
} }
signals:
void requestViewTopCardsDialog(int defaultNumberTopCards, int deckSize);
void requestViewBottomCardsDialog(int defaultNumberBottomCards, int deckSize);
void requestShuffleTopDialog(int defaultNumberTopCards, int maxCards);
void requestShuffleBottomDialog(int defaultNumberBottomCards, int maxCards);
void requestMulliganDialog(int startSize, int handSize, int deckSize);
void requestDrawCardsDialog(int defaultNumberTopCards, int deckSize);
void requestMoveTopCardsToDialog(int defaultNumberTopCards,
int maxCards,
const QString &targetZone,
const QString &zoneDisplayName,
bool faceDown);
void requestMoveTopCardsUntilDialog(MoveTopCardsUntilOptions options);
void requestMoveBottomCardsToDialog(int defaultNumberBottomCards,
int maxCards,
const QString &targetZone,
const QString &zoneDisplayName,
bool faceDown);
void requestDrawBottomCardsDialog(int defaultNumberBottomCards, int maxCards);
void requestRollDieDialog();
void requestCreateTokenDialog(const QStringList &predefinedTokens);
void requestCreateRelatedFromRelationDialog(const CardItem *sourceCard, const CardRelation *cardRelation);
void requestMoveCardXCardsFromTopDialog(int defaultNumberTopCardsToPlaceBelow, int deckSize);
void requestSetPTDialog(const QString &oldPT);
void requestSetAnnotationDialog(const QString &oldAnnotation);
void requestSetCardCounterDialog(int counterId, const QString &oldValueForDlg);
void requestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed = false);
void requestSortHand(const QList<CardList::SortOption> &options);
void requestEnableAndSetCreateAnotherTokenAction(const QString &lastTokenName);
void requestSetLastToken(CardInfoPtr lastToken);
public slots: public slots:
void setLastToken(CardInfoPtr cardInfo); void setLastToken(CardInfoPtr cardInfo);
void setLastTokenInfo(CardInfoPtr cardInfo);
void playCard(CardItem *c, bool faceDown); void playCard(CardItem *c, bool faceDown);
void playCardToTable(const CardItem *c, bool faceDown); void playCardToTable(const CardItem *c, bool faceDown);
void actUntapAll(); void actUntapAll();
void actRollDie(); void actRequestRollDieDialog();
void actRollDie(int sides, int count);
void actFlipCoin(); void actFlipCoin();
void actCreateToken(); void actRequestCreateTokenDialog(const QStringList &predefinedTokens);
void actCreateToken(TokenInfo tokenToCreate);
void actCreateAnotherToken(); void actCreateAnotherToken();
void actRequestCreateRelatedFromRelationDialog(const CardItem *sourceCard, const CardRelation *cardRelation);
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation, int variableCount);
void onRelatedCardCreated(const CardItem *sourceCard, const CardRelation *cardRelation);
void setLastRelatedCreationSucceeded(bool succeeded)
{
lastRelatedCreationSucceeded = succeeded;
}
void actShuffle(); void actShuffle();
void actShuffleTop(); void actRequestShuffleTopDialog();
void actShuffleBottom(); void actShuffleTop(int number);
void actRequestShuffleBottomDialog();
void actShuffleBottom(int number);
void actDrawCard(); void actDrawCard();
void actDrawCards(); void actRequestDrawCardsDialog();
void actDrawCards(int number);
void actUndoDraw(); void actUndoDraw();
void actMulligan(); void actRequestMulliganDialog();
void actMulligan(int number);
void actMulliganSameSize(); void actMulliganSameSize();
void actMulliganMinusOne(); void actMulliganMinusOne();
void doMulligan(int number); void doMulligan(int number);
void actPlay(); void actPlay(QList<CardItem *> selectedCards);
void actPlayFacedown(); void actPlayFacedown(QList<CardItem *> selectedCards);
void actHide(); void actHide(QList<CardItem *> selectedCards);
void actMoveTopCardToPlay(); void actMoveTopCardToPlay();
void actMoveTopCardToPlayFaceDown(); void actMoveTopCardToPlayFaceDown();
@ -89,10 +136,14 @@ public slots:
void actMoveTopCardsToGraveFaceDown(); void actMoveTopCardsToGraveFaceDown();
void actMoveTopCardsToExile(); void actMoveTopCardsToExile();
void actMoveTopCardsToExileFaceDown(); void actMoveTopCardsToExileFaceDown();
void actMoveTopCardsUntil(); void actRequestMoveTopCardsUntilDialog();
void moveTopCardsUntil(const QString &expr, MoveTopCardsUntilOptions options);
void actMoveTopCardToBottom(); void actMoveTopCardToBottom();
void actRequestMoveTopCardsToDialog(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);
void moveTopCardsTo(int number, const QString &targetZone, bool faceDown);
void actDrawBottomCard(); void actDrawBottomCard();
void actDrawBottomCards(); void actRequestDrawBottomCardsDialog();
void actDrawBottomCards(int number);
void actMoveBottomCardToPlay(); void actMoveBottomCardToPlay();
void actMoveBottomCardToPlayFaceDown(); void actMoveBottomCardToPlayFaceDown();
void actMoveBottomCardToGrave(); void actMoveBottomCardToGrave();
@ -102,6 +153,8 @@ public slots:
void actMoveBottomCardsToExile(); void actMoveBottomCardsToExile();
void actMoveBottomCardsToExileFaceDown(); void actMoveBottomCardsToExileFaceDown();
void actMoveBottomCardToTop(); void actMoveBottomCardToTop();
void actRequestMoveBottomCardsToDialog(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);
void moveBottomCardsTo(int number, const QString &targetZone, bool faceDown);
void actSelectAll(); void actSelectAll();
void actSelectRow(); void actSelectRow();
@ -109,10 +162,12 @@ public slots:
void actViewLibrary(); void actViewLibrary();
void actViewHand(); void actViewHand();
void actViewTopCards(); void actRequestViewTopCardsDialog();
void actViewBottomCards(); void actViewTopCards(int number);
void actAlwaysRevealTopCard(); void actRequestViewBottomCardsDialog();
void actAlwaysLookAtTopCard(); void actViewBottomCards(int number);
void actAlwaysRevealTopCard(bool alwaysRevealTopCard);
void actAlwaysLookAtTopCard(bool alwaysRevealTopCard);
void actViewGraveyard(); void actViewGraveyard();
void actLendLibrary(int lendToPlayerId); void actLendLibrary(int lendToPlayerId);
void actRevealTopCards(int revealToPlayerId, int amount); void actRevealTopCards(int revealToPlayerId, int amount);
@ -127,37 +182,41 @@ public slots:
void actCreateRelatedCard(); void actCreateRelatedCard();
void actCreateAllRelatedCards(); void actCreateAllRelatedCards();
void actMoveCardXCardsFromTop(); void actRequestMoveCardXCardsFromTopDialog();
void actRemoveCardCounter(int counterId); void actMoveCardXCardsFromTop(QList<CardItem *> selectedCards, int number);
void actAddCardCounter(int counterId); void actRemoveCardCounter(QList<CardItem *> selectedCards, int counterId);
void actSetCardCounter(int counterId); void actAddCardCounter(QList<CardItem *> selectedCards, int counterId);
void actIncrementAllCardCounters(); void actRequestSetCardCounterDialog(QList<CardItem *> selectedCards, int counterId);
void actSetCardCounter(QList<CardItem *> selectedCards, int counterId, const QString &counterValue);
void actIncrementAllCardCounters(QList<CardItem *> cardsToUpdate);
void actAttach(); void actAttach();
void actUnattach(); void actUnattach(QList<CardItem *> selectedCards);
void actDrawArrow(); void actDrawArrow();
void actIncPT(int deltaP, int deltaT); void actIncPT(QList<CardItem *> selectedCards, int deltaP, int deltaT);
void actResetPT(); void actResetPT(QList<CardItem *> selectedCards);
void actSetPT(); void actRequestSetPTDialog(QList<CardItem *> selectedCards);
void actIncP(); void actSetPT(QList<CardItem *> selectedCards, const QString &pt);
void actDecP(); void actIncP(QList<CardItem *> selectedCards);
void actIncT(); void actDecP(QList<CardItem *> selectedCards);
void actDecT(); void actIncT(QList<CardItem *> selectedCards);
void actIncPT(); void actDecT(QList<CardItem *> selectedCards);
void actDecPT(); void actIncPT(QList<CardItem *> selectedCards);
void actFlowP(); void actDecPT(QList<CardItem *> selectedCards);
void actFlowT(); void actFlowP(QList<CardItem *> selectedCards);
void actFlowT(QList<CardItem *> selectedCards);
void actReduceLifeByPower(); void actReduceLifeByPower(QList<CardItem *> selectedCards);
void actSetAnnotation(); void actRequestSetAnnotationDialog(QList<CardItem *> selectedCards);
void actReveal(QAction *action); void actSetAnnotation(QList<CardItem *> selectedCards, const QString &annotation);
void actReveal(QList<CardItem *> selectedCards, QAction *action);
void actRevealHand(int revealToPlayerId); void actRevealHand(int revealToPlayerId);
void actRevealRandomHandCard(int revealToPlayerId); void actRevealRandomHandCard(int revealToPlayerId);
void actRevealLibrary(int revealToPlayerId); void actRevealLibrary(int revealToPlayerId);
void actSortHand(); void actSortHand();
void cardMenuAction(); void cardMenuAction(QList<CardItem *> selectedCards, CardMenuActionType type);
private: private:
PlayerLogic *player; PlayerLogic *player;
@ -176,21 +235,19 @@ private:
int movingCardsUntilCounter = 0; int movingCardsUntilCounter = 0;
MoveTopCardsUntilOptions movingCardsUntilOptions; MoveTopCardsUntilOptions movingCardsUntilOptions;
void moveTopCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown); bool lastRelatedCreationSucceeded = false;
void moveBottomCardsTo(const QString &targetZone, const QString &zoneDisplayName, bool faceDown);
void createCard(const CardItem *sourceCard, void createCard(const CardItem *sourceCard,
const QString &dbCardName, const QString &dbCardName,
CardRelationType attach = CardRelationType::DoesNotAttach, CardRelationType attach = CardRelationType::DoesNotAttach,
bool persistent = false); bool persistent = false);
bool createRelatedFromRelation(const CardItem *sourceCard, const CardRelation *cardRelation);
void playSelectedCards(bool faceDown = false); void playSelectedCards(QList<CardItem *> selectedCards, bool faceDown = false);
void cmdSetTopCard(Command_MoveCard &cmd); void cmdSetTopCard(Command_MoveCard &cmd);
void cmdSetBottomCard(Command_MoveCard &cmd); void cmdSetBottomCard(Command_MoveCard &cmd);
void offsetCardCounter(int counterId, int offset); void offsetCardCounter(QList<CardItem *> selectedCards, int counterId, int offset);
}; };
#endif // COCKATRICE_PLAYER_ACTIONS_H #endif // COCKATRICE_PLAYER_ACTIONS_H

View file

@ -1,12 +1,11 @@
#include "player_event_handler.h" #include "player_event_handler.h"
#include "../../game_graphics/board/arrow_item.h"
#include "../../game_graphics/board/card_item.h"
#include "../../game_graphics/zones/view_zone.h" #include "../../game_graphics/zones/view_zone.h"
#include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/tabs/tab_game.h"
#include "../board/arrow_data.h" #include "../board/arrow_data.h"
#include "../board/arrow_item.h"
#include "../board/card_item.h"
#include "../board/card_list.h" #include "../board/card_list.h"
#include "libcockatrice/utility/color.h"
#include "player_actions.h" #include "player_actions.h"
#include "player_logic.h" #include "player_logic.h"
@ -33,10 +32,12 @@
#include <libcockatrice/protocol/pb/event_set_card_counter.pb.h> #include <libcockatrice/protocol/pb/event_set_card_counter.pb.h>
#include <libcockatrice/protocol/pb/event_set_counter.pb.h> #include <libcockatrice/protocol/pb/event_set_counter.pb.h>
#include <libcockatrice/protocol/pb/event_shuffle.pb.h> #include <libcockatrice/protocol/pb/event_shuffle.pb.h>
#include <libcockatrice/utility/color.h>
#include <libcockatrice/utility/zone_names.h> #include <libcockatrice/utility/zone_names.h>
PlayerEventHandler::PlayerEventHandler(PlayerLogic *_player) : QObject(_player), player(_player) PlayerEventHandler::PlayerEventHandler(PlayerLogic *_player) : QObject(_player), player(_player)
{ {
connect(this, &PlayerEventHandler::requestCardMenuUpdate, player, &PlayerLogic::requestCardMenuUpdate);
} }
void PlayerEventHandler::eventGameSay(const Event_GameSay &event) void PlayerEventHandler::eventGameSay(const Event_GameSay &event)
@ -252,7 +253,7 @@ void PlayerEventHandler::eventSetCardCounter(const Event_SetCardCounter &event)
int oldValue = card->getCounters().value(event.counter_id(), 0); int oldValue = card->getCounters().value(event.counter_id(), 0);
card->setCounter(event.counter_id(), event.counter_value()); card->setCounter(event.counter_id(), event.counter_value());
player->getPlayerMenu()->updateCardMenu(card); emit requestCardMenuUpdate(card);
emit logSetCardCounter(player, card->getName(), event.counter_id(), event.counter_value(), oldValue); emit logSetCardCounter(player, card->getName(), event.counter_id(), event.counter_value(), oldValue);
} }
@ -370,7 +371,7 @@ void PlayerEventHandler::eventMoveCard(const Event_MoveCard &event, const GameEv
targetZone->addCard(card, true, x, y); targetZone->addCard(card, true, x, y);
emit cardZoneChanged(card, startZone == targetZone); emit cardZoneChanged(card, startZone == targetZone);
player->getPlayerMenu()->updateCardMenu(card); emit requestCardMenuUpdate(card);
if (player->getPlayerActions()->isMovingCardsUntil() && startZoneString == ZoneNames::DECK && if (player->getPlayerActions()->isMovingCardsUntil() && startZoneString == ZoneNames::DECK &&
targetZone->getName() == ZoneNames::STACK) { targetZone->getName() == ZoneNames::STACK) {
@ -397,7 +398,7 @@ void PlayerEventHandler::eventFlipCard(const Event_FlipCard &event)
emit logFlipCard(player, card->getName(), event.face_down()); emit logFlipCard(player, card->getName(), event.face_down());
card->setFaceDown(event.face_down()); card->setFaceDown(event.face_down());
player->getPlayerMenu()->updateCardMenu(card); emit requestCardMenuUpdate(card);
} }
void PlayerEventHandler::eventDestroyCard(const Event_DestroyCard &event) void PlayerEventHandler::eventDestroyCard(const Event_DestroyCard &event)
@ -466,7 +467,7 @@ void PlayerEventHandler::eventAttachCard(const Event_AttachCard &event)
} else { } else {
emit logUnattachCard(player, startCard->getName()); emit logUnattachCard(player, startCard->getName());
} }
player->getPlayerMenu()->updateCardMenu(startCard); emit requestCardMenuUpdate(startCard);
} }
void PlayerEventHandler::eventDrawCards(const Event_DrawCards &event) void PlayerEventHandler::eventDrawCards(const Event_DrawCards &event)
@ -552,7 +553,7 @@ void PlayerEventHandler::eventRevealCards(const Event_RevealCards &event, EventP
} }
if (!options.testFlag(SKIP_REVEAL_WINDOW) && showZoneView && !cardList.isEmpty()) { if (!options.testFlag(SKIP_REVEAL_WINDOW) && showZoneView && !cardList.isEmpty()) {
player->getGameScene()->addRevealedZoneView(player, zone, cardList, event.grant_write_access()); emit player->requestRevealedZoneView(player, zone, cardList, event.grant_write_access());
} }
emit logRevealCards(player, zone, cardId, cardName, otherPlayer, false, emit logRevealCards(player, zone, cardId, cardName, otherPlayer, false,

View file

@ -83,6 +83,7 @@ signals:
void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); void logAlwaysRevealTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal);
void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal); void logAlwaysLookAtTopCard(PlayerLogic *player, CardZoneLogic *zone, bool reveal);
void cardZoneChanged(CardItem *card, bool sameZone); void cardZoneChanged(CardItem *card, bool sameZone);
void requestCardMenuUpdate(const CardItem *card);
public: public:
PlayerEventHandler(PlayerLogic *player); PlayerEventHandler(PlayerLogic *player);

View file

@ -7,7 +7,7 @@
#ifndef COCKATRICE_PLAYER_INFO_H #ifndef COCKATRICE_PLAYER_INFO_H
#define COCKATRICE_PLAYER_INFO_H #define COCKATRICE_PLAYER_INFO_H
#include "player_target.h" #include "../../game_graphics/player/player_target.h"
#include <QObject> #include <QObject>
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h> #include <libcockatrice/protocol/pb/serverinfo_user.pb.h>

View file

@ -1,18 +1,18 @@
#include "player_logic.h" #include "player_logic.h"
#include "../../game_graphics/board/arrow_item.h"
#include "../../game_graphics/board/card_item.h"
#include "../../game_graphics/board/counter_general.h"
#include "../../game_graphics/game_scene.h"
#include "../../game_graphics/player/player_target.h"
#include "../../game_graphics/zones/hand_zone.h" #include "../../game_graphics/zones/hand_zone.h"
#include "../../game_graphics/zones/pile_zone.h" #include "../../game_graphics/zones/pile_zone.h"
#include "../../game_graphics/zones/stack_zone.h" #include "../../game_graphics/zones/stack_zone.h"
#include "../../game_graphics/zones/table_zone.h" #include "../../game_graphics/zones/table_zone.h"
#include "../../interface/theme_manager.h" #include "../../interface/theme_manager.h"
#include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/tabs/tab_game.h"
#include "../board/arrow_item.h"
#include "../board/card_item.h"
#include "../board/card_list.h" #include "../board/card_list.h"
#include "../board/counter_general.h"
#include "../game_scene.h"
#include "player_actions.h" #include "player_actions.h"
#include "player_target.h"
#include <QDebug> #include <QDebug>
#include <QMenu> #include <QMenu>
@ -35,14 +35,6 @@ PlayerLogic::PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool
conceded(false), zoneId(0), dialogSemaphore(false) conceded(false), zoneId(0), dialogSemaphore(false)
{ {
initializeZones(); initializeZones();
playerMenu = new PlayerMenu(this);
graphicsItem = new PlayerGraphicsItem(this);
playerMenu->setMenusForGraphicItems();
connect(this, &PlayerLogic::activeChanged, graphicsItem, &PlayerGraphicsItem::onPlayerActiveChanged);
connect(this, &PlayerLogic::openDeckEditor, game->getTab(), &TabGame::openDeckEditor);
} }
void PlayerLogic::initializeZones() void PlayerLogic::initializeZones()
@ -68,7 +60,6 @@ PlayerLogic::~PlayerLogic()
} }
zones.clear(); zones.clear();
delete playerMenu;
delete getPlayerInfo()->userInfo; delete getPlayerInfo()->userInfo;
} }
@ -326,22 +317,16 @@ void PlayerLogic::setActive(bool _active)
active = _active; active = _active;
emit activeChanged(active); emit activeChanged(active);
} }
void PlayerLogic::onRequestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed)
{
emit requestZoneViewToggle(this, zoneName, numberCards, isReversed);
}
void PlayerLogic::updateZones() void PlayerLogic::updateZones()
{ {
getTableZone()->reorganizeCards(); getTableZone()->reorganizeCards();
} }
PlayerGraphicsItem *PlayerLogic::getGraphicsItem()
{
return graphicsItem;
}
GameScene *PlayerLogic::getGameScene()
{
return getGraphicsItem()->getGameScene();
}
void PlayerLogic::setGameStarted() void PlayerLogic::setGameStarted()
{ {
if (playerInfo->local) { if (playerInfo->local) {

View file

@ -7,6 +7,7 @@
#ifndef PLAYER_H #ifndef PLAYER_H
#define PLAYER_H #define PLAYER_H
#include "../../game_graphics/player/player_area.h"
#include "../../interface/widgets/menus/tearoff_menu.h" #include "../../interface/widgets/menus/tearoff_menu.h"
#include "../board/arrow_data.h" #include "../board/arrow_data.h"
#include "../interface/deck_loader/loaded_deck.h" #include "../interface/deck_loader/loaded_deck.h"
@ -14,10 +15,7 @@
#include "../zones/pile_zone_logic.h" #include "../zones/pile_zone_logic.h"
#include "../zones/stack_zone_logic.h" #include "../zones/stack_zone_logic.h"
#include "../zones/table_zone_logic.h" #include "../zones/table_zone_logic.h"
#include "menu/player_menu.h"
#include "player_area.h"
#include "player_event_handler.h" #include "player_event_handler.h"
#include "player_graphics_item.h"
#include "player_info.h" #include "player_info.h"
#include <QInputDialog> #include <QInputDialog>
@ -54,6 +52,7 @@ class PlayerMenu;
class QAction; class QAction;
class QMenu; class QMenu;
class ServerInfo_Arrow; class ServerInfo_Arrow;
class ServerInfo_Card;
class ServerInfo_Counter; class ServerInfo_Counter;
class ServerInfo_Player; class ServerInfo_Player;
class ServerInfo_User; class ServerInfo_User;
@ -67,8 +66,14 @@ class PlayerLogic : public QObject
signals: signals:
void openDeckEditor(const LoadedDeck &deck); void openDeckEditor(const LoadedDeck &deck);
void requestZoneViewToggle(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed);
void requestRevealedZoneView(PlayerLogic *player,
CardZoneLogic *zone,
const QList<const ServerInfo_Card *> &cardList,
bool withWritePermission);
void deckChanged(); void deckChanged();
void newCardAdded(AbstractCardItem *card); void newCardAdded(AbstractCardItem *card);
void requestCardMenuUpdate(const CardItem *card);
void counterAdded(CounterState *state); void counterAdded(CounterState *state);
void counterRemoved(int counterId); void counterRemoved(int counterId);
void rearrangeCounters(); void rearrangeCounters();
@ -85,6 +90,7 @@ signals:
public slots: public slots:
void setActive(bool _active); void setActive(bool _active);
void onRequestZoneViewToggle(const QString &zoneName, int numberCards, bool isReversed);
public: public:
PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent); PlayerLogic(const ServerInfo_User &info, int _id, bool _local, bool _judge, AbstractGame *_parent);
@ -112,10 +118,6 @@ public:
return game; return game;
} }
GameScene *getGameScene();
[[nodiscard]] PlayerGraphicsItem *getGraphicsItem();
[[nodiscard]] PlayerActions *getPlayerActions() const [[nodiscard]] PlayerActions *getPlayerActions() const
{ {
return playerActions; return playerActions;
@ -131,11 +133,6 @@ public:
return playerInfo; return playerInfo;
} }
[[nodiscard]] PlayerMenu *getPlayerMenu() const
{
return playerMenu;
}
void setDeck(const DeckList &_deck); void setDeck(const DeckList &_deck);
[[nodiscard]] const DeckList &getDeck() const [[nodiscard]] const DeckList &getDeck() const
@ -234,8 +231,6 @@ private:
PlayerInfo *playerInfo; PlayerInfo *playerInfo;
PlayerEventHandler *playerEventHandler; PlayerEventHandler *playerEventHandler;
PlayerActions *playerActions; PlayerActions *playerActions;
PlayerMenu *playerMenu;
PlayerGraphicsItem *graphicsItem;
bool active; bool active;
bool conceded; bool conceded;

View file

@ -2,9 +2,9 @@
#include "../interface/widgets/tabs/tab_game.h" #include "../interface/widgets/tabs/tab_game.h"
Replay::Replay(TabGame *_tab, GameReplay *_replay) : AbstractGame(_tab) Replay::Replay(QObject *_parent, GameReplay *_replay, bool isLocalGame) : AbstractGame(_parent)
{ {
gameState = new GameState(this, 0, -1, tab->getTabSupervisor()->getIsLocalGame(), {}, false, false, -1, false); gameState = new GameState(this, 0, -1, isLocalGame, {}, false, false, -1, false);
connect(gameMetaInfo, &GameMetaInfo::startedChanged, gameState, &GameState::onStartedChanged); connect(gameMetaInfo, &GameMetaInfo::startedChanged, gameState, &GameState::onStartedChanged);
playerManager = new PlayerManager(this, -1, false, true); playerManager = new PlayerManager(this, -1, false, true);
loadReplay(_replay); loadReplay(_replay);

View file

@ -15,7 +15,7 @@ class Replay : public AbstractGame
Q_OBJECT Q_OBJECT
public: public:
explicit Replay(TabGame *_tab, GameReplay *_replay); explicit Replay(QObject *_parent, GameReplay *_replay, bool isLocalGame);
}; };
#endif // COCKATRICE_REPLAY_H #endif // COCKATRICE_REPLAY_H

View file

@ -1,7 +1,7 @@
#include "card_zone_logic.h" #include "card_zone_logic.h"
#include "../../game_graphics/board/card_item.h"
#include "../../game_graphics/zones/view_zone.h" #include "../../game_graphics/zones/view_zone.h"
#include "../board/card_item.h"
#include "../player/player_actions.h" #include "../player/player_actions.h"
#include "../player/player_logic.h" #include "../player/player_logic.h"
#include "view_zone_logic.h" #include "view_zone_logic.h"

View file

@ -1,6 +1,6 @@
#include "hand_zone_logic.h" #include "hand_zone_logic.h"
#include "../board/card_item.h" #include "../../game_graphics/board/card_item.h"
#include "card_zone_algorithms.h" #include "card_zone_algorithms.h"
HandZoneLogic::HandZoneLogic(PlayerLogic *_player, HandZoneLogic::HandZoneLogic(PlayerLogic *_player,

View file

@ -1,6 +1,6 @@
#include "pile_zone_logic.h" #include "pile_zone_logic.h"
#include "../board/card_item.h" #include "../../game_graphics/board/card_item.h"
PileZoneLogic::PileZoneLogic(PlayerLogic *_player, PileZoneLogic::PileZoneLogic(PlayerLogic *_player,
const QString &_name, const QString &_name,

View file

@ -1,6 +1,6 @@
#include "stack_zone_logic.h" #include "stack_zone_logic.h"
#include "../board/card_item.h" #include "../../game_graphics/board/card_item.h"
#include "card_zone_algorithms.h" #include "card_zone_algorithms.h"
StackZoneLogic::StackZoneLogic(PlayerLogic *_player, StackZoneLogic::StackZoneLogic(PlayerLogic *_player,

View file

@ -1,6 +1,6 @@
#include "table_zone_logic.h" #include "table_zone_logic.h"
#include "../board/card_item.h" #include "../../game_graphics/board/card_item.h"
TableZoneLogic::TableZoneLogic(PlayerLogic *_player, TableZoneLogic::TableZoneLogic(PlayerLogic *_player,
const QString &_name, const QString &_name,

View file

@ -1,7 +1,7 @@
#include "view_zone_logic.h" #include "view_zone_logic.h"
#include "../../client/settings/cache_settings.h" #include "../../client/settings/cache_settings.h"
#include "../board/card_item.h" #include "../../game_graphics/board/card_item.h"
/** /**
* @param _player the player that the cards are revealed to. * @param _player the player that the cards are revealed to.

View file

@ -7,9 +7,9 @@
#ifndef ABSTRACTCARDITEM_H #ifndef ABSTRACTCARDITEM_H
#define ABSTRACTCARDITEM_H #define ABSTRACTCARDITEM_H
#include "../../game_graphics/board/graphics_item_type.h"
#include "../card_dimensions.h" #include "../card_dimensions.h"
#include "arrow_target.h" #include "arrow_target.h"
#include "graphics_item_type.h"
#include <libcockatrice/card/printing/exact_card.h> #include <libcockatrice/card/printing/exact_card.h>
#include <libcockatrice/utility/card_ref.h> #include <libcockatrice/utility/card_ref.h>
@ -44,6 +44,11 @@ signals:
void deleteCardInfoPopup(QString cardName); void deleteCardInfoPopup(QString cardName);
void sigPixmapUpdated(); void sigPixmapUpdated();
void cardShiftClicked(QString cardName); void cardShiftClicked(QString cardName);
void rightClicked(AbstractCardItem *card, QPoint screenPos);
void playSelected(AbstractCardItem *card);
void playSelectedFaceDown(AbstractCardItem *card);
void hideSelected(AbstractCardItem *card);
void selectionChanged(AbstractCardItem *card, bool selected);
public: public:
enum enum

View file

@ -1,10 +1,10 @@
#include "abstract_counter.h" #include "abstract_counter.h"
#include "../../client/settings/cache_settings.h" #include "../../client/settings/cache_settings.h"
#include "../../game/player/player_actions.h"
#include "../../game/player/player_logic.h"
#include "../../game_graphics/board/translate_counter_name.h"
#include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/tabs/tab_game.h"
#include "../player/player_actions.h"
#include "../player/player_logic.h"
#include "translate_counter_name.h"
#include <QAction> #include <QAction>
#include <QApplication> #include <QApplication>

View file

@ -7,9 +7,9 @@
#ifndef COUNTER_H #ifndef COUNTER_H
#define COUNTER_H #define COUNTER_H
#include "../../game/board/counter_state.h"
#include "../../interface/widgets/menus/tearoff_menu.h" #include "../../interface/widgets/menus/tearoff_menu.h"
#include "../player/menu/abstract_player_component.h" #include "../player/menu/abstract_player_component.h"
#include "counter_state.h"
#include <QGraphicsItem> #include <QGraphicsItem>
#include <QInputDialog> #include <QInputDialog>

View file

@ -2,11 +2,11 @@
#include "arrow_item.h" #include "arrow_item.h"
#include "../../client/settings/cache_settings.h" #include "../../client/settings/cache_settings.h"
#include "../../game_graphics/zones/card_zone.h" #include "../../game/player/player_actions.h"
#include "../player/player_actions.h" #include "../../game/player/player_logic.h"
#include "../player/player_logic.h"
#include "../player/player_target.h" #include "../player/player_target.h"
#include "../z_values.h" #include "../z_values.h"
#include "../zones/card_zone.h"
#include "card_item.h" #include "card_item.h"
#include <QDebug> #include <QDebug>

View file

@ -1,7 +1,7 @@
#ifndef ARROWITEM_H #ifndef ARROWITEM_H
#define ARROWITEM_H #define ARROWITEM_H
#include "arrow_data.h" #include "../../game/board/arrow_data.h"
#include "arrow_target.h" #include "arrow_target.h"
#include <QGraphicsItem> #include <QGraphicsItem>

View file

@ -1,6 +1,6 @@
#include "arrow_target.h" #include "arrow_target.h"
#include "../player/player_logic.h" #include "../../game/player/player_logic.h"
#include "arrow_item.h" #include "arrow_item.h"
ArrowTarget::ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent) : AbstractGraphicsItem(parent), owner(_owner) ArrowTarget::ArrowTarget(PlayerLogic *_owner, QGraphicsItem *parent) : AbstractGraphicsItem(parent), owner(_owner)

View file

@ -7,7 +7,7 @@
#ifndef ARROWTARGET_H #ifndef ARROWTARGET_H
#define ARROWTARGET_H #define ARROWTARGET_H
#include "../../game_graphics/board/abstract_graphics_item.h" #include "abstract_graphics_item.h"
#include <QList> #include <QList>

View file

@ -1,9 +1,9 @@
#include "card_drag_item.h" #include "card_drag_item.h"
#include "../../game_graphics/zones/card_zone.h"
#include "../../game_graphics/zones/table_zone.h"
#include "../../game_graphics/zones/view_zone.h"
#include "../game_scene.h" #include "../game_scene.h"
#include "../zones/card_zone.h"
#include "../zones/table_zone.h"
#include "../zones/view_zone.h"
#include "card_item.h" #include "card_item.h"
#include <QCursor> #include <QCursor>

View file

@ -1,14 +1,14 @@
#include "card_item.h" #include "card_item.h"
#include "../../client/settings/cache_settings.h" #include "../../client/settings/cache_settings.h"
#include "../../game_graphics/zones/table_zone.h" #include "../../game/phase.h"
#include "../../game_graphics/zones/view_zone.h" #include "../../game/player/player_actions.h"
#include "../../game/player/player_logic.h"
#include "../../game/zones/view_zone_logic.h"
#include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/tabs/tab_game.h"
#include "../game_scene.h" #include "../game_scene.h"
#include "../phase.h" #include "../zones/table_zone.h"
#include "../player/player_actions.h" #include "../zones/view_zone.h"
#include "../player/player_logic.h"
#include "../zones/view_zone_logic.h"
#include "arrow_item.h" #include "arrow_item.h"
#include "card_drag_item.h" #include "card_drag_item.h"
@ -40,7 +40,7 @@ void CardItem::prepareDelete()
{ {
if (owner != nullptr) { if (owner != nullptr) {
if (owner->getGame()->getActiveCard() == this) { if (owner->getGame()->getActiveCard() == this) {
owner->getPlayerMenu()->updateCardMenu(nullptr); emit owner->requestCardMenuUpdate(nullptr);
owner->getGame()->setActiveCard(nullptr); owner->getGame()->setActiveCard(nullptr);
} }
owner = nullptr; owner = nullptr;
@ -399,8 +399,11 @@ void CardItem::playCard(bool faceDown)
emit tz->toggleTapped(); emit tz->toggleTapped();
} else { } else {
if (SettingsCache::instance().getClickPlaysAllSelected()) { if (SettingsCache::instance().getClickPlaysAllSelected()) {
faceDown ? state->getZone()->getPlayer()->getPlayerActions()->actPlayFacedown() if (faceDown) {
: state->getZone()->getPlayer()->getPlayerActions()->actPlay(); emit playSelectedFaceDown(this);
} else {
emit playSelected(this);
}
} else { } else {
state->getZone()->getPlayer()->getPlayerActions()->playCard(this, faceDown); state->getZone()->getPlayer()->getPlayerActions()->playCard(this, faceDown);
} }
@ -460,7 +463,7 @@ void CardItem::handleClickedToPlay(bool shiftHeld)
{ {
if (isUnwritableRevealZone(state->getZone())) { if (isUnwritableRevealZone(state->getZone())) {
if (SettingsCache::instance().getClickPlaysAllSelected()) { if (SettingsCache::instance().getClickPlaysAllSelected()) {
state->getZone()->getPlayer()->getPlayerActions()->actHide(); emit hideSelected(this);
} else { } else {
state->getZone()->removeCard(this); state->getZone()->removeCard(this);
} }
@ -471,21 +474,15 @@ void CardItem::handleClickedToPlay(bool shiftHeld)
void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void CardItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::RightButton) { if (event->button() == Qt::RightButton && owner != nullptr) {
emit rightClicked(this, event->screenPos());
if (owner != nullptr) { return;
owner->getGame()->setActiveCard(this); }
if (QMenu *cardMenu = owner->getPlayerMenu()->updateCardMenu(this)) { if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) &&
cardMenu->popup(event->screenPos()); (!SettingsCache::instance().getDoubleClickToPlay())) {
return;
}
}
} else if ((event->modifiers() != Qt::AltModifier) && (event->button() == Qt::LeftButton) &&
(!SettingsCache::instance().getDoubleClickToPlay())) {
handleClickedToPlay(event->modifiers().testFlag(Qt::ShiftModifier)); handleClickedToPlay(event->modifiers().testFlag(Qt::ShiftModifier));
} }
if (owner != nullptr) {
if (owner != nullptr) { // cards without owner will be deleted
setCursor(Qt::OpenHandCursor); setCursor(Qt::OpenHandCursor);
} }
AbstractCardItem::mouseReleaseEvent(event); AbstractCardItem::mouseReleaseEvent(event);
@ -531,14 +528,14 @@ bool CardItem::animationEvent()
QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value) QVariant CardItem::itemChange(GraphicsItemChange change, const QVariant &value)
{ {
if ((change == ItemSelectedHasChanged) && owner != nullptr) { if ((change == ItemSelectedHasChanged) && owner != nullptr) {
if (value == true) { bool selected = value.toBool();
owner->getGame()->setActiveCard(this);
owner->getPlayerMenu()->updateCardMenu(this);
} else if (owner->getGameScene()->selectedItems().isEmpty()) {
owner->getGame()->setActiveCard(nullptr); if (selected) {
owner->getPlayerMenu()->updateCardMenu(nullptr); owner->getGame()->setActiveCard(this);
} }
emit selectionChanged(this, selected);
} }
return AbstractCardItem::itemChange(change, value); return AbstractCardItem::itemChange(change, value);
} }

View file

@ -7,9 +7,9 @@
#ifndef CARDITEM_H #ifndef CARDITEM_H
#define CARDITEM_H #define CARDITEM_H
#include "../zones/card_zone_logic.h" #include "../../game/board/card_state.h"
#include "../../game/zones/card_zone_logic.h"
#include "abstract_card_item.h" #include "abstract_card_item.h"
#include "card_state.h"
#include <libcockatrice/network/server/remote/game/server_card.h> #include <libcockatrice/network/server/remote/game/server_card.h>
#include <libcockatrice/utility/trice_limits.h> #include <libcockatrice/utility/trice_limits.h>

View file

@ -1,7 +1,7 @@
#include "counter_general.h" #include "counter_general.h"
#include "../../game_graphics/board/abstract_graphics_item.h"
#include "../../interface/pixel_map_generator.h" #include "../../interface/pixel_map_generator.h"
#include "abstract_graphics_item.h"
#include <QPainter> #include <QPainter>

View file

@ -1,13 +1,17 @@
#include "game_scene.h" #include "game_scene.h"
#include "../client/settings/cache_settings.h" #include "../client/settings/cache_settings.h"
#include "../game_graphics/zones/select_zone.h" #include "../game/abstract_game.h"
#include "../game_graphics/zones/view_zone.h" #include "../game/player/player_actions.h"
#include "../game_graphics/zones/view_zone_widget.h" #include "../game/player/player_logic.h"
#include "../game_graphics/player/player_graphics_item.h"
#include "board/card_item.h" #include "board/card_item.h"
#include "phases_toolbar.h" #include "phases_toolbar.h"
#include "player/menu/player_menu.h"
#include "player/player_graphics_item.h" #include "player/player_graphics_item.h"
#include "player/player_logic.h" #include "zones/select_zone.h"
#include "zones/view_zone.h"
#include "zones/view_zone_widget.h"
#include <QBasicTimer> #include <QBasicTimer>
#include <QDebug> #include <QDebug>
@ -72,6 +76,80 @@ QList<CardItem *> GameScene::selectedCards() const
return selectedCards; return selectedCards;
} }
void GameScene::onCardSelectionChanged(AbstractCardItem *abstractCard, bool selected)
{
CardItem *card = qobject_cast<CardItem *>(abstractCard);
if (!card || !card->getOwner()) {
return;
}
auto *owner = card->getOwner();
if (selected) {
owner->requestCardMenuUpdate(card);
return;
}
if (selectedItems().isEmpty()) {
owner->getGame()->setActiveCard(nullptr);
owner->requestCardMenuUpdate(nullptr);
}
}
void GameScene::onCardRightClicked(AbstractCardItem *abstractCard, QPoint screenPos)
{
auto *card = qobject_cast<CardItem *>(abstractCard);
if (!card) {
return;
}
if (!card->getOwner()) {
return;
}
auto *view = playerViews.value(card->getOwner()->getPlayerInfo()->getId());
if (!view) {
return;
}
card->getOwner()->getGame()->setActiveCard(card);
if (auto *menu = view->getPlayerMenu()->updateCardMenu(card)) {
menu->popup(screenPos);
}
}
void GameScene::playSelected(AbstractCardItem *card)
{
if (!card) {
return;
}
if (!card->getOwner()) {
return;
}
card->getOwner()->getPlayerActions()->actPlay(selectedCards());
}
void GameScene::playSelectedFaceDown(AbstractCardItem *card)
{
if (!card) {
return;
}
if (!card->getOwner()) {
return;
}
card->getOwner()->getPlayerActions()->actPlayFacedown(selectedCards());
}
void GameScene::hideSelected(AbstractCardItem *card)
{
if (!card) {
return;
}
if (!card->getOwner()) {
return;
}
card->getOwner()->getPlayerActions()->actHide(selectedCards());
}
/** /**
* @brief Adds a player to the scene and stores their graphics item. * @brief Adds a player to the scene and stores their graphics item.
* @param player Player to add. * @param player Player to add.
@ -82,9 +160,11 @@ void GameScene::addPlayer(PlayerLogic *player)
{ {
qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::addPlayer name=" << player->getPlayerInfo()->getName(); qCInfo(GameScenePlayerAdditionRemovalLog) << "GameScene::addPlayer name=" << player->getPlayerInfo()->getName();
playerViews.insert(player->getPlayerInfo()->getId(), player->getGraphicsItem()); auto *view = new PlayerGraphicsItem(player);
addItem(player->getGraphicsItem());
connect(player->getGraphicsItem(), &PlayerGraphicsItem::sizeChanged, this, &GameScene::rearrange); playerViews.insert(player->getPlayerInfo()->getId(), view);
addItem(view);
connect(view, &PlayerGraphicsItem::sizeChanged, this, &GameScene::rearrange);
connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) { connect(player, &PlayerLogic::concededChanged, this, [this](int id, bool conceded) {
if (conceded) { if (conceded) {
@ -93,6 +173,8 @@ void GameScene::addPlayer(PlayerLogic *player)
rearrange(); rearrange();
}); });
connect(player, &PlayerLogic::requestZoneViewToggle, this, &GameScene::toggleZoneView);
connect(player, &PlayerLogic::requestRevealedZoneView, this, &GameScene::addRevealedZoneView);
connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::deleteArrow); connect(player, &PlayerLogic::arrowDeleted, this, &GameScene::deleteArrow);
connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::addArrow); connect(player, &PlayerLogic::arrowCreateRequested, this, &GameScene::addArrow);
connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::requestArrowDeletion); connect(player, &PlayerLogic::arrowDeleteRequested, this, &GameScene::requestArrowDeletion);
@ -123,6 +205,7 @@ void GameScene::removePlayer(PlayerLogic *player)
} }
auto *view = playerViews.take(player->getPlayerInfo()->getId()); auto *view = playerViews.take(player->getPlayerInfo()->getId());
removeItem(view); removeItem(view);
view->deleteLater();
rearrange(); rearrange();
} }
@ -204,7 +287,7 @@ QList<PlayerLogic *> GameScene::collectActivePlayers(int &firstPlayerIndex) cons
bool firstPlayerFound = false; bool firstPlayerFound = false;
for (auto *pgItem : playerViews.values()) { for (auto *pgItem : playerViews.values()) {
PlayerLogic *p = pgItem->getPlayer(); PlayerLogic *p = pgItem->getLogic();
if (p && !p->getConceded()) { if (p && !p->getConceded()) {
activePlayers.append(p); activePlayers.append(p);
if (!firstPlayerFound && p->getPlayerInfo()->getLocal()) { if (!firstPlayerFound && p->getPlayerInfo()->getLocal()) {
@ -275,12 +358,12 @@ QSizeF GameScene::computeSceneSizeAndPlayerLayout(const QList<PlayerLogic *> &pl
for (int j = 0; j < rowsInColumn; ++j) { for (int j = 0; j < rowsInColumn; ++j) {
PlayerLogic *player = playersIter.next(); PlayerLogic *player = playersIter.next();
if (col == 0) { if (col == 0) {
playersByColumn[col].prepend(player->getGraphicsItem()); playersByColumn[col].prepend(playerViews.value(player->getPlayerInfo()->getId()));
} else { } else {
playersByColumn[col].append(player->getGraphicsItem()); playersByColumn[col].append(playerViews.value(player->getPlayerInfo()->getId()));
} }
auto *pgItem = player->getGraphicsItem(); auto *pgItem = playerViews.value(player->getPlayerInfo()->getId());
thisColumnHeight += pgItem->boundingRect().height() + playerAreaSpacing; thisColumnHeight += pgItem->boundingRect().height() + playerAreaSpacing;
columnWidth[col] = std::max(columnWidth[col], (int)pgItem->boundingRect().width()); columnWidth[col] = std::max(columnWidth[col], (int)pgItem->boundingRect().width());
} }
@ -375,7 +458,8 @@ void GameScene::addArrow(QSharedPointer<ArrowData> data)
return; return;
} }
auto *startZone = startView->getPlayer()->getZones().value(data->startZone); PlayerLogic *startLogic = startView->getLogic();
auto *startZone = startLogic->getZones().value(data->startZone);
if (!startZone) { if (!startZone) {
return; return;
} }
@ -389,7 +473,8 @@ void GameScene::addArrow(QSharedPointer<ArrowData> data)
if (data->isPlayerTargeted()) { if (data->isPlayerTargeted()) {
targetItem = targetView->getPlayerTarget(); targetItem = targetView->getPlayerTarget();
} else { } else {
if (auto *zone = targetView->getPlayer()->getZones().value(data->targetZone)) { auto *zone = targetView->getLogic()->getZones().value(data->targetZone);
if (zone) {
targetItem = zone->getCard(data->targetCardId); targetItem = zone->getCard(data->targetCardId);
} }
} }

View file

@ -1,10 +1,10 @@
#ifndef GAMESCENE_H #ifndef GAMESCENE_H
#define GAMESCENE_H #define GAMESCENE_H
#include "arrow_registry.h" #include "../game/arrow_registry.h"
#include "board/arrow_data.h" #include "../game/board/arrow_data.h"
#include "../game/zones/card_zone_logic.h"
#include "board/arrow_item.h" #include "board/arrow_item.h"
#include "zones/card_zone_logic.h"
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QList> #include <QList>
@ -97,6 +97,16 @@ public:
*/ */
void removePlayer(PlayerLogic *player); void removePlayer(PlayerLogic *player);
QMap<int, PlayerGraphicsItem *> getPlayers() const
{
return playerViews;
}
PlayerGraphicsItem *viewForPlayer(int playerId)
{
return playerViews.value(playerId);
}
/** /**
* @brief Adjusts the global rotation offset for player layout. * @brief Adjusts the global rotation offset for player layout.
* @param rotationAdjustment Number of positions to rotate. * @param rotationAdjustment Number of positions to rotate.
@ -182,6 +192,11 @@ public:
void stopRubberBand(); void stopRubberBand();
public slots: public slots:
void onCardSelectionChanged(AbstractCardItem *card, bool selected);
void onCardRightClicked(AbstractCardItem *card, QPoint screenPos);
void playSelected(AbstractCardItem *card);
void playSelectedFaceDown(AbstractCardItem *card);
void hideSelected(AbstractCardItem *card);
/** @brief Toggles a zone view for a player. */ /** @brief Toggles a zone view for a player. */
void toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed = false); void toggleZoneView(PlayerLogic *player, const QString &zoneName, int numberCards, bool isReversed = false);

View file

@ -1,6 +1,6 @@
#include "hand_counter.h" #include "hand_counter.h"
#include "../game_graphics/zones/card_zone.h" #include "zones/card_zone.h"
#include <QGraphicsSceneMouseEvent> #include <QGraphicsSceneMouseEvent>
#include <QPainter> #include <QPainter>

View file

@ -7,8 +7,8 @@
#ifndef HANDCOUNTER_H #ifndef HANDCOUNTER_H
#define HANDCOUNTER_H #define HANDCOUNTER_H
#include "../game_graphics/board/abstract_graphics_item.h" #include "board/abstract_graphics_item.h"
#include "../game_graphics/board/graphics_item_type.h" #include "board/graphics_item_type.h"
#include <QString> #include <QString>

View file

@ -1,13 +1,13 @@
#include "message_log_widget.h" #include "message_log_widget.h"
#include "../../client/settings/card_counter_settings.h"
#include "../../client/sound_engine.h" #include "../../client/sound_engine.h"
#include "../../game/phase.h"
#include "../../game/player/player_logic.h"
#include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/tabs/tab_game.h"
#include "../board/card_item.h" #include "../board/card_item.h"
#include "../board/translate_counter_name.h" #include "../board/translate_counter_name.h"
#include "../phase.h"
#include "../player/player_logic.h"
#include <../../client/settings/card_counter_settings.h>
#include <libcockatrice/protocol/pb/context_move_card.pb.h> #include <libcockatrice/protocol/pb/context_move_card.pb.h>
#include <libcockatrice/protocol/pb/context_mulligan.pb.h> #include <libcockatrice/protocol/pb/context_mulligan.pb.h>
#include <libcockatrice/utility/zone_names.h> #include <libcockatrice/utility/zone_names.h>

View file

@ -7,8 +7,8 @@
#ifndef MESSAGELOGWIDGET_H #ifndef MESSAGELOGWIDGET_H
#define MESSAGELOGWIDGET_H #define MESSAGELOGWIDGET_H
#include "../../game/zones/card_zone_logic.h"
#include "../../interface/widgets/server/chat_view/chat_view.h" #include "../../interface/widgets/server/chat_view/chat_view.h"
#include "../zones/card_zone_logic.h"
class AbstractGame; class AbstractGame;
class CardItem; class CardItem;

View file

@ -8,7 +8,7 @@
#ifndef PHASESTOOLBAR_H #ifndef PHASESTOOLBAR_H
#define PHASESTOOLBAR_H #define PHASESTOOLBAR_H
#include "../game_graphics/board/abstract_graphics_item.h" #include "board/abstract_graphics_item.h"
#include <QFrame> #include <QFrame>
#include <QGraphicsObject> #include <QGraphicsObject>

View file

@ -3,10 +3,11 @@
#include "../../../client/settings/card_counter_settings.h" #include "../../../client/settings/card_counter_settings.h"
#include "../../../interface/widgets/tabs/tab_game.h" #include "../../../interface/widgets/tabs/tab_game.h"
#include "../../board/card_item.h" #include "../../board/card_item.h"
#include "../../zones/view_zone_logic.h" #include "../../game/player/player_actions.h"
#include "../../game/player/player_logic.h"
#include "../../game/zones/view_zone_logic.h"
#include "../card_menu_action_type.h" #include "../card_menu_action_type.h"
#include "../player_actions.h" #include "../player_graphics_item.h"
#include "../player_logic.h"
#include "move_menu.h" #include "move_menu.h"
#include "pt_menu.h" #include "pt_menu.h"
@ -31,93 +32,92 @@ static QIcon createCircleIcon(const QColor &color)
return QIcon(pixmap); return QIcon(pixmap);
} }
CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsActive) template <typename Slot>
static QAction *makeAction(QObject *parent, Slot &&slot, bool checkable = false, bool checked = false)
{
auto *a = new QAction(parent);
a->setCheckable(checkable);
if (checkable) {
a->setChecked(checked);
}
QObject::connect(a, &QAction::triggered, parent, std::forward<Slot>(slot));
return a;
}
CardMenu::CardMenu(PlayerGraphicsItem *_player, const CardItem *_card, bool _shortcutsActive)
: player(_player), card(_card), shortcutsActive(_shortcutsActive) : player(_player), card(_card), shortcutsActive(_shortcutsActive)
{ {
auto playerActions = player->getPlayerActions(); const QList<PlayerLogic *> &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
const QList<PlayerLogic *> &players = player->getGame()->getPlayerManager()->getPlayers().values();
for (auto playerToAdd : players) { for (auto playerToAdd : players) {
if (playerToAdd == player) { if (playerToAdd == player->getLogic()) {
continue; continue;
} }
playersInfo.append(qMakePair(playerToAdd->getPlayerInfo()->getName(), playerToAdd->getPlayerInfo()->getId())); playersInfo.append(qMakePair(playerToAdd->getPlayerInfo()->getName(), playerToAdd->getPlayerInfo()->getId()));
} }
connect(player->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this, &CardMenu::removePlayer); connect(player->getLogic()->getGame()->getPlayerManager(), &PlayerManager::playerRemoved, this,
&CardMenu::removePlayer);
aTap = new QAction(this); auto *actions = player->getLogic()->getPlayerActions();
aTap->setData(cmTap); auto *gameScene = player->getGameScene();
connect(aTap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction);
aDoesntUntap = new QAction(this); // Single selection resolver used by all lambdas — called at trigger time
aDoesntUntap->setData(cmDoesntUntap); auto sel = [gameScene]() { return gameScene->selectedCards(); };
aDoesntUntap->setCheckable(true);
aDoesntUntap->setChecked(card != nullptr && card->getDoesntUntap()); // Unified dispatcher for card menu actions
connect(aDoesntUntap, &QAction::triggered, playerActions, &PlayerActions::cardMenuAction); auto invoke = [actions, sel](CardMenuActionType type) {
return [actions, sel, type]() { actions->cardMenuAction(sel(), type); };
};
// Actions using invoke (type dispatch, need selection)
aTap = makeAction(this, invoke(cmTap));
aDoesntUntap = makeAction(this, invoke(cmDoesntUntap), /*checkable=*/true, card && card->getDoesntUntap());
aFlip = makeAction(this, invoke(cmFlip));
aPeek = makeAction(this, invoke(cmPeek));
aClone = makeAction(this, invoke(cmClone));
// Actions using selection directly
aUnattach = makeAction(this, [actions, sel]() { actions->actUnattach(sel()); });
aSetAnnotation = makeAction(this, [actions, sel]() { actions->actRequestSetAnnotationDialog(sel()); });
aPlay = makeAction(this, [actions, sel]() { actions->actPlay(sel()); });
aPlayFacedown = makeAction(this, [actions, sel]() { actions->actPlayFacedown(sel()); });
aHide = makeAction(this, [actions, sel]() { actions->actHide(sel()); });
aReduceLifeByPower = makeAction(this, [actions, sel]() { actions->actReduceLifeByPower(sel()); });
// Actions that use activeCard, not selection — direct connection
aAttach = new QAction(this); aAttach = new QAction(this);
connect(aAttach, &QAction::triggered, playerActions, &PlayerActions::actAttach);
aUnattach = new QAction(this);
connect(aUnattach, &QAction::triggered, playerActions, &PlayerActions::actUnattach);
aDrawArrow = new QAction(this); aDrawArrow = new QAction(this);
connect(aDrawArrow, &QAction::triggered, playerActions, &PlayerActions::actDrawArrow);
aSetAnnotation = new QAction(this);
connect(aSetAnnotation, &QAction::triggered, playerActions, &PlayerActions::actSetAnnotation);
aFlip = new QAction(this);
aFlip->setData(cmFlip);
connect(aFlip, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
aPeek = new QAction(this);
aPeek->setData(cmPeek);
connect(aPeek, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
aClone = new QAction(this);
aClone->setData(cmClone);
connect(aClone, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
aSelectAll = new QAction(this); aSelectAll = new QAction(this);
connect(aSelectAll, &QAction::triggered, playerActions, &PlayerActions::actSelectAll);
aSelectRow = new QAction(this); aSelectRow = new QAction(this);
connect(aSelectRow, &QAction::triggered, playerActions, &PlayerActions::actSelectRow);
aSelectColumn = new QAction(this); aSelectColumn = new QAction(this);
connect(aSelectColumn, &QAction::triggered, playerActions, &PlayerActions::actSelectColumn);
aReduceLifeByPower = new QAction(this); connect(aAttach, &QAction::triggered, actions, &PlayerActions::actAttach);
connect(aReduceLifeByPower, &QAction::triggered, playerActions, &PlayerActions::actReduceLifeByPower); connect(aDrawArrow, &QAction::triggered, actions, &PlayerActions::actDrawArrow);
connect(aSelectAll, &QAction::triggered, actions, &PlayerActions::actSelectAll);
aPlay = new QAction(this); connect(aSelectRow, &QAction::triggered, actions, &PlayerActions::actSelectRow);
connect(aPlay, &QAction::triggered, playerActions, &PlayerActions::actPlay); connect(aSelectColumn, &QAction::triggered, actions, &PlayerActions::actSelectColumn);
aHide = new QAction(this);
connect(aHide, &QAction::triggered, playerActions, &PlayerActions::actHide);
aPlayFacedown = new QAction(this);
connect(aPlayFacedown, &QAction::triggered, playerActions, &PlayerActions::actPlayFacedown);
aRevealToAll = new QAction(this); aRevealToAll = new QAction(this);
mCardCounters = new QMenu; mCardCounters = new QMenu;
// Card counters
for (int i = 0; i < 6; ++i) { for (int i = 0; i < 6; ++i) {
QColor color = SettingsCache::instance().cardCounters().color(i); QColor color = SettingsCache::instance().cardCounters().color(i);
QIcon circleIcon = createCircleIcon(color); QIcon circleIcon = createCircleIcon(color);
auto *tempAddCounter = new QAction(this); auto *addAction = makeAction(this, [actions, sel, i]() { actions->actAddCardCounter(sel(), i); });
tempAddCounter->setIconVisibleInMenu(true); addAction->setIcon(circleIcon);
tempAddCounter->setIcon(circleIcon); aAddCounter.append(addAction);
auto *tempRemoveCounter = new QAction(this); auto *removeAction = makeAction(this, [actions, sel, i]() { actions->actRemoveCardCounter(sel(), i); });
tempRemoveCounter->setIconVisibleInMenu(true); removeAction->setIcon(circleIcon);
tempRemoveCounter->setIcon(circleIcon); aRemoveCounter.append(removeAction);
auto *tempSetCounter = new QAction(this); auto *setAction = makeAction(this, [actions, sel, i]() { actions->actRequestSetCardCounterDialog(sel(), i); });
tempSetCounter->setIconVisibleInMenu(true); setAction->setIcon(circleIcon);
tempSetCounter->setIcon(circleIcon); aSetCounter.append(setAction);
aAddCounter.append(tempAddCounter);
aRemoveCounter.append(tempRemoveCounter);
aSetCounter.append(tempSetCounter);
connect(tempAddCounter, &QAction::triggered, playerActions,
[playerActions, i] { playerActions->actAddCardCounter(i); });
connect(tempRemoveCounter, &QAction::triggered, playerActions,
[playerActions, i] { playerActions->actRemoveCardCounter(i); });
connect(tempSetCounter, &QAction::triggered, playerActions,
[playerActions, i] { playerActions->actSetCardCounter(i); });
} }
setShortcutsActive(); setShortcutsActive();
@ -129,7 +129,7 @@ CardMenu::CardMenu(PlayerLogic *_player, const CardItem *_card, bool _shortcutsA
} }
bool revealedCard = false; bool revealedCard = false;
bool writeableCard = player->getPlayerInfo()->getLocalOrJudge(); bool writeableCard = player->getLogic()->getPlayerInfo()->getLocalOrJudge();
if (auto *view = qobject_cast<ZoneViewZoneLogic *>(card->getZone())) { if (auto *view = qobject_cast<ZoneViewZoneLogic *>(card->getZone())) {
if (view->getRevealZone()) { if (view->getRevealZone()) {
if (view->getWriteableRevealZone()) { if (view->getWriteableRevealZone()) {
@ -313,7 +313,9 @@ void CardMenu::createHandOrCustomZoneMenu(bool canModifyCard)
initContextualPlayersMenu(revealMenu, aRevealToAll); initContextualPlayersMenu(revealMenu, aRevealToAll);
connect(revealMenu, &QMenu::triggered, player->getPlayerActions(), &PlayerActions::actReveal); connect(revealMenu, &QMenu::triggered, this, [this](QAction *action) {
player->getLogic()->getPlayerActions()->actReveal(player->getGameScene()->selectedCards(), action);
});
addSeparator(); addSeparator();
addAction(aClone); addAction(aClone);
@ -398,8 +400,7 @@ void CardMenu::addRelatedCardView()
QAction *viewCard = viewRelatedCards->addAction(relatedCardName); QAction *viewCard = viewRelatedCards->addAction(relatedCardName);
Q_UNUSED(viewCard); Q_UNUSED(viewCard);
connect(viewCard, &QAction::triggered, player->getGame(), connect(viewCard, &QAction::triggered, this, [this, cardRef] { emit cardInfoRequested(cardRef); });
[this, cardRef] { player->getGame()->getTab()->viewCardInfo(cardRef); });
} }
} }
@ -461,7 +462,8 @@ void CardMenu::addRelatedCardActions()
auto *createRelated = new QAction(text, this); auto *createRelated = new QAction(text, this);
createRelated->setData(QVariant(index++)); createRelated->setData(QVariant(index++));
connect(createRelated, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreateRelatedCard); connect(createRelated, &QAction::triggered, player->getLogic()->getPlayerActions(),
&PlayerActions::actCreateRelatedCard);
addAction(createRelated); addAction(createRelated);
} }
@ -470,7 +472,7 @@ void CardMenu::addRelatedCardActions()
createRelatedCards->setShortcuts( createRelatedCards->setShortcuts(
SettingsCache::instance().shortcuts().getShortcut("Player/aCreateRelatedTokens")); SettingsCache::instance().shortcuts().getShortcut("Player/aCreateRelatedTokens"));
} }
connect(createRelatedCards, &QAction::triggered, player->getPlayerActions(), connect(createRelatedCards, &QAction::triggered, player->getLogic()->getPlayerActions(),
&PlayerActions::actCreateAllRelatedCards); &PlayerActions::actCreateAllRelatedCards);
addAction(createRelatedCards); addAction(createRelatedCards);
} }

View file

@ -8,15 +8,20 @@
#define COCKATRICE_CARD_MENU_H #define COCKATRICE_CARD_MENU_H
#include <QMenu> #include <QMenu>
#include <libcockatrice/utility/card_ref.h>
class CardItem; class CardItem;
class PlayerGraphicsItem;
class PlayerLogic; class PlayerLogic;
class CardMenu : public QMenu class CardMenu : public QMenu
{ {
Q_OBJECT Q_OBJECT
signals:
void cardInfoRequested(const CardRef &cardRef);
public: public:
explicit CardMenu(PlayerLogic *player, const CardItem *card, bool shortcutsActive); explicit CardMenu(PlayerGraphicsItem *player, const CardItem *card, bool shortcutsActive);
void removePlayer(PlayerLogic *playerToRemove); void removePlayer(PlayerLogic *playerToRemove);
void createTableMenu(bool canModifyCard); void createTableMenu(bool canModifyCard);
void createStackMenu(bool canModifyCard); void createStackMenu(bool canModifyCard);
@ -41,7 +46,7 @@ public:
QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter; QList<QAction *> aAddCounter, aSetCounter, aRemoveCounter;
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
const CardItem *card; const CardItem *card;
QList<QPair<QString, int>> playersInfo; QList<QPair<QString, int>> playersInfo;
bool shortcutsActive; bool shortcutsActive;

View file

@ -1,13 +1,14 @@
#include "custom_zone_menu.h" #include "custom_zone_menu.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
CustomZoneMenu::CustomZoneMenu(PlayerLogic *_player) : player(_player) CustomZoneMenu::CustomZoneMenu(PlayerGraphicsItem *_player) : player(_player)
{ {
menuAction()->setVisible(false); menuAction()->setVisible(false);
connect(player, &PlayerLogic::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu); connect(player->getLogic(), &PlayerLogic::clearCustomZonesMenu, this, &CustomZoneMenu::clearCustomZonesMenu);
connect(player, &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this, connect(player->getLogic(), &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this,
&CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu); &CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu);
retranslateUi(); retranslateUi();
@ -17,7 +18,7 @@ void CustomZoneMenu::retranslateUi()
{ {
setTitle(tr("C&ustom Zones")); setTitle(tr("C&ustom Zones"));
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
for (auto aViewZone : actions()) { for (auto aViewZone : actions()) {
aViewZone->setText(tr("View custom zone '%1'").arg(aViewZone->data().toString())); aViewZone->setText(tr("View custom zone '%1'").arg(aViewZone->data().toString()));
@ -37,5 +38,5 @@ void CustomZoneMenu::addViewCustomZoneActionToCustomZoneMenu(QString zoneName)
QAction *aViewZone = addAction(tr("View custom zone '%1'").arg(zoneName)); QAction *aViewZone = addAction(tr("View custom zone '%1'").arg(zoneName));
aViewZone->setData(zoneName); aViewZone->setData(zoneName);
connect(aViewZone, &QAction::triggered, this, connect(aViewZone, &QAction::triggered, this,
[zoneName, this]() { player->getGameScene()->toggleZoneView(player, zoneName, -1); }); [zoneName, this]() { player->getGameScene()->toggleZoneView(player->getLogic(), zoneName, -1); });
} }

View file

@ -11,12 +11,12 @@
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class CustomZoneMenu : public QMenu, public AbstractPlayerComponent class CustomZoneMenu : public QMenu, public AbstractPlayerComponent
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit CustomZoneMenu(PlayerLogic *player); explicit CustomZoneMenu(PlayerGraphicsItem *player);
void retranslateUi() override; void retranslateUi() override;
void setShortcutsActive() override void setShortcutsActive() override
{ {
@ -26,7 +26,7 @@ public:
} }
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
private slots: private slots:
void clearCustomZonesMenu(); void clearCustomZonesMenu();
void addViewCustomZoneActionToCustomZoneMenu(QString zoneName); void addViewCustomZoneActionToCustomZoneMenu(QString zoneName);

View file

@ -1,21 +1,22 @@
#include "grave_menu.h" #include "grave_menu.h"
#include "../../abstract_game.h" #include "../../game/abstract_game.h"
#include "../player_actions.h" #include "../../game/player/player_actions.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
#include <QAction> #include <QAction>
#include <QMenu> #include <QMenu>
#include <libcockatrice/utility/zone_names.h> #include <libcockatrice/utility/zone_names.h>
GraveyardMenu::GraveyardMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) GraveyardMenu::GraveyardMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
{ {
createMoveActions(); createMoveActions();
createViewActions(); createViewActions();
addAction(aViewGraveyard); addAction(aViewGraveyard);
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
mRevealRandomGraveyardCard = addMenu(QString()); mRevealRandomGraveyardCard = addMenu(QString());
connect(mRevealRandomGraveyardCard, &QMenu::aboutToShow, this, connect(mRevealRandomGraveyardCard, &QMenu::aboutToShow, this,
&GraveyardMenu::populateRevealRandomMenuWithActivePlayers); &GraveyardMenu::populateRevealRandomMenuWithActivePlayers);
@ -36,9 +37,9 @@ GraveyardMenu::GraveyardMenu(PlayerLogic *_player, QWidget *parent) : TearOffMen
void GraveyardMenu::createMoveActions() void GraveyardMenu::createMoveActions()
{ {
auto grave = player->getGraveZone(); auto grave = player->getLogic()->getGraveZone();
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
aMoveGraveToTopLibrary = new QAction(this); aMoveGraveToTopLibrary = new QAction(this);
aMoveGraveToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0); aMoveGraveToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0);
@ -60,7 +61,7 @@ void GraveyardMenu::createMoveActions()
void GraveyardMenu::createViewActions() void GraveyardMenu::createViewActions()
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
aViewGraveyard = new QAction(this); aViewGraveyard = new QAction(this);
connect(aViewGraveyard, &QAction::triggered, playerActions, &PlayerActions::actViewGraveyard); connect(aViewGraveyard, &QAction::triggered, playerActions, &PlayerActions::actViewGraveyard);
@ -76,9 +77,9 @@ void GraveyardMenu::populateRevealRandomMenuWithActivePlayers()
mRevealRandomGraveyardCard->addSeparator(); mRevealRandomGraveyardCard->addSeparator();
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) { for (auto *other : players) {
if (other == player) { if (other == player->getLogic()) {
continue; continue;
} }
QAction *a = mRevealRandomGraveyardCard->addAction(other->getPlayerInfo()->getName()); QAction *a = mRevealRandomGraveyardCard->addAction(other->getPlayerInfo()->getName());
@ -90,7 +91,7 @@ void GraveyardMenu::populateRevealRandomMenuWithActivePlayers()
void GraveyardMenu::onRevealRandomTriggered() void GraveyardMenu::onRevealRandomTriggered()
{ {
if (auto *a = qobject_cast<QAction *>(sender())) { if (auto *a = qobject_cast<QAction *>(sender())) {
player->getPlayerActions()->actRevealRandomGraveyardCard(a->data().toInt()); player->getLogic()->getPlayerActions()->actRevealRandomGraveyardCard(a->data().toInt());
} }
} }
@ -100,7 +101,7 @@ void GraveyardMenu::retranslateUi()
aViewGraveyard->setText(tr("&View graveyard")); aViewGraveyard->setText(tr("&View graveyard"));
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
moveGraveMenu->setTitle(tr("&Move graveyard to...")); moveGraveMenu->setTitle(tr("&Move graveyard to..."));
aMoveGraveToTopLibrary->setText(tr("&Top of library")); aMoveGraveToTopLibrary->setText(tr("&Top of library"));
aMoveGraveToBottomLibrary->setText(tr("&Bottom of library")); aMoveGraveToBottomLibrary->setText(tr("&Bottom of library"));

View file

@ -13,7 +13,7 @@
#include <QAction> #include <QAction>
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class GraveyardMenu : public TearOffMenu, public AbstractPlayerComponent class GraveyardMenu : public TearOffMenu, public AbstractPlayerComponent
{ {
Q_OBJECT Q_OBJECT
@ -21,7 +21,7 @@ signals:
void newPlayerActionCreated(QAction *action); void newPlayerActionCreated(QAction *action);
public: public:
explicit GraveyardMenu(PlayerLogic *player, QWidget *parent = nullptr); explicit GraveyardMenu(PlayerGraphicsItem *player, QWidget *parent = nullptr);
void createMoveActions(); void createMoveActions();
void createViewActions(); void createViewActions();
void populateRevealRandomMenuWithActivePlayers(); void populateRevealRandomMenuWithActivePlayers();
@ -40,7 +40,7 @@ public:
QAction *aMoveGraveToRfg = nullptr; QAction *aMoveGraveToRfg = nullptr;
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
}; };
#endif // COCKATRICE_GRAVE_MENU_H #endif // COCKATRICE_GRAVE_MENU_H

View file

@ -3,18 +3,22 @@
#include "../../../client/settings/cache_settings.h" #include "../../../client/settings/cache_settings.h"
#include "../../../client/settings/shortcuts_settings.h" #include "../../../client/settings/shortcuts_settings.h"
#include "../../../game_graphics/zones/hand_zone.h" #include "../../../game_graphics/zones/hand_zone.h"
#include "../../abstract_game.h" #include "../../game/abstract_game.h"
#include "../player_actions.h" #include "../../game/player/player_actions.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
#include <QAction> #include <QAction>
#include <QMenu> #include <QMenu>
#include <libcockatrice/utility/zone_names.h> #include <libcockatrice/utility/zone_names.h>
HandMenu::HandMenu(PlayerLogic *_player, PlayerActions *actions, QWidget *parent) : TearOffMenu(parent), player(_player) HandMenu::HandMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
{ {
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { auto *actions = player->getLogic()->getPlayerActions();
if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
aViewHand = new QAction(this); aViewHand = new QAction(this);
connect(aViewHand, &QAction::triggered, actions, &PlayerActions::actViewHand); connect(aViewHand, &QAction::triggered, actions, &PlayerActions::actViewHand);
addAction(aViewHand); addAction(aViewHand);
@ -58,7 +62,7 @@ HandMenu::HandMenu(PlayerLogic *_player, PlayerActions *actions, QWidget *parent
addSeparator(); addSeparator();
aMulligan = new QAction(this); aMulligan = new QAction(this);
connect(aMulligan, &QAction::triggered, actions, &PlayerActions::actMulligan); connect(aMulligan, &QAction::triggered, actions, &PlayerActions::actRequestMulliganDialog);
addAction(aMulligan); addAction(aMulligan);
// Mulligan same size // Mulligan same size
@ -75,7 +79,7 @@ HandMenu::HandMenu(PlayerLogic *_player, PlayerActions *actions, QWidget *parent
mMoveHandMenu = addTearOffMenu(QString()); mMoveHandMenu = addTearOffMenu(QString());
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
aMoveHandToTopLibrary = new QAction(this); aMoveHandToTopLibrary = new QAction(this);
aMoveHandToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0); aMoveHandToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0);
aMoveHandToBottomLibrary = new QAction(this); aMoveHandToBottomLibrary = new QAction(this);
@ -85,7 +89,7 @@ HandMenu::HandMenu(PlayerLogic *_player, PlayerActions *actions, QWidget *parent
aMoveHandToRfg = new QAction(this); aMoveHandToRfg = new QAction(this);
aMoveHandToRfg->setData(QList<QVariant>() << ZoneNames::EXILE << 0); aMoveHandToRfg->setData(QList<QVariant>() << ZoneNames::EXILE << 0);
auto hand = player->getHandZone(); auto hand = player->getLogic()->getHandZone();
connect(aMoveHandToTopLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); connect(aMoveHandToTopLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone);
connect(aMoveHandToBottomLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone); connect(aMoveHandToBottomLibrary, &QAction::triggered, hand, &HandZoneLogic::moveAllToZone);
@ -107,7 +111,7 @@ void HandMenu::retranslateUi()
{ {
setTitle(tr("&Hand")); setTitle(tr("&Hand"));
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aViewHand->setText(tr("&View hand")); aViewHand->setText(tr("&View hand"));
mSortHand->setTitle(tr("Sort hand by...")); mSortHand->setTitle(tr("Sort hand by..."));
@ -166,9 +170,9 @@ void HandMenu::populateRevealHandMenuWithActivePlayers()
mRevealHand->addSeparator(); mRevealHand->addSeparator();
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) { for (auto *other : players) {
if (other == player) { if (other == player->getLogic()) {
continue; continue;
} }
QAction *a = mRevealHand->addAction(other->getPlayerInfo()->getName()); QAction *a = mRevealHand->addAction(other->getPlayerInfo()->getName());
@ -185,9 +189,9 @@ void HandMenu::populateRevealRandomHandCardMenuWithActivePlayers()
mRevealRandomHandCard->addSeparator(); mRevealRandomHandCard->addSeparator();
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) { for (auto *other : players) {
if (other == player) { if (other == player->getLogic()) {
continue; continue;
} }
QAction *a = mRevealRandomHandCard->addAction(other->getPlayerInfo()->getName()); QAction *a = mRevealRandomHandCard->addAction(other->getPlayerInfo()->getName());
@ -204,7 +208,7 @@ void HandMenu::onRevealHandTriggered()
} }
const int targetId = action->data().toInt(); const int targetId = action->data().toInt();
player->getPlayerActions()->actRevealHand(targetId); player->getLogic()->getPlayerActions()->actRevealHand(targetId);
} }
void HandMenu::onRevealRandomHandCardTriggered() void HandMenu::onRevealRandomHandCardTriggered()
@ -215,5 +219,5 @@ void HandMenu::onRevealRandomHandCardTriggered()
} }
const int targetId = action->data().toInt(); const int targetId = action->data().toInt();
player->getPlayerActions()->actRevealRandomHandCard(targetId); player->getLogic()->getPlayerActions()->actRevealRandomHandCard(targetId);
} }

View file

@ -13,7 +13,7 @@
#include <QAction> #include <QAction>
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class PlayerActions; class PlayerActions;
class HandMenu : public TearOffMenu, public AbstractPlayerComponent class HandMenu : public TearOffMenu, public AbstractPlayerComponent
@ -21,7 +21,7 @@ class HandMenu : public TearOffMenu, public AbstractPlayerComponent
Q_OBJECT Q_OBJECT
public: public:
HandMenu(PlayerLogic *player, PlayerActions *actions, QWidget *parent = nullptr); HandMenu(PlayerGraphicsItem *player, QWidget *parent = nullptr);
QMenu *revealHandMenu() const QMenu *revealHandMenu() const
{ {
@ -43,7 +43,7 @@ private slots:
void onRevealRandomHandCardTriggered(); void onRevealRandomHandCardTriggered();
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
QAction *aViewHand = nullptr; QAction *aViewHand = nullptr;
QAction *aMulligan = nullptr; QAction *aMulligan = nullptr;

View file

@ -3,14 +3,16 @@
#include "../../../client/settings/cache_settings.h" #include "../../../client/settings/cache_settings.h"
#include "../../../client/settings/shortcuts_settings.h" #include "../../../client/settings/shortcuts_settings.h"
#include "../../../interface/widgets/tabs/tab_game.h" #include "../../../interface/widgets/tabs/tab_game.h"
#include "../../abstract_game.h" #include "../../game/abstract_game.h"
#include "../player_actions.h" #include "../../game/player/player_actions.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
#include <QAction> #include <QAction>
#include <QGraphicsView>
#include <QMenu> #include <QMenu>
LibraryMenu::LibraryMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) LibraryMenu::LibraryMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
{ {
createDrawActions(); createDrawActions();
createShuffleActions(); createShuffleActions();
@ -75,8 +77,8 @@ LibraryMenu::LibraryMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(pa
bottomLibraryMenu->addSeparator(); bottomLibraryMenu->addSeparator();
bottomLibraryMenu->addAction(aShuffleBottomCards); bottomLibraryMenu->addAction(aShuffleBottomCards);
connect(player, &PlayerLogic::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions); connect(player->getLogic(), &PlayerLogic::resetTopCardMenuActions, this, &LibraryMenu::resetTopCardMenuActions);
connect(player, &PlayerLogic::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction); connect(player->getLogic(), &PlayerLogic::deckChanged, this, &LibraryMenu::enableOpenInDeckEditorAction);
retranslateUi(); retranslateUi();
} }
@ -94,41 +96,41 @@ void LibraryMenu::resetTopCardMenuActions()
void LibraryMenu::createDrawActions() void LibraryMenu::createDrawActions()
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
aDrawCard = new QAction(this); aDrawCard = new QAction(this);
connect(aDrawCard, &QAction::triggered, playerActions, &PlayerActions::actDrawCard); connect(aDrawCard, &QAction::triggered, playerActions, &PlayerActions::actDrawCard);
aDrawCards = new QAction(this); aDrawCards = new QAction(this);
connect(aDrawCards, &QAction::triggered, playerActions, &PlayerActions::actDrawCards); connect(aDrawCards, &QAction::triggered, playerActions, &PlayerActions::actRequestDrawCardsDialog);
aUndoDraw = new QAction(this); aUndoDraw = new QAction(this);
connect(aUndoDraw, &QAction::triggered, playerActions, &PlayerActions::actUndoDraw); connect(aUndoDraw, &QAction::triggered, playerActions, &PlayerActions::actUndoDraw);
aDrawBottomCard = new QAction(this); aDrawBottomCard = new QAction(this);
connect(aDrawBottomCard, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCard); connect(aDrawBottomCard, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCard);
aDrawBottomCards = new QAction(this); aDrawBottomCards = new QAction(this);
connect(aDrawBottomCards, &QAction::triggered, playerActions, &PlayerActions::actDrawBottomCards); connect(aDrawBottomCards, &QAction::triggered, playerActions, &PlayerActions::actRequestDrawBottomCardsDialog);
} }
} }
void LibraryMenu::createShuffleActions() void LibraryMenu::createShuffleActions()
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
aShuffle = new QAction(this); aShuffle = new QAction(this);
connect(aShuffle, &QAction::triggered, playerActions, &PlayerActions::actShuffle); connect(aShuffle, &QAction::triggered, playerActions, &PlayerActions::actShuffle);
aShuffleTopCards = new QAction(this); aShuffleTopCards = new QAction(this);
connect(aShuffleTopCards, &QAction::triggered, playerActions, &PlayerActions::actShuffleTop); connect(aShuffleTopCards, &QAction::triggered, playerActions, &PlayerActions::actRequestShuffleTopDialog);
aShuffleBottomCards = new QAction(this); aShuffleBottomCards = new QAction(this);
connect(aShuffleBottomCards, &QAction::triggered, playerActions, &PlayerActions::actShuffleBottom); connect(aShuffleBottomCards, &QAction::triggered, playerActions, &PlayerActions::actRequestShuffleBottomDialog);
} }
} }
void LibraryMenu::createMoveActions() void LibraryMenu::createMoveActions()
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
aMoveTopToPlay = new QAction(this); aMoveTopToPlay = new QAction(this);
connect(aMoveTopToPlay, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToPlay); connect(aMoveTopToPlay, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToPlay);
aMoveTopToPlayFaceDown = new QAction(this); aMoveTopToPlayFaceDown = new QAction(this);
@ -149,7 +151,8 @@ void LibraryMenu::createMoveActions()
connect(aMoveTopCardsToExileFaceDown, &QAction::triggered, playerActions, connect(aMoveTopCardsToExileFaceDown, &QAction::triggered, playerActions,
&PlayerActions::actMoveTopCardsToExileFaceDown); &PlayerActions::actMoveTopCardsToExileFaceDown);
aMoveTopCardsUntil = new QAction(this); aMoveTopCardsUntil = new QAction(this);
connect(aMoveTopCardsUntil, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardsUntil); connect(aMoveTopCardsUntil, &QAction::triggered, playerActions,
&PlayerActions::actRequestMoveTopCardsUntilDialog);
aMoveTopCardToBottom = new QAction(this); aMoveTopCardToBottom = new QAction(this);
connect(aMoveTopCardToBottom, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToBottom); connect(aMoveTopCardToBottom, &QAction::triggered, playerActions, &PlayerActions::actMoveTopCardToBottom);
@ -181,16 +184,16 @@ void LibraryMenu::createMoveActions()
void LibraryMenu::createViewActions() void LibraryMenu::createViewActions()
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
if (player->getPlayerInfo()->local || player->getPlayerInfo()->judge) { if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
aViewLibrary = new QAction(this); aViewLibrary = new QAction(this);
connect(aViewLibrary, &QAction::triggered, playerActions, &PlayerActions::actViewLibrary); connect(aViewLibrary, &QAction::triggered, playerActions, &PlayerActions::actViewLibrary);
aViewTopCards = new QAction(this); aViewTopCards = new QAction(this);
connect(aViewTopCards, &QAction::triggered, playerActions, &PlayerActions::actViewTopCards); connect(aViewTopCards, &QAction::triggered, playerActions, &PlayerActions::actRequestViewTopCardsDialog);
aViewBottomCards = new QAction(this); aViewBottomCards = new QAction(this);
connect(aViewBottomCards, &QAction::triggered, playerActions, &PlayerActions::actViewBottomCards); connect(aViewBottomCards, &QAction::triggered, playerActions, &PlayerActions::actRequestViewBottomCardsDialog);
aAlwaysRevealTopCard = new QAction(this); aAlwaysRevealTopCard = new QAction(this);
aAlwaysRevealTopCard->setCheckable(true); aAlwaysRevealTopCard->setCheckable(true);
connect(aAlwaysRevealTopCard, &QAction::triggered, playerActions, &PlayerActions::actAlwaysRevealTopCard); connect(aAlwaysRevealTopCard, &QAction::triggered, playerActions, &PlayerActions::actAlwaysRevealTopCard);
@ -207,7 +210,7 @@ void LibraryMenu::retranslateUi()
{ {
setTitle(tr("&Library")); setTitle(tr("&Library"));
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aViewLibrary->setText(tr("&View library")); aViewLibrary->setText(tr("&View library"));
aViewTopCards->setText(tr("View &top cards of library...")); aViewTopCards->setText(tr("View &top cards of library..."));
aViewBottomCards->setText(tr("View bottom cards of library...")); aViewBottomCards->setText(tr("View bottom cards of library..."));
@ -263,9 +266,9 @@ void LibraryMenu::populateRevealLibraryMenuWithActivePlayers()
mRevealLibrary->addSeparator(); mRevealLibrary->addSeparator();
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) { for (auto *other : players) {
if (other == player) { if (other == player->getLogic()) {
continue; continue;
} }
QAction *a = mRevealLibrary->addAction(other->getPlayerInfo()->getName()); QAction *a = mRevealLibrary->addAction(other->getPlayerInfo()->getName());
@ -278,9 +281,9 @@ void LibraryMenu::populateLendLibraryMenuWithActivePlayers()
{ {
mLendLibrary->clear(); mLendLibrary->clear();
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) { for (auto *other : players) {
if (other == player) { if (other == player->getLogic()) {
continue; continue;
} }
QAction *a = mLendLibrary->addAction(other->getPlayerInfo()->getName()); QAction *a = mLendLibrary->addAction(other->getPlayerInfo()->getName());
@ -299,9 +302,9 @@ void LibraryMenu::populateRevealTopCardMenuWithActivePlayers()
mRevealTopCard->addSeparator(); mRevealTopCard->addSeparator();
const auto &players = player->getGame()->getPlayerManager()->getPlayers().values(); const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) { for (auto *other : players) {
if (other == player) { if (other == player->getLogic()) {
continue; continue;
} }
QAction *a = mRevealTopCard->addAction(other->getPlayerInfo()->getName()); QAction *a = mRevealTopCard->addAction(other->getPlayerInfo()->getName());
@ -313,27 +316,33 @@ void LibraryMenu::populateRevealTopCardMenuWithActivePlayers()
void LibraryMenu::onRevealLibraryTriggered() void LibraryMenu::onRevealLibraryTriggered()
{ {
if (auto *a = qobject_cast<QAction *>(sender())) { if (auto *a = qobject_cast<QAction *>(sender())) {
player->getPlayerActions()->actRevealLibrary(a->data().toInt()); player->getLogic()->getPlayerActions()->actRevealLibrary(a->data().toInt());
} }
} }
void LibraryMenu::onLendLibraryTriggered() void LibraryMenu::onLendLibraryTriggered()
{ {
if (auto *a = qobject_cast<QAction *>(sender())) { if (auto *a = qobject_cast<QAction *>(sender())) {
player->getPlayerActions()->actLendLibrary(a->data().toInt()); player->getLogic()->getPlayerActions()->actLendLibrary(a->data().toInt());
} }
} }
void LibraryMenu::onRevealTopCardTriggered() void LibraryMenu::onRevealTopCardTriggered()
{ {
QWidget *parent = nullptr;
if (auto *view = player->scene() ? player->scene()->views().value(0) : nullptr) {
parent = view->window();
}
if (auto *a = qobject_cast<QAction *>(sender())) { if (auto *a = qobject_cast<QAction *>(sender())) {
int deckSize = player->getDeckZone()->getCards().size();
bool ok; int deckSize = player->getLogic()->getDeckZone()->getCards().size();
int number = QInputDialog::getInt(player->getGame()->getTab(), tr("Reveal top cards of library"), bool ok = true;
int number = QInputDialog::getInt(parent, tr("Reveal top cards of library"),
tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberTopCards, 1, tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberTopCards, 1,
deckSize, 1, &ok); deckSize, 1, &ok);
if (ok) { if (ok) {
player->getPlayerActions()->actRevealTopCards(a->data().toInt(), number); player->getLogic()->getPlayerActions()->actRevealTopCards(a->data().toInt(), number);
defaultNumberTopCards = number; defaultNumberTopCards = number;
} }
} }

View file

@ -13,6 +13,7 @@
#include <QAction> #include <QAction>
#include <QMenu> #include <QMenu>
class PlayerGraphicsItem;
class PlayerLogic; class PlayerLogic;
class PlayerActions; class PlayerActions;
@ -24,7 +25,7 @@ public slots:
void resetTopCardMenuActions(); void resetTopCardMenuActions();
public: public:
LibraryMenu(PlayerLogic *player, QWidget *parent = nullptr); LibraryMenu(PlayerGraphicsItem *player, QWidget *parent = nullptr);
void createDrawActions(); void createDrawActions();
void createShuffleActions(); void createShuffleActions();
void createMoveActions(); void createMoveActions();
@ -111,7 +112,7 @@ public:
int defaultNumberTopCards = 1; int defaultNumberTopCards = 1;
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
}; };
#endif // COCKATRICE_LIBRARY_MENU_H #endif // COCKATRICE_LIBRARY_MENU_H

View file

@ -1,10 +1,11 @@
#include "move_menu.h" #include "move_menu.h"
#include "../../game/player/player_actions.h"
#include "../../game/player/player_logic.h"
#include "../card_menu_action_type.h" #include "../card_menu_action_type.h"
#include "../player_actions.h" #include "../player_graphics_item.h"
#include "../player_logic.h"
MoveMenu::MoveMenu(PlayerLogic *player) : QMenu(tr("Move to")) MoveMenu::MoveMenu(PlayerGraphicsItem *player) : QMenu(tr("Move to"))
{ {
aMoveToTopLibrary = new QAction(this); aMoveToTopLibrary = new QAction(this);
aMoveToTopLibrary->setData(cmMoveToTopLibrary); aMoveToTopLibrary->setData(cmMoveToTopLibrary);
@ -20,14 +21,22 @@ MoveMenu::MoveMenu(PlayerLogic *player) : QMenu(tr("Move to"))
aMoveToExile = new QAction(this); aMoveToExile = new QAction(this);
aMoveToExile->setData(cmMoveToExile); aMoveToExile->setData(cmMoveToExile);
connect(aMoveToTopLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); auto *actions = player->getLogic()->getPlayerActions();
connect(aMoveToBottomLibrary, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
connect(aMoveToXfromTopOfLibrary, &QAction::triggered, player->getPlayerActions(), auto invoke = [player](CardMenuActionType type) {
&PlayerActions::actMoveCardXCardsFromTop); return [type, player]() {
connect(aMoveToTable, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); player->getLogic()->getPlayerActions()->cardMenuAction(player->getGameScene()->selectedCards(), type);
connect(aMoveToHand, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); };
connect(aMoveToGraveyard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction); };
connect(aMoveToExile, &QAction::triggered, player->getPlayerActions(), &PlayerActions::cardMenuAction);
connect(aMoveToTopLibrary, &QAction::triggered, actions, invoke(cmMoveToTopLibrary));
connect(aMoveToBottomLibrary, &QAction::triggered, actions, invoke(cmMoveToBottomLibrary));
connect(aMoveToXfromTopOfLibrary, &QAction::triggered, actions,
&PlayerActions::actRequestMoveCardXCardsFromTopDialog);
connect(aMoveToTable, &QAction::triggered, actions, invoke(cmMoveToTable));
connect(aMoveToHand, &QAction::triggered, actions, invoke(cmMoveToHand));
connect(aMoveToGraveyard, &QAction::triggered, actions, invoke(cmMoveToGraveyard));
connect(aMoveToExile, &QAction::triggered, actions, invoke(cmMoveToExile));
addAction(aMoveToTopLibrary); addAction(aMoveToTopLibrary);
addAction(aMoveToXfromTopOfLibrary); addAction(aMoveToXfromTopOfLibrary);

View file

@ -8,13 +8,13 @@
#define COCKATRICE_MOVE_MENU_H #define COCKATRICE_MOVE_MENU_H
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class MoveMenu : public QMenu class MoveMenu : public QMenu
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MoveMenu(PlayerLogic *player); explicit MoveMenu(PlayerGraphicsItem *player);
void setShortcutsActive(); void setShortcutsActive();
void retranslateUi(); void retranslateUi();

View file

@ -5,17 +5,21 @@
#include "../../../game_graphics/zones/table_zone.h" #include "../../../game_graphics/zones/table_zone.h"
#include "../../../interface/widgets/tabs/tab_game.h" #include "../../../interface/widgets/tabs/tab_game.h"
#include "../../board/card_item.h" #include "../../board/card_item.h"
#include "../player_graphics_item.h"
#include "card_menu.h" #include "card_menu.h"
#include "hand_menu.h" #include "hand_menu.h"
#include <libcockatrice/protocol/pb/command_reveal_cards.pb.h> #include <libcockatrice/protocol/pb/command_reveal_cards.pb.h>
PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player) PlayerMenu::PlayerMenu(PlayerGraphicsItem *_player) : QObject(_player), player(_player)
{ {
connect(player->getLogic(), &PlayerLogic::requestCardMenuUpdate, this, &PlayerMenu::updateCardMenu);
connect(this, &PlayerMenu::cardInfoRequested, player, &PlayerGraphicsItem::cardInfoRequested);
playerMenu = new TearOffMenu(); playerMenu = new TearOffMenu();
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
handMenu = addManagedMenu<HandMenu>(player, player->getPlayerActions(), playerMenu); handMenu = addManagedMenu<HandMenu>(player, playerMenu);
libraryMenu = addManagedMenu<LibraryMenu>(player, playerMenu); libraryMenu = addManagedMenu<LibraryMenu>(player, playerMenu);
} else { } else {
handMenu = nullptr; handMenu = nullptr;
@ -25,7 +29,7 @@ PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player)
graveMenu = addManagedMenu<GraveyardMenu>(player, playerMenu); graveMenu = addManagedMenu<GraveyardMenu>(player, playerMenu);
rfgMenu = addManagedMenu<RfgMenu>(player, playerMenu); rfgMenu = addManagedMenu<RfgMenu>(player, playerMenu);
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
sideboardMenu = addManagedMenu<SideboardMenu>(player, playerMenu); sideboardMenu = addManagedMenu<SideboardMenu>(player, playerMenu);
customZonesMenu = addManagedMenu<CustomZoneMenu>(player); customZonesMenu = addManagedMenu<CustomZoneMenu>(player);
playerMenu->addSeparator(); playerMenu->addSeparator();
@ -40,7 +44,7 @@ PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player)
utilityMenu = nullptr; utilityMenu = nullptr;
} }
if (player->getPlayerInfo()->getLocal()) { if (player->getLogic()->getPlayerInfo()->getLocal()) {
sayMenu = addManagedMenu<SayMenu>(player); sayMenu = addManagedMenu<SayMenu>(player);
} else { } else {
sayMenu = nullptr; sayMenu = nullptr;
@ -55,13 +59,13 @@ PlayerMenu::PlayerMenu(PlayerLogic *_player) : QObject(_player), player(_player)
void PlayerMenu::setMenusForGraphicItems() void PlayerMenu::setMenusForGraphicItems()
{ {
player->getGraphicsItem()->getTableZoneGraphicsItem()->setMenu(playerMenu); player->getTableZoneGraphicsItem()->setMenu(playerMenu);
player->getGraphicsItem()->getGraveyardZoneGraphicsItem()->setMenu(graveMenu, graveMenu->aViewGraveyard); player->getGraveyardZoneGraphicsItem()->setMenu(graveMenu, graveMenu->aViewGraveyard);
player->getGraphicsItem()->getRfgZoneGraphicsItem()->setMenu(rfgMenu, rfgMenu->aViewRfg); player->getRfgZoneGraphicsItem()->setMenu(rfgMenu, rfgMenu->aViewRfg);
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
player->getGraphicsItem()->getHandZoneGraphicsItem()->setMenu(handMenu); player->getHandZoneGraphicsItem()->setMenu(handMenu);
player->getGraphicsItem()->getDeckZoneGraphicsItem()->setMenu(libraryMenu, libraryMenu->aDrawCard); player->getDeckZoneGraphicsItem()->setMenu(libraryMenu, libraryMenu->aDrawCard);
player->getGraphicsItem()->getSideboardZoneGraphicsItem()->setMenu(sideboardMenu); player->getSideboardZoneGraphicsItem()->setMenu(sideboardMenu);
} }
} }
@ -74,12 +78,14 @@ QMenu *PlayerMenu::updateCardMenu(const CardItem *card)
// If is spectator (as spectators don't need card menus), return // If is spectator (as spectators don't need card menus), return
// only update the menu if the card is actually selected // only update the menu if the card is actually selected
if ((player->getGame()->getPlayerManager()->isSpectator() && !player->getGame()->getPlayerManager()->isJudge()) || if ((player->getLogic()->getGame()->getPlayerManager()->isSpectator() &&
player->getGame()->getActiveCard() != card) { !player->getLogic()->getGame()->getPlayerManager()->isJudge()) ||
player->getLogic()->getGame()->getActiveCard() != card) {
return nullptr; return nullptr;
} }
QMenu *menu = new CardMenu(player, card, shortcutsActive); CardMenu *menu = new CardMenu(player, card, shortcutsActive);
connect(menu, &CardMenu::cardInfoRequested, this, &PlayerMenu::cardInfoRequested);
emit cardMenuUpdated(menu); emit cardMenuUpdated(menu);
return menu; return menu;
@ -87,7 +93,7 @@ QMenu *PlayerMenu::updateCardMenu(const CardItem *card)
void PlayerMenu::retranslateUi() void PlayerMenu::retranslateUi()
{ {
playerMenu->setTitle(tr("Player \"%1\"").arg(player->getPlayerInfo()->getName())); playerMenu->setTitle(tr("Player \"%1\"").arg(player->getLogic()->getPlayerInfo()->getName()));
for (auto *component : managedComponents) { for (auto *component : managedComponents) {
component->retranslateUi(); component->retranslateUi();
@ -104,7 +110,8 @@ void PlayerMenu::refreshShortcuts()
{ {
if (shortcutsActive) { if (shortcutsActive) {
// Judges get access to every player's menus but only want shortcuts to be set for their own. // Judges get access to every player's menus but only want shortcuts to be set for their own.
if (player->getPlayerInfo()->getLocalOrJudge() && !player->getPlayerInfo()->getLocal()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge() &&
!player->getLogic()->getPlayerInfo()->getLocal()) {
setShortcutsInactive(); setShortcutsInactive();
} else { } else {
setShortcutsActive(); setShortcutsActive();

View file

@ -8,7 +8,6 @@
#define COCKATRICE_PLAYER_MENU_H #define COCKATRICE_PLAYER_MENU_H
#include "../../../interface/widgets/menus/tearoff_menu.h" #include "../../../interface/widgets/menus/tearoff_menu.h"
#include "../player_logic.h"
#include "custom_zone_menu.h" #include "custom_zone_menu.h"
#include "grave_menu.h" #include "grave_menu.h"
#include "hand_menu.h" #include "hand_menu.h"
@ -23,29 +22,31 @@
#include <QObject> #include <QObject>
class CardItem; class CardItem;
class CardMenu;
class PlayerGraphicsItem;
class PlayerMenu : public QObject class PlayerMenu : public QObject
{ {
Q_OBJECT Q_OBJECT
signals: signals:
void cardMenuUpdated(QMenu *cardMenu); void cardMenuUpdated(CardMenu *cardMenu);
void cardInfoRequested(const CardRef &cardRef);
void shortcutsActivated(); void shortcutsActivated();
void shortcutsDeactivated(); void shortcutsDeactivated();
void retranslateRequested(); void retranslateRequested();
public slots: public slots:
void setMenusForGraphicItems(); void setMenusForGraphicItems();
QMenu *updateCardMenu(const CardItem *card);
private slots: private slots:
void refreshShortcuts(); void refreshShortcuts();
public: public:
explicit PlayerMenu(PlayerLogic *player); explicit PlayerMenu(PlayerGraphicsItem *player);
/** @brief Retranslate all user-visible strings. Called on language change. */ /** @brief Retranslate all user-visible strings. Called on language change. */
void retranslateUi(); void retranslateUi();
QMenu *updateCardMenu(const CardItem *card);
[[nodiscard]] QMenu *getPlayerMenu() const [[nodiscard]] QMenu *getPlayerMenu() const
{ {
return playerMenu; return playerMenu;
@ -77,7 +78,7 @@ public:
void setShortcutsInactive(); void setShortcutsInactive();
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
TearOffMenu *playerMenu; TearOffMenu *playerMenu;
QMenu *countersMenu; QMenu *countersMenu;
HandMenu *handMenu; HandMenu *handMenu;

View file

@ -1,32 +1,43 @@
#include "pt_menu.h" #include "pt_menu.h"
#include "../player_actions.h" #include "../../game/player/player_actions.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
PtMenu::PtMenu(PlayerLogic *player) : QMenu(tr("Power / toughness")) PtMenu::PtMenu(PlayerGraphicsItem *player) : QMenu(tr("Power / toughness"))
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
aIncP = new QAction(this); aIncP = new QAction(this);
connect(aIncP, &QAction::triggered, playerActions, &PlayerActions::actIncP); connect(aIncP, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actIncP(player->getGameScene()->selectedCards()); });
aDecP = new QAction(this); aDecP = new QAction(this);
connect(aDecP, &QAction::triggered, playerActions, &PlayerActions::actDecP); connect(aDecP, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actDecP(player->getGameScene()->selectedCards()); });
aIncT = new QAction(this); aIncT = new QAction(this);
connect(aIncT, &QAction::triggered, playerActions, &PlayerActions::actIncT); connect(aIncT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actIncT(player->getGameScene()->selectedCards()); });
aDecT = new QAction(this); aDecT = new QAction(this);
connect(aDecT, &QAction::triggered, playerActions, &PlayerActions::actDecT); connect(aDecT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actDecT(player->getGameScene()->selectedCards()); });
aIncPT = new QAction(this); aIncPT = new QAction(this);
connect(aIncPT, &QAction::triggered, playerActions, [playerActions] { playerActions->actIncPT(); }); connect(aIncPT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actIncPT(player->getGameScene()->selectedCards()); });
aDecPT = new QAction(this); aDecPT = new QAction(this);
connect(aDecPT, &QAction::triggered, playerActions, &PlayerActions::actDecPT); connect(aDecPT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actDecPT(player->getGameScene()->selectedCards()); });
aFlowP = new QAction(this); aFlowP = new QAction(this);
connect(aFlowP, &QAction::triggered, playerActions, &PlayerActions::actFlowP); connect(aFlowP, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actFlowP(player->getGameScene()->selectedCards()); });
aFlowT = new QAction(this); aFlowT = new QAction(this);
connect(aFlowT, &QAction::triggered, playerActions, &PlayerActions::actFlowT); connect(aFlowT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actFlowT(player->getGameScene()->selectedCards()); });
aSetPT = new QAction(this); aSetPT = new QAction(this);
connect(aSetPT, &QAction::triggered, playerActions, &PlayerActions::actSetPT); connect(aSetPT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actRequestSetPTDialog(player->getGameScene()->selectedCards()); });
aResetPT = new QAction(this); aResetPT = new QAction(this);
connect(aResetPT, &QAction::triggered, playerActions, &PlayerActions::actResetPT); connect(aResetPT, &QAction::triggered, playerActions,
[player, playerActions] { playerActions->actResetPT(player->getGameScene()->selectedCards()); });
addAction(aIncP); addAction(aIncP);
addAction(aDecP); addAction(aDecP);

View file

@ -8,14 +8,14 @@
#define COCKATRICE_PT_MENU_H #define COCKATRICE_PT_MENU_H
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class PtMenu : public QMenu class PtMenu : public QMenu
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PtMenu(PlayerLogic *player); explicit PtMenu(PlayerGraphicsItem *player);
void retranslateUi(); void retranslateUi();
void setShortcutsActive(); void setShortcutsActive();

View file

@ -1,18 +1,19 @@
#include "rfg_menu.h" #include "rfg_menu.h"
#include "../player_actions.h" #include "../../game/player/player_actions.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
#include <libcockatrice/utility/zone_names.h> #include <libcockatrice/utility/zone_names.h>
RfgMenu::RfgMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), player(_player) RfgMenu::RfgMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
{ {
createMoveActions(); createMoveActions();
createViewActions(); createViewActions();
addAction(aViewRfg); addAction(aViewRfg);
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
addSeparator(); addSeparator();
moveRfgMenu = addTearOffMenu(QString()); moveRfgMenu = addTearOffMenu(QString());
moveRfgMenu->addAction(aMoveRfgToTopLibrary); moveRfgMenu->addAction(aMoveRfgToTopLibrary);
@ -28,8 +29,8 @@ RfgMenu::RfgMenu(PlayerLogic *_player, QWidget *parent) : TearOffMenu(parent), p
void RfgMenu::createMoveActions() void RfgMenu::createMoveActions()
{ {
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
auto rfg = player->getRfgZone(); auto rfg = player->getLogic()->getRfgZone();
aMoveRfgToTopLibrary = new QAction(this); aMoveRfgToTopLibrary = new QAction(this);
aMoveRfgToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0); aMoveRfgToTopLibrary->setData(QList<QVariant>() << ZoneNames::DECK << 0);
@ -49,7 +50,7 @@ void RfgMenu::createMoveActions()
void RfgMenu::createViewActions() void RfgMenu::createViewActions()
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
aViewRfg = new QAction(this); aViewRfg = new QAction(this);
connect(aViewRfg, &QAction::triggered, playerActions, &PlayerActions::actViewRfg); connect(aViewRfg, &QAction::triggered, playerActions, &PlayerActions::actViewRfg);
@ -61,7 +62,7 @@ void RfgMenu::retranslateUi()
aViewRfg->setText(tr("&View exile")); aViewRfg->setText(tr("&View exile"));
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
moveRfgMenu->setTitle(tr("&Move exile to...")); moveRfgMenu->setTitle(tr("&Move exile to..."));
aMoveRfgToTopLibrary->setText(tr("&Top of library")); aMoveRfgToTopLibrary->setText(tr("&Top of library"));
aMoveRfgToBottomLibrary->setText(tr("&Bottom of library")); aMoveRfgToBottomLibrary->setText(tr("&Bottom of library"));

View file

@ -13,12 +13,12 @@
#include <QAction> #include <QAction>
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class RfgMenu : public TearOffMenu, public AbstractPlayerComponent class RfgMenu : public TearOffMenu, public AbstractPlayerComponent
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit RfgMenu(PlayerLogic *player, QWidget *parent = nullptr); explicit RfgMenu(PlayerGraphicsItem *player, QWidget *parent = nullptr);
void createMoveActions(); void createMoveActions();
void createViewActions(); void createViewActions();
void retranslateUi() override; void retranslateUi() override;
@ -38,7 +38,7 @@ public:
QAction *aMoveRfgToGrave = nullptr; QAction *aMoveRfgToGrave = nullptr;
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
}; };
#endif // COCKATRICE_RFG_MENU_H #endif // COCKATRICE_RFG_MENU_H

View file

@ -1,10 +1,11 @@
#include "say_menu.h" #include "say_menu.h"
#include "../../../client/settings/cache_settings.h" #include "../../../client/settings/cache_settings.h"
#include "../player_actions.h" #include "../../game/player/player_actions.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
SayMenu::SayMenu(PlayerLogic *_player) : player(_player) SayMenu::SayMenu(PlayerGraphicsItem *_player) : player(_player)
{ {
connect(&SettingsCache::instance().messages(), &MessageSettings::messageMacrosChanged, this, &SayMenu::initSayMenu); connect(&SettingsCache::instance().messages(), &MessageSettings::messageMacrosChanged, this, &SayMenu::initSayMenu);
initSayMenu(); initSayMenu();
@ -44,7 +45,7 @@ void SayMenu::initSayMenu()
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
auto *newAction = new QAction(SettingsCache::instance().messages().getMessageAt(i), this); auto *newAction = new QAction(SettingsCache::instance().messages().getMessageAt(i), this);
connect(newAction, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actSayMessage); connect(newAction, &QAction::triggered, player->getLogic()->getPlayerActions(), &PlayerActions::actSayMessage);
addAction(newAction); addAction(newAction);
} }

View file

@ -11,12 +11,12 @@
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class SayMenu : public QMenu, public AbstractPlayerComponent class SayMenu : public QMenu, public AbstractPlayerComponent
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SayMenu(PlayerLogic *player); explicit SayMenu(PlayerGraphicsItem *player);
void retranslateUi() override; void retranslateUi() override;
void setShortcutsActive() override; void setShortcutsActive() override;
@ -26,7 +26,7 @@ private slots:
void initSayMenu(); void initSayMenu();
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
bool shortcutsActive = false; bool shortcutsActive = false;
}; };

View file

@ -1,14 +1,16 @@
#include "sideboard_menu.h" #include "sideboard_menu.h"
#include "../player_actions.h" #include "../../game/player/player_actions.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
SideboardMenu::SideboardMenu(PlayerLogic *player, QMenu *playerMenu) : QMenu(playerMenu) SideboardMenu::SideboardMenu(PlayerGraphicsItem *player, QMenu *playerMenu) : QMenu(playerMenu)
{ {
aViewSideboard = new QAction(this); aViewSideboard = new QAction(this);
connect(aViewSideboard, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actViewSideboard); connect(aViewSideboard, &QAction::triggered, player->getLogic()->getPlayerActions(),
&PlayerActions::actViewSideboard);
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
addAction(aViewSideboard); addAction(aViewSideboard);
} }

View file

@ -11,19 +11,19 @@
#include <QMenu> #include <QMenu>
class PlayerLogic; class PlayerGraphicsItem;
class SideboardMenu : public QMenu, public AbstractPlayerComponent class SideboardMenu : public QMenu, public AbstractPlayerComponent
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit SideboardMenu(PlayerLogic *player, QMenu *playerMenu); explicit SideboardMenu(PlayerGraphicsItem *player, QMenu *playerMenu);
void retranslateUi() override; void retranslateUi() override;
void setShortcutsActive() override; void setShortcutsActive() override;
void setShortcutsInactive() override; void setShortcutsInactive() override;
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
QAction *aViewSideboard; QAction *aViewSideboard;
}; };

View file

@ -1,41 +1,49 @@
#include "utility_menu.h" #include "utility_menu.h"
#include "../../../interface/deck_loader/deck_loader.h" #include "../../../interface/deck_loader/deck_loader.h"
#include "../player_actions.h" #include "../../game/player/player_actions.h"
#include "../player_logic.h" #include "../../game/player/player_logic.h"
#include "../player_graphics_item.h"
#include "player_menu.h" #include "player_menu.h"
#include <libcockatrice/deck_list/tree/deck_list_card_node.h> #include <libcockatrice/deck_list/tree/deck_list_card_node.h>
#include <libcockatrice/deck_list/tree/inner_deck_list_node.h> #include <libcockatrice/deck_list/tree/inner_deck_list_node.h>
UtilityMenu::UtilityMenu(PlayerLogic *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player) UtilityMenu::UtilityMenu(PlayerGraphicsItem *_player, QMenu *playerMenu) : QMenu(playerMenu), player(_player)
{ {
PlayerActions *playerActions = player->getPlayerActions(); PlayerActions *playerActions = player->getLogic()->getPlayerActions();
connect(playerActions, &PlayerActions::requestEnableAndSetCreateAnotherTokenAction, this,
&UtilityMenu::setAndEnableCreateAnotherTokenAction);
connect(playerActions, &PlayerActions::requestSetLastToken, this, &UtilityMenu::setLastToken);
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aUntapAll = new QAction(this); aUntapAll = new QAction(this);
connect(aUntapAll, &QAction::triggered, playerActions, &PlayerActions::actUntapAll); connect(aUntapAll, &QAction::triggered, playerActions, &PlayerActions::actUntapAll);
aRollDie = new QAction(this); aRollDie = new QAction(this);
connect(aRollDie, &QAction::triggered, playerActions, &PlayerActions::actRollDie); connect(aRollDie, &QAction::triggered, playerActions, &PlayerActions::actRequestRollDieDialog);
aFlipCoin = new QAction(this); aFlipCoin = new QAction(this);
connect(aFlipCoin, &QAction::triggered, playerActions, &PlayerActions::actFlipCoin); connect(aFlipCoin, &QAction::triggered, playerActions, &PlayerActions::actFlipCoin);
aCreateToken = new QAction(this); aCreateToken = new QAction(this);
connect(aCreateToken, &QAction::triggered, playerActions, &PlayerActions::actCreateToken); connect(aCreateToken, &QAction::triggered, playerActions, [this]() {
player->getLogic()->getPlayerActions()->actRequestCreateTokenDialog(getPredefinedTokens());
});
aCreateAnotherToken = new QAction(this); aCreateAnotherToken = new QAction(this);
connect(aCreateAnotherToken, &QAction::triggered, playerActions, &PlayerActions::actCreateAnotherToken); connect(aCreateAnotherToken, &QAction::triggered, playerActions, &PlayerActions::actCreateAnotherToken);
aCreateAnotherToken->setEnabled(false); aCreateAnotherToken->setEnabled(false);
aIncrementAllCardCounters = new QAction(this); aIncrementAllCardCounters = new QAction(this);
connect(aIncrementAllCardCounters, &QAction::triggered, playerActions, connect(aIncrementAllCardCounters, &QAction::triggered, playerActions, [this]() {
&PlayerActions::actIncrementAllCardCounters); player->getLogic()->getPlayerActions()->actIncrementAllCardCounters(
player->getGameScene()->selectedCards());
});
createPredefinedTokenMenu = new QMenu(QString()); createPredefinedTokenMenu = new QMenu(QString());
createPredefinedTokenMenu->setEnabled(false); createPredefinedTokenMenu->setEnabled(false);
connect(player, &PlayerLogic::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu); connect(player->getLogic(), &PlayerLogic::deckChanged, this, &UtilityMenu::populatePredefinedTokensMenu);
playerMenu->addAction(aIncrementAllCardCounters); playerMenu->addAction(aIncrementAllCardCounters);
playerMenu->addSeparator(); playerMenu->addSeparator();
@ -66,7 +74,7 @@ void UtilityMenu::populatePredefinedTokensMenu()
clear(); clear();
setEnabled(false); setEnabled(false);
predefinedTokens.clear(); predefinedTokens.clear();
const DeckList &deckList = player->getDeck(); const DeckList &deckList = player->getLogic()->getDeck();
if (deckList.isEmpty()) { if (deckList.isEmpty()) {
return; return;
@ -84,14 +92,24 @@ void UtilityMenu::populatePredefinedTokensMenu()
if (i < 10) { if (i < 10) {
a->setShortcut(QKeySequence("Alt+" + QString::number((i + 1) % 10))); a->setShortcut(QKeySequence("Alt+" + QString::number((i + 1) % 10)));
} }
connect(a, &QAction::triggered, player->getPlayerActions(), &PlayerActions::actCreatePredefinedToken); connect(a, &QAction::triggered, player->getLogic()->getPlayerActions(),
&PlayerActions::actCreatePredefinedToken);
} }
} }
} }
void UtilityMenu::setLastToken(CardInfoPtr lastToken)
{
if (!createAnotherTokenActionExists()) {
return;
}
player->getLogic()->getPlayerActions()->setLastTokenInfo(lastToken);
}
void UtilityMenu::retranslateUi() void UtilityMenu::retranslateUi()
{ {
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aIncrementAllCardCounters->setText(tr("Increment all card counters")); aIncrementAllCardCounters->setText(tr("Increment all card counters"));
aUntapAll->setText(tr("&Untap all permanents")); aUntapAll->setText(tr("&Untap all permanents"));
aRollDie->setText(tr("R&oll die...")); aRollDie->setText(tr("R&oll die..."));
@ -106,7 +124,7 @@ void UtilityMenu::setShortcutsActive()
{ {
ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts(); ShortcutsSettings &shortcuts = SettingsCache::instance().shortcuts();
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aIncrementAllCardCounters->setShortcuts(shortcuts.getShortcut("Player/aIncrementAllCardCounters")); aIncrementAllCardCounters->setShortcuts(shortcuts.getShortcut("Player/aIncrementAllCardCounters"));
aUntapAll->setShortcuts(shortcuts.getShortcut("Player/aUntapAll")); aUntapAll->setShortcuts(shortcuts.getShortcut("Player/aUntapAll"));
aRollDie->setShortcuts(shortcuts.getShortcut("Player/aRollDie")); aRollDie->setShortcuts(shortcuts.getShortcut("Player/aRollDie"));
@ -118,7 +136,7 @@ void UtilityMenu::setShortcutsActive()
void UtilityMenu::setShortcutsInactive() void UtilityMenu::setShortcutsInactive()
{ {
if (player->getPlayerInfo()->getLocalOrJudge()) { if (player->getLogic()->getPlayerInfo()->getLocalOrJudge()) {
aUntapAll->setShortcut(QKeySequence()); aUntapAll->setShortcut(QKeySequence());
aRollDie->setShortcut(QKeySequence()); aRollDie->setShortcut(QKeySequence());
aFlipCoin->setShortcut(QKeySequence()); aFlipCoin->setShortcut(QKeySequence());

View file

@ -10,19 +10,21 @@
#include "abstract_player_component.h" #include "abstract_player_component.h"
#include <QMenu> #include <QMenu>
#include <libcockatrice/card/card_info.h>
class PlayerLogic; class PlayerGraphicsItem;
class UtilityMenu : public QMenu, public AbstractPlayerComponent class UtilityMenu : public QMenu, public AbstractPlayerComponent
{ {
Q_OBJECT Q_OBJECT
public slots: public slots:
void populatePredefinedTokensMenu(); void populatePredefinedTokensMenu();
void setLastToken(CardInfoPtr lastToken);
void retranslateUi() override; void retranslateUi() override;
void setShortcutsActive() override; void setShortcutsActive() override;
void setShortcutsInactive() override; void setShortcutsInactive() override;
public: public:
explicit UtilityMenu(PlayerLogic *player, QMenu *playerMenu); explicit UtilityMenu(PlayerGraphicsItem *player, QMenu *playerMenu);
[[nodiscard]] bool createAnotherTokenActionExists() const [[nodiscard]] bool createAnotherTokenActionExists() const
{ {
@ -31,7 +33,7 @@ public:
void setAndEnableCreateAnotherTokenAction(QString text) void setAndEnableCreateAnotherTokenAction(QString text)
{ {
aCreateAnotherToken->setText(text); aCreateAnotherToken->setText(tr("C&reate another %1 token").arg(text));
aCreateAnotherToken->setEnabled(true); aCreateAnotherToken->setEnabled(true);
} }
@ -41,7 +43,7 @@ public:
} }
private: private:
PlayerLogic *player; PlayerGraphicsItem *player;
QStringList predefinedTokens; QStringList predefinedTokens;
QMenu *createPredefinedTokenMenu; QMenu *createPredefinedTokenMenu;

View file

@ -7,7 +7,7 @@
#ifndef COCKATRICE_PLAYER_AREA_H #ifndef COCKATRICE_PLAYER_AREA_H
#define COCKATRICE_PLAYER_AREA_H #define COCKATRICE_PLAYER_AREA_H
#include "../../game_graphics/board/graphics_item_type.h" #include "../board/graphics_item_type.h"
#include "QGraphicsItem" #include "QGraphicsItem"
/** /**

View file

@ -0,0 +1,298 @@
#include "player_dialogs.h"
#include "../../client/settings/card_counter_settings.h"
#include "../../interface/widgets/utility/get_text_with_max.h"
#include "../board/card_item.h"
#include "../dialogs/dlg_roll_dice.h"
#include "../player/player_graphics_item.h"
#include <QInputDialog>
#include <libcockatrice/card/relation/card_relation.h>
PlayerDialogs::PlayerDialogs(PlayerGraphicsItem *_player, PlayerActions *_playerActions)
: QObject(_player), player(_player), playerActions(_playerActions)
{
connect(playerActions, &PlayerActions::requestViewTopCardsDialog, this,
&PlayerDialogs::onViewTopCardsDialogRequested);
connect(playerActions, &PlayerActions::requestViewBottomCardsDialog, this,
&PlayerDialogs::onViewBottomCardsDialogRequested);
connect(playerActions, &PlayerActions::requestShuffleTopDialog, this, &PlayerDialogs::onShuffleTopDialogRequested);
connect(playerActions, &PlayerActions::requestShuffleBottomDialog, this,
&PlayerDialogs::onShuffleBottomDialogRequested);
connect(playerActions, &PlayerActions::requestMulliganDialog, this, &PlayerDialogs::onMulliganDialogRequested);
connect(playerActions, &PlayerActions::requestDrawCardsDialog, this, &PlayerDialogs::onDrawCardsDialogRequested);
connect(playerActions, &PlayerActions::requestMoveTopCardsToDialog, this,
&PlayerDialogs::onMoveTopCardsToDialogRequested);
connect(playerActions, &PlayerActions::requestMoveTopCardsUntilDialog, this,
&PlayerDialogs::onMoveTopCardsUntilDialogRequested);
connect(playerActions, &PlayerActions::requestMoveBottomCardsToDialog, this,
&PlayerDialogs::onMoveBottomCardsToDialogRequested);
connect(playerActions, &PlayerActions::requestDrawBottomCardsDialog, this,
&PlayerDialogs::onDrawBottomCardsDialogRequested);
connect(playerActions, &PlayerActions::requestRollDieDialog, this, &PlayerDialogs::onRollDieDialogRequested);
connect(playerActions, &PlayerActions::requestCreateTokenDialog, this,
&PlayerDialogs::onCreateTokenDialogRequested);
connect(playerActions, &PlayerActions::requestCreateRelatedFromRelationDialog, this,
&PlayerDialogs::onCreateRelatedFromRelationDialogRequested);
connect(playerActions, &PlayerActions::requestMoveCardXCardsFromTopDialog, this,
&PlayerDialogs::onMoveCardXCardsFromTopDialogRequested);
connect(playerActions, &PlayerActions::requestSetPTDialog, this, &PlayerDialogs::onSetPTDialogRequested);
connect(playerActions, &PlayerActions::requestSetAnnotationDialog, this,
&PlayerDialogs::onSetAnnotationDialogRequested);
connect(playerActions, &PlayerActions::requestSetCardCounterDialog, this,
&PlayerDialogs::onSetCardCounterDialogRequested);
}
void PlayerDialogs::onViewTopCardsDialogRequested(int defaultNumberTopCards, int deckSize)
{
bool ok;
int number = QInputDialog::getInt(dialogParent(), tr("View top cards of library"),
tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberTopCards, 1,
deckSize, 1, &ok);
if (ok) {
playerActions->actViewTopCards(number);
}
}
void PlayerDialogs::onViewBottomCardsDialogRequested(int defaultNumberBottomCards, int deckSize)
{
bool ok;
int number = QInputDialog::getInt(dialogParent(), tr("View bottom cards of library"),
tr("Number of cards: (max. %1)").arg(deckSize), defaultNumberBottomCards, 1,
deckSize, 1, &ok);
if (ok) {
playerActions->actViewBottomCards(number);
}
}
void PlayerDialogs::onShuffleTopDialogRequested(int defaultNumberTopCards, int maxCards)
{
bool ok;
int number = QInputDialog::getInt(dialogParent(), tr("Shuffle top cards of library"),
tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberTopCards, 1,
maxCards, 1, &ok);
if (ok) {
playerActions->actShuffleTop(number);
}
}
void PlayerDialogs::onShuffleBottomDialogRequested(int defaultNumberBottomCards, int maxCards)
{
bool ok;
int number = QInputDialog::getInt(dialogParent(), tr("Shuffle bottom cards of library"),
tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1,
maxCards, 1, &ok);
if (ok) {
playerActions->actShuffleBottom(number);
}
}
void PlayerDialogs::onMulliganDialogRequested(int startSize, int handSize, int deckSize)
{
bool ok;
int number = QInputDialog::getInt(dialogParent(), tr("Draw hand"),
tr("Number of cards: (max. %1)").arg(deckSize) + '\n' +
tr("0 and lower are in comparison to current hand size"),
startSize, -handSize, deckSize, 1, &ok);
if (ok) {
playerActions->actMulligan(number);
}
}
void PlayerDialogs::onDrawCardsDialogRequested(int defaultNumberTopCards, int deckSize)
{
bool ok;
int number = QInputDialog::getInt(dialogParent(), tr("Draw cards"), tr("Number of cards: (max. %1)").arg(deckSize),
defaultNumberTopCards, 1, deckSize, 1, &ok);
if (ok) {
playerActions->actDrawCards(number);
}
}
void PlayerDialogs::onMoveTopCardsToDialogRequested(int defaultNumberTopCards,
int maxCards,
const QString &targetZone,
const QString &zoneDisplayName,
bool faceDown)
{
bool ok;
int number = QInputDialog::getInt(dialogParent(), tr("Move top cards to %1").arg(zoneDisplayName),
tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberTopCards, 1,
maxCards, 1, &ok);
if (ok) {
playerActions->moveTopCardsTo(number, targetZone, faceDown);
}
}
void PlayerDialogs::onMoveTopCardsUntilDialogRequested(MoveTopCardsUntilOptions options)
{
DlgMoveTopCardsUntil dlg(dialogParent(), options);
if (!dlg.exec()) {
return;
}
playerActions->moveTopCardsUntil(dlg.getExpr(), dlg.getOptions());
}
void PlayerDialogs::onMoveBottomCardsToDialogRequested(int defaultNumberBottomCards,
int maxCards,
const QString &targetZone,
const QString &zoneDisplayName,
bool faceDown)
{
bool ok;
int number = QInputDialog::getInt(dialogParent(), tr("Move bottom cards to %1").arg(zoneDisplayName),
tr("Number of cards: (max. %1)").arg(maxCards), defaultNumberBottomCards, 1,
maxCards, 1, &ok);
if (ok) {
playerActions->moveBottomCardsTo(number, targetZone, faceDown);
}
}
void PlayerDialogs::onDrawBottomCardsDialogRequested(int defaultNumberBottomCards, int maxCards)
{
bool ok;
int number =
QInputDialog::getInt(dialogParent(), tr("Draw bottom cards"), tr("Number of cards: (max. %1)").arg(maxCards),
defaultNumberBottomCards, 1, maxCards, 1, &ok);
if (ok) {
playerActions->actDrawBottomCards(number);
}
}
void PlayerDialogs::onRollDieDialogRequested()
{
DlgRollDice dlg(dialogParent());
if (!dlg.exec()) {
return;
}
playerActions->actRollDie(dlg.getDieSideCount(), dlg.getDiceToRollCount());
}
void PlayerDialogs::onCreateRelatedFromRelationDialogRequested(const CardItem *sourceCard,
const CardRelation *cardRelation)
{
if (sourceCard == nullptr || cardRelation == nullptr) {
playerActions->setLastRelatedCreationSucceeded(false);
return;
}
int variableCount = cardRelation->getDefaultCount();
if (cardRelation->getIsVariable()) {
bool ok;
emit requestDialogSemaphore(true);
variableCount = QInputDialog::getInt(dialogParent(), tr("Create tokens"), tr("Number:"),
cardRelation->getDefaultCount(), 1, MAX_TOKENS_PER_DIALOG, 1, &ok);
emit requestDialogSemaphore(false);
if (!ok) {
playerActions->setLastRelatedCreationSucceeded(false); // cancelled
return;
}
}
const bool succeeded = playerActions->createRelatedFromRelation(sourceCard, cardRelation, variableCount);
playerActions->setLastRelatedCreationSucceeded(succeeded);
if (succeeded) {
playerActions->onRelatedCardCreated(sourceCard, cardRelation); // only on confirmed success
}
}
void PlayerDialogs::onCreateTokenDialogRequested(const QStringList &predefinedTokens)
{
DlgCreateToken dlg(predefinedTokens, dialogParent());
if (!dlg.exec()) {
return;
}
playerActions->actCreateToken(dlg.getTokenInfo());
}
void PlayerDialogs::onMoveCardXCardsFromTopDialogRequested(int defaultNumberTopCardsToPlaceBelow, int deckSize)
{
bool ok;
int number =
QInputDialog::getInt(dialogParent(), tr("Place card X cards from top of library"),
tr("Which position should this card be placed:") + "\n" + tr("(max. %1)").arg(deckSize),
defaultNumberTopCardsToPlaceBelow, 1, deckSize, 1, &ok);
number -= 1; // indexes start at 0
if (ok) {
playerActions->actMoveCardXCardsFromTop(player->getGameScene()->selectedCards(), number);
}
}
void PlayerDialogs::onSetPTDialogRequested(const QString &oldPT)
{
bool ok;
auto cards = player->getGameScene()->selectedCards();
emit requestDialogSemaphore(true);
QString pt = getTextWithMax(dialogParent(), tr("Change power/toughness"), tr("Change stats to:"), QLineEdit::Normal,
oldPT, &ok);
emit requestDialogSemaphore(false);
if (!ok || player->getLogic()->clearCardsToDelete()) {
return;
}
playerActions->actSetPT(cards, pt);
}
void PlayerDialogs::onSetAnnotationDialogRequested(const QString &oldAnnotation)
{
auto cards = player->getGameScene()->selectedCards();
emit requestDialogSemaphore(true);
AnnotationDialog *dialog = new AnnotationDialog(dialogParent());
dialog->setOptions(QInputDialog::UsePlainTextEditForTextInput);
dialog->setWindowTitle(tr("Set annotation"));
dialog->setLabelText(tr("Please enter the new annotation:"));
dialog->setTextValue(oldAnnotation);
bool ok = dialog->exec();
emit requestDialogSemaphore(false);
if (!ok || player->getLogic()->clearCardsToDelete()) {
return;
}
QString annotation = dialog->textValue().left(MAX_NAME_LENGTH);
playerActions->actSetAnnotation(cards, annotation);
}
void PlayerDialogs::onSetCardCounterDialogRequested(int counterId, const QString &oldValueForDlg)
{
auto cards = player->getGameScene()->selectedCards();
emit requestDialogSemaphore(true);
auto &cardCounterSettings = SettingsCache::instance().cardCounters();
QString counterName = cardCounterSettings.displayName(counterId);
AbstractCounterDialog dialog(counterName, oldValueForDlg, dialogParent());
int ok = dialog.exec();
emit requestDialogSemaphore(false);
if (!ok || player->getLogic()->clearCardsToDelete()) {
return;
}
playerActions->actSetCardCounter(cards, counterId, dialog.textValue());
}

View file

@ -0,0 +1,63 @@
#ifndef COCKATRICE_PLAYER_DIALOGS_H
#define COCKATRICE_PLAYER_DIALOGS_H
#include "../../game/player/player_actions.h"
#include "player_graphics_item.h"
#include <QGraphicsView>
#include <QObject>
class PlayerGraphicsItem;
class PlayerDialogs : public QObject
{
Q_OBJECT
public:
explicit PlayerDialogs(PlayerGraphicsItem *player, PlayerActions *playerActions);
signals:
void requestDialogSemaphore(bool active);
public slots:
void onViewTopCardsDialogRequested(int defaultNumberTopCards, int deckSize);
void onViewBottomCardsDialogRequested(int defaultNumberBottomCards, int deckSize);
void onShuffleTopDialogRequested(int defaultNumberTopCards, int maxCards);
void onShuffleBottomDialogRequested(int defaultNumberBottomCards, int maxCards);
void onMulliganDialogRequested(int startSize, int handSize, int deckSize);
void onDrawCardsDialogRequested(int defaultNumberTopCards, int deckSize);
void onMoveTopCardsToDialogRequested(int defaultNumberTopCards,
int maxCards,
const QString &targetZone,
const QString &zoneDisplayName,
bool faceDown);
void onMoveTopCardsUntilDialogRequested(MoveTopCardsUntilOptions options);
void onMoveBottomCardsToDialogRequested(int defaultNumberBottomCards,
int maxCards,
const QString &targetZone,
const QString &zoneDisplayName,
bool faceDown);
void onDrawBottomCardsDialogRequested(int defaultNumberBottomCards, int maxCards);
void onRollDieDialogRequested();
void onCreateRelatedFromRelationDialogRequested(const CardItem *sourceCard, const CardRelation *cardRelation);
void onCreateTokenDialogRequested(const QStringList &predefinedTokens);
void onMoveCardXCardsFromTopDialogRequested(int defaultNumberTopCardsToPlaceBelow, int deckSize);
void onSetPTDialogRequested(const QString &oldPT);
void onSetAnnotationDialogRequested(const QString &oldAnnotation);
void onSetCardCounterDialogRequested(int counterId, const QString &oldValueForDlg);
private:
PlayerGraphicsItem *player;
PlayerActions *playerActions;
QWidget *dialogParent() const
{
if (auto *s = player->scene()) {
if (auto *v = s->views().value(0)) {
return v->window();
}
}
return nullptr;
}
};
#endif // COCKATRICE_PLAYER_DIALOGS_H

View file

@ -1,13 +1,18 @@
#include "player_graphics_item.h" #include "player_graphics_item.h"
#include "../../game_graphics/zones/hand_zone.h" #include "../../game/player/player_actions.h"
#include "../../game_graphics/zones/pile_zone.h"
#include "../../game_graphics/zones/stack_zone.h"
#include "../../game_graphics/zones/table_zone.h"
#include "../../interface/widgets/tabs/tab_game.h" #include "../../interface/widgets/tabs/tab_game.h"
#include "../board/abstract_card_item.h" #include "../board/abstract_card_item.h"
#include "../board/counter_general.h" #include "../board/counter_general.h"
#include "../hand_counter.h" #include "../hand_counter.h"
#include "../zones/hand_zone.h"
#include "../zones/pile_zone.h"
#include "../zones/stack_zone.h"
#include "../zones/table_zone.h"
#include "menu/player_menu.h"
#include "player_dialogs.h"
#include <QGraphicsView>
PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player) PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
{ {
@ -16,28 +21,35 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
connect(&SettingsCache::instance(), &SettingsCache::handJustificationChanged, this, connect(&SettingsCache::instance(), &SettingsCache::handJustificationChanged, this,
&PlayerGraphicsItem::rearrangeZones); &PlayerGraphicsItem::rearrangeZones);
connect(player, &PlayerLogic::rearrangeCounters, this, &PlayerGraphicsItem::rearrangeCounters); connect(player, &PlayerLogic::rearrangeCounters, this, &PlayerGraphicsItem::rearrangeCounters);
connect(player, &PlayerLogic::activeChanged, this, &PlayerGraphicsItem::onPlayerActiveChanged);
connect(player, &PlayerLogic::concededChanged, this, [this](int, bool c) { setVisible(!c); }); connect(player, &PlayerLogic::concededChanged, this, [this](int, bool c) { setVisible(!c); });
connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); }); connect(player, &PlayerLogic::zoneIdChanged, this, [this](int id) { playerArea->setPlayerZoneId(id); });
connect(player, &PlayerLogic::counterAdded, this, &PlayerGraphicsItem::onCounterAdded); connect(player, &PlayerLogic::counterAdded, this, &PlayerGraphicsItem::onCounterAdded);
connect(player, &PlayerLogic::counterRemoved, this, &PlayerGraphicsItem::onCounterRemoved); connect(player, &PlayerLogic::counterRemoved, this, &PlayerGraphicsItem::onCounterRemoved);
connect(player->getPlayerMenu(), &PlayerMenu::shortcutsActivated, this, [this]() { playerMenu = new PlayerMenu(this);
connect(playerMenu, &PlayerMenu::shortcutsActivated, this, [this]() {
for (auto *ctr : counterWidgets) { for (auto *ctr : counterWidgets) {
ctr->setShortcutsActive(); ctr->setShortcutsActive();
} }
}); });
connect(player->getPlayerMenu(), &PlayerMenu::shortcutsDeactivated, this, [this]() { connect(playerMenu, &PlayerMenu::shortcutsDeactivated, this, [this]() {
for (auto *ctr : counterWidgets) { for (auto *ctr : counterWidgets) {
ctr->setShortcutsInactive(); ctr->setShortcutsInactive();
} }
}); });
connect(player->getPlayerMenu(), &PlayerMenu::retranslateRequested, this, [this]() { connect(playerMenu, &PlayerMenu::retranslateRequested, this, [this]() {
for (auto *ctr : counterWidgets) { for (auto *ctr : counterWidgets) {
ctr->retranslateUi(); ctr->retranslateUi();
} }
}); });
playerDialogs = new PlayerDialogs(this, player->getPlayerActions());
connect(playerDialogs, &PlayerDialogs::requestDialogSemaphore, player, &PlayerLogic::setDialogSemaphore);
playerArea = new PlayerArea(this); playerArea = new PlayerArea(this);
playerTarget = new PlayerTarget(player, playerArea); playerTarget = new PlayerTarget(player, playerArea);
@ -47,6 +59,11 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
initializeZones(); initializeZones();
connect(player, &PlayerLogic::addViewCustomZoneActionToCustomZoneMenu, this,
&PlayerGraphicsItem::onCustomZoneAdded);
playerMenu->setMenusForGraphicItems();
connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect); connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect);
updateBoundingRect(); updateBoundingRect();
@ -57,7 +74,7 @@ PlayerGraphicsItem::PlayerGraphicsItem(PlayerLogic *_player) : player(_player)
void PlayerGraphicsItem::retranslateUi() void PlayerGraphicsItem::retranslateUi()
{ {
player->getPlayerMenu()->retranslateUi(); playerMenu->retranslateUi();
QMapIterator<QString, CardZoneLogic *> zoneIterator(player->getZones()); QMapIterator<QString, CardZoneLogic *> zoneIterator(player->getZones());
while (zoneIterator.hasNext()) { while (zoneIterator.hasNext()) {
@ -93,18 +110,33 @@ void PlayerGraphicsItem::initializeZones()
rfgZoneGraphicsItem = new PileZone(player->getRfgZone(), this); rfgZoneGraphicsItem = new PileZone(player->getRfgZone(), this);
rfgZoneGraphicsItem->setPos(base + QPointF(0, 2 * h + h2 + 10)); rfgZoneGraphicsItem->setPos(base + QPointF(0, 2 * h + h2 + 10));
tableZoneGraphicsItem = new TableZone(player->getTableZone(), this); tableZoneGraphicsItem = new TableZone(player->getTableZone(), mirrored, this);
connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect); connect(tableZoneGraphicsItem, &TableZone::sizeChanged, this, &PlayerGraphicsItem::updateBoundingRect);
connect(this, &PlayerGraphicsItem::mirroredChanged, tableZoneGraphicsItem, &TableZone::setMirrored);
stackZoneGraphicsItem = stackZoneGraphicsItem =
new StackZone(player->getStackZone(), static_cast<int>(tableZoneGraphicsItem->boundingRect().height()), this); new StackZone(player->getStackZone(), static_cast<int>(tableZoneGraphicsItem->boundingRect().height()), this);
handZoneGraphicsItem = handZoneGraphicsItem =
new HandZone(player->getHandZone(), static_cast<int>(tableZoneGraphicsItem->boundingRect().height()), this); new HandZone(player->getHandZone(), static_cast<int>(tableZoneGraphicsItem->boundingRect().height()), this);
connect(player->getPlayerActions(), &PlayerActions::requestSortHand, handZoneGraphicsItem, &HandZone::sortHand);
connect(handZoneGraphicsItem->getLogic(), &HandZoneLogic::cardCountChanged, handCounter, connect(handZoneGraphicsItem->getLogic(), &HandZoneLogic::cardCountChanged, handCounter,
&HandCounter::updateNumber); &HandCounter::updateNumber);
connect(handCounter, &HandCounter::showContextMenu, handZoneGraphicsItem, &HandZone::showContextMenu); connect(handCounter, &HandCounter::showContextMenu, handZoneGraphicsItem, &HandZone::showContextMenu);
zoneGraphicsItems.insert(player->getDeckZone()->getName(), deckZoneGraphicsItem);
zoneGraphicsItems.insert(player->getGraveZone()->getName(), graveyardZoneGraphicsItem);
zoneGraphicsItems.insert(player->getRfgZone()->getName(), rfgZoneGraphicsItem);
zoneGraphicsItems.insert(player->getSideboardZone()->getName(), sideboardGraphicsItem);
zoneGraphicsItems.insert(player->getTableZone()->getName(), tableZoneGraphicsItem);
zoneGraphicsItems.insert(player->getStackZone()->getName(), stackZoneGraphicsItem);
zoneGraphicsItems.insert(player->getHandZone()->getName(), handZoneGraphicsItem);
}
void PlayerGraphicsItem::onCustomZoneAdded(QString customZoneName)
{
zoneGraphicsItems.insert(customZoneName, nullptr); // Custom zone view goes here, if we ever implement it.
} }
QRectF PlayerGraphicsItem::boundingRect() const QRectF PlayerGraphicsItem::boundingRect() const
@ -145,6 +177,7 @@ void PlayerGraphicsItem::setMirrored(bool _mirrored)
{ {
if (mirrored != _mirrored) { if (mirrored != _mirrored) {
mirrored = _mirrored; mirrored = _mirrored;
emit mirroredChanged(mirrored);
rearrangeZones(); rearrangeZones();
} }
} }
@ -159,11 +192,11 @@ void PlayerGraphicsItem::onCounterAdded(CounterState *state)
} }
counterWidgets.insert(state->getId(), widget); counterWidgets.insert(state->getId(), widget);
if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { if (playerMenu->getCountersMenu() && widget->getMenu()) {
player->getPlayerMenu()->getCountersMenu()->addMenu(widget->getMenu()); playerMenu->getCountersMenu()->addMenu(widget->getMenu());
} }
if (player->getPlayerMenu()->getShortcutsActive()) { if (playerMenu->getShortcutsActive()) {
widget->setShortcutsActive(); widget->setShortcutsActive();
} }
@ -176,8 +209,8 @@ void PlayerGraphicsItem::onCounterRemoved(int counterId)
if (!widget) { if (!widget) {
return; return;
} }
if (player->getPlayerMenu()->getCountersMenu() && widget->getMenu()) { if (playerMenu->getCountersMenu() && widget->getMenu()) {
player->getPlayerMenu()->getCountersMenu()->removeAction(widget->getMenu()->menuAction()); playerMenu->getCountersMenu()->removeAction(widget->getMenu()->menuAction());
} }
widget->delCounter(); widget->delCounter();
rearrangeCounters(); rearrangeCounters();

View file

@ -6,14 +6,16 @@
#ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H #ifndef COCKATRICE_PLAYER_GRAPHICS_ITEM_H
#define COCKATRICE_PLAYER_GRAPHICS_ITEM_H #define COCKATRICE_PLAYER_GRAPHICS_ITEM_H
#include "../../game/player/player_logic.h"
#include "../board/abstract_counter.h" #include "../board/abstract_counter.h"
#include "../game_scene.h" #include "../game_scene.h"
#include "player_logic.h"
#include <QGraphicsObject> #include <QGraphicsObject>
class HandZone; class HandZone;
class PileZone; class PileZone;
class PlayerDialogs;
class PlayerMenu;
class PlayerTarget; class PlayerTarget;
class StackZone; class StackZone;
class TableZone; class TableZone;
@ -55,11 +57,16 @@ public:
return static_cast<GameScene *>(scene()); return static_cast<GameScene *>(scene());
} }
PlayerLogic *getPlayer() const PlayerLogic *getLogic() const
{ {
return player; return player;
} }
[[nodiscard]] PlayerMenu *getPlayerMenu() const
{
return playerMenu;
}
PlayerArea *getPlayerArea() const PlayerArea *getPlayerArea() const
{ {
return playerArea; return playerArea;
@ -70,6 +77,11 @@ public:
return playerTarget; return playerTarget;
} }
CardZone *getZoneGraphicsItem(const QString &name) const
{
return zoneGraphicsItems.value(name, nullptr);
}
[[nodiscard]] PileZone *getDeckZoneGraphicsItem() const [[nodiscard]] PileZone *getDeckZoneGraphicsItem() const
{ {
return deckZoneGraphicsItem; return deckZoneGraphicsItem;
@ -103,6 +115,7 @@ public:
public slots: public slots:
void onPlayerActiveChanged(bool _active); void onPlayerActiveChanged(bool _active);
void onCustomZoneAdded(QString customZoneName);
void onCounterAdded(CounterState *state); void onCounterAdded(CounterState *state);
void onCounterRemoved(int counterId); void onCounterRemoved(int counterId);
void rearrangeCounters(); void rearrangeCounters();
@ -111,12 +124,17 @@ public slots:
signals: signals:
void sizeChanged(); void sizeChanged();
void playerCountChanged(); void playerCountChanged();
void mirroredChanged(bool isMirrored);
void cardInfoRequested(const CardRef &cardRef);
private: private:
PlayerLogic *player; PlayerLogic *player;
PlayerMenu *playerMenu;
PlayerDialogs *playerDialogs;
PlayerArea *playerArea; PlayerArea *playerArea;
PlayerTarget *playerTarget; PlayerTarget *playerTarget;
QMap<int, AbstractCounter *> counterWidgets; QMap<int, AbstractCounter *> counterWidgets;
QMap<QString, CardZone *> zoneGraphicsItems;
PileZone *deckZoneGraphicsItem; PileZone *deckZoneGraphicsItem;
PileZone *sideboardGraphicsItem; PileZone *sideboardGraphicsItem;
PileZone *graveyardZoneGraphicsItem; PileZone *graveyardZoneGraphicsItem;

Some files were not shown because too many files have changed in this diff Show more