예제 #1
0
 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()
예제 #2
0
 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
예제 #3
0
    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
예제 #4
0
    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
예제 #5
0
    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
예제 #6
0
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()
예제 #7
0
    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
예제 #8
0
	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()
예제 #9
0
 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()
예제 #10
0
	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
예제 #11
0
 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
예제 #12
0
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
예제 #13
0
 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
예제 #14
0
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
예제 #15
0
 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
예제 #16
0
	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}")
예제 #17
0
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)
예제 #18
0
 def load_animations(self):
     with open(
             common.get_resource([self.resource_subpath, "manifests"],
                                 "animations.json")) as file:
         self.animations = json.load(file)
         file.close()
예제 #19
0
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")
예제 #20
0
    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
예제 #21
0
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
예제 #22
0
 def load_layout(self):
     self.layout = layoutlib.Layout(
         common.get_resource([self.resource_subpath, "manifests"],
                             "layout.json"))