ConsoleLib 1.2.2__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.2.2
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.2.2
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.2.2"
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,223 +0,0 @@
1
- # ConsoleLib - The best Console Renderer of the Python
2
- # By: Suleiman
3
- # Copyright © Suleiman 2026
4
- import os
5
- import sys
6
- import time
7
- import subprocess as CMD
8
- import math
9
- class Render:
10
- @staticmethod
11
- def DrawPic(points=None, width=80, height=25, clear_before_draw=False, default_char=' '):
12
- if clear_before_draw:
13
- os.system("cls" if os.name == "nt" else "clear")
14
- field = [[default_char for _ in range(width)] for _ in range(height)]
15
- if points:
16
- for item in points:
17
- if len(item) == 3:
18
- x, y, char = item
19
- if 0 <= x < width and 0 <= y < height:
20
- field[y][x] = char
21
- for row in field:
22
- print(''.join(row))
23
- @staticmethod
24
- def get_line_points(x1, y1, x2, y2, char='#'):
25
- points = []
26
- dx = abs(x2 - x1)
27
- dy = abs(y2 - y1)
28
- sx = 1 if x1 < x2 else -1
29
- sy = 1 if y1 < y2 else -1
30
- err = dx - dy
31
- while True:
32
- points.append((x1, y1, char))
33
- if x1 == x2 and y1 == y2:
34
- break
35
- e2 = err * 2
36
- if e2 > -dy:
37
- err -= dy
38
- x1 += sx
39
- if e2 < dx:
40
- err += dx
41
- y1 += sy
42
- return points
43
- @staticmethod
44
- def get_circle_points(cx, cy, r, char='#'):
45
- points = []
46
- for angle in range(0, 360, 5):
47
- rad = angle * math.pi / 180
48
- x = int(cx + r * math.cos(rad))
49
- y = int(cy + r * math.sin(rad))
50
- points.append((x, y, char))
51
- return points
52
- @staticmethod
53
- def get_filled_circle_points(cx, cy, r, char='#'):
54
- points = []
55
- for y in range(cy - r, cy + r + 1):
56
- for x in range(cx - r, cx + r + 1):
57
- if (x - cx) ** 2 + (y - cy) ** 2 <= r ** 2:
58
- points.append((x, y, char))
59
- return points
60
- @staticmethod
61
- def get_rect_points(x1, y1, x2, y2, char='#'):
62
- points = []
63
- for x in range(x1, x2 + 1):
64
- points.append((x, y1, char))
65
- points.append((x, y2, char))
66
- for y in range(y1, y2 + 1):
67
- points.append((x1, y, char))
68
- points.append((x2, y, char))
69
- return points
70
- @staticmethod
71
- def get_fill_rect_points(x1, y1, x2, y2, char='#'):
72
- points = []
73
- for y in range(y1, y2 + 1):
74
- for x in range(x1, x2 + 1):
75
- points.append((x, y, char))
76
- return points
77
- @staticmethod
78
- def get_text_points(x, y, text, char=None):
79
- points = []
80
- if char is None:
81
- for i, ch in enumerate(text):
82
- points.append((x + i, y, ch))
83
- else:
84
- for i in range(len(text)):
85
- points.append((x + i, y, char))
86
- return points
87
- @staticmethod
88
- def get_triangle_points(x1, y1, x2, y2, x3, y3, char='#'):
89
- points = []
90
- points.extend(Render.get_line_points(x1, y1, x2, y2, char))
91
- points.extend(Render.get_line_points(x2, y2, x3, y3, char))
92
- points.extend(Render.get_line_points(x3, y3, x1, y1, char))
93
- return points
94
- @staticmethod
95
- def get_filled_triangle_points(x1, y1, x2, y2, x3, y3, char='#'):
96
- points = []
97
- min_x = min(x1, x2, x3)
98
- max_x = max(x1, x2, x3)
99
- min_y = min(y1, y2, y3)
100
- max_y = max(y1, y2, y3)
101
- for y in range(min_y, max_y + 1):
102
- for x in range(min_x, max_x + 1):
103
- if Render._point_in_triangle(x, y, x1, y1, x2, y2, x3, y3):
104
- points.append((x, y, char))
105
- return points
106
- @staticmethod
107
- def get_heart_points(cx, cy, size=5, char='#'):
108
- points = []
109
- for y in range(-size, size + 1):
110
- for x in range(-size, size + 1):
111
- if ((x * x + y * y - size * size) ** 3 <= size * size * x * x * y * y * 0.5):
112
- points.append((cx + x, cy - y, char))
113
- return points
114
- @staticmethod
115
- def get_star_points(cx, cy, radius=5, points_count=5, char='*'):
116
- points = []
117
- angle = -math.pi / 2
118
- step = math.pi / points_count
119
- outer_points = []
120
- inner_points = []
121
- for i in range(points_count * 2):
122
- r = radius if i % 2 == 0 else radius * 0.4
123
- x = cx + r * math.cos(angle + i * step)
124
- y = cy + r * math.sin(angle + i * step)
125
- if i % 2 == 0:
126
- outer_points.append((x, y))
127
- else:
128
- inner_points.append((x, y))
129
- for i in range(points_count):
130
- p1 = outer_points[i]
131
- p2 = inner_points[i]
132
- p3 = outer_points[(i + 1) % points_count]
133
- points.extend(Render.get_line_points(int(p1[0]), int(p1[1]), int(p2[0]), int(p2[1]), char))
134
- points.extend(Render.get_line_points(int(p2[0]), int(p2[1]), int(p3[0]), int(p3[1]), char))
135
- return points
136
- @staticmethod
137
- def get_bezier_points(x1, y1, x2, y2, x3, y3, steps=20, char='#'):
138
- points = []
139
- for t in range(steps + 1):
140
- t = t / steps
141
- x = (1 - t) ** 2 * x1 + 2 * (1 - t) * t * x2 + t ** 2 * x3
142
- y = (1 - t) ** 2 * y1 + 2 * (1 - t) * t * y2 + t ** 2 * y3
143
- points.append((int(x), int(y), char))
144
- return points
145
- @staticmethod
146
- def get_wave_points(cx, cy, amplitude=5, length=20, char='~'):
147
- points = []
148
- for x in range(length):
149
- y = cy + int(amplitude * math.sin(x * 0.5))
150
- points.append((cx + x, y, char))
151
- return points
152
- @staticmethod
153
- def _point_in_triangle(px, py, x1, y1, x2, y2, x3, y3):
154
- def sign(a, b, c):
155
- return (a[0] - c[0]) * (b[1] - c[1]) - (b[0] - c[0]) * (a[1] - c[1])
156
- p = (px, py)
157
- d1 = sign(p, (x2, y2), (x1, y1))
158
- d2 = sign(p, (x3, y3), (x2, y2))
159
- d3 = sign(p, (x1, y1), (x3, y3))
160
- has_neg = (d1 < 0) or (d2 < 0) or (d3 < 0)
161
- has_pos = (d1 > 0) or (d2 > 0) or (d3 > 0)
162
- return not (has_neg and has_pos)
163
- @staticmethod
164
- def draw_line(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
165
- points = Render.get_line_points(x1, y1, x2, y2, char)
166
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
167
- @staticmethod
168
- def draw_circle(cx, cy, r, char='#', width=80, height=25, clear_before_draw=False):
169
- points = Render.get_circle_points(cx, cy, r, char)
170
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
171
- @staticmethod
172
- def draw_filled_circle(cx, cy, r, char='#', width=80, height=25, clear_before_draw=False):
173
- points = Render.get_filled_circle_points(cx, cy, r, char)
174
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
175
- @staticmethod
176
- def draw_rect(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
177
- points = Render.get_rect_points(x1, y1, x2, y2, char)
178
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
179
- @staticmethod
180
- def fill_rect(x1, y1, x2, y2, char='#', width=80, height=25, clear_before_draw=False):
181
- points = Render.get_fill_rect_points(x1, y1, x2, y2, char)
182
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
183
- @staticmethod
184
- def draw_text(x, y, text, width=80, height=25, clear_before_draw=False):
185
- points = Render.get_text_points(x, y, text)
186
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
187
- @staticmethod
188
- def draw_triangle(x1, y1, x2, y2, x3, y3, char='#', width=80, height=25, clear_before_draw=False):
189
- points = Render.get_triangle_points(x1, y1, x2, y2, x3, y3, char)
190
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
191
- @staticmethod
192
- def fill_triangle(x1, y1, x2, y2, x3, y3, char='#', width=80, height=25, clear_before_draw=False):
193
- points = Render.get_filled_triangle_points(x1, y1, x2, y2, x3, y3, char)
194
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
195
- @staticmethod
196
- def draw_heart(cx, cy, size=5, char='#', width=80, height=25, clear_before_draw=False):
197
- points = Render.get_heart_points(cx, cy, size, char)
198
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
199
- @staticmethod
200
- def draw_star(cx, cy, radius=5, points_count=5, char='#', width=80, height=25, clear_before_draw=False):
201
- points = Render.get_star_points(cx, cy, radius, points_count, char)
202
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
203
- @staticmethod
204
- def draw_bezier(x1, y1, x2, y2, x3, y3, steps=20, char='#', width=80, height=25, clear_before_draw=False):
205
- points = Render.get_bezier_points(x1, y1, x2, y2, x3, y3, steps, char)
206
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
207
- @staticmethod
208
- def draw_wave(cx, cy, amplitude=5, length=20, char='~', width=80, height=25, clear_before_draw=False):
209
- points = Render.get_wave_points(cx, cy, amplitude, length, char)
210
- Render.DrawPic(points=points, width=width, height=height, clear_before_draw=clear_before_draw)
211
- class ConsoleInfo:
212
- @staticmethod
213
- def GetConsole():
214
- return sys.stdout
215
- @staticmethod
216
- def GetPipVer():
217
- try:
218
- result = CMD.run(['python', '-m', 'pip', '--version'], capture_output=True, text=True, check=True)
219
- return result.stdout.strip()
220
- except CMD.CalledProcessError as e:
221
- return f"Error: pip not found (code {e.returncode})"
222
- except FileNotFoundError:
223
- return "Error: Python not installed or not in PATH"
File without changes
File without changes