|
|
249386 |
|
|
|
249386 |
// TnzTools includes
|
|
|
249386 |
#include <tools tool.h=""></tools>
|
|
|
249386 |
#include <tools toolutils.h=""></tools>
|
|
|
249386 |
#include <tools toolhandle.h=""></tools>
|
|
|
249386 |
#include <tools cursors.h=""></tools>
|
|
|
249386 |
#include <tools assistant.h=""></tools>
|
|
|
da847a |
#include <tools replicator.h=""></tools>
|
|
|
3bac66 |
#include <tools inputmanager.h=""></tools>
|
|
|
249386 |
|
|
|
249386 |
// TnzLib includes
|
|
|
249386 |
#include <toonz tapplication.h=""></toonz>
|
|
|
249386 |
#include <toonz txshlevelhandle.h=""></toonz>
|
|
|
8f7a4e |
#include <toonz txsheethandle.h=""></toonz>
|
|
|
bae79a |
#include <toonz tframehandle.h=""></toonz>
|
|
|
bae79a |
#include <toonz dpiscale.h=""></toonz>
|
|
|
249386 |
|
|
|
249386 |
// TnzCore includes
|
|
|
249386 |
#include <tgl.h></tgl.h>
|
|
|
249386 |
#include <tproperty.h></tproperty.h>
|
|
|
249386 |
#include <tmetaimage.h></tmetaimage.h>
|
|
|
249386 |
|
|
|
4dfb4a |
#include <toonzqt selection.h=""></toonzqt>
|
|
|
4dfb4a |
#include <toonzqt selectioncommandids.h=""></toonzqt>
|
|
|
1715cd |
#include <toonzqt tselectionhandle.h=""></toonzqt>
|
|
|
1715cd |
|
|
|
249386 |
// For Qt translation support
|
|
|
249386 |
#include <qcoreapplication></qcoreapplication>
|
|
|
249386 |
|
|
|
249386 |
#include <map></map>
|
|
|
249386 |
|
|
|
249386 |
|
|
|
249386 |
//-------------------------------------------------------------------
|
|
|
249386 |
|
|
|
249386 |
//=============================================================================
|
|
|
da847a |
// Edit Assistants Swap Undo
|
|
|
da847a |
//-----------------------------------------------------------------------------
|
|
|
da847a |
|
|
|
da847a |
class EditAssistantsReorderUndo final : public ToolUtils::TToolUndo {
|
|
|
da847a |
private:
|
|
|
da847a |
int m_oldPos;
|
|
|
da847a |
int m_newPos;
|
|
|
da847a |
|
|
|
da847a |
public:
|
|
|
da847a |
EditAssistantsReorderUndo(
|
|
|
da847a |
TXshSimpleLevel *level,
|
|
|
da847a |
const TFrameId &frameId,
|
|
|
da847a |
int m_oldPos,
|
|
|
da847a |
int m_newPos
|
|
|
da847a |
):
|
|
|
da847a |
ToolUtils::TToolUndo(level, frameId),
|
|
|
da847a |
m_oldPos(m_oldPos),
|
|
|
da847a |
m_newPos(m_newPos)
|
|
|
da847a |
{ }
|
|
|
da847a |
|
|
|
da847a |
QString getToolName() override
|
|
|
da847a |
{ return QString("Edit Assistants Tool"); }
|
|
|
da847a |
|
|
|
da847a |
int getSize() const override
|
|
|
da847a |
{ return sizeof(*this); }
|
|
|
da847a |
|
|
|
da847a |
void process(int oldPos, int newPos) const {
|
|
|
da847a |
if (oldPos == newPos || oldPos < 0 || newPos < 0)
|
|
|
da847a |
return;
|
|
|
da847a |
TMetaImage *metaImage = dynamic_cast<tmetaimage*>(m_level->getFrame(m_frameId, true).getPointer());</tmetaimage*>
|
|
|
da847a |
if (!metaImage)
|
|
|
da847a |
return;
|
|
|
da847a |
|
|
|
da847a |
TMetaImage::Writer writer(*metaImage);
|
|
|
da847a |
TMetaObjectList &list = *writer;
|
|
|
da847a |
if (oldPos >= list.size() || newPos >= writer->size())
|
|
|
da847a |
return;
|
|
|
da847a |
|
|
|
da847a |
TMetaObjectP obj = list[oldPos];
|
|
|
da847a |
list.erase(list.begin() + oldPos);
|
|
|
da847a |
list.insert(list.begin() + newPos, obj);
|
|
|
da847a |
}
|
|
|
da847a |
|
|
|
da847a |
void undo() const override {
|
|
|
da847a |
process(m_newPos, m_oldPos);
|
|
|
da847a |
TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
|
|
|
da847a |
notifyImageChanged();
|
|
|
da847a |
}
|
|
|
da847a |
|
|
|
da847a |
void redo() const override {
|
|
|
da847a |
process(m_oldPos, m_newPos);
|
|
|
da847a |
TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
|
|
|
da847a |
notifyImageChanged();
|
|
|
da847a |
}
|
|
|
da847a |
};
|
|
|
da847a |
|
|
|
da847a |
|
|
|
da847a |
//=============================================================================
|
|
|
249386 |
// Edit Assistants Undo
|
|
|
249386 |
//-----------------------------------------------------------------------------
|
|
|
249386 |
|
|
|
249386 |
class EditAssistantsUndo final : public ToolUtils::TToolUndo {
|
|
|
249386 |
private:
|
|
|
d94945 |
bool m_isCreated;
|
|
|
d94945 |
bool m_isRemoved;
|
|
|
c5e805 |
int m_index;
|
|
|
249386 |
TMetaObjectP m_metaObject;
|
|
|
249386 |
TVariant m_oldData;
|
|
|
249386 |
TVariant m_newData;
|
|
|
249386 |
size_t m_size;
|
|
|
249386 |
|
|
|
249386 |
public:
|
|
|
249386 |
EditAssistantsUndo(
|
|
|
249386 |
TXshSimpleLevel *level,
|
|
|
249386 |
const TFrameId &frameId,
|
|
|
8f7a4e |
bool frameCreated,
|
|
|
8f7a4e |
bool levelCreated,
|
|
|
8f7a4e |
bool objectCreated,
|
|
|
8f7a4e |
bool objectRemoved,
|
|
|
c5e805 |
int index,
|
|
|
3bac66 |
TMetaObjectP metaObject,
|
|
|
249386 |
TVariant oldData
|
|
|
249386 |
):
|
|
|
8f7a4e |
ToolUtils::TToolUndo(level, frameId, frameCreated, levelCreated),
|
|
|
8f7a4e |
m_isCreated(objectCreated),
|
|
|
8f7a4e |
m_isRemoved(objectRemoved),
|
|
|
c5e805 |
m_index(index),
|
|
|
3bac66 |
m_metaObject(metaObject),
|
|
|
249386 |
m_oldData(oldData),
|
|
|
249386 |
m_newData(m_metaObject->data()),
|
|
|
da847a |
m_size(sizeof(*this) + m_oldData.getMemSize() + m_newData.getMemSize())
|
|
|
249386 |
{ }
|
|
|
249386 |
|
|
|
249386 |
int getSize() const override
|
|
|
249386 |
{ return m_size; }
|
|
|
249386 |
QString getToolName() override
|
|
|
249386 |
{ return QString("Edit Assistants Tool"); }
|
|
|
249386 |
|
|
|
d94945 |
void process(bool remove, const TVariant &data) const {
|
|
|
c5e805 |
if (TMetaImage *metaImage = dynamic_cast<tmetaimage*>(m_level->getFrame(m_frameId, true).getPointer())) {</tmetaimage*>
|
|
|
c5e805 |
TMetaImage::Writer writer(*metaImage);
|
|
|
c5e805 |
bool found = false;
|
|
|
c5e805 |
for(TMetaObjectList::iterator i = writer->begin(); i != writer->end(); ++i)
|
|
|
c5e805 |
if ((*i) == m_metaObject) {
|
|
|
c5e805 |
if (remove) writer->erase(i);
|
|
|
c5e805 |
found = true;
|
|
|
c5e805 |
break;
|
|
|
d94945 |
}
|
|
|
c5e805 |
if (!remove) {
|
|
|
c5e805 |
if (!found)
|
|
|
c5e805 |
writer->insert(
|
|
|
c5e805 |
writer->begin() + std::max(0, std::min((int)writer->size(), m_index)),
|
|
|
c5e805 |
m_metaObject );
|
|
|
c5e805 |
m_metaObject->data() = data;
|
|
|
c5e805 |
if (m_metaObject->handler())
|
|
|
c5e805 |
m_metaObject->handler()->fixData();
|
|
|
249386 |
}
|
|
|
249386 |
}
|
|
|
249386 |
}
|
|
|
249386 |
|
|
|
8f7a4e |
void undo() const override {
|
|
|
8f7a4e |
removeLevelAndFrameIfNeeded();
|
|
|
8f7a4e |
process(m_isCreated, m_oldData);
|
|
|
8f7a4e |
TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
|
|
|
8f7a4e |
notifyImageChanged();
|
|
|
8f7a4e |
}
|
|
|
d94945 |
|
|
|
8f7a4e |
void redo() const override {
|
|
|
8f7a4e |
insertLevelAndFrameIfNeeded();
|
|
|
8f7a4e |
process(m_isRemoved, m_newData);
|
|
|
8f7a4e |
TTool::getApplication()->getCurrentXsheet()->notifyXsheetChanged();
|
|
|
8f7a4e |
notifyImageChanged();
|
|
|
8f7a4e |
}
|
|
|
249386 |
};
|
|
|
249386 |
|
|
|
249386 |
|
|
|
249386 |
//=============================================================================
|
|
|
249386 |
// Edit Assistants Tool
|
|
|
249386 |
//-----------------------------------------------------------------------------
|
|
|
249386 |
|
|
|
249386 |
class EditAssistantsTool final : public TTool {
|
|
|
249386 |
Q_DECLARE_TR_FUNCTIONS(EditAssistantsTool)
|
|
|
4dfb4a |
public:
|
|
|
4dfb4a |
class Selection final : public TSelection {
|
|
|
4dfb4a |
private:
|
|
|
4dfb4a |
EditAssistantsTool &tool;
|
|
|
4dfb4a |
public:
|
|
|
4dfb4a |
explicit Selection(EditAssistantsTool &tool):
|
|
|
4dfb4a |
tool(tool) { }
|
|
|
4dfb4a |
void deleteSelection()
|
|
|
4dfb4a |
{ tool.removeSelected(); }
|
|
|
4dfb4a |
|
|
|
4dfb4a |
void enableCommands() override
|
|
|
4dfb4a |
{ if (!isEmpty()) enableCommand(this, MI_Clear, &Selection::deleteSelection); }
|
|
|
4dfb4a |
bool isEmpty() const override
|
|
|
4dfb4a |
{ return !tool.isSelected(); }
|
|
|
4dfb4a |
void selectNone() override
|
|
|
4dfb4a |
{ tool.deselect(); }
|
|
|
4dfb4a |
};
|
|
|
4dfb4a |
|
|
|
4da757 |
protected:
|
|
|
3bac66 |
enum Mode {
|
|
|
3bac66 |
ModeImage,
|
|
|
3bac66 |
ModeAssistant,
|
|
|
3bac66 |
ModePoint
|
|
|
3bac66 |
};
|
|
|
249386 |
|
|
|
3bac66 |
TPropertyGroup m_allProperties;
|
|
|
3bac66 |
TPropertyGroup m_toolProperties;
|
|
|
249386 |
TEnumProperty m_assistantType;
|
|
|
da847a |
TIntProperty m_replicatorIndex;
|
|
|
249386 |
TStringId m_newAssisnantType;
|
|
|
249386 |
|
|
|
249386 |
bool m_dragging;
|
|
|
aedcda |
bool m_dragAllPoints;
|
|
|
9bb114 |
TSmartHolderT<timage> m_currentImage;</timage>
|
|
|
3bac66 |
TMetaObjectH m_currentAssistant;
|
|
|
249386 |
bool m_currentAssistantCreated;
|
|
|
3bac66 |
bool m_currentAssistantChanged;
|
|
|
249386 |
int m_currentAssistantIndex;
|
|
|
3bac66 |
TVariant m_currentAssistantBackup;
|
|
|
c5e805 |
TStringId m_currentPointName;
|
|
|
249386 |
TPointD m_currentPointOffset;
|
|
|
249386 |
TPointD m_currentPosition;
|
|
|
249386 |
TGuidelineList m_currentGuidelines;
|
|
|
da847a |
|
|
|
da847a |
TReplicator::PointList m_replicatorPoints;
|
|
|
da847a |
|
|
|
da847a |
TMetaImage::Reader *m_reader;
|
|
|
da847a |
TMetaImage *m_readImage;
|
|
|
da847a |
TMetaObjectPC m_readObject;
|
|
|
da847a |
const TAssistantBase *m_readAssistant;
|
|
|
249386 |
|
|
|
da847a |
TMetaImage::Writer *m_writer;
|
|
|
da847a |
TMetaImage *m_writeImage;
|
|
|
da847a |
TMetaObjectP m_writeObject;
|
|
|
da847a |
TAssistantBase *m_writeAssistant;
|
|
|
3bac66 |
|
|
|
4dfb4a |
Selection *selection;
|
|
|
534c7c |
|
|
|
534c7c |
// don't try to follow the pointer from history, it may be invalidated
|
|
|
534c7c |
typedef std::pair<const int="" void*,=""> HistoryItem;</const>
|
|
|
534c7c |
typedef std::vector<historyitem> History;</historyitem>
|
|
|
534c7c |
History m_history;
|
|
|
4dfb4a |
|
|
|
249386 |
public:
|
|
|
249386 |
EditAssistantsTool():
|
|
|
249386 |
TTool("T_EditAssistants"),
|
|
|
249386 |
m_assistantType("AssistantType"),
|
|
|
da847a |
m_replicatorIndex("ReplicatorIndex", 1, 10, 1, false),
|
|
|
249386 |
m_dragging(),
|
|
|
aedcda |
m_dragAllPoints(),
|
|
|
249386 |
m_currentAssistantCreated(),
|
|
|
3bac66 |
m_currentAssistantChanged(),
|
|
|
249386 |
m_currentAssistantIndex(-1),
|
|
|
3bac66 |
m_reader(),
|
|
|
3bac66 |
m_readImage(),
|
|
|
3bac66 |
m_readAssistant(),
|
|
|
3bac66 |
m_writer(),
|
|
|
3bac66 |
m_writeImage(),
|
|
|
3bac66 |
m_writeAssistant()
|
|
|
249386 |
{
|
|
|
4dfb4a |
selection = new Selection(*this);
|
|
|
534c7c |
// also assign assistants to the "brush" button in toolbar
|
|
|
534c7c |
bind(MetaImage | EmptyTarget, "T_Brush");
|
|
|
3bac66 |
m_toolProperties.bind(m_assistantType);
|
|
|
da847a |
m_replicatorIndex.setSpinner();
|
|
|
249386 |
updateTranslation();
|
|
|
249386 |
}
|
|
|
3bac66 |
|
|
|
4dfb4a |
~EditAssistantsTool() {
|
|
|
4dfb4a |
close();
|
|
|
4dfb4a |
delete selection;
|
|
|
4dfb4a |
}
|
|
|
3bac66 |
|
|
|
249386 |
ToolType getToolType() const override
|
|
|
249386 |
{ return TTool::LevelWriteTool; }
|
|
|
fa009d |
unsigned int getToolHints() const override
|
|
|
da847a |
{ return TTool::getToolHints() & ~(HintAssistantsAll | HintReplicatorsAll); }
|
|
|
249386 |
int getCursorId() const override
|
|
|
249386 |
{ return ToolCursor::StrokeSelectCursor; }
|
|
|
9bb114 |
void onImageChanged() override {
|
|
|
534c7c |
if (m_currentImage != getImage(false)) loadHistory();
|
|
|
9bb114 |
getViewer()->GLInvalidateAll();
|
|
|
9bb114 |
}
|
|
|
249386 |
|
|
|
4da757 |
void updateAssistantTypes() {
|
|
|
4da757 |
std::wstring value = m_assistantType.getValue();
|
|
|
4da757 |
|
|
|
4da757 |
m_assistantType.deleteAllValues();
|
|
|
534c7c |
m_assistantType.addValueWithUIName(L"", tr("<choose create="" to="">"));</choose>
|
|
|
4da757 |
|
|
|
4da757 |
const TMetaObject::Registry ®istry = TMetaObject::getRegistry();
|
|
|
4da757 |
for(TMetaObject::Registry::const_iterator i = registry.begin(); i != registry.end(); ++i)
|
|
|
4da757 |
if (const TAssistantType *assistantType = dynamic_cast<const tassistanttype*="">(i->second))</const>
|
|
|
4da757 |
if (assistantType->name)
|
|
|
4da757 |
m_assistantType.addValueWithUIName(
|
|
|
4da757 |
to_wstring(assistantType->name.str()),
|
|
|
4da757 |
assistantType->getLocalName() );
|
|
|
4da757 |
|
|
|
4da757 |
if (m_assistantType.indexOf(value) >= 0)
|
|
|
4da757 |
m_assistantType.setValue(value);
|
|
|
4da757 |
}
|
|
|
4da757 |
|
|
|
3bac66 |
TPropertyGroup* getProperties(int) override {
|
|
|
3bac66 |
m_allProperties.clear();
|
|
|
3bac66 |
for(int i = 0; i < m_toolProperties.getPropertyCount(); ++i)
|
|
|
3bac66 |
m_allProperties.bind( *m_toolProperties.getProperty(i) );
|
|
|
3bac66 |
if (Closer closer = read(ModeAssistant)) {
|
|
|
4da757 |
m_readAssistant->updateTranslation();
|
|
|
da847a |
if (int i = readReplicatorIndex(*m_reader)) {
|
|
|
da847a |
m_replicatorIndex.setValue(i);
|
|
|
da847a |
m_allProperties.bind( m_replicatorIndex );
|
|
|
da847a |
}
|
|
|
3bac66 |
TPropertyGroup &assistantProperties = m_readAssistant->getProperties();
|
|
|
3bac66 |
for(int i = 0; i < assistantProperties.getPropertyCount(); ++i)
|
|
|
3bac66 |
m_allProperties.bind( *assistantProperties.getProperty(i) );
|
|
|
3bac66 |
}
|
|
|
3bac66 |
return &m_allProperties;
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
9bb114 |
void onActivate() override {
|
|
|
9bb114 |
updateAssistantTypes();
|
|
|
534c7c |
loadHistory();
|
|
|
9bb114 |
}
|
|
|
9bb114 |
|
|
|
9bb114 |
void onDeactivate() override
|
|
|
534c7c |
{ resetCurrentPoint(true, false); }
|
|
|
249386 |
|
|
|
249386 |
void updateTranslation() override {
|
|
|
4da757 |
m_assistantType.setQStringName( tr("Assistant Type") );
|
|
|
da847a |
m_replicatorIndex.setQStringName( tr("Order") );
|
|
|
4da757 |
updateAssistantTypes();
|
|
|
4da757 |
if (Closer closer = read(ModeAssistant))
|
|
|
4da757 |
m_readAssistant->updateTranslation();
|
|
|
249386 |
}
|
|
|
249386 |
|
|
|
d07d8b |
bool onPropertyChanged(std::string name, bool addToUndo) override {
|
|
|
da847a |
if (m_replicatorIndex.getName() == name) {
|
|
|
da847a |
writeReplicatorIndex(m_replicatorIndex.getValue());
|
|
|
da847a |
} else
|
|
|
da847a |
if (name == m_assistantType.getName()) {
|
|
|
da847a |
m_newAssisnantType = TStringId::find( to_string(m_assistantType.getValue()) );
|
|
|
3bac66 |
} else {
|
|
|
3bac66 |
if (Closer closer = write(ModeAssistant, true))
|
|
|
3bac66 |
m_writeAssistant->propertyChanged(TStringId::find(name));
|
|
|
d07d8b |
if (addToUndo) apply();
|
|
|
3bac66 |
getViewer()->GLInvalidateAll();
|
|
|
3bac66 |
}
|
|
|
249386 |
return true;
|
|
|
249386 |
}
|
|
|
4dfb4a |
|
|
|
4dfb4a |
TSelection* getSelection() override
|
|
|
4dfb4a |
{ return isSelected() ? selection : 0; }
|
|
|
4dfb4a |
|
|
|
3bac66 |
protected:
|
|
|
534c7c |
void putHistory(const void *img, int assistantIndex) {
|
|
|
534c7c |
if (!img) return;
|
|
|
534c7c |
for(History::iterator i = m_history.begin(); i != m_history.end(); )
|
|
|
534c7c |
if (i->first == img) i = m_history.erase(i); else ++i;
|
|
|
534c7c |
if (m_history.size() >= 10) m_history.pop_back();
|
|
|
534c7c |
m_history.push_back(HistoryItem(img, assistantIndex));
|
|
|
534c7c |
}
|
|
|
534c7c |
|
|
|
534c7c |
void loadHistory() {
|
|
|
534c7c |
int index = -1;
|
|
|
534c7c |
if (Closer closer = read(ModeImage))
|
|
|
534c7c |
for(History::iterator i = m_history.begin(); i != m_history.end(); ++i)
|
|
|
534c7c |
if (i->first == m_readImage) index = i->second;
|
|
|
534c7c |
if (index < 0) resetCurrentPoint(true, false); else chooseAssistant(index);
|
|
|
534c7c |
}
|
|
|
534c7c |
|
|
|
3bac66 |
void close() {
|
|
|
3bac66 |
m_readAssistant = 0;
|
|
|
3bac66 |
m_readObject.reset();
|
|
|
3bac66 |
m_readImage = 0;
|
|
|
3bac66 |
if (m_reader) delete(m_reader);
|
|
|
3bac66 |
m_reader = 0;
|
|
|
3bac66 |
|
|
|
3bac66 |
m_writeAssistant = 0;
|
|
|
3bac66 |
m_writeObject.reset();
|
|
|
3bac66 |
m_writeImage = 0;
|
|
|
3bac66 |
if (m_writer) delete(m_writer);
|
|
|
3bac66 |
m_writer = 0;
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
bool openRead(Mode mode) {
|
|
|
3bac66 |
close();
|
|
|
3bac66 |
|
|
|
3bac66 |
if ( (mode >= ModeAssistant && !m_currentAssistant)
|
|
|
3bac66 |
|| (mode >= ModeAssistant && m_currentAssistantIndex < 0)
|
|
|
c5e805 |
|| (mode >= ModePoint && !m_currentPointName) ) return false;
|
|
|
3bac66 |
|
|
|
4dfb4a |
m_readImage = dynamic_cast<tmetaimage*>(getImage(false));</tmetaimage*>
|
|
|
3bac66 |
if (m_readImage) {
|
|
|
3bac66 |
m_reader = new TMetaImage::Reader(*m_readImage);
|
|
|
3bac66 |
if (mode == ModeImage) return true;
|
|
|
3bac66 |
|
|
|
3bac66 |
if ( m_currentAssistantIndex < (int)(*m_reader)->size()
|
|
|
3bac66 |
&& (**m_reader)[m_currentAssistantIndex] == m_currentAssistant )
|
|
|
3bac66 |
{
|
|
|
3bac66 |
m_readObject = (**m_reader)[m_currentAssistantIndex];
|
|
|
da847a |
m_readAssistant = m_readObject->getHandler<tassistantbase>();</tassistantbase>
|
|
|
3bac66 |
if (mode == ModeAssistant) return true;
|
|
|
3bac66 |
|
|
|
c5e805 |
if (m_readAssistant->findPoint(m_currentPointName)) {
|
|
|
3bac66 |
if (mode == ModePoint) return true;
|
|
|
3bac66 |
}
|
|
|
3bac66 |
}
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
close();
|
|
|
3bac66 |
return false;
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
void touch() {
|
|
|
3bac66 |
if (m_writeAssistant && !m_currentAssistantChanged) {
|
|
|
3bac66 |
m_currentAssistantBackup = m_writeAssistant->data();
|
|
|
3bac66 |
m_currentAssistantChanged = true;
|
|
|
3bac66 |
}
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
bool openWrite(Mode mode, bool touch = false) {
|
|
|
3bac66 |
close();
|
|
|
3bac66 |
|
|
|
3bac66 |
if ( (mode >= ModeAssistant && !m_currentAssistant)
|
|
|
3bac66 |
|| (mode >= ModeAssistant && m_currentAssistantIndex < 0)
|
|
|
c5e805 |
|| (mode >= ModePoint && !m_currentPointName) ) return false;
|
|
|
3bac66 |
|
|
|
3bac66 |
m_writeImage = dynamic_cast<tmetaimage*>(getImage(true));</tmetaimage*>
|
|
|
3bac66 |
if (m_writeImage) {
|
|
|
3bac66 |
m_writer = new TMetaImage::Writer(*m_writeImage);
|
|
|
3bac66 |
if (mode == ModeImage) return true;
|
|
|
3bac66 |
|
|
|
3bac66 |
if ( m_currentAssistantIndex < (int)(*m_writer)->size()
|
|
|
3bac66 |
&& (**m_writer)[m_currentAssistantIndex] == m_currentAssistant )
|
|
|
3bac66 |
{
|
|
|
3bac66 |
m_writeObject = (**m_writer)[m_currentAssistantIndex];
|
|
|
da847a |
m_writeAssistant = m_writeObject->getHandler<tassistantbase>();</tassistantbase>
|
|
|
3bac66 |
if ( (mode == ModeAssistant)
|
|
|
c5e805 |
|| (mode == ModePoint && m_writeAssistant->findPoint(m_currentPointName)) )
|
|
|
3bac66 |
{
|
|
|
3bac66 |
if (touch) this->touch();
|
|
|
3bac66 |
return true;
|
|
|
3bac66 |
}
|
|
|
3bac66 |
}
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
close();
|
|
|
3bac66 |
return false;
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
|
|
|
3bac66 |
//! helper functions for construction like this:
|
|
|
3bac66 |
//! if (Closer closer = read(ModeAssistant)) { do-something... }
|
|
|
3bac66 |
struct Closer {
|
|
|
3bac66 |
struct Args {
|
|
|
3bac66 |
EditAssistantsTool *owner;
|
|
|
3bac66 |
Args(EditAssistantsTool &owner): owner(&owner) { }
|
|
|
3bac66 |
operator bool() const //!< declare bool-convertor here to prevent convertion path: Args->Closer->bool
|
|
|
3bac66 |
{ return owner && (owner->m_reader || owner->m_writer); }
|
|
|
3bac66 |
void close()
|
|
|
3bac66 |
{ if (owner) owner->close(); }
|
|
|
3bac66 |
};
|
|
|
3bac66 |
Closer(const Args &args): args(args) { }
|
|
|
3bac66 |
~Closer() { args.close(); }
|
|
|
3bac66 |
operator bool() const { return args; }
|
|
|
3bac66 |
private:
|
|
|
3bac66 |
Args args;
|
|
|
3bac66 |
};
|
|
|
3bac66 |
|
|
|
3bac66 |
Closer::Args read(Mode mode)
|
|
|
3bac66 |
{ openRead(mode); return Closer::Args(*this); }
|
|
|
3bac66 |
Closer::Args write(Mode mode, bool touch = false)
|
|
|
3bac66 |
{ openWrite(mode, touch); return Closer::Args(*this); }
|
|
|
3bac66 |
|
|
|
3bac66 |
void updateOptionsBox()
|
|
|
cbbe07 |
{ getApplication()->getCurrentTool()->notifyToolOptionsBoxChanged(); }
|
|
|
3bac66 |
|
|
|
534c7c |
void resetCurrentPoint(bool updateOptionsBox = true, bool updateHistory = true) {
|
|
|
3bac66 |
close();
|
|
|
9bb114 |
m_currentImage.reset();
|
|
|
3bac66 |
m_currentAssistant.reset();
|
|
|
249386 |
m_currentAssistantCreated = false;
|
|
|
3bac66 |
m_currentAssistantChanged = false;
|
|
|
249386 |
m_currentAssistantIndex = -1;
|
|
|
c5e805 |
m_currentPointName.reset();
|
|
|
249386 |
m_currentPointOffset = TPointD();
|
|
|
249386 |
m_currentAssistantBackup.reset();
|
|
|
9bb114 |
|
|
|
9bb114 |
// deselect points
|
|
|
534c7c |
if (Closer closer = read(ModeImage)) {
|
|
|
9bb114 |
for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i)
|
|
|
9bb114 |
if (*i)
|
|
|
da847a |
if (const TAssistantBase *assistant = (*i)->getHandler<tassistantbase>())</tassistantbase>
|
|
|
9bb114 |
assistant->deselectAll();
|
|
|
534c7c |
if (updateHistory) putHistory(m_readImage, -1);
|
|
|
534c7c |
}
|
|
|
9bb114 |
|
|
|
3bac66 |
if (updateOptionsBox) this->updateOptionsBox();
|
|
|
249386 |
}
|
|
|
249386 |
|
|
|
534c7c |
bool chooseAssistant(int index) {
|
|
|
534c7c |
resetCurrentPoint(false);
|
|
|
534c7c |
if (index >= 0)
|
|
|
534c7c |
if (Closer closer = read(ModeImage)) {
|
|
|
534c7c |
m_currentImage.set(m_readImage);
|
|
|
534c7c |
if (index < (*m_reader)->size())
|
|
|
534c7c |
if (const TMetaObjectPC &obj = (**m_reader)[index])
|
|
|
534c7c |
if (const TAssistant *assistant = obj->getHandler<tassistant>()) {</tassistant>
|
|
|
534c7c |
assistant->deselectAll();
|
|
|
534c7c |
m_currentAssistant.set(obj);
|
|
|
534c7c |
m_currentAssistantIndex = index;
|
|
|
534c7c |
m_currentPointName = assistant->getBasePoint().name;
|
|
|
534c7c |
assistant->selectAll();
|
|
|
534c7c |
}
|
|
|
534c7c |
putHistory(m_readImage, m_currentAssistantIndex);
|
|
|
534c7c |
}
|
|
|
534c7c |
this->updateOptionsBox();
|
|
|
534c7c |
return m_currentAssistantIndex >= 0;
|
|
|
534c7c |
}
|
|
|
534c7c |
|
|
|
3bac66 |
bool findCurrentPoint(const TPointD &position, double pixelSize = 1, bool updateOptionsBox = true) {
|
|
|
3bac66 |
resetCurrentPoint(false);
|
|
|
3bac66 |
if (Closer closer = read(ModeImage)) {
|
|
|
9bb114 |
m_currentImage.set(m_readImage);
|
|
|
3bac66 |
for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i) {
|
|
|
3bac66 |
if (!*i) continue;
|
|
|
3bac66 |
|
|
|
da847a |
const TAssistantBase *assistant = (*i)->getHandler<tassistantbase>();</tassistantbase>
|
|
|
3bac66 |
if (!assistant) continue;
|
|
|
3bac66 |
|
|
|
3bac66 |
assistant->deselectAll();
|
|
|
7900ea |
|
|
|
7900ea |
// last points is less significant and don't affecting the first points
|
|
|
7900ea |
// so iterate points in reverse order to avoid unsolvable points overlapping
|
|
|
7900ea |
const TAssistantPointOrder &points = assistant->pointsOrder();
|
|
|
7900ea |
for( TAssistantPointOrder::const_reverse_iterator j = points.rbegin();
|
|
|
7900ea |
j != points.rend() && m_currentAssistantIndex < 0;
|
|
|
7900ea |
++j )
|
|
|
7900ea |
{
|
|
|
7900ea |
const TAssistantPoint &p = **j;
|
|
|
3bac66 |
TPointD offset = p.position - position;
|
|
|
c5e805 |
if (p.visible && norm2(offset) <= p.radius*p.radius*pixelSize*pixelSize) {
|
|
|
3bac66 |
m_currentAssistant.set(*i);
|
|
|
3bac66 |
m_currentAssistantIndex = i - (*m_reader)->begin();
|
|
|
7900ea |
m_currentPointName = p.name;
|
|
|
3bac66 |
m_currentPointOffset = offset;
|
|
|
3bac66 |
assistant->selectAll();
|
|
|
3bac66 |
}
|
|
|
249386 |
}
|
|
|
249386 |
}
|
|
|
534c7c |
putHistory(m_readImage, m_currentAssistantIndex);
|
|
|
249386 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
if (updateOptionsBox) this->updateOptionsBox();
|
|
|
3bac66 |
return m_currentAssistantIndex >= 0;
|
|
|
249386 |
}
|
|
|
249386 |
|
|
|
3bac66 |
bool apply() {
|
|
|
3bac66 |
bool success = false;
|
|
|
3bac66 |
if (m_currentAssistantChanged || m_currentAssistantCreated) {
|
|
|
7900ea |
if (Closer closer = write(ModeAssistant)) {
|
|
|
3bac66 |
m_writeAssistant->fixData();
|
|
|
3bac66 |
TUndoManager::manager()->add(new EditAssistantsUndo(
|
|
|
3bac66 |
getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(),
|
|
|
3bac66 |
getCurrentFid(),
|
|
|
8f7a4e |
m_isFrameCreated,
|
|
|
8f7a4e |
m_isLevelCreated,
|
|
|
3bac66 |
m_currentAssistantCreated,
|
|
|
3bac66 |
false,
|
|
|
c5e805 |
m_currentAssistantIndex,
|
|
|
3bac66 |
m_writeObject,
|
|
|
3bac66 |
m_currentAssistantBackup ));
|
|
|
3bac66 |
m_currentAssistantCreated = false;
|
|
|
3bac66 |
m_currentAssistantChanged = false;
|
|
|
8f7a4e |
m_isFrameCreated = false;
|
|
|
8f7a4e |
m_isLevelCreated = false;
|
|
|
3bac66 |
success = true;
|
|
|
3bac66 |
}
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
if (success) {
|
|
|
3bac66 |
notifyImageChanged();
|
|
|
3bac66 |
getApplication()->getCurrentTool()->notifyToolChanged();
|
|
|
4dfb4a |
TTool::getApplication()->getCurrentSelection()->setSelection( getSelection() );
|
|
|
3bac66 |
getViewer()->GLInvalidateAll();
|
|
|
3bac66 |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
return success;
|
|
|
249386 |
}
|
|
|
4dfb4a |
|
|
|
da847a |
int readReplicatorIndex(TMetaImage::Reader &reader) {
|
|
|
da847a |
int cnt = (int)reader->size();
|
|
|
da847a |
int index = 0;
|
|
|
da847a |
for(int i = 0; i < cnt; ++i) {
|
|
|
da847a |
if (const TMetaObjectPC &obj = (*reader)[i])
|
|
|
da847a |
if (obj->getHandler<treplicator>()) {</treplicator>
|
|
|
da847a |
++index;
|
|
|
da847a |
if (m_currentAssistantIndex == i)
|
|
|
da847a |
return index;
|
|
|
da847a |
}
|
|
|
da847a |
}
|
|
|
da847a |
return 0;
|
|
|
da847a |
}
|
|
|
da847a |
|
|
|
da847a |
void writeReplicatorIndex(int index) {
|
|
|
da847a |
apply();
|
|
|
da847a |
|
|
|
da847a |
int wantIndex = index;
|
|
|
da847a |
int oldPos = -1;
|
|
|
da847a |
int newPos = -1;
|
|
|
da847a |
bool changed = false;
|
|
|
da847a |
|
|
|
da847a |
if (Closer closer = write(ModeAssistant)) {
|
|
|
da847a |
if (index < 1)
|
|
|
da847a |
index = 1;
|
|
|
da847a |
|
|
|
da847a |
int idx = 0;
|
|
|
da847a |
int lastPos = -1;
|
|
|
da847a |
|
|
|
da847a |
TMetaObjectList &list = **m_writer;
|
|
|
da847a |
|
|
|
da847a |
int cnt = (int)list.size();
|
|
|
da847a |
for(int i = 0; i < cnt; ++i) {
|
|
|
da847a |
if (list[i] && list[i]->getHandler<treplicator>()) {</treplicator>
|
|
|
da847a |
++idx;
|
|
|
da847a |
if (m_currentAssistantIndex == i) oldPos = i;
|
|
|
da847a |
if (idx == index) newPos = i;
|
|
|
da847a |
lastPos = i;
|
|
|
da847a |
}
|
|
|
da847a |
}
|
|
|
da847a |
|
|
|
da847a |
if (oldPos >= 0 && lastPos >= 0) {
|
|
|
da847a |
assert(idx);
|
|
|
da847a |
if (newPos < 0)
|
|
|
da847a |
{ index = idx; newPos = lastPos; }
|
|
|
da847a |
if (oldPos != newPos) {
|
|
|
da847a |
TMetaObjectP obj = list[oldPos];
|
|
|
da847a |
list.erase(list.begin() + oldPos);
|
|
|
da847a |
list.insert(list.begin() + newPos, obj);
|
|
|
da847a |
|
|
|
da847a |
TUndoManager::manager()->add(new EditAssistantsReorderUndo(
|
|
|
da847a |
getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(),
|
|
|
da847a |
getCurrentFid(),
|
|
|
da847a |
oldPos,
|
|
|
da847a |
newPos ));
|
|
|
da847a |
|
|
|
da847a |
changed = true;
|
|
|
da847a |
}
|
|
|
da847a |
}
|
|
|
da847a |
}
|
|
|
da847a |
|
|
|
da847a |
if (changed) {
|
|
|
da847a |
m_currentAssistantIndex = newPos;
|
|
|
da847a |
invalidate();
|
|
|
da847a |
}
|
|
|
da847a |
|
|
|
da847a |
if (wantIndex != index)
|
|
|
da847a |
this->updateOptionsBox();
|
|
|
da847a |
}
|
|
|
da847a |
|
|
|
8f7a4e |
public:
|
|
|
4dfb4a |
void deselect()
|
|
|
534c7c |
{ resetCurrentPoint(true, false); }
|
|
|
4dfb4a |
|
|
|
4dfb4a |
bool isSelected()
|
|
|
4dfb4a |
{ return read(ModeAssistant); }
|
|
|
4dfb4a |
|
|
|
4dfb4a |
bool removeSelected() {
|
|
|
4dfb4a |
apply();
|
|
|
4dfb4a |
bool success = false;
|
|
|
4dfb4a |
if (Closer closer = write(ModeAssistant, true)) {
|
|
|
4dfb4a |
(*m_writer)->erase((*m_writer)->begin() + m_currentAssistantIndex);
|
|
|
4dfb4a |
TUndoManager::manager()->add(new EditAssistantsUndo(
|
|
|
4dfb4a |
getApplication()->getCurrentLevel()->getLevel()->getSimpleLevel(),
|
|
|
4dfb4a |
getCurrentFid(),
|
|
|
4dfb4a |
false, // frameCreated
|
|
|
4dfb4a |
false, // levelCreated
|
|
|
4dfb4a |
false, // objectCreated
|
|
|
4dfb4a |
true, // objectRemoved
|
|
|
4dfb4a |
m_currentAssistantIndex, m_writeObject, m_writeObject->data()));
|
|
|
4dfb4a |
success = true;
|
|
|
4dfb4a |
}
|
|
|
4dfb4a |
|
|
|
4dfb4a |
if (success) notifyImageChanged();
|
|
|
4dfb4a |
|
|
|
4dfb4a |
resetCurrentPoint();
|
|
|
4dfb4a |
getApplication()->getCurrentTool()->notifyToolChanged();
|
|
|
4dfb4a |
TTool::getApplication()->getCurrentSelection()->setSelection( getSelection() );
|
|
|
4dfb4a |
getViewer()->GLInvalidateAll();
|
|
|
4dfb4a |
return success;
|
|
|
4dfb4a |
}
|
|
|
4dfb4a |
|
|
|
8f7a4e |
bool preLeftButtonDown() override {
|
|
|
af0f93 |
if (m_assistantType.getIndex() != 0) touchImage();
|
|
|
4dfb4a |
TTool::getApplication()->getCurrentSelection()->setSelection( getSelection() );
|
|
|
8f7a4e |
return true;
|
|
|
8f7a4e |
}
|
|
|
8f7a4e |
|
|
|
aedcda |
void leftButtonDown(const TPointD &position, const TMouseEvent &event) override {
|
|
|
3bac66 |
apply();
|
|
|
249386 |
m_dragging = true;
|
|
|
aedcda |
m_dragAllPoints = false;
|
|
|
249386 |
if (m_newAssisnantType) {
|
|
|
249386 |
// create assistant
|
|
|
7900ea |
resetCurrentPoint(false);
|
|
|
3bac66 |
if (Closer closer = write(ModeImage)) {
|
|
|
3bac66 |
TMetaObjectP object(new TMetaObject(m_newAssisnantType));
|
|
|
da847a |
if (TAssistantBase *assistant = object->getHandler<tassistantbase>()) {</tassistantbase>
|
|
|
c5e805 |
assistant->setDefaults();
|
|
|
7900ea |
assistant->move(position);
|
|
|
7900ea |
assistant->selectAll();
|
|
|
4dfb4a |
m_currentImage.set(m_writeImage);
|
|
|
aedcda |
m_dragAllPoints = true;
|
|
|
c5e805 |
m_currentAssistantCreated = true;
|
|
|
c5e805 |
m_currentAssistantChanged = true;
|
|
|
c5e805 |
m_currentAssistantIndex = (int)(*m_writer)->size();
|
|
|
c5e805 |
m_currentAssistant = object;
|
|
|
c5e805 |
m_currentPointName = assistant->getBasePoint().name;
|
|
|
c5e805 |
m_currentPointOffset = TPointD();
|
|
|
c5e805 |
m_currentAssistantBackup = assistant->data();
|
|
|
3bac66 |
(*m_writer)->push_back(object);
|
|
|
249386 |
}
|
|
|
249386 |
}
|
|
|
7900ea |
updateOptionsBox();
|
|
|
249386 |
m_newAssisnantType.reset();
|
|
|
3bac66 |
} else {
|
|
|
985f38 |
findCurrentPoint(position, getViewer()->getPixelSize());
|
|
|
aedcda |
if (event.isShiftPressed())
|
|
|
aedcda |
if (Closer closer = read(ModePoint)) {
|
|
|
aedcda |
m_currentPointName = m_readAssistant->getBasePoint().name;
|
|
|
aedcda |
m_currentPointOffset = m_readAssistant->getBasePoint().position - position;
|
|
|
aedcda |
m_dragAllPoints = true;
|
|
|
aedcda |
}
|
|
|
249386 |
}
|
|
|
3bac66 |
|
|
|
249386 |
m_currentPosition = position;
|
|
|
249386 |
getViewer()->GLInvalidateAll();
|
|
|
249386 |
}
|
|
|
249386 |
|
|
|
249386 |
void leftButtonDrag(const TPointD &position, const TMouseEvent&) override {
|
|
|
aedcda |
if (m_dragAllPoints) {
|
|
|
b15438 |
if (Closer closer = write(ModeAssistant))
|
|
|
b15438 |
if (m_writeAssistant->move(position + m_currentPointOffset))
|
|
|
b15438 |
touch();
|
|
|
7900ea |
} else {
|
|
|
b15438 |
if (Closer closer = write(ModePoint))
|
|
|
b15438 |
if (m_writeAssistant->movePoint(m_currentPointName, position + m_currentPointOffset))
|
|
|
b15438 |
touch();
|
|
|
7900ea |
}
|
|
|
249386 |
m_currentPosition = position;
|
|
|
249386 |
getViewer()->GLInvalidateAll();
|
|
|
249386 |
}
|
|
|
249386 |
|
|
|
249386 |
void leftButtonUp(const TPointD &position, const TMouseEvent&) override {
|
|
|
4dfb4a |
if (m_dragAllPoints) {
|
|
|
b15438 |
if (Closer closer = write(ModeAssistant))
|
|
|
b15438 |
if (m_writeAssistant->move(position + m_currentPointOffset))
|
|
|
b15438 |
touch();
|
|
|
7900ea |
} else {
|
|
|
b15438 |
if (Closer closer = write(ModePoint))
|
|
|
b15438 |
if (m_writeAssistant->movePoint(m_currentPointName, position + m_currentPointOffset))
|
|
|
b15438 |
touch();
|
|
|
7900ea |
}
|
|
|
3bac66 |
|
|
|
3bac66 |
apply();
|
|
|
d94945 |
m_assistantType.setIndex(0);
|
|
|
249386 |
getApplication()->getCurrentTool()->notifyToolChanged();
|
|
|
4dfb4a |
TTool::getApplication()->getCurrentSelection()->setSelection( getSelection() );
|
|
|
249386 |
m_currentPosition = position;
|
|
|
249386 |
getViewer()->GLInvalidateAll();
|
|
|
aedcda |
m_dragAllPoints = false;
|
|
|
249386 |
m_dragging = false;
|
|
|
249386 |
}
|
|
|
249386 |
|
|
|
bae79a |
void mouseMove(const TPointD &position, const TMouseEvent&) override {
|
|
|
bae79a |
m_currentPosition = position;
|
|
|
bae79a |
m_currentPointOffset = TPointD();
|
|
|
bae79a |
getViewer()->GLInvalidateAll();
|
|
|
bae79a |
}
|
|
|
bae79a |
|
|
|
249386 |
void draw() override {
|
|
|
249386 |
m_currentGuidelines.clear();
|
|
|
bae79a |
TPointD position = m_currentPosition + m_currentPointOffset;
|
|
|
bae79a |
|
|
|
249386 |
// draw assistants
|
|
|
da847a |
int index = 0;
|
|
|
3bac66 |
if (Closer closer = read(ModeImage))
|
|
|
3bac66 |
for(TMetaObjectListCW::iterator i = (*m_reader)->begin(); i != (*m_reader)->end(); ++i)
|
|
|
249386 |
if (*i)
|
|
|
da847a |
if (const TAssistantBase *base = (*i)->getHandler<tassistantbase>())</tassistantbase>
|
|
|
249386 |
{
|
|
|
da847a |
if (dynamic_cast<const treplicator*="">(base)) {</const>
|
|
|
da847a |
++index;
|
|
|
da847a |
base->drawEdit(getViewer(), index);
|
|
|
da847a |
} else {
|
|
|
da847a |
base->drawEdit(getViewer());
|
|
|
da847a |
}
|
|
|
da847a |
|
|
|
da847a |
if (const TAssistant *assistant = dynamic_cast<const tassistant*="">(base))</const>
|
|
|
da847a |
assistant->getGuidelines(
|
|
|
da847a |
position,
|
|
|
da847a |
TAffine(),
|
|
|
da847a |
m_currentGuidelines );
|
|
|
249386 |
}
|
|
|
bae79a |
|
|
|
da847a |
TImage *img = getImage(false);
|
|
|
da847a |
|
|
|
fa009d |
// draw assistans and guidelines from other layers
|
|
|
fa009d |
TAssistant::scanAssistants(
|
|
|
fa009d |
this, // tool
|
|
|
fa009d |
&position, 1, // pointer positions
|
|
|
3a19fe |
&m_currentGuidelines, // out guidelines
|
|
|
fa009d |
true, // draw
|
|
|
fa009d |
false, // enabled only
|
|
|
fa009d |
false, // mark enabled
|
|
|
fa009d |
true, // draw guidelines
|
|
|
da847a |
img ); // skip image
|
|
|
da847a |
|
|
|
da847a |
// draw replicators from other layers
|
|
|
da847a |
TReplicator::scanReplicators(
|
|
|
da847a |
this, // tool
|
|
|
da847a |
nullptr, // in/out points
|
|
|
da847a |
nullptr, // out modifiers
|
|
|
da847a |
true, // draw
|
|
|
da847a |
false, // enabled only
|
|
|
da847a |
false, // mark enabled
|
|
|
da847a |
false, // draw points
|
|
|
da847a |
img ); // skip image
|
|
|
da847a |
|
|
|
da847a |
// draw replicator points
|
|
|
da847a |
m_replicatorPoints.clear();
|
|
|
da847a |
m_replicatorPoints.push_back(position);
|
|
|
da847a |
TReplicator::scanReplicators(
|
|
|
da847a |
this, // tool
|
|
|
da847a |
&m_replicatorPoints, // in/out points
|
|
|
da847a |
nullptr, // out modifiers
|
|
|
da847a |
false, // draw
|
|
|
da847a |
false, // enabled only
|
|
|
da847a |
false, // mark enabled
|
|
|
da847a |
true, // draw points
|
|
|
fa009d |
nullptr ); // skip image
|
|
|
249386 |
}
|
|
|
249386 |
};
|
|
|
249386 |
|
|
|
249386 |
//-------------------------------------------------------------------
|
|
|
249386 |
|
|
|
249386 |
EditAssistantsTool editAssistantsTool;
|