ConsoleLib 1.3.0__tar.gz → 1.3.1__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.
@@ -0,0 +1,532 @@
1
+ """
2
+ ConsoleLib - The best Console Renderer of the Python.
3
+ By: Suleiman
4
+ Copyright © Suleiman 2026
5
+ All rights are reserved.
6
+ """
7
+ import os
8
+ import sys
9
+ import time
10
+ import subprocess as CMD
11
+ import math
12
+ import random
13
+
14
+ class Render:
15
+ @staticmethod
16
+ def DrawPic(points=None, width=80, height=25, clear_before_draw=False, default_char=' '):
17
+ if clear_before_draw:
18
+ os.system("cls" if os.name == "nt" else "clear")
19
+ field = [[default_char for _ in range(width)] for _ in range(height)]
20
+ if points:
21
+ for item in points:
22
+ if len(item) == 3:
23
+ x, y, char = item
24
+ if 0 <= x < width and 0 <= y < height:
25
+ field[y][x] = char
26
+ for row in field:
27
+ print(''.join(row))
28
+
29
+ @staticmethod
30
+ def get_line_points(x1, y1, x2, y2, char='#'):
31
+ points = []
32
+ dx = abs(x2 - x1)
33
+ dy = abs(y2 - y1)
34
+ sx = 1 if x1 < x2 else -1
35
+ sy = 1 if y1 < y2 else -1
36
+ err = dx - dy
37
+ while True:
38
+ points.append((x1, y1, char))
39
+ if x1 == x2 and y1 == y2:
40
+ break
41
+ e2 = err * 2
42
+ if e2 > -dy:
43
+ err -= dy
44
+ x1 += sx
45
+ if e2 < dx:
46
+ err += dx
47
+ y1 += sy
48
+ return points
49
+
50
+ @staticmethod
51
+ def get_circle_points(cx, cy, r, char='#'):
52
+ points = []
53
+ for angle in range(0, 360, 5):
54
+ rad = angle * math.pi / 180
55
+ x = int(cx + r * math.cos(rad))
56
+ y = int(cy + r * math.sin(rad))
57
+ points.append((x, y, char))
58
+ return points
59
+
60
+ @staticmethod
61
+ def get_filled_circle_points(cx, cy, r, char='#'):
62
+ points = []
63
+ for y in range(cy - r, cy + r + 1):
64
+ for x in range(cx - r, cx + r + 1):
65
+ if (x - cx) ** 2 + (y - cy) ** 2 <= r ** 2:
66
+ points.append((x, y, char))
67
+ return points
68
+
69
+ @staticmethod
70
+ def get_rect_points(x1, y1, x2, y2, char='#'):
71
+ points = []
72
+ for x in range(x1, x2 + 1):
73
+ points.append((x, y1, char))
74
+ points.append((x, y2, char))
75
+ for y in range(y1, y2 + 1):
76
+ points.append((x1, y, char))
77
+ points.append((x2, y, char))
78
+ return points
79
+
80
+ @staticmethod
81
+ def get_fill_rect_points(x1, y1, x2, y2, char='#'):
82
+ points = []
83
+ for y in range(y1, y2 + 1):
84
+ for x in range(x1, x2 + 1):
85
+ points.append((x, y, char))
86
+ return points
87
+
88
+ @staticmethod
89
+ def get_text_points(x, y, text, char=None):
90
+ points = []
91
+ if char is None:
92
+ for i, ch in enumerate(text):
93
+ points.append((x + i, y, ch))
94
+ else:
95
+ for i in range(len(text)):
96
+ points.append((x + i, y, char))
97
+ return points
98
+
99
+ @staticmethod
100
+ def get_triangle_points(x1, y1, x2, y2, x3, y3, char='#'):
101
+ points = []
102
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
103
+ points.extend(Render.get_line_points(x2, y2, x3, y3, char))
104
+ points.extend(Render.get_line_points(x3, y3, x1, y1, char))
105
+ return points
106
+
107
+ @staticmethod
108
+ def get_filled_triangle_points(x1, y1, x2, y2, x3, y3, char='#'):
109
+ points = []
110
+ min_x = min(x1, x2, x3)
111
+ max_x = max(x1, x2, x3)
112
+ min_y = min(y1, y2, y3)
113
+ max_y = max(y1, y2, y3)
114
+ for y in range(min_y, max_y + 1):
115
+ for x in range(min_x, max_x + 1):
116
+ if Render._point_in_triangle(x, y, x1, y1, x2, y2, x3, y3):
117
+ points.append((x, y, char))
118
+ return points
119
+
120
+ @staticmethod
121
+ def get_heart_points(cx, cy, size=5, char='#'):
122
+ points = []
123
+ for y in range(-size, size + 1):
124
+ for x in range(-size, size + 1):
125
+ if ((x * x + y * y - size * size) ** 3 <= size * size * x * x * y * y * 0.5):
126
+ points.append((cx + x, cy - y, char))
127
+ return points
128
+
129
+ @staticmethod
130
+ def get_star_points(cx, cy, radius=5, points_count=5, char='*'):
131
+ points = []
132
+ angle = -math.pi / 2
133
+ step = math.pi / points_count
134
+ outer_points = []
135
+ inner_points = []
136
+ for i in range(points_count * 2):
137
+ r = radius if i % 2 == 0 else radius * 0.4
138
+ x = cx + r * math.cos(angle + i * step)
139
+ y = cy + r * math.sin(angle + i * step)
140
+ if i % 2 == 0:
141
+ outer_points.append((x, y))
142
+ else:
143
+ inner_points.append((x, y))
144
+ for i in range(points_count):
145
+ p1 = outer_points[i]
146
+ p2 = inner_points[i]
147
+ p3 = outer_points[(i + 1) % points_count]
148
+ points.extend(Render.get_line_points(int(p1[0]), int(p1[1]), int(p2[0]), int(p2[1]), char))
149
+ points.extend(Render.get_line_points(int(p2[0]), int(p2[1]), int(p3[0]), int(p3[1]), char))
150
+ return points
151
+
152
+ @staticmethod
153
+ def get_bezier_points(x1, y1, x2, y2, x3, y3, steps=20, char='#'):
154
+ points = []
155
+ for t in range(steps + 1):
156
+ t = t / steps
157
+ x = (1 - t) ** 2 * x1 + 2 * (1 - t) * t * x2 + t ** 2 * x3
158
+ y = (1 - t) ** 2 * y1 + 2 * (1 - t) * t * y2 + t ** 2 * y3
159
+ points.append((int(x), int(y), char))
160
+ return points
161
+
162
+ @staticmethod
163
+ def get_wave_points(cx, cy, amplitude=5, length=20, char='~'):
164
+ points = []
165
+ for x in range(length):
166
+ y = cy + int(amplitude * math.sin(x * 0.5))
167
+ points.append((cx + x, y, char))
168
+ return points
169
+
170
+ @staticmethod
171
+ def get_spiral_points(cx, cy, turns=3, radius=10, step=0.1, char='*'):
172
+ points = []
173
+ angle = 0
174
+ r = 0
175
+ while r < radius:
176
+ x = int(cx + r * math.cos(angle))
177
+ y = int(cy + r * math.sin(angle))
178
+ points.append((x, y, char))
179
+ angle += step
180
+ r += step * 2
181
+ return points
182
+
183
+ @staticmethod
184
+ def get_grid_points(x1, y1, x2, y2, step=2, char='+'):
185
+ points = []
186
+ for x in range(x1, x2 + 1, step):
187
+ for y in range(y1, y2 + 1, step):
188
+ points.append((x, y, char))
189
+ return points
190
+
191
+ @staticmethod
192
+ def get_noise_points(cx, cy, radius, count=50, char='.'):
193
+ points = []
194
+ for _ in range(count):
195
+ angle = random.uniform(0, 2 * math.pi)
196
+ r = random.uniform(0, radius)
197
+ x = int(cx + r * math.cos(angle))
198
+ y = int(cy + r * math.sin(angle))
199
+ points.append((x, y, char))
200
+ return points
201
+
202
+ @staticmethod
203
+ def _point_in_triangle(px, py, x1, y1, x2, y2, x3, y3):
204
+ def sign(a, b, c):
205
+ return (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1])
206
+ p = (px, py)
207
+ d1 = sign(p, (x2, y2), (x1, y1))
208
+ d2 = sign(p, (x3, y3), (x2, y2))
209
+ d3 = sign(p, (x1, y1), (x3, y3))
210
+ has_neg = (d1 < 0) or (d2 < 0) or (d3 < 0)
211
+ has_pos = (d1 > 0) or (d2 > 0) or (d3 > 0)
212
+ return not (has_neg and has_pos)
213
+
214
+ @staticmethod
215
+ def _rotx(x, y, z, angle):
216
+ rad = math.radians(angle)
217
+ cos_a = math.cos(rad)
218
+ sin_a = math.sin(rad)
219
+ y_new = y * cos_a - z * sin_a
220
+ z_new = y * sin_a + z * cos_a
221
+ return x, y_new, z_new
222
+
223
+ @staticmethod
224
+ def _roty(x, y, z, angle):
225
+ rad = math.radians(angle)
226
+ cos_a = math.cos(rad)
227
+ sin_a = math.sin(rad)
228
+ x_new = x * cos_a + z * sin_a
229
+ z_new = -x * sin_a + z * cos_a
230
+ return x_new, y, z_new
231
+
232
+ @staticmethod
233
+ def _rotz(x, y, z, angle):
234
+ rad = math.radians(angle)
235
+ cos_a = math.cos(rad)
236
+ sin_a = math.sin(rad)
237
+ x_new = x * cos_a - y * sin_a
238
+ y_new = x * sin_a + y * cos_a
239
+ return x_new, y_new, z
240
+
241
+ @staticmethod
242
+ def _project_3d(x, y, z, rotx, roty, rotz, scale, cx, cy):
243
+ x, y, z = Render._rotx(x, y, z, rotx)
244
+ x, y, z = Render._roty(x, y, z, roty)
245
+ x, y, z = Render._rotz(x, y, z, rotz)
246
+ x2d = int(x * scale + cx)
247
+ y2d = int(-y * scale + cy)
248
+ return x2d, y2d
249
+
250
+ @staticmethod
251
+ def get_cube_3d_points(size=5, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#'):
252
+ s = size / 2
253
+ vertices = [
254
+ (-s, -s, -s), (s, -s, -s), (s, s, -s), (-s, s, -s),
255
+ (-s, -s, s), (s, -s, s), (s, s, s), (-s, s, s)
256
+ ]
257
+ edges = [
258
+ (0,1), (1,2), (2,3), (3,0),
259
+ (4,5), (5,6), (6,7), (7,4),
260
+ (0,4), (1,5), (2,6), (3,7)
261
+ ]
262
+ points = []
263
+ projected = []
264
+ for v in vertices:
265
+ x2d, y2d = Render._project_3d(v[0], v[1], v[2], rotx, roty, rotz, scale, cx, cy)
266
+ projected.append((x2d, y2d))
267
+ for edge in edges:
268
+ x1, y1 = projected[edge[0]]
269
+ x2, y2 = projected[edge[1]]
270
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
271
+ return points
272
+
273
+ @staticmethod
274
+ def get_pyramid_3d_points(size=5, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#'):
275
+ s = size / 2
276
+ vertices = [
277
+ (-s, -s, -s), (s, -s, -s), (s, -s, s), (-s, -s, s),
278
+ (0, s, 0)
279
+ ]
280
+ edges = [
281
+ (0,1), (1,2), (2,3), (3,0),
282
+ (0,4), (1,4), (2,4), (3,4)
283
+ ]
284
+ points = []
285
+ projected = []
286
+ for v in vertices:
287
+ x2d, y2d = Render._project_3d(v[0], v[1], v[2], rotx, roty, rotz, scale, cx, cy)
288
+ projected.append((x2d, y2d))
289
+ for edge in edges:
290
+ x1, y1 = projected[edge[0]]
291
+ x2, y2 = projected[edge[1]]
292
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
293
+ return points
294
+
295
+ @staticmethod
296
+ def get_cylinder_3d_points(radius=5, height=10, segments=12, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#'):
297
+ points = []
298
+ top_points = []
299
+ bottom_points = []
300
+ for i in range(segments):
301
+ rad = i / segments * 2 * math.pi
302
+ x = radius * math.cos(rad)
303
+ z = radius * math.sin(rad)
304
+ top_points.append((x, height/2, z))
305
+ bottom_points.append((x, -height/2, z))
306
+ all_vertices = top_points + bottom_points
307
+ projected = []
308
+ for v in all_vertices:
309
+ x2d, y2d = Render._project_3d(v[0], v[1], v[2], rotx, roty, rotz, scale, cx, cy)
310
+ projected.append((x2d, y2d))
311
+ for i in range(segments):
312
+ j = (i + 1) % segments
313
+ x1, y1 = projected[i]
314
+ x2, y2 = projected[j]
315
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
316
+ x1, y1 = projected[i + segments]
317
+ x2, y2 = projected[j + segments]
318
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
319
+ x1, y1 = projected[i]
320
+ x2, y2 = projected[i + segments]
321
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
322
+ return points
323
+
324
+ @staticmethod
325
+ def get_sphere_3d_points(radius=5, segments=12, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#'):
326
+ points = []
327
+ for i in range(segments):
328
+ theta = i / segments * math.pi
329
+ for j in range(segments):
330
+ phi = j / segments * 2 * math.pi
331
+ x = radius * math.sin(theta) * math.cos(phi)
332
+ y = radius * math.cos(theta)
333
+ z = radius * math.sin(theta) * math.sin(phi)
334
+ x2d, y2d = Render._project_3d(x, y, z, rotx, roty, rotz, scale, cx, cy)
335
+ points.append((x2d, y2d, char))
336
+ return points
337
+
338
+ @staticmethod
339
+ def get_cone_3d_points(radius=5, height=10, segments=12, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#'):
340
+ points = []
341
+ base_points = []
342
+ for i in range(segments):
343
+ rad = i / segments * 2 * math.pi
344
+ x = radius * math.cos(rad)
345
+ z = radius * math.sin(rad)
346
+ base_points.append((x, -height/2, z))
347
+ apex = (0, height/2, 0)
348
+ all_vertices = base_points + [apex]
349
+ projected = []
350
+ for v in all_vertices:
351
+ x2d, y2d = Render._project_3d(v[0], v[1], v[2], rotx, roty, rotz, scale, cx, cy)
352
+ projected.append((x2d, y2d))
353
+ for i in range(segments):
354
+ j = (i + 1) % segments
355
+ x1, y1 = projected[i]
356
+ x2, y2 = projected[j]
357
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
358
+ x1, y1 = projected[i]
359
+ x2, y2 = projected[-1]
360
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
361
+ return points
362
+
363
+ @staticmethod
364
+ def get_torus_3d_points(radius=8, tube=3, segments=16, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#'):
365
+ points = []
366
+ for i in range(segments):
367
+ theta = i / segments * 2 * math.pi
368
+ for j in range(segments):
369
+ phi = j / segments * 2 * math.pi
370
+ x = (radius + tube * math.cos(phi)) * math.cos(theta)
371
+ y = tube * math.sin(phi)
372
+ z = (radius + tube * math.cos(phi)) * math.sin(theta)
373
+ x2d, y2d = Render._project_3d(x, y, z, rotx, roty, rotz, scale, cx, cy)
374
+ points.append((x2d, y2d, char))
375
+ return points
376
+
377
+ @staticmethod
378
+ def get_ico_sphere_3d_points(radius=5, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#'):
379
+ points = []
380
+ phi = (1 + math.sqrt(5)) / 2
381
+ vertices = [
382
+ (-1, phi, 0), ( 1, phi, 0), (-1, -phi, 0), ( 1, -phi, 0),
383
+ ( 0, -1, phi), ( 0, 1, phi), ( 0, -1, -phi), ( 0, 1, -phi),
384
+ ( phi, 0, -1), ( phi, 0, 1), (-phi, 0, -1), (-phi, 0, 1)
385
+ ]
386
+ vertices = [(x * radius / 1.618, y * radius / 1.618, z * radius / 1.618) for x, y, z in vertices]
387
+ edges = [
388
+ (0,1), (0,4), (0,5), (0,10), (0,11),
389
+ (1,2), (1,5), (1,7), (1,8), (1,9),
390
+ (2,3), (2,6), (2,7), (2,10), (2,11),
391
+ (3,4), (3,6), (3,8), (3,9), (3,11),
392
+ (4,5), (4,9), (4,11),
393
+ (5,7), (5,9),
394
+ (6,7), (6,10),
395
+ (7,8),
396
+ (8,9), (8,10),
397
+ (10,11)
398
+ ]
399
+ projected = []
400
+ for v in vertices:
401
+ x2d, y2d = Render._project_3d(v[0], v[1], v[2], rotx, roty, rotz, scale, cx, cy)
402
+ projected.append((x2d, y2d))
403
+ for edge in edges:
404
+ x1, y1 = projected[edge[0]]
405
+ x2, y2 = projected[edge[1]]
406
+ points.extend(Render.get_line_points(x1, y1, x2, y2, char))
407
+ return points
408
+
409
+ @staticmethod
410
+ def draw_cube_3d(size=5, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#', width=80, height=25, clear_before_draw=False):
411
+ points = Render.get_cube_3d_points(size, rotx, roty, rotz, scale, cx, cy, char)
412
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
413
+
414
+ @staticmethod
415
+ def draw_pyramid_3d(size=5, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#', width=80, height=25, clear_before_draw=False):
416
+ points = Render.get_pyramid_3d_points(size, rotx, roty, rotz, scale, cx, cy, char)
417
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
418
+
419
+ @staticmethod
420
+ def draw_cylinder_3d(radius=5, height=10, segments=12, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#', width=80, clear_before_draw=False):
421
+ points = Render.get_cylinder_3d_points(radius, height, segments, rotx, roty, rotz, scale, cx, cy, char)
422
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
423
+
424
+ @staticmethod
425
+ def draw_sphere_3d(radius=5, segments=12, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#', width=80, height=25, clear_before_draw=False):
426
+ points = Render.get_sphere_3d_points(radius, segments, rotx, roty, rotz, scale, cx, cy, char)
427
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
428
+
429
+ @staticmethod
430
+ def draw_cone_3d(radius=5, height=10, segments=12, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#', width=80, clear_before_draw=False):
431
+ points = Render.get_cone_3d_points(radius, height, segments, rotx, roty, rotz, scale, cx, cy, char)
432
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
433
+
434
+ @staticmethod
435
+ def draw_torus_3d(radius=8, tube=3, segments=16, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#', width=80, height=25, clear_before_draw=False):
436
+ points = Render.get_torus_3d_points(radius, tube, segments, rotx, roty, rotz, scale, cx, cy, char)
437
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
438
+
439
+ @staticmethod
440
+ def draw_ico_sphere_3d(radius=5, rotx=0, roty=0, rotz=0, scale=10, cx=40, cy=12, char='#', width=80, height=25, clear_before_draw=False):
441
+ points = Render.get_ico_sphere_3d_points(radius, rotx, roty, rotz, scale, cx, cy, char)
442
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
443
+
444
+ @staticmethod
445
+ def draw_line(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
446
+ points = Render.get_line_points(x1, y1, x2, y2, char)
447
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
448
+
449
+ @staticmethod
450
+ def draw_circle(cx, cy, r, char='#', width=80, height=25, clear_before_draw=False):
451
+ points = Render.get_circle_points(cx, cy, r, char)
452
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
453
+
454
+ @staticmethod
455
+ def draw_filled_circle(cx, cy, r, char='#', width=80, height=25, clear_before_draw=False):
456
+ points = Render.get_filled_circle_points(cx, cy, r, char)
457
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
458
+
459
+ @staticmethod
460
+ def draw_rect(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
461
+ points = Render.get_rect_points(x1, y1, x2, y2, char)
462
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
463
+
464
+ @staticmethod
465
+ def fill_rect(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
466
+ points = Render.get_fill_rect_points(x1, y1, x2, y2, char)
467
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
468
+
469
+ @staticmethod
470
+ def draw_text(x, y, text, width=80, height=25, clear_before_draw=False):
471
+ points = Render.get_text_points(x, y, text)
472
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
473
+
474
+ @staticmethod
475
+ def draw_triangle(x1, y1, x2, y2, x3, y3, char='#', width=80, height=25, clear_before_draw=False):
476
+ points = Render.get_triangle_points(x1, y1, x2, y2, x3, y3, char)
477
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
478
+
479
+ @staticmethod
480
+ def fill_triangle(x1, y1, x2, y2, x3, y3, char='#', width=80, height=25, clear_before_draw=False):
481
+ points = Render.get_filled_triangle_points(x1, y1, x2, y2, x3, y3, char)
482
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
483
+
484
+ @staticmethod
485
+ def draw_heart(cx, cy, size=5, char='#', width=80, height=25, clear_before_draw=False):
486
+ points = Render.get_heart_points(cx, cy, size, char)
487
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
488
+
489
+ @staticmethod
490
+ def draw_star(cx, cy, radius=5, points_count=5, char='#', width=80, height=25, clear_before_draw=False):
491
+ points = Render.get_star_points(cx, cy, radius, points_count, char)
492
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
493
+
494
+ @staticmethod
495
+ def draw_bezier(x1, y1, x2, y2, x3, y3, steps=20, char='#', width=80, height=25, clear_before_draw=False):
496
+ points = Render.get_bezier_points(x1, y1, x2, y2, x3, y3, steps, char)
497
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
498
+
499
+ @staticmethod
500
+ def draw_wave(cx, cy, amplitude=5, length=20, char='~', width=80, height=25, clear_before_draw=False):
501
+ points = Render.get_wave_points(cx, cy, amplitude, length, char)
502
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
503
+
504
+ @staticmethod
505
+ def draw_spiral(cx, cy, turns=3, radius=10, step=0.1, char='*', width=80, height=25, clear_before_draw=False):
506
+ points = Render.get_spiral_points(cx, cy, turns, radius, step, char)
507
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
508
+
509
+ @staticmethod
510
+ def draw_grid(x1, y1, x2, y2, step=2, char='+', width=80, height=25, clear_before_draw=False):
511
+ points = Render.get_grid_points(x1, y1, x2, y2, step, char)
512
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
513
+
514
+ @staticmethod
515
+ def draw_noise(cx, cy, radius, count=50, char='.', width=80, height=25, clear_before_draw=False):
516
+ points = Render.get_noise_points(cx, cy, radius, count, char)
517
+ Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
518
+
519
+ class ConsoleInfo:
520
+ @staticmethod
521
+ def GetConsole():
522
+ return sys.stdout
523
+
524
+ @staticmethod
525
+ def GetPipVer():
526
+ try:
527
+ result = CMD.run(['python', '-m', 'pip', '--version'], capture_output=True, text=True, check=True)
528
+ return result.stdout.strip()
529
+ except CMD.CalledProcessError as e:
530
+ return f"Error: pip not found (code {e.returncode})"
531
+ except FileNotFoundError:
532
+ return "Error: Python not installed or not in PATH"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ConsoleLib
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: The library for easy and best control on the Console.
5
5
  Author-email: Suleiman <steal.apet@mail.ru>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ConsoleLib
3
- Version: 1.3.0
3
+ Version: 1.3.1
4
4
  Summary: The library for easy and best control on the Console.
5
5
  Author-email: Suleiman <steal.apet@mail.ru>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "ConsoleLib"
7
- version = "1.3.0"
7
+ version = "1.3.1"
8
8
  description = "The library for easy and best control on the Console."
9
9
  authors = [{name = "Suleiman", email = "steal.apet@mail.ru"}]
10
10
  readme = "README.md"
@@ -1,226 +0,0 @@
1
- """
2
- ConsoleLib - The best Console Renderer of the Python.
3
- By: Suleiman
4
- Copyright © Suleiman 2026
5
- All rights are reserved.
6
- """
7
- import os
8
- import sys
9
- import time
10
- import subprocess as CMD
11
- import math
12
- class Render:
13
- @staticmethod
14
- def DrawPic(points=None, width=80, height=25, clear_before_draw=False, default_char=' '):
15
- if clear_before_draw:
16
- os.system("cls" if os.name == "nt" else "clear")
17
- field = [[default_char for _ in range(width)] for _ in range(height)]
18
- if points:
19
- for item in points:
20
- if len(item) == 3:
21
- x, y, char = item
22
- if 0 <= x < width and 0 <= y < height:
23
- field[y][x] = char
24
- for row in field:
25
- print(''.join(row))
26
- @staticmethod
27
- def get_line_points(x1, y1, x2, y2, char='#'):
28
- points = []
29
- dx = abs(x2 - x1)
30
- dy = abs(y2 - y1)
31
- sx = 1 if x1 < x2 else -1
32
- sy = 1 if y1 < y2 else -1
33
- err = dx - dy
34
- while True:
35
- points.append((x1, y1, char))
36
- if x1 == x2 and y1 == y2:
37
- break
38
- e2 = err * 2
39
- if e2 > -dy:
40
- err -= dy
41
- x1 += sx
42
- if e2 < dx:
43
- err += dx
44
- y1 += sy
45
- return points
46
- @staticmethod
47
- def get_circle_points(cx, cy, r, char='#'):
48
- points = []
49
- for angle in range(0, 360, 5):
50
- rad = angle * math.pi / 180
51
- x = int(cx + r * math.cos(rad))
52
- y = int(cy + r * math.sin(rad))
53
- points.append((x, y, char))
54
- return points
55
- @staticmethod
56
- def get_filled_circle_points(cx, cy, r, char='#'):
57
- points = []
58
- for y in range(cy - r, cy + r + 1):
59
- for x in range(cx - r, cx + r + 1):
60
- if (x - cx) ** 2 + (y - cy) ** 2 <= r ** 2:
61
- points.append((x, y, char))
62
- return points
63
- @staticmethod
64
- def get_rect_points(x1, y1, x2, y2, char='#'):
65
- points = []
66
- for x in range(x1, x2 + 1):
67
- points.append((x, y1, char))
68
- points.append((x, y2, char))
69
- for y in range(y1, y2 + 1):
70
- points.append((x1, y, char))
71
- points.append((x2, y, char))
72
- return points
73
- @staticmethod
74
- def get_fill_rect_points(x1, y1, x2, y2, char='#'):
75
- points = []
76
- for y in range(y1, y2 + 1):
77
- for x in range(x1, x2 + 1):
78
- points.append((x, y, char))
79
- return points
80
- @staticmethod
81
- def get_text_points(x, y, text, char=None):
82
- points = []
83
- if char is None:
84
- for i, ch in enumerate(text):
85
- points.append((x + i, y, ch))
86
- else:
87
- for i in range(len(text)):
88
- points.append((x + i, y, char))
89
- return points
90
- @staticmethod
91
- def get_triangle_points(x1, y1, x2, y2, x3, y3, char='#'):
92
- points = []
93
- points.extend(Render.get_line_points(x1, y1, x2, y2, char))
94
- points.extend(Render.get_line_points(x2, y2, x3, y3, char))
95
- points.extend(Render.get_line_points(x3, y3, x1, y1, char))
96
- return points
97
- @staticmethod
98
- def get_filled_triangle_points(x1, y1, x2, y2, x3, y3, char='#'):
99
- points = []
100
- min_x = min(x1, x2, x3)
101
- max_x = max(x1, x2, x3)
102
- min_y = min(y1, y2, y3)
103
- max_y = max(y1, y2, y3)
104
- for y in range(min_y, max_y + 1):
105
- for x in range(min_x, max_x + 1):
106
- if Render._point_in_triangle(x, y, x1, y1, x2, y2, x3, y3):
107
- points.append((x, y, char))
108
- return points
109
- @staticmethod
110
- def get_heart_points(cx, cy, size=5, char='#'):
111
- points = []
112
- for y in range(-size, size + 1):
113
- for x in range(-size, size + 1):
114
- if ((x * x + y * y - size * size) ** 3 <= size * size * x * x * y * y * 0.5):
115
- points.append((cx + x, cy - y, char))
116
- return points
117
- @staticmethod
118
- def get_star_points(cx, cy, radius=5, points_count=5, char='*'):
119
- points = []
120
- angle = -math.pi / 2
121
- step = math.pi / points_count
122
- outer_points = []
123
- inner_points = []
124
- for i in range(points_count * 2):
125
- r = radius if i % 2 == 0 else radius * 0.4
126
- x = cx + r * math.cos(angle + i * step)
127
- y = cy + r * math.sin(angle + i * step)
128
- if i % 2 == 0:
129
- outer_points.append((x, y))
130
- else:
131
- inner_points.append((x, y))
132
- for i in range(points_count):
133
- p1 = outer_points[i]
134
- p2 = inner_points[i]
135
- p3 = outer_points[(i + 1) % points_count]
136
- points.extend(Render.get_line_points(int(p1[0]), int(p1[1]), int(p2[0]), int(p2[1]), char))
137
- points.extend(Render.get_line_points(int(p2[0]), int(p2[1]), int(p3[0]), int(p3[1]), char))
138
- return points
139
- @staticmethod
140
- def get_bezier_points(x1, y1, x2, y2, x3, y3, steps=20, char='#'):
141
- points = []
142
- for t in range(steps + 1):
143
- t = t / steps
144
- x = (1 - t) ** 2 * x1 + 2 * (1 - t) * t * x2 + t ** 2 * x3
145
- y = (1 - t) ** 2 * y1 + 2 * (1 - t) * t * y2 + t ** 2 * y3
146
- points.append((int(x), int(y), char))
147
- return points
148
- @staticmethod
149
- def get_wave_points(cx, cy, amplitude=5, length=20, char='~'):
150
- points = []
151
- for x in range(length):
152
- y = cy + int(amplitude * math.sin(x * 0.5))
153
- points.append((cx + x, y, char))
154
- return points
155
- @staticmethod
156
- def _point_in_triangle(px, py, x1, y1, x2, y2, x3, y3):
157
- def sign(a, b, c):
158
- return (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1])
159
- p = (px, py)
160
- d1 = sign(p, (x2, y2), (x1, y1))
161
- d2 = sign(p, (x3, y3), (x2, y2))
162
- d3 = sign(p, (x1, y1), (x3, y3))
163
- has_neg = (d1 < 0) or (d2 < 0) or (d3 < 0)
164
- has_pos = (d1 > 0) or (d2 > 0) or (d3 > 0)
165
- return not (has_neg and has_pos)
166
- @staticmethod
167
- def draw_line(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
168
- points = Render.get_line_points(x1, y1, x2, y2, char)
169
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
170
- @staticmethod
171
- def draw_circle(cx, cy, r, char='#', width=80, height=25, clear_before_draw=False):
172
- points = Render.get_circle_points(cx, cy, r, char)
173
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
174
- @staticmethod
175
- def draw_filled_circle(cx, cy, r, char='#', width=80, height=25, clear_before_draw=False):
176
- points = Render.get_filled_circle_points(cx, cy, r, char)
177
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
178
- @staticmethod
179
- def draw_rect(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
180
- points = Render.get_rect_points(x1, y1, x2, y2, char)
181
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
182
- @staticmethod
183
- def fill_rect(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
184
- points = Render.get_fill_rect_points(x1, y1, x2, y2, char)
185
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
186
- @staticmethod
187
- def draw_text(x, y, text, width=80, height=25, clear_before_draw=False):
188
- points = Render.get_text_points(x, y, text)
189
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
190
- @staticmethod
191
- def draw_triangle(x1, y1, x2, y2, x3, y3, char='#', width=80, height=25, clear_before_draw=False):
192
- points = Render.get_triangle_points(x1, y1, x2, y2, x3, y3, char)
193
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
194
- @staticmethod
195
- def fill_triangle(x1, y1, x2, y2, x3, y3, char='#', width=80, height=25, clear_before_draw=False):
196
- points = Render.get_filled_triangle_points(x1, y1, x2, y2, x3, y3, char)
197
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
198
- @staticmethod
199
- def draw_heart(cx, cy, size=5, char='#', width=80, height=25, clear_before_draw=False):
200
- points = Render.get_heart_points(cx, cy, size, char)
201
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
202
- @staticmethod
203
- def draw_star(cx, cy, radius=5, points_count=5, char='#', width=80, height=25, clear_before_draw=False):
204
- points = Render.get_star_points(cx, cy, radius, points_count, char)
205
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
206
- @staticmethod
207
- def draw_bezier(x1, y1, x2, y2, x3, y3, steps=20, char='#', width=80, height=25, clear_before_draw=False):
208
- points = Render.get_bezier_points(x1, y1, x2, y2, x3, y3, steps, char)
209
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
210
- @staticmethod
211
- def draw_wave(cx, cy, amplitude=5, length=20, char='~', width=80, height=25, clear_before_draw=False):
212
- points = Render.get_wave_points(cx, cy, amplitude, length, char)
213
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
214
- class ConsoleInfo:
215
- @staticmethod
216
- def GetConsole():
217
- return sys.stdout
218
- @staticmethod
219
- def GetPipVer():
220
- try:
221
- result = CMD.run(['python', '-m', 'pip', '--version'], capture_output=True, text=True, check=True)
222
- return result.stdout.strip()
223
- except CMD.CalledProcessError as e:
224
- return f"Error: pip not found (code {e.returncode})"
225
- except FileNotFoundError:
226
- return "Error: Python not installed or not in PATH"
File without changes
File without changes