fix copying
This commit is contained in:
		
							parent
							
								
									802ba51875
								
							
						
					
					
						commit
						aa82295182
					
				
					 5 changed files with 55 additions and 36 deletions
				
			
		| 
						 | 
					@ -36,7 +36,11 @@ class Doodle(ABC):
 | 
				
			||||||
        # All references to _pos_vec are internal to the class,
 | 
					        # All references to _pos_vec are internal to the class,
 | 
				
			||||||
        # so it will be trivial to swap this out later.
 | 
					        # so it will be trivial to swap this out later.
 | 
				
			||||||
        self._pos_vec = (0, 0)
 | 
					        self._pos_vec = (0, 0)
 | 
				
			||||||
        if parent:
 | 
					        self._register()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _register(self):
 | 
				
			||||||
 | 
					        """ register with parent and world """
 | 
				
			||||||
 | 
					        if self._parent:
 | 
				
			||||||
            # register with parent for updates
 | 
					            # register with parent for updates
 | 
				
			||||||
            self._parent.add(self)
 | 
					            self._parent.add(self)
 | 
				
			||||||
        world.add(self)
 | 
					        world.add(self)
 | 
				
			||||||
| 
						 | 
					@ -63,20 +67,20 @@ class Doodle(ABC):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Additionally, while a shallow copy is enough for most
 | 
					        Additionally, while a shallow copy is enough for most
 | 
				
			||||||
        cases, it will be possible for child classes to override
 | 
					        cases, it will be possible for child classes to override
 | 
				
			||||||
        this to opt for a deepcopy or other logic.
 | 
					        this.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        new = copy.copy(self)
 | 
					        new = copy.copy(self)
 | 
				
			||||||
        world.add(new)
 | 
					        new._register()
 | 
				
			||||||
        return new
 | 
					        return new
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def color(self, r: int, g: int, b: int) -> "Doodle":
 | 
					    def color(self, color: tuple[int, int, int]) -> "Doodle":
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Color works as a kind of setter function.
 | 
					        Color works as a kind of setter function.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        The only unique part is that it returns self, accomodating the
 | 
					        The only unique part is that it returns self, accomodating the
 | 
				
			||||||
        chained object pattern.
 | 
					        chained object pattern.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        self._color = (r, g, b)
 | 
					        self._color = color
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pos(self, x: float, y: float) -> "Doodle":
 | 
					    def pos(self, x: float, y: float) -> "Doodle":
 | 
				
			||||||
| 
						 | 
					@ -111,11 +115,11 @@ class Doodle(ABC):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        x = random.random() * world.WIDTH
 | 
					        x = random.random() * world.WIDTH
 | 
				
			||||||
        y = random.random() * world.HEIGHT
 | 
					        y = random.random() * world.HEIGHT
 | 
				
			||||||
        r, g, b = Color.random()
 | 
					        color = Color.random()
 | 
				
			||||||
        # again here, we opt to use the setters so that
 | 
					        # again here, we opt to use the setters so that
 | 
				
			||||||
        # future extensions to their behavior will be
 | 
					        # future extensions to their behavior will be
 | 
				
			||||||
        # used by all downstream functions
 | 
					        # used by all downstream functions
 | 
				
			||||||
        return self.pos(x, y).color(r, g, b)
 | 
					        return self.pos(x, y).color(color)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def x(self) -> float:
 | 
					    def x(self) -> float:
 | 
				
			||||||
| 
						 | 
					@ -265,10 +269,13 @@ class Group(Doodle):
 | 
				
			||||||
    in some languages would be much trickier to pull off.
 | 
					    in some languages would be much trickier to pull off.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self, parent=None):
 | 
				
			||||||
        super().__init__()
 | 
					        super().__init__(parent)
 | 
				
			||||||
        self._doodles = []
 | 
					        self._doodles = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        return f"Group(pos={self.pos_vec}, doodles={len(self._doodles)})"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def draw(self, screen):
 | 
					    def draw(self, screen):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Groups, despite being an abstract concept, are drawable.
 | 
					        Groups, despite being an abstract concept, are drawable.
 | 
				
			||||||
| 
						 | 
					@ -285,11 +292,16 @@ class Group(Doodle):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        We are storing a list, so deep copies are necessary.
 | 
					        We are storing a list, so deep copies are necessary.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        new = copy.deepcopy(self)
 | 
					        new = copy.copy(self)
 | 
				
			||||||
        world.add(new)
 | 
					        new._register()
 | 
				
			||||||
 | 
					        new._doodles = []
 | 
				
			||||||
 | 
					        for child in self._doodles:
 | 
				
			||||||
 | 
					            child = copy.copy(child)
 | 
				
			||||||
 | 
					            child._parent = new
 | 
				
			||||||
 | 
					            child._register()
 | 
				
			||||||
        return new
 | 
					        return new
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def color(self, r: int, g: int, b: int) -> "Doodle":
 | 
					    def color(self, color: tuple[int, int, int]) -> "Doodle":
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        Another override.
 | 
					        Another override.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -299,9 +311,9 @@ class Group(Doodle):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        We don't cascade pos() calls, why not?
 | 
					        We don't cascade pos() calls, why not?
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        super().color(r, g, b)
 | 
					        super().color(color)
 | 
				
			||||||
        for d in self._doodles:
 | 
					        for d in self._doodles:
 | 
				
			||||||
            d.color(r, g, b)
 | 
					            d.color(color)
 | 
				
			||||||
        return self
 | 
					        return self
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add(self, doodle: "Doodle") -> "Group":
 | 
					    def add(self, doodle: "Doodle") -> "Group":
 | 
				
			||||||
| 
						 | 
					@ -338,7 +350,7 @@ class Circle(Doodle):
 | 
				
			||||||
        self._radius = 0
 | 
					        self._radius = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __repr__(self):
 | 
					    def __repr__(self):
 | 
				
			||||||
        return f"Circle(pos={self.pos_vec}, radius={self._radius}, {self._color})"
 | 
					        return f"Circle(pos={self.pos_vec}, radius={self._radius}, {self._color}, parent={self._parent}))"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def draw(self, screen):
 | 
					    def draw(self, screen):
 | 
				
			||||||
        pygame.draw.circle(screen, self._color, self.pos_vec, self._radius)
 | 
					        pygame.draw.circle(screen, self._color, self.pos_vec, self._radius)
 | 
				
			||||||
| 
						 | 
					@ -359,4 +371,4 @@ class Circle(Doodle):
 | 
				
			||||||
    def random(self) -> "Doodle":
 | 
					    def random(self) -> "Doodle":
 | 
				
			||||||
        super().random()
 | 
					        super().random()
 | 
				
			||||||
        # constrain to 10-100
 | 
					        # constrain to 10-100
 | 
				
			||||||
        return self.radius(random.random*90 + 10)
 | 
					        return self.radius(random.random()*90 + 10)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										16
									
								
								src/doodles/examples/copies.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/doodles/examples/copies.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					from doodles.doodles import Group, Line, Circle, Color
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def original():
 | 
				
			||||||
 | 
					    g = Group()
 | 
				
			||||||
 | 
					    c = Circle(g).radius(80).color(Color.RED).pos(0, 0)
 | 
				
			||||||
 | 
					    for _ in range(15):
 | 
				
			||||||
 | 
					        c = c.copy().move(45, 45)
 | 
				
			||||||
 | 
					    return g
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					r = original()
 | 
				
			||||||
 | 
					r.copy().move(200, 0).color(Color.GREEN)
 | 
				
			||||||
 | 
					r.copy().move(400, 0).color(Color.BLUE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# from doodles.world import world
 | 
				
			||||||
 | 
					# for d in world._drawables:
 | 
				
			||||||
 | 
					#     print(" >", d)
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,13 @@
 | 
				
			||||||
from doodles.doodles import Group, Line
 | 
					from doodles.doodles import Group, Line
 | 
				
			||||||
from doodles.layouts import make_grid, copies
 | 
					from doodles.layouts import make_grid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def same_spiral():
 | 
				
			||||||
 | 
					    while True:
 | 
				
			||||||
        # Create a group of lines all with same origin, different angles.
 | 
					        # Create a group of lines all with same origin, different angles.
 | 
				
			||||||
        g = Group()
 | 
					        g = Group()
 | 
				
			||||||
        for d in range(0, 180, 10):
 | 
					        for d in range(0, 180, 10):
 | 
				
			||||||
            Line(g).vec(d, 200 - d)
 | 
					            Line(g).vec(d, 200 - d)
 | 
				
			||||||
 | 
					        yield g
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Make copies, moving each one and modifying the color
 | 
					# Make copies, moving each one and modifying the color
 | 
				
			||||||
make_grid(copies(g), 3, 4, 250, 140, x_offset=70, y_offset=20)
 | 
					make_grid(same_spiral(), 3, 4, 250, 140, x_offset=70, y_offset=20)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,21 +5,9 @@ def make_grid(iterable, cols, rows, width, height, *, x_offset=0, y_offset=0):
 | 
				
			||||||
    Arranges the objects in iterable in a grid with the given parameters.
 | 
					    Arranges the objects in iterable in a grid with the given parameters.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
        doodle = next(iterable)
 | 
					 | 
				
			||||||
        for c in range(cols):
 | 
					        for c in range(cols):
 | 
				
			||||||
            for r in range(rows):
 | 
					            for r in range(rows):
 | 
				
			||||||
                doodle.pos(width * c + x_offset, height * r + y_offset)
 | 
					 | 
				
			||||||
                doodle = next(iterable)
 | 
					                doodle = next(iterable)
 | 
				
			||||||
 | 
					                doodle.pos(width * c + x_offset, height * r + y_offset)
 | 
				
			||||||
    except StopIteration:
 | 
					    except StopIteration:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def copies(doodle):
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    Lazily makes an infinite number of copies of a given doodle.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Can be combined with things like `make_grid` that require
 | 
					 | 
				
			||||||
    an iterable of doodles to repeat.
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    while True:
 | 
					 | 
				
			||||||
        yield doodle.copy()
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ def main(modname: str):
 | 
				
			||||||
                pygame.quit()
 | 
					                pygame.quit()
 | 
				
			||||||
                sys.exit()
 | 
					                sys.exit()
 | 
				
			||||||
        world.render()
 | 
					        world.render()
 | 
				
			||||||
        # print(f"world contains {world._drawables}")
 | 
					        #print(f"world contains {len(world._drawables)}")
 | 
				
			||||||
        pygame.display.flip()
 | 
					        pygame.display.flip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue