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