Compare commits
3 Commits
78cf579e0f
...
974ed1de0b
| Author | SHA1 | Date | |
|---|---|---|---|
| 974ed1de0b | |||
| 8025514ab3 | |||
| 095a18b0ea |
3
.idea/workspace.xml
generated
3
.idea/workspace.xml
generated
@ -6,9 +6,12 @@
|
|||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="ae2847d5-ce86-4d84-8e66-f1369f1438e2" name="Changes" comment="">
|
<list default="true" id="ae2847d5-ce86-4d84-8e66-f1369f1438e2" name="Changes" comment="">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/controller/controller.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/controller/controller.py" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/controller/window.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/controller/window.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/entry.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/entry.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/entry.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/entry.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/projection/screen.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/projection/screen.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/projection/screen.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/projection/screen.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/resources/objects.yml" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/resources/objects.yml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/resources/objects.yml" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/resources/objects.yml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/starsky_presenter/resources/scenes.yml" beforeDir="false" afterPath="$PROJECT_DIR$/src/starsky_presenter/resources/scenes.yml" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
|||||||
@ -4,12 +4,13 @@ from time import time
|
|||||||
|
|
||||||
|
|
||||||
class Controller(QObject):
|
class Controller(QObject):
|
||||||
def __init__(self, window, screen, parent=None):
|
def __init__(self, window, screen, max_scene, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.window = window
|
self.window = window
|
||||||
self.last_close_press = 0
|
self.last_close_press = 0
|
||||||
self.successful_clicks = 0
|
self.successful_clicks = 0
|
||||||
self.screen = screen
|
self.screen = screen
|
||||||
|
self.max_scene = max_scene
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def close_application(self):
|
def close_application(self):
|
||||||
@ -26,6 +27,8 @@ class Controller(QObject):
|
|||||||
|
|
||||||
@pyqtSlot(int)
|
@pyqtSlot(int)
|
||||||
def select_scene(self, scene: int):
|
def select_scene(self, scene: int):
|
||||||
|
if scene >= self.max_scene:
|
||||||
|
return
|
||||||
self.screen.last_scene = self.screen.active_scene
|
self.screen.last_scene = self.screen.active_scene
|
||||||
self.screen.active_scene = scene
|
self.screen.active_scene = scene
|
||||||
self.screen.scene_time = 0
|
self.screen.scene_time = 0
|
||||||
@ -8,12 +8,12 @@ from starsky_presenter.projection.screen import Screen
|
|||||||
|
|
||||||
|
|
||||||
class ControlWindow:
|
class ControlWindow:
|
||||||
def __init__(self, screen):
|
def __init__(self, screen, max_scene):
|
||||||
self.app = QGuiApplication([])
|
self.app = QGuiApplication([])
|
||||||
self.running = True
|
self.running = True
|
||||||
|
|
||||||
self.engine = QQmlApplicationEngine(self.app)
|
self.engine = QQmlApplicationEngine(self.app)
|
||||||
self.controller = Controller(self, screen)
|
self.controller = Controller(self, screen, max_scene)
|
||||||
self.engine.quit.connect(self.app.quit)
|
self.engine.quit.connect(self.app.quit)
|
||||||
self.engine.rootContext().setContextProperty("controller_backend", self.controller)
|
self.engine.rootContext().setContextProperty("controller_backend", self.controller)
|
||||||
self.engine.load(f"{Path(__file__).parent.parent}/resources/main_window.qml")
|
self.engine.load(f"{Path(__file__).parent.parent}/resources/main_window.qml")
|
||||||
|
|||||||
@ -6,6 +6,7 @@ from importlib.readers import FileReader
|
|||||||
from importlib.machinery import SourcelessFileLoader
|
from importlib.machinery import SourcelessFileLoader
|
||||||
from io import BufferedReader
|
from io import BufferedReader
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from time import time
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
from random import random, seed
|
from random import random, seed
|
||||||
@ -29,22 +30,28 @@ def cli_main():
|
|||||||
scenes = yaml.safe_load(reader.open_resource('resources/scenes.yml'))
|
scenes = yaml.safe_load(reader.open_resource('resources/scenes.yml'))
|
||||||
objects = yaml.safe_load(reader.open_resource('resources/objects.yml'))
|
objects = yaml.safe_load(reader.open_resource('resources/objects.yml'))
|
||||||
|
|
||||||
scene_data = [{ obj['sid']: deepcopy(obj) for obj in objects["stars"] }] + [
|
scene_data = [
|
||||||
{ obj['sid']: dict_update(obj, scenes[i][obj['sid']]) if scenes[i] and obj['sid'] in scenes[i] else deepcopy(obj) for obj in objects["stars"] }
|
dict_update(
|
||||||
|
{ obj['sid']: dict_update(obj, scenes[i][obj['sid']]) if scenes[i] and obj['sid'] in scenes[i] else deepcopy(obj) for obj in objects["stars"] },
|
||||||
|
{
|
||||||
|
'transition': scenes[i]['transition'],
|
||||||
|
}
|
||||||
|
)
|
||||||
if i < len(scenes) else { obj['sid']: deepcopy(obj) for obj in objects["stars"] }
|
if i < len(scenes) else { obj['sid']: deepcopy(obj) for obj in objects["stars"] }
|
||||||
for i in range(0,8)
|
for i in range(0,9)
|
||||||
]
|
]
|
||||||
|
|
||||||
star_references = {}
|
star_references = {}
|
||||||
|
|
||||||
print(json.dumps(scenes, indent=4))
|
#print(json.dumps(scenes, indent=4))
|
||||||
print(json.dumps(objects, indent=4))
|
#print(json.dumps(objects, indent=4))
|
||||||
print(json.dumps(scene_data, indent=4))
|
#print(json.dumps(scene_data, indent=4))
|
||||||
|
|
||||||
def setup_star_instance(data: dict) -> Star:
|
def setup_star_instance(data: dict) -> Star:
|
||||||
image_path = f"resources/{data['image']}"
|
image_path = f"resources/{data['image']}"
|
||||||
image = pygame.image.load(reader.open_resource(image_path))
|
image = pygame.image.load(reader.open_resource(image_path))
|
||||||
data['image'] = image
|
data['image'] = image
|
||||||
|
|
||||||
star = Star(**data)
|
star = Star(**data)
|
||||||
star_references[data['sid']] = star
|
star_references[data['sid']] = star
|
||||||
return star
|
return star
|
||||||
@ -55,16 +62,31 @@ def cli_main():
|
|||||||
# load the background image
|
# load the background image
|
||||||
background = pygame.image.load(reader.open_resource(f"resources/{objects['background']}"))
|
background = pygame.image.load(reader.open_resource(f"resources/{objects['background']}"))
|
||||||
|
|
||||||
screen = Screen(stars, background)
|
screen = Screen(stars, background, objects['framerate'])
|
||||||
control_window = ControlWindow(screen)
|
control_window = ControlWindow(screen, len(scenes))
|
||||||
|
|
||||||
|
last_time = time()
|
||||||
|
frame_count = 0
|
||||||
|
fps_update = objects['framerate']
|
||||||
|
star_time = time()
|
||||||
|
|
||||||
while control_window.is_running():
|
while control_window.is_running():
|
||||||
control_window.process_events()
|
control_window.process_events()
|
||||||
screen.update(scene_data)
|
screen.update(scene_data)
|
||||||
|
if frame_count % fps_update == 0:
|
||||||
|
now = time()
|
||||||
|
print(f"{time() - star_time:.3f}s: {1/((now - last_time) / fps_update):.02f} fps")
|
||||||
|
last_time = now
|
||||||
|
frame_count = 0
|
||||||
|
|
||||||
|
frame_count += 1
|
||||||
|
|
||||||
|
|
||||||
screen.close()
|
screen.close()
|
||||||
control_window.close()
|
control_window.close()
|
||||||
|
pygame.quit()
|
||||||
|
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,20 @@ from math import sin, cos, pi
|
|||||||
from time import time, sleep
|
from time import time, sleep
|
||||||
from random import random
|
from random import random
|
||||||
|
|
||||||
|
INTERPOLATION = {
|
||||||
|
'sin2': lambda x: sin(x) ** 2,
|
||||||
|
'sin': lambda x: sin(x),
|
||||||
|
'cos': lambda x: 1 - cos(x),
|
||||||
|
'lin': lambda x: x
|
||||||
|
}
|
||||||
|
|
||||||
|
FADE = {
|
||||||
|
(True, True): lambda x: sin(x) ** 2, # fade both
|
||||||
|
(True, False): lambda x: 1 - cos(x), # fade in
|
||||||
|
(False, True): lambda x: sin(x), # fade out
|
||||||
|
(False, False): lambda x: x / (pi/2) # linear
|
||||||
|
}
|
||||||
|
|
||||||
class Star:
|
class Star:
|
||||||
def __init__(self, sid: str, x: int, y: int, alpha: float, rot: float, scale: float, offset: float, image: pygame.Surface):
|
def __init__(self, sid: str, x: int, y: int, alpha: float, rot: float, scale: float, offset: float, image: pygame.Surface):
|
||||||
self.sid = sid
|
self.sid = sid
|
||||||
@ -18,11 +32,12 @@ class Star:
|
|||||||
self.offset = offset
|
self.offset = offset
|
||||||
self.image = image
|
self.image = image
|
||||||
|
|
||||||
|
|
||||||
class Screen:
|
class Screen:
|
||||||
def __init__(self, stars: list[Star], background: Surface | None) -> None:
|
def __init__(self, stars: list[Star], background: Surface | None, framerate: float = 30) -> None:
|
||||||
if not pygame.get_init():
|
if not pygame.get_init():
|
||||||
pygame.init()
|
pygame.init()
|
||||||
self.screen = pygame.display.set_mode((1920, 1080))
|
self.screen = pygame.display.set_mode((1920, 1080), display=1, flags=pygame.FULLSCREEN | pygame.DOUBLEBUF | pygame.WINDOWTAKEFOCUS)
|
||||||
self.clock = pygame.time.Clock()
|
self.clock = pygame.time.Clock()
|
||||||
self.stars = stars
|
self.stars = stars
|
||||||
self.last = time()
|
self.last = time()
|
||||||
@ -30,52 +45,66 @@ class Screen:
|
|||||||
self.active_scene = 0
|
self.active_scene = 0
|
||||||
self.last_scene = 0
|
self.last_scene = 0
|
||||||
self.scene_time: float = 0
|
self.scene_time: float = 0
|
||||||
self.background = background
|
self.framerate: float = framerate
|
||||||
|
self.overlay = pygame.surface.Surface(self.screen.get_size(), depth=32)
|
||||||
|
if background:
|
||||||
|
ratio_x = self.screen.get_width() / background.get_width()
|
||||||
|
ratio_y = self.screen.get_height() / background.get_height()
|
||||||
|
scaled_background = transform.rotozoom(background, 0, max(ratio_x, ratio_y))
|
||||||
|
|
||||||
|
self.bg_pos = (
|
||||||
|
(self.screen.get_width() - scaled_background.get_width()) / 2,
|
||||||
|
(self.screen.get_height() - scaled_background.get_height()) / 2
|
||||||
|
)
|
||||||
|
self.background = scaled_background
|
||||||
|
else:
|
||||||
|
self.background = None
|
||||||
|
self.bg_pos = None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def update(self, scene_data):
|
def update(self, scene_data):
|
||||||
self.screen.fill((0, 0, 0))
|
if not self.background:
|
||||||
|
self.screen.fill((0, 0, 0))
|
||||||
now = time()
|
now = time()
|
||||||
delta = now - self.last
|
delta = now - self.last
|
||||||
self.last = now
|
self.last = now
|
||||||
|
|
||||||
self.scene_time += delta
|
self.scene_time += delta
|
||||||
weight = sin(min(self.scene_time, pi/2)) ** 2
|
fade_in = scene_data[self.active_scene]['transition']['fade_in']
|
||||||
|
fade_out = scene_data[self.active_scene]['transition']['fade_out']
|
||||||
|
t = FADE[(fade_in, fade_out)](min(self.scene_time / scene_data[self.active_scene]['transition']['t'], 1) * pi/2) * pi/2
|
||||||
|
weight_x = INTERPOLATION[scene_data[self.active_scene]['transition']['x']](t)
|
||||||
|
weight_y = INTERPOLATION[scene_data[self.active_scene]['transition']['y']](t)
|
||||||
|
weight = INTERPOLATION['sin2'](t)
|
||||||
|
|
||||||
def update_star_scene(star, old, new, weight):
|
def update_star_scene(star, old, new):
|
||||||
star.x = weight*new[star.sid]['x'] + (1-weight)*old[star.sid]['x']
|
star.x = weight_x*new[star.sid]['x'] + (1-weight_x)*old[star.sid]['x']
|
||||||
star.y = weight*new[star.sid]['y'] + (1-weight)*old[star.sid]['y']
|
star.y = weight_y*new[star.sid]['y'] + (1-weight_y)*old[star.sid]['y']
|
||||||
star.rot = weight*new[star.sid]['rot'] + (1-weight)*old[star.sid]['rot']
|
star.rot = weight*new[star.sid]['rot'] + (1-weight)*old[star.sid]['rot']
|
||||||
star.scale = weight*new[star.sid]['scale'] + (1-weight)*old[star.sid]['scale']
|
star.scale = weight*new[star.sid]['scale'] + (1-weight)*old[star.sid]['scale']
|
||||||
|
|
||||||
|
|
||||||
# first draw the background, if any
|
# first draw the background, if any
|
||||||
if self.background:
|
if self.background:
|
||||||
ratio_x = self.screen.get_width() / self.background.get_width()
|
self.screen.blit(self.background, self.bg_pos)
|
||||||
ratio_y = self.screen.get_height() / self.background.get_height()
|
|
||||||
scaled_background = transform.rotozoom(self.background, 0, max(ratio_x, ratio_y))
|
|
||||||
|
|
||||||
bg_pos = (
|
|
||||||
(self.screen.get_width() - scaled_background.get_width()) / 2,
|
|
||||||
(self.screen.get_height() - scaled_background.get_height()) / 2
|
|
||||||
)
|
|
||||||
self.screen.blit(scaled_background, bg_pos)
|
|
||||||
|
|
||||||
# draw all the star objects
|
# draw all the star objects
|
||||||
for star in self.stars:
|
for star in self.stars:
|
||||||
update_star_scene(star, scene_data[self.last_scene], scene_data[self.active_scene], weight)
|
update_star_scene(star, scene_data[self.last_scene], scene_data[self.active_scene])
|
||||||
star.alpha += star.rot * delta
|
star.alpha += star.rot * delta
|
||||||
scaled = transform.rotozoom(star.image, star.alpha, star.scale)
|
computed_scale = star.scale * (self.screen.get_width() / star.image.get_width() / 100)
|
||||||
|
scaled = transform.rotozoom(star.image, star.alpha, computed_scale)
|
||||||
(w, h) = scaled.get_size()
|
(w, h) = scaled.get_size()
|
||||||
pos = (star.x*self.screen.get_width() - w/2, star.y*self.screen.get_height() - h/2)
|
pos = (star.x*self.screen.get_width() - w/2, star.y*self.screen.get_height() - h/2)
|
||||||
self.screen.blit(scaled, pos)
|
self.screen.blit(scaled, pos)
|
||||||
|
|
||||||
overlay = pygame.surface.Surface((1920, 1080), depth=32)
|
|
||||||
overlay.set_alpha(int(255 * (1 - self.brightness)))
|
self.overlay.set_alpha(int(255 * (1 - self.brightness)))
|
||||||
self.screen.blit(overlay, (0, 0))
|
self.screen.blit(self.overlay, (0, 0))
|
||||||
|
|
||||||
pygame.display.flip()
|
pygame.display.flip()
|
||||||
self.clock.tick(60)
|
self.clock.tick(self.framerate)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
@ -8,7 +8,8 @@ ApplicationWindow {
|
|||||||
width: 800
|
width: 800
|
||||||
height: 600
|
height: 600
|
||||||
title: "StarSky Presenter"
|
title: "StarSky Presenter"
|
||||||
flags: Qt.FramelessWindowHint
|
flags: Qt.WindowCloseButtonHint | Qt.WindowStaysOnBottomHint
|
||||||
|
modality: Qt.ApplicationModal
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|||||||
@ -1,18 +1,11 @@
|
|||||||
stars:
|
stars:
|
||||||
- sid: star-bg-01
|
- sid: star-1
|
||||||
x: 0.1
|
x: 0.1
|
||||||
y: 0.1
|
y: 0.1
|
||||||
scale: 0.6
|
scale: 5
|
||||||
alpha: 0
|
alpha: 0
|
||||||
rot: 30
|
rot: 30
|
||||||
offset: 0
|
offset: 0
|
||||||
image: BasicStar1.png
|
image: nice-star-1.png
|
||||||
- sid: star-bg-02
|
|
||||||
x: 0.3
|
|
||||||
y: 0.4
|
|
||||||
scale: 0.8
|
|
||||||
alpha: 25
|
|
||||||
rot: 29
|
|
||||||
offset: 0
|
|
||||||
image: BasicStar1.png
|
|
||||||
background: background-01.jpg
|
background: background-01.jpg
|
||||||
|
framerate: 30
|
||||||
@ -1,4 +1,27 @@
|
|||||||
- star-bg-01:
|
- star-1:
|
||||||
x: 0.6
|
x: 1.1
|
||||||
star-bg-02:
|
y: 1.1
|
||||||
y: 0.6
|
transition:
|
||||||
|
t: 2
|
||||||
|
fade_in: true
|
||||||
|
fade_out: false
|
||||||
|
x: sin
|
||||||
|
y: cos
|
||||||
|
- star-1:
|
||||||
|
x: 0.5
|
||||||
|
y: 0.5
|
||||||
|
transition:
|
||||||
|
t: 2
|
||||||
|
fade_in: false
|
||||||
|
fade_out: true
|
||||||
|
x: cos
|
||||||
|
y: sin
|
||||||
|
- star-1:
|
||||||
|
x: -0.1
|
||||||
|
y: 1.1
|
||||||
|
transition:
|
||||||
|
t: 2
|
||||||
|
fade_in: true
|
||||||
|
fade_out: false
|
||||||
|
x: sin
|
||||||
|
y: cos
|
||||||
Loading…
x
Reference in New Issue
Block a user