📄 sample_circlecontrol.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 + -