Merge branch 'vector_clip_actions' into feature
This commit is contained in:
commit
ff20805ae6
10 changed files with 107 additions and 49 deletions
|
@ -178,7 +178,7 @@ namespace {
|
|||
STR_HELP("When the surrounding plane is also visible, switches which quad is locked. If inactive, the inner quad can only be resized without changing the perspective plane. If active, this holds for the outer quad instead.")
|
||||
|
||||
bool Validate(const agi::Context *c) override {
|
||||
return c->videoDisplay->ToolIsType(typeid(VisualToolPerspective)) && c->videoDisplay->GetSubTool() | PERSP_OUTER;
|
||||
return c->videoDisplay->ToolIsType(typeid(VisualToolPerspective)) && c->videoDisplay->GetSubTool() & PERSP_OUTER;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -41,17 +41,22 @@
|
|||
|
||||
#include <limits>
|
||||
|
||||
Spline::Spline(const VisualToolBase &tl)
|
||||
Spline::Spline(const VisualToolBase *tl)
|
||||
: coord_translator(tl)
|
||||
{
|
||||
}
|
||||
|
||||
Vector2D Spline::ToScript(Vector2D vec) const {
|
||||
return coord_translator.ToScriptCoords(vec) * scale;
|
||||
if (coord_translator)
|
||||
vec = coord_translator->ToScriptCoords(vec);
|
||||
return vec * scale;
|
||||
}
|
||||
|
||||
Vector2D Spline::FromScript(Vector2D vec) const {
|
||||
return coord_translator.FromScriptCoords(vec / scale);
|
||||
vec = vec / scale;
|
||||
if (coord_translator)
|
||||
vec = coord_translator->FromScriptCoords(vec);
|
||||
return vec;
|
||||
}
|
||||
|
||||
void Spline::SetScale(int new_scale) {
|
||||
|
|
|
@ -36,7 +36,7 @@ class VisualToolBase;
|
|||
|
||||
class Spline final : private std::vector<SplineCurve> {
|
||||
/// Visual tool to do the conversion between script and video pixels
|
||||
const VisualToolBase &coord_translator;
|
||||
const VisualToolBase *coord_translator = nullptr;
|
||||
/// Spline scale
|
||||
int scale = 0;
|
||||
int raw_scale = 0;
|
||||
|
@ -47,7 +47,8 @@ class Spline final : private std::vector<SplineCurve> {
|
|||
/// Script coordinates -> Video coordinates
|
||||
Vector2D FromScript(Vector2D vec) const;
|
||||
public:
|
||||
Spline(const VisualToolBase &scale);
|
||||
Spline() {};
|
||||
Spline(const VisualToolBase *scale);
|
||||
|
||||
/// Encode to an ASS vector drawing
|
||||
std::string EncodeToAss() const;
|
||||
|
|
|
@ -115,6 +115,15 @@ Vector2D& SplineCurve::EndPoint() {
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<Vector2D> SplineCurve::AnchorPoints() {
|
||||
switch (type) {
|
||||
case POINT: return std::vector<Vector2D>({p1});
|
||||
case LINE: return std::vector<Vector2D>({p1, p2});
|
||||
case BICUBIC: return std::vector<Vector2D>({p1, p2, p3, p4});
|
||||
default: return std::vector<Vector2D>();
|
||||
}
|
||||
}
|
||||
|
||||
Vector2D SplineCurve::GetClosestPoint(Vector2D ref) const {
|
||||
return GetPoint(GetClosestParam(ref));
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ public:
|
|||
|
||||
Vector2D GetPoint(float t) const;
|
||||
Vector2D& EndPoint();
|
||||
std::vector<Vector2D> AnchorPoints();
|
||||
/// Get point on the curve closest to reference
|
||||
Vector2D GetClosestPoint(Vector2D ref) const;
|
||||
/// Get t value for the closest point to reference
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#include <libaegisub/of_type_adaptor.h>
|
||||
#include <libaegisub/split.h>
|
||||
|
||||
#include <boost/algorithm/string/join.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -540,11 +542,9 @@ int VisualToolBase::GetLineAlignment(AssDialogue *diag) {
|
|||
return an;
|
||||
}
|
||||
|
||||
void VisualToolBase::GetLineBaseExtents(AssDialogue *diag, double &width, double &height, double &descent, double &extlead) {
|
||||
width = 0.;
|
||||
height = 0.;
|
||||
descent = 0.;
|
||||
extlead = 0.;
|
||||
std::pair<Vector2D, Vector2D> VisualToolBase::GetLineBaseExtents(AssDialogue *diag) {
|
||||
double width = 0.;
|
||||
double height = 0.;
|
||||
|
||||
AssStyle style;
|
||||
if (AssStyle *basestyle = c->ass->GetStyle(diag->Style)) {
|
||||
|
@ -554,25 +554,57 @@ void VisualToolBase::GetLineBaseExtents(AssDialogue *diag, double &width, double
|
|||
}
|
||||
|
||||
auto blocks = diag->ParseTags();
|
||||
if (param_vec tag = find_tag(blocks, "\\fs"))
|
||||
style.fontsize = tag->front().Get(style.fontsize);
|
||||
if (param_vec tag = find_tag(blocks, "\\fn"))
|
||||
style.font = tag->front().Get(style.font);
|
||||
param_vec ptag = find_tag(blocks, "\\p");
|
||||
|
||||
std::string text = diag->GetStrippedText();
|
||||
std::vector<std::string> textlines;
|
||||
boost::replace_all(text, "\\N", "\n");
|
||||
agi::Split(textlines, text, '\n');
|
||||
for (std::string line : textlines) {
|
||||
double linewidth = 0;
|
||||
double lineheight = 0;
|
||||
if (!Automation4::CalculateTextExtents(&style, line, linewidth, lineheight, descent, extlead)) {
|
||||
// meh... let's make some ballpark estimates
|
||||
linewidth = style.fontsize * line.length();
|
||||
lineheight = style.fontsize;
|
||||
if (ptag && ptag->front().Get(0)) { // A drawing
|
||||
Spline spline;
|
||||
spline.SetScale(ptag->front().Get(1));
|
||||
std::string drawing_text = join(blocks | agi::of_type<AssDialogueBlockDrawing>() | boost::adaptors::transformed([&](AssDialogueBlock *d) { return d->GetText(); }), "");
|
||||
spline.DecodeFromAss(drawing_text);
|
||||
|
||||
if (!spline.size())
|
||||
return std::make_pair(Vector2D(0, 0), Vector2D(0, 0));
|
||||
|
||||
float left = FLT_MAX;
|
||||
float top = FLT_MAX;
|
||||
float right = -FLT_MAX;
|
||||
float bot = -FLT_MAX;
|
||||
|
||||
for (SplineCurve curve : spline) {
|
||||
for (Vector2D pt : curve.AnchorPoints()) {
|
||||
left = std::min(left, pt.X());
|
||||
top = std::min(top, pt.Y());
|
||||
right = std::max(right, pt.X());
|
||||
bot = std::max(bot, pt.Y());
|
||||
}
|
||||
}
|
||||
width = std::max(width, linewidth);
|
||||
height += lineheight;
|
||||
|
||||
return std::make_pair(Vector2D(left, top), Vector2D(right, bot));
|
||||
} else {
|
||||
if (param_vec tag = find_tag(blocks, "\\fs"))
|
||||
style.fontsize = tag->front().Get(style.fontsize);
|
||||
if (param_vec tag = find_tag(blocks, "\\fn"))
|
||||
style.font = tag->front().Get(style.font);
|
||||
|
||||
std::string text = diag->GetStrippedText();
|
||||
std::vector<std::string> textlines;
|
||||
boost::replace_all(text, "\\N", "\n");
|
||||
agi::Split(textlines, text, '\n');
|
||||
for (std::string line : textlines) {
|
||||
double linewidth = 0;
|
||||
double lineheight = 0;
|
||||
|
||||
double descent;
|
||||
double extlead;
|
||||
if (!Automation4::CalculateTextExtents(&style, line, linewidth, lineheight, descent, extlead)) {
|
||||
// meh... let's make some ballpark estimates
|
||||
linewidth = style.fontsize * line.length();
|
||||
lineheight = style.fontsize;
|
||||
}
|
||||
width = std::max(width, linewidth);
|
||||
height += lineheight;
|
||||
}
|
||||
return std::make_pair(Vector2D(0, 0), Vector2D(width, height));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -133,11 +133,18 @@ protected:
|
|||
float GetLineFontSize(AssDialogue *diag);
|
||||
int GetLineAlignment(AssDialogue *diag);
|
||||
/// @brief Compute text extents of the given line without any formatting
|
||||
/// @param diag The dialogue line
|
||||
/// @return The top left and bottom right corners of the line's bounding box respectively.
|
||||
///
|
||||
/// Formatting tags are stripped and \fs tags are respected, but \fscx and \fscy are kept as 100 even if
|
||||
/// they are different in the style.
|
||||
/// For text the top left corner of the bounding box will always be at the origin, but this needn't be
|
||||
/// the case for drawings. The width and height of the bounding box are the shifts used for text alignment.
|
||||
///
|
||||
/// This function works for most common line formats, but can be inaccurate for more complex cases such as lines
|
||||
/// containing both text and drawings.
|
||||
/// Returns a rough estimate when getting the precise extents fails
|
||||
void GetLineBaseExtents(AssDialogue *diag, double &width, double &height, double &descent, double &extlead);
|
||||
std::pair<Vector2D, Vector2D> GetLineBaseExtents(AssDialogue *diag);
|
||||
void GetLineClip(AssDialogue *diag, Vector2D &p1, Vector2D &p2, bool &inverse);
|
||||
std::string GetLineVectorClip(AssDialogue *diag, int &scale, bool &inverse);
|
||||
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include <libaegisub/split.h>
|
||||
#include <libaegisub/util.h>
|
||||
|
||||
#include <libaegisub/log.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <wx/colour.h>
|
||||
|
||||
|
@ -332,7 +334,7 @@ void VisualToolPerspective::Draw() {
|
|||
gl.SetRotation(angle_x, angle_y, angle_z);
|
||||
gl.SetScale(fsc);
|
||||
gl.SetShear(fax, fay);
|
||||
Vector2D glScale = textheight * Vector2D(1, 1) / spacing / 4;
|
||||
Vector2D glScale = (bbox.second.Y() - bbox.first.Y()) * Vector2D(1, 1) / spacing / 4;
|
||||
gl.SetScale(100 * glScale);
|
||||
|
||||
// Draw grid
|
||||
|
@ -678,17 +680,18 @@ bool VisualToolPerspective::InnerToText() {
|
|||
|
||||
float quadwidth = ab.Len();
|
||||
float quadheight = abs(ad.Y());
|
||||
float scalex = quadwidth / textwidth;
|
||||
float scaley = quadheight / textheight;
|
||||
float scalex = quadwidth / std::max(bbox.second.X() - bbox.first.X(), 1.0f);
|
||||
float scaley = quadheight / std::max(bbox.second.Y() - bbox.first.Y(), 1.0f);
|
||||
Vector2D scale = Vector2D(scalex, scaley);
|
||||
|
||||
float shiftv = align <= 3 ? 1 : (align <= 6 ? 0.5 : 0);
|
||||
float shifth = align % 3 == 0 ? 1 : (align % 3 == 2 ? 0.5 : 0);
|
||||
pos = org + r[0].XY() + Vector2D(quadwidth * shifth, quadheight * shiftv);
|
||||
pos = org + r[0].XY() - bbox.first * scale + Vector2D(quadwidth * shifth, quadheight * shiftv);
|
||||
angle_x = rotx * rad2deg;
|
||||
angle_y = -roty * rad2deg;
|
||||
angle_z = -rotz * rad2deg;
|
||||
Vector2D oldfsc = fsc;
|
||||
fsc = 100 * Vector2D(scalex, scaley);
|
||||
fsc = 100 * scale;
|
||||
fax = rawfax * scaley / scalex;
|
||||
fay = 0;
|
||||
|
||||
|
@ -779,40 +782,39 @@ void VisualToolPerspective::TextToPersp() {
|
|||
|
||||
align = GetLineAlignment(active_line);
|
||||
|
||||
double descend, extlead;
|
||||
GetLineBaseExtents(active_line, textwidth, textheight, descend, extlead);
|
||||
textwidth = std::max(textwidth, 1.);
|
||||
textheight = std::max(textheight, 1.);
|
||||
double textleft, texttop = 0.;
|
||||
bbox = GetLineBaseExtents(active_line);
|
||||
float textwidth = std::max(bbox.second.X() - bbox.first.X(), 1.f);
|
||||
float textheight = std::max(bbox.second.Y() - bbox.first.Y(), 1.f);
|
||||
double shiftx = 0., shifty = 0.;
|
||||
|
||||
switch ((align - 1) % 3) {
|
||||
case 1:
|
||||
textleft = -textwidth / 2;
|
||||
shiftx = -textwidth / 2;
|
||||
break;
|
||||
case 2:
|
||||
textleft = -textwidth;
|
||||
shiftx = -textwidth;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch ((align - 1) / 3) {
|
||||
case 0:
|
||||
texttop = -textheight;
|
||||
shifty = -textheight;
|
||||
break;
|
||||
case 1:
|
||||
texttop = -textheight / 2;
|
||||
shifty = -textheight / 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<Vector2D> textrect = MakeRect(Vector2D(0, 0), Vector2D(textwidth, textheight));
|
||||
std::vector<Vector2D> textrect = MakeRect(bbox.first, bbox.second);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Vector2D p = textrect[i];
|
||||
// Apply \fax and \fay
|
||||
p = Vector2D(p.X() + p.Y() * fax, p.X() * fay + p.Y());
|
||||
// Translate to alignment point
|
||||
p = p + Vector2D(textleft, texttop);
|
||||
p = p + Vector2D(shiftx, shifty);
|
||||
// Apply scaling
|
||||
p = Vector2D(p.X() * fsc.X() / 100., p.Y() * fsc.Y() / 100.);
|
||||
// Translate relative to origin
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
|
||||
class VisualToolPerspective final : public VisualTool<VisualToolPerspectiveDraggableFeature> {
|
||||
wxToolBar *toolBar = nullptr; /// The subtoolbar
|
||||
int settings = 0;
|
||||
int settings = 0;
|
||||
|
||||
agi::OptionValue* optOuter;
|
||||
agi::OptionValue* optOuterLocked;
|
||||
|
@ -69,8 +69,9 @@ class VisualToolPerspective final : public VisualTool<VisualToolPerspectiveDragg
|
|||
|
||||
int align = 0;
|
||||
|
||||
double textwidth = 0.f;
|
||||
double textheight = 0.f;
|
||||
// Corners of the bounding box of the event without any formatting.
|
||||
// The top left corner is the zero vector for text but might not be for drawings.
|
||||
std::pair<Vector2D, Vector2D> bbox;
|
||||
|
||||
Vector2D fsc;
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ int BUTTON_ID_BASE = 1300;
|
|||
|
||||
VisualToolVectorClip::VisualToolVectorClip(VideoDisplay *parent, agi::Context *context)
|
||||
: VisualTool<VisualToolVectorClipDraggableFeature>(parent, context)
|
||||
, spline(*this)
|
||||
, spline(this)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue