Hoo-ha! The trick is to build the multi-colored bar ahead of time.
Code:
## Last=YV12
## begin user config section: ######################
## (debugging)
#ShowFrameNumber(x=30, y=30)
#ShowTime(x=80, y=50)
#return Last
## progress bar placement
global barhgt = 16 ## bar height (not tested at other heights)
global lftpad = 16 ## left pad
global rgtpad = 80 ## right pad
global botpad = 16 ## bottom pad
## colors etc
global outlclr = color_black ## outline color
global outlopc = 0.75 ## outline opacity (should be >= progress bar opacity)
global outlwid = 3 ## outline width (0 for no outline)
global progopc = 0.5 ## progress bar opacity
global txtclr = transparent_color(0.75, color_khaki) ## progress text color
## EDITING:
## scenes must be assigned clip var's
C1=Trim(150,350+30)
C2=Trim(900,1100+30)
C3=Trim(1350,1700)
## - assign each scene a color
## preset color chooser: see
## http://avisynth.nl/index.php?title=Color_presets
##
global gF = StackHorizontal(
\ BlankClip(Last, length=1, pixel_type="RGB32",
\ width=C1.FrameCount, color=color_khaki),
\ BlankClip(Last, length=1, pixel_type="RGB32",
\ width=C2.FrameCount, color=color_indianred),
\ BlankClip(Last, length=1, pixel_type="RGB32",
\ width=C3.FrameCount, color=color_khaki)
\ ).BilinearResize(Width-(lftpad+rgtpad), Height).ConvertToYV12
\ .AddBorders(lftpad, 0, rgtpad, 0)
\ .Loop(-1).Trim(0, -FrameCount)
## (you may want to save this as a still image and enhance in a paint program)
#return gF
## assembled timeline
C1.Dissolve(C2, 30).Dissolve(C3, 30)
#return Last
## /end user config section ########################
## progress bar master rectangle
global ox1 = lftpad
global ox2 = Width - rgtpad
global oy1 = Height - (barhgt+botpad)
global oy2 = oy1 + barhgt
## do it!
return ProgressBar3
##################################
### create a multicolored progress bar that is slowly revealed as video plays
##
function ProgressBar3(clip C)
{
## filled progress bar + fixed readout
Animate(C, 1, C.FrameCount, "simple_box_3",
\ gF, 1.0,
\ gF, ox2-ox1)
## outline
Last = (outlopc<=0.0 || outlwid<1) ? Last
\ : BoxMaskOverlay(
\ ox1, oy1, ox2, oy2,
\ color=outlclr, opacity=outlopc,
\ outline_width=outlwid, maskblur=0.5)
return Last
}
##################################
### video clip as progress bar + fixed readout
##
function simple_box_3(clip C, clip F, float "wid")
{
## progress bar
bx1 = ox1 + 1
bx2 = bx1 + Round(wid)
by1 = oy1 + 1
by2 = by1 + barhgt - 2
## progress readout
progress = wid/(C.width-(lftpad+rgtpad))*100
return C.BoxMaskOverlay(
\ bx1, by1, bx2, by2,
\ outline_width=0, over=F,
\ opacity=progopc, maskblur=0.3+Abs(wid-Round(wid)))
\ .Subtitle(String(progress, "%0.2f")+"%",
\ x=ox2+8, y=by1-1, size=barhgt-1, text_color=txtclr)
}
##################################
### DrawBox mask
##
## @ x1, y1 - left, top of rectangle mask
## @ x2, y2 - right, bottom of rectangle mask
## @ wid, hgt - width, height of rectangle mask; x2, y2 have priority
## @ outline_width - if zero (default), draw a filled rectangle; else draw outline
## @ preclear - if true (default), start with a pure white (opaque) clip,
## else keep C inside rect & set to black outside
##
function BoxMask3(clip C,
\ int "x1", int "y1", int "x2", int "y2",
\ int "wid", int "hgt", float "outline_width",
\ bool "preclear")
{
preclear = Default(preclear, true)
w = C.Width
h = C.Height
x1 = Default(x1, 0)
y1 = Default(y1, 0)
x2 = Default(x2, x1+Default(wid, w))
y2 = Default(y2, y1+Default(hgt, h))
o = Default(outline_width, 0.0)
o = 0.1 * Round(10.0 * Default(outline_width, 0.0))
o2 = o / 2.0
C = (preclear==false) ? C.ConvertToY8
\ : BlankClip(C.ConvertToY8, color=$ffffff)
## arg validation v2:
x1 = Min(Max( 0 , x1 ), C.Width-2)
x2 = Min(Max(x1+1, x2 ), C.Width-1)
y1 = Min(Max( 0 , y1 ), C.Height-2)
y2 = Min(Max(y1+1, y2 ), C.Height-1)
## letterbox args:
llft = x1
ltop = y1
lrgt = Min(Max( 0, w-x2 ), C.Width-(llft+1))
lbot = Min(Max( 0, h-y2 ), C.Height-(ltop+1))
return (o>0.0)
\ ? C.BoxMask3(x1+Ceil(o2), y1+Ceil(o2), x2-Floor(o2), y2-Floor(o2)).Invert
\ .BoxMask3(x1-Floor(o2), y1-Floor(o2), x2+Ceil(o2), y2+Ceil(o2), preclear=false)
\ : C.Letterbox(ltop, lbot, llft, lrgt, color=$0).ColorYUV(levels="TV->PC")
}
#######################################
### overlay a clip or solid color using BoxMask3
##
## @ x1, y1 - left, top of rectangle mask
## @ x2, y2 - right, bottom of rectangle mask
## @ wid, hgt - width, height of rectangle mask; x2, y2 have priority
## @ outline_width - if zero, draw a filled rectangle; else draw outline
## @ over - if supplied, use for overlay fill, overriding "color"
## @ color - default black
## @ mode, opacity - cf. Overlay
## @ maskblur - mask blur
##
function BoxMaskOverlay(clip C,
\ int "x1", int "y1", int "x2", int "y2",
\ int "wid", int "hgt", int "outline_width",
\ clip "over", int "color",
\ string "mode", float "opacity", float "maskblur")
{
color = Default(color, $0)
mode = Default(mode, "blend")
opacity = Float(Min(Max(0, Default(opacity, 1)), 1))
a_blur = Default(maskblur, 0.0)
w = C.Width
h = C.Height
x1 = Default(x1, 0)
y1 = Default(y1, 0)
x2 = Default(x2, x1+Default(wid, w))
y2 = Default(y2, y1+Default(hgt, h))
o = Min(Default(outline_width, 0), w/8)
over = (IsClip(over) && over.Width==C.Width && over.Height==C.Height)
\ ? over.AssumeFPS(C).Loop
\ : BlankClip(C, color=color)
return (opacity<0.001) ? C
\ : C.Overlay(over,
\ mask=C.BoxMask3(x1, y1, x2, y2, outline_width=o, preclear=true)
\ .Blur(a_blur),
\ mode=mode,
\ opacity=opacity)
}
#######################################
## given Avisynth color, set its transparency
## @ a - 0.0 = transparent, 1.0 = opaque.
##
function transparent_color(float a, int color) {
a = 255 - Min(Max(0, Round(a * 256.0)), 255)
return BitOr(a*$1000000, BitAnd(color, $00ffffff))
}
__END__