mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 13:06:59 -04:00
thumbnails for choice editor
git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@159 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
@@ -166,14 +166,19 @@ ChoiceStyle::ChoiceStyle(const ChoiceFieldP& field)
|
||||
, combine(COMBINE_NORMAL)
|
||||
, alignment(ALIGN_STRETCH)
|
||||
, colors_card_list(false)
|
||||
, thumbnails(nullptr)
|
||||
{}
|
||||
|
||||
ChoiceStyle::~ChoiceStyle() {
|
||||
delete thumbnails;
|
||||
}
|
||||
|
||||
// TODO
|
||||
/*
|
||||
void ChoiceStyle::invalidate() {
|
||||
// rebuild choice images
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
bool ChoiceStyle::update(Context& ctx) {
|
||||
// Don't update the choice images, leave that to invalidate()
|
||||
|
||||
@@ -115,6 +115,7 @@ class ChoiceStyle : public Style {
|
||||
public:
|
||||
ChoiceStyle(const ChoiceFieldP& field);
|
||||
DECLARE_STYLE_TYPE(Choice);
|
||||
~ChoiceStyle();
|
||||
|
||||
ChoicePopupStyle popup_style; ///< Style of popups/menus
|
||||
ChoiceRenderStyle render_style; ///< Style of rendering
|
||||
@@ -126,6 +127,8 @@ class ChoiceStyle : public Style {
|
||||
ImageCombine combine; ///< Combining mode for drawing the images
|
||||
Alignment alignment; ///< Alignment of images
|
||||
Image mask; ///< The actual mask image
|
||||
wxImageList* thumbnails; ///< Thumbnails for the choices
|
||||
Age thumbnail_age; ///< Age the thumbnails were generated
|
||||
|
||||
/// Load the mask image, if it's not already done
|
||||
void loadMask(Package& pkg);
|
||||
|
||||
@@ -48,15 +48,39 @@ Set::~Set() {}
|
||||
|
||||
|
||||
Context& Set::getContext() {
|
||||
assert(wxThread::IsMain());
|
||||
return script_manager->getContext(stylesheet);
|
||||
}
|
||||
Context& Set::getContext(const CardP& card) {
|
||||
assert(wxThread::IsMain());
|
||||
return script_manager->getContext(card);
|
||||
}
|
||||
void Set::updateFor(const CardP& card) {
|
||||
script_manager->updateStyles(card);
|
||||
}
|
||||
|
||||
Context& Set::getContextForThumbnails() {
|
||||
assert(!wxThread::IsMain());
|
||||
if (!thumbnail_script_context) {
|
||||
thumbnail_script_context.reset(new SetScriptContext(*this));
|
||||
}
|
||||
return thumbnail_script_context->getContext(stylesheet);
|
||||
}
|
||||
Context& Set::getContextForThumbnails(const CardP& card) {
|
||||
assert(!wxThread::IsMain());
|
||||
if (!thumbnail_script_context) {
|
||||
thumbnail_script_context.reset(new SetScriptContext(*this));
|
||||
}
|
||||
return thumbnail_script_context->getContext(card);
|
||||
}
|
||||
Context& Set::getContextForThumbnails(const StyleSheetP& stylesheet) {
|
||||
assert(!wxThread::IsMain());
|
||||
if (!thumbnail_script_context) {
|
||||
thumbnail_script_context.reset(new SetScriptContext(*this));
|
||||
}
|
||||
return thumbnail_script_context->getContext(stylesheet);
|
||||
}
|
||||
|
||||
StyleSheetP Set::stylesheetFor(const CardP& card) {
|
||||
if (card && card->stylesheet) return card->stylesheet;
|
||||
else return stylesheet;
|
||||
|
||||
@@ -71,6 +71,9 @@ class Set : public Packaged {
|
||||
/// A context for performing scripts on a particular card
|
||||
/** Should only be used from the thumbnail thread! */
|
||||
Context& getContextForThumbnails(const CardP& card);
|
||||
/// A context for performing scripts on a particular stylesheet
|
||||
/** Should only be used from the thumbnail thread! */
|
||||
Context& getContextForThumbnails(const StyleSheetP& stylesheet);
|
||||
|
||||
/// Stylesheet to use for a particular card
|
||||
/** card may be null */
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <gui/control/card_list.hpp>
|
||||
#include <gui/control/card_list_column_select.hpp>
|
||||
#include <gui/icon_menu.hpp>
|
||||
#include <data/game.hpp>
|
||||
#include <data/field.hpp>
|
||||
#include <data/field/choice.hpp>
|
||||
@@ -60,6 +61,10 @@ void CardListBase::onAction(const Action& action, bool undone) {
|
||||
TYPE_CASE(action, AddCardAction) {
|
||||
if (undone) {
|
||||
refreshList();
|
||||
if (!allowModify()) {
|
||||
// Let some other card list else do the selecting
|
||||
return;
|
||||
}
|
||||
selectCardPos((long)sorted_card_list.size() - 1, true);
|
||||
} else {
|
||||
// select the new card
|
||||
@@ -75,6 +80,10 @@ void CardListBase::onAction(const Action& action, bool undone) {
|
||||
} else {
|
||||
long pos = selected_card_pos;
|
||||
refreshList();
|
||||
if (!allowModify()) {
|
||||
// Let some other card list else do the selecting
|
||||
return;
|
||||
}
|
||||
if (action.card == selected_card) {
|
||||
// select the next card, if not possible, select the last
|
||||
if ((size_t)pos + 1 < sorted_card_list.size()) {
|
||||
@@ -140,8 +149,8 @@ void CardListBase::selectCard(const CardP& card, bool focus, bool event) {
|
||||
CardSelectEvent ev(card);
|
||||
ProcessEvent(ev);
|
||||
}
|
||||
findSelectedCardPos();
|
||||
if (focus) {
|
||||
findSelectedCardPos();
|
||||
selectCurrentCard();
|
||||
}
|
||||
}
|
||||
@@ -443,6 +452,19 @@ void CardListBase::onDrag(wxMouseEvent& ev) {
|
||||
}
|
||||
}
|
||||
|
||||
void CardListBase::onContextMenu(wxContextMenuEvent&) {
|
||||
if (allowModify()) {
|
||||
IconMenu m;
|
||||
m.Append(wxID_CUT, _("TOOL_CUT"), _("Cu&t"), _("Move the selected card to the clipboard"));
|
||||
m.Append(wxID_COPY, _("TOOL_COPY"), _("&Copy"), _("Place the selected card on the clipboard"));
|
||||
m.Append(wxID_PASTE, _("TOOL_PASTE"), _("&Paste"), _("Inserts the card from the clipboard"));
|
||||
m.AppendSeparator();
|
||||
m.Append(ID_CARD_ADD, _("TOOL_CARD_ADD"), _("&Add Card"), _("Add a new, blank, card to this set"));
|
||||
m.Append(ID_CARD_REMOVE,_("TOOL_CARD_DEL"), _("&Remove Select Card"), _("Delete the selected card from this set"));
|
||||
PopupMenu(&m);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : CardListBase : Event table
|
||||
|
||||
BEGIN_EVENT_TABLE(CardListBase, wxListView)
|
||||
@@ -452,4 +474,5 @@ BEGIN_EVENT_TABLE(CardListBase, wxListView)
|
||||
EVT_CHAR ( CardListBase::onChar)
|
||||
EVT_MOTION ( CardListBase::onDrag)
|
||||
EVT_MENU (ID_SELECT_COLUMNS, CardListBase::onSelectColumns)
|
||||
EVT_CONTEXT_MENU ( CardListBase::onContextMenu)
|
||||
END_EVENT_TABLE ()
|
||||
|
||||
@@ -154,6 +154,7 @@ class CardListBase : public wxListView, public SetView {
|
||||
void onItemFocus (wxListEvent& ev);
|
||||
void onChar (wxKeyEvent& ev);
|
||||
void onDrag (wxMouseEvent& ev);
|
||||
void onContextMenu (wxContextMenuEvent&);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -12,6 +12,30 @@
|
||||
typedef pair<ThumbnailRequestP,Image> pair_ThumbnailRequestP_Image;
|
||||
DECLARE_TYPEOF_COLLECTION(pair_ThumbnailRequestP_Image);
|
||||
|
||||
// ----------------------------------------------------------------------------- : Image Cache
|
||||
|
||||
String user_settings_dir();
|
||||
String image_cache_dir() {
|
||||
String dir = user_settings_dir() + _("/cache");
|
||||
if (!wxDirExists(dir)) wxMkDir(dir);
|
||||
return dir + _("/");
|
||||
}
|
||||
|
||||
/// A name that is safe to use as a filename, for the cache
|
||||
String safe_filename(const String& str) {
|
||||
String ret; ret.reserve(str.size());
|
||||
FOR_EACH_CONST(c, str) {
|
||||
if (isAlnum(c)) {
|
||||
ret += c;
|
||||
} else if (c==_(' ') || c==_('-')) {
|
||||
ret += _('-');
|
||||
} else {
|
||||
ret += _('_');
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : ThumbnailThreadWorker
|
||||
|
||||
class ThumbnailThreadWorker : public wxThread {
|
||||
@@ -50,7 +74,15 @@ wxThread::ExitCode ThumbnailThreadWorker::Entry() {
|
||||
if (TestDestroy()) return 0;
|
||||
Image img = current->generate();
|
||||
if (TestDestroy()) return 0;
|
||||
// store result
|
||||
// store in cache
|
||||
if (img.Ok()) {
|
||||
String filename = image_cache_dir() + safe_filename(current->cache_name) + _(".png");
|
||||
img.SaveFile(filename, wxBITMAP_TYPE_PNG);
|
||||
// set modification time
|
||||
wxFileName fn(filename);
|
||||
fn.SetTimes(0, ¤t->modified, 0);
|
||||
}
|
||||
// store result in closed request list
|
||||
{
|
||||
wxMutexLocker lock(parent->mutex);
|
||||
parent->closed_requests.push_back(make_pair(current,img));
|
||||
@@ -79,27 +111,6 @@ ThumbnailThread::~ThumbnailThread() {
|
||||
abortAll();
|
||||
}
|
||||
|
||||
String user_settings_dir();
|
||||
String image_cache_dir() {
|
||||
String dir = user_settings_dir() + _("/cache");
|
||||
if (!wxDirExists(dir)) wxMkDir(dir);
|
||||
return dir + _("/");
|
||||
}
|
||||
|
||||
String ThumbnailThread::safeFilename(const String& str) {
|
||||
String ret; ret.reserve(str.size());
|
||||
FOR_EACH_CONST(c, str) {
|
||||
if (isAlnum(c)) {
|
||||
ret += c;
|
||||
} else if (c==_(' ') || c==_('-')) {
|
||||
ret += _('-');
|
||||
} else {
|
||||
ret += _('_');
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ThumbnailThread::request(const ThumbnailRequestP& request) {
|
||||
assert(wxThread::IsMain());
|
||||
// Is the request in progress?
|
||||
@@ -108,7 +119,7 @@ void ThumbnailThread::request(const ThumbnailRequestP& request) {
|
||||
}
|
||||
request_names.insert(request);
|
||||
// Is the image in the cache?
|
||||
String filename = image_cache_dir() + safeFilename(request->cache_name) + _(".png");
|
||||
String filename = image_cache_dir() + safe_filename(request->cache_name) + _(".png");
|
||||
wxFileName fn(filename);
|
||||
if (fn.FileExists()) {
|
||||
wxDateTime modified;
|
||||
@@ -152,14 +163,6 @@ bool ThumbnailThread::done(void* owner) {
|
||||
FOR_EACH(r, finished) {
|
||||
// store image
|
||||
r.first->store(r.second);
|
||||
// store in cache
|
||||
if (r.second.Ok()) {
|
||||
String filename = image_cache_dir() + safeFilename(r.first->cache_name) + _(".png");
|
||||
r.second.SaveFile(filename, wxBITMAP_TYPE_PNG);
|
||||
// set modification time
|
||||
wxFileName fn(filename);
|
||||
fn.SetTimes(0, &r.first->modified, 0);
|
||||
}
|
||||
// remove from name list
|
||||
request_names.erase(r.first);
|
||||
}
|
||||
|
||||
@@ -69,9 +69,6 @@ class ThumbnailThread {
|
||||
set<ThumbnailRequestP> request_names; ///< Requests that haven't been stored yet, to prevent duplicates
|
||||
friend class ThumbnailThreadWorker;
|
||||
ThumbnailThreadWorker* worker; ///< The worker thread. invariant: no requests ==> worker==nullptr
|
||||
|
||||
/// A name that is safe to use as a filename, for the cache
|
||||
static String safeFilename(const String& str);
|
||||
};
|
||||
|
||||
/// The global thumbnail generator thread
|
||||
|
||||
+114
-6
@@ -8,17 +8,66 @@
|
||||
|
||||
#include <gui/value/choice.hpp>
|
||||
#include <gui/util.hpp>
|
||||
#include <gui/thumbnail_thread.hpp>
|
||||
#include <data/action/value.hpp>
|
||||
#include <data/stylesheet.hpp>
|
||||
#include <script/image.hpp>
|
||||
|
||||
DECLARE_TYPEOF_COLLECTION(ChoiceField::ChoiceP);
|
||||
|
||||
// ----------------------------------------------------------------------------- : ChoiceThumbnailRequest
|
||||
|
||||
class ChoiceThumbnailRequest : public ThumbnailRequest {
|
||||
public:
|
||||
ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id);
|
||||
virtual Image generate();
|
||||
virtual void store(const Image&);
|
||||
private:
|
||||
int id;
|
||||
StyleSheetP stylesheet;
|
||||
};
|
||||
|
||||
ChoiceThumbnailRequest::ChoiceThumbnailRequest(ChoiceValueEditor* cve, int id)
|
||||
: ThumbnailRequest(
|
||||
cve,
|
||||
cve->viewer.stylesheet->name() + _("/") + cve->field().name + _("/") << id,
|
||||
cve->viewer.stylesheet->lastModified())
|
||||
, stylesheet(cve->viewer.stylesheet)
|
||||
, id(id)
|
||||
{}
|
||||
|
||||
Image ChoiceThumbnailRequest::generate() {
|
||||
ChoiceValueEditor& cve = *(ChoiceValueEditor*)owner;
|
||||
Context& ctx = cve.getSet().getContextForThumbnails(stylesheet);
|
||||
String name = cannocial_name_form(cve.field().choices->choiceName(id));
|
||||
ScriptableImage& img = cve.style().choice_images[name];
|
||||
return img.generate(ctx, *stylesheet, 16, 16, ASPECT_BORDER, true)->image;
|
||||
}
|
||||
|
||||
void ChoiceThumbnailRequest::store(const Image& img) {
|
||||
ChoiceValueEditor& cve = *(ChoiceValueEditor*)owner;
|
||||
wxImageList* il = cve.style().thumbnails;
|
||||
while (id > il->GetImageCount()) {
|
||||
il->Add(wxBitmap(16,16),*wxBLACK);
|
||||
}
|
||||
if (img.Ok()) {
|
||||
if (id == il->GetImageCount()) {
|
||||
il->Add(img);
|
||||
} else {
|
||||
il->Replace(id, img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- : DropDownChoiceList
|
||||
|
||||
DropDownChoiceList::DropDownChoiceList(Window* parent, bool is_submenu, ChoiceValueEditor& cve, ChoiceField::ChoiceP group)
|
||||
: DropDownList(parent, is_submenu, is_submenu ? nullptr : &cve)
|
||||
, group(group)
|
||||
, cve(cve)
|
||||
{}
|
||||
{
|
||||
icon_size.width = 16;
|
||||
}
|
||||
|
||||
size_t DropDownChoiceList::itemCount() const {
|
||||
return group->choices.size() + hasDefault();
|
||||
@@ -59,7 +108,20 @@ DropDownList* DropDownChoiceList::submenu(size_t item) const {
|
||||
}
|
||||
|
||||
void DropDownChoiceList::drawIcon(DC& dc, int x, int y, size_t item, bool selected) const {
|
||||
// TODO
|
||||
// imagelist to use
|
||||
wxImageList* il = cve.style().thumbnails;
|
||||
assert(il);
|
||||
// find the image for the item
|
||||
int image_id;
|
||||
if (isFieldDefault(item)) {
|
||||
image_id = default_id;
|
||||
} else {
|
||||
image_id = getChoice(item)->first_id;
|
||||
}
|
||||
// draw image
|
||||
if (image_id < il->GetImageCount()) {
|
||||
il->Draw(image_id, dc, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,11 +134,24 @@ void DropDownChoiceList::select(size_t item) {
|
||||
}
|
||||
}
|
||||
size_t DropDownChoiceList::selection() const {
|
||||
if (hasFieldDefault() && cve.value().value.isDefault()) {
|
||||
return 0;
|
||||
}
|
||||
size_t i = hasDefault();
|
||||
// we need thumbnail images soon
|
||||
const_cast<DropDownChoiceList*>(this)->generateThumbnailImages();
|
||||
// selected item
|
||||
int id = field().choices->choiceId(cve.value().value());
|
||||
// id of default item
|
||||
if (hasFieldDefault()) {
|
||||
if (cve.value().value.isDefault()) {
|
||||
// default is selected
|
||||
default_id = id;
|
||||
return 0;
|
||||
} else {
|
||||
// run default script to find out what the default choice would be
|
||||
String default_choice = *cve.field().default_script.invoke( cve.viewer.getContext() );
|
||||
default_id = group->choiceId(default_choice);
|
||||
}
|
||||
}
|
||||
// item corresponding to id
|
||||
size_t i = hasDefault();
|
||||
FOR_EACH(c, group->choices) {
|
||||
if (id >= c->first_id && id < c->lastId()) {
|
||||
return i;
|
||||
@@ -86,12 +161,45 @@ size_t DropDownChoiceList::selection() const {
|
||||
return NO_SELECTION;
|
||||
}
|
||||
|
||||
void DropDownChoiceList::generateThumbnailImages() {
|
||||
if (!isRoot()) return;
|
||||
if (!cve.style().thumbnails) {
|
||||
cve.style().thumbnails = new wxImageList(16,16);
|
||||
}
|
||||
int image_count = cve.style().thumbnails->GetImageCount();
|
||||
int end = group->lastId();
|
||||
Context& ctx = cve.viewer.getContext();
|
||||
for (int i = 0 ; i < end ; ++i) {
|
||||
String name = cannocial_name_form(group->choiceName(i));
|
||||
ScriptableImage& img = cve.style().choice_images[name];
|
||||
if (i >= image_count || !img.upToDate(ctx, cve.style().thumbnail_age)) {
|
||||
// TODO : handle the case where image i was previously skipped
|
||||
// request this thumbnail
|
||||
thumbnail_thread.request( new_shared2<ChoiceThumbnailRequest>(&cve, i) );
|
||||
}
|
||||
}
|
||||
cve.style().thumbnail_age.update();
|
||||
}
|
||||
|
||||
void DropDownChoiceList::onIdle(wxIdleEvent& ev) {
|
||||
if (!isRoot()) return;
|
||||
thumbnail_thread.done(&cve);
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(DropDownChoiceList, DropDownList)
|
||||
EVT_IDLE(DropDownChoiceList::onIdle)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ----------------------------------------------------------------------------- : ChoiceValueEditor
|
||||
|
||||
IMPLEMENT_VALUE_EDITOR(Choice)
|
||||
, drop_down(new DropDownChoiceList(&editor(), false, *this, field().choices))
|
||||
{}
|
||||
|
||||
ChoiceValueEditor::~ChoiceValueEditor() {
|
||||
thumbnail_thread.abort(this);
|
||||
}
|
||||
|
||||
void ChoiceValueEditor::onLeftDown(const RealPoint& pos, wxMouseEvent& ev) {
|
||||
drop_down->onMouseInParent(ev, style().popup_style == POPUP_DROPDOWN_IN_PLACE && !nativeLook());
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ DECLARE_POINTER_TYPE(DropDownList);
|
||||
class ChoiceValueEditor : public ChoiceValueViewer, public ValueEditor {
|
||||
public:
|
||||
DECLARE_VALUE_EDITOR(Choice);
|
||||
~ChoiceValueEditor();
|
||||
|
||||
// --------------------------------------------------- : Events
|
||||
virtual void onLeftDown(const RealPoint& pos, wxMouseEvent& ev);
|
||||
@@ -34,6 +35,7 @@ class ChoiceValueEditor : public ChoiceValueViewer, public ValueEditor {
|
||||
private:
|
||||
DropDownListP drop_down;
|
||||
friend class DropDownChoiceList;
|
||||
friend class ChoiceThumbnailRequest;
|
||||
/// Change the choice
|
||||
void change(const Defaultable<String>& c);
|
||||
};
|
||||
@@ -56,13 +58,17 @@ class DropDownChoiceList : public DropDownList {
|
||||
virtual size_t selection() const;
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE();
|
||||
|
||||
ChoiceValueEditor& cve;
|
||||
ChoiceField::ChoiceP group; ///< Group this menu shows
|
||||
mutable vector<DropDownListP> submenus;
|
||||
mutable int default_id; ///< Item id for the default item (if !hasFieldDefault()) this is undefined)
|
||||
|
||||
inline const ChoiceField& field() const { return cve.field(); }
|
||||
|
||||
inline bool hasFieldDefault() const { return group == field().choices && field().default_script; }
|
||||
inline bool isRoot() const { return group == field().choices; }
|
||||
inline bool hasFieldDefault() const { return isRoot() && field().default_script; }
|
||||
inline bool hasGroupDefault() const { return group->hasDefault(); }
|
||||
inline bool hasDefault() const { return hasFieldDefault() || hasGroupDefault(); }
|
||||
inline bool isFieldDefault(size_t item) const { return item == 0 && hasFieldDefault(); }
|
||||
@@ -71,6 +77,9 @@ class DropDownChoiceList : public DropDownList {
|
||||
|
||||
// Find an item in the group of choices
|
||||
ChoiceField::ChoiceP getChoice(size_t item) const;
|
||||
/// Start generating thumbnail images
|
||||
void generateThumbnailImages();
|
||||
void onIdle(wxIdleEvent&);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------- : EOF
|
||||
|
||||
@@ -51,6 +51,8 @@ class DataViewer : public SetView {
|
||||
Context& getContext() const;
|
||||
/// The rotation to use
|
||||
virtual Rotation getRotation() const;
|
||||
/// The card we are viewing
|
||||
inline CardP getCard() const { return card; }
|
||||
|
||||
// --------------------------------------------------- : Setting data
|
||||
|
||||
|
||||
@@ -46,6 +46,12 @@ ScriptImageP to_script_image(const ScriptValueP& value) {
|
||||
} else {
|
||||
throw ScriptError(_("Unable to load image '") + filename + _("' from '" + pkg->name() + _("'")));
|
||||
}
|
||||
} else if (value->type() == SCRIPT_NIL) {
|
||||
// error, return blank image
|
||||
Image i(1,1);
|
||||
i.InitAlpha();
|
||||
i.SetAlpha(0,0,0);
|
||||
return new_intrusive1<ScriptImage>(i);
|
||||
} else {
|
||||
throw ScriptError(_("Can not convert from '") + value->typeName() + _("' to image"));
|
||||
}
|
||||
@@ -129,6 +135,7 @@ ScriptImageP ScriptableImage::update(Context& ctx, Package& pkg, UInt width, UIn
|
||||
}
|
||||
|
||||
bool ScriptableImage::upToDate(Context& ctx, Age age) const {
|
||||
if (!script) return true;
|
||||
try {
|
||||
WITH_DYNAMIC_ARG(last_update_age, age.get());
|
||||
return script_image_up_to_date(script.invoke(ctx));
|
||||
|
||||
@@ -63,6 +63,13 @@ Context& SetScriptContext::getContext(const StyleSheetP& stylesheet) {
|
||||
ctx->setVariable(_("stylesheet"), toScript(stylesheet));
|
||||
ctx->setVariable(_("card"), set.cards.empty() ? script_nil : toScript(set.cards.front())); // dummy value
|
||||
ctx->setVariable(_("styling"), toScript(&set.stylingDataFor(*stylesheet)));
|
||||
try {
|
||||
// perform init scripts, don't use a scope, variables stay bound in the context
|
||||
set.game ->init_script.invoke(*ctx, false);
|
||||
stylesheet->init_script.invoke(*ctx, false);
|
||||
} catch (const Error& e) {
|
||||
handle_error(e, false, false);
|
||||
}
|
||||
onInit(stylesheet, ctx);
|
||||
return *ctx;
|
||||
}
|
||||
@@ -94,13 +101,10 @@ void SetScriptManager::onInit(const StyleSheetP& stylesheet, Context* ctx) {
|
||||
assert(wxThread::IsMain());
|
||||
// initialize dependencies
|
||||
try {
|
||||
// perform init scripts, don't use a scope, variables stay bound in the context
|
||||
set.game ->init_script.invoke(*ctx, false);
|
||||
stylesheet->init_script.invoke(*ctx, false);
|
||||
// find script dependencies
|
||||
initDependencies(*ctx, *set.game);
|
||||
initDependencies(*ctx, *stylesheet);
|
||||
} catch (Error e) {
|
||||
} catch (const Error& e) {
|
||||
handle_error(e, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,8 @@ class Package {
|
||||
virtual String fullName() const;
|
||||
/// Return the absolute filename of this file
|
||||
const String& absoluteFilename() const;
|
||||
/// The time this package was last modified
|
||||
inline wxDateTime lastModified() const { return modified; }
|
||||
|
||||
/// Get an input stream for the package icon, if there is any
|
||||
virtual InputStreamP openIconFile();
|
||||
|
||||
Reference in New Issue
Block a user