refactorization

This commit is contained in:
MeexReay 2025-09-20 15:56:18 +03:00
parent ceaf3d455a
commit c0731d3b2a
71 changed files with 218 additions and 1950 deletions

16
src/pygwin2/__init__.py Normal file
View file

@ -0,0 +1,16 @@
from pygwin.surface import surface
import pygwin.keyboard as keyboard
from pygwin.console import console
from pygwin.color import color
import pygwin.gamepad as _gp
import pygwin.mouse as mouse
from pygwin.rect import rect
import pygwin.image as image
import pygwin.mixer as mixer
from pygwin.tray import tray
from pygame.locals import *
import pygwin.font as font
from pygwin._win import *
from pygwin._pg import pg
import pygwin.ui as ui
gamepad = _gp.gamepad(pg)

16
src/pygwin2/_pg.py Normal file
View file

@ -0,0 +1,16 @@
from contextlib import contextmanager as _cm
import os as _os
import sys as _sys
@_cm
def _suppress_stdout():
with open(_os.devnull, "w") as devnull:
old_stdout = _sys.stdout
_sys.stdout = devnull
try:
yield
finally:
_sys.stdout = old_stdout
with _suppress_stdout():
import pygame as pg
pg.init()

231
src/pygwin2/_win.py Normal file
View file

@ -0,0 +1,231 @@
from pygwin.surface import surface as _surface
from pygwin.tray import tray as _tray
from datetime import datetime as _dt
from pygwin.image import save as _s
from pygwin._pg import pg as _pg
import pygwin.image as _img
try:
import win32job as _w32j
import win32api as _w32a
import win32con as _w32c
import win32gui as _w32g
nonwin32api = False
except:
nonwin32api = True
import sys as _sys
import warnings as _warn
import winerror as _we
import requests as _req
import tempfile as _tf
import threading as _t
import pickle as _p
import mouse as _m
import time as _ti
class _win(_surface):
def __init__(self, iconpath=None):
self._orig = _pg.display.get_surface()
super().__init__(self._orig.get_size())
self._orig = _pg.display.get_surface()
self._clock = _pg.time.Clock()
self._withfps = False
self._iconpath = iconpath
self._isallowdrag = False
# self._issmartdrag = False
if iconpath != None:
self.tray = _tray(self.title,iconpath)
def update(self, fps=-1):
if fps != -1:
self._clock.tick(fps)
self._withfps = True
_pg.display.update()
def resize(self, size=None):
if size == None:
return self.size
else:
self._orig = _pg.display.set_mode(size)
def title():
def fget(self):
return _pg.display.get_caption()[0]
def fset(self, value):
if type(value) != str:
return
_pg.display.set_caption(value)
def fdel(self):
pass
return locals()
title = property(**title())
def icon(value):
_pg.display.set_icon(_pg.image.load(value))
self._iconpath = iconpath
def size():
def fget(self):
return _pg.display.get_window_size()
def fset(self, value):
if type(value) in [list,tuple]:
return
_pg.display.set_mode(value)
def fdel(self):
pass
return locals()
size = property(**size())
def fullscreen(self):
_pg.display.toogle_fullscreen()
def close(self):
# _w32g.PostMessage(self.hwnd, _w32c.WM_CLOSE, 0, 0)
_pg.display.quit()
try:self.tray.stop()
except:pass
def focus(self):
if not nonwin32api:
self.hide()
self.show()
_w32g.BringWindowToTop(self.hwnd)
_w32g.ShowWindow(self.hwnd, _w32c.SW_SHOWNORMAL)
_w32g.SetForegroundWindow(self.hwnd)
def hide(self):
if not nonwin32api:
_w32g.ShowWindow(self.hwnd, _w32c.SW_HIDE)
def show(self):
if not nonwin32api:
_w32g.ShowWindow(self.hwnd, _w32c.SW_SHOW)
def move(self, x, y):
if not nonwin32api:
rect = self._getRect()
_w32g.MoveWindow(self.hwnd, int(x), int(y),
rect[2]-x, rect[3]-y, 0)
def screenshot(self, path):
_s(self._orig, path)
return path
def center(self,x=_pg.display.get_desktop_sizes()[0][0]/2,
y=_pg.display.get_desktop_sizes()[0][1]/2):
self.move(x-self.size[0]/2,y-self.size[1]/2)
def _getRect(self):
if not nonwin32api:
return _w32g.GetWindowRect(self.hwnd)
def denyDrag(self):
if not nonwin32api:
self._isallowdrag = True
def loop(self):
while self._isallowdrag:
pos = _m.get_position()
pos = [pos[i]-self.position[i] for i in range(2)]
if pos[0] < self._getRect()[2]-137:
if pos[1] < 30:
_m.release('left')
_t.Thread(target=lambda:loop(self),daemon=1).start()
def allowDrag(self):
if not nonwin32api:
self._isallowdrag = False
# def smartDrag(self, x):
# self.allowDrag()
# self._issmartdrag = x
# if x:
# self._isallowdrag = True
# def loop(self):
# wsd = None
# while self._issmartdrag:
# self.update()
# pos = _m.get_position()
# pos = [pos[i]-self.position[i] for i in range(2)]
# if pos[0] < _w32g.GetWindowRect(self.hwnd)[2]-137:
# if pos[1] < 30:
# if _m.is_pressed('left'):
# _m.release('left')
# if wsd == None:
# wsd = pos+list(self.position)
# else:
# if wsd != pos+list(self.position):
# self.move(wsd[2]+(pos[0]-wsd[0]),
# wsd[3]+(pos[1]-wsd[1]))
# else:
# wsd = None
# _ti.sleep(0.5)
# _t.Thread(target=lambda:loop(self),daemon=1).start()
@property
def position(self):
if not nonwin32api:
rect = self._getRect()
x = rect[0]
y = rect[1]
return (x, y)
@property
def rawFps(self):
if self._withfps:
return self._clock.get_fps()
else:
return float(f'2010.{_dt.now().year}')
@property
def fps(self):
return int(self.rawFps)
@property
def hwnd(self):
if not nonwin32api:
return _pg.display.get_wm_info()['window']
@property
def visible(self):
if not nonwin32api:
return _w32g.IsWindowVisible(self._win)
def create(title=None, size=(0,0), icon=None, resizable=False, noframe=False):
screen = _pg.display.set_mode(size)
if resizable:
screen = _pg.display.set_mode(size,_pg.RESIZABLE)
if noframe:
screen = _pg.display.set_mode(size,_pg.NOFRAME)
else:
if title != None:
_pg.display.set_caption(title)
if icon != None:
_pg.display.set_icon(_pg.image.load(icon))
return _win(icon)
def ramLimit(memory_limit):
if not nonwin32api:
g_hjob = None
def create_job(job_name='', breakaway='silent'):
hjob = _w32j.CreateJobObject(None, job_name)
if breakaway:
info = _w32j.QueryInformationJobObject(hjob,
_w32j.JobObjectExtendedLimitInformation)
if breakaway == 'silent':
info['BasicLimitInformation']['LimitFlags'] |= (
_w32j.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)
else:
info['BasicLimitInformation']['LimitFlags'] |= (
_w32j.JOB_OBJECT_LIMIT_BREAKAWAY_OK)
_w32j.SetInformationJobObject(hjob,
_w32j.JobObjectExtendedLimitInformation, info)
return hjob
def assign_job(hjob):
global g_hjob
hprocess = _w32a.GetCurrentProcess()
try:
_w32j.AssignProcessToJobObject(hjob, hprocess)
g_hjob = hjob
except _w32j.error as e:
if (e._we != _we.ERROR_ACCESS_DENIED or
_sys.getwindowsversion() >= (6, 2) or
not _w32j.IsProcessInJob(hprocess, None)):
raise
_warn.warn('The process is already in a job. Nested jobs are not '
'supported prior to Windows 8.')
def limit_memory(memory_limit):
if g_hjob is None:
return
info = _w32j.QueryInformationJobObject(g_hjob,
_w32j.JobObjectExtendedLimitInformation)
info['ProcessMemoryLimit'] = memory_limit
info['BasicLimitInformation']['LimitFlags'] |= (
_w32j.JOB_OBJECT_LIMIT_PROCESS_MEMORY)
_w32j.SetInformationJobObject(g_hjob,
_w32j.JobObjectExtendedLimitInformation, info)
assign_job(create_job())
limit_memory(memory_limit)
def close():
_pg.quit()
quit()
def getEvents():
return _pg.event.get()

27
src/pygwin2/color.py Normal file
View file

@ -0,0 +1,27 @@
class color:
def __init__(self,r,g=None,b=None,a=255):
try:
r,g,b = tuple(int(r[i:i+2],16)for i in(0,2,4))
except:
pass
self.r = r
self.g = g
self.b = b
self.a = a
def hex(self):
return '%02x%02x%02x' % (self.r,self.g,self.b)
def rgb(self):
return (self.r,self.g,self.b,self.a)
def inverse(self):
return color(255-self.r,255-self.g,
255-self.b,255-self.a)
def __getitem__(self,x):
return [self.r,self.g,self.b,self.a][x]
def __list__(self):
return [self.r,self.g,self.b,self.a]
def __tuple__(self):
return self.rgb()
def __repr__(self):
return self.__str__()
def __str__(self):
return f'({",".join(str(i)for i in self.__list__())})'

86
src/pygwin2/console.py Normal file
View file

@ -0,0 +1,86 @@
from pygwin._pg import pg
try:
import win32console as w32con
import win32con as w32c
import win32gui as w32g
import win32api as w32a
nonwin32api = True
except:
nonwin32api = False
import pyautogui as pag
class console:
def __init__(self):
if not nonwin32api:
self._hwnd = w32con.GetConsoleWindow()
@property
def hwnd(self):
if not nonwin32api:
return self._hwnd
def focus(self):
if not nonwin32api:
self.hide()
self.show()
w32g.BringWindowToTop(self.hwnd)
w32g.ShowWindow(self.hwnd, w32c.SW_SHOWNORMAL)
w32g.SetForegroundWindow(self.hwnd)
def hide(self):
if not nonwin32api:
w32g.ShowWindow(self.hwnd, w32c.SW_HIDE)
def show(self):
if not nonwin32api:
w32g.ShowWindow(self.hwnd, w32c.SW_SHOW)
def move(self, x, y):
if not nonwin32api:
w32g.SetWindowPos(self.hwnd, x, y, self.size[0], self.size[1])
def resize(self, width, height):
if not nonwin32api:
w32g.SetWindowPos(self.hwnd, self.position[0], self.position[1], width, height)
def minimize(self):
if not nonwin32api:
w32g.ShowWindow(hwnd, w32c.SW_MINIMIZE)
return self.size
def maximize(self):
if not nonwin32api:
w32g.ShowWindow(hwnd, w32c.SW_MAXIMIZE)
return self.size
def title():
def fget(self):
if not nonwin32api:
return w32con.GetConsoleTitle()
def fset(self, value):
if not nonwin32api:
w32con.SetConsoleTitle(str(value))
def fdel(self):
pass
return locals()
title = property(**title())
def center(self,x=_pg.display.get_desktop_sizes()[0][0]/2,
y=_pg.display.get_desktop_sizes()[0][1]/2):
if not nonwin32api:
self.move(x-self.size[0]/2,y-self.size[1]/2)
@property
def visible(self):
if not nonwin32api:
return w32g.IsWindowVisible(self.hwnd)
@property
def position(self):
if not nonwin32api:
rect = w32g.GetWindowRect(self.hwnd)
x = rect[0]+7
y = rect[1]
return (x, y)
@property
def size(self):
if not nonwin32api:
rect = w32g.GetWindowRect(self.hwnd)
w = rect[2] - self.position[0]-7
h = rect[3] - self.position[1]-7
return (w, h)
def screenshot(self, path):
if not nonwin32api:
rect = self.position+self.size
self.focus()
pag.screenshot(path, region=rect)
return path
console = console()

43
src/pygwin2/font.py Normal file
View file

@ -0,0 +1,43 @@
from pygwin.surface import surface as _surface
from pygwin._pg import pg as _pg
class font:
def __init__(self, path):
self._path = path
def _font(self, size):
return _pg.font.Font(self._path,size)
def render(self, text, size, color, newLineSpace=5,
italic=False, bold=False, underline=False):
text = str(text)
font = self._font(size)
font.set_italic(italic)
font.set_bold(bold)
font.set_underline(underline)
if text.replace('\n', '') != text:
text = text.split('\n')
surf = _pg.Surface([font.size(max(text,key=lambda x:font.size(x)[0]))[0],
(font.size('123')[1]+newLineSpace)*len(text)],_pg.SRCALPHA)
y = 0
for i in text:
r = font.render(i, True, color)
surf.blit(r, (0, y))
y += font.size(i)[1]
if i != text[-1]:
y += newLineSpace
else:
surf = font.render(text, True, color)
surface = _surface(surf.get_size())
surface._surface_orig = surf
return surface
def size(self, text, size, newLineSpace=5,
italic=False,bold=False,underline=False):
return self.render(text, size, (255,255,255),
newLineSpace=newLineSpace,
italic=italic, bold=bold,
underline=underline).size
class sysFont(font):
def __init__(self, name):
self._path = _pg.font.match_font(name)
defaultFont = font(_pg.font.get_default_font())

114
src/pygwin2/gamepad.py Normal file
View file

@ -0,0 +1,114 @@
import inputs as _inputs
import threading as _threading
import time as _time
class gamepad:
def __init__(self, pygame):
self._lasty = ''
self._lastx = ''
self.founded = False
self._buttons = {'left-joystick': False,
'right-joystick': False,
'north': False,
'south': False,
'west': False,
'east': False,
'l1': False,
'l2': False,
'r1': False,
'r2': False,
'up': False,
'down': False,
'left': False,
'right': False,
'start': False,
'select': False}
self.leftJoystick = [0, 0]
self.rightJoystick = [0, 0]
self._pygame = pygame
self._start()
def _tick(self):
try:
events = _inputs.get_gamepad()
except:
return
if not self._pygame.display.get_active():
return
self.founded = True
if events:
for event in events:
if event.code == 'ABS_X':
self.leftJoystick[0] = event.state
elif event.code == 'ABS_Y':
self.leftJoystick[1] = event.state
elif event.code == 'ABS_RY':
self.rightJoystick[1] = event.state
elif event.code == 'ABS_RX':
self.rightJoystick[0] = event.state
elif event.code == 'BTN_THUMBL':
self._buttons['left-joystick'] = event.state
elif event.code == 'BTN_THUMBR':
self._buttons['right-joystick'] = event.state
elif event.code == 'BTN_TL':
self._buttons['l1'] = event.state
elif event.code == 'BTN_TR':
self._buttons['r1'] = event.state
elif event.code == 'ABS_Z':
if event.state == 255:
self._buttons['l2'] = 1
elif event.state == 0:
self._buttons['l2'] = 0
elif event.code == 'ABS_RZ':
if event.state == 255:
self._buttons['r2'] = 1
elif event.state == 0:
self._buttons['r2'] = 0
elif event.code == 'BTN_WEST':
self._buttons['west'] = event.state
elif event.code == 'BTN_NORTH':
self._buttons['north'] = event.state
elif event.code == 'BTN_EAST':
self._buttons['east'] = event.state
elif event.code == 'BTN_SOUTH':
self._buttons['south'] = event.state
elif event.code == 'ABS_HAT0Y':
if event.state == 1:
self._buttons['down'] = True
self._lasty = 'down'
elif event.state == -1:
self._buttons['up'] = True
self._lasty = 'up'
else:
self._buttons[self._lasty] = False
elif event.code == 'ABS_HAT0X':
if event.state == 1:
self._buttons['right'] = True
self._lastx = 'right'
elif event.state == -1:
self._buttons['left'] = True
self._lastx = 'left'
else:
self._buttons[self._lastx] = False
elif event.code == 'BTN_START':
self._buttons['select'] = event.state
elif event.code == 'BTN_SELECT':
self._buttons['start'] = event.state
def _start(self):
self.founded = False
self._started = True
def ttcb(self):
while self._started:
self._tick()
_threading.Thread(target=lambda:ttcb(self),daemon=True).start()
def close(self):
self._started = False
def isPressed(self, btn):
return btn in self._buttons
def reset(self):
self._lasty = ''
self._lastx = ''
self._buttons = []
self.leftJoystick = [0, 0]
self.rightJoystick = [0, 0]
def getPressed(self):
return self._buttons

43
src/pygwin2/image.py Normal file
View file

@ -0,0 +1,43 @@
from pygwin._pg import pg as _pg
from pygwin.surface import surface as _surface
from PIL import Image as _im
import tempfile as _tf
import randstr as _rs
import pickle as _p
import bz2 as _bz2
import os as _os
def load(path):
if path.endswith('.gif'):
im = _im.open(path)
with _tf.TemporaryDirectory() as td:
surfs = []
for i in range(im.n_frames):
im.seek(i)
p = _os.path.join(td,f'{i}.png')
im.save(p)
s = _pg.image.load(p)
_os.remove(p)
sg = _surface(s.get_size())
sg.blit(s,(0,0))
surfs.append(sg)
return surfs
else:
im = _im.open(path.encode('utf8').decode('utf8'))
image = _pg.image.fromstring(im.tobytes(),im.size,im.mode)
surf = _surface(im.size)
surf.blit(image,(0,0))
return surf
def save(surface, dest):
_pg.image.save_extended(surface._grp(), dest)
def toBytes(surface):
return _bz2.compress(_p.dumps([_pg.image.tostring(surface._grp(),"RGBA"),list(surface.size)]))
def fromBytes(bytes):
string = _p.loads(_bz2.decompress(bytes))
surf = _pg.image.fromstring(string[0],tuple(string[1]),"RGBA")
surface = _surface(tuple(string[1]))
surface.blit(surf,(0,0))
return surface

22
src/pygwin2/keyboard.py Normal file
View file

@ -0,0 +1,22 @@
from pygwin._pg import pg as _pg
def getPressed():
fkeys = {}
keys = _pg.key.get_pressed()
for i in range(len(keys)):
fkeys.update({_pg.key.name(i):keys[i]})
return fkeys
def isPressed(key):
return getPressed()[key]
import inspect as _i
_aliases = {'getPressed':['gprs','getkeys'],
'isPressed':['isprs','keyprs']}
for i in _aliases.items():
exec(f'args = _i.signature({i[0]})')
args = [str(i[1]) for i in dict(args.parameters).items()]
args = ', '.join(args)
for i0 in i[1]:
exec(f"def {i0}({args}):return {i[0]}({args})")

92
src/pygwin2/mixer.py Normal file
View file

@ -0,0 +1,92 @@
from pygwin._pg import pg as _pg
import os as _os
import tempfile as _tf
ffmpeg = None
class sound:
def __init__(self, path):
if not (path.endswith('.wav') or path.endswith('.ogg')):
try:
from pydub import AudioSegment as _as
if ffmpeg != None:
_as.ffmpeg = ffmpeg
_as.converter = ffmpeg
sound = _as.from_file(path, _os.path.splitext(path)[1])
path = _tf.mkstemp('.wav')
sound.export(path, format="wav")
except:
print('Set ffmpeg to path so that you don'+\
"'t have to convert the file to "+\
'".wav". If you have installed, but the error still appears, write down the path to ffmpeg.exe in plugin.ffmpeg.')
self._sound = _pg.mixer.Sound(path)
def play(self):
self._sound.play()
def stop(self):
self._sound.stop()
def volume():
def fget(self):
return self._sound.get_volume()
def fset(self, value):
if type(value) == int:
self._sound.set_volume(value)
def fdel(self):
pass
return locals()
volume = property(**volume())
@property
def length(self):
return self._sound.get_length()
class music:
def __init__(self, path):
if path.endswith('.wav') or path.endswith('.ogg'):
self._path = path
else:
try:
from pydub import AudioSegment as _as
if ffmpeg != None:
_as.ffmpeg = ffmpeg
_as.converter = ffmpeg
sound = _as.from_file(path, _os.path.splitext(path)[1])
path = _tf.mkstemp('.wav')
sound.export(path, format="wav")
except:
print('Set ffmpeg to path so that you don'+\
"'t have to convert the file to "+\
'".wav". If you have installed, but the error still appears, write down the path to ffmpeg.exe in plugin.ffmpeg.')
_pg.mixer.music.load(path)
def play(self, loops=0):
_pg.mixer.music.play(loops)
def stop(self):
_pg.mixer.music.stop()
def restart(self):
_pg.mixer.music.rewind()
def pause(self):
_pg.mixer.music.pause()
def release(self):
_pg.mixer.music.unpause()
def queue(self):
_pg.mixer.music.queue(self._path)
def volume():
def fget(self):
return _pg.mixer.music.get_volume()
def fset(self, value):
if type(value) == int:
_pg.mixer.music.set_volume(value)
def fdel(self):
pass
return locals()
volume = property(**volume())
def pos():
def fget(self):
return _pg.mixer.music.get_pos()
def fset(self, value):
if type(value) == int:
_pg.mixer.music.set_pos(value)
def fdel(self):
pass
return locals()
pos = property(**pos())

36
src/pygwin2/mouse.py Normal file
View file

@ -0,0 +1,36 @@
from pygwin._pg import pg as _pg
def getPressed():
orig = _pg.mouse.get_pressed(3)
return {'left':orig[0],'middle':orig[1],'right':orig[2]}
def isPressed(x):
return getPressed()[x.lower()]
def setPosition(x):
_pg.mouse.set_pos(x)
def getPosition():
return _pg.mouse.get_pos()
def setVisible(x):
_pg.mouse.set_visible(x)
def getVisible():
return _pg.mouse.get_visible()
def getCursor():
return _pg.mouse.get_cursor()
def setCursor(size, hotspot=None, xormasks=None, andmasks=None):
if hotspot == None and xormasks == None and andmasks == None:
_pg.mouse.set_system_cursor(size)
else:
_pg.mouse.set_cursor(size, hotspot, xormasks, andmasks)
import inspect as _i
_aliases = {'getPressed':['gprs','getbtns'],
'isPressed':['isprs','btnprs'],
'setPosition':['spos','setpos','move'],
'getPosition':['gpos','getpos']}
for i in _aliases.items():
exec(f'args = _i.signature({i[0]})')
args = [str(i[1]) for i in dict(args.parameters).items()]
args = ', '.join(args)
for i0 in i[1]:
exec(f"def {i0}({args}):return {i[0]}({args})")

107
src/pygwin2/record.py Normal file
View file

@ -0,0 +1,107 @@
from contextlib import contextmanager
from pygwin._pg import pg as _pg
import moviepy.editor as mpe
from array import array
from PIL import Image
import numpy as np
import threading
import pyautogui
import tempfile
import pyaudio
import wave
import time
import sys
import cv2
import os
class record:
def __init__(self,win,audio=False):
self._isaudio = audio
self._surface = win
self.reset()
def reset(self):
self._run = False
self._fpss = []
self._frames = []
self._codec = cv2.VideoWriter_fourcc(*"mp4v")
if self._isaudio:
self._apy = pyaudio.PyAudio()
self._aframs = []
self._astrm = self.apy.open(format=pyaudio.paInt16,channels=1,
rate=44100,input=True,frames_per_buffer=1024)
def start(self,newThread=True):
self._run = True
if self._isaudio:
def audiot(self):
while self._run:
self._aframs.append(self.astrm.read(1024))
self._athread = threading.Thread(target=lambda:audiot(self))
self._athread.start()
def main(self):
while self.run:
self._record()
if newThread:
self._thread = threading.Thread(target=lambda:main(self))
self._thread.start()
else:main()
def _record(self):
if self._run:
try:
self._frames.append(self._surface)
self._fpss.append(self._surface.rawFps)
except:
pass
def render(self, path):
temp = tempfile.gettempdir()
if self.isaudio:
wavpath = os.path.join(temp, 'audio.wav')
wavfile = wave.open(wavpath, 'wb')
wavfile.setnchannels(1)
wavfile.setsampwidth(self._apy.get_sample_size(pyaudio.paInt16))
wavfile.setframerate(44100)
af = []
for i in self._aframs:
af.append(array('h',i))
wavfile.writeframes(b''.join(af))
wavfile.close()
fps = 0
for i in self._fpss:
fps += i
fps = fps/len(self._fpss)
if self._isaudio:
noaudiopath = os.path.join(temp, 'noaudio.mp4')
else:
noaudiopath = path
out = cv2.VideoWriter(noaudiopath,self._codec,
fps,self._surface.size)
for i in self._frames:
frame = np.array(_pg.surfarray.array3d(i).swapaxes(0,1))
frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
out.write(frame)
out.release()
if self._isaudio:
videoclip = mpe.VideoFileClip(noaudiopath)
audioclip = mpe.AudioFileClip(wavpath)
new_audioclip = mpe.CompositeAudioClip([audioclip])
videoclip.audio = new_audioclip
@contextmanager
def ss():
with open(os.devnull, "w") as devnull:
oso = sys.stdout
sys.stdout = devnull
try:yield
finally:sys.stdout=oso
with ss():
videoclip.write_videofile(path)
os.remove(noaudiopath)
os.remove(wavpath)
def stop(self):
self._run = False
try:
self._thread.join()
except:
pass
if self._isaudio:
self._athread.join()

60
src/pygwin2/rect.py Normal file
View file

@ -0,0 +1,60 @@
from pygwin._pg import pg
_aliases = {'w':['width'],'h':['height'],
'c':['center','middle'],
'x':['left'],'y':['up'],
'r':['right'],'d':['down']}
class rect:
def __init__(self,x,y,w,h):
self.x = x
self.y = y
self.w = w
self.h = h
self._reload()
def collide(self, x):
try:return self._rect.colliderect(x._rect_rect)
except:return self._rect.colliderect(x._rect)
def contains(self, x, y):
return self._rect.collidepoint(x,y)
def copy(self):
return rect(self.x,self.y,self.w,self.h)
def _reload(self):
self.c = (self.x/2+self.w/2,self.y/2+self.h/2)
self.cx, self.cy = self.c
self.r,self.d = self.x+self.w,self.y+self.h
self._rect = pg.Rect(self.x,self.y,self.w,self.h)
def __getitem__(self,x):
return [self.x,self.y,self.w,self.h][x]
def __list__(self):
return [self.x,self.y,self.w,self.h]
def __tuple__(self):
return (self.x,self.y,self.w,self.h)
def __str__(self):
return f'<{self.x}x{self.y},{self.w}x{self.h}>'
def __setattr__(self,attr,data):
if attr in _aliases.values():
ma = None
for i in _aliases.items():
if i[1] in attr:
ma = i[0]
break
attr = ma
object.__setattr__(self,attr,data)
def __getattr__(self,attr):
if attr in _aliases.values():
ma = None
for i in _aliases.items():
if i[1] == attr:
ma = i[0]
break
attr = ma
data = self.__dict__[attr]
return data
# def fromSurface(surf,x=0,y=0,c=())
#
# # print(dir(property))
# r = rect(123,321,654,987)
# print(r.width)

150
src/pygwin2/surface.py Normal file
View file

@ -0,0 +1,150 @@
from pygwin.rect import rect as _r
from pygwin.color import color as _clr
from pygwin._pg import pg as _pg
from PIL import Image as _im
import tempfile as _tf
import randstr as _rs
import time as _t
import os as _os
class surface:
def __init__(self, size):
self._size = size
self._orig = _pg.Surface(size, _pg.SRCALPHA)
@property
def pixels(self):
pixels = []
for x in range(self.size[0]):
pixels.append([])
for y in range(self.size[1]):
pixels[x].append(self.getPixel(x,y))
return pixels
@property
def size(self):
return self._size
def _grp(self):
return self._orig
def rect(self, x=0, y=0, center=[]):
if center == []:
return _r(x, y, self.size[0], self.size[1])
else:
return _r(center[0]-(self.size[0]/2),
center[1]-(self.size[1]/2),
self.size[0], self.size[1])
def copy(self):
surf = surface(self._size)
surf._surface_orig = self._orig
surf._surface_size = self._size
return surf
def getPixel(self, x, y):
return _clr(*self._orig.get_at((x,y)))
def setPixel(self, x, y, color):
self._orig.set_at((x,y),color)
return self.copy()
def blit(self, surf, xy):
if type(surf) != surface and type(surf) != _pg.Surface:
from pygwin.font import defaultFont as _df
surf = _df.render(surf, 25, (0,0,0))
try:
self._orig.blit(surf._surface_orig, xy)
except:
try:
self._orig.blit(surf._orig, xy)
except:
self._orig.blit(surf, xy)
return self.copy()
def fill(self, color):
self._orig.fill(list(color))
return self.copy()
def crop(self, rect):
self._orig = self._orig.subsurface(rect)
self._size = self._orig.get_size()
return self.copy()
def scale(self, size, smooth=False):
if not smooth:
self._orig = _pg.transform.scale(self._orig, size)
else:
self._orig = _pg.transform.smoothscale(self._orig, size)
self._size = self._orig.get_size()
return self.copy()
def rotate(self, angle):
self._orig = _pg.transform.rotate(self._orig, angle)
self._size = self._orig.get_size()
return self.copy()
def flip(self, x, y):
self._orig = _pg.transform.flip(self._orig, x, y)
return self.copy()
def blur(self, amt):
if amt < 0:return self.copy()
scale = (int(self._orig.get_width()*(amt+1)),
int(self._orig.get_height()*(amt+1)))
size = self._orig.get_size()
self._orig = _pg.transform.smoothscale(self._orig,scale)
self._orig = _pg.transform.smoothscale(self._orig,size)
return self.copy()
class _draw:
def __init__(self,surface):
self._surf = surface
def rect(self,color,rect,
width=0,borderRadius=0,
borderTopLeftRadius=-1,
borderTopRightRadius=-1,
borderBottomLeftRadius=-1,
borderBottomRightRadius=-1):
try:
orig = self._surf._surface_orig
except:
orig = self._surf._orig
_pg.draw.rect(orig,color,_pg.Rect(rect[0],rect[1],rect[2],rect[3]),
width,borderRadius,borderTopLeftRadius,borderTopRightRadius,
borderBottomLeftRadius,borderBottomRightRadius)
return self._surf.copy()
def polygon(self, color, points, width=0):
try:
orig = self._surf._surface_orig
except:
orig = self._surf._orig
_pg.draw.polygon(orig,color,points,width)
return self._surf.copy()
def circle(self,color,center,
radius,width=0,
drawTopLeft=1,
drawTopRight=1,
drawBottomLeft=1,
drawBottomRight=1):
try:
orig = self._surf._surface_orig
except:
orig = self._surf._orig
_pg.draw.circle(orig,color,center,radius,
width,drawTopRight,drawTopLeft,
drawBottomLeft,drawBottomRight)
return self._surf.copy()
def ellipse(self,color,rect,width=0):
try:
orig = self._surf._surface_orig
except:
orig = self._surf._orig
_pg.draw.ellipse(orig,color,_pg.Rect(rect[0],
rect[1],rect[2],rect[3]),width)
return self._surf.copy()
def line(self,color,start,end,width=1):
try:
orig = self._surf._surface_orig
except:
orig = self._surf._orig
_pg.draw.line(orig,color,start,end,width)
return self._surf.copy()
def arc(self,color,rect,startAngle,stopAngle,width=1):
try:
orig = self._surf._surface_orig
except:
orig = self._surf._orig
_pg.draw.arc(orig,color,_pg.Rect(rect[0],
rect[1],rect[2],rect[3]),
startAngle,stopAngle,width)
return self._surf.copy()
@property
def draw(self):
return self._draw(self)

49
src/pygwin2/tray.py Normal file
View file

@ -0,0 +1,49 @@
import threading
import wx
import wx.adv
from pygwin._pg import pg
import copy
class tray(wx.adv.TaskBarIcon):
def __init__(self, tooltip, iconpath):
class App(wx.App):
def OnInit(self):
self.frame = wx.Frame(None)
self.SetTopWindow(self.frame)
return True
self._app = App(False)
self.frame = self._app.frame
super().__init__()
self._tooltip = tooltip
self._iconpath = iconpath
self.setIcon(iconpath)
self._menu = wx.Menu()
def CreatePopupMenu(self):
return self._menu
def GetPopupMenu(self):
return self._menu
def setIcon(self, path):
self._bicon = wx.Icon(wx.Bitmap(path))
self.SetIcon(self._bicon, self._tooltip)
def setTooltip(self, tooltip):
self.SetIcon(self._bicon, tooltip)
self._tooltip = tooltip
def onLeftMouseButton(self):
pass
def addSeparator(self):
self._menu.AppendSeparator()
def addCommand(self,text,func=lambda:None):
item = wx.MenuItem(self._menu,-1,text)
self._menu.Bind(wx.EVT_MENU,
lambda x:func(),
id=item.GetId())
self._menu.Append(item)
def start(self, thread=True):
cbotld = lambda x:self.onLeftMouseButton()
self.Bind(wx.adv.EVT_TASKBAR_LEFT_DOWN,cbotld)
if thread: threading.Thread(
target=self._app.MainLoop,
daemon=1).start()
else: self._app.MainLoop()
def stop(self):
wx.CallAfter(self._app.frame.Close)

734
src/pygwin2/ui.py Normal file
View file

@ -0,0 +1,734 @@
from pygwin._pg import pg as _pg
from pygwin.surface import surface as _s
from pygwin.font import defaultFont as _df
from pygwin.image import load as _l
from pygwin.rect import rect as _r
import pygwin.mouse as _m
import pygwin.keyboard as _k
import ctypes as _ct
import copy as _copy
class widget:
power = True
destroyed = False
def _args(self, locals):
args = _copy.copy(locals)
for i in args.items():
if i[0] != 'self':
exec(f'self.{i[0]} = args["{i[0]}"]')
self._args = args
def __init__(self, surface):
self._args(locals())
def draw(self, win, pos):
win.blit(self.surface,pos)
def on(self):
self.power = True
def off(self):
self.power = False
def destroy(self):
self.destroyed = True
def config(self, **parameters):
if parameters != {}:
for i in parameters.items():
if i[0] in list(self.__dict__.keys()):
exec(f'self.{i[0]} = parameters["{i[0]}"]')
self._args[i[0]] = i[1]
else:
return self._args
self.__init__(**self._args)
class button(widget):
def __init__(self,text,
func=lambda:None,
fontSize=30,font=_df,
width=None,height=None,
bg=(70,70,70),fg=(180,180,200),
afg=(50,50,50),abg=(200,200,200),
borderColor=(50,50,50),borderWidth=5):
super()._args(locals())
self.cl0 = False
self.cl1 = False
self.nc0 = True
self._generate()
def _generate(self, position=None):
if self.width == None or self.height == None:
textSize = self.font.size(self.text,self.fontSize)
if self.width != None:
self.surface = _s((self.width,textSize[1]+10))
elif self.height != None:
self.surface = _s((textSize[0]+50,self.height))
else:
self.surface = _s((textSize[0]+50,textSize[1]+10))
else:
self.surface = _s((self.width,self.height))
if position != None:
contains = self.surface.rect(position[0], position[1]).contains(
_m.getPosition()[0], _m.getPosition()[1])
cacm = contains and _m.isPressed('left')
else:
contains = False
cacm = False
if contains and not self.cl0:
_m.setCursor(_pg.SYSTEM_CURSOR_HAND)
self.cl0 = True
self.nc0 = True
elif not contains:
if self.nc0:
_m.setCursor(_pg.SYSTEM_CURSOR_ARROW)
self.nc0 = False
self.cl0 = False
if cacm and not self.cl1:
self.func()
self.cl1 = True
elif not cacm:
self.cl1 = False
self.surface.fill(self.borderColor)
if cacm:
self.surface.draw.rect(self.abg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
else:
self.surface.draw.rect(self.bg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if cacm:
text = self.font.render(self.text,self.fontSize,self.afg)
else:
text = self.font.render(self.text,self.fontSize,self.fg)
pos = text.rect(center=(
self.surface.size[0]/2,
self.surface.size[1]/2))
pos = [pos.x, pos.y]
self.surface.blit(text,pos)
def draw(self, win, pos):
self._generate(pos)
win.blit(self.surface,pos)
class label(widget):
def __init__(self,text,size=30,
color=(0,0,0),font=_df):
self.surface = font.render(text,size,color)
class entry(widget):
def __init__(self,hint='',fontSize=30,font=_df,
width=None,height=None,hide=False,
bg=(70,70,70),fg=(180,180,200),
afg=(200,200,200),abg=(50,50,50),
hintColor=(100,100,100),
lineColor=(200,200,200),
borderColor=(50,50,50),
borderWidth=5,maxSymbols=None,
whitelist=None,blacklist=[]):
super()._args(locals())
self.text = ''
self.focus = False
self.tick = 0
self.wcl = False
self.startHint = self.hint
self.ws = False
if self.width == None or self.height == None:
if self.hint != '':
hintSize = self.font.size(self.hint,self.fontSize)
else:
hintSize = (150,self.font.size('X',self.fontSize)[1])
if self.height == None:
self.height = hintSize[1]+10
if self.width == None:
self.width = hintSize[0]+50
self.surface = _s((self.width,self.height))
self.wclk = []
self.wsnr = False
def _generate(self,position=None):
self.surface.fill(self.borderColor)
if self.focus:
self.surface.draw.rect(self.abg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if self.text == '':
if not self.hide:
text = self.font.render(self.hint,self.fontSize,self.hintColor)
else:
text = self.font.render('*'*len(self.hint),self.fontSize,self.hintColor)
else:
if not self.hide:
text = self.font.render(self.text,self.fontSize,self.afg)
else:
text = self.font.render('*'*len(self.text),self.fontSize,self.afg)
x = 10
if text.size[0] >= self.surface.size[0]-20:
x = self.surface.size[0]-text.size[0]-10
self.surface.blit(text,(x,self.surface.size[1]/2-text.size[1]/2))
for i in _k.getPressed().items():
if i[1]:
if i[0] not in self.wclk:
if len(i[0]) == 1:
self.insert(i[0])
elif i[0] == 'backspace':
self.delete()
elif i[0] == 'return':
self.focus = False
elif i[0] == 'space':
self.insert(' ')
self.wclk.append(i[0])
else:
if i[0] in self.wclk:
self.wclk.remove(i[0])
self.tick += 1
if self.tick >= 60:
if self.text != '':
points = [[x+text.size[0],self.surface.size[1]/2-text.size[1]/2],
[x+text.size[0],self.surface.size[1]/2-text.size[1]/2+self.surface.size[1]-10]]
self.surface.draw.line(self.lineColor,points[0],points[1],3)
if self.tick == 120:
self.tick = 0
else:
self.surface.draw.rect(self.bg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if self.text == '':
if not self.hide:
text = self.font.render(self.hint,self.fontSize,self.hintColor)
else:
text = self.font.render('*'*len(self.hint),self.fontSize,self.hintColor)
else:
if self.hide:
text = self.font.render(self.text,self.fontSize,self.fg)
else:
text = self.font.render('*'*len(self.text),self.fontSize,self.fg)
x = self.surface.size[0]/2-text.size[0]/2
if text.size[0] >= self.surface.size[0]-20:
x = self.surface.size[0]-text.size[0]-10
self.surface.blit(text,(x,self.surface.size[1]/2-text.size[1]/2))
if position != None:
if self.surface.rect(position[0],
position[1]).contains(_m.getPosition()[0],
_m.getPosition()[1]):
if not self.wcl:
_m.setCursor(_pg.SYSTEM_CURSOR_HAND)
else:
if not self.ws:
_m.setCursor(_pg.SYSTEM_CURSOR_ARROW)
self.ws = True
if _m.isPressed('left'):
if not self.wcl:
self.focus=self.focus==0
self.wcl = True
else:
self.wcl = False
self.wsnr = False
else:
if not self.wsnr:
_m.setCursor(_pg.SYSTEM_CURSOR_ARROW)
self.wsnr = True
if _m.isPressed('left'):
self.focus = False
def insert(self,text):
if _ct.WinDLL("User32.dll").GetKeyState(0x14):
text = text.upper()
if hex(getattr(_ct.windll.LoadLibrary("user32.dll"), "GetKeyboardLayout")(0))=='0x4190419':
text = text.translate(dict(zip(map(ord,
'''qwertyuiop[]asdfghjkl;'zxcvbnm,./`QWERTYUIOPASDFGHJKLZXCVBNM'''),
'''йцукенгшщзхъфывапролджэячсмитьбю.ёЙЦУКЕНГШЩЗФЫВАПРОЛДЯЧСМИТЬ''')))
if _pg.key.get_pressed()[_pg.K_LSHIFT] or _pg.key.get_pressed()[_pg.K_RSHIFT]:
text = text.translate(dict(zip(map(ord,
u'''1234567890-=[]\;',./`'''),
u'''!@#$%^&*()_+{}|:"<>?~''')))
if text in self.blacklist:
return
if self.whitelist != None:
if text not in self.whitelist:
return
if self.maxSymbols != None:
if len(self.text) > self.maxSymbols:
return
self.text += text
def delete(self,symbols=1):
self.text = self.text[:0-symbols]
def draw(self, win, pos):
self._generate(pos)
win.blit(self.surface,pos)
def get(self):
return self.text
class textarea(widget):
def __init__(self,hint='',fontSize=30,
font=_df,width=None,bg=(70,70,70),
fg=(180,180,200),afg=(200,200,200),
abg=(50,50,50),hintColor=(100,100,100),
lineColor=(200,200,200),
borderColor=(50,50,50),
borderWidth=5,maxSymbols=None,
whitelist=None,blacklist=[]):
super()._args(locals())
self.text = ''
self.focus = False
self.tick = 0
self.wcl = False
self.startHint = self.hint
self.ws = False
if self.hint != '':
hintSize = self.font.size(self.hint,self.fontSize)
else:
hintSize = (150,self.font.size('X',self.fontSize)[1])
self.height = hintSize[1]+10
if self.width == None:
self.width = hintSize[0]+50
self.surface = _s((self.width,self.height))
self.wclk = []
self.wsnr = False
def _generate(self,position=None):
self.surface.fill(self.borderColor)
if self.focus:
if self.text != '':
self.height = self.font.size(self.text,self.fontSize)[1]+10
else:
self.height = self.font.size('X',self.fontSize)[1]+10
self.surface = _s((self.width,self.height))
self.surface.fill(self.borderColor)
self.surface.draw.rect(self.abg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if self.text == '':
text = self.font.render(self.hint,self.fontSize,self.hintColor)
else:
text = self.font.render(self.text,self.fontSize,self.afg)
try:
last = self.text.split('\n')[-1]
except:
last = self.text
x = 10
if self.font.size(last,self.fontSize)[0] >= self.surface.size[0]-20:
x = self.surface.size[0]-self.font.size(last,self.fontSize)[0]
self.surface.blit(text,(x,self.surface.size[1]/2-text.size[1]/2))
for i in _k.getPressed().items():
if i[1]:
if i[0] not in self.wclk:
if len(i[0]) == 1:
self.insert(i[0])
elif i[0] == 'backspace':
self.delete()
elif i[0] == 'return':
if self.maxSymbols != None:
if len(self.text) > self.maxSymbols:
continue
self.text += '\n'
elif i[0] == 'space':
self.insert(' ')
self.wclk.append(i[0])
else:
if i[0] in self.wclk:
self.wclk.remove(i[0])
self.tick += 1
if self.tick >= 60:
if self.text != '':
points = [[x+self.font.size(last,self.fontSize)[0],
self.surface.size[1]-(self.font.size('X',self.fontSize)[1])],
[x+self.font.size(last,self.fontSize)[0],
self.surface.size[1]/2-text.size[1]/2+self.surface.size[1]-10]]
self.surface.draw.line(self.lineColor,points[0],points[1],3)
if self.tick == 120:
self.tick = 0
else:
self.surface.draw.rect(self.bg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if self.text == '':
text = self.font.render(self.hint,self.fontSize,self.hintColor)
else:
text = self.font.render(self.text,self.fontSize,self.fg)
try:
last = self.text.split('\n')[-1]
except:
last = self.text
x = self.surface.size[0]/2-text.size[0]/2
if self.font.size(last,self.fontSize)[0] >= self.surface.size[0]-20:
x = self.surface.size[0]-self.font.size(last,self.fontSize)[0]
self.surface.blit(text,(x,self.surface.size[1]/2-text.size[1]/2))
if position != None:
if self.surface.rect(position[0],
position[1]).contains(_m.getPosition()[0],
_m.getPosition()[1]):
if not self.wcl:
_m.setCursor(_pg.SYSTEM_CURSOR_HAND)
else:
if not self.ws:
_m.setCursor(_pg.SYSTEM_CURSOR_ARROW)
self.ws = True
if _m.isPressed('left'):
if not self.wcl:
self.focus=self.focus==0
self.wcl = True
else:
self.wcl = False
self.wsnr = False
else:
if not self.wsnr:
_m.setCursor(_pg.SYSTEM_CURSOR_ARROW)
self.wsnr = True
if _m.isPressed('left'):
self.focus = False
def insert(self,text):
if _ct.WinDLL("User32.dll").GetKeyState(0x14):
text = text.upper()
if _pg.key.get_pressed()[_pg.K_LSHIFT] or _pg.key.get_pressed()[_pg.K_RSHIFT]:
text = text.translate(dict(zip(map(ord, '''1234567890-=[]\\;'''+"',./`"),
'''!@#$%^&*()_+{}|:"<>?~''')))
if hex(getattr(_ct.windll.LoadLibrary("user32.dll"),
"GetKeyboardLayout")(0))=='0x4190419':
text = text.translate(dict(zip(map(ord,
'''qwertyuiop[]asdfghjkl;'zxcvbnm,./`QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>?~'''),
'''йцукенгшщзхъфывапролджэячсмитьбю.ёЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,Ё''')))
if text in self.blacklist:
return
if self.whitelist != None:
if text not in self.whitelist:
return
if self.maxSymbols != None:
if len(self.text) > self.maxSymbols:
return
self.text += text
def delete(self,symbols=1):
self.text = self.text[:0-symbols]
def draw(self, win, pos):
self._generate(pos)
win.blit(self.surface,pos)
def get(self):
return self.text
class keySelect(entry):
def __init__(self,keyBefore='',
fontSize=30,font=_df,
width=None,height=None,
bg=(70,70,70),fg=(180,180,200),
afg=(200,200,200),abg=(50,50,50),
hintColor=(100,100,100),
lineColor=(200,200,200),
borderColor=(50,50,50),
borderWidth=5,maxSymbols=None,
whitelist=None,blacklist=[]):
super()._args(locals())
self.hint = ''
self.text = keyBefore
self.focus = False
self.tick = 0
self.wcl = False
self.startHint = self.hint
self.ws = False
if self.width == None or self.height == None:
if self.hint != '':
hintSize = self.font.size(self.hint,self.fontSize)
else:
hintSize = (150,self.font.size('X',self.fontSize)[1])
if self.height == None:
self.height = hintSize[1]+10
if self.width == None:
self.width = hintSize[0]+50
self.surface = _s((self.width,self.height))
self.wclk = []
self.wsnr = False
def _generate(self,position=None):
self.surface.fill(self.borderColor)
if self.focus:
self.surface.draw.rect(self.abg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if self.text == '':
text = self.font.render(self.hint,self.fontSize,self.hintColor)
else:
text = self.font.render(self.text,self.fontSize,self.afg)
x = self.surface.size[0]/2-text.size[0]/2
if text.size[0] >= self.surface.size[0]-20:
x = self.surface.size[0]-text.size[0]-10
self.surface.blit(text,(x,self.surface.size[1]/2-text.size[1]/2))
for i in _k.getPressed().items():
if i[1] and self.focus:
if i[0] in self.blacklist:
continue
if self.whitelist != None:
if i[0] not in self.whitelist:
continue
if self.maxSymbols != None:
if len(self.text) > self.maxSymbols:
continue
self.text = i[0]
break
self.tick += 1
if self.tick >= 60:
if self.text != '':
points = [[x+text.size[0],self.surface.size[1]/2-text.size[1]/2],
[x+text.size[0],self.surface.size[1]/2-text.size[1]/2+self.surface.size[1]-10]]
self.surface.draw.line(self.lineColor,points[0],points[1],3)
if self.tick == 120:
self.tick = 0
else:
self.surface.draw.rect(self.bg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if self.text == '':
text = self.font.render(self.hint,self.fontSize,self.hintColor)
else:
text = self.font.render(self.text,self.fontSize,self.fg)
x = self.surface.size[0]/2-text.size[0]/2
if text.size[0] >= self.surface.size[0]-20:
x = self.surface.size[0]-text.size[0]-10
self.surface.blit(text,(x,self.surface.size[1]/2-text.size[1]/2))
if position != None:
if self.surface.rect(position[0],
position[1]).contains(_m.getPosition()[0],
_m.getPosition()[1]):
if not self.wcl:
_m.setCursor(_pg.SYSTEM_CURSOR_HAND)
else:
if not self.ws:
_m.setCursor(_pg.SYSTEM_CURSOR_ARROW)
self.ws = True
if _m.isPressed('left'):
if not self.wcl:
self.focus=self.focus==0
self.wcl = True
else:
self.wcl = False
self.wsnr = False
else:
if not self.wsnr:
_m.setCursor(_pg.SYSTEM_CURSOR_ARROW)
self.wsnr = True
if _m.isPressed('left'):
self.focus = False
def draw(self, win, pos):
self._generate(pos)
win.blit(self.surface,pos)
def get(self):
return self.text
class image(widget):
def __init__(self, path):
self.surface = _l(path)
class loadingBar(widget):
def __init__(self,width,
height=50,
length=100,
bg=(70,70,70),
loadedColor=(50,200,50),
borderColor=(50,50,50),
borderWidth=5):
super()._args(locals())
self.loaded = 0
def step(self,count=1):
self.loaded += 1
if self.loaded > self.length:
self.loaded = self.length
def set(self, x):
self.loaded = x
if self.loaded > self.length:
self.loaded = self.length
def reset(self):
self.loaded = 0
def get(self):
return self.loaded
def draw(self, win, pos):
self.surface = _s((self.width,self.height))
self.surface.fill(self.borderColor)
self.surface.draw.rect(self.bg,_r(5,5,
self.surface.size[0]-10,
self.surface.size[1]-10))
self.surface.draw.rect(self.loadedColor,_r(self.borderWidth,self.borderWidth,
(self.surface.size[0]/self.length*self.loaded)-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
win.blit(self.surface, pos)
class slider(widget):
def __init__(self,width,
bg=(70,70,70),
fg=(200,200,200),
horizontal=True):
super()._args(locals())
self.s = False
self.x = 12.5
self._generate(None)
def _generate(self, pos):
if self.horizontal:
self.surface = _s((self.width,50))
self.surface.draw.line(self.bg,[12.5,25],[self.width-12.5,25],10)
self.surface.draw.circle(self.bg,[12.5,26],5)
self.surface.draw.circle(self.bg,[self.width-12.5,26],5)
self.surface.draw.circle(self.fg,[self.x,25],12.5)
else:
self.surface = _s((50,self.width))
self.surface.draw.line(self.bg,[25,12.5],[25,self.width-12.5],10)
self.surface.draw.circle(self.bg,[26,12.5],5)
self.surface.draw.circle(self.bg,[26,self.width-12.5],5)
self.surface.draw.circle(self.fg,[25,self.x],12.5)
if pos != None:
if _m.isPressed('left'):
if self.horizontal:
rect = _r(pos[0]+5,pos[1],
self.surface.size[0]-10,
self.surface.size[1])
if rect.contains(_m.getPosition()[0],
_m.getPosition()[1]) or self.s:
self.x = _m.getPosition()[0]-pos[0]
if self.x < 12.5: self.x = 12.5
if self.x > self.width-12.5: self.x = self.width-12.5
self.s = True
else:
rect = _r(pos[0],pos[1]+5,
self.surface.size[0],
self.surface.size[1]-10)
if rect.contains(_m.getPosition()[0],
_m.getPosition()[1]) or self.s:
self.x = _m.getPosition()[1]-pos[1]
if self.x < 12.5: self.x = 12.5
if self.x > self.width-12.5: self.x = self.width-12.5
self.s = True
else:
self.s = False
def get(self):
return int(self.x/(self.width-10)*101)
def set(self, x):
self.x = x/101*(self.width-10)
def draw(self, win, pos):
self._generate(pos)
win.blit(self.surface, pos)
class checkBox(widget):
def __init__(self,width=50,bg=(180,180,180),
fg=(50,180,50),afg=(70,200,70),
abg=(120,120,120),borderColor=(220,220,220),
borderWidth=5):
super()._args(locals())
self.cl0 = False
self.cl1 = False
self.nc0 = True
self.x = False
self._generate()
def set(self, x):
self.x = x
def get(self):
return self.x
def _generate(self, position=None):
self.surface = _s((self.width,self.width))
if position != None:
contains = self.surface.rect(position[0], position[1]).contains(
_m.getPosition()[0], _m.getPosition()[1])
cacm = contains and _m.isPressed('left')
else:
contains = False
cacm = False
if contains and not self.cl0:
_m.setCursor(_pg.SYSTEM_CURSOR_HAND)
self.cl0 = True
self.nc0 = True
elif not contains:
if self.nc0:
_m.setCursor(_pg.SYSTEM_CURSOR_ARROW)
self.nc0 = False
self.cl0 = False
if cacm and not self.cl1:
self.x=self.x==0
self.cl1 = True
elif not cacm:
self.cl1 = False
self.surface.fill(self.borderColor)
if cacm:
self.surface.draw.rect(self.abg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if self.x:
self.surface.draw.line(self.afg,[self.borderWidth,self.width/2+self.borderWidth],
[self.width/2,self.width-self.borderWidth],self.borderWidth)
self.surface.draw.line(self.afg,[self.width/2,self.width-self.borderWidth],
[self.width-self.borderWidth,self.borderWidth],self.borderWidth)
else:
self.surface.draw.rect(self.bg,_r(self.borderWidth,self.borderWidth,
self.surface.size[0]-self.borderWidth*2,
self.surface.size[1]-self.borderWidth*2))
if self.x:
self.surface.draw.line(self.fg,[self.borderWidth,self.width/2+self.borderWidth],
[self.width/2,self.width-self.borderWidth],self.borderWidth)
self.surface.draw.line(self.fg,[self.width/2,self.width-self.borderWidth],
[self.width-self.borderWidth,self.borderWidth],self.borderWidth)
def draw(self, win, pos):
self._generate(pos)
win.blit(self.surface,pos)
class comboBox(widget):
def __init__(self,text,values=[],
fontSize=30,font=_df,width=None,height=None,
bg=(70,70,70),fg=(180,180,200),afg=(50,50,50),
abg=(200,200,200),borderColor=(50,50,50),borderWidth=5):
super()._args(locals())
self._generate()
def _generate(self, position=None):
self.surface = _s((255,self.width))
def draw(self, win, pos):
self._generate(pos)
win.blit(self.surface,pos)
class tip(widget):
def __init__(self,text,responceWidth,responceHeight,fontSize=15,font=_df,
borderColor=(180,180,50),borderWidth=2,bg=(255,255,128),
fg=(35,35,5),waitBeforeShowing=0,
tipPosRelativeCursor=(10,10)):
super()._args(locals())
self.tick = -1
self.lcp = (0,0)
self.tprc = self.tipPosRelativeCursor
self._generate()
def _generate(self, position=None):
self.surface = _s((self.responceWidth,
self.responceHeight))
if position != None:
self.tick += 1
if self.lcp != _m.getPosition():
self.tick = 0
self.lcp = _m.getPosition()
if self.tick >= self.waitBeforeShowing:
mp = _m.getPosition()
mp = [mp[0]+self.tprc[0]-position[0],
mp[1]+self.tprc[1]-position[1]]
rect = _r(mp[0],mp[1],
self.font.size(self.text,self.fontSize)[0]+4,
self.font.size(self.text,self.fontSize)[1]+6)
if mp[0]<0 or mp[1]<0:return
if mp[0]>self.responceWidth:return
if mp[1]>self.responceHeight:return
if mp[0]>self.responceWidth-rect.w:
mp[0]=self.responceWidth-rect.w
if mp[1]>self.responceHeight-rect.h:
mp[1]=self.responceHeight-rect.h
rect = _r(mp[0],mp[1],
self.font.size(self.text,self.fontSize)[0]+4,
self.font.size(self.text,self.fontSize)[1]+6)
self.surface.draw.rect(self.bg,rect)
self.surface.draw.rect(
self.borderColor,rect,self.borderWidth)
ts = self.font.render(
self.text,self.fontSize,self.fg)
self.surface.blit(ts,(mp[0]+2,mp[1]+3))
def draw(self, win, pos):
self._generate(pos)
win.blit(self.surface,pos)
class base:
def __init__(self, win, bg=(128,128,128)):
self._widgets = {}
self._bg = bg
self._win = win
self._page = 0
def draw(self):
self._win.fill(self._bg)
for i in self._widgets[self._page]:
if i[0].power:
i[0].draw(self._win, i[1])
if i[0].destroyed:
self._widgets[self._page].remove(i)
def put(self, widget, pos, page=0):
if page not in self._widgets:
self.blankPage(page)
self._widgets[page].append([widget, pos])
def selectPage(self, page):
self._page = page
def getPage(self):
return self._page
def getWidgets(self, page=0):
return self._widgets[page]
def setWidgetPos(self,index,pos,page=0):
self._widgets[page][index] = [self._widgets[page][index][0], pos]
def blankPage(self,page):
self._widgets.update({page:[]})