Add support for rendering vector clips with multiple 'm' commands.

Originally committed to SVN as r4463.
This commit is contained in:
Thomas Goyne 2010-06-08 06:09:19 +00:00
parent c7da8d9f61
commit f361d1a67b
8 changed files with 329 additions and 449 deletions

View file

@ -52,24 +52,6 @@
#include "options.h" #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 /// @brief Constructor
/// ///
OpenGLWrapper::OpenGLWrapper() { OpenGLWrapper::OpenGLWrapper() {

View file

@ -51,6 +51,19 @@ typedef GLuint GLhandleARB;
#include <wx/colour.h> #include <wx/colour.h>
#endif #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<type>(glGetProc(#name)); \
if (!name) { \
name = & name ## Fallback; \
}
/// DOCME /// DOCME
/// @class OpenGLWrapper /// @class OpenGLWrapper

View file

@ -40,11 +40,12 @@
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
#endif #endif
#include <limits>
#include "spline.h" #include "spline.h"
#include "utils.h" #include "utils.h"
#include "video_display.h" #include "video_display.h"
/// @brief Spline constructor /// @brief Spline constructor
Spline::Spline(const VideoDisplay &scale) : scale(scale) { Spline::Spline(const VideoDisplay &scale) : scale(scale) {
} }
@ -54,23 +55,21 @@ wxString Spline::EncodeToASS() {
wxString result; wxString result;
char lastCommand = 0; char lastCommand = 0;
// At least one element?
bool isFirst = true;
// Insert each element // Insert each element
for (std::list<SplineCurve>::iterator cur=curves.begin();cur!=curves.end();cur++) { for (iterator cur=begin();cur!=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;
}
// Each curve // Each curve
switch (cur->type) { 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: { case CURVE_LINE: {
if (lastCommand != 'l') { if (lastCommand != 'l') {
result += L"l "; result += L"l ";
@ -109,14 +108,13 @@ wxString Spline::EncodeToASS() {
/// @param str /// @param str
void Spline::DecodeFromASS(wxString str) { void Spline::DecodeFromASS(wxString str) {
// Clear current // Clear current
curves.clear(); clear();
std::vector<int> stack; std::vector<int> stack;
// Prepare // Prepare
char lastCommand = 'm'; char lastCommand = 'm';
int x = 0; int x = 0;
int y = 0; int y = 0;
bool coordsSet = false;
// Tokenize the string // Tokenize the string
wxStringTokenizer tkn(str,L" "); wxStringTokenizer tkn(str,L" ");
@ -131,11 +129,13 @@ void Spline::DecodeFromASS(wxString str) {
// Move // Move
if (stack.size() == 2 && lastCommand == 'm') { if (stack.size() == 2 && lastCommand == 'm') {
x = stack[0]; scale.FromScriptCoords(&stack[0], &stack[1]);
y = stack[1]; SplineCurve curve;
scale.FromScriptCoords(&x, &y); x = curve.p1.x = stack[0];
coordsSet = true; y = curve.p1.y = stack[1];
curve.type = CURVE_POINT;
stack.clear(); stack.clear();
push_back(curve);
} }
// Line // Line
@ -144,13 +144,11 @@ void Spline::DecodeFromASS(wxString str) {
SplineCurve curve; SplineCurve curve;
curve.p1.x = x; curve.p1.x = x;
curve.p1.y = y; curve.p1.y = y;
curve.p2.x = stack[0]; x = curve.p2.x = stack[0];
curve.p2.y = stack[1]; y = curve.p2.y = stack[1];
curve.type = CURVE_LINE; curve.type = CURVE_LINE;
x = curve.p2.x;
y = curve.p2.y;
stack.clear(); stack.clear();
AppendCurve(curve); push_back(curve);
} }
// Bicubic // Bicubic
@ -171,7 +169,7 @@ void Spline::DecodeFromASS(wxString str) {
x = curve.p4.x; x = curve.p4.x;
y = curve.p4.y; y = curve.p4.y;
stack.clear(); stack.clear();
AppendCurve(curve); push_back(curve);
} }
// Close // Close
@ -190,161 +188,128 @@ void Spline::DecodeFromASS(wxString str) {
else if (token == L"c") lastCommand = 'c'; 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<SplineCurve>::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<SplineCurve>::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 /// @brief Moves a specific point in the spline
/// @param curveIndex /// @param curveIndex
/// @param point /// @param point
/// @param pos /// @param pos
void Spline::MovePoint(int curveIndex,int point,wxPoint pos) { void Spline::MovePoint(iterator curve,int point,Vector2D const& pos) {
// Curves iterator prev = curve;
int i = 0; if (curve != begin()) --prev;
SplineCurve *c0 = NULL; iterator next = curve;
SplineCurve *c1 = NULL; ++next;
SplineCurve *c2 = NULL; if (next != end() && next->type == CURVE_POINT) next = end();
// Indices
int i0 = curveIndex-1;
int i1 = curveIndex;
int i2 = curveIndex+1;
// Get the curves
for (std::list<SplineCurve>::iterator cur = curves.begin();cur!=curves.end();cur++) {
if (i == i0) c0 = &(*cur);
if (i == i1) c1 = &(*cur);
if (i == i2) c2 = &(*cur);
i++;
}
// Modify // Modify
if (point == 0) { if (point == 0) {
c1->p1.x = pos.x; curve->p1 = pos;
c1->p1.y = pos.y; if (curve != begin() && curve->type != CURVE_POINT) prev->EndPoint() = pos;
if (c0) { if (next != end() && curve->type == CURVE_POINT) next->p1 = pos;
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;
}
}
} }
else if (point == 1) { else if (point == 1) {
c1->p2.x = pos.x; curve->p2 = pos;
c1->p2.y = pos.y; if (next != end() && curve->type == CURVE_LINE) next->p1 = pos;
if (c2 && c1->type != CURVE_BICUBIC) {
c2->p1.x = pos.x;
c2->p1.y = pos.y;
}
} }
else if (point == 2) { else if (point == 2) {
c1->p3.x = pos.x; curve->p3 = pos;
c1->p3.y = pos.y;
} }
else if (point == 3) { else if (point == 3) {
c1->p4.x = pos.x; curve->p4 = pos;
c1->p4.y = pos.y; if (next != end()) next->p1 = pos;
if (c2 && c1->type == CURVE_BICUBIC) {
c2->p1.x = pos.x;
c2->p1.y = pos.y;
}
} }
} }
/// @brief Gets a list of points in the curve /// @brief Gets a list of points in the curve
/// @param points /// @param points
/// @param pointCurve /// @param pointCurve
void Spline::GetPointList(std::vector<float> &points,std::vector<int> &pointCurve) { void Spline::GetPointList(std::vector<float>& points, std::vector<int>& first, std::vector<int>& count) {
// Prepare
points.clear(); points.clear();
points.reserve((curves.size() + 1) * 2); first.clear();
pointCurve.reserve(curves.size() + 1); count.clear();
pointCurve.clear();
Vector2D pt; points.reserve((size() + 1) * 2);
bool isFirst = true; int curCount = 0;
int curve = 0;
// Generate points for each curve // Generate points for each curve
for (std::list<SplineCurve>::iterator cur = curves.begin();cur!=curves.end();cur++,curve++) { for (iterator cur = begin();cur!=end();cur++) {
// First point switch (cur->type) {
if (isFirst) { case CURVE_POINT:
points.push_back(cur->p1.x); if (curCount > 0) {
points.push_back(cur->p1.y); count.push_back(curCount);
pointCurve.push_back(curve); }
isFirst = false;
}
// Line // start new path
if (cur->type == CURVE_LINE) { first.push_back(points.size() / 2);
points.push_back(cur->p2.x); points.push_back(cur->p1.x);
points.push_back(cur->p2.y); points.push_back(cur->p1.y);
pointCurve.push_back(curve); 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 // Find number of steps
else if (cur->type == CURVE_BICUBIC) { 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<float> &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 // Get the control points
Vector2D p1 = cur->p1; Vector2D p1 = curve->p1;
Vector2D p2 = cur->p2; Vector2D p2 = curve->p2;
Vector2D p3 = cur->p3; Vector2D p3 = curve->p3;
Vector2D p4 = cur->p4; Vector2D p4 = curve->p4;
// Find number of steps // Find number of steps
int len = (int)((p2-p1).Len() + (p3-p2).Len() + (p4-p3).Len()); int len = (int)((p2-p1).Len() + (p3-p2).Len() + (p4-p3).Len());
int steps = len/8; int steps = len/8;
// Render curve // Render curve
for (int i=1;i<=steps;i++) { for (int i=0;i<=steps;i++) {
// Get t and t-1 (u) // Get t and t-1 (u)
float t = float(i)/float(steps); 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.x);
points.push_back(p.y); points.push_back(p.y);
pointCurve.push_back(curve);
} }
break;
} }
} default: 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);
} }
} }
@ -353,77 +318,64 @@ void Spline::GetPointList(std::vector<float> &points,std::vector<int> &pointCurv
/// @param curve /// @param curve
/// @param t /// @param t
/// @param pt /// @param pt
void Spline::GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &pt) { void Spline::GetClosestParametricPoint(Vector2D const& reference,iterator &curve,float &t,Vector2D &pt) {
// Has at least one curve? curve = end();
curve = -1; t = 0.f;
t = 0.0f; if (empty()) return;
if (curves.size() == 0) return;
// Close the shape // Close the shape
SplineCurve pad; SplineCurve pad;
pad.p1 = curves.back().GetEndPoint(); pad.p1 = back().EndPoint();
pad.p2 = curves.front().p1; pad.p2 = front().p1;
pad.type = CURVE_LINE; pad.type = CURVE_LINE;
curves.push_back(pad); push_back(pad);
// Prepare float closest = std::numeric_limits<float>::infinity();
float closest = 8000000.0f; for (iterator cur = begin();cur!=end();cur++) {
int i = 0;
for (std::list<SplineCurve>::iterator cur = curves.begin();cur!=curves.end();cur++,i++) {
float param = cur->GetClosestParam(reference); float param = cur->GetClosestParam(reference);
Vector2D p1 = cur->GetPoint(param); Vector2D p1 = cur->GetPoint(param);
float dist = (p1-reference).Len(); float dist = (p1-reference).SquareLen();
if (dist < closest) { if (dist < closest) {
closest = dist; closest = dist;
t = param; t = param;
curve = i; curve = cur;
pt = p1; pt = p1;
} }
} }
if (&*curve == &back()) {
curve = end();
}
// Remove closing and return // Remove closing and return
curves.pop_back(); pop_back();
} }
/// @brief Point closest to reference /// @brief Point closest to reference
/// @param reference /// @param reference
/// @return /// @return
Vector2D Spline::GetClosestPoint(Vector2D reference) { Vector2D Spline::GetClosestPoint(Vector2D const& reference) {
int curve; iterator curve;
float t; float t;
Vector2D point; Vector2D point;
GetClosestParametricPoint(reference,curve,t,point); GetClosestParametricPoint(reference,curve,t,point);
return 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 /// @brief Smoothes the spline
/// @param smooth /// @param smooth
void Spline::Smooth(float smooth) { void Spline::Smooth(float smooth) {
// See if there are enough curves // See if there are enough curves
if (curves.size() < 3) return; if (size() < 3) return;
// Smooth curve // Smooth curve
SplineCurve *curve0 = NULL; iterator curve1 = end();
SplineCurve *curve1 = &curves.back(); --curve1;
SplineCurve *curve2 = NULL; for (iterator cur = begin(); cur != end();) {
for (std::list<SplineCurve>::iterator cur=curves.begin();cur!=curves.end();) { iterator curve0 = curve1;
// Get curves curve1 = cur;
curve0 = curve1;
curve1 = &(*cur);
cur++; cur++;
if (cur == curves.end()) curve2 = &curves.front(); iterator curve2 = cur == end() ? begin() : cur;
else curve2 = &(*cur);
// Smooth curve // Smooth curve
curve1->Smooth(curve0->p1,curve2->p2,smooth); curve1->Smooth(curve0->p1,curve2->p2,smooth);

View file

@ -45,36 +45,53 @@
class VideoDisplay; class VideoDisplay;
/// DOCME /// DOCME
/// @class Spline /// @class Spline
/// @brief DOCME /// @brief DOCME
class Spline { class Spline : private std::list<SplineCurve> {
private: private:
const VideoDisplay &scale; const VideoDisplay &scale;
public: public:
/// DOCME
std::list<SplineCurve> curves;
Spline(const VideoDisplay &scale); Spline(const VideoDisplay &scale);
wxString EncodeToASS(); wxString EncodeToASS();
void DecodeFromASS(wxString str); void DecodeFromASS(wxString str);
void MovePoint(iterator curve,int point,Vector2D const& pos);
/// @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 Smooth(float smooth=1.0f); void Smooth(float smooth=1.0f);
void GetPointList(std::vector<float> &points,std::vector<int> &pointCurve); void GetPointList(std::vector<float>& points, std::vector<int>& first, std::vector<int>& count);
SplineCurve *GetCurve(int index); void GetPointList(std::vector<float> &points, iterator curve);
void GetClosestParametricPoint(Vector2D reference,int &curve,float &t,Vector2D &point); void GetClosestParametricPoint(Vector2D const& reference, iterator& curve, float &t, Vector2D &point);
Vector2D GetClosestPoint(Vector2D reference); Vector2D GetClosestPoint(Vector2D const& reference);
Vector2D GetClosestControlPoint(Vector2D reference); Vector2D GetClosestControlPoint(Vector2D const& reference);
// This list intentionally excludes things specific to std::list
using std::list<SplineCurve>::value_type;
using std::list<SplineCurve>::pointer;
using std::list<SplineCurve>::reference;
using std::list<SplineCurve>::const_reference;
using std::list<SplineCurve>::size_type;
using std::list<SplineCurve>::difference_type;
using std::list<SplineCurve>::iterator;
using std::list<SplineCurve>::const_iterator;
using std::list<SplineCurve>::reverse_iterator;
using std::list<SplineCurve>::const_reverse_iterator;
using std::list<SplineCurve>::begin;
using std::list<SplineCurve>::end;
using std::list<SplineCurve>::rbegin;
using std::list<SplineCurve>::rend;
using std::list<SplineCurve>::size;
using std::list<SplineCurve>::empty;
using std::list<SplineCurve>::front;
using std::list<SplineCurve>::back;
using std::list<SplineCurve>::push_front;
using std::list<SplineCurve>::push_back;
using std::list<SplineCurve>::pop_front;
using std::list<SplineCurve>::pop_back;
using std::list<SplineCurve>::insert;
using std::list<SplineCurve>::erase;
using std::list<SplineCurve>::clear;
}; };

View file

@ -34,7 +34,6 @@
/// @ingroup visual_ts /// @ingroup visual_ts
/// ///
/////////// ///////////
// Headers // Headers
#include "config.h" #include "config.h"
@ -42,15 +41,12 @@
#include "spline_curve.h" #include "spline_curve.h"
#include "utils.h" #include "utils.h"
/// @brief Curve constructor /// @brief Curve constructor
/// ///
SplineCurve::SplineCurve() { SplineCurve::SplineCurve() {
type = CURVE_INVALID; type = CURVE_INVALID;
} }
/// @brief Split a curve in two using the de Casteljau algorithm /// @brief Split a curve in two using the de Casteljau algorithm
/// @param c1 /// @param c1
/// @param c2 /// @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 /// @brief Based on http://antigrain.com/research/bezier_interpolation/index.html Smoothes the curve
/// @param P0 /// @param P0
/// @param P3 /// @param P3
/// @param smooth /// @param smooth
/// @return /// @return
/// ///
void SplineCurve::Smooth(Vector2D P0,Vector2D P3,float smooth) { void SplineCurve::Smooth(Vector2D const& P0,Vector2D const& P3,float smooth) {
// Validate // Validate
if (type != CURVE_LINE) return; if (type != CURVE_LINE) return;
if (p1 == p2) return; if (p1 == p2) return;
smooth = MID(0.0f,smooth,1.0f); smooth = MID(0.f,smooth,1.f);
// Get points // Get points
Vector2D P1 = p1; Vector2D P1 = p1;
Vector2D P2 = p2; Vector2D P2 = p2;
// Calculate intermediate points // Calculate intermediate points
Vector2D c1 = (P0+P1)/2.0f; Vector2D c1 = (P0+P1)/2.f;
Vector2D c2 = (P1+P2)/2.0f; Vector2D c2 = (P1+P2)/2.f;
Vector2D c3 = (P2+P3)/2.0f; Vector2D c3 = (P2+P3)/2.f;
float len1 = (P1-P0).Len(); float len1 = (P1-P0).Len();
float len2 = (P2-P1).Len(); float len2 = (P2-P1).Len();
float len3 = (P3-P2).Len(); float len3 = (P3-P2).Len();
@ -130,43 +124,24 @@ void SplineCurve::Smooth(Vector2D P0,Vector2D P3,float smooth) {
type = CURVE_BICUBIC; type = CURVE_BICUBIC;
} }
/// @brief Get a point /// @brief Get a point
/// @param t /// @param t
/// @return /// @return
/// ///
Vector2D SplineCurve::GetPoint(float t) const { Vector2D SplineCurve::GetPoint(float t) const {
// Point
if (type == CURVE_POINT) return p1; if (type == CURVE_POINT) return p1;
if (type == CURVE_LINE) {
// Line return p1*(1.f-t) + p2*t;
else if (type == CURVE_LINE) {
return p1*(1.0f-t) + p2*t;
} }
if (type == CURVE_BICUBIC) {
// Bicubic float u = 1.f-t;
else if (type == CURVE_BICUBIC) {
float u = 1.0f-t;
return p1*u*u*u + 3*p2*t*u*u + 3*p3*t*t*u + p4*t*t*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);
} }
Vector2D& SplineCurve::EndPoint() {
/// @brief Get start/end point
/// @return
///
Vector2D SplineCurve::GetStartPoint() const {
return p1;
}
/// @brief DOCME
/// @return
///
Vector2D SplineCurve::GetEndPoint() const {
switch (type) { switch (type) {
case CURVE_POINT: return p1; case CURVE_POINT: return p1;
case CURVE_LINE: return p2; case CURVE_LINE: return p2;
@ -175,33 +150,26 @@ Vector2D SplineCurve::GetEndPoint() const {
} }
} }
/// @brief Get point closest to reference /// @brief Get point closest to reference
/// @param ref /// @param ref
/// @return /// @return
/// ///
Vector2D SplineCurve::GetClosestPoint(Vector2D ref) const { Vector2D SplineCurve::GetClosestPoint(Vector2D const& ref) const {
return GetPoint(GetClosestParam(ref)); return GetPoint(GetClosestParam(ref));
} }
/// @brief Get value of parameter closest to point /// @brief Get value of parameter closest to point
/// @param ref /// @param ref
/// @return /// @return
/// ///
float SplineCurve::GetClosestParam(Vector2D ref) const { float SplineCurve::GetClosestParam(Vector2D const& ref) const {
// Line
if (type == CURVE_LINE) { if (type == CURVE_LINE) {
return GetClosestSegmentPart(p1,p2,ref); return GetClosestSegmentPart(p1,p2,ref);
} }
// Bicubic
if (type == CURVE_BICUBIC) { if (type == CURVE_BICUBIC) {
int steps = 100; int steps = 100;
float bestDist = 80000000.0f; float bestDist = 80000000.f;
float bestT = 0.0f; float bestT = 0.f;
for (int i=0;i<=steps;i++) { for (int i=0;i<=steps;i++) {
float t = float(i)/float(steps); float t = float(i)/float(steps);
float dist = (GetPoint(t)-ref).Len(); float dist = (GetPoint(t)-ref).Len();
@ -212,19 +180,15 @@ float SplineCurve::GetClosestParam(Vector2D ref) const {
} }
return bestT; return bestT;
} }
return 0.f;
// Something else
return 0.0f;
} }
/// @brief Quick distance /// @brief Quick distance
/// @param ref /// @param ref
/// @return /// @return
/// ///
float SplineCurve::GetQuickDistance(Vector2D ref) const { float SplineCurve::GetQuickDistance(Vector2D const& ref) const {
// Bicubic using std::min;
if (type == CURVE_BICUBIC) { if (type == CURVE_BICUBIC) {
float len1 = GetClosestSegmentDistance(p1,p2,ref); float len1 = GetClosestSegmentDistance(p1,p2,ref);
float len2 = GetClosestSegmentDistance(p2,p3,ref); float len2 = GetClosestSegmentDistance(p2,p3,ref);
@ -232,35 +196,29 @@ float SplineCurve::GetQuickDistance(Vector2D ref) const {
float len4 = GetClosestSegmentDistance(p4,p1,ref); float len4 = GetClosestSegmentDistance(p4,p1,ref);
float len5 = GetClosestSegmentDistance(p1,p3,ref); float len5 = GetClosestSegmentDistance(p1,p3,ref);
float len6 = GetClosestSegmentDistance(p2,p4,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 // Something else
else return (GetClosestPoint(ref)-ref).Len(); else return (GetClosestPoint(ref)-ref).Len();
} }
/// @brief Closest t in segment p1-p2 to point p3 /// @brief Closest t in segment p1-p2 to point p3
/// @param pt1 /// @param pt1
/// @param pt2 /// @param pt2
/// @param pt3 /// @param pt3
/// @return /// @return
/// ///
float SplineCurve::GetClosestSegmentPart(Vector2D pt1,Vector2D pt2,Vector2D pt3) const { float SplineCurve::GetClosestSegmentPart(Vector2D const& pt1,Vector2D const& pt2,Vector2D const& pt3) const {
return MID(0.0f,(pt3-pt1).Dot(pt2-pt1)/(pt2-pt1).SquareLen(),1.0f); return MID(0.f,(pt3-pt1).Dot(pt2-pt1)/(pt2-pt1).SquareLen(),1.f);
} }
/// @brief Closest distance between p3 and segment p1-p2 /// @brief Closest distance between p3 and segment p1-p2
/// @param pt1 /// @param pt1
/// @param pt2 /// @param pt2
/// @param pt3 /// @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); float t = GetClosestSegmentPart(pt1,pt2,pt3);
return (pt1*(1.0f-t)+pt2*t-pt3).Len(); return (pt1*(1.f-t)+pt2*t-pt3).Len();
} }

View file

@ -34,14 +34,10 @@
/// @ingroup visual_ts /// @ingroup visual_ts
/// ///
/////////// ///////////
// Headers // Headers
#include "vector2d.h" #include "vector2d.h"
/// DOCME /// DOCME
enum CurveType { enum CurveType {
@ -58,8 +54,6 @@ enum CurveType {
CURVE_BICUBIC CURVE_BICUBIC
}; };
/// DOCME /// DOCME
/// @class SplineCurve /// @class SplineCurve
/// @brief DOCME /// @brief DOCME
@ -67,8 +61,8 @@ enum CurveType {
/// DOCME /// DOCME
class SplineCurve { class SplineCurve {
private: private:
float GetClosestSegmentPart(Vector2D p1,Vector2D p2,Vector2D p3) const; float GetClosestSegmentPart(Vector2D const& p1,Vector2D const& p2,Vector2D const& p3) const;
float GetClosestSegmentDistance(Vector2D p1,Vector2D p2,Vector2D p3) const; float GetClosestSegmentDistance(Vector2D const& p1,Vector2D const& p2,Vector2D const& p3) const;
public: public:
@ -86,14 +80,11 @@ public:
SplineCurve(); SplineCurve();
void Split(SplineCurve &c1,SplineCurve &c2,float t=0.5); 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 GetPoint(float t) const;
Vector2D GetStartPoint() const; Vector2D& EndPoint();
Vector2D GetEndPoint() const; Vector2D GetClosestPoint(Vector2D const& ref) const;
Vector2D GetClosestPoint(Vector2D ref) const; float GetClosestParam(Vector2D const& ref) const;
float GetClosestParam(Vector2D ref) const; float GetQuickDistance(Vector2D const& ref) const;
float GetQuickDistance(Vector2D ref) const;
}; };

View file

@ -35,6 +35,7 @@
#ifndef AGI_PRE #ifndef AGI_PRE
#include <wx/toolbar.h> #include <wx/toolbar.h>
#include "gl/glext.h"
#endif #endif
#include "config.h" #include "config.h"
@ -44,36 +45,16 @@
#include "video_display.h" #include "video_display.h"
#include "visual_tool_vector_clip.h" #include "visual_tool_vector_clip.h"
///////
// IDs
enum { enum {
/// DOCME
BUTTON_DRAG = VISUAL_SUB_TOOL_START, BUTTON_DRAG = VISUAL_SUB_TOOL_START,
/// DOCME
BUTTON_LINE, BUTTON_LINE,
/// DOCME
BUTTON_BICUBIC, BUTTON_BICUBIC,
/// DOCME
BUTTON_CONVERT, BUTTON_CONVERT,
/// DOCME
BUTTON_INSERT, BUTTON_INSERT,
/// DOCME
BUTTON_REMOVE, BUTTON_REMOVE,
/// DOCME
BUTTON_FREEHAND, BUTTON_FREEHAND,
/// DOCME
BUTTON_FREEHAND_SMOOTH, BUTTON_FREEHAND_SMOOTH,
BUTTON_LAST // Leave this at the end and don't use it
/// DOCME
BUTTON_LAST // Leave this at the end and don't use it
}; };
/// @brief Constructor /// @brief Constructor
@ -107,25 +88,30 @@ VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, VideoState cons
if (features.size() == 0) SetMode(1); if (features.size() == 0) SetMode(1);
} }
/// @brief Sub-tool pressed
/// @param event
void VisualToolVectorClip::OnSubTool(wxCommandEvent &event) { void VisualToolVectorClip::OnSubTool(wxCommandEvent &event) {
SetMode(event.GetId() - BUTTON_DRAG); SetMode(event.GetId() - BUTTON_DRAG);
} }
/// @brief Set mode void VisualToolVectorClip::SetMode(int newMode) {
/// @param _mode // Manually enforce radio behavior as we want one selection in the bar
void VisualToolVectorClip::SetMode(int _mode) { // rather than one per group
// Make sure clicked is checked and everything else isn't. (Yes, this is radio behavior, but the separators won't let me use it)
for (int i=BUTTON_DRAG;i<BUTTON_LAST;i++) { for (int i=BUTTON_DRAG;i<BUTTON_LAST;i++) {
toolBar->ToggleTool(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() { void VisualToolVectorClip::Draw() {
if (spline.curves.empty()) return; if (spline.empty()) return;
GL_EXT(PFNGLMULTIDRAWARRAYSPROC, glMultiDrawArrays);
// Get line // Get line
AssDialogue *line = GetActiveDialogueLine(); AssDialogue *line = GetActiveDialogueLine();
@ -133,8 +119,12 @@ void VisualToolVectorClip::Draw() {
// Parse vector // Parse vector
std::vector<float> points; std::vector<float> points;
std::vector<int> pointCurve; std::vector<int> start;
spline.GetPointList(points,pointCurve); std::vector<int> count;
spline.GetPointList(points, start, count);
assert(!start.empty());
assert(!count.empty());
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, &points[0]); glVertexPointer(2, GL_FLOAT, 0, &points[0]);
@ -156,12 +146,12 @@ void VisualToolVectorClip::Draw() {
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(GL_BACK); 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 // Decrement the winding number for each backfacing triangle
glStencilOp(GL_DECR, GL_DECR, GL_DECR); glStencilOp(GL_DECR, GL_DECR, GL_DECR);
glCullFace(GL_FRONT); 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); glDisable(GL_CULL_FACE);
// Draw the actual rectangle // Draw the actual rectangle
@ -176,29 +166,26 @@ void VisualToolVectorClip::Draw() {
DrawRectangle(0,0,video.w,video.h); DrawRectangle(0,0,video.w,video.h);
glDisable(GL_STENCIL_TEST); 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 // Draw lines
SetFillColour(colour[3],0.0f); SetFillColour(colour[3],0.0f);
SetLineColour(colour[3],1.0f,2); SetLineColour(colour[3],1.0f,2);
SetModeLine(); 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 // Draw highlighted line
if (!curFeature && points.size() > 1 && highCurve > -1) { if ((mode == 3 || mode == 4) && !curFeature && points.size() > 2) {
std::pair<std::vector<int>::iterator, std::vector<int>::iterator> high = std::equal_range(pointCurve.begin(), pointCurve.end(), highCurve); std::vector<float> highPoints;
if (high.first != high.second) { spline.GetPointList(highPoints, highCurve);
if (!highPoints.empty()) {
glVertexPointer(2, GL_FLOAT, 0, &highPoints[0]);
SetLineColour(colour[2], 1.f, 2); SetLineColour(colour[2], 1.f, 2);
int first = std::distance(pointCurve.begin(), high.first); SetModeLine();
int count = std::distance(high.first, high.second); glDrawArrays(GL_LINE_STRIP, 0, highPoints.size() / 2);
if (first > 0) first -= 1;
glDrawArrays(GL_LINE_STRIP, first, count);
} }
} }
@ -206,23 +193,22 @@ void VisualToolVectorClip::Draw() {
// Draw lines connecting the bicubic features // Draw lines connecting the bicubic features
SetLineColour(colour[3],0.9f,1); SetLineColour(colour[3],0.9f,1);
for (std::list<SplineCurve>::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) { if (cur->type == CURVE_BICUBIC) {
DrawDashedLine(cur->p1.x,cur->p1.y,cur->p2.x,cur->p2.y,6); 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); DrawDashedLine(cur->p3.x,cur->p3.y,cur->p4.x,cur->p4.y,6);
} }
} }
// Draw features
DrawAllFeatures(); DrawAllFeatures();
// Draw preview of inserted line // Draw preview of inserted line
if (mode == 1 || mode == 2) { if (mode == 1 || mode == 2) {
if (spline.curves.size() && video.x > INT_MIN && video.y > INT_MIN) { if (spline.size() && video.x > INT_MIN && video.y > INT_MIN) {
SplineCurve *c0 = &spline.curves.front(); SplineCurve *c0 = &spline.front();
SplineCurve *c1 = &spline.curves.back(); SplineCurve *c1 = &spline.back();
DrawDashedLine(video.x,video.y,c0->p1.x,c0->p1.y,6); 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); ClearSelection(false);
features.clear(); features.clear();
// This is perhaps a bit conservative as there can be up to 3N+1 features // 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; VisualToolVectorClipDraggableFeature feat;
// Go through each curve // Go through each curve
bool isFirst = true;
int i = 0; int i = 0;
int j = 0; int j = 0;
for (std::list<SplineCurve>::iterator cur=spline.curves.begin();cur!=spline.curves.end();cur++,i++) { for (Spline::iterator cur=spline.begin();cur!=spline.end();cur++,i++) {
// First point if (cur->type == CURVE_POINT) {
if (isFirst) {
isFirst = false;
feat.x = (int)cur->p1.x; feat.x = (int)cur->p1.x;
feat.y = (int)cur->p1.y; feat.y = (int)cur->p1.y;
feat.type = DRAG_SMALL_CIRCLE; feat.type = DRAG_SMALL_CIRCLE;
feat.index = i; feat.curve = cur;
feat.point = 0; feat.point = 0;
features.push_back(feat); features.push_back(feat);
AddSelection(j++); AddSelection(j++);
} }
if (cur->type == CURVE_LINE) { else if (cur->type == CURVE_LINE) {
feat.x = (int)cur->p2.x; feat.x = (int)cur->p2.x;
feat.y = (int)cur->p2.y; feat.y = (int)cur->p2.y;
feat.type = DRAG_SMALL_CIRCLE; feat.type = DRAG_SMALL_CIRCLE;
feat.index = i; feat.curve = cur;
feat.point = 1; feat.point = 1;
features.push_back(feat); features.push_back(feat);
AddSelection(j++); AddSelection(j++);
@ -269,7 +252,7 @@ void VisualToolVectorClip::PopulateFeatureList() {
// Control points // Control points
feat.x = (int)cur->p2.x; feat.x = (int)cur->p2.x;
feat.y = (int)cur->p2.y; feat.y = (int)cur->p2.y;
feat.index = i; feat.curve = cur;
feat.point = 1; feat.point = 1;
feat.type = DRAG_SMALL_SQUARE; feat.type = DRAG_SMALL_SQUARE;
features.push_back(feat); features.push_back(feat);
@ -295,7 +278,7 @@ void VisualToolVectorClip::PopulateFeatureList() {
/// @brief Update /// @brief Update
/// @param feature /// @param feature
void VisualToolVectorClip::UpdateDrag(VisualToolVectorClipDraggableFeature* 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 /// @brief Commit
@ -310,25 +293,26 @@ void VisualToolVectorClip::CommitDrag(VisualToolVectorClipDraggableFeature* feat
bool VisualToolVectorClip::InitializeDrag(VisualToolVectorClipDraggableFeature* feature) { bool VisualToolVectorClip::InitializeDrag(VisualToolVectorClipDraggableFeature* feature) {
// Delete a control point // Delete a control point
if (mode == 5) { if (mode == 5) {
int i = 0; // Update next
for (std::list<SplineCurve>::iterator cur=spline.curves.begin();cur!=spline.curves.end();i++,cur++) { Spline::iterator next = feature->curve;
if (i == feature->index) { next++;
// Update next if (next != spline.end()) {
if (i != 0 || feature->point != 0) { if (feature->curve->type == CURVE_POINT) {
std::list<SplineCurve>::iterator next = cur; next->p1 = next->EndPoint();
next++; next->type = CURVE_POINT;
if (next != spline.curves.end()) next->p1 = cur->p1; }
} else {
next->p1 = feature->curve->p1;
// Erase and save changes
spline.curves.erase(cur);
CommitDrag(feature);
PopulateFeatureList();
curFeature = NULL;
Commit(true);
return false;
} }
} }
// Erase and save changes
spline.erase(feature->curve);
CommitDrag(feature);
PopulateFeatureList();
curFeature = NULL;
Commit(true);
return false;
} }
return true; return true;
} }
@ -341,13 +325,10 @@ bool VisualToolVectorClip::InitializeHold() {
SplineCurve curve; SplineCurve curve;
// Set start position // Set start position
if (spline.curves.size()) { if (!spline.empty()) {
curve.p1 = spline.curves.back().GetEndPoint(); curve.p1 = spline.back().EndPoint();
if (mode == 1) curve.type = CURVE_LINE; if (mode == 1) curve.type = CURVE_LINE;
else curve.type = CURVE_BICUBIC; 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 // First point
@ -357,7 +338,7 @@ bool VisualToolVectorClip::InitializeHold() {
} }
// Insert // Insert
spline.AppendCurve(curve); spline.push_back(curve);
UpdateHold(); UpdateHold();
return true; return true;
} }
@ -366,26 +347,23 @@ bool VisualToolVectorClip::InitializeHold() {
if (mode == 3 || mode == 4) { if (mode == 3 || mode == 4) {
// Get closest point // Get closest point
Vector2D pt; Vector2D pt;
int curve; Spline::iterator curve;
float t; float t;
spline.GetClosestParametricPoint(Vector2D(video.x,video.y),curve,t,pt); spline.GetClosestParametricPoint(Vector2D(video.x,video.y),curve,t,pt);
// Convert // Convert
if (mode == 3) { if (mode == 3) {
SplineCurve *c1 = spline.GetCurve(curve); if (curve != spline.end()) {
if (!c1) { if (curve->type == CURVE_LINE) {
} curve->type = CURVE_BICUBIC;
else { curve->p4 = curve->p2;
if (c1->type == CURVE_LINE) { curve->p2 = curve->p1 * 0.75 + curve->p4 * 0.25;
c1->type = CURVE_BICUBIC; curve->p3 = curve->p1 * 0.25 + curve->p4 * 0.75;
c1->p4 = c1->p2;
c1->p2 = c1->p1 * 0.75 + c1->p4 * 0.25;
c1->p3 = c1->p1 * 0.25 + c1->p4 * 0.75;
} }
else if (c1->type == CURVE_BICUBIC) { else if (curve->type == CURVE_BICUBIC) {
c1->type = CURVE_LINE; curve->type = CURVE_LINE;
c1->p2 = c1->p4; curve->p2 = curve->p4;
} }
} }
} }
@ -393,28 +371,28 @@ bool VisualToolVectorClip::InitializeHold() {
// Insert // Insert
else { else {
// Check if there is at least one curve to split // 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 // Split the curve
SplineCurve *c1 = spline.GetCurve(curve); if (curve == spline.end()) {
SplineCurve c2;
if (!c1) {
SplineCurve ct; SplineCurve ct;
ct.type = CURVE_LINE; ct.type = CURVE_LINE;
ct.p1 = spline.curves.back().GetEndPoint(); ct.p1 = spline.back().EndPoint();
ct.p2 = spline.curves.front().p1; ct.p2 = spline.front().p1;
ct.p2 = ct.p1*(1-t) + ct.p2*t; ct.p2 = ct.p1*(1-t) + ct.p2*t;
spline.AppendCurve(ct); spline.push_back(ct);
} }
else { else {
c1->Split(*c1,c2,t); SplineCurve c2;
spline.InsertCurve(c2,curve+1); curve->Split(*curve,c2,t);
spline.insert(++curve, c2);
} }
} }
// Commit // Commit
SetOverride(GetActiveDialogueLine(), inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")"); SetOverride(GetActiveDialogueLine(), inverse ? L"\\iclip" : L"\\clip", L"(" + spline.EncodeToASS() + L")");
Commit(true); Commit(true);
DoRefresh();
return false; return false;
} }
@ -422,30 +400,32 @@ bool VisualToolVectorClip::InitializeHold() {
if (mode == 6 || mode == 7) { if (mode == 6 || mode == 7) {
ClearSelection(false); ClearSelection(false);
features.clear(); features.clear();
spline.curves.clear(); spline.clear();
lastX = INT_MIN; SplineCurve curve;
lastY = INT_MIN; curve.type = CURVE_POINT;
curve.p1.x = video.x;
curve.p1.y = video.y;
spline.push_back(curve);
return true; return true;
} }
return false; return false;
} }
/// @brief Update hold /// @brief Update hold
/// @return
void VisualToolVectorClip::UpdateHold() { void VisualToolVectorClip::UpdateHold() {
// Insert line // Insert line
if (mode == 1) { if (mode == 1) {
spline.curves.back().p2 = Vector2D(video.x,video.y); spline.back().p2 = Vector2D(video.x,video.y);
} }
// Insert bicubic // Insert bicubic
if (mode == 2) { if (mode == 2) {
SplineCurve &curve = spline.curves.back(); SplineCurve &curve = spline.back();
curve.p4 = Vector2D(video.x,video.y); curve.p4 = Vector2D(video.x,video.y);
// Control points // Control points
if (spline.curves.size() > 1) { if (spline.size() > 1) {
std::list<SplineCurve>::reverse_iterator iter = spline.curves.rbegin(); std::list<SplineCurve>::reverse_iterator iter = spline.rbegin();
iter++; iter++;
SplineCurve &c0 = *iter; SplineCurve &c0 = *iter;
Vector2D prevVector; Vector2D prevVector;
@ -460,22 +440,18 @@ void VisualToolVectorClip::UpdateHold() {
// Freehand // Freehand
if (mode == 6 || mode == 7) { if (mode == 6 || mode == 7) {
if (lastX != INT_MIN && lastY != INT_MIN) { // See if distance is enough
// See if distance is enough Vector2D const& last = spline.back().EndPoint();
Vector2D delta(lastX-video.x,lastY-video.y); int len = (int)Vector2D(last.x-video.x, last.y-video.y).Len();
int len = (int)delta.Len(); if (mode == 6 && len < 30) return;
if (mode == 6 && len < 30) return; if (mode == 7 && len < 60) return;
if (mode == 7 && len < 60) return;
// Generate curve and add it
// Generate curve and add it SplineCurve curve;
SplineCurve curve; curve.type = CURVE_LINE;
curve.type = CURVE_LINE; curve.p1 = Vector2D(last.x,last.y);
curve.p1 = Vector2D(lastX,lastY); curve.p2 = Vector2D(video.x,video.y);
curve.p2 = Vector2D(video.x,video.y); spline.push_back(curve);
spline.AppendCurve(curve);
}
lastX = video.x;
lastY = video.y;
} }
} }
@ -510,4 +486,3 @@ void VisualToolVectorClip::DoRefresh() {
PopulateFeatureList(); PopulateFeatureList();
} }
} }

View file

@ -46,13 +46,12 @@ class wxToolBar;
class VisualToolVectorClipDraggableFeature : public VisualDraggableFeature { class VisualToolVectorClipDraggableFeature : public VisualDraggableFeature {
public: public:
/// Which curve in the spline this feature is a point on /// 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 /// 0-3; indicates which part of the curve this point is
int point; int point;
/// @brief Constructor /// @brief Constructor
VisualToolVectorClipDraggableFeature() VisualToolVectorClipDraggableFeature()
: VisualDraggableFeature() : VisualDraggableFeature()
, index(0)
, point(0) , point(0)
{ } { }
}; };
@ -62,24 +61,18 @@ public:
/// @brief DOCME /// @brief DOCME
class VisualToolVectorClip : public VisualTool<VisualToolVectorClipDraggableFeature> { class VisualToolVectorClip : public VisualTool<VisualToolVectorClipDraggableFeature> {
private: private:
Spline spline; /// The current spline
/// DOCME wxToolBar *toolBar; /// The subtoolbar
Spline spline;
/// DOCME
wxToolBar *toolBar;
/// DOCME /// DOCME
int mode; int mode;
/// DOCME
/// DOCME
int lastX,lastY;
/// DOCME /// DOCME
bool inverse; bool inverse;
/// @brief Set the mode
/// @param mode 0-7
void SetMode(int mode); void SetMode(int mode);
@ -90,7 +83,6 @@ private:
void UpdateHold(); void UpdateHold();
void CommitHold(); void CommitHold();
void PopulateFeatureList(); void PopulateFeatureList();
void UpdateDrag(VisualToolVectorClipDraggableFeature* feature); void UpdateDrag(VisualToolVectorClipDraggableFeature* feature);
void CommitDrag(VisualToolVectorClipDraggableFeature* feature); void CommitDrag(VisualToolVectorClipDraggableFeature* feature);