From 9d6c19cfd5537295f336985fe76978597c301334 Mon Sep 17 00:00:00 2001 From: Quinn Date: Tue, 27 Aug 2024 23:21:18 -0400 Subject: [PATCH] You can now generate many consecutive frames --- src/main.cpp | 3 +- tools/animation-tools/AnimationExporter.py | 4 +- tools/animation-tools/UI.py | 91 ++++++++++++++++++++++ tools/animation-tools/animation-tool.py | 50 +++--------- 4 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 tools/animation-tools/UI.py diff --git a/src/main.cpp b/src/main.cpp index 3728c34..91f810b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,7 +30,8 @@ TaskHandle_t updateCommunicaitonTask; TaskHandle_t updateBoardTask; -std::array*, 2> animations = { +// WARNING! This array size should always be equal to the number of entries in it!! +std::array*, 1> animations = { &RisingCubes::rising, // &RotatingCubes::rotating, }; diff --git a/tools/animation-tools/AnimationExporter.py b/tools/animation-tools/AnimationExporter.py index a267ad0..fdab606 100644 --- a/tools/animation-tools/AnimationExporter.py +++ b/tools/animation-tools/AnimationExporter.py @@ -68,7 +68,7 @@ def mesh_to_cell(mesh: Mesh) -> Cell: cell = Cell(pos, Vector3(mesh.face_color)) return cell -def scene_to_frame(scene: Scene) -> str: +def scene_to_frame(scene: Scene, scene_number: int) -> str: cells = [mesh_to_cell(cube) for cube in scene.meshes] frame = AnimationFrame(cells, FillInterpolation.NO_FILL, FrameInterpolation.FADE, 1000) - return frame.to_string(0) \ No newline at end of file + return frame.to_string(scene_number) \ No newline at end of file diff --git a/tools/animation-tools/UI.py b/tools/animation-tools/UI.py new file mode 100644 index 0000000..29f5935 --- /dev/null +++ b/tools/animation-tools/UI.py @@ -0,0 +1,91 @@ +from AnimationExporter import scene_to_frame +from CustomWidgets import ColorPicker +from itertools import product +from pygame_widgets.button import Button +import pygame_widgets +from Scene import Scene +from Shapes import * +import pygame + +class SceneManager: + def __init__(self, window, color_picker: ColorPicker): + self.file_data: str = "" + self._scenes: list[Scene] = [self.new_scene()] + self._current_scene_idx: int = 0 + self.window = window + self.color_picker = color_picker + self._selected_meshes: list[Mesh] = [] + self.make_buttons() + + def make_buttons(self): + scr_wdt, scr_hgt = self.window.get_size() + self.save_button = Button(self.window, 20, scr_hgt-40, 60, 30, text="Save",onClick=self.save_frame_to_file) + self.next_frame_button = Button(self.window, scr_wdt-120, scr_hgt-40, 120, 30, text="Next Frame",onClick=self.next_scene) + self.last_frame_button = Button(self.window, scr_wdt-240, scr_hgt-40, 120, 30, text="last Frame",onClick=self.previous_scene) + def save_frame_to_file(self): + with open("tools/animation-tools/output.txt", 'w') as file: + for i, scene in enumerate(self._scenes): + file.write(scene_to_frame(scene, i)) + + def generate_meshes(self) -> list[Mesh]: + # generate a list of cubes + meshes: list[Mesh] = [] + for origin in product([-1, 0, 1],[-1, 0, 1],[-1, 0, 1]): + cube = Cube() + cube.scale((0.35, 0.35, 0.35)) + cube.set_position(origin) + cube.set_face_color((0, 0, 0)) + meshes.append(cube) + return meshes + + def new_scene(self) -> Scene: + return Scene(self.generate_meshes(), 90, 5) + + def draw(self): + for mesh in self._selected_meshes: + mesh.set_face_color(self.color_picker.get_color()) + self.get_current_scene().draw(self.window) + + def get_current_scene(self) -> Scene: + return self._scenes[self._current_scene_idx] + + def click_mesh(self, coordinates: tuple[int, int]): + mesh = self.get_current_scene().get_mesh_from_xy(coordinates) + + if mesh == None: + return + + if mesh in self._selected_meshes: + mesh.set_edge_color((0,0,0)) + self._selected_meshes.remove(mesh) + else: + mesh.set_edge_color((255,0,0)) + self._selected_meshes.append(mesh) + + def deselect_all_mesh(self): + for mesh in self._selected_meshes: + mesh.set_edge_color((0,0,0)) + self._selected_meshes = [] + + def next_scene(self): + self.deselect_all_mesh() + current_angles = self.get_current_scene().euler_angles + if len(self._scenes)-1 == self._current_scene_idx: + self._scenes.append(self.new_scene()) + + self._current_scene_idx += 1 + + self.get_current_scene().euler_angles = [angle for angle in current_angles] + + def previous_scene(self): + if self._current_scene_idx > 0: + current_angles = self.get_current_scene().euler_angles + self._current_scene_idx -= 1 + self.get_current_scene().euler_angles = [angle for angle in current_angles] + self.deselect_all_mesh() + +def create_ui(window, scr_wdt, scr_hgt) -> SceneManager: + colorPicker = ColorPicker(window, 20, 20, 100, 300) + sceneManager = SceneManager(window, colorPicker) + + return sceneManager \ No newline at end of file diff --git a/tools/animation-tools/animation-tool.py b/tools/animation-tools/animation-tool.py index 5a5b58f..cbcb2ab 100644 --- a/tools/animation-tools/animation-tool.py +++ b/tools/animation-tools/animation-tool.py @@ -1,37 +1,20 @@ import pygame -from itertools import product import pygame_widgets from Shapes import * from Scene import Scene -from CustomWidgets import ColorPicker -from pygame_widgets.button import Button -from AnimationExporter import scene_to_frame - - -# generate a list of cubes -meshes: list[Mesh] = [] -for origin in product([-1, 0, 1],[-1, 0, 1],[-1, 0, 1]): - cube = Cube() - cube.scale((0.35, 0.35, 0.35)) - cube.set_position(origin) - cube.set_face_color((0, 0, 0)) - meshes.append(cube) - -scene = Scene(meshes, 90, 5) +from UI import create_ui, SceneManager WINDOW_W = 500 WINDOW_H = 500 -def save_frame_to_file(frame_data=""): - frame_data += scene_to_frame(scene) - print(frame_data) - with open("tools/animation-tools/output.txt", 'w') as file: - file.write(frame_data) + +file_data = "" pygame.init() window = pygame.display.set_mode((WINDOW_W, WINDOW_H)) -colorPicker = ColorPicker(window, 20, 20, 100, 300) -save_button = Button(window, 20, WINDOW_H-40, 60, 30, text="Save",onClick=save_frame_to_file) + +sceneManager: SceneManager = create_ui(window, WINDOW_W, WINDOW_H) + clock = pygame.time.Clock() selected_meshes = [] run = True @@ -40,6 +23,7 @@ trackMouseMotion = False while run: clock.tick(60) window.fill((255, 255, 255)) + current_scene: Scene = sceneManager.get_current_scene() events = pygame.event.get() for event in events: if event.type == pygame.QUIT: @@ -48,33 +32,21 @@ while run: if event.button == 2: # middle mouse click trackMouseMotion = True elif event.button == 1: # left click - mousePosition = pygame.mouse.get_pos() - mesh = scene.get_mesh_from_xy(mousePosition) - if mesh != None: - if mesh in selected_meshes: - mesh.set_edge_color((0,0,0)) - selected_meshes.remove(mesh) - else: - mesh.set_edge_color((255,0,0)) - selected_meshes.append(mesh) - - pass + sceneManager.click_mesh(pygame.mouse.get_pos()) elif event.type == pygame.MOUSEBUTTONUP: if event.button == 2: # middle mouse release trackMouseMotion = False elif trackMouseMotion and event.type == pygame.MOUSEMOTION: mouseMovement = pygame.mouse.get_rel() - scene.euler_angles[0] -= mouseMovement[1] - scene.euler_angles[1] -= mouseMovement[0] + current_scene.euler_angles[0] -= mouseMovement[1] + current_scene.euler_angles[1] -= mouseMovement[0] pygame_widgets.update(events) if not trackMouseMotion: pygame.mouse.get_rel() - for mesh in selected_meshes: - mesh.set_face_color(colorPicker.get_color()) - scene.draw(window) + sceneManager.draw() pygame.display.flip() pygame.quit() \ No newline at end of file