1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
/*
* Copyright (c) 2020, Till Mayer <till.mayer@web.de>
* Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "CardGame.h"
#include <LibCards/CardPainter.h>
#include <LibConfig/Client.h>
#include <LibGfx/Palette.h>
namespace Cards {
CardGame::CardGame()
{
auto background_color = Gfx::Color::from_string(Config::read_string("Games"sv, "Cards"sv, "BackgroundColor"sv));
set_background_color(background_color.value_or(Color::from_rgb(0x008000)));
}
void CardGame::add_stack(NonnullRefPtr<CardStack> stack)
{
m_stacks.append(move(stack));
}
void CardGame::mark_intersecting_stacks_dirty(Cards::Card const& intersecting_card)
{
for (auto& stack : stacks()) {
if (intersecting_card.rect().intersects(stack.bounding_box()))
update(stack.bounding_box());
}
update(intersecting_card.rect());
}
Gfx::IntRect CardGame::moving_cards_bounds() const
{
if (!is_moving_cards())
return {};
// Note: This assumes that the cards are arranged in a line.
return m_moving_cards.first().rect().united(m_moving_cards.last().rect());
}
void CardGame::pick_up_cards_from_stack(Cards::CardStack& stack, Gfx::IntPoint click_location, CardStack::MovementRule movement_rule)
{
stack.add_all_grabbed_cards(click_location, m_moving_cards, movement_rule);
m_moving_cards_source_stack = stack;
}
RefPtr<CardStack> CardGame::find_stack_to_drop_on(CardStack::MovementRule movement_rule) const
{
auto bounds_to_check = moving_cards_bounds();
RefPtr<CardStack> closest_stack;
float closest_distance = FLT_MAX;
for (auto const& stack : stacks()) {
if (stack == moving_cards_source_stack())
continue;
if (stack.bounding_box().intersects(bounds_to_check)
&& stack.is_allowed_to_push(moving_cards().at(0), moving_cards().size(), movement_rule)) {
auto distance = bounds_to_check.center().distance_from(stack.bounding_box().center());
if (distance < closest_distance) {
closest_stack = stack;
closest_distance = distance;
}
}
}
return closest_stack;
}
void CardGame::drop_cards_on_stack(Cards::CardStack& stack, CardStack::MovementRule movement_rule)
{
VERIFY(stack.is_allowed_to_push(m_moving_cards.at(0), m_moving_cards.size(), movement_rule));
for (auto& to_intersect : moving_cards()) {
mark_intersecting_stacks_dirty(to_intersect);
stack.push(to_intersect);
(void)moving_cards_source_stack()->pop();
}
update(moving_cards_source_stack()->bounding_box());
update(stack.bounding_box());
}
void CardGame::clear_moving_cards()
{
m_moving_cards_source_stack.clear();
m_moving_cards.clear();
}
void CardGame::dump_layout() const
{
dbgln("------------------------------");
for (auto const& stack : stacks())
dbgln("{}", stack);
}
void CardGame::config_string_did_change(DeprecatedString const& domain, DeprecatedString const& group, DeprecatedString const& key, DeprecatedString const& value)
{
if (domain == "Games" && group == "Cards") {
if (key == "BackgroundColor") {
if (auto maybe_color = Gfx::Color::from_string(value); maybe_color.has_value())
set_background_color(maybe_color.value());
return;
}
if (key == "CardBackImage") {
CardPainter::the().set_background_image_path(value);
update();
return;
}
}
}
Gfx::Color CardGame::background_color() const
{
return palette().color(background_role());
}
void CardGame::set_background_color(Gfx::Color color)
{
auto new_palette = palette();
new_palette.set_color(Gfx::ColorRole::Background, color);
set_palette(new_palette);
CardPainter::the().set_background_color(color);
}
}
|