e2D 1.3.2__tar.gz → 1.3.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: e2D
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
5
5
  Home-page: https://github.com/marick-py/e2D
6
6
  Author: Riccardo Mariani
@@ -315,11 +315,11 @@ class Vector2D:
315
315
  It then generates random x and y coordinates in the range [0, 1) using the `random()` function from the `random` module.
316
316
  These random values are then scaled by (end - start) and added to the start point to obtain the final random Vector2D point.
317
317
  """
318
- if not isinstance(start, Vector2D|V2):
318
+ if not any(isinstance(start, cls) for cls in {Vector2D, V2}):
319
319
  if type(start) in int|float: start = Vector2D(start, start) #type: ignore
320
320
  elif type(start) == None: start = Vector2D(0,0)
321
321
  else: raise Exception(f"\nArg start must be in [Vector2D, int, float, tuple, list] not a [{type(start)}]\n")
322
- if not isinstance(end, Vector2D|V2):
322
+ if not any(isinstance(end, cls) for cls in {Vector2D, V2}):
323
323
  if type(end) in int|float: end = Vector2D(end, end) #type: ignore
324
324
  elif type(end) == None: end = Vector2D(1,1)
325
325
  else: raise Exception(f"\nArg end must be in [Vector2D, int, float, tuple, list] not a [{type(end)}]\n")
@@ -704,12 +704,12 @@ class Vector2D:
704
704
 
705
705
  If n is neither a numeric value nor a Vector2D other, the function raises an exception.
706
706
  """
707
- if isinstance(n, int|float):
707
+ if any(isinstance(n, cls) for cls in {int, float}):
708
708
  if n == 0:
709
709
  return Vector2D(0 if error_mode == "zero" else (self.x if error_mode == "null" else _mt.nan), 0 if error_mode == "zero" else (self.y if error_mode == "null" else _mt.nan))
710
710
  else:
711
711
  return self / n
712
- elif isinstance(n, Vector2D|V2):
712
+ elif any(isinstance(n, cls) for cls in {Vector2D, V2}):
713
713
  return Vector2D((0 if error_mode == "zero" else (self.x if error_mode == "null" else _mt.nan)) if n.x == 0 else self.x / n.x, (0 if error_mode == "zero" else (self.y if error_mode == "null" else _mt.nan)) if n.y == 0 else self.y / n.y)
714
714
  else:
715
715
  raise Exception(f"\nArg n must be in [Vector2D, int, float, tuple, list] not a [{type(n)}]\n")
@@ -832,7 +832,7 @@ class Vector2D:
832
832
 
833
833
  # comparasion
834
834
  def __eq__(self, other) -> bool:
835
- if not isinstance(other, Vector2D|V2|list|tuple):
835
+ if not any(isinstance(other, cls) for cls in {Vector2D, V2, list, tuple}):
836
836
  return False
837
837
  other = self.__normalize__(other)
838
838
  return self.x == other.x and self.y == other.y
@@ -868,9 +868,9 @@ class Vector2D:
868
868
 
869
869
  def __normalize__(self:"V2|Vector2D", other) -> "Vector2D|V2":
870
870
  if not isinstance(other, Vector2D):
871
- if isinstance(other, int|float):
871
+ if any(isinstance(other, cls) for cls in {int, float}):
872
872
  return Vector2D(other, other)
873
- elif isinstance(other, list|tuple):
873
+ elif any(isinstance(other, cls) for cls in {list, tuple}):
874
874
  return Vector2D(*other[:2])
875
875
  else:
876
876
  raise TypeError(f"The value {other} is not a num type: [{int|float}] nor an array type: [{list|tuple}]")
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  from .utils import *
2
3
  import pygame as pg
3
4
 
@@ -65,7 +66,7 @@ class RootEnv:
65
66
  text_box = font.render(text, True, color)
66
67
  size = V2(*text_box.get_size()) + margin * 2
67
68
  position = position - size * self.__fixed_sides_multiplier[fixed_sides] + margin
68
- if not isinstance(border_radius, tuple|list): border_radius = [border_radius]*4
69
+ if not any(isinstance(border_radius, cls) for cls in {tuple, list}): border_radius = [border_radius]*4
69
70
  surface = (self.screen if personalized_surface == None else personalized_surface)
70
71
  if bg_color != None:
71
72
  pg.draw.rect(surface, bg_color, (position - margin)() + size(), 0, -1, *border_radius)
e2D-1.3.4/e2D/plots.py ADDED
@@ -0,0 +1,272 @@
1
+ from __future__ import annotations
2
+ from .envs import *
3
+ import numpy as np
4
+
5
+ def no_error_complex_function(function, args) -> V2|Vector2D:
6
+ res :complex= function(args)
7
+ return V2(res.real, res.imag)
8
+
9
+ sign = lambda value: -1 if value < 0 else (1 if value > 0 else 0)
10
+
11
+ class Function:
12
+ def __init__(self, function, color) -> None:
13
+ self.plot : Plot
14
+ self.color = color
15
+ self.function = function
16
+
17
+ def update_points(self) -> None:
18
+ self.update_function(self.function)
19
+
20
+ def get_points(self) -> list:
21
+ signs_self = np.sign(self.function(*self.plot.meshgrid))
22
+ signs_sum = signs_self + np.roll(signs_self, axis=1, shift=1) + np.roll(signs_self, axis=0, shift=-1) + np.roll(signs_self, axis=(1,0), shift=(1,-1))
23
+ return np.column_stack(np.where(((-4 < signs_sum) & (signs_sum < 4))[:-1, 1:])[::-1]) / self.plot.scale()
24
+
25
+ def update_function(self, new_function) -> None:
26
+ self.function = new_function
27
+ self.points = self.get_points()
28
+ self.render()
29
+
30
+ def render(self) -> None:
31
+ self.__layer_surface__.fill((0,0,0,0))
32
+ offset = self.plot.dragging - self.plot.start_dragging if (self.plot.dragging != None) and (not self.plot.settings.get("use_real_time_rendering")) else None
33
+ if any(x < 1 for x in self.plot.scale):
34
+ for point in self.points:
35
+ # radius = max(min(self.plot.pixel_size)*.5, 1)
36
+ # pg.draw.circle(self.plot.canvas, self.color, (point + self.plot.pixel_size*.5)(), radius)
37
+ pg.draw.rect(self.__layer_surface__, self.color, (point.tolist() + (offset if offset != None else V2z))() + self.plot.pixel_size()) #type: ignore
38
+ else:
39
+ for point in self.points:
40
+ point = point.astype(int).tolist()
41
+ if self.plot.dragging != None:
42
+ point = round(point + offset)()
43
+ self.__layer_surface__.set_at(point, self.color)
44
+
45
+ def draw(self) -> None:
46
+ self.plot.canvas.blit(self.__layer_surface__, (0,0))
47
+
48
+ # class ComplexFunction:
49
+ # def __init__(self, function, plot:"Plot", starting_t:float=-10, ending_t:float=10, step=.01, color=(255,255,255), auto_connect_treshold=float("inf"), points_radius=2, points_color=None) -> None:
50
+ # self.auto_connect_treshold = auto_connect_treshold
51
+ # self.plot = plot
52
+ # self.starting_t = starting_t
53
+ # self.ending_t = ending_t
54
+ # self.color = color
55
+ # self.step = step
56
+ # self.points_color = points_color
57
+ # self.points_radius = points_radius
58
+ # self.update_function(function)
59
+
60
+ # def update_points(self) -> None:
61
+ # self.update_function(self.function)
62
+
63
+ # def update_function(self, new_function) -> None:
64
+ # self.function = new_function
65
+ # self.points :list[V2|Vector2D]= [point for t in range(int(self.starting_t / self.step), int(self.ending_t / self.step)) if (self.plot.bottom_right_y < (point:=no_error_complex_function(new_function, t * self.step)).y < self.plot.top_left_y) and (self.plot.top_left_x < point.x < self.plot.bottom_right_x)]
66
+ # self.full_auto_connect = not any(point.distance_to(self.points[i]) > self.auto_connect_treshold for i,point in enumerate(self.points[1:]))
67
+
68
+ # def draw(self) -> None:
69
+ # if self.points_radius:
70
+ # for point in self.points:
71
+ # pg.draw.circle(self.plot.canvas, self.color if self.points_color == None else self.points_color, self.plot.__plot2real__(point)(), self.points_radius)
72
+
73
+ # if len(self.points) < 2: return
74
+ # if self.full_auto_connect:
75
+ # pg.draw.lines(self.plot.canvas, self.color, False, [self.plot.__plot2real__(point)() for point in self.points])
76
+ # else:
77
+ # real_points = [self.plot.__plot2real__(point)() for point in self.points]
78
+ # for i,(point, real_point) in enumerate(zip(self.points[1:], real_points[1:])):
79
+ # if point.distance_to(self.points[i]) < self.auto_connect_treshold:
80
+ # pg.draw.line(self.plot.canvas, self.color, real_points[i], real_point) #type: ignore
81
+
82
+ class __PlotSettings__:
83
+ def __init__(self, plot:Plot) -> None:
84
+ self.plot = plot
85
+ self.settings :dict[str: bool|V2|Vector2D|int|float]= {
86
+ "use_real_time_rendering" : True,
87
+ "show_corners_coords" : True,
88
+
89
+ "use_inter_pixel_correction" : True,
90
+
91
+ "show_zoom_info": True,
92
+ "top_left_info_position" : self.plot.position + V2(20, 100),
93
+ "info_spacing" : V2(0, 32),
94
+ "info_precision" : 2,
95
+
96
+ "distance_to_axis_for_scalar_zoom" : 10,
97
+
98
+ "bg_color" : (25, 25, 25),
99
+ "axes_default_color" : (100, 100, 100),
100
+ "x_axis_color" : None,
101
+ "y_axis_color" : None,
102
+
103
+ "axes_default_width" : 5,
104
+ "x_axis_width" : None,
105
+ "y_axis_width" : None,
106
+
107
+ "show_cursor_coords" : False,
108
+ }
109
+
110
+ def print_current_settings(self) -> None:
111
+ longest_key = max(map(len, self.settings))
112
+ longest_type = max(map(lambda setting: len(str(type(setting)).split("'")[1]), self.settings.values()))
113
+ for setting in self.settings:
114
+ print(f"{setting}{' '*(longest_key-len(setting))} :{str(type(self.settings[setting])).split("'")[1]}{' '*(longest_type-len(str(type(self.settings[setting])).split("'")[1]))}=\t{self.settings[setting]}")
115
+
116
+ def set(self, key:str, new_value) -> None:
117
+ if not (key in self.settings): raise ValueError(f"The key [{key}] does not exist...")
118
+ self.settings[key] = new_value
119
+
120
+ def multiple_set(self, keys:list[str], new_values:list) -> None:
121
+ for key, new_value in zip(keys, new_values):
122
+ self.set(key, new_value)
123
+
124
+ def get(self, key:str) -> bool|V2|Vector2D|int|float:
125
+ return self.settings[key]
126
+
127
+ def multiple_set(self, keys:list[str]) -> list[bool|V2|Vector2D|int|float]:
128
+ return [self.get(key) for key in keys]
129
+
130
+ class Plot:
131
+ __top_left_multiplier__ = V2(1, -1)
132
+ __bottop_right_multiplier__ = V2(1, -1)
133
+ def __init__(self, rootEnv:"RootEnv", plot_position:V2|Vector2D, plot_size:V2|Vector2D, top_left_plot_coord:V2|Vector2D, bottom_right_plot_coord: V2|Vector2D, scale:V2|Vector2D=V2one) -> None:
134
+ self.rootEnv = rootEnv
135
+
136
+ self.top_left_plot_coord = top_left_plot_coord
137
+ self.bottom_right_plot_coord = bottom_right_plot_coord
138
+
139
+ self.position = plot_position
140
+ self.size = plot_size
141
+ self.scale = scale
142
+
143
+ self.settings = __PlotSettings__(self)
144
+
145
+ self.current_zoom = V2one * -np.log2(10)*10
146
+ self.current_offset = V2(0,0)
147
+ self.update_grid(True)
148
+
149
+ self.functions :list[Function]= []
150
+
151
+ self.canvas = pg.Surface(self.size())
152
+ self.dragging = None
153
+ self.start_dragging = V2z
154
+ self.is_mouse_in_rect = False
155
+
156
+ def set_borders_by_position_and_zoom(self) -> None:
157
+ self.top_left_plot_coord = self.current_offset - (.5**(.1*self.current_zoom)) * self.__top_left_multiplier__
158
+ self.bottom_right_plot_coord = self.current_offset + (.5**(.1*self.current_zoom)) * self.__bottop_right_multiplier__
159
+ self.top_left_x, self.top_left_y = self.top_left_plot_coord
160
+ self.bottom_right_x, self.bottom_right_y = self.bottom_right_plot_coord
161
+
162
+ def update_grid(self, update_step_grid=False) -> None:
163
+ self.set_borders_by_position_and_zoom()
164
+ if update_step_grid:
165
+ self.step = (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size / self.scale
166
+ X, Y = np.arange(self.top_left_plot_coord.x, self.bottom_right_plot_coord.x, self.step.x), np.arange(self.top_left_plot_coord.y, self.bottom_right_plot_coord.y, self.step.y)
167
+ self.meshgrid = np.meshgrid(X, Y)
168
+ self.pixel_size = abs(self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord) * (self.step * -1))
169
+ if self.settings.get("use_inter_pixel_correction"):
170
+ self.pixel_size += V2one
171
+
172
+ def load_function(self, function:Function) -> None:
173
+ function.plot = self
174
+ function.__layer_surface__ = pg.Surface(self.size(), pg.SRCALPHA, 32).convert_alpha()
175
+ function.update_function(function.function)
176
+ self.functions.append(function)
177
+
178
+ def __plot2real__(self, plot_position:V2|Vector2D) -> V2|Vector2D:
179
+ return (plot_position + self.top_left_plot_coord * -1) * self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord)
180
+
181
+ def __real2plot__(self, real_position:V2|Vector2D) -> V2|Vector2D:
182
+ return (real_position - self.position) * (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size + self.top_left_plot_coord
183
+
184
+ def render(self) -> None:
185
+ self.canvas.fill(self.settings.get("bg_color"))
186
+ if self.top_left_x < 0 < self.bottom_right_x:
187
+ pg.draw.line(self.canvas,
188
+ self.settings.get("axes_default_color") if (x_color:=self.settings.get("x_axis_color"))==None else x_color,
189
+ self.__plot2real__(V2(0, self.top_left_y))(),
190
+ self.__plot2real__(V2(0, self.bottom_right_y))(),
191
+ self.settings.get("axes_default_width") if (x_width:=self.settings.get("x_axis_width"))==None else x_width)
192
+ if self.bottom_right_y < 0 < self.top_left_y:
193
+ pg.draw.line(self.canvas,
194
+ self.settings.get("axes_default_color") if (y_color:=self.settings.get("y_axis_color"))==None else y_color,
195
+ self.__plot2real__(V2(self.top_left_x, 0))(),
196
+ self.__plot2real__(V2(self.bottom_right_x, 0))(),
197
+ self.settings.get("axes_default_width") if (y_width:=self.settings.get("y_axis_width"))==None else y_width)
198
+
199
+ for function in self.functions: function.draw()
200
+
201
+ pg.draw.rect(self.canvas, (255,255,255), V2z() + self.size(), 5) #type: ignore
202
+
203
+ center = self.size * .5
204
+ aimer_radius = 15
205
+ pg.draw.line(self.canvas, (100,100,100), (center + aimer_radius)(), (center - aimer_radius)(), 1)
206
+ pg.draw.line(self.canvas, (100,100,100), (center + self.__top_left_multiplier__ * aimer_radius)(), (center - self.__top_left_multiplier__ * aimer_radius)(), 1)
207
+ pg.draw.circle(self.canvas, (100,100,100), (self.size * .5)(), 15, 1)
208
+
209
+ if self.settings.get("show_corners_coords"):
210
+ self.rootEnv.print(str(self.top_left_plot_coord.__round__(.1)), V2z.copy(), bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
211
+ self.rootEnv.print(str(V2(self.top_left_plot_coord.x, self.bottom_right_plot_coord.y).__round__(.1)), self.size * V2(0, 1), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_LEFT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
212
+ self.rootEnv.print(str(self.bottom_right_plot_coord.__round__(.1)), self.size.copy(), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
213
+ self.rootEnv.print(str(V2(self.bottom_right_plot_coord.x, self.top_left_plot_coord.y).__round__(.1)), self.size * V2(1, 0), fixed_sides=TEXT_FIXED_SIDES_TOP_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
214
+
215
+ def update(self) -> None:
216
+ self.plot_mouse_position = self.__real2plot__(self.rootEnv.mouse.position)
217
+ self.plot_center_real_position = self.__plot2real__(V2z) + self.position
218
+
219
+ self.is_mouse_in_rect = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and \
220
+ self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
221
+
222
+ if self.rootEnv.mouse.just_released[0] and self.dragging != None:
223
+ self.dragging = None
224
+ self.update_grid(True)
225
+ for function in self.functions:
226
+ function.update_points()
227
+ self.render()
228
+
229
+
230
+ if self.is_mouse_in_rect:
231
+ for event in self.rootEnv.events:
232
+ if event.type == pg.MOUSEWHEEL:
233
+
234
+ range_n = self.settings.get("distance_to_axis_for_scalar_zoom")
235
+ scalar = V2(0 if abs(self.plot_center_real_position.x - self.rootEnv.mouse.position.x) < range_n else 1, 0 if abs(self.plot_center_real_position.y - self.rootEnv.mouse.position.y) < range_n else 1)
236
+ self.current_zoom += event.y * scalar
237
+
238
+ self.update_grid(True)
239
+ for function in self.functions:
240
+ function.update_points()
241
+ self.render()
242
+
243
+ if self.rootEnv.mouse.just_pressed[0] and self.dragging == None:
244
+ self.dragging = self.rootEnv.mouse.position.copy()
245
+ self.start_dragging = self.dragging.copy()
246
+
247
+ if self.dragging:
248
+ offset = (self.dragging - self.rootEnv.mouse.position)* V2(1, -1) * (abs(self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size)
249
+ self.dragging = self.rootEnv.mouse.position.copy()
250
+ self.current_offset += offset
251
+
252
+ if self.settings.get("use_real_time_rendering"):
253
+ self.update_grid(True)
254
+ for function in self.functions: function.update_points()
255
+ else:
256
+ self.update_grid()
257
+ self.render()
258
+
259
+ def draw(self) -> None:
260
+ self.rootEnv.screen.blit(self.canvas, self.position())
261
+ if self.is_mouse_in_rect and self.settings.get("show_cursor_coords"):
262
+ self.rootEnv.print(str(round(self.plot_mouse_position, .1)), self.rootEnv.mouse.position, fixed_sides=TEXT_FIXED_SIDES_BOTTOM_MIDDLE)
263
+
264
+ data = [
265
+ [f"ZOOM:", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
266
+ [f" x: {self.current_zoom.x:.{self.settings.get("info_precision")}f};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
267
+ [f" y: {self.current_zoom.y:.{self.settings.get("info_precision")}f};", TEXT_FIXED_SIDES_TOP_LEFT, self.settings.get("show_zoom_info")],
268
+ ]
269
+
270
+ for i, (d, fixed_side, show) in enumerate(data):
271
+ if show:
272
+ self.rootEnv.print(d, self.settings.get("top_left_info_position") + self.settings.get("info_spacing") * i, fixed_sides=fixed_side)
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import pygame as pg
2
3
  from e2D import *
3
4
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: e2D
3
- Version: 1.3.2
3
+ Version: 1.3.4
4
4
  Summary: Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
5
5
  Home-page: https://github.com/marick-py/e2D
6
6
  Author: Riccardo Mariani
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = e2D
3
- version = 1.3.2
3
+ version = 1.3.4
4
4
  author = Riccardo Mariani
5
5
  author_email = ricomari2006@gmail.com
6
6
  description = Python library for 2D games. Streamlines dev with keyboard/mouse input, vector calculations, color manipulation, and collision detection. Simplify game creation and unleash creativity!
e2D-1.3.2/e2D/plots.py DELETED
@@ -1,159 +0,0 @@
1
- from .envs import *
2
- import numpy as np
3
- import pickle as pk
4
-
5
- def no_error_complex_function(function, args) -> V2|Vector2D:
6
- res :complex= function(args)
7
- return V2(res.real, res.imag)
8
-
9
- sign = lambda value: -1 if value < 0 else (1 if value > 0 else 0)
10
-
11
- class Function:
12
- def __init__(self, function, plot:"Plot", color) -> None:
13
- self.plot = plot
14
- self.color = color
15
- self.update_function(function)
16
-
17
- def update_points(self) -> None:
18
- self.update_function(self.function)
19
-
20
- def get_points(self) -> list:
21
- signs_self = np.sign(self.function(*self.plot.meshgrid))
22
- signs_sum = signs_self + np.roll(signs_self, axis=1, shift=1) + np.roll(signs_self, axis=0, shift=-1) + np.roll(signs_self, axis=(1,0), shift=(1,-1))
23
- return np.column_stack(np.where(((-4 < signs_sum) & (signs_sum < 4))[:-1, 1:])[::-1]) / self.plot.scale()
24
-
25
- def update_function(self, new_function) -> None:
26
- self.function = new_function
27
- self.points = self.get_points()
28
-
29
- def draw(self) -> None:
30
- # pg.draw.aalines(self.plot.canvas, self.color, False, self.points)
31
- for point in self.points:
32
- self.plot.canvas.set_at(list(map(int, point)), self.color)
33
-
34
- # class ComplexFunction:
35
- # def __init__(self, function, plot:"Plot", starting_t:float=-10, ending_t:float=10, step=.01, color=(255,255,255), auto_connect_treshold=float("inf"), points_radius=2, points_color=None) -> None:
36
- # self.auto_connect_treshold = auto_connect_treshold
37
- # self.plot = plot
38
- # self.starting_t = starting_t
39
- # self.ending_t = ending_t
40
- # self.color = color
41
- # self.step = step
42
- # self.points_color = points_color
43
- # self.points_radius = points_radius
44
- # self.update_function(function)
45
-
46
- # def update_points(self) -> None:
47
- # self.update_function(self.function)
48
-
49
- # def update_function(self, new_function) -> None:
50
- # self.function = new_function
51
- # self.points :list[V2|Vector2D]= [point for t in range(int(self.starting_t / self.step), int(self.ending_t / self.step)) if (self.plot.bottom_right_y < (point:=no_error_complex_function(new_function, t * self.step)).y < self.plot.top_left_y) and (self.plot.top_left_x < point.x < self.plot.bottom_right_x)]
52
- # self.full_auto_connect = not any(point.distance_to(self.points[i]) > self.auto_connect_treshold for i,point in enumerate(self.points[1:]))
53
-
54
- # def draw(self) -> None:
55
- # if self.points_radius:
56
- # for point in self.points:
57
- # pg.draw.circle(self.plot.canvas, self.color if self.points_color == None else self.points_color, self.plot.__plot2real__(point)(), self.points_radius)
58
-
59
- # if len(self.points) < 2: return
60
- # if self.full_auto_connect:
61
- # pg.draw.lines(self.plot.canvas, self.color, False, [self.plot.__plot2real__(point)() for point in self.points])
62
- # else:
63
- # real_points = [self.plot.__plot2real__(point)() for point in self.points]
64
- # for i,(point, real_point) in enumerate(zip(self.points[1:], real_points[1:])):
65
- # if point.distance_to(self.points[i]) < self.auto_connect_treshold:
66
- # pg.draw.line(self.plot.canvas, self.color, real_points[i], real_point) #type: ignore
67
-
68
- class Plot:
69
- __top_left_multiplier__ = V2(1, -1)
70
- __bottop_right_multiplier__ = V2(1, -1)
71
- def __init__(self, rootEnv:"RootEnv", plot_position:V2|Vector2D, plot_size:V2|Vector2D, top_left_plot_coord:V2|Vector2D, bottom_right_plot_coord: V2|Vector2D, scale:V2|Vector2D=V2one) -> None:
72
- self.rootEnv = rootEnv
73
-
74
- self.top_left_plot_coord = top_left_plot_coord
75
- self.bottom_right_plot_coord = bottom_right_plot_coord
76
-
77
- self.position = plot_position
78
- self.size = plot_size
79
- self.scale = scale
80
-
81
- self.current_zoom = V2one * -np.log2(10)*10
82
- self.current_offset = V2(0,0)
83
- self.update_grid(True)
84
-
85
- self.functions :list[Function]= []
86
-
87
- self.canvas = pg.Surface(self.size())
88
- self.dragging = None
89
- self.is_mouse_in_rect = False
90
-
91
- def set_borders_by_position_and_zoom(self) -> None:
92
- self.top_left_plot_coord = self.current_offset - (.5**(.1*self.current_zoom)) * self.__top_left_multiplier__
93
- self.bottom_right_plot_coord = self.current_offset + (.5**(.1*self.current_zoom)) * self.__bottop_right_multiplier__
94
- self.top_left_x, self.top_left_y = self.top_left_plot_coord
95
- self.bottom_right_x, self.bottom_right_y = self.bottom_right_plot_coord
96
-
97
- def update_grid(self, update_step_grid=False) -> None:
98
- self.set_borders_by_position_and_zoom()
99
- if update_step_grid:
100
- self.step = (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size / self.scale
101
- X, Y = np.arange(self.top_left_plot_coord.x, self.bottom_right_plot_coord.x, self.step.x), np.arange(self.top_left_plot_coord.y, self.bottom_right_plot_coord.y, self.step.y)
102
- self.meshgrid = np.meshgrid(X, Y)
103
-
104
- def load_function(self, function:Function) -> None:
105
- self.functions.append(function)
106
-
107
- def __plot2real__(self, plot_position:V2|Vector2D) -> V2|Vector2D:
108
- return (plot_position + self.top_left_plot_coord * -1) * self.size / (self.bottom_right_plot_coord - self.top_left_plot_coord)
109
-
110
- def __real2plot__(self, real_position:V2|Vector2D) -> V2|Vector2D:
111
- return (real_position - self.position) * (self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size + self.top_left_plot_coord
112
-
113
- def render(self) -> None:
114
- self.canvas.fill((0,0,0))
115
- if self.bottom_right_y < 0 < self.top_left_y: pg.draw.line(self.canvas, (100,100,100), self.__plot2real__(V2(self.top_left_x, 0))(), self.__plot2real__(V2(self.bottom_right_x, 0))())
116
- if self.top_left_x < 0 < self.bottom_right_x: pg.draw.line(self.canvas, (100,100,100), self.__plot2real__(V2(0, self.top_left_y))(), self.__plot2real__(V2(0, self.bottom_right_y))())
117
-
118
- for function in self.functions: function.draw()
119
-
120
- pg.draw.rect(self.canvas, (255,255,255), V2z() + self.size(), 5) #type: ignore
121
- self.rootEnv.print(str(self.top_left_plot_coord.__round__(.1)), V2z.copy(), bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
122
- self.rootEnv.print(str(V2(self.top_left_plot_coord.x, self.bottom_right_plot_coord.y).__round__(.1)), self.size * V2(0, 1), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_LEFT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
123
- self.rootEnv.print(str(self.bottom_right_plot_coord.__round__(.1)), self.size.copy(), fixed_sides=TEXT_FIXED_SIDES_BOTTOM_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
124
- self.rootEnv.print(str(V2(self.bottom_right_plot_coord.x, self.top_left_plot_coord.y).__round__(.1)), self.size * V2(1, 0), fixed_sides=TEXT_FIXED_SIDES_TOP_RIGHT, bg_color=(0,0,0), border_color=(255,255,255), border_width=2, border_radius=15, margin=V2(10,10), personalized_surface=self.canvas)
125
-
126
- def update(self) -> None:
127
- self.is_mouse_in_rect = self.position.x < self.rootEnv.mouse.position.x < self.position.x + self.size.x and \
128
- self.position.y < self.rootEnv.mouse.position.y < self.position.y + self.size.y
129
-
130
- if self.rootEnv.mouse.just_released[0] and self.dragging != None:
131
- self.dragging = None
132
- self.update_grid(True)
133
- for function in self.functions:
134
- function.update_points()
135
- self.render()
136
-
137
- if self.is_mouse_in_rect:
138
- for event in self.rootEnv.events:
139
- if event.type == pg.MOUSEWHEEL:
140
- self.current_zoom += event.y
141
- self.update_grid(True)
142
- for function in self.functions:
143
- function.update_points()
144
- self.render()
145
-
146
- if self.rootEnv.mouse.just_pressed[0] and self.dragging == None:
147
- self.dragging = self.rootEnv.mouse.position.copy()
148
-
149
- if self.dragging:
150
- offset = (self.dragging - self.rootEnv.mouse.position)* V2(1, -1) * (abs(self.bottom_right_plot_coord - self.top_left_plot_coord) / self.size)
151
- self.dragging = self.rootEnv.mouse.position.copy()
152
- self.current_offset += offset
153
- self.update_grid()
154
- self.render()
155
-
156
- def draw(self) -> None:
157
- self.rootEnv.screen.blit(self.canvas, self.position())
158
- if self.is_mouse_in_rect:
159
- self.rootEnv.print(str(round(self.__real2plot__(self.rootEnv.mouse.position), .1)), self.rootEnv.mouse.position, fixed_sides=TEXT_FIXED_SIDES_BOTTOM_MIDDLE)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes