diff --git a/toonz/sources/include/tools/tooloptions.h b/toonz/sources/include/tools/tooloptions.h index bc77562..b3a3f61 100644 --- a/toonz/sources/include/tools/tooloptions.h +++ b/toonz/sources/include/tools/tooloptions.h @@ -108,7 +108,7 @@ protected: QHBoxLayout *m_layout; public: - ToolOptionsBox(QWidget *parent); + ToolOptionsBox(QWidget *parent, bool isScrollable = false); ~ToolOptionsBox(); virtual void @@ -183,6 +183,8 @@ public: class ArrowToolOptionsBox final : public ToolOptionsBox { Q_OBJECT + enum AXIS { Position = 0, Rotation, Scale, Shear, CenterPosition, AllAxis }; + TPropertyGroup *m_pg; bool m_splined; TTool *m_tool; @@ -190,7 +192,8 @@ class ArrowToolOptionsBox final : public ToolOptionsBox { TObjectHandle *m_objHandle; TXsheetHandle *m_xshHandle; - QStackedWidget *m_mainStackedWidget; + QWidget **m_axisOptionWidgets; + QWidget *m_pickWidget; // General ToolOptionCombo *m_chooseActiveAxisCombo; @@ -249,6 +252,9 @@ class ArrowToolOptionsBox final : public ToolOptionsBox { ToolOptionCheckbox *m_globalKey; + // enables adjusting value by dragging on the label + void connectLabelAndField(ClickableLabel *label, MeasuredValueField *field); + public: ArrowToolOptionsBox(QWidget *parent, TTool *tool, TPropertyGroup *pg, TFrameHandle *frameHandle, TObjectHandle *objHandle, @@ -272,6 +278,8 @@ protected slots: void syncCurrentStageObjectComboItem(); // change the current stage object when user changes it via combobox by hand void onCurrentStageObjectComboActivated(int index); + + void onCurrentAxisChanged(int); }; //============================================================================= diff --git a/toonz/sources/include/toonzqt/dvdialog.h b/toonz/sources/include/toonzqt/dvdialog.h index fd15ac0..8f1f49c 100644 --- a/toonz/sources/include/toonzqt/dvdialog.h +++ b/toonz/sources/include/toonzqt/dvdialog.h @@ -146,7 +146,7 @@ class DVAPI Separator final : public QFrame { bool m_isHorizontal; public: - Separator(QString name = "", QWidget *parent = 0); + Separator(QString name = "", QWidget *parent = 0, bool isHorizontal = true); ~Separator(); /*! Set dialog saparator \b name to name, if name is empty dialog separator diff --git a/toonz/sources/tnztools/edittool.cpp b/toonz/sources/tnztools/edittool.cpp index fbfeb06..aa4af74 100644 --- a/toonz/sources/tnztools/edittool.cpp +++ b/toonz/sources/tnztools/edittool.cpp @@ -666,6 +666,9 @@ class EditTool final : public TTool { TPropertyGroup m_prop; + void drawMainHandle(); + void onEditAllLeftButtonDown(TPointD &pos, const TMouseEvent &e); + public: EditTool(); ~EditTool(); @@ -793,6 +796,7 @@ EditTool::EditTool() m_activeAxis.addValue(L"Scale"); m_activeAxis.addValue(L"Shear"); m_activeAxis.addValue(L"Center"); + m_activeAxis.addValue(L"All"); m_activeAxis.setValue(L"Position"); m_activeAxis.setId("EditToolActiveAxis"); @@ -860,14 +864,16 @@ const TStroke *EditTool::getSpline() const { //----------------------------------------------------------------------------- void EditTool::mouseMove(const TPointD &, const TMouseEvent &e) { - /*--左ドラッグ中なら無視--*/ + /*-- return while left dragging --*/ if (e.isLeftButtonPressed()) return; - /*-- FxGadgetを表示していなかったらPICKをしないで済ませる --*/ - int selectedDevice = -1; - if (m_fxGadgetController->hasGadget()) selectedDevice = pick(e.m_pos); + /*-- Pick screen only when the FxGadget is displayed or + when the "All" axis is selected. --*/ + int selectedDevice = -1; + if (m_fxGadgetController->hasGadget() || m_activeAxis.getValue() == L"All") + selectedDevice = pick(e.m_pos); - if (selectedDevice < 1000) { + if (selectedDevice <= 0) { selectedDevice = m_what; if (m_what == Translation && e.isCtrlPressed()) selectedDevice = ZTranslation; @@ -909,6 +915,8 @@ void EditTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) { m_what = ScaleXY; else m_what = Scale; + else if (m_activeAxis.getValue() == L"All") + onEditAllLeftButtonDown(pos, e); int scaleConstraint = 0; if (m_scaleConstraint.getValue() == L"A/R") @@ -975,6 +983,58 @@ void EditTool::leftButtonDown(const TPointD &ppos, const TMouseEvent &e) { //----------------------------------------------------------------------------- +void EditTool::onEditAllLeftButtonDown(TPointD &pos, const TMouseEvent &e) { + int selectedDevice = pick(e.m_pos); + m_what = selectedDevice >= 0 ? selectedDevice : Translation; + + if (selectedDevice < 0 && m_autoSelect.getValue() != L"None") { + pos = getMatrix() * pos; + int columnIndex = + getViewer()->posToColumnIndex(e.m_pos, 5 * getPixelSize(), false); + if (columnIndex >= 0) { + TStageObjectId id = TStageObjectId::ColumnId(columnIndex); + int currentColumnIndex = getColumnIndex(); + TXsheet *xsh = getXsheet(); + + if (m_autoSelect.getValue() == L"Pegbar") { + TStageObjectId id2 = id; + while (!id2.isPegbar()) { + id2 = xsh->getStageObjectParent(id2); + if (!id2.isColumn() && !id2.isPegbar()) break; + } + if (id2.isPegbar()) id = id2; + } + if (id.isColumn()) { + if (columnIndex >= 0 && columnIndex != currentColumnIndex) { + if (e.isShiftPressed()) { + TXsheetHandle *xshHandle = + TTool::getApplication()->getCurrentXsheet(); + TStageObjectId curColId = + TStageObjectId::ColumnId(currentColumnIndex); + TStageObjectId colId = TStageObjectId::ColumnId(columnIndex); + TStageObjectCmd::setParent(curColId, colId, "", xshHandle); + m_what = None; + xshHandle->notifyXsheetChanged(); + } else { + TXshColumn *column = xsh->getColumn(columnIndex); + if (!column || !column->isLocked()) { + TTool::getApplication()->getCurrentColumn()->setColumnIndex( + columnIndex); + updateMatrix(); + } + } + } + } else { + TTool::getApplication()->getCurrentObject()->setObjectId(id); + updateMatrix(); + } + } + pos = getMatrix().inv() * pos; + } +} + +//----------------------------------------------------------------------------- + void EditTool::leftButtonDrag(const TPointD &pos, const TMouseEvent &e) { if (!m_dragTool) return; m_dragTool->leftButtonDrag(pos, e); @@ -1121,26 +1181,186 @@ glColor3d(0,0,0); //----------------------------------------------------------------------------- +void EditTool::drawMainHandle() { + const TPixel32 normalColor(250, 127, 240); + const TPixel32 highlightedColor(150, 255, 140); + + // collect information + TXsheet *xsh = getXsheet(); + TStageObjectId objId = getObjectId(); + int frame = getFrame(); + TAffine parentAff = xsh->getParentPlacement(objId, frame); + TAffine aff = xsh->getPlacement(objId, frame); + TPointD center = Stage::inch * xsh->getCenter(objId, frame); + + // the gadget appears on the center of the level. orientation and dimension + // are independent of the movement of the level + glPushMatrix(); + + tglMultMatrix(parentAff.inv() * TTranslation(aff * center)); + + // so in the system of ref. of the gadget the center is always in the origin + center = TPointD(); + + double unit = sqrt(tglGetPixelSize2()); + + bool dragging = m_dragTool != 0; + + // draw center + tglColor(m_highlightedDevice == Center ? highlightedColor : normalColor); + glPushName(Center); + if (isPicking()) + tglDrawDisk(center, unit * 12); + else { + tglDrawCircle(center, unit * 10); + tglDrawCircle(center, unit * 8); + if (m_highlightedDevice == Center && !dragging) + drawText(center + TPointD(4 * unit, 0), unit, "Move center"); + } + glPopName(); + + // draw label (column/pegbar name; possibly camera icon) + tglColor(normalColor); + glPushMatrix(); + glTranslated(center.x + unit * 10, center.y - unit * 20, 0); + + if (objId.isColumn() || objId.isPegbar()) { + TStageObject *pegbar = xsh->getStageObject(objId); + std::string name = pegbar->getFullName(); + glScaled(unit * 2, unit * 1.5, 1); + tglDrawText(TPointD(0, 0), name); + } else if (objId.isCamera()) { + glScaled(unit, unit, 1); + drawCameraIcon(); + } + glPopMatrix(); + + // draw rotation handle + const double delta = 30; + tglColor(m_highlightedDevice == Rotation ? highlightedColor : normalColor); + glPushName(Rotation); + TPointD p = center + unit * TPointD(0, delta); + if (isPicking()) + tglDrawDisk(p, unit * 10); + else + tglDrawDisk(p, unit * 5); + glPopName(); + if (m_highlightedDevice == Rotation && !dragging && !isPicking()) + drawText(p, unit, "Rotate"); + tglColor(normalColor); + tglDrawSegment(p, center); + + // draw scale handle + p = center + m_currentScaleFactor * unit * delta * TPointD(-1, -1); + double r = unit * 3; + double f = 5; + TRectD hitRect; + + tglColor(m_highlightedDevice == Scale ? highlightedColor : normalColor); + glPushName(Scale); + hitRect = + TRectD(p.x - (f - 2) * r, p.y - (f - 2) * r, p.x + r * 2, p.y + r * 2); + // tglDrawRect(hitRect); + if (isPicking()) + tglFillRect(hitRect); + else + tglDrawRect(p.x - r, p.y - r, p.x + r, p.y + r); + glPopName(); + TPointD scaleTooltipPos = p + unit * TPointD(-16, -16); + if (m_highlightedDevice == Scale && !dragging && !isPicking()) + drawText(scaleTooltipPos, unit, "Scale"); + + tglColor(normalColor); + tglDrawSegment(p, center); + + TPointD q; + double dd = unit * 10; + + q = p + TPointD(dd, dd); + tglColor(m_highlightedDevice == ScaleXY ? highlightedColor : normalColor); + glPushName(ScaleXY); + hitRect = + TRectD(q.x - 2 * r, q.y - 2 * r, q.x + r * (f - 2), q.y + r * (f - 2)); + // tglDrawRect(hitRect); + if (isPicking()) + tglFillRect(hitRect); + else + tglDrawRect(q.x - r, q.y - r, q.x + r, q.y + r); + glPopName(); + if (m_highlightedDevice == ScaleXY && !dragging && !isPicking()) + drawText(scaleTooltipPos, unit, "Horizontal/Vertical scale"); + + // draw shear handle + p = center + m_currentScaleFactor * unit * delta * TPointD(1, -1); + tglColor(m_highlightedDevice == Shear ? highlightedColor : normalColor); + glPushName(Shear); + if (isPicking()) { + glBegin(GL_POLYGON); + glVertex2d(p.x - unit * 6, p.y - unit * 3); + glVertex2d(p.x - unit * 3, p.y - unit * 3); + glVertex2d(p.x + unit * 6, p.y + unit * 3); + glVertex2d(p.x + unit * 3, p.y + unit * 3); + glVertex2d(p.x - unit * 6, p.y - unit * 3); + glEnd(); + } else { + glBegin(GL_LINE_STRIP); + glVertex2d(p.x - unit * 6, p.y - unit * 3); + glVertex2d(p.x - unit * 3, p.y - unit * 3); + glVertex2d(p.x + unit * 6, p.y + unit * 3); + glVertex2d(p.x + unit * 3, p.y + unit * 3); + glVertex2d(p.x - unit * 6, p.y - unit * 3); + glEnd(); + } + glPopName(); + if (m_highlightedDevice == Shear && !dragging) + drawText(p + TPointD(0, -unit * 10), unit, "Shear"); + tglColor(normalColor); + tglDrawSegment(p, center); + + // + if (objId.isCamera()) { + if (xsh->getStageObjectTree()->getCurrentCameraId() != objId) { + glEnable(GL_LINE_STIPPLE); + glColor3d(1.0, 0.0, 1.0); + glLineStipple(1, 0x1111); + TRectD cameraRect = TTool::getApplication() + ->getCurrentScene() + ->getScene() + ->getCurrentCamera() + ->getStageRect(); + + glPushMatrix(); + // tglMultMatrix(mat); + tglDrawRect(cameraRect); + glPopMatrix(); + glDisable(GL_LINE_STIPPLE); + } + } + + glPopMatrix(); +} +//----------------------------------------------------------------------------- + void EditTool::draw() { // the tool is using the coordinate system of the parent object // glColor3d(1,0,1); // tglDrawCircle(crossHair,50); - /*--Level編集モードのときは表示しない--*/ + /*-- Show nothing on Level Editing mode --*/ if (TTool::getApplication()->getCurrentFrame()->isEditingLevel()) return; const TPixel32 normalColor(250, 127, 240); const TPixel32 highlightedColor(150, 255, 140); // collect information TXsheet *xsh = getXsheet(); - /*--編集中のStageObjectIDを取得--*/ + /*-- Obtain ID of the current editing stage object --*/ TStageObjectId objId = getObjectId(); int frame = getFrame(); TAffine parentAff = xsh->getParentPlacement(objId, frame); TAffine aff = xsh->getPlacement(objId, frame); TPointD center = Stage::inch * xsh->getCenter(objId, frame); - /*--3D表示のとき、Zを動かせるようにする--*/ + /*-- Enable Z translation on 3D view --*/ if (getViewer()->is3DView()) { glPushMatrix(); glPushName(ZTranslation); @@ -1159,16 +1379,23 @@ void EditTool::draw() { return; } + // Edit-all + if (m_activeAxis.getValue() == L"All") { + if (!m_fxGadgetController->isEditingNonZeraryFx()) drawMainHandle(); + m_fxGadgetController->draw(isPicking()); + return; + } + double unit = getPixelSize(); - /*-- ObjectのCenter位置を取得 --*/ + /*-- Obtain object's center position --*/ glPushMatrix(); tglMultMatrix(parentAff.inv() * TTranslation(aff * TPointD(0.0, 0.0))); tglColor(normalColor); tglDrawDisk(TPointD(0.0, 0.0), unit * 4); glPopMatrix(); - /*-- Z移動 : 矢印(中心はCameraのCenter) --*/ + /*-- Z translation : Draw arrow mark (placed at the camera center) --*/ if (m_activeAxis.getValue() == L"Position" && m_highlightedDevice == ZTranslation) { tglColor(normalColor); @@ -1183,10 +1410,9 @@ void EditTool::draw() { drawZArrow(); glPopMatrix(); } - - /*-- Rotation, Position : 垂直/水平線 --*/ - if (m_activeAxis.getValue() == L"Rotation" || - m_activeAxis.getValue() == L"Position") { + /*-- Rotation, Position : Draw vertical and horizontal lines --*/ + else if (m_activeAxis.getValue() == L"Rotation" || + m_activeAxis.getValue() == L"Position") { glPushMatrix(); tglMultMatrix(parentAff.inv() * aff * TTranslation(center)); glScaled(unit, unit, 1); @@ -1215,7 +1441,8 @@ void EditTool::draw() { tglDrawCircle(center, unit * 10); tglDrawCircle(center, unit * 8); - /*-- 円の中に十字を描く Center位置にTranslate済み --*/ + /*-- Draw crossed lines in the circle. It's already translated to the center + * position. --*/ glBegin(GL_LINE_STRIP); glVertex2d(-unit * 8, 0.0); glVertex2d(unit * 8, 0.0); @@ -1232,7 +1459,7 @@ void EditTool::draw() { glPushMatrix(); glTranslated(center.x + unit * 10, center.y - unit * 20, 0); - /*-- Object名を表示 --*/ + /*-- Object name --*/ TStageObject *pegbar = xsh->getStageObject(objId); std::string name = pegbar->getFullName(); if (objId.isColumn() || objId.isPegbar() || objId.isTable()) { @@ -1248,7 +1475,7 @@ void EditTool::draw() { } glPopMatrix(); - /*--- アクティブでないカメラのPegbarを編集するときは、カメラ枠を表示する ---*/ + /*--- When editing non-active camera, draw its camera frame ---*/ if (objId.isCamera()) { if (xsh->getStageObjectTree()->getCurrentCameraId() != objId) { // TODO : glLineStipple has been deprecated in the OpenGL APIs. Need to be @@ -1391,6 +1618,8 @@ bool EditTool::onPropertyChanged(std::string propertyName) { m_what = Shear; else if (activeAxis == L"Center") m_what = Center; + else if (activeAxis == L"All") + m_what = None; } return true; diff --git a/toonz/sources/tnztools/tooloptions.cpp b/toonz/sources/tnztools/tooloptions.cpp index 4edd6c1..da92652 100644 --- a/toonz/sources/tnztools/tooloptions.cpp +++ b/toonz/sources/tnztools/tooloptions.cpp @@ -82,7 +82,8 @@ void ToolOptionToolBar::addSpacing(int width) { //============================================================================= // ToolOptionsBox -ToolOptionsBox::ToolOptionsBox(QWidget *parent) : QFrame(parent) { +ToolOptionsBox::ToolOptionsBox(QWidget *parent, bool isScrollable) + : QFrame(parent) { setObjectName("toolOptionsPanel"); setStyleSheet("#toolOptionsPanel {border: 0px; margin: 1px;}"); @@ -93,7 +94,30 @@ ToolOptionsBox::ToolOptionsBox(QWidget *parent) : QFrame(parent) { m_layout->setMargin(0); m_layout->setSpacing(5); m_layout->addSpacing(5); - setLayout(m_layout); + + if (isScrollable) { + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->setMargin(0); + hLayout->setSpacing(0); + setLayout(hLayout); + + // Build the scroll widget vin which the toolbar will be placed + DvScrollWidget *scrollWidget = new DvScrollWidget; + hLayout->addWidget(scrollWidget); + + // In the scrollable layout we add a widget of 24 height + // which contains the tooloptionBar. This is necessary + // to make the hboxlayout adjust the bar's vertical position. + QWidget *toolContainer = new QWidget; + scrollWidget->setWidget(toolContainer); + + toolContainer->setSizePolicy(QSizePolicy::MinimumExpanding, + QSizePolicy::Fixed); + toolContainer->setFixedHeight(24); + + toolContainer->setLayout(m_layout); + } else + setLayout(m_layout); } //----------------------------------------------------------------------------- @@ -424,10 +448,31 @@ GenericToolOptionsBox::GenericToolOptionsBox(QWidget *parent, TTool *tool, //----------------------------------------------------------------------------- +// show 17x17 icon without style dependency +class SimpleIconViewField : public QWidget { + QIcon m_icon; + +public: + SimpleIconViewField(const QString &iconName, const QString &toolTipStr = "", + QWidget *parent = 0) + : QWidget(parent), m_icon(createQIcon(iconName.toUtf8())) { + setMinimumSize(17, 25); + setToolTip(toolTipStr); + } + +protected: + void paintEvent(QPaintEvent *e) { + QPainter p(this); + p.drawPixmap(QRect(0, 4, 17, 17), m_icon.pixmap(17, 17)); + } +}; + +//----------------------------------------------------------------------------- + ArrowToolOptionsBox::ArrowToolOptionsBox( QWidget *parent, TTool *tool, TPropertyGroup *pg, TFrameHandle *frameHandle, TObjectHandle *objHandle, TXsheetHandle *xshHandle, ToolHandle *toolHandle) - : ToolOptionsBox(parent) + : ToolOptionsBox(parent, true) , m_pg(pg) , m_splined(false) , m_tool(tool) @@ -438,7 +483,7 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( setObjectName("toolOptionsPanel"); setFixedHeight(26); - m_mainStackedWidget = new QStackedWidget(this); + m_axisOptionWidgets = new QWidget *[AllAxis]; /* --- General Parts --- */ @@ -455,6 +500,8 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( if (autoSelectProp) m_pickCombo = new ToolOptionCombo(m_tool, autoSelectProp, toolHandle); + m_pickWidget = new QWidget(this); + /* --- Position --- */ m_motionPathPosField = new PegbarChannelField(m_tool, TStageObject::T_Path, "field", frameHandle, @@ -603,15 +650,25 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( const int ITEM_SPACING = 10; const int LABEL_SPACING = 3; /* --- Layout --- */ - /* --- Layout --- */ QHBoxLayout *mainLay = m_layout; { mainLay->addWidget(m_currentStageObjectCombo, 0); mainLay->addWidget(m_chooseActiveAxisCombo, 0); + // Pick combobox only available on "All" axis mode + QHBoxLayout *pickLay = new QHBoxLayout(); + pickLay->setMargin(0); + pickLay->setSpacing(0); + { + pickLay->addSpacing(5); + pickLay->addWidget(new QLabel(tr("Pick:"), this), 0); + pickLay->addWidget(m_pickCombo, 0); + } + m_pickWidget->setLayout(pickLay); + mainLay->addWidget(m_pickWidget, 0); + addSeparator(); - mainLay->addWidget(m_mainStackedWidget, 1); { // Position QFrame *posFrame = new QFrame(this); @@ -619,11 +676,11 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( posLay->setMargin(0); posLay->setSpacing(0); posFrame->setLayout(posLay); - m_mainStackedWidget->addWidget(posFrame); { + posLay->addWidget( + new SimpleIconViewField("edit_position", tr("Position"), this), 0); + posLay->addSpacing(LABEL_SPACING * 2); posLay->addWidget(m_motionPathPosLabel, 0); - posLay->addSpacing(ITEM_SPACING); - posLay->addWidget(m_motionPathPosField, 0); posLay->addWidget(m_ewPosLabel, 0); @@ -653,8 +710,13 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( posLay->addWidget(m_soLabel, 0); posLay->addWidget(m_soField, 10); + posLay->addSpacing(ITEM_SPACING); + posLay->addWidget(new DVGui::Separator("", this, false)); + posLay->addStretch(1); } + m_axisOptionWidgets[Position] = posFrame; + mainLay->addWidget(m_axisOptionWidgets[Position], 0); // Rotation QFrame *rotFrame = new QFrame(this); @@ -662,15 +724,21 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( rotLay->setMargin(0); rotLay->setSpacing(0); rotFrame->setLayout(rotLay); - m_mainStackedWidget->addWidget(rotFrame); { + rotLay->addWidget( + new SimpleIconViewField("edit_rotation", tr("Rotation"), this), 0); + rotLay->addSpacing(LABEL_SPACING * 2); rotLay->addWidget(m_rotationLabel, 0); - rotLay->addSpacing(ITEM_SPACING); - + rotLay->addSpacing(LABEL_SPACING); rotLay->addWidget(m_rotationField, 10); + rotLay->addSpacing(ITEM_SPACING); + rotLay->addWidget(new DVGui::Separator("", this, false)); + rotLay->addStretch(1); } + m_axisOptionWidgets[Rotation] = rotFrame; + mainLay->addWidget(m_axisOptionWidgets[Rotation], 0); // Scale QFrame *scaleFrame = new QFrame(this); @@ -678,10 +746,10 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( scaleLay->setMargin(0); scaleLay->setSpacing(0); scaleFrame->setLayout(scaleLay); - m_mainStackedWidget->addWidget(scaleFrame); { - scaleLay->addWidget(new QLabel(tr("Scale"), this), 0); - scaleLay->addSpacing(ITEM_SPACING); + scaleLay->addWidget( + new SimpleIconViewField("edit_scale", tr("Scale"), this), 0); + scaleLay->addSpacing(LABEL_SPACING * 2); scaleLay->addWidget(m_globalScaleLabel, 0); scaleLay->addSpacing(LABEL_SPACING); @@ -707,8 +775,13 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( scaleLay->addSpacing(LABEL_SPACING); scaleLay->addWidget(m_maintainCombo, 0); + scaleLay->addSpacing(ITEM_SPACING); + scaleLay->addWidget(new DVGui::Separator("", this, false)); + scaleLay->addStretch(1); } + m_axisOptionWidgets[Scale] = scaleFrame; + mainLay->addWidget(m_axisOptionWidgets[Scale], 0); // Shear QFrame *shearFrame = new QFrame(this); @@ -716,10 +789,10 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( shearLay->setMargin(0); shearLay->setSpacing(0); shearFrame->setLayout(shearLay); - m_mainStackedWidget->addWidget(shearFrame); { - shearLay->addWidget(new QLabel(tr("Shear"), this), 0); - shearLay->addSpacing(ITEM_SPACING); + shearLay->addWidget( + new SimpleIconViewField("edit_shear", tr("Shear"), this), 0); + shearLay->addSpacing(LABEL_SPACING * 2); shearLay->addWidget(m_shearHLabel, 0); shearLay->addSpacing(LABEL_SPACING); @@ -735,8 +808,12 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( shearLay->addSpacing(ITEM_SPACING); + shearLay->addWidget(new DVGui::Separator("", this, false)); + shearLay->addStretch(1); } + m_axisOptionWidgets[Shear] = shearFrame; + mainLay->addWidget(m_axisOptionWidgets[Shear], 0); // Center Position QFrame *centerPosFrame = new QFrame(this); @@ -744,10 +821,11 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( centerPosLay->setMargin(0); centerPosLay->setSpacing(0); centerPosFrame->setLayout(centerPosLay); - m_mainStackedWidget->addWidget(centerPosFrame); { - centerPosLay->addWidget(new QLabel(tr("Center Position"), this), 0); - centerPosLay->addSpacing(ITEM_SPACING); + centerPosLay->addWidget( + new SimpleIconViewField("edit_center", tr("Center Position"), this), + 0); + centerPosLay->addSpacing(LABEL_SPACING * 2); centerPosLay->addWidget(m_ewCenterLabel, 0); centerPosLay->addSpacing(LABEL_SPACING); @@ -761,30 +839,24 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( centerPosLay->addWidget(m_nsCenterField, 10); centerPosLay->addWidget(m_lockNSCenterCheckbox, 0); + centerPosLay->addSpacing(ITEM_SPACING); + centerPosLay->addWidget(new DVGui::Separator("", this, false)); + centerPosLay->addStretch(1); } + m_axisOptionWidgets[CenterPosition] = centerPosFrame; + mainLay->addWidget(m_axisOptionWidgets[CenterPosition], 0); } - addSeparator(); - mainLay->addWidget(m_globalKey, 0); - mainLay->addSpacing(5); - - QHBoxLayout *pickLay = new QHBoxLayout(); - pickLay->setMargin(0); - pickLay->setSpacing(0); - mainLay->addLayout(pickLay, 0); - { - pickLay->addWidget(new QLabel(tr("Pick:"), this), 0); - pickLay->addWidget(m_pickCombo, 0); - } + mainLay->addSpacing(ITEM_SPACING); } /* --- signal-slot connections --- */ // swap page when the active axis is changed - connect(m_chooseActiveAxisCombo, SIGNAL(currentIndexChanged(int)), - m_mainStackedWidget, SLOT(setCurrentIndex(int))); + connect(m_chooseActiveAxisCombo, SIGNAL(currentIndexChanged(int)), this, + SLOT(onCurrentAxisChanged(int))); // when the current stage object is changed via combo box, then switch the // current stage object in the scene connect(m_currentStageObjectCombo, SIGNAL(activated(int)), this, @@ -831,84 +903,20 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( SLOT(onScaleTypeChanged(int))); } - connect(m_motionPathPosLabel, SIGNAL(onMousePress(QMouseEvent *)), - m_motionPathPosField, SLOT(receiveMousePress(QMouseEvent *))); - connect(m_motionPathPosLabel, SIGNAL(onMouseMove(QMouseEvent *)), - m_motionPathPosField, SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_motionPathPosLabel, SIGNAL(onMouseRelease(QMouseEvent *)), - m_motionPathPosField, SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_ewPosLabel, SIGNAL(onMousePress(QMouseEvent *)), m_ewPosField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_ewPosLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_ewPosField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_ewPosLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_ewPosField, - SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_nsPosLabel, SIGNAL(onMousePress(QMouseEvent *)), m_nsPosField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_nsPosLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_nsPosField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_nsPosLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_nsPosField, - SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_zLabel, SIGNAL(onMousePress(QMouseEvent *)), m_zField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_zLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_zField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_zLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_zField, - SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_soLabel, SIGNAL(onMousePress(QMouseEvent *)), m_soField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_soLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_soField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_soLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_soField, - SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_rotationLabel, SIGNAL(onMousePress(QMouseEvent *)), m_rotationField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_rotationLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_rotationField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_rotationLabel, SIGNAL(onMouseRelease(QMouseEvent *)), - m_rotationField, SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_globalScaleLabel, SIGNAL(onMousePress(QMouseEvent *)), - m_globalScaleField, SLOT(receiveMousePress(QMouseEvent *))); - connect(m_globalScaleLabel, SIGNAL(onMouseMove(QMouseEvent *)), - m_globalScaleField, SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_globalScaleLabel, SIGNAL(onMouseRelease(QMouseEvent *)), - m_globalScaleField, SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_scaleHLabel, SIGNAL(onMousePress(QMouseEvent *)), m_scaleHField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_scaleHLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_scaleHField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_scaleHLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_scaleHField, - SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_scaleVLabel, SIGNAL(onMousePress(QMouseEvent *)), m_scaleVField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_scaleVLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_scaleVField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_scaleVLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_scaleVField, - SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_shearHLabel, SIGNAL(onMousePress(QMouseEvent *)), m_shearHField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_shearHLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_shearHField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_shearHLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_shearHField, - SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_shearVLabel, SIGNAL(onMousePress(QMouseEvent *)), m_shearVField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_shearVLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_shearVField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_shearVLabel, SIGNAL(onMouseRelease(QMouseEvent *)), m_shearVField, - SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_ewCenterLabel, SIGNAL(onMousePress(QMouseEvent *)), m_ewCenterField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_ewCenterLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_ewCenterField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_ewCenterLabel, SIGNAL(onMouseRelease(QMouseEvent *)), - m_ewCenterField, SLOT(receiveMouseRelease(QMouseEvent *))); - connect(m_nsCenterLabel, SIGNAL(onMousePress(QMouseEvent *)), m_nsCenterField, - SLOT(receiveMousePress(QMouseEvent *))); - connect(m_nsCenterLabel, SIGNAL(onMouseMove(QMouseEvent *)), m_nsCenterField, - SLOT(receiveMouseMove(QMouseEvent *))); - connect(m_nsCenterLabel, SIGNAL(onMouseRelease(QMouseEvent *)), - m_nsCenterField, SLOT(receiveMouseRelease(QMouseEvent *))); + // enables adjusting value by dragging on the label + connectLabelAndField(m_motionPathPosLabel, m_motionPathPosField); + connectLabelAndField(m_ewPosLabel, m_ewPosField); + connectLabelAndField(m_nsPosLabel, m_nsPosField); + connectLabelAndField(m_zLabel, m_zField); + connectLabelAndField(m_soLabel, m_soField); + connectLabelAndField(m_rotationLabel, m_rotationField); + connectLabelAndField(m_globalScaleLabel, m_globalScaleField); + connectLabelAndField(m_scaleHLabel, m_scaleHField); + connectLabelAndField(m_scaleVLabel, m_scaleVField); + connectLabelAndField(m_shearHLabel, m_shearHField); + connectLabelAndField(m_shearVLabel, m_shearVField); + connectLabelAndField(m_ewCenterLabel, m_ewCenterField); + connectLabelAndField(m_nsCenterLabel, m_nsCenterField); if (globalKeyProp) { std::string actionName = "A_ToolOption_" + globalKeyProp->getId(); @@ -919,6 +927,21 @@ ArrowToolOptionsBox::ArrowToolOptionsBox( connect(a, SIGNAL(triggered(bool)), m_globalKey, SLOT(doClick(bool))); } } + + onCurrentAxisChanged(activeAxisProp->getIndex()); +} + +//----------------------------------------------------------------------------- +// enables adjusting value by dragging on the label + +void ArrowToolOptionsBox::connectLabelAndField(ClickableLabel *label, + MeasuredValueField *field) { + connect(label, SIGNAL(onMousePress(QMouseEvent *)), field, + SLOT(receiveMousePress(QMouseEvent *))); + connect(label, SIGNAL(onMouseMove(QMouseEvent *)), field, + SLOT(receiveMouseMove(QMouseEvent *))); + connect(label, SIGNAL(onMouseRelease(QMouseEvent *)), field, + SLOT(receiveMouseRelease(QMouseEvent *))); } //----------------------------------------------------------------------------- @@ -958,6 +981,7 @@ void ArrowToolOptionsBox::hideEvent(QShowEvent *) { void ArrowToolOptionsBox::setSplined(bool on) { m_splined = on; // Activate on selecting spline + m_motionPathPosLabel->setVisible(on); m_motionPathPosField->setVisible(on); // DEactivate on selecting spline m_ewPosField->setVisible(!on); @@ -1083,6 +1107,16 @@ void ArrowToolOptionsBox::onCurrentStageObjectComboActivated(int index) { m_objHandle->setObjectId(id); } +//------------------------------------------------------------------------------ + +void ArrowToolOptionsBox::onCurrentAxisChanged(int axisId) { + // Show the specified axis options, hide all the others + for (int a = 0; a != AllAxis; ++a) + m_axisOptionWidgets[a]->setVisible(a == axisId || axisId == AllAxis); + + m_pickWidget->setVisible(axisId == AllAxis); +} + //============================================================================= // // SelectionToolOptionsBox diff --git a/toonz/sources/toonz/mainwindow.cpp b/toonz/sources/toonz/mainwindow.cpp index 15c5f4d..3853cbe 100644 --- a/toonz/sources/toonz/mainwindow.cpp +++ b/toonz/sources/toonz/mainwindow.cpp @@ -2260,6 +2260,8 @@ void MainWindow::defineActions() { tr("Active Axis - Shear"), ""); createToolOptionsAction("A_ToolOption_EditToolActiveAxis:Center", tr("Active Axis - Center"), ""); + createToolOptionsAction("A_ToolOption_EditToolActiveAxis:All", + tr("Active Axis - All"), ""); createToolOptionsAction("A_ToolOption_SkeletonMode:Build Skeleton", tr("Build Skeleton Mode"), ""); diff --git a/toonz/sources/toonz/sceneviewer.cpp b/toonz/sources/toonz/sceneviewer.cpp index 280915f..add8483 100644 --- a/toonz/sources/toonz/sceneviewer.cpp +++ b/toonz/sources/toonz/sceneviewer.cpp @@ -1671,7 +1671,7 @@ TAffine SceneViewer::getSceneMatrix() const { void SceneViewer::setViewMatrix(const TAffine &aff, int viewMode) { m_viewAff[viewMode] = aff; - + if (aff.a11 == 0.0) std::cout << "STOP" << std::endl; // In case the previewer is on, request a delayed update if (m_previewMode != NO_PREVIEW) requestTimedRefresh(); } @@ -2040,6 +2040,7 @@ void SceneViewer::fitToCamera() { double xratio = (double)viewRect.width() / cameraRect.getLx(); double yratio = (double)viewRect.height() / cameraRect.getLy(); double ratio = std::min(xratio, yratio); + if (ratio == 0.0) return; if (tempIsFlippedX) setViewMatrix(TScale(-1, 1) * m_viewAff[m_viewMode], m_viewMode); if (tempIsFlippedY) diff --git a/toonz/sources/toonzqt/Resources/edit_center.svg b/toonz/sources/toonzqt/Resources/edit_center.svg new file mode 100644 index 0000000..7e79557 --- /dev/null +++ b/toonz/sources/toonzqt/Resources/edit_center.svg @@ -0,0 +1,111 @@ + +image/svg+xml \ No newline at end of file diff --git a/toonz/sources/toonzqt/Resources/edit_position.svg b/toonz/sources/toonzqt/Resources/edit_position.svg new file mode 100644 index 0000000..dcbe5f8 --- /dev/null +++ b/toonz/sources/toonzqt/Resources/edit_position.svg @@ -0,0 +1,108 @@ + +image/svg+xml \ No newline at end of file diff --git a/toonz/sources/toonzqt/Resources/edit_rotation.svg b/toonz/sources/toonzqt/Resources/edit_rotation.svg new file mode 100644 index 0000000..bf99c97 --- /dev/null +++ b/toonz/sources/toonzqt/Resources/edit_rotation.svg @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/toonz/sources/toonzqt/Resources/edit_scale.svg b/toonz/sources/toonzqt/Resources/edit_scale.svg new file mode 100644 index 0000000..96ed0a8 --- /dev/null +++ b/toonz/sources/toonzqt/Resources/edit_scale.svg @@ -0,0 +1,107 @@ + +image/svg+xml \ No newline at end of file diff --git a/toonz/sources/toonzqt/Resources/edit_shear.svg b/toonz/sources/toonzqt/Resources/edit_shear.svg new file mode 100644 index 0000000..8337e9b --- /dev/null +++ b/toonz/sources/toonzqt/Resources/edit_shear.svg @@ -0,0 +1,113 @@ + +image/svg+xml \ No newline at end of file diff --git a/toonz/sources/toonzqt/dvdialog.cpp b/toonz/sources/toonzqt/dvdialog.cpp index b611545..e2b7081 100644 --- a/toonz/sources/toonzqt/dvdialog.cpp +++ b/toonz/sources/toonzqt/dvdialog.cpp @@ -99,8 +99,8 @@ QString getMsgBoxTitle(MsgType type) { // Separator //----------------------------------------------------------------------------- -Separator::Separator(QString name, QWidget *parent) - : QFrame(parent), m_name(name), m_isHorizontal(true) { +Separator::Separator(QString name, QWidget *parent, bool isHorizontal) + : QFrame(parent), m_name(name), m_isHorizontal(isHorizontal) { // if(m_name.isEmpty()) // setMinimumSize(1,1); // else diff --git a/toonz/sources/toonzqt/toonzqt.qrc b/toonz/sources/toonzqt/toonzqt.qrc index a5ff7d6..ae43122 100644 --- a/toonz/sources/toonzqt/toonzqt.qrc +++ b/toonz/sources/toonzqt/toonzqt.qrc @@ -23,6 +23,11 @@ Resources/delete_over.svg Resources/dragpalette.svg Resources/dragpalette_over.svg + Resources/edit_center.svg + Resources/edit_position.svg + Resources/edit_rotation.svg + Resources/edit_scale.svg + Resources/edit_shear.svg Resources/fit_off.svg Resources/fit_on.svg Resources/fx_off.svg