aboutsummaryrefslogtreecommitdiff
path: root/srb_tk.py
diff options
context:
space:
mode:
authorB. Stack <bgstack15@gmail.com>2024-04-05 16:59:45 -0400
committerB. Stack <bgstack15@gmail.com>2024-04-05 16:59:45 -0400
commit9f94a372f0aabc2967efa38023086ca904f59c2d (patch)
treee82eac38eadbce2a481c273ddc6b5309202aa757 /srb_tk.py
parentlib: rename to completed_levels, tk: show enabled levels (diff)
downloadsrb_lib-9f94a372f0aabc2967efa38023086ca904f59c2d.tar.gz
srb_lib-9f94a372f0aabc2967efa38023086ca904f59c2d.tar.bz2
srb_lib-9f94a372f0aabc2967efa38023086ca904f59c2d.zip
all: add reset breakables
Diffstat (limited to 'srb_tk.py')
-rwxr-xr-xsrb_tk.py103
1 files changed, 87 insertions, 16 deletions
diff --git a/srb_tk.py b/srb_tk.py
index dda1029..c141bb6 100755
--- a/srb_tk.py
+++ b/srb_tk.py
@@ -21,8 +21,14 @@
# possible way to have a widget store its variable: https://stackoverflow.com/questions/63871376/tkinter-widget-cgetvariable
# count number of 1s in a binary value https://stackoverflow.com/questions/8871204/count-number-of-1s-in-binary-representation/71307775#71307775
# https://stackoverflow.com/questions/67334913/can-i-possibly-put-an-image-label-into-an-option-box-in-tkinter
+# haybale <a target="_blank" href="https://icons8.com/icon/8Sk1THlBUpC6/hay-bale">Hay Bale</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
+# barrel <a target="_blank" href="https://icons8.com/icon/23346/wooden-beer-keg">Wooden Beer Keg</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
+# geyser <a target="_blank" href="https://icons8.com/icon/IjFwYfQ6Hmgc/geyser">Geyser</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
+# pumpkin <a target="_blank" href="https://icons8.com/icon/17358/pumpkin">Pumpkin</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
+# battery <a target="_blank" href="https://icons8.com/icon/dwzqRjO6XcTN/battery">Battery</a> icon by <a target="_blank" href="https://icons8.com">Icons8</a>
+# transparent image https://stackoverflow.com/questions/8376359/how-to-create-a-transparent-gif-or-png-with-pil-python-imaging
+# combine images https://stackoverflow.com/questions/30227466/combine-several-images-horizontally-with-python/30228308#30228308
# Improve:
-# Add reset-level-breakables
# Dependencies:
# dep-devuan: python3-tkinter, python3-pil.imagetk
# rec-devuan: python3-cairosvg
@@ -48,13 +54,16 @@ SPDX-License-Identifier: GPL-3.0-only
Icon courtesy of https://icons8.com/icon/9336/aircraft
"""
-def get_srb_image(filename, sizex, sizey, resample=Image.Resampling.LANCZOS):
+def get_srb_image(filename, sizex, sizey, resample=Image.Resampling.LANCZOS, photoImage = True):
""" helper function that returns an ImageTk from the named file from the configured images directory, resized for you. """
global IMAGE_FAILURES
if IMAGES and IMAGE_FAILURES < 5:
try:
img = Image.open(os.path.join(image_dir,filename)).resize((sizex,sizey),resample=resample)
- return ImageTk.PhotoImage(img)
+ if photoImage:
+ return ImageTk.PhotoImage(img)
+ else:
+ return img
except:
IMAGE_FAILURES += 1
print(f"Failed to load image {filename}, only {5-IMAGE_FAILURES} failures left before giving up on images entirely.",file=sys.stderr)
@@ -147,12 +156,14 @@ class App(tk.Frame):
self.level_letters = []
statuses = [i["name"] for i in srb_lib.LEVEL_STATUSES]
statuses_hex = [i["b"] for i in srb_lib.LEVEL_STATUSES]
+ self.level_breakables = []
for i in range(0,len(srb_lib.LEVELS)):
self.level_strs.append(tk.StringVar(value=srb_lib.get_level_info(i)[0]["name"]))
self.level_statuses_hex.append(tk.StringVar(value=statuses_hex[0]))
self.level_statuses.append(tk.StringVar(value=statuses[0]))
self.level_balloons.append(tk.IntVar())
self.level_letters.append(tk.IntVar())
+ self.level_breakables.append(tk.IntVar())
# END DATA VARIABLES
# statusbar variable
@@ -253,8 +264,6 @@ class App(tk.Frame):
self.spn_gun.grid(row=4,column=1)
self.lbl_pur = tk.Label(self.frm_curprof,text="Purchased: Weapons")
self.lbl_pur.grid(row=5,column=0)
- #self.lbl_pur_weap = tk.Label(self.frm_curprof,text="Weapons")
- #self.lbl_pur_weap.grid(row=5,column=0)
self.lbl_pur_weap = tk.Label(self.frm_curprof,text="Planes")
self.lbl_pur_weap.grid(row=5,column=1)
self.img_potato = get_srb_image("Potato Gun.png",16,16)
@@ -300,16 +309,12 @@ class App(tk.Frame):
self.lbl_levelsets = []
self.spn_levelsets = []
self.ent_levelsets_balloons = []
- self.lbl_levelsets_name = tk.Label(self.frm_levels,text="Billboard/Completed")
- self.lbl_levelsets_name.grid(row=0,column=0,sticky="EW",columnspan=4)
- self.lbl_levels_name = tk.Label(self.frm_levels,text="Level")
- self.lbl_levels_name.grid(row=0,column=5,sticky="EW")
- self.lbl_levels_status = tk.Label(self.frm_levels,text="Rank")
- self.lbl_levels_status.grid(row=0,column=6,sticky="EW",columnspan=2)
- self.lbl_levels_balloons = tk.Label(self.frm_levels,text="Balloons")
- self.lbl_levels_balloons.grid(row=0,column=8,columnspan=4,sticky="EW")
- self.lbl_levels_letters = tk.Label(self.frm_levels,text="Letters")
- self.lbl_levels_letters.grid(row=0,column=12,columnspan=4,sticky="EW")
+ tk.Label(self.frm_levels,text="Billboard/Completed").grid(row=0,column=0,sticky="EW",columnspan=4)
+ tk.Label(self.frm_levels,text="Level").grid(row=0,column=5,sticky="EW")
+ tk.Label(self.frm_levels,text="Rank").grid(row=0,column=6,sticky="EW",columnspan=2)
+ tk.Label(self.frm_levels,text="Balloons").grid(row=0,column=8,columnspan=4,sticky="EW")
+ tk.Label(self.frm_levels,text="Letters").grid(row=0,column=12,columnspan=4,sticky="EW")
+ tk.Label(self.frm_levels,text="Breakables").grid(row=0,column=16,columnspan=1,sticky="EW")
self.lbl_levels = []
self.opt_levels_hex = []
self.opt_levels = []
@@ -319,8 +324,17 @@ class App(tk.Frame):
self.btn_balloons_all = []
self.btn_letters_none = []
self.btn_letters_all = []
- x = 1
+ self.btn_levels_breakables = []
+ self.bim_levels_breakables = []
self.img_balloons = []
+ self.img_breakables = []
+ self.BREAKABLES = sorted(srb_lib.BREAKABLES,key=lambda i: i["w"])
+ self.BREAKABLES = [b for b in self.BREAKABLES if b["w"] != 0]
+ self.BREAKABLES_NAMES = [b["name"] for b in self.BREAKABLES if b["w"] != 0]
+ for i in self.BREAKABLES:
+ self.img_breakables.append(get_srb_image(os.path.join(image_dir,"breakables",i["name"]+".png"),16,16,photoImage=False))
+ self.img_breakables.append(get_srb_image(os.path.join(image_dir,"breakables","empty.png"),16,16,photoImage=False))
+ x = 1
for i in range(0,len(srb_lib.LEVELSETS)):
tl = srb_lib.get_levelset_info(i)[0]
if "c" not in tl or tl["c"] == "none":
@@ -371,7 +385,17 @@ class App(tk.Frame):
self.btn_letters_none[-1].grid(row=x,column=14)
self.btn_letters_all.append(tk.Button(self.frm_levels,text="all",padx=0,pady=0,command=lambda tl=j,action="all",ty="letters": self.button_action_level(tl,action,ty)))
self.btn_letters_all[-1].grid(row=x,column=15)
+ # breakables
+ if "r" in j and j["r"]:
+ self.bim_levels_breakables.append(get_srb_image(os.path.join("breakables","empty.png"),16,16))
+ # until you apply an image, width of a widget measures approximate width of text characters
+ self.btn_levels_breakables.append(tk.Button(self.frm_levels,padx=0,pady=0,width=2,compound="left",command=lambda tl=j: self.button_reset_level_breakables(tl)))
+ if IMAGES:
+ # and now all of a sudden it does pixels.
+ self.btn_levels_breakables[-1].config(width=88,image=self.bim_levels_breakables[-1])
+ self.btn_levels_breakables[-1].grid(row=x,column=16)
x += 1
+ # end for-j-in-levels
x += 1
# end for-i-in-levelsets
@@ -381,6 +405,22 @@ class App(tk.Frame):
# and now open the first file
self.func_open(self.current_file.get())
+ def get_single_image_from_breakables(self,b_list):
+ """ Given a list of breakable names, return a single image that has those items displayed. Fixed size of 80px x 16px. """
+ #print(f"debug: got list of {b_list}")
+ if IMAGES:
+ new_im = Image.new("RGBA",(16*5,16),(255,127,127,0))
+ x_offset = 0
+ for i in self.BREAKABLES_NAMES:
+ using = i in b_list
+ #print(f"For {i}, using {using}, index is {self.BREAKABLES_NAMES.index(i)}")
+ this_img = self.img_breakables[self.BREAKABLES_NAMES.index(i)] if i in b_list else self.img_breakables[-1]
+ new_im.paste(this_img, (x_offset,0))
+ x_offset += this_img.size[0]
+ return ImageTk.PhotoImage(new_im)
+ else:
+ return -1
+
def set_frame_backgrounds(self, arg1 = None, arg2 = None, arg3 = None):
""" Reacts to the frame colors checkbox and sets frames which make development and layout easier. """
if self.frame_backgrounds.get():
@@ -393,6 +433,18 @@ class App(tk.Frame):
self.frm_curprof.config(background=bg,borderwidth=0)
self.frm_levels.config(background=bg,borderwidth=0)
+ def button_reset_level_breakables(self, level_obj):
+ """ Handle button press to reset breakables for a level. """
+ profile_id = self.selected_profile.get()
+ _, b_mask = srb_lib.get_collected_breakables(self.bdata,profile_id,level_obj,silent=True)
+ amount = "all" if 0 == b_mask else "none"
+ bdata, message = srb_lib.set_collected_breakables(self.bdata,profile_id,level_obj,amount)
+ if -1 == bdata or message != "":
+ raise Exception("Unable to reset breakables for level {level_obj} because {message}")
+ else:
+ self.bdata = bdata
+ self.load_form_into_data()
+
def button_action_level(self, level_obj, action, type_):
""" Handle button press from "none" and "all" for balloons and letters for a level """
#print(f"debug (button_action_level): {level_obj}, {action}, {type_}")
@@ -623,6 +675,7 @@ class App(tk.Frame):
if not self.bdata:
return "No file loaded."
profile_id = self.selected_profile.get()
+ y = 0
if profile_id >= 1 and profile_id <= 3:
self.mark_traces(False)
# money
@@ -690,6 +743,7 @@ class App(tk.Frame):
self.levelset_status_ints[x].set(mission_mask)
self.levelset_balloons_ints[x].set(balloon_count)
x += 1
+ # end for-in-in-levelsets
# levels
for i in range(0,len(srb_lib.LEVELS)):
this_level = [j for j in srb_lib.LEVELS if j["id"] == i][0]
@@ -731,6 +785,23 @@ class App(tk.Frame):
# if level set_pos 0, then update the label for the whole levelset
if this_level["set_pos"] == 0:
self.lbl_levelsets[this_level["setid"]].config(state=state)
+ if this_level["r"]:
+ b_str, b_mask = srb_lib.get_collected_breakables(self.bdata,profile_id,this_level,silent=True)
+ if "all" == b_str:
+ b_str = ','.join([b["name"] for b in self.BREAKABLES])
+ b_list = b_str.split(",")
+ if "none" in b_list:
+ b_list.pop(b_list.index("none"))
+ #print(f"debug: for {this_level['name']}, i {i}, y {y}, got b {b_list}, mask {b_mask}")
+ self.bim_levels_breakables[y] = self.get_single_image_from_breakables(b_list)
+ if self.bim_levels_breakables[y] != -1: # which really means, if IMAGES
+ self.btn_levels_breakables[y].config(image=self.bim_levels_breakables[y])
+ self.btn_levels_breakables[y].config(text=str(len(b_list)))
+ # y counts number of levels with breakables
+ y = y + 1
+ # end of if-level-has-breakables
+
+ # end for-i-in-levels
# end if-profile_id is 1,2 or 3.
# mark-traces-enable must happen at the end!
self.mark_traces(True)
bgstack15