Sped up listing of paths a fair amount, added options for displaying size and number of frames.

This commit is contained in:
Jennifer Taylor 2021-05-29 03:41:25 +00:00
parent 1dbe51d96d
commit 161544e612
2 changed files with 78 additions and 39 deletions

View File

@ -476,6 +476,18 @@ class AFPRenderer(VerboseOutput):
raise Exception(f'{path} not found in registered SWFs!')
def compute_path_size(
self,
path: str,
) -> Rectangle:
# Given a path to a SWF root animation, figure out what the dimensions
# of the SWF are.
for name, swf in self.swfs.items():
if swf.exported_name == path:
return swf.location
raise Exception(f'{path} not found in registered SWFs!')
def list_paths(self, verbose: bool = False) -> Generator[str, None, None]:
# Given the loaded animations, return a list of possible paths to render.
for name, swf in self.swfs.items():
@ -1279,6 +1291,9 @@ class AFPRenderer(VerboseOutput):
# Calculate actual size based on given movie transform.
actual_size = movie_transform.multiply_point(Point(swf.location.width, swf.location.height)).as_tuple()
# TODO: If the location top/left is nonzero, we need move the root transform
# so that the correct viewport is rendered.
# Create a root clip for the movie to play.
root_clip = PlacedClip(
-1,

View File

@ -381,7 +381,7 @@ def parse_geo(geo: str, *, verbose: bool=False) -> int:
return 0
def load_containers(renderer: AFPRenderer, containers: List[str], verbose: bool) -> None:
def load_containers(renderer: AFPRenderer, containers: List[str], *, need_extras: bool, verbose: bool) -> None:
# This is a complicated one, as we need to be able to specify multiple
# directories of files as well as support IFS files and TXP2 files.
for container in containers:
@ -399,41 +399,42 @@ def load_containers(renderer: AFPRenderer, containers: List[str], verbose: bool)
if verbose:
print(f"Loading files out of TXP2 container {container}...", file=sys.stderr)
# First, load GE2D structures into the renderer.
for i, name in enumerate(afpfile.shapemap.entries):
shape = afpfile.shapes[i]
renderer.add_shape(name, shape)
if verbose:
print(f"Added {name} to SWF shape library.", file=sys.stderr)
# Now, split and load textures into the renderer.
sheets: Dict[str, Any] = {}
for i, name in enumerate(afpfile.regionmap.entries):
if i < 0 or i >= len(afpfile.texture_to_region):
raise Exception(f"Out of bounds region {i}")
region = afpfile.texture_to_region[i]
texturename = afpfile.texturemap.entries[region.textureno]
if texturename not in sheets:
for tex in afpfile.textures:
if tex.name == texturename:
sheets[texturename] = tex
break
else:
raise Exception("Could not find texture {texturename} to split!")
if sheets[texturename].img:
sprite = sheets[texturename].img.crop(
(region.left // 2, region.top // 2, region.right // 2, region.bottom // 2),
)
renderer.add_texture(name, sprite)
if need_extras:
# First, load GE2D structures into the renderer.
for i, name in enumerate(afpfile.shapemap.entries):
shape = afpfile.shapes[i]
renderer.add_shape(name, shape)
if verbose:
print(f"Added {name} to SWF texture library.", file=sys.stderr)
else:
print(f"Cannot load {name} from {texturename} because it is not a supported format!")
print(f"Added {name} to SWF shape library.", file=sys.stderr)
# Now, split and load textures into the renderer.
sheets: Dict[str, Any] = {}
for i, name in enumerate(afpfile.regionmap.entries):
if i < 0 or i >= len(afpfile.texture_to_region):
raise Exception(f"Out of bounds region {i}")
region = afpfile.texture_to_region[i]
texturename = afpfile.texturemap.entries[region.textureno]
if texturename not in sheets:
for tex in afpfile.textures:
if tex.name == texturename:
sheets[texturename] = tex
break
else:
raise Exception("Could not find texture {texturename} to split!")
if sheets[texturename].img:
sprite = sheets[texturename].img.crop(
(region.left // 2, region.top // 2, region.right // 2, region.bottom // 2),
)
renderer.add_texture(name, sprite)
if verbose:
print(f"Added {name} to SWF texture library.", file=sys.stderr)
else:
print(f"Cannot load {name} from {texturename} because it is not a supported format!")
# Finally, load the SWF data itself into the renderer.
for i, name in enumerate(afpfile.swfmap.entries):
@ -456,6 +457,9 @@ def load_containers(renderer: AFPRenderer, containers: List[str], verbose: bool)
print(f"Loading files out of IFS container {container}...", file=sys.stderr)
for fname in ifsfile.filenames:
if fname.startswith(f"geo{os.sep}"):
if not need_extras:
continue
# Trim off directory.
shapename = fname[(3 + len(os.sep)):]
@ -467,6 +471,9 @@ def load_containers(renderer: AFPRenderer, containers: List[str], verbose: bool)
if verbose:
print(f"Added {shapename} to SWF shape library.", file=sys.stderr)
elif fname.startswith(f"tex{os.sep}") and fname.endswith(".png"):
if not need_extras:
continue
# Trim off directory, png extension.
texname = fname[(3 + len(os.sep)):][:-4]
@ -493,12 +500,19 @@ def load_containers(renderer: AFPRenderer, containers: List[str], verbose: bool)
continue
def list_paths(containers: List[str], *, verbose: bool=False) -> int:
def list_paths(containers: List[str], *, include_frames: bool=False, include_size: bool=False, verbose: bool=False) -> int:
renderer = AFPRenderer()
load_containers(renderer, containers, verbose=verbose)
load_containers(renderer, containers, need_extras=False, verbose=verbose)
for path in renderer.list_paths(verbose=verbose):
print(path)
display = path
if include_size:
location = renderer.compute_path_size(path)
display = f"{display} - {int(location.width)}x{int(location.height)}"
if include_frames:
frames = renderer.compute_path_frames(path)
display = f"{display} - {frames} frames"
print(display)
return 0
@ -519,7 +533,7 @@ def render_path(
verbose: bool = False,
) -> int:
renderer = AFPRenderer(single_threaded=disable_threads)
load_containers(renderer, containers, verbose=verbose)
load_containers(renderer, containers, need_extras=True, verbose=verbose)
# Verify the correct params.
if output.lower().endswith(".gif"):
@ -919,6 +933,16 @@ def main() -> int:
nargs='+',
help="A container file to use for loading SWF data. Can be either a TXP2 or IFS container.",
)
list_parser.add_argument(
"--include-frames",
action="store_true",
help="Include number of frames per path in the output list.",
)
list_parser.add_argument(
"--include-size",
action="store_true",
help="Include width/height of the path in the output list.",
)
list_parser.add_argument(
"-v",
"--verbose",
@ -951,7 +975,7 @@ def main() -> int:
elif args.action == "parsegeo":
return parse_geo(args.geo, verbose=args.verbose)
elif args.action == "list":
return list_paths(args.container, verbose=args.verbose)
return list_paths(args.container, include_size=args.include_size, include_frames=args.include_frames, verbose=args.verbose)
elif args.action == "render":
return render_path(
args.container,