mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
649 lines
21 KiB
C++
649 lines
21 KiB
C++
//+----------------------------------------------------------------------------+
|
|
//| Description: Magic Set Editor - Program to make Magic (tm) cards |
|
|
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
|
//| License: GNU General Public License 2 or later (see file COPYING) |
|
|
//+----------------------------------------------------------------------------+
|
|
|
|
// ----------------------------------------------------------------------------- : Includes
|
|
|
|
#include <util/prec.hpp>
|
|
#include <gui/set/random_pack_panel.hpp>
|
|
#include <gui/control/card_viewer.hpp>
|
|
#include <gui/control/filtered_card_list.hpp>
|
|
#include <gui/util.hpp>
|
|
#include <gui/about_window.hpp> // HoverButtonBase
|
|
#include <data/action/set.hpp>
|
|
#include <data/game.hpp>
|
|
#include <data/pack.hpp>
|
|
#include <data/settings.hpp>
|
|
#include <util/window_id.hpp>
|
|
#include <wx/spinctrl.h>
|
|
#include <wx/dcbuffer.h>
|
|
|
|
// ----------------------------------------------------------------------------- : RandomCardList
|
|
|
|
/// A card list that contains the
|
|
class RandomCardList : public CardListBase {
|
|
public:
|
|
RandomCardList(Window* parent, int id, long style = 0);
|
|
|
|
/// Reset the list
|
|
void reset();
|
|
|
|
using CardListBase::rebuild;
|
|
|
|
const vector<CardP>* getCardsPtr() const { return &cards; }
|
|
vector<CardP> cards;
|
|
|
|
protected:
|
|
void getItems(vector<VoidP>& out) const override;
|
|
void onChangeSet() override;
|
|
};
|
|
|
|
RandomCardList::RandomCardList(Window* parent, int id, long style)
|
|
: CardListBase(parent, id, style)
|
|
{}
|
|
|
|
void RandomCardList::reset() {
|
|
cards.clear();
|
|
}
|
|
|
|
void RandomCardList::onChangeSet() {
|
|
reset();
|
|
CardListBase::onChangeSet();
|
|
}
|
|
|
|
void RandomCardList::getItems(vector<VoidP>& out) const {
|
|
out.reserve(cards.size());
|
|
FOR_EACH_CONST(c, cards) {
|
|
out.push_back(c);
|
|
}
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------- : PackTotalsPanel
|
|
|
|
class PackTotalsPanel : public wxPanel {
|
|
public:
|
|
PackTotalsPanel(Window* parent, int id, PackGenerator& generator, bool show_all = false)
|
|
: wxPanel(parent,id), generator(generator), show_all(show_all) {}
|
|
void setGame(const GameP& game);
|
|
virtual wxSize DoGetBestSize() const override;
|
|
private:
|
|
DECLARE_EVENT_TABLE();
|
|
GameP game;
|
|
void onPaint(wxPaintEvent&);
|
|
void draw(DC& dc);
|
|
void drawItem(DC& dc, int& y, const String& name, double value);
|
|
PackGenerator& generator;
|
|
bool show_all;
|
|
};
|
|
|
|
void PackTotalsPanel::onPaint(wxPaintEvent&) {
|
|
wxBufferedPaintDC dc(this);
|
|
draw(dc);
|
|
}
|
|
void PackTotalsPanel::draw(DC& dc) {
|
|
// clear background
|
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
|
dc.SetBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
|
|
wxSize size = dc.GetSize();
|
|
dc.DrawRectangle(0,0,size.x,size.y);
|
|
// draw table
|
|
dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
|
|
dc.SetFont(*wxNORMAL_FONT);
|
|
int y = 0;
|
|
int total = 0;
|
|
FOR_EACH(pack, game->pack_types) {
|
|
PackInstance& i = generator.get(pack);
|
|
if (pack->summary && (show_all || i.has_cards())) {
|
|
drawItem(dc, y, tr(*game, pack->name, capitalize), i.get_card_copies());
|
|
total += (int)i.get_card_copies();
|
|
}
|
|
}
|
|
// draw total
|
|
dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DSHADOW));
|
|
dc.DrawLine(0, y-3, size.x, y-3);
|
|
dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT));
|
|
dc.DrawLine(0, y-2, size.x, y-2);
|
|
y += 7;
|
|
drawItem(dc, y, _LABEL_("total cards"), total);
|
|
}
|
|
void PackTotalsPanel::drawItem(DC& dc, int& y, const String& name, double value) {
|
|
wxSize size = dc.GetSize();
|
|
int w,h;
|
|
String amount = String::Format(_("%.f"),value);
|
|
dc.GetTextExtent(amount,&w,&h);
|
|
dc.DrawText(name, 0, y);
|
|
dc.DrawText(amount, size.x-w, y);//align right
|
|
y += h + 10;
|
|
}
|
|
|
|
wxSize PackTotalsPanel::DoGetBestSize() const {
|
|
// count lines
|
|
int lines = 0;
|
|
if (game && generator.set) {
|
|
FOR_EACH(pack, game->pack_types) {
|
|
PackInstance& i = generator.get(pack);
|
|
if (pack->summary && (show_all || i.has_cards())) {
|
|
lines++;
|
|
}
|
|
}
|
|
}
|
|
// don't forget the total
|
|
lines++;
|
|
// size
|
|
int height = lines * (GetCharHeight() + 10) + 7 - 10;
|
|
wxSize ws = GetSize(), cs = GetClientSize();
|
|
return wxSize(0,height) + ws - cs;
|
|
}
|
|
|
|
void PackTotalsPanel::setGame(const GameP& game) {
|
|
this->game = game;
|
|
}
|
|
|
|
BEGIN_EVENT_TABLE(PackTotalsPanel, wxPanel)
|
|
EVT_PAINT(PackTotalsPanel::onPaint)
|
|
END_EVENT_TABLE()
|
|
|
|
|
|
// ----------------------------------------------------------------------------- : SelectableLabel
|
|
|
|
class SelectableLabel : public HoverButtonBase {
|
|
public:
|
|
SelectableLabel(wxWindow* parent, int id, const String& label, bool interactive = true)
|
|
: HoverButtonBase(parent, id, false)
|
|
, label(label)
|
|
, interactive(interactive)
|
|
, buddy(nullptr)
|
|
{}
|
|
void draw(DC& dc) override {
|
|
Color bg = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
|
|
Color fg = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT);
|
|
// clear background
|
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
|
//dc.SetBrush(mouse_down ? wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)
|
|
// : hover ? lerp(bg,fg,0.1) : bg);
|
|
//dc.SetTextForeground(mouse_down ? wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) : fg);
|
|
dc.SetBrush(interactive && hover ? lerp(bg,fg,0.1) : bg);
|
|
dc.SetTextForeground(fg);
|
|
wxSize size = dc.GetSize();
|
|
dc.DrawRectangle(0,0,size.x,size.y);
|
|
// draw label
|
|
dc.SetFont(*wxNORMAL_FONT);
|
|
int w,h;
|
|
wxSize s = dc.GetSize();
|
|
dc.GetTextExtent(label,&w,&h);
|
|
dc.DrawText(interactive && hover ? label + _("...") : label, 2, (s.y-h)/2);
|
|
}
|
|
wxSize DoGetBestSize() const override {
|
|
int w,h;
|
|
wxClientDC dc(const_cast<SelectableLabel*>(this));
|
|
dc.SetFont(*wxNORMAL_FONT);
|
|
dc.GetTextExtent(label,&w,&h);
|
|
return wxSize(w+6,h);
|
|
}
|
|
void setBuddy(wxWindow* buddy) {
|
|
this->buddy = buddy;
|
|
}
|
|
void onClick() override {
|
|
if (buddy) buddy->SetFocus();
|
|
}
|
|
void onDoubleClick(wxMouseEvent&) {
|
|
if (interactive) HoverButtonBase::onClick();
|
|
}
|
|
private:
|
|
String label;
|
|
bool interactive;
|
|
wxWindow* buddy;
|
|
DECLARE_EVENT_TABLE();
|
|
};
|
|
|
|
BEGIN_EVENT_TABLE(SelectableLabel, HoverButtonBase)
|
|
EVT_LEFT_DCLICK(SelectableLabel::onDoubleClick)
|
|
END_EVENT_TABLE()
|
|
|
|
// ----------------------------------------------------------------------------- : PackAmountPicker
|
|
|
|
PackAmountPicker::PackAmountPicker(wxWindow* parent, wxFlexGridSizer* sizer, const PackTypeP& pack, bool active)
|
|
: pack(pack)
|
|
, label(new SelectableLabel(parent, ID_PACK_TYPE, capitalize_sentence(pack->name), active))
|
|
, value(new wxSpinCtrl(parent, ID_PACK_AMOUNT, _("0"), wxDefaultPosition, wxSize(50,-1)))
|
|
{
|
|
label->setBuddy(value);
|
|
sizer->Add(label, 1, wxEXPAND | wxALIGN_CENTER_VERTICAL);
|
|
sizer->Add(value, 0, wxEXPAND | wxALIGN_CENTER_VERTICAL);
|
|
if (active) {
|
|
label->SetHelpText(_HELP_("edit pack type"));
|
|
}
|
|
set_help_text(value, _HELP_1_("number of packs", pack->name));
|
|
}
|
|
|
|
void PackAmountPicker::destroy(wxFlexGridSizer* sizer) {
|
|
sizer->Detach(label);
|
|
sizer->Detach(value);
|
|
delete label;
|
|
delete value;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------- : CustomPackDialog
|
|
|
|
class CustomPackDialog : public wxDialog {
|
|
public:
|
|
CustomPackDialog(Window* parent, const SetP& set, const PackTypeP& edited_pack, bool can_remove);
|
|
PackTypeP get() const { return edited_pack; }
|
|
private:
|
|
DECLARE_EVENT_TABLE();
|
|
|
|
SetP set;
|
|
PackTypeP edited_pack;
|
|
PackGenerator generator;
|
|
wxTextCtrl* name;
|
|
PackTotalsPanel* totals;
|
|
vector<PackAmountPicker> pickers;
|
|
|
|
void updateTotals();
|
|
void storePack();
|
|
void onAmountChange(wxSpinEvent&);
|
|
void onOk(wxCommandEvent&);
|
|
void onRemove(wxCommandEvent&);
|
|
bool isDuplicateName(const String& name);
|
|
};
|
|
|
|
CustomPackDialog::CustomPackDialog(Window* parent, const SetP& set, const PackTypeP& edited_pack, bool can_remove)
|
|
: wxDialog(parent, wxID_ANY, _TITLE_("custom pack"), wxDefaultPosition, wxSize(500,500))
|
|
, set(set), edited_pack(edited_pack)
|
|
{
|
|
// init ui
|
|
totals = new PackTotalsPanel(this, wxID_ANY, generator, true);
|
|
name = new wxTextCtrl(this, wxID_ANY, edited_pack ? edited_pack->name : _("custom pack"));
|
|
wxButton* remove =
|
|
can_remove ? new wxButton(this, ID_REMOVE_ITEM, _BUTTON_("remove item"))
|
|
: nullptr;
|
|
// init sizer
|
|
wxSizer* s = new wxBoxSizer(wxVERTICAL);
|
|
wxSizer* s2 = new wxStaticBoxSizer(wxHORIZONTAL, this, _LABEL_("pack name"));
|
|
s2->Add(name, 1, wxEXPAND | wxALL, 4);
|
|
s->Add(s2, 0, wxEXPAND | wxALL, 8);
|
|
wxSizer* s3 = new wxBoxSizer(wxHORIZONTAL);
|
|
wxSizer* s4 = new wxStaticBoxSizer(wxHORIZONTAL, this, _LABEL_("pack selection"));
|
|
s4->AddSpacer(2);
|
|
wxFlexGridSizer* packsSizer = new wxFlexGridSizer(0, 2, 4, 4);
|
|
packsSizer->AddGrowableCol(0);
|
|
s4->Add(packsSizer, 1, wxEXPAND | (wxALL & ~wxTOP & ~wxLEFT), 4);
|
|
s3->Add(s4, 1, wxEXPAND, 8);
|
|
wxSizer* s5 = new wxStaticBoxSizer(wxHORIZONTAL, this, _LABEL_("pack totals"));
|
|
s5->Add(totals, 1, wxEXPAND | wxALL, 4);
|
|
s3->Add(s5, 1, wxEXPAND | wxLEFT, 8);
|
|
s->Add(s3, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
|
wxSizer* s6 = new wxBoxSizer(wxHORIZONTAL);
|
|
if (can_remove) {
|
|
s6->Add(remove, 0, wxALL & ~wxTOP & ~wxRIGHT, 8);
|
|
}
|
|
s6->Add(CreateButtonSizer(wxOK | wxCANCEL), 1, wxALL & ~wxTOP, 8);
|
|
s->Add(s6, 0, wxEXPAND);
|
|
// add spin controls
|
|
FOR_EACH(pack, set->game->pack_types) {
|
|
if (pack->selectable) continue; // this pack is already selectable from the main UI
|
|
PackAmountPicker pick(this, packsSizer, pack, false);
|
|
pickers.push_back(pick);
|
|
// set value if it is nonzero
|
|
if (edited_pack) {
|
|
FOR_EACH(i, edited_pack->items) {
|
|
if (i->name == pack->name) {
|
|
pick.value->SetValue(i->amount);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// update totals
|
|
generator.reset(set,0);
|
|
totals->setGame(set->game);
|
|
updateTotals();
|
|
// set sizer
|
|
s->SetSizeHints(this);
|
|
SetSizer(s);
|
|
}
|
|
|
|
void CustomPackDialog::updateTotals() {
|
|
generator.reset(0);
|
|
int total_packs = 0;
|
|
FOR_EACH(pick,pickers) {
|
|
int copies = pick.value->GetValue();
|
|
total_packs += copies;
|
|
generator.get(pick.pack).request_copy(copies);
|
|
}
|
|
generator.update_card_counts();
|
|
// update UI
|
|
totals->Refresh(false);
|
|
FindWindow(wxID_OK)->Enable(total_packs > 0);
|
|
}
|
|
|
|
void CustomPackDialog::storePack() {
|
|
edited_pack = make_intrusive<PackType>();
|
|
edited_pack->selectable = true;
|
|
edited_pack->select = SELECT_ALL;
|
|
edited_pack->name = name->GetValue();
|
|
FOR_EACH(pick,pickers) {
|
|
int copies = pick.value->GetValue();
|
|
if (copies > 0) {
|
|
edited_pack->items.push_back(make_intrusive<PackItem>(pick.pack->name, copies));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CustomPackDialog::isDuplicateName(const String& name) {
|
|
FOR_EACH_CONST(pack, set->game->pack_types) {
|
|
if (pack->name == name) return true;
|
|
}
|
|
FOR_EACH_CONST(pack, set->pack_types) {
|
|
if (pack->name == name) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void CustomPackDialog::onOk(wxCommandEvent&) {
|
|
// check for duplicates
|
|
if (isDuplicateName(name->GetValue())) {
|
|
wxMessageBox(_ERROR_1_("pack type duplicate name",name->GetValue()),_TITLE_("custom pack"),wxOK|wxICON_EXCLAMATION);
|
|
return;
|
|
}
|
|
// done
|
|
storePack();
|
|
EndModal(wxID_OK);
|
|
}
|
|
void CustomPackDialog::onRemove(wxCommandEvent&) {
|
|
edited_pack = PackTypeP();
|
|
EndModal(wxID_OK);
|
|
}
|
|
void CustomPackDialog::onAmountChange(wxSpinEvent&) {
|
|
updateTotals();
|
|
}
|
|
|
|
BEGIN_EVENT_TABLE(CustomPackDialog, wxDialog)
|
|
EVT_BUTTON (wxID_OK, CustomPackDialog::onOk)
|
|
EVT_BUTTON (ID_REMOVE_ITEM, CustomPackDialog::onRemove)
|
|
EVT_SPINCTRL (ID_PACK_AMOUNT, CustomPackDialog::onAmountChange)
|
|
END_EVENT_TABLE()
|
|
|
|
// ----------------------------------------------------------------------------- : RandomPackPanel
|
|
|
|
RandomPackPanel::RandomPackPanel(Window* parent, int id)
|
|
: SetWindowPanel(parent, id)
|
|
{
|
|
// delayed initialization by initControls()
|
|
}
|
|
|
|
void RandomPackPanel::initControls() {
|
|
// init controls
|
|
preview = new CardViewer(this, wxID_ANY);
|
|
card_list = new RandomCardList(this, wxID_ANY);
|
|
generate_button = new wxButton(this, ID_GENERATE_PACK, _BUTTON_("generate pack"));
|
|
seed_random = new wxRadioButton(this, ID_SEED_RANDOM, _BUTTON_("random seed"));
|
|
seed_fixed = new wxRadioButton(this, ID_SEED_FIXED, _BUTTON_("fixed seed"));
|
|
seed = new wxTextCtrl(this, wxID_ANY);
|
|
totals = new PackTotalsPanel(this, wxID_ANY, generator);
|
|
set_help_text(seed_random, _HELP_("random seed"));
|
|
set_help_text(seed_fixed, _HELP_("fixed seed"));
|
|
set_help_text(seed, _HELP_("seed"));
|
|
// init sizer
|
|
wxSizer* s = new wxBoxSizer(wxHORIZONTAL);
|
|
s->Add(preview, 0, wxRIGHT, 2);
|
|
wxSizer* s2 = new wxBoxSizer(wxVERTICAL);
|
|
wxSizer* s3 = new wxBoxSizer(wxHORIZONTAL);
|
|
wxSizer* s4 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("pack selection"));
|
|
wxSizer* s4b = new wxBoxSizer(wxHORIZONTAL);
|
|
packsSizer = new wxFlexGridSizer(0, 2, 4, 4);
|
|
packsSizer->AddGrowableCol(0);
|
|
s4b->Add(packsSizer, 1, wxEXPAND | (wxALL & ~wxTOP & ~wxLEFT), 4);
|
|
s4->Add(s4b, 1, wxEXPAND | wxLEFT, 2);
|
|
s4->Add(new wxButton(this, ID_CUSTOM_PACK, _BUTTON_("add custom pack")), 0, wxEXPAND | wxALIGN_TOP | (wxALL & ~wxTOP), 4);
|
|
s3->Add(s4, 1, wxEXPAND, 8);
|
|
wxSizer* s5 = new wxStaticBoxSizer(wxHORIZONTAL, this, _LABEL_("pack totals"));
|
|
s5->Add(totals, 1, wxEXPAND | wxALL, 4);
|
|
s3->Add(s5, 1, wxEXPAND | wxLEFT, 8);
|
|
wxSizer* s6 = new wxBoxSizer(wxVERTICAL);
|
|
wxSizer* s7 = new wxStaticBoxSizer(wxVERTICAL, this, _LABEL_("seed"));
|
|
s7->Add(seed_random, 0, wxALL, 4);
|
|
s7->Add(seed_fixed, 0, wxALL, 4);
|
|
wxSizer* s8 = new wxBoxSizer(wxHORIZONTAL);
|
|
s8->Add(seed, 1, wxLEFT, 20);
|
|
s7->Add(s8, 0, wxALL & ~wxTOP, 4);
|
|
s6->Add(s7, 0, 0, 8);
|
|
//s6->AddStretchSpacer();
|
|
//s6->Add(generate_button, 0, wxTOP | wxALIGN_RIGHT, 8);
|
|
s6->Add(generate_button, 1, wxTOP | wxEXPAND, 8);
|
|
s3->Add(s6, 0, wxEXPAND | wxLEFT, 8);
|
|
s2->Add(s3, 0, wxEXPAND | (wxALL & ~wxTOP), 4);
|
|
s2->Add(card_list, 1, wxEXPAND);
|
|
s->Add(s2, 1, wxEXPAND, 8);
|
|
s->SetSizeHints(this);
|
|
SetSizer(s);
|
|
}
|
|
|
|
RandomPackPanel::~RandomPackPanel() {
|
|
storeSettings();
|
|
}
|
|
|
|
void RandomPackPanel::onBeforeChangeSet() {
|
|
if (set) {
|
|
storeSettings();
|
|
}
|
|
}
|
|
void RandomPackPanel::onChangeSet() {
|
|
if (!isInitialized()) return;
|
|
preview ->setSet(set);
|
|
card_list->setSet(set);
|
|
totals ->setGame(set->game);
|
|
|
|
// remove old pack controls
|
|
FOR_EACH(pick, pickers) pick.destroy(packsSizer);
|
|
pickers.clear();
|
|
|
|
// add pack controls
|
|
FOR_EACH(pack, set->game->pack_types) {
|
|
if (pack->selectable) {
|
|
pickers.push_back(PackAmountPicker(this,packsSizer,pack,false));
|
|
}
|
|
}
|
|
FOR_EACH(pack, set->pack_types) {
|
|
if (pack->selectable) {
|
|
pickers.push_back(PackAmountPicker(this,packsSizer,pack,true));
|
|
}
|
|
}
|
|
|
|
Layout();
|
|
|
|
// settings
|
|
GameSettings& gs = settings.gameSettingsFor(*set->game);
|
|
seed_random->SetValue(gs.pack_seed_random);
|
|
seed_fixed ->SetValue(!gs.pack_seed_random);
|
|
seed->Enable(!gs.pack_seed_random);
|
|
setSeed(gs.pack_seed);
|
|
generator.set = SetP(); // prevent spurious events
|
|
FOR_EACH(pick, pickers) {
|
|
pick.value->SetValue(gs.pack_amounts[pick.pack->name]);
|
|
}
|
|
|
|
generator.reset(set,last_seed=getSeed());
|
|
updateTotals();
|
|
}
|
|
|
|
void RandomPackPanel::onAction(const Action& action, bool undone) {
|
|
TYPE_CASE_(action, PackTypesAction) {
|
|
// rebuild the list
|
|
storeSettings();
|
|
onChangeSet();
|
|
}
|
|
}
|
|
|
|
void RandomPackPanel::storeSettings() {
|
|
if (!isInitialized()) return;
|
|
GameSettings& gs = settings.gameSettingsFor(*set->game);
|
|
gs.pack_seed_random = seed_random->GetValue();
|
|
FOR_EACH(pick, pickers) {
|
|
gs.pack_amounts[pick.pack->name] = pick.value->GetValue();
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------- : UI
|
|
|
|
void RandomPackPanel::initUI(wxToolBar* tb, wxMenuBar* mb) {
|
|
// Init controls?
|
|
if (!isInitialized()) {
|
|
wxBusyCursor busy;
|
|
initControls();
|
|
onChangeSet();
|
|
}
|
|
// this is a good moment to update, because the set has likely changed
|
|
generator.reset(set,last_seed);
|
|
updateTotals();
|
|
}
|
|
|
|
void RandomPackPanel::destroyUI(wxToolBar* tb, wxMenuBar* mb) {}
|
|
|
|
void RandomPackPanel::onUpdateUI(wxUpdateUIEvent& ev) {}
|
|
|
|
void RandomPackPanel::onCommand(int id) {
|
|
if (!isInitialized()) return;
|
|
switch (id) {
|
|
case ID_PACK_AMOUNT: {
|
|
updateTotals();
|
|
break;
|
|
}
|
|
case ID_GENERATE_PACK: {
|
|
generate();
|
|
break;
|
|
}
|
|
case ID_SEED_RANDOM: case ID_SEED_FIXED: {
|
|
seed->Enable(seed_fixed->GetValue());
|
|
break;
|
|
}
|
|
case ID_CUSTOM_PACK: {
|
|
CustomPackDialog dlg(this, set, PackTypeP(), false);
|
|
if (dlg.ShowModal() == wxID_OK) {
|
|
set->actions.addAction(make_unique<AddPackAction>(ADD,*set,dlg.get()));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
void RandomPackPanel::onPackTypeClick(wxCommandEvent& ev) {
|
|
FOR_EACH(pick, pickers) {
|
|
if (pick.label == ev.GetEventObject()) {
|
|
// edit this pack type
|
|
CustomPackDialog dlg(this, set, pick.pack, true);
|
|
if (dlg.ShowModal() == wxID_OK) {
|
|
if (dlg.get()) {
|
|
// update pack
|
|
for (size_t i = 0 ; i < set->pack_types.size() ; ++i) {
|
|
if (set->pack_types[i] == pick.pack) {
|
|
set->actions.addAction(make_unique<ChangePackAction>(*set,i,dlg.get()));
|
|
}
|
|
}
|
|
} else {
|
|
// delete pack
|
|
set->actions.addAction(make_unique<AddPackAction>(REMOVE,*set,pick.pack));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------- : Generating
|
|
|
|
void RandomPackPanel::updateTotals() {
|
|
if (!generator.set) return; // not initialized
|
|
generator.reset(last_seed);
|
|
int total_packs = 0;
|
|
FOR_EACH(pick,pickers) {
|
|
int copies = pick.value->GetValue();
|
|
total_packs += copies;
|
|
generator.get(pick.pack).request_copy(copies);
|
|
}
|
|
generator.update_card_counts();
|
|
// update UI
|
|
totals->Refresh(false);
|
|
generate_button->Enable(total_packs > 0);
|
|
}
|
|
|
|
int RandomPackPanel::getSeed() {
|
|
// determine seed value
|
|
int seed = 0;
|
|
if (seed_random->GetValue()) {
|
|
// use the C rand() function to get a seed
|
|
seed = rand() % 1000 * 1000
|
|
+ clock() % 1000;
|
|
} else {
|
|
// convert *any* string to a number
|
|
String s = this->seed->GetValue();
|
|
FOR_EACH_CONST(c,s) {
|
|
seed *= 10;
|
|
seed += abs(c - '0') + 123456789*(abs(c - '0')/10);
|
|
}
|
|
}
|
|
setSeed(seed);
|
|
return seed;
|
|
}
|
|
void RandomPackPanel::setSeed(int seed) {
|
|
seed %= 1000000;
|
|
this->seed->SetValue(wxString::Format(_("%06d"),seed));
|
|
GameSettings& gs = settings.gameSettingsFor(*set->game);
|
|
gs.pack_seed = seed;
|
|
}
|
|
|
|
void RandomPackPanel::generate() {
|
|
generator.reset(set,last_seed=getSeed());
|
|
// add packs to card list
|
|
card_list->reset();
|
|
FOR_EACH(pick,pickers) {
|
|
int copies = pick.value->GetValue();
|
|
for (int i = 0 ; i < copies ; ++i) {
|
|
generator.get(pick.pack).request_copy();
|
|
generator.generate(card_list->cards);
|
|
}
|
|
}
|
|
card_list->rebuild();
|
|
card_list->selectFirst();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------- : Selection
|
|
|
|
CardP RandomPackPanel::selectedCard() const {
|
|
if (!isInitialized()) return CardP();
|
|
return card_list->getCard();
|
|
}
|
|
|
|
void RandomPackPanel::selectCard(const CardP& card) {
|
|
// Don't change the card based on other panels
|
|
//preview->setCard(card);
|
|
}
|
|
void RandomPackPanel::onCardSelect(CardSelectEvent& ev) {
|
|
preview->setCard(ev.getCard());
|
|
ev.Skip(); // but do change other panels' selection
|
|
}
|
|
|
|
void RandomPackPanel::selectionChoices(ExportCardSelectionChoices& out) {
|
|
if (!isInitialized()) return;
|
|
out.push_back(make_intrusive<ExportCardSelectionChoice>(
|
|
_BUTTON_("export generated packs"),
|
|
card_list->getCardsPtr()
|
|
));
|
|
}
|
|
|
|
void RandomPackPanel::getCardLists(vector<CardListBase*>& out) {
|
|
if (isInitialized()) out.push_back(card_list);
|
|
}
|
|
|
|
BEGIN_EVENT_TABLE(RandomPackPanel, wxPanel)
|
|
EVT_CARD_SELECT(wxID_ANY, RandomPackPanel::onCardSelect)
|
|
EVT_BUTTON (ID_PACK_TYPE, RandomPackPanel::onPackTypeClick)
|
|
END_EVENT_TABLE ()
|
|
|
|
|
|
// ----------------------------------------------------------------------------- : Clipboard
|
|
|
|
bool RandomPackPanel::canCopy() const { return isInitialized() && card_list->canCopy(); }
|
|
void RandomPackPanel::doCopy() { isInitialized() && card_list->doCopy(); }
|