[CLX] Library Motion - Examples
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © cryptolinx

//@version=5
indicator('[CLX] Motion - Examples', overlay = true)

import cryptolinx/Motion/11 as motion

// var table exTable = table.new(position=position.middle_center, columns=1, rows=4, border_width=1)

// varip kf_0 = m.keyframe.new(intv = 1, steps = 2)
// string content_0 = m.marquee(kf_0, 'marquee', _ws = 10)
// table.cell(exTable, 0, 0,  kf_0.output, width = 50, text_color = color.white, bgcolor = color.maroon)

// varip kf_1 = m.keyframe.new(intv = 1), m.blink(kf_1, 'blink')
// table.cell(exTable, 0, 1,  kf_1.output, width = 50, text_color = color.white, bgcolor = color.blue)

// varip kf_2 = m.keyframe.new(intv = 1), m.slideInLeft(kf_2, 'slide in left')
// table.cell(exTable, 0, 2,  kf_2.output, width = 50, text_color = color.white, bgcolor = color.orange)

// varip kf_3 = m.keyframe.new(intv = 1), m.slideInRight(kf_3, 'slide in right')
// table.cell(exTable, 0, 3,  kf_3.output, width = 50, text_color = color.white, bgcolor = color.aqua)


// ------------------------------------------------------------------------------------------------


/// ———— User Input {
//
// ⚠️ IMPORTANT: Example Type. NOT REQUIRED.
//
type user_input
    // --
    string fx
    bool play
    string timing
    int intv
    int mu
    int step
    bool reset
    int max_loops
    int sub_start
    int sub_length
    bool ltr
    bool refill
    string prefix
    string txt
    int ws
    string suffix
    int color_steps
    bool color_cycle
    color color_from
    color color_to
    string mode_start
    int mode_calc
// --
var __settings = user_input.new(
 fx = input.string('marquee', 'Transition', options = ['marquee', 'blink', 'blend_in_right', 'blend_out_right', 'blend_in_left', 'blend_out_left', 'slide_in_left', 'slide_in_right', 'slide_out_left', 'slide_out_right'], group = 'ACTION'),
 play = input.bool(true, 'Play', group = 'ACTION'),
 timing = input.string('on_time', 'Event Producer', options = ['on_tick', 'on_time', 'on_index'], group = 'TIMING'),
 intv = input.int(1, title = 'Interval (Δt)', step = 1, minval = 1, maxval = 100, tooltip = 'Delta Time [1;∞[', group = 'TIMING'),
 mu = input.int(1000, title = 'onTime - Fineness (μ)', step = 50, minval = 50, maxval = 2000, tooltip = '[50-2000] 1000 = default. lower value = higher freq.', group = 'TIMING'),
 step = input.int(1, title = 'Steps Per Execution', step = 1, minval = 1, maxval = 20, group = 'PREFERENCES'),
 reset = input.bool(false, title = 'Reset On Every Bar', group = 'PREFERENCES'),
 max_loops = input.int(0, title = 'Max. Loops', step = 1, minval = 0, maxval = 100, tooltip = '0 = infinite', group = 'PREFERENCES'),
 sub_start = input.int(0, title = 'Subsequence Start', step = 1, minval = 0, maxval = 20, tooltip = '[ABCDEF]GHI...\n|      |\n0     5', group = 'PREFERENCES'),
 sub_length = input.int(0, title = 'Subsequence Length', step = 1, minval = 0, maxval = 20, group = 'PREFERENCES'),
 refill = input.bool(true, 'Placeholder String', group = 'PREFERENCES', tooltip = 'true = default; false = slide effect without placeholder (+/- string length)'),
 ltr = input.bool(false, title = 'Left To Right', group = 'ONLY MARQUEE'),
 prefix = input.string('', 'Prefix', group = 'CONTENT'),
 txt = input.string('ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789', 'Text', group = 'CONTENT'),
 ws = input.int(0, title = 'Trailing White Space', step = 1, minval = 0, maxval = 10, group = 'CONTENT'),
 suffix = input.string('', 'Suffix', group = 'CONTENT'),
 color_steps = input.int(6, title = 'Gradient Steps', step = 1, minval = 1, maxval = 20, group = 'COLOR'),
 color_cycle = input.bool(true, title = 'Color Cycle', group = 'COLOR'),
 color_from = input.color(color.rgb(0, 57, 212), 'Color From', group = 'COLOR'),
 color_to = input.color(color.rgb(59, 209, 255), 'Color To', group = 'COLOR'),
 mode_start = 'now', // input.string('now', 'Effect Start', options = ['now', 'on_open', 'on_close'], group = 'ADVANCED/DEVELOPMENT'),
 mode_calc = 1) // input.int(1, 'Calculation Mode', minval  = 0, maxval = 1, step = 1, tooltip = '0 = relative; 1 = absolute', group = 'ADVANCED/DEVELOPMENT'))
// }

// ———— Motion 🪄 {
//
// ⚠️ IMPORTANT:  The keyframe object must be created by using the `varip` keyword. 
//
varip transitionKf = motion.keyframe.new(intv = __settings.intv, steps = __settings.step, execution = __settings.play) // create keyframe
string transitionString = motion.transition(transitionKf, _seq = __settings.txt, _fx = __settings.fx, _ws = __settings.ws, _maxLoops = __settings.max_loops,
 _subLen = __settings.sub_length, _subStart = __settings.sub_start, _ltr = __settings.ltr, _resetOnEveryBar = __settings.reset, _autoplay = __settings.play,
 _refill = __settings.refill, _timerType = __settings.timing, _timerMu = __settings.mu, _timerMode = __settings.mode_calc, _prefix = __settings.prefix, _suffix = __settings.suffix)
// --
varip iterationKf = motion.keyframe.new(intv = 3, steps = __settings.step, execution = __settings.play)
motion.iteration(iterationKf, _seqArr = array.from('THIS','IS','AN','ITERATION','EFFECT!'), _ws = __settings.ws,
 _subLen = __settings.sub_length, _subStart = __settings.sub_start, _ltr = __settings.ltr, _resetOnEveryBar = __settings.reset, _autoplay = false, //__settings.play,
 _refill = __settings.refill, _timerType = __settings.timing, _timerMu = __settings.mu, _timerMode = __settings.mode_calc, _prefix = __settings.prefix, _suffix = __settings.suffix)
// --
varip colorKf = motion.keyframe.new(intv = __settings.intv, steps = __settings.step, execution = __settings.play)
color gradient = motion.color_gradient(colorKf, __settings.color_from, __settings.color_to, _steps = __settings.color_steps, _cycle = __settings.color_cycle, _timerType = __settings.timing)
// }

// ———— Label {
//
var select = label.new(bar_index, 750, text = 'Double click, to select a transition effect from input:', textcolor = color.white, color = #ffffff0b, size = size.normal, style = label.style_label_center)
var fx = label.new(bar_index, 700, text = __settings.fx, textcolor = #AAFF00, color = #ffffff0b, size = size.normal, style = label.style_label_center, textalign = text.align_center, text_font_family = font.family_default)
var openSource = label.new(bar_index, 300, text = 'open 💙 source', textcolor = color.white, color = #ffffff0b, size = size.normal, style = label.style_label_center)
var example = label.new(bar_index, 600, text = '', textcolor = color.white, color = #ffffff0b, size = size.huge, style = label.style_label_center, textalign = text.align_center, text_font_family = font.family_monospace)
var itr = label.new(bar_index, 450, text = '', textcolor = color.white, color = #ffffff0b, size = size.normal, style = label.style_label_center, textalign = text.align_center, text_font_family = font.family_monospace)
// --
label.set_x(select, bar_index), label.set_x(fx, bar_index), label.set_x(example, bar_index), label.set_x(openSource, bar_index), label.set_x(itr, bar_index),
label.set_text(fx, __settings.fx), label.set_text(example, transitionString), label.set_text(itr, iterationKf.output)
label.set_textcolor(itr, gradient)
// }


// ------------------------------------------------------------------------------------------------

// ———— Simple Animated Logo/Tag Idea {
//
renderLogo(string _tagline, string _sizeLogo = size.huge, string _sizeTag = size.normal, color _colorLogo = #ff5252, color _colorTag = #ffffff96, _colorDecor = #ff525234, int _x = bar_index, float _y = 1000) =>
    // >>
    array.from(
     label.new(_x, _y, text = '', size = _sizeLogo, color = #00000000, textcolor = _colorLogo, text_font_family = font.family_default, style = label.style_label_center, textalign = text.align_center),
     label.new(_x, _y, text = '└', size = _sizeLogo, color = #00000000, textcolor = _colorDecor, text_font_family = font.family_default, style = label.style_label_upper_right, textalign = text.align_left),
     label.new(_x, _y, text = '┘', size = _sizeLogo, color = #00000000, textcolor = _colorDecor, text_font_family = font.family_default, style = label.style_label_upper_left, textalign = text.align_left),
     label.new(_x, _y, text = '┌', size = _sizeLogo, color = #00000000, textcolor = _colorDecor, text_font_family = font.family_default, style = label.style_label_lower_right, textalign = text.align_left),
     label.new(_x, _y, text = '┐', size = _sizeLogo, color = #00000000, textcolor = _colorDecor, text_font_family = font.family_default, style = label.style_label_lower_left, textalign = text.align_left),
     label.new(_x, _y, text = ' ', size = _sizeLogo, color = #00000000, textcolor = color.new(_colorLogo, 75), text_font_family = font.family_default, style = label.style_label_down, textalign = text.align_left),
     label.new(_x, _y, text = '\n\n\n\n' + _tagline, size = _sizeTag, color = #00000000, textcolor = _colorTag, text_font_family = font.family_monospace, style = label.style_label_up, textalign = text.align_left))
// }

// ———— Update Logo {
//
update(array <label> _logo, string _textLogo, string _textTagline, int _x = bar_index, float _y = 1000) =>
    // --
    if barstate.islast
        for i = 0 to array.size(_logo) - 1
            label.set_xy(array.get(_logo, i), _x, _y)
        label.set_text(array.get(_logo, 0), _textLogo)
        label.set_text(array.get(_logo, 6), _textTagline)
    // >>
    // void
// }

// ———— Motion 🪄 {
//
varip logoKf = motion.keyframe.new(1, 7)
string marquee = motion.transition(logoKf, _fx = 'marquee', _seq = 'M◞TION.M◟TION.M◜TION.M◝TION.', _subLen = 7)
varip taglineKf = motion.keyframe.new(4, 1)
motion.iteration(taglineKf, _seqArr = array.from('Showcase','Library'), _refill = true)
// --
var array <label> LOGO = renderLogo('- A Pine Script™ Showcase -', size.huge)
update(LOGO, marquee, '\n\n\n\n' + '- A Pine Script™ ' + taglineKf.output + ' -')
// }

// # EOF