|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/tool.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/toolutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/cursors.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tproperty.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tdata.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tconvert.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tgl.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "hookselection.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/toolhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonzqt/selection.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tframehandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshlevelhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tscenehandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txsheethandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tcolumnhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/hook.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshlevel.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/toonzscene.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txsheet.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshcell.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshcolumn.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tstageobjecttree.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/txshsimplelevel.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/levelproperties.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/toonzimageutils.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/dpiscale.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/onionskinmask.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "toonz/tonionskinmaskhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
#include <math.h></math.h>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// For Qt translation support
|
|
Toshihiro Shimizu |
890ddd |
#include <qcoreapplication></qcoreapplication>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include <qpainter></qpainter>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
using namespace ToolUtils;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Shinya Kitaoka |
120a6e |
namespace {
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// OtherHook
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class OtherHook {
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
int m_columnIndex;
|
|
Shinya Kitaoka |
120a6e |
int m_hookIndex;
|
|
Shinya Kitaoka |
120a6e |
TPointD m_hookPos;
|
|
Shinya Kitaoka |
120a6e |
OtherHook(int columnIndex, int hookIndex, const TPointD &hookPos)
|
|
Shinya Kitaoka |
120a6e |
: m_columnIndex(columnIndex)
|
|
Shinya Kitaoka |
120a6e |
, m_hookIndex(hookIndex)
|
|
Shinya Kitaoka |
120a6e |
, m_hookPos(hookPos) {}
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//=============================================================================
|
|
Toshihiro Shimizu |
890ddd |
// HookTool
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
class HookTool : public TTool {
|
|
Shinya Kitaoka |
120a6e |
Q_DECLARE_TR_FUNCTIONS(HookTool)
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
HookSelection m_selection;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD m_firstPos, m_lastPos;
|
|
Shinya Kitaoka |
120a6e |
int m_hookId, m_hookSide;
|
|
Shinya Kitaoka |
120a6e |
bool m_deselectArmed;
|
|
Shinya Kitaoka |
120a6e |
HookUndo *m_undo;
|
|
Shinya Kitaoka |
120a6e |
std::vector<otherhook> m_otherHooks;</otherhook>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPropertyGroup m_prop;
|
|
Shinya Kitaoka |
120a6e |
TBoolProperty m_snappedActive;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
TPointD m_snappedPos;
|
|
Shinya Kitaoka |
120a6e |
std::string m_snappedReason;
|
|
Shinya Kitaoka |
120a6e |
TRectD m_shapeBBox;
|
|
Shinya Kitaoka |
120a6e |
bool m_snapped, m_hookSetChanged;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool m_buttonDown;
|
|
Shinya Kitaoka |
120a6e |
TPointD m_pivotOffset;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void getOtherHooks(std::vector<otherhook> &otherHooks);</otherhook>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
public:
|
|
Shinya Kitaoka |
120a6e |
HookTool();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
ToolType getToolType() const override { return TTool::LevelReadTool; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
HookSet *getHookSet() const;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void updateTranslation() override;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void draw() override;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void leftButtonDown(const TPointD &pos, const TMouseEvent &e) override;
|
|
Shinya Kitaoka |
473e70 |
void leftButtonDrag(const TPointD &pos, const TMouseEvent &e) override;
|
|
Shinya Kitaoka |
473e70 |
void leftButtonUp(const TPointD &pos, const TMouseEvent &) override;
|
|
Shinya Kitaoka |
473e70 |
void mouseMove(const TPointD &pos, const TMouseEvent &e) override;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
void onActivate() override;
|
|
Shinya Kitaoka |
473e70 |
void onDeactivate() override;
|
|
Shinya Kitaoka |
473e70 |
void onEnter() override;
|
|
Shinya Kitaoka |
473e70 |
void onImageChanged() override {
|
|
Shinya Kitaoka |
120a6e |
m_selection.selectNone();
|
|
Shinya Kitaoka |
120a6e |
m_hookId = -1;
|
|
Shinya Kitaoka |
120a6e |
m_otherHooks.clear();
|
|
Shinya Kitaoka |
120a6e |
getOtherHooks(m_otherHooks);
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
TPropertyGroup *getProperties(int targetType) override { return &m_prop; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
473e70 |
int getCursorId() const override { return ToolCursor::MoveCursor; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
void onSelectionChanged() { invalidate(); }
|
|
Shinya Kitaoka |
120a6e |
bool select(const TSelection *) { return false; }
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool pick(int &hookId, int &side, const TPointD &pos);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool snap(TPointD &pos, double &range2);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool isSnappedActive() const { return m_snappedActive.getValue(); }
|
|
Shinya Kitaoka |
120a6e |
bool isEditingScene() const {
|
|
Shinya Kitaoka |
120a6e |
return getApplication()->getCurrentFrame()->isEditingScene();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// pivot is the hook the level is attached to.
|
|
Shinya Kitaoka |
120a6e |
// returns -1 if no pivot is defined.
|
|
Shinya Kitaoka |
120a6e |
// Hook1 <==> index=0
|
|
Shinya Kitaoka |
120a6e |
int getPivotIndex() {
|
|
Shinya Kitaoka |
120a6e |
if (!isEditingScene())
|
|
Shinya Kitaoka |
120a6e |
return -1; // a pivot can be defined only when editing a scene
|
|
Shinya Kitaoka |
120a6e |
std::string handle =
|
|
Shinya Kitaoka |
120a6e |
getXsheet()->getStageObject(getObjectId())->getHandle();
|
|
Shinya Kitaoka |
120a6e |
if (handle.find("H") != 0) return -1;
|
|
Shinya Kitaoka |
120a6e |
return std::stoi(handle.substr(1)) - 1;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
void drawHooks(HookSet *hookSet, const TFrameId &fid, bool isOnion);
|
|
Shinya Kitaoka |
120a6e |
// other hooks are drawn in the current level reference frame
|
|
Shinya Kitaoka |
120a6e |
// when the current matrix changes (e.g. because of a parent change or a
|
|
Shinya Kitaoka |
120a6e |
// handle change)
|
|
Shinya Kitaoka |
120a6e |
// we must recompute the hooks positions
|
|
Shinya Kitaoka |
473e70 |
void updateMatrix() override {
|
|
Shinya Kitaoka |
120a6e |
TTool::updateMatrix();
|
|
Shinya Kitaoka |
120a6e |
m_otherHooks.clear();
|
|
Shinya Kitaoka |
120a6e |
getOtherHooks(m_otherHooks);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} hookTool;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
HookTool::HookTool()
|
|
Shinya Kitaoka |
120a6e |
: TTool("T_Hook")
|
|
Shinya Kitaoka |
120a6e |
, m_hookId(-1)
|
|
Shinya Kitaoka |
120a6e |
, m_hookSide(0)
|
|
Shinya Kitaoka |
120a6e |
, m_deselectArmed(false)
|
|
Shinya Kitaoka |
120a6e |
, m_undo(0)
|
|
Shinya Kitaoka |
120a6e |
, m_snappedActive("Snap", true) // W_ToolOptions_Snapped
|
|
Shinya Kitaoka |
120a6e |
, m_snappedPos()
|
|
Shinya Kitaoka |
120a6e |
, m_snappedReason("")
|
|
Shinya Kitaoka |
120a6e |
, m_shapeBBox()
|
|
Shinya Kitaoka |
120a6e |
, m_snapped(false)
|
|
Shinya Kitaoka |
120a6e |
, m_hookSetChanged(false)
|
|
Shinya Kitaoka |
120a6e |
, m_buttonDown(false)
|
|
Shinya Kitaoka |
120a6e |
, m_pivotOffset() {
|
|
Shinya Kitaoka |
120a6e |
bind(TTool::CommonLevels);
|
|
Shinya Kitaoka |
120a6e |
m_prop.bind(m_snappedActive);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_snappedActive.setId("Snap");
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::updateTranslation() {
|
|
Shinya Kitaoka |
120a6e |
m_snappedActive.setQStringName(tr("Snap"));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
HookSet *HookTool::getHookSet() const {
|
|
Shinya Kitaoka |
120a6e |
TXshLevel *xl = TTool::getApplication()->getCurrentLevel()->getLevel();
|
|
Shinya Kitaoka |
120a6e |
if (!xl) return 0;
|
|
Shinya Kitaoka |
120a6e |
return xl->getHookSet();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Toshihiro Shimizu |
890ddd |
// search for hooks located on other columns (they are used as a reference)
|
|
Toshihiro Shimizu |
890ddd |
// the position of hooks is computed in the current level reference frame
|
|
Toshihiro Shimizu |
890ddd |
//
|
|
Shinya Kitaoka |
120a6e |
void HookTool::getOtherHooks(std::vector<otherhook> &otherHooks) {</otherhook>
|
|
Shinya Kitaoka |
120a6e |
if (!getViewer()) return;
|
|
Shinya Kitaoka |
120a6e |
TPointD dpi = getViewer()->getDpiScale();
|
|
Shinya Kitaoka |
120a6e |
TAffine myAffInv = (getCurrentColumnMatrix() * TScale(dpi.x, dpi.y)).inv();
|
|
Shinya Kitaoka |
120a6e |
TXsheet *xsh = getXsheet();
|
|
Shinya Kitaoka |
120a6e |
int row = getFrame();
|
|
Shinya Kitaoka |
120a6e |
int curCol = getColumnIndex();
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < xsh->getColumnCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
if (!xsh->getColumn(i) || !xsh->getColumn(i)->isCamstandVisible()) continue;
|
|
Shinya Kitaoka |
120a6e |
if (i == curCol) continue;
|
|
Shinya Kitaoka |
120a6e |
TXshCell cell = xsh->getCell(row, i);
|
|
Shinya Kitaoka |
120a6e |
if (cell.isEmpty()) continue;
|
|
Shinya Kitaoka |
120a6e |
TAffine aff =
|
|
Shinya Kitaoka |
120a6e |
myAffInv * xsh->getPlacement(TStageObjectId::ColumnId(i), row);
|
|
Shinya Kitaoka |
120a6e |
if (cell.getSimpleLevel())
|
|
Shinya Kitaoka |
120a6e |
aff = aff * getDpiAffine(cell.getSimpleLevel(), cell.m_frameId, true);
|
|
Shinya Kitaoka |
120a6e |
HookSet *hookSet = cell.m_level->getHookSet();
|
|
Shinya Kitaoka |
120a6e |
int j;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (j = 0; j < hookSet->getHookCount(); j++) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->getHook(j);
|
|
Shinya Kitaoka |
120a6e |
if (hook == 0 || hook->isEmpty()) continue;
|
|
Shinya Kitaoka |
120a6e |
TPointD aPos = aff * hook->getAPos(cell.m_frameId);
|
|
Shinya Kitaoka |
120a6e |
TPointD bPos = aff * hook->getBPos(cell.m_frameId);
|
|
Shinya Kitaoka |
120a6e |
otherHooks.push_back(OtherHook(i, j, aPos));
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::drawHooks(HookSet *hookSet, const TFrameId &fid, bool isOnion) {
|
|
Shinya Kitaoka |
120a6e |
int pivotIndex = getPivotIndex();
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < hookSet->getHookCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->getHook(i);
|
|
Shinya Kitaoka |
120a6e |
if (!hook || hook->isEmpty()) continue;
|
|
Shinya Kitaoka |
120a6e |
assert(hook);
|
|
Shinya Kitaoka |
120a6e |
TPointD p0 = hook->getAPos(fid);
|
|
Shinya Kitaoka |
120a6e |
TPointD p1 = hook->getBPos(fid);
|
|
Shinya Kitaoka |
120a6e |
if (pivotIndex == i) {
|
|
Shinya Kitaoka |
120a6e |
// translating the pivot doesn't change its actual position, but just the
|
|
Shinya Kitaoka |
120a6e |
// m_pivotOffset
|
|
Shinya Kitaoka |
120a6e |
// the actual pivot position is changed in the mouseUp event
|
|
Shinya Kitaoka |
120a6e |
p0 += m_pivotOffset;
|
|
Shinya Kitaoka |
120a6e |
p1 += m_pivotOffset;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
bool linked = p0 == p1;
|
|
Shinya Kitaoka |
120a6e |
drawHook(p0, linked ? NormalHook : PassHookA, m_selection.isSelected(i, 1),
|
|
Shinya Kitaoka |
120a6e |
isOnion);
|
|
Shinya Kitaoka |
120a6e |
if (!linked) drawHook(p1, PassHookB, m_selection.isSelected(i, 2), isOnion);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::draw() {
|
|
Shinya Kitaoka |
120a6e |
// ToolUtils::drawRect(TRectD(10,10,110,110), TPixel32(255,200,200), 0xFFF0);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// draw the current image bounding box
|
|
Shinya Kitaoka |
120a6e |
const double v200 = 200.0 / 255.0;
|
|
Shinya Kitaoka |
120a6e |
TImageP image = getImage(false);
|
|
Shinya Kitaoka |
120a6e |
if (!image) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TToonzImageP ti = image;
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vi = image;
|
|
Shinya Kitaoka |
120a6e |
if (ti) {
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox =
|
|
Shinya Kitaoka |
120a6e |
ToonzImageUtils::convertRasterToWorld(convert(ti->getBBox()), ti);
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::drawRect(bbox * ti->getSubsampling(), TPixel32(200, 200, 200),
|
|
Shinya Kitaoka |
120a6e |
0x5555);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (vi) {
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox = vi->getBBox();
|
|
Shinya Kitaoka |
120a6e |
ToolUtils::drawRect(bbox, TPixel32(200, 200, 200), 0x5555);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// draw hooks
|
|
Shinya Kitaoka |
120a6e |
HookSet *hookSet = getHookSet();
|
|
Shinya Kitaoka |
120a6e |
if (!hookSet) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
TFrameHandle *fh = app->getCurrentFrame();
|
|
Shinya Kitaoka |
120a6e |
TFrameId fid = getCurrentFid();
|
|
Shinya Kitaoka |
120a6e |
TXshSimpleLevel *level = 0;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
OnionSkinMask osm = app->getCurrentOnionSkin()->getOnionSkinMask();
|
|
Shinya Kitaoka |
120a6e |
std::vector<int> os;</int>
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isEditingScene())
|
|
Shinya Kitaoka |
120a6e |
osm.getAll(getFrame(), os);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
level = app->getCurrentLevel()->getSimpleLevel();
|
|
Shinya Kitaoka |
120a6e |
assert(level);
|
|
Shinya Kitaoka |
120a6e |
osm.getAll(level->guessIndex(fid), os);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int i;
|
|
Shinya Kitaoka |
120a6e |
if (osm.isEnabled())
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < (int)os.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
if (isEditingScene()) {
|
|
Shinya Kitaoka |
120a6e |
const TXshCell &cell = getXsheet()->getCell(
|
|
Shinya Kitaoka |
120a6e |
os[i], app->getCurrentColumn()->getColumnIndex());
|
|
Shinya Kitaoka |
120a6e |
drawHooks(hookSet, cell.getFrameId(), true);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
const TFrameId &fid2 = level->index2fid(os[i]);
|
|
Shinya Kitaoka |
120a6e |
drawHooks(hookSet, fid2, true);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
drawHooks(hookSet, fid, false);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// TXshCell cell = xsh->getCell(row, i);
|
|
Shinya Kitaoka |
120a6e |
// draw other level hooks
|
|
Shinya Kitaoka |
120a6e |
if (isSnappedActive() && isEditingScene()) {
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < (int)m_otherHooks.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
drawHook(m_otherHooks[i].m_hookPos, OtherLevelHook, false);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// draw hooks balloons
|
|
Shinya Kitaoka |
120a6e |
std::vector<trectd> balloons; // this is used to avoid balloons overlapping</trectd>
|
|
Shinya Kitaoka |
120a6e |
int pivotIndex = getPivotIndex();
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < hookSet->getHookCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->getHook(i);
|
|
Shinya Kitaoka |
120a6e |
if (!hook || hook->isEmpty()) continue;
|
|
Shinya Kitaoka |
120a6e |
assert(hook);
|
|
Shinya Kitaoka |
120a6e |
TPointD p0 = hook->getAPos(fid);
|
|
Shinya Kitaoka |
120a6e |
TPointD p1 = hook->getBPos(fid);
|
|
Shinya Kitaoka |
120a6e |
bool linked = p0 == p1;
|
|
Shinya Kitaoka |
120a6e |
if (i == pivotIndex) {
|
|
Shinya Kitaoka |
120a6e |
p0 += m_pivotOffset;
|
|
Shinya Kitaoka |
120a6e |
p1 += m_pivotOffset;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
TPixel32 balloonColor(200, 220, 205, 200);
|
|
Shinya Kitaoka |
120a6e |
TPoint balloonOffset(20, 20);
|
|
Shinya Kitaoka |
120a6e |
std::string hookName = std::to_string(i + 1);
|
|
Shinya Kitaoka |
120a6e |
drawBalloon(p0, hookName, balloonColor, balloonOffset, false, &balloons);
|
|
Shinya Kitaoka |
120a6e |
if (!linked)
|
|
Shinya Kitaoka |
120a6e |
drawBalloon(p1, hookName, balloonColor, balloonOffset, false, &balloons);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
// draw snapped hook balloon
|
|
Shinya Kitaoka |
120a6e |
if (m_snappedReason != "") {
|
|
Shinya Kitaoka |
120a6e |
TPointD pos = m_snappedPos;
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox = m_shapeBBox;
|
|
Shinya Kitaoka |
120a6e |
if (bbox.getLx() > 0 && bbox.getLy() > 0) {
|
|
Shinya Kitaoka |
120a6e |
glColor3d(v200, v200, v200);
|
|
Shinya Kitaoka |
120a6e |
glEnable(GL_LINE_STIPPLE);
|
|
Shinya Kitaoka |
120a6e |
glLineStipple(5, 0xAAAA);
|
|
Shinya Kitaoka |
120a6e |
tglDrawRect(bbox);
|
|
Shinya Kitaoka |
120a6e |
glDisable(GL_LINE_STIPPLE);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
glBegin(GL_LINES);
|
|
Shinya Kitaoka |
120a6e |
glVertex2d(pos.x, bbox.y0);
|
|
Shinya Kitaoka |
120a6e |
glVertex2d(pos.x, bbox.y1);
|
|
Shinya Kitaoka |
120a6e |
glVertex2d(bbox.x0, pos.y);
|
|
Shinya Kitaoka |
120a6e |
glVertex2d(bbox.x1, pos.y);
|
|
Shinya Kitaoka |
120a6e |
glEnd();
|
|
Shinya Kitaoka |
120a6e |
glDisable(GL_LINE_STIPPLE);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
drawBalloon(pos, m_snappedReason, TPixel32(200, 250, 180, 200),
|
|
Shinya Kitaoka |
120a6e |
TPoint(20, 20), false, &balloons);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// side : 1=A,2=B,3=A&B
|
|
Shinya Kitaoka |
120a6e |
bool HookTool::pick(int &hookId, int &side, const TPointD &pos) {
|
|
Shinya Kitaoka |
120a6e |
HookSet *hookSet = getHookSet();
|
|
Shinya Kitaoka |
120a6e |
if (!hookSet) return false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TFrameId fid = getCurrentFid();
|
|
Shinya Kitaoka |
120a6e |
double minDist2 = 1e8;
|
|
Shinya Kitaoka |
120a6e |
for (int i = 0; i < hookSet->getHookCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->getHook(i);
|
|
Shinya Kitaoka |
120a6e |
if (!hook || hook->isEmpty()) continue;
|
|
Shinya Kitaoka |
120a6e |
TPointD aPos = hook->getAPos(fid);
|
|
Shinya Kitaoka |
120a6e |
TPointD bPos = hook->getBPos(fid);
|
|
Shinya Kitaoka |
120a6e |
bool linked = aPos == bPos;
|
|
Shinya Kitaoka |
120a6e |
if (linked) {
|
|
Shinya Kitaoka |
120a6e |
double dist2 = tdistance2(pos, aPos);
|
|
Shinya Kitaoka |
120a6e |
if (dist2 < minDist2) {
|
|
Shinya Kitaoka |
120a6e |
minDist2 = dist2;
|
|
Shinya Kitaoka |
120a6e |
hookId = hook->getId();
|
|
Shinya Kitaoka |
120a6e |
side = 3;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
double aDist2 = tdistance2(pos, aPos);
|
|
Shinya Kitaoka |
120a6e |
double bDist2 = tdistance2(pos, bPos);
|
|
Shinya Kitaoka |
120a6e |
double dist2 = aDist2;
|
|
Shinya Kitaoka |
120a6e |
int s = 1;
|
|
Shinya Kitaoka |
120a6e |
if (bDist2 < dist2) {
|
|
Shinya Kitaoka |
120a6e |
dist2 = bDist2;
|
|
Shinya Kitaoka |
120a6e |
s = 2;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (dist2 < minDist2) {
|
|
Shinya Kitaoka |
120a6e |
minDist2 = dist2;
|
|
Shinya Kitaoka |
120a6e |
hookId = hook->getId();
|
|
Shinya Kitaoka |
120a6e |
side = s;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
double pixelSize = getPixelSize();
|
|
Shinya Kitaoka |
120a6e |
return minDist2 < 100 * pixelSize * pixelSize;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::leftButtonDown(const TPointD &pos, const TMouseEvent &e) {
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
if (!app) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_buttonDown = true;
|
|
Shinya Kitaoka |
120a6e |
m_snapped = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TXshLevel *xl = app->getCurrentLevel()->getLevel();
|
|
Shinya Kitaoka |
120a6e |
if (xl && xl->getSimpleLevel()) m_undo = new HookUndo(xl->getSimpleLevel());
|
|
Shinya Kitaoka |
120a6e |
m_selection.setLevel(xl);
|
|
Shinya Kitaoka |
120a6e |
m_firstPos = m_lastPos = pos;
|
|
Shinya Kitaoka |
120a6e |
m_hookId = -1, m_hookSide = 0;
|
|
Shinya Kitaoka |
120a6e |
m_deselectArmed = false;
|
|
Shinya Kitaoka |
120a6e |
if (pick(m_hookId, m_hookSide, pos)) {
|
|
Shinya Kitaoka |
120a6e |
if (m_hookSide == 3) // ho cliccato su un cerchio-croce
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if (e.isAltPressed()) // con l'alt voglio dividere
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
m_selection.selectNone();
|
|
Shinya Kitaoka |
120a6e |
m_selection.select(m_hookId, 2);
|
|
Shinya Kitaoka |
120a6e |
} else if (e.isCtrlPressed()) {
|
|
Shinya Kitaoka |
120a6e |
// se sono tutti e due selezionati li deseleziono
|
|
Shinya Kitaoka |
120a6e |
if (m_selection.isSelected(m_hookId, 1) &&
|
|
Shinya Kitaoka |
120a6e |
m_selection.isSelected(m_hookId, 2)) {
|
|
Shinya Kitaoka |
120a6e |
m_selection.unselect(m_hookId, 1);
|
|
Shinya Kitaoka |
120a6e |
m_selection.unselect(m_hookId, 2);
|
|
Shinya Kitaoka |
120a6e |
} else // altrimenti li seleziono tutti e due
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
m_selection.select(m_hookId, 1);
|
|
Shinya Kitaoka |
120a6e |
m_selection.select(m_hookId, 2);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
// senza control ne' shift ne' alt: se ho cliccato su un hook non
|
|
Shinya Kitaoka |
120a6e |
// selezionato
|
|
Shinya Kitaoka |
120a6e |
// deseleziono tutti gli altri e lo seleziono, altrimenti lascio tutto
|
|
Shinya Kitaoka |
120a6e |
// com'e' e al buttonup se non c'e' stato movimento deseleziono gli
|
|
Shinya Kitaoka |
120a6e |
// altri
|
|
Shinya Kitaoka |
120a6e |
if (m_selection.isSelected(m_hookId, 1) ||
|
|
Shinya Kitaoka |
120a6e |
m_selection.isSelected(m_hookId, 2))
|
|
Shinya Kitaoka |
120a6e |
m_deselectArmed = true;
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
m_selection.selectNone();
|
|
Shinya Kitaoka |
120a6e |
m_selection.select(m_hookId, 1);
|
|
Shinya Kitaoka |
120a6e |
m_selection.select(m_hookId, 2);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else // ho cliccato o su un cerchio o su una croce
|
|
Shinya Kitaoka |
120a6e |
{
|
|
Shinya Kitaoka |
120a6e |
if (e.isCtrlPressed())
|
|
Shinya Kitaoka |
120a6e |
m_selection.invertSelection(m_hookId, m_hookSide);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
m_selection.selectNone();
|
|
Shinya Kitaoka |
120a6e |
m_selection.select(m_hookId, m_hookSide);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
// non ho cliccato su nulla: con ctrl non faccio nulla, senza creo un nuovo
|
|
Shinya Kitaoka |
120a6e |
// hook
|
|
Shinya Kitaoka |
120a6e |
if (!e.isCtrlPressed()) {
|
|
Shinya Kitaoka |
120a6e |
m_selection.selectNone();
|
|
Shinya Kitaoka |
120a6e |
TFrameId fid = getCurrentFid();
|
|
Shinya Kitaoka |
120a6e |
HookSet *hookSet = getHookSet();
|
|
Shinya Kitaoka |
120a6e |
if (hookSet && xl->getSimpleLevel() &&
|
|
Shinya Kitaoka |
120a6e |
!xl->getSimpleLevel()->isReadOnly()) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->addHook();
|
|
Shinya Kitaoka |
120a6e |
m_hookSetChanged = true;
|
|
Shinya Kitaoka |
120a6e |
if (hook) {
|
|
Shinya Kitaoka |
120a6e |
TPointD ppos(pos);
|
|
Shinya Kitaoka |
120a6e |
if (m_snappedReason != "") {
|
|
Shinya Kitaoka |
120a6e |
m_snapped = true;
|
|
Shinya Kitaoka |
120a6e |
ppos = m_snappedPos;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_snappedReason = "";
|
|
Shinya Kitaoka |
120a6e |
hook->setAPos(fid, ppos);
|
|
Shinya Kitaoka |
120a6e |
ppos = hook->getAPos(fid);
|
|
Shinya Kitaoka |
120a6e |
m_selection.select(hook->getId(), 1);
|
|
Shinya Kitaoka |
120a6e |
m_selection.select(hook->getId(), 2);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_pivotOffset = TPointD();
|
|
Shinya Kitaoka |
120a6e |
m_selection.makeCurrent();
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::leftButtonDrag(const TPointD &pp, const TMouseEvent &e) {
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
if (!app) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_snapped) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TFrameId fid = getCurrentFid();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// cerco di capire se sto muovendo un unico hook "unito"
|
|
Shinya Kitaoka |
120a6e |
TPointD hookPos;
|
|
Shinya Kitaoka |
120a6e |
HookSet *hookSet = getHookSet();
|
|
Shinya Kitaoka |
120a6e |
if (!hookSet) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
bool draggingPivot = false;
|
|
Shinya Kitaoka |
120a6e |
int pivotIndex = getPivotIndex();
|
|
Shinya Kitaoka |
120a6e |
int i, count = 0;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < hookSet->getHookCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->getHook(i);
|
|
Shinya Kitaoka |
120a6e |
if (!hook || hook->isEmpty()) continue;
|
|
Shinya Kitaoka |
120a6e |
TPointD aPos = hook->getAPos(fid);
|
|
Shinya Kitaoka |
120a6e |
TPointD bPos = hook->getBPos(fid);
|
|
Shinya Kitaoka |
120a6e |
if (m_selection.isSelected(i, 1) && m_selection.isSelected(i, 2) &&
|
|
Shinya Kitaoka |
120a6e |
aPos == bPos) {
|
|
Shinya Kitaoka |
120a6e |
count++;
|
|
Shinya Kitaoka |
120a6e |
hookPos = aPos;
|
|
Shinya Kitaoka |
120a6e |
} else if (m_selection.isSelected(i, 1) || m_selection.isSelected(i, 2)) {
|
|
Shinya Kitaoka |
120a6e |
count = 0;
|
|
Shinya Kitaoka |
120a6e |
break;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (i == pivotIndex && m_selection.isSelected(i, 1)) draggingPivot = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD pos(pp);
|
|
Shinya Kitaoka |
120a6e |
TPointD delta = pos - m_lastPos;
|
|
Shinya Kitaoka |
120a6e |
if (e.isShiftPressed()) {
|
|
Shinya Kitaoka |
120a6e |
// se e' pigiato lo shift non snappa e si muove solo in
|
|
Shinya Kitaoka |
120a6e |
// orizzontale/verticale
|
|
Shinya Kitaoka |
120a6e |
TPointD d = pos - m_firstPos;
|
|
Shinya Kitaoka |
120a6e |
if (d.x * d.x > d.y * d.y)
|
|
Shinya Kitaoka |
120a6e |
pos.y = m_firstPos.y;
|
|
Shinya Kitaoka |
120a6e |
else
|
|
Shinya Kitaoka |
120a6e |
pos.x = m_firstPos.x;
|
|
Shinya Kitaoka |
120a6e |
delta = pos - m_lastPos;
|
|
Shinya Kitaoka |
120a6e |
} else if (count == 1 && isSnappedActive() && !draggingPivot) {
|
|
Shinya Kitaoka |
120a6e |
// snappa
|
|
Shinya Kitaoka |
120a6e |
TPointD oldHookPos = hookPos;
|
|
Shinya Kitaoka |
120a6e |
hookPos += pos - m_lastPos;
|
|
Shinya Kitaoka |
120a6e |
double range2 = getPixelSize() * 20;
|
|
Shinya Kitaoka |
120a6e |
range2 *= range2;
|
|
Shinya Kitaoka |
120a6e |
m_snappedReason = "";
|
|
Shinya Kitaoka |
120a6e |
m_shapeBBox = TRectD();
|
|
Shinya Kitaoka |
120a6e |
if (snap(hookPos, range2)) {
|
|
Shinya Kitaoka |
120a6e |
delta = hookPos - oldHookPos;
|
|
Shinya Kitaoka |
120a6e |
pos = delta + m_lastPos;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
} else if (count > 1 && isSnappedActive() && !draggingPivot) {
|
|
Shinya Kitaoka |
120a6e |
TPointD oldHookPos = hookPos;
|
|
Shinya Kitaoka |
120a6e |
// delta = pos - m_lastPos;
|
|
Shinya Kitaoka |
120a6e |
TPointD snappedDelta = delta;
|
|
Shinya Kitaoka |
120a6e |
double range2 = getPixelSize() * 20;
|
|
Shinya Kitaoka |
120a6e |
range2 *= range2;
|
|
Shinya Kitaoka |
120a6e |
m_snappedReason = "";
|
|
Shinya Kitaoka |
120a6e |
m_shapeBBox = TRectD();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < hookSet->getHookCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->getHook(i);
|
|
Shinya Kitaoka |
120a6e |
if (hook && !hook->isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
if (m_selection.isSelected(i, 1)) {
|
|
Shinya Kitaoka |
120a6e |
TPointD p0 = hook->getAPos(fid);
|
|
Shinya Kitaoka |
120a6e |
TPointD p1 = p0 + delta;
|
|
Shinya Kitaoka |
120a6e |
if (snap(p1, range2)) snappedDelta = p1 - p0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (m_selection.isSelected(i, 1)) {
|
|
Shinya Kitaoka |
120a6e |
TPointD p0 = hook->getBPos(fid);
|
|
Shinya Kitaoka |
120a6e |
TPointD p1 = p0 + delta;
|
|
Shinya Kitaoka |
120a6e |
if (snap(p1, range2)) snappedDelta = p1 - p0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
pos = m_lastPos + snappedDelta;
|
|
Shinya Kitaoka |
120a6e |
delta = snappedDelta;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_lastPos = pos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TXsheet *xsh = getXsheet();
|
|
Shinya Kitaoka |
120a6e |
// std::string handle =
|
|
Shinya Kitaoka |
120a6e |
// getXsheet()->getStageObject(TStageObjectId::ColumnId())->getHandle();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// actual movement
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < hookSet->getHookCount(); i++) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->getHook(i);
|
|
Shinya Kitaoka |
120a6e |
if (!hook || hook->isEmpty()) continue;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
TPointD aPos = hook->getAPos(fid);
|
|
Shinya Kitaoka |
120a6e |
TPointD bPos = hook->getBPos(fid);
|
|
Shinya Kitaoka |
120a6e |
bool aSelected = m_selection.isSelected(i, 1);
|
|
Shinya Kitaoka |
120a6e |
bool bSelected = m_selection.isSelected(i, 2);
|
|
Shinya Kitaoka |
120a6e |
if (pivotIndex == i) {
|
|
Shinya Kitaoka |
120a6e |
if (aSelected) {
|
|
Shinya Kitaoka |
120a6e |
m_pivotOffset += delta;
|
|
Shinya Kitaoka |
120a6e |
if (!bSelected) hook->setBPos(fid, bPos - delta);
|
|
Shinya Kitaoka |
120a6e |
} else if (bSelected)
|
|
Shinya Kitaoka |
120a6e |
hook->setBPos(fid, bPos + delta);
|
|
Shinya Kitaoka |
120a6e |
} else {
|
|
Shinya Kitaoka |
120a6e |
if (aSelected) hook->setAPos(fid, aPos + delta);
|
|
Shinya Kitaoka |
120a6e |
if (bSelected) hook->setBPos(fid, bPos + delta);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_hookSetChanged = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
getXsheet()->getStageObjectTree()->invalidateAll();
|
|
Shinya Kitaoka |
120a6e |
invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::leftButtonUp(const TPointD &pos, const TMouseEvent &) {
|
|
Shinya Kitaoka |
120a6e |
TTool::Application *app = TTool::getApplication();
|
|
Shinya Kitaoka |
120a6e |
if (!app) return;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// note: apparently sometimes (when the user triple-clicks) we receive this
|
|
Shinya Kitaoka |
120a6e |
// event twice
|
|
Shinya Kitaoka |
120a6e |
if (!m_buttonDown) return;
|
|
Shinya Kitaoka |
120a6e |
m_buttonDown = false;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
// if I've moved the pivot hook I have to perform the actual movement in the
|
|
Shinya Kitaoka |
120a6e |
// mouse up event
|
|
Shinya Kitaoka |
120a6e |
int pivotIndex = getPivotIndex();
|
|
Shinya Kitaoka |
120a6e |
if (m_selection.isSelected(pivotIndex, 1) && m_pivotOffset != TPointD()) {
|
|
Shinya Kitaoka |
120a6e |
HookSet *hookSet = getHookSet();
|
|
Shinya Kitaoka |
120a6e |
if (hookSet) {
|
|
Shinya Kitaoka |
120a6e |
Hook *hook = hookSet->getHook(pivotIndex);
|
|
Shinya Kitaoka |
120a6e |
if (hook && !hook->isEmpty()) {
|
|
Shinya Kitaoka |
120a6e |
TFrameId fid = getCurrentFid();
|
|
Shinya Kitaoka |
120a6e |
TPointD aPos = hook->getAPos(fid);
|
|
Shinya Kitaoka |
120a6e |
TPointD bPos = hook->getBPos(fid);
|
|
Shinya Kitaoka |
120a6e |
hook->setAPos(fid, aPos + m_pivotOffset);
|
|
Shinya Kitaoka |
120a6e |
hook->setBPos(fid, bPos + m_pivotOffset);
|
|
Shinya Kitaoka |
120a6e |
getXsheet()->getStageObjectTree()->invalidateAll();
|
|
Shinya Kitaoka |
120a6e |
updateMatrix();
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_snapped = false;
|
|
Shinya Kitaoka |
120a6e |
// m_selection.selectNone();
|
|
Shinya Kitaoka |
120a6e |
TXshLevel *xl = app->getCurrentLevel()->getLevel();
|
|
Shinya Kitaoka |
120a6e |
if (!xl || !xl->getSimpleLevel()) return;
|
|
Shinya Kitaoka |
120a6e |
xl->getSimpleLevel()->getProperties()->setDirtyFlag(true);
|
|
Shinya Kitaoka |
120a6e |
TPointD delta = m_lastPos - m_firstPos;
|
|
Shinya Kitaoka |
120a6e |
if (m_deselectArmed && norm2(delta) < 10) {
|
|
Shinya Kitaoka |
120a6e |
m_selection.selectNone();
|
|
Shinya Kitaoka |
120a6e |
m_selection.unselect(m_hookId, 1);
|
|
Shinya Kitaoka |
120a6e |
m_selection.unselect(m_hookId, 2);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_deselectArmed = false;
|
|
Shinya Kitaoka |
120a6e |
if (m_undo && m_hookSetChanged)
|
|
Shinya Kitaoka |
120a6e |
TUndoManager::manager()->add(m_undo);
|
|
Shinya Kitaoka |
120a6e |
else {
|
|
Shinya Kitaoka |
120a6e |
delete m_undo;
|
|
Shinya Kitaoka |
120a6e |
m_undo = 0;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
m_hookSetChanged = false;
|
|
Shinya Kitaoka |
120a6e |
m_pivotOffset = TPointD();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
bool HookTool::snap(TPointD &pos, double &range2) {
|
|
Shinya Kitaoka |
120a6e |
bool ret = false;
|
|
Shinya Kitaoka |
120a6e |
TPointD snappedPos = pos;
|
|
Shinya Kitaoka |
120a6e |
TVectorImageP vi = TImageP(getImage(false));
|
|
Shinya Kitaoka |
120a6e |
TStroke *selectedShape = 0;
|
|
Shinya Kitaoka |
120a6e |
TRectD selectedShapeBBox;
|
|
Shinya Kitaoka |
120a6e |
double selectedShapeBBoxArea = 0;
|
|
Shinya Kitaoka |
120a6e |
int i, n;
|
|
Shinya Kitaoka |
120a6e |
n = vi ? (int)vi->getStrokeCount() : 0;
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < n; i++) {
|
|
Shinya Kitaoka |
120a6e |
TStroke *stroke = vi->getStroke(i);
|
|
Shinya Kitaoka |
120a6e |
if (!stroke->isSelfLoop()) continue;
|
|
Shinya Kitaoka |
120a6e |
TRectD bbox = stroke->getBBox();
|
|
Shinya Kitaoka |
120a6e |
TPointD strokeCenter = 0.5 * (bbox.getP00() + bbox.getP11());
|
|
Shinya Kitaoka |
120a6e |
if (bbox.contains(pos)) {
|
|
Shinya Kitaoka |
120a6e |
double dist2 = norm2(pos - strokeCenter);
|
|
Shinya Kitaoka |
120a6e |
if (dist2 < range2) {
|
|
Shinya Kitaoka |
120a6e |
double bboxArea = bbox.getLx() * bbox.getLy();
|
|
Shinya Kitaoka |
120a6e |
if (selectedShape == 0 || selectedShapeBBoxArea > bboxArea) {
|
|
Shinya Kitaoka |
120a6e |
range2 = dist2;
|
|
Shinya Kitaoka |
120a6e |
selectedShape = stroke;
|
|
Shinya Kitaoka |
120a6e |
selectedShapeBBox = bbox;
|
|
Shinya Kitaoka |
120a6e |
selectedShapeBBoxArea = bboxArea;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (selectedShape) {
|
|
Shinya Kitaoka |
120a6e |
m_shapeBBox = selectedShapeBBox;
|
|
Shinya Kitaoka |
120a6e |
snappedPos =
|
|
Shinya Kitaoka |
120a6e |
0.5 * (selectedShapeBBox.getP00() + selectedShapeBBox.getP11());
|
|
Shinya Kitaoka |
120a6e |
m_snappedPos = snappedPos;
|
|
Shinya Kitaoka |
120a6e |
m_snappedReason = "shape center";
|
|
Shinya Kitaoka |
120a6e |
ret = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int k = -1;
|
|
Shinya Kitaoka |
120a6e |
if (isEditingScene()) {
|
|
Shinya Kitaoka |
120a6e |
for (i = 0; i < (int)m_otherHooks.size(); i++) {
|
|
Shinya Kitaoka |
120a6e |
double dist2 = norm2(pos - m_otherHooks[i].m_hookPos);
|
|
Shinya Kitaoka |
120a6e |
if (dist2 < range2) {
|
|
Shinya Kitaoka |
120a6e |
range2 = dist2;
|
|
Shinya Kitaoka |
120a6e |
k = i;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
if (k >= 0) {
|
|
Shinya Kitaoka |
120a6e |
m_shapeBBox = TRectD();
|
|
Shinya Kitaoka |
120a6e |
snappedPos = m_otherHooks[k].m_hookPos;
|
|
Shinya Kitaoka |
120a6e |
m_snappedPos = snappedPos;
|
|
Shinya Kitaoka |
120a6e |
m_snappedReason = "Col" +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(m_otherHooks[k].m_columnIndex + 1) + "/" +
|
|
Shinya Kitaoka |
120a6e |
std::to_string(m_otherHooks[k].m_hookIndex + 1);
|
|
Shinya Kitaoka |
120a6e |
ret = true;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
pos = snappedPos;
|
|
Shinya Kitaoka |
120a6e |
return ret;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::mouseMove(const TPointD &pos, const TMouseEvent &e) {
|
|
Shinya Kitaoka |
120a6e |
std::string oldReason = m_snappedReason;
|
|
Shinya Kitaoka |
120a6e |
TPointD oldPos = m_snappedPos;
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_snappedPos = TPointD();
|
|
Shinya Kitaoka |
120a6e |
m_snappedReason = "";
|
|
Shinya Kitaoka |
120a6e |
m_shapeBBox = TRectD();
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
m_otherHooks.clear();
|
|
Shinya Kitaoka |
120a6e |
getOtherHooks(m_otherHooks);
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
int hookId, side;
|
|
Shinya Kitaoka |
120a6e |
if (pick(hookId, side, pos)) {
|
|
Shinya Kitaoka |
120a6e |
if (oldReason != "") invalidate();
|
|
Shinya Kitaoka |
120a6e |
return;
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (isSnappedActive()) {
|
|
Shinya Kitaoka |
120a6e |
double range2 = getPixelSize() * 20.0;
|
|
Shinya Kitaoka |
120a6e |
range2 *= range2;
|
|
Shinya Kitaoka |
120a6e |
TPointD snappedPos = pos;
|
|
Shinya Kitaoka |
120a6e |
snap(snappedPos, range2);
|
|
Shinya Kitaoka |
120a6e |
}
|
|
Shinya Kitaoka |
120a6e |
|
|
Shinya Kitaoka |
120a6e |
if (m_snappedReason != oldReason || m_snappedPos != oldPos) invalidate();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::onActivate() {
|
|
Shinya Kitaoka |
120a6e |
// TODO: getApplication()->editImageOrSpline();
|
|
Shinya Kitaoka |
120a6e |
m_otherHooks.clear();
|
|
Shinya Kitaoka |
120a6e |
getOtherHooks(m_otherHooks);
|
|
Shinya Kitaoka |
120a6e |
m_selection.makeCurrent();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::onDeactivate() {
|
|
Shinya Kitaoka |
120a6e |
m_selection.selectNone();
|
|
Shinya Kitaoka |
120a6e |
TSelection::setCurrent(0);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//-----------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Shinya Kitaoka |
120a6e |
void HookTool::onEnter() { m_selection.makeCurrent(); }
|