void FunctionViewer::showEvent(QShowEvent *) { refreshModel(); // Connect handles bool ret = true; if (m_xshHandle) { ret = connect(m_xshHandle, SIGNAL(xsheetChanged()), this, SLOT(refreshModel())) && ret; ret = connect(m_xshHandle, SIGNAL(xsheetSwitched()), this, SLOT(rebuildModel())) && ret; } if (m_frameHandle) ret = connect(m_frameHandle, SIGNAL(frameSwitched()), this, SLOT(propagateExternalSetFrame())) && ret; if (m_objectHandle) { ret = connect(m_objectHandle, SIGNAL(objectSwitched()), this, SLOT(onStageObjectSwitched())) && ret; ret = connect(m_objectHandle, SIGNAL(objectChanged(bool)), this, SLOT(onStageObjectChanged(bool))) && ret; } if (m_fxHandle) ret = connect(m_fxHandle, SIGNAL(fxSwitched()), this, SLOT(onFxSwitched())) && ret; // display animated channels when the scene is switched if (m_sceneHandle) ret = connect(m_sceneHandle, SIGNAL(sceneSwitched()), m_treeView, SLOT(displayAnimatedChannels())) && ret; assert(ret); m_treeView->setExpanded(m_treeView->model()->index(0, 0), true); m_treeView->setExpanded(m_treeView->model()->index(1, 0), true); FunctionTreeModel *ftm = static_cast<FunctionTreeModel *>(m_treeView->model()); if (m_objectHandle) { assert(m_xshHandle); TXsheet *xsh = m_xshHandle->getXsheet(); const TStageObjectId &objId = m_objectHandle->getObjectId(); ftm->setCurrentStageObject((objId == TStageObjectId::NoneId) ? (TStageObject *)0 : xsh->getStageObject(objId)); } if (m_fxHandle) ftm->setCurrentFx(m_fxHandle->getFx()); }
void TKeyframeSelection::setKeyframes() { TApp *app = TApp::instance(); TXsheetHandle *xsheetHandle = app->getCurrentXsheet(); TXsheet *xsh = xsheetHandle->getXsheet(); TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); if (isEmpty()) return; Position pos = *m_positions.begin(); int row = pos.first; int col = pos.second; TStageObjectId id = col < 0 ? cameraId : TStageObjectId::ColumnId(col); TStageObject *pegbar = xsh->getStageObject(id); if (!pegbar) return; if (pegbar->isKeyframe(row)) { TStageObject::Keyframe key = pegbar->getKeyframe(row); pegbar->removeKeyframeWithoutUndo(row); UndoRemoveKeyFrame *undo = new UndoRemoveKeyFrame(id, row, key, xsheetHandle); undo->setObjectHandle(app->getCurrentObject()); TUndoManager::manager()->add(undo); } else { pegbar->setKeyframeWithoutUndo(row); UndoSetKeyFrame *undo = new UndoSetKeyFrame(id, row, xsheetHandle); undo->setObjectHandle(app->getCurrentObject()); TUndoManager::manager()->add(undo); } TApp::instance()->getCurrentScene()->setDirtyFlag(true); TApp::instance()->getCurrentObject()->notifyObjectIdChanged(false); }
void SkeletonTool::magicLink(int index) { if (index < 0 || index >= (int)m_magicLinks.size()) return; HookData h0 = m_magicLinks[index].m_h0; HookData h1 = m_magicLinks[index].m_h1; TTool::Application *app = TTool::getApplication(); TXsheet *xsh = app->getCurrentXsheet()->getXsheet(); int columnIndex = app->getCurrentColumn()->getColumnIndex(); TStageObjectId id = TStageObjectId::ColumnId(columnIndex); TStageObject *obj = xsh->getStageObject(id); int parentColumnIndex = h1.m_columnIndex; TStageObjectId parentId = TStageObjectId::ColumnId(parentColumnIndex); std::string parentHandle = h1.getHandle(); std::string handle = ""; if (h0.m_columnIndex < 0) { handle = obj->getHandle(); } else { handle = h0.getHandle(); } //TUndoManager *undoManager = TUndoManager::manager(); //undoManager->beginBlock(); TStageObjectCmd::setHandle(id, handle, app->getCurrentXsheet()); TStageObjectCmd::setParent(id, parentId, parentHandle, app->getCurrentXsheet()); //undoManager->endBlock(); }
void Stage::visit(Visitor &visitor, const VisitArgs &args) { ToonzScene *scene = args.m_scene; TXsheet *xsh = args.m_xsh; int row = args.m_row; int col = args.m_col; const OnionSkinMask *osm = args.m_osm; bool camera3d = args.m_camera3d; int xsheetLevel = args.m_xsheetLevel; bool isPlaying = args.m_isPlaying; StageBuilder sb; sb.m_vs = &visitor.m_vs; TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *camera = xsh->getStageObject(cameraId); TAffine cameraAff = camera->getPlacement(row); double z = camera->getZ(row); sb.m_cameraPlacement = ZPlacement(cameraAff, z); sb.m_camera3d = camera3d; sb.m_currentColumnIndex = col; sb.m_xsheetLevel = xsheetLevel; sb.m_onionSkinMask = *osm; Player::m_onionSkinFrontSize = 0; Player::m_onionSkinBackSize = 0; sb.addFrame(sb.m_players, scene, xsh, row, 0, args.m_onlyVisible, args.m_checkPreviewVisibility); updateOnionSkinSize(sb.m_players); sb.visit(sb.m_players, visitor, isPlaying); }
void TApp::onSplineChanged() { if (m_currentObject->isSpline()) { TXsheet *xsh = m_currentXsheet->getXsheet(); TStageObject *currentObject = xsh->getStageObject(m_currentObject->getObjectId()); currentObject->setOffset(currentObject->getOffset()); //invalidate currentObject } }
void TCellKeyframeSelection::selectCellKeyframe(int row, int col) { m_cellSelection->selectCell(row, col); TXsheet *xsh = m_xsheetHandle->getXsheet(); TStageObjectId id = col < 0 ? TStageObjectId::CameraId(0) : TStageObjectId::ColumnId(col); TStageObject *stObj = xsh->getStageObject(id); m_keyframeSelection->clear(); if (stObj->isKeyframe(row)) m_keyframeSelection->select(row, col); }
void TApp::onObjectSwitched() { if (m_currentObject->isSpline()) { TXsheet *xsh = m_currentXsheet->getXsheet(); TStageObject *currentObject = xsh->getStageObject(m_currentObject->getObjectId()); TStageObjectSpline *ps = currentObject->getSpline(); m_currentObject->setSplineObject(ps); } else m_currentObject->setSplineObject(0); onImageChanged(); }
void SceneViewerContextMenu::addSelectCommand(QMenu *menu, const TStageObjectId &id) { TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TStageObject *stageObject = xsh->getStageObject(id); if (!stageObject) return; QString text = getName(stageObject); if (menu == this) text = "Select " + text; QAction *action = new QAction(text, this); action->setData(id.getCode()); connect(action, SIGNAL(triggered()), this, SLOT(onSetCurrent())); menu->addAction(action); }
void SceneViewerContextMenu::addShowHideCommand(QMenu *menu, TXshColumn *column) { bool isHidden = !column->isCamstandVisible(); TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TStageObject *stageObject = xsh->getStageObject(TStageObjectId::ColumnId(column->getIndex())); QString text = (isHidden ? "Show " : "Hide ") + getName(stageObject); QAction *action = new QAction(text, this); action->setData(column->getIndex()); connect(action, SIGNAL(triggered()), this, SLOT(onShowHide())); menu->addAction(action); }
TStageObject *ViewerKeyframeNavigator::getStageObject() const { if (!m_xsheetHandle || !m_objectHandle) return 0; TStageObjectId objectId = m_objectHandle->getObjectId(); TXsheet *xsh = m_xsheetHandle->getXsheet(); // Se e' una colonna sound non posso settare chiavi if (objectId.isColumn()) { TXshColumn *column = xsh->getColumn(objectId.getIndex()); if (column && column->getSoundColumn()) return 0; } return xsh->getStageObject(objectId); }
TAffine TTool::getColumnMatrix(int columnIndex) const { if (!m_application) return TAffine(); TFrameHandle *fh = m_application->getCurrentFrame(); if (fh->isEditingLevel()) return TAffine(); int frame = fh->getFrame(); TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); TStageObjectId columnId = TStageObjectId::ColumnId(columnIndex); TAffine columnPlacement = xsh->getPlacement(columnId, frame); double columnZ = xsh->getZ(columnId, frame); TStageObjectId cameraId = xsh->getStageObjectTree()->getCurrentCameraId(); TStageObject *camera = xsh->getStageObject(cameraId); TAffine cameraPlacement = camera->getPlacement(frame); double cameraZ = camera->getZ(frame); TStageObject *object = xsh->getStageObject(columnId); TAffine placement; TStageObject::perspective(placement, cameraPlacement, cameraZ, columnPlacement, columnZ, object->getGlobalNoScaleZ()); return placement; }
void addShowHideStageObjectCmd(QMenu *menu, const TStageObjectId &id, bool isShow) { TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TStageObject *pegbar = xsh->getStageObject(id); QString cmdStr; if (id.isCamera()) cmdStr = (isShow ? "Show " : "Hide ") + QString::fromStdString(pegbar->getName()); else cmdStr = (isShow ? "Show Column" : "Hide Column") + QString::fromStdString(pegbar->getName()); QAction *showHideAction = new QAction(cmdStr, menu); showHideAction->setData((int)id.getCode()); menu->addAction(showHideAction); }
void notify() const { m_tool->invalidate(); TXsheet *xsh = getXsheet(); int index = m_columnIndex; if (index < 0) index = m_oldColumnIndex; if (index >= 0) { TStageObjectId id = TStageObjectId::ColumnId(index); TStageObjectId parentId; while (parentId = xsh->getStageObjectParent(id), parentId.isColumn()) id = parentId; xsh->getStageObject(id)->invalidate(); TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged(); TTool::getApplication()->getCurrentObject()->notifyObjectIdChanged(false); } }
void TCellKeyframeSelection::selectCellsKeyframes(int r0, int c0, int r1, int c1) { m_cellSelection->selectCells(r0, c0, r1, c1); TXsheet *xsh = m_xsheetHandle->getXsheet(); m_xsheetHandle->getXsheet(); if (r1 < r0) std::swap(r0, r1); if (c1 < c0) std::swap(c0, c1); m_keyframeSelection->clear(); int r, c; for (c = c0; c <= c1; c++) for (r = r0; r <= r1; r++) { TStageObjectId id = c < 0 ? TStageObjectId::CameraId(0) : TStageObjectId::ColumnId(c); TStageObject *stObj = xsh->getStageObject(id); if (stObj->isKeyframe(r)) m_keyframeSelection->select(r, c); } }
void MeshifyPopup::acquirePreview() { m_viewer->clear(); // Assign preview input to the viewer bool enabled = false; ::xshPos(m_r, m_c); m_cell = TApp::instance()->getCurrentXsheet()->getXsheet()->getCell(m_r, m_c); // Redirect mesh case to texture TXshSimpleLevel *sl = m_cell.getSimpleLevel(); if (sl && sl->getType() == MESH_XSHLEVEL) { // Mesh image case TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TStageObject *meshObj = xsh->getStageObject(TStageObjectId::ColumnId(m_c)); const TStageObjectId &childId = ::firstChildLevelColumn(*xsh, *meshObj); if (childId.isColumn()) // Retrieved the associated texture cell - redirect acquisition there m_cell = xsh->getCell(m_r, childId.getIndex()); } if ((sl = m_cell.getSimpleLevel())) { // Standard image case m_viewer->m_img = sl->getFullsampledFrame(m_cell.getFrameId(), ImageManager::dontPutInCache); enabled = true; } else if (TXshChildLevel *cl = m_cell.getChildLevel()) { // Sub-xsheet case TXsheet *xsh = cl->getXsheet(); int row = m_cell.getFrameId().getNumber() - 1; m_viewer->m_xsh = xsh, m_viewer->m_row = row; enabled = true; } m_okBtn->setEnabled(enabled); // Update the corresponding processed image in the viewer updateMeshPreview(); }
/*! Notify change of current image: update icon and notify level change. If current object is a spline commit spline chenged. If current mode is EditingLevel touch current frame. */ void TTool::notifyImageChanged() { onImageChanged(); if (!m_application) return; m_application->getCurrentScene()->setDirtyFlag(true); if (m_application->getCurrentFrame()->isEditingLevel()) { TXshLevel *xl = m_application->getCurrentLevel()->getLevel(); if (!xl) return; TXshSimpleLevel *sl = xl->getSimpleLevel(); if (!sl) return; TFrameId fid = m_application->getCurrentFrame()->getFid(); sl->touchFrame(fid); // sl->setDirtyFlag(true); IconGenerator::instance()->invalidate(sl, fid); IconGenerator::instance()->invalidateSceneIcon(); } else { TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); if (!xsh) return; TObjectHandle *currentObject = m_application->getCurrentObject(); if (currentObject->isSpline()) { m_application->getCurrentObject()->commitSplineChanges(); TStageObject *pegbar = xsh->getStageObject(currentObject->getObjectId()); IconGenerator::instance()->invalidate(pegbar->getSpline()); } else { int row = m_application->getCurrentFrame()->getFrame(); int col = m_application->getCurrentColumn()->getColumnIndex(); if (col < 0) return; TXshCell cell = xsh->getCell(row, col); TXshSimpleLevel *sl = cell.getSimpleLevel(); if (sl) { IconGenerator::instance()->invalidate(sl, cell.m_frameId); sl->touchFrame(cell.m_frameId); IconGenerator::instance()->invalidateSceneIcon(); } } } m_application->getCurrentLevel()->notifyLevelChange(); }
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; }
QString TTool::updateEnabled() { // Disable every tool during playback if (m_application->getCurrentFrame()->isPlaying()) return (enable(false), QString()); // Release Generic tools at once int toolType = getToolType(); int targetType = getTargetType(); if (toolType == TTool::GenericTool) return (enable(true), QString()); // Retrieve vars and view modes TXsheet *xsh = m_application->getCurrentXsheet()->getXsheet(); int rowIndex = m_application->getCurrentFrame()->getFrame(); int columnIndex = m_application->getCurrentColumn()->getColumnIndex(); TXshColumn *column = (columnIndex >= 0) ? xsh->getColumn(columnIndex) : 0; TXshLevel *xl = m_application->getCurrentLevel()->getLevel(); TXshSimpleLevel *sl = xl ? xl->getSimpleLevel() : 0; int levelType = sl ? sl->getType() : NO_XSHLEVEL; TStageObject *obj = xsh->getStageObject(TStageObjectId::ColumnId(columnIndex)); bool spline = m_application->getCurrentObject()->isSpline(); bool filmstrip = m_application->getCurrentFrame()->isEditingLevel(); /*-- MultiLayerStylePickerONのときは、現状に関わらず使用可能 --*/ if (m_name == T_StylePicker && Preferences::instance()->isMultiLayerStylePickerEnabled()) return (enable(true), QString()); // Check against unplaced columns (not in filmstrip mode) if (column && !filmstrip) { if (column->isLocked()) return (enable(false), QObject::tr("The current column is locked.")); else if (!column->isCamstandVisible()) return (enable(false), QObject::tr("The current column is hidden.")); else if (column->getSoundColumn()) return (enable(false), QObject::tr("It is not possible to edit the audio column.")); else if (column->getSoundTextColumn()) return ( enable(false), QObject::tr( "Note columns can only be edited in the xsheet or timeline.")); if (toolType == TTool::ColumnTool) { // Check column target if (column->getLevelColumn() && !(targetType & LevelColumns)) return ( enable(false), QObject::tr("The current tool cannot be used on a Level column.")); if (column->getMeshColumn() && !(targetType & MeshColumns)) return ( enable(false), QObject::tr("The current tool cannot be used on a Mesh column.")); } } // Check column tools if (toolType == TTool::ColumnTool) { if (filmstrip) return ( enable(false), QObject::tr("The current tool cannot be used in Level Strip mode.")); if ((!column || column->isEmpty()) && !(targetType & TTool::EmptyTarget)) return (enable(false), QString()); } // Check LevelRead & LevelWrite tools if (toolType & TTool::LevelTool) { // Check against splines if (spline) { return (targetType & Splines) ? (enable(true), QString()) : (enable(false), QObject::tr("The current tool cannot be " "used to edit a motion path.")); } // Check against empty levels if (!xl) return (targetType & EmptyTarget) ? (enable(true), QString()) : (enable(false), QString()); // Check against simple-level-edness if (!sl) return (enable(false), QObject::tr("The current level is not editable.")); // Does it // happen at // all btw? // Check against level types { if ((levelType == PLI_XSHLEVEL) && !(targetType & VectorImage)) return ( enable(false), QObject::tr("The current tool cannot be used on a Vector Level.")); if ((levelType == TZP_XSHLEVEL) && !(targetType & ToonzImage)) return ( enable(false), QObject::tr("The current tool cannot be used on a Toonz Level.")); if ((levelType == OVL_XSHLEVEL) && !(targetType & RasterImage)) return ( enable(false), QObject::tr("The current tool cannot be used on a Raster Level.")); if ((levelType == MESH_XSHLEVEL) && !(targetType & MeshImage)) return ( enable(false), QObject::tr("The current tool cannot be used on a Mesh Level.")); } // Check against impossibly traceable movements on the column if ((levelType & LEVELCOLUMN_XSHLEVEL) && !filmstrip) { // Test for Mesh-deformed levels const TStageObjectId &parentId = obj->getParent(); if (parentId.isColumn() && obj->getParentHandle()[0] != 'H') { TXshSimpleLevel *parentSl = xsh->getCell(rowIndex, parentId.getIndex()).getSimpleLevel(); if (parentSl && parentSl->getType() == MESH_XSHLEVEL) return ( enable(false), QObject::tr( "The current tool cannot be used on a mesh-deformed level")); } } // Check TTool::ImageType tools if (toolType == TTool::LevelWriteTool) { // Check level against read-only status if (sl->isReadOnly()) { const std::set<TFrameId> &editableFrames = sl->getEditableRange(); TFrameId currentFid = getCurrentFid(); if (editableFrames.find(currentFid) == editableFrames.end()) return ( enable(false), QObject::tr( "The current frame is locked: any editing is forbidden.")); } // Check level type write support if (sl->getPath().getType() == "psd" || // We don't have the API to write psd files sl->is16BitChannelLevel() || // Inherited by previous implementation. // Could be fixed? sl->getProperties()->getBpp() == 1) // Black & White images. Again, could be fixed? return (enable(false), QObject::tr("The current level is not editable.")); } } return (enable(true), QString()); }
player.m_opacity = 30; players.push_back(player); player.m_opacity = opacity; player.m_placement = m_onionSkinMask.getShiftTraceGhostAff(1) * player.m_placement; } } } players.push_back(player); } else if (TXshChildLevel *cl = xl->getChildLevel()) { int childRow = cell.m_frameId.getNumber() - 1; TXsheet *childXsheet = cl->getXsheet(); TStageObjectId childCameraId = childXsheet->getStageObjectTree()->getCurrentCameraId(); TStageObject *childCamera = childXsheet->getStageObject(childCameraId); TAffine childCameraAff = childCamera->getPlacement(childRow); double childCameraZ = childCamera->getZ(childRow); std::vector<UCHAR> originalOpacity(childXsheet->getColumnCount()); for (int c = 0; c < childXsheet->getColumnCount(); c++) { originalOpacity[c] = childXsheet->getColumn(c)->getOpacity(); childXsheet->getColumn(c)->setOpacity(column->getOpacity()); } SubXSheet subXSheet; subXSheet.m_camera = ZPlacement(childCameraAff, childCameraZ); subXSheet.m_z = columnZ; TAffine childCameraZaff =
void ColumnCmd::cloneChild(int index) { if (!canResequence(index)) return; /*-- カラムを取得 --*/ TXsheet *xsh = TApp::instance()->getCurrentXsheet()->getXsheet(); TXshColumn *column = xsh->getColumn(index); assert(column); // get the subxsheet to clone (childLevel, childXsh) /*-- SubXsheetレベルを取得 --*/ TXshLevelColumn *lcolumn = column->getLevelColumn(); assert(lcolumn); int r0 = 0, r1 = -1; lcolumn->getRange(r0, r1); assert(r0 <= r1); /*-- SubXsheetの一番頭のセル --*/ TXshCell cell = lcolumn->getCell(r0); assert(!cell.isEmpty()); /*- cell内に格納されているLevelを取得 -*/ TXshChildLevel *childLevel = cell.m_level->getChildLevel(); assert(childLevel); /*- SubXsheetのXsheetを取得 -*/ TXsheet *childXsh = childLevel->getXsheet(); // insert a new empty column /*- 隣に空きColumnをInsertしてCloneに備える -*/ int newColumnIndex = index + 1; xsh->insertColumn(newColumnIndex); // create a subxsheet (newChildLevel, newChildXsh) ToonzScene *scene = TApp::instance()->getCurrentScene()->getScene(); ChildStack *childStack = scene->getChildStack(); TXshChildLevel *newChildLevel = childStack->createChild(0, newColumnIndex); TXsheet *newChildXsh = newChildLevel->getXsheet(); // copy columns. std::set<int> indices; for (int i = 0; i < childXsh->getColumnCount(); i++) indices.insert(i); StageObjectsData *data = new StageObjectsData(); data->storeColumns(indices, childXsh, 0); data->storeColumnFxs(indices, childXsh, 0); std::list<int> restoredSplineIds; data->restoreObjects(indices, restoredSplineIds, newChildXsh, StageObjectsData::eDoClone); delete data; cloneNotColumnLinkedFxsAndOutputsFx(childXsh, newChildXsh); cloneXsheetTStageObjectTree(childXsh, newChildXsh); /*--以下は、Clone SubXsheet するときに、SubXsheet内にある子SubXsheetをクローンする関数 クローンされた中にある子SubXsheetは、同じもので良いので、スキップする --*/ // cloneSubXsheets(newChildXsh); /*-- XSheetノードのFxSchematicでのDagNodePosを再現 FxやColumnノードの位置の再現は上のsetColumnで行っている --*/ newChildXsh->getFxDag()->getXsheetFx()->getAttributes()->setDagNodePos( childXsh->getFxDag()->getXsheetFx()->getAttributes()->getDagNodePos()); newChildXsh->updateFrameCount(); /*-- TXshChildLevel作成時にsetCellした1つ目のセルを消去 --*/ xsh->removeCells(0, newColumnIndex); /*-- CloneしたColumnのセル番号順を再現 --*/ for (int r = r0; r <= r1; r++) { TXshCell cell = lcolumn->getCell(r); if (cell.isEmpty()) continue; cell.m_level = newChildLevel; xsh->setCell(r, newColumnIndex, cell); } TStageObjectId currentObjectId = TApp::instance()->getCurrentObject()->getObjectId(); xsh->getStageObject(TStageObjectId::ColumnId(newColumnIndex)) ->setParent(xsh->getStageObjectParent(currentObjectId)); xsh->updateFrameCount(); TUndoManager::manager()->add( new CloneChildUndo(newChildLevel, newColumnIndex)); // notify changes TApp::instance()->getCurrentScene()->setDirtyFlag(true); TApp::instance()->getCurrentXsheet()->notifyXsheetChanged(); }
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::drawSkeleton(const Skeleton &skeleton, int row) { bool buildingSkeleton = m_mode.getValue() == BUILD_SKELETON; bool ikEnabled = m_mode.getValue() == INVERSE_KINEMATICS; TXsheet *xsh = getXsheet(); std::vector<int> showBoneIndex; int i; for (i = 0; i < skeleton.getBoneCount(); i++) { Skeleton::Bone *bone = skeleton.getBone(i); TStageObjectId id = bone->getStageObject()->getId(); bool canShow = canShowBone(bone, xsh, row); if (!canShow) continue; showBoneIndex.push_back(i); } bool changingParent = dynamic_cast<ParentChangeTool *>(m_dragTool) != 0; TStageObjectId currentObjectId = TTool::getApplication()->getCurrentObject()->getObjectId(); std::string currentHandle = xsh->getStageObject(currentObjectId)->getHandle(); for (i = 0; i < (int)showBoneIndex.size(); i++) { Skeleton::Bone *bone = skeleton.getBone(showBoneIndex[i]); TStageObjectId id = bone->getStageObject()->getId(); bool isCurrent = id == currentObjectId; if (isCurrent && buildingSkeleton && m_parentProbeEnabled) { if (!m_magicLinks.empty()) { drawBone(bone->getCenter(), m_magicLinks[0].m_h1.m_pos, false); } drawBone(bone->getCenter(), m_parentProbe, true); } else if (ikEnabled) { if (bone->getParent()) drawIKBone(bone->getCenter(), bone->getParent()->getCenter()); } else if (bone->getParent() || isCurrent) { double pixelSize = getPixelSize(); TPointD a = bone->getCenter(); TPointD b, pm; if (bone->getParent()) { b = bone->getParent()->getCenter(); pm = (a + b) * 0.5; } else { pm = b = a + TPointD(0, 60) * pixelSize; } bool boneIsVisible = false; if (buildingSkeleton) { boneIsVisible = true; if (bone->isSelected()) drawBone(a, b, true); else if (!m_showOnlyActiveSkeleton.getValue()) drawBone(a, b, false); else boneIsVisible = false; } if (boneIsVisible && isCurrent) { // draw change parent gadget double r = pixelSize * 5; if (isPicking()) { // int code = TD_ResetParent + bone->getStageObject()->getId().getIndex(); glPushName(TD_ChangeParent); tglDrawDisk(pm, r); glPopName(); } else { if (m_device == TD_ChangeParent) { glColor4d(0.47 * alpha, 0.6 * alpha, 0.65 * alpha, alpha); r *= 1.5; } else glColor4d(0.37 * alpha, 0.5 * alpha, 0.55 * alpha, alpha); glRectd(pm.x - r, pm.y - r, pm.x + r, pm.y + r); glColor3d(0, 0, 0); tglDrawRect(pm.x - r, pm.y - r, pm.x + r, pm.y + r); } } } } for (i = 0; i < (int)showBoneIndex.size(); i++) { Skeleton::Bone *bone = skeleton.getBone(showBoneIndex[i]); if (!m_showOnlyActiveSkeleton.getValue() || bone->isSelected()) drawJoint(bone->getCenter(), currentObjectId == bone->getStageObject()->getId() && currentHandle.find("H") != 0); } }
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(); }