From 6bf4dd60d40bc7b0677669a9ba5f5a872369fee0 Mon Sep 17 00:00:00 2001 From: Jared Miller Date: Thu, 12 Feb 2026 19:50:51 -0500 Subject: [PATCH] Convert percent formatting to f-strings --- art.py | 63 ++++++++--------- art_export.py | 6 +- art_import.py | 4 +- camera.py | 2 +- charset.py | 36 +++++++--- collision.py | 10 +-- cursor.py | 7 +- edit_command.py | 14 ++-- formats/in_bitmap.py | 4 +- formats/in_bitmap_sequence.py | 9 +-- formats/out_png.py | 2 +- formats/out_png_set.py | 8 +-- game_object.py | 42 ++++++------ game_room.py | 20 +++--- game_util_objects.py | 15 +++-- game_world.py | 62 ++++++++--------- games/crawler/scripts/player.py | 2 +- games/fireplace/scripts/fireplace.py | 10 +-- games/flood/scripts/game.py | 2 +- games/maze/scripts/objects.py | 6 +- games/wildflowers/scripts/flower.py | 2 +- games/wildflowers/scripts/frond.py | 5 +- games/wildflowers/scripts/petal.py | 9 +-- games/wildflowers/scripts/wildflowers.py | 2 +- image_convert.py | 7 +- image_export.py | 5 +- input_handler.py | 25 ++++--- palette.py | 33 +++++---- playscii.py | 86 +++++++++++++----------- renderable.py | 15 +++-- renderable_line.py | 6 +- renderable_sprite.py | 2 +- shader.py | 26 ++++--- ui.py | 17 +++-- ui_art_dialog.py | 12 ++-- ui_button.py | 14 ++-- ui_chooser_dialog.py | 2 +- ui_console.py | 18 +++-- ui_edit_panel.py | 4 +- ui_element.py | 11 +-- ui_file_chooser_dialog.py | 14 ++-- ui_game_menu_pulldown_item.py | 2 +- ui_info_dialog.py | 2 +- ui_menu_bar.py | 2 +- ui_menu_pulldown.py | 4 +- ui_menu_pulldown_item.py | 48 ++++++------- ui_object_panel.py | 8 +-- ui_popup.py | 22 +++--- ui_status_bar.py | 20 +++--- ui_swatch.py | 4 +- ui_tool.py | 10 +-- vector.py | 2 +- 52 files changed, 416 insertions(+), 347 deletions(-) diff --git a/art.py b/art.py index afbef4f..dfdd3a5 100644 --- a/art.py +++ b/art.py @@ -107,8 +107,8 @@ class Art: def __init__(self, filename, app, charset, palette, width, height): "Creates a new, blank document with given parameters." self.valid = False - if filename and not filename.endswith(".%s" % ART_FILE_EXTENSION): - filename += ".%s" % ART_FILE_EXTENSION + if filename and not filename.endswith(".{}".format(ART_FILE_EXTENSION)): + filename += ".{}".format(ART_FILE_EXTENSION) self.filename = filename self.app = app # save "time loaded" for menu sorting @@ -162,11 +162,11 @@ class Art: def log_init(self): self.app.log("created new document:") - self.app.log(" character set: %s" % self.charset.name) - self.app.log(" palette: %s" % self.palette.name) - self.app.log(" width/height: %s x %s" % (self.width, self.height)) - self.app.log(" frames: %s" % self.frames) - self.app.log(" layers: %s" % self.layers) + self.app.log(" character set: {}".format(self.charset.name)) + self.app.log(" palette: {}".format(self.palette.name)) + self.app.log(" width/height: {} x {}".format(self.width, self.height)) + self.app.log(" frames: {}".format(self.frames)) + self.app.log(" layers: {}".format(self.layers)) def init_layers(self): self.layers = 1 @@ -219,7 +219,7 @@ class Art: if self.app.ui and self is self.app.ui.active_art: self.app.ui.set_active_frame(index) if log: - self.app.log("Created new frame at index %s" % str(index)) + self.app.log("Created new frame at index {}".format(str(index))) def add_frame_to_end(self, delay=DEFAULT_FRAME_DELAY, log=True): "Add a blank frame at the end of the current animation." @@ -246,7 +246,9 @@ class Art: if self is self.app.ui.active_art: self.app.ui.set_active_frame(dest_frame_index - 1) self.app.log( - "Duplicated frame %s at frame %s" % (src_frame_index + 1, dest_frame_index) + "Duplicated frame {} at frame {}".format( + src_frame_index + 1, dest_frame_index + ) ) def delete_frame_at(self, index): @@ -306,7 +308,7 @@ class Art: z = z if z is not None else self.layers_z[src_index] self.layers_z.append(z) self.layers_visibility.append(True) - new_name = new_name or "Copy of %s" % self.layer_names[src_index] + new_name = new_name or "Copy of {}".format(self.layer_names[src_index]) self.layer_names.append(new_name) # rebuild geo with added verts for new layer self.geo_changed = True @@ -315,7 +317,7 @@ class Art: self.app.ui.set_active_layer(self.layers - 1) # don't log new layers created on the fly in game mode if not self.app.game_mode: - self.app.log("Added new layer %s" % new_name) + self.app.log("Added new layer {}".format(new_name)) self.set_unsaved_changes(True) def clear_frame_layer(self, frame, layer, bg_color=0, fg_color=None): @@ -366,7 +368,7 @@ class Art: self.geo_changed = True if log: self.app.ui.message_line.post_line( - "Character set changed to %s" % self.charset.name + "Character set changed to {}".format(self.charset.name) ) def set_charset_by_name(self, new_charset_name): @@ -382,7 +384,7 @@ class Art: self.set_unsaved_changes(True) if log: self.app.ui.message_line.post_line( - "Color palette changed to %s" % self.palette.name + "Color palette changed to {}".format(self.palette.name) ) def set_palette_by_name(self, new_palette_name): @@ -871,7 +873,7 @@ class Art: end_time = time.time() self.set_unsaved_changes(False) # self.app.log('saved %s to disk in %.5f seconds' % (self.filename, end_time - start_time)) - self.app.log("saved %s" % self.filename) + self.app.log("saved {}".format(self.filename)) # remove old thumbnail thumb_dir = self.app.cache_dir + THUMBNAIL_CACHE_DIR if os.path.exists(self.filename): @@ -936,8 +938,9 @@ class Art: json.dump(d, open(self.filename + "2", "w"), sort_keys=True, indent=None) end_time = time.time() self.app.log( - "ALT saved %s to disk in %.5f seconds" - % (self.filename, end_time - start_time) + "ALT saved {} to disk in {:.5f} seconds".format( + self.filename, end_time - start_time + ) ) def set_unsaved_changes(self, new_status): @@ -985,13 +988,13 @@ class Art: exec(open(script_filename).read()) # (assume script changed art) self.unsaved_changes = True - logline = "Executed %s" % script_filename + logline = "Executed {}".format(script_filename) if log: self.app.log(logline) error = False except Exception: error = True - logline = "Error executing %s:" % script_filename + logline = "Error executing {}:".format(script_filename) self.app.log(logline) # skip first 3 lines of callstack before artscript exec for line in traceback.format_exc().split("\n")[3:]: @@ -1021,7 +1024,7 @@ class Art: if not script_filename: return if script_filename in self.scripts: - self.app.log("script %s is already running." % script_filename) + self.app.log("script {} is already running.".format(script_filename)) return # add to "scripts currently running" list self.scripts.append(script_filename) @@ -1037,7 +1040,7 @@ class Art: if not script_filename: return if script_filename not in self.scripts: - self.app.log("script %s exists but isn't running." % script_filename) + self.app.log("script {} exists but isn't running.".format(script_filename)) return script_index = self.scripts.index(script_filename) self.scripts.pop(script_index) @@ -1208,11 +1211,11 @@ class ArtFromDisk(Art): height = d["height"] charset = app.load_charset(d["charset"]) if not charset: - app.log("Character set %s not found!" % d["charset"]) + app.log("Character set {} not found!".format(d["charset"])) return palette = app.load_palette(d["palette"]) if not palette: - app.log("Palette %s not found!" % d["palette"]) + app.log("Palette {} not found!".format(d["palette"])) return # store loaded data for init_layers/frames self.loaded_data = d @@ -1240,12 +1243,12 @@ class ArtFromDisk(Art): self.valid = True def log_init(self): - self.app.log("Loaded %s from disk:" % filename) - self.app.log(" character set: %s" % self.charset.name) - self.app.log(" palette: %s" % self.palette.name) - self.app.log(" width/height: %s x %s" % (self.width, self.height)) - self.app.log(" frames: %s" % self.frames) - self.app.log(" layers: %s" % self.layers) + self.app.log("Loaded {} from disk:".format(filename)) + self.app.log(" character set: {}".format(self.charset.name)) + self.app.log(" palette: {}".format(self.palette.name)) + self.app.log(" width/height: {} x {}".format(self.width, self.height)) + self.app.log(" frames: {}".format(self.frames)) + self.app.log(" layers: {}".format(self.layers)) def init_layers(self): frames = self.loaded_data["frames"] @@ -1256,7 +1259,7 @@ class ArtFromDisk(Art): self.layers_z.append(layer["z"]) self.layers_visibility.append(bool(layer.get("visible", 1))) layer_num = str(i + 1) - self.layer_names.append(layer.get("name", "Layer %s" % layer_num)) + self.layer_names.append(layer.get("name", "Layer {}".format(layer_num))) active_layer = self.loaded_data.get("active_layer", 0) self.set_active_layer(active_layer) @@ -1312,7 +1315,7 @@ class ArtInstance(Art): def __init__(self, source): self.source = source # unique(?) filename - self.filename = "%s_Instance%i" % (source.filename, time.time()) + self.filename = f"{source.filename}_Instance{time.time()}" self.app = source.app self.instances = None self.char_changed_frames, self.uv_changed_frames = {}, {} diff --git a/art_export.py b/art_export.py index 92282e8..9ca0c42 100644 --- a/art_export.py +++ b/art_export.py @@ -24,9 +24,9 @@ class ArtExporter: self.art = self.app.ui.active_art # add file extension to output filename if not present if self.file_extension and not out_filename.endswith( - ".%s" % self.file_extension + ".{}".format(self.file_extension) ): - out_filename += ".%s" % self.file_extension + out_filename += ".{}".format(self.file_extension) # output filename in documents/art dir if not out_filename.startswith(self.app.documents_dir + ART_DIR): out_filename = self.app.documents_dir + ART_DIR + out_filename @@ -41,7 +41,7 @@ class ArtExporter: if self.run_export(out_filename, options): self.success = True else: - line = "%s failed to export %s, see console for errors" % ( + line = "{} failed to export {}, see console for errors".format( self.__class__.__name__, out_filename, ) diff --git a/art_import.py b/art_import.py index d5c9303..029deb6 100644 --- a/art_import.py +++ b/art_import.py @@ -32,7 +32,9 @@ class ArtImporter: def __init__(self, app, in_filename, options={}): self.app = app - new_filename = "%s.%s" % (os.path.splitext(in_filename)[0], ART_FILE_EXTENSION) + new_filename = "{}.{}".format( + os.path.splitext(in_filename)[0], ART_FILE_EXTENSION + ) self.art = self.app.new_art(new_filename) # use charset and palette of existing art charset = ( diff --git a/camera.py b/camera.py index 40b014a..34098af 100644 --- a/camera.py +++ b/camera.py @@ -313,4 +313,4 @@ class Camera: self.mouse_panned = False def log_loc(self): - self.app.log("camera x=%s, y=%s, z=%s" % (self.x, self.y, self.z)) + self.app.log("camera x={}, y={}, z={}".format(self.x, self.y, self.z)) diff --git a/charset.py b/charset.py index f41eeed..3522504 100644 --- a/charset.py +++ b/charset.py @@ -34,16 +34,23 @@ class CharacterSetLord: success = charset.load_char_data() if success: self.app.log( - "CharacterSetLord: success reloading %s" % charset.filename + "CharacterSetLord: success reloading {}".format( + charset.filename + ) ) else: self.app.log( - "CharacterSetLord: failed reloading %s" % charset.filename, + "CharacterSetLord: failed reloading {}".format( + charset.filename + ), True, ) except: self.app.log( - "CharacterSetLord: failed reloading %s" % charset.filename, True + "CharacterSetLord: failed reloading {}".format( + charset.filename + ), + True, ) @@ -57,7 +64,7 @@ class CharacterSet: src_filename, CHARSET_DIR, CHARSET_FILE_EXTENSION ) if not self.filename: - self.app.log("Couldn't find character set data %s" % self.filename) + self.app.log("Couldn't find character set data {}".format(self.filename)) return self.name = os.path.basename(self.filename) self.name = os.path.splitext(self.name)[0] @@ -71,7 +78,9 @@ class CharacterSet: return # report if log and not self.app.game_mode: - self.app.log("loaded charmap '%s' from %s:" % (self.name, self.filename)) + self.app.log( + "loaded charmap '{}' from {}:".format(self.name, self.filename) + ) self.report() self.init_success = True @@ -90,7 +99,9 @@ class CharacterSet: char_data.pop(0).strip(), CHARSET_DIR, "png" ) if not img_filename: - self.app.log("Couldn't find character set image %s" % self.image_filename) + self.app.log( + "Couldn't find character set image {}".format(self.image_filename) + ) return False self.image_filename = img_filename # now that we know the image file's name, store its last modified time @@ -167,16 +178,19 @@ class CharacterSet: def report(self): self.app.log( - " source texture %s is %s x %s pixels" - % (self.image_filename, self.image_width, self.image_height) + " source texture {} is {} x {} pixels".format( + self.image_filename, self.image_width, self.image_height + ) ) self.app.log( - " char pixel width/height is %s x %s" % (self.char_width, self.char_height) + " char pixel width/height is {} x {}".format( + self.char_width, self.char_height + ) ) self.app.log( - " char map width/height is %s x %s" % (self.map_width, self.map_height) + " char map width/height is {} x {}".format(self.map_width, self.map_height) ) - self.app.log(" last character index: %s" % self.last_index) + self.app.log(" last character index: {}".format(self.last_index)) def has_updated(self): "return True if source image file has changed since last check" diff --git a/collision.py b/collision.py index 40bcb0a..05cfbf8 100644 --- a/collision.py +++ b/collision.py @@ -307,8 +307,9 @@ class Collideable: frame = self.go.renderable.frame if self.go.col_layer_name not in self.go.art.layer_names: self.go.app.dev_log( - "%s: Couldn't find collision layer with name '%s'" - % (self.go.name, self.go.col_layer_name) + "{}: Couldn't find collision layer with name '{}'".format( + self.go.name, self.go.col_layer_name + ) ) return layer = self.go.art.layer_names.index(self.go.col_layer_name) @@ -442,8 +443,9 @@ class CollisionLord: def report(self): print( - "%s: %s dynamic shapes, %s static shapes" - % (self, len(self.dynamic_shapes), len(self.static_shapes)) + "{}: {} dynamic shapes, {} static shapes".format( + self, len(self.dynamic_shapes), len(self.static_shapes) + ) ) def reset(self): diff --git a/cursor.py b/cursor.py index 8ebf860..b9f21da 100644 --- a/cursor.py +++ b/cursor.py @@ -141,8 +141,9 @@ class Cursor: self.app.keyboard_editing = True if self.logg: self.app.log( - "Cursor: %s,%s,%s scale %.2f,%.2f" - % (self.x, self.y, self.z, self.scale_x, self.scale_y) + "Cursor: {},{},{} scale {:.2f},{:.2f}".format( + self.x, self.y, self.z, self.scale_x, self.scale_y + ) ) def set_scale(self, new_scale): @@ -185,7 +186,7 @@ class Cursor: x0, y0 = self.x, -self.y x1, y1 = self.last_x, -self.last_y tiles = vector.get_tiles_along_line(x0, y0, x1, y1) - print("drag from %s,%s to %s,%s:" % (x0, y0, x1, y1)) + print("drag from {},{} to {},{}:".format(x0, y0, x1, y1)) print(tiles) return tiles diff --git a/edit_command.py b/edit_command.py index 92ed2fe..75def5e 100644 --- a/edit_command.py +++ b/edit_command.py @@ -23,7 +23,7 @@ class EditCommand: # get unique-ish ID from memory address addr = self.__repr__() addr = addr[addr.find("0") : -1] - s = "EditCommand_%s: %s tiles, time %s" % ( + s = "EditCommand_{}: {} tiles, time {}".format( addr, self.get_number_of_commands(), self.finish_time, @@ -95,7 +95,7 @@ class EntireArtCommand: for atype in self.array_types: # save list as eg "b_chars" for "character data before operation" src_data = getattr(self.art, atype) - var_name = "%s_%s" % (prefix, atype) + var_name = "{}_{}".format(prefix, atype) # deep copy each frame's data, else before == after new_data = [] for frame in src_data: @@ -145,15 +145,17 @@ class EditCommandTile: self.a_char = self.a_fg = self.a_bg = self.a_xform = None def __str__(self): - s = "F%s L%s %s,%s @ %.2f: " % ( + s = "F{} L{} {},{} @ {:.2f}: ".format( self.frame, self.layer, str(self.x).rjust(2, "0"), str(self.y).rjust(2, "0"), self.creation_time, ) - s += "c%s f%s b%s x%s -> " % (self.b_char, self.b_fg, self.b_bg, self.b_xform) - s += "c%s f%s b%s x%s" % (self.a_char, self.a_fg, self.a_bg, self.a_xform) + s += "c{} f{} b{} x{} -> ".format( + self.b_char, self.b_fg, self.b_bg, self.b_xform + ) + s += "c{} f{} b{} x{}".format(self.a_char, self.a_fg, self.a_bg, self.a_xform) return s def __eq__(self, value): @@ -259,7 +261,7 @@ class CommandStack: self.undo_commands, self.redo_commands = [], [] def __str__(self): - s = "stack for %s:\n" % self.art.filename + s = "stack for {}:\n".format(self.art.filename) s += "===\nundo:\n" for cmd in self.undo_commands: s += str(cmd) + "\n" diff --git a/formats/in_bitmap.py b/formats/in_bitmap.py index b01852b..a6ba1b3 100644 --- a/formats/in_bitmap.py +++ b/formats/in_bitmap.py @@ -100,13 +100,13 @@ class ConvertImageOptionsDialog(ImportOptionsDialog): # can't assume any art is open, use defaults if needed w = self.ui.active_art.width if self.ui.active_art else DEFAULT_WIDTH h = self.ui.active_art.height if self.ui.active_art else DEFAULT_HEIGHT - label %= "%s x %s" % (w, h) + label %= "{} x {}".format(w, h) elif field_index == 7: # scale # might not be valid valid, _ = self.is_input_valid() if not valid: return label % "???" - label %= "%s x %s" % self.get_tile_scale() + label %= "{} x {}".format(*self.get_tile_scale()) return label def get_tile_scale(self): diff --git a/formats/in_bitmap_sequence.py b/formats/in_bitmap_sequence.py index 394bfe8..06324ad 100644 --- a/formats/in_bitmap_sequence.py +++ b/formats/in_bitmap_sequence.py @@ -50,7 +50,7 @@ class ImageSequenceConverter: self.app.update_window_title() def fail(self): - self.app.log("Bad frame %s" % self.image_filenames[0], error=True) + self.app.log("Bad frame {}".format(self.image_filenames[0]), error=True) self.finish(True) def update(self): @@ -65,8 +65,9 @@ class ImageSequenceConverter: time_taken = time.time() - self.start_time (verb, error) = ("cancelled", True) if cancelled else ("finished", False) self.app.log( - "Conversion of image sequence %s %s after %.3f seconds" - % (self.image_name, verb, time_taken), + "Conversion of image sequence {} {} after {:.3f} seconds".format( + self.image_name, verb, time_taken + ), error, ) self.app.converter = None @@ -96,7 +97,7 @@ image chosen. bicubic_scale = options["bicubic_scale"] # get dir listing with full pathname in_dir = os.path.dirname(in_filename) - in_files = ["%s/%s" % (in_dir, f) for f in os.listdir(in_dir)] + in_files = ["{}/{}".format(in_dir, f) for f in os.listdir(in_dir)] in_files.sort() # assume numeric sequence starts from chosen file in_files = in_files[in_files.index(in_filename) :] diff --git a/formats/out_png.py b/formats/out_png.py index e39169f..10fea82 100644 --- a/formats/out_png.py +++ b/formats/out_png.py @@ -37,7 +37,7 @@ class PNGExportOptionsDialog(ExportOptionsDialog): scale = int(self.field_texts[0]) width = art.charset.char_width * art.width * scale height = art.charset.char_height * art.height * scale - label %= "%s x %s" % (width, height) + label %= "{} x {}".format(width, height) return label def is_input_valid(self): diff --git a/formats/out_png_set.py b/formats/out_png_set.py index 5b94c9d..c5c5102 100644 --- a/formats/out_png_set.py +++ b/formats/out_png_set.py @@ -22,14 +22,14 @@ def get_full_filename( base_filename = os.path.splitext(base_filename)[0] fn = base_filename if use_frame: - fn += "_%s" % (str(frame).rjust(4, "0")) + fn += "_{}".format(str(frame).rjust(4, "0")) if use_layer: - fn += "_%s" % layer_name + fn += "_{}".format(layer_name) # strip unfriendly chars from output filename for forbidden_char in ["\\", "/", "*", ":"]: fn = fn.replace(forbidden_char, "") # add path and extension for final mutated filename - return "%s/%s.%s" % (dirname, fn, FILE_EXTENSION) + return "{}/{}.{}".format(dirname, fn, FILE_EXTENSION) class PNGSetExportOptionsDialog(ExportOptionsDialog): @@ -78,7 +78,7 @@ class PNGSetExportOptionsDialog(ExportOptionsDialog): scale = int(self.field_texts[0]) width = art.charset.char_width * art.width * scale height = art.charset.char_height * art.height * scale - label %= "%s x %s" % (width, height) + label %= "{} x {}".format(width, height) # show how many images exported set will be elif field_index == 4: export_frames = bool(self.field_texts[2].strip()) diff --git a/game_object.py b/game_object.py index 5d3a80e..337c8c5 100644 --- a/game_object.py +++ b/game_object.py @@ -243,7 +243,9 @@ class GameObject: if v not in obj_data: if self.log_load: self.app.dev_log( - "Serialized property '%s' not found for %s" % (v, self.name) + "Serialized property '{}' not found for {}".format( + v, self.name + ) ) continue # if value is in data and serialized list but undeclared, do so @@ -286,7 +288,7 @@ class GameObject: "Dict of all Arts this object can reference, eg for states" # if art_src not specified, create a new art according to dimensions if self.generate_art: - self.art_src = "%s_art" % self.name + self.art_src = "{}_art".format(self.name) self.art = self.app.new_art( self.art_src, self.art_width, @@ -306,7 +308,7 @@ class GameObject: self.art = self.arts[art] break if not self.art: - self.app.log("Couldn't spawn GameObject with art %s" % self.art_src) + self.app.log("Couldn't spawn GameObject with art {}".format(self.art_src)) return self.renderable = GameObjectRenderable(self.app, self.art, self) self.renderable.alpha = self.alpha @@ -343,14 +345,15 @@ class GameObject: self.start_animating() if self.log_spawn: self.app.log( - "Spawned %s with Art %s" - % (self.name, os.path.basename(self.art.filename)) + "Spawned {} with Art {}".format( + self.name, os.path.basename(self.art.filename) + ) ) def get_unique_name(self): "Generate and return a somewhat human-readable unique name for object" name = str(self) - return "%s_%s" % (type(self).__name__, name[name.rfind("x") + 1 : -1]) + return "{}_{}".format(type(self).__name__, name[name.rfind("x") + 1 : -1]) def _rename(self, new_name): # pass thru to world, this method exists for edit set method @@ -376,13 +379,13 @@ class GameObject: if self.facing_changes_art: # load each facing for each state for facing in FACINGS.values(): - art_name = "%s_%s_%s" % (self.art_src, state, facing) + art_name = "{}_{}_{}".format(self.art_src, state, facing) art = self.app.load_art(art_name, False) if art: self.arts[art_name] = art else: # load each state - art_name = "%s_%s" % (self.art_src, state) + art_name = "{}_{}".format(self.art_src, state) art = self.app.load_art(art_name, False) if art: self.arts[art_name] = art @@ -664,14 +667,14 @@ class GameObject: "Return Art (and 'flip X' bool) that best represents current state" # use current state if none specified state = self.state if state is None else state - art_state_name = "%s_%s" % (self.art_src, self.state) + art_state_name = "{}_{}".format(self.art_src, self.state) # simple case: no facing, just state if not self.facing_changes_art: # return art for current state, use default if not available if art_state_name in self.arts: return self.arts[art_state_name], False else: - default_name = "%s_%s" % (self.art_src, self.state or DEFAULT_STATE) + default_name = "{}_{}".format(self.art_src, self.state or DEFAULT_STATE) # assert(default_name in self.arts # don't assert - if base+state name available, use that if default_name in self.arts: @@ -682,7 +685,7 @@ class GameObject: # more complex case: art determined by both state and facing facing_suffix = FACINGS[self.facing] # first see if anim exists for this exact state, skip subsequent logic - exact_name = "%s_%s" % (art_state_name, facing_suffix) + exact_name = "{}_{}".format(art_state_name, facing_suffix) if exact_name in self.arts: return self.arts[exact_name], False # see what anims are available and try to choose best for facing @@ -693,12 +696,12 @@ class GameObject: break # if NO anims for current state, fall back to default if not has_state: - default_name = "%s_%s" % (self.art_src, DEFAULT_STATE) + default_name = "{}_{}".format(self.art_src, DEFAULT_STATE) art_state_name = default_name - front_name = "%s_%s" % (art_state_name, FACINGS[GOF_FRONT]) - left_name = "%s_%s" % (art_state_name, FACINGS[GOF_LEFT]) - right_name = "%s_%s" % (art_state_name, FACINGS[GOF_RIGHT]) - back_name = "%s_%s" % (art_state_name, FACINGS[GOF_BACK]) + front_name = "{}_{}".format(art_state_name, FACINGS[GOF_FRONT]) + left_name = "{}_{}".format(art_state_name, FACINGS[GOF_LEFT]) + right_name = "{}_{}".format(art_state_name, FACINGS[GOF_RIGHT]) + back_name = "{}_{}".format(art_state_name, FACINGS[GOF_BACK]) has_front = front_name in self.arts has_left = left_name in self.arts has_right = right_name in self.arts @@ -991,7 +994,7 @@ class GameObject: ) if not timer: self.app.log( - "Timer named %s not found on object %s" % (timer_name, self.name) + "Timer named {} not found on object {}".format(timer_name, self.name) ) d = [ self.timer_functions_pre_update, @@ -1119,8 +1122,9 @@ class GameObject: or abs(self.y) > self.kill_distance_from_origin ): self.app.log( - "%s reached %s from origin, destroying." - % (self.name, self.kill_distance_from_origin) + "{} reached {} from origin, destroying.".format( + self.name, self.kill_distance_from_origin + ) ) self.destroy() diff --git a/game_room.py b/game_room.py index cfb45b1..583e24e 100644 --- a/game_room.py +++ b/game_room.py @@ -44,7 +44,9 @@ class GameRoom: for v in self.serialized: if v not in room_data: self.world.app.dev_log( - "Serialized property '%s' not found for room %s" % (v, self.name) + "Serialized property '{}' not found for room {}".format( + v, self.name + ) ) continue if not hasattr(self, v): @@ -90,7 +92,9 @@ class GameRoom: def set_camera_marker_name(self, marker_name): if marker_name not in self.world.objects: - self.world.app.log("Couldn't find camera marker with name %s" % marker_name) + self.world.app.log( + "Couldn't find camera marker with name {}".format(marker_name) + ) return self.camera_marker_name = marker_name if self is self.world.current_room: @@ -105,7 +109,7 @@ class GameRoom: def entered(self, old_room): "Run when the player enters this room." if self.log_changes: - self.world.app.log('Room "%s" entered' % self.name) + self.world.app.log('Room "{}" entered'.format(self.name)) # set camera if marker is set if self.world.room_camera_changes_enabled: self.use_camera_marker() @@ -120,7 +124,7 @@ class GameRoom: def exited(self, new_room): "Run when the player exits this room." if self.log_changes: - self.world.app.log('Room "%s" exited' % self.name) + self.world.app.log('Room "{}" exited'.format(self.name)) # tell objects in this room player has exited for obj in self.objects.values(): obj.room_exited(self, new_room) @@ -129,7 +133,7 @@ class GameRoom: "Add object with given name to this room." obj = self.world.objects.get(obj_name, None) if not obj: - self.world.app.log("Couldn't find object named %s" % obj_name) + self.world.app.log("Couldn't find object named {}".format(obj_name)) return self.add_object(obj) @@ -142,7 +146,7 @@ class GameRoom: "Remove object with given name from this room." obj = self.world.objects.get(obj_name, None) if not obj: - self.world.app.log("Couldn't find object named %s" % obj_name) + self.world.app.log("Couldn't find object named {}".format(obj_name)) return self.remove_object(obj) @@ -152,13 +156,13 @@ class GameRoom: self.objects.pop(obj.name) else: self.world.app.log( - "GameRoom %s doesn't contain GameObject %s" % (self.name, obj.name) + "GameRoom {} doesn't contain GameObject {}".format(self.name, obj.name) ) if self.name in obj.rooms: obj.rooms.pop(self.name) else: self.world.app.log( - "GameObject %s not found in GameRoom %s" % (obj.name, self.name) + "GameObject {} not found in GameRoom {}".format(obj.name, self.name) ) def get_dict(self): diff --git a/game_util_objects.py b/game_util_objects.py index f71c5d8..900f43f 100644 --- a/game_util_objects.py +++ b/game_util_objects.py @@ -369,8 +369,9 @@ class WarpTrigger(StaticTileTrigger): marker = self.world.objects.get(self.destination_marker_name, None) if not marker: self.app.log( - "Warp destination object %s not found" - % self.destination_marker_name + "Warp destination object {} not found".format( + self.destination_marker_name + ) ) return other.set_loc(marker.x, marker.y, marker.z) @@ -383,8 +384,9 @@ class WarpTrigger(StaticTileTrigger): and room.name != self.destination_room_name ): self.app.log( - "Marker %s's room differs from destination room %s" - % (marker.name, self.destination_room_name) + "Marker {}'s room differs from destination room {}".format( + marker.name, self.destination_room_name + ) ) self.world.change_room(room.name) other.last_warp_update = self.world.updates @@ -502,8 +504,9 @@ class SoundBlaster(LocationMarker): self.sound_filenames[self.sound_name] = filename return self.world.app.log( - "Couldn't find sound file %s for SoundBlaster %s" - % (self.sound_name, self.name) + "Couldn't find sound file {} for SoundBlaster {}".format( + self.sound_name, self.name + ) ) def room_entered(self, room, old_room): diff --git a/game_world.py b/game_world.py index 3e435c4..45e19d4 100644 --- a/game_world.py +++ b/game_world.py @@ -220,7 +220,7 @@ class GameWorld: new_obj = self.spawn_object_of_class(self.classname_to_spawn, x, y) if self.current_room: self.current_room.add_object(new_obj) - self.app.ui.message_line.post_line("Spawned %s" % new_obj.name) + self.app.ui.message_line.post_line("Spawned {}".format(new_obj.name)) return objects = self.get_objects_at(x, y) next_obj = self.pick_next_object_at(x, y) @@ -408,7 +408,7 @@ class GameWorld: self.unload_game() new_dir = self.app.documents_dir + TOP_GAME_DIR + new_game_dir + "/" if os.path.exists(new_dir): - self.app.log("Game dir %s already exists!" % new_game_dir) + self.app.log("Game dir {} already exists!".format(new_game_dir)) return False os.mkdir(new_dir) os.mkdir(new_dir + ART_DIR) @@ -514,7 +514,7 @@ class GameWorld: self.game_name = dir_name if not d.endswith("/"): self.game_dir += "/" - self.app.log("Game data folder is now %s" % self.game_dir) + self.app.log("Game data folder is now {}".format(self.game_dir)) # set sounds dir before loading state; some obj inits depend on it self.sounds_dir = self.game_dir + SOUNDS_DIR if reset: @@ -526,7 +526,7 @@ class GameWorld: self.classes = self._get_all_loaded_classes() break if not self.game_dir: - self.app.log("Couldn't find game directory %s" % dir_name) + self.app.log("Couldn't find game directory {}".format(dir_name)) def _remove_non_current_game_modules(self): """ @@ -535,7 +535,7 @@ class GameWorld: """ modules_to_remove = [] games_dir_prefix = TOP_GAME_DIR.replace("/", "") - this_game_dir_prefix = "%s.%s" % (games_dir_prefix, self.game_name) + this_game_dir_prefix = "{}.{}".format(games_dir_prefix, self.game_name) for module_name in sys.modules: # remove any module that isn't for this game or part of its path if ( @@ -555,7 +555,7 @@ class GameWorld: # build list of module files modules_list = self.builtin_module_names[:] # create appropriately-formatted python import path - module_path_prefix = "%s.%s.%s." % ( + module_path_prefix = "{}.{}.{}.".format( TOP_GAME_DIR.replace("/", ""), self.game_name, GAME_SCRIPTS_DIR.replace("/", ""), @@ -603,7 +603,7 @@ class GameWorld: if not self.allow_pause: return self.paused = not self.paused - s = "Game %spaused." % ["un", ""][self.paused] + s = "Game {}paused.".format(["un", ""][self.paused]) self.app.ui.message_line.post_line(s) def get_elapsed_time(self): @@ -758,7 +758,7 @@ class GameWorld: and line.strip() != "method()" ): self.app.log(line.rstrip()) - s = "Error in %s.%s! See console." % (obj.name, method.__name__) + s = "Error in {}.{}! See console.".format(obj.name, method.__name__) self.app.ui.message_line.post_line(s, 10, True) def pre_update(self): @@ -938,14 +938,14 @@ class GameWorld: if filename and filename != "": if not filename.endswith(STATE_FILE_EXTENSION): filename += "." + STATE_FILE_EXTENSION - filename = "%s%s" % (self.game_dir, filename) + filename = "{}{}".format(self.game_dir, filename) else: # state filename example: # games/mytestgame2/1431116386.gs timestamp = int(time.time()) - filename = "%s%s.%s" % (self.game_dir, timestamp, STATE_FILE_EXTENSION) + filename = "{}{}.{}".format(self.game_dir, timestamp, STATE_FILE_EXTENSION) json.dump(d, open(filename, "w"), sort_keys=True, indent=1) - self.app.log("Saved game state %s to disk." % filename) + self.app.log("Saved game state {} to disk.".format(filename)) self.app.update_window_title() def _get_all_loaded_classes(self): @@ -982,7 +982,7 @@ class GameWorld: obj_class = obj.__class__.__name__ spawned = self.spawn_object_of_class(obj_class, x, y) if spawned: - self.app.log("%s reset to class defaults" % obj.name) + self.app.log("{} reset to class defaults".format(obj.name)) if obj is self.player: self.player = spawned obj.destroy() @@ -994,9 +994,9 @@ class GameWorld: new_objects.append(self.duplicate_object(obj)) # report on objects created if len(new_objects) == 1: - self.app.log("%s created from %s" % (new_objects[0].name, obj.name)) + self.app.log("{} created from {}".format(new_objects[0].name, obj.name)) elif len(new_objects) > 1: - self.app.log("%s new objects created" % len(new_objects)) + self.app.log("{} new objects created".format(len(new_objects))) def duplicate_object(self, obj): "Create a duplicate of given object." @@ -1025,7 +1025,9 @@ class GameWorld: for other_obj in self.objects.values(): if other_obj is not self and other_obj.name == new_name: self.app.ui.message_line.post_line( - "Can't rename %s to %s, name already in use" % (obj.name, new_name) + "Can't rename {} to {}, name already in use".format( + obj.name, new_name + ) ) return self.objects.pop(obj.name) @@ -1066,7 +1068,7 @@ class GameWorld: def add_room(self, new_room_name, new_room_classname="GameRoom"): "Add a new Room with given name of (optional) given class." if new_room_name in self.rooms: - self.log("Room called %s already exists!" % new_room_name) + self.log("Room called {} already exists!".format(new_room_name)) return new_room_class = self.classes[new_room_classname] new_room = new_room_class(self, new_room_name) @@ -1084,7 +1086,7 @@ class GameWorld: def change_room(self, new_room_name): "Set world's current active room to Room with given name." if new_room_name not in self.rooms: - self.app.log("Couldn't change to missing room %s" % new_room_name) + self.app.log("Couldn't change to missing room {}".format(new_room_name)) return old_room = self.current_room self.current_room = self.rooms[new_room_name] @@ -1122,7 +1124,7 @@ class GameWorld: d = json.load(open(filename)) # self.app.log('Loading game state %s...' % filename) except: - self.app.log("Couldn't load game state from %s" % filename) + self.app.log("Couldn't load game state from {}".format(filename)) # self.app.log(sys.exc_info()) return errors = False @@ -1159,7 +1161,7 @@ class GameWorld: self.hud = hud_class(self) self.hud_class_name = hud_class.__name__ if not errors and self.app.init_success: - self.app.log("Loaded game state from %s" % filename) + self.app.log("Loaded game state from {}".format(filename)) self.last_state_loaded = filename self.set_for_all_objects("show_collision", self.show_collision_all) self.set_for_all_objects("show_bounds", self.show_bounds_all) @@ -1170,13 +1172,13 @@ class GameWorld: def report(self): "Print (not log) information about current world state." - print("--------------\n%s report:" % self) + print("--------------\n{} report:".format(self)) obj_arts, obj_rends, obj_dbg_rends, obj_cols, obj_col_rends = 0, 0, 0, 0, 0 attachments = 0 # create merged dict of existing and just-spawned objects all_objects = self.objects.copy() all_objects.update(self.new_objects) - print("%s objects:" % len(all_objects)) + print("{} objects:".format(len(all_objects))) for obj in all_objects.values(): obj_arts += len(obj.arts) if obj.renderable is not None: @@ -1191,12 +1193,11 @@ class GameWorld: attachments += len(obj.attachments) print( """ - %s arts in objects, %s arts loaded, - %s HUD arts, %s HUD renderables, - %s renderables, %s debug renderables, - %s collideables, %s collideable viz renderables, - %s attachments""" - % ( + {} arts in objects, {} arts loaded, + {} HUD arts, {} HUD renderables, + {} renderables, {} debug renderables, + {} collideables, {} collideable viz renderables, + {} attachments""".format( obj_arts, len(self.art_loaded), len(self.hud.arts), @@ -1210,10 +1211,11 @@ class GameWorld: ) self.cl.report() print( - "%s charsets loaded, %s palettes" - % (len(self.app.charsets), len(self.app.palettes)) + "{} charsets loaded, {} palettes".format( + len(self.app.charsets), len(self.app.palettes) + ) ) - print("%s arts loaded for edit" % len(self.app.art_loaded_for_edit)) + print("{} arts loaded for edit".format(len(self.app.art_loaded_for_edit))) def toggle_all_origin_viz(self): "Toggle visibility of XYZ markers for all object origins." diff --git a/games/crawler/scripts/player.py b/games/crawler/scripts/player.py index 2c4dc21..67fcc01 100644 --- a/games/crawler/scripts/player.py +++ b/games/crawler/scripts/player.py @@ -55,7 +55,7 @@ class CrawlPlayer(Player): if key == "up" else DIR_NAMES[OPPOSITE_DIRS[self.direction]] ) - self.app.log("can't go %s!" % dir_name) + self.app.log("can't go {}!".format(dir_name)) else: self.x, self.y = self.maze.x + new_x, self.maze.y - new_y # update art to show facing diff --git a/games/fireplace/scripts/fireplace.py b/games/fireplace/scripts/fireplace.py index 1538344..a8b5f0b 100644 --- a/games/fireplace/scripts/fireplace.py +++ b/games/fireplace/scripts/fireplace.py @@ -79,7 +79,7 @@ class Fireplace(GameObject): self.credit_screen = None self.music_exists = False if os.path.exists(self.world.sounds_dir + MUSIC_FILENAME): - self.app.log("%s found in %s" % (MUSIC_FILENAME, self.world.sounds_dir)) + self.app.log("{} found in {}".format(MUSIC_FILENAME, self.world.sounds_dir)) self.world.play_music(MUSIC_FILENAME) self.music_paused = False self.music_exists = True @@ -88,7 +88,9 @@ class Fireplace(GameObject): self.credit_screen.z = 1.1 self.credit_screen.set_scale(0.75, 0.75, 1) else: - self.app.log("No %s found in %s" % (MUSIC_FILENAME, self.world.sounds_dir)) + self.app.log( + "No {} found in {}".format(MUSIC_FILENAME, self.world.sounds_dir) + ) self.set_new_message_time() def update(self): @@ -190,14 +192,14 @@ class Fireplace(GameObject): elif key == "=" or key == "+": self.target_particles += 10 self.art.write_string( - 0, 0, 0, 0, "Embers: %s" % self.target_particles, 15, 1 + 0, 0, 0, 0, "Embers: {}".format(self.target_particles), 15, 1 ) elif key == "-": if self.target_particles <= 10: return self.target_particles -= 10 self.art.write_string( - 0, 0, 0, 0, "Embers: %s" % self.target_particles, 15, 1 + 0, 0, 0, 0, "Embers: {}".format(self.target_particles), 15, 1 ) diff --git a/games/flood/scripts/game.py b/games/flood/scripts/game.py index 08f5591..6fc86ee 100644 --- a/games/flood/scripts/game.py +++ b/games/flood/scripts/game.py @@ -79,7 +79,7 @@ class Board(GameObject): self.reset() return # get list of valid keys from length of tile_colors - valid_keys = ["%s" % str(i + 1) for i in range(len(TILE_COLORS))] + valid_keys = ["{}".format(str(i + 1)) for i in range(len(TILE_COLORS))] if key not in valid_keys: return key = int(key) - 1 diff --git a/games/maze/scripts/objects.py b/games/maze/scripts/objects.py index 7094b57..8739438 100644 --- a/games/maze/scripts/objects.py +++ b/games/maze/scripts/objects.py @@ -88,7 +88,7 @@ class MazePickup(GameObject): def picked_up(self, new_holder): self.holder = new_holder - self.world.hud.post_msg("got %s!" % self.display_name) + self.world.hud.post_msg("got {}!".format(self.display_name)) self.disable_collision() self.play_sound("pickup") @@ -167,7 +167,9 @@ class MazeLock(StaticTileBG): if other.held_object and type(other.held_object) is self.key_type: self.unlocked(other) else: - self.world.hud.post_msg("blocked - need %s!" % self.key_type.display_name) + self.world.hud.post_msg( + "blocked - need {}!".format(self.key_type.display_name) + ) def unlocked(self, other): self.disable_collision() diff --git a/games/wildflowers/scripts/flower.py b/games/wildflowers/scripts/flower.py index 84f3e48..a1dfc31 100644 --- a/games/wildflowers/scripts/flower.py +++ b/games/wildflowers/scripts/flower.py @@ -90,7 +90,7 @@ class FlowerObject(GameObject): # track # of growth updates we've had self.grows = 0 # create an art document we can add frames to and later export - self.export_filename = "%s%swildflower_%s" % ( + self.export_filename = "{}{}wildflower_{}".format( self.app.documents_dir, ART_DIR, self.seed, diff --git a/games/wildflowers/scripts/frond.py b/games/wildflowers/scripts/frond.py index 1e13b00..20be34a 100644 --- a/games/wildflowers/scripts/frond.py +++ b/games/wildflowers/scripts/frond.py @@ -81,12 +81,11 @@ class Frond: if self.life <= 0 or self.color == self.ramp.end: self.finished_growing = True if self.debug: - print(" frond %i finished." % self.index) + print(f" frond {self.index} finished.") return painted if self.debug: print( - " frond %i at (%i, %i) using %s" - % (self.index, self.x, self.y, self.get_grow_dir.__name__) + f" frond {self.index} at ({self.x}, {self.y}) using {self.get_grow_dir.__name__}" ) # if we're out of bounds, simply don't paint; # we might go back in bounds next grow diff --git a/games/wildflowers/scripts/petal.py b/games/wildflowers/scripts/petal.py index 30b0b18..0f0698a 100644 --- a/games/wildflowers/scripts/petal.py +++ b/games/wildflowers/scripts/petal.py @@ -68,14 +68,7 @@ class Petal: return if self.debug: print( - " petal %i at (%i, %i) at radius %i using %s" - % ( - self.index, - self.x, - self.y, - self.radius, - self.get_ring_tiles.__name__, - ) + f" petal {self.index} at ({self.x}, {self.y}) at radius {self.radius} using {self.get_ring_tiles.__name__}" ) self.paint_ring() # grow and change diff --git a/games/wildflowers/scripts/wildflowers.py b/games/wildflowers/scripts/wildflowers.py index 5d0fb1c..f5615f9 100644 --- a/games/wildflowers/scripts/wildflowers.py +++ b/games/wildflowers/scripts/wildflowers.py @@ -69,7 +69,7 @@ class FlowerGlobals(WorldGlobalsObject): scale=4, bg_color=self.world.bg_color, ) - self.app.log("Exported %s.png" % self.flower.export_filename) + self.app.log("Exported {}.png".format(self.flower.export_filename)) class SeedDisplay(GameObject): diff --git a/image_convert.py b/image_convert.py index aca78f2..739d35a 100644 --- a/image_convert.py +++ b/image_convert.py @@ -38,7 +38,7 @@ class ImageConverter: self.init_success = False image_filename = app.find_filename_path(image_filename) if not image_filename or not os.path.exists(image_filename): - app.log("ImageConverter: Couldn't find image %s" % image_filename) + app.log("ImageConverter: Couldn't find image {}".format(image_filename)) app.converter = None return self.app = app @@ -266,8 +266,9 @@ class ImageConverter: time_taken = time.time() - self.start_time verb = "cancelled" if cancelled else "finished" self.app.log( - "Conversion of image %s %s after %.3f seconds" - % (self.image_filename, verb, time_taken) + "Conversion of image {} {} after {:.3f} seconds".format( + self.image_filename, verb, time_taken + ) ) self.app.converter = None self.preview_sprite = None diff --git a/image_export.py b/image_export.py index 9085e88..c7cf815 100644 --- a/image_export.py +++ b/image_export.py @@ -14,8 +14,9 @@ def get_frame_image(app, art, frame, allow_crt=True, scale=1, bg_color=(0, 0, 0, # error out if over max texture size if w > app.max_texture_size or h > app.max_texture_size: app.log( - "ERROR: Image output size (%s x %s) exceeds your hardware's max supported texture size (%s x %s)!" - % (w, h, app.max_texture_size, app.max_texture_size), + "ERROR: Image output size ({} x {}) exceeds your hardware's max supported texture size ({} x {})!".format( + w, h, app.max_texture_size, app.max_texture_size + ), error=True, ) app.log( diff --git a/input_handler.py b/input_handler.py index 453f40c..506144b 100644 --- a/input_handler.py +++ b/input_handler.py @@ -89,13 +89,13 @@ class InputLord: ) < os.path.getmtime(BINDS_TEMPLATE_FILENAME) if not binds_outdated and os.path.exists(binds_filename): exec(open(binds_filename).read()) - self.app.log("Loaded key binds from %s" % binds_filename) + self.app.log("Loaded key binds from {}".format(binds_filename)) else: default_data = open(BINDS_TEMPLATE_FILENAME).readlines()[1:] new_binds = open(binds_filename, "w") new_binds.writelines(default_data) new_binds.close() - self.app.log("Created new key binds file %s" % binds_filename) + self.app.log("Created new key binds file {}".format(binds_filename)) exec("".join(default_data)) if not self.edit_bind_src: self.app.log("No bind data found, Is binds.cfg.default present?") @@ -109,9 +109,9 @@ class InputLord: # bind data could be a single item (string) or a list/tuple bind_data = self.edit_bind_src[bind_string] if type(bind_data) is str: - bind_fnames = ["BIND_%s" % bind_data] + bind_fnames = ["BIND_{}".format(bind_data)] else: - bind_fnames = ["BIND_%s" % s for s in bind_data] + bind_fnames = ["BIND_{}".format(s) for s in bind_data] bind_functions = [] for bind_fname in bind_fnames: if not hasattr(self, bind_fname): @@ -123,7 +123,7 @@ class InputLord: js_init = sdl2.SDL_InitSubSystem(sdl2.SDL_INIT_JOYSTICK) if js_init != 0: self.app.log( - "SDL2: Couldn't initialize joystick subsystem, code %s" % js_init + "SDL2: Couldn't initialize joystick subsystem, code {}".format(js_init) ) return sticks = sdl2.SDL_NumJoysticks() @@ -137,8 +137,9 @@ class InputLord: pad_axes = sdl2.SDL_JoystickNumAxes(pad) pad_buttons = sdl2.SDL_JoystickNumButtons(pad) self.app.log( - "Gamepad found: %s with %s axes, %s buttons" - % (pad_name, pad_axes, pad_buttons) + "Gamepad found: {} with {} axes, {} buttons".format( + pad_name, pad_axes, pad_buttons + ) ) self.gamepad = pad # before main loop begins, set initial mouse position - @@ -204,7 +205,7 @@ class InputLord: if not hasattr(button, "menu_data"): continue for item in button.menu_data.items: - if function.__name__ == "BIND_%s" % item.command: + if function.__name__ == "BIND_{}".format(item.command): items.append(item) return items @@ -1224,10 +1225,14 @@ class InputLord: for obj in self.app.gw.selected_objects: if obj.orig_collision_type and obj.collision_type == CT_NONE: obj.enable_collision() - self.ui.message_line.post_line("Collision enabled for %s" % obj.name) + self.ui.message_line.post_line( + "Collision enabled for {}".format(obj.name) + ) elif obj.collision_type != CT_NONE: obj.disable_collision() - self.ui.message_line.post_line("Collision disabled for %s" % obj.name) + self.ui.message_line.post_line( + "Collision disabled for {}".format(obj.name) + ) def BIND_toggle_game_edit_ui(self): self.ui.toggle_game_edit_ui() diff --git a/palette.py b/palette.py index 477f94f..1bdc46d 100644 --- a/palette.py +++ b/palette.py @@ -34,10 +34,13 @@ class PaletteLord: changed = palette.filename try: palette.load_image() - self.app.log("PaletteLord: success reloading %s" % palette.filename) + self.app.log( + "PaletteLord: success reloading {}".format(palette.filename) + ) except: self.app.log( - "PaletteLord: failed reloading %s" % palette.filename, True + "PaletteLord: failed reloading {}".format(palette.filename), + True, ) @@ -49,7 +52,7 @@ class Palette: src_filename, PALETTE_DIR, PALETTE_EXTENSIONS ) if self.filename is None: - self.app.log("Couldn't find palette image %s" % src_filename) + self.app.log("Couldn't find palette image {}".format(src_filename)) return self.last_image_change = os.path.getmtime(self.filename) self.name = os.path.basename(self.filename) @@ -57,10 +60,12 @@ class Palette: self.load_image() self.base_filename = os.path.splitext(os.path.basename(self.filename))[0] if log and not self.app.game_mode: - self.app.log("loaded palette '%s' from %s:" % (self.name, self.filename)) - self.app.log(" unique colors found: %s" % int(len(self.colors) - 1)) - self.app.log(" darkest color index: %s" % self.darkest_index) - self.app.log(" lightest color index: %s" % self.lightest_index) + self.app.log( + "loaded palette '{}' from {}:".format(self.name, self.filename) + ) + self.app.log(" unique colors found: {}".format(int(len(self.colors) - 1))) + self.app.log(" darkest color index: {}".format(self.darkest_index)) + self.app.log(" lightest color index: {}".format(self.lightest_index)) self.init_success = True def load_image(self): @@ -219,7 +224,7 @@ class PaletteFromList(Palette): self.init_success = False self.app = app # generate a unique non-user-facing palette name - name = "PaletteFromList_%s" % time.time() + name = "PaletteFromList_{}".format(time.time()) self.filename = self.name = self.base_filename = name colors = [] for color in src_color_list: @@ -247,10 +252,10 @@ class PaletteFromList(Palette): x += 1 self.texture = Texture(img.tobytes(), MAX_COLORS, 1) if log and not self.app.game_mode: - self.app.log("generated new palette '%s'" % (self.name)) - self.app.log(" unique colors: %s" % int(len(self.colors) - 1)) - self.app.log(" darkest color index: %s" % self.darkest_index) - self.app.log(" lightest color index: %s" % self.lightest_index) + self.app.log("generated new palette '{}'".format(self.name)) + self.app.log(" unique colors: {}".format(int(len(self.colors) - 1))) + self.app.log(" darkest color index: {}".format(self.darkest_index)) + self.app.log(" lightest color index: {}".format(self.lightest_index)) def has_updated(self): "No bitmap source for this type of palette, so no hot-reload" @@ -262,7 +267,7 @@ class PaletteFromFile(Palette): self.init_success = False src_filename = app.find_filename_path(src_filename) if not src_filename: - app.log("Couldn't find palette source image %s" % src_filename) + app.log("Couldn't find palette source image {}".format(src_filename)) return # dither source image, re-save it, use that as the source for a palette src_img = Image.open(src_filename) @@ -281,7 +286,7 @@ class PaletteFromFile(Palette): if os.path.exists(palette_path + palette_filename + ".png"): i = 0 while os.path.exists( - "%s%s%s.png" % (palette_path, palette_filename, str(i)) + "{}{}{}.png".format(palette_path, palette_filename, str(i)) ): i += 1 palette_filename += str(i) diff --git a/playscii.py b/playscii.py index 3c704e3..6d79732 100755 --- a/playscii.py +++ b/playscii.py @@ -284,7 +284,7 @@ class Application: gpu_renderer = GL.glGetString(GL.GL_RENDERER).decode("utf-8") except: gpu_renderer = "[couldn't detect renderer]" - self.log(" GPU: %s - %s" % (gpu_vendor, gpu_renderer)) + self.log(" GPU: {} - {}".format(gpu_vendor, gpu_renderer)) try: # try single-argument GL2.0 version first gl_ver = GL.glGetString(GL.GL_VERSION) @@ -293,7 +293,7 @@ class Application: gl_ver = gl_ver.decode("utf-8") except: gl_ver = "[couldn't detect GL version]" - self.log(" OpenGL detected: %s" % gl_ver) + self.log(" OpenGL detected: {}".format(gl_ver)) # GL 1.1 doesn't even habla shaders, quit if we fail GLSL version check try: glsl_ver = GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION) @@ -306,14 +306,16 @@ class Application: self.should_quit = True return glsl_ver = glsl_ver.decode("utf-8") if glsl_ver != None else None - self.log(" GLSL detected: %s" % glsl_ver or "[unknown]") + self.log(" GLSL detected: {}".format(glsl_ver) or "[unknown]") # verify that we got at least a 2.1 context majorv, minorv = ctypes.c_int(0), ctypes.c_int(0) video.SDL_GL_GetAttribute(video.SDL_GL_CONTEXT_MAJOR_VERSION, majorv) video.SDL_GL_GetAttribute(video.SDL_GL_CONTEXT_MINOR_VERSION, minorv) context_version = majorv.value + (minorv.value * 0.1) self.use_vao = bool(GL.glGenVertexArrays) - self.log(" Vertex Array Object support %sfound." % ["NOT ", ""][self.use_vao]) + self.log( + " Vertex Array Object support {}found.".format(["NOT ", ""][self.use_vao]) + ) if not self.context: self.log("No OpenGL context found!") # enforce GL version requirement @@ -341,41 +343,43 @@ class Application: GL.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, mts) self.max_texture_size = mts.value self.log( - " Maximum supported texture size: %s x %s" - % (self.max_texture_size, self.max_texture_size) + " Maximum supported texture size: {} x {}".format( + self.max_texture_size, self.max_texture_size + ) ) self.log( - " Detected screen resolution: %.0f x %.0f, window: %s x %s" - % (screen_width, screen_height, self.window_width, self.window_height) + " Detected screen resolution: {:.0f} x {:.0f}, window: {} x {}".format( + screen_width, screen_height, self.window_width, self.window_height + ) ) self.log("Detecting software environment...") - self.log(" OS: %s" % platform.platform()) + self.log(" OS: {}".format(platform.platform())) py_version = " ".join(sys.version.split("\n")) # report 32 vs 64 bit as it's not clear from sys.version or OS bitness = platform.architecture()[0] # on linux, report whether we're running x11 or wayland if platform.system() == "Linux": driver = sdl2.SDL_GetCurrentVideoDriver().decode("utf-8") - self.log(' Linux SDL2 "video driver": %s' % driver) - self.log(" Python: %s (%s)" % (py_version, bitness)) - module_versions = "PySDL2 %s, " % sdl2.__version__ - module_versions += "numpy %s, " % numpy.__version__ - module_versions += "PyOpenGL %s, " % OpenGL.__version__ - module_versions += "appdirs %s, " % appdirs.__version__ - module_versions += "PIL %s" % PIL.__version__ - self.log(" Modules: %s" % module_versions) - sdl_version = "%s.%s.%s " % ( + self.log(' Linux SDL2 "video driver": {}'.format(driver)) + self.log(" Python: {} ({})".format(py_version, bitness)) + module_versions = "PySDL2 {}, ".format(sdl2.__version__) + module_versions += "numpy {}, ".format(numpy.__version__) + module_versions += "PyOpenGL {}, ".format(OpenGL.__version__) + module_versions += "appdirs {}, ".format(appdirs.__version__) + module_versions += "PIL {}".format(PIL.__version__) + self.log(" Modules: {}".format(module_versions)) + sdl_version = "{}.{}.{} ".format( sdl2.version.SDL_MAJOR_VERSION, sdl2.version.SDL_MINOR_VERSION, sdl2.version.SDL_PATCHLEVEL, ) sdl_version += sdl2.version.SDL_GetRevision().decode("utf-8") - sdl_version += ", SDLmixer: %s.%s.%s" % ( + sdl_version += ", SDLmixer: {}.{}.{}".format( sdlmixer.SDL_MIXER_MAJOR_VERSION, sdlmixer.SDL_MIXER_MINOR_VERSION, sdlmixer.SDL_MIXER_PATCHLEVEL, ) - self.log(" SDL: %s" % sdl_version) + self.log(" SDL: {}".format(sdl_version)) # draw black screen while doing other init GL.glClearColor(0.0, 0.0, 0.0, 1.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT) @@ -562,7 +566,7 @@ class Application: and "_bootstrap._gcd_import" not in line ): self.log(line.rstrip()) - s = "Error importing module %s! See console." % module_name + s = "Error importing module {}! See console.".format(module_name) if self.ui: self.ui.message_line.post_line(s, 10, True) @@ -585,7 +589,7 @@ class Application: art = None if not valid_filename: if autocreate: - self.log("Creating new art %s" % filename) + self.log("Creating new art {}".format(filename)) return self.new_art(filename) else: # self.log("Couldn't find art %s" % filename) @@ -637,7 +641,7 @@ class Application: self.edit_renderables.remove(r) if art is self.ui.active_art: self.ui.active_art = None - self.log("Unloaded %s" % art.filename) + self.log("Unloaded {}".format(art.filename)) if len(self.art_loaded_for_edit) > 0: self.ui.set_active_art(self.art_loaded_for_edit[0]) self.update_window_title() @@ -694,7 +698,7 @@ class Application: extensions = [extensions] for dirname in dirnames: for ext in extensions: - f = "%s%s" % (dirname, filename) + f = "{}{}".format(dirname, filename) # filename passed in might already have intended extension, # eg from a directory listing if ext and ext != "" and not filename.endswith(ext): @@ -723,7 +727,7 @@ class Application: if basename in self.converter_modules: m = importlib.reload(self.converter_modules[basename]) else: - m = importlib.import_module("formats.%s" % basename) + m = importlib.import_module("formats.{}".format(basename)) self.converter_modules[basename] = m except Exception as e: self.log_import_exception(e, basename) @@ -778,7 +782,7 @@ class Application: def set_window_title(self, text=None): # if editing is locked, don't even show Playscii name - new_title = "%s - %s" % (APP_NAME, text) if self.can_edit else str(text) + new_title = "{} - {}".format(APP_NAME, text) if self.can_edit else str(text) new_title = bytes(new_title, "utf-8") sdl2.SDL_SetWindowTitle(self.window, new_title) @@ -833,7 +837,7 @@ class Application: def screenshot(self): "saves a date + time-stamped screenshot" timestamp = time.strftime("%Y-%m-%d_%H-%M-%S") - output_filename = "playscii_%s.png" % timestamp + output_filename = "playscii_{}.png".format(timestamp) w, h = self.window_width, self.window_height pixels = GL.glReadPixels( 0, 0, w, h, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, outputType=None @@ -841,8 +845,8 @@ class Application: pixel_bytes = pixels.flatten().tobytes() img = Image.frombytes(mode="RGBA", size=(w, h), data=pixel_bytes) img = img.transpose(Image.FLIP_TOP_BOTTOM) - img.save("%s%s" % (self.documents_dir + SCREENSHOT_DIR, output_filename)) - self.log("Saved screenshot %s" % output_filename) + img.save("{}{}".format(self.documents_dir + SCREENSHOT_DIR, output_filename)) + self.log("Saved screenshot {}".format(output_filename)) def enter_game_mode(self): self.game_mode = True @@ -960,12 +964,12 @@ class Application: def debug_onion_frames(self): "debug function to log onion renderable state" # TODO: remove this once it's served its purpose - debug = ["current frame: %s" % self.ui.active_art.active_frame, ""] + debug = ["current frame: {}".format(self.ui.active_art.active_frame), ""] debug.append("onion_renderables_prev:") def get_onion_info(i, r): visible = "VISIBLE" if r.visible else "" - return "%s: %s frame %s %s" % ( + return "{}: {} frame {} {}".format( i, r.art.filename.ljust(20), r.frame, @@ -991,7 +995,7 @@ class Application: if line.strip(): self.log(line.rstrip()) return - self.log("Using %s as overlay image." % image_filename) + self.log("Using {} as overlay image.".format(image_filename)) self.overlay_renderable = r self.ui.size_and_position_overlay_image() self.draw_overlay = True @@ -1058,7 +1062,7 @@ class Application: # setting already found, remove this redundant line self.config_lines.remove(line) # get current value from top-level scope and write it to end of cfg - self.config_lines += "%s = %s\n" % (setting_name, setting_value) + self.config_lines += "{} = {}\n".format(setting_name, setting_value) def save_persistent_config(self): "write options we want to persist across sessions to config file" @@ -1126,7 +1130,7 @@ class Application: editor_bin = os.environ.get("EDITOR", None) if not editor_bin: return - cmd = '%s "%s"' % (editor_bin, cfg_path) + cmd = '{} "{}"'.format(editor_bin, cfg_path) os.system(cmd) # update resident cfg file lines, which will be saved out on exit self.config_lines = open(cfg_path).readlines() @@ -1136,7 +1140,7 @@ class Application: def open_local_url(self, url): "opens given local (this file system) URL in a cross-platform way" - webbrowser.open("file://%s/%s" % (os.getcwd(), url)) + webbrowser.open("file://{}/{}".format(os.getcwd(), url)) def open_help_docs(self): self.open_local_url(WEBSITE_HELP_URL) @@ -1202,7 +1206,7 @@ def get_paths(): if os.path.exists(documents_dir + DOCUMENTS_SUBDIR): documents_dir += DOCUMENTS_SUBDIR # add Playscii/ to documents path - documents_dir += "/%s/" % APP_NAME + documents_dir += "/{}/".format(APP_NAME) # create Playscii dir AND subdirs for user art, charsets etc if not present for subdir in [ "", @@ -1242,7 +1246,7 @@ class Logger: self.log_file = open(config_dir + LOG_FILENAME, "w", bufsize) def log(self, new_line): - self.log_file.write("%s\n" % new_line) + self.log_file.write("{}\n".format(new_line)) self.lines.append(str(new_line)) print(new_line) @@ -1257,7 +1261,7 @@ def get_app(): # start logger even before Application has initialized so we can write to it # startup message: application and version # logger = Logger(config_dir) - logger.log("%s v%s" % (APP_NAME, get_version())) + logger.log("{} v{}".format(APP_NAME, get_version())) # see if "autoplay this game" file exists and has anything in it autoplay_game = None if os.path.exists(AUTOPLAY_GAME_FILENAME): @@ -1267,7 +1271,7 @@ def get_app(): # load in config - may change above values and submodule class defaults cfg_filename = config_dir + CONFIG_FILENAME if os.path.exists(cfg_filename): - logger.log("Loading config from %s..." % cfg_filename) + logger.log("Loading config from {}...".format(cfg_filename)) # execute cfg line by line so we can continue past lines with errors. # this does mean that commenting out blocks with triple-quotes fails, # but that's not a good practice anyway. @@ -1287,7 +1291,7 @@ def get_app(): if "Error" in el: error = el break - logger.log(" Removing line %s with %s" % (i, error)) + logger.log(" Removing line {} with {}".format(i, error)) new_cfg = open(cfg_filename, "w") new_cfg.writelines(new_cfg_lines) new_cfg.close() @@ -1300,7 +1304,7 @@ def get_app(): new_cfg.writelines(default_data) new_cfg.close() exec("".join(default_data)) - logger.log("Created new config file %s" % cfg_filename) + logger.log("Created new config file {}".format(cfg_filename)) art_to_load, game_dir_to_load, state_to_load = None, None, None # usage: # playscii.py [artfile] | [-game gamedir [-state statefile | artfile]] diff --git a/renderable.py b/renderable.py index c3fa184..9fc82ac 100644 --- a/renderable.py +++ b/renderable.py @@ -97,14 +97,14 @@ class TileRenderable: if self.app.use_vao: GL.glBindVertexArray(0) if self.log_create_destroy: - self.app.log("created: %s" % self) + self.app.log("created: {}".format(self)) def __str__(self): "for debug purposes, return a concise unique name" for i, r in enumerate(self.art.renderables): if r is self: break - return "%s %s %s" % (self.art.get_simple_name(), self.__class__.__name__, i) + return "{} {} {}".format(self.art.get_simple_name(), self.__class__.__name__, i) def create_buffers(self): # vertex positions and elements @@ -229,8 +229,7 @@ class TileRenderable: ): if self.log_buffer_updates: self.app.log( - "update_buffer: %s, %s, %s, %s, %s, %s, %s" - % ( + "update_buffer: {}, {}, {}, {}, {}, {}, {}".format( buffer_index, array, target, @@ -268,7 +267,7 @@ class TileRenderable: self.update_tile_buffers(True, True, True, True) if self.log_animation: self.app.log( - "%s animating from frames %s to %s" % (self, old_frame, self.frame) + "{} animating from frames {} to {}".format(self, old_frame, self.frame) ) def start_animating(self): @@ -320,7 +319,9 @@ class TileRenderable: self.goal_x, self.goal_y, self.goal_z = x, y, z if self.log_animation: self.app.log( - "%s will move to %s,%s" % (self.art.filename, self.goal_x, self.goal_y) + "{} will move to {},{}".format( + self.art.filename, self.goal_x, self.goal_y + ) ) def snap_to(self, x, y, z): @@ -409,7 +410,7 @@ class TileRenderable: if self.art and self in self.art.renderables: self.art.renderables.remove(self) if self.log_create_destroy: - self.app.log("destroyed: %s" % self) + self.app.log("destroyed: {}".format(self)) def get_projection_matrix(self): """ diff --git a/renderable_line.py b/renderable_line.py index 06b6a8b..7598297 100644 --- a/renderable_line.py +++ b/renderable_line.py @@ -27,7 +27,7 @@ class LineRenderable: self.app = app # we may be attached to a game object self.go = game_object - self.unique_name = "%s_%s" % (int(time.time()), self.__class__.__name__) + self.unique_name = "{}_{}".format(int(time.time()), self.__class__.__name__) self.quad_size_ref = quad_size_ref self.x, self.y, self.z = 0, 0, 0 self.scale_x, self.scale_y = 1, 1 @@ -94,7 +94,7 @@ class LineRenderable: if self.app.use_vao: GL.glBindVertexArray(0) if self.log_create_destroy: - self.app.log("created: %s" % self) + self.app.log("created: {}".format(self)) def __str__(self): "for debug purposes, return a unique name" @@ -178,7 +178,7 @@ class LineRenderable: GL.glDeleteVertexArrays(1, [self.vao]) GL.glDeleteBuffers(3, [self.vert_buffer, self.elem_buffer, self.color_buffer]) if self.log_create_destroy: - self.app.log("destroyed: %s" % self) + self.app.log("destroyed: {}".format(self)) def render(self): if not self.visible: diff --git a/renderable_sprite.py b/renderable_sprite.py index 34e5e9c..1cdbbd5 100644 --- a/renderable_sprite.py +++ b/renderable_sprite.py @@ -23,7 +23,7 @@ class SpriteRenderable: def __init__(self, app, texture_filename=None, image_data=None): self.app = app - self.unique_name = "%s_%s" % (int(time.time()), self.__class__.__name__) + self.unique_name = "{}_{}".format(int(time.time()), self.__class__.__name__) self.x, self.y, self.z = self.get_initial_position() self.scale_x, self.scale_y, self.scale_z = self.get_initial_scale() if self.app.use_vao: diff --git a/shader.py b/shader.py index d21ed3e..c0cf2ee 100644 --- a/shader.py +++ b/shader.py @@ -65,28 +65,34 @@ class Shader: self.last_vert_change = time.time() vert_source = self.get_shader_source(self.vert_source_file) if self.log_compile: - self.sl.app.log("Compiling vertex shader %s..." % self.vert_source_file) + self.sl.app.log( + "Compiling vertex shader {}...".format(self.vert_source_file) + ) self.vert_shader = self.try_compile_shader( vert_source, GL.GL_VERTEX_SHADER, self.vert_source_file ) if self.log_compile and self.vert_shader: self.sl.app.log( - "Compiled vertex shader %s in %.6f seconds" - % (self.vert_source_file, time.time() - self.last_vert_change) + "Compiled vertex shader {} in {:.6f} seconds".format( + self.vert_source_file, time.time() - self.last_vert_change + ) ) # fragment shader self.frag_source_file = frag_source_file self.last_frag_change = time.time() frag_source = self.get_shader_source(self.frag_source_file) if self.log_compile: - self.sl.app.log("Compiling fragment shader %s..." % self.frag_source_file) + self.sl.app.log( + "Compiling fragment shader {}...".format(self.frag_source_file) + ) self.frag_shader = self.try_compile_shader( frag_source, GL.GL_FRAGMENT_SHADER, self.frag_source_file ) if self.log_compile and self.frag_shader: self.sl.app.log( - "Compiled fragment shader %s in %.6f seconds" - % (self.frag_source_file, time.time() - self.last_frag_change) + "Compiled fragment shader {} in {:.6f} seconds".format( + self.frag_source_file, time.time() - self.last_frag_change + ) ) # shader program if self.vert_shader and self.frag_shader: @@ -103,7 +109,7 @@ class Shader: shader_version = self.glsl_version_macos else: shader_version = self.glsl_version_unix - version_string = "#version %s\n" % shader_version + version_string = "#version {}\n".format(shader_version) src = bytes(version_string, "utf-8") + src return src @@ -112,7 +118,7 @@ class Shader: try: shader = shaders.compileShader(source, shader_type) except Exception as e: - self.sl.app.log("%s: " % source_filename) + self.sl.app.log("{}: ".format(source_filename)) lines = e.args[0].split("\\n") # salvage block after "shader compile failure" enclosed in b"" pre = lines.pop(0).split('b"') @@ -142,9 +148,9 @@ class Shader: try: new_shader = shaders.compileShader(new_shader_source, shader_type) # TODO: use try_compile_shader instead here, make sure exception passes thru ok - self.sl.app.log("ShaderLord: success reloading %s" % file_to_reload) + self.sl.app.log("ShaderLord: success reloading {}".format(file_to_reload)) except: - self.sl.app.log("ShaderLord: failed reloading %s" % file_to_reload) + self.sl.app.log("ShaderLord: failed reloading {}".format(file_to_reload)) return # recompile program with new shader if shader_type == GL.GL_VERTEX_SHADER: diff --git a/ui.py b/ui.py index c606954..10490b8 100644 --- a/ui.py +++ b/ui.py @@ -120,7 +120,7 @@ class UI: # create tools for t in self.tool_classes: new_tool = t(self) - tool_name = "%s_tool" % new_tool.name + tool_name = "{}_tool".format(new_tool.name) setattr(self, tool_name, new_tool) # stick in a list for popup tool tab self.tools.append(new_tool) @@ -208,8 +208,9 @@ class UI: self.set_elements_scale() if self.scale != old_scale: self.message_line.post_line( - "UI scale is now %s (%.3f x %.3f)" - % (self.scale, self.width_tiles, self.height_tiles) + "UI scale is now {} ({:.3f} x {:.3f})".format( + self.scale, self.width_tiles, self.height_tiles + ) ) def set_elements_scale(self): @@ -282,7 +283,7 @@ class UI: self.app.update_window_title() if self.app.can_edit: self.message_line.post_line( - "%s %s" % (self.art_selected_log, self.active_art.filename) + "{} {}".format(self.art_selected_log, self.active_art.filename) ) def set_active_art_by_filename(self, art_filename): @@ -345,7 +346,9 @@ class UI: if self.menu_bar.active_menu_name and not cycled_fill: self.menu_bar.close_active_menu() self.message_line.post_line( - "%s %s" % (self.selected_tool.get_button_caption(), self.tool_selected_log) + "{} {}".format( + self.selected_tool.get_button_caption(), self.tool_selected_log + ) ) def cycle_fill_tool_mode(self): @@ -374,7 +377,7 @@ class UI: self.selected_xform = new_xform self.popup.set_xform(new_xform) self.tool_settings_changed = True - line = "%s %s" % (self.xform_selected_log, uv_names[self.selected_xform]) + line = "{} {}".format(self.xform_selected_log, uv_names[self.selected_xform]) self.message_line.post_line(line) def cycle_selected_xform(self, back=False): @@ -592,7 +595,7 @@ class UI: command = EntireArtCommand(art, min_x, min_y) command.save_tiles(before=True) art.resize(w, h, min_x, min_y) - self.app.log("Resized %s to %s x %s" % (art.filename, w, h)) + self.app.log("Resized {} to {} x {}".format(art.filename, w, h)) art.set_unsaved_changes(True) # clear selection to avoid having tiles we know are OoB selected self.select_tool.selected_tiles = {} diff --git a/ui_art_dialog.py b/ui_art_dialog.py index 26d2e45..d100e72 100644 --- a/ui_art_dialog.py +++ b/ui_art_dialog.py @@ -74,7 +74,7 @@ class NewArtDialog(BaseFileDialog): def get_initial_field_text(self, field_number): if field_number == 0: - return "new%s" % len(self.ui.app.art_loaded_for_edit) + return "new{}".format(len(self.ui.app.art_loaded_for_edit)) elif field_number == 2: return str(DEFAULT_WIDTH) elif field_number == 4: @@ -116,7 +116,7 @@ class NewArtDialog(BaseFileDialog): name = self.field_texts[0] w, h = int(self.field_texts[2]), int(self.field_texts[4]) self.ui.app.new_art_for_edit(name, w, h) - self.ui.app.log("Created %s.psci with size %s x %s" % (name, w, h)) + self.ui.app.log("Created {}.psci with size {} x {}".format(name, w, h)) self.dismiss() @@ -266,7 +266,7 @@ class ImportOptionsDialog(UIDialog): importer = app.importer(app, filename, options) if importer.success: if app.importer.completes_instantly: - app.log("Imported %s successfully." % filename) + app.log("Imported {} successfully.".format(filename)) app.importer = None @@ -280,7 +280,7 @@ class ExportOptionsDialog(UIDialog): # if importer needs no options, run it exporter = app.exporter(app, filename, options) if exporter.success: - app.log("Exported %s successfully." % exporter.out_filename) + app.log("Exported {} successfully.".format(exporter.out_filename)) class ExportFileDialog(ConvertFileDialog): @@ -606,7 +606,7 @@ class AddLayerDialog(UIDialog): def get_initial_field_text(self, field_number): if field_number == 0: - return "Layer %s" % str(self.ui.active_art.layers + 1) + return "Layer {}".format(str(self.ui.active_art.layers + 1)) elif field_number == 1: return str( self.ui.active_art.layers_z[self.ui.active_art.active_layer] @@ -761,7 +761,7 @@ class SetCameraZoomDialog(UIDialog): def get_initial_field_text(self, field_number): if field_number == 0: - return "%.1f" % self.ui.app.camera.get_current_zoom_pct() + return "{:.1f}".format(self.ui.app.camera.get_current_zoom_pct()) return "" def is_input_valid(self): diff --git a/ui_button.py b/ui_button.py index 28f1ca3..326dfa1 100644 --- a/ui_button.py +++ b/ui_button.py @@ -52,15 +52,17 @@ class UIButton: "common code for button event logging" if self.element.ui.logg: self.element.ui.app.log( - "UIButton: %s's %s %s" - % (self.element.__class__.__name__, self.__class__.__name__, event_type) + "UIButton: {}'s {} {}".format( + self.element.__class__.__name__, self.__class__.__name__, event_type + ) ) def set_state(self, new_state): if new_state not in BUTTON_STATES: self.element.ui.app.log( - "Unrecognized state for button %s: %s" - % (self.__class__.__name__, new_state) + "Unrecognized state for button {}: {}".format( + self.__class__.__name__, new_state + ) ) return self.dimmed = new_state == "dimmed" @@ -68,8 +70,8 @@ class UIButton: self.set_state_colors() def get_state_colors(self, state): - fg = getattr(self, "%s_fg_color" % state) - bg = getattr(self, "%s_bg_color" % state) + fg = getattr(self, "{}_fg_color".format(state)) + bg = getattr(self, "{}_bg_color".format(state)) return fg, bg def set_state_colors(self): diff --git a/ui_chooser_dialog.py b/ui_chooser_dialog.py index e4bf2be..90269af 100644 --- a/ui_chooser_dialog.py +++ b/ui_chooser_dialog.py @@ -178,7 +178,7 @@ class ChooserDialog(UIDialog): try: l = os.listdir(new_dir) except PermissionError: - line = "No permission to access %s!" % os.path.abspath(new_dir) + line = "No permission to access {}!".format(os.path.abspath(new_dir)) self.ui.message_line.post_line(line, error=True) return False self.current_dir = new_dir diff --git a/ui_console.py b/ui_console.py index e8bb848..dd756fc 100644 --- a/ui_console.py +++ b/ui_console.py @@ -138,9 +138,11 @@ class ImportCommand(ConsoleCommand): if c.__name__ == importer_classname: importer_class = c if not importer_class: - console.ui.app.log("Couldn't find importer class %s" % importer_classname) + console.ui.app.log( + "Couldn't find importer class {}".format(importer_classname) + ) if not os.path.exists(filename): - console.ui.app.log("Couldn't find file %s" % filename) + console.ui.app.log("Couldn't find file {}".format(filename)) importer = importer_class(console.ui.app, filename) @@ -157,7 +159,9 @@ class ExportCommand(ConsoleCommand): if c.__name__ == exporter_classname: exporter_class = c if not exporter_class: - console.ui.app.log("Couldn't find exporter class %s" % exporter_classname) + console.ui.app.log( + "Couldn't find exporter class {}".format(exporter_classname) + ) exporter = exporter_class(console.ui.app, filename) @@ -227,7 +231,7 @@ class CommandListCommand(ConsoleCommand): command_list.sort() for command in command_list: desc = commands[command].description - console.ui.app.log(" %s - %s" % (command, desc)) + console.ui.app.log(" {} - {}".format(command, desc)) class RunArtScriptCommand(ConsoleCommand): @@ -417,7 +421,7 @@ class ConsoleUI(UIElement): "draw current user input on second to last line, with >_ prompt" # clear entire user line first self.art.write_string(0, 0, 0, -2, " " * self.width, self.text_color) - self.art.write_string(0, 0, 0, -2, "%s " % self.prompt, self.text_color) + self.art.write_string(0, 0, 0, -2, "{} ".format(self.prompt), self.text_color) # if first item of line is a valid command, change its color items = self.current_line.split() if len(items) > 0 and items[0] in commands: @@ -487,7 +491,7 @@ class ConsoleUI(UIElement): self.toggle() return elif keystr == "Return": - line = "%s %s" % (self.prompt, self.current_line) + line = "{} {}".format(self.prompt, self.current_line) self.ui.app.log(line) # if command is same as last, don't repeat it if len(self.command_history) == 0 or ( @@ -579,7 +583,7 @@ class ConsoleUI(UIElement): output = str(eval(line)) except Exception as e: # try to output useful error text - output = "%s: %s" % (e.__class__.__name__, str(e)) + output = "{}: {}".format(e.__class__.__name__, str(e)) # commands CAN return None, so only log if there's something if output and output != "None": self.ui.app.log(output) diff --git a/ui_edit_panel.py b/ui_edit_panel.py index 1606c54..930f74c 100644 --- a/ui_edit_panel.py +++ b/ui_edit_panel.py @@ -296,7 +296,7 @@ class EditListPanel(GamePanel): self.list_scroll_index = min(self.list_scroll_index, len(self.items)) def get_label(self): - label = "%s (%s)" % ( + label = "{} ({})".format( self.list_operation_labels[self.list_operation], self.cancel_tip, ) @@ -475,7 +475,7 @@ class EditListPanel(GamePanel): items = self.list_rooms() # prefix room names with "ROOM:" for i, item in enumerate(items): - item.name = "ROOM: %s" % item.name + item.name = "ROOM: {}".format(item.name) items += self.list_objects() return items diff --git a/ui_element.py b/ui_element.py index 5ede0ce..b62088f 100644 --- a/ui_element.py +++ b/ui_element.py @@ -37,7 +37,7 @@ class UIElement: self.ui = ui self.hovered_buttons = [] # generate a unique name - art_name = "%s_%s" % (int(time.time()), self.__class__.__name__) + art_name = "{}_{}".format(int(time.time()), self.__class__.__name__) self.art = UIArt( art_name, self.ui.app, @@ -135,8 +135,9 @@ class UIElement: mouse_button = mouse_button or "[n/a]" if self.ui.logg: self.ui.app.log( - "UIElement: %s %s with mouse button %s" - % (self.__class__.__name__, event_type, mouse_button) + "UIElement: {} {} with mouse button {}".format( + self.__class__.__name__, event_type, mouse_button + ) ) def is_visible(self): @@ -303,11 +304,11 @@ class FPSCounterUI(UIElement): color = self.ui.colors.yellow if self.ui.app.fps < 10: color = self.ui.colors.red - text = "%.1f fps" % self.ui.app.fps + text = "{:.1f} fps".format(self.ui.app.fps) x = self.tile_width - 1 self.art.write_string(0, 0, x, 0, text, color, None, True) # display last tick time; frame_time includes delay, is useless - text = "%.1f ms " % self.ui.app.frame_time + text = "{:.1f} ms ".format(self.ui.app.frame_time) self.art.write_string(0, 0, x, 1, text, color, None, True) def render(self): diff --git a/ui_file_chooser_dialog.py b/ui_file_chooser_dialog.py index 6840401..72cf259 100644 --- a/ui_file_chooser_dialog.py +++ b/ui_file_chooser_dialog.py @@ -144,15 +144,15 @@ class ArtChooserItem(BaseFileChooserItem): return [] mod_time = time.gmtime(self.art_mod_time) mod_time = time.strftime("%Y-%m-%d %H:%M:%S", mod_time) - lines = ["last change: %s" % mod_time] - line = "%s x %s, " % (self.art_width, self.art_height) - line += "%s frame" % self.art_frames + lines = ["last change: {}".format(mod_time)] + line = "{} x {}, ".format(self.art_width, self.art_height) + line += "{} frame".format(self.art_frames) # pluralize properly line += "s" if self.art_frames > 1 else "" - line += ", %s layer" % self.art_layers + line += ", {} layer".format(self.art_layers) line += "s" if self.art_layers > 1 else "" lines += [line] - lines += ["char: %s, pal: %s" % (self.art_charset, self.art_palette)] + lines += ["char: {}, pal: {}".format(self.art_charset, self.art_palette)] return lines def get_preview_texture(self, app): @@ -312,7 +312,7 @@ class PaletteChooserItem(BaseFileChooserItem): def get_description_lines(self): colors = len(self.palette.colors) - return ["Unique colors: %s" % str(colors - 1)] + return ["Unique colors: {}".format(str(colors - 1))] def get_preview_texture(self, app): return self.palette.src_texture @@ -370,7 +370,7 @@ class CharsetChooserItem(BaseFileChooserItem): if line.startswith("//"): lines.append(line[2:]) break - lines.append("Characters: %s" % str(self.charset.last_index)) + lines.append("Characters: {}".format(str(self.charset.last_index))) return lines def get_preview_texture(self, app): diff --git a/ui_game_menu_pulldown_item.py b/ui_game_menu_pulldown_item.py index 553f60c..1907f88 100644 --- a/ui_game_menu_pulldown_item.py +++ b/ui_game_menu_pulldown_item.py @@ -443,7 +443,7 @@ class GameRoomMenuData(PulldownMenuData): item = TempMenuItemClass # leave spaces for mark - item.label = " %s" % room_name + item.label = " {}".format(room_name) # pad, put Z depth on far right item.label = item.label.ljust(longest_line) # trim to keep below a max length diff --git a/ui_info_dialog.py b/ui_info_dialog.py index 85df1c5..9833aaf 100644 --- a/ui_info_dialog.py +++ b/ui_info_dialog.py @@ -131,5 +131,5 @@ class AboutDialog(PagedInfoDialog): all_modes_visible = True def __init__(self, ui, options): - self.title += " %s" % ui.app.version + self.title += " {}".format(ui.app.version) PagedInfoDialog.__init__(self, ui, options) diff --git a/ui_menu_bar.py b/ui_menu_bar.py index a4cf5c0..a1011da 100644 --- a/ui_menu_bar.py +++ b/ui_menu_bar.py @@ -217,7 +217,7 @@ class MenuBar(UIElement): button.width = len(button.caption) + 2 button.x = x x += button.width + self.button_padding - setattr(self, "%s_button" % button.name, button) + setattr(self, "{}_button".format(button.name), button) # NOTE: callback already defined in MenuButton class, # menu data for pulldown with set in MenuButton subclass button.pulldown = self.ui.pulldown diff --git a/ui_menu_pulldown.py b/ui_menu_pulldown.py index 98eb7da..a690238 100644 --- a/ui_menu_pulldown.py +++ b/ui_menu_pulldown.py @@ -173,7 +173,7 @@ class PulldownMenu(UIElement): for bind_tuple in binds: command_functions = binds[bind_tuple] for f in command_functions: - if f.__name__ == "BIND_%s" % menu_item.command: + if f.__name__ == "BIND_{}".format(menu_item.command): shortcut = "" # shift, alt, ctrl if bind_tuple[1]: @@ -187,5 +187,5 @@ class PulldownMenu(UIElement): if not (bind_tuple[0].startswith("_") and len(bind_tuple[0]) > 1): shortcut += bind_tuple[0] return shortcut, f - self.ui.app.log("Shortcut/command not found: %s" % menu_item.command) + self.ui.app.log("Shortcut/command not found: {}".format(menu_item.command)) return "", null diff --git a/ui_menu_pulldown_item.py b/ui_menu_pulldown_item.py index d5acaea..aa59909 100644 --- a/ui_menu_pulldown_item.py +++ b/ui_menu_pulldown_item.py @@ -229,7 +229,9 @@ class ToolTogglePickerHoldItem(ArtModePulldownMenuItem): command = "toggle_picker_hold" def get_label(app): - return "Picker toggle key: %s" % ["press", "hold"][app.ui.popup_hold_to_show] + return "Picker toggle key: {}".format( + ["press", "hold"][app.ui.popup_hold_to_show] + ) class ToolSwapSelectedColors(ArtModePulldownMenuItem): @@ -247,42 +249,42 @@ class ToolToggleArtToolbar(ArtModePulldownMenuItem): class ToolPaintItem(ArtModePulldownMenuItem): # two spaces in front of each label to leave room for mark - label = " %s" % PencilTool.button_caption + label = " {}".format(PencilTool.button_caption) command = "select_pencil_tool" class ToolEraseItem(ArtModePulldownMenuItem): - label = " %s" % EraseTool.button_caption + label = " {}".format(EraseTool.button_caption) command = "select_erase_tool" class ToolRotateItem(ArtModePulldownMenuItem): - label = " %s" % RotateTool.button_caption + label = " {}".format(RotateTool.button_caption) command = "select_rotate_tool" class ToolGrabItem(ArtModePulldownMenuItem): - label = " %s" % GrabTool.button_caption + label = " {}".format(GrabTool.button_caption) command = "select_grab_tool" class ToolTextItem(ArtModePulldownMenuItem): - label = " %s" % TextTool.button_caption + label = " {}".format(TextTool.button_caption) command = "select_text_tool" class ToolSelectItem(ArtModePulldownMenuItem): - label = " %s" % SelectTool.button_caption + label = " {}".format(SelectTool.button_caption) command = "select_select_tool" class ToolPasteItem(ArtModePulldownMenuItem): - label = " %s" % PasteTool.button_caption + label = " {}".format(PasteTool.button_caption) command = "select_paste_tool" class ToolFillItem(ArtModePulldownMenuItem): - label = " %s" % FillTool.button_caption + label = " {}".format(FillTool.button_caption) command = "select_fill_tool" @@ -299,7 +301,7 @@ class ToolIncreaseBrushSizeItem(ArtModePulldownMenuItem): if not app.ui.selected_tool.brush_size: return "Increase brush size" size = app.ui.selected_tool.brush_size + 1 - return "Increase brush size to %s" % size + return "Increase brush size to {}".format(size) class ToolDecreaseBrushSizeItem(ArtModePulldownMenuItem): @@ -315,7 +317,7 @@ class ToolDecreaseBrushSizeItem(ArtModePulldownMenuItem): if not app.ui.selected_tool.brush_size: return "Decrease brush size" size = app.ui.selected_tool.brush_size - 1 - return "Decrease brush size to %s" % size + return "Decrease brush size to {}".format(size) class ToolSettingsItem(ArtModePulldownMenuItem): @@ -366,9 +368,8 @@ class ToolSetFillBoundariesItem(ArtModePulldownMenuItem): return type(app.ui.selected_tool) is not FillTool def get_label(app): - return ( - "Fill tool bounded by: %s" - % app.ui.fill_tool.boundary_mode_names[app.ui.fill_tool.boundary_mode] + return "Fill tool bounded by: {}".format( + app.ui.fill_tool.boundary_mode_names[app.ui.fill_tool.boundary_mode] ) @@ -467,9 +468,8 @@ class ViewSetOverlayImageScalingItem(ArtModePulldownMenuItem): command = "set_overlay_image_scaling" def get_label(app): - return ( - "Overlay image scaling: %s" - % ["width", "height", "fill"][app.overlay_scale_type] + return "Overlay image scaling: {}".format( + ["width", "height", "fill"][app.overlay_scale_type] ) def should_dim(app): @@ -588,7 +588,7 @@ class FrameToggleOnionItem(ArtModePulldownMenuItem): return not app.ui.active_art or app.ui.active_art.frames < 2 def get_label(app): - l = "%s onion skin frames" % ["Show", "Hide"][app.onion_frames_visible] + l = "{} onion skin frames".format(["Show", "Hide"][app.onion_frames_visible]) return l @@ -600,7 +600,7 @@ class FrameCycleOnionFramesItem(ArtModePulldownMenuItem): return not app.ui.active_art or app.ui.active_art.frames < 2 def get_label(app): - return "Number of onion frames: %s" % app.onion_show_frames + return "Number of onion frames: {}".format(app.onion_show_frames) class FrameCycleOnionDisplayItem(ArtModePulldownMenuItem): @@ -617,7 +617,7 @@ class FrameCycleOnionDisplayItem(ArtModePulldownMenuItem): display = "Previous" else: display = "Next" - return "Onion frames show: %s" % display + return "Onion frames show: {}".format(display) class FrameAddFrameItem(ArtModePulldownMenuItem): @@ -872,7 +872,7 @@ class ToolMenuData(PulldownMenuData): # if it's a tool setting toggle, use its own mark check function if item.__bases__[0] is ToolSettingsItem or hasattr(item, "should_mark"): return item.should_mark(ui) - return item.label == " %s" % ui.selected_tool.button_caption + return item.label == " {}".format(ui.selected_tool.button_caption) class ViewMenuData(PulldownMenuData): @@ -933,7 +933,7 @@ class ArtMenuData(PulldownMenuData): item = TempMenuItemClass # leave spaces for mark - item.label = " %s" % art.filename + item.label = " {}".format(art.filename) item.command = "art_switch_to" item.cb_arg = art.filename # order list by art's time loaded @@ -1008,7 +1008,7 @@ class LayerMenuData(PulldownMenuData): item = TempMenuItemClass # leave spaces for mark - item.label = " %s" % layer_name + item.label = " {}".format(layer_name) if not app.ui.active_art.layers_visibility[i]: item.label += " (hidden)" # pad, put Z depth on far right @@ -1016,7 +1016,7 @@ class LayerMenuData(PulldownMenuData): # trim to keep below a max length item.label = item.label[:longest_line] # spaces between layer name and z depth - item.label += "z:%.2f" % app.ui.active_art.layers_z[i] + item.label += "z:{:.2f}".format(app.ui.active_art.layers_z[i]) # tell PulldownMenu's button creation process not to auto-pad item.no_pad = True item.command = "layer_switch_to" diff --git a/ui_object_panel.py b/ui_object_panel.py index 5d30531..ab2d65f 100644 --- a/ui_object_panel.py +++ b/ui_object_panel.py @@ -64,7 +64,7 @@ class PropertyItem: def set_value(self, value): # convert value to a button-friendly string if type(value) is float: - valstr = "%.3f" % value + valstr = "{:.3f}".format(value) # non-fixed decimal version may be shorter, if so use it if len(str(value)) < len(valstr): valstr = str(value) @@ -178,7 +178,7 @@ class EditObjectPanel(GamePanel): elif selected == 1 and self.world.selected_objects[0]: return self.world.selected_objects[0].name else: - return "[%s selected]" % selected + return "[{} selected]".format(selected) def refresh_items(self): if len(self.world.selected_objects) == 0: @@ -222,14 +222,14 @@ class EditObjectPanel(GamePanel): button.can_hover = False return # set button caption, width, x based on value - button.caption = "%s " % item.prop_value + button.caption = "{} ".format(item.prop_value) button.width = len(button.caption) + 1 button.x = self.tile_width - button.width button.cb_arg = item button.can_hover = True # set non-button text to the left correctly x = button.x + 1 - label = "%s: " % item.prop_name + label = "{}: ".format(item.prop_name) self.art.write_string(0, 0, x, y, label, UIColors.darkgrey, None, True) def update(self): diff --git a/ui_popup.py b/ui_popup.py index 3750cd6..18878ed 100644 --- a/ui_popup.py +++ b/ui_popup.py @@ -261,10 +261,10 @@ class ToolPopup(UIElement): for tool in self.ui.tools: tool_button = ToolButton(self) # caption: 1-space padding from left - tool_button.caption = " %s" % tool.button_caption - tool_button_name = "%s_tool_button" % tool.name + tool_button.caption = " {}".format(tool.button_caption) + tool_button_name = "{}_tool_button".format(tool.name) setattr(self, tool_button_name, tool_button) - cb_name = "%s_pressed" % tool_button_name + cb_name = "{}_pressed".format(tool_button_name) tool_button.callback = getattr(self, cb_name) # set a special property UI can refer to tool_button.tool_name = tool.name @@ -280,9 +280,9 @@ class ToolPopup(UIElement): buttons = [] for button_class in button_dict: button = button_class(self) - button_name = "%s_button" % button_dict[button_class] + button_name = "{}_button".format(button_dict[button_class]) setattr(self, button_name, button) - cb_name = "%s_pressed" % button_name + cb_name = "{}_pressed".format(button_name) button.callback = getattr(self, cb_name) buttons.append(button) return buttons @@ -439,13 +439,13 @@ class ToolPopup(UIElement): # position & caption charset button y = self.tab_height + 1 self.choose_charset_button.y = y - self.choose_charset_button.caption = " %s %s " % ( + self.choose_charset_button.caption = " {} {} ".format( CharSetChooserButton.caption, charset.name, ) self.choose_charset_button.width = len(self.choose_charset_button.caption) # charset scale - charset_scale = "%.2fx" % self.charset_swatch.char_scale + charset_scale = "{:.2f}x".format(self.charset_swatch.char_scale) x = -self.scale_charset_up_button.width * 2 self.art.write_string(0, 0, x, y, charset_scale, None, None, True) # transform labels and buttons, eg @@ -460,7 +460,7 @@ class ToolPopup(UIElement): pal_caption_y = (cqh * charset.map_height) / self.art.quad_height pal_caption_y += self.tab_height + 5 self.choose_palette_button.y = int(pal_caption_y) - self.choose_palette_button.caption = " %s %s " % ( + self.choose_palette_button.caption = " {} {} ".format( PaletteChooserButton.caption, palette.name, ) @@ -495,7 +495,7 @@ class ToolPopup(UIElement): # draw current tool settings x = TOOL_PANE_WIDTH + 1 y = self.tab_height + 1 - label = "%s %s" % ( + label = "{} {}".format( self.ui.selected_tool.button_caption, self.tool_settings_label, ) @@ -510,7 +510,7 @@ class ToolPopup(UIElement): # calculate X of + and - buttons based on size string self.brush_size_down_button.x = TOOL_PANE_WIDTH + len(label) + 2 label += " " * (self.brush_size_down_button.width + 1) - label += "%s" % self.ui.selected_tool.brush_size + label += "{}".format(self.ui.selected_tool.brush_size) self.brush_size_up_button.x = TOOL_PANE_WIDTH + len(label) + 3 self.art.write_string(0, 0, x, y, label) else: @@ -546,7 +546,7 @@ class ToolPopup(UIElement): (self.affects_xform_label, self.ui.selected_tool.affects_xform) ] for label, toggle in label_toggle_pairs: - self.art.write_string(0, 0, x + w + 1, y, "%s" % label) + self.art.write_string(0, 0, x + w + 1, y, "{}".format(label)) # self.art.set_tile_at(0, 0, x, y, get_affects_char(toggle), 4, 2) self.art.set_char_index_at(0, 0, x + 1, y, get_affects_char(toggle)) y += 1 diff --git a/ui_status_bar.py b/ui_status_bar.py index af9ed49..d1c13f7 100644 --- a/ui_status_bar.py +++ b/ui_status_bar.py @@ -29,7 +29,7 @@ class CharToggleButton(StatusBarToggleButton): tooltip_on_hover = True def get_tooltip_text(self): - return "character index: %s" % self.element.ui.selected_char + return "character index: {}".format(self.element.ui.selected_char) def get_tooltip_location(self): return 1, self.element.get_tile_y() - 1 @@ -54,7 +54,7 @@ class FGToggleButton(StatusBarToggleButton): tooltip_on_hover = True def get_tooltip_text(self): - return "foreground color index: %s" % self.element.ui.selected_fg_color + return "foreground color index: {}".format(self.element.ui.selected_fg_color) def get_tooltip_location(self): return 8, self.element.get_tile_y() - 1 @@ -78,7 +78,7 @@ class BGToggleButton(StatusBarToggleButton): tooltip_on_hover = True def get_tooltip_text(self): - return "background color index: %s" % self.element.ui.selected_bg_color + return "background color index: {}".format(self.element.ui.selected_bg_color) def get_tooltip_location(self): return 15, self.element.get_tile_y() - 1 @@ -188,7 +188,7 @@ class StatusBarUI(UIElement): art = ui.active_art self.ui = ui # create 3 custom Arts w/ source charset and palette, renderables for each - art_name = "%s_%s" % (int(time.time()), self.__class__.__name__) + art_name = "{}_{}".format(int(time.time()), self.__class__.__name__) self.char_art = UIArt( art_name, ui.app, art.charset, art.palette, self.swatch_width, 1 ) @@ -225,7 +225,7 @@ class StatusBarUI(UIElement): for button_class, button_name in self.button_names.items(): button = button_class(self) setattr(self, button_name + "_button", button) - cb_name = "%s_button_pressed" % button_name + cb_name = "{}_button_pressed".format(button_name) button.callback = getattr(self, cb_name) self.buttons.append(button) # keep a mapping of button names to buttons, for eg tooltip updates @@ -436,15 +436,17 @@ class StatusBarUI(UIElement): # NOTE: button X offsets will be set in write_right_elements null = "---" layers = art.layers if art else 0 - layer = "%s/%s" % (art.active_layer + 1, layers) if art else null + layer = "{}/{}".format(art.active_layer + 1, layers) if art else null self.layer_cycle_button.caption = layer self.layer_cycle_button.width = len(self.layer_cycle_button.caption) frames = art.frames if art else 0 - frame = "%s/%s" % (art.active_frame + 1, frames) if art else null + frame = "{}/{}".format(art.active_frame + 1, frames) if art else null self.frame_cycle_button.caption = frame self.frame_cycle_button.width = len(self.frame_cycle_button.caption) # zoom % - zoom = "%.1f" % self.ui.app.camera.get_current_zoom_pct() if art else null + zoom = ( + "{:.1f}".format(self.ui.app.camera.get_current_zoom_pct()) if art else null + ) self.zoom_set_button.caption = zoom[:5] # maintain size def update(self): @@ -512,7 +514,7 @@ class StatusBarUI(UIElement): color = self.dim_color tile_x = str(tile_x).rjust(3) tile_y = str(tile_y).rjust(3) - tile = "%s,%s" % (tile_x, tile_y) + tile = "{},{}".format(tile_x, tile_y) self.art.write_string(0, 0, x, 0, tile, color, dark, True) # tile label x -= len(tile) diff --git a/ui_swatch.py b/ui_swatch.py index ed346e4..61831ab 100644 --- a/ui_swatch.py +++ b/ui_swatch.py @@ -20,7 +20,7 @@ class UISwatch(UIElement): self.tile_width, self.tile_height = self.get_size() art = self.ui.active_art # generate a unique name for debug purposes - art_name = "%s_%s" % (int(time.time()), self.__class__.__name__) + art_name = "{}_{}".format(int(time.time()), self.__class__.__name__) self.art = UIArt( art_name, self.ui.app, @@ -405,7 +405,7 @@ class PaletteSwatch(UISwatch): class ColorSelectionLabelArt(UIArt): def __init__(self, ui, letter): letter_index = ui.charset.get_char_index(letter) - art_name = "%s_%s" % (int(time.time()), self.__class__.__name__) + art_name = "{}_{}".format(int(time.time()), self.__class__.__name__) UIArt.__init__(self, art_name, ui.app, ui.charset, ui.palette, 1, 1) label_color = ui.colors.white label_bg_color = 0 diff --git a/ui_tool.py b/ui_tool.py index 8668575..6e2074a 100644 --- a/ui_tool.py +++ b/ui_tool.py @@ -69,7 +69,7 @@ class UITool: self.affects_char = not self.affects_char self.ui.tool_settings_changed = True line = self.button_caption + " " - line = "%s %s" % ( + line = "{} {}".format( self.button_caption, [self.ui.affects_char_off_log, self.ui.affects_char_on_log][ self.affects_char @@ -82,7 +82,7 @@ class UITool: return self.affects_fg_color = not self.affects_fg_color self.ui.tool_settings_changed = True - line = "%s %s" % ( + line = "{} {}".format( self.button_caption, [self.ui.affects_fg_off_log, self.ui.affects_fg_on_log][ self.affects_fg_color @@ -95,7 +95,7 @@ class UITool: return self.affects_bg_color = not self.affects_bg_color self.ui.tool_settings_changed = True - line = "%s %s" % ( + line = "{} {}".format( self.button_caption, [self.ui.affects_bg_off_log, self.ui.affects_bg_on_log][ self.affects_bg_color @@ -108,7 +108,7 @@ class UITool: return self.affects_xform = not self.affects_xform self.ui.tool_settings_changed = True - line = "%s %s" % ( + line = "{} {}".format( self.button_caption, [self.ui.affects_xform_off_log, self.ui.affects_xform_on_log][ self.affects_xform @@ -587,7 +587,7 @@ class FillTool(UITool): ] def get_button_caption(self): - return "%s (%s bounded)" % ( + return "{} ({} bounded)".format( self.button_caption, self.boundary_mode_names[self.boundary_mode], ) diff --git a/vector.py b/vector.py index 4770093..56b80e4 100644 --- a/vector.py +++ b/vector.py @@ -11,7 +11,7 @@ class Vec3: self.x, self.y, self.z = x, y, z def __str__(self): - return "Vec3 %.4f, %.4f, %.4f" % (self.x, self.y, self.z) + return "Vec3 {:.4f}, {:.4f}, {:.4f}".format(self.x, self.y, self.z) def __sub__(self, b): "Return a new vector subtracted from given other vector."