void multiAutocloseRegion(TStroke *stroke, const TMouseEvent &e) { TTool::Application *app = TTool::getApplication(); if (m_firstStroke) { multiApplyAutoclose(m_firstFrameId, getFrameId(), TRectD(), TRectD(), m_firstStroke, stroke); invalidate(); if (e.isShiftPressed()) { delete m_firstStroke; m_firstStroke = new TStroke(*stroke); m_firstFrameId = getFrameId(); } else { if (m_isXsheetCell) { app->getCurrentColumn()->setColumnIndex(m_currCell.first); app->getCurrentFrame()->setFrame(m_currCell.second); } else app->getCurrentFrame()->setFid(m_veryFirstFrameId); resetMulti(); } } else { m_isXsheetCell = app->getCurrentFrame()->isEditingScene(); // if (m_isXsheetCell) m_currCell = std::pair<int, int>(getColumnIndex(), getFrame()); m_firstStroke = new TStroke(*stroke); } return; }
void updateLevel() { TTool::Application *app = TTool::getApplication(); if (!app->getCurrentLevel()->getLevel()) return; TXshSimpleLevelP xl = app->getCurrentLevel()->getLevel()->getSimpleLevel(); if (app->getCurrentFrame()->getFrameType() != TFrameHandle::LevelFrame) return; TFrameId fid = app->getCurrentFrame()->getFid(); TVectorImageP src = xl->getFrame(fid, true); int count = src->getStrokeCount(); for (int i = 1; i < 10; i++) { ++fid; if (!xl->isFid(fid)) { TVectorImageP vi = new TVectorImage(); xl->setFrame(fid, vi); } TVectorImageP vi = xl->getFrame(fid, true); TVectorImageP dst = src->clone(); deform(dst.getPointer(), src.getPointer(), (double)i / (double)9); count = dst->getStrokeCount(); vi->mergeImage(dst, TAffine()); app->getCurrentTool()->getTool()->notifyImageChanged(fid); } }
void leftButtonDown(const TPointD &pos, const TMouseEvent &) override { TToonzImageP ti = TToonzImageP(getImage(true)); if (!ti) return; if (m_closeType.getValue() == RECT_CLOSE) { m_selecting = true; m_selectingRect.x0 = pos.x; m_selectingRect.y0 = pos.y; m_selectingRect.x1 = pos.x + 1; m_selectingRect.y1 = pos.y + 1; return; } else if (m_closeType.getValue() == FREEHAND_CLOSE) { startFreehand(pos); return; } else if (m_closeType.getValue() == POLYLINE_CLOSE) { addPointPolyline(pos); return; } else if (m_closeType.getValue() == NORMAL_CLOSE) { if (m_multi.getValue()) { TTool::Application *app = TTool::getApplication(); if (m_firstFrameSelected) { multiApplyAutoclose(m_firstFrameId, getFrameId()); invalidate(); if (m_isXsheetCell) { app->getCurrentColumn()->setColumnIndex(m_currCell.first); app->getCurrentFrame()->setFrame(m_currCell.second); } else app->getCurrentFrame()->setFid(m_veryFirstFrameId); resetMulti(); } else { m_isXsheetCell = app->getCurrentFrame()->isEditingScene(); // if (m_isXsheetCell) m_currCell = std::pair<int, int>(getColumnIndex(), getFrame()); m_firstFrameSelected = true; m_firstPoint = pos; } invalidate(); return; } m_selecting = false; applyAutoclose(ti); invalidate(); notifyImageChanged(); } }
TAffine TTool::getCurrentObjectParentMatrix2() const { TTool::Application *app = m_application; TFrameHandle *fh = app->getCurrentFrame(); if (fh->isEditingLevel()) return TAffine(); int frame = fh->getFrame(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); TStageObjectId id = app->getCurrentObject()->getObjectId(); double objZ = xsh->getZ(id, frame); TStageObjectId parentId = xsh->getStageObjectParent(id); if (parentId == TStageObjectId::NoneId) return TAffine(); id = parentId; TAffine objPlacement = xsh->getPlacement(id, frame); TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *camera = xsh->getStageObject(cameraId); TAffine cameraPlacement = camera->getPlacement(frame); double cameraZ = camera->getZ(frame); TAffine placement; TStageObject::perspective(placement, cameraPlacement, cameraZ, objPlacement, objZ, 0); return placement; }
void leftButtonUp(const TPointD &pos, const TMouseEvent &e) override { TToonzImageP ti = TToonzImageP(getImage(true)); if (!ti) return; /*-- Rectの座標の向きを揃える --*/ if (m_selectingRect.x0 > m_selectingRect.x1) tswap(m_selectingRect.x1, m_selectingRect.x0); if (m_selectingRect.y0 > m_selectingRect.y1) tswap(m_selectingRect.y1, m_selectingRect.y0); TTool::Application *app = TTool::getApplication(); m_selecting = false; TRasterCM32P ras; if (m_closeType.getValue() == RECT_CLOSE) { if (m_multi.getValue()) { if (m_firstFrameSelected) { multiApplyAutoclose(m_firstFrameId, getFrameId(), m_firstRect, m_selectingRect); invalidate(m_selectingRect.enlarge(2)); if (e.isShiftPressed()) { m_firstRect = m_selectingRect; m_firstFrameId = getFrameId(); } else { if (m_isXsheetCell) { app->getCurrentColumn()->setColumnIndex(m_currCell.first); app->getCurrentFrame()->setFrame(m_currCell.second); } else app->getCurrentFrame()->setFid(m_veryFirstFrameId); resetMulti(); } } else { m_isXsheetCell = app->getCurrentFrame()->isEditingScene(); // if (m_isXsheetCell) m_currCell = std::pair<int, int>(getColumnIndex(), this->getFrame()); } return; } /*-- AutoCloseが実行されたか判定する --*/ if (!applyAutoclose(ti, m_selectingRect)) { if (m_stroke) { delete m_stroke; m_stroke = 0; } invalidate(); return; } invalidate(); notifyImageChanged(); } else if (m_closeType.getValue() == FREEHAND_CLOSE) { closeFreehand(pos); if (m_multi.getValue()) multiAutocloseRegion(m_stroke, e); else applyAutoclose(ti, TRectD(), m_stroke); m_track.clear(); invalidate(); } if (m_stroke) { delete m_stroke; m_stroke = 0; } }
void SkeletonTool::drawHooks() { // camera stand reference system //glColor3d(0,0,1); //tglDrawRect(3,3,97,97); //glColor3d(0,1,1); //tglDrawRect(0,100,Stage::inch,110); QTime time; time.start(); m_magicLinks.clear(); computeMagicLinks(); TTool::Application *app = TTool::getApplication(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); int row = app->getCurrentFrame()->getFrame(); int col = app->getCurrentColumn()->getColumnIndex(); TPointD dpiScale = getViewer()->getDpiScale(); // glColor3d(1,0,1); // tglDrawRect(-100*dpiScale.x, -100*dpiScale.y, 0,0); // I should not show hooks of columns already connected with the current one // ("linking" to those hooks would create evil loops in the hierarchy) std::set<int> connectedColumns; getConnectedColumns(connectedColumns, xsh, col); std::vector<HookData> currentColumnHooks; std::vector<HookData> otherColumnsHooks; // fill currentColumnHooks // detect otherColumn (i.e. the active column during a click&drag operator int otherColumn = -1; if (m_parentProbeEnabled) { // qDebug(" parent probe enabled"); // currentColumnHooks <- current column & current handle int hookId = 0; std::string handle = xsh->getStageObject(TStageObjectId::ColumnId(col))->getHandle(); if (handle.find("H") == 0) { int j = 1; while (j < (int)handle.size() && '0' <= handle[j] && handle[j] <= '9') { hookId = hookId * 10 + (int)handle[j] - '0'; j++; } } currentColumnHooks.push_back(HookData(xsh, col, hookId, m_parentProbe)); // otherColumn = "picked" column not connected TPoint parentProbePos = getViewer()->worldToPos(m_parentProbe); std::vector<int> indexes; getViewer()->posToColumnIndexes(parentProbePos, indexes, getPixelSize() * 10, false); for (int i = (int)indexes.size() - 1; i >= 0; i--) { if (connectedColumns.count(indexes[i]) == 0) { otherColumn = indexes[i]; break; } } // if the mouse is not on a stroke, I'm using the "old" m_otherColumn, if any. // (this is needed because of the hooks put inside of unfilled regions) if (otherColumn < 0 && m_otherColumn >= 0) { if (m_otherColumnBBox.contains(m_otherColumnBBoxAff.inv() * m_parentProbe)) otherColumn = m_otherColumn; else m_otherColumn = -1; } } else { // parent probe not enabled: get all hooks of current column. other column = -1 getHooks(currentColumnHooks, xsh, row, col, TPointD(1, 1)); // dpiScale); } // other columns hooks <- all hooks of all unlinked columns for (int i = 0; i < xsh->getColumnCount(); i++) if (xsh->getColumn(i)->isCamstandVisible()) if (connectedColumns.count(i) == 0) getHooks(otherColumnsHooks, xsh, row, i, TPointD(1, 1)); // dpiScale); /* qDebug(" time=%dms", time.elapsed()); qDebug(" %d hooks (current column)", currentColumnHooks.size()); for(int i=0;i<(int)currentColumnHooks.size();i++) qDebug(" %d,%d",currentColumnHooks[i].m_columnIndex,currentColumnHooks[i].m_hookId); qDebug(" %d hooks (other columns)", otherColumnsHooks.size()); for(int i=0;i<(int)otherColumnsHooks.size();i++) qDebug(" %d,%d",otherColumnsHooks[i].m_columnIndex,otherColumnsHooks[i].m_hookId); */ std::vector<TRectD> balloons; // draw current column hooks for (int i = 0; i < (int)currentColumnHooks.size(); i++) { const HookData &hook = currentColumnHooks[i]; if (hook.m_name == "") continue; // should not happen int code = TD_Hook + hook.m_hookId; TPointD pos = hook.m_pos; ToolUtils::drawHook(pos, ToolUtils::OtherLevelHook); glPushName(code); TPixel32 color(200, 220, 205, 200); if (hook.m_isPivot) color = TPixel32(200, 200, 10, 200); else if (code == m_device) color = TPixel32(185, 255, 255); ToolUtils::drawBalloon(pos, hook.m_name, color, TPoint(20, 20), isPicking(), &balloons); glPopName(); } if (m_parentProbeEnabled) { for (int i = 0; i < (int)otherColumnsHooks.size(); i++) ToolUtils::drawHook(otherColumnsHooks[i].m_pos, ToolUtils::OtherLevelHook); } // search for magic links double minDist2 = 0; double snapRadius2 = 100 * getPixelSize() * getPixelSize(); double snapRadius2bis = 100; if (!m_parentProbeEnabled) { // "static" magic links: no parent probe for (int i = 0; i < (int)currentColumnHooks.size(); i++) { for (int j = 0; j < (int)otherColumnsHooks.size(); j++) { double dist2 = norm2(currentColumnHooks[i].m_pos - otherColumnsHooks[j].m_pos); if (currentColumnHooks[i].m_hookId == 0 || otherColumnsHooks[j].m_hookId == 0) continue; if (dist2 < snapRadius2bis) { m_magicLinks.push_back(MagicLink(currentColumnHooks[i], otherColumnsHooks[j], dist2)); qDebug(" magic link_a %d (%d,%d) %d (%d,%d); dist=%f", i, currentColumnHooks[i].m_columnIndex, currentColumnHooks[i].m_hookId, j, otherColumnsHooks[j].m_columnIndex, otherColumnsHooks[j].m_hookId, dist2); } } } } if (m_parentProbeEnabled) { // search for the closest hook of the picked column int i = -1, j = -1; double minDist2 = snapRadius2; for (i = 0; i < (int)otherColumnsHooks.size(); i++) { double dist2 = tdistance2(otherColumnsHooks[i].m_pos, m_parentProbe); if (dist2 < minDist2) { j = i; minDist2 = dist2; otherColumn = otherColumnsHooks[i].m_columnIndex; } } } if (m_parentProbeEnabled && otherColumn >= 0) // && m_magicLinks.empty() { // "dynamic" magic links: probing and picking a column // show image bounding box m_otherColumn = otherColumn; getImageBoundingBox(m_otherColumnBBox, m_otherColumnBBoxAff, row, otherColumn); if (!m_otherColumnBBox.isEmpty()) { glPushMatrix(); tglMultMatrix(m_otherColumnBBoxAff); ToolUtils::drawRect(m_otherColumnBBox, TPixel32(188, 202, 191), 0xF0F0); //tglDrawRect(img->getBBox()); glPopMatrix(); } /* TXshCell cell = xsh->getCell(row, otherColumn); //TAffine aff = xsh->getPlacement(TStageObjectId::ColumnId(otherColumn),row); //m_otherColumnAff = aff; TImageP img = cell.getImage(false); if(img) { getImageBoundingBox(m_otherColumnBBox, m_otherColumnBBoxAff, row, otherColumn); //glColor3d(188.0/255.0, 202.0/255.0, 191.0/255.0); glPushMatrix(); tglMultMatrix(aff * imageDpiAff); ToolUtils::drawRect(img->getBBox(), TPixel32(188,202,191), 0xF0F0); //tglDrawRect(img->getBBox()); glPopMatrix(); } */ // search for the closest hook of the picked column int i = -1, j = -1; double minDist2 = snapRadius2; for (i = 0; i < (int)otherColumnsHooks.size(); i++) if (otherColumnsHooks[i].m_columnIndex == otherColumn) { double dist2 = tdistance2(otherColumnsHooks[i].m_pos, m_parentProbe); if (j < 0) j = i; else if (dist2 < minDist2 || otherColumnsHooks[i].m_hookId == 0) { j = i; minDist2 = dist2; } } // visualize a balloon for the closest hook if (0 <= j && j < (int)otherColumnsHooks.size()) { // I want to get a specific color when overlaying the label on white int alfa = 100, ialfa = 255 - alfa; TPixel32 color(255 * (188 - ialfa) / alfa, 255 * (202 - ialfa) / alfa, 255 * (191 - ialfa) / alfa, alfa); ToolUtils::drawBalloon( otherColumnsHooks[j].m_pos, otherColumnsHooks[j].m_name, // getHandle(), color, TPoint(20, 20), false, &balloons); HookData baseHook = currentColumnHooks[0]; baseHook.m_pos = otherColumnsHooks[j].m_pos; // this is also a magic link m_magicLinks.push_back(MagicLink(baseHook, otherColumnsHooks[j], 10000)); } } // visualize all the magic links for (int i = 0; i < (int)m_magicLinks.size(); i++) { const MagicLink &magicLink = m_magicLinks[i]; const HookData &h1 = magicLink.m_h1; std::string name; name = (m_parentProbeEnabled ? "Linking " : "Link ") + removeTrailingH(magicLink.m_h0.getHandle()) + " to Col " + std::to_string(h1.m_columnIndex + 1) + "/" + removeTrailingH(h1.getHandle()); int code = TD_MagicLink + i; glPushName(code); TPixel32 color(100, 255, 100, 100); if (code == m_device) color = TPixel32(185, 255, 255); ToolUtils::drawBalloon(magicLink.m_h0.m_pos, name, color, TPoint(20, -20), isPicking(), &balloons); glPopName(); } }
void SkeletonTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) { m_otherColumn = -1; m_otherColumnBBox = TRectD(); m_otherColumnBBoxAff = TAffine(); m_labelPos = TPointD(0, 0); m_label = ""; TUndoManager::manager()->beginBlock(); if (!doesApply()) return; assert(m_dragTool == 0); m_dragTool = 0; TTool::Application *app = TTool::getApplication(); int currentColumnIndex = app->getCurrentColumn()->getColumnIndex(); TXsheet *xsh = app->getCurrentScene()->getScene()->getXsheet(); TPointD pos = ppos; int selectedDevice = pick(e.m_pos); // cambio drawing if (selectedDevice == TD_ChangeDrawing || selectedDevice == TD_IncrementDrawing || selectedDevice == TD_DecrementDrawing) { int d = 0; if (selectedDevice == TD_IncrementDrawing) d = 1; else if (selectedDevice == TD_DecrementDrawing) d = -1; m_dragTool = new ChangeDrawingTool(this, d); m_dragTool->leftButtonDown(ppos, e); return; } // click su un hook: attacca la colonna corrente tramite quell'hook if (TD_Hook <= selectedDevice && selectedDevice < TD_Hook + 50) { TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); TStageObjectId objId = TStageObjectId::ColumnId(currentColumnIndex); TPointD p0 = getCurrentColumnMatrix() * TPointD(0, 0); HookData hook(xsh, currentColumnIndex, selectedDevice - TD_Hook, p0); TStageObjectCmd::setHandle(objId, hook.getHandle(), app->getCurrentXsheet()); app->getCurrentXsheet()->notifyXsheetChanged(); invalidate(); return; } // magic link if (TD_MagicLink <= selectedDevice && selectedDevice < TD_MagicLink + (int)m_magicLinks.size()) { magicLink(selectedDevice - TD_MagicLink); app->getCurrentXsheet()->notifyXsheetChanged(); return; } m_device = selectedDevice; bool justSelected = false; if (m_device < 0) { // nessun gadget cliccato. Eventualmente seleziono la colonna std::vector<int> columnIndexes; getViewer()->posToColumnIndexes(e.m_pos, columnIndexes, getPixelSize() * 5, false); if (!columnIndexes.empty()) { int columnIndex; columnIndex = columnIndexes.back(); if (columnIndex >= 0 && columnIndex != currentColumnIndex) { if (!isColumnLocked(columnIndex)) { pos = getMatrix() * pos; app->getCurrentColumn()->setColumnIndex(columnIndex); updateMatrix(); currentColumnIndex = columnIndex; justSelected = true; pos = getMatrix().inv() * pos; } else { m_label = "Column is locked"; m_labelPos = pos; } } } } if (m_device < 0) { if (m_mode.getValue() == INVERSE_KINEMATICS) m_device = TD_InverseKinematics; else if (m_mode.getValue() == ANIMATE) m_device = TD_Rotation; } // lock/unlock: modalita IK if (TD_LockStageObject <= m_device && m_device < TD_LockStageObject + 1000) { int columnIndex = m_device - TD_LockStageObject; int frame = app->getCurrentFrame()->getFrame(); togglePinnedStatus(columnIndex, frame, e.isShiftPressed()); invalidate(); m_dragTool = 0; return; } switch (m_device) { case TD_Center: m_dragTool = new DragCenterTool(this); break; case TD_Translation: m_dragTool = new DragPositionTool(this); break; case TD_Rotation: m_dragTool = new DragRotationTool(this, justSelected); break; case TD_ChangeParent: m_dragTool = new ParentChangeTool(this, getViewer()); break; case TD_InverseKinematics: { Skeleton *skeleton = new Skeleton(); buildSkeleton(*skeleton, currentColumnIndex); m_dragTool = new IKTool(this, getViewer(), skeleton, currentColumnIndex); break; } } if (m_dragTool) { m_dragTool->leftButtonDown(pos, e); invalidate(); } }
void SkeletonTool::draw() { // parent object reference system //glColor3d(1,0,0); //tglDrawRect(0,0,100,100); if (m_label != "") ToolUtils::drawBalloon(m_labelPos, m_label, TPixel32::Red, TPoint(20, -20), false); bool ikEnabled = m_mode.getValue() == INVERSE_KINEMATICS; assert(glGetError() == GL_NO_ERROR); // l'xsheet, oggetto (e relativo placement), frame corrente TTool::Application *app = TTool::getApplication(); TXsheet *xsh = getXsheet(); assert(xsh); TStageObjectId objId = app->getCurrentObject()->getObjectId(); // se l'oggetto corrente non e' una colonna non disegno nulla if (!objId.isColumn()) return; TStageObject *pegbar = xsh->getStageObject(objId); int col = objId.getIndex(); int frame = app->getCurrentFrame()->getFrame(); if (m_currentFrame != frame) m_temporaryPinnedColumns.clear(); TAffine aff = getMatrix(); // puo' suggere che il placement degeneri (es.: c'e' uno h-scale = 0%) if (fabs(aff.det()) < 0.00001) return; // m_unit = getPixelSize() * sqrt(fabs(aff.det())); if (!ikEnabled) drawLevelBoundingBox(frame, col); glPushMatrix(); tglMultMatrix(aff.inv()); // camera stand reference system //glColor3d(0,1,0); //tglDrawRect(0,0,100,100); bool changingParent = dynamic_cast<ParentChangeTool *>(m_dragTool) != 0; // !changingParent && if (m_mode.getValue() == BUILD_SKELETON && !xsh->getStageObjectParent(objId).isColumn()) { if (!changingParent) drawHooks(); } Skeleton skeleton; buildSkeleton(skeleton, col); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); drawSkeleton(skeleton, frame); glDisable(GL_BLEND); TXshCell cell = xsh->getCell(frame, objId.getIndex()); Skeleton::Bone *rootBone = skeleton.getRootBone(); for (int i = 0; i < skeleton.getBoneCount(); i++) { Skeleton::Bone *bone = skeleton.getBone(i); TStageObjectId currentId = bone->getStageObject()->getId(); bool isCurrent = (currentId == objId); TPointD pos = bone->getCenter(); if (isCurrent && m_mode.getValue() != BUILD_SKELETON) { drawDrawingBrowser(cell, pos); } bool isActiveChain = bone->isSelected(); glColor3d(0, 1, 0); if (ikEnabled) { drawIKJoint(bone); } else { TPointD pos = bone->getCenter(); if (isCurrent && m_mode.getValue() == ANIMATE) { drawMainGadget(pos); } } } m_currentFrame = frame; if (m_dragTool) m_dragTool->draw(); glPopMatrix(); }