1 #pragma once 2 3 #ifndef TXSHSIMPLELEVEL_INCLUDED 4 #define TXSHSIMPLELEVEL_INCLUDED 5 6 #include <memory> 7 8 // TnzLib includes 9 #include "toonz/txshlevel.h" 10 #include "toonz/txshleveltypes.h" 11 #include "toonz/imagemanager.h" 12 13 // TnzCore includes 14 #include "traster.h" 15 #include "trasterimage.h" 16 17 // Qt includes 18 #include <QObject> 19 #include <QStringList> 20 21 // boost includes 22 #include <boost/container/flat_set.hpp> 23 #include <boost/container/flat_map.hpp> 24 25 // STD includes 26 #include <set> 27 28 #undef DVAPI 29 #undef DVVAR 30 #ifdef TOONZLIB_EXPORTS 31 #define DVAPI DV_EXPORT_API 32 #define DVVAR DV_EXPORT_VAR 33 #else 34 #define DVAPI DV_IMPORT_API 35 #define DVVAR DV_IMPORT_VAR 36 #endif 37 38 //=================================================================== 39 40 // Forward declarations 41 42 class ImageBuilder; 43 class LevelProperties; 44 class TPalette; 45 class TContentHistory; 46 47 //=================================================================== 48 49 //************************************************************************************************* 50 // TXshSimpleLevel declaration 51 //************************************************************************************************* 52 53 /*! 54 \brief The \p TXshLevel specialization for image levels. 55 56 \todo Substitute m_frames with a sorted vector or 57 a boost flat_set. 58 */ 59 60 class DVAPI TXshSimpleLevel final : public TXshLevel { 61 Q_OBJECT 62 63 PERSIST_DECLARATION(TXshSimpleLevel) 64 DECLARE_CLASS_CODE 65 66 public: 67 /*! \details Level frames may have special properties depending on 68 the level type they are part of. 69 70 \sa \p TXshSimpleLevel::getFrameStatus() and 71 \p setFrameStatus() for further details. */ 72 73 enum FrameStatusBit //! Describes a level's frame status. 74 { Normal = 0x0, //!< Frame has no special status. 75 Scanned = 0x1, //!< A fullcolor frame (only tlv levels). 76 Cleanupped = 0x2, //!< A cleanupped frame (only tlv levels). 77 CleanupPreview = 0x4 //!< A cleanup preview (only fullcolor levels). 78 }; 79 80 public: 81 static bool 82 m_rasterizePli; //!< \internal Not the proper place for this data. 83 static bool m_fillFullColorRaster; //!< \internal Not the proper place for 84 //! this data. 85 86 public: 87 TXshSimpleLevel( 88 const std::wstring &name = 89 std::wstring()); //!< Constructs a TXshSimpleLevel with a name 90 ~TXshSimpleLevel(); 91 getSimpleLevel()92 TXshSimpleLevel *getSimpleLevel() override { 93 return this; 94 } //!< Reimplemented for TXshLevel. 95 isSubsequence()96 bool isSubsequence() const { return m_isSubsequence; } 97 is16BitChannelLevel()98 bool is16BitChannelLevel() const { 99 return getType() == OVL_XSHLEVEL && m_16BitChannelLevel; 100 } set16BitChannelLevel(bool value)101 void set16BitChannelLevel(bool value) { 102 m_16BitChannelLevel = (value && getType() == OVL_XSHLEVEL); 103 } 104 isReadOnly()105 bool isReadOnly() const { return m_isReadOnly; } setIsReadOnly(bool value)106 void setIsReadOnly(bool value) { m_isReadOnly = value; } 107 void updateReadOnly(); 108 getProperties()109 LevelProperties *getProperties() 110 const //!< Returns a pointer to the \a owned level properties. 111 { 112 return m_properties.get(); 113 } 114 void clonePropertiesFrom(const TXshSimpleLevel *oldSl); 115 116 TPalette *getPalette() 117 const; //!< Returns a pointer to the \a shared level palette. 118 void setPalette(TPalette *palette); //!< Assigns a palette to the level. 119 getPath()120 TFilePath getPath() const override { return m_path; } 121 void setPath(const TFilePath &path, bool retainCachedImages = false); 122 getScannedPath()123 TFilePath getScannedPath() const { return m_scannedPath; } 124 void setScannedPath(const TFilePath &path); 125 126 /*! \details Each level frame have a corresponding image retrievable 127 with the getFrame() method and similar. 128 129 \remark Consider using functions getFrameCount() and getFrameId() 130 to avoid a container copy. */ 131 132 std::vector<TFrameId> getFids() 133 const; //!< Returns a copy of the level's frame ids. 134 void getFids( 135 std::vector<TFrameId> &fids) const override; //!< Copies fids() into 136 //! fids. \deprecated Use 137 //! the return valued 138 //! variation instead. 139 140 TFrameId getFirstFid() 141 const; //!< Returns the first level frame's id; roughly equivalent to 142 //! <TT>index2fid(0)</TT>. 143 TFrameId getLastFid() 144 const; //!< Returns the last level frame's id; roughly equivalent to 145 //! <TT>index2fid(getFrameCount()-1)</TT>. 146 isEmpty()147 bool isEmpty() const override { 148 return m_frames.empty(); 149 } //!< Returns whether the level is empty. 150 bool isFid(const TFrameId &fid) 151 const; //!< Returns whether a given frameId is in the level. 152 153 /*! \details Unlike function index2fid(), getFrameId() \a asserts 154 beyond current frames count. */ 155 156 const TFrameId &getFrameId( 157 int index) const; //!< Returns the frame id at specified index. getFrameCount()158 int getFrameCount() const override { 159 return m_frames.size(); 160 } //!< Returns the level's frames count. 161 162 /*! \details Function index2fid() attempts guessing frame ids for 163 frame indexes beyond current frames count. See function 164 guessStep() for further details. */ 165 166 TFrameId index2fid(int index) const; //!< Returns a frame id corresponding to 167 //! the specified frame index, or 168 //! an invalid frame otherwise. 169 int fid2index(const TFrameId &fid) const; //!< Returns the frame \a index 170 //! corresponding to the specified 171 //! frame id, 172 //! or \p -1 if not found. 173 174 /* 175 if the table contains 'fid' it returns fid2index(fid). 176 if fid is greater than the last fid in the table, it returns a "guessed" index. 177 e.g. if fids = [1,3,5,7] then fid2index(11) == 5 178 if fid is smaller than the last fid in the table (and is not contained in the 179 table) it returns the proper insertion index 180 */ 181 int guessIndex(const TFrameId &fid) const; 182 183 //! Analyzes the level's frames table and returns the alleged entries \a step 184 //! - ie the distance 185 //! from each entry to the next. 186 int guessStep() const; 187 188 void setFrame(const TFrameId &fid, const TImageP &img); 189 190 TImageP getFrame(const TFrameId &fid, UCHAR imgManagerParamsMask, 191 int subsampling) const; getFrame(const TFrameId & fid,bool toBeModified)192 TImageP getFrame(const TFrameId &fid, bool toBeModified) const { 193 return getFrame( 194 fid, toBeModified ? ImageManager::toBeModified : ImageManager::none, 0); 195 } 196 TImageP getFullsampledFrame(const TFrameId &fid, 197 UCHAR imgManagerParamsMask) const; 198 199 TImageInfo *getFrameInfo(const TFrameId &fid, bool toBeModified); 200 TImageP getFrameIcon(const TFrameId &fid) const; 201 202 // load icon (and image) data of all frames into cache 203 void loadAllIconsAndPutInCache(bool cacheImagesAsWell); 204 205 TRasterImageP getFrameToCleanup(const TFrameId &fid) const; 206 207 std::string getImageId(const TFrameId &fid, int frameStatus = -1) const; 208 std::string getIconId(const TFrameId &fid, int frameStatus = -1) const; 209 std::string getIconId(const TFrameId &fid, const TDimension &size) const; 210 211 void eraseFrame(const TFrameId &fid); 212 void clearFrames(); 213 void invalidateFrames(); 214 215 void invalidateFrame(const TFrameId &fid); 216 217 /*! 218 Set the range of frame that can be edited and saved. 219 Editable range is contained in \b m_editableRange. 220 */ 221 void setEditableRange(unsigned int from, unsigned int to, 222 const std::wstring &userName); 223 void mergeTemporaryHookFile(unsigned int from, unsigned int to, 224 const TFilePath &hookFile); 225 void clearEditableRange(); 226 std::wstring getEditableFileName(); 227 228 std::set<TFrameId> 229 getEditableRange(); //!< Returns the set of editable frames. 230 231 int getFrameStatus(const TFrameId &fid) const; 232 void setFrameStatus(const TFrameId &fid, int status); 233 234 /*! \details This function will implicitly convert the input path 235 extension to a correctly formatted \a tlv. Behavior 236 is undefined in case the level is not of fullcolor type. 237 238 \deprecated Function is obviously an implementation detail of the 239 cleanup process. Should be moved there. */ 240 241 void makeTlv(const TFilePath &tlvPath); //!< Transforms the level from \a 242 //! fullcolor to tlv (colormap), 243 //! and assigns the specified level path. 244 TImageP createEmptyFrame(); 245 246 void initializePalette(); 247 void initializeResolutionAndDpi(const TDimension &dim = TDimension(), 248 double dpi = 0); 249 250 TDimension getResolution(); 251 252 TPointD getImageDpi(const TFrameId &fid = TFrameId::NO_FRAME, 253 int frameStatus = -1); 254 int getImageSubsampling(const TFrameId &fid) const; 255 TPointD getDpi(const TFrameId &fid = TFrameId::NO_FRAME, 256 int frameStatus = -1); 257 258 /*! \brief Returns the bbox for the level's fid, specified in standard 259 \a inch coordinates (which are \a different from Toonz's 260 standard world coordinates, by a \p Stage::inch factor). */ 261 262 TRectD getBBox(const TFrameId &fid) const; 263 264 void setDirtyFlag(bool on) override; 265 bool getDirtyFlag() const; 266 267 //! Updates content history (invokes setDirtyFlag(true)) 268 //! \warning Not what users may expect! 269 void touchFrame(const TFrameId &fid); 270 271 void loadData(TIStream &is) override; 272 void saveData(TOStream &os) override; 273 274 //! Loads the level from disk, translating encoded level paths relative 275 //! to the level's scene path. 276 void load() override; 277 void load(const std::vector<TFrameId> &fIds); 278 279 //! Saves the level to disk, with the same path deduction from load() 280 void save() override; 281 282 /*! 283 Save the level in the specified fp. 284 The oldFp is used when the current scene path change... 285 */ 286 void save(const TFilePath &fp, const TFilePath &oldFp = TFilePath(), 287 bool overwritePalette = true); 288 289 //! note gets the contentHistory. can be 0 getContentHistory()290 const TContentHistory *getContentHistory() const { 291 return m_contentHistory.get(); 292 } getContentHistory()293 TContentHistory *getContentHistory() { return m_contentHistory.get(); } 294 295 //! destroys the old contentHistory and replaces it with the new one. Gets 296 //! ownership 297 void setContentHistory(TContentHistory *contentHistory); 298 299 //! Set elements of m_renumberTable with m_frames. 300 void setRenumberTable(); renumberTable()301 const std::map<TFrameId, TFrameId> &renumberTable() const { 302 return m_renumberTable; 303 } 304 305 //! Renumbers the level frames to the specified fids (fids and this->fids() 306 //! must have the same size). 307 void renumber(const std::vector<TFrameId> &fids); 308 309 bool isFrameReadOnly(TFrameId fid); 310 311 public: 312 // Auxiliary files management: hooks, tpl, etc. 313 // May throw; copy and rename perform touchparentdir 314 315 static void copyFiles(const TFilePath &dst, 316 const TFilePath &src); //!< Copy files from src to dst. 317 static void renameFiles( 318 const TFilePath &dst, 319 const TFilePath &src); //!< Rename files from src to dst. 320 static void removeFiles(const TFilePath &fp); //!< Remove files at fp. 321 322 //! Get the auxiliary files list: hooks, tpl, etc. 323 static void getFiles(const TFilePath &fp, TFilePathSet &fpset); 324 325 /*! 326 Translates a level path into the corresponding hook path (no check for 327 the existence of said hook file). 328 */ 329 static TFilePath getHookPath(const TFilePath &levelPath); 330 331 /*! 332 \brief Returns the list of \a existing hook files associated to the 333 specified level, sorted by modification date (last modified at front). 334 The list stores <I>local paths<\I> relative to 335 decodedLevelPath.getParentDir(). 336 337 \note A level may have multiple hook files if the hook set was edited 338 with older Toonz versions. Use this function if you need to access all 339 of them. Only the latest file format is considered when loading a level. 340 */ 341 static QStringList getHookFiles(const TFilePath &decodedLevelPath); 342 343 /*! 344 \brief Returns the path of the newest \a existing hook file associated to the 345 specified \b decoded level path - or an empty path if none was found. 346 347 \note In case there are more than one hook file (ie files from older 348 Toonz version), the latest file version is used. 349 */ 350 static TFilePath getExistingHookFile(const TFilePath &decodedLevelPath); 351 352 static void setCompatibilityMasks(int writeMask, int neededMask, 353 int forbiddenMask); 354 355 public Q_SLOTS: 356 357 void onPaletteChanged(); //!< Invoked when some colorstyle has been changed 358 359 private: 360 typedef boost::container::flat_set<TFrameId> FramesSet; 361 362 private: 363 std::unique_ptr<LevelProperties> m_properties; 364 std::unique_ptr<TContentHistory> m_contentHistory; 365 366 TPalette *m_palette; 367 368 FramesSet m_frames; 369 370 std::map<TFrameId, TFrameId> 371 m_renumberTable; //!< Maps disk-frames to level-frames. 372 //! Typically, the 2 match - however, the situation changes 373 //! after an explicit frame renumbering process. In case 374 //! a level-frame is deleted, the table entry is removed; 375 //! it will be physically removed only when the level is saved. 376 //! A similar thing happens with newly inserted frames. 377 std::map<TFrameId, int> m_framesStatus; 378 379 std::set<TFrameId> m_editableRange; 380 381 TFilePath m_path, m_scannedPath; 382 383 std::string m_idBase; 384 std::wstring m_editableRangeUserInfo; 385 386 bool m_isSubsequence, m_16BitChannelLevel, m_isReadOnly, 387 m_temporaryHookMerged; //!< Used only during hook merge (and hence during 388 //! saving) 389 390 private: 391 //! Save simple level in scene-decoded path \p decodedFp. 392 void saveSimpleLevel( 393 const TFilePath &decodedFp, 394 bool overwritePalette = true); // Difference from save(..)? 395 396 private: 397 // Not copyable 398 TXshSimpleLevel(const TXshSimpleLevel &); 399 TXshSimpleLevel &operator=(const TXshSimpleLevel &); 400 }; 401 402 //===================================================================================== 403 404 #ifdef _WIN32 405 template class DV_EXPORT_API TSmartPointerT<TXshSimpleLevel>; 406 #endif 407 typedef TSmartPointerT<TXshSimpleLevel> TXshSimpleLevelP; 408 409 //===================================================================================== 410 411 void DVAPI setLoadingLevelRange(const TFrameId &fromFid, const TFrameId &toFid); 412 void DVAPI getLoadingLevelRange(TFrameId &fromFid, TFrameId &toFid); 413 414 #endif // TXSHSIMPLELEVEL_INCLUDED 415