Blob Blame Raw
#pragma once

#ifndef PLASTICSKELETON_H
#define PLASTICSKELETON_H

#include <memory>

// TnzCore includes
#include "tsmartpointer.h"
#include "tpersist.h"

// TnzExt includes
#include "plastichandle.h"

// Boost includes
#include <boost/config.hpp>

// Qt includes
#include <QString>

#if (defined TNZEXT_EXPORTS && !defined INCLUDE_HPP)
#define REMOVE_INCLUDE_HPP
#define INCLUDE_HPP // Exporting templates needs full instantiation
#endif

#include "tcg_wrap.h"
#include "tcg/tcg_vertex.h"
#include "tcg/tcg_edge.h"
#include "tcg/tcg_face.h"
#include "tcg/tcg_mesh.h"

#ifdef REMOVE_INCLUDE_HPP
#undef INCLUDE_HPP
#endif

#undef DVAPI
#undef DVVAR
#ifdef TNZEXT_EXPORTS
#define DVAPI DV_EXPORT_API
#define DVVAR DV_EXPORT_VAR
#else
#define DVAPI DV_IMPORT_API
#define DVVAR DV_IMPORT_VAR
#endif

//==========================================================================

//    Forward declarations

class PlasticSkeletonDeformation;

//==========================================================================

//************************************************************************************
//    PlasticSkeletonVertex  declaration
//************************************************************************************

//! PlasticSkeletonVertex is the vertex of a plastic skeleton object.
struct DVAPI PlasticSkeletonVertex : public tcg::Vertex<TPointD>, public TPersist {
	PERSIST_DECLARATION(PlasticSkeletonVertex)

private:
	friend class PlasticSkeleton;

	QString m_name; //!< Vertex name
	int m_number;   //!< Vertex \a number - assigned persistently upon addition
	//!< in a skeleton
	int m_parent; //!< Index of the parent vertex in the skeleton

public:
	// Tool data

	double m_minAngle, m_maxAngle; //!< Minimum and maximum accepted angles when updating the vertex
								   //!< position with the mouse. In degrees.
public:
	// Handle data

	bool m_interpolate; //!< Whether the vertex needs to be interpolated (see plasticdeformer.h)

public:
	PlasticSkeletonVertex();
	explicit PlasticSkeletonVertex(const TPointD &pos);

	operator PlasticHandle() const;
	operator TPointD() const { return P(); }

	const QString &name() const { return m_name; }
	int number() const { return m_number; } // Should be removed

	int parent() const { return m_parent; }

	void saveData(TOStream &os);
	void loadData(TIStream &is);
};

//************************************************************************************
//    PlasticSkeleton  declaration
//************************************************************************************

class DVAPI PlasticSkeleton : public TSmartObject, public tcg::Mesh<PlasticSkeletonVertex, tcg::Edge, tcg::FaceN<3>>, public TPersist
{
	DECLARE_CLASS_CODE
	PERSIST_DECLARATION(PlasticSkeleton)

private:
	class Imp;
	std::unique_ptr<Imp> m_imp;

public:
	typedef tcg::Mesh<PlasticSkeletonVertex, tcg::Edge, tcg::FaceN<3>> mesh_type;

public:
	PlasticSkeleton();
	PlasticSkeleton(const PlasticSkeleton &other);
	~PlasticSkeleton();

	PlasticSkeleton &operator=(const PlasticSkeleton &other);

	int parentVertex(int v) { return vertex(v).m_parent; }

	void moveVertex(int v, const TPointD &pos);					  //!< Moves a vertex to the specified position, informing associated deformers
	int addVertex(const PlasticSkeletonVertex &vx, int parent);   //!< Adds a vertex to the skeleton
	int insertVertex(const PlasticSkeletonVertex &vx, int e);	 //!< Inserts a vertex splitting an existing edge
																  //!< \note Inserted Vertex will connect to parent first
	int insertVertex(const PlasticSkeletonVertex &vx, int parent, //!< Generalization of vertex addition/insertion,
					 const std::vector<int> &children);			  //!< it is useful as inverse of vertex removal.
	void removeVertex(int v);									  //!< Removes a vertex, reattaching all its children to parent
	void clear();
	void squeeze();

	bool setVertexName(int v, const QString &name);

	void saveData(TOStream &os);
	void loadData(TIStream &is);

	// Utility functions

	int closestVertex(const TPointD &pos, double *distance = 0) const;
	int closestEdge(const TPointD &pos, double *distance = 0) const;

	std::vector<PlasticHandle> verticesToHandles() const;

public:
	// RValues-related functions
	PlasticSkeleton(PlasticSkeleton &&other);
	PlasticSkeleton &operator=(PlasticSkeleton &&other);

private:
	friend class PlasticSkeletonDeformation; // Skeleton deformations can register to be notified

	void addListener(PlasticSkeletonDeformation *deformation);
	void removeListener(PlasticSkeletonDeformation *deformation);
};

//===============================================================================

#ifdef _WIN32
template class DVAPI TSmartPointerT<PlasticSkeleton>;
#endif

typedef TSmartPointerT<PlasticSkeleton> PlasticSkeletonP;

#endif // PLASTICSKELETON_H