Skip to content

Commit d6df277

Browse files
committed
New Features for Shapery
1 parent 344d7b2 commit d6df277

File tree

4 files changed

+276
-68
lines changed

4 files changed

+276
-68
lines changed

macros/ILL.Shapery.moon

Lines changed: 78 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
export script_name = "Shapery"
22
export script_description = "Does several types of shape manipulations from the simplest to the most complex"
3-
export script_version = "2.5.8"
3+
export script_version = "2.6.0"
44
export script_author = "ILLTeam"
55
export script_namespace = "ILL.Shapery"
66

77
haveDepCtrl, DependencyControl = pcall require, "l0.DependencyControl"
88

9-
local depctrl, Clipper, ILL, Aegi, Ass, Config, Line, Curve, Path, Point, Util, Math, Table, Util
9+
local depctrl, Clipper, ILL
1010
if haveDepCtrl
1111
depctrl = DependencyControl {
1212
feed: "https://raw.githubusercontent.com/TypesettingTools/ILL-Aegisub-Scripts/main/DependencyControl.json",
@@ -19,19 +19,18 @@ if haveDepCtrl
1919
}
2020
{
2121
"ILL.ILL"
22-
version: "1.4.5"
22+
version: "1.6.5"
2323
url: "https://github.com/TypesettingTools/ILL-Aegisub-Scripts/"
2424
feed: "https://raw.githubusercontent.com/TypesettingTools/ILL-Aegisub-Scripts/main/DependencyControl.json"
2525
}
2626
}
2727
}
2828
Clipper, ILL = depctrl\requireModules!
29-
{:Aegi, :Ass, :Config, :Line, :Curve, :Path, :Point, :Util, :Math, :Table, :Util} = ILL
3029
else
3130
Clipper = require "clipper2.clipper2"
3231
ILL = require "ILL.ILL"
33-
{:Aegi, :Ass, :Config, :Line, :Curve, :Path, :Point, :Util, :Math, :Table, :Util} = ILL
3432

33+
{:Aegi, :Ass, :Config, :Line, :Curve, :Path, :Point, :Util, :Math, :Table, :Util} = ILL
3534
clipboard = require "aegisub.clipboard"
3635

3736
checkPathClockWise = (path) ->
@@ -504,6 +503,23 @@ ShaperyMacrosDialog = (macro) ->
504503
ass\setLine l, s
505504
else
506505
ass\warning s, "Expected a shape"
506+
when "Shape morph"
507+
if l.isShape
508+
if n < 2 or n > 2
509+
ass\error s, "Expected two selected lines"
510+
ass\removeLine l, s
511+
Line.callBackExpand ass, l, nil, (line) ->
512+
{px, py} = line.data.pos
513+
line.shape = Path(line.shape)\move(px, py)\export!
514+
table.insert lines, line
515+
if i == n
516+
a = Path lines[1].shape
517+
b = Path lines[2].shape
518+
Line.callBackFBF ass, lines[1], (line, frame_index, end_frame, j, n) ->
519+
line.shape = a\morph(b, (j - 1) / (n - 1))\export!
520+
ass\insertLine line, s
521+
else
522+
ass\warning s, "Expected a shape"
507523
when "Shape merge"
508524
if l.isShape
509525
{:color1, :color3, :color4, :alpha, :alpha1, :alpha2, :alpha3, :alpha4} = l.data
@@ -536,6 +552,45 @@ ShaperyMacrosDialog = (macro) ->
536552
mergeShapesObj[code] = {:i, pos: l.data.pos, line: lcopy, shape: table.concat clip}
537553
else
538554
ass\warning s, "Expected a shape"
555+
when "Shape blend"
556+
if l.isShape
557+
if n < 2
558+
ass\error s, "Expected one or more selected lines"
559+
Line.callBackExpand ass, l, nil, (line, j) ->
560+
{x, y} = l.data.pos
561+
newPath = Path line.shape
562+
newPath\move x, y
563+
line.tags\remove "move"
564+
line.tags\insert {{"pos", {0, 0}}, true}
565+
line.data.pos = {0, 0}
566+
table.insert mergeShapesObj, {tags: line.tags, path: newPath}
567+
if j == 1 and i == 1
568+
lines.line = Table.copy line
569+
if i == n
570+
ass\deleteLines l, sel
571+
prev = mergeShapesObj[1]
572+
preb = prev.path\boundingBox!
573+
sumw = preb.width
574+
maxh = preb.height
575+
buff = {}
576+
for j = 2, #mergeShapesObj
577+
buff[j] = mergeShapesObj[j].path\boundingBox!
578+
maxh = math.max maxh, buff[j].height
579+
text = prev.tags\get! .. prev.path\move(0, -maxh + preb.height)\export!
580+
for j = 2, #mergeShapesObj
581+
curr = mergeShapesObj[j]
582+
tags = Table.copy curr.tags
583+
tags\difference prev.tags
584+
tags\insert "\\p1"
585+
curr.path\move -sumw, -maxh + buff[j].height
586+
text ..= tags\get! .. curr.path\export!
587+
sumw += buff[j].width
588+
prev = curr
589+
lines.line.text = ILL.Text text
590+
lines.line.isShape = false
591+
ass\insertLine lines.line, s
592+
else
593+
ass\warning s, "Expected a shape"
539594
when "Shape without holes"
540595
if l.isShape
541596
newShape = Path!
@@ -627,13 +682,13 @@ ShaperyMacrosDialog = (macro) ->
627682

628683
if haveDepCtrl
629684
depctrl\registerMacros {
630-
{"Pathfinder", "", PathfinderDialog}
631-
{"Offsetting", "", OffsettingDialog}
632-
{"Manipulate", "", ManipulateDialog}
633-
{"Transform", "", TransformDialog}
634-
{"Utilities", "", UtilitiesDialog}
635-
{"Cut Contour", "", CutContourDialog}
636-
{"Config", "", ConfigDialog}
685+
{"Pathfinder", "", PathfinderDialog}
686+
{"Offsetting", "", OffsettingDialog}
687+
{"Manipulate", "", ManipulateDialog}
688+
{"Transform", "", TransformDialog}
689+
{"Utilities", "", UtilitiesDialog}
690+
{"Cut Contour", "", CutContourDialog}
691+
{"Config", "", ConfigDialog}
637692
}
638693

639694
depctrl\registerMacros {
@@ -643,6 +698,8 @@ if haveDepCtrl
643698
{"Shape to clip", "", ShaperyMacrosDialog "Shape to clip"}
644699
{"Shape to clip (clipboard)", "", ShaperyMacrosDialog "Shape to clip (clipboard)"}
645700
{"Shape merge", "", ShaperyMacrosDialog "Shape merge"}
701+
{"Shape blend", "", ShaperyMacrosDialog "Shape blend"}
702+
{"Shape morph", "", ShaperyMacrosDialog "Shape morph"}
646703
{"Shape trim", "", ShaperyMacrosDialog "Shape trim"}
647704
{"Shape to 0,0", "", ShaperyMacrosDialog "Shape to 0,0"}
648705
{"Shape to pos", "", ShaperyMacrosDialog "Shape to pos"}
@@ -652,20 +709,22 @@ if haveDepCtrl
652709
{"Shape bounding box", "", ShaperyMacrosDialog "Shape bounding box"}
653710
}, ": Shapery macros :"
654711
else
655-
aegisub.register_macro "#{script_name}/Pathfinder", "", PathfinderDialog
656-
aegisub.register_macro "#{script_name}/Offsetting", "", OffsettingDialog
657-
aegisub.register_macro "#{script_name}/Manipulate", "", ManipulateDialog
658-
aegisub.register_macro "#{script_name}/Transform", "", TransformDialog
659-
aegisub.register_macro "#{script_name}/Utilities", "", UtilitiesDialog
660-
aegisub.register_macro "#{script_name}/Cut Contour", "", CutContourDialog
661-
aegisub.register_macro "#{script_name}/Config", "", ConfigDialog
712+
aegisub.register_macro "#{script_name}/Pathfinder", "", PathfinderDialog
713+
aegisub.register_macro "#{script_name}/Offsetting", "", OffsettingDialog
714+
aegisub.register_macro "#{script_name}/Manipulate", "", ManipulateDialog
715+
aegisub.register_macro "#{script_name}/Transform", "", TransformDialog
716+
aegisub.register_macro "#{script_name}/Utilities", "", UtilitiesDialog
717+
aegisub.register_macro "#{script_name}/Cut Contour", "", CutContourDialog
718+
aegisub.register_macro "#{script_name}/Config", "", ConfigDialog
662719

663720
aegisub.register_macro ": Shapery macros :/Shape expand", "", ShaperyMacrosDialog "Shape expand"
664721
aegisub.register_macro ": Shapery macros :/Shape clipper", "", ShaperyMacrosDialog "Shape clipper"
665722
aegisub.register_macro ": Shapery macros :/Clip to shape", "", ShaperyMacrosDialog "Clip to shape"
666723
aegisub.register_macro ": Shapery macros :/Shape to clip", "", ShaperyMacrosDialog "Shape to clip"
667724
aegisub.register_macro ": Shapery macros :/Shape to clip (clipboard)", "", ShaperyMacrosDialog "Shape to clip (clipboard)"
668725
aegisub.register_macro ": Shapery macros :/Shape merge", "", ShaperyMacrosDialog "Shape merge"
726+
aegisub.register_macro ": Shapery macros :/Shape blend", "", ShaperyMacrosDialog "Shape blend"
727+
aegisub.register_macro ": Shapery macros :/Shape morph", "", ShaperyMacrosDialog "Shape morph"
669728
aegisub.register_macro ": Shapery macros :/Shape trim", "", ShaperyMacrosDialog "Shape trim"
670729
aegisub.register_macro ": Shapery macros :/Shape to 0,0", "", ShaperyMacrosDialog "Shape to 0,0"
671730
aegisub.register_macro ": Shapery macros :/Shape to pos", "", ShaperyMacrosDialog "Shape to pos"

modules/ILL/ILL.moon

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module_version = "1.6.4"
1+
module_version = "1.6.5"
22

33
haveDepCtrl, DependencyControl = pcall require, "l0.DependencyControl"
44

@@ -16,7 +16,7 @@ if haveDepCtrl
1616
{"ffi", "json"}
1717
{
1818
"clipper2.clipper2"
19-
version: "1.3.2"
19+
version: "1.4.0"
2020
url: "https://github.com/TypesettingTools/ILL-Aegisub-Scripts/"
2121
feed: "https://raw.githubusercontent.com/TypesettingTools/ILL-Aegisub-Scripts/main/DependencyControl.json"
2222
}

modules/ILL/ILL/Ass/Line.moon

Lines changed: 71 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,10 @@ class Line
107107
.ascent = textMetrics.ascent
108108
.descent = textMetrics.descent
109109
else
110-
textValue = .isShape and "" or .text_stripped
110+
textValue = ""
111+
unless .isShape
112+
textValue = .text_stripped\gsub "\\h", " "
113+
.text_stripped = textValue
111114
textExtents = font\getTextExtents textValue
112115
textMetrics = font\getMetrics!
113116
.width = textExtents.width * video_x_correct_factor
@@ -189,8 +192,8 @@ class Line
189192

190193
line.text_stripped = text
191194
line.tags = tags\clean!
192-
line.text = Text line.tags\__tostring! .. text
193-
line.text.textBlocks[1] = text
195+
line.text = Text line.tags\__tostring! .. line.text_stripped
196+
line.text.textBlocks[1] = line.text_stripped
194197

195198
-- support for the \r tag in line processing
196199
if reset = line.tags\getTag "r"
@@ -343,18 +346,22 @@ class Line
343346
lineTags = lineBreak[j]
344347
lineTagsText = lineTags.text_stripped
345348
lineTagsTags = lineTags.tags\get!
346-
for prevspace, wordText, postspace in lineTagsText\gmatch "(%s*)(.+)(%s*)"
349+
wordText, k = "", 1
350+
while k <= #lineTagsText
351+
s = lineTagsText\sub k, k
352+
if s\match "%s"
353+
wordText = lineTagsText\match "(%s+)", k
354+
k += #wordText
355+
else
356+
wordText = lineTagsText\match "(%S+)", k
357+
k += #wordText
347358
word = Table.copy lineTags
348359
word.tags = Tags lineTagsTags
349360
word.text = Text wordText
350361
word.text.tagsBlocks[1] = Tags lineTagsTags
351362
word.text_stripped = wordText
352363
font = Font word.data
353364
textExtents = font\getTextExtents wordText
354-
prevspace = prevspace\len!
355-
postspace = postspace\len!
356-
spacewidth = font\getTextExtents(" ").width
357-
left += prevspace * spacewidth
358365
word.width = textExtents.width * ass.meta.video_x_correct_factor
359366
word.left = left
360367
word.center = left + word.width * 0.5
@@ -367,7 +374,7 @@ class Line
367374
when 2, 5, 8 then word.center
368375
when 3, 6, 9 then word.right
369376
word.y = lineTags.y
370-
left += word.width + postspace * spacewidth
377+
left += word.width
371378
words.n += 1
372379
words[words.n] = word
373380
left += lineTags.postspace
@@ -383,7 +390,7 @@ class Line
383390
error "You have to extend the line before you get the words", 2
384391

385392
-- splits the text character by character
386-
chars: (ass, l, noblank = true) ->
393+
chars: (ass, l, noblank = false) ->
387394
if l.extended
388395
chars = {n: 0}
389396
for i = 1, l.lines.n
@@ -432,7 +439,7 @@ class Line
432439
error "You have to extend the line before you get the characters", 2
433440

434441
-- splits the text line break by line break
435-
breaks: (ass, l) ->
442+
breaks: (ass, l, noblank = false) ->
436443
if l.extended
437444
lines = {n: 0}
438445
for line in *l.lines
@@ -442,11 +449,10 @@ class Line
442449
newBreakTags = Table.copy line[i].tags
443450
if i > 1
444451
newBreakTags\difference line[i-1].tags
445-
newBreakText ..= newBreakTags\get! .. line[i].text_stripped
452+
newBreakText ..= newBreakTags\get! .. line[i].text.textBlocks[1]
446453
lineBreak.y = math.max line[i].y, lineBreak.y
447454
lineBreak.text = Text newBreakText
448455
lineBreak.tags = Tags lineBreak.text.tagsBlocks[1]\get!
449-
lineBreak.text.tagsBlocks[1] = Tags lineBreak.text.tagsBlocks[1]\get!
450456
lineBreak.text_stripped = newBreakText
451457
left = switch l.data.an
452458
when 1, 4, 7 then l.eff_margin_l
@@ -458,42 +464,36 @@ class Line
458464
when 3, 6, 9 then left + lineBreak.width
459465
lines.n += 1
460466
lines[lines.n] = lineBreak
467+
if noblank
468+
linesNoblank = {n: 0}
469+
for line in *lines
470+
unless Util.isBlank line.text_stripped
471+
linesNoblank.n += 1
472+
linesNoblank[linesNoblank.n] = line
473+
return linesNoblank
461474
return lines
462475
else
463476
error "You have to extend the line before you get the breaks", 2
464477

465478
-- splits the text tags blocks by tags blocks
466-
tags: (ass, l) ->
479+
tags: (ass, l, noblank = false) ->
467480
if l.extended
468481
lines = {n: 0}
469482
for line in *l.lines
470483
for lineTags in *line
471-
unless Util.isBlank lineTags.text_stripped
472-
lines.n += 1
473-
lines[lines.n] = Table.copy lineTags
484+
lines.n += 1
485+
lines[lines.n] = Table.copy lineTags
486+
if noblank
487+
linesNoblank = {n: 0}
488+
for line in *lines
489+
unless Util.isBlank line.text_stripped
490+
linesNoblank.n += 1
491+
linesNoblank[linesNoblank.n] = line
492+
return linesNoblank
474493
return lines
475494
else
476495
error "You have to extend the line before you get the tags", 2
477496

478-
-- callback to map between all possible lines of text
479-
callBackTags: (ass, l, fn) ->
480-
unless l.isShape
481-
{:clip, :isIclip} = l.data
482-
j, isMove = 0, l.tags\existsTag "move"
483-
for lineBreak in *l.lines
484-
for lineBlock in *lineBreak
485-
j += 1
486-
-- gets the new position of the text
487-
lineBlock.data.pos = Line.reallocate l, lineBlock
488-
if isMove
489-
lineBlock.tags\insert {{"move", Line.reallocate l, lineBlock, true}, true}
490-
else
491-
lineBlock.tags\insert {{"pos", lineBlock.data.pos}, true}
492-
-- adds the values \clip or \iclip to all tag blocks
493-
if clip
494-
lineBlock.tags\insert {{isIclip and "iclip" or "clip", clip}}
495-
fn lineBlock, j
496-
497497
-- callback to access the line values frame by frame
498498
callBackFBF: (ass, l, fn) ->
499499
-- gets the line data
@@ -562,6 +562,8 @@ class Line
562562
-- gets the start and end time values in frames
563563
stt_frame = Aegi.ffm start_time
564564
end_frame = Aegi.ffm end_time
565+
j = 0
566+
n = end_frame - stt_frame
565567
-- iterates over all the identified frames
566568
for i = stt_frame, end_frame - 1
567569
s = Aegi.mff i
@@ -572,15 +574,39 @@ class Line
572574
line.start_time = s
573575
line.end_time = e
574576
line.duration = e - s
575-
line.text\callBack (tags, text, j) ->
576-
if j == 1
577-
lerpTagMove f, dado, tags
578-
lerpTagTransform f, dado, tags
579-
lerpTagFade f, dado, tags
580-
return tags, text
581-
if l.isShape
582-
line.tags = line.text.tagsBlocks[1]
583-
fn line, i, end_frame
577+
unless l.isShape
578+
line.text\callBack (tags, text, j) ->
579+
if j == 1
580+
lerpTagMove f, dado, tags
581+
lerpTagTransform f, dado, tags
582+
lerpTagFade f, dado, tags
583+
return tags, text
584+
else
585+
lerpTagMove f, dado, line.tags
586+
lerpTagTransform f, dado, line.tags
587+
lerpTagFade f, dado, line.tags
588+
j += 1
589+
fn line, i, end_frame, j, n
590+
591+
-- callback to map between all possible lines of text
592+
callBackTags: (ass, l, fn) ->
593+
unless l.isShape
594+
{:clip, :isIclip} = l.data
595+
j, isMove = 0, l.tags\existsTag "move"
596+
for lineBreak in *l.lines
597+
for lineBlock in *lineBreak
598+
j += 1
599+
-- gets the new position of the text
600+
lineBlock.text_stripped = lineBlock.text_stripped\gsub "\\h", " "
601+
lineBlock.data.pos = Line.reallocate l, lineBlock
602+
if isMove
603+
lineBlock.tags\insert {{"move", Line.reallocate l, lineBlock, true}, true}
604+
else
605+
lineBlock.tags\insert {{"pos", lineBlock.data.pos}, true}
606+
-- adds the values \clip or \iclip to all tag blocks
607+
if clip
608+
lineBlock.tags\insert {{isIclip and "iclip" or "clip", clip}}
609+
fn lineBlock, j
584610

585611
-- callback to access the shapes
586612
callBackShape: (ass, l, fn) ->

0 commit comments

Comments
 (0)