Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,16 @@ src/run.dist.zip
/src/run.dist
src/TOTKOptimizer.ini
TOTKOptimizer.ini
NX Optimizer.AppImage
NX Optimizer.AppImage
# build/runtime
.venv/
build/
dist/
Extracted Files/
.DS_Store
__pycache__/
*.pyc
*.pyo
.idea/
.vscode/
*.log
42 changes: 19 additions & 23 deletions src/modules/FrontEnd/AnimationMgr.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,38 @@
import threading
from time import sleep
from modules.logger import log
from collections import deque

_INTERVAL_MS = 400


class AnimationQueue:
isInit: bool = False
queue = deque()

__running: bool = True
__lock = threading.Lock()
_master = None

@classmethod
def Initialize(cls):

def Initialize(cls, master):
log.warning("Initialize AnimationQueue")

if cls.isInit:
raise ("Already Initialized.")

thread = threading.Thread(name="AnimationQueue", target=cls.UpdateQueue)
thread.daemon = True
thread.start()
cls._master = master
cls._schedule()
cls.isInit = True

@classmethod
def AddToQueue(cls, func):
with cls.__lock:
cls.queue.append(func)
cls.queue.append(func)

@classmethod
def UpdateQueue(cls):
while cls.__running:
with cls.__lock:
if len(cls.queue) > 0:
queue = cls.queue.copy()

for func in queue:
func()
def _schedule(cls):
cls._master.after(_INTERVAL_MS, cls._tick)

sleep(0.15)
@classmethod
def _tick(cls):
if not cls.queue:
cls._schedule()
return

for func in cls.queue:
func()

cls._schedule()
7 changes: 2 additions & 5 deletions src/modules/FrontEnd/CanvasMgr.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from modules.FrontEnd.ImageButton import *
from PIL import Image, ImageTk, ImageFilter, ImageOps
from PIL import Image as PILImage, ImageTk, ImageFilter, ImageOps
from idlelib.tooltip import Hovertip
from tkinter import *
from configuration.settings import *
Expand Down Expand Up @@ -257,13 +257,11 @@ def custom_command():

new_variable.trace_add("write", lambda *args: custom_command())


# create scale box
scale_box = ttk.Scale(
master=master,
from_=scale_from,
to=scale_to,
command=lambda e: custom_command(),
length=width,
style=style,
variable=new_variable,
Expand Down Expand Up @@ -708,7 +706,6 @@ def show_tooltip(
x += canvas.winfo_rootx()
y += canvas.winfo_rooty()

master.after(50)
cls.tooltip = Tk.Toplevel(master=master)
cls.tooltip.wm_overrideredirect(True)
cls.tooltip.geometry(f"+{x + scale(20)}+{y + scale(25)}")
Expand Down Expand Up @@ -785,7 +782,7 @@ def Photo_Image(
) -> PhotoImage:

UI_path = cls.get_UI_path(image_path)
image = ttk.Image.open(UI_path)
image = PILImage.open(UI_path)
if isinstance(img_scale, int) or isinstance(img_scale, float):
width = int(width * img_scale)
height = int(height * img_scale)
Expand Down
2 changes: 1 addition & 1 deletion src/modules/FrontEnd/FrontEnd.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def __init__(Manager, window):
Game_Manager.LoadPatches()
FileManager.Initialize(window, Manager)
TextureMgr.Initialize() # load all images.
AnimationQueue.Initialize()
AnimationQueue.Initialize(window)
Manager.patches = Game_Manager.GetPatches()

# Emulator Scaling
Expand Down
27 changes: 20 additions & 7 deletions src/modules/FrontEnd/ImageButton.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,27 @@ def AddAnimationToQueue(self):

def Animation(self):
try:
if self.__IsHovering is False:
if not self.__IsHovering:
return

if not self._Images:
return

if self.__AniIndex + 1 > len(self._Images):
self.__AniIndex = 1

self._Canvas.itemconfig(self.Tag, image=self._Images[self.__AniIndex])

self.__AniIndex += 1
if hasattr(self, "_last_drawn_index"):
if self.__AniIndex == self._last_drawn_index:
return

next_index = self.__AniIndex +1
if next_index > len(self._Images):
next_index = 0

self._Canvas.itemconfig(
self.Tag,
image=self._Images(self.__AniIndex)
)

self._last_drawn_index = self.__AniIndex
self.__AniIndex = next_index

except Exception:
pass
31 changes: 21 additions & 10 deletions src/modules/FrontEnd/TextureMgr.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from PIL import ImageTk
from PIL import Image as PILImage, ImageTk
from modules.FrontEnd.CanvasMgr import Canvas_Create


Expand Down Expand Up @@ -28,6 +28,22 @@ def Request(cls, Name: str):

raise f"Texture Doesn't exist {Name}"

@classmethod
def CreateCompositeTexture(cls, name, image_paths):
"""Precomposite multiple full-canvas RGBA images into one PhotoImage.
Reduces per-frame CoreGraphics RGBA compositing passes on macOS."""
from modules.scaling import sf
w, h = int(1200 * sf), int(600 * sf)
base = PILImage.new("RGBA", (w, h), (0, 0, 0, 0))
for path in image_paths:
full_path = Canvas_Create.get_UI_path(path)
img = PILImage.open(full_path).resize((w, h), PILImage.LANCZOS)
if img.mode != "RGBA":
img = img.convert("RGBA")
base = PILImage.alpha_composite(base, img)
photo = ImageTk.PhotoImage(base)
cls.AppendTexture(Texture(name, photo))

@classmethod
def CreateTexture(
cls,
Expand Down Expand Up @@ -191,10 +207,10 @@ def Initialize(cls):
width=int(72 * 1.2),
height=int(114 * 1.2),
)
TextureMgr.CreateTexture(
image_path="BG_Left_2.png",
width=1200,
height=600,
# ponytail: precomposite static overlays → 1 RGBA pass/frame instead of 2
TextureMgr.CreateCompositeTexture(
"ui_static_overlay",
["BG_Left_2.png", "BG_Right_UI.png"],
)
TextureMgr.CreateTexture(
image_path="BG_Left_Cheats.png",
Expand All @@ -206,11 +222,6 @@ def Initialize(cls):
width=1200,
height=600,
)
TextureMgr.CreateTexture(
image_path="BG_Right_UI.png",
width=1200,
height=600,
)
TextureMgr.CreateTexture(
image_path="browse.png",
width=int(115 * 0.8),
Expand Down
5 changes: 2 additions & 3 deletions src/modules/GameManager/FileManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

from run_config import __ROOT__


class FileManager:

_window: ttk.Window = None
Expand Down Expand Up @@ -221,7 +220,7 @@ def __TransferMods(filemgr):
os.makedirs(destination, exist_ok=True)
shutil.copytree(source, destination, dirs_exist_ok=True)
else:
destination = os.path.join(os.getcwd(), "Extracted Files", patchinfo.ModName)
destination = os.path.join(__ROOT__, "Extracted Files", patchinfo.ModName)
os.makedirs(destination, exist_ok=True)
shutil.copytree(source, destination, dirs_exist_ok=True)

Expand Down Expand Up @@ -346,7 +345,7 @@ def UltraCam_ConfigPath(filemgr) -> str:
SdCard = filemgr.sdmc

if filemgr.is_extracting is True:
Folder = os.path.join(os.getcwd(), "Extracted Files")
Folder = os.path.join(__ROOT__, "Extracted Files")
os.makedirs(Folder, exist_ok=True)
return os.path.join(Folder, PatchInfo.ModName, PatchInfo.ConfigPath)
if PatchInfo.isSDconfig is True:
Expand Down
11 changes: 1 addition & 10 deletions src/modules/load_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,7 @@ def load_UI_elements(manager, canvas: ttk.Canvas):
)

canvas.create_image(
0, 0, anchor="nw", image=TextureMgr.Request("BG_Left_2.png"), tags="overlay"
)

# Benchmark Window.
canvas.create_image(
0 - scale(20),
0,
anchor="nw",
image=TextureMgr.Request("BG_Right_UI.png"),
tags="overlay",
0, 0, anchor="nw", image=TextureMgr.Request("ui_static_overlay"), tags="overlay"
)

Offset = 255
Expand Down