⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sample_circlecontrol.cpp

📁 The full Fusion SDK consists of a directory of header files (*.h), the eyeonSystem.lib file and the
💻 CPP
字号:
#include "stdafx.h"

#define MODULENAME "Sample_CircleControl"
#define BaseClass PreviewControl
#define ThisClass Sample_CircleControl

#include "dfmath.h"
#include "Sample_CircleControl.h"

#define ELLIPSE_POINTS 120

FuRegisterClass(COMPANY_ID ".Sample_CircleControl", CT_PreviewControl)
	TAG_DONE);

/////////////////////////////////////////////////////////////////////////////
// CircleControl

// Constructor. Just initialise things. No need to handle loading (we never get saved).
Sample_CircleControl::Sample_CircleControl(const Registry *reg, const ScriptVal &table, const TagList &tags) : BaseClass(reg, table, tags)
{
	X = Y = 0.5;
	Size = 1.0;

	InCenter = NULL;

	Hover = false;
}

// Destructor. Make sure we're not still on any Input's lists.
Sample_CircleControl::~Sample_CircleControl()
{
	if (InCenter)
		InCenter->PreviewControlList.Remove(this);
}

// This is where we recognise any extra tags we might support. In this case, we
// look for ECP_Center, which should point to a CLSID_DataType_Point Input containing the
// position of our center point. Here we add ourselves to this Input's PreviewControlList,
// to ensure our NotifyChanged() is called when the center point changes. We
// also have to remove ourselves from this list, in our destructor and if the
// ECP_Center input changes. We also get the current value of this Input. And
// finally, we allow manual setting of the center point via ECD_SetX & ECD_SetY.
bool Sample_CircleControl::SetAttrsTagList(Input *inp, const TagList& tags)
{
	Input *in = (Input *)tags.GetPtr(ECP_Center, InCenter);

	if (InCenter != in)
	{
		if (InCenter)
			InCenter->PreviewControlList.Remove(this);

		InCenter = in;
		
		if (InCenter)
		{
			InCenter->PreviewControlList.Add(this);
			Point *p = (Point *)InCenter->GetSource(Document->GetCurrentTime());
			NotifyChanged(InCenter, p);
			if (p)
				p->Recycle();
		}
	}

	if (!InCenter)
	{
		X = tags.GetDouble(ECD_SetX, X);
		Y = tags.GetDouble(ECD_SetY, Y);
	}

	return BaseClass::SetAttrsTagList(inp, tags);
}


// This will be called whenever your controls need drawing.
void Sample_CircleControl::GLDrawControls(PreviewInfo *pi, TagList *tags)
{
	if (Hover)
		pi->Color4ubv((GLubyte *)&pi->ColorHover);
	else
		pi->Color4ubv((GLubyte *)&pi->Color);

	float64 xpos = X, ypos = Y;

	float64 xval = Size / 2.0;
	float64 yval = Size / 2.0;

	if (m_CoordSpace != PCCS_3D)
	{
		xval *= 1.0;
		yval *= pi->AspectScaleYOut(1.0);

		Vector4 p, startp;
		float64 w2, h2, r, sinA1, cosA1, sinA2, cosA2, ang, increment, s;

		w2 = xval * xval;
		h2 = yval * yval;

		s = w2 * h2;
		ang = 0.0;
		increment = 360.0 / ELLIPSE_POINTS;

		glBegin(GL_LINE_STRIP);
			for (int32 i = 0; i < ELLIPSE_POINTS; i++)
			{
				sinA1 = sin(DegToRad(ang));
				cosA1 = cos(DegToRad(ang));
				sinA2 = sinA1 * sinA1;
				cosA2 = cosA1 * cosA1;
				r = sqrt(s / (w2 * sinA2 + h2 * cosA2));

				p.x = xpos + r * cosA1;
				p.y = ypos + r * sinA1;
				p.z = 0.0;

				pi->TransformOut(p.x, p.y, p.z);

				if (i == 0)
					startp = p;

				glVertex3f(p.x, p.y, p.z);

				ang += increment;
			}
			glVertex3f(startp.x, startp.y, startp.z);
		glEnd();
	}

	BaseClass::GLDrawControls(pi, tags);
}


void Sample_CircleControl::ControlMove(PreviewInfo *pi, CPoint point, TagList *tags)
{
	BaseClass::ControlMove(pi, point, tags);

	if (Dragging == DR_Dragging)
	{
		float64 x = (pi->XPos - X) * pi->Width;
		float64 y = (pi->YPos - Y) * pi->Height * (pi->DispXScale / pi->XScale) * (pi->YScale / pi->DispYScale) * (pi->ViewAspect / pi->SourceAspect);
		float64 xx = fabs(x) / pi->Width * 2.0;
		float64 yy = fabs(y) / pi->Width * 2.0;
		float64 d = sqrt(float64(xx * xx + yy * yy));

		bool end = false;
		if (!UndoSet)
		{
			Document->StartUndo("Adjust Circle");
			UndoSet = end = true;
		}

		if (fabs(d - Size) > 0.00001)
		{
			AutoNumber newsize(d);
			SetInputs(newsize, Document->GetCurrentTime(), 0);
		}

		if (end)
			Document->EndUndo();
	}
}


DragType Sample_CircleControl::ControlDown(PreviewInfo *pi, CPoint point, TagList *tags)
{
	if (pi->DragPC)
	{
		Input *dragInput = (Input *)pi->DragPC->InputList.First();
		if (dragInput == InCenter)
			Dragging = DR_Following;
	}
	else
	{
		float64 x = (pi->XPos - X) * pi->Width;
		float64 y = (pi->YPos - Y) * pi->Height * (pi->DispXScale / pi->XScale) * (pi->YScale / pi->DispYScale) * (pi->ViewAspect / pi->SourceAspect);
		float64 ow = Size / 2.0  * pi->Width;
		float64 d = sqrt(float64(x * x + y * y));

		if (fabs(d - ow) <= GetPrefLong(PREF_GrabDistance))
			Dragging = DR_Dragging;
	}

	return BaseClass::ControlDown(pi, point, tags);
}


void Sample_CircleControl::ControlUp(PreviewInfo *pi, CPoint point, TagList *tags)
{
	BaseClass::ControlUp(pi, point, tags);
}

// Called whenever one of our "friend" inputs (those who have us on their
// PreviewControlList) changes. This is a good place to remember what our
// current center point now is.
void Sample_CircleControl::NotifyChanged(Input *input, Parameter *param, TagList *tags)
{
	if (param)
	{
		if (input == InCenter)			// has our friend Center changed?
		{
			float64 x = ((Point *) param)->X;
			float64 y = ((Point *) param)->Y;

			if (fabs(x - X) > 0.00001 || fabs(y - Y) > 0.00001)
			{
				X = x;
				Y = y;
				BaseClass::NotifyChanged(input, param, tags);
			}
		}
		else
		{
			float64 value = *(Number *) param;

			if (fabs(value - Size) > 0.00001)
			{
				Size = value;
				BaseClass::NotifyChanged(input, param, tags);
			}
		}
	}
}

// This is called if an Input we've added ourselves to doesn't want us anymore.
bool Sample_CircleControl::RemoveInput(Input *inp, TagList *tags)
{
	if (inp == InCenter)
		InCenter = NULL;

	return BaseClass::RemoveInput(inp, tags);
}

// General things can be handled here. In this case, we respond to CCMD_GetInputAt by
// returning a pointer to an Input that could be animated, if a user right-clicks on
// an appropriate part of our controls (i.e. the circumferance of our circle).
uint_ptr Sample_CircleControl::ControlCommand(PreviewInfo *pi, const FuID &id, uint_ptr data, TagList *tags)
{
	uint_ptr ret = NULL;

	if (id == CCMD_HitTest)
	{
		bool oldhover = Hover;

		float64 x = (pi->XPos - X) * pi->Width;
		float64 y = (pi->YPos - Y) * pi->Height * (pi->DispXScale / pi->XScale) * (pi->YScale / pi->DispYScale) * (pi->ViewAspect / pi->SourceAspect);
		float64 ow = Size/2.0 * pi->Width;
		float64 d = sqrt(float64(x * x + y * y));

		Hover = fabs(d - ow) <= GetPrefLong(PREF_GrabDistance);

		// refresh if hover has changed
		if (Hover)
			ret |= CHT_Hit;
		if (Hover != oldhover)
			ret |= CHT_Changed;
	}
	else if (id == CCMD_GetInputAt)
	{
		int32 inpid = -1;
		Input *in = NULL;

		float64 x = (pi->XPos - X) * pi->Width;
		float64 y = (pi->YPos - Y) * pi->Height;
		float64 ow = Size / 2.0 * pi->Width;
		float64 d = sqrt(float64(x * x + y * y));

		if (fabs(d - ow) <= GetPrefLong(PREF_GrabDistance))
			inpid = 0;

		if (inpid != -1)
		{
			ListIterator<Input> lit(InputList);
			while (in = lit.NextObj())
			{
				if (in->GetAttr(PC_ControlID) == inpid)
					break;
			}
		}

		if (in)
			ret = uint_ptr(in);
		else
			ret = BaseClass::ControlCommand(pi, id, data, tags);
	}
	else
		ret = BaseClass::ControlCommand(pi, id, data, tags);

	return ret;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -