Skip to content

Commit bfb7347

Browse files
authored
v9.3 MORE CONSOLES MOREEEEEEE!!!!!!!
1 parent 3aff7b5 commit bfb7347

20 files changed

Lines changed: 763 additions & 237 deletions

Engine/Color.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ class Color:
55
underline = "\33[4m"
66
negative = "\33[7m"
77

8-
def rgbBackground(r, g, b):
9-
"""Возвращает символ-код установки цвета фона\nПринимает: (int) r - красная составляющая, (int) g - зеленая составляющая, (int) b - синяя составляющая\nВозвращает: (string) - цвет код для консоли"""
8+
def rgb_background(r:int=0, g:int=0, b:int=0) -> str:
9+
"""Возвращает символ-код установки цвета фона"""
1010
return f"\33[48;2;{r};{g};{b}m"
1111

12-
def rgbText(r, g, b):
13-
"""Возвращает символ-код установки цвета основного текста\nПринимает: (int) r - красная составляющая, (int) g - зеленая составляющая, (int) b - синяя составляющая\nВозвращает: (string) - цвет код для консоли"""
12+
def rgb_text(r:int=0, g:int=0, b:int=0) -> str:
13+
"""Возвращает символ-код установки цвета основного текста"""
1414
return f"\33[38;2;{r};{g};{b}m"

Engine/Console.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import ctypes
2+
import sys
3+
import os
4+
import ctypes.wintypes
5+
import threading
6+
import time
7+
import win32file
8+
import win32pipe
9+
import random
10+
import json
11+
12+
class CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
13+
_fields_ = [
14+
("dwSize", ctypes.wintypes._COORD),
15+
("dwCursorPosition", ctypes.wintypes._COORD),
16+
("wAttributes", ctypes.wintypes.WORD),
17+
("srWindow", ctypes.wintypes.SMALL_RECT),
18+
("dwMaximumWindowSize", ctypes.wintypes._COORD),
19+
]
20+
21+
class Console:
22+
def __init__(self):
23+
self.id = random.randint(1000, 9999)
24+
self.pipe_out_name = r"\\.\pipe\consoleout" + str(self.id)
25+
self.pipe_in_name = r"\\.\pipe\consolein" + str(self.id)
26+
self.enable = False
27+
28+
self.pipe_in = win32pipe.CreateNamedPipe(
29+
self.pipe_in_name,
30+
win32pipe.PIPE_ACCESS_DUPLEX,
31+
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT,
32+
1,
33+
65536,
34+
65536,
35+
0,
36+
None
37+
)
38+
39+
threading.Thread(target=os.system, args=[f"start py ./engine/sub_console.py {self.id}"], daemon=False).start()
40+
time.sleep(1)
41+
42+
try:
43+
self.pipe_out = win32file.CreateFile(
44+
self.pipe_out_name,
45+
win32file.GENERIC_READ | win32file.GENERIC_WRITE,
46+
0, None,
47+
win32file.OPEN_EXISTING,
48+
0, None
49+
)
50+
self.enable = True
51+
except:
52+
print(f"[ERROR][Console] Не удалось соединится с консолью")
53+
self.pipe_out = None
54+
self.enable = False
55+
56+
def _send_(self, data):
57+
if not self.enable: return
58+
try:
59+
win32file.WriteFile(self.pipe_out, data)
60+
except:
61+
self.enable = False
62+
63+
64+
def input_init(self):
65+
request = (8).to_bytes(1, "little")
66+
self._send_(request)
67+
68+
def input_tick(self):
69+
request = (7).to_bytes(1, "little")
70+
self._send_(request)
71+
res = win32file.ReadFile(self.pipe_in, 4096)
72+
return json.loads(res[1][1:].decode())
73+
74+
def print(self, data):
75+
request = ((2).to_bytes(1, "little")) + data.encode()
76+
self._send_(request)
77+
78+
def set_size(self, w:int, h:int):
79+
if w > 255 or h > 255: return
80+
request = ((5).to_bytes(1, "little")) + ((w).to_bytes(1, "little")) + ((h).to_bytes(1, "little"))
81+
self._send_(request)
82+
time.sleep(1)
83+
84+
def set_title(self, title:str):
85+
request = ((3).to_bytes(1, "little")) + title.encode()
86+
self._send_(request)
87+
time.sleep(0.01)
88+
89+
def set_icon(self, path:str):
90+
request = ((4).to_bytes(1, "little")) + path.encode()
91+
self._send_(request)
92+
93+
def close(self):
94+
if not self.enable: return
95+
request = (1).to_bytes(1, "little")
96+
self._send_(request)
97+
self.enable = False
98+
99+
def get_size(self):
100+
request = ((6).to_bytes(1, "little"))
101+
self._send_(request)
102+
time.sleep(1)
103+
res = win32file.ReadFile(self.pipe_in, 4096)
104+
if int(res[1][0]) == 1:
105+
return (int(res[1][1]), int(res[1][2]))
106+
else:
107+
return (0, 0)
108+
109+
def __del__(self):
110+
self.close()
111+
112+
class Root_Console:
113+
def __init__(self):
114+
...
115+
116+
def print(self, data:str):
117+
print(data, end="")
118+
119+
def set_title(self, title:str):
120+
ctypes.windll.kernel32.SetConsoleTitleW(title)
121+
122+
def set_size(self, w:int, h:int):
123+
os.system(f'mode con cols={w} lines={h}')
124+
125+
def set_icon(self, path:str):
126+
hwnd = ctypes.windll.kernel32.GetConsoleWindow()
127+
icon_handle = ctypes.windll.user32.LoadImageW(None, path, 1, 0, 0, 16)
128+
ctypes.windll.user32.SendMessageW(hwnd, 0x80, 0, icon_handle)
129+
130+
def get_size(self):
131+
csbi = CONSOLE_SCREEN_BUFFER_INFO()
132+
ctypes.windll.kernel32.GetConsoleScreenBufferInfo(ctypes.windll.kernel32.GetStdHandle(-11), ctypes.byref(csbi))
133+
134+
width = csbi.srWindow.Right - csbi.srWindow.Left + 1
135+
height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1
136+
return (width, height)
137+
138+
def set_size(self, w:int, h:int):
139+
if w > 255 or h > 255: return
140+
os.system(f'mode con cols={w} lines={h-1}')
141+
142+
def close(self):
143+
...

Engine/GUIBorder.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from Engine.GUIStyle import Style
2+
3+
class Border:
4+
"""[GUI] Рамка для изображения"""
5+
6+
def __init__(self, screen, style, symbol="*"):
7+
"""Конструктор\nПринимает: (Window) screen - окно в котором необдимо рисовать, (Style) style - стиль, (string) symbol - символ"""
8+
self.screen = screen
9+
self.style = style
10+
self.symbol = symbol
11+
12+
def draw(self):
13+
"""Отрисовка"""
14+
self.screen.rect(0, 0, self.screen.w, self.screen.h, self.style["text"] + self.style["background"] + self.symbol)

Engine/GUIButton.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from Engine.GUIElement import Element
2+
3+
class Button(Element):
4+
"""[GUI] Кнопка"""
5+
6+
def draw(self):
7+
"""Отрисовка"""
8+
text = f"[ {self.text} ]"
9+
self.intersectionLen = len(text)
10+
11+
if self.enable:
12+
if self.focused:
13+
self.screen.text(text, self.x, self.y, wordPrefix=self.style["backgroundF"] + self.style["textF"])
14+
else:
15+
self.screen.text(text, self.x, self.y, wordPrefix=self.style["background"] + self.style["text"])
16+
else:
17+
self.screen.text(text, self.x, self.y, wordPrefix=self.style["disable"] + self.style["text"])

Engine/GUICheckbox.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from Engine.GUIElement import Element
2+
3+
class Checkbox(Element):
4+
"""[GUI] Переключатель"""
5+
6+
def __init__(self, screen, style, x=0, y=0, text="", enable=True, checked=False):
7+
"""Коснтруктор\nПринимает: (Window) screen - окно в котором необходимо рисовать, (Style) style - стиль, (int) x - коорината x, (int) y - координата y, (string) text - текст, (bool) enable - состояние, (bool) checked - отмечен ли чекбокс"""
8+
super().__init__(screen, style, x, y, text, enable)
9+
self.checked = checked
10+
11+
def __bool__(self):
12+
"""Возвращает состояние переключателя\nВозвращает: (bool) - отмечена ли чекбокс"""
13+
return self.checked
14+
15+
def click(self, obj):
16+
"""Событие нажатия\nПринимает: (object) obj - инициатор события"""
17+
self.checked = not(self.checked)
18+
self.change(self)
19+
20+
def draw(self):
21+
"""Отрисовка"""
22+
text = ("[X] " if self.checked else "[ ] ") + self.text
23+
self.intersectionLen = len(text)
24+
25+
if self.enable:
26+
if self.focused:
27+
self.screen.text(text, self.x, self.y, wordPrefix=self.style["backgroundF"] + self.style["textF"])
28+
else:
29+
self.screen.text(text, self.x, self.y, wordPrefix=self.style["background"] + self.style["text"])
30+
else:
31+
self.screen.text(text, self.x, self.y, wordPrefix=self.style["disable"] + self.style["text"])

Engine/GUIElement.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
from Engine.Input import Input
2+
from Engine.GUIEvents import Events
3+
4+
class Element(Events):
5+
"""[GUI] База для GUI элементов"""
6+
7+
def __init__(self, screen=None, style=None, x=0, y=0, text="", enable=True, visible=True, root=None):
8+
"""Коснтруктор\nПринимает: (Window) screen - окно в котором необходимо рисовать, (Style) style - стиль, (int) x - коорината x, (int) y - координата y, (string) text - текст, (bool) enable - состояние, (bool) visible - отрисовывать ли элемент"""
9+
self.screen = screen
10+
self.style = style
11+
self.x = x
12+
self.y = y
13+
self.text = text
14+
self.root = root
15+
self.focused = False
16+
self.intersectionLen = len(text)
17+
self.enable = enable
18+
self.visible = visible
19+
20+
def block(self):
21+
"""Блокировка элемента"""
22+
self.focused = False
23+
self.enable = False
24+
25+
def intersectionFromEvent(self):
26+
"""Проверка на пересечение с мышью из события\n(Event) - событие"""
27+
if self.enable:
28+
if Input.eventType == Input.Types.Mouse:
29+
if Input.mouseType == Input.Mouse.MOVE:
30+
self.intersection(Input.mouseX, Input.mouseY)
31+
32+
def intersection(self, x, y):
33+
"""Проверка на пересечение по координатам\nПринимает: (int) x - координата x, (int) y - координата y"""
34+
if self.enable:
35+
if (self.x <= x < self.x + self.intersectionLen) and (self.y == y):
36+
self.focused = True
37+
self.focus(self)
38+
else:
39+
self.focused = False

Engine/GUIEvents.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
class Events:
2+
"""[GUI] Шаблоны событий для GUI элементов"""
3+
4+
def click(self, obj):
5+
"""Нажатие\nПринимает: (object) obj - инициатор события"""
6+
pass
7+
8+
def change(self, obj):
9+
"""Изменение состояние\nПринимает: (object) obj - инициатор события"""
10+
pass
11+
12+
def focus(self, obj):
13+
"""Наведение мышью на элемент\nПринимает: (object) obj - инициатор события"""
14+
pass
15+
16+
def select(self, obj):
17+
"""Выбор элемента\nПринимает: (object) obj - инициатор события"""
18+
pass

Engine/GUIFrame.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class Frame:
2+
"""[GUI] Фона"""
3+
4+
def __init__(self):
5+
"""[GUI] Фон """
6+
self.root = None
7+
self.style = None
8+
9+
def draw(self):
10+
"""Отрисовка"""
11+
self.screen.fill(self.style["background"] + " ")

Engine/GUIGrid.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
3+
class Grid:
4+
"""[GUI] Визуальная сетка"""
5+
6+
def __init__(self, screen, x, y, w, h, columns, strings, style):
7+
"""Коструктор\nПринимает: (Window) screen - окно для отрисовки, (int) x - координата x, (int) y - координата y, (int) w - ширина, (int) h - высота, (int) columns - кол-во столбцов, (int) strings - кол-во строк, (Style) style - стиль"""
8+
self.screen = screen
9+
self.w = w
10+
self.h = h
11+
self.x = x
12+
self.y = y
13+
self.columns = columns
14+
self.strings = strings
15+
self.style = style
16+
17+
self.cellW = (w - (columns - 1)) // columns
18+
self.cellH = (h - (strings - 1)) // strings
19+
20+
def intersection(self, x, y):
21+
"""Вовзращает координаты в сетке\nПринимает: (int) x - координата x, (int) y - координата y\nВозвращает: (tuple_int) - координаты ячейки по которой нажали"""
22+
x1 = x // self.cellW
23+
y1 = y // self.cellH
24+
return (x1, y1)
25+
26+
def draw(self):
27+
"""Отрисовка"""
28+
for i in range(1, self.columns):
29+
self.screen.line(self.x + i * self.cellW, self.y, self.x + i * self.cellW, self.y + self.h, self.style["background"] + self.style["text"] + "|")
30+
31+
for i in range(1, self.strings):
32+
self.screen.line(self.x, self.y + i * self.cellH, self.x + self.w, self.y + i * self.cellH, self.style["background"] + self.style["text"] + "-")

Engine/GUIGroup.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from Engine.Logging import Logging
2+
3+
class Group:
4+
"""[GUI] Группа GUI элементов"""
5+
6+
def __init__(self, screen, x, y, interval=1, maxElements=10):
7+
"""Конструктор\nПринимает: (Winow) screen - окно для отрисовки, (int) x - кооридната x, (int) y - координата y, (int) interval - интервал между элементами, (int) maxElements - максимальное кол-во элеметов для отрисовки"""
8+
self.screen = screen
9+
self.x = x
10+
self.y = y
11+
self.elements = []
12+
self.interval = interval
13+
self.selected = {}
14+
self.maxElements = maxElements
15+
16+
def append(self, element):
17+
"""Добавление элементов в группу\nПринимает: (Element or any [GUI]) element - элемент для добавления в группу"""
18+
self.elements.append(element)
19+
20+
def eventHandler(self):
21+
"""Обработка событий для всех элементов в группе\nПринимает: (Event) - событие"""
22+
for element in self.elements:
23+
element.intersectionFromEvent()
24+
25+
if hasattr(element, "inputFromEvent"):
26+
element.inputFromEvent()
27+
28+
def click(self):
29+
"""Обработка событий для всех элементов в группе"""
30+
for element in self.elements:
31+
if element.focused:
32+
element.click(element)
33+
34+
def sort(self):
35+
"""Автопозиционирование элементов группы"""
36+
for i in range(len(self.elements)):
37+
element = self.elements[i]
38+
element.x = self.x
39+
element.y = self.y + i * (self.interval + 1)
40+
41+
def draw(self):
42+
"""Отрисовка всех элементов группы"""
43+
for i in range(min(len(self.elements), self.maxElements)):
44+
self.elements[i].draw()

0 commit comments

Comments
 (0)