mirror of https://github.com/odrling/Aegisub
Visual typesetting vector clip now supports insertion of new points.
Originally committed to SVN as r1390.
This commit is contained in:
parent
14ade371f3
commit
12534f74a7
|
@ -181,9 +181,26 @@ void Spline::DecodeFromASS(wxString str) {
|
|||
|
||||
|
||||
////////////////////////////////
|
||||
// Append a curve to the spline
|
||||
void Spline::AppendCurve(SplineCurve &curve) {
|
||||
curves.push_back(curve);
|
||||
// Insert a curve to the spline
|
||||
void Spline::InsertCurve(SplineCurve &curve,int index) {
|
||||
if (index == -1) curves.push_back(curve);
|
||||
else {
|
||||
std::list<SplineCurve>::iterator cur;
|
||||
int i=0;
|
||||
for (cur=curves.begin();cur!=curves.end() && i < index;cur++,i++);
|
||||
curves.insert(cur,curve);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////
|
||||
// Get a specific curve
|
||||
SplineCurve *Spline::GetCurve(int index) {
|
||||
int i=0;
|
||||
for (std::list<SplineCurve>::iterator cur=curves.begin();cur!=curves.end() && i <= index;cur++,i++) {
|
||||
if (i==index) return &(*cur);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -279,7 +296,7 @@ void Spline::GetPointList(std::vector<Vector2D> &points) {
|
|||
int steps = len/8;
|
||||
|
||||
// Render curve
|
||||
for (int i=0;i<steps;i++) {
|
||||
for (int i=1;i<=steps;i++) {
|
||||
// Get t and t-1 (u)
|
||||
float t = float(i)/float(steps);
|
||||
points.push_back(cur->GetPoint(t));
|
||||
|
|
|
@ -56,11 +56,13 @@ public:
|
|||
wxString EncodeToASS();
|
||||
void DecodeFromASS(wxString str);
|
||||
|
||||
void AppendCurve(SplineCurve &curve);
|
||||
void AppendCurve(SplineCurve &curve) { InsertCurve(curve,-1); }
|
||||
void InsertCurve(SplineCurve &curve,int index);
|
||||
void MovePoint(int curveIndex,int point,wxPoint pos);
|
||||
void Smooth(float smooth=1.0f);
|
||||
|
||||
void GetPointList(std::vector<Vector2D> &points);
|
||||
SplineCurve *GetCurve(int index);
|
||||
|
||||
void GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &point);
|
||||
Vector2D GetClosestPoint(Vector2D reference);
|
||||
|
|
|
@ -55,9 +55,9 @@ void SplineCurve::Split(SplineCurve &c1,SplineCurve &c2,float t) {
|
|||
c1.type = CURVE_LINE;
|
||||
c2.type = CURVE_LINE;
|
||||
c1.p1 = p1;
|
||||
c1.p2 = p1*t+p2*(1-t);
|
||||
c2.p1 = c1.p2;
|
||||
c2.p2 = p2;
|
||||
c1.p2 = p1*(1-t)+p2*t;
|
||||
c2.p1 = c1.p2;
|
||||
}
|
||||
|
||||
// Split a bicubic
|
||||
|
@ -67,22 +67,22 @@ void SplineCurve::Split(SplineCurve &c1,SplineCurve &c2,float t) {
|
|||
|
||||
// Sub-divisions
|
||||
float u = 1-t;
|
||||
Vector2D p12 = p1*t+p2*u;
|
||||
Vector2D p23 = p2*t+p3*u;
|
||||
Vector2D p34 = p3*t+p4*u;
|
||||
Vector2D p123 = p12*t+p23*u;
|
||||
Vector2D p234 = p23*t+p34*u;
|
||||
Vector2D p1234 = p123*t+p234*u;
|
||||
Vector2D p12 = p1*u+p2*t;
|
||||
Vector2D p23 = p2*u+p3*t;
|
||||
Vector2D p34 = p3*u+p4*t;
|
||||
Vector2D p123 = p12*u+p23*t;
|
||||
Vector2D p234 = p23*u+p34*t;
|
||||
Vector2D p1234 = p123*u+p234*t;
|
||||
|
||||
// Set points
|
||||
c1.p1 = p1;
|
||||
c2.p4 = p4;
|
||||
c1.p2 = p12;
|
||||
c1.p3 = p123;
|
||||
c1.p4 = p1234;
|
||||
c2.p1 = p1234;
|
||||
c2.p2 = p234;
|
||||
c2.p3 = p34;
|
||||
c2.p4 = p4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,8 +168,7 @@ Vector2D SplineCurve::GetClosestPoint(Vector2D ref) const {
|
|||
float SplineCurve::GetClosestParam(Vector2D ref) const {
|
||||
// Line
|
||||
if (type == CURVE_LINE) {
|
||||
//return MID(0.0f,((ref.x-p1.x)*(p2.x-p1.x) + (ref.y-p1.y)*(p2.y-p1.y))/(p2-p1).SquareLen(),1.0f);
|
||||
return MID(0.0f,(ref-p1).Dot(p2-p1)/(p2-p1).SquareLen(),1.0f);
|
||||
return GetClosestSegmentPart(p1,p2,ref);
|
||||
}
|
||||
|
||||
// Bicubic
|
||||
|
@ -196,6 +195,32 @@ float SplineCurve::GetClosestParam(Vector2D ref) const {
|
|||
//////////////////
|
||||
// Quick distance
|
||||
float SplineCurve::GetQuickDistance(Vector2D ref) const {
|
||||
if (type == CURVE_BICUBIC) return MIN(MIN((ref-p1).Len(),(ref-p2).Len()),MIN((ref-p3).Len(),(ref-p4).Len()));
|
||||
// Bicubic
|
||||
if (type == CURVE_BICUBIC) {
|
||||
float len1 = GetClosestSegmentDistance(p1,p2,ref);
|
||||
float len2 = GetClosestSegmentDistance(p2,p3,ref);
|
||||
float len3 = GetClosestSegmentDistance(p3,p4,ref);
|
||||
float len4 = GetClosestSegmentDistance(p4,p1,ref);
|
||||
float len5 = GetClosestSegmentDistance(p1,p3,ref);
|
||||
float len6 = GetClosestSegmentDistance(p2,p4,ref);
|
||||
return MIN(MIN(MIN(len1,len2),MIN(len3,len4)),MIN(len5,len6));
|
||||
}
|
||||
|
||||
// Something else
|
||||
else return (GetClosestPoint(ref)-ref).Len();
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Closest t in segment p1-p2 to point p3
|
||||
float SplineCurve::GetClosestSegmentPart(Vector2D pt1,Vector2D pt2,Vector2D pt3) const {
|
||||
return MID(0.0f,(pt3-pt1).Dot(pt2-pt1)/(pt2-pt1).SquareLen(),1.0f);
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// Closest distance between p3 and segment p1-p2
|
||||
float SplineCurve::GetClosestSegmentDistance(Vector2D pt1,Vector2D pt2,Vector2D pt3) const {
|
||||
float t = GetClosestSegmentPart(pt1,pt2,pt3);
|
||||
return (pt1*(1.0f-t)+pt2*t-pt3).Len();
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@ enum CurveType {
|
|||
////////////////
|
||||
// Spline curve
|
||||
class SplineCurve {
|
||||
private:
|
||||
float GetClosestSegmentPart(Vector2D p1,Vector2D p2,Vector2D p3) const;
|
||||
float GetClosestSegmentDistance(Vector2D p1,Vector2D p2,Vector2D p3) const;
|
||||
|
||||
public:
|
||||
Vector2D p1,p2,p3,p4;
|
||||
CurveType type;
|
||||
|
|
|
@ -289,7 +289,7 @@ void VisualToolVectorClip::ClickedFeature(VisualDraggableFeature &feature) {
|
|||
/////////////
|
||||
// Can hold?
|
||||
bool VisualToolVectorClip::HoldEnabled() {
|
||||
return mode == 1 || mode == 2 || mode == 6 || mode == 7;
|
||||
return mode <= 4 || mode == 6 || mode == 7;
|
||||
}
|
||||
|
||||
|
||||
|
@ -320,8 +320,45 @@ void VisualToolVectorClip::InitializeHold() {
|
|||
spline.AppendCurve(curve);
|
||||
}
|
||||
|
||||
// Convert and insert
|
||||
else if (mode == 3 || mode == 4) {
|
||||
// Get closest point
|
||||
Vector2D pt;
|
||||
int curve;
|
||||
float t;
|
||||
spline.GetClosestParametricPoint(Vector2D(mx,my),curve,t,pt);
|
||||
|
||||
// Convert
|
||||
if (mode == 3) {
|
||||
}
|
||||
|
||||
// Insert
|
||||
else {
|
||||
// Split the curve
|
||||
SplineCurve *c1 = spline.GetCurve(curve);
|
||||
SplineCurve c2;
|
||||
if (!c1) {
|
||||
SplineCurve ct;
|
||||
ct.type = CURVE_LINE;
|
||||
ct.p1 = spline.curves.back().GetEndPoint();
|
||||
ct.p2 = spline.curves.front().p1;
|
||||
ct.p2 = ct.p1*(1-t) + ct.p2*t;
|
||||
spline.AppendCurve(ct);
|
||||
}
|
||||
else {
|
||||
c1->Split(*c1,c2,t);
|
||||
spline.InsertCurve(c2,curve+1);
|
||||
}
|
||||
}
|
||||
|
||||
// Commit
|
||||
SetOverride(_T("\\clip"),_T("(") + spline.EncodeToASS() + _T(")"));
|
||||
Commit(true);
|
||||
holding = false;
|
||||
}
|
||||
|
||||
// Freehand
|
||||
if (mode == 6 || mode == 7) {
|
||||
else if (mode == 6 || mode == 7) {
|
||||
spline.curves.clear();
|
||||
lastX = -100000;
|
||||
lastY = -100000;
|
||||
|
@ -386,7 +423,7 @@ void VisualToolVectorClip::CommitHold() {
|
|||
if (!holding && mode == 7) spline.Smooth();
|
||||
|
||||
// Save it
|
||||
SetOverride(_T("\\clip"),_T("(") + spline.EncodeToASS() + _T(")"));
|
||||
if (mode != 3 && mode != 4) SetOverride(_T("\\clip"),_T("(") + spline.EncodeToASS() + _T(")"));
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue