crystalwindow 1.4.8__py3-none-any.whl → 2.7.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of crystalwindow might be problematic. Click here for more details.

@@ -1,3 +1,10 @@
1
+ """
2
+ CrystalWindow FileHelper
3
+ ------------------------
4
+ A utility class that handles saving/loading text, JSON, and pickle files,
5
+ with optional Tk file dialogs and a default 'saves' directory.
6
+ """
7
+
1
8
  import os
2
9
  import json
3
10
  import pickle
@@ -9,84 +16,127 @@ class FileHelper:
9
16
  """CrystalWindow integrated file helper with default folders & Tk dialogs."""
10
17
 
11
18
  def __init__(self, default_save_folder="saves"):
12
- # auto-make folder if not found
19
+ """
20
+ Initialize the FileHelper.
21
+
22
+ Args:
23
+ default_save_folder (str): Folder to save files in by default.
24
+ Created automatically if missing.
25
+ """
13
26
  self.default_save_folder = default_save_folder
14
27
  os.makedirs(self.default_save_folder, exist_ok=True)
15
28
 
16
- # ---- TK FILE DIALOGS ----
29
+ # -------------------------------------------------------------------------
30
+ # TK FILE DIALOGS
31
+ # -------------------------------------------------------------------------
17
32
  def ask_save_file(self, default_name="save.json",
18
33
  filetypes=[("JSON files", "*.json"), ("All files", "*.*")]):
19
- """Open a Tkinter Save dialog inside default folder."""
34
+ """Open a Tkinter Save dialog starting in the default folder."""
20
35
  root = tk.Tk()
21
36
  root.withdraw()
22
37
  path = filedialog.asksaveasfilename(
38
+ title="Save As",
23
39
  initialdir=self.default_save_folder,
24
40
  initialfile=default_name,
25
41
  filetypes=filetypes,
26
42
  defaultextension=filetypes[0][1]
27
43
  )
28
44
  root.destroy()
29
- return path
45
+ return path if path else None # Return None if cancelled
30
46
 
31
47
  def ask_open_file(self,
32
48
  filetypes=[("JSON files", "*.json"), ("All files", "*.*")]):
33
- """Open a Tkinter Open dialog inside default folder."""
49
+ """Open a Tkinter Open dialog starting in the default folder."""
34
50
  root = tk.Tk()
35
51
  root.withdraw()
36
52
  path = filedialog.askopenfilename(
53
+ title="Open File",
37
54
  initialdir=self.default_save_folder,
38
55
  filetypes=filetypes
39
56
  )
40
57
  root.destroy()
41
- return path
58
+ return path if path else None
59
+
60
+ # -------------------------------------------------------------------------
61
+ # INTERNAL PATH HELPER
62
+ # -------------------------------------------------------------------------
63
+ def _resolve_path(self, filename):
64
+ """Return a full path, resolving relative paths to the default folder."""
65
+ if not filename:
66
+ return None
67
+ if os.path.isabs(filename):
68
+ return filename
69
+ return os.path.join(self.default_save_folder, filename)
42
70
 
43
- # ---- TEXT ----
71
+ # -------------------------------------------------------------------------
72
+ # TEXT FILES
73
+ # -------------------------------------------------------------------------
44
74
  def save_text(self, filename, content):
45
- """Save plain text data to file."""
46
- path = os.path.join(self.default_save_folder, filename)
75
+ """Save plain text data to a file."""
76
+ path = self._resolve_path(filename)
77
+ if not path:
78
+ print("[CANCELLED] No save path provided.")
79
+ return None
80
+ os.makedirs(os.path.dirname(path), exist_ok=True)
47
81
  with open(path, "w", encoding="utf-8") as f:
48
82
  f.write(content)
83
+ print(f"[INFO] Text saved to: {path}")
49
84
  return path
50
85
 
51
86
  def load_text(self, filename):
52
- """Load plain text data from file."""
53
- path = os.path.join(self.default_save_folder, filename)
54
- if os.path.exists(path):
87
+ """Load plain text data from a file."""
88
+ path = self._resolve_path(filename)
89
+ if path and os.path.exists(path):
55
90
  with open(path, "r", encoding="utf-8") as f:
56
91
  return f.read()
57
- print(f"[WARN] Text file not found: {filename}")
92
+ print(f"[WARN] Text file not found: {path}")
58
93
  return None
59
94
 
60
- # ---- JSON ----
95
+ # -------------------------------------------------------------------------
96
+ # JSON FILES
97
+ # -------------------------------------------------------------------------
61
98
  def save_json(self, filename, data):
62
- """Save JSON serializable data."""
63
- path = os.path.join(self.default_save_folder, filename)
99
+ """Save JSON-serializable data."""
100
+ path = self._resolve_path(filename)
101
+ if not path:
102
+ print("[CANCELLED] No save path provided.")
103
+ return None
104
+ os.makedirs(os.path.dirname(path), exist_ok=True)
64
105
  with open(path, "w", encoding="utf-8") as f:
65
106
  json.dump(data, f, indent=4)
107
+ print(f"[INFO] JSON saved to: {path}")
66
108
  return path
67
109
 
68
110
  def load_json(self, filename):
69
- """Load JSON file."""
70
- path = os.path.join(self.default_save_folder, filename)
71
- if os.path.exists(path):
111
+ """Load JSON data."""
112
+ path = self._resolve_path(filename)
113
+ if path and os.path.exists(path):
72
114
  with open(path, "r", encoding="utf-8") as f:
73
115
  return json.load(f)
74
- print(f"[WARN] JSON file not found: {filename}")
116
+ print(f"[WARN] JSON file not found: {path}")
75
117
  return None
76
118
 
77
- # ---- PICKLE ----
119
+ # -------------------------------------------------------------------------
120
+ # PICKLE FILES
121
+ # -------------------------------------------------------------------------
78
122
  def save_pickle(self, filename, obj):
79
- """Save object using pickle (binary)."""
80
- path = os.path.join(self.default_save_folder, filename)
123
+ """Save a Python object using pickle."""
124
+ path = self._resolve_path(filename)
125
+ if not path:
126
+ print("[CANCELLED] No save path provided.")
127
+ return None
128
+ os.makedirs(os.path.dirname(path), exist_ok=True)
81
129
  with open(path, "wb") as f:
82
130
  pickle.dump(obj, f)
131
+ print(f"[INFO] Pickle saved to: {path}")
83
132
  return path
84
133
 
85
134
  def load_pickle(self, filename):
86
- """Load pickle file (binary)."""
87
- path = os.path.join(self.default_save_folder, filename)
88
- if os.path.exists(path):
135
+ """Load a pickled Python object."""
136
+ path = self._resolve_path(filename)
137
+ if path and os.path.exists(path):
89
138
  with open(path, "rb") as f:
90
139
  return pickle.load(f)
91
- print(f"[WARN] Pickle file not found: {filename}")
140
+ print(f"[WARN] Pickle file not found: {path}")
92
141
  return None
142
+
Binary file
crystalwindow/__init__.py CHANGED
@@ -1,47 +1,57 @@
1
1
  # crystalwindow/__init__.py
2
- # 🪞 CrystalWindow - Master import hub
2
+ # 💎 CrystalWindow - Master Import Hub
3
+ from .ver_warner import check_for_update
4
+ check_for_update("crystalwindow")
3
5
 
4
- # --- Core systems ---
6
+ # === Core Systems ===
5
7
  from .window import Window
6
8
  from .sprites import Sprite
7
9
  from .tilemap import TileMap
8
10
  from .player import Player
9
11
  from .gravity import Gravity
10
12
  from .FileHelper import FileHelper
13
+ from .math import Mathematics
11
14
 
12
- # --- Assets & Animations ---
15
+ # === Assets & Animation ===
13
16
  from .assets import load_image, load_folder_images, load_music, play_music
14
17
  from .animation import Animation
15
18
 
16
- # --- Collision ---
19
+ # === Collision ===
17
20
  from .collision import check_collision, resolve_collision
18
21
 
19
- # --- GUI & Extensions ---
22
+ # === GUI & Extensions ===
20
23
  from .gui import Button, Label, GUIManager, random_color, hex_to_rgb
21
24
  from .gui_ext import Toggle, Slider
22
25
 
23
- # --- Drawing Helpers ---
26
+ # === Drawing Helpers ===
24
27
  from .draw_helpers import gradient_rect, CameraShake
25
28
  from .draw_rects import DrawHelper
26
29
  from .draw_text_helper import DrawTextManager
30
+ from .draw_tool import CrystalDraw
27
31
 
28
- # --- Misc Helpers ---
32
+ # === Misc Helpers ===
29
33
  from .fun_helpers import random_name, DebugOverlay
30
34
 
31
35
 
32
36
  __all__ = [
33
- # Core
34
- "Window", "Sprite", "TileMap", "Player", "Gravity", "FileHelper",
35
- # Assets & Animation
37
+ # --- Core ---
38
+ "Window", "Sprite", "TileMap", "Player", "Gravity", "FileHelper", "Mathematics",
39
+
40
+ # --- Assets & Animation ---
36
41
  "load_image", "load_folder_images", "load_music", "play_music", "Animation",
37
- # Collision
42
+
43
+ # --- Collision ---
38
44
  "check_collision", "resolve_collision",
39
- # GUI
45
+
46
+ # --- GUI ---
40
47
  "Button", "Label", "GUIManager", "random_color", "hex_to_rgb",
41
- # GUI Ext
48
+
49
+ # --- GUI Extensions ---
42
50
  "Toggle", "Slider",
43
- # Drawing
44
- "gradient_rect", "CameraShake", "DrawHelper", "DrawTextManager",
45
- # Misc
46
- "random_name", "DebugOverlay"
51
+
52
+ # --- Drawing ---
53
+ "gradient_rect", "CameraShake", "DrawHelper", "DrawTextManager", "CrystalDraw",
54
+
55
+ # --- Misc ---
56
+ "random_name", "DebugOverlay",
47
57
  ]
crystalwindow/assets.py CHANGED
@@ -1,33 +1,30 @@
1
- import pygame
2
1
  import os
2
+ from tkinter import PhotoImage
3
3
 
4
4
  ASSETS = {}
5
5
 
6
6
  def load_image(path, size=None):
7
7
  if not os.path.exists(path):
8
8
  raise FileNotFoundError(f"Image not found: {path}")
9
- img = pygame.image.load(path).convert_alpha()
10
- if size:
11
- img = pygame.transform.scale(img, size)
9
+ img = PhotoImage(file=path)
12
10
  ASSETS[path] = img
13
11
  return img
14
12
 
15
- def load_folder_images(folder, size=None, nested=True):
13
+ def load_folder_images(folder, nested=True):
16
14
  result = {}
17
15
  for item in os.listdir(folder):
18
16
  full_path = os.path.join(folder, item)
19
17
  if os.path.isdir(full_path) and nested:
20
- result[item] = load_folder_images(full_path, size=size, nested=True)
21
- elif item.lower().endswith((".png", ".jpg", ".jpeg")):
22
- result[item] = load_image(full_path, size=size)
18
+ result[item] = load_folder_images(full_path, nested=True)
19
+ elif item.lower().endswith((".png", ".gif")): # Tk supports PNG/GIF
20
+ result[item] = load_image(full_path)
23
21
  return result
24
22
 
25
23
  def load_music(path):
26
- if not os.path.exists(path):
27
- raise FileNotFoundError(f"Music not found: {path}")
28
- pygame.mixer.music.load(path)
29
- ASSETS[path] = path
30
- return path
24
+ """No-op: Tkinter does not handle music. Placeholder for compatibility."""
25
+ print(f"[assets] Music loading not supported in this current crystalwindow ver sorry! ~Crystal: {path}")
26
+ return None
31
27
 
32
28
  def play_music(loop=-1):
33
- pygame.mixer.music.play(loop)
29
+ """No-op: placeholder."""
30
+ print("[assets] Music playback not supported in this current crystalwindow ver sorry! ~Crystal")
@@ -1,51 +1,36 @@
1
- import pygame as py
2
1
  from crystalwindow import *
3
2
 
4
3
  class DrawHelper:
5
- def __init__(self):
6
- pass
7
-
8
4
  def rect(self, win, x, y, w, h, color):
9
- py.draw.rect(win.screen, color, (x, y, w, h))
5
+ win.draw_rect(color, (x, y, w, h))
10
6
  return self
11
7
 
12
8
  def square(self, win, x, y, size, color):
13
- py.draw.rect(win.screen, color, (x, y, size, size))
9
+ win.draw_rect(color, (x, y, size, size))
14
10
  return self
15
11
 
16
12
  def circle(self, win, x, y, radius, color):
17
- py.draw.circle(win.screen, color, (x, y), radius)
13
+ win.draw_circle(color, (x, y), radius)
18
14
  return self
19
15
 
20
16
  def triangle(self, win, points, color):
21
- py.draw.polygon(win.screen, color, points)
22
- return self
23
-
24
- def texture(self, win, x, y, w, h, image):
25
- if image:
26
- img = py.transform.scale(image, (w, h))
27
- win.screen.blit(img, (x, y))
17
+ flat_points = [coord for pt in points for coord in pt]
18
+ win.canvas.create_polygon(flat_points, fill=win._to_hex(color))
28
19
  return self
29
20
 
30
21
  def text(self, win, text, font="Arial", size=16, x=0, y=0, color=(255,255,255), bold=False, cursive=False):
31
- fnt = py.font.SysFont(font, size, bold=bold, italic=cursive)
32
- surf = fnt.render(text, True, color)
33
- win.screen.blit(surf, (x, y))
22
+ win.draw_text(text, font=font, size=size, pos=(x, y), color=color, bold=bold, italic=cursive)
34
23
  return self
35
24
 
36
25
  def gradient_rect(self, win, x, y, w, h, start_color, end_color, vertical=True):
37
- if vertical:
38
- for i in range(h):
39
- ratio = i / h
40
- r = int(start_color[0]*(1-ratio) + end_color[0]*ratio)
41
- g = int(start_color[1]*(1-ratio) + end_color[1]*ratio)
42
- b = int(start_color[2]*(1-ratio) + end_color[2]*ratio)
43
- py.draw.line(win.screen, (r, g, b), (x, y+i), (x+w, y+i))
44
- else:
45
- for i in range(w):
46
- ratio = i / w
47
- r = int(start_color[0]*(1-ratio) + end_color[0]*ratio)
48
- g = int(start_color[1]*(1-ratio) + end_color[1]*ratio)
49
- b = int(start_color[2]*(1-ratio) + end_color[2]*ratio)
50
- py.draw.line(win.screen, (r, g, b), (x+i, y), (x+i, y+h))
26
+ for i in range(h if vertical else w):
27
+ ratio = i / (h if vertical else w)
28
+ r = int(start_color[0]*(1-ratio) + end_color[0]*ratio)
29
+ g = int(start_color[1]*(1-ratio) + end_color[1]*ratio)
30
+ b = int(start_color[2]*(1-ratio) + end_color[2]*ratio)
31
+ color = f"#{r:02x}{g:02x}{b:02x}"
32
+ if vertical:
33
+ win.canvas.create_line(x, y+i, x+w, y+i, fill=color)
34
+ else:
35
+ win.canvas.create_line(x+i, y, x+i, y+h, fill=color)
51
36
  return self
@@ -1,3 +1,4 @@
1
+ #draw_text_helper.py
1
2
  from .window import Window
2
3
 
3
4
  class DrawTextManager:
@@ -0,0 +1,49 @@
1
+ from .gui import hex_to_rgb
2
+
3
+ class CrystalDraw:
4
+ def __init__(self, win, brush_color="#00aaff", brush_size=8, canvas_rect=None):
5
+ """
6
+ win: CrystalWindow instance
7
+ brush_color: color string or tuple
8
+ brush_size: int
9
+ canvas_rect: (x, y, w, h) optional drawing area
10
+ """
11
+ self.win = win
12
+ self.brush_color = hex_to_rgb(brush_color)
13
+ self.brush_size = brush_size
14
+ self.drawing = False
15
+ self.last_pos = None
16
+ self.canvas_rect = canvas_rect or (0, 0, win.width, win.height)
17
+
18
+ def set_color(self, color):
19
+ if isinstance(color, str):
20
+ self.brush_color = hex_to_rgb(color)
21
+ else:
22
+ self.brush_color = color
23
+
24
+ def set_brush_size(self, size):
25
+ self.brush_size = max(1, int(size))
26
+
27
+ def clear(self):
28
+ self.win.fill((255,255,255))
29
+
30
+ def update(self):
31
+ """Draw if mouse pressed."""
32
+ x, y, w, h = self.canvas_rect
33
+ mx, my = self.win.mouse_pos
34
+ in_bounds = x <= mx <= x+w and y <= my <= y+h
35
+
36
+ if self.win.mouse_pressed(1) and in_bounds:
37
+ if self.last_pos:
38
+ self.win.canvas.create_line(
39
+ self.last_pos[0], self.last_pos[1], mx, my,
40
+ fill=self._to_hex(self.brush_color),
41
+ width=self.brush_size,
42
+ capstyle="round", smooth=True
43
+ )
44
+ self.last_pos = (mx, my)
45
+ else:
46
+ self.last_pos = None
47
+
48
+ def _to_hex(self, color):
49
+ return f"#{color[0]:02x}{color[1]:02x}{color[2]:02x}"
@@ -0,0 +1,14 @@
1
+ """
2
+ CrystalWindow Example Demos
3
+ ---------------------------
4
+ Run demos like this:
5
+
6
+ python -m CrystalWindow.examples.<demo_name>
7
+
8
+ Available demos:
9
+ guitesting → GUI widgets & layout demo
10
+ gravitytest → Physics & gravity simulation
11
+ windowtesting → Basic window + drawing
12
+ sandbox → Open testbed for experiments
13
+ """
14
+ __all__ = ["guitesting", "gravitytest", "windowtesting", "sandbox"]
@@ -0,0 +1,23 @@
1
+ # crystalWindow/examples/__main__.py
2
+ import importlib
3
+
4
+ DEMO_SCRIPTS = {
5
+ "guitesting": "GUI widgets & layout demo",
6
+ "gravitytest": "Gravity + physics test",
7
+ "windowtesting": "Basic window and draw test",
8
+ "sandbox": "Free experiment playground",
9
+ }
10
+
11
+ def list_demos():
12
+ print("CrystalWindow Example Demos 🧊")
13
+ print("--------------------------------")
14
+ for name, desc in DEMO_SCRIPTS.items():
15
+ print(f"{name:<15} - {desc}")
16
+ print("\nRun one with:")
17
+ print(" python -m cystalWindow.examples.<demo_name>\n")
18
+
19
+ def main():
20
+ list_demos()
21
+
22
+ if __name__ == "__main__":
23
+ main()
@@ -0,0 +1,47 @@
1
+ from crystalwindow import *
2
+
3
+ # --- custom player/ball class ---
4
+ class PlayerRect:
5
+ def __init__(self, x, y, w=32, h=32, color=(255,0,0)):
6
+ self.x = x
7
+ self.y = y
8
+ self.width = w
9
+ self.height = h
10
+ self.color = color
11
+ self.vel_y = 0
12
+
13
+ # draw either sprite or rect
14
+ def draw(self, win):
15
+ win.draw_rect(self.color, (self.x, self.y, self.width, self.height))
16
+
17
+ # --- setup window ---
18
+ win = Window(800, 600, "Gravity Sprite/Rect Test")
19
+
20
+ # --- player as colored rect ---
21
+ player = PlayerRect(100, 100, 50, 50, color=(0,255,0))
22
+
23
+ # --- platform as rect ---
24
+ class Platform:
25
+ def __init__(self, x, y, w, h, color=(100,200,100)):
26
+ self.x = x
27
+ self.y = y
28
+ self.width = w
29
+ self.height = h
30
+ self.color = color
31
+ def draw(self, win):
32
+ win.draw_rect(self.color, (self.x, self.y, self.width, self.height))
33
+
34
+ platform = Platform(0, 500, 800, 50)
35
+
36
+ # --- attach gravity ---
37
+ player.gravity = Gravity(player, force=1, bouncy=True, bounce_strength=0.7)
38
+
39
+ # --- main loop ---
40
+ def update(win):
41
+ player.gravity.update(1/60, [platform])
42
+ win.screen.fill((20,20,50))
43
+ player.draw(win)
44
+ platform.draw(win)
45
+
46
+ win.run(update)
47
+ win.quit()
@@ -0,0 +1,56 @@
1
+ from crystalwindow import *
2
+
3
+ # --- Window setup ---
4
+ win = Window(800, 600, "CrystalWindowLib Mega Sandbox")
5
+
6
+ # --- GUI ---
7
+ gui = GUIManager()
8
+ toggle1 = Toggle((50, 50, 100, 40), value=False)
9
+ slider1 = Slider((50, 120, 200, 30), min_val=0, max_val=100, value=50)
10
+
11
+ btn1 = Button(rect=(50, 200, 150, 50), text="Click Me!", color=random_color(),
12
+ hover_color=random_color(), callback=lambda: print("Button clicked!"))
13
+ lbl1 = Label((250, 50), "Hello GUI!", color=random_color(), size=24)
14
+
15
+ gui.add(toggle1)
16
+ gui.add(slider1)
17
+ gui.add(btn1)
18
+ gui.add(lbl1)
19
+
20
+ # --- Debug Overlay ---
21
+ debug = DebugOverlay()
22
+
23
+ # --- Camera Shake ---
24
+ shake = CameraShake(intensity=20)
25
+
26
+ # --- Main loop ---
27
+ def update(win):
28
+ gui.update(win)
29
+ gui.draw(win)
30
+
31
+ # --- draw text examples ---
32
+ win.draw_text("Normal Text", pos=(400, 50), size=18, color=random_color())
33
+ win.draw_text("Bold Text", pos=(400, 80), size=20, color=random_color(), bold=True)
34
+ win.draw_text("Italic Text", pos=(400, 110), size=20, color=random_color(), italic=True)
35
+ win.draw_text("Bold + Italic", pos=(400, 140), size=22, color=random_color(), bold=True, italic=True)
36
+
37
+ # --- draw toggle/slider values ---
38
+ win.draw_text(f"Toggle: {toggle1.value}", pos=(50, 90), size=18)
39
+ win.draw_text(f"Slider: {int(slider1.value)}", pos=(50, 160), size=18)
40
+
41
+ # --- draw gradient ---
42
+ gradient_rect(win, (50, 300, 200, 100), (255,0,0), (0,0,255))
43
+
44
+ # --- screen shake example (move a rectangle with shake) ---
45
+ shake.update()
46
+ x_off, y_off = shake.offset
47
+ win.draw_rect((0,255,0), (500+x_off, 300+y_off, 100, 50))
48
+
49
+ # --- draw random name + color ---
50
+ win.draw_text(f"Random Name: {random_name()}", pos=(50, 420), size=20, color=random_color())
51
+
52
+ # --- debug overlay ---
53
+ debug.draw(win, fps=int(win.clock.get_fps()))
54
+
55
+ win.run(update)
56
+ win.quit()
@@ -0,0 +1,49 @@
1
+ from crystalwindow import *
2
+
3
+ # --- setup window ---
4
+ win = Window(800, 600, "CrystalWindow Sandbox")
5
+
6
+ # --- setup debug overlay ---
7
+ debug = DebugOverlay()
8
+ draw = DrawHelper()
9
+ draw.rect(win, 100, 100, 50, 60, (255,0,0)).circle(win, 300, 200, 40, (0,255,0))
10
+
11
+
12
+ # --- player setup ---
13
+ player = Player((100, 400), speed=220)
14
+
15
+
16
+ # --- gravity system ---
17
+ gravity = Gravity(player, force=1.5)
18
+
19
+ # --- GUI setup ---
20
+
21
+ lbl = Label((20, 70), "CrystalWindow Sandbox Ready 🧠")
22
+
23
+ gui = GUIManager()
24
+ gui.add(lbl)
25
+
26
+ # --- rect testing helper ---
27
+ draw = DrawHelper()
28
+ draw.add_rect((300, 500, 200, 50), (50, 200, 255))
29
+
30
+ # --- text system ---
31
+ text_draw = DrawTextManager()
32
+ text_draw.write("Hello Crystal Sandbox!", (250, 50), (255, 255, 255))
33
+
34
+ # --- main loop ---
35
+ running = True
36
+ while running:
37
+ player.update()
38
+ gravity.apply()
39
+ win.fill((20, 20, 30))
40
+
41
+ draw.render()
42
+ player.draw(win)
43
+ gui.draw(win)
44
+ text_draw.render()
45
+
46
+ win.flip()
47
+
48
+ win.run()
49
+ win.quit()
@@ -0,0 +1,5 @@
1
+ from crystalwindow import Window
2
+
3
+ win = Window(800, 600, "Crystal Demo")
4
+ win.run()
5
+ win.quit()
crystalwindow/gui.py CHANGED
@@ -1,4 +1,4 @@
1
- import pygame
1
+ #gui.py
2
2
  import random
3
3
 
4
4
  # ----------------- Color Helpers -----------------
@@ -18,20 +18,25 @@ def lerp_color(c1, c2, t):
18
18
  # ----------------- GUI Elements -----------------
19
19
  class Button:
20
20
  def __init__(self, rect, text, color=(200,200,200), hover_color=(255,255,255), callback=None):
21
- self.rect = pygame.Rect(rect)
21
+ self.rect = rect # (x, y, w, h)
22
22
  self.text = text
23
23
  self.color = color
24
24
  self.hover_color = hover_color
25
25
  self.callback = callback
26
+ self.hovered = False
26
27
 
27
28
  def draw(self, win):
28
- mouse_pos = win.mouse_pos
29
- cur_color = self.hover_color if self.rect.collidepoint(mouse_pos) else self.color
29
+ x, y, w, h = self.rect
30
+ mx, my = win.mouse_pos
31
+ self.hovered = x <= mx <= x+w and y <= my <= y+h
32
+ cur_color = self.hover_color if self.hovered else self.color
30
33
  win.draw_rect(cur_color, self.rect)
31
- win.draw_text(self.text, pos=(self.rect.x+5, self.rect.y+5))
34
+ win.draw_text(self.text, pos=(x+5, y+5))
32
35
 
33
36
  def check_click(self, win):
34
- if self.rect.collidepoint(win.mouse_pos) and win.is_mouse_pressed(1):
37
+ mx, my = win.mouse_pos
38
+ x, y, w, h = self.rect
39
+ if x <= mx <= x+w and y <= my <= y+h and win.mouse_pressed(1):
35
40
  if self.callback:
36
41
  self.callback()
37
42