def __init__(self, filename, manifest_dict, my_subpath): self.classic_name = manifest_dict["name"] #e.g. "Samus" or "Link" self.resource_subpath = my_subpath #the path to this sprite's subfolder in resources self.metadata = { "sprite.name": "", "author.name": "", "author.name-short": "" } self.filename = filename self.overview_scale_factor = 2 if "input" in manifest_dict and "png" in manifest_dict[ "input"] and "overview-scale-factor" in manifest_dict["input"][ "png"]: self.overview_scale_factor = manifest_dict["input"]["png"][ "overview-scale-factor"] self.plugins = None self.has_plugins = False self.layout = layoutlib.Layout( common.get_resource([self.resource_subpath, "manifests"], "layout.json")) with open( common.get_resource([self.resource_subpath, "manifests"], "animations.json")) as file: self.animations = json.load(file) file.close() self.import_from_filename()
def make_vcr_button(text="", icon_name=None, command=None, side=""): side = side if not side == "" else "right" icon_path = common.get_resource( ["meta", "icons"], icon_name if not icon_name == None else "blank.png") image = ImageTk.PhotoImage( Image.open(icon_path)) if icon_path else None if side == "right": side = tk.RIGHT elif side == "left": side = tk.LEFT else: side = tk.NONE vcr_button = tk.Button(control_section, image=image, text=text, compound=side, width=BUTTON_WIDTH, command=command) vcr_button.image = image vcr_button.grid(row=self.current_grid_cell // 3, column=1 + (self.current_grid_cell % 3), sticky=['nesw', 'nesw', 'nesw'][self.current_grid_cell % 3]) self.current_grid_cell += 1
def __init__(self, my_subpath, sprite): self.sprite = sprite self.resource_subpath = my_subpath #the path to this sprite's subfolder in resources self.spiffy_dict = { } #the variables created by the spiffy buttons will go here self.overhead = True #by default, this will create NESW direction buttons. If false, only left/right buttons self.overview_scale_factor = sprite.overview_scale_factor #when the overview is made, it is scaled up by this amount self.step_number_label = tk.Label() self.step_total_label = tk.Label() self.tiles_list_label = tk.Label() self.plugins = [] self.prev_palette_info = [] with open( common.get_resource([self.resource_subpath, "manifests"], "animations.json")) as file: self.animations = json.load(file) file.close() if "$schema" in self.animations: del self.animations["$schema"] self.current_animation = next( iter(self.animations.keys()) ) #using a default value until the animation_panel attachment overrides this
def get_spiffy_buttons(self, parent, fish): spiffy_buttons = widgetlib.SpiffyButtons(parent, self.resource_subpath, self) spiffy_manifest = common.get_resource( [self.resource_subpath, "manifests"], "spiffy-buttons.json") if spiffy_manifest: with open(spiffy_manifest) as f: spiffy_list = json.load(f) f.close() for group in spiffy_list["button-groups"]: group_key = group["group-fish-key"] button_group = spiffy_buttons.make_new_group( group_key, fish) button_list = [] for button in group["buttons"]: if "meta" in button and button["meta"] == "newline": button_list.append((None, None, None, None)) elif "meta" in button and button[ "meta"] == "blank": #a blank space, baby button_list.append((None, "", None, None)) else: default = button[ "default"] if "default" in button else False disabled = group[ "disabled"] if "disabled" in group else False button_list.append( (button["fish-subkey"], button["img"], default, disabled)) button_group.adds(button_list, fish) return spiffy_buttons
def get_direction_buttons(self, parent, fish): #if this is not overriden by the child (sprite-specific) class, then it will default to WASD layout for overhead, or just left/right if sideview (not overhead). direction_buttons = widgetlib.SpiffyButtons( parent, self.resource_subpath, self, frame_name="direction_buttons", align="center") direction_manifest = common.get_resource( [self.resource_subpath, "manifests"], "direction-buttons.json") if direction_manifest: with open(direction_manifest) as f: direction_list = json.load(f) f.close() for group in direction_list["button-groups"]: group_key = group["group-fish-key"] button_group = direction_buttons.make_new_group( group_key, fish) button_list = [] for button in group["buttons"]: if "meta" in button and button["meta"] == "newline": button_list.append((None, None, None, None)) elif "meta" in button and button[ "meta"] == "blank": #a blank space, baby button_list.append((None, "", None, None)) else: default = button[ "default"] if "default" in button else False disabled = group[ "disabled"] if "disabled" in group else False button_list.append( (button["fish-subkey"], button["img"], default, disabled)) button_group.adds(button_list, fish) else: facing_group = direction_buttons.make_new_group("facing", fish) if self.overhead: facing_group.adds( [ (None, "", None, None), #a blank space, baby ("up", "arrow-up.png", False, False), (None, "", None, None), #a blank space, baby (None, None, None, None) ], fish) facing_group.add("left", "arrow-left.png", fish) if self.overhead: facing_group.add("down", "arrow-down.png", fish) facing_group.add("right", "arrow-right.png", fish, default=True) return direction_buttons
def make_GUI(command_line_args): root = tk.Tk() try: root.iconbitmap(default=common.get_resource(["meta", "icons"], 'app.ico')) #Windows except Exception: try: root.tk.call( 'wm', 'iconphoto', root._w, tk.PhotoImage(file='@' + common.get_resource(["meta", "icons"], 'app.gif') )) #Linux? except Exception: try: root.tk.call('wm', 'iconphoto', root._w, tk.PhotoImage(file=common.get_resource( ["meta", "icons"], 'app.gif'))) #MacOSX? except Exception: pass #give up root.geometry("900x768") #window size root.configure(bg='#f0f0f0') #background color main_frame = SpriteSomethingMainFrame(root, command_line_args) root.protocol("WM_DELETE_WINDOW", main_frame.exit) #intercept when the user clicks the X def show_error(self, exception, message, callstack): if exception.__name__.upper() == "NOTIMPLEMENTEDERROR": messagebox.showerror( "Not Yet Implemented", "This function is not yet implemented\n\n" + str(message)) else: messagebox.showerror( "FATAL ERROR", f"While running, encountered fatal error:\n\n" + f"{exception.__name__.upper()}\n" + f"{str(message)}\n" + f"{traceback.format_exc()}") tk.Tk.report_callback_exception = show_error #tie this in so we see errors when they happen root.mainloop()
def get_representative_images(self, style="default"): if "sprite.name" in self.metadata and self.metadata["sprite.name"]: sprite_save_name = self.metadata["sprite.name"].lower() else: #FIXME: English sprite_save_name = "unknown" manifest_file = common.get_resource( [self.resource_subpath, "manifests"], "representative-images.json") if manifest_file: with open(manifest_file) as manifest: manifest_images = json.load(manifest) else: manifest_images = {} if "default" not in manifest_images: #try to have sane defaults animation = self.animations[0] #default to first image here direction = self.animations[animation].keys()[0] #first direction pose = 0 #first pose #by default, will use default palettes, without having any info supplied frame = 0 #probably won't matter, but just in case, use the first frame of palette if style in manifest_images: images = manifest_images[style] elif style == "default": images = [[]] #use defaults else: #FIXME: English raise AssertionError( f"received call to get_representative_image() with unknown style {style}" ) return_images = [] for image in images: animation = image[0] if image else self.animations[ 0] #default to first image here direction = image[1] if len(image) > 1 else self.animations[ animation].keys()[0] #default: first direction pose = image[2] if len(image) > 2 else 0 #default: #first pose palette = image[3] if len(image) > 3 else [ ] #defaults to the defaults determined by get_image frame = image[4] if len( image) > 4 else 0 #default to the first frame of timed palette filename = image[5] if len(image) > 5 else \ common.filename_scrub("-".join([sprite_save_name,style]) + ".png") #default to the sprite name and style return_images.append((filename, self.get_image(animation, direction, pose, palette, frame)[0])) #should return a list of tuples of the form (filename, PIL Image) return return_images
def add_translation_file(self,subpath=["meta"]): if not isinstance(subpath, list): subpath = [subpath] subpath.append("lang") #look in lang folder subpath = os.path.join(*subpath) #put in path separators for lang in self.langs: if not lang in self.lang_defns: self.lang_defns[lang] = {} langs_filename = common.get_resource(subpath,lang + ".json") #get filename of translation file if langs_filename: #if we've got a file with open(langs_filename,encoding="utf-8") as f: #open it self.lang_defns[lang][subpath[:subpath.rfind(os.sep)].replace(os.sep,'.')] = json.load(f) #save translation definitions f.close()
def attach_both_panels(self): #this same function can also be used to re-create the panels #have to make the canvas before the buttons so that the left panel buttons can manipulate it self.freeze_ray = True #do not update the sprite while doing this if hasattr(self, "timer_callback"): self.master.after_cancel(self.timer_callback) if hasattr(self, "left_panel"): for widget in self.left_panel.winfo_children(): #if we've got direction buttons if "direction_buttons" in widget.winfo_name(): #get the main bindings file bindings = None bindings_filename = common.get_resource( ["meta", "manifests"], "bindings.json") with open(bindings_filename, encoding="utf-8") as f: bindings = json.load(f) f.close() #cycle through all spiffy buttons for subwidget in widget.winfo_children(): if "_button" in subwidget.winfo_name(): button_name = subwidget.winfo_name().replace( "_button", "") button_section = button_name[:button_name.find("_" )] button_name = button_name[button_name.find("_") + 1:] keypresses = None keypresses_switcher = bindings[button_section] if button_section in bindings else {} keypresses = keypresses_switcher.get( button_name.lower(), None) if keypresses: #nuke all the bindings from orbit for keypress in keypresses: subwidget.unbind_all(keypress) #nuke this button from orbit subwidget.destroy() self.left_panel = tk.PanedWindow(self.panes, orient=tk.VERTICAL, name="left_panel", width=320, handlesize=0, sashwidth=0, sashpad=2) self.right_panel = ttk.Notebook(self.panes, name="right_pane") self.canvas = tk.Canvas(self.right_panel, name="main_canvas") self.overview_frame = tk.Frame(self.right_panel, name="overview_frame") self.overview_canvas = tk.Canvas(self.overview_frame, name="overview_canvas") self.attach_left_panel() self.attach_right_panel() self.create_status_bar()
def set_background(self, image_title): if self.current_background_title == image_title: if self.last_known_zoom == self.zoom_getter(): return #there is nothing to do here, because nothing has changed else: #image name is different, so need to load a new image image_filename = self.background_datas["title"][image_title] self.raw_background = Image.open(common.get_resource([self.internal_name,"backgrounds"],image_filename)) #now re-zoom the image new_size = tuple(int(dim*self.zoom_getter()) for dim in self.raw_background.size) self.background_image = gui_common.get_tk_image(self.raw_background.resize(new_size,resample=Image.NEAREST)) if self.current_background_title is None: self.background_ID = self.canvas.create_image(0, 0, image=self.background_image, anchor=tk.NW) #so that we can manipulate the object later else: self.canvas.itemconfig(self.background_ID, image=self.background_image) self.last_known_zoom = self.zoom_getter() self.current_background_title = image_title
def make_vcr_label(textvariable, icon_name=None): icon_path = common.get_resource( ["meta", "icons"], icon_name if not icon_name == None else "blank.png") image = ImageTk.PhotoImage( Image.open(icon_path)) if icon_path else None vcr_label = tk.Label(control_section, image=image, anchor='e', compound="left", width=BUTTON_WIDTH, textvariable=textvariable) vcr_label.grid(row=self.current_grid_cell // 3, column=1 + (self.current_grid_cell % 3), sticky=['nes']) self.current_grid_cell += 1 return vcr_label
def autodetect_game_type_from_rom(rom): rom_name = rom.get_name() with open(common.get_resource(["meta","manifests"],"game_header_info.json")) as file: game_header_info = json.load(file) file.close() game_names = [] for game_name, header_name_list in game_header_info.items(): for header_name in header_name_list: if rom_name[:len(header_name)] == header_name: game_names.append(game_name) if len(game_names) == 0: game_names = None #raise AssertionError(f"Could not identify the type of ROM from its header name: {rom_name}") print(f"Could not identify the type of ROM from its header name: {rom_name}") return game_names
def create_cascade(self, name, internal_name, options_list, parent_menu=None): #options_list must be a list of 3-tuples containing # Display Name # image name (without the .png extension) # function to call if parent_menu == None: parent_menu = self.menu cascade = tk.Menu(parent_menu, tearoff=0, name=internal_name) cascade.images = {} for display_name, image_name, function_to_call in options_list: if (display_name, image_name, function_to_call) == (None, None, None): cascade.add_separator() else: if image_name: image_filename = (f"{image_name}") image_filename += ".gif" if "gif" in image_filename else ".png" image_path = os.path.join("meta", "icons") if "game_plugins" in internal_name: image_path = os.path.join(self.game.resource_subpath, "icons") if "sprite_plugins" in internal_name: image_path = os.path.join(self.sprite.resource_subpath, "icons") cascade.images[image_name] = ImageTk.PhotoImage( Image.open( common.get_resource(image_path, image_filename))) else: cascade.images[image_name] = None cascade.add_command( label=display_name, image=cascade.images[image_name], compound=tk.LEFT, command=function_to_call, state="disabled" if function_to_call == None else "normal") parent_menu.add_cascade(label=name, menu=cascade) return cascade
def create_chooser(game_names): def choose_game(game_name): game_selector.set(game_name) game_chooser.destroy() selected_game = None if len(game_names) > 1: game_chooser = tk.Toplevel() #FIXME: English game_chooser.title("Choose Sprite to Extract") game_chooser.geometry("320x100") game_selector = tk.StringVar(game_chooser) game_buttons = [] i = 1 for game_name in game_names: sprite_name = "" with open( common.get_resource([game_name, "manifests"], "manifest.json")) as f: manifest = json.load(f) f.close() sprite_name = manifest["1"]["name"] game_button = tk.Button(game_chooser, width=16, height=1, text=sprite_name, command=partial(choose_game, game_name)) game_button.grid(row=1, column=i, sticky=tk.NSEW) game_buttons.append(game_button) i += 1 game_chooser.grid_rowconfigure(0, weight=1) game_chooser.grid_rowconfigure(2, weight=1) game_chooser.grid_columnconfigure(0, weight=1) game_chooser.grid_columnconfigure(i, weight=1) game_chooser.wait_window() selected_game = game_selector.get() else: selected_game = random.choice(game_names) return selected_game
def create_toolbar_button(fish_key, fish_subkey, image_filename=None, command=None): icon_path = common.get_resource( ["meta", "icons"], image_filename if not image_filename == None else "blank.png") img = ImageTk.PhotoImage( Image.open(icon_path)) if icon_path else None display_text = self.fish.translate("meta", fish_key, fish_subkey) button = tk.Button( toolbar, image=img, relief=tk.FLAT, width=16, height=16, command=command, state="disabled" if command == None else "normal") button.img = img widgetlib.ToolTip(button, display_text) button.pack(side=tk.LEFT, padx=2, pady=2) return button
def make_sprite_by_number(self, sprite_number, sprite_filename): #go into the manifest and get the actual name of the sprite with open(common.get_resource([self.internal_name,"manifests"],"manifest.json")) as file: manifest = json.load(file) file.close() if str(sprite_number) in manifest: folder_name = manifest[str(sprite_number)]["folder name"] #dynamic imports to follow source_subpath = f"source.{self.internal_name}.{folder_name}" sprite_module = importlib.import_module(f"{source_subpath}.sprite") resource_subpath = os.path.join(self.internal_name,folder_name) sprite = sprite_module.Sprite(sprite_filename,manifest[str(sprite_number)],resource_subpath) try: animationlib = importlib.import_module(f"{source_subpath}.animation") animation_assist = animationlib.AnimationEngine(resource_subpath, sprite) except ImportError: #there was no sprite-specific animation library, so import the parent animationlib = importlib.import_module(f"source.animationlib") animation_assist = animationlib.AnimationEngineParent(resource_subpath, sprite) return sprite, animation_assist else: raise AssertionError(f"make_sprite_by_number() called for non-implemented sprite_number {sprite_number}")
from source import common APP_VERSION = "" app_version_filename = common.get_resource(["meta","manifests"],"app_version.txt") with(open(app_version_filename)) as f: APP_VERSION = f.read() f.close() MAX_FRAMES = 1E9 #maximum number of frames an animation will display before it stops DEBUG_MODE = True #adds some extra checks that are useful for development purposes (to unset this, just comment out this line, don't set to false)
def load_animations(self): with open( common.get_resource([self.resource_subpath, "manifests"], "animations.json")) as file: self.animations = json.load(file) file.close()
def equipment_test(): #get equipment image equipment_image = Image.open( common.get_resource(["zelda3", "link", "sheets"], "equipment.png")) equipment = {} #collect icon names & coordinates icon_specs = {} #the swords are at the same x-coordinate but have differing y-values, set up these y-values swords = [("fighter", 0), ("master", 32), ("tempered", 64), ("gold", 96)] #tuples for fun stuff; first is top-left origin, second is width,height coords = [((0, 0), (8, 16)), ((8, 0), (8, 16)), ((16, 0), (16, 16)), ((32, 0), (16, 16)), ((48, 0), (19, 8)), ((48, 8), (16, 8)), ((64, 8), (16, 8)), ((80, 0), (16, 16)), ((96, 0), (16, 16)), ((112, 6), (16, 18)), ((128, 3), (8, 21)), ((136, 0), (8, 16)), ((144, 0), (16, 16)), ((160, 0), (16, 8))] #cycle through coordinate info for i in range(len(coords)): #cycle through swords and y-offsets for j in range(len(swords)): origin, dims = coords[i] x, y = origin level, y_offset = swords[j] icon_specs[level + "_sword" + str(i)] = coord_calc( (x, y + y_offset), dims) #next row is some inventory stuff inventory = { "main_shadow": ((0, 112), (16, 16)), "small_shadow": ((16, 112), (16, 16)), "book": ((32, 112), (16, 16)), "bush": ((48, 112), (16, 16)), "pendant": ((64, 112), (16, 16)), "crystal": ((80, 112), (16, 16)) } #add some inventory stuff for key in inventory: origin, dims = inventory[key] icon_specs[key] = coord_calc(origin, dims) #shields shields = [("fighter", 0), ("fire", 16), ("mirror", 32)] #cycle through x-coordinates for i in range(4): #cycle through shields and y-offsets for j in range(len(shields)): level, y_offset = shields[j] origin = (i * 16, 128 + y_offset) icon_specs[level + "_shield" + str(i)] = coord_calc( origin, (16, 16)) inventory = { "cane0": ((0, 176), (8, 16)), #vertical "cane1": ((8, 176), (8, 16)), #vertical "cane2": ((16, 176), (16, 8)), #horizontal "cane3": ((32, 176), (16, 16)), #diagonal ltr "cane4": ((48, 176), (8, 16)), #vertical "somaria_block": ((64, 176), (16, 16)), "rod0": ((0, 192), (8, 16)), #vertical "rod1": ((8, 192), (8, 16)), #vertical "rod2": ((16, 192), (16, 8)), #horizontal "rod3": ((16, 200), (8, 8)), #fourth-wall NtS "rod4": ((32, 192), (16, 16)), #diagonal ltr "rod5": ((48, 192), (8, 16)), #vertical "hammer0": ((0, 208), (8, 16)), #vertical ltr "hammer1": ((8, 208), (8, 16)), #vertical "hammer2": ((16, 208), (8, 16)), #vertical "hammer3": ((24, 208), (8, 16)), #vertical "hammer4": ((32, 208), (16, 8)), #horizontal "hammer5": ((32, 216), (8, 8)), #vertical "hammer6": ((48, 208), (16, 16)), #diagonal ltr "hook0": ((0, 224), (8, 8)), #horizontal "hook1": ((8, 224), (8, 8)), #vertical "hook2": ((0, 232), (16, 8)), #vertical "hook3": ((16, 232), (8, 8)), #chainlink "hook4": ((24, 224), (8, 16)), #horizontal "boom": ((32, 224), (16, 16)), #NE "bow0": ((0, 256), (8, 16)), "bow1": ((16, 256), (16, 8)), "bow2": ((32, 256), (16, 16)), "shovel0": ((0, 272), (8, 8)), #down "shovel1": ((16, 272), (8, 8)), #up "swagduck0": ((32, 272), (16, 16)), "swagduck1": ((48, 272), (16, 16)), #flap "bed0": ((0, 288), (32, 32)), "bed1": ((32, 288), (32, 32)), "tall_grass0": ((0, 320), (16, 8)), "tall_grass1": ((0, 328), (16, 8)), "tall_grass2": ((16, 320), (16, 8)) } #add more inventory stuff for key in inventory: origin, dims = inventory[key] icon_specs[key] = coord_calc(origin, dims) #add bugnet for i in range(7): icon_specs["bugnet" + str(i)] = coord_calc((i * 16, 240), (16, 16)) #cycle through collected icons and write to disk for icon in icon_specs: icon_coords = icon_specs.get(icon) cropped_image = equipment_image.crop(icon_coords) equipment[icon] = cropped_image cropped_image.save("./user_resources/zelda3/link/sheets/" + icon + ".png")
def add(self, internal_value_name, image_filename, fish, default=False, disabled=False): if image_filename == None: image_filename == "blank.png" #disable sprite object in widgetlib icon_path = common.get_resource( [self.sprite_resource_subpath, "icons"], image_filename ) #common.get_resource([self.parent.animation_engine.resource_subpath,"icons"],image_filename) if icon_path is None: icon_path = common.get_resource(["meta", "icons"], image_filename) if icon_path is None: #FIXME: English raise AssertionError( f"No image resource found with name {image_filename}") img = ImageTk.PhotoImage(Image.open(icon_path)) #disable sprite object in widgetlib display_text = fish.translate( self.sprite_resource_subpath.replace(os.sep, '.'), self.label, internal_value_name ) #fish.translate(self.parent.animation_engine.resource_subpath, self.label, internal_value_name) button = tk.Radiobutton( self.parent.spiffy_buttons_section, image=img, name="_".join([self.label.lower(), internal_value_name, "button"]), text=display_text, variable=self.var, value=internal_value_name, activebackground=self.parent.DIMENSIONS["button"]["color.active"], selectcolor=self.parent.DIMENSIONS["button"]["color.selected"], width=self.parent.DIMENSIONS["button"]["width"], height=self.parent.DIMENSIONS["button"]["height"], indicatoron=False, command=self.press_spiffy_button) if disabled: button.configure(state="disabled") bindings = None keypresses = None bindings_filename = common.get_resource(["meta", "manifests"], "bindings.json") with open(bindings_filename, encoding="utf-8") as f: bindings = json.load(f) f.close() keypresses_switcher = bindings[ self.label.lower()] if self.label.lower() in bindings else {} keypresses = keypresses_switcher.get(internal_value_name.lower(), None) if keypresses: for keypress in keypresses: button.bind_all(keypress, partial(self.invoke_spiffy_button, button)) ToolTip(button, display_text) button.image = img button.grid(row=self.row, column=self.col) if not self.default_exists or default: button.select() self.press_spiffy_button() self.default_exists = True self.col += 1
def equipment_test(save=False): #get equipment image equipment_image = Image.open( common.get_resource(["metroid3", "samus", "sheets"], "equipment.png")) equipment = {} #collect icon names & coordinates icon_specs = {} #lemons, missiles, supers projectiles = { "lemon_right": [(0, 0), (16, 16)], #left: h-flip "lemon_upright": [(16, 0), (16, 16)], #downright: v-flip; upleft: h-flip; downleft: both "lemon_up": [(32, 0), (16, 16)], #down: v-flip "missile_right": [(48, 0), (16, 16)], #left: h-flip "missile_upright": [(64, 0), (16, 16)], #downright: v-flip, upleft: h-flip; downleft: both "missile_up": [(80, 0), (16, 16)], #down: v-flip "super_right": [(96, 0), (16, 16)], #left: h-flip "super_upright": [(112, 0), (16, 16)], #downright: v-flip; upleft: h-flip; downleft: both "super_up": [(128, 0), (16, 16)] #down: v-flip } for k, v in projectiles.items(): icon_specs[k] = coord_calc(v[0], v[1]) #morph ball bombs for i in range(3): icon_specs["mbb" + str(i)] = coord_calc((144 + (8 * i), 0), (8, 8)) #powerbombs for i in range(3): icon_specs["pb" + str(i)] = coord_calc((144 + (8 * i), 8), (8, 8)) #poof cloud for i in range(3): icon_specs["poof" + str(i)] = coord_calc((144 + (8 * i), 16), (8, 8)) #morph ball bombs blast for i in range(3): for j in range(2): w = 32 h = 32 x1 = 176 + (w * j) x2 = 0 + (h * i) id = (i * 2) + (j * 1) if (id < 5): icon_specs["mbb_blast" + str(id)] = coord_calc((x1, x2), (w, h)) #charg[ing|ed] lemon for i in range(6): w = 16 h = 16 x1 = 0 + (w * i) x2 = 16 icon_specs["charge" + str(i)] = coord_calc((x1, x2), (w, h)) #iced lemon for i in range(3): w = 16 h = 16 x1 = 64 + (w * i) x2 = 48 icon_specs["ice" + str(i)] = coord_calc((x1, x2), (w, h)) #iced particles for i in range(4): w = 16 h = 16 x1 = 80 + (w * i) x2 = 32 icon_specs["ice_particle" + str(i)] = coord_calc((x1, x2), (w, h)) #charged ice for i in range(2): w = 16 h = 16 x1 = 112 + (w * i) x2 = 48 icon_specs["charge_ice" + str(i)] = coord_calc((x1, x2), (w, h)) #spazer icon_specs["spazer0"] = coord_calc((112, 16), (9, 2)) #from blaster icon_specs["spazer1"] = coord_calc( (112, 19), (18, 2)) #repeated; #FIXME: Get number of repeats #plasma icon_specs["plasma0"] = coord_calc((128, 16), (5, 3)) #from blaster icon_specs["plasma1"] = coord_calc( (134, 16), (4, 3)) #repeated; #FIXME: Get number of repeats #charged spazer icon_specs["charge_spazer0"] = coord_calc((112, 22), (5, 2)) #from blaster #charged plasma #charged spazer/plasma (none/ice/wave) icon_specs["charge_special0"] = coord_calc( (128, 22), (8, 7)) #repeated; #FIXME: Get number of repeats #wave lemon for i in range(5): w = 16 h = 16 x1 = 0 + (w * i) x2 = 32 icon_specs["wave" + str(i)] = coord_calc((x1, x2), (w, h)) #cycle through collected icons and write to disk for icon in icon_specs: icon_coords = icon_specs.get(icon) cropped_image = equipment_image.crop(icon_coords) equipment[icon] = cropped_image if save: cropped_image.save("./user_resources/metroid3/samus/sheets/" + icon + ".png") return equipment
def load_layout(self): self.layout = layoutlib.Layout( common.get_resource([self.resource_subpath, "manifests"], "layout.json"))