diff --git a/bemani/format/afp/blend.py b/bemani/format/afp/blend.py index 851c29f..46e6384 100644 --- a/bemani/format/afp/blend.py +++ b/bemani/format/afp/blend.py @@ -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. diff --git a/bemani/format/afp/blendalt.pyi b/bemani/format/afp/blendalt.pyi index 292d88c..3d2b2f7 100644 --- a/bemani/format/afp/blendalt.pyi +++ b/bemani/format/afp/blendalt.pyi @@ -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, diff --git a/bemani/format/afp/blendalt.pyx b/bemani/format/afp/blendalt.pyx index dd388c8..5fd6867 100644 --- a/bemani/format/afp/blendalt.pyx +++ b/bemani/format/afp/blendalt.pyx @@ -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, diff --git a/bemani/format/afp/blendaltimpl.cxx b/bemani/format/afp/blendaltimpl.cxx index a788da6..9b764ad 100644 --- a/bemani/format/afp/blendaltimpl.cxx +++ b/bemani/format/afp/blendaltimpl.cxx @@ -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; diff --git a/bemani/format/afp/render.py b/bemani/format/afp/render.py index 55ca78d..c00a4ad 100644 --- a/bemani/format/afp/render.py +++ b/bemani/format/afp/render.py @@ -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") diff --git a/bemani/format/afp/types/generic.py b/bemani/format/afp/types/generic.py index e663b5f..de53d47 100644 --- a/bemani/format/afp/types/generic.py +++ b/bemani/format/afp/types/generic.py @@ -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,