1
0
mirror of synced 2025-02-07 15:01:21 +01:00

Add support for rendering only certain depth planes for debugging.

This commit is contained in:
Jennifer Taylor 2021-05-16 19:40:06 +00:00
parent 89af7c100a
commit 21ba1db898
2 changed files with 28 additions and 8 deletions

View File

@ -139,7 +139,7 @@ class AFPRenderer(VerboseOutput):
data.parse() data.parse()
self.swfs[name] = data self.swfs[name] = data
def render_path(self, path: str, background_color: Optional[Color] = None, verbose: bool = False) -> Tuple[int, List[Image.Image]]: def render_path(self, path: str, background_color: Optional[Color] = None, verbose: bool = False, only_depths: Optional[List[int]] = None) -> Tuple[int, List[Image.Image]]:
# Given a path to a SWF root animation or an exported animation inside a SWF, # Given a path to a SWF root animation or an exported animation inside a SWF,
# attempt to render it to a list of frames, one per image. # attempt to render it to a list of frames, one per image.
components = path.split(".") components = path.split(".")
@ -152,7 +152,7 @@ class AFPRenderer(VerboseOutput):
# This is the SWF we care about. # This is the SWF we care about.
with self.debugging(verbose): with self.debugging(verbose):
swf.color = background_color or swf.color swf.color = background_color or swf.color
return self.__render(swf, components[1] if len(components) > 1 else None) return self.__render(swf, components[1] if len(components) > 1 else None, only_depths=only_depths)
raise Exception(f'{path} not found in registered SWFs!') raise Exception(f'{path} not found in registered SWFs!')
@ -366,7 +366,15 @@ class AFPRenderer(VerboseOutput):
else: else:
raise Exception(f"Failed to process tag: {tag}") raise Exception(f"Failed to process tag: {tag}")
def __render_object(self, img: Image.Image, renderable: PlacedObject, parent_transform: Matrix, parent_origin: Point, prefix: str="") -> Image.Image: def __render_object(
self,
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}") 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. # Compute the affine transformation matrix for this object.
@ -390,7 +398,7 @@ class AFPRenderer(VerboseOutput):
key=lambda obj: obj.depth, key=lambda obj: obj.depth,
) )
for obj in objs: for obj in objs:
img = self.__render_object(img, obj, transform, parent_origin.add(renderable.rotation_offset), prefix=prefix + " ") img = self.__render_object(img, obj, transform, parent_origin.add(renderable.rotation_offset), only_depths=only_depths, prefix=prefix + " ")
elif isinstance(renderable, PlacedShape): elif isinstance(renderable, PlacedShape):
# This is a shape draw reference. # This is a shape draw reference.
shape = renderable.source shape = renderable.source
@ -405,6 +413,9 @@ class AFPRenderer(VerboseOutput):
if not (params.flags & 0x1): if not (params.flags & 0x1):
# Not instantiable, don't render. # Not instantiable, don't render.
return img return img
if only_depths is not None and renderable.depth not in only_depths:
# Not on the correct depth plane.
return img
if params.flags & 0x8: if params.flags & 0x8:
# TODO: Need to support blending and UV coordinate colors here. # TODO: Need to support blending and UV coordinate colors here.
@ -507,7 +518,7 @@ class AFPRenderer(VerboseOutput):
return None return None
def __render(self, swf: SWF, export_tag: Optional[str]) -> Tuple[int, List[Image.Image]]: def __render(self, swf: SWF, export_tag: Optional[str], only_depths: Optional[List[int]] = None) -> Tuple[int, List[Image.Image]]:
# If we are rendering an exported tag, we want to perform the actions of the # If we are rendering an exported tag, we want to perform the actions of the
# rest of the SWF but not update any layers as a result. # rest of the SWF but not update any layers as a result.
visible_tag = None visible_tag = None
@ -562,7 +573,7 @@ class AFPRenderer(VerboseOutput):
clip = self.__find_renderable(root_clip, visible_tag) clip = self.__find_renderable(root_clip, visible_tag)
if clip: if clip:
for obj in sorted(clip.placed_objects, key=lambda obj: obj.depth): for obj in sorted(clip.placed_objects, key=lambda obj: obj.depth):
curimage = self.__render_object(curimage, obj, root_clip.transform, root_clip.rotation_offset) curimage = self.__render_object(curimage, obj, root_clip.transform, root_clip.rotation_offset, only_depths=only_depths)
else: else:
# Nothing changed, make a copy of the previous render. # Nothing changed, make a copy of the previous render.
self.vprint(" Using previous frame render") self.vprint(" Using previous frame render")

View File

@ -267,6 +267,12 @@ def main() -> int:
default=None, default=None,
help="Set the background color of the animation as a comma-separated RGB or RGBA color, overriding a default if present in the SWF.", help="Set the background color of the animation as a comma-separated RGB or RGBA color, overriding a default if present in the SWF.",
) )
render_parser.add_argument(
"--only-depths",
type=str,
default=None,
help="Only render objects on these depth planes. Can provide either a number or a comma-separated list of numbers.",
)
render_parser.add_argument( render_parser.add_argument(
"--disable-threads", "--disable-threads",
action="store_true", action="store_true",
@ -293,7 +299,6 @@ def main() -> int:
help="Disable multi-threaded rendering.", help="Disable multi-threaded rendering.",
) )
args = parser.parse_args() args = parser.parse_args()
if args.action == "extract": if args.action == "extract":
@ -710,7 +715,11 @@ def main() -> int:
color = None color = None
# Render the gif/webp frames. # Render the gif/webp frames.
duration, images = renderer.render_path(args.path, verbose=args.verbose, background_color=color) if args.only_depths is not None:
depths = [int(d.strip()) for d in args.only_depths.split(",")]
else:
depths = None
duration, images = renderer.render_path(args.path, verbose=args.verbose, background_color=color, only_depths=depths)
if len(images) == 0: if len(images) == 0:
raise Exception("Did not render any frames!") raise Exception("Did not render any frames!")