コード例 #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))
コード例 #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
コード例 #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
コード例 #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
コード例 #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')
コード例 #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,
    )
コード例 #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)
コード例 #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)
コード例 #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')
コード例 #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
コード例 #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
コード例 #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
コード例 #13
0
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,
    )
コード例 #14
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
コード例 #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')
コード例 #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)
コード例 #17
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),
    ]

    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
コード例 #18
0
def _text(**params):
    return ngl.Text("This\nis\nnode.gl", font_scale=0.7, padding=8, **params)
コード例 #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
コード例 #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