| |
| |
|
|
| #include "tsystem.h" |
| #include "tstream.h" |
| #include "tthreadmessage.h" |
| #include "tconvert.h" |
| #include "tstopwatch.h" |
| #include "tlevel_io.h" |
| #include "tflash.h" |
| #include "trasterimage.h" |
| #include "ttoonzimage.h" |
| #include "tvectorimage.h" |
| #include "timagecache.h" |
| #include "timageinfo.h" |
| #include "tropcm.h" |
| #include "tofflinegl.h" |
| #include "tvectorrenderdata.h" |
| |
| |
| #include "ttzpimagefx.h" |
| #include "trasterfx.h" |
| #include "tzeraryfx.h" |
| #include "trenderer.h" |
| #include "tfxcachemanager.h" |
| |
| |
| #include "toonz/toonzscene.h" |
| #include "toonz/txsheet.h" |
| #include "toonz/txshlevelcolumn.h" |
| #include "toonz/txshpalettecolumn.h" |
| #include "toonz/txshzeraryfxcolumn.h" |
| #include "toonz/txshlevel.h" |
| #include "toonz/txshcell.h" |
| #include "toonz/txshsimplelevel.h" |
| #include "toonz/txshpalettelevel.h" |
| #include "toonz/txshleveltypes.h" |
| #include "toonz/levelset.h" |
| #include "toonz/txshchildlevel.h" |
| #include "toonz/fxdag.h" |
| #include "toonz/tcolumnfxset.h" |
| #include "toonz/stage.h" |
| #include "toonz/fill.h" |
| #include "toonz/tstageobjectid.h" |
| #include "toonz/tstageobject.h" |
| #include "toonz/levelproperties.h" |
| #include "toonz/imagemanager.h" |
| #include "toonz/toonzimageutils.h" |
| #include "toonz/tvectorimageutils.h" |
| #include "toonz/preferences.h" |
| #include "toonz/dpiscale.h" |
| #include "imagebuilders.h" |
| |
| |
| #include "toonz4.6/raster.h" |
| #include "sandor_fxs/blend.h" |
| extern "C" { |
| #include "sandor_fxs/calligraph.h" |
| #include "sandor_fxs/patternmap.h" |
| } |
| |
| #include "toonz/tcolumnfx.h" |
| |
| |
| |
| |
| |
| #ifdef WIN32 |
| template class DV_EXPORT_API TFxDeclarationT<TLevelColumnFx>; |
| template class DV_EXPORT_API TFxDeclarationT<TZeraryColumnFx>; |
| template class DV_EXPORT_API TFxDeclarationT<TXsheetFx>; |
| template class DV_EXPORT_API TFxDeclarationT<TOutputFx>; |
| #endif |
| |
| TFxDeclarationT<TLevelColumnFx> columnFxInfo(TFxInfo("Toonz_columnFx", true)); |
| TFxDeclarationT<TPaletteColumnFx> paletteColumnFxInfo(TFxInfo("Toonz_paletteColumnFx", true)); |
| TFxDeclarationT<TZeraryColumnFx> zeraryColumnFxInfo(TFxInfo("Toonz_zeraryColumnFx", true)); |
| TFxDeclarationT<TXsheetFx> infoTXsheetFx(TFxInfo("Toonz_xsheetFx", true)); |
| TFxDeclarationT<TOutputFx> infoTOutputFx(TFxInfo("Toonz_outputFx", true)); |
| |
| |
| |
| |
| |
| namespace |
| { |
| |
| void setMaxMatte(TRasterP r) |
| { |
| TRaster32P r32 = (TRaster32P)r; |
| |
| TRaster64P r64 = (TRaster64P)r; |
| |
| if (r32) |
| for (int i = 0; i < r32->getLy(); i++) { |
| TPixel *pix = r32->pixels(i); |
| for (int j = 0; j < r32->getLx(); j++, pix++) |
| pix->m = 255; |
| } |
| else if (r64) |
| for (int i = 0; i < r64->getLy(); i++) { |
| TPixel64 *pix = r64->pixels(i); |
| for (int j = 0; j < r64->getLx(); j++, pix++) |
| pix->m = 65535; |
| } |
| } |
| |
| |
| |
| char *strsave(const char *t) |
| { |
| char *s; |
| s = (char *)malloc(strlen(t) + 1); |
| strcpy(s, t); |
| return s; |
| } |
| |
| |
| |
| inline TRect myConvert(const TRectD &r) |
| { |
| return TRect(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1)); |
| } |
| |
| |
| |
| inline TRect myConvert(const TRectD &r, TPointD &dp) |
| { |
| TRect ri(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1)); |
| dp.x = r.x0 - ri.x0; |
| dp.y = r.y0 - ri.y0; |
| assert(dp.x >= 0 && dp.y >= 0); |
| return ri; |
| } |
| |
| |
| |
| |
| inline QString traduce(const TRectD &rect) |
| { |
| return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " + |
| QString::number(rect.x1) + " " + QString::number(rect.y1) + "]"; |
| } |
| |
| |
| |
| |
| inline QString traduce(const TRectD &rect, const TRenderSettings &info) |
| { |
| return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " + |
| QString::number(rect.x1) + " " + QString::number(rect.y1) + "]; aff = (" + |
| QString::number(info.m_affine.a11, 'f') + " " + |
| QString::number(info.m_affine.a12, 'f') + " " + |
| QString::number(info.m_affine.a13, 'f') + " " + |
| QString::number(info.m_affine.a21, 'f') + " " + |
| QString::number(info.m_affine.a22, 'f') + " " + |
| QString::number(info.m_affine.a23, 'f') + ")"; |
| } |
| |
| |
| |
| inline int colorDistance(const TPixel32 &c0, const TPixel32 &c1) |
| { |
| return (c0.r - c1.r) * (c0.r - c1.r) + (c0.g - c1.g) * (c0.g - c1.g) + (c0.b - c1.b) * (c0.b - c1.b); |
| } |
| |
| |
| |
| std::string getAlias(TXsheet *xsh, double frame, const TRenderSettings &info) |
| { |
| TFxSet *fxs = xsh->getFxDag()->getTerminalFxs(); |
| std::string alias; |
| |
| |
| for (int i = 0; i < fxs->getFxCount(); ++i) { |
| TRasterFx *fx = dynamic_cast<TRasterFx *>(fxs->getFx(i)); |
| assert(fx); |
| if (!fx) |
| continue; |
| |
| alias += fx->getAlias(frame, info) + ";"; |
| } |
| |
| return alias; |
| } |
| |
| } |
| |
| |
| |
| |
| |
| bool vectorMustApplyCmappedFx(const vector<TRasterFxRenderDataP> &fxs) |
| { |
| std::vector<TRasterFxRenderDataP>::const_iterator ft, fEnd(fxs.end()); |
| for (ft = fxs.begin(); ft != fEnd; ++ft) { |
| PaletteFilterFxRenderData *paletteFilterData = dynamic_cast<PaletteFilterFxRenderData *>(ft->getPointer()); |
| SandorFxRenderData *sandorData = dynamic_cast<SandorFxRenderData *>(ft->getPointer()); |
| |
| |
| |
| |
| if (sandorData || (paletteFilterData && paletteFilterData->m_type != ::eApplyToInksAndPaints)) |
| return true; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| } |
| |
| return false; |
| } |
| |
| |
| |
| bool mustApplySandorFx(const vector<TRasterFxRenderDataP> &fxs) |
| { |
| std::vector<TRasterFxRenderDataP>::const_iterator ft, fEnd(fxs.end()); |
| for (ft = fxs.begin(); ft != fEnd; ++ft) { |
| SandorFxRenderData *sandorData = dynamic_cast<SandorFxRenderData *>(ft->getPointer()); |
| |
| if (sandorData) |
| return true; |
| } |
| return false; |
| } |
| |
| |
| |
| int getEnlargement(const vector<TRasterFxRenderDataP> &fxs, double scale) |
| { |
| int enlargement = 1; |
| |
| std::vector<TRasterFxRenderDataP>::const_iterator ft, fEnd(fxs.end()); |
| for (ft = fxs.begin(); ft != fEnd; ++ft) { |
| SandorFxRenderData *sandorData = dynamic_cast<SandorFxRenderData *>(ft->getPointer()); |
| |
| if (sandorData) { |
| switch (sandorData->m_type) { |
| case BlendTz: { |
| |
| |
| vector<string> items; |
| string indexes = std::string(sandorData->m_argv[0]); |
| parseIndexes(indexes, items); |
| PaletteFilterFxRenderData paletteFilterData; |
| insertIndexes(items, &paletteFilterData); |
| |
| if (!paletteFilterData.m_colors.empty() && *paletteFilterData.m_colors.begin() == 0) { |
| BlendTzParams ¶ms = sandorData->m_blendParams; |
| enlargement = params.m_amount * scale; |
| } |
| } |
| |
| CASE Calligraphic : __OR OutBorder: |
| { |
| CalligraphicParams ¶ms = sandorData->m_callParams; |
| enlargement = params.m_thickness * scale; |
| } |
| |
| CASE ArtAtContour: |
| { |
| ArtAtContourParams ¶ms = sandorData->m_contourParams; |
| enlargement = |
| tmax(tceil(sandorData->m_controllerBBox.getLx()), tceil(sandorData->m_controllerBBox.getLy())) * |
| params.m_maxSize; |
| } |
| } |
| } |
| } |
| |
| return enlargement; |
| } |
| |
| |
| |
| void applyPaletteFilter(TPalette *&plt, bool keep, const set<int> &colors, const TPalette *srcPlt) |
| { |
| if (colors.empty()) |
| return; |
| |
| if (!plt) |
| plt = srcPlt->clone(); |
| |
| if (keep) { |
| for (int i = 0; i < plt->getStyleCount(); ++i) { |
| if (colors.find(i) == colors.end()) |
| plt->setStyle(i, TPixel32::Transparent); |
| } |
| } else { |
| std::set<int>::const_iterator ct, cEnd(colors.end()); |
| for (ct = colors.begin(); ct != cEnd; ++ct) { |
| TColorStyle *style = plt->getStyle(*ct); |
| if (style) |
| plt->setStyle(*ct, TPixel32::Transparent); |
| } |
| } |
| } |
| |
| |
| |
| TPalette *getPliPalette(const TFilePath &path) |
| { |
| TLevelReaderP levelReader = TLevelReaderP(path); |
| if (!levelReader.getPointer()) |
| return 0; |
| |
| TLevelP level = levelReader->loadInfo(); |
| TPalette *plt = level->getPalette(); |
| |
| return plt ? plt->clone() : (TPalette *)0; |
| } |
| |
| |
| |
| inline bool fxLess(TRasterFxRenderDataP a, TRasterFxRenderDataP b) |
| { |
| SandorFxRenderData *sandorDataA = dynamic_cast<SandorFxRenderData *>(a.getPointer()); |
| if (!sandorDataA) |
| return false; |
| |
| SandorFxRenderData *sandorDataB = dynamic_cast<SandorFxRenderData *>(b.getPointer()); |
| if (!sandorDataB) |
| return true; |
| |
| int aIndex = |
| sandorDataA->m_type == OutBorder ? 2 : sandorDataA->m_type == BlendTz ? 1 : 0; |
| int bIndex = |
| sandorDataB->m_type == OutBorder ? 2 : sandorDataB->m_type == BlendTz ? 1 : 0; |
| |
| return aIndex < bIndex; |
| } |
| |
| |
| |
| inline void sortCmappedFxs(vector<TRasterFxRenderDataP> &fxs) |
| { |
| std::stable_sort(fxs.begin(), fxs.end(), fxLess); |
| } |
| |
| |
| |
| vector<int> getAllBut(vector<int> &colorIds) |
| { |
| assert(TPixelCM32::getMaxInk() == TPixelCM32::getMaxPaint()); |
| |
| vector<int> curColorIds; |
| std::sort(colorIds.begin(), colorIds.end()); |
| |
| |
| unsigned int count1 = 0, count2 = 0; |
| int size = TPixelCM32::getMaxInk(); |
| |
| curColorIds.resize(size + 1 - colorIds.size()); |
| for (int i = 0; i < size; i++) |
| if (count1 < colorIds.size() && colorIds[count1] == i) |
| count1++; |
| else |
| curColorIds[count2++] = i; |
| |
| return curColorIds; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| TImageP applyCmappedFx(TToonzImageP &ti, const vector<TRasterFxRenderDataP> &fxs, int frame, double scale) |
| { |
| TImageP result = ti; |
| TTile resultTile; |
| TPalette *inPalette, *tempPlt; |
| TPaletteP filteredPalette; |
| TRasterCM32P copyRas; |
| string cmRasCacheId; |
| |
| |
| double dpiX, dpiY; |
| ti->getDpi(dpiX, dpiY); |
| double dpi = (dpiX > 0) ? dpiX / Stage::inch : 1.0; |
| |
| |
| std::vector<TRasterFxRenderDataP> fxsCopy = fxs; |
| sortCmappedFxs(fxsCopy); |
| |
| |
| inPalette = ti->getPalette(); |
| |
| std::vector<TRasterFxRenderDataP>::reverse_iterator it; |
| for (it = fxsCopy.rbegin(); it != fxsCopy.rend(); ++it) { |
| ExternalPaletteFxRenderData *extpltData = dynamic_cast<ExternalPaletteFxRenderData *>((*it).getPointer()); |
| PaletteFilterFxRenderData *PaletteFilterData = dynamic_cast<PaletteFilterFxRenderData *>((*it).getPointer()); |
| if (extpltData && extpltData->m_palette) { |
| filteredPalette = extpltData->m_palette->clone(); |
| filteredPalette->setFrame(frame); |
| } else if (PaletteFilterData && PaletteFilterData->m_type == eApplyToInksAndPaints) { |
| bool keep = PaletteFilterData->m_keep; |
| |
| set<int> colors; |
| colors.insert(PaletteFilterData->m_colors.begin(), PaletteFilterData->m_colors.end()); |
| |
| |
| tempPlt = filteredPalette.getPointer(); |
| applyPaletteFilter(tempPlt, keep, colors, inPalette); |
| filteredPalette = tempPlt; |
| |
| inPalette = filteredPalette.getPointer(); |
| } |
| } |
| |
| if (filteredPalette) { |
| |
| result = ti = TToonzImageP(ti->getRaster(), ti->getSavebox()); |
| filteredPalette->setFrame(frame); |
| ti->setPalette(filteredPalette.getPointer()); |
| } |
| |
| |
| bool firstSandorFx = true; |
| TRasterCM32P cmRas = ti->getRaster(); |
| TRect tiSaveBox(ti->getSavebox()); |
| TPaletteP tiPalette(ti->getPalette()); |
| ti = 0; |
| |
| |
| for (it = fxsCopy.rbegin(); it != fxsCopy.rend(); ++it) { |
| PaletteFilterFxRenderData *PaletteFilterData = dynamic_cast<PaletteFilterFxRenderData *>(it->getPointer()); |
| if (PaletteFilterData && PaletteFilterData->m_type != eApplyToInksAndPaints) { |
| vector<int> indexes; |
| indexes.resize(PaletteFilterData->m_colors.size()); |
| |
| set<int>::const_iterator jt = PaletteFilterData->m_colors.begin(); |
| for (int j = 0; j < (int)indexes.size(); ++j, ++jt) |
| indexes[j] = *jt; |
| |
| if (copyRas == TRasterCM32P()) |
| copyRas = cmRas->clone(); |
| |
| |
| if (PaletteFilterData->m_keep) |
| indexes = getAllBut(indexes); |
| |
| |
| if (PaletteFilterData->m_type != eApplyToInksKeepingAllPaints) |
| TRop::eraseColors(copyRas, PaletteFilterData->m_type == eApplyToInksDeletingAllPaints ? 0 : &indexes, false); |
| |
| |
| if (PaletteFilterData->m_type != eApplyToPaintsKeepingAllInks) |
| TRop::eraseColors(copyRas, PaletteFilterData->m_type == eApplyToPaintsDeletingAllInks ? 0 : &indexes, true); |
| } |
| } |
| |
| if (copyRas) { |
| cmRas = copyRas; |
| result = TToonzImageP(cmRas, tiSaveBox); |
| result->setPalette(tiPalette.getPointer()); |
| } |
| |
| |
| |
| |
| std::vector<BlendParam> blendParams; |
| for (it = fxsCopy.rbegin(); it != fxsCopy.rend(); ++it) { |
| SandorFxRenderData *sandorData = dynamic_cast<SandorFxRenderData *>(it->getPointer()); |
| if (sandorData && sandorData->m_type == BlendTz) { |
| BlendParam param; |
| |
| param.intensity = toDouble(std::string(sandorData->m_argv[3])) * scale * dpi; |
| param.smoothness = sandorData->m_blendParams.m_smoothness; |
| param.stopAtCountour = sandorData->m_blendParams.m_noBlending; |
| |
| param.superSampling = sandorData->m_blendParams.m_superSampling; |
| |
| |
| vector<string> items; |
| string indexes = std::string(sandorData->m_argv[0]); |
| parseIndexes(indexes, items); |
| PaletteFilterFxRenderData paletteFilterData; |
| insertIndexes(items, &paletteFilterData); |
| |
| param.colorsIndexes.reserve(paletteFilterData.m_colors.size()); |
| |
| std::set<int>::iterator it; |
| for (it = paletteFilterData.m_colors.begin(); it != paletteFilterData.m_colors.end(); ++it) |
| param.colorsIndexes.push_back(*it); |
| |
| blendParams.push_back(param); |
| } |
| } |
| |
| |
| for (it = fxsCopy.rbegin(); it != fxsCopy.rend(); ++it) { |
| SandorFxRenderData *sandorData = dynamic_cast<SandorFxRenderData *>(it->getPointer()); |
| |
| if (sandorData) { |
| |
| if ((sandorData->m_type == BlendTz && blendParams.empty()) || |
| (sandorData->m_type == OutBorder && !firstSandorFx)) |
| continue; |
| |
| if (!firstSandorFx) { |
| |
| cmRas = TToonzImageP(TImageCache::instance()->get(cmRasCacheId, true))->getRaster(); |
| |
| |
| vector<string> items; |
| string indexes = std::string(sandorData->m_argv[0]); |
| parseIndexes(indexes, items); |
| PaletteFilterFxRenderData paletteFilterData; |
| insertIndexes(items, &paletteFilterData); |
| |
| filteredPalette = tempPlt = 0; |
| applyPaletteFilter(tempPlt, true, paletteFilterData.m_colors, tiPalette.getPointer()); |
| filteredPalette = tempPlt; |
| } else { |
| |
| cmRasCacheId = TImageCache::instance()->getUniqueId(); |
| TImageCache::instance()->add(cmRasCacheId, TToonzImageP(cmRas, tiSaveBox)); |
| result = 0; |
| } |
| |
| |
| |
| RASTER *oldRasterIn, *oldRasterOut; |
| oldRasterIn = TRop::convertRaster50to46(cmRas, filteredPalette ? filteredPalette : tiPalette.getPointer()); |
| cmRas = TRasterCM32P(0); |
| { |
| TRaster32P rasterOut(TDimension(oldRasterIn->lx, oldRasterIn->ly)); |
| oldRasterOut = TRop::convertRaster50to46(rasterOut, 0); |
| } |
| |
| switch (sandorData->m_type) { |
| case BlendTz: { |
| if (blendParams.empty()) |
| continue; |
| |
| |
| cmRas = TToonzImageP(TImageCache::instance()->get(cmRasCacheId, true))->getRaster(); |
| |
| TToonzImageP ti(cmRas, tiSaveBox); |
| ti->setPalette(filteredPalette ? filteredPalette.getPointer() : tiPalette.getPointer()); |
| |
| TRasterImageP riOut(TImageCache::instance()->get(std::string(oldRasterOut->cacheId, oldRasterOut->cacheIdLength), true)); |
| TRaster32P rasterOut = riOut->getRaster(); |
| |
| blend(ti, rasterOut, blendParams); |
| |
| blendParams.clear(); |
| } |
| CASE Calligraphic : __OR OutBorder: |
| { |
| if (sandorData->m_type == OutBorder && !firstSandorFx) |
| continue; |
| |
| const char *argv[12]; |
| memcpy(argv, sandorData->m_argv, 12 * sizeof(const char *)); |
| |
| double thickness = toDouble(std::string(sandorData->m_argv[7])) * scale * dpi; |
| argv[7] = strsave(toString(thickness).c_str()); |
| |
| calligraph(oldRasterIn, oldRasterOut, sandorData->m_border, sandorData->m_argc, |
| argv, sandorData->m_shrink, sandorData->m_type == OutBorder); |
| } |
| CASE ArtAtContour: |
| { |
| const char *argv[12]; |
| memcpy(argv, sandorData->m_argv, 12 * sizeof(const char *)); |
| |
| double distance = toDouble(std::string(sandorData->m_argv[6])) * scale * dpi; |
| argv[6] = strsave(toString(distance).c_str()); |
| distance = toDouble(std::string(sandorData->m_argv[7])) * scale * dpi; |
| argv[7] = strsave(toString(distance).c_str()); |
| double density = toDouble(std::string(sandorData->m_argv[8])) / sq(scale * dpi); |
| argv[8] = strsave(toString(density).c_str()); |
| double size = toDouble(std::string(sandorData->m_argv[1])) * scale * dpi; |
| argv[1] = strsave(toString(size).c_str()); |
| size = toDouble(std::string(sandorData->m_argv[2])) * scale * dpi; |
| argv[2] = strsave(toString(size).c_str()); |
| RASTER *imgContour = TRop::convertRaster50to46(sandorData->m_controller, 0); |
| patternmap(oldRasterIn, oldRasterOut, sandorData->m_border, sandorData->m_argc, |
| argv, sandorData->m_shrink, imgContour); |
| TRop::releaseRaster46(imgContour); |
| } |
| DEFAULT: |
| assert(false); |
| } |
| |
| TRasterImageP riOut(TImageCache::instance()->get(std::string(oldRasterOut->cacheId, oldRasterOut->cacheIdLength), true)); |
| TRaster32P rasterOut = riOut->getRaster(); |
| |
| TRop::releaseRaster46(oldRasterIn); |
| TRop::releaseRaster46(oldRasterOut); |
| |
| if (firstSandorFx) { |
| resultTile.setRaster(rasterOut); |
| firstSandorFx = false; |
| } else |
| TRop::over(resultTile.getRaster(), rasterOut); |
| } |
| } |
| |
| |
| TImageCache::instance()->remove(cmRasCacheId); |
| |
| if (!result) |
| result = TRasterImageP(resultTile.getRaster()); |
| |
| return result; |
| } |
| |
| |
| |
| void applyCmappedFx(TVectorImageP &vi, const vector<TRasterFxRenderDataP> &fxs, int frame) |
| { |
| TRasterP ras; |
| bool keep = false; |
| TPaletteP modPalette; |
| set<int> colors; |
| std::vector<TRasterFxRenderDataP>::const_iterator it = fxs.begin(); |
| |
| |
| for (; it != fxs.end(); ++it) { |
| ExternalPaletteFxRenderData *extpltData = dynamic_cast<ExternalPaletteFxRenderData *>((*it).getPointer()); |
| PaletteFilterFxRenderData *pltFilterData = dynamic_cast<PaletteFilterFxRenderData *>((*it).getPointer()); |
| |
| if (extpltData && extpltData->m_palette) |
| modPalette = extpltData->m_palette->clone(); |
| else if (pltFilterData) { |
| assert(pltFilterData->m_type == eApplyToInksAndPaints); |
| |
| keep = pltFilterData->m_keep; |
| colors.insert(pltFilterData->m_colors.begin(), pltFilterData->m_colors.end()); |
| } |
| } |
| |
| TPalette *tempPlt = modPalette.getPointer(); |
| applyPaletteFilter(tempPlt, keep, colors, vi->getPalette()); |
| modPalette = tempPlt; |
| |
| if (modPalette) { |
| vi = vi->clone(); |
| vi->setPalette(modPalette.getPointer()); |
| } |
| } |
| |
| |
| |
| |
| |
| class LevelFxBuilder : public ResourceBuilder |
| { |
| TRasterP m_loadedRas; |
| TPaletteP m_palette; |
| |
| TXshSimpleLevel *m_sl; |
| TFrameId m_fid; |
| TRectD m_tileGeom; |
| bool m_64bit; |
| |
| TRect m_rasBounds; |
| |
| public: |
| LevelFxBuilder(const string &resourceName, double frame, const TRenderSettings &rs, |
| TXshSimpleLevel *sl, TFrameId fid) |
| : ResourceBuilder(resourceName, 0, frame, rs), m_loadedRas(), m_palette(), m_sl(sl), m_fid(fid), m_64bit(rs.m_bpp == 64) {} |
| |
| void setRasBounds(const TRect &rasBounds) |
| { |
| m_rasBounds = rasBounds; |
| } |
| |
| void compute(const TRectD &tileRect) |
| { |
| |
| TImageP img(m_sl->getFullsampledFrame(m_fid, (m_64bit ? ImageManager::is64bitEnabled : 0) | |
| ImageManager::dontPutInCache)); |
| |
| if (!img) |
| return; |
| |
| TRasterImageP rimg(img); |
| TToonzImageP timg(img); |
| |
| m_loadedRas = rimg ? (TRasterP)rimg->getRaster() : timg ? (TRasterP)timg->getRaster() : TRasterP(); |
| assert(m_loadedRas); |
| |
| if (timg) |
| m_palette = timg->getPalette(); |
| |
| assert(tileRect == TRectD(0, 0, m_loadedRas->getLx(), m_loadedRas->getLy())); |
| } |
| |
| void simCompute(const TRectD &rect) {} |
| |
| void upload(TCacheResourceP &resource) |
| { |
| assert(m_loadedRas); |
| resource->upload(TPoint(), m_loadedRas); |
| if (m_palette) |
| resource->uploadPalette(m_palette); |
| } |
| |
| bool download(TCacheResourceP &resource) |
| { |
| |
| if (m_loadedRas) |
| return true; |
| |
| |
| |
| if (resource->canDownloadAll(m_rasBounds)) { |
| m_loadedRas = resource->buildCompatibleRaster(m_rasBounds.getSize()); |
| resource->downloadPalette(m_palette); |
| return resource->downloadAll(TPoint(), m_loadedRas); |
| } else |
| return false; |
| } |
| |
| TImageP getImage() const |
| { |
| if (!m_loadedRas) |
| return TImageP(); |
| |
| TRasterCM32P cm(m_loadedRas); |
| |
| TImageP result(cm ? TImageP(TToonzImageP(cm, cm->getBounds())) : TImageP(TRasterImageP(m_loadedRas))); |
| if (m_palette) |
| result->setPalette(m_palette.getPointer()); |
| |
| return result; |
| } |
| }; |
| |
| |
| |
| |
| |
| TLevelColumnFx::TLevelColumnFx() |
| : m_levelColumn(0), m_isCachable(true), m_mutex(), m_offlineContext(0) |
| { |
| setName(L"LevelColumn"); |
| } |
| |
| |
| |
| TLevelColumnFx::~TLevelColumnFx() |
| { |
| if (m_offlineContext) |
| delete m_offlineContext; |
| } |
| |
| |
| |
| bool TLevelColumnFx::canHandle(const TRenderSettings &info, double frame) |
| { |
| |
| |
| |
| |
| if (!m_levelColumn) |
| return true; |
| |
| TXshCell cell = m_levelColumn->getCell(m_levelColumn->getFirstRow()); |
| if (cell.isEmpty()) |
| return true; |
| |
| TXshSimpleLevel *sl = cell.m_level->getSimpleLevel(); |
| if (!sl) |
| return true; |
| |
| return (sl->getType() == PLI_XSHLEVEL && !vectorMustApplyCmappedFx(info.m_data)); |
| } |
| |
| |
| |
| TAffine TLevelColumnFx::handledAffine(const TRenderSettings &info, double frame) |
| { |
| if (!m_levelColumn) |
| return TAffine(); |
| |
| TXshCell cell = m_levelColumn->getCell(m_levelColumn->getFirstRow()); |
| if (cell.isEmpty()) |
| return TAffine(); |
| |
| TXshSimpleLevel *sl = cell.m_level->getSimpleLevel(); |
| if (!sl) |
| return TAffine(); |
| |
| if (sl->getType() == PLI_XSHLEVEL) |
| return vectorMustApplyCmappedFx(info.m_data) ? TRasterFx::handledAffine(info, frame) : info.m_affine; |
| |
| |
| TImageInfo imageInfo; |
| getImageInfo(imageInfo, sl, cell.m_frameId); |
| |
| TPointD pixelsOrigin(-0.5 * imageInfo.m_lx, -0.5 * imageInfo.m_ly); |
| |
| const TAffine &aff = info.m_affine; |
| if (aff.a11 != 1.0 || aff.a22 != 1.0 || aff.a12 != 0.0 || aff.a21 != 0.0) |
| return TTranslation(-pixelsOrigin); |
| |
| |
| TAffine consistentAff(aff); |
| |
| consistentAff.a13 -= pixelsOrigin.x, consistentAff.a23 -= pixelsOrigin.y; |
| consistentAff.a13 = tfloor(consistentAff.a13), consistentAff.a23 = tfloor(consistentAff.a23); |
| consistentAff.a13 += pixelsOrigin.x, consistentAff.a23 += pixelsOrigin.y; |
| |
| return consistentAff; |
| } |
| |
| |
| |
| TFilePath TLevelColumnFx::getPalettePath(int frame) const |
| { |
| if (!m_levelColumn) |
| return TFilePath(); |
| |
| TXshCell cell = m_levelColumn->getCell(frame); |
| if (cell.isEmpty()) |
| return TFilePath(); |
| |
| TXshSimpleLevel *sl = cell.m_level->getSimpleLevel(); |
| if (!sl) |
| return TFilePath(); |
| |
| if (sl->getType() == TZP_XSHLEVEL) |
| return sl->getScene()->decodeFilePath(sl->getPath().withNoFrame().withType("tpl")); |
| |
| if (sl->getType() == PLI_XSHLEVEL) |
| return sl->getScene()->decodeFilePath(sl->getPath()); |
| |
| return TFilePath(); |
| } |
| |
| |
| |
| TPalette *TLevelColumnFx::getPalette(int frame) const |
| { |
| if (!m_levelColumn) |
| return 0; |
| |
| TXshCell cell = m_levelColumn->getCell(frame); |
| if (cell.isEmpty()) |
| return 0; |
| |
| TXshSimpleLevel *sl = cell.m_level->getSimpleLevel(); |
| if (!sl) |
| return 0; |
| |
| return sl->getPalette(); |
| } |
| |
| |
| |
| TFx *TLevelColumnFx::clone(bool recursive) const |
| { |
| TLevelColumnFx *clonedFx = dynamic_cast<TLevelColumnFx *>(TFx::clone(recursive)); |
| assert(clonedFx); |
| clonedFx->m_levelColumn = m_levelColumn; |
| clonedFx->m_isCachable = m_isCachable; |
| return clonedFx; |
| } |
| |
| |
| |
| void TLevelColumnFx::doDryCompute(TRectD &rect, double frame, const TRenderSettings &info) |
| { |
| if (!m_levelColumn) |
| return; |
| |
| int row = (int)frame; |
| TXshCell cell = m_levelColumn->getCell(row); |
| if (cell.isEmpty()) |
| return; |
| |
| TXshSimpleLevel *sl = cell.m_level->getSimpleLevel(); |
| if (!sl) |
| return; |
| |
| |
| |
| if (sl->getType() == PLI_XSHLEVEL) |
| return; |
| |
| int renderStatus = TRenderer::instance().getRenderStatus(TRenderer::renderId()); |
| |
| string alias = getAlias(frame, TRenderSettings()) + "_image"; |
| |
| TImageInfo imageInfo; |
| getImageInfo(imageInfo, sl, cell.m_frameId); |
| TRectD imgRect(0, 0, imageInfo.m_lx, imageInfo.m_ly); |
| |
| if (renderStatus == TRenderer::FIRSTRUN) { |
| ResourceBuilder::declareResource(alias, 0, imgRect, frame, info, false); |
| } else { |
| LevelFxBuilder builder(alias, frame, info, sl, cell.m_frameId); |
| builder.setRasBounds(TRect(0, 0, imageInfo.m_lx - 1, imageInfo.m_ly - 1)); |
| builder.simBuild(imgRect); |
| } |
| } |
| |
| |
| |
| bool isSubsheetChainOnColumn0(TXsheet *topXsheet, TXsheet *subsheet, int frame) |
| { |
| if (topXsheet == subsheet) |
| return true; |
| |
| const TXshCell cell = topXsheet->getCell(frame, 0); |
| if (!cell.m_level) |
| return false; |
| TXshChildLevel *cl = cell.m_level->getChildLevel(); |
| if (!cl) |
| return false; |
| return isSubsheetChainOnColumn0(cl->getXsheet(), subsheet, frame); |
| } |
| |
| |
| |
| void TLevelColumnFx::doCompute(TTile &tile, double frame, const TRenderSettings &info) |
| { |
| if (!m_levelColumn) |
| return; |
| |
| |
| int row = (int)frame; |
| TXshCell cell = m_levelColumn->getCell(row); |
| |
| if (cell.isEmpty()) |
| return; |
| |
| TXshSimpleLevel *sl = cell.m_level->getSimpleLevel(); |
| if (!sl) |
| return; |
| |
| TFrameId fid = cell.m_frameId; |
| |
| TImageP img; |
| TImageInfo imageInfo; |
| |
| |
| if (sl->getType() != PLI_XSHLEVEL) { |
| |
| LevelFxBuilder builder(getAlias(frame, TRenderSettings()) + "_image", |
| frame, info, sl, fid); |
| |
| getImageInfo(imageInfo, sl, fid); |
| TRectD imgRect(0, 0, imageInfo.m_lx, imageInfo.m_ly); |
| |
| builder.setRasBounds(TRect(0, 0, imageInfo.m_lx - 1, imageInfo.m_ly - 1)); |
| builder.build(imgRect); |
| |
| img = builder.getImage(); |
| } else { |
| |
| if (!img) { |
| img = sl->getFullsampledFrame(fid, ((info.m_bpp == 64) ? ImageManager::is64bitEnabled : 0) | |
| ImageManager::dontPutInCache); |
| } |
| } |
| |
| |
| TRect tileBounds(tile.getRaster()->getBounds()); |
| TRectD tileRectD = TRectD(tileBounds.x0, tileBounds.y0, tileBounds.x1 + 1, tileBounds.y1 + 1) + tile.m_pos; |
| |
| |
| if (!img) |
| return; |
| |
| TRectD bBox = img->getBBox(); |
| |
| |
| if (TVectorImageP vectorImage = img) { |
| |
| |
| if (vectorMustApplyCmappedFx(info.m_data)) { |
| |
| applyTzpFxsOnVector(vectorImage, tile, frame, info); |
| } else { |
| QMutexLocker m(&m_mutex); |
| bBox = info.m_affine * vectorImage->getBBox(); |
| TDimension size(tile.getRaster()->getSize()); |
| |
| TAffine aff = |
| TTranslation(-tile.m_pos.x, -tile.m_pos.y) * |
| TScale(1.0 / info.m_shrinkX, 1.0 / info.m_shrinkY) * |
| info.m_affine; |
| |
| applyCmappedFx(vectorImage, info.m_data, (int)frame); |
| TPalette *vpalette = vectorImage->getPalette(); |
| assert(vpalette); |
| m_isCachable = !vpalette->isAnimated(); |
| int oldFrame = vpalette->getFrame(); |
| |
| TVectorRenderData rd(TVectorRenderData::ProductionSettings(), |
| aff, TRect(size), vpalette); |
| |
| if (!m_offlineContext || m_offlineContext->getLx() < size.lx || m_offlineContext->getLy() < size.ly) { |
| if (m_offlineContext) |
| delete m_offlineContext; |
| m_offlineContext = new TOfflineGL(size); |
| } |
| |
| m_offlineContext->makeCurrent(); |
| m_offlineContext->clear(TPixel32(0, 0, 0, 0)); |
| |
| |
| |
| if (!m_isCachable) |
| vpalette->mutex()->lock(); |
| |
| vpalette->setFrame((int)frame); |
| m_offlineContext->draw(vectorImage, rd, true); |
| vpalette->setFrame(oldFrame); |
| |
| if (!m_isCachable) |
| vpalette->mutex()->unlock(); |
| |
| m_offlineContext->getRaster(tile.getRaster()); |
| |
| m_offlineContext->doneCurrent(); |
| } |
| } else { |
| |
| |
| TRasterP ras; |
| TAffine aff; |
| |
| TRasterImageP ri = img; |
| TToonzImageP ti = img; |
| img = 0; |
| |
| if (ri) { |
| |
| |
| ras = ri->getRaster(); |
| ri = 0; |
| TRaster32P ras32(ras); |
| TRaster64P ras64(ras); |
| |
| |
| |
| if (!ras32 && !ras64) { |
| TRasterP tileRas(tile.getRaster()); |
| TRaster32P tileRas32(tileRas); |
| TRaster64P tileRas64(tileRas); |
| |
| if (tileRas32) { |
| ras32 = TRaster32P(ras->getLx(), ras->getLy()); |
| TRop::convert(ras32, ras); |
| ras = ras32; |
| } else if (tileRas64) { |
| ras64 = TRaster64P(ras->getLx(), ras->getLy()); |
| TRop::convert(ras64, ras); |
| ras = ras64; |
| } else |
| assert(0); |
| } |
| TXsheet *xsh = m_levelColumn->getLevelColumn()->getXsheet(); |
| TXsheet *txsh = sl->getScene()->getTopXsheet(); |
| |
| LevelProperties *levelProp = sl->getProperties(); |
| if (Preferences::instance()->isIgnoreAlphaonColumn1Enabled() && m_levelColumn->getIndex() == 0 && isSubsheetChainOnColumn0(txsh, xsh, frame)) { |
| TRasterP appRas(ras->clone()); |
| setMaxMatte(appRas); |
| ras = appRas; |
| } |
| if (levelProp->doPremultiply()) { |
| TRasterP appRas = ras->clone(); |
| TRop::premultiply(appRas); |
| ras = appRas; |
| } |
| if (levelProp->whiteTransp()) { |
| TRasterP appRas(ras->clone()); |
| TRop::whiteTransp(appRas); |
| ras = appRas; |
| } |
| if (levelProp->antialiasSoftness() > 0) { |
| TRasterP appRas = ras->create(ras->getLx(), ras->getLy()); |
| TRop::antialias(ras, appRas, 10, levelProp->antialiasSoftness()); |
| ras = appRas; |
| } |
| |
| if (TXshSimpleLevel::m_fillFullColorRaster) { |
| TRasterP appRas(ras->clone()); |
| FullColorAreaFiller filler(appRas); |
| TPaletteP palette = new TPalette(); |
| int styleId = palette->getPage(0)->addStyle(TPixel32::White); |
| FillParameters params; |
| params.m_palette = palette.getPointer(); |
| params.m_styleId = styleId; |
| params.m_minFillDepth = 0; |
| params.m_maxFillDepth = 15; |
| filler.rectFill(appRas->getBounds(), params, false); |
| ras = appRas; |
| } |
| } else if (ti) { |
| |
| |
| |
| ti->setDpi(imageInfo.m_dpix, imageInfo.m_dpiy); |
| |
| TImageP newImg = applyTzpFxs(ti, frame, info); |
| |
| ri = newImg; |
| ti = newImg; |
| |
| if (ri) |
| ras = ri->getRaster(); |
| else |
| ras = ti->getRaster(); |
| |
| if (sl->getProperties()->antialiasSoftness() > 0) { |
| TRasterP appRas = ras->create(ras->getLx(), ras->getLy()); |
| TRop::antialias(ras, appRas, 10, sl->getProperties()->antialiasSoftness()); |
| ras = appRas; |
| } |
| |
| ri = 0; |
| } |
| |
| if (ras) { |
| double lx_2 = ras->getLx() / 2.0; |
| double ly_2 = ras->getLy() / 2.0; |
| |
| TRenderSettings infoAux(info); |
| assert(info.m_affine.isTranslation()); |
| infoAux.m_data.clear(); |
| |
| |
| tileRectD += TPointD(lx_2 - info.m_affine.a13, ly_2 - info.m_affine.a23); |
| |
| |
| TRectD inTileRectD; |
| if (ti) { |
| TRect saveBox(ti->getSavebox()); |
| inTileRectD = TRectD(saveBox.x0, saveBox.y0, saveBox.x1 + 1, saveBox.y1 + 1); |
| } else { |
| TRect rasBounds(ras->getBounds()); |
| inTileRectD = TRectD(rasBounds.x0, rasBounds.y0, rasBounds.x1 + 1, rasBounds.y1 + 1); |
| } |
| |
| |
| inTileRectD *= tileRectD; |
| |
| |
| if (inTileRectD.x0 >= inTileRectD.x1 || inTileRectD.y0 >= inTileRectD.y1) |
| return; |
| |
| |
| TRect inTileRect(tround(inTileRectD.x0), tround(inTileRectD.y0), tround(inTileRectD.x1) - 1, tround(inTileRectD.y1) - 1); |
| TTile inTile(ras->extract(inTileRect), inTileRectD.getP00() + TPointD(-lx_2, -ly_2)); |
| |
| |
| |
| if (ti) { |
| |
| TPalette *palette = ti->getPalette(); |
| |
| if (!m_isCachable) |
| palette->mutex()->lock(); |
| |
| int prevFrame = palette->getFrame(); |
| |
| palette->setFrame((int)frame); |
| TTile auxtile(TRaster32P(inTile.getRaster()->getSize()), inTile.m_pos); |
| TRop::convert(auxtile, inTile, palette, false, true); |
| palette->setFrame(prevFrame); |
| |
| if (!m_isCachable) |
| palette->mutex()->unlock(); |
| |
| inTile.setRaster(auxtile.getRaster()); |
| } |
| |
| TRasterFx::applyAffine(tile, inTile, infoAux); |
| } |
| } |
| } |
| |
| |
| |
| TImageP TLevelColumnFx::applyTzpFxs(TToonzImageP &ti, double frame, const TRenderSettings &info) |
| { |
| double scale = sqrt(fabs(info.m_affine.det())); |
| |
| int prevFrame = ti->getPalette()->getFrame(); |
| m_isCachable = !ti->getPalette()->isAnimated(); |
| |
| if (!m_isCachable) |
| ti->getPalette()->mutex()->lock(); |
| |
| TPaletteP palette(ti->getPalette()); |
| palette->setFrame((int)frame); |
| TImageP newImg = applyCmappedFx(ti, info.m_data, (int)frame, scale); |
| palette->setFrame(prevFrame); |
| |
| if (!m_isCachable) |
| palette->mutex()->unlock(); |
| |
| return newImg; |
| } |
| |
| |
| |
| void TLevelColumnFx::applyTzpFxsOnVector( |
| const TVectorImageP &vi, |
| TTile &tile, double frame, const TRenderSettings &info) |
| { |
| TRect tileBounds(tile.getRaster()->getBounds()); |
| TRectD tileRectD = TRectD(tileBounds.x0, tileBounds.y0, tileBounds.x1 + 1, tileBounds.y1 + 1) + tile.m_pos; |
| |
| |
| double scale = sqrt(fabs(info.m_affine.det())); |
| int enlargement = getEnlargement(info.m_data, scale); |
| |
| |
| std::vector<TVectorImageP> groupsList; |
| getGroupsList(vi, groupsList); |
| |
| |
| |
| unsigned int i; |
| for (i = 0; i < groupsList.size(); ++i) { |
| TVectorImageP &groupVi = groupsList[i]; |
| |
| |
| TRectD groupBBox(info.m_affine * groupVi->getBBox()); |
| if (!mustApplySandorFx(info.m_data)) |
| groupBBox *= tileRectD; |
| |
| groupBBox = groupBBox.enlarge(enlargement); |
| |
| if (groupBBox.x0 >= groupBBox.x1 || groupBBox.y0 >= groupBBox.y1) |
| continue; |
| |
| |
| groupBBox -= tile.m_pos; |
| groupBBox.x0 = tfloor(groupBBox.x0); |
| groupBBox.y0 = tfloor(groupBBox.y0); |
| groupBBox.x1 = tceil(groupBBox.x1); |
| groupBBox.y1 = tceil(groupBBox.y1); |
| groupBBox += tile.m_pos; |
| |
| |
| TPoint groupRelativePosToTile(groupBBox.x0 - tile.m_pos.x, groupBBox.y0 - tile.m_pos.y); |
| |
| |
| TToonzImageP groupTi = ToonzImageUtils::vectorToToonzImage( |
| groupVi, info.m_affine, groupVi->getPalette(), |
| groupBBox.getP00(), TDimension(groupBBox.getLx(), groupBBox.getLy()), |
| &info.m_data, true); |
| |
| |
| TImageP groupResult = applyTzpFxs(groupTi, frame, info); |
| |
| |
| TRasterImageP groupRi = groupResult; |
| if (!groupRi) { |
| groupTi = groupResult; |
| assert(groupTi); |
| |
| TRasterP groupTiRas(groupTi->getRaster()); |
| TRaster32P tempRas(groupTiRas->getSize()); |
| groupRi = TRasterImageP(tempRas); |
| |
| TRop::convert(tempRas, groupTiRas, groupTi->getPalette()); |
| } |
| |
| |
| TRasterP tileRas(tile.getRaster()); |
| TRop::over(tileRas, groupRi->getRaster(), groupRelativePosToTile); |
| } |
| } |
| |
| |
| |
| int TLevelColumnFx::getMemoryRequirement(const TRectD &rect, double frame, const TRenderSettings &info) |
| { |
| |
| if (mustApplySandorFx(info.m_data)) { |
| return -1; |
| } |
| return 0; |
| } |
| |
| |
| |
| void TLevelColumnFx::getImageInfo(TImageInfo &info, TXshSimpleLevel *sl, TFrameId frameId) |
| { |
| int type = sl->getType(); |
| assert(type != PLI_XSHLEVEL); |
| if (type == PLI_XSHLEVEL) |
| return; |
| |
| string imageId = sl->getImageId(frameId); |
| |
| const TImageInfo *storedInfo = ImageManager::instance()->getInfo(imageId, ImageManager::none, 0); |
| |
| if (!storedInfo) |
| |
| { |
| TImageP img; |
| if (!(img = sl->getFullsampledFrame(frameId, ImageManager::dontPutInCache))) { |
| assert(false); |
| return; |
| } |
| |
| info.m_lx = (int)img->getBBox().getLx(); |
| info.m_ly = (int)img->getBBox().getLy(); |
| info.m_x0 = info.m_y0 = 0; |
| info.m_x1 = (int)img->getBBox().getP11().x; |
| info.m_y1 = (int)img->getBBox().getP11().y; |
| } else |
| info = *storedInfo; |
| } |
| |
| |
| |
| bool TLevelColumnFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) |
| { |
| |
| if (!m_levelColumn) |
| return false; |
| |
| int row = (int)frame; |
| const TXshCell &cell = m_levelColumn->getCell(row); |
| if (cell.isEmpty()) |
| return false; |
| |
| TXshLevelP xshl = cell.m_level; |
| if (!xshl) |
| return false; |
| |
| TXshSimpleLevel *sl = xshl->getSimpleLevel(); |
| if (!sl) |
| return false; |
| |
| double dpi = 1.0; |
| |
| |
| int type = xshl->getType(); |
| if (type != PLI_XSHLEVEL) { |
| TImageInfo imageInfo; |
| getImageInfo(imageInfo, sl, cell.m_frameId); |
| |
| TRect imageSavebox(imageInfo.m_x0, imageInfo.m_y0, imageInfo.m_x1, imageInfo.m_y1); |
| double cx = 0.5 * imageInfo.m_lx; |
| double cy = 0.5 * imageInfo.m_ly; |
| double x0 = (imageSavebox.x0 - cx); |
| double y0 = (imageSavebox.y0 - cy); |
| double x1 = x0 + imageSavebox.getLx(); |
| double y1 = y0 + imageSavebox.getLy(); |
| bBox = TRectD(x0, y0, x1, y1); |
| |
| dpi = imageInfo.m_dpix / Stage::inch; |
| } else { |
| TImageP img = m_levelColumn->getCell(row).getImage(false); |
| if (!img) |
| return false; |
| bBox = img->getBBox(); |
| } |
| |
| |
| if (info.m_data.size()) { |
| TRectD imageBBox(bBox); |
| for (unsigned int i = 0; i < info.m_data.size(); ++i) { |
| TRectD enlargedImageBBox = info.m_data[i]->getBBoxEnlargement(imageBBox); |
| double enlargement = enlargedImageBBox.x1 - imageBBox.x1; |
| bBox += imageBBox.enlarge(enlargement * dpi); |
| } |
| } |
| |
| return true; |
| } |
| |
| |
| |
| const TPersistDeclaration *TLevelColumnFx::getDeclaration() const |
| { |
| return &columnFxInfo; |
| } |
| |
| |
| |
| string TLevelColumnFx::getPluginId() const |
| { |
| return "Toonz_"; |
| } |
| |
| |
| |
| TFxTimeRegion TLevelColumnFx::getTimeRegion() const |
| { |
| if (!m_levelColumn) |
| return TFxTimeRegion(); |
| |
| int first = m_levelColumn->getFirstRow(); |
| int last = m_levelColumn->getRowCount(); |
| |
| return TFxTimeRegion(first, last); |
| } |
| |
| |
| |
| void TLevelColumnFx::setColumn(TXshLevelColumn *column) |
| { |
| m_levelColumn = column; |
| } |
| |
| |
| |
| wstring TLevelColumnFx::getColumnId() const |
| { |
| if (!m_levelColumn) |
| return L"Col?"; |
| return L"Col" + toWideString(m_levelColumn->getIndex() + 1); |
| } |
| |
| |
| |
| wstring TLevelColumnFx::getColumnName() const |
| { |
| if (!m_levelColumn) |
| return L""; |
| int idx = getColumnIndex(); |
| return toWideString(m_levelColumn->getXsheet()->getStageObject(TStageObjectId::ColumnId(idx))->getName()); |
| } |
| |
| |
| |
| string TLevelColumnFx::getAlias(double frame, const TRenderSettings &info) const |
| { |
| if (!m_levelColumn || m_levelColumn->getCell((int)frame).isEmpty()) |
| return string(); |
| |
| const TXshCell &cell = m_levelColumn->getCell((int)frame); |
| |
| TFilePath fp; |
| TXshSimpleLevel *sl = cell.getSimpleLevel(); |
| |
| if (!sl) { |
| |
| TXshChildLevel *childLevel = cell.m_level->getChildLevel(); |
| if (childLevel) |
| return ::getAlias(childLevel->getXsheet(), frame, info); |
| |
| return string(); |
| } |
| |
| TFilePath path = sl->getPath(); |
| if (!cell.m_frameId.isNoFrame()) |
| fp = path.withFrame(cell.m_frameId); |
| else |
| fp = path; |
| |
| string rdata; |
| std::vector<TRasterFxRenderDataP>::const_iterator it = info.m_data.begin(); |
| for (; it != info.m_data.end(); ++it) { |
| TRasterFxRenderDataP data = *it; |
| if (data) |
| rdata += data->toString(); |
| } |
| |
| if (sl->getType() == PLI_XSHLEVEL || sl->getType() == TZP_XSHLEVEL) { |
| TPalette *palette = cell.getPalette(); |
| if (palette && palette->isAnimated()) |
| rdata += "animatedPlt" + toString(frame); |
| } |
| |
| if (Preferences::instance()->isIgnoreAlphaonColumn1Enabled()) { |
| TXsheet *xsh = m_levelColumn->getLevelColumn()->getXsheet(); |
| TXsheet *txsh = sl->getScene()->getTopXsheet(); |
| |
| if (m_levelColumn->getIndex() == 0 && isSubsheetChainOnColumn0(txsh, xsh, frame)) |
| rdata += "column_0"; |
| } |
| |
| return getFxType() + "[" + toString(fp.getWideString()) + "," + rdata + "]"; |
| } |
| |
| |
| |
| int TLevelColumnFx::getColumnIndex() const |
| { |
| return m_levelColumn ? m_levelColumn->getIndex() : -1; |
| } |
| |
| |
| |
| TXshColumn *TLevelColumnFx::getXshColumn() const |
| { |
| return m_levelColumn; |
| } |
| |
| |
| |
| void TLevelColumnFx::compute(TFlash &flash, int frame) |
| { |
| if (!m_levelColumn) |
| return; |
| |
| TImageP img = m_levelColumn->getCell(frame).getImage(false); |
| if (!img) |
| return; |
| |
| flash.draw(img, 0); |
| } |
| |
| |
| |
| TAffine TLevelColumnFx::getDpiAff(int frame) |
| { |
| if (!m_levelColumn) |
| return TAffine(); |
| |
| TXshCell cell = m_levelColumn->getCell(frame); |
| if (cell.isEmpty()) |
| return TAffine(); |
| |
| TXshSimpleLevel *sl = cell.m_level->getSimpleLevel(); |
| TFrameId fid = cell.m_frameId; |
| |
| if (sl) |
| return ::getDpiAffine(sl, cell.m_frameId, true); |
| |
| return TAffine(); |
| } |
| |
| |
| |
| void TLevelColumnFx::saveData(TOStream &os) |
| { |
| assert(m_levelColumn); |
| TFx::saveData(os); |
| } |
| |
| |
| |
| void TLevelColumnFx::loadData(TIStream &is) |
| { |
| |
| |
| |
| |
| |
| TFx::loadData(is); |
| setNewIdentifier(); |
| } |
| |
| |
| |
| |
| |
| TPaletteColumnFx::TPaletteColumnFx() |
| : m_paletteColumn(0) |
| { |
| } |
| |
| |
| |
| TPaletteColumnFx::~TPaletteColumnFx() |
| { |
| } |
| |
| |
| |
| TFx *TPaletteColumnFx::clone(bool recursive) const |
| { |
| TPaletteColumnFx *clonedFx = dynamic_cast<TPaletteColumnFx *>(TFx::clone(recursive)); |
| assert(clonedFx); |
| clonedFx->m_paletteColumn = m_paletteColumn; |
| return clonedFx; |
| } |
| |
| |
| |
| void TPaletteColumnFx::doCompute(TTile &tile, double frame, const TRenderSettings &) |
| { |
| } |
| |
| |
| |
| bool TPaletteColumnFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) |
| { |
| return false; |
| } |
| |
| |
| |
| TAffine TPaletteColumnFx::getDpiAff(int frame) |
| { |
| return TAffine(); |
| } |
| |
| |
| |
| bool TPaletteColumnFx::canHandle(const TRenderSettings &info, double frame) |
| { |
| return false; |
| } |
| |
| |
| |
| TFilePath TPaletteColumnFx::getPalettePath(int frame) const |
| { |
| if (!m_paletteColumn) |
| return TFilePath(); |
| TXshCell cell = m_paletteColumn->getCell(frame); |
| if (cell.isEmpty() || cell.m_level->getPaletteLevel() == 0) |
| return TFilePath(); |
| |
| TXshPaletteLevel *paletteLevel = cell.m_level->getPaletteLevel(); |
| TFilePath path = paletteLevel->getPath(); |
| path = paletteLevel->getScene()->decodeFilePath(path); |
| return path; |
| } |
| |
| |
| |
| TPalette *TPaletteColumnFx::getPalette(int frame) const |
| { |
| if (!m_paletteColumn) |
| return 0; |
| TXshCell cell = m_paletteColumn->getCell(frame); |
| if (cell.isEmpty() || cell.m_level->getPaletteLevel() == 0) |
| return 0; |
| |
| TXshPaletteLevel *paletteLevel = cell.m_level->getPaletteLevel(); |
| return paletteLevel->getPalette(); |
| } |
| |
| |
| |
| const TPersistDeclaration *TPaletteColumnFx::getDeclaration() const |
| { |
| return &paletteColumnFxInfo; |
| } |
| |
| |
| |
| string TPaletteColumnFx::getPluginId() const |
| { |
| return "Toonz_"; |
| } |
| |
| |
| |
| TFxTimeRegion TPaletteColumnFx::getTimeRegion() const |
| { |
| int first = 0; |
| int last = 11; |
| return TFxTimeRegion(first, last); |
| } |
| |
| |
| |
| wstring TPaletteColumnFx::getColumnName() const |
| { |
| if (!m_paletteColumn) |
| return L"Col?"; |
| return L"Col" + toWideString(m_paletteColumn->getIndex() + 1); |
| } |
| |
| |
| |
| wstring TPaletteColumnFx::getColumnId() const |
| { |
| if (!m_paletteColumn) |
| return L"Col?"; |
| return L"Col" + toWideString(m_paletteColumn->getIndex() + 1); |
| } |
| |
| |
| |
| string TPaletteColumnFx::getAlias(double frame, const TRenderSettings &info) const |
| { |
| TFilePath palettePath = getPalettePath(frame); |
| return "TPaletteColumnFx[" + toString(palettePath.getWideString()) + "]"; |
| } |
| |
| |
| |
| void TPaletteColumnFx::compute(TFlash &flash, int frame) |
| { |
| } |
| |
| |
| |
| int TPaletteColumnFx::getColumnIndex() const |
| { |
| return m_paletteColumn ? m_paletteColumn->getIndex() : -1; |
| } |
| |
| |
| |
| TXshColumn *TPaletteColumnFx::getXshColumn() const |
| { |
| return m_paletteColumn; |
| } |
| |
| |
| |
| |
| |
| TZeraryColumnFx::TZeraryColumnFx() |
| : m_zeraryFxColumn(0), m_fx(0) |
| { |
| setName(L"ZeraryColumn"); |
| } |
| |
| |
| |
| TZeraryColumnFx::~TZeraryColumnFx() |
| { |
| if (m_zeraryFxColumn) |
| m_zeraryFxColumn->release(); |
| if (m_fx) { |
| m_fx->m_columnFx = 0; |
| m_fx->release(); |
| } |
| } |
| |
| |
| |
| void TZeraryColumnFx::doCompute(TTile &tile, double frame, const TRenderSettings &info) |
| { |
| if (m_zeraryFxColumn) { |
| TRasterFx *fx = dynamic_cast<TRasterFx *>(m_fx); |
| if (fx) |
| fx->compute(tile, frame, info); |
| } |
| } |
| |
| |
| |
| bool TZeraryColumnFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) |
| { |
| if (m_zeraryFxColumn) { |
| TRasterFx *fx = dynamic_cast<TRasterFx *>(m_fx); |
| if (fx) |
| return fx->doGetBBox(frame, bBox, info); |
| } |
| |
| return false; |
| } |
| |
| |
| |
| const TPersistDeclaration *TZeraryColumnFx::getDeclaration() const |
| { |
| return &zeraryColumnFxInfo; |
| } |
| |
| |
| |
| string TZeraryColumnFx::getPluginId() const |
| { |
| return "Toonz_"; |
| } |
| |
| |
| |
| TFxTimeRegion TZeraryColumnFx::getTimeRegion() const |
| { |
| return TFxTimeRegion(0, (std::numeric_limits<double>::max)()); |
| } |
| |
| |
| |
| void TZeraryColumnFx::setColumn(TXshZeraryFxColumn *column) |
| { |
| m_zeraryFxColumn = column; |
| } |
| |
| |
| |
| wstring TZeraryColumnFx::getColumnName() const |
| { |
| return getZeraryFx()->getName(); |
| } |
| |
| |
| |
| wstring TZeraryColumnFx::getColumnId() const |
| { |
| return getZeraryFx()->getFxId(); |
| } |
| |
| |
| |
| void TZeraryColumnFx::setZeraryFx(TFx *fx) |
| { |
| TZeraryFx *zfx = static_cast<TZeraryFx *>(fx); |
| |
| if (fx) { |
| assert(dynamic_cast<TZeraryFx *>(fx)); |
| |
| fx->addRef(); |
| fx->setNewIdentifier(); |
| |
| zfx->m_columnFx = this; |
| } |
| |
| if (m_fx) { |
| m_fx->m_columnFx = 0; |
| m_fx->release(); |
| } |
| |
| m_fx = zfx; |
| } |
| |
| |
| |
| string TZeraryColumnFx::getAlias(double frame, const TRenderSettings &info) const |
| { |
| return "TZeraryColumnFx[" + m_fx->getAlias(frame, info) + "]"; |
| } |
| |
| |
| |
| void TZeraryColumnFx::loadData(TIStream &is) |
| { |
| if (m_fx) |
| m_fx->release(); |
| |
| m_fx = 0; |
| TPersist *p = 0; |
| is >> p; |
| |
| m_fx = dynamic_cast<TZeraryFx *>(p); |
| if (m_fx) { |
| m_fx->addRef(); |
| m_fx->m_columnFx = this; |
| m_fx->setNewIdentifier(); |
| } |
| |
| TFx::loadData(is); |
| setNewIdentifier(); |
| } |
| |
| |
| |
| void TZeraryColumnFx::saveData(TOStream &os) |
| { |
| assert(m_fx); |
| os << m_fx; |
| TFx::saveData(os); |
| } |
| |
| |
| |
| int TZeraryColumnFx::getColumnIndex() const |
| { |
| return m_zeraryFxColumn ? m_zeraryFxColumn->getIndex() : -1; |
| } |
| |
| |
| |
| TXshColumn *TZeraryColumnFx::getXshColumn() const |
| { |
| return m_zeraryFxColumn; |
| } |
| |
| |
| |
| |
| |
| const TPersistDeclaration *TXsheetFx::getDeclaration() const |
| { |
| return &infoTXsheetFx; |
| } |
| |
| |
| |
| TXsheetFx::TXsheetFx() |
| : m_fxDag(0) |
| { |
| setName(L"Xsheet"); |
| } |
| |
| |
| |
| void TXsheetFx::doCompute(TTile &tile, double frame, const TRenderSettings &) |
| { |
| } |
| |
| |
| |
| bool TXsheetFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) |
| { |
| return false; |
| } |
| |
| |
| |
| string TXsheetFx::getPluginId() const |
| { |
| return "Toonz_"; |
| } |
| |
| |
| |
| string TXsheetFx::getAlias(double frame, const TRenderSettings &info) const |
| { |
| string alias = getFxType(); |
| alias += "["; |
| |
| |
| TFxSet *terminalFxs = m_fxDag->getTerminalFxs(); |
| int i, fxsCount = terminalFxs->getFxCount(); |
| for (i = 0; i < fxsCount; ++i) { |
| alias += static_cast<TRasterFx *>(terminalFxs->getFx(i))->getAlias(frame, info) + ","; |
| } |
| |
| return alias + "]"; |
| } |
| |
| |
| |
| void TXsheetFx::setFxDag(FxDag *fxDag) |
| { |
| m_fxDag = fxDag; |
| } |
| |
| |
| |
| |
| |
| TOutputFx::TOutputFx() |
| { |
| addInputPort("source", m_input); |
| setName(L"Output"); |
| } |
| |
| |
| |
| const TPersistDeclaration *TOutputFx::getDeclaration() const |
| { |
| return &infoTOutputFx; |
| } |
| |
| |
| |
| void TOutputFx::doCompute(TTile &tile, double frame, const TRenderSettings &) |
| { |
| } |
| |
| |
| |
| bool TOutputFx::doGetBBox(double frame, TRectD &bBox, const TRenderSettings &info) |
| { |
| return false; |
| } |
| |
| |
| |
| string TOutputFx::getPluginId() const |
| { |
| return "Toonz_"; |
| } |
| |