Exemplo n.º 1
0
def _get_render_with_legend(cfg, fields, area, title, block_definition, color_definition, block_fields, color_fields, layout):
    title_h = 1 / 10.

    ax, ay, aw, ah = area
    title_node = ngl.Text(
        title,
        box_corner=(ax, ay + ah - title_h, 0),
        box_width=(aw, 0, 0),
        box_height=(0, title_h, 0),
        fg_color=(0, 0, 0, 1),
        bg_color=(1, 1, 1, 1),
        aspect_ratio=cfg.aspect_ratio,
    )

    text_group = ngl.Group()
    nb_fields = len(fields)
    field_h = (ah - title_h) / float(nb_fields)
    for i, field in enumerate(fields):
        field_hpos = nb_fields - i - 1
        text_node = ngl.Text('#%02d %s' % (field['pos'], field['name']),
                             box_corner=(ax, ay + field_hpos * field_h, 0),
                             box_width=(aw / 2., 0, 0),
                             box_height=(0, field_h, 0),
                             fg_color=list(field['color']) + [1],
                             halign='left',
                             aspect_ratio=cfg.aspect_ratio)
        text_group.add_children(text_node)

    quad = ngl.Quad((ax + aw / 2., ay, 0), (aw / 2., 0, 0), (0, ah - title_h, 0))
    render = get_render(cfg, quad, fields, block_definition, color_definition, block_fields, color_fields, layout)

    return ngl.Group(children=(title_node, text_group, render))
Exemplo n.º 2
0
def parallel_playback(cfg,
                      fast=True,
                      segment_time=2.0,
                      constrained_timeranges=False):
    """
    Parallel media playback, flipping between the two sources.

    The fast version makes sure the textures continue to be updated even though
    they are not displayed. On the other hand, the slow version will update the
    textures only when needed to be displayed, causing potential seek in the
    underlying media, and thus undesired delays.
    """
    m1 = ngl.Media(cfg.medias[0].filename, label="media #1")
    m2 = ngl.Media(cfg.medias[0].filename, label="media #2")

    t1 = ngl.Texture2D(data_src=m1, label="texture #1")
    t2 = ngl.Texture2D(data_src=m2, label="texture #2")

    render1 = ngl.RenderTexture(t1)
    render2 = ngl.RenderTexture(t2)

    text_settings = {
        "box_corner": (-1, 1 - 0.2, 0),
        "box_height": (0, 0.2, 0),
        "aspect_ratio": cfg.aspect_ratio,
    }
    render1 = ngl.Group(children=(render1,
                                  ngl.Text("media #1", **text_settings)))
    render2 = ngl.Group(children=(render2,
                                  ngl.Text("media #2", **text_settings)))

    rf1 = ngl.TimeRangeFilter(render1)
    rf2 = ngl.TimeRangeFilter(render2)

    if constrained_timeranges:
        rf1.set_prefetch_time(segment_time / 3.0)
        rf2.set_prefetch_time(segment_time / 3.0)
        rf1.set_max_idle_time(segment_time / 2.0)
        rf2.set_max_idle_time(segment_time / 2.0)

    t = 0
    rr1 = []
    rr2 = []
    while t < cfg.duration:
        rr1.append(ngl.TimeRangeModeCont(t))
        rr1.append(ngl.TimeRangeModeNoop(t + segment_time))

        rr2.append(ngl.TimeRangeModeNoop(t))
        rr2.append(ngl.TimeRangeModeCont(t + segment_time))

        t += 2 * segment_time

    rf1.add_ranges(*rr1)
    rf2.add_ranges(*rr2)

    g = ngl.Group()
    g.add_children(rf1, rf2)
    if fast:
        g.add_children(t1, t2)
    return g
Exemplo n.º 3
0
def debug_block(cfg, seed=0, layout=LAYOUTS[0], color_tint=True):
    cfg.duration = ANIM_DURATION
    cfg.aspect_ratio = (1, 1)

    spec = _get_data_spec(layout)

    fields_info, block_fields, color_fields, block_definition, color_definition = get_random_block_info(spec, seed, layout, color_tint=color_tint)

    fields_single   = [f for f in fields_info if f['category'] == 'single']
    fields_array    = [f for f in fields_info if f['category'] == 'array']
    fields_animated = [f for f in fields_info if f['category'].startswith('animated')]
    field_specs = (
        (fields_single,   (-1/3., -1, 2/3., 2.), 'Single fields'),
        (fields_array,    ( 1/3.,  0, 2/3., 1.), 'Arrays'),
        (fields_animated, ( 1/3., -1, 2/3., 1.), 'Animated'),
    )

    g = ngl.Group()
    block_def_text = ngl.Text(
        f'{layout}:\n\n{block_definition}',
        valign='top',
        box_corner=(-1, -1, 0),
        box_width=(2/3., 0, 0),
        box_height=(0, 2, 0),
        aspect_ratio=cfg.aspect_ratio,
    )
    g.add_children(block_def_text)

    for cat_fields, area, title in field_specs:
        visual_fields = _get_render_with_legend(cfg, cat_fields, area, title, block_definition, color_definition, block_fields, color_fields, layout)
        g.add_children(visual_fields)
    return g
Exemplo n.º 4
0
def api_text_live_change(width=320, height=240):
    import zlib

    ctx = ngl.Context()
    capture_buffer = bytearray(width * height * 4)
    ret = ctx.configure(offscreen=1, width=width, height=height, backend=_backend, capture_buffer=capture_buffer)
    assert ret == 0

    # An empty string forces the text node to deal with a pipeline with nul
    # attributes, this is what we exercise here, along with a varying up and
    # down number of characters
    text_strings = ["foo", "", "foobar", "world", "hello\nworld", "\n\n", "last"]

    # Exercise the diamond-form/prepare mechanism
    text_node = ngl.Text()
    assert ctx.set_scene(autogrid_simple([text_node] * 4)) == 0

    ctx.draw(0)
    last_crc = zlib.crc32(capture_buffer)
    for i, s in enumerate(text_strings, 1):
        text_node.set_text(s)
        ctx.draw(i)
        crc = zlib.crc32(capture_buffer)
        assert crc != last_crc
        last_crc = crc
Exemplo n.º 5
0
def get_debug_points(cfg,
                     points,
                     radius=0.025,
                     color=COLORS['green'],
                     text_size=(0.1, 0.1)):
    prog = ngl.Program(vertex=cfg.get_vert('color'),
                       fragment=cfg.get_frag('color'))
    g = ngl.Group()
    circle = ngl.Circle(radius=radius)
    circle_render = ngl.Render(circle, prog)
    circle_render.update_uniforms(color=ngl.UniformVec4(value=color))
    box_w = (text_size[0], 0, 0)
    box_h = (0, text_size[1], 0)
    for pos_name, position in points.items():
        text = ngl.Text(pos_name,
                        box_width=box_w,
                        box_height=box_h,
                        bg_color=(0, 0, 0, 0),
                        valign='top')
        text = ngl.Translate(text, (1 + radius, 1 - radius - text_size[1], 0))
        point = ngl.Group(children=(circle_render, text))
        point = ngl.Translate(point, list(position) + [0])
        g.add_children(point)
    return ngl.GraphicConfig(g,
                             blend=True,
                             blend_src_factor='src_alpha',
                             blend_dst_factor='one_minus_src_alpha',
                             blend_src_factor_a='zero',
                             blend_dst_factor_a='one',
                             label='Debug circles')
Exemplo n.º 6
0
def text(
    cfg,
    txt="the quick brown fox\njumps over the lazy dog",
    fg_color=COLORS.cgreen,
    bg_color=(0.3, 0.3, 0.3),
    box_corner=(-1 + 0.25, -1 + 0.25, 0),
    box_width=(1.5, 0, 0),
    box_height=(0, 1.5, 0),
    padding=2,
    font_scale=1.3,
    valign="center",
    halign="center",
):
    return ngl.Text(
        txt,
        fg_color=fg_color,
        bg_color=bg_color,
        box_corner=box_corner,
        box_width=box_width,
        box_height=box_height,
        padding=padding,
        font_scale=font_scale,
        valign=valign,
        halign=halign,
        aspect_ratio=cfg.aspect_ratio,
    )
Exemplo n.º 7
0
def text_0_to_127(cfg):
    s = ""
    for y in range(8):
        for x in range(16):
            c = y << 4 | x
            s += chr(c) if c else " "
        s += "\n"
    return ngl.Text(s)
Exemplo n.º 8
0
def text_0_to_127(cfg):
    s = ''
    for y in range(8):
        for x in range(16):
            c = y << 4 | x
            s += chr(c) if c else ' '
        s += '\n'
    return ngl.Text(s)
Exemplo n.º 9
0
def text(cfg,
         demo_str='Hello World!\n\nThis is a multi-line\ntext demonstration.',
         time_unit=0.05):
    '''Demonstrate the text node features (colors, scale, alignment, fitting, ...)'''

    random.seed(0)

    group = ngl.Group()

    cfg.duration = time_unit * 2 * len(demo_str)

    nb_chars = len(demo_str)
    for i in range(nb_chars):
        ascii_text = ngl.Text(demo_str[:i + 1],
                              aspect_ratio=cfg.aspect_ratio,
                              bg_color=(0.15, 0.15, 0.15, 1),
                              font_scale=1 / 2.)
        start = i * time_unit
        text_range = [ngl.TimeRangeModeNoop(0), ngl.TimeRangeModeCont(start)]
        if i != nb_chars - 1:
            end = (i + 1) * time_unit
            text_range.append(ngl.TimeRangeModeNoop(end))
        text_range_filter = ngl.TimeRangeFilter(ascii_text, ranges=text_range)
        group.add_children(text_range_filter)

    for valign in ('top', 'center', 'bottom'):
        for halign in ('left', 'center', 'right'):
            if (valign, halign) == ('center', 'center'):
                continue
            fg_color = list(colorsys.hls_to_rgb(random.uniform(0, 1), 0.5,
                                                1.0)) + [1]
            aligned_text = ngl.Text('%s-%s' % (valign, halign),
                                    valign=valign,
                                    halign=halign,
                                    aspect_ratio=cfg.aspect_ratio,
                                    fg_color=fg_color,
                                    bg_color=(0, 0, 0, 0),
                                    font_scale=1 / 5.)
            group.add_children(aligned_text)

    return ngl.GraphicConfig(group,
                             blend=True,
                             blend_src_factor='src_alpha',
                             blend_dst_factor='one_minus_src_alpha',
                             blend_src_factor_a='zero',
                             blend_dst_factor_a='one')
Exemplo n.º 10
0
def text(cfg,
         demo_str="Hello World!\n\nThis is a multi-line\ntext demonstration.",
         time_unit=0.05):
    """Demonstrate the text node features (colors, scale, alignment, fitting, ...)"""

    group = ngl.Group()

    cfg.duration = time_unit * 2 * len(demo_str)

    nb_chars = len(demo_str)
    for i in range(nb_chars):
        ascii_text = ngl.Text(
            demo_str[:i + 1],
            aspect_ratio=cfg.aspect_ratio,
            bg_color=(0.15, 0.15, 0.15),
            bg_opacity=1,
            font_scale=1 / 2.0,
        )
        start = i * time_unit
        text_range = [ngl.TimeRangeModeNoop(0), ngl.TimeRangeModeCont(start)]
        if i != nb_chars - 1:
            end = (i + 1) * time_unit
            text_range.append(ngl.TimeRangeModeNoop(end))
        text_range_filter = ngl.TimeRangeFilter(ascii_text, ranges=text_range)
        group.add_children(text_range_filter)

    for valign in ("top", "center", "bottom"):
        for halign in ("left", "center", "right"):
            if (valign, halign) == ("center", "center"):
                continue
            fg_color = colorsys.hls_to_rgb(cfg.rng.uniform(0, 1), 0.5, 1.0)
            aligned_text = ngl.Text(
                f"{valign}-{halign}",
                valign=valign,
                halign=halign,
                aspect_ratio=cfg.aspect_ratio,
                fg_color=fg_color,
                bg_opacity=0,
                font_scale=1 / 5.0,
            )
            group.add_children(aligned_text)

    return group
Exemplo n.º 11
0
def _get_compositing_scene(cfg, op, show_label=False):
    cfg.aspect_ratio = (1, 1)
    cfg.duration = 6

    # We can not use a circle geometry because the whole areas must be
    # rasterized for the compositing to work, so instead we build 2 overlapping
    # quad into which we draw colored circles, offsetted with an animation.
    # Alternatively, we could use a RTT.
    quad = ngl.Quad(corner=(-1, -1, 0), width=(2, 0, 0), height=(0, 2, 0))
    prog = ngl.Program(vertex=_VERTEX, fragment=_FRAGMENT)
    prog.update_vert_out_vars(uv=ngl.IOVec2())

    A_off_kf = (
        ngl.AnimKeyFrameVec2(0, (-1 / 3, 0)),
        ngl.AnimKeyFrameVec2(cfg.duration / 2, (1 / 3, 0)),
        ngl.AnimKeyFrameVec2(cfg.duration, (-1 / 3, 0)),
    )
    B_off_kf = (
        ngl.AnimKeyFrameVec2(0, (1 / 3, 0)),
        ngl.AnimKeyFrameVec2(cfg.duration / 2, (-1 / 3, 0)),
        ngl.AnimKeyFrameVec2(cfg.duration, (1 / 3, 0)),
    )
    A_off = ngl.AnimatedVec2(A_off_kf)
    B_off = ngl.AnimatedVec2(B_off_kf)

    A = ngl.Render(quad, prog, label="A")
    A.update_frag_resources(color=ngl.UniformVec3(value=COLORS.azure),
                            off=A_off)

    B = ngl.Render(quad, prog, label="B", blending=op)
    B.update_frag_resources(color=ngl.UniformVec3(value=COLORS.orange),
                            off=B_off)

    bg = ngl.RenderColor(blending="dst_over")

    # draw A in current FBO, then draw B with the current operator, and
    # then result goes over the white background
    ret = ngl.Group(children=(A, B, bg))

    if show_label:
        label_h = 1 / 4
        label_pad = 0.1
        label = ngl.Text(
            op,
            fg_color=COLORS.black,
            bg_color=(0.8, 0.8, 0.8),
            bg_opacity=1,
            box_corner=(label_pad / 2 - 1, 1 - label_h - label_pad / 2, 0),
            box_width=(2 - label_pad, 0, 0),
            box_height=(0, label_h, 0),
        )
        ret.add_children(label)

    return ret
Exemplo n.º 12
0
def _debug_overlay(cfg,
                   scene,
                   grid_names,
                   show_dbg_points=False,
                   show_labels=False):
    if not show_dbg_points and not show_labels:
        return scene

    assert grid_names is not None

    text_height = 0.25

    overlay = ngl.Group()

    if show_labels:
        text_group = ngl.Group()
        ag = AutoGrid(grid_names)
        for grid_name, _, col, row in ag:
            text = ngl.Text(
                grid_name,
                fg_color=COLORS.white,
                bg_opacity=1,
                valign="top",
                box_width=(2.0, 0, 0),
                box_height=(0, text_height, 0),
                box_corner=(-1, 1.0 - text_height, 0),
            )
            text = ag.place_node(text, (col, row))
            text_group.add_children(text)

        scene = ngl.Translate(scene, (0, -text_height / 2.0 * ag.scale, 0),
                              label="text offsetting")
        overlay.add_children(scene, text_group)
    else:
        overlay.add_children(scene)

    if show_dbg_points:
        nb = len(grid_names)
        dbg_positions = _get_dbg_positions(nb)
        if show_labels:
            dbg_positions = {
                name: (p[0], p[1] - text_height / 2.0 * ag.scale)
                for name, p in dbg_positions.items()
            }
        dbg_points = get_debug_points(cfg,
                                      dbg_positions,
                                      radius=0.01,
                                      text_size=(0.08, 0.08))

        overlay.add_children(dbg_points)

    return overlay
def _get_random_text(cfg, rng):
    words = """
        Broccoli Cabbage Mushroom Cucumber Kombu Potato Celery Lettuce Garlic
        Pumpkin Leek Bulbasaur Monkey Goose Axolotl Capybara Wombat Kakapo
        Yip-yip! Nyaa~ Oulala Hehehe Puni-puni Tutuluu~ Gaoo~ Unchi! Maho?
    """
    return ngl.Text(
        box_width=(1, 0, 0),
        box_height=(0, 1, 0),
        box_corner=(-0.5, -0.5, 0),
        text=rng.choice(words.split()),
        fg_color=_get_random_color(rng),
        fg_opacity=_get_random_opacity(rng),
        bg_opacity=0,
    )
def get_debug_points(cfg,
                     points,
                     radius=0.025,
                     color=COLORS.green,
                     text_size=(0.1, 0.1)):
    g = ngl.Group(label="Debug circles")
    circle = ngl.Circle(radius=radius)
    circle_render = ngl.RenderColor(color, geometry=circle)
    box_w = (text_size[0], 0, 0)
    box_h = (0, text_size[1], 0)
    for pos_name, position in points.items():
        text = ngl.Text(pos_name,
                        box_width=box_w,
                        box_height=box_h,
                        bg_opacity=0,
                        valign="top")
        text = ngl.Translate(text, (1 + radius, 1 - radius - text_size[1], 0))
        point = ngl.Group(children=(circle_render, text))
        point = ngl.Translate(point, list(position) + [0])
        g.add_children(point)
    return g
Exemplo n.º 15
0
def time_remapping(cfg):
    '''
    Time remapping in the following order:
    - nothing displayed for a while (but media prefetch happening in background)
    - first frame displayed for a while
    - normal playback
    - last frame displayed for a while (even though the media is closed)
    - nothing again until the end
    '''
    m0 = cfg.medias[0]

    media_seek = 10
    noop_duration = 2
    prefetch_duration = 2
    freeze_duration = 3
    playback_duration = 5

    range_start = noop_duration + prefetch_duration
    play_start = range_start + freeze_duration
    play_stop = play_start + playback_duration
    range_stop = play_stop + freeze_duration
    duration = range_stop + noop_duration

    cfg.duration = duration
    cfg.aspect_ratio = (m0.width, m0.height)

    media_animkf = [
        ngl.AnimKeyFrameFloat(play_start, media_seek),
        ngl.AnimKeyFrameFloat(play_stop, media_seek + playback_duration),
    ]

    q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0))
    m = ngl.Media(m0.filename, time_anim=ngl.AnimatedTime(media_animkf))
    m.set_sxplayer_min_level('verbose')
    t = ngl.Texture2D(data_src=m)
    p = ngl.Program(vertex=cfg.get_vert('texture'),
                    fragment=cfg.get_frag('texture'))
    p.update_vert_out_vars(var_tex0_coord=ngl.IOVec2(),
                           var_uvcoord=ngl.IOVec2())
    r = ngl.Render(q, p)
    r.update_frag_resources(tex0=t)

    time_ranges = [
        ngl.TimeRangeModeNoop(0),
        ngl.TimeRangeModeCont(range_start),
        ngl.TimeRangeModeNoop(range_stop),
    ]
    rf = ngl.TimeRangeFilter(r,
                             ranges=time_ranges,
                             prefetch_time=prefetch_duration)

    base_string = 'media time: %2g to %2g\nscene time: %2g to %2g\ntime range: %2g to %2g' % (
        media_seek, media_seek + playback_duration, play_start, play_stop,
        range_start, range_stop)
    text = ngl.Text(base_string,
                    box_height=(0, 0.3, 0),
                    box_corner=(-1, 1 - 0.3, 0),
                    aspect_ratio=cfg.aspect_ratio,
                    halign='left')

    group = ngl.Group()
    group.add_children(rf, text)

    steps = (
        ('default color, nothing yet', 0, noop_duration),
        ('default color, media prefetched', noop_duration, range_start),
        ('first frame', range_start, play_start),
        ('normal playback', play_start, play_stop),
        ('last frame', play_stop, range_stop),
        ('default color, media released', range_stop, duration),
    )

    for i, (description, start_time, end_time) in enumerate(steps):
        text = ngl.Text('%g to %g: %s' % (start_time, end_time, description),
                        aspect_ratio=cfg.aspect_ratio,
                        box_height=(0, 0.2, 0))
        text_tr = (
            ngl.TimeRangeModeNoop(0),
            ngl.TimeRangeModeCont(start_time),
            ngl.TimeRangeModeNoop(end_time),
        )
        text_rf = ngl.TimeRangeFilter(text,
                                      ranges=text_tr,
                                      label='text-step-%d' % i)
        group.add_children(text_rf)

    return ngl.GraphicConfig(group,
                             blend=True,
                             blend_src_factor='src_alpha',
                             blend_dst_factor='one_minus_src_alpha',
                             blend_src_factor_a='zero',
                             blend_dst_factor_a='one')
Exemplo n.º 16
0
def api_livectls():
    # Build a scene and extract its live controls
    rng = random.Random(0)
    scene = ngl.Group(
        children=(
            ngl.UniformBool(live_id="b"),
            ngl.UniformFloat(live_id="f"),
            ngl.UniformIVec3(live_id="iv3"),
            ngl.UserSwitch(
                ngl.Group(
                    children=(
                        ngl.UniformMat4(live_id="m4"),
                        ngl.UniformColor(live_id="clr"),
                        ngl.UniformQuat(as_mat4=True, live_id="rot"),
                    )
                ),
                live_id="switch",
            ),
            ngl.Text(live_id="txt"),
        )
    )
    livectls = ngl.get_livectls(scene)
    assert len(livectls) == 8

    # Attach scene and run a dummy draw to make sure it's valid
    ctx = ngl.Context()
    ret = ctx.configure(offscreen=1, width=16, height=16, backend=_backend)
    assert ret == 0
    assert ctx.set_scene(scene) == 0
    assert ctx.draw(0) == 0

    # Apply live changes on nodes previously tracked by get_livectls()
    values = dict(
        b=True,
        f=rng.uniform(-1, 1),
        iv3=[rng.randint(-100, 100) for i in range(3)],
        switch=False,
        m4=[rng.uniform(-1, 1) for i in range(16)],
        clr=(0.9, 0.3, 0.8),
        rot=(0.1, -0.2, 0.5, -0.3),
        txt="test string",
    )
    for live_id, value in values.items():
        node = livectls[live_id]["node"]
        node_type = livectls[live_id]["node_type"]
        assert node_type == node.__class__.__name__
        if node_type == "UserSwitch":
            node.set_enabled(value)
        elif node_type == "Text":
            node.set_text(value)
        elif hasattr(value, "__iter__"):
            node.set_value(*value)
        else:
            node.set_value(value)

    # Detach scene from context and grab all live controls again
    assert ctx.set_scene(None) == 0
    livectls = ngl.get_livectls(scene)

    # Inspect nodes to check if they were properly altered by the live changes
    for live_id, expected_value in values.items():
        value = livectls[live_id]["val"]
        node_type = livectls[live_id]["node_type"]
        if node_type == "Text":
            assert value == expected_value, (value, expected_value)
        elif hasattr(value, "__iter__"):
            assert all(math.isclose(v, e, rel_tol=1e-6) for v, e in zip(value, expected_value))
        else:
            assert math.isclose(value, expected_value, rel_tol=1e-6)
def time_remapping(cfg):
    """
    Time remapping in the following order:
    - nothing displayed for a while (but media prefetch happening in background)
    - first frame displayed for a while
    - normal playback
    - last frame displayed for a while (even though the media is closed)
    - nothing again until the end
    """
    m0 = cfg.medias[0]

    media_seek = 10
    noop_duration = 2
    prefetch_duration = 2
    freeze_duration = 3
    playback_duration = 5

    range_start = noop_duration + prefetch_duration
    play_start = range_start + freeze_duration
    play_stop = play_start + playback_duration
    range_stop = play_stop + freeze_duration
    duration = range_stop + noop_duration

    cfg.duration = duration
    cfg.aspect_ratio = (m0.width, m0.height)

    media_animkf = [
        ngl.AnimKeyFrameFloat(play_start, media_seek),
        ngl.AnimKeyFrameFloat(play_stop, media_seek + playback_duration),
    ]

    m = ngl.Media(m0.filename, time_anim=ngl.AnimatedTime(media_animkf))
    m.set_sxplayer_min_level("verbose")
    t = ngl.Texture2D(data_src=m)
    r = ngl.RenderTexture(t)

    time_ranges = [
        ngl.TimeRangeModeNoop(0),
        ngl.TimeRangeModeCont(range_start),
        ngl.TimeRangeModeNoop(range_stop),
    ]
    rf = ngl.TimeRangeFilter(r, ranges=time_ranges, prefetch_time=prefetch_duration)

    base_string = "media time: {:2g} to {:2g}\nscene time: {:2g} to {:2g}\ntime range: {:2g} to {:2g}".format(
        media_seek, media_seek + playback_duration, play_start, play_stop, range_start, range_stop
    )
    text = ngl.Text(
        base_string, box_height=(0, 0.3, 0), box_corner=(-1, 1 - 0.3, 0), aspect_ratio=cfg.aspect_ratio, halign="left"
    )

    group = ngl.Group()
    group.add_children(rf, text)

    steps = (
        ("default color, nothing yet", 0, noop_duration),
        ("default color, media prefetched", noop_duration, range_start),
        ("first frame", range_start, play_start),
        ("normal playback", play_start, play_stop),
        ("last frame", play_stop, range_stop),
        ("default color, media released", range_stop, duration),
    )

    for i, (description, start_time, end_time) in enumerate(steps):
        text = ngl.Text(
            f"{start_time:g} to {end_time:g}: {description}", aspect_ratio=cfg.aspect_ratio, box_height=(0, 0.2, 0)
        )
        text_tr = (
            ngl.TimeRangeModeNoop(0),
            ngl.TimeRangeModeCont(start_time),
            ngl.TimeRangeModeNoop(end_time),
        )
        text_rf = ngl.TimeRangeFilter(text, ranges=text_tr, label="text-step-%d" % i)
        group.add_children(text_rf)

    return group
Exemplo n.º 18
0
def _text(**params):
    return ngl.Text("This\nis\nnode.gl", font_scale=0.7, padding=8, **params)
Exemplo n.º 19
0
def _get_easing_node(cfg, easing, curve_zoom, color_program, nb_points=128):
    text_vratio = 1 / 8.
    graph_hpad_ratio = 1 / 16.

    area_size = 2.0
    width, height = area_size, area_size
    text_height = text_vratio * height
    pad_height = graph_hpad_ratio * height

    # Colors
    hue = random.uniform(0, 0.6)
    color = list(colorsys.hls_to_rgb(hue, 0.6, 1.0)) + [1]
    ucolor = ngl.UniformVec4(value=color)
    graph_bg_ucolor = ngl.UniformVec4(value=(.15, .15, .15, 1))
    normed_graph_bg_ucolor = ngl.UniformVec4(value=(0, 0, 0, 1))
    line_ucolor = ngl.UniformVec4(value=(1, 1, 1, .4))

    # Text legend
    text = ngl.Text(text=easing,
                    fg_color=color,
                    padding=3,
                    bg_color=(0, 0, 0, 1),
                    box_corner=(-width / 2., height / 2. - text_height, 0),
                    box_width=(width, 0, 0),
                    box_height=(0, text_height, 0),
                    label='%s legend' % easing)

    # Graph drawing area (where the curve may overflow)
    graph_size = area_size - text_height - pad_height * 2
    graph_block = _block(graph_size,
                         graph_size,
                         color_program,
                         corner=(-graph_size / 2,
                                 -(graph_size + text_height) / 2, 0),
                         color=graph_bg_ucolor)

    # Normed area of the graph
    normed_graph_size = graph_size * curve_zoom
    normed_graph_block = _block(normed_graph_size,
                                normed_graph_size,
                                color_program,
                                corner=(-normed_graph_size / 2,
                                        -(normed_graph_size + text_height) / 2,
                                        0),
                                color=normed_graph_bg_ucolor)

    # Curve
    easing_name, easing_args = _easing_split(easing)
    curve_scale_factor = graph_size / area_size * curve_zoom
    vertices_data = array.array('f')
    for i in range(nb_points + 1):
        t = i / float(nb_points)
        v = ngl.easing_evaluate(easing_name, t, easing_args)
        x = curve_scale_factor * (t * width - width / 2.)
        y = curve_scale_factor * (v * height - height / 2.)
        y -= text_height / 2.
        vertices_data.extend([x, y, 0])
    vertices = ngl.BufferVec3(data=vertices_data)
    geometry = ngl.Geometry(vertices, topology='line_strip')
    curve = ngl.Render(geometry, color_program, label='%s curve' % easing)
    curve.update_uniforms(color=ucolor)

    # Value cursor
    y = 2 / 3. * pad_height
    x = y * math.sqrt(3)
    cursor_geometry = ngl.Triangle((-x, y, 0), (0, 0, 0), (-x, -y, 0))
    cursor = ngl.Render(cursor_geometry,
                        color_program,
                        label='%s cursor' % easing)
    cursor.update_uniforms(color=ucolor)

    # Horizontal value line
    hline_data = array.array('f', (0, 0, 0, graph_size, 0, 0))
    hline_vertices = ngl.BufferVec3(data=hline_data)
    hline_geometry = ngl.Geometry(hline_vertices, topology='line_strip')
    hline = ngl.Render(hline_geometry,
                       color_program,
                       label='%s value line' % easing)
    hline.update_uniforms(color=line_ucolor)

    # Value animation (cursor + h-line)
    value_x = -graph_size / 2.
    value_y = (-text_height - normed_graph_size) / 2.
    value_animkf = (
        ngl.AnimKeyFrameVec3(0, (value_x, value_y, 0)),
        ngl.AnimKeyFrameVec3(cfg.duration,
                             (value_x, value_y + normed_graph_size, 0),
                             easing_name, easing_args),
    )
    value_anim = ngl.Group(children=(hline, cursor))
    value_anim = ngl.Translate(value_anim,
                               anim=ngl.AnimatedVec3(value_animkf),
                               label='%s value anim' % easing)

    # Vertical time line
    vline_data = array.array('f', (0, 0, 0, 0, graph_size, 0))
    vline_vertices = ngl.BufferVec3(data=vline_data)
    vline_geometry = ngl.Geometry(vline_vertices, topology='line_strip')
    vline = ngl.Render(vline_geometry,
                       color_program,
                       label='%s time line' % easing)
    vline.update_uniforms(color=line_ucolor)

    # Time animation (v-line only)
    time_x = -normed_graph_size / 2.
    time_y = (-text_height - graph_size) / 2.
    time_animkf = (ngl.AnimKeyFrameVec3(0, (time_x, time_y, 0)),
                   ngl.AnimKeyFrameVec3(
                       cfg.duration, (time_x + normed_graph_size, time_y, 0)))
    time_anim = ngl.Translate(vline,
                              anim=ngl.AnimatedVec3(time_animkf),
                              label='%s time anim' % easing)

    group = ngl.Group(label='%s block' % easing)
    group.add_children(text, graph_block, normed_graph_block, curve,
                       value_anim, time_anim)
    return group
Exemplo n.º 20
0
def parallel_playback(cfg,
                      fast=True,
                      segment_time=2.,
                      constrained_timeranges=False):
    '''
    Parallel media playback, flipping between the two sources.

    The fast version makes sure the textures continue to be updated even though
    they are not displayed. On the other hand, the slow version will update the
    textures only when needed to be displayed, causing potential seek in the
    underlying media, and thus undesired delays.
    '''
    q = ngl.Quad((-1, -1, 0), (2, 0, 0), (0, 2, 0))
    p = ngl.Program()

    m1 = ngl.Media(cfg.medias[0].filename, label='media #1')
    m2 = ngl.Media(cfg.medias[0].filename, label='media #2')

    t1 = ngl.Texture2D(data_src=m1, label='texture #1')
    t2 = ngl.Texture2D(data_src=m2, label='texture #2')

    render1 = ngl.Render(q, p, label='render #1')
    render1.update_textures(tex0=t1)
    render2 = ngl.Render(q, p, label='render #2')
    render2.update_textures(tex0=t2)

    text_settings = {
        'box_corner': (-1, 1 - 0.2, 0),
        'box_height': (0, 0.2, 0),
        'aspect_ratio': cfg.aspect_ratio,
    }
    render1 = ngl.Group(children=(render1,
                                  ngl.Text('media #1', **text_settings)))
    render2 = ngl.Group(children=(render2,
                                  ngl.Text('media #2', **text_settings)))

    rf1 = ngl.TimeRangeFilter(render1)
    rf2 = ngl.TimeRangeFilter(render2)

    if constrained_timeranges:
        rf1.set_prefetch_time(segment_time / 3.)
        rf2.set_prefetch_time(segment_time / 3.)
        rf1.set_max_idle_time(segment_time / 2.)
        rf2.set_max_idle_time(segment_time / 2.)

    t = 0
    rr1 = []
    rr2 = []
    while t < cfg.duration:
        rr1.append(ngl.TimeRangeModeCont(t))
        rr1.append(ngl.TimeRangeModeNoop(t + segment_time))

        rr2.append(ngl.TimeRangeModeNoop(t))
        rr2.append(ngl.TimeRangeModeCont(t + segment_time))

        t += 2 * segment_time

    rf1.add_ranges(*rr1)
    rf2.add_ranges(*rr2)

    g = ngl.Group()
    g.add_children(rf1, rf2)
    if fast:
        g.add_children(t1, t2)
    return g