Fix translation matrix application on embedded clips, fixes placement of lots of complex animations.
This commit is contained in:
parent
2c678e60f8
commit
70f06b2b33
@ -114,7 +114,6 @@ except ImportError:
|
||||
add_color: Tuple[int, int, int, int],
|
||||
mult_color: Color,
|
||||
transform: Matrix,
|
||||
origin: Point,
|
||||
blendfunc: int,
|
||||
texture: Image.Image,
|
||||
single_threaded: bool = False,
|
||||
@ -126,7 +125,6 @@ except ImportError:
|
||||
# If this happens, that means one of the scaling factors was zero, making
|
||||
# this object invisible. We can ignore this since the object should not
|
||||
# be drawn.
|
||||
print(f"WARNING: Transform Matrix {transform} has zero scaling factor, making it non-invertible!")
|
||||
return img
|
||||
|
||||
# Warn if we have an unsupported blend.
|
||||
@ -142,10 +140,10 @@ except ImportError:
|
||||
texheight = texture.height
|
||||
|
||||
# Calculate the maximum range of update this texture can possibly reside in.
|
||||
pix1 = transform.multiply_point(Point.identity().subtract(origin))
|
||||
pix2 = transform.multiply_point(Point.identity().subtract(origin).add(Point(texwidth, 0)))
|
||||
pix3 = transform.multiply_point(Point.identity().subtract(origin).add(Point(0, texheight)))
|
||||
pix4 = transform.multiply_point(Point.identity().subtract(origin).add(Point(texwidth, texheight)))
|
||||
pix1 = transform.multiply_point(Point.identity())
|
||||
pix2 = transform.multiply_point(Point.identity().add(Point(texwidth, 0)))
|
||||
pix3 = transform.multiply_point(Point.identity().add(Point(0, texheight)))
|
||||
pix4 = transform.multiply_point(Point.identity().add(Point(texwidth, texheight)))
|
||||
|
||||
# Map this to the rectangle we need to sweep in the rendering image.
|
||||
minx = max(int(min(pix1.x, pix2.x, pix3.x, pix4.x)), 0)
|
||||
@ -170,7 +168,7 @@ except ImportError:
|
||||
imgoff = imgx + (imgy * imgwidth)
|
||||
|
||||
# Calculate what texture pixel data goes here.
|
||||
texloc = inverse.multiply_point(Point(float(imgx), float(imgy))).add(origin)
|
||||
texloc = inverse.multiply_point(Point(float(imgx), float(imgy)))
|
||||
texx, texy = texloc.as_tuple()
|
||||
|
||||
# If we're out of bounds, don't update.
|
||||
@ -197,7 +195,7 @@ except ImportError:
|
||||
nonlocal interrupted
|
||||
interrupted = True
|
||||
|
||||
original_handler = signal.getsignal(signal.SIGINT)
|
||||
previous_handler = signal.getsignal(signal.SIGINT)
|
||||
signal.signal(signal.SIGINT, ctrlc)
|
||||
|
||||
for _ in range(cores):
|
||||
@ -212,7 +210,6 @@ except ImportError:
|
||||
texwidth,
|
||||
texheight,
|
||||
inverse,
|
||||
origin,
|
||||
add_color,
|
||||
mult_color,
|
||||
blendfunc,
|
||||
@ -244,7 +241,7 @@ except ImportError:
|
||||
for proc in procs:
|
||||
proc.join()
|
||||
|
||||
signal.signal(signal.SIGINT, original_handler)
|
||||
signal.signal(signal.SIGINT, previous_handler)
|
||||
if interrupted:
|
||||
raise KeyboardInterrupt()
|
||||
|
||||
@ -260,7 +257,6 @@ except ImportError:
|
||||
texwidth: int,
|
||||
texheight: int,
|
||||
inverse: Matrix,
|
||||
origin: Point,
|
||||
add_color: Tuple[int, int, int, int],
|
||||
mult_color: Color,
|
||||
blendfunc: int,
|
||||
@ -281,7 +277,7 @@ except ImportError:
|
||||
continue
|
||||
|
||||
# Calculate what texture pixel data goes here.
|
||||
texloc = inverse.multiply_point(Point(float(imgx), float(imgy))).add(origin)
|
||||
texloc = inverse.multiply_point(Point(float(imgx), float(imgy)))
|
||||
texx, texy = texloc.as_tuple()
|
||||
|
||||
# If we're out of bounds, don't update.
|
||||
|
@ -8,7 +8,6 @@ def affine_composite(
|
||||
add_color: Tuple[int, int, int, int],
|
||||
mult_color: Color,
|
||||
transform: Matrix,
|
||||
origin: Point,
|
||||
blendfunc: int,
|
||||
texture: Image.Image,
|
||||
single_threaded: bool = False,
|
||||
|
@ -39,7 +39,6 @@ cdef extern int affine_composite_fast(
|
||||
intcolor_t add_color,
|
||||
floatcolor_t mult_color,
|
||||
matrix_t inverse,
|
||||
point_t origin,
|
||||
int blendfunc,
|
||||
unsigned char *texdata,
|
||||
unsigned int texwidth,
|
||||
@ -52,7 +51,6 @@ def affine_composite(
|
||||
add_color: Tuple[int, int, int, int],
|
||||
mult_color: Color,
|
||||
transform: Matrix,
|
||||
origin: Point,
|
||||
blendfunc: int,
|
||||
texture: Image.Image,
|
||||
single_threaded: bool = False,
|
||||
@ -64,7 +62,6 @@ def affine_composite(
|
||||
# If this happens, that means one of the scaling factors was zero, making
|
||||
# this object invisible. We can ignore this since the object should not
|
||||
# be drawn.
|
||||
print(f"WARNING: Transform Matrix {transform} has zero scaling factor, making it non-invertible!")
|
||||
return img
|
||||
|
||||
if blendfunc not in {0, 2, 3, 8, 9, 70}:
|
||||
@ -79,10 +76,10 @@ def affine_composite(
|
||||
texheight = texture.height
|
||||
|
||||
# Calculate the maximum range of update this texture can possibly reside in.
|
||||
pix1 = transform.multiply_point(Point.identity().subtract(origin))
|
||||
pix2 = transform.multiply_point(Point.identity().subtract(origin).add(Point(texwidth, 0)))
|
||||
pix3 = transform.multiply_point(Point.identity().subtract(origin).add(Point(0, texheight)))
|
||||
pix4 = transform.multiply_point(Point.identity().subtract(origin).add(Point(texwidth, texheight)))
|
||||
pix1 = transform.multiply_point(Point.identity())
|
||||
pix2 = transform.multiply_point(Point.identity().add(Point(texwidth, 0)))
|
||||
pix3 = transform.multiply_point(Point.identity().add(Point(0, texheight)))
|
||||
pix4 = transform.multiply_point(Point.identity().add(Point(texwidth, texheight)))
|
||||
|
||||
# Map this to the rectangle we need to sweep in the rendering image.
|
||||
minx = max(int(min(pix1.x, pix2.x, pix3.x, pix4.x)), 0)
|
||||
@ -102,7 +99,6 @@ def affine_composite(
|
||||
cdef intcolor_t c_addcolor = intcolor_t(r=add_color[0], g=add_color[1], b=add_color[2], a=add_color[3])
|
||||
cdef floatcolor_t c_multcolor = floatcolor_t(r=mult_color.r, g=mult_color.g, b=mult_color.b, a=mult_color.a)
|
||||
cdef matrix_t c_inverse = matrix_t(a=inverse.a, b=inverse.b, c=inverse.c, d=inverse.d, tx=inverse.tx, ty=inverse.ty)
|
||||
cdef point_t c_origin = point_t(x=origin.x, y=origin.y)
|
||||
cdef unsigned int threads = 1 if single_threaded else multiprocessing.cpu_count()
|
||||
|
||||
# Call the C++ function.
|
||||
@ -117,7 +113,6 @@ def affine_composite(
|
||||
c_addcolor,
|
||||
c_multcolor,
|
||||
c_inverse,
|
||||
c_origin,
|
||||
blendfunc,
|
||||
texbytes,
|
||||
texwidth,
|
||||
|
@ -60,7 +60,6 @@ extern "C"
|
||||
unsigned int texwidth;
|
||||
unsigned int texheight;
|
||||
matrix_t inverse;
|
||||
point_t origin;
|
||||
intcolor_t add_color;
|
||||
floatcolor_t mult_color;
|
||||
int blendfunc;
|
||||
@ -213,7 +212,7 @@ extern "C"
|
||||
unsigned int imgoff = imgx + (imgy * work->imgwidth);
|
||||
|
||||
// Calculate what texture pixel data goes here.
|
||||
point_t texloc = work->inverse.multiply_point((point_t){(float)imgx, (float)imgy}).add(work->origin);
|
||||
point_t texloc = work->inverse.multiply_point((point_t){(float)imgx, (float)imgy});
|
||||
int texx = roundf(texloc.x);
|
||||
int texy = roundf(texloc.y);
|
||||
|
||||
@ -246,7 +245,6 @@ extern "C"
|
||||
intcolor_t add_color,
|
||||
floatcolor_t mult_color,
|
||||
matrix_t inverse,
|
||||
point_t origin,
|
||||
int blendfunc,
|
||||
unsigned char *texbytes,
|
||||
unsigned int texwidth,
|
||||
@ -270,7 +268,6 @@ extern "C"
|
||||
work.texwidth = texwidth;
|
||||
work.texheight = texheight;
|
||||
work.inverse = inverse;
|
||||
work.origin = origin;
|
||||
work.add_color = add_color;
|
||||
work.mult_color = mult_color;
|
||||
work.blendfunc = blendfunc;
|
||||
@ -312,7 +309,6 @@ extern "C"
|
||||
work->texwidth = texwidth;
|
||||
work->texheight = texheight;
|
||||
work->inverse = inverse;
|
||||
work->origin = origin;
|
||||
work->add_color = add_color;
|
||||
work->mult_color = mult_color;
|
||||
work->blendfunc = blendfunc;
|
||||
|
@ -434,15 +434,13 @@ class AFPRenderer(VerboseOutput):
|
||||
img: Image.Image,
|
||||
renderable: PlacedObject,
|
||||
parent_transform: Matrix,
|
||||
parent_origin: Point,
|
||||
only_depths: Optional[List[int]] = None,
|
||||
prefix: str="",
|
||||
) -> Image.Image:
|
||||
self.vprint(f"{prefix} Rendering placed object ID {renderable.object_id} from sprite {renderable.source.tag_id} onto Depth {renderable.depth}")
|
||||
|
||||
# Compute the affine transformation matrix for this object.
|
||||
transform = parent_transform.multiply(renderable.transform)
|
||||
origin = parent_origin.add(renderable.rotation_offset)
|
||||
transform = renderable.transform.multiply(parent_transform).translate(Point.identity().subtract(renderable.rotation_offset))
|
||||
|
||||
# Render individual shapes if this is a sprite.
|
||||
if isinstance(renderable, PlacedClip):
|
||||
@ -452,7 +450,7 @@ class AFPRenderer(VerboseOutput):
|
||||
key=lambda obj: obj.depth,
|
||||
)
|
||||
for obj in objs:
|
||||
img = self.__render_object(img, obj, transform, origin, only_depths=only_depths, prefix=prefix + " ")
|
||||
img = self.__render_object(img, obj, transform, only_depths=only_depths, prefix=prefix + " ")
|
||||
elif isinstance(renderable, PlacedShape):
|
||||
# This is a shape draw reference.
|
||||
shape = renderable.source
|
||||
@ -515,7 +513,7 @@ class AFPRenderer(VerboseOutput):
|
||||
(blend == 0 or blend == 2)
|
||||
):
|
||||
# We can!
|
||||
cutin = transform.multiply_point(Point.identity().subtract(origin))
|
||||
cutin = transform.multiply_point(Point.identity())
|
||||
cutoff = Point.identity()
|
||||
if cutin.x < 0:
|
||||
cutoff.x = -cutin.x
|
||||
@ -527,7 +525,7 @@ class AFPRenderer(VerboseOutput):
|
||||
img.alpha_composite(texture, cutin.as_tuple(), cutoff.as_tuple())
|
||||
else:
|
||||
# We can't, so do the slow render that's correct.
|
||||
img = affine_composite(img, add_color, mult_color, transform, origin, blend, texture, single_threaded=self.__single_threaded)
|
||||
img = affine_composite(img, add_color, mult_color, transform, blend, texture, single_threaded=self.__single_threaded)
|
||||
elif isinstance(renderable, PlacedDummy):
|
||||
# Nothing to do!
|
||||
pass
|
||||
@ -699,7 +697,7 @@ class AFPRenderer(VerboseOutput):
|
||||
# get the layering correct, but its important to preserve the original
|
||||
# insertion order for delete requests.
|
||||
curimage = Image.new("RGBA", actual_size, color=color.as_tuple())
|
||||
curimage = self.__render_object(curimage, root_clip, root_clip.transform, root_clip.rotation_offset, only_depths=only_depths)
|
||||
curimage = self.__render_object(curimage, root_clip, root_clip.transform, only_depths=only_depths)
|
||||
else:
|
||||
# Nothing changed, make a copy of the previous render.
|
||||
self.vprint(" Using previous frame render")
|
||||
|
@ -120,6 +120,17 @@ class Matrix:
|
||||
y=(self.b * point.x) + (self.d * point.y) + self.ty,
|
||||
)
|
||||
|
||||
def translate(self, point: Point) -> "Matrix":
|
||||
new_point = self.multiply_point(point)
|
||||
return Matrix(
|
||||
a=self.a,
|
||||
b=self.b,
|
||||
c=self.c,
|
||||
d=self.d,
|
||||
tx=new_point.x,
|
||||
ty=new_point.y,
|
||||
)
|
||||
|
||||
def multiply(self, other: "Matrix") -> "Matrix":
|
||||
return Matrix(
|
||||
a=self.a * other.a + self.b * other.c,
|
||||
|
Loading…
Reference in New Issue
Block a user