diff --git a/aegisub/src/gl_wrap.cpp b/aegisub/src/gl_wrap.cpp index ee0faa939..062f4a9fb 100644 --- a/aegisub/src/gl_wrap.cpp +++ b/aegisub/src/gl_wrap.cpp @@ -52,24 +52,6 @@ #include "options.h" -////////////////////////// -// Extension get function -#ifdef __WIN32__ - -/// @brief DOCME -/// @param str -/// @return -/// -void* glGetProc(const char *str) { return wglGetProcAddress(str); } -#else - -/// DOCME -#define glGetProc(a) glXGetProcAddress((const GLubyte *)(a)) -#endif - - - - /// @brief Constructor /// OpenGLWrapper::OpenGLWrapper() { diff --git a/aegisub/src/gl_wrap.h b/aegisub/src/gl_wrap.h index 126992b81..1e6c66162 100644 --- a/aegisub/src/gl_wrap.h +++ b/aegisub/src/gl_wrap.h @@ -51,6 +51,19 @@ typedef GLuint GLhandleARB; #include #endif +#ifdef __WIN32__ +#define glGetProc(a) wglGetProcAddress(a) +#else +#define glGetProc(a) glXGetProcAddress((const GLubyte *)(a)) +#endif + +#define GL_EXT(type, name) \ + static type name = reinterpret_cast(glGetProc(#name)); \ + if (!name) { \ + name = & name ## Fallback; \ + } + + /// DOCME /// @class OpenGLWrapper diff --git a/aegisub/src/spline.cpp b/aegisub/src/spline.cpp index 7b97821df..5a2b28ebb 100644 --- a/aegisub/src/spline.cpp +++ b/aegisub/src/spline.cpp @@ -40,11 +40,12 @@ #include #endif +#include + #include "spline.h" #include "utils.h" #include "video_display.h" - /// @brief Spline constructor Spline::Spline(const VideoDisplay &scale) : scale(scale) { } @@ -54,23 +55,21 @@ wxString Spline::EncodeToASS() { wxString result; char lastCommand = 0; - // At least one element? - bool isFirst = true; - // Insert each element - for (std::list::iterator cur=curves.begin();cur!=curves.end();cur++) { - // Start of spline - if (isFirst) { - int x = cur->p1.x; - int y = cur->p1.y; - scale.ToScriptCoords(&x, &y); - result = wxString::Format(L"m %i %i ", x, y); - lastCommand = 'm'; - isFirst = false; - } - + for (iterator cur=begin();cur!=end();cur++) { // Each curve switch (cur->type) { + case CURVE_POINT: { + if (lastCommand != 'm') { + result += L"m "; + lastCommand = 'm'; + } + int x = cur->p1.x; + int y = cur->p1.y; + scale.ToScriptCoords(&x, &y); + result += wxString::Format(L"%i %i ", x, y); + break; + } case CURVE_LINE: { if (lastCommand != 'l') { result += L"l "; @@ -109,14 +108,13 @@ wxString Spline::EncodeToASS() { /// @param str void Spline::DecodeFromASS(wxString str) { // Clear current - curves.clear(); + clear(); std::vector stack; // Prepare char lastCommand = 'm'; int x = 0; int y = 0; - bool coordsSet = false; // Tokenize the string wxStringTokenizer tkn(str,L" "); @@ -131,11 +129,13 @@ void Spline::DecodeFromASS(wxString str) { // Move if (stack.size() == 2 && lastCommand == 'm') { - x = stack[0]; - y = stack[1]; - scale.FromScriptCoords(&x, &y); - coordsSet = true; + scale.FromScriptCoords(&stack[0], &stack[1]); + SplineCurve curve; + x = curve.p1.x = stack[0]; + y = curve.p1.y = stack[1]; + curve.type = CURVE_POINT; stack.clear(); + push_back(curve); } // Line @@ -144,13 +144,11 @@ void Spline::DecodeFromASS(wxString str) { SplineCurve curve; curve.p1.x = x; curve.p1.y = y; - curve.p2.x = stack[0]; - curve.p2.y = stack[1]; + x = curve.p2.x = stack[0]; + y = curve.p2.y = stack[1]; curve.type = CURVE_LINE; - x = curve.p2.x; - y = curve.p2.y; stack.clear(); - AppendCurve(curve); + push_back(curve); } // Bicubic @@ -171,7 +169,7 @@ void Spline::DecodeFromASS(wxString str) { x = curve.p4.x; y = curve.p4.y; stack.clear(); - AppendCurve(curve); + push_back(curve); } // Close @@ -190,161 +188,128 @@ void Spline::DecodeFromASS(wxString str) { else if (token == L"c") lastCommand = 'c'; } } - - // Got coordinates, but list is empty - if (curves.size() == 0 && coordsSet) { - SplineCurve curve; - curve.p1.x = x; - curve.p1.y = y; - curve.type = CURVE_POINT; - AppendCurve(curve); - } -} - -/// @brief Insert a curve to the spline -/// @param curve -/// @param index -void Spline::InsertCurve(SplineCurve &curve,int index) { - if (index == -1) curves.push_back(curve); - else { - std::list::iterator cur; - int i=0; - for (cur=curves.begin();cur!=curves.end() && i < index;cur++,i++) ; - curves.insert(cur,curve); - } -} - -/// @brief Get a specific curve -/// @param index -/// @return -SplineCurve *Spline::GetCurve(int index) { - int i=0; - for (std::list::iterator cur=curves.begin();cur!=curves.end() && i <= index;cur++,i++) { - if (i==index) return &(*cur); - } - return NULL; } /// @brief Moves a specific point in the spline /// @param curveIndex /// @param point /// @param pos -void Spline::MovePoint(int curveIndex,int point,wxPoint pos) { - // Curves - int i = 0; - SplineCurve *c0 = NULL; - SplineCurve *c1 = NULL; - SplineCurve *c2 = NULL; - - // Indices - int i0 = curveIndex-1; - int i1 = curveIndex; - int i2 = curveIndex+1; - - // Get the curves - for (std::list::iterator cur = curves.begin();cur!=curves.end();cur++) { - if (i == i0) c0 = &(*cur); - if (i == i1) c1 = &(*cur); - if (i == i2) c2 = &(*cur); - i++; - } +void Spline::MovePoint(iterator curve,int point,Vector2D const& pos) { + iterator prev = curve; + if (curve != begin()) --prev; + iterator next = curve; + ++next; + if (next != end() && next->type == CURVE_POINT) next = end(); // Modify if (point == 0) { - c1->p1.x = pos.x; - c1->p1.y = pos.y; - if (c0) { - if (c0->type == CURVE_BICUBIC) { - c0->p4.x = pos.x; - c0->p4.y = pos.y; - } - else { - c0->p2.x = pos.x; - c0->p2.y = pos.y; - } - } + curve->p1 = pos; + if (curve != begin() && curve->type != CURVE_POINT) prev->EndPoint() = pos; + if (next != end() && curve->type == CURVE_POINT) next->p1 = pos; } else if (point == 1) { - c1->p2.x = pos.x; - c1->p2.y = pos.y; - if (c2 && c1->type != CURVE_BICUBIC) { - c2->p1.x = pos.x; - c2->p1.y = pos.y; - } + curve->p2 = pos; + if (next != end() && curve->type == CURVE_LINE) next->p1 = pos; } else if (point == 2) { - c1->p3.x = pos.x; - c1->p3.y = pos.y; + curve->p3 = pos; } else if (point == 3) { - c1->p4.x = pos.x; - c1->p4.y = pos.y; - if (c2 && c1->type == CURVE_BICUBIC) { - c2->p1.x = pos.x; - c2->p1.y = pos.y; - } + curve->p4 = pos; + if (next != end()) next->p1 = pos; } } /// @brief Gets a list of points in the curve /// @param points /// @param pointCurve -void Spline::GetPointList(std::vector &points,std::vector &pointCurve) { - // Prepare +void Spline::GetPointList(std::vector& points, std::vector& first, std::vector& count) { points.clear(); - points.reserve((curves.size() + 1) * 2); - pointCurve.reserve(curves.size() + 1); - pointCurve.clear(); - Vector2D pt; - bool isFirst = true; - int curve = 0; + first.clear(); + count.clear(); + + points.reserve((size() + 1) * 2); + int curCount = 0; // Generate points for each curve - for (std::list::iterator cur = curves.begin();cur!=curves.end();cur++,curve++) { - // First point - if (isFirst) { - points.push_back(cur->p1.x); - points.push_back(cur->p1.y); - pointCurve.push_back(curve); - isFirst = false; - } + for (iterator cur = begin();cur!=end();cur++) { + switch (cur->type) { + case CURVE_POINT: + if (curCount > 0) { + count.push_back(curCount); + } - // Line - if (cur->type == CURVE_LINE) { - points.push_back(cur->p2.x); - points.push_back(cur->p2.y); - pointCurve.push_back(curve); - } + // start new path + first.push_back(points.size() / 2); + points.push_back(cur->p1.x); + points.push_back(cur->p1.y); + curCount = 1; + break; + case CURVE_LINE: + points.push_back(cur->p2.x); + points.push_back(cur->p2.y); + curCount++; + break; + case CURVE_BICUBIC: { + // Get the control points + Vector2D p1 = cur->p1; + Vector2D p2 = cur->p2; + Vector2D p3 = cur->p3; + Vector2D p4 = cur->p4; - // Bicubic - else if (cur->type == CURVE_BICUBIC) { + // Find number of steps + int len = (int)((p2-p1).Len() + (p3-p2).Len() + (p4-p3).Len()); + int steps = len/8; + + // Render curve + for (int i=1;i<=steps;i++) { + // Get t and t-1 (u) + float t = float(i)/float(steps); + Vector2D p = cur->GetPoint(t); + points.push_back(p.x); + points.push_back(p.y); + } + curCount += steps; + break; + } + default: break; + } + } + + count.push_back(curCount); +} +void Spline::GetPointList(std::vector &points, iterator curve) { + points.clear(); + if (curve == end()) return; + switch (curve->type) { + case CURVE_LINE: + points.push_back(curve->p1.x); + points.push_back(curve->p1.y); + points.push_back(curve->p2.x); + points.push_back(curve->p2.y); + break; + case CURVE_BICUBIC: { // Get the control points - Vector2D p1 = cur->p1; - Vector2D p2 = cur->p2; - Vector2D p3 = cur->p3; - Vector2D p4 = cur->p4; + Vector2D p1 = curve->p1; + Vector2D p2 = curve->p2; + Vector2D p3 = curve->p3; + Vector2D p4 = curve->p4; // Find number of steps int len = (int)((p2-p1).Len() + (p3-p2).Len() + (p4-p3).Len()); int steps = len/8; // Render curve - for (int i=1;i<=steps;i++) { + for (int i=0;i<=steps;i++) { // Get t and t-1 (u) float t = float(i)/float(steps); - Vector2D p = cur->GetPoint(t); + Vector2D p = curve->GetPoint(t); points.push_back(p.x); points.push_back(p.y); - pointCurve.push_back(curve); } + break; } - } - - // Insert a copy of the first point at the end - if (!points.empty()) { - points.push_back(points[0]); - points.push_back(points[1]); - pointCurve.push_back(curve); + default: break; } } @@ -353,77 +318,64 @@ void Spline::GetPointList(std::vector &points,std::vector &pointCurv /// @param curve /// @param t /// @param pt -void Spline::GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &pt) { - // Has at least one curve? - curve = -1; - t = 0.0f; - if (curves.size() == 0) return; +void Spline::GetClosestParametricPoint(Vector2D const& reference,iterator &curve,float &t,Vector2D &pt) { + curve = end(); + t = 0.f; + if (empty()) return; // Close the shape SplineCurve pad; - pad.p1 = curves.back().GetEndPoint(); - pad.p2 = curves.front().p1; + pad.p1 = back().EndPoint(); + pad.p2 = front().p1; pad.type = CURVE_LINE; - curves.push_back(pad); + push_back(pad); - // Prepare - float closest = 8000000.0f; - int i = 0; - for (std::list::iterator cur = curves.begin();cur!=curves.end();cur++,i++) { + float closest = std::numeric_limits::infinity(); + for (iterator cur = begin();cur!=end();cur++) { float param = cur->GetClosestParam(reference); Vector2D p1 = cur->GetPoint(param); - float dist = (p1-reference).Len(); + float dist = (p1-reference).SquareLen(); if (dist < closest) { closest = dist; t = param; - curve = i; + curve = cur; pt = p1; } } + if (&*curve == &back()) { + curve = end(); + } + // Remove closing and return - curves.pop_back(); + pop_back(); } /// @brief Point closest to reference /// @param reference /// @return -Vector2D Spline::GetClosestPoint(Vector2D reference) { - int curve; +Vector2D Spline::GetClosestPoint(Vector2D const& reference) { + iterator curve; float t; Vector2D point; GetClosestParametricPoint(reference,curve,t,point); return point; } - - -/// @brief Control point closest to reference -/// @param reference -/// @return -/// -Vector2D Spline::GetClosestControlPoint(Vector2D reference) { - // TODO - return Vector2D(-1,-1); -} - /// @brief Smoothes the spline /// @param smooth void Spline::Smooth(float smooth) { // See if there are enough curves - if (curves.size() < 3) return; + if (size() < 3) return; // Smooth curve - SplineCurve *curve0 = NULL; - SplineCurve *curve1 = &curves.back(); - SplineCurve *curve2 = NULL; - for (std::list::iterator cur=curves.begin();cur!=curves.end();) { - // Get curves - curve0 = curve1; - curve1 = &(*cur); + iterator curve1 = end(); + --curve1; + for (iterator cur = begin(); cur != end();) { + iterator curve0 = curve1; + curve1 = cur; cur++; - if (cur == curves.end()) curve2 = &curves.front(); - else curve2 = &(*cur); + iterator curve2 = cur == end() ? begin() : cur; // Smooth curve curve1->Smooth(curve0->p1,curve2->p2,smooth); diff --git a/aegisub/src/spline.h b/aegisub/src/spline.h index ad7552913..98e9f90c8 100644 --- a/aegisub/src/spline.h +++ b/aegisub/src/spline.h @@ -45,36 +45,53 @@ class VideoDisplay; - /// DOCME /// @class Spline /// @brief DOCME -class Spline { +class Spline : private std::list { private: const VideoDisplay &scale; public: - - /// DOCME - std::list curves; - Spline(const VideoDisplay &scale); wxString EncodeToASS(); void DecodeFromASS(wxString str); - - /// @brief DOCME - /// @param curve - /// - void AppendCurve(SplineCurve &curve) { InsertCurve(curve,-1); } - void InsertCurve(SplineCurve &curve,int index); - void MovePoint(int curveIndex,int point,wxPoint pos); + void MovePoint(iterator curve,int point,Vector2D const& pos); void Smooth(float smooth=1.0f); - void GetPointList(std::vector &points,std::vector &pointCurve); - SplineCurve *GetCurve(int index); + void GetPointList(std::vector& points, std::vector& first, std::vector& count); + void GetPointList(std::vector &points, iterator curve); - void GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &point); - Vector2D GetClosestPoint(Vector2D reference); - Vector2D GetClosestControlPoint(Vector2D reference); + void GetClosestParametricPoint(Vector2D const& reference, iterator& curve, float &t, Vector2D &point); + Vector2D GetClosestPoint(Vector2D const& reference); + Vector2D GetClosestControlPoint(Vector2D const& reference); + + // This list intentionally excludes things specific to std::list + using std::list::value_type; + using std::list::pointer; + using std::list::reference; + using std::list::const_reference; + using std::list::size_type; + using std::list::difference_type; + using std::list::iterator; + using std::list::const_iterator; + using std::list::reverse_iterator; + using std::list::const_reverse_iterator; + + using std::list::begin; + using std::list::end; + using std::list::rbegin; + using std::list::rend; + using std::list::size; + using std::list::empty; + using std::list::front; + using std::list::back; + using std::list::push_front; + using std::list::push_back; + using std::list::pop_front; + using std::list::pop_back; + using std::list::insert; + using std::list::erase; + using std::list::clear; }; diff --git a/aegisub/src/spline_curve.cpp b/aegisub/src/spline_curve.cpp index 00e142433..9b67bb94d 100644 --- a/aegisub/src/spline_curve.cpp +++ b/aegisub/src/spline_curve.cpp @@ -34,7 +34,6 @@ /// @ingroup visual_ts /// - /////////// // Headers #include "config.h" @@ -42,15 +41,12 @@ #include "spline_curve.h" #include "utils.h" - /// @brief Curve constructor /// SplineCurve::SplineCurve() { type = CURVE_INVALID; } - - /// @brief Split a curve in two using the de Casteljau algorithm /// @param c1 /// @param c2 @@ -93,28 +89,26 @@ void SplineCurve::Split(SplineCurve &c1,SplineCurve &c2,float t) { } } - - /// @brief Based on http://antigrain.com/research/bezier_interpolation/index.html Smoothes the curve /// @param P0 /// @param P3 /// @param smooth /// @return /// -void SplineCurve::Smooth(Vector2D P0,Vector2D P3,float smooth) { +void SplineCurve::Smooth(Vector2D const& P0,Vector2D const& P3,float smooth) { // Validate if (type != CURVE_LINE) return; if (p1 == p2) return; - smooth = MID(0.0f,smooth,1.0f); + smooth = MID(0.f,smooth,1.f); // Get points Vector2D P1 = p1; Vector2D P2 = p2; // Calculate intermediate points - Vector2D c1 = (P0+P1)/2.0f; - Vector2D c2 = (P1+P2)/2.0f; - Vector2D c3 = (P2+P3)/2.0f; + Vector2D c1 = (P0+P1)/2.f; + Vector2D c2 = (P1+P2)/2.f; + Vector2D c3 = (P2+P3)/2.f; float len1 = (P1-P0).Len(); float len2 = (P2-P1).Len(); float len3 = (P3-P2).Len(); @@ -130,43 +124,24 @@ void SplineCurve::Smooth(Vector2D P0,Vector2D P3,float smooth) { type = CURVE_BICUBIC; } - - /// @brief Get a point /// @param t /// @return /// Vector2D SplineCurve::GetPoint(float t) const { - // Point if (type == CURVE_POINT) return p1; - - // Line - else if (type == CURVE_LINE) { - return p1*(1.0f-t) + p2*t; + if (type == CURVE_LINE) { + return p1*(1.f-t) + p2*t; } - - // Bicubic - else if (type == CURVE_BICUBIC) { - float u = 1.0f-t; + if (type == CURVE_BICUBIC) { + float u = 1.f-t; return p1*u*u*u + 3*p2*t*u*u + 3*p3*t*t*u + p4*t*t*t; } - else return Vector2D(0,0); + return Vector2D(0,0); } - - -/// @brief Get start/end point -/// @return -/// -Vector2D SplineCurve::GetStartPoint() const { - return p1; -} - -/// @brief DOCME -/// @return -/// -Vector2D SplineCurve::GetEndPoint() const { +Vector2D& SplineCurve::EndPoint() { switch (type) { case CURVE_POINT: return p1; case CURVE_LINE: return p2; @@ -175,33 +150,26 @@ Vector2D SplineCurve::GetEndPoint() const { } } - - /// @brief Get point closest to reference /// @param ref /// @return /// -Vector2D SplineCurve::GetClosestPoint(Vector2D ref) const { +Vector2D SplineCurve::GetClosestPoint(Vector2D const& ref) const { return GetPoint(GetClosestParam(ref)); } - - /// @brief Get value of parameter closest to point /// @param ref /// @return /// -float SplineCurve::GetClosestParam(Vector2D ref) const { - // Line +float SplineCurve::GetClosestParam(Vector2D const& ref) const { if (type == CURVE_LINE) { return GetClosestSegmentPart(p1,p2,ref); } - - // Bicubic if (type == CURVE_BICUBIC) { int steps = 100; - float bestDist = 80000000.0f; - float bestT = 0.0f; + float bestDist = 80000000.f; + float bestT = 0.f; for (int i=0;i<=steps;i++) { float t = float(i)/float(steps); float dist = (GetPoint(t)-ref).Len(); @@ -212,19 +180,15 @@ float SplineCurve::GetClosestParam(Vector2D ref) const { } return bestT; } - - // Something else - return 0.0f; + return 0.f; } - - /// @brief Quick distance /// @param ref /// @return /// -float SplineCurve::GetQuickDistance(Vector2D ref) const { - // Bicubic +float SplineCurve::GetQuickDistance(Vector2D const& ref) const { + using std::min; if (type == CURVE_BICUBIC) { float len1 = GetClosestSegmentDistance(p1,p2,ref); float len2 = GetClosestSegmentDistance(p2,p3,ref); @@ -232,35 +196,29 @@ float SplineCurve::GetQuickDistance(Vector2D ref) const { 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)); + return min(min(min(len1,len2),min(len3,len4)),min(len5,len6)); } // Something else else return (GetClosestPoint(ref)-ref).Len(); } - - /// @brief Closest t in segment p1-p2 to point p3 /// @param pt1 /// @param pt2 /// @param pt3 /// @return /// -float SplineCurve::GetClosestSegmentPart(Vector2D pt1,Vector2D pt2,Vector2D pt3) const { - return MID(0.0f,(pt3-pt1).Dot(pt2-pt1)/(pt2-pt1).SquareLen(),1.0f); +float SplineCurve::GetClosestSegmentPart(Vector2D const& pt1,Vector2D const& pt2,Vector2D const& pt3) const { + return MID(0.f,(pt3-pt1).Dot(pt2-pt1)/(pt2-pt1).SquareLen(),1.f); } - - /// @brief Closest distance between p3 and segment p1-p2 /// @param pt1 /// @param pt2 /// @param pt3 /// -float SplineCurve::GetClosestSegmentDistance(Vector2D pt1,Vector2D pt2,Vector2D pt3) const { +float SplineCurve::GetClosestSegmentDistance(Vector2D const& pt1,Vector2D const& pt2,Vector2D const& pt3) const { float t = GetClosestSegmentPart(pt1,pt2,pt3); - return (pt1*(1.0f-t)+pt2*t-pt3).Len(); + return (pt1*(1.f-t)+pt2*t-pt3).Len(); } - - diff --git a/aegisub/src/spline_curve.h b/aegisub/src/spline_curve.h index 35c4e5e65..0da098ced 100644 --- a/aegisub/src/spline_curve.h +++ b/aegisub/src/spline_curve.h @@ -34,14 +34,10 @@ /// @ingroup visual_ts /// - - - /////////// // Headers #include "vector2d.h" - /// DOCME enum CurveType { @@ -58,8 +54,6 @@ enum CurveType { CURVE_BICUBIC }; - - /// DOCME /// @class SplineCurve /// @brief DOCME @@ -67,8 +61,8 @@ enum CurveType { /// DOCME class SplineCurve { private: - float GetClosestSegmentPart(Vector2D p1,Vector2D p2,Vector2D p3) const; - float GetClosestSegmentDistance(Vector2D p1,Vector2D p2,Vector2D p3) const; + float GetClosestSegmentPart(Vector2D const& p1,Vector2D const& p2,Vector2D const& p3) const; + float GetClosestSegmentDistance(Vector2D const& p1,Vector2D const& p2,Vector2D const& p3) const; public: @@ -86,14 +80,11 @@ public: SplineCurve(); void Split(SplineCurve &c1,SplineCurve &c2,float t=0.5); - void Smooth(Vector2D prev,Vector2D next,float smooth=1.0f); + void Smooth(Vector2D const& prev,Vector2D const& next,float smooth=1.0f); Vector2D GetPoint(float t) const; - Vector2D GetStartPoint() const; - Vector2D GetEndPoint() const; - Vector2D GetClosestPoint(Vector2D ref) const; - float GetClosestParam(Vector2D ref) const; - float GetQuickDistance(Vector2D ref) const; + Vector2D& EndPoint(); + Vector2D GetClosestPoint(Vector2D const& ref) const; + float GetClosestParam(Vector2D const& ref) const; + float GetQuickDistance(Vector2D const& ref) const; }; - - diff --git a/aegisub/src/visual_tool_vector_clip.cpp b/aegisub/src/visual_tool_vector_clip.cpp index 16c4207c0..9f738f1df 100644 --- a/aegisub/src/visual_tool_vector_clip.cpp +++ b/aegisub/src/visual_tool_vector_clip.cpp @@ -35,6 +35,7 @@ #ifndef AGI_PRE #include +#include "gl/glext.h" #endif #include "config.h" @@ -44,36 +45,16 @@ #include "video_display.h" #include "visual_tool_vector_clip.h" -/////// -// IDs enum { - - /// DOCME BUTTON_DRAG = VISUAL_SUB_TOOL_START, - - /// DOCME BUTTON_LINE, - - /// DOCME BUTTON_BICUBIC, - - /// DOCME BUTTON_CONVERT, - - /// DOCME BUTTON_INSERT, - - /// DOCME BUTTON_REMOVE, - - /// DOCME BUTTON_FREEHAND, - - /// DOCME BUTTON_FREEHAND_SMOOTH, - - /// DOCME - BUTTON_LAST // Leave this at the end and don't use it + BUTTON_LAST // Leave this at the end and don't use it }; /// @brief Constructor @@ -107,25 +88,30 @@ VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, VideoState cons if (features.size() == 0) SetMode(1); } -/// @brief Sub-tool pressed -/// @param event void VisualToolVectorClip::OnSubTool(wxCommandEvent &event) { SetMode(event.GetId() - BUTTON_DRAG); } -/// @brief Set mode -/// @param _mode -void VisualToolVectorClip::SetMode(int _mode) { - // Make sure clicked is checked and everything else isn't. (Yes, this is radio behavior, but the separators won't let me use it) +void VisualToolVectorClip::SetMode(int newMode) { + // Manually enforce radio behavior as we want one selection in the bar + // rather than one per group for (int i=BUTTON_DRAG;iToggleTool(i,i == _mode + BUTTON_DRAG); + toolBar->ToggleTool(i,i == newMode + BUTTON_DRAG); + } + mode = newMode; +} + +// Substitute for glMultiDrawArrays for sub-1.4 OpenGL +static void APIENTRY glMultiDrawArraysFallback(GLenum mode, GLint *first, GLsizei *count, GLsizei primcount) { + for (int i = 0; i < primcount; ++i) { + glDrawArrays(mode, *first++, *count++); } - mode = _mode; } -/// @brief Draw void VisualToolVectorClip::Draw() { - if (spline.curves.empty()) return; + if (spline.empty()) return; + + GL_EXT(PFNGLMULTIDRAWARRAYSPROC, glMultiDrawArrays); // Get line AssDialogue *line = GetActiveDialogueLine(); @@ -133,8 +119,12 @@ void VisualToolVectorClip::Draw() { // Parse vector std::vector points; - std::vector pointCurve; - spline.GetPointList(points,pointCurve); + std::vector start; + std::vector count; + + spline.GetPointList(points, start, count); + assert(!start.empty()); + assert(!count.empty()); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, 0, &points[0]); @@ -156,12 +146,12 @@ void VisualToolVectorClip::Draw() { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); - glDrawArrays(GL_TRIANGLE_FAN, 0, points.size() / 2); + glMultiDrawArrays(GL_TRIANGLE_FAN, &start[0], &count[0], start.size()); // Decrement the winding number for each backfacing triangle glStencilOp(GL_DECR, GL_DECR, GL_DECR); glCullFace(GL_FRONT); - glDrawArrays(GL_TRIANGLE_FAN, 0, points.size() / 2); + glMultiDrawArrays(GL_TRIANGLE_FAN, &start[0], &count[0], start.size()); glDisable(GL_CULL_FACE); // Draw the actual rectangle @@ -176,29 +166,26 @@ void VisualToolVectorClip::Draw() { DrawRectangle(0,0,video.w,video.h); glDisable(GL_STENCIL_TEST); - // Get current position information for modes 3 and 4 - Vector2D pt; - int highCurve = -1; - if (mode == 3 || mode == 4) { - float t; - spline.GetClosestParametricPoint(Vector2D(video.x,video.y),highCurve,t,pt); - } - // Draw lines SetFillColour(colour[3],0.0f); SetLineColour(colour[3],1.0f,2); SetModeLine(); - glDrawArrays(GL_LINE_STRIP, 0, points.size() / 2); + glMultiDrawArrays(GL_LINE_LOOP, &start[0], &count[0], start.size()); + + Vector2D pt; + float t; + Spline::iterator highCurve; + spline.GetClosestParametricPoint(Vector2D(video.x, video.y), highCurve, t, pt); // Draw highlighted line - if (!curFeature && points.size() > 1 && highCurve > -1) { - std::pair::iterator, std::vector::iterator> high = std::equal_range(pointCurve.begin(), pointCurve.end(), highCurve); - if (high.first != high.second) { + if ((mode == 3 || mode == 4) && !curFeature && points.size() > 2) { + std::vector highPoints; + spline.GetPointList(highPoints, highCurve); + if (!highPoints.empty()) { + glVertexPointer(2, GL_FLOAT, 0, &highPoints[0]); SetLineColour(colour[2], 1.f, 2); - int first = std::distance(pointCurve.begin(), high.first); - int count = std::distance(high.first, high.second); - if (first > 0) first -= 1; - glDrawArrays(GL_LINE_STRIP, first, count); + SetModeLine(); + glDrawArrays(GL_LINE_STRIP, 0, highPoints.size() / 2); } } @@ -206,23 +193,22 @@ void VisualToolVectorClip::Draw() { // Draw lines connecting the bicubic features SetLineColour(colour[3],0.9f,1); - for (std::list::iterator cur=spline.curves.begin();cur!=spline.curves.end();cur++) { + for (Spline::iterator cur=spline.begin();cur!=spline.end();cur++) { if (cur->type == CURVE_BICUBIC) { DrawDashedLine(cur->p1.x,cur->p1.y,cur->p2.x,cur->p2.y,6); DrawDashedLine(cur->p3.x,cur->p3.y,cur->p4.x,cur->p4.y,6); } } - // Draw features DrawAllFeatures(); // Draw preview of inserted line if (mode == 1 || mode == 2) { - if (spline.curves.size() && video.x > INT_MIN && video.y > INT_MIN) { - SplineCurve *c0 = &spline.curves.front(); - SplineCurve *c1 = &spline.curves.back(); + if (spline.size() && video.x > INT_MIN && video.y > INT_MIN) { + SplineCurve *c0 = &spline.front(); + SplineCurve *c1 = &spline.back(); DrawDashedLine(video.x,video.y,c0->p1.x,c0->p1.y,6); - DrawDashedLine(video.x,video.y,c1->GetEndPoint().x,c1->GetEndPoint().y,6); + DrawDashedLine(video.x,video.y,c1->EndPoint().x,c1->EndPoint().y,6); } } @@ -235,31 +221,28 @@ void VisualToolVectorClip::PopulateFeatureList() { ClearSelection(false); features.clear(); // This is perhaps a bit conservative as there can be up to 3N+1 features - features.reserve(spline.curves.size()); + features.reserve(spline.size()); VisualToolVectorClipDraggableFeature feat; // Go through each curve - bool isFirst = true; int i = 0; int j = 0; - for (std::list::iterator cur=spline.curves.begin();cur!=spline.curves.end();cur++,i++) { - // First point - if (isFirst) { - isFirst = false; + for (Spline::iterator cur=spline.begin();cur!=spline.end();cur++,i++) { + if (cur->type == CURVE_POINT) { feat.x = (int)cur->p1.x; feat.y = (int)cur->p1.y; feat.type = DRAG_SMALL_CIRCLE; - feat.index = i; + feat.curve = cur; feat.point = 0; features.push_back(feat); AddSelection(j++); } - if (cur->type == CURVE_LINE) { + else if (cur->type == CURVE_LINE) { feat.x = (int)cur->p2.x; feat.y = (int)cur->p2.y; feat.type = DRAG_SMALL_CIRCLE; - feat.index = i; + feat.curve = cur; feat.point = 1; features.push_back(feat); AddSelection(j++); @@ -269,7 +252,7 @@ void VisualToolVectorClip::PopulateFeatureList() { // Control points feat.x = (int)cur->p2.x; feat.y = (int)cur->p2.y; - feat.index = i; + feat.curve = cur; feat.point = 1; feat.type = DRAG_SMALL_SQUARE; features.push_back(feat); @@ -295,7 +278,7 @@ void VisualToolVectorClip::PopulateFeatureList() { /// @brief Update /// @param feature void VisualToolVectorClip::UpdateDrag(VisualToolVectorClipDraggableFeature* feature) { - spline.MovePoint(feature->index,feature->point,wxPoint(feature->x,feature->y)); + spline.MovePoint(feature->curve,feature->point,Vector2D(feature->x,feature->y)); } /// @brief Commit @@ -310,25 +293,26 @@ void VisualToolVectorClip::CommitDrag(VisualToolVectorClipDraggableFeature* feat bool VisualToolVectorClip::InitializeDrag(VisualToolVectorClipDraggableFeature* feature) { // Delete a control point if (mode == 5) { - int i = 0; - for (std::list::iterator cur=spline.curves.begin();cur!=spline.curves.end();i++,cur++) { - if (i == feature->index) { - // Update next - if (i != 0 || feature->point != 0) { - std::list::iterator next = cur; - next++; - if (next != spline.curves.end()) next->p1 = cur->p1; - } - - // Erase and save changes - spline.curves.erase(cur); - CommitDrag(feature); - PopulateFeatureList(); - curFeature = NULL; - Commit(true); - return false; + // Update next + Spline::iterator next = feature->curve; + next++; + if (next != spline.end()) { + if (feature->curve->type == CURVE_POINT) { + next->p1 = next->EndPoint(); + next->type = CURVE_POINT; + } + else { + next->p1 = feature->curve->p1; } } + + // Erase and save changes + spline.erase(feature->curve); + CommitDrag(feature); + PopulateFeatureList(); + curFeature = NULL; + Commit(true); + return false; } return true; } @@ -341,13 +325,10 @@ bool VisualToolVectorClip::InitializeHold() { SplineCurve curve; // Set start position - if (spline.curves.size()) { - curve.p1 = spline.curves.back().GetEndPoint(); + if (!spline.empty()) { + curve.p1 = spline.back().EndPoint(); if (mode == 1) curve.type = CURVE_LINE; else curve.type = CURVE_BICUBIC; - - // Remove point if that's all there is - if (spline.curves.size()==1 && spline.curves.front().type == CURVE_POINT) spline.curves.clear(); } // First point @@ -357,7 +338,7 @@ bool VisualToolVectorClip::InitializeHold() { } // Insert - spline.AppendCurve(curve); + spline.push_back(curve); UpdateHold(); return true; } @@ -366,26 +347,23 @@ bool VisualToolVectorClip::InitializeHold() { if (mode == 3 || mode == 4) { // Get closest point Vector2D pt; - int curve; + Spline::iterator curve; float t; spline.GetClosestParametricPoint(Vector2D(video.x,video.y),curve,t,pt); // Convert if (mode == 3) { - SplineCurve *c1 = spline.GetCurve(curve); - if (!c1) { - } - else { - if (c1->type == CURVE_LINE) { - c1->type = CURVE_BICUBIC; - c1->p4 = c1->p2; - c1->p2 = c1->p1 * 0.75 + c1->p4 * 0.25; - c1->p3 = c1->p1 * 0.25 + c1->p4 * 0.75; + if (curve != spline.end()) { + if (curve->type == CURVE_LINE) { + curve->type = CURVE_BICUBIC; + curve->p4 = curve->p2; + curve->p2 = curve->p1 * 0.75 + curve->p4 * 0.25; + curve->p3 = curve->p1 * 0.25 + curve->p4 * 0.75; } - else if (c1->type == CURVE_BICUBIC) { - c1->type = CURVE_LINE; - c1->p2 = c1->p4; + else if (curve->type == CURVE_BICUBIC) { + curve->type = CURVE_LINE; + curve->p2 = curve->p4; } } } @@ -393,28 +371,28 @@ bool VisualToolVectorClip::InitializeHold() { // Insert else { // Check if there is at least one curve to split - if (spline.curves.size() == 0) return false; + if (spline.empty()) return false; // Split the curve - SplineCurve *c1 = spline.GetCurve(curve); - SplineCurve c2; - if (!c1) { + if (curve == spline.end()) { SplineCurve ct; ct.type = CURVE_LINE; - ct.p1 = spline.curves.back().GetEndPoint(); - ct.p2 = spline.curves.front().p1; + ct.p1 = spline.back().EndPoint(); + ct.p2 = spline.front().p1; ct.p2 = ct.p1*(1-t) + ct.p2*t; - spline.AppendCurve(ct); + spline.push_back(ct); } else { - c1->Split(*c1,c2,t); - spline.InsertCurve(c2,curve+1); + SplineCurve c2; + curve->Split(*curve,c2,t); + spline.insert(++curve, c2); } } // Commit SetOverride(GetActiveDialogueLine(), inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")"); Commit(true); + DoRefresh(); return false; } @@ -422,30 +400,32 @@ bool VisualToolVectorClip::InitializeHold() { if (mode == 6 || mode == 7) { ClearSelection(false); features.clear(); - spline.curves.clear(); - lastX = INT_MIN; - lastY = INT_MIN; + spline.clear(); + SplineCurve curve; + curve.type = CURVE_POINT; + curve.p1.x = video.x; + curve.p1.y = video.y; + spline.push_back(curve); return true; } return false; } /// @brief Update hold -/// @return void VisualToolVectorClip::UpdateHold() { // Insert line if (mode == 1) { - spline.curves.back().p2 = Vector2D(video.x,video.y); + spline.back().p2 = Vector2D(video.x,video.y); } // Insert bicubic if (mode == 2) { - SplineCurve &curve = spline.curves.back(); + SplineCurve &curve = spline.back(); curve.p4 = Vector2D(video.x,video.y); // Control points - if (spline.curves.size() > 1) { - std::list::reverse_iterator iter = spline.curves.rbegin(); + if (spline.size() > 1) { + std::list::reverse_iterator iter = spline.rbegin(); iter++; SplineCurve &c0 = *iter; Vector2D prevVector; @@ -460,22 +440,18 @@ void VisualToolVectorClip::UpdateHold() { // Freehand if (mode == 6 || mode == 7) { - if (lastX != INT_MIN && lastY != INT_MIN) { - // See if distance is enough - Vector2D delta(lastX-video.x,lastY-video.y); - int len = (int)delta.Len(); - if (mode == 6 && len < 30) return; - if (mode == 7 && len < 60) return; - - // Generate curve and add it - SplineCurve curve; - curve.type = CURVE_LINE; - curve.p1 = Vector2D(lastX,lastY); - curve.p2 = Vector2D(video.x,video.y); - spline.AppendCurve(curve); - } - lastX = video.x; - lastY = video.y; + // See if distance is enough + Vector2D const& last = spline.back().EndPoint(); + int len = (int)Vector2D(last.x-video.x, last.y-video.y).Len(); + if (mode == 6 && len < 30) return; + if (mode == 7 && len < 60) return; + + // Generate curve and add it + SplineCurve curve; + curve.type = CURVE_LINE; + curve.p1 = Vector2D(last.x,last.y); + curve.p2 = Vector2D(video.x,video.y); + spline.push_back(curve); } } @@ -510,4 +486,3 @@ void VisualToolVectorClip::DoRefresh() { PopulateFeatureList(); } } - diff --git a/aegisub/src/visual_tool_vector_clip.h b/aegisub/src/visual_tool_vector_clip.h index 7869c3c00..5ab66e575 100644 --- a/aegisub/src/visual_tool_vector_clip.h +++ b/aegisub/src/visual_tool_vector_clip.h @@ -46,13 +46,12 @@ class wxToolBar; class VisualToolVectorClipDraggableFeature : public VisualDraggableFeature { public: /// Which curve in the spline this feature is a point on - int index; + Spline::iterator curve; /// 0-3; indicates which part of the curve this point is int point; /// @brief Constructor VisualToolVectorClipDraggableFeature() : VisualDraggableFeature() - , index(0) , point(0) { } }; @@ -62,24 +61,18 @@ public: /// @brief DOCME class VisualToolVectorClip : public VisualTool { private: + Spline spline; /// The current spline - /// DOCME - Spline spline; - - /// DOCME - wxToolBar *toolBar; + wxToolBar *toolBar; /// The subtoolbar /// DOCME int mode; - /// DOCME - - /// DOCME - int lastX,lastY; - /// DOCME bool inverse; + /// @brief Set the mode + /// @param mode 0-7 void SetMode(int mode); @@ -90,7 +83,6 @@ private: void UpdateHold(); void CommitHold(); - void PopulateFeatureList(); void UpdateDrag(VisualToolVectorClipDraggableFeature* feature); void CommitDrag(VisualToolVectorClipDraggableFeature* feature);