Support slot machine game.
This commit is contained in:
parent
3feea400af
commit
7f956d32a6
|
@ -508,6 +508,8 @@ PRIVATE
|
||||||
history/view/media/history_view_photo.cpp
|
history/view/media/history_view_photo.cpp
|
||||||
history/view/media/history_view_poll.h
|
history/view/media/history_view_poll.h
|
||||||
history/view/media/history_view_poll.cpp
|
history/view/media/history_view_poll.cpp
|
||||||
|
history/view/media/history_view_slot_machine.h
|
||||||
|
history/view/media/history_view_slot_machine.cpp
|
||||||
history/view/media/history_view_sticker.h
|
history/view/media/history_view_sticker.h
|
||||||
history/view/media/history_view_sticker.cpp
|
history/view/media/history_view_sticker.cpp
|
||||||
history/view/media/history_view_theme_document.h
|
history/view/media/history_view_theme_document.h
|
||||||
|
|
|
@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_message.h" // NewMessageFlags.
|
#include "history/history_message.h" // NewMessageFlags.
|
||||||
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
|
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
|
||||||
|
#include "chat_helpers/stickers_dice_pack.h" // DicePacks::kDiceString.
|
||||||
#include "ui/text/text_entity.h" // TextWithEntities.
|
#include "ui/text/text_entity.h" // TextWithEntities.
|
||||||
#include "ui/item_text_options.h" // Ui::ItemTextOptions.
|
#include "ui/item_text_options.h" // Ui::ItemTextOptions.
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
|
@ -221,8 +222,9 @@ bool SendDice(Api::MessageToSend &message) {
|
||||||
auto &account = message.action.history->session().account();
|
auto &account = message.action.history->session().account();
|
||||||
auto &config = account.appConfig();
|
auto &config = account.appConfig();
|
||||||
static const auto hardcoded = std::vector<QString>{
|
static const auto hardcoded = std::vector<QString>{
|
||||||
QString::fromUtf8("\xF0\x9F\x8E\xB2"),
|
Stickers::DicePacks::kDiceString,
|
||||||
QString::fromUtf8("\xF0\x9F\x8E\xAF")
|
Stickers::DicePacks::kDartString,
|
||||||
|
Stickers::DicePacks::kSlotString,
|
||||||
};
|
};
|
||||||
const auto list = config.get<std::vector<QString>>(
|
const auto list = config.get<std::vector<QString>>(
|
||||||
"emojies_send_dice",
|
"emojies_send_dice",
|
||||||
|
|
|
@ -20,6 +20,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Stickers {
|
namespace Stickers {
|
||||||
|
|
||||||
|
const QString DicePacks::kDiceString = QString::fromUtf8("\xF0\x9F\x8E\xB2");
|
||||||
|
const QString DicePacks::kDartString = QString::fromUtf8("\xF0\x9F\x8E\xAF");
|
||||||
|
const QString DicePacks::kSlotString = QString::fromUtf8("\xF0\x9F\x8E\xB0");
|
||||||
|
|
||||||
DicePack::DicePack(not_null<Main::Session*> session, const QString &emoji)
|
DicePack::DicePack(not_null<Main::Session*> session, const QString &emoji)
|
||||||
: _session(session)
|
: _session(session)
|
||||||
, _emoji(emoji) {
|
, _emoji(emoji) {
|
||||||
|
@ -54,13 +58,21 @@ void DicePack::load() {
|
||||||
void DicePack::applySet(const MTPDmessages_stickerSet &data) {
|
void DicePack::applySet(const MTPDmessages_stickerSet &data) {
|
||||||
_map.clear();
|
_map.clear();
|
||||||
auto documents = base::flat_map<DocumentId, not_null<DocumentData*>>();
|
auto documents = base::flat_map<DocumentId, not_null<DocumentData*>>();
|
||||||
|
const auto isSlotMachine = DicePacks::IsSlot(_emoji);
|
||||||
for (const auto &sticker : data.vdocuments().v) {
|
for (const auto &sticker : data.vdocuments().v) {
|
||||||
const auto document = _session->data().processDocument(
|
const auto document = _session->data().processDocument(
|
||||||
sticker);
|
sticker);
|
||||||
if (document->sticker()) {
|
if (document->sticker()) {
|
||||||
|
if (isSlotMachine) {
|
||||||
|
_map.emplace(_map.size(), document);
|
||||||
|
} else {
|
||||||
documents.emplace(document->id, document);
|
documents.emplace(document->id, document);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (isSlotMachine) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (const auto pack : data.vpacks().v) {
|
for (const auto pack : data.vpacks().v) {
|
||||||
pack.match([&](const MTPDstickerPack &data) {
|
pack.match([&](const MTPDstickerPack &data) {
|
||||||
const auto emoji = qs(data.vemoticon());
|
const auto emoji = qs(data.vemoticon());
|
||||||
|
@ -86,11 +98,9 @@ void DicePack::tryGenerateLocalZero() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const auto kDiceString = QString::fromUtf8("\xF0\x9F\x8E\xB2");
|
const auto path = (_emoji == DicePacks::kDiceString)
|
||||||
static const auto kDartString = QString::fromUtf8("\xF0\x9F\x8E\xAF");
|
|
||||||
const auto path = (_emoji == kDiceString)
|
|
||||||
? qsl(":/gui/art/dice_idle.tgs")
|
? qsl(":/gui/art/dice_idle.tgs")
|
||||||
: (_emoji == kDartString)
|
: (_emoji == DicePacks::kDartString)
|
||||||
? qsl(":/gui/art/dart_idle.tgs")
|
? qsl(":/gui/art/dart_idle.tgs")
|
||||||
: QString();
|
: QString();
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty()) {
|
||||||
|
|
|
@ -21,7 +21,7 @@ public:
|
||||||
DicePack(not_null<Main::Session*> session, const QString &emoji);
|
DicePack(not_null<Main::Session*> session, const QString &emoji);
|
||||||
~DicePack();
|
~DicePack();
|
||||||
|
|
||||||
DocumentData *lookup(int value);
|
[[nodiscard]] DocumentData *lookup(int value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load();
|
void load();
|
||||||
|
@ -39,7 +39,15 @@ class DicePacks final {
|
||||||
public:
|
public:
|
||||||
explicit DicePacks(not_null<Main::Session*> session);
|
explicit DicePacks(not_null<Main::Session*> session);
|
||||||
|
|
||||||
DocumentData *lookup(const QString &emoji, int value);
|
static const QString kDiceString;
|
||||||
|
static const QString kDartString;
|
||||||
|
static const QString kSlotString;
|
||||||
|
|
||||||
|
[[nodiscard]] static bool IsSlot(const QString &emoji) {
|
||||||
|
return (emoji == kSlotString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] DocumentData *lookup(const QString &emoji, int value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
|
|
|
@ -23,13 +23,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/media/history_view_web_page.h"
|
#include "history/view/media/history_view_web_page.h"
|
||||||
#include "history/view/media/history_view_poll.h"
|
#include "history/view/media/history_view_poll.h"
|
||||||
#include "history/view/media/history_view_theme_document.h"
|
#include "history/view/media/history_view_theme_document.h"
|
||||||
|
#include "history/view/media/history_view_slot_machine.h"
|
||||||
#include "history/view/media/history_view_dice.h"
|
#include "history/view/media/history_view_dice.h"
|
||||||
#include "ui/image/image.h"
|
#include "ui/image/image.h"
|
||||||
#include "ui/text/format_values.h"
|
#include "ui/text/format_values.h"
|
||||||
#include "ui/text/text_options.h"
|
#include "ui/text/text_options.h"
|
||||||
|
#include "ui/text/text_utilities.h"
|
||||||
|
#include "ui/toast/toast.h"
|
||||||
#include "ui/emoji_config.h"
|
#include "ui/emoji_config.h"
|
||||||
|
#include "api/api_sending.h"
|
||||||
#include "storage/storage_shared_media.h"
|
#include "storage/storage_shared_media.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
|
#include "chat_helpers/stickers_dice_pack.h" // Stickers::DicePacks::IsSlot.
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_photo.h"
|
#include "data/data_photo.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
@ -42,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "storage/file_upload.h"
|
#include "storage/file_upload.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -1339,9 +1345,60 @@ std::unique_ptr<HistoryView::Media> MediaDice::createView(
|
||||||
not_null<HistoryView::Element*> message,
|
not_null<HistoryView::Element*> message,
|
||||||
not_null<HistoryItem*> realParent,
|
not_null<HistoryItem*> realParent,
|
||||||
HistoryView::Element *replacing) {
|
HistoryView::Element *replacing) {
|
||||||
return std::make_unique<HistoryView::UnwrappedMedia>(
|
return ::Stickers::DicePacks::IsSlot(_emoji)
|
||||||
|
? std::make_unique<HistoryView::UnwrappedMedia>(
|
||||||
|
message,
|
||||||
|
std::make_unique<HistoryView::SlotMachine>(message, this))
|
||||||
|
: std::make_unique<HistoryView::UnwrappedMedia>(
|
||||||
message,
|
message,
|
||||||
std::make_unique<HistoryView::Dice>(message, this));
|
std::make_unique<HistoryView::Dice>(message, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr MediaDice::makeHandler() const {
|
||||||
|
return MakeHandler(parent()->history(), _emoji);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr MediaDice::MakeHandler(
|
||||||
|
not_null<History*> history,
|
||||||
|
const QString &emoji) {
|
||||||
|
static auto ShownToast = base::weak_ptr<Ui::Toast::Instance>();
|
||||||
|
static const auto HideExisting = [] {
|
||||||
|
if (const auto toast = ShownToast.get()) {
|
||||||
|
toast->hideAnimated();
|
||||||
|
ShownToast = nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return std::make_shared<LambdaClickHandler>([=] {
|
||||||
|
auto config = Ui::Toast::Config{
|
||||||
|
.text = { tr::lng_about_random(tr::now, lt_emoji, emoji) },
|
||||||
|
.st = &st::historyDiceToast,
|
||||||
|
.durationMs = Ui::Toast::kDefaultDuration * 2,
|
||||||
|
.multiline = true,
|
||||||
|
};
|
||||||
|
if (history->peer->canWrite()) {
|
||||||
|
auto link = Ui::Text::Link(
|
||||||
|
tr::lng_about_random_send(tr::now).toUpper());
|
||||||
|
link.entities.push_back(
|
||||||
|
EntityInText(EntityType::Semibold, 0, link.text.size()));
|
||||||
|
config.text.append(' ').append(std::move(link));
|
||||||
|
config.filter = crl::guard(&history->session(), [=](
|
||||||
|
const ClickHandlerPtr &handler,
|
||||||
|
Qt::MouseButton button) {
|
||||||
|
if (button == Qt::LeftButton && !ShownToast.empty()) {
|
||||||
|
auto message = Api::MessageToSend(history);
|
||||||
|
message.action.clearDraft = false;
|
||||||
|
message.textWithTags.text = emoji;
|
||||||
|
|
||||||
|
Api::SendDice(message);
|
||||||
|
HideExisting();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
HideExisting();
|
||||||
|
ShownToast = Ui::Toast::Show(config);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_location.h"
|
#include "data/data_location.h"
|
||||||
|
|
||||||
class Image;
|
class Image;
|
||||||
|
class History;
|
||||||
class HistoryItem;
|
class HistoryItem;
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
@ -447,6 +448,11 @@ public:
|
||||||
not_null<HistoryItem*> realParent,
|
not_null<HistoryItem*> realParent,
|
||||||
HistoryView::Element *replacing = nullptr) override;
|
HistoryView::Element *replacing = nullptr) override;
|
||||||
|
|
||||||
|
[[nodiscard]] ClickHandlerPtr makeHandler() const;
|
||||||
|
[[nodiscard]] static ClickHandlerPtr MakeHandler(
|
||||||
|
not_null<History*> history,
|
||||||
|
const QString &emoji);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString _emoji;
|
QString _emoji;
|
||||||
int _value = 0;
|
int _value = 0;
|
||||||
|
|
|
@ -9,15 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "chat_helpers/stickers_dice_pack.h"
|
#include "chat_helpers/stickers_dice_pack.h"
|
||||||
#include "api/api_sending.h"
|
|
||||||
#include "api/api_common.h"
|
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "history/history_item_components.h"
|
#include "history/history_item_components.h"
|
||||||
#include "history/view/history_view_element.h"
|
#include "history/view/history_view_element.h"
|
||||||
#include "ui/toast/toast.h"
|
|
||||||
#include "ui/text/text_utilities.h"
|
|
||||||
#include "lang/lang_keys.h"
|
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
|
@ -32,49 +27,6 @@ namespace {
|
||||||
return session.diceStickersPacks().lookup(emoji, value);
|
return session.diceStickersPacks().lookup(emoji, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] ClickHandlerPtr MakeDiceHandler(
|
|
||||||
not_null<History*> history,
|
|
||||||
const QString &emoji) {
|
|
||||||
static auto ShownToast = base::weak_ptr<Ui::Toast::Instance>();
|
|
||||||
static const auto HideExisting = [] {
|
|
||||||
if (const auto toast = ShownToast.get()) {
|
|
||||||
toast->hideAnimated();
|
|
||||||
ShownToast = nullptr;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return std::make_shared<LambdaClickHandler>([=] {
|
|
||||||
auto config = Ui::Toast::Config{
|
|
||||||
.text = { tr::lng_about_random(tr::now, lt_emoji, emoji) },
|
|
||||||
.st = &st::historyDiceToast,
|
|
||||||
.durationMs = Ui::Toast::kDefaultDuration * 2,
|
|
||||||
.multiline = true,
|
|
||||||
};
|
|
||||||
if (history->peer->canWrite()) {
|
|
||||||
auto link = Ui::Text::Link(
|
|
||||||
tr::lng_about_random_send(tr::now).toUpper());
|
|
||||||
link.entities.push_back(
|
|
||||||
EntityInText(EntityType::Semibold, 0, link.text.size()));
|
|
||||||
config.text.append(' ').append(std::move(link));
|
|
||||||
config.filter = crl::guard(&history->session(), [=](
|
|
||||||
const ClickHandlerPtr &handler,
|
|
||||||
Qt::MouseButton button) {
|
|
||||||
if (button == Qt::LeftButton && !ShownToast.empty()) {
|
|
||||||
auto message = Api::MessageToSend(history);
|
|
||||||
message.action.clearDraft = false;
|
|
||||||
message.textWithTags.text = emoji;
|
|
||||||
|
|
||||||
Api::SendDice(message);
|
|
||||||
HideExisting();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
HideExisting();
|
|
||||||
ShownToast = Ui::Toast::Show(config);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Dice::Dice(not_null<Element*> parent, not_null<Data::MediaDice*> dice)
|
Dice::Dice(not_null<Element*> parent, not_null<Data::MediaDice*> dice)
|
||||||
|
@ -82,7 +34,7 @@ Dice::Dice(not_null<Element*> parent, not_null<Data::MediaDice*> dice)
|
||||||
, _dice(dice)
|
, _dice(dice)
|
||||||
, _link(_parent->data()->Has<HistoryMessageForwarded>()
|
, _link(_parent->data()->Has<HistoryMessageForwarded>()
|
||||||
? nullptr
|
? nullptr
|
||||||
: MakeDiceHandler(_parent->history(), dice->emoji())) {
|
: dice->makeHandler()) {
|
||||||
if (const auto document = Lookup(parent, dice->emoji(), 0)) {
|
if (const auto document = Lookup(parent, dice->emoji(), 0)) {
|
||||||
_start.emplace(parent, document);
|
_start.emplace(parent, document);
|
||||||
_start->setDiceIndex(_dice->emoji(), 0);
|
_start->setDiceIndex(_dice->emoji(), 0);
|
||||||
|
|
|
@ -0,0 +1,200 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "history/view/media/history_view_slot_machine.h"
|
||||||
|
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "chat_helpers/stickers_dice_pack.h"
|
||||||
|
#include "history/history.h"
|
||||||
|
#include "history/history_item.h"
|
||||||
|
#include "history/history_item_components.h"
|
||||||
|
#include "history/view/history_view_element.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "styles/style_chat.h"
|
||||||
|
|
||||||
|
namespace HistoryView {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kStartBackIndex = 0;
|
||||||
|
constexpr auto kWinBackIndex = 1;
|
||||||
|
constexpr auto kPullIndex = 2;
|
||||||
|
constexpr auto kShifts = std::array<int, 3>{ 3, 9, 15 };
|
||||||
|
constexpr auto kSevenWinIndex = 0;
|
||||||
|
constexpr auto kSevenIndex = 1;
|
||||||
|
constexpr auto kBarIndex = 2;
|
||||||
|
constexpr auto kBerriesIndex = 3;
|
||||||
|
constexpr auto kLemonIndex = 4;
|
||||||
|
constexpr auto kStartIndex = 5;
|
||||||
|
|
||||||
|
constexpr auto kWinValue = 64;
|
||||||
|
|
||||||
|
const auto &kEmoji = ::Stickers::DicePacks::kSlotString;
|
||||||
|
|
||||||
|
[[nodiscard]] DocumentData *Lookup(
|
||||||
|
not_null<Element*> view,
|
||||||
|
int value) {
|
||||||
|
const auto &session = view->data()->history()->session();
|
||||||
|
return session.diceStickersPacks().lookup(kEmoji, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int ComplexIndex(int partIndex, int inPartIndex) {
|
||||||
|
Expects(partIndex >= 0 && partIndex < 3);
|
||||||
|
|
||||||
|
return kShifts[partIndex] + inPartIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int ComputeComplexIndex(int value, int partIndex) {
|
||||||
|
Expects(value > 0 && value <= 64);
|
||||||
|
|
||||||
|
if (value == kWinValue) {
|
||||||
|
return ComplexIndex(partIndex, kSevenWinIndex);
|
||||||
|
}
|
||||||
|
const auto bits = ((value - 1) >> (partIndex * 2)) & 0x03; // 0..3
|
||||||
|
return ComplexIndex(partIndex, [&] {
|
||||||
|
switch (bits) {
|
||||||
|
case 0: return kBarIndex;
|
||||||
|
case 1: return kBerriesIndex;
|
||||||
|
case 2: return kLemonIndex;
|
||||||
|
case 3: return kSevenIndex;
|
||||||
|
}
|
||||||
|
Unexpected("Bits value in ComputeComplexIndex.");
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
SlotMachine::SlotMachine(
|
||||||
|
not_null<Element*> parent,
|
||||||
|
not_null<Data::MediaDice*> dice)
|
||||||
|
: _parent(parent)
|
||||||
|
, _dice(dice)
|
||||||
|
, _link(_parent->data()->Has<HistoryMessageForwarded>()
|
||||||
|
? nullptr
|
||||||
|
: dice->makeHandler()) {
|
||||||
|
resolveStarts();
|
||||||
|
_showLastFrame = _parent->data()->Has<HistoryMessageForwarded>();
|
||||||
|
if (_showLastFrame) {
|
||||||
|
for (auto &drawingEnd : _drawingEnd) {
|
||||||
|
drawingEnd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SlotMachine::~SlotMachine() = default;
|
||||||
|
|
||||||
|
void SlotMachine::resolve(
|
||||||
|
std::optional<Sticker> &sticker,
|
||||||
|
int singleTimeIndex,
|
||||||
|
int index,
|
||||||
|
bool initSize) const {
|
||||||
|
if (sticker) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto document = Lookup(_parent, index);
|
||||||
|
if (!document) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sticker.emplace(_parent, document);
|
||||||
|
sticker->setDiceIndex(kEmoji, singleTimeIndex);
|
||||||
|
if (initSize) {
|
||||||
|
sticker->initSize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlotMachine::resolveStarts(bool initSize) {
|
||||||
|
resolve(_pull, kPullIndex, kPullIndex, initSize);
|
||||||
|
resolve(_start[0], 0, kStartBackIndex, initSize);
|
||||||
|
for (auto i = 0; i != 3; ++i) {
|
||||||
|
resolve(_start[i + 1], 0, ComplexIndex(i, kStartIndex), initSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlotMachine::resolveEnds(int value) {
|
||||||
|
if (value <= 0 || value > 64) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (value == kWinValue) {
|
||||||
|
resolve(_end[0], kWinBackIndex, kWinBackIndex, true);
|
||||||
|
}
|
||||||
|
for (auto i = 0; i != 3; ++i) {
|
||||||
|
const auto index = ComputeComplexIndex(value, i);
|
||||||
|
resolve(_end[i + 1], index, index, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SlotMachine::isEndResolved() const {
|
||||||
|
for (auto i = 0; i != 3; ++i) {
|
||||||
|
if (!_end[i + 1]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _end[0].has_value() || (_dice->value() != kWinValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize SlotMachine::size() {
|
||||||
|
return _pull
|
||||||
|
? _pull->size()
|
||||||
|
: Sticker::GetAnimatedEmojiSize(&_parent->history()->session());
|
||||||
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr SlotMachine::link() {
|
||||||
|
return _link;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SlotMachine::draw(Painter &p, const QRect &r, bool selected) {
|
||||||
|
resolveStarts(true);
|
||||||
|
resolveEnds(_dice->value());
|
||||||
|
|
||||||
|
//const auto endResolved = isEndResolved();
|
||||||
|
//if (!endResolved) {
|
||||||
|
// for (auto &drawingEnd : _drawingEnd) {
|
||||||
|
// drawingEnd = false;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
auto switchedToEnd = _drawingEnd;
|
||||||
|
const auto pullReady = _pull && _pull->readyToDrawLottie();
|
||||||
|
const auto paintReady = [&] {
|
||||||
|
auto result = pullReady;
|
||||||
|
for (auto i = 1; i != 4; ++i) {
|
||||||
|
if (!_end[i] || !_end[i]->readyToDrawLottie()) {
|
||||||
|
switchedToEnd[i] = false;
|
||||||
|
}
|
||||||
|
if (!switchedToEnd[i]
|
||||||
|
&& (!_start[i] || !_start[i]->readyToDrawLottie())) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!_end[0] || !_end[0]->readyToDrawLottie()) {
|
||||||
|
switchedToEnd[0] = false;
|
||||||
|
}
|
||||||
|
if (ranges::contains(switchedToEnd, false)
|
||||||
|
&& (!_start[0] || !_start[0]->readyToDrawLottie())) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (!paintReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i != 4; ++i) {
|
||||||
|
if (switchedToEnd[i]) {
|
||||||
|
_end[i]->draw(p, r, selected);
|
||||||
|
} else {
|
||||||
|
_start[i]->draw(p, r, selected);
|
||||||
|
if (_end[i]
|
||||||
|
&& _end[i]->readyToDrawLottie()
|
||||||
|
&& _start[i]->atTheEnd()) {
|
||||||
|
_drawingEnd[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_pull->draw(p, r, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace HistoryView
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "history/view/media/history_view_media_unwrapped.h"
|
||||||
|
#include "history/view/media/history_view_sticker.h"
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
class MediaDice;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
|
namespace HistoryView {
|
||||||
|
|
||||||
|
class SlotMachine final : public UnwrappedMedia::Content {
|
||||||
|
public:
|
||||||
|
SlotMachine(not_null<Element*> parent, not_null<Data::MediaDice*> dice);
|
||||||
|
~SlotMachine();
|
||||||
|
|
||||||
|
QSize size() override;
|
||||||
|
void draw(Painter &p, const QRect &r, bool selected) override;
|
||||||
|
|
||||||
|
ClickHandlerPtr link() override;
|
||||||
|
|
||||||
|
bool hasHeavyPart() const override {
|
||||||
|
if (_pull && _pull->hasHeavyPart()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (auto i = 0; i != 4; ++i) {
|
||||||
|
if ((_start[i] && _start[i]->hasHeavyPart())
|
||||||
|
|| (_end[i] && _end[i]->hasHeavyPart())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void unloadHeavyPart() override {
|
||||||
|
if (_pull) {
|
||||||
|
_pull->unloadHeavyPart();
|
||||||
|
}
|
||||||
|
for (auto i = 0; i != 4; ++i) {
|
||||||
|
if (_start[i]) {
|
||||||
|
_start[i]->unloadHeavyPart();
|
||||||
|
}
|
||||||
|
if (_end[i]) {
|
||||||
|
_end[i]->unloadHeavyPart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool hidesForwardedInfo() override {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void resolveStarts(bool initSize = false);
|
||||||
|
void resolveEnds(int value);
|
||||||
|
[[nodiscard]] bool isEndResolved() const;
|
||||||
|
void resolve(
|
||||||
|
std::optional<Sticker> &sticker,
|
||||||
|
int singleTimeIndex,
|
||||||
|
int index,
|
||||||
|
bool initSize) const;
|
||||||
|
|
||||||
|
const not_null<Element*> _parent;
|
||||||
|
const not_null<Data::MediaDice*> _dice;
|
||||||
|
ClickHandlerPtr _link;
|
||||||
|
std::optional<Sticker> _pull;
|
||||||
|
std::array<std::optional<Sticker>, 4> _start;
|
||||||
|
std::array<std::optional<Sticker>, 4> _end;
|
||||||
|
mutable bool _showLastFrame = false;
|
||||||
|
mutable std::array<bool, 4> _drawingEnd = { { false } };
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace HistoryView
|
|
@ -109,7 +109,9 @@ void Sticker::initSize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize Sticker::size() {
|
QSize Sticker::size() {
|
||||||
|
if (_size.isEmpty()) {
|
||||||
initSize();
|
initSize();
|
||||||
|
}
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,7 +303,7 @@ void Sticker::setupLottie() {
|
||||||
_dataMedia.get(),
|
_dataMedia.get(),
|
||||||
_replacements,
|
_replacements,
|
||||||
ChatHelpers::StickerLottieSize::MessageHistory,
|
ChatHelpers::StickerLottieSize::MessageHistory,
|
||||||
_size * cIntRetinaFactor(),
|
size() * cIntRetinaFactor(),
|
||||||
Lottie::Quality::High);
|
Lottie::Quality::High);
|
||||||
lottieCreated();
|
lottieCreated();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue