diff --git a/manim/mobject/mobject.py b/manim/mobject/mobject.py index 721ce57356..5b83908fff 100644 --- a/manim/mobject/mobject.py +++ b/manim/mobject/mobject.py @@ -2561,10 +2561,23 @@ def arrange( direction: Vector3DLike = RIGHT, buff: float = DEFAULT_MOBJECT_TO_MOBJECT_BUFFER, center: bool = True, + reference: Mobject | None = None, **kwargs: Any, ) -> Self: """Sorts :class:`~.Mobject` next to each other on screen. + Parameters + ---------- + direction + The direction in which the submobjects should be arranged. + buff + The distance between neighboring submobjects. + center + Whether to center the mobject after arranging. + reference + The submobject to use as the reference for the arrangement. If not + set, the first submobject is used. + Examples -------- @@ -2580,8 +2593,26 @@ def construct(self): x = VGroup(s1, s2, s3, s4).set_x(0).arrange(buff=1.0) self.add(x) """ - for m1, m2 in zip(self.submobjects[:-1], self.submobjects[1:], strict=True): + submobjects = list(self.submobjects) + + if reference is None: + reference_index = 0 + else: + reference_index = submobjects.index(reference) + + for m1, m2 in zip( + submobjects[reference_index:], + submobjects[reference_index + 1 :], + ): m2.next_to(m1, direction, buff, **kwargs) + + for m1, m2 in zip( + reversed(submobjects[:reference_index]), + reversed(submobjects[1 : reference_index + 1]), + strict=True, + ): + m1.next_to(m2, -direction, buff, **kwargs) + if center: self.center() return self diff --git a/tests/module/mobject/mobject/test_mobject.py b/tests/module/mobject/mobject/test_mobject.py index 203d312627..765739bc5b 100644 --- a/tests/module/mobject/mobject/test_mobject.py +++ b/tests/module/mobject/mobject/test_mobject.py @@ -243,3 +243,19 @@ def test_apply_matrix_about_vertex_view(): # The first vertex should remain in the same position (within numerical precision) transformed_vertices = triangle.get_vertices() np.testing.assert_allclose(transformed_vertices[0], first_vertex, atol=1e-6) + + +def test_mobject_arrange_reference(): + """Test Mobject.arrange() can use a submobject as the reference.""" + square1 = Square() + square2 = Square() + square3 = Square() + + group = VGroup(square1, square2, square3) + original_reference_center = square3.get_center().copy() + + group.arrange(reference=square3, center=False) + + assert np.allclose(square3.get_center(), original_reference_center) + assert square1.get_x() < square2.get_x() + assert square2.get_x() < square3.get_x()