Пример #1
0
    def adjust_lines(self):
        tabledict = self.tabledict
        cell_height = self.cell_height
        cell_length = self.cell_length

        vertlines = self.submobjects[-(len(tabledict) - 1):]
        lowestmobject = min(self.submobjects[0:len(self.submobjects) -
                                             (len(tabledict))],
                            key=lambda m: m.get_y())
        rightestmobject = max(self.submobjects[:len(tabledict)],
                              key=lambda m: m.get_x())
        anims = []

        for line in vertlines:
            curr_start, curr_end = line.get_start_and_end()
            if line.get_angle(
            ) * DEGREES == 0:  #This only happens when a field has been added, but a vertical separator doesnt exist for it.
                new_end = np.array(curr_end +
                                   (rightestmobject.get_x() - curr_end[0] +
                                    cell_length / 4, 0, 0))

                newsep = Line(  #This is the vertical separator for the new field.
                    start=(rightestmobject.get_center() -
                           (cell_length / 4, -cell_height / 4, 0)),
                    end=(rightestmobject.get_center() -
                         (cell_length / 4, +rightestmobject.get_y() -
                          lowestmobject.get_y() + cell_height / 4, 0)),
                    color=self.line_color)

                anims.append(ShowCreation(newsep))
                self.add(newsep)
            else:
                new_end = np.array((curr_end) +
                                   (0, lowestmobject.get_y() - curr_end[1] -
                                    cell_height / 4, 0))

            new_line = Line(curr_start, new_end, color=self.line_color)
            anims.append(Transform(
                line, new_line))  #Set the new bottom to the required position
        return AnimationGroup(*anims)
Пример #2
0
def test_succession_in_succession_timing():
    """Test timing of nested successions."""
    line = Line()
    animation_1s = FadeIn(line, shift=UP, run_time=1.0)
    animation_4s = FadeOut(line, shift=DOWN, run_time=4.0)
    nested_succession = Succession(animation_1s, animation_4s)
    succession = Succession(
        FadeIn(line, shift=UP, run_time=4.0),
        nested_succession,
        FadeIn(line, shift=UP, run_time=1.0),
    )
    assert nested_succession.get_run_time() == 5.0
    assert succession.get_run_time() == 10.0
    succession._setup_scene(Mock())
    succession.begin()
    succession.interpolate(0.1)
    assert succession.active_index == 0
    # The nested succession must not be active yet, and as a result hasn't set active_animation yet.
    assert not hasattr(nested_succession, "active_animation")
    succession.interpolate(0.39)
    assert succession.active_index == 0
    assert not hasattr(nested_succession, "active_animation")
    # The nested succession starts at 40% of total run time
    succession.interpolate(0.4)
    assert succession.active_index == 1
    assert nested_succession.active_index == 0
    # The nested succession second animation starts at 50% of total run time.
    succession.interpolate(0.49)
    assert succession.active_index == 1
    assert nested_succession.active_index == 0
    succession.interpolate(0.5)
    assert succession.active_index == 1
    assert nested_succession.active_index == 1
    # The last animation starts at 90% of total run time. The nested succession must be finished at that time.
    succession.interpolate(0.89)
    assert succession.active_index == 1
    assert nested_succession.active_index == 1
    succession.interpolate(0.9)
    assert succession.active_index == 2
    assert nested_succession.active_index == 2
    assert nested_succession.active_animation is None
    # After 100%, nothing must be playing anymore.
    succession.interpolate(1.0)
    assert succession.active_index == 3
    assert succession.active_animation is None
    assert nested_succession.active_index == 2
    assert nested_succession.active_animation is None
Пример #3
0
def test_succession_timing():
    """Test timing of animations in a succession."""
    line = Line()
    animation_1s = FadeIn(line, shift=UP, run_time=1.0)
    animation_4s = FadeOut(line, shift=DOWN, run_time=4.0)
    succession = Succession(animation_1s, animation_4s)
    assert succession.get_run_time() == 5.0
    succession.begin()
    assert succession.active_index == 0
    # The first animation takes 20% of the total run time.
    succession.interpolate(0.199)
    assert succession.active_index == 0
    succession.interpolate(0.2)
    assert succession.active_index == 1
    succession.interpolate(0.8)
    assert succession.active_index == 1
    # At 100% and more, no animation must be active anymore.
    succession.interpolate(1.0)
    assert succession.active_index == 2
    assert succession.active_animation is None
    succession.interpolate(1.2)
    assert succession.active_index == 2
    assert succession.active_animation is None
Пример #4
0
 def __init__(self):
     super().__init__()
     self.left_dot = Dot().shift((-1, 0, 0))
     self.right_dot = Dot().shift((1, 0, 0))
     self.line = Line(self.left_dot, self.right_dot)
     self.add(self.left_dot, self.right_dot, self.line)
Пример #5
0
    def make_table(self):

        self.unchanged = True  #unchanged becomes False when some record or field has been added.

        #Get values from CONFIG
        tabledict = self.tabledict
        buff_length = self.buff_length
        hbuff_length = self.hbuff_length
        vbuff_length = self.vbuff_length
        line_color = self.line_color
        raw_string_color = self.raw_string_color

        #self is now the table. so self.add has replaced table.add in this function.

        fields = list(tabledict.keys(
        ))  #Since the data is recieved as a dict, the keys will be the fields

        #the for loop below checks that every field and record is of a valid type and converts to TextMobject if need be:
        for fieldnum in range(len(fields)):

            if isinstance(fields[fieldnum], (TextMobject, TexMobject, Text,
                                             DecimalNumber, Integer)) == False:
                tabledict[TextMobject(
                    fields[fieldnum],
                    fill_color=raw_string_color)] = tabledict.pop(
                        fields[fieldnum])

            fields = list(tabledict.keys())

            for recordnum in range(0, len(tabledict[fields[fieldnum]])):
                if isinstance(tabledict[fields[fieldnum]][recordnum],
                              (TexMobject, TextMobject, Text, DecimalNumber,
                               Integer)) == False:
                    tabledict[fields[fieldnum]][recordnum] = TextMobject(
                        tabledict[fields[fieldnum]][recordnum],
                        fill_color=raw_string_color)
                else:
                    continue

        cell_length = (max(
            fields + Tools.flatten(tabledict.values()),
            key=lambda mobject: mobject.get_width())).get_width(
            ) + 2 * hbuff_length  #The length/height of a record/field of
        cell_height = (max(
            fields + Tools.flatten(tabledict.values()),
            key=lambda mobject: mobject.get_height())).get_height(
            ) + 2 * vbuff_length  #max length/height is the base cell size

        self.cell_height = cell_height
        self.cell_length = cell_length

        #The first position is set like so.

        field_position = [
            (cell_length - TexMobject(fields[0]).get_width()) / 2 +
            TexMobject(fields[0]).get_width() / 2, 0, 0
        ]  #The initial position of the first field.

        #NOTE: Coordinates of TexMobjects in Manim are taken from centre, not top-right. Adjustments have been made by adding half the width of the object in all calculations.

        total_table_width = (
            cell_length * len(fields)
        )  #The remaining width and height will be successively added
        total_table_height = cell_height * (
            len(max(tabledict.values(), key=len)) + 1
        )  #while drawing the Mobjects to the screen. +1 is added to account for headings.

        for n in range(0, len(fields)):

            field = fields[n]
            field_length = field.get_width(
            )  #This is the length that the actual field name will take up on-screen

            if n + 1 < len(
                    fields
            ):  #This gets the nxt field if it exists and chooses an empty TexMobject if it doesn't
                next_field = (fields[n + 1])
            else:
                next_field = TexMobject("")

            next_field_length = next_field.get_width(
            )  #Gets the next fields length

            field.move_to(field_position)

            space_to_right_of_field = (cell_length - field_length) / 2

            space_to_left_of_next_field = (cell_length - next_field_length) / 2

            space_to_leave = space_to_right_of_field + space_to_left_of_next_field + next_field_length / 2

            #next_field_length/2 is added to account for the fact that coordinates are taken from centre and not left edges.

            self.add(field)
            field_position = field.get_right() + (space_to_leave, 0, 0)

        for keynum in range(len(tabledict.keys())):
            key = list(tabledict.keys())[keynum]  #gets the actual key
            recordlist = tabledict[key]  #selects the list with the records for

            if recordlist != []:

                record_position = [
                    self[keynum].get_center()[0],
                    -((cell_height - fields[keynum].get_height()) / 2 +
                      fields[keynum].get_height() / 2 + cell_height), 0
                ]

                #the record position is set to be the [center of the field it belongs to, buffer space above the record + centered height of the record, 0  ]

                for recordnum in range(len(recordlist)):  # for each record for
                    record = recordlist[recordnum]  # the selected field

                    if recordnum + 1 < len(
                            recordlist
                    ):  #This gets the nxt record if it exists and chooses an empty TexMobject if it doesn't
                        next_record = recordlist[recordnum + 1]
                    else:
                        next_record = TexMobject("")

                    record.move_to(record_position)
                    record_position = record.get_center() + (0, -cell_height,
                                                             0)
                    self.add(record)
            else:
                pass

        line_hor = Line(start=(0, -2 * cell_height / 3, 0),
                        end=(total_table_width, -2 * cell_height / 3, 0),
                        color=line_color)
        self.add(line_hor)  #This is the horizontal separator

        for l in range(len(fields) -
                       1):  #These create the vertical separators.
            line = Line(start=(self[l].get_center() +
                               (cell_length / 2, cell_height / 2, 0)),
                        end=(self[l].get_center() +
                             (cell_length / 2, -total_table_height, 0)),
                        color=line_color)

            self.add(line)