Compare commits
No commits in common. "7f04e0e0775ebbda331d7ae9088287165ff37cf5" and "070c1290b938afb17aae76749b4eb966f77497e0" have entirely different histories.
7f04e0e077
...
070c1290b9
@ -146,7 +146,7 @@ async def main():
|
|||||||
plotter.add_mesh(line, color="red", line_width=2)
|
plotter.add_mesh(line, color="red", line_width=2)
|
||||||
|
|
||||||
|
|
||||||
kitty.hide_cursor()
|
#kitty.hide_cursor()
|
||||||
try:
|
try:
|
||||||
#asyncio.run(plotter.run())
|
#asyncio.run(plotter.run())
|
||||||
await plotter.run()
|
await plotter.run()
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import io
|
||||||
import math
|
import math
|
||||||
import select
|
import select
|
||||||
import sys
|
import sys
|
||||||
import termios
|
import termios
|
||||||
import tty
|
import tty
|
||||||
import vtk
|
|
||||||
from vtk.util import numpy_support
|
|
||||||
import numpy as np
|
|
||||||
from io import BytesIO
|
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
import pyvista as pv
|
import pyvista as pv
|
||||||
|
|
||||||
@ -21,14 +17,13 @@ class TerminalPlotter(pv.Plotter):
|
|||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self._running = True
|
self._running = True
|
||||||
self.w2i_filter = vtk.vtkWindowToImageFilter()
|
self._needs_render = True
|
||||||
self.w2i_filter.SetInputBufferTypeToRGBA()
|
self._render_complete = False
|
||||||
self.w2i_filter.ReadFrontBufferOff()
|
self._rendering = False
|
||||||
self.w2i_filter.SetInput(self.ren_win)
|
self._render_pending = True
|
||||||
self.set_background([0.0, 0.0, 0.0])
|
self.set_background([0.0, 0.0, 0.0])
|
||||||
# transparency
|
self.add_on_render_callback(self._on_render)
|
||||||
self.ren_win.SetAlphaBitPlanes(1)
|
# if we are too close to the bottom of the terminal, create some space.
|
||||||
self.ren_win.SetMultiSamples(0)
|
|
||||||
|
|
||||||
async def initialize(self):
|
async def initialize(self):
|
||||||
h_pix, _ = await kitty.get_terminal_cell_size()
|
h_pix, _ = await kitty.get_terminal_cell_size()
|
||||||
@ -43,19 +38,14 @@ class TerminalPlotter(pv.Plotter):
|
|||||||
print("\n" * self.needed_lines, end="")
|
print("\n" * self.needed_lines, end="")
|
||||||
kitty.set_position(self.start_y, self.start_x)
|
kitty.set_position(self.start_y, self.start_x)
|
||||||
|
|
||||||
async def _handle_key(self, c):
|
|
||||||
if c == "a":
|
async def render_to_kitty(self):
|
||||||
self.camera.Azimuth(10)
|
self.render()
|
||||||
elif c == "d":
|
buf = io.BytesIO()
|
||||||
self.camera.Azimuth(-10)
|
self.screenshot(buf, transparent_background=True, window_size=(self.width, self.height))
|
||||||
elif c == "w":
|
await kitty.draw_to_terminal(buf)
|
||||||
self.camera.Elevation(10)
|
# print("y:", self.start_y, "rows:", self.rows, end="")
|
||||||
elif c == "s":
|
kitty.set_position(self.start_y, self.start_x)
|
||||||
self.camera.Elevation(-10)
|
|
||||||
elif c == "+":
|
|
||||||
self.camera.zoom(1.1)
|
|
||||||
elif c == "-":
|
|
||||||
self.camera.zoom(0.9)
|
|
||||||
|
|
||||||
async def _input_loop(self):
|
async def _input_loop(self):
|
||||||
fd = sys.stdin.fileno()
|
fd = sys.stdin.fileno()
|
||||||
@ -74,37 +64,60 @@ class TerminalPlotter(pv.Plotter):
|
|||||||
finally:
|
finally:
|
||||||
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
||||||
|
|
||||||
|
async def _handle_key(self, c):
|
||||||
|
if c == "a":
|
||||||
|
self.camera.Azimuth(10)
|
||||||
|
elif c == "d":
|
||||||
|
self.camera.Azimuth(-10)
|
||||||
|
elif c == "w":
|
||||||
|
self.camera.Elevation(10)
|
||||||
|
elif c == "s":
|
||||||
|
self.camera.Elevation(-10)
|
||||||
|
self._needs_render = True
|
||||||
|
# await self.render_to_kitty()
|
||||||
|
|
||||||
|
def _on_render(self, *args):
|
||||||
|
"""Callback that runs after each render."""
|
||||||
|
self._rendering = False
|
||||||
|
self._render_complete = True
|
||||||
|
|
||||||
|
async def _display_loop(self):
|
||||||
|
"""Loop that captures the screen and updates the terminal after rendering."""
|
||||||
|
while self._running:
|
||||||
|
if self._render_complete:
|
||||||
|
self._render_complete = False
|
||||||
|
buf = io.BytesIO()
|
||||||
|
# Safe: Screenshot only after render is confirmed complete
|
||||||
|
self.screenshot(buf, transparent_background=True, window_size=(self.width, self.height))
|
||||||
|
await kitty.draw_to_terminal(buf)
|
||||||
|
kitty.set_position(self.start_y, self.start_x)
|
||||||
|
await asyncio.sleep(0.001)
|
||||||
|
|
||||||
async def _render_loop(self):
|
async def _render_loop(self):
|
||||||
while self._running:
|
while self._running:
|
||||||
# keep renedring the scene
|
if self._needs_render and not self._rendering:
|
||||||
self.ren_win.Render()
|
self._rendering = True
|
||||||
# Update the filter to grab the current buffer
|
self._needs_render = False
|
||||||
self.w2i_filter.Modified()
|
self.update() # triggers a render and calls _on_render
|
||||||
self.w2i_filter.Update()
|
await asyncio.sleep(0.001)
|
||||||
|
|
||||||
vtk_image = self.w2i_filter.GetOutput()
|
async def _display_in_terminal(self, buf):
|
||||||
|
await kitty.draw_to_terminal(buf)
|
||||||
width, height, _ = vtk_image.GetDimensions()
|
|
||||||
vtk_array = vtk_image.GetPointData().GetScalars()
|
|
||||||
arr = numpy_support.vtk_to_numpy(vtk_array)
|
|
||||||
|
|
||||||
# Reshape the array to height x width x channels (probably 3 or 4)
|
|
||||||
arr = arr.reshape(height, width, -1)
|
|
||||||
|
|
||||||
# Flip vertically because VTK's origin is bottom-left
|
|
||||||
arr = np.flip(arr, axis=0)
|
|
||||||
img = Image.fromarray(arr)
|
|
||||||
buffer: BytesIO = BytesIO()
|
|
||||||
img.save(buffer, format="PNG")
|
|
||||||
await kitty.draw_to_terminal(buffer)
|
|
||||||
kitty.set_position(self.start_y, self.start_x)
|
kitty.set_position(self.start_y, self.start_x)
|
||||||
|
|
||||||
|
|
||||||
async def run(self):
|
async def run(self):
|
||||||
await self.initialize()
|
await self.initialize()
|
||||||
self.iren.initialize()
|
self.iren.initialize()
|
||||||
|
self._needs_render = True
|
||||||
tasks = [
|
tasks = [
|
||||||
asyncio.create_task(self._input_loop()),
|
asyncio.create_task(self._input_loop()),
|
||||||
asyncio.create_task(self._render_loop()),
|
asyncio.create_task(self._render_loop()),
|
||||||
|
asyncio.create_task(self._display_loop()),
|
||||||
]
|
]
|
||||||
await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
|
await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)
|
||||||
self._running = False
|
self._running = False
|
||||||
|
|
||||||
|
|
||||||
|
#await self.render_to_kitty()
|
||||||
|
#await self._input_loop()
|
||||||
|
Loading…
Reference in New Issue
Block a user