void AbstractResourceItem::validateItem() { if (_state == ResourceState::FILE_ERROR || _state == ResourceState::NOT_LOADED) { return; } ErrorList err; // check dependencies bool dependenciesOk = true; for (auto& dep : _dependencies) { AbstractResourceItem* dItem = _project->findResourceItem(dep.type, dep.name); if (dItem == nullptr) { if (auto* rl = _project->findResourceList(dep.type)) { QString rtn = rl->resourceTypeNameSingle(); err.addError("Dependency Error: Missing " + rtn.toStdString() + u8" · " + dep.name.toStdString()); } else { err.addError("Dependency Error: Missing " + dep.name.toStdString()); } dependenciesOk = false; } else if (dItem->state() != ResourceState::VALID) { QString rtn = dItem->resourceList()->resourceTypeNameSingle(); err.addError("Dependency Error: " + rtn.toStdString() + u8" · " + dep.name.toStdString()); dependenciesOk = false; } } if (dependenciesOk) { try { bool s = compileResource(err); setState(s ? ResourceState::VALID : ResourceState::ERROR); } catch (const std::exception& ex) { err.addError(std::string("EXCEPTION: ") + ex.what()); setState(ResourceState::ERROR); } _errorList = std::move(err); emit errorListChanged(); emit resourceComplied(); } else { _errorList = std::move(err); emit errorListChanged(); setState(ResourceState::DEPENDENCY_ERROR); } }
ActionPointMapping MetaSprite::generateActionPointMapping(const NamedList<ActionPointFunction>& apFunctions, ErrorList& err) { bool valid = true; auto addError = [&](const std::string msg) { err.addError(std::move(msg)); valid = false; }; auto addApfError = [&](const ActionPointFunction& apf, const std::string msg) { err.addError(std::make_unique<ListItemError>(&apf, std::move(msg))); valid = false; }; ActionPointMapping ret; if (apFunctions.empty()) { addError("Expected at least one action point function"); return ret; } if (apFunctions.size() > MAX_ACTION_POINT_FUNCTIONS) { addError("Too many action point functions (max " + std::to_string(MAX_ACTION_POINT_FUNCTIONS) + ")"); return ret; } ret.reserve(apFunctions.size()); for (unsigned i = 0; i < apFunctions.size(); i++) { const unsigned romValue = (i + 1) * 2; assert(romValue <= 255 - 2); const ActionPointFunction& apf = apFunctions.at(i); if (not apf.name.isValid()) { addApfError(apf, "Missing action point function name"); } auto success = ret.emplace(apf.name, romValue); if (success.second == false) { addApfError(apf, "Action point function name already exists: " + apf.name); } } if (not valid) { ret.clear(); } return ret; }
bool AnimationFramesInput::validate(ErrorList& err) const { bool valid = true; if (bitDepth != 2 && bitDepth != 4 && bitDepth != 8) { err.addError("Invalid bit-depth, expected 2, 4 or 8"); valid = false; } if (frameImageFilenames.empty()) { err.addError("Missing frame image"); valid = false; } std::vector<usize> imageSizes(frameImageFilenames.size()); for (unsigned i = 0; i < frameImageFilenames.size(); i++) { const auto& imageFilename = frameImageFilenames.at(i); const auto& image = ImageCache::loadPngImage(imageFilename); imageSizes.at(i) = image->size(); if (image->empty()) { err.addError("Missing frame image: " + image->errorString()); valid = false; break; } if (image->size().width % 8 != 0 || image->size().height % 8 != 0) { err.addError("image size invalid (height and width must be a multiple of 8): " + imageFilename); valid = false; } } if (valid) { for (const usize& imgSize : imageSizes) { if (imgSize != imageSizes.front()) { err.addError("All frame images must be the same size"); valid = false; break; } } } return valid; }
static bool _testFrameSet(const FrameSetExportOrder& eo, const FrameSetT& frameSet, ErrorList& errorList) { bool valid = true; for (auto& en : eo.stillFrames) { if (en.frameExists(frameSet.frames) == false) { errorList.addError("Cannot find frame " + en.name); valid = false; } } for (auto& en : eo.animations) { if (en.animationExists(frameSet.animations) == false) { errorList.addError("Cannot find animation " + en.name); valid = false; } } return valid; }
bool Animation::_validate(const FrameSetT& frameSet, ErrorList& err) const { const unsigned oldErrorCount = err.errorCount(); if (oneShot == false && nextAnimation.isValid()) { if (!frameSet.animations.find(nextAnimation)) { err.addError(animationError(*this, "Cannot find animation " + nextAnimation)); } } if (frames.size() == 0) { err.addError(animationError(*this, "Expected at least one animation frame")); } for (unsigned i = 0; i < frames.size(); i++) { const AnimationFrame& aFrame = frames.at(i); if (aFrame.testFrameValid(frameSet) == false) { err.addError(animationFrameError(*this, i, "Cannot find frame " + aFrame.frame.name)); } } return err.errorCount() == oldErrorCount; }
void AbstractResourceItem::loadResource() { Q_ASSERT(_undoStack->count() == 0); ErrorList err; try { bool s = loadResourceData(err); setState(s ? ResourceState::UNCHECKED : ResourceState::FILE_ERROR); } catch (const std::exception& ex) { err.addError(std::string("EXCEPTION: ") + ex.what()); setState(ResourceState::FILE_ERROR); } _errorList = std::move(err); emit resourceLoaded(); emit errorListChanged(); }
static std::vector<std::vector<FrameTile>> tilesFromFrameImages(const AnimationFramesInput input, const std::vector<Snes::SnesColor>& palettes, ErrorList& err) { const unsigned colorsPerPalette = 1 << input.bitDepth; std::vector<std::vector<FrameTile>> frameTiles; frameTiles.reserve(input.frameImageFilenames.size()); const unsigned nFrames = input.frameImageFilenames.size(); for (unsigned frameId = 0; frameId < nFrames; frameId++) { auto imageErr = std::make_unique<InvalidImageError>(frameId); const auto& image = ImageCache::loadPngImage(input.frameImageFilenames.at(frameId)); frameTiles.emplace_back( tilesFromFrameImage(*image, palettes, colorsPerPalette, *imageErr)); if (imageErr->hasError()) { err.addError(std::move(imageErr)); } } return frameTiles; }
static AnimatedTilesetIntermediate combineFrameTiles(const std::vector<std::vector<FrameTile>>& frameTiles, unsigned tileWidth, ErrorList& err) { assert(!frameTiles.empty()); const unsigned nTiles = frameTiles.front().size(); for (const auto& tf : frameTiles) { assert(tf.size() == nTiles); } auto getTile = [&](unsigned frameId, unsigned tileId) -> const Tile8px& { return frameTiles.at(frameId).at(tileId).tile; }; auto getPalette = [&](unsigned frameId, unsigned tileId) -> unsigned { return frameTiles.at(frameId).at(tileId).palette; }; const unsigned nFrames = frameTiles.size(); auto imageErr = std::make_unique<InvalidImageError>(); AnimatedTilesetIntermediate ret; ret.animatedTiles.reserve(64); ret.tileMap.resize(nTiles); for (unsigned tileId = 0; tileId < nTiles; tileId++) { const static unsigned TS = Tile8px::TILE_SIZE; auto& tm = ret.tileMap.at(tileId); unsigned palette = getPalette(0, tileId); for (unsigned frameId = 1; frameId < nFrames; frameId++) { if (getPalette(frameId, tileId) != palette) { imageErr->addInvalidTile(TS, (tileId % tileWidth) * TS, (tileId / tileWidth) * TS, InvalidImageError::NOT_SAME_PALETTE); break; } } tm.palette = palette; const Tile8px& firstTile = getTile(0, tileId); bool isAnimated = false; for (unsigned frameId = 1; frameId < nFrames; frameId++) { if (getTile(frameId, tileId) != firstTile) { isAnimated = true; break; } } tm.isAnimated = isAnimated; if (isAnimated == false) { tm.tile = ret.staticTiles.size(); ret.staticTiles.emplace_back(firstTile); } else { tm.tile = ret.animatedTiles.size(); ret.animatedTiles.emplace_back(nFrames); auto& animatedTile = ret.animatedTiles.back(); for (unsigned frameId = 0; frameId < nFrames; frameId++) { animatedTile.at(frameId) = getTile(frameId, tileId); } } } if (imageErr->hasError()) { err.addError(std::move(imageErr)); } return ret; }