tahoma2d/toonz/sources/tnztools/plastictool.h

502 lines
16 KiB
C
Raw Normal View History

2016-05-17 03:04:11 +12:00
#pragma once
2016-03-19 06:57:51 +13:00
#ifndef PLASTICTOOL_H
#define PLASTICTOOL_H
// TnzCore includes
#include "tproperty.h"
#include "tmeshimage.h"
// TnzBase includes
#include "tparamchange.h"
#include "tdoubleparamrelayproperty.h"
// TnzExt includes
#include "ext/plasticskeleton.h"
#include "ext/plasticskeletondeformation.h"
#include "ext/plasticvisualsettings.h"
// TnzQt includes
#include "toonzqt/plasticvertexselection.h"
// TnzTools includes
#include "tools/tool.h"
#include "tools/cursors.h"
#include "tools/tooloptions.h"
// STD includes
#include <memory>
// tcg includes
#include "tcg/tcg_base.h"
#include "tcg/tcg_controlled_access.h"
// Qt includes
#include <QObject>
//****************************************************************************************
// Metric defines
//****************************************************************************************
// Skeleton primitives
2016-06-15 18:43:10 +12:00
#define HIGHLIGHT_DISTANCE 8 // Pixels distance to highlight
#define HANDLE_SIZE 4 // Size of vertex handles
#define HIGHLIGHTED_HANDLE_SIZE HIGHLIGHT_DISTANCE // Size of handle highlights
#define SELECTED_HANDLE_SIZE \
HIGHLIGHTED_HANDLE_SIZE // Size of handle selections
2016-03-19 06:57:51 +13:00
// Mesh primitives
#define MESH_HIGHLIGHT_DISTANCE 8
#define MESH_HIGHLIGHTED_HANDLE_SIZE 4
#define MESH_SELECTED_HANDLE_SIZE 2
//****************************************************************************************
// PlasticTool declaration
//****************************************************************************************
class PlasticTool final : public QObject,
public TTool,
public TParamObserver,
public TSelection::View {
2016-06-15 18:43:10 +12:00
Q_OBJECT
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
friend class PlasticToolOptionsBox;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
class TemporaryActivation {
bool m_activate;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
public:
TemporaryActivation(int row, int col);
~TemporaryActivation();
};
2016-03-19 06:57:51 +13:00
struct MeshIndex final : public tcg::safe_bool<MeshIndex> {
2016-06-15 18:43:10 +12:00
int m_meshIdx, //!< Mesh index in a TMeshImage
m_idx; //!< Index in the referenced mesh
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
explicit MeshIndex(int meshIdx = -1, int idx = -1)
: m_meshIdx(meshIdx), m_idx(idx) {}
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool operator_bool() const { return (m_meshIdx >= 0) && (m_idx >= 0); }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool operator<(const MeshIndex &other) const {
return (m_meshIdx == other.m_meshIdx) ? (m_idx < other.m_idx)
: (m_meshIdx < other.m_meshIdx);
}
};
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
typedef MultipleSelection<MeshIndex> MeshSelection;
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
PlasticSkeletonDeformationP m_sd; //!< Current column's skeleton deformation
int m_skelId; //!< Current m_sd's skeleton id
tcg::invalidable<PlasticSkeleton>
m_deformedSkeleton; //!< The interactively-deformed \a animation-mode
2016-06-20 14:23:05 +12:00
//! skeleton
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TMeshImageP m_mi; //!< Current mesh image
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Property-related vars (ie, tool options)
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TPropertyGroup
*m_propGroup; //!< Tool properties groups (needed for toolbar-building)
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TEnumProperty m_mode; //!< Editing mode (BUILD, ANIMATE, etc..)
TStringProperty m_vertexName; //!< Vertex name property
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TBoolProperty m_interpolate; //!< Strict vertex interpolation property
TBoolProperty m_snapToMesh; //!< Snap to Mesh vertexes during skeleton build
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TDoubleProperty m_thickness; //!< Brush radius, from 1 to 100
TEnumProperty
m_rigidValue; //!< Rigidity drawing value (ie draw rigidity/flexibility)
//!< put a keyframe at current frame
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TBoolProperty
m_globalKey; //!< Whether animating a vertex will cause EVERY vertex to
TBoolProperty
m_keepDistance; //!< Whether animation editing can alter vertex distances
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TStringProperty m_minAngle,
m_maxAngle; //!< Minimum and maximum angle values allowed
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TPropertyGroup m_relayGroup; //!< Group for each vertex parameter relay
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TDoubleParamRelayProperty
m_distanceRelay; //!< Relay property for vertex distance
TDoubleParamRelayProperty m_angleRelay; //!< Relay property for vertex angle
TDoubleParamRelayProperty m_soRelay; //!< Relay property for vertex so
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TDoubleParamRelayProperty
m_skelIdRelay; //!< Relay property for m_sd's skeleton id
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Mouse-related vars
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
TPointD m_pos; //!< Last known mouse position
TPointD m_pressedPos; //!< Last mouse press position
bool m_dragged; //!< Whether dragging occurred between a press/release
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
std::vector<TPointD>
m_pressedVxsPos; //!< Position of selected vertices at mouse press
SkDKey m_pressedSkDF; //!< Skeleton deformation keyframes at mouse press
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Selection/Highlighting-related vars
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int m_svHigh, //!< Highlighted skeleton vertexes
m_seHigh; //!< Highlighted skeleton edges
PlasticVertexSelection m_svSel; //!< Selected skeleton vertexes
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
MeshIndex m_mvHigh, //!< Highlighted mesh vertexes
m_meHigh; //!< Highlighted mesh edges
MeshSelection m_mvSel, //!< Selected mesh vertexes
m_meSel; //!< Selected mesh edges
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Drawing-related vars
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
PlasticVisualSettings m_pvs; //!< Visual options for plastic painting
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Editing-related vars
2016-03-19 06:57:51 +13:00
std::unique_ptr<tcg::polymorphic> m_rigidityPainter; //!< Delegate class to
//! deal with (undoable)
2016-06-20 14:23:05 +12:00
//! rigidity painting
2016-06-15 18:43:10 +12:00
bool m_showSkeletonOS; //!< Whether onion-skinned skeletons must be shown
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Deformation-related vars
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
bool m_recompileOnMouseRelease; //!< Whether skeleton recompilation should
2016-06-20 14:23:05 +12:00
//! happen on mouse release
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
enum Modes {
MESH_IDX = 0,
RIGIDITY_IDX,
BUILD_IDX,
ANIMATE_IDX,
MODES_COUNT
};
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
PlasticTool();
~PlasticTool();
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
ToolType getToolType() const override;
int getCursorId() const override { return ToolCursor::SplineEditorCursor; }
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
ToolOptionsBox *createOptionsBox() override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
TPropertyGroup *getProperties(int idx) override { return &m_propGroup[idx]; }
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void updateTranslation() override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void onSetViewer() override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void onActivate() override;
void onDeactivate() override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void onEnter() override;
void onLeave() override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void addContextMenuItems(QMenu *menu) override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void reset() override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
bool onPropertyChanged(std::string propertyName) override;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
// Methods reimplemented in each interaction mode
2016-06-19 20:06:29 +12:00
void mouseMove(const TPointD &pos, const TMouseEvent &me) override;
void leftButtonDown(const TPointD &pos, const TMouseEvent &me) override;
void leftButtonDrag(const TPointD &pos, const TMouseEvent &me) override;
void leftButtonUp(const TPointD &pos, const TMouseEvent &me) override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void draw() override;
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
// Skeleton methods
void setSkeletonSelection(const PlasticVertexSelection &vSel);
void toggleSkeletonSelection(const PlasticVertexSelection &vSel);
void clearSkeletonSelections();
const PlasticVertexSelection &skeletonVertexSelection() const {
return m_svSel;
}
PlasticVertexSelection branchSelection(int vIdx) const;
void moveVertex_build(const std::vector<TPointD> &originalVxsPos,
const TPointD &posShift);
void addVertex(const PlasticSkeletonVertex &vx);
void insertVertex(const PlasticSkeletonVertex &vx, int e);
void insertVertex(const PlasticSkeletonVertex &vx, int parent,
const std::vector<int> &children);
void removeVertex();
void setVertexName(QString &name);
int addSkeleton(const PlasticSkeletonP &skeleton);
void addSkeleton(int skelId, const PlasticSkeletonP &skeleton);
void removeSkeleton(int skelId);
PlasticSkeletonP skeleton() const;
void touchSkeleton();
PlasticSkeletonDeformationP deformation() const { return m_sd; }
void touchDeformation();
void storeDeformation(); //!< Stores deformation of current column (copying
2016-06-20 14:23:05 +12:00
//! its reference)
2016-06-15 18:43:10 +12:00
void storeSkeletonId(); //!< Stores current skeleton id associated to current
2016-06-20 14:23:05 +12:00
//! deformation
2016-06-15 18:43:10 +12:00
void onChange(); //!< Updates the tool after a deformation parameter change.
//!< It can be used to refresh the tool in ANIMATION mode.
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
// Mesh methods
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const MeshSelection &meshVertexesSelection() const { return m_mvSel; }
const MeshSelection &meshEdgesSelection() const { return m_meSel; }
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setMeshVertexesSelection(const MeshSelection &vSel);
void toggleMeshVertexesSelection(const MeshSelection &vSel);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setMeshEdgesSelection(const MeshSelection &eSel);
void toggleMeshEdgesSelection(const MeshSelection &eSel);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void clearMeshSelections();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void storeMeshImage();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void moveVertex_mesh(const std::vector<TPointD> &originalVxsPos,
const TPointD &posShift);
2016-03-19 06:57:51 +13:00
public:
2016-06-15 18:43:10 +12:00
// Actions with associated undo
int addSkeleton_undo(const PlasticSkeletonP &skeleton);
void addSkeleton_undo(int skelId, const PlasticSkeletonP &skeleton);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void removeSkeleton_undo(int skelId);
void removeSkeleton_withKeyframes_undo(int skelId);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void editSkelId_undo(int skelId);
2016-03-19 06:57:51 +13:00
public slots:
2016-06-15 18:43:10 +12:00
void swapEdge_mesh_undo();
void collapseEdge_mesh_undo();
void splitEdge_mesh_undo();
void cutEdges_mesh_undo();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void deleteSelectedVertex_undo();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setKey_undo();
void setGlobalKey_undo();
void setRestKey_undo();
void setGlobalRestKey_undo();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void copySkeleton();
void pasteSkeleton_undo();
void copyDeformation();
void pasteDeformation_undo();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
signals: // privates
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void skelIdsListChanged();
void skelIdChanged();
2016-03-19 06:57:51 +13:00
protected:
2016-06-15 18:43:10 +12:00
void mouseMove_mesh(const TPointD &pos, const TMouseEvent &me);
void leftButtonDown_mesh(const TPointD &pos, const TMouseEvent &me);
void leftButtonDrag_mesh(const TPointD &pos, const TMouseEvent &me);
void leftButtonUp_mesh(const TPointD &pos, const TMouseEvent &me);
void addContextMenuActions_mesh(QMenu *menu);
void mouseMove_build(const TPointD &pos, const TMouseEvent &me);
void leftButtonDown_build(const TPointD &pos, const TMouseEvent &me);
void leftButtonDrag_build(const TPointD &pos, const TMouseEvent &me);
void leftButtonUp_build(const TPointD &pos, const TMouseEvent &me);
void addContextMenuActions_build(QMenu *menu);
void mouseMove_rigidity(const TPointD &pos, const TMouseEvent &me);
void leftButtonDown_rigidity(const TPointD &pos, const TMouseEvent &me);
void leftButtonDrag_rigidity(const TPointD &pos, const TMouseEvent &me);
void leftButtonUp_rigidity(const TPointD &pos, const TMouseEvent &me);
void addContextMenuActions_rigidity(QMenu *menu);
void mouseMove_animate(const TPointD &pos, const TMouseEvent &me);
void leftButtonDown_animate(const TPointD &pos, const TMouseEvent &me);
void leftButtonDrag_animate(const TPointD &pos, const TMouseEvent &me);
void leftButtonUp_animate(const TPointD &pos, const TMouseEvent &me);
void addContextMenuActions_animate(QMenu *menu);
void draw_mesh();
void draw_build();
void draw_rigidity();
void draw_animate();
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
// Skeleton methods
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
PlasticSkeleton &deformedSkeleton();
void updateDeformedSkeleton(PlasticSkeleton &deformedSkeleton);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Keyframe methods
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void keyFunc_undo(void (PlasticTool::*keyFunc)());
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setKey();
void setGlobalKey();
void setRestKey();
void setGlobalRestKey();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Rigidity methods
static std::unique_ptr<tcg::polymorphic> createRigidityPainter();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Drawing methods
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void drawSkeleton(const PlasticSkeleton &skel, double pixelSize,
UCHAR alpha = 255);
void drawOnionSkinSkeletons_build(double pixelSize);
void drawOnionSkinSkeletons_animate(double pixelSize);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void drawHighlights(const SkDP &sd, const PlasticSkeleton *skel,
double pixelSize);
void drawSelections(const SkDP &sd, const PlasticSkeleton &skel,
double pixelSize);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void drawAngleLimits(const SkDP &sd, int skeId, int v, double pixelSize);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Selection methods
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void setMeshSelection(MeshSelection &target, const MeshSelection &newSel);
void toggleMeshSelection(MeshSelection &target,
const MeshSelection &addedSel);
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void onSelectionChanged() override;
void enableCommands() override;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
// Parameter Observation methods
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void onChange(const TParamChange &) override;
2016-03-19 06:57:51 +13:00
private slots:
2016-06-19 20:06:29 +12:00
void onFrameSwitched() override;
2016-06-15 18:43:10 +12:00
void onColumnSwitched();
void onXsheetChanged();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void onShowMeshToggled(bool on);
void onShowSOToggled(bool on);
void onShowRigidityToggled(bool on);
void onShowSkelOSToggled(bool on);
2016-03-19 06:57:51 +13:00
};
//****************************************************************************************
// PlasticToolOptionsBox declaration
//****************************************************************************************
class PlasticToolOptionsBox final : public GenericToolOptionsBox,
public TProperty::Listener {
2016-06-15 18:43:10 +12:00
Q_OBJECT
2016-03-19 06:57:51 +13:00
public:
2017-05-26 23:06:19 +12:00
PlasticToolOptionsBox(QWidget *parent, TTool *tool, TPaletteHandle *pltHandle,
ToolHandle *toolHandle);
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
class SkelIdsComboBox;
2016-03-19 06:57:51 +13:00
private:
2016-06-15 18:43:10 +12:00
TTool *m_tool;
GenericToolOptionsBox **m_subToolbars;
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
SkelIdsComboBox *m_skelIdComboBox;
QPushButton *m_addSkelButton, *m_removeSkelButton;
2016-03-19 06:57:51 +13:00
private:
2016-06-19 20:06:29 +12:00
void showEvent(QShowEvent *se) override;
void hideEvent(QHideEvent *he) override;
2016-03-19 06:57:51 +13:00
2016-06-19 20:06:29 +12:00
void onPropertyChanged() override;
2016-03-19 06:57:51 +13:00
private slots:
2016-06-15 18:43:10 +12:00
void onSkelIdsListChanged();
void onSkelIdChanged();
void onSkelIdEdited();
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void onAddSkeleton();
void onRemoveSkeleton();
2016-03-19 06:57:51 +13:00
};
//****************************************************************************************
// PlasticTool local functions
//****************************************************************************************
2016-06-15 18:43:10 +12:00
namespace PlasticToolLocals {
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
extern PlasticTool l_plasticTool; //!< Tool instance.
extern bool l_suspendParamsObservation; //!< Used to join multiple param change
2016-06-20 14:23:05 +12:00
//! notifications.
2016-03-19 06:57:51 +13:00
//------------------------------------------------------------------------------
// Generic functions
2016-06-15 18:43:10 +12:00
TPointD projection(
const PlasticSkeleton &skeleton, int e,
const TPointD &pos); //!< Projects specified position an a skeleton edge.
2016-03-19 06:57:51 +13:00
// Global getters
2016-06-15 18:43:10 +12:00
double frame(); //!< Returns current global xsheet frame.
int row(); //!< Returns current global xsheet row.
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int column(); //!< Returns current global xsheet column index.
TXshColumn *xshColumn(); //!< Returns current xsheet column object.
TStageObject *stageObject(); //!< Returns current stage object.
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
const TXshCell &xshCell(); //!< Returns current xsheet cell.
void setCell(
int row,
int col); //!< Moves current xsheet cell to the specified position.
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
int skeletonId(); //!< Returns current skeleton id.
double sdFrame(); //!< Returns current stage object's <I>parameters time</I>
//! (ie the frame value to be used with function editor curves,
//! which takes cyclicity into consideration).
2016-03-19 06:57:51 +13:00
// Keyframe functions
2016-06-15 18:43:10 +12:00
void setKeyframe(
TDoubleParamP &param,
double frame); //!< Sets a keyframe to the specified parameter curve.
void setKeyframe(
SkVD *vd,
double frame); //!< Sets a keyframe to the specified vertex deformation.
void setKeyframe(
const PlasticSkeletonDeformationP &sd,
double frame); //!< Sets a keyframe to an entire skeleton deformation.
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
void invalidateXsheet(); //!< Refreshes xsheet content.
2016-03-19 06:57:51 +13:00
// Draw functions
2016-06-15 18:43:10 +12:00
void drawSquare(const TPointD &pos,
double radius); //!< Draws the outline of a square
void drawFullSquare(const TPointD &pos,
double radius); //!< Draws a filled square
2016-03-19 06:57:51 +13:00
// Mesh functions
2016-06-15 18:43:10 +12:00
std::pair<double, PlasticTool::MeshIndex> closestVertex(const TMeshImage &mi,
const TPointD &pos);
std::pair<double, PlasticTool::MeshIndex> closestEdge(const TMeshImage &mi,
const TPointD &pos);
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
} // namespace PlasticToolLocals
2016-03-19 06:57:51 +13:00
2016-06-15 18:43:10 +12:00
#endif // PLASTICTOOL_H