Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tpixelutils.h"
Toshihiro Shimizu 890ddd
#include "tstroke.h"
Toshihiro Shimizu 890ddd
#include "tofflinegl.h"
Toshihiro Shimizu 890ddd
#include "tstencilcontrol.h"
Toshihiro Shimizu 890ddd
#include "tvectorgl.h"
Toshihiro Shimizu 890ddd
#include "tvectorrenderdata.h"
Toshihiro Shimizu 890ddd
#include "tcolorfunctions.h"
Toshihiro Shimizu 890ddd
#include "tpalette.h"
Toshihiro Shimizu 890ddd
#include "tropcm.h"
Toshihiro Shimizu 890ddd
#include "trasterimage.h"
Toshihiro Shimizu 890ddd
#include "tvectorimage.h"
Toshihiro Shimizu 890ddd
#include "tmeshimage.h"
Toshihiro Shimizu 890ddd
#include "tcolorstyles.h"
Toshihiro Shimizu 890ddd
#include "timage_io.h"
Toshihiro Shimizu 890ddd
#include "tregion.h"
Toshihiro Shimizu 890ddd
#include "toonz/toonzscene.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tenv.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzExt includes
Toshihiro Shimizu 890ddd
#include "ext/meshutils.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticskeleton.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticskeletondeformation.h"
Toshihiro Shimizu 890ddd
#include "ext/plasticdeformerstorage.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/stageplayer.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage.h"
Toshihiro Shimizu 890ddd
#include "toonz/stage2.h"
Campbell Barton b3bd84
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshsimplelevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshchildlevel.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcolumn.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshcell.h"
Toshihiro Shimizu 890ddd
#include "toonz/onionskinmask.h"
Toshihiro Shimizu 890ddd
#include "toonz/dpiscale.h"
Toshihiro Shimizu 890ddd
#include "toonz/imagemanager.h"
Toshihiro Shimizu 890ddd
#include "toonz/tstageobjecttree.h"
Toshihiro Shimizu 890ddd
#include "toonz/glrasterpainter.h"
Toshihiro Shimizu 890ddd
#include "toonz/preferences.h"
Toshihiro Shimizu 890ddd
#include "toonz/fill.h"
Toshihiro Shimizu 890ddd
#include "toonz/levelproperties.h"
Toshihiro Shimizu 890ddd
#include "toonz/autoclose.h"
Toshihiro Shimizu 890ddd
#include "toonz/txshleveltypes.h"
Toshihiro Shimizu 890ddd
#include "imagebuilders.h"
Jeremy Bullock 1e17ed
#include "toonz/tframehandle.h"
shun-iwasawa 1d5937
#include "toonz/preferences.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qimage></qimage>
Toshihiro Shimizu 890ddd
#include <qpainter></qpainter>
Toshihiro Shimizu 890ddd
#include <qpolygon></qpolygon>
Toshihiro Shimizu 890ddd
#include <qthreadstorage></qthreadstorage>
Toshihiro Shimizu 890ddd
#include <qmatrix></qmatrix>
shun_iwasawa ed1861
#include <qthread></qthread>
shun_iwasawa ed1861
#include <qguiapplication></qguiapplication>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonz/stagevisitor.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
//    Stage namespace
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \namespace Stage
Shinya Kitaoka 120a6e
    \brief The Stage namespace provides objects, classes and methods useful to
Shinya Kitaoka 120a6e
   view or display images.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
using namespace Stage;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! \var Stage::inch
Shinya Kitaoka 120a6e
                For historical reasons camera stand is defined in a coordinate
Shinya Kitaoka 120a6e
   system in which
Shinya Kitaoka 120a6e
                an inch is equal to 'Stage::inch' unit.
Shinya Kitaoka 120a6e
                Pay attention: modify this value condition apparent line
Shinya Kitaoka 120a6e
   thickness of
Shinya Kitaoka 120a6e
                images .pli.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
// const double Stage::inch = 53.33333;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
//    Local namespace
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QImage rasterToQImage(const TRaster32P &ras) {
Shinya Kitaoka 120a6e
  QImage image(ras->getRawData(), ras->getLx(), ras->getLy(),
Shinya Kitaoka 120a6e
               QImage::Format_ARGB32_Premultiplied);
Shinya Kitaoka 120a6e
  return image;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QImage rasterToQImage(const TRasterGR8P &ras) {
Shinya Kitaoka 120a6e
  QImage image(ras->getLx(), ras->getLy(), QImage::Format_ARGB32_Premultiplied);
Shinya Kitaoka 120a6e
  int lx = ras->getLx(), ly = ras->getLy();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  for (int y = 0; y < ly; y++) {
Shinya Kitaoka 120a6e
    TPixelGR8 *pix    = ras->pixels(y);
Shinya Kitaoka 120a6e
    TPixelGR8 *endPix = pix + lx;
Shinya Kitaoka 120a6e
    QRgb *outPix      = (QRgb *)image.scanLine(y);
Shinya Kitaoka 120a6e
    for (; pix < endPix; ++pix) {
Shinya Kitaoka 120a6e
      int value = pix->value;
Shinya Kitaoka 120a6e
      *outPix++ = qRgba(value, value, value, 255);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  return image;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
QImage rasterToQImage(const TRasterP &ras) {
Shinya Kitaoka 120a6e
  if (TRaster32P src32 = ras)
Shinya Kitaoka 120a6e
    return rasterToQImage(src32);
Shinya Kitaoka 120a6e
  else if (TRasterGR8P srcGr8 = ras)
Shinya Kitaoka 120a6e
    return rasterToQImage(srcGr8);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // assert(!"Cannot use drawImage with this image!");
Shinya Kitaoka 120a6e
  return QImage();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//----------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Draw orthogonal projection of \b bbox onto x-axis and y-axis.
Shinya Kitaoka 120a6e
void draw3DShadow(const TRectD &bbox, double z, double phi) {
Shinya Kitaoka 120a6e
  // bruttino assai, ammetto
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double a = bigBoxSize[0];
Shinya Kitaoka 120a6e
  double b = bigBoxSize[1];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glColor3d(0.9, 0.9, 0.86);
Shinya Kitaoka 120a6e
  glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
  glVertex3d(bbox.x0, bbox.y0, z);
Shinya Kitaoka 120a6e
  glVertex3d(bbox.x0, bbox.y1, z);
Shinya Kitaoka 120a6e
  glVertex3d(bbox.x1, bbox.y1, z);
Shinya Kitaoka 120a6e
  glVertex3d(bbox.x1, bbox.y0, z);
Shinya Kitaoka 120a6e
  glVertex3d(bbox.x0, bbox.y0, z);
Shinya Kitaoka 120a6e
  glEnd();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double y = -b;
Shinya Kitaoka 120a6e
  double x = phi >= 0 ? a : -a;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double xm = 0.5 * (bbox.x0 + bbox.x1);
Shinya Kitaoka 120a6e
  double ym = 0.5 * (bbox.y0 + bbox.y1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (bbox.y0 > y) {
Shinya Kitaoka 120a6e
    glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
    glVertex3d(xm, y, z);
Shinya Kitaoka 120a6e
    glVertex3d(xm, bbox.y0, z);
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
  } else if (bbox.y1 < y) {
Shinya Kitaoka 120a6e
    glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
    glVertex3d(xm, y, z);
Shinya Kitaoka 120a6e
    glVertex3d(xm, bbox.y1, z);
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (bbox.x0 > x) {
Shinya Kitaoka 120a6e
    glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
    glVertex3d(x, ym, z);
Shinya Kitaoka 120a6e
    glVertex3d(bbox.x0, ym, z);
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
  } else if (bbox.x1 < x) {
Shinya Kitaoka 120a6e
    glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
    glVertex3d(x, ym, z);
Shinya Kitaoka 120a6e
    glVertex3d(bbox.x1, ym, z);
Shinya Kitaoka 120a6e
    glEnd();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glColor3d(0.0, 0.0, 0.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
  glVertex3d(bbox.x0, -b, z);
Shinya Kitaoka 120a6e
  glVertex3d(bbox.x1, -b, z);
Shinya Kitaoka 120a6e
  glEnd();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glBegin(GL_LINE_STRIP);
Shinya Kitaoka 120a6e
  glVertex3d(x, bbox.y0, z);
Shinya Kitaoka 120a6e
  glVertex3d(x, bbox.y1, z);
Shinya Kitaoka 120a6e
  glEnd();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=====================================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//  Plastic function declarations
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*!
Toshihiro Shimizu 890ddd
  Returns from the specified player the stage object to be plastic
Toshihiro Shimizu 890ddd
  deformed - or 0 if current Toonz rules prevent it from being deformed.
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
TStageObject *plasticDeformedObj(const Stage::Player &player,
Shinya Kitaoka 120a6e
                                 const PlasticVisualSettings &pvs);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Draws the specified mesh image
Shinya Kitaoka 120a6e
void onMeshImage(TMeshImage *mi, const Stage::Player &player,
Shinya Kitaoka 120a6e
                 const ImagePainter::VisualSettings &vs,
Shinya Kitaoka 120a6e
                 const TAffine &viewAff);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Applies Plastic deformation of the specified player's stage object.
Shinya Kitaoka 120a6e
void onPlasticDeformedImage(TStageObject *playerObj,
Shinya Kitaoka 120a6e
                            const Stage::Player &player,
Shinya Kitaoka 120a6e
                            const ImagePainter::VisualSettings &vs,
Shinya Kitaoka 120a6e
                            const TAffine &viewAff);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
//    Picker  implementation
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Picker::Picker(const TAffine &viewAff, const TPointD &point,
shun-iwasawa 2d0135
               const ImagePainter::VisualSettings &vs, int devPixRatio)
Shinya Kitaoka 120a6e
    : Visitor(vs)
Shinya Kitaoka 120a6e
    , m_viewAff(viewAff)
Shinya Kitaoka 120a6e
    , m_point(point)
Shinya Kitaoka 120a6e
    , m_columnIndexes()
shun-iwasawa 2d0135
    , m_minDist2(25.0)
shun-iwasawa 2d0135
    , m_devPixRatio(devPixRatio) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
shun-iwasawa 2d0135
void Picker::setMinimumDistance(double d) {
shun-iwasawa 2d0135
  m_minDist2 = (double)(m_devPixRatio * m_devPixRatio) * d * d;
shun-iwasawa 2d0135
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Picker::onImage(const Stage::Player &player) {
shun-iwasawa 1d5937
  // if m_currentColumnIndex is other than the default value (-1),
shun-iwasawa 1d5937
  // then pick only the current column.
shun-iwasawa 1d5937
  if (m_currentColumnIndex != -1 &&
shun-iwasawa 1d5937
      m_currentColumnIndex != player.m_ancestorColumnIndex)
shun-iwasawa 1d5937
    return;
shun-iwasawa 1d5937
Shinya Kitaoka 120a6e
  bool picked   = false;
Shinya Kitaoka 120a6e
  TAffine aff   = m_viewAff * player.m_placement;
Shinya Kitaoka 120a6e
  TPointD point = aff.inv() * m_point;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const TImageP &img = player.image();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (TVectorImageP vi = img) {
Shinya Kitaoka 120a6e
    double w         = 0;
Shinya Kitaoka 120a6e
    UINT strokeIndex = 0;
Shinya Kitaoka 120a6e
    double dist2     = 0;
Shinya Kitaoka 120a6e
    TRegion *r       = vi->getRegion(point);
Shinya Kitaoka 120a6e
    int styleId      = 0;
shun-iwasawa 84ffc5
    if (r) styleId = r->getStyle();
Shinya Kitaoka 120a6e
    if (styleId != 0)
Shinya Kitaoka 120a6e
      picked = true;
Martin van Zijl b39989
    else if (vi->getNearestStroke(point, w, strokeIndex, dist2)) {
shun-iwasawa 2d0135
      dist2 *= aff.det();
Jeremy Bullock ff7b10
      TStroke *stroke        = vi->getStroke(strokeIndex);
Martin van Zijl b39989
      TThickPoint thickPoint = stroke->getThickPoint(w);
shun-iwasawa 2d0135
      double len2            = thickPoint.thick * thickPoint.thick * aff.det();
shun-iwasawa 2d0135
      double checkDist       = std::max(m_minDist2, len2);
Jeremy Bullock ff7b10
      if (dist2 < checkDist) picked = true;
Martin van Zijl b39989
    }
Shinya Kitaoka 120a6e
  } else if (TRasterImageP ri = img) {
Shinya Kitaoka 120a6e
    TRaster32P ras = ri->getRaster();
Shinya Kitaoka 120a6e
    if (!ras) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ras->lock();
Shinya Kitaoka 120a6e
    TPointD pp = player.m_dpiAff.inv() * point + ras->getCenterD();
Shinya Kitaoka 120a6e
    TPoint p(tround(pp.x), tround(pp.y));
Shinya Kitaoka 120a6e
    if (!ras->getBounds().contains(p)) return;
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
    TPixel32 *pix = ras->pixels(p.y);
Shinya Kitaoka 120a6e
    if (pix[p.x].m != 0) picked = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TAffine aff2 = (aff * player.m_dpiAff).inv();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPointD pa(p.x, p.y);
Shinya Kitaoka 120a6e
    TPointD dx = aff2 * (m_point + TPointD(3, 0)) - aff2 * m_point;
Shinya Kitaoka 120a6e
    TPointD dy = aff2 * (m_point + TPointD(0, 3)) - aff2 * m_point;
Shinya Kitaoka 120a6e
    double rx  = dx.x * dx.x + dx.y * dx.y;
Shinya Kitaoka 120a6e
    double ry  = dy.x * dy.x + dy.y * dy.y;
Shinya Kitaoka 120a6e
    int radius = tround(sqrt(rx > ry ? rx : ry));
Shinya Kitaoka 120a6e
    TRect rect = TRect(p.x - radius, p.y - radius, p.x + radius, p.y + radius) *
Shinya Kitaoka 120a6e
                 ras->getBounds();
Shinya Kitaoka 120a6e
    for (int y = rect.y0; !picked && y <= rect.y1; y++) {
Shinya Kitaoka 120a6e
      pix = ras->pixels(y);
shun-iwasawa 84ffc5
      for (int x = rect.x0; !picked && x <= rect.x1; x++)
Shinya Kitaoka 120a6e
        if (pix[x].m != 0) picked = true;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ras->unlock();
Shinya Kitaoka 120a6e
  } else if (TToonzImageP ti = img) {
Shinya Kitaoka 120a6e
    TRasterCM32P ras = ti->getRaster();
Shinya Kitaoka 120a6e
    if (!ras) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ras->lock();
Shinya Kitaoka 120a6e
    TPointD pp = player.m_dpiAff.inv() * point + ras->getCenterD();
Shinya Kitaoka 120a6e
    TPoint p(tround(pp.x), tround(pp.y));
Shinya Kitaoka 120a6e
    if (!ras->getBounds().contains(p)) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixelCM32 *pix = ras->pixels(p.y) + p.x;
Shinya Kitaoka 120a6e
    if (!pix->isPurePaint() || pix->getPaint() != 0) picked = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    ras->unlock();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (picked) {
Shinya Kitaoka 120a6e
    int columnIndex = player.m_ancestorColumnIndex;
Shinya Kitaoka 120a6e
    if (m_columnIndexes.empty() || m_columnIndexes.back() != columnIndex)
Shinya Kitaoka 120a6e
      m_columnIndexes.push_back(columnIndex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int row = player.m_frame;
Shinya Kitaoka 120a6e
    if (m_rows.empty() || m_rows.back() != row) m_rows.push_back(row);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Picker::beginMask() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Picker::endMask() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Picker::enableMask() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Picker::disableMask() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int Picker::getColumnIndex() const {
Shinya Kitaoka 120a6e
  if (m_columnIndexes.empty())
Shinya Kitaoka 120a6e
    return -1;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return m_columnIndexes.back();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void Picker::getColumnIndexes(std::vector<int> &indexes) const {</int>
Shinya Kitaoka 120a6e
  indexes = m_columnIndexes;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int Picker::getRow() const {
Shinya Kitaoka 120a6e
  if (m_rows.empty())
Shinya Kitaoka 120a6e
    return -1;
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    return m_rows.back();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
//    RasterPainter  implementation
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
RasterPainter::RasterPainter(const TDimension &dim, const TAffine &viewAff,
Shinya Kitaoka 120a6e
                             const TRect &rect,
Shinya Kitaoka 120a6e
                             const ImagePainter::VisualSettings &vs,
Shinya Kitaoka 120a6e
                             bool checkFlags)
Shinya Kitaoka 120a6e
    : Visitor(vs)
Shinya Kitaoka 120a6e
    , m_dim(dim)
Shinya Kitaoka 120a6e
    , m_viewAff(viewAff)
Shinya Kitaoka 120a6e
    , m_clipRect(rect)
Shinya Kitaoka 120a6e
    , m_maskLevel(0)
Shinya Kitaoka 120a6e
    , m_singleColumnEnabled(false)
Shinya Kitaoka 120a6e
    , m_checkFlags(checkFlags)
Shinya Kitaoka 120a6e
    , m_doRasterDarkenBlendedView(false) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
//! Utilizzato solo per TAB Pro
Shinya Kitaoka 120a6e
void RasterPainter::beginMask() {
Shinya Kitaoka 120a6e
  flushRasterImages();  // per evitare che venga fatto dopo il beginMask
Shinya Kitaoka 120a6e
  ++m_maskLevel;
Shinya Kitaoka 120a6e
  TStencilControl::instance()->beginMask();
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
//! Utilizzato solo per TAB Pro
Shinya Kitaoka 120a6e
void RasterPainter::endMask() {
Shinya Kitaoka 120a6e
  flushRasterImages();  // se ci sono delle immagini raster nella maschera
Shinya Kitaoka 120a6e
                        // devono uscire ora
Shinya Kitaoka 120a6e
  --m_maskLevel;
Shinya Kitaoka 120a6e
  TStencilControl::instance()->endMask();
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
//! Utilizzato solo per TAB Pro
Shinya Kitaoka 120a6e
void RasterPainter::enableMask() {
Shinya Kitaoka 120a6e
  TStencilControl::instance()->enableMask(TStencilControl::SHOW_INSIDE);
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
//! Utilizzato solo per TAB Pro
Shinya Kitaoka 120a6e
void RasterPainter::disableMask() {
Shinya Kitaoka 120a6e
  flushRasterImages();  // se ci sono delle immagini raster mascherate devono
Shinya Kitaoka 120a6e
                        // uscire ora
Shinya Kitaoka 120a6e
  TStencilControl::instance()->disableMask();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::DoubleVar AutocloseDistance("InknpaintAutocloseDistance", 10.0);
Toshihiro Shimizu 890ddd
TEnv::DoubleVar AutocloseAngle("InknpaintAutocloseAngle", 60.0);
Toshihiro Shimizu 890ddd
TEnv::IntVar AutocloseInk("InknpaintAutocloseInk", 1);
Toshihiro Shimizu 890ddd
TEnv::IntVar AutocloseOpacity("InknpaintAutocloseOpacity", 255);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int RasterPainter::getNodesCount() { return m_nodes.size(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RasterPainter::clearNodes() { m_nodes.clear(); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TRasterP RasterPainter::getRaster(int index, QMatrix &matrix) {
Shinya Kitaoka 120a6e
  if ((int)m_nodes.size() <= index) return TRasterP();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_nodes[index].m_onionMode != Node::eOnionSkinNone) return TRasterP();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_nodes.empty()) return TRasterP();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double delta = sqrt(fabs(m_nodes[0].m_aff.det()));
Shinya Kitaoka 120a6e
  TRectD bbox  = m_nodes[0].m_bbox.enlarge(delta);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 1; i < (int)m_nodes.size(); i++) {
Shinya Kitaoka 120a6e
    delta = sqrt(fabs(m_nodes[i].m_aff.det()));
Shinya Kitaoka 120a6e
    bbox += m_nodes[i].m_bbox.enlarge(delta);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TRect rect(tfloor(bbox.x0), tfloor(bbox.y0), tceil(bbox.x1), tceil(bbox.y1));
Shinya Kitaoka 120a6e
  rect = rect * TRect(0, 0, m_dim.lx - 1, m_dim.ly - 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TAffine aff = TTranslation(-rect.x0, -rect.y0) * m_nodes[index].m_aff;
Shinya Kitaoka 120a6e
  matrix      = QMatrix(aff.a11, aff.a21, aff.a12, aff.a22, aff.a13, aff.a23);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return m_nodes[index].m_raster;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! Make frame visualization.
Shinya Kitaoka 120a6e
\n	If onon-skin is active, create a new raster with dimension containing
Shinya Kitaoka 120a6e
all
Shinya Kitaoka 120a6e
                frame with onion-skin; recall \b TRop::quickPut with argument
Shinya Kitaoka 120a6e
each frame
Shinya Kitaoka 120a6e
                with onion-skin and new raster. If onion-skin is not active
Shinya Kitaoka 120a6e
recall
Shinya Kitaoka 120a6e
                \b TRop::quickPut with argument current frame and new raster.
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Toshihiro Shimizu 890ddd
QThreadStorage<std::vector<char> *> threadBuffers;</std::vector<char>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void RasterPainter::flushRasterImages() {
Shinya Kitaoka 120a6e
  if (m_nodes.empty()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Build nodes bbox union
Shinya Kitaoka 120a6e
  double delta = sqrt(fabs(m_nodes[0].m_aff.det()));
Shinya Kitaoka 120a6e
  TRectD bbox  = m_nodes[0].m_bbox.enlarge(delta);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i, nodesCount = m_nodes.size();
Shinya Kitaoka 120a6e
  for (i = 1; i < nodesCount; ++i) {
Shinya Kitaoka 120a6e
    delta = sqrt(fabs(m_nodes[i].m_aff.det()));
Shinya Kitaoka 120a6e
    bbox += m_nodes[i].m_bbox.enlarge(delta);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect rect(tfloor(bbox.x0), tfloor(bbox.y0), tceil(bbox.x1), tceil(bbox.y1));
Shinya Kitaoka 120a6e
  rect = rect * TRect(0, 0, m_dim.lx - 1, m_dim.ly - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int lx = rect.getLx(), ly = rect.getLy();
Shinya Kitaoka 120a6e
  TDimension dim(lx, ly);
Shinya Kitaoka 120a6e
Jeremy Bullock f15907
  // this is needed since a stop motion live view
Jeremy Bullock f15907
  // doesn't register as a node correctly
Jeremy Bullock f15907
  // there is probably a better way to do this.
Jeremy Bullock f15907
  if (rect.getLx() == 0 && lx == 0) {
Jeremy Bullock f15907
    rect = m_clipRect;
Jeremy Bullock f15907
    dim  = m_dim;
Jeremy Bullock f15907
  }
Jeremy Bullock f15907
Shinya Kitaoka 120a6e
  // Build a raster buffer of sufficient size to hold said union.
Shinya Kitaoka 120a6e
  // The buffer is per-thread cached in order to improve the rendering speed.
Shinya Kitaoka 120a6e
  if (!threadBuffers.hasLocalData())
Shinya Kitaoka 120a6e
    threadBuffers.setLocalData(new std::vector<char>());</char>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int size = dim.lx * dim.ly * sizeof(TPixel32);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<char> *vbuff = (std::vector<char> *)threadBuffers.localData();</char></char>
Shinya Kitaoka 120a6e
  if (size > (int)vbuff->size()) vbuff->resize(size);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRaster32P ras(dim.lx, dim.ly, dim.lx, (TPixel32 *)&(*vbuff)[0]);
Shinya Kitaoka 120a6e
  TRaster32P ras2;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_vs.m_colorMask != 0) {
Shinya Kitaoka 120a6e
    ras2 = TRaster32P(ras->getSize());
Shinya Kitaoka 120a6e
    ras->clear();
Shinya Kitaoka 120a6e
  } else
Shinya Kitaoka 120a6e
    ras2 = ras;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Clear the buffer - it will hold all the stacked nodes content to be overed
Shinya Kitaoka 120a6e
  // on top of the OpenGL buffer through a glDrawPixel()
Shinya Kitaoka 120a6e
  ras->lock();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ras->clear();  // ras is typically reused - and we need it transparent first
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect r                 = rect - rect.getP00();
Shinya Kitaoka 120a6e
  TRaster32P viewedRaster = ras->extract(r);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int current = -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Retrieve preferences-related data
Shinya Kitaoka 120a6e
  int tc    = m_checkFlags ? ToonzCheck::instance()->getChecks() : 0;
Shinya Kitaoka 120a6e
  int index = ToonzCheck::instance()->getColorIndex();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPixel32 frontOnionColor, backOnionColor;
Shinya Kitaoka 120a6e
  bool onionInksOnly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Preferences::instance()->getOnionData(frontOnionColor, backOnionColor,
Shinya Kitaoka 120a6e
                                        onionInksOnly);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Stack every node on top of the raster buffer
Shinya Kitaoka 120a6e
  for (i = 0; i < nodesCount; ++i) {
Shinya Kitaoka 120a6e
    if (m_nodes[i].m_isCurrentColumn) current = i;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TAffine aff         = TTranslation(-rect.x0, -rect.y0) * m_nodes[i].m_aff;
Shinya Kitaoka 120a6e
    TDimension imageDim = m_nodes[i].m_raster->getSize();
Shinya Kitaoka 120a6e
    TPointD offset(0.5, 0.5);
Shinya Kitaoka 120a6e
    aff *= TTranslation(offset);  // very quick and very dirty fix: in
Shinya Kitaoka 120a6e
                                  // camerastand the images seems shifted of an
Shinya Kitaoka 120a6e
                                  // half pixel...it's a quickput approximation?
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TPixel32 colorscale = TPixel32(0, 0, 0, m_nodes[i].m_alpha);
Shinya Kitaoka 120a6e
    int inksOnly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (m_nodes[i].m_onionMode != Node::eOnionSkinNone) {
Shinya Kitaoka 120a6e
      inksOnly = onionInksOnly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (m_nodes[i].m_onionMode == Node::eOnionSkinFront)
Shinya Kitaoka 120a6e
        colorscale = TPixel32(frontOnionColor.r, frontOnionColor.g,
Shinya Kitaoka 120a6e
                              frontOnionColor.b, m_nodes[i].m_alpha);
Shinya Kitaoka 120a6e
      else if (m_nodes[i].m_onionMode == Node::eOnionSkinBack)
Shinya Kitaoka 120a6e
        colorscale = TPixel32(backOnionColor.r, backOnionColor.g,
Shinya Kitaoka 120a6e
                              backOnionColor.b, m_nodes[i].m_alpha);
shun_iwasawa a3cdd8
    } else {
shun_iwasawa a3cdd8
      if (m_nodes[i].m_filterColor != TPixel32::Black) {
shun_iwasawa a3cdd8
        colorscale   = m_nodes[i].m_filterColor;
shun-iwasawa 646fd4
        colorscale.m = (typename TPixel32::Channel)((int)colorscale.m *
shun-iwasawa 646fd4
                                                    (int)m_nodes[i].m_alpha /
shun-iwasawa 646fd4
                                                    TPixel32::maxChannelValue);
shun_iwasawa a3cdd8
      }
Shinya Kitaoka 120a6e
      inksOnly = tc & ToonzCheck::eInksOnly;
shun_iwasawa a3cdd8
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (TRaster32P src32 = m_nodes[i].m_raster)
Shinya Kitaoka 120a6e
      TRop::quickPut(viewedRaster, src32, aff, colorscale,
Shinya Kitaoka 120a6e
                     m_nodes[i].m_doPremultiply, m_nodes[i].m_whiteTransp,
Shinya Kitaoka 120a6e
                     m_nodes[i].m_isFirstColumn, m_doRasterDarkenBlendedView);
Shinya Kitaoka 120a6e
    else if (TRasterGR8P srcGr8 = m_nodes[i].m_raster)
Shinya Kitaoka 120a6e
      TRop::quickPut(viewedRaster, srcGr8, aff, colorscale);
Shinya Kitaoka 120a6e
    else if (TRasterCM32P srcCm = m_nodes[i].m_raster) {
Shinya Kitaoka 120a6e
      assert(m_nodes[i].m_palette);
Shinya Kitaoka 120a6e
      int oldframe = m_nodes[i].m_palette->getFrame();
Shinya Kitaoka 120a6e
      m_nodes[i].m_palette->setFrame(m_nodes[i].m_frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      TPaletteP plt;
Jeremy Bullock ff7b10
      int styleIndex = -1;
Shinya Kitaoka 120a6e
      if ((tc & ToonzCheck::eGap || tc & ToonzCheck::eAutoclose) &&
Shinya Kitaoka 120a6e
          m_nodes[i].m_isCurrentColumn) {
Jeremy Bullock ff7b10
        srcCm      = srcCm->clone();
Jeremy Bullock ff7b10
        plt        = m_nodes[i].m_palette->clone();
Jeremy Bullock ff7b10
        styleIndex = plt->addStyle(TPixel::Magenta);
Shinya Kitaoka 120a6e
        if (tc & ToonzCheck::eAutoclose)
Shinya Kitaoka 120a6e
          TAutocloser(srcCm, AutocloseDistance, AutocloseAngle, styleIndex,
Shinya Kitaoka 120a6e
                      AutocloseOpacity)
Shinya Kitaoka 120a6e
              .exec();
Shinya Kitaoka 120a6e
        if (tc & ToonzCheck::eGap)
Shinya Kitaoka 120a6e
          AreaFiller(srcCm).rectFill(m_nodes[i].m_savebox, 1, true, true,
Shinya Kitaoka 120a6e
                                     false);
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        plt = m_nodes[i].m_palette;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (tc == 0 || tc == ToonzCheck::eBlackBg ||
Shinya Kitaoka 120a6e
          !m_nodes[i].m_isCurrentColumn)
Shinya Kitaoka 120a6e
        TRop::quickPut(viewedRaster, srcCm, plt, aff, colorscale, inksOnly);
Shinya Kitaoka 120a6e
      else {
Shinya Kitaoka 120a6e
        TRop::CmappedQuickputSettings settings;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        settings.m_globalColorScale = colorscale;
Shinya Kitaoka 120a6e
        settings.m_inksOnly         = inksOnly;
Shinya Kitaoka 120a6e
        settings.m_transparencyCheck =
Shinya Kitaoka 120a6e
            tc & (ToonzCheck::eTransparency | ToonzCheck::eGap);
Shinya Kitaoka 120a6e
        settings.m_blackBgCheck = tc & ToonzCheck::eBlackBg;
Shinya Kitaoka 120a6e
        /*-- InkCheck, Ink#1Check, PaintCheckはカレントカラムにのみ有効 --*/
Shinya Kitaoka 120a6e
        settings.m_inkIndex =
Shinya Kitaoka 120a6e
            m_nodes[i].m_isCurrentColumn
Shinya Kitaoka 120a6e
                ? (tc & ToonzCheck::eInk ? index
Shinya Kitaoka 120a6e
                                         : (tc & ToonzCheck::eInk1 ? 1 : -1))
Shinya Kitaoka 120a6e
                : -1;
Shinya Kitaoka 120a6e
        settings.m_paintIndex = m_nodes[i].m_isCurrentColumn
Shinya Kitaoka 120a6e
                                    ? (tc & ToonzCheck::ePaint ? index : -1)
Shinya Kitaoka 120a6e
                                    : -1;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        Preferences::instance()->getTranspCheckData(
Shinya Kitaoka 120a6e
            settings.m_transpCheckBg, settings.m_transpCheckInk,
Shinya Kitaoka 120a6e
            settings.m_transpCheckPaint);
Shinya Kitaoka 120a6e
Jeremy Bullock ff7b10
        settings.m_isOnionSkin = m_nodes[i].m_onionMode != Node::eOnionSkinNone;
Jeremy Bullock ff7b10
        settings.m_gapCheckIndex = styleIndex;
Jeremy Bullock ff7b10
Shinya Kitaoka 120a6e
        TRop::quickPut(viewedRaster, srcCm, plt, aff, settings);
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      srcCm = TRasterCM32P();
Shinya Kitaoka 120a6e
      plt   = TPaletteP();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      m_nodes[i].m_palette->setFrame(oldframe);
Shinya Kitaoka 120a6e
    } else
Shinya Kitaoka 120a6e
      assert(!"Cannot use quickput with this raster combination!");
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_vs.m_colorMask != 0) {
Shinya Kitaoka 120a6e
    TRop::setChannel(ras, ras, m_vs.m_colorMask, false);
Shinya Kitaoka 120a6e
    TRop::quickPut(ras2, ras, TAffine());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now, output the raster buffer on top of the OpenGL buffer
Shinya Kitaoka 120a6e
  glPushAttrib(GL_COLOR_BUFFER_BIT);  // Preserve blending and stuff
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glEnable(GL_BLEND);
Shinya Kitaoka 120a6e
  glBlendFunc(GL_ONE,
Shinya Kitaoka 120a6e
              GL_ONE_MINUS_SRC_ALPHA);  // The raster buffer is intended in
Shinya Kitaoka 120a6e
  // premultiplied form - thus the GL_ONE on src
Shinya Kitaoka 120a6e
  glDisable(GL_DEPTH_TEST);
Shinya Kitaoka 120a6e
  glDisable(GL_DITHER);
Shinya Kitaoka 120a6e
  glDisable(GL_LOGIC_OP);
Toshihiro Shimizu 890ddd
Campbell Barton 4cdcb0
/* disable, since these features are never enabled, and cause OpenGL to assert
Campbell Barton 4cdcb0
 * on systems that don't support them: see #591 */
Campbell Barton 4cdcb0
#if 0
Toshihiro Shimizu 890ddd
#ifdef GL_EXT_convolution
Martin van Zijl 708c58
  if( GLEW_EXT_convolution ) {
Martin van Zijl 708c58
    glDisable(GL_CONVOLUTION_1D_EXT);
Martin van Zijl 708c58
    glDisable(GL_CONVOLUTION_2D_EXT);
Martin van Zijl 708c58
    glDisable(GL_SEPARABLE_2D_EXT);
Martin van Zijl 708c58
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef GL_EXT_histogram
Martin van Zijl 708c58
  if( GLEW_EXT_histogram ) {
Martin van Zijl 708c58
    glDisable(GL_HISTOGRAM_EXT);
Martin van Zijl 708c58
    glDisable(GL_MINMAX_EXT);
Martin van Zijl 708c58
  }
Toshihiro Shimizu 890ddd
#endif
Campbell Barton 4cdcb0
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef GL_EXT_texture3D
Jeremy Bullock ff7b10
  if (GL_EXT_texture3D) {
Martin van Zijl 708c58
    glDisable(GL_TEXTURE_3D_EXT);
Martin van Zijl 708c58
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
  glLoadIdentity();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glRasterPos2d(rect.x0, rect.y0);
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
Shinya Kitaoka 120a6e
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glDrawPixels(ras2->getLx(), ras2->getLy(),            // Perform the over
Shinya Kitaoka 120a6e
               TGL_FMT, TGL_TYPE, ras2->getRawData());  //
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ras->unlock();
Shinya Kitaoka 120a6e
  glPopMatrix();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPopAttrib();  // Restore blending status
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (m_vs.m_showBBox && current > -1) {
Shinya Kitaoka 120a6e
    glPushMatrix();
Shinya Kitaoka 120a6e
    glLoadIdentity();
Shinya Kitaoka 120a6e
    tglColor(TPixel(200, 200, 200));
Shinya Kitaoka 120a6e
    tglMultMatrix(m_nodes[current].m_aff);
Shinya Kitaoka 120a6e
    tglDrawRect(m_nodes[current].m_raster->getBounds());
Shinya Kitaoka 120a6e
    glPopMatrix();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_nodes.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Make frame visualization in QPainter.
Toshihiro Shimizu 890ddd
\n	Draw in painter mode just raster image in m_nodes.
Toshihiro Shimizu 890ddd
\n  Onon-skin or channel mode are not considered.
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
void RasterPainter::drawRasterImages(QPainter &p, QPolygon cameraPol) {
Shinya Kitaoka 120a6e
  if (m_nodes.empty()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  double delta = sqrt(fabs(m_nodes[0].m_aff.det()));
Shinya Kitaoka 120a6e
  TRectD bbox  = m_nodes[0].m_bbox.enlarge(delta);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int i;
Shinya Kitaoka 120a6e
  for (i = 1; i < (int)m_nodes.size(); i++) {
Shinya Kitaoka 120a6e
    delta = sqrt(fabs(m_nodes[i].m_aff.det()));
Shinya Kitaoka 120a6e
    bbox += m_nodes[i].m_bbox.enlarge(delta);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TRect rect(tfloor(bbox.x0), tfloor(bbox.y0), tceil(bbox.x1), tceil(bbox.y1));
Shinya Kitaoka 120a6e
  rect = rect * TRect(0, 0, m_dim.lx - 1, m_dim.ly - 1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRect r = rect - rect.getP00();
Shinya Kitaoka 120a6e
  TAffine flipY(1, 0, 0, 0, -1, m_dim.ly);
Shinya Kitaoka 120a6e
  p.setClipRegion(QRegion(cameraPol));
Shinya Kitaoka 120a6e
  for (i = 0; i < (int)m_nodes.size(); i++) {
Shinya Kitaoka 120a6e
    if (m_nodes[i].m_onionMode != Node::eOnionSkinNone) continue;
Rozhuk Ivan 823a31
    p.resetTransform();
Shinya Kitaoka 120a6e
    TRasterP ras = m_nodes[i].m_raster;
Shinya Kitaoka 120a6e
    TAffine aff  = TTranslation(-rect.x0, -rect.y0) * flipY * m_nodes[i].m_aff;
Shinya Kitaoka 120a6e
    QMatrix matrix(aff.a11, aff.a21, aff.a12, aff.a22, aff.a13, aff.a23);
Shinya Kitaoka 120a6e
    QImage image = rasterToQImage(ras);
Shinya Kitaoka 120a6e
    if (image.isNull()) continue;
Shinya Kitaoka 120a6e
    p.setMatrix(matrix);
Shinya Kitaoka 120a6e
    p.drawImage(rect.getP00().x, rect.getP00().y, image);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Rozhuk Ivan 823a31
  p.resetTransform();
Shinya Kitaoka 120a6e
  m_nodes.clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
shun-iwasawa 27b0cf
static void buildAutocloseImage(
shun-iwasawa 27b0cf
    TVectorImage *vaux, TVectorImage *vi,
shun-iwasawa 27b0cf
    const std::vector<std::pair<int, double="">> &startPoints,</std::pair<int,>
shun-iwasawa 27b0cf
    const std::vector<std::pair<int, double="">> &endPoints) {</std::pair<int,>
Shinya Kitaoka 120a6e
  for (UINT i = 0; i < startPoints.size(); i++) {
Shinya Kitaoka 120a6e
    TThickPoint p1 = vi->getStroke(startPoints[i].first)
Shinya Kitaoka 120a6e
                         ->getThickPoint(startPoints[i].second);
Shinya Kitaoka 120a6e
    TThickPoint p2 =
Shinya Kitaoka 120a6e
        vi->getStroke(endPoints[i].first)->getThickPoint(endPoints[i].second);
Shinya Kitaoka 120a6e
    std::vector<tthickpoint> points(3);</tthickpoint>
Shinya Kitaoka 120a6e
    points[0]       = p1;
Shinya Kitaoka 120a6e
    points[1]       = 0.5 * (p1 + p2);
Shinya Kitaoka 120a6e
    points[2]       = p2;
Shinya Kitaoka 120a6e
    points[0].thick = points[1].thick = points[2].thick = 0.0;
Shinya Kitaoka 120a6e
    TStroke *auxStroke                                  = new TStroke(points);
Shinya Kitaoka 120a6e
    auxStroke->setStyle(2);
Shinya Kitaoka 120a6e
    vaux->addStroke(auxStroke);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TEnv::DoubleVar AutocloseFactor("InknpaintAutocloseFactor", 4.0);
Toshihiro Shimizu 890ddd
Campbell Barton b3bd84
static void drawAutocloses(TVectorImage *vi, TVectorRenderData &rd) {
Shinya Kitaoka 120a6e
  static TPalette *plt = 0;
Shinya Kitaoka 120a6e
  if (!plt) {
Shinya Kitaoka 120a6e
    plt = new TPalette();
Shinya Kitaoka 120a6e
    plt->addStyle(TPixel::Magenta);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::vector<std::pair<int, double="">> startPoints, endPoints;</std::pair<int,>
Shinya Kitaoka 120a6e
  getClosingPoints(vi->getBBox(), AutocloseFactor, vi, startPoints, endPoints);
Shinya Kitaoka 120a6e
  TVectorImage *vaux = new TVectorImage();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  rd.m_palette = plt;
Shinya Kitaoka 120a6e
  buildAutocloseImage(vaux, vi, startPoints, endPoints);
Martin van Zijl 53ad92
  // temporarily disable fill check, to preserve the gap indicator color
Martin van Zijl 53ad92
  bool tCheckEnabledOriginal = rd.m_tcheckEnabled;
Jeremy Bullock ff7b10
  rd.m_tcheckEnabled         = false;
Martin van Zijl 53ad92
  // draw
Shinya Kitaoka 120a6e
  tglDraw(rd, vaux);
Martin van Zijl 53ad92
  // restore original value
Martin van Zijl 53ad92
  rd.m_tcheckEnabled = tCheckEnabledOriginal;
Shinya Kitaoka 120a6e
  delete vaux;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! Take image from \b Stage::Player \b data and recall the right method for
Shinya Kitaoka 120a6e
                this kind of image, for vector image recall \b onVectorImage(),
Shinya Kitaoka 120a6e
   for raster
Shinya Kitaoka 120a6e
                image recall \b onRasterImage() for toonz image recall \b
Shinya Kitaoka 120a6e
   onToonzImage().
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
void RasterPainter::onImage(const Stage::Player &player) {
Shinya Kitaoka 120a6e
  if (m_singleColumnEnabled && !player.m_isCurrentColumn) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Attempt Plastic-deformed drawing
shun_iwasawa ed1861
  // For now generating icons of plastic-deformed image causes crash as
shun_iwasawa ed1861
  // QOffscreenSurface is created outside the gui thread.
shun_iwasawa ed1861
  // As a quick workaround, ignore the deformation if this is called from
shun_iwasawa ed1861
  // non-gui thread (i.e. icon generator thread)
shun_iwasawa 7e52a2
  // 12/1/2018 Now the scene icon is rendered without deformation either
shun_iwasawa 7e52a2
  // since it causes unknown error with opengl contexts..
shun_iwasawa ed1861
  TStageObject *obj =
shun_iwasawa ed1861
      ::plasticDeformedObj(player, m_vs.m_plasticVisualSettings);
shun_iwasawa 7e52a2
  if (obj && QThread::currentThread() == qGuiApp->thread() &&
shun_iwasawa 7e52a2
      !m_vs.m_forSceneIcon) {
Shinya Kitaoka 120a6e
    flushRasterImages();
Shinya Kitaoka 120a6e
    ::onPlasticDeformedImage(obj, player, m_vs, m_viewAff);
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // Common image draw
Shinya Kitaoka 120a6e
    const TImageP &img = player.image();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (TVectorImageP vi = img)
Shinya Kitaoka 120a6e
      onVectorImage(vi.getPointer(), player);
Shinya Kitaoka 120a6e
    else if (TRasterImageP ri = img)
Shinya Kitaoka 120a6e
      onRasterImage(ri.getPointer(), player);
Shinya Kitaoka 120a6e
    else if (TToonzImageP ti = img)
Shinya Kitaoka 120a6e
      onToonzImage(ti.getPointer(), player);
Shinya Kitaoka 120a6e
    else if (TMeshImageP mi = img) {
Shinya Kitaoka 120a6e
      flushRasterImages();
Shinya Kitaoka 120a6e
      ::onMeshImage(mi.getPointer(), player, m_vs, m_viewAff);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! View a vector cell images.
Toshihiro Shimizu 890ddd
\n	If onion-skin is active compute \b TOnionFader value.
Shinya Kitaoka 120a6e
                Create and boot a \b TVectorRenderData and recall \b tglDraw().
Toshihiro Shimizu 890ddd
*/
Shinya Kitaoka 120a6e
void RasterPainter::onVectorImage(TVectorImage *vi,
Shinya Kitaoka 120a6e
                                  const Stage::Player &player) {
Shinya Kitaoka 120a6e
  flushRasterImages();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // When loaded, vectorimages needs to have regions recomputed, but doing that
Shinya Kitaoka 120a6e
  // while loading them
Shinya Kitaoka 120a6e
  // is quite slow (think about loading whole scenes!..). They are recomputed
Shinya Kitaoka 120a6e
  // the first time they
Shinya Kitaoka 120a6e
  // are selected and shown on screen...except when playing back, to avoid
Shinya Kitaoka 120a6e
  // slowness!
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // (Daniele) This function should *NOT* be responsible of that.
Shinya Kitaoka 120a6e
  //           It's the *image itself* that should recalculate or initialize
Shinya Kitaoka 120a6e
  //           said data
Shinya Kitaoka 120a6e
  //           if queried about it and turns out it's not available...
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (!player.m_isPlaying && player.m_isCurrentColumn)
Shinya Kitaoka 120a6e
    vi->recomputeRegionsIfNeeded();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const Preferences &prefs = *Preferences::instance();
Shinya Kitaoka 120a6e
Jeremy Bullock 1e17ed
  TColorFunction *cf = 0, *guidedCf = 0;
Shinya Kitaoka 120a6e
  TPalette *vPalette = vi->getPalette();
Shinya Kitaoka 120a6e
  TPixel32 bgColor   = TPixel32::White;
Shinya Kitaoka 120a6e
shun-iwasawa 646fd4
  int tc        = (m_checkFlags && player.m_isCurrentColumn)
shun-iwasawa 646fd4
                      ? ToonzCheck::instance()->getChecks()
shun-iwasawa 646fd4
                      : 0;
Shinya Kitaoka 120a6e
  bool inksOnly = tc & ToonzCheck::eInksOnly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int oldFrame = vPalette->getFrame();
Shinya Kitaoka 120a6e
  vPalette->setFrame(player.m_frame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (player.m_onionSkinDistance != c_noOnionSkin) {
Shinya Kitaoka 120a6e
    TPixel32 frontOnionColor, backOnionColor;
Shinya Kitaoka 120a6e
shun-iwasawa 1d5937
    if (player.m_onionSkinDistance != 0 &&
shun-iwasawa 1d5937
        (!player.m_isShiftAndTraceEnabled ||
shun-iwasawa 1d5937
         Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts())) {
Shinya Kitaoka 120a6e
      prefs.getOnionData(frontOnionColor, backOnionColor, inksOnly);
Shinya Kitaoka 120a6e
      bgColor =
Shinya Kitaoka 120a6e
          (player.m_onionSkinDistance < 0) ? backOnionColor : frontOnionColor;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    double m[4] = {1.0, 1.0, 1.0, 1.0}, c[4];
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Weighted addition to RGB and matte multiplication
Shinya Kitaoka 120a6e
    m[3] = 1.0 -
Shinya Kitaoka 120a6e
           ((player.m_onionSkinDistance == 0)
Shinya Kitaoka 120a6e
                ? 0.1
Shinya Kitaoka 120a6e
                : OnionSkinMask::getOnionSkinFade(player.m_onionSkinDistance));
Shinya Kitaoka 120a6e
    c[0] = (1.0 - m[3]) * bgColor.r, c[1] = (1.0 - m[3]) * bgColor.g,
Shinya Kitaoka 120a6e
    c[2] = (1.0 - m[3]) * bgColor.b;
Shinya Kitaoka 120a6e
    c[3] = 0.0;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    cf = new TGenericColorFunction(m, c);
shun_iwasawa 2c0f50
  } else if (player.m_filterColor != TPixel::Black) {
shun_iwasawa 2c0f50
    TPixel32 colorScale = player.m_filterColor;
shun_iwasawa 2c0f50
    colorScale.m        = player.m_opacity;
shun_iwasawa 2c0f50
    cf                  = new TColumnColorFilterFunction(colorScale);
Shinya Kitaoka 120a6e
  } else if (player.m_opacity < 255)
Shinya Kitaoka 120a6e
    cf = new TTranspFader(player.m_opacity / 255.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TVectorRenderData rd(m_viewAff * player.m_placement, TRect(), vPalette, cf,
Shinya Kitaoka 120a6e
                       true  // alpha enabled
shun-iwasawa 84ffc5
  );
Shinya Kitaoka 120a6e
Jeremy Bullock 1e17ed
  rd.m_drawRegions           = !inksOnly;
Jeremy Bullock 1e17ed
  rd.m_inkCheckEnabled       = tc & ToonzCheck::eInk;
Martin van Zijl 5b5587
  rd.m_ink1CheckEnabled      = tc & ToonzCheck::eInk1;
Jeremy Bullock 1e17ed
  rd.m_paintCheckEnabled     = tc & ToonzCheck::ePaint;
Jeremy Bullock 1e17ed
  rd.m_blackBgEnabled        = tc & ToonzCheck::eBlackBg;
Jeremy Bullock 1e17ed
  rd.m_colorCheckIndex       = ToonzCheck::instance()->getColorIndex();
Jeremy Bullock 1e17ed
  rd.m_show0ThickStrokes     = prefs.getShow0ThickLines();
Jeremy Bullock 1e17ed
  rd.m_regionAntialias       = prefs.getRegionAntialias();
Jeremy Bullock 1e17ed
  rd.m_animatedGuidedDrawing = prefs.getAnimatedGuidedDrawing();
manongjohn 40a40e
  if (player.m_onionSkinDistance != 0 &&
Jeremy Bullock 1e17ed
      (player.m_isCurrentColumn || player.m_isCurrentXsheetLevel)) {
Jeremy Bullock 1e17ed
    if (player.m_isGuidedDrawingEnabled == 3         // show guides on all
Jeremy Bullock 1e17ed
        || (player.m_isGuidedDrawingEnabled == 1 &&  // show guides on closest
manongjohn 40a40e
            (player.m_onionSkinDistance == player.m_firstBackOnionSkin ||
manongjohn 40a40e
             player.m_onionSkinDistance == player.m_firstFrontOnionSkin)) ||
Jeremy Bullock 1e17ed
        (player.m_isGuidedDrawingEnabled == 2 &&  // show guides on farthest
manongjohn 40a40e
         (player.m_onionSkinDistance == player.m_onionSkinBackSize ||
manongjohn 40a40e
          player.m_onionSkinDistance == player.m_onionSkinFrontSize)) ||
Jeremy Bullock 1e17ed
        (player.m_isEditingLevel &&  // fix for level editing mode sending extra
Jeremy Bullock 1e17ed
                                     // players
Jeremy Bullock 1e17ed
         player.m_isGuidedDrawingEnabled == 2 &&
Jeremy Bullock 1e17ed
         player.m_onionSkinDistance == player.m_lastBackVisibleSkin)) {
Jeremy Bullock 1e17ed
      rd.m_showGuidedDrawing = player.m_isGuidedDrawingEnabled > 0;
Jeremy Bullock 1e17ed
      int currentStrokeCount = 0;
Jeremy Bullock 1e17ed
      int totalStrokes       = vi->getStrokeCount();
Jeremy Bullock 1e17ed
      TXshSimpleLevel *sl    = player.m_sl;
Jeremy Bullock 1e17ed
Jeremy Bullock 1e17ed
      if (sl) {
Jeremy Bullock 1e17ed
        TImageP image          = sl->getFrame(player.m_currentFrameId, false);
Jeremy Bullock 1e17ed
        TVectorImageP vecImage = image;
Jeremy Bullock 1e17ed
        if (vecImage) currentStrokeCount = vecImage->getStrokeCount();
manongjohn 40a40e
        if (currentStrokeCount < 0) currentStrokeCount = 0;
manongjohn 40a40e
        if (player.m_guidedFrontStroke != -1 &&
manongjohn 40a40e
            (player.m_onionSkinDistance == player.m_onionSkinFrontSize ||
manongjohn 40a40e
             player.m_onionSkinDistance == player.m_firstFrontOnionSkin))
manongjohn 40a40e
          rd.m_indexToHighlight = player.m_guidedFrontStroke;
manongjohn 40a40e
        else if (player.m_guidedBackStroke != -1 &&
manongjohn 40a40e
                 (player.m_onionSkinDistance == player.m_onionSkinBackSize ||
manongjohn 40a40e
                  player.m_onionSkinDistance == player.m_firstBackOnionSkin))
manongjohn 40a40e
          rd.m_indexToHighlight = player.m_guidedBackStroke;
manongjohn 40a40e
        else if (currentStrokeCount < totalStrokes)
Jeremy Bullock 1e17ed
          rd.m_indexToHighlight = currentStrokeCount;
Jeremy Bullock 1e17ed
Jeremy Bullock 1e17ed
        double guidedM[4] = {1.0, 1.0, 1.0, 1.0}, guidedC[4];
Jeremy Bullock 1e17ed
        TPixel32 bgColor  = TPixel32::Blue;
Jeremy Bullock 1e17ed
        guidedM[3] =
Jeremy Bullock 1e17ed
            1.0 -
Jeremy Bullock 1e17ed
            ((player.m_onionSkinDistance == 0)
Jeremy Bullock 1e17ed
                 ? 0.1
Jeremy Bullock 1e17ed
                 : OnionSkinMask::getOnionSkinFade(player.m_onionSkinDistance));
Jeremy Bullock 1e17ed
Jeremy Bullock 1e17ed
        guidedC[0] = (1.0 - guidedM[3]) * bgColor.r,
Jeremy Bullock 1e17ed
        guidedC[1] = (1.0 - guidedM[3]) * bgColor.g,
Jeremy Bullock 1e17ed
        guidedC[2] = (1.0 - guidedM[3]) * bgColor.b;
Jeremy Bullock 1e17ed
        guidedC[3] = 0.0;
Jeremy Bullock 1e17ed
Jeremy Bullock 1e17ed
        guidedCf      = new TGenericColorFunction(guidedM, guidedC);
Jeremy Bullock 1e17ed
        rd.m_guidedCf = guidedCf;
Jeremy Bullock 1e17ed
      }
Jeremy Bullock 1e17ed
    }
Jeremy Bullock 1e17ed
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (tc & (ToonzCheck::eTransparency | ToonzCheck::eGap)) {
Shinya Kitaoka 120a6e
    TPixel dummy;
Shinya Kitaoka 120a6e
    rd.m_tcheckEnabled = true;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (rd.m_blackBgEnabled)
Shinya Kitaoka 120a6e
      prefs.getTranspCheckData(rd.m_tCheckInk, dummy, rd.m_tCheckPaint);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      prefs.getTranspCheckData(dummy, rd.m_tCheckInk, rd.m_tCheckPaint);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_vs.m_colorMask != 0) {
Shinya Kitaoka 120a6e
    glColorMask((m_vs.m_colorMask & TRop::RChan) ? GL_TRUE : GL_FALSE,
Shinya Kitaoka 120a6e
                (m_vs.m_colorMask & TRop::GChan) ? GL_TRUE : GL_FALSE,
Shinya Kitaoka 120a6e
                (m_vs.m_colorMask & TRop::BChan) ? GL_TRUE : GL_FALSE, GL_TRUE);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  TVectorImageP viDelete;
Shinya Kitaoka 120a6e
  if (tc & ToonzCheck::eGap) {
Shinya Kitaoka 120a6e
    viDelete = vi->clone();
Shinya Kitaoka 120a6e
    vi       = viDelete.getPointer();
Shinya Kitaoka 120a6e
    vi->selectFill(vi->getBBox(), 0, 1, true, true, false);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
shun-iwasawa 18a7c6
  TStroke *guidedStroke = 0;
Shinya Kitaoka 120a6e
  if (m_maskLevel > 0)
Shinya Kitaoka 120a6e
    tglDrawMask(rd, vi);
Shinya Kitaoka 120a6e
  else
shun-iwasawa 18a7c6
    tglDraw(rd, vi, &guidedStroke);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (tc & ToonzCheck::eAutoclose) drawAutocloses(vi, rd);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
Shinya Kitaoka 120a6e
  vPalette->setFrame(oldFrame);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  delete cf;
Jeremy Bullock 1e17ed
  delete guidedCf;
shun-iwasawa 18a7c6
shun-iwasawa 18a7c6
  if (guidedStroke) m_guidedStrokes.push_back(guidedStroke);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*! Create a \b Node and put it in \b m_nodes.
shun-iwasawa 84ffc5
 */
Shinya Kitaoka 120a6e
void RasterPainter::onRasterImage(TRasterImage *ri,
Shinya Kitaoka 120a6e
                                  const Stage::Player &player) {
Shinya Kitaoka 120a6e
  TRasterP r = ri->getRaster();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine aff;
Shinya Kitaoka 120a6e
  aff = m_viewAff * player.m_placement * player.m_dpiAff;
Shinya Kitaoka 120a6e
  aff = TTranslation(m_dim.lx * 0.5, m_dim.ly * 0.5) * aff *
Shinya Kitaoka 120a6e
        TTranslation(-r->getCenterD() +
Shinya Kitaoka 120a6e
                     convert(ri->getOffset()));  // this offset is !=0 only if
Shinya Kitaoka 120a6e
                                                 // in cleanup camera test mode
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD bbox = TRectD(0, 0, m_dim.lx, m_dim.ly);
Shinya Kitaoka 120a6e
  bbox *= convert(m_clipRect);
Shinya Kitaoka 120a6e
  if (bbox.isEmpty()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int alpha                 = 255;
Shinya Kitaoka 120a6e
  Node::OnionMode onionMode = Node::eOnionSkinNone;
Shinya Kitaoka 120a6e
  if (player.m_onionSkinDistance != c_noOnionSkin) {
Shinya Kitaoka 120a6e
    // GetOnionSkinFade va bene per il vettoriale mentre il raster funziona al
Shinya Kitaoka 120a6e
    // contrario
Shinya Kitaoka 120a6e
    // 1 opaco -> 0 completamente trasparente
Shinya Kitaoka 120a6e
    // inverto quindi il risultato della funzione stando attento al caso 0
Shinya Kitaoka 120a6e
    // (in cui era scolpito il valore 0.9)
Shinya Kitaoka 120a6e
    double onionSkiFade = player.m_onionSkinDistance == 0
Shinya Kitaoka 120a6e
                              ? 0.9
Shinya Kitaoka 120a6e
                              : (1.0 - OnionSkinMask::getOnionSkinFade(
Shinya Kitaoka 120a6e
                                           player.m_onionSkinDistance));
shun-iwasawa 646fd4
    alpha               = tcrop(tround(onionSkiFade * 255.0), 0, 255);
shun-iwasawa 1d5937
    if (player.m_isShiftAndTraceEnabled &&
shun-iwasawa 1d5937
        !Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts())
shun-iwasawa 1d5937
      onionMode = Node::eOnionSkinNone;
shun-iwasawa 1d5937
    else {
shun-iwasawa 1d5937
      onionMode =
shun-iwasawa 1d5937
          (player.m_onionSkinDistance > 0)
shun-iwasawa 1d5937
              ? Node::eOnionSkinFront
shun-iwasawa 1d5937
              : ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack
shun-iwasawa 1d5937
                                                  : Node::eOnionSkinNone);
shun-iwasawa 1d5937
    }
Shinya Kitaoka 120a6e
  } else if (player.m_opacity < 255)
shun-iwasawa 84ffc5
    alpha = player.m_opacity;
Shinya Kitaoka 120a6e
  TXshSimpleLevel *sl = player.m_sl;
Shinya Kitaoka 120a6e
  bool doPremultiply  = false;
Shinya Kitaoka 120a6e
  bool whiteTransp    = false;
Shinya Kitaoka 120a6e
  if (sl) {
Shinya Kitaoka 120a6e
    LevelProperties *levelProp = sl->getProperties();
Shinya Kitaoka 120a6e
    if (levelProp->doPremultiply())
Shinya Kitaoka 120a6e
      doPremultiply = true;
Shinya Kitaoka 120a6e
    else if (levelProp->whiteTransp())
Shinya Kitaoka 120a6e
      whiteTransp = true;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool ignoreAlpha =
Shinya Kitaoka 120a6e
      (Preferences::instance()->isIgnoreAlphaonColumn1Enabled() &&
Shinya Kitaoka 120a6e
       player.m_column == 0 &&
Shinya Kitaoka 120a6e
       isSubsheetChainOnColumn0(sl->getScene()->getTopXsheet(), player.m_xsh,
Shinya Kitaoka 120a6e
                                player.m_frame));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_nodes.push_back(Node(r, 0, alpha, aff, ri->getSavebox(), bbox,
Shinya Kitaoka 120a6e
                         player.m_frame, player.m_isCurrentColumn, onionMode,
shun_iwasawa a3cdd8
                         doPremultiply, whiteTransp, ignoreAlpha,
shun_iwasawa a3cdd8
                         player.m_filterColor));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
/*! Create a \b Node and put it in \b m_nodes.
shun-iwasawa 84ffc5
 */
Shinya Kitaoka 120a6e
void RasterPainter::onToonzImage(TToonzImage *ti, const Stage::Player &player) {
Shinya Kitaoka 120a6e
  TRasterCM32P r = ti->getRaster();
Shinya Kitaoka 120a6e
  if (!ti->getPalette()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TAffine aff = m_viewAff * player.m_placement * player.m_dpiAff;
Shinya Kitaoka 120a6e
  aff         = TTranslation(m_dim.lx / 2.0, m_dim.ly / 2.0) * aff *
Shinya Kitaoka 120a6e
        TTranslation(-r->getCenterD());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TRectD bbox = TRectD(0, 0, m_dim.lx, m_dim.ly);
Shinya Kitaoka 120a6e
  bbox *= convert(m_clipRect);
Shinya Kitaoka 120a6e
  if (bbox.isEmpty()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int alpha                 = 255;
Shinya Kitaoka 120a6e
  Node::OnionMode onionMode = Node::eOnionSkinNone;
Shinya Kitaoka 120a6e
  if (player.m_onionSkinDistance != c_noOnionSkin) {
Jeremy Bullock ff7b10
    // GetOnionSkinFade is good for the vector while the raster works at the
Jeremy Bullock ff7b10
    //    Opposite 1 opaque -> 0 completely transparent
Jeremy Bullock ff7b10
    //    I therefore reverse the result of the function by being attentive to
Jeremy Bullock ff7b10
    //    case 0
Jeremy Bullock ff7b10
    //    (where the value 0.9 was carved)
Shinya Kitaoka 120a6e
    double onionSkiFade = player.m_onionSkinDistance == 0
Shinya Kitaoka 120a6e
                              ? 0.9
Shinya Kitaoka 120a6e
                              : (1.0 - OnionSkinMask::getOnionSkinFade(
Shinya Kitaoka 120a6e
                                           player.m_onionSkinDistance));
shun-iwasawa 646fd4
    alpha               = tcrop(tround(onionSkiFade * 255.0), 0, 255);
shun-iwasawa 1d5937
shun-iwasawa 1d5937
    if (player.m_isShiftAndTraceEnabled &&
shun-iwasawa 1d5937
        !Preferences::instance()->areOnionColorsUsedForShiftAndTraceGhosts())
shun-iwasawa 1d5937
      onionMode = Node::eOnionSkinNone;
shun-iwasawa 1d5937
    else {
shun-iwasawa 1d5937
      onionMode =
shun-iwasawa 1d5937
          (player.m_onionSkinDistance > 0)
shun-iwasawa 1d5937
              ? Node::eOnionSkinFront
shun-iwasawa 1d5937
              : ((player.m_onionSkinDistance < 0) ? Node::eOnionSkinBack
shun-iwasawa 1d5937
                                                  : Node::eOnionSkinNone);
shun-iwasawa 1d5937
    }
shun-iwasawa 1d5937
Shinya Kitaoka 120a6e
  } else if (player.m_opacity < 255)
Shinya Kitaoka 120a6e
    alpha = player.m_opacity;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  m_nodes.push_back(Node(r, ti->getPalette(), alpha, aff, ti->getSavebox(),
Shinya Kitaoka 120a6e
                         bbox, player.m_frame, player.m_isCurrentColumn,
shun_iwasawa a3cdd8
                         onionMode, false, false, false, player.m_filterColor));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
//    OpenGLPainter  implementation
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
OpenGlPainter::OpenGlPainter(const TAffine &viewAff, const TRect &rect,
Shinya Kitaoka 120a6e
                             const ImagePainter::VisualSettings &vs,
Shinya Kitaoka 120a6e
                             bool isViewer, bool alphaEnabled)
Shinya Kitaoka 120a6e
    : Visitor(vs)
Shinya Kitaoka 120a6e
    , m_viewAff(viewAff)
Shinya Kitaoka 120a6e
    , m_clipRect(rect)
Shinya Kitaoka 120a6e
    , m_camera3d(false)
Shinya Kitaoka 120a6e
    , m_phi(0)
Shinya Kitaoka 120a6e
    , m_maskLevel(0)
Shinya Kitaoka 120a6e
    , m_isViewer(isViewer)
Shinya Kitaoka 120a6e
    , m_alphaEnabled(alphaEnabled)
Shinya Kitaoka 120a6e
    , m_paletteHasChanged(false)
Shinya Kitaoka 120a6e
    , m_minZ(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OpenGlPainter::onImage(const Stage::Player &player) {
Shinya Kitaoka 120a6e
  if (player.m_z < m_minZ) m_minZ = player.m_z;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glPushAttrib(GL_ALL_ATTRIB_BITS);
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_camera3d)
Shinya Kitaoka 120a6e
    glTranslated(
Shinya Kitaoka 120a6e
        0, 0,
Shinya Kitaoka 120a6e
        player.m_z);  // Ok, move object along z as specified in the player
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Attempt Plastic-deformed drawing
Shinya Kitaoka 120a6e
  if (TStageObject *obj =
Shinya Kitaoka 120a6e
          ::plasticDeformedObj(player, m_vs.m_plasticVisualSettings))
Shinya Kitaoka 120a6e
    ::onPlasticDeformedImage(obj, player, m_vs, m_viewAff);
Shinya Kitaoka 120a6e
  else if (const TImageP &image = player.image()) {
Shinya Kitaoka 120a6e
    if (TVectorImageP vi = image)
Shinya Kitaoka 120a6e
      onVectorImage(vi.getPointer(), player);
Shinya Kitaoka 120a6e
    else if (TRasterImageP ri = image)
Shinya Kitaoka 120a6e
      onRasterImage(ri.getPointer(), player);
Shinya Kitaoka 120a6e
    else if (TToonzImageP ti = image)
Shinya Kitaoka 120a6e
      onToonzImage(ti.getPointer(), player);
Shinya Kitaoka 120a6e
    else if (TMeshImageP mi = image)
Shinya Kitaoka 120a6e
      onMeshImage(mi.getPointer(), player, m_vs, m_viewAff);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glPopMatrix();
Shinya Kitaoka 120a6e
  glPopAttrib();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OpenGlPainter::onVectorImage(TVectorImage *vi,
Shinya Kitaoka 120a6e
                                  const Stage::Player &player) {
Shinya Kitaoka 120a6e
  if (m_camera3d && (player.m_onionSkinDistance == c_noOnionSkin ||
Shinya Kitaoka 120a6e
                     player.m_onionSkinDistance == 0)) {
Shinya Kitaoka 120a6e
    const TRectD &bbox = player.m_placement * player.m_dpiAff * vi->getBBox();
Shinya Kitaoka 120a6e
    draw3DShadow(bbox, player.m_z, m_phi);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TColorFunction *cf = 0;
Shinya Kitaoka 120a6e
  TOnionFader fader;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TPalette *vPalette = vi->getPalette();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  int oldFrame = vPalette->getFrame();
Shinya Kitaoka 120a6e
  vPalette->setFrame(player.m_frame);  // Hehe. Should be locking
Shinya Kitaoka 120a6e
                                       // vPalette's mutex here...
Shinya Kitaoka 120a6e
  if (player.m_onionSkinDistance != c_noOnionSkin) {
Shinya Kitaoka 120a6e
    TPixel32 bgColor = TPixel32::White;
Shinya Kitaoka 120a6e
    fader            = TOnionFader(
Shinya Kitaoka 120a6e
        bgColor, OnionSkinMask::getOnionSkinFade(player.m_onionSkinDistance));
Shinya Kitaoka 120a6e
    cf = &fader;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TVectorRenderData rd =
Shinya Kitaoka 120a6e
      isViewer() ? TVectorRenderData(TVectorRenderData::ViewerSettings(),
Shinya Kitaoka 120a6e
                                     m_viewAff * player.m_placement, m_clipRect,
Shinya Kitaoka 120a6e
                                     vPalette)
Shinya Kitaoka 120a6e
                 : TVectorRenderData(TVectorRenderData::ProductionSettings(),
Shinya Kitaoka 120a6e
                                     m_viewAff * player.m_placement, m_clipRect,
Shinya Kitaoka 120a6e
                                     vPalette);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  rd.m_alphaChannel = m_alphaEnabled;
Shinya Kitaoka 120a6e
  rd.m_is3dView     = m_camera3d;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (m_maskLevel > 0)
Shinya Kitaoka 120a6e
    tglDrawMask(rd, vi);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    tglDraw(rd, vi);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  vPalette->setFrame(oldFrame);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OpenGlPainter::onRasterImage(TRasterImage *ri,
Shinya Kitaoka 120a6e
                                  const Stage::Player &player) {
Shinya Kitaoka 120a6e
  if (m_camera3d && (player.m_onionSkinDistance == c_noOnionSkin ||
Shinya Kitaoka 120a6e
                     player.m_onionSkinDistance == 0)) {
Shinya Kitaoka 120a6e
    TRectD bbox(ri->getBBox());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Since bbox is in image coordinates, adjust to level coordinates first
Shinya Kitaoka 120a6e
    bbox -= ri->getRaster()->getCenterD() - convert(ri->getOffset());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Then, to world coordinates
Shinya Kitaoka 120a6e
    bbox = player.m_placement * player.m_dpiAff * bbox;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    draw3DShadow(bbox, player.m_z, m_phi);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool tlvFlag = player.m_sl && player.m_sl->getType() == TZP_XSHLEVEL;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (tlvFlag &&
Shinya Kitaoka 120a6e
      m_paletteHasChanged)  // o.o! Raster images here - should never be
Shinya Kitaoka 120a6e
    assert(false);          // dealing with tlv stuff!
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  bool premultiplied = tlvFlag;  // xD
Shinya Kitaoka 120a6e
  static std::vector<char></char>
luzpaz 27707d
      matteChan;  // Wtf this is criminal. Although probably this
Shinya Kitaoka 120a6e
                  // stuff is used only in the main thread... hmmm....
Shinya Kitaoka 120a6e
  TRaster32P r = (TRaster32P)ri->getRaster();
Shinya Kitaoka 120a6e
  r->lock();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (c_noOnionSkin != player.m_onionSkinDistance) {
Shinya Kitaoka 120a6e
    double fade =
Shinya Kitaoka 120a6e
        0.5 - 0.45 * (1 - 1 / (1 + 0.15 * abs(player.m_onionSkinDistance)));
Shinya Kitaoka 120a6e
    if ((int)matteChan.size() < r->getLx() * r->getLy())
Shinya Kitaoka 120a6e
      matteChan.resize(r->getLx() * r->getLy());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int k = 0;
Shinya Kitaoka 120a6e
    for (int y = 0; y < r->getLy(); ++y) {
Shinya Kitaoka 120a6e
      TPixel32 *pix    = r->pixels(y);
Shinya Kitaoka 120a6e
      TPixel32 *endPix = pix + r->getLx();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      while (pix < endPix) {
Shinya Kitaoka 120a6e
        matteChan[k++] = pix->m;
Shinya Kitaoka 120a6e
        pix->m         = (int)(pix->m * fade);
Shinya Kitaoka 120a6e
        pix++;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    premultiplied = false;  // pfff
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TAffine aff = player.m_dpiAff;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPushAttrib(GL_ALL_ATTRIB_BITS);
Shinya Kitaoka 120a6e
  tglEnableBlending(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  GLRasterPainter::drawRaster(m_viewAff * player.m_placement * aff *
Shinya Kitaoka 120a6e
                                  TTranslation(convert(ri->getOffset())),
Shinya Kitaoka 120a6e
                              ri, premultiplied);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPopAttrib();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (c_noOnionSkin != player.m_onionSkinDistance) {
Shinya Kitaoka 120a6e
    int k = 0;
Shinya Kitaoka 120a6e
    for (int y = 0; y < r->getLy(); ++y) {
Shinya Kitaoka 120a6e
      TPixel32 *pix    = r->pixels(y);
Shinya Kitaoka 120a6e
      TPixel32 *endPix = pix + r->getLx();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      while (pix < endPix) pix++->m = matteChan[k++];
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  r->unlock();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OpenGlPainter::onToonzImage(TToonzImage *ti, const Stage::Player &player) {
Shinya Kitaoka 120a6e
  if (m_camera3d && (player.m_onionSkinDistance == c_noOnionSkin ||
Shinya Kitaoka 120a6e
                     player.m_onionSkinDistance == 0)) {
Shinya Kitaoka 120a6e
    TRectD bbox(ti->getBBox());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    bbox -= ti->getRaster()->getCenterD();
Shinya Kitaoka 120a6e
    bbox = player.m_placement * player.m_dpiAff * bbox;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    draw3DShadow(bbox, player.m_z, m_phi);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterCM32P ras = ti->getRaster();
Shinya Kitaoka 120a6e
  TRaster32P ras32(ras->getSize());
Shinya Kitaoka 120a6e
  ras32->fill(TPixel32(0, 0, 0, 0));
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // onionSkin
Shinya Kitaoka 120a6e
  TRop::quickPut(ras32, ras, ti->getPalette(), TAffine());
Shinya Kitaoka 120a6e
  TAffine aff = player.m_dpiAff;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TRasterImageP ri(ras32);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  GLRasterPainter::drawRaster(m_viewAff * player.m_placement * aff, ri, true);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void OpenGlPainter::beginMask() {
Shinya Kitaoka 120a6e
  ++m_maskLevel;
Shinya Kitaoka 120a6e
  TStencilControl::instance()->beginMask();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
void OpenGlPainter::endMask() {
Shinya Kitaoka 120a6e
  --m_maskLevel;
Shinya Kitaoka 120a6e
  TStencilControl::instance()->endMask();
Shinya Kitaoka 120a6e
}
Shinya Kitaoka 120a6e
void OpenGlPainter::enableMask() {
Shinya Kitaoka 120a6e
  TStencilControl::instance()->enableMask(TStencilControl::SHOW_INSIDE);
Toshihiro Shimizu 890ddd
}
Shinya Kitaoka 120a6e
void OpenGlPainter::disableMask() {
Shinya Kitaoka 120a6e
  TStencilControl::instance()->disableMask();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
//    Plastic functions  implementation
Toshihiro Shimizu 890ddd
//**********************************************************************************************
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
namespace {
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
TStageObject *plasticDeformedObj(const Stage::Player &player,
Shinya Kitaoka 120a6e
                                 const PlasticVisualSettings &pvs) {
Shinya Kitaoka 120a6e
  struct locals {
Shinya Kitaoka 120a6e
    static inline bool isDeformableMeshColumn(
Shinya Kitaoka 120a6e
        TXshColumn *column, const PlasticVisualSettings &pvs) {
Shinya Kitaoka 120a6e
      return (column->getColumnType() == TXshColumn::eMeshType) &&
Shinya Kitaoka 120a6e
             (pvs.m_showOriginalColumn != column);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    static inline bool isDeformableMeshLevel(TXshSimpleLevel *sl) {
Shinya Kitaoka 120a6e
      return sl && (sl->getType() == MESH_XSHLEVEL);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };  // locals
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (pvs.m_applyPlasticDeformation && player.m_column >= 0) {
Shinya Kitaoka 120a6e
    // Check whether the player's column is a direct stage-schematic child of a
Shinya Kitaoka 120a6e
    // mesh object
Shinya Kitaoka 120a6e
    TStageObject *playerObj =
Shinya Kitaoka 120a6e
        player.m_xsh->getStageObject(TStageObjectId::ColumnId(player.m_column));
Shinya Kitaoka 120a6e
    assert(playerObj);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    const TStageObjectId &parentId = playerObj->getParent();
Shinya Kitaoka 120a6e
    if (parentId.isColumn() && playerObj->getParentHandle()[0] != 'H') {
Shinya Kitaoka 120a6e
      TXshColumn *parentCol = player.m_xsh->getColumn(parentId.getIndex());
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      if (locals::isDeformableMeshColumn(parentCol, pvs) &&
Shinya Kitaoka 120a6e
          !locals::isDeformableMeshLevel(player.m_sl)) {
Shinya Kitaoka 120a6e
        const SkDP &sd = player.m_xsh->getStageObject(parentId)
Shinya Kitaoka 120a6e
                             ->getPlasticSkeletonDeformation();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        const TXshCell &parentCell =
Shinya Kitaoka 120a6e
            player.m_xsh->getCell(player.m_frame, parentId.getIndex());
Shinya Kitaoka 120a6e
        TXshSimpleLevel *parentSl = parentCell.getSimpleLevel();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
        if (sd && locals::isDeformableMeshLevel(parentSl)) return playerObj;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void onMeshImage(TMeshImage *mi, const Stage::Player &player,
Shinya Kitaoka 120a6e
                 const ImagePainter::VisualSettings &vs,
Shinya Kitaoka 120a6e
                 const TAffine &viewAff) {
Shinya Kitaoka 120a6e
  assert(mi);
Shinya Kitaoka 120a6e
shun-iwasawa 84ffc5
  static const double soMinColor[4]  = {0.0, 0.0, 0.0,
shun-iwasawa 646fd4
                                        0.6};  // Translucent black
shun-iwasawa 84ffc5
  static const double soMaxColor[4]  = {1.0, 1.0, 1.0,
shun-iwasawa 646fd4
                                        0.6};  // Translucent white
Shinya Kitaoka 120a6e
  static const double rigMinColor[4] = {0.0, 1.0, 0.0,
Shinya Kitaoka 120a6e
                                        0.6};  // Translucent green
Shinya Kitaoka 120a6e
  static const double rigMaxColor[4] = {1.0, 0.0, 0.0, 0.6};  // Translucent red
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool doOnionSkin    = (player.m_onionSkinDistance != c_noOnionSkin);
Shinya Kitaoka 120a6e
  bool onionSkinImage = doOnionSkin && (player.m_onionSkinDistance != 0);
Shinya Kitaoka 120a6e
  bool drawMeshes =
Shinya Kitaoka 120a6e
      vs.m_plasticVisualSettings.m_drawMeshesWireframe && !onionSkinImage;
Shinya Kitaoka 120a6e
  bool drawSO = vs.m_plasticVisualSettings.m_drawSO && !onionSkinImage;
Shinya Kitaoka 120a6e
  bool drawRigidity =
Shinya Kitaoka 120a6e
      vs.m_plasticVisualSettings.m_drawRigidity && !onionSkinImage;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Currently skipping onion skinned meshes
Shinya Kitaoka 120a6e
  if (onionSkinImage) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Build dpi
Shinya Kitaoka 120a6e
  TPointD meshSlDpi(player.m_sl->getDpi(player.m_fid, 0));
Shinya Kitaoka 120a6e
  assert(meshSlDpi.x != 0.0 && meshSlDpi.y != 0.0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Build reference change affines
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const TAffine &worldMeshToMeshAff =
Shinya Kitaoka 120a6e
      TScale(meshSlDpi.x / Stage::inch, meshSlDpi.y / Stage::inch);
Shinya Kitaoka 120a6e
  const TAffine &meshToWorldMeshAff =
Shinya Kitaoka 120a6e
      TScale(Stage::inch / meshSlDpi.x, Stage::inch / meshSlDpi.y);
Shinya Kitaoka 120a6e
  const TAffine &worldMeshToWorldAff = player.m_placement;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  const TAffine &meshToWorldAff = worldMeshToWorldAff * meshToWorldMeshAff;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Prepare OpenGL
Shinya Kitaoka 120a6e
  glEnable(GL_BLEND);
shun-iwasawa ecfcc0
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Shinya Kitaoka 120a6e
  glEnable(GL_LINE_SMOOTH);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Push mesh coordinates
Shinya Kitaoka 120a6e
  glPushMatrix();
Shinya Kitaoka 120a6e
  tglMultMatrix(viewAff * meshToWorldAff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Fetch deformation
Shinya Kitaoka 120a6e
  PlasticSkeletonDeformation *deformation = 0;
Shinya Kitaoka 120a6e
  double sdFrame;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (vs.m_plasticVisualSettings.m_applyPlasticDeformation &&
Shinya Kitaoka 120a6e
      player.m_column >= 0) {
Shinya Kitaoka 120a6e
    TXshColumn *column = player.m_xsh->getColumn(player.m_column);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (column != vs.m_plasticVisualSettings.m_showOriginalColumn) {
Shinya Kitaoka 120a6e
      TStageObject *playerObj = player.m_xsh->getStageObject(
Shinya Kitaoka 120a6e
          TStageObjectId::ColumnId(player.m_column));
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      deformation = playerObj->getPlasticSkeletonDeformation().getPointer();
Shinya Kitaoka 120a6e
      sdFrame     = playerObj->paramsTime(player.m_frame);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (deformation) {
Shinya Kitaoka 120a6e
    // Retrieve the associated plastic deformers data (this may eventually
Shinya Kitaoka 120a6e
    // update the deforms)
Shinya Kitaoka 120a6e
    const PlasticDeformerDataGroup *dataGroup =
Shinya Kitaoka 120a6e
        PlasticDeformerStorage::instance()->process(
Shinya Kitaoka 120a6e
            sdFrame, mi, deformation, deformation->skeletonId(sdFrame),
Shinya Kitaoka 120a6e
            worldMeshToMeshAff);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Draw faces first
Shinya Kitaoka 120a6e
    if (drawSO)
Shinya Kitaoka 120a6e
      tglDrawSO(*mi, (double *)soMinColor, (double *)soMaxColor, dataGroup,
Shinya Kitaoka 120a6e
                true);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (drawRigidity)
Shinya Kitaoka 120a6e
      tglDrawRigidity(*mi, (double *)rigMinColor, (double *)rigMaxColor,
Shinya Kitaoka 120a6e
                      dataGroup, true);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Draw edges next
Shinya Kitaoka 120a6e
    if (drawMeshes) {
Shinya Kitaoka 120a6e
      glColor4d(0.0, 1.0, 0.0, 0.7 * player.m_opacity / 255.0);  // Green
Shinya Kitaoka 120a6e
      tglDrawEdges(*mi, dataGroup);  // The mesh must be deformed
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else {
Shinya Kitaoka 120a6e
    // Draw un-deformed data
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Draw faces first
Shinya Kitaoka 120a6e
    if (drawSO) tglDrawSO(*mi, (double *)soMinColor, (double *)soMaxColor);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (drawRigidity)
Shinya Kitaoka 120a6e
      tglDrawRigidity(*mi, (double *)rigMinColor, (double *)rigMaxColor);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    // Just draw the mesh image next
Shinya Kitaoka 120a6e
    if (drawMeshes) {
Shinya Kitaoka 120a6e
      glColor4d(0.0, 1.0, 0.0, 0.7 * player.m_opacity / 255.0);  // Green
Shinya Kitaoka 120a6e
      tglDrawEdges(*mi);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Cleanup OpenGL
Shinya Kitaoka 120a6e
  glPopMatrix();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  glDisable(GL_LINE_SMOOTH);
Shinya Kitaoka 120a6e
  glDisable(GL_BLEND);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Applies Plastic deformation of the specified player's stage object.
Shinya Kitaoka 120a6e
void onPlasticDeformedImage(TStageObject *playerObj,
Shinya Kitaoka 120a6e
                            const Stage::Player &player,
Shinya Kitaoka 120a6e
                            const ImagePainter::VisualSettings &vs,
Shinya Kitaoka 120a6e
                            const TAffine &viewAff) {
Shinya Kitaoka 120a6e
  bool doOnionSkin    = (player.m_onionSkinDistance != c_noOnionSkin);
Shinya Kitaoka 120a6e
  bool onionSkinImage = doOnionSkin && (player.m_onionSkinDistance != 0);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Deal with color scaling due to transparency / onion skin
Shinya Kitaoka 120a6e
  double pixScale[4] = {1.0, 1.0, 1.0, 1.0};
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  if (doOnionSkin) {
Shinya Kitaoka 120a6e
    if (onionSkinImage) {
Shinya Kitaoka 120a6e
      TPixel32 frontOnionColor, backOnionColor;
Shinya Kitaoka 120a6e
      bool inksOnly;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      Preferences::instance()->getOnionData(frontOnionColor, backOnionColor,
Shinya Kitaoka 120a6e
                                            inksOnly);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
      const TPixel32 &refColor =
Shinya Kitaoka 120a6e
          (player.m_onionSkinDistance < 0) ? backOnionColor : frontOnionColor;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      pixScale[3] =
Shinya Kitaoka 120a6e
          1.0 - OnionSkinMask::getOnionSkinFade(player.m_onionSkinDistance);
Shinya Kitaoka 120a6e
      pixScale[0] =
Shinya Kitaoka 120a6e
          (refColor.r / 255.0) * pixScale[3];  // refColor is not premultiplied
Shinya Kitaoka 120a6e
      pixScale[1] = (refColor.g / 255.0) * pixScale[3];
Shinya Kitaoka 120a6e
      pixScale[2] = (refColor.b / 255.0) * pixScale[3];
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  } else if (player.m_opacity < 255) {
Shinya Kitaoka 120a6e
    pixScale[3] = player.m_opacity / 255.0;
Shinya Kitaoka 120a6e
    pixScale[0] = pixScale[1] = pixScale[2] = 0.0;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build the Mesh-related data
Shinya Kitaoka 120a6e
  const TXshCell &cell =
Shinya Kitaoka 120a6e
      player.m_xsh->getCell(player.m_frame, playerObj->getParent().getIndex());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TXshSimpleLevel *meshLevel = cell.getSimpleLevel();
Shinya Kitaoka 120a6e
  const TFrameId &meshFid    = cell.getFrameId();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TMeshImageP &mi = meshLevel->getFrame(meshFid, false);
Shinya Kitaoka 120a6e
  if (!mi) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build deformation-related data
Shinya Kitaoka 120a6e
  TStageObject *parentObj =
Shinya Kitaoka 120a6e
      player.m_xsh->getStageObject(playerObj->getParent());
Shinya Kitaoka 120a6e
  assert(playerObj);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const PlasticSkeletonDeformationP &deformation =
Shinya Kitaoka 120a6e
      parentObj->getPlasticSkeletonDeformation().getPointer();
Shinya Kitaoka 120a6e
  assert(deformation);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  double sdFrame = parentObj->paramsTime(player.m_frame);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build dpis
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD meshSlDpi(meshLevel->getDpi(meshFid, 0));
Shinya Kitaoka 120a6e
  assert(meshSlDpi.x != 0.0 && meshSlDpi.y != 0.0);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  TPointD slDpi(player.m_sl ? player.m_sl->getDpi(player.m_fid, 0) : TPointD());
Shinya Kitaoka 120a6e
  if (slDpi.x == 0.0 || slDpi.y == 0.0 ||
Shinya Kitaoka 120a6e
      player.m_sl->getType() == PLI_XSHLEVEL)
Shinya Kitaoka 120a6e
    slDpi.x = slDpi.y = Stage::inch;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build reference transforms
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TAffine &worldTextureToWorldMeshAff =
Shinya Kitaoka 120a6e
      playerObj->getLocalPlacement(player.m_frame);
Shinya Kitaoka 120a6e
  const TAffine &worldTextureToWorldAff = player.m_placement;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (fabs(worldTextureToWorldMeshAff.det()) < 1e-6)
Shinya Kitaoka 120a6e
    return;  // Skip near-singular mesh/texture placements
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TAffine &worldMeshToWorldTextureAff = worldTextureToWorldMeshAff.inv();
Shinya Kitaoka 120a6e
  const TAffine &worldMeshToWorldAff =
Shinya Kitaoka 120a6e
      worldTextureToWorldAff * worldMeshToWorldTextureAff;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TAffine &meshToWorldMeshAff =
Shinya Kitaoka 120a6e
      TScale(Stage::inch / meshSlDpi.x, Stage::inch / meshSlDpi.y);
Shinya Kitaoka 120a6e
  const TAffine &worldMeshToMeshAff =
Shinya Kitaoka 120a6e
      TScale(meshSlDpi.x / Stage::inch, meshSlDpi.y / Stage::inch);
Shinya Kitaoka 120a6e
  const TAffine &worldTextureToTextureAff = TScale(
Shinya Kitaoka 120a6e
      slDpi.x / Stage::inch,
Shinya Kitaoka 120a6e
      slDpi.y /
Shinya Kitaoka 120a6e
          Stage::inch);  // ::getDpiScale().inv() should be used instead...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  const TAffine &meshToWorldAff   = worldMeshToWorldAff * meshToWorldMeshAff;
Shinya Kitaoka 120a6e
  const TAffine &meshToTextureAff = worldTextureToTextureAff *
Shinya Kitaoka 120a6e
                                    worldMeshToWorldTextureAff *
Shinya Kitaoka 120a6e
                                    meshToWorldMeshAff;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve a drawable texture from the player's simple level
Shinya Kitaoka 120a6e
  const DrawableTextureDataP &texData = player.texture();
Shinya Kitaoka 120a6e
  if (!texData) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve the associated plastic deformers data (this may eventually update
Shinya Kitaoka 120a6e
  // the deforms)
Shinya Kitaoka 120a6e
  const PlasticDeformerDataGroup *dataGroup =
Shinya Kitaoka 120a6e
      PlasticDeformerStorage::instance()->process(
Shinya Kitaoka 120a6e
          sdFrame, mi.getPointer(), deformation.getPointer(),
Shinya Kitaoka 120a6e
          deformation->skeletonId(sdFrame), worldMeshToMeshAff);
Shinya Kitaoka 120a6e
  assert(dataGroup);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Set up OpenGL stuff
Shinya Kitaoka 120a6e
  glEnable(GL_BLEND);
shun-iwasawa ecfcc0
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Shinya Kitaoka 120a6e
  glEnable(GL_LINE_SMOOTH);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Push mesh coordinates
Shinya Kitaoka 120a6e
  glPushMatrix();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  tglMultMatrix(viewAff * meshToWorldAff);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glEnable(GL_TEXTURE_2D);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Applying modulation by the specified transparency parameter
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glColor4d(pixScale[3], pixScale[3], pixScale[3], pixScale[3]);
Shinya Kitaoka 120a6e
  tglDraw(*mi, *texData, meshToTextureAff, *dataGroup);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glDisable(GL_TEXTURE_2D);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (onionSkinImage) {
Shinya Kitaoka 120a6e
    glBlendFunc(GL_ONE, GL_ONE);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Add Onion skin color. Observe that this way we don't consider blending
Shinya Kitaoka 120a6e
    // with the texture's
Shinya Kitaoka 120a6e
    // alpha - to obtain that, there is no simple way...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    double k = (1.0 - pixScale[3]);
Shinya Kitaoka 120a6e
    glColor4d(k * pixScale[0], k * pixScale[1], k * pixScale[2], 0.0);
Shinya Kitaoka 120a6e
    tglDrawFaces(*mi, dataGroup);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glPopMatrix();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  glDisable(GL_LINE_SMOOTH);
Shinya Kitaoka 120a6e
  glDisable(GL_BLEND);
shun_iwasawa 7e52a2
  assert(glGetError() == GL_NO_ERROR);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
}  // namespace