crystalwindow 4.5__tar.gz → 4.6__tar.gz

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.
Files changed (48) hide show
  1. {crystalwindow-4.5/crystalwindow.egg-info → crystalwindow-4.6}/PKG-INFO +1 -1
  2. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/__init__.py +10 -4
  3. crystalwindow-4.6/crystalwindow/clock.py +189 -0
  4. {crystalwindow-4.5 → crystalwindow-4.6/crystalwindow.egg-info}/PKG-INFO +1 -1
  5. {crystalwindow-4.5 → crystalwindow-4.6}/setup.py +1 -1
  6. crystalwindow-4.5/crystalwindow/clock.py +0 -23
  7. {crystalwindow-4.5 → crystalwindow-4.6}/LICENSE +0 -0
  8. {crystalwindow-4.5 → crystalwindow-4.6}/MANIFEST.in +0 -0
  9. {crystalwindow-4.5 → crystalwindow-4.6}/README.md +0 -0
  10. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/FileHelper.py +0 -0
  11. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/Icons/default_icon.png +0 -0
  12. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/ai.py +0 -0
  13. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/animation.py +0 -0
  14. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/assets.py +0 -0
  15. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/camera.py +0 -0
  16. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/collision.py +0 -0
  17. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/color_handler.py +0 -0
  18. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/crystal3d.py +0 -0
  19. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/cw_client.py +0 -0
  20. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/docs/getting_started.md +0 -0
  21. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/docs/index.md +0 -0
  22. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/draw_helpers.py +0 -0
  23. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/draw_rects.py +0 -0
  24. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/draw_text_helper.py +0 -0
  25. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/draw_tool.py +0 -0
  26. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/fun_helpers.py +0 -0
  27. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gametests/3dsquare.py +0 -0
  28. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gametests/__init__.py +0 -0
  29. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gametests/__main__.py +0 -0
  30. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gametests/gravitytest.py +0 -0
  31. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gametests/guitesting.py +0 -0
  32. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gametests/sandbox.py +0 -0
  33. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gametests/squaremove.py +0 -0
  34. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gametests/windowtesting.py +0 -0
  35. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gravity.py +0 -0
  36. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gui.py +0 -0
  37. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/gui_ext.py +0 -0
  38. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/math.py +0 -0
  39. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/player.py +0 -0
  40. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/sprites.py +0 -0
  41. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/tilemap.py +0 -0
  42. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/ver_warner.py +0 -0
  43. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/websearch.py +0 -0
  44. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow/window.py +0 -0
  45. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow.egg-info/SOURCES.txt +0 -0
  46. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow.egg-info/dependency_links.txt +0 -0
  47. {crystalwindow-4.5 → crystalwindow-4.6}/crystalwindow.egg-info/top_level.txt +0 -0
  48. {crystalwindow-4.5 → crystalwindow-4.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crystalwindow
3
- Version: 4.5
3
+ Version: 4.6
4
4
  Summary: A Tkinter powered window + GUI toolkit made by Crystal (MEEEEEE)! Easier apps, smoother UI and all-in-one helpers!
5
5
  Home-page: https://pypi.org/project/crystalwindow/
6
6
  Author: CrystalBallyHereXD
@@ -32,8 +32,9 @@ from .collision import check_collision, resolve_collision
32
32
  from .gui import Button, Label, GUIManager, hex_to_rgb, Fade
33
33
  from .gui_ext import Toggle, Slider
34
34
 
35
- # === Time ===
36
- from .clock import Clock
35
+ # === Time System ===
36
+ # Includes upgraded Clock + all helper utilities
37
+ from .clock import Clock, Stopwatch, CountdownTimer, Scheduler
37
38
 
38
39
  # === Drawing Helpers ===
39
40
  from .draw_helpers import gradient_rect, CameraShake
@@ -81,14 +82,19 @@ __all__ = [
81
82
  # --- GUI Extensions ---
82
83
  "Toggle", "Slider",
83
84
 
84
- # --- Time ---
85
+ # --- Time System ---
86
+ # FULL time system is now exposed
85
87
  "Clock",
88
+ "Stopwatch",
89
+ "CountdownTimer",
90
+ "Scheduler",
86
91
 
87
92
  # --- Drawing ---
88
93
  "gradient_rect", "CameraShake", "DrawHelper", "DrawTextManager", "CrystalDraw",
89
94
 
90
95
  # --- Misc ---
91
- "random_name", "DebugOverlay", "Camera", "Colors", "Color", "random_palette", "lerp", "WebSearchResult", "WebSearch",
96
+ "random_name", "DebugOverlay", "Camera", "Colors", "Color",
97
+ "random_palette", "lerp", "WebSearchResult", "WebSearch",
92
98
 
93
99
  # --- 3D ---
94
100
  "CW3D",
@@ -0,0 +1,189 @@
1
+ import time
2
+ from datetime import datetime
3
+ from collections import deque
4
+
5
+
6
+ # ============================================================
7
+ # Stopwatch Helper
8
+ # ============================================================
9
+ class Stopwatch:
10
+ def __init__(self):
11
+ self.start_time = None
12
+ self.elapsed_time = 0.0
13
+ self.running = False
14
+
15
+ def start(self):
16
+ if not self.running:
17
+ self.start_time = time.perf_counter()
18
+ self.running = True
19
+
20
+ def stop(self):
21
+ if self.running:
22
+ self.elapsed_time += time.perf_counter() - self.start_time
23
+ self.running = False
24
+
25
+ def reset(self):
26
+ self.start_time = None
27
+ self.elapsed_time = 0.0
28
+ self.running = False
29
+
30
+ def elapsed(self):
31
+ if self.running:
32
+ return self.elapsed_time + (time.perf_counter() - self.start_time)
33
+ return self.elapsed_time
34
+
35
+
36
+ # ============================================================
37
+ # Countdown Timer Helper
38
+ # ============================================================
39
+ class CountdownTimer:
40
+ def __init__(self):
41
+ self.target_time = None
42
+
43
+ def start(self, seconds: float):
44
+ self.target_time = time.perf_counter() + seconds
45
+
46
+ def remaining(self):
47
+ if not self.target_time:
48
+ return 0
49
+ return max(0, self.target_time - time.perf_counter())
50
+
51
+ def done(self):
52
+ return self.remaining() == 0
53
+
54
+
55
+ # ============================================================
56
+ # Event Scheduler Helper
57
+ # ============================================================
58
+ class Scheduler:
59
+ def __init__(self):
60
+ self.events = [] # list of (interval, last_run, function)
61
+
62
+ def schedule(self, interval: float, func):
63
+ """Run function every `interval` seconds."""
64
+ self.events.append([interval, time.perf_counter(), func])
65
+
66
+ def run_pending(self):
67
+ now = time.perf_counter()
68
+ for event in self.events:
69
+ interval, last_run, func = event
70
+ if now - last_run >= interval:
71
+ func()
72
+ event[1] = now # update last_run
73
+
74
+
75
+ # ============================================================
76
+ # MAIN CLOCK
77
+ # ============================================================
78
+ class Clock:
79
+ def __init__(self, target_fps: int = 60, smooth_fps: int = 30):
80
+ self.last = time.perf_counter()
81
+ self.delta = 0.0
82
+
83
+ # FPS
84
+ self.target_fps = target_fps
85
+ self.min_frame_time = 1 / target_fps if target_fps else 0
86
+ self.frame_times = deque(maxlen=smooth_fps)
87
+
88
+ self.paused = False
89
+
90
+ # Utilities
91
+ self.stopwatch = Stopwatch()
92
+ self.timer = CountdownTimer()
93
+ self.scheduler = Scheduler()
94
+
95
+ # ----------------------------------------------------------
96
+ # TICK + FPS
97
+ # ----------------------------------------------------------
98
+ def tick(self, fps: int | None = None):
99
+ if fps:
100
+ self.target_fps = fps
101
+ self.min_frame_time = 1 / fps
102
+
103
+ now = time.perf_counter()
104
+ raw_delta = now - self.last
105
+ self.last = now
106
+
107
+ # Paused = no delta
108
+ if self.paused:
109
+ self.delta = 0.0
110
+ return 0.0
111
+
112
+ # FPS limiting
113
+ sleep_time = self.min_frame_time - raw_delta
114
+ if sleep_time > 0:
115
+ time.sleep(sleep_time)
116
+ now2 = time.perf_counter()
117
+ raw_delta = now2 - (self.last - raw_delta)
118
+
119
+ self.delta = raw_delta
120
+ self.frame_times.append(raw_delta)
121
+
122
+ # Scheduler update
123
+ self.scheduler.run_pending()
124
+
125
+ return self.delta
126
+
127
+ def get_fps(self):
128
+ if not self.frame_times:
129
+ return 0.0
130
+ avg = sum(self.frame_times) / len(self.frame_times)
131
+ return round(1 / avg, 2) if avg > 0 else 0
132
+
133
+ # ----------------------------------------------------------
134
+ # PAUSE / RESUME
135
+ # ----------------------------------------------------------
136
+ def pause(self):
137
+ self.paused = True
138
+
139
+ def resume(self):
140
+ self.paused = False
141
+ self.last = time.perf_counter()
142
+
143
+ # ----------------------------------------------------------
144
+ # TIME + DATE UTILITIES
145
+ # ----------------------------------------------------------
146
+ def time(self, milliseconds: bool = True, hour_12: bool = False):
147
+ now = datetime.now()
148
+
149
+ if hour_12:
150
+ fmt = "%I:%M:%S" + (" %p" if not milliseconds else ".%f %p")
151
+ else:
152
+ fmt = "%H:%M:%S" + (".%f" if milliseconds else "")
153
+
154
+ text = now.strftime(fmt)
155
+ if milliseconds:
156
+ # Trim microseconds to milliseconds
157
+ if hour_12:
158
+ # Example: "03:20:15.123000 PM" -> "03:20:15.123 PM"
159
+ parts = text.split(".")
160
+ ms = parts[1][:3] + parts[1][6:] # keep .mmm, remove "000 PM"
161
+ text = parts[0] + "." + parts[1][:3] + " " + now.strftime("%p")
162
+ else:
163
+ text = text[:-3] # remove last 3 microseconds digits
164
+
165
+ return text
166
+
167
+ def date(self, format: str = "%m/%d/%Y"):
168
+ return datetime.now().strftime(format)
169
+
170
+ def time_date(self, order: str = "time_first", **kwargs):
171
+ t = self.time(**kwargs)
172
+ d = self.date()
173
+ return f"{t} | {d}" if order == "time_first" else f"{d} | {t}"
174
+
175
+ # ----------------------------------------------------------
176
+ # CUSTOM FORMATTERS
177
+ # ----------------------------------------------------------
178
+ def format_time(self, fmt: str):
179
+ return datetime.now().strftime(fmt)
180
+
181
+ def format_date(self, fmt: str):
182
+ return datetime.now().strftime(fmt)
183
+
184
+ # ----------------------------------------------------------
185
+ # MONOTONIC TIMESTAMP
186
+ # ----------------------------------------------------------
187
+ def timestamp(self):
188
+ """High-precision monotonic timestamp."""
189
+ return time.perf_counter()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crystalwindow
3
- Version: 4.5
3
+ Version: 4.6
4
4
  Summary: A Tkinter powered window + GUI toolkit made by Crystal (MEEEEEE)! Easier apps, smoother UI and all-in-one helpers!
5
5
  Home-page: https://pypi.org/project/crystalwindow/
6
6
  Author: CrystalBallyHereXD
@@ -7,7 +7,7 @@ with open("README.md", encoding="utf-8") as f:
7
7
 
8
8
  setup(
9
9
  name="crystalwindow",
10
- version="4.5", # Force metadata refresh
10
+ version="4.6", # Force metadata refresh
11
11
  packages=find_packages(include=["crystalwindow", "crystalwindow.*"]),
12
12
 
13
13
  include_package_data=True, # include package_data files
@@ -1,23 +0,0 @@
1
- import time
2
-
3
- class Clock:
4
- def __init__(self):
5
- self.last = time.time()
6
- self.delta = 0
7
- self.fps = 60
8
-
9
- def tick(self, fps=None):
10
- now = time.time()
11
- self.delta = now - self.last
12
- self.last = now
13
-
14
- if fps:
15
- self.fps = fps
16
- sleep_for = (1 / fps) - self.delta
17
- if sleep_for > 0:
18
- time.sleep(sleep_for)
19
-
20
- return self.delta
21
-
22
- def get_fps(self):
23
- return round(1 / self.delta, 2) if self.delta else 0
File without changes
File without changes
File without changes
File without changes