mirror of https://github.com/odrling/Aegisub
Add support for rendering vector clips with multiple 'm' commands.
Originally committed to SVN as r4463.
This commit is contained in:
parent
c7da8d9f61
commit
f361d1a67b
|
@ -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() {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue