//+----------------------------------------------------------------------------+ //| Description: Magic Set Editor - Program to make card games | //| Copyright: (C) Twan van Laarhoven and the other MSE developers | //| License: GNU General Public License 2 or later (see file COPYING) | //+----------------------------------------------------------------------------+ #pragma once // ----------------------------------------------------------------------------- : Includes #include #include #include #include #include // for Set::value #include DECLARE_POINTER_TYPE(Card); DECLARE_POINTER_TYPE(Set); DECLARE_POINTER_TYPE(Game); DECLARE_POINTER_TYPE(StyleSheet); DECLARE_POINTER_TYPE(Styling); DECLARE_POINTER_TYPE(Field); DECLARE_POINTER_TYPE(Value); DECLARE_POINTER_TYPE(Keyword); DECLARE_POINTER_TYPE(PackType); DECLARE_POINTER_TYPE(ScriptValue); class SetScriptManager; class SetScriptContext; class Context; class Dependency; template class OrderCache; typedef intrusive_ptr> OrderCacheP; // ----------------------------------------------------------------------------- : Set /// A set of cards class Set : public Packaged { public: /// Create a set, the set should be open()ed later Set(); /// Create a set using the given game Set(const GameP& game); /// Create a set using the given stylesheet, and its game Set(const StyleSheetP& stylesheet); ~Set(); GameP game; ///< The game this set uses StyleSheetP stylesheet; ///< The default stylesheet /// The values on the fields of the set /** The indices should correspond to the set_fields in the Game */ IndexMap data; /// Extra values for specific stylesheets, indexed by stylesheet name DelayedIndexMaps styling_data; vector cards; ///< The cards in the set unordered_map card_uids; ///< The uids of the cards in the set vector keywords; ///< Additional keywords used in this set vector pack_types; ///< Additional/replacement pack types String apprentice_code; ///< Code to use for apprentice (magic only) ActionStack actions; ///< Actions performed on this set and the cards in it KeywordDatabase keyword_db; ///< Database for matching keywords, must be cleared when keywords change VCSP vcs; ///< The version control system to use /// What version of the game was this set using when it was last saved? Version game_version; /// What version of the default stylesheet was this set using when it was last saved? Version stylesheet_version; /// A context for performing scripts /** Should only be used from the main thread! */ Context& getContext(); /// A context for performing scripts on a particular card /** Should only be used from the main thread! */ Context& getContext(const CardP& card); /// Update styles and extra_card_fields for a card void updateStyles(const CardP& card, bool only_content_dependent); /// Update scripts that were delayed void updateDelayed(); /// Update uid map void buildUIDMap(); /// A context for performing scripts /** Should only be used from the thumbnail thread! */ Context& getContextForThumbnails(); /// 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 */ const StyleSheet& stylesheetFor (const CardP& card); StyleSheetP stylesheetForP(const CardP& card); /// Styling information for a particular stylesheet IndexMap& stylingDataFor(const StyleSheet&); /// Styling information for a particular card IndexMap& stylingDataFor(const CardP& card); /// Make sure the image and symbol files from /// the ActionStack are saved so we can undo void referenceActionStackFiles(); void referenceActionStackFiles(bool undo); /// Get the identification of this set, an identification is something like a name, title, etc. /** May return "" */ String identification() const; /// Find a value in the data by name and type template T& value(const String& name) { for(IndexMap::iterator it = data.begin() ; it != data.end() ; ++it) { if ((*it)->fieldP->name == name) { T* ret = dynamic_cast(it->get()); if (!ret) throw InternalError(_("Set field with name '")+name+_("' doesn't have the right type")); return *ret; } } throw InternalError(_("Expected a set field with name '")+name+_("'")); } /// Find the position of a card in this set, when the card list is sorted using the given cirterium int positionOfCard(const CardP& card, const ScriptValueP& order_by, const ScriptValueP& filter); /// Find the number of cards that match the given filter int numberOfCards(const ScriptValueP& filter); /// Clear the order_cache used by positionOfCard void clearOrderCache(); String typeName() const override; Version fileVersion() const override; /// Validate that the set is correctly loaded void validate(Version = app_version) override; protected: VCSP getVCS() override { return vcs; } private: DECLARE_REFLECTION_OVERRIDE(); template void reflect_cards(Handler& handler); /// Object for managing and executing scripts unique_ptr script_manager; /// Object for executing scripts from the thumbnail thread unique_ptr thumbnail_script_context; /// Cache of cards ordered by some criterion map,OrderCacheP> order_cache; map filter_cache; }; inline String type_name(const Set&) { return _TYPE_("set"); } inline int item_count(const Set& set) { return (int)set.cards.size(); } ScriptValueP make_iterator(const Set& set); void mark_dependency_member(const Set& set, const String& name, const Dependency& dep); // ----------------------------------------------------------------------------- : SetView /// A 'view' of a Set, is notified when the Set is updated /** To listen to events, derived classes should override onAction(const Action&, bool undone) */ class SetView : public ActionListener { public: SetView(); ~SetView(); /// Get the set that is currently being viewed inline SetP getSet() const { return set; } /// Change the set that is being viewed void setSet(const SetP& set); protected: /// The set that is currently being viewed, should not be modified directly! SetP set; /// Called when another set is being viewed (using setSet) virtual void onChangeSet() {} /// Called when just before another set is being viewed (using setSet) virtual void onBeforeChangeSet() {} };