diff --git a/pulsar/numerator.py b/pulsar/numerator.py new file mode 100644 index 0000000..e69de29 diff --git a/pulsar/src/dock/angle_limit.png b/pulsar/src/dock/angle_limit.png new file mode 100644 index 0000000..31a0224 Binary files /dev/null and b/pulsar/src/dock/angle_limit.png differ diff --git a/pulsar/src/dock/drop_indicator.png b/pulsar/src/dock/drop_indicator.png new file mode 100644 index 0000000..b704d50 Binary files /dev/null and b/pulsar/src/dock/drop_indicator.png differ diff --git a/pulsar/src/dock/extremis.png b/pulsar/src/dock/extremis.png new file mode 100644 index 0000000..1106272 Binary files /dev/null and b/pulsar/src/dock/extremis.png differ diff --git a/pulsar/src/dock/landing_mode.png b/pulsar/src/dock/landing_mode.png new file mode 100644 index 0000000..5e7eae2 Binary files /dev/null and b/pulsar/src/dock/landing_mode.png differ diff --git a/pulsar/src/dock/recording_indicator.png b/pulsar/src/dock/recording_indicator.png new file mode 100644 index 0000000..b8c8d48 Binary files /dev/null and b/pulsar/src/dock/recording_indicator.png differ diff --git a/pulsar/src/dock/sync_indicator.png b/pulsar/src/dock/sync_indicator.png new file mode 100644 index 0000000..da155c5 Binary files /dev/null and b/pulsar/src/dock/sync_indicator.png differ diff --git a/testfield/vgl/aux.py b/testfield/vgl/aux.py deleted file mode 100644 index 66e6879..0000000 --- a/testfield/vgl/aux.py +++ /dev/null @@ -1,113 +0,0 @@ -def generate_shape_dict(shape, **kwargs): - if shape == 'rect': - return { - 'method': 'rect', - 'pos': kwargs.get('pos', (0, 0)), - 'size': kwargs.get('size', (1, 1)), - 'color': kwargs.get('color', (255, 255, 255)), - 'width': kwargs.get('width', 0) # 添加边框宽度 - } - elif shape == 'line': - return { - 'method': 'line', - 'start_pos': kwargs.get('start_pos', (0, 0)), - 'end_pos': kwargs.get('end_pos', (1, 1)), - 'color': kwargs.get('color', (255, 255, 255)) - } - elif shape == 'circle': - return { - 'method': 'circle', - 'center': kwargs.get('center', (0, 0)), - 'radius': kwargs.get('radius', 1), - 'color': kwargs.get('color', (255, 255, 255)) - } - elif shape == 'ellipse': - return { - 'method': 'ellipse', - 'pos': kwargs.get('pos', (0, 0)), - 'size': kwargs.get('size', (1, 1)), - 'color': kwargs.get('color', (255, 255, 255)) - } - elif shape == 'polygon': - return { - 'method': 'polygon', - 'pointlist': kwargs.get('pointlist', []), - 'color': kwargs.get('color', (255, 255, 255)) - } - elif shape == 'arc': - return { - 'method': 'arc', - 'pos': kwargs.get('pos', (0, 0)), - 'size': kwargs.get('size', (1, 1)), - 'color': kwargs.get('color', (255, 255, 255)), - 'start_angle': kwargs.get('start_angle', 0), - 'stop_angle': kwargs.get('stop_angle', 3.14) - } - elif shape == 'point': - return { - 'method': 'point', - 'pos': kwargs.get('pos', (0, 0)), - 'color': kwargs.get('color', (255, 255, 255)) - } - elif shape == 'lines': - return { - 'method': 'lines', - 'pointlist': kwargs.get('pointlist', []), - 'color': kwargs.get('color', (255, 255, 255)) - } - else: - raise ValueError("Unsupported shape type") - -def main(): - print("欢迎使用图形参数生成器!") - shape = input("请输入图形类型 (rect, line, circle, ellipse, polygon, arc, point, lines): ").strip().lower() - - params = {} - - if shape == 'rect': - params['pos'] = tuple(map(int, input("请输入矩形位置 (x y): ").split())) - params['size'] = tuple(map(int, input("请输入矩形大小 (width height): ").split())) - params['color'] = tuple(map(int, input("请输入矩形颜色 (R G B): ").split())) - params['width'] = int(input("请输入矩形边框宽度: ")) # 添加边框宽度输入 - elif shape == 'line': - params['start_pos'] = tuple(map(int, input("请输入起始位置 (x y): ").split())) - params['end_pos'] = tuple(map(int, input("请输入结束位置 (x y): ").split())) - params['color'] = tuple(map(int, input("请输入线条颜色 (R G B): ").split())) - elif shape == 'circle': - params['center'] = tuple(map(int, input("请输入圆心位置 (x y): ").split())) - params['radius'] = int(input("请输入圆的半径: ")) - params['color'] = tuple(map(int, input("请输入圆的颜色 (R G B): ").split())) - elif shape == 'ellipse': - params['pos'] = tuple(map(int, input("请输入椭圆位置 (x y): ").split())) - params['size'] = tuple(map(int, input("请输入椭圆大小 (width height): ").split())) - params['color'] = tuple(map(int, input("请输入椭圆颜色 (R G B): ").split())) - elif shape == 'polygon': - points = input("请输入多边形的点 (x1 y1 x2 y2 ...): ").split() - params['pointlist'] = [(int(points[i]), int(points[i + 1])) for i in range(0, len(points), 2)] - params['color'] = tuple(map(int, input("请输入多边形颜色 (R G B): ").split())) - elif shape == 'arc': - params['pos'] = tuple(map(int, input("请输入弧的位置 (x y): ").split())) - params['size'] = tuple(map(int, input("请输入弧的大小 (width height): ").split())) - params['color'] = tuple(map(int, input("请输入弧的颜色 (R G B): ").split())) - params['start_angle'] = float(input("请输入弧的起始角度 (弧度制): ")) - params['stop_angle'] = float(input("请输入弧的结束角度 (弧度制): ")) - elif shape == 'point': - params['pos'] = tuple(map(int, input("请输入点的位置 (x y): ").split())) - params['color'] = tuple(map(int, input("请输入点的颜色 (R G B): ").split())) - elif shape == 'lines': - points = input("请输入线段的点 (x1 y1 x2 y2 ...): ").split() - params['pointlist'] = [(int(points[i]), int(points[i + 1])) for i in range(0, len(points), 2)] - params['color'] = tuple(map(int, input("请输入线段颜色 (R G B): ").split())) - else: - print("不支持的图形类型") - return - - # 生成图形字典 - shape_dict = generate_shape_dict(shape, **params) - - # 输出结果 - print("生成的图形参数字典:") - print(shape_dict) - -if __name__ == "__main__": - main() diff --git a/testfield/vgl/default.vgld b/testfield/vgl/default.vgld deleted file mode 100644 index c47953e..0000000 --- a/testfield/vgl/default.vgld +++ /dev/null @@ -1,31 +0,0 @@ -{'method': 'rect', 'pos': (12, 45), 'size': (25, 15), 'color': (34, 200, 150)} -{'method': 'rect', 'pos': (67, 22), 'size': (18, 28), 'color': (255, 100, 50)} -{'method': 'rect', 'pos': (5, 78), 'size': (30, 20), 'color': (0, 0, 255)} -{'method': 'rect', 'pos': (90, 10), 'size': (15, 25), 'color': (200, 50, 100)} -{'method': 'rect', 'pos': (33, 60), 'size': (20, 30), 'color': (150, 200, 255)} -{'method': 'rect', 'pos': (50, 50), 'size': (10, 10), 'color': (255, 0, 0)} -{'method': 'rect', 'pos': (80, 40), 'size': (22, 18), 'color': (100, 255, 100)} -{'method': 'rect', 'pos': (15, 15), 'size': (28, 12), 'color': (255, 255, 0)} -{'method': 'rect', 'pos': (70, 70), 'size': (20, 20), 'color': (0, 255, 255)} -{'method': 'rect', 'pos': (40, 30), 'size': (25, 25), 'color': (255, 0, 255)} -{'method': 'rect', 'pos': (24, 88), 'size': (15, 25), 'color': (123, 45, 67)} -{'method': 'rect', 'pos': (56, 12), 'size': (20, 30), 'color': (200, 150, 100)} -{'method': 'rect', 'pos': (3, 55), 'size': (10, 20), 'color': (0, 128, 255)} -{'method': 'rect', 'pos': (77, 33), 'size': (18, 18), 'color': (255, 165, 0)} -{'method': 'rect', 'pos': (39, 72), 'size': (22, 14), 'color': (75, 0, 130)} -{'method': 'rect', 'pos': (90, 5), 'size': (30, 10), 'color': (255, 20, 147)} -{'method': 'rect', 'pos': (11, 44), 'size': (25, 25), 'color': (135, 206, 235)} -{'method': 'rect', 'pos': (62, 29), 'size': (15, 15), 'color': (255, 99, 71)} -{'method': 'rect', 'pos': (48, 60), 'size': (20, 20), 'color': (0, 255, 127)} -{'method': 'rect', 'pos': (34, 10), 'size': (28, 12), 'color': (255, 228, 196)} -{'method': 'rect', 'pos': (70, 80), 'size': (12, 22), 'color': (255, 0, 0)} -{'method': 'rect', 'pos': (15, 15), 'size': (20, 30), 'color': (0, 0, 0)} -{'method': 'rect', 'pos': (88, 44), 'size': (18, 18), 'color': (255, 215, 0)} -{'method': 'rect', 'pos': (5, 90), 'size': (30, 20), 'color': (0, 0, 139)} -{'method': 'rect', 'pos': (40, 40), 'size': (25, 25), 'color': (255, 105, 180)} -{'method': 'rect', 'pos': (60, 20), 'size': (15, 25), 'color': (255, 140, 0)} -{'method': 'rect', 'pos': (20, 70), 'size': (22, 18), 'color': (0, 191, 255)} -{'method': 'rect', 'pos': (30, 30), 'size': (10, 10), 'color': (255, 20, 147)} -{'method': 'rect', 'pos': (75, 50), 'size': (20, 20), 'color': (255, 0, 255)} -{'method': 'rect', 'pos': (10, 10), 'size': (28, 12), 'color': (128, 0, 128)} -{'method': 'rect', 'pos': (45, 55), 'size': (15, 15), 'color': (255, 69, 0)} \ No newline at end of file diff --git a/testfield/vgl/elements/ basic.py b/testfield/vgl/elements/ basic.py new file mode 100644 index 0000000..3810c12 --- /dev/null +++ b/testfield/vgl/elements/ basic.py @@ -0,0 +1,51 @@ +from vgllib import * +import pygame +import time +class Line(Element): + angle = None + def move(self, delta, duration): + self.add_task(group = "move", start_time = Aux.gettime(), duration = duration, delta = delta) + def update(self): + for i in self.tasks.get("move", []): + self.teleport(Aux.tuple_scale(tup = i['delta'], mul = Aux.getprogress(i))) +class Graph: + @staticmethod + def rect(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0): + pygame.draw.rect(frame.surface, color=color, rect=(pos[0], pos[1], size[0], size[1]), width=width) + + @staticmethod + def line(frame, start_pos: tuple, end_pos: tuple, color: tuple = (255, 255, 255)): + pygame.draw.aaline(frame.surface, color, start_pos, end_pos) + + @staticmethod + def circle(frame, center: tuple, radius: int, color: tuple = (255, 255, 255), width: int = 0): + pygame.draw.circle(frame.surface, color, center, radius, width) + + @staticmethod + def ellipse(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0): + rect=(pos[0], pos[1], size[0], size[1]) + pygame.draw.ellipse(frame.surface, color, rect, width) + + @staticmethod + def polygon(frame, pointlist: list, color: tuple = (255, 255, 255), width: int = 0): + pygame.draw.polygon(frame.surface, color, pointlist, width) + + @staticmethod + def arc(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), start_angle: float = 0, stop_angle: float = 3.14, width: int = 1): + rect=(pos[0], pos[1], size[0], size[1]) + pygame.draw.arc(frame.surface, color, rect, start_angle, stop_angle, width) + + @staticmethod + def point(frame, pos: tuple, color: tuple = (255, 255, 255)): + pygame.draw.point(frame.surface, color, pos) + + @staticmethod + def lines(frame, pointlist: list, color: tuple = (255, 255, 255)): + pygame.draw.aalines(frame.surface, color, closed=False, points=pointlist) + + @staticmethod + def call(frame, method, **kwargs): + if hasattr(Graph, method): + getattr(Graph, method)(frame, **kwargs) + else: + print(f"方法 {method} 不存在") \ No newline at end of file diff --git a/testfield/vgl/test.py b/testfield/vgl/test.py index 4b85888..e69de29 100644 --- a/testfield/vgl/test.py +++ b/testfield/vgl/test.py @@ -1,26 +0,0 @@ -import pygame -import sys -from testfield.vgl.vgllib import * -pygame.init() -window_size = (800, 600) -window = pygame.display.set_mode(window_size) - -frame = Frame("Main Frame", window_size) - -# 注册一个矩形组件 -frame.register("rectangle", {"method": "rect", "pos": (100, 100), "size": (200, 150), "color": (255, 0, 0)}) - -# 注册一个圆形组件 -frame.register("circle", {"method": "circle", "center": (400, 300), "radius": 50, "color": (0, 255, 0)}) - -# 主循环 -while True: - for event in pygame.event.get(): - if event.type == pygame.QUIT: - pygame.quit() - sys.exit() - - window.fill((0, 0, 0)) # 清空窗口 - frame.drawall(frame.components) # 绘制所有组件 - frame.show(window, (0, 0)) # 显示框架 - pygame.display.flip() # 更新显示 diff --git a/testfield/vgl/vgllib old.py b/testfield/vgl/vgllib old.py new file mode 100644 index 0000000..46b1317 --- /dev/null +++ b/testfield/vgl/vgllib old.py @@ -0,0 +1,189 @@ +# Vector Graphics Library +# vgllib.py +import pygame +import uuid +import time +import threading +import math + +class Graph: + @staticmethod + def rect(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0): + pygame.draw.rect(frame.surface, color=color, rect=(pos[0], pos[1], size[0], size[1]), width=width) + + @staticmethod + def line(frame, start_pos: tuple, end_pos: tuple, color: tuple = (255, 255, 255)): + pygame.draw.aaline(frame.surface, color, start_pos, end_pos) + + @staticmethod + def circle(frame, center: tuple, radius: int, color: tuple = (255, 255, 255), width: int = 0): + pygame.draw.circle(frame.surface, color, center, radius, width) + + @staticmethod + def ellipse(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0): + rect=(pos[0], pos[1], size[0], size[1]) + pygame.draw.ellipse(frame.surface, color, rect, width) + + @staticmethod + def polygon(frame, pointlist: list, color: tuple = (255, 255, 255), width: int = 0): + pygame.draw.polygon(frame.surface, color, pointlist, width) + + @staticmethod + def arc(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), start_angle: float = 0, stop_angle: float = 3.14, width: int = 1): + rect=(pos[0], pos[1], size[0], size[1]) + pygame.draw.arc(frame.surface, color, rect, start_angle, stop_angle, width) + + @staticmethod + def point(frame, pos: tuple, color: tuple = (255, 255, 255)): + pygame.draw.point(frame.surface, color, pos) + + @staticmethod + def lines(frame, pointlist: list, color: tuple = (255, 255, 255)): + pygame.draw.aalines(frame.surface, color, closed=False, points=pointlist) + + @staticmethod + def call(frame, method, **kwargs): + if hasattr(Graph, method): + getattr(Graph, method)(frame, **kwargs) + else: + print(f"方法 {method} 不存在") + +class Frame(object): + components = dict() + components_stat = dict() + render_thread = None + motion_queue = list() + def __init__(self, name: str, size: tuple): + self.name = name + self.size = size + self.surface = pygame.Surface(size, flags=pygame.HWSURFACE) + self.is_hide = False + print("初始化子模块") + self.render_thread = threading.Thread(target=self.render) + print("启动图形渲染子线程") + self.render_thread.start() + + def move(self, subname, direction, length, duration = 0, effect="linear"): # our powerful move! + # direction: 使用角度制, 以直角笛卡尔坐标系的x正半轴方向为0度, 逆时针为加, 接受负数 + # length: 百分数 + # duration: "动画"时间, 为0则即时 + # effect: "动画"效果, linear为线性移动, 或许会在未来增加贝塞尔曲线 + # TODO: 增加 bezier 曲线 + if duration == 0: + self.components[subname]["pos"][0] += math.cos(math.radians(direction)) * length / 100 * self.size[0] + self.components[subname]["pos"][1] += math.sin(math.radians(direction)) * length / 100 * self.size[1] + return + self.motion_queue.append({"subname":subname, "direction":direction, "length":length, "start":round(time.time(), 1), "duration":duration, "effect":"linear"}) + + def render(self): + while 1: + rest = list() + while self.motion_queue: + i = self.motion_queue.pop(0) # 从队列的开头移除元素 + self.move(subname=i['subname'], direction=i['direction'], + length=((time.time() - i['start']) / i['duration']) * i['length'], + duration=0) + if ((time.time() - i['start']) / i['duration']) > 0: + i['start'] = time.time() + i['duration'] -= (time.time() - i['start']) + rest.append(i) + self.draw_all() + self.motion_queue = rest + time.sleep(0.1) + + + def show(self, window, position: tuple): + if not self.is_hide: + window.blit(self.surface, position) + + def set_visible(self, newstat=True): + self.is_hide = newstat + + def set_position(self, newposition): + self.position = newposition + + def register(self, subname="", attr=None): + if subname == "": + subname = uuid.uuid4() + # use percent of frame size instead of pixels :) + attr['pos'] = list(attr['pos']) + attr['pos'][0] = round(attr['pos'][0] / 100 * self.size[0]) + attr['pos'][1] = round(attr['pos'][1] / 100 * self.size[1]) + attr['size'] = list(attr['size']) + attr['size'][0] = round(attr['size'][0] / 100 * self.size[0]) + attr['size'][1] = round(attr['size'][1] / 100 * self.size[1]) + self.components[subname] = attr + self.components_stat[subname] = 1 # by default, not hiding + + def draw(self, attr): + Graph.call(self, **attr) + + def set_component_visible(self, subname, newstat): + self.components_stat[subname] = newstat + + def draw_all(self): + for i in self.components.keys(): + if self.components_stat[i]: + self.draw(self.components[i]) + + def refresh(self, color=(0,0,0)): + self.surface.fill(color) + + def clear(self): + components = dict() + components_stat = dict() + + def loads(self, grap_str): + # TODO: 将会重写 以替代不安全的 eval + self.register(subname="", attr=(eval(grap_str))) + + def load(self, file="default.vgld", mode="a"): + # a: 增量加载 (默认) + # w: 覆盖式加载 + # 文件扩展名: vgld (矢量图形层描述文件) + if mode == 'w': + self.clear() + with open(file=file, mode="r+", encoding="UTF-8") as f: + for i in f.readlines(): + #print(i) + self.loads(i) + + +# 示例 +if __name__ == "__main__": + frame = None + def grap(): + global frame + pygame.init() + window = pygame.display.set_mode((1200, 900)) + frame = Frame("Test", (1200, 900)) + #frame.load() + frame.register(subname="test", attr={'method': 'rect', 'pos': (33, 33), 'size': (50, 50), 'color': (255, 255, 255)}) + #frame.move(subname='test', direction=0, length=90, duration=1, effect="linear") + running = True + while running: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + + window.fill((0, 0, 0)) + frame.show(window, (0, 0)) + pygame.display.flip() + pygame.time.delay(10) + pygame.quit() + def debug(): + global frame + while 1: + try: + e = input(">>>") + if e == "f": + e = "frame.move(subname='test', direction=0, length=3, duration=1, effect='linear')" + if e == "g": + e = "frame.move(subname='test', direction=180, length=3, duration=1, effect='linear')" + exec(e) + except: + print("ER") + grap_thd = threading.Thread(target=grap) + debug_thd = threading.Thread(target=debug) + grap_thd.start() + debug_thd.start() \ No newline at end of file diff --git a/testfield/vgl/vgllib.py b/testfield/vgl/vgllib.py index 46b1317..3edc89e 100644 --- a/testfield/vgl/vgllib.py +++ b/testfield/vgl/vgllib.py @@ -5,185 +5,85 @@ import uuid import time import threading import math +import copy -class Graph: - @staticmethod - def rect(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0): - pygame.draw.rect(frame.surface, color=color, rect=(pos[0], pos[1], size[0], size[1]), width=width) - - @staticmethod - def line(frame, start_pos: tuple, end_pos: tuple, color: tuple = (255, 255, 255)): - pygame.draw.aaline(frame.surface, color, start_pos, end_pos) - - @staticmethod - def circle(frame, center: tuple, radius: int, color: tuple = (255, 255, 255), width: int = 0): - pygame.draw.circle(frame.surface, color, center, radius, width) - - @staticmethod - def ellipse(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), width: int = 0): - rect=(pos[0], pos[1], size[0], size[1]) - pygame.draw.ellipse(frame.surface, color, rect, width) - - @staticmethod - def polygon(frame, pointlist: list, color: tuple = (255, 255, 255), width: int = 0): - pygame.draw.polygon(frame.surface, color, pointlist, width) - - @staticmethod - def arc(frame, pos: tuple = (0, 0), size: tuple = (1, 1), color: tuple = (255, 255, 255), start_angle: float = 0, stop_angle: float = 3.14, width: int = 1): - rect=(pos[0], pos[1], size[0], size[1]) - pygame.draw.arc(frame.surface, color, rect, start_angle, stop_angle, width) - - @staticmethod - def point(frame, pos: tuple, color: tuple = (255, 255, 255)): - pygame.draw.point(frame.surface, color, pos) - - @staticmethod - def lines(frame, pointlist: list, color: tuple = (255, 255, 255)): - pygame.draw.aalines(frame.surface, color, closed=False, points=pointlist) - - @staticmethod - def call(frame, method, **kwargs): - if hasattr(Graph, method): - getattr(Graph, method)(frame, **kwargs) - else: - print(f"方法 {method} 不存在") +class Aux(): + def gettime(): + return round(time.time(), 1) + def getprogress(task): + return (Aux.gettime() - task["start"] / task["duration"]) + def tuple_scale(tup, mul): + return (tup[0]*mul, tup[1]*mul) +class Element(object): + poscale: tuple = (0, 0) + is_hide = False + is_template = True + attached = None + tasks = dict() + def __init__(self, name="Element"): + self.name = name + def attach(self, clone_name, frame_object, poscale): + if clone_name == "": + clone_name = str(uuid.uuid4()) + clone = copy.deepcopy(self) + clone.poscale = poscale + clone.is_template = False + frame_object.elements[clone_name] = clone + def teleport(self, delta: tuple): + if not self.is_template: + self.poscale[0] += delta[0] + self.poscale[1] += delta[1] + def add_task(self, group, start_time, duration, **kwargs): + if group not in self.tasks(): + self.tasks[group] = list() + self.tasks[group].append({"start": start_time, "duration":duration, "para":kwargs}) + def update(): + pass class Frame(object): - components = dict() - components_stat = dict() - render_thread = None - motion_queue = list() - def __init__(self, name: str, size: tuple): + elements = dict() + is_hide = False + is_template = True + poscale: tuple = (0, 0) # 左上角, 对于每个实例的位置矢量 + def __init__(self, name="Frame", scale: tuple=(1, 1)): self.name = name + self.scale = scale + def attach(self, clone_name, window_object, poscale): + if clone_name == "": + clone_name = str(uuid.uuid4()) + clone = copy.deepcopy(self) + clone.poscale = poscale + clone.is_template = False + window_object.frames[clone_name] = clone + def render(): + pass + +class Window(object): + frames = list() + def __init__(self, title="Vector Graphic Layer Window", size: tuple=(1024,768)): + self.title = title self.size = size - self.surface = pygame.Surface(size, flags=pygame.HWSURFACE) - self.is_hide = False - print("初始化子模块") - self.render_thread = threading.Thread(target=self.render) - print("启动图形渲染子线程") - self.render_thread.start() - - def move(self, subname, direction, length, duration = 0, effect="linear"): # our powerful move! - # direction: 使用角度制, 以直角笛卡尔坐标系的x正半轴方向为0度, 逆时针为加, 接受负数 - # length: 百分数 - # duration: "动画"时间, 为0则即时 - # effect: "动画"效果, linear为线性移动, 或许会在未来增加贝塞尔曲线 - # TODO: 增加 bezier 曲线 - if duration == 0: - self.components[subname]["pos"][0] += math.cos(math.radians(direction)) * length / 100 * self.size[0] - self.components[subname]["pos"][1] += math.sin(math.radians(direction)) * length / 100 * self.size[1] - return - self.motion_queue.append({"subname":subname, "direction":direction, "length":length, "start":round(time.time(), 1), "duration":duration, "effect":"linear"}) - - def render(self): - while 1: - rest = list() - while self.motion_queue: - i = self.motion_queue.pop(0) # 从队列的开头移除元素 - self.move(subname=i['subname'], direction=i['direction'], - length=((time.time() - i['start']) / i['duration']) * i['length'], - duration=0) - if ((time.time() - i['start']) / i['duration']) > 0: - i['start'] = time.time() - i['duration'] -= (time.time() - i['start']) - rest.append(i) - self.draw_all() - self.motion_queue = rest - time.sleep(0.1) - - - def show(self, window, position: tuple): - if not self.is_hide: - window.blit(self.surface, position) - - def set_visible(self, newstat=True): - self.is_hide = newstat - - def set_position(self, newposition): - self.position = newposition - - def register(self, subname="", attr=None): - if subname == "": - subname = uuid.uuid4() - # use percent of frame size instead of pixels :) - attr['pos'] = list(attr['pos']) - attr['pos'][0] = round(attr['pos'][0] / 100 * self.size[0]) - attr['pos'][1] = round(attr['pos'][1] / 100 * self.size[1]) - attr['size'] = list(attr['size']) - attr['size'][0] = round(attr['size'][0] / 100 * self.size[0]) - attr['size'][1] = round(attr['size'][1] / 100 * self.size[1]) - self.components[subname] = attr - self.components_stat[subname] = 1 # by default, not hiding - - def draw(self, attr): - Graph.call(self, **attr) - - def set_component_visible(self, subname, newstat): - self.components_stat[subname] = newstat - - def draw_all(self): - for i in self.components.keys(): - if self.components_stat[i]: - self.draw(self.components[i]) - - def refresh(self, color=(0,0,0)): - self.surface.fill(color) - - def clear(self): - components = dict() - components_stat = dict() - - def loads(self, grap_str): - # TODO: 将会重写 以替代不安全的 eval - self.register(subname="", attr=(eval(grap_str))) - - def load(self, file="default.vgld", mode="a"): - # a: 增量加载 (默认) - # w: 覆盖式加载 - # 文件扩展名: vgld (矢量图形层描述文件) - if mode == 'w': - self.clear() - with open(file=file, mode="r+", encoding="UTF-8") as f: - for i in f.readlines(): - #print(i) - self.loads(i) - - -# 示例 -if __name__ == "__main__": - frame = None - def grap(): - global frame + self.running = 1 pygame.init() - window = pygame.display.set_mode((1200, 900)) - frame = Frame("Test", (1200, 900)) - #frame.load() - frame.register(subname="test", attr={'method': 'rect', 'pos': (33, 33), 'size': (50, 50), 'color': (255, 255, 255)}) - #frame.move(subname='test', direction=0, length=90, duration=1, effect="linear") - running = True - while running: + self.window = pygame.display.set_mode(size) + pygame.display.set_caption(title) + def set_title(self, title): + self.title = title + pygame.display.set_caption(title) + def start(self): + self.thr = threading.Thread(target=self.main_loop, name="main_loop") + self.thr.start() + def kill(self): + self.running = 0 + def main_loop(self): + while self.running: for event in pygame.event.get(): if event.type == pygame.QUIT: - running = False - - window.fill((0, 0, 0)) - frame.show(window, (0, 0)) + self.running = 0 + self.window.fill((0, 0, 0)) pygame.display.flip() pygame.time.delay(10) pygame.quit() - def debug(): - global frame - while 1: - try: - e = input(">>>") - if e == "f": - e = "frame.move(subname='test', direction=0, length=3, duration=1, effect='linear')" - if e == "g": - e = "frame.move(subname='test', direction=180, length=3, duration=1, effect='linear')" - exec(e) - except: - print("ER") - grap_thd = threading.Thread(target=grap) - debug_thd = threading.Thread(target=debug) - grap_thd.start() - debug_thd.start() \ No newline at end of file + +if __name__ == "__main__": + pass \ No newline at end of file