crystalwindow 3.8.3__py3-none-any.whl → 3.8.5__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.
crystalwindow/__init__.py CHANGED
@@ -20,6 +20,8 @@ from .assets import (
20
20
  flip_image,
21
21
  flip_horizontal,
22
22
  flip_vertical,
23
+ LoopAnim,
24
+ loop_image,
23
25
  )
24
26
  from .animation import Animation
25
27
 
@@ -42,6 +44,7 @@ from .draw_tool import CrystalDraw
42
44
  # === Misc Helpers ===
43
45
  from .fun_helpers import random_name, DebugOverlay
44
46
  from .camera import Camera
47
+ from .color_handler import Colors, Color
45
48
 
46
49
  # === 3D Engine ===
47
50
  from .crystal3d import CW3D
@@ -60,6 +63,8 @@ __all__ = [
60
63
  "flip_horizontal",
61
64
  "flip_vertical",
62
65
  "Animation",
66
+ "LoopAnim",
67
+ "loop_image",
63
68
 
64
69
  # --- Collision ---
65
70
  "check_collision", "resolve_collision",
@@ -77,7 +82,7 @@ __all__ = [
77
82
  "gradient_rect", "CameraShake", "DrawHelper", "DrawTextManager", "CrystalDraw",
78
83
 
79
84
  # --- Misc ---
80
- "random_name", "DebugOverlay", "Camera",
85
+ "random_name", "DebugOverlay", "Camera", "Colors", "Color",
81
86
 
82
87
  # --- 3D ---
83
88
  "CW3D",
crystalwindow/assets.py CHANGED
@@ -118,6 +118,47 @@ def flip_horizontal(img):
118
118
  def flip_vertical(img):
119
119
  return flip_image(img, flip_v=True)
120
120
 
121
+ # --------------------------------------------------------
122
+ # LOOPING ANIMAITONS/IMAGES
123
+ # --------------------------------------------------------
124
+ class LoopAnim:
125
+ def __init__(self, frames, speed=0.2):
126
+ self.frames = frames
127
+ self.i = 0
128
+ self.speed = speed
129
+
130
+ def next(self):
131
+ """Return next frame automatically looping."""
132
+ if not self.frames:
133
+ return None
134
+
135
+ self.i += self.speed
136
+ if self.i >= len(self.frames):
137
+ self.i = 0
138
+
139
+ return self.frames[int(self.i)]
140
+
141
+
142
+ def loop_image(*imgs, speed=0.2):
143
+ """
144
+ Usage:
145
+ anim = loop_image(img1, img2, img3)
146
+ anim = loop_image(load_image("p1.png"), load_image("p2.png"))
147
+
148
+ Returns a LoopAnim object.
149
+ """
150
+ frames = [x for x in imgs if x is not None]
151
+
152
+ # If nothing was passed → fallback
153
+ if not frames:
154
+ print("⚠️ loop_image() got no frames.")
155
+ fb = load_image("fallback.png") if os.path.exists("fallback.png") else None
156
+ if fb is None:
157
+ return LoopAnim([None], speed=speed)
158
+ return LoopAnim([fb], speed=speed)
159
+
160
+ return LoopAnim(frames, speed=speed)
161
+
121
162
 
122
163
  # --------------------------------------------------------
123
164
  # FOLDER LOADING
@@ -0,0 +1,123 @@
1
+ # --------------------------------------
2
+ # CrystalWindow Color System v2.0
3
+ # --------------------------------------
4
+
5
+ class Colors:
6
+ # BASIC COLORS
7
+ Black = (0, 0, 0)
8
+ White = (255, 255, 255)
9
+ Red = (255, 0, 0)
10
+ Green = (0, 255, 0)
11
+ Blue = (0, 0, 255)
12
+ Yellow = (255, 255, 0)
13
+ Cyan = (0, 255, 255)
14
+ Magenta = (255, 0, 255)
15
+ Gray = (120, 120, 120)
16
+ DarkGray = (40, 40, 40)
17
+
18
+ # CRYSTALWINDOW CUSTOM
19
+ CrystalBlue = (87, 199, 255)
20
+ Accent = (87, 199, 255)
21
+ Success = (76, 255, 111)
22
+ Error = (255, 68, 68)
23
+ Transparent = (0, 0, 0, 0) # full alpha
24
+
25
+
26
+ class Color:
27
+ COLOR_NAMES = {name.lower(): value for name, value in Colors.__dict__.items()
28
+ if not name.startswith("__")}
29
+
30
+ def __init__(self, r=None, g=None, b=None, a=255, hex_value=None):
31
+ # -------------------------------------------------
32
+ # 1) raw tuple variable: Color(Blue)
33
+ # -------------------------------------------------
34
+ if isinstance(r, (tuple, list)):
35
+ if len(r) == 3: # rgb
36
+ self.r, self.g, self.b = r
37
+ self.a = a
38
+ elif len(r) == 4: # rgba
39
+ self.r, self.g, self.b, self.a = r
40
+ return
41
+
42
+ # -------------------------------------------------
43
+ # 2) name string: Color("blue")
44
+ # -------------------------------------------------
45
+ if isinstance(r, str):
46
+ name = r.lower()
47
+ if name not in self.COLOR_NAMES:
48
+ raise ValueError(f"unknown color name: {r}")
49
+ data = self.COLOR_NAMES[name]
50
+ if len(data) == 4:
51
+ self.r, self.g, self.b, self.a = data
52
+ else:
53
+ self.r, self.g, self.b = data
54
+ self.a = a
55
+ return
56
+
57
+ # -------------------------------------------------
58
+ # 3) HEX input
59
+ # -------------------------------------------------
60
+ if hex_value is not None:
61
+ self.r, self.g, self.b, self.a = self.hex_to_rgba(hex_value)
62
+ return
63
+
64
+ # -------------------------------------------------
65
+ # 4) manual RGB
66
+ # -------------------------------------------------
67
+ self.r = r or 0
68
+ self.g = g or 0
69
+ self.b = b or 0
70
+ self.a = a
71
+
72
+ # convert hex -> rgba
73
+ @staticmethod
74
+ def hex_to_rgba(hex_value: str):
75
+ hex_value = hex_value.replace("#", "")
76
+ if len(hex_value) == 6:
77
+ r = int(hex_value[0:2], 16)
78
+ g = int(hex_value[2:4], 16)
79
+ b = int(hex_value[4:6], 16)
80
+ a = 255
81
+ elif len(hex_value) == 8:
82
+ r = int(hex_value[0:2], 16)
83
+ g = int(hex_value[2:4], 16)
84
+ b = int(hex_value[4:6], 16)
85
+ a = int(hex_value[6:8], 16)
86
+ else:
87
+ raise ValueError("bad hex bruh")
88
+ return r, g, b, a
89
+
90
+ # return pygame-friendly color tuple
91
+ def to_tuple(self):
92
+ return (self.r, self.g, self.b, self.a)
93
+
94
+ # rgba -> hex
95
+ def to_hex(self):
96
+ return "#{:02X}{:02X}{:02X}{:02X}".format(self.r, self.g, self.b, self.a)
97
+
98
+ # quick alpha edit
99
+ def set_alpha(self, a):
100
+ self.a = max(0, min(255, a))
101
+ return self
102
+
103
+ # color math
104
+ def brighten(self, amt=30):
105
+ self.r = min(255, self.r + amt)
106
+ self.g = min(255, self.g + amt)
107
+ self.b = min(255, self.b + amt)
108
+ return self
109
+
110
+ def darken(self, amt=30):
111
+ self.r = max(0, self.r - amt)
112
+ self.g = max(0, self.g - amt)
113
+ self.b = max(0, self.b - amt)
114
+ return self
115
+
116
+ @staticmethod
117
+ def lerp(c1, c2, t: float):
118
+ """blend between two colors"""
119
+ r = c1.r + (c2.r - c1.r) * t
120
+ g = c1.g + (c2.g - c1.g) * t
121
+ b = c1.b + (c2.b - c1.b) * t
122
+ a = c1.a + (c2.a - c1.a) * t
123
+ return Color(int(r), int(g), int(b), int(a))
crystalwindow/gui.py CHANGED
@@ -9,10 +9,6 @@ def hex_to_rgb(hex_str):
9
9
  hex_str = hex_str.lstrip("#")
10
10
  return tuple(int(hex_str[i:i+2], 16) for i in (0, 2, 4))
11
11
 
12
- def random_color():
13
- """Return a random RGB color"""
14
- return (random.randint(0,255), random.randint(0,255), random.randint(0,255))
15
-
16
12
  def lerp_color(c1, c2, t):
17
13
  """Linearly interpolate between two colors"""
18
14
  return tuple(int(a + (b-a)*t) for a,b in zip(c1,c2))
crystalwindow/sprites.py CHANGED
@@ -90,7 +90,7 @@ class Sprite:
90
90
  self.x + getattr(self, "width", 0) > other.x and
91
91
  self.y < other.y + getattr(other, "height", 0) and
92
92
  self.y + getattr(self, "height", 0) > other.y
93
- ), # returns tuple for consistency
93
+ ) # returns tuple for consistency
94
94
 
95
95
  def set_image(self, img):
96
96
  """Update sprite's image at runtime (like flipping)"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crystalwindow
3
- Version: 3.8.3
3
+ Version: 3.8.5
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
@@ -1,10 +1,11 @@
1
1
  crystalwindow/FileHelper.py,sha256=aUnnRG7UwvzJt-idjWjmpwy3RM6nqLlC3-7Bae6Yb94,5471
2
- crystalwindow/__init__.py,sha256=1O0qUvD6dGRZEwCXZU5byqWQUdRNYhyUZ54SN_NM2Dk,2015
2
+ crystalwindow/__init__.py,sha256=Ugp3GLsfYK_OAA8J9WnGc95P4Uev5fAePmzNNXmpSKQ,2144
3
3
  crystalwindow/animation.py,sha256=zHjrdBXQeyNaLAuaGPldJueX05OZ5j31YR8NizmR0uQ,427
4
- crystalwindow/assets.py,sha256=3FubtFHcemIFBiV5h79QyvKkHiLSUNBEPbGP4UyGRyI,3999
4
+ crystalwindow/assets.py,sha256=2Cj0zdhMWo3mWjdr9KU5n-9_8iKj_fJ9uShMFA-27HU,5193
5
5
  crystalwindow/camera.py,sha256=tbn4X-jxMIszAUg3Iu-89gJN5nij0mjPMEzGotcLbJI,712
6
6
  crystalwindow/clock.py,sha256=iryeURnfXx6TIDyJhpxe0KkeSaHCdxrMckN6Tby00i0,461
7
7
  crystalwindow/collision.py,sha256=hpkHTp_KparghVK-itp_rxuYdd2GbQMxICHlUBv0rSw,472
8
+ crystalwindow/color_handler.py,sha256=ZnXnz8552GPiRAnCkW_8wycwRRMAaFRFLlCcsrv0j2E,4071
8
9
  crystalwindow/crystal3d.py,sha256=-Te9IJgbtzl8Mpuc4BPi2bn2apnvBNTI2GwxSLd8sqg,2006
9
10
  crystalwindow/draw_helpers.py,sha256=HqjI5fTbdnA55g4LKYEuMUdIjrWaBm2U8RmeUXjcQGw,821
10
11
  crystalwindow/draw_rects.py,sha256=o7siET3y35N2LPeNBGe8QhsQbOH8J-xF6fOUz07rymU,1484
@@ -12,11 +13,11 @@ crystalwindow/draw_text_helper.py,sha256=qv5fFCuTCKWeGDk9Z_ZpOzrTFP8YYwlgQrrorwr
12
13
  crystalwindow/draw_tool.py,sha256=1YYEqjmgt4HpV3S15sTjCSmcqgHup4fD8gskTkxU0t4,1638
13
14
  crystalwindow/fun_helpers.py,sha256=fo5yTwGENltdtVIVwgITtUkvzpsImujOcqTxe8XPzR8,760
14
15
  crystalwindow/gravity.py,sha256=pZJykZzO-mKVBPsZRP55nnlvUoYQfR29wPgJcI4IbBs,2904
15
- crystalwindow/gui.py,sha256=D-El18XUaZQR-XZoOr28hnhO7EEoGuypCHxPbPR_yng,3680
16
+ crystalwindow/gui.py,sha256=vqI2Qpus0RHEwEsef0gojXb54yOFo6p-9TnDF4bEnSg,3538
16
17
  crystalwindow/gui_ext.py,sha256=ZhNgc5eK6Vzj-jUNeFzimuEbLnTmM7Bx594Z34_N0oM,2856
17
18
  crystalwindow/math.py,sha256=slOY3KQZ99VDMUMxsSJabMyRtJcwVzEyxR2RoXspHho,963
18
19
  crystalwindow/player.py,sha256=4wpIdUZLTlRXV8fDRQ11yVJRbx_cv8Ekpn2y7pQGgAQ,3442
19
- crystalwindow/sprites.py,sha256=V84FBsr4DJKLtart3OEb8lvLow20wZ6JuVZ5I4TRiFg,3412
20
+ crystalwindow/sprites.py,sha256=2kYW4QfSnyUwRLedZCkb99wUSxn2a0JdWOHcfkxcG0U,3411
20
21
  crystalwindow/tilemap.py,sha256=PHoKL1eWuNeHIf0w-Jh5MGdQGEgklVsxqqJOS-GNMKI,322
21
22
  crystalwindow/ver_warner.py,sha256=qEN3ulc1NixBy15FFx2R3Zu0DhyJTVJwiESGAPwpynM,3373
22
23
  crystalwindow/window.py,sha256=e6C8yIdVdjOduIeU0ZmlrNn8GmyvHuzKs473pRggkz0,18180
@@ -31,8 +32,8 @@ crystalwindow/gametests/guitesting.py,sha256=SrOssY5peCQEV6TQ1AiOWtjb9phVGdRzW-Q
31
32
  crystalwindow/gametests/sandbox.py,sha256=Oo2tU2N0y3BPVa6T5vs_h9N6islhQrjSrr_78XLut5I,1007
32
33
  crystalwindow/gametests/squaremove.py,sha256=poP2Zjl2oc2HVvIAgIK34H2jVj6otL4jEdvAOR6L9sI,572
33
34
  crystalwindow/gametests/windowtesting.py,sha256=_9X6wnV1-_X_PtNS-0zu-k209NtFIwAc4vpxLPp7V2o,97
34
- crystalwindow-3.8.3.dist-info/licenses/LICENSE,sha256=7pvUgvRXL3ED5VVAZPH5oGn1CaIXcyoDC9gqox6sB0g,1079
35
- crystalwindow-3.8.3.dist-info/METADATA,sha256=h_abo60ExVg_jZNFt6rUHUUzAmx1MTDaDcxMJJ-v4CI,7340
36
- crystalwindow-3.8.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
37
- crystalwindow-3.8.3.dist-info/top_level.txt,sha256=PeQSld4b19XWT-zvbYkvE2Xg8sakIMbDzSzSdOSRN8o,14
38
- crystalwindow-3.8.3.dist-info/RECORD,,
35
+ crystalwindow-3.8.5.dist-info/licenses/LICENSE,sha256=Gt5cJRchdNt0guxyQMHKsATN5PM5mjuDhdO6Gzs9qQc,1096
36
+ crystalwindow-3.8.5.dist-info/METADATA,sha256=8aRebxnTtseTd_BNHaPHtCzvs90NNM9S87WK1buHgYw,7340
37
+ crystalwindow-3.8.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ crystalwindow-3.8.5.dist-info/top_level.txt,sha256=PeQSld4b19XWT-zvbYkvE2Xg8sakIMbDzSzSdOSRN8o,14
39
+ crystalwindow-3.8.5.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 C
3
+ Copyright (c) 2025 CrystalBallyHereXD
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal