Created
September 11, 2021 00:48
-
-
Save tshirtman/adc06eb3b1187248ea20d8244b1d5ff7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
''' | |
GLSLiewer | |
======= | |
GlslViewer, for KV-Viewer, is a simple tool allowing you to dynamically display | |
a GLSL file, taking its changes into account (thanks to watchdog). | |
You can use the script as follows:: | |
python glsl_viewer.py ./test.glsl | |
This will display the test.glsl and automatically update the display when the | |
file changes. | |
.. note: This scripts uses watchdog to listen for file changes. To install | |
watchdog:: | |
pip install watchdog | |
''' | |
from kivy.lang import Builder | |
from kivy.app import App | |
from kivy.core.window import Window | |
from kivy.clock import Clock, mainthread | |
from kivy.uix.label import Label | |
from kivy.animation import Animation | |
from kivy.uix.widget import Widget | |
from kivy.properties import StringProperty | |
from kivy.graphics import RenderContext | |
from watchdog.observers import Observer | |
from watchdog.events import FileSystemEventHandler | |
from os.path import dirname, basename, join | |
from pathlib import Path | |
kv = ''' | |
<ShaderWidget>: | |
canvas: | |
Color: | |
rgb: 1, 0, 0 | |
Rectangle: | |
pos: self.pos | |
size: self.size | |
''' | |
class ShaderWidget(Widget): | |
fs = StringProperty(None) | |
def __init__(self, **kwargs): | |
self.canvas = RenderContext() | |
super().__init__(**kwargs) | |
# We'll update our glsl variables in a clock | |
Clock.schedule_interval(self.update_glsl, 1 / 60.) | |
def on_fs(self, instance, value): | |
shader = self.canvas.shader | |
old_value = shader.fs | |
shader.fs = value | |
if not shader.success: | |
shader.fs = old_value | |
raise Exception('failed') | |
def update_glsl(self, *largs): | |
self.canvas['time'] = Clock.get_boottime() | |
self.canvas['resolution'] = list(map(float, self.size)) | |
win_rc = Window.render_context | |
self.canvas['projection_mat'] = win_rc['projection_mat'] | |
self.canvas['modelview_mat'] = win_rc['modelview_mat'] | |
self.canvas['frag_modelview_mat'] = win_rc['frag_modelview_mat'] | |
class GlslHandler(FileSystemEventHandler): | |
def __init__(self, callback, target, **kwargs): | |
super().__init__(**kwargs) | |
self.callback = callback | |
self.target = target | |
def on_any_event(self, event): | |
if basename(event.src_path) == self.target.name: | |
self.callback() | |
class GLSLViewerApp(App): | |
def __init__(self, path): | |
self.path = path | |
super().__init__() | |
def build(self): | |
event_handler = GlslHandler(self.update, self.path) | |
o = Observer() | |
o.schedule(event_handler, self.path.parent) | |
o.start() | |
Clock.schedule_once(self.update, 0) | |
return ShaderWidget() | |
@mainthread | |
def update(self, *args): | |
print("load new shader content") | |
try: | |
self.root.fs = self.path.read_text() | |
print("loaded successfully") | |
except Exception as e: | |
pass | |
Builder.load_string(kv) | |
if __name__ == '__main__': | |
from sys import argv | |
if len(argv) != 2: | |
print('usage: %s filename.glsl' % argv[0]) | |
exit(1) | |
GLSLViewerApp(Path(argv[1])).run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment