diff --git a/kglobe.py b/kglobe.py index a3c3a1e..7d221b1 100644 --- a/kglobe.py +++ b/kglobe.py @@ -1,42 +1,26 @@ #!/usr/bin/env python3 -from kitty import draw_to_terminal +from kitty import draw_to_terminal, get_position, set_position, hide_cursor, show_cursor #, draw_animation from PIL import Image -import numpy as np -import trimesh -import pyrender +import pyvista as pv +sphere = pv.Tetrahedron()# Sphere() +pl=pv.Plotter(off_screen=True) +pl.add_mesh(sphere, color='tan', show_edges=False) -sphere = trimesh.creation.icosphere(subdivisions=3, radius=1.0) -# create mesh -mesh = pyrender.Mesh.from_trimesh(sphere, smooth=True, wireframe=True) +hide_cursor() +y, x = get_position() +print('\n' * 25, end='') -# Create a scene and add the mesh -scene = pyrender.Scene(bg_color = [0, 0, 0, 0]) -scene.add(mesh) - -# Add a directional light to illuminate the sphere -light = pyrender.DirectionalLight(color=np.ones(3), intensity=3.0) -light_pose = np.eye(4) -light_pose[:3, 3] = [0, 2, 2] # light from above and in front -scene.add(light, pose=light_pose) - -# Add a camera -camera = pyrender.PerspectiveCamera(yfov=np.pi / 3.0) -camera_pose = np.array([ - [1.0, 0.0, 0.0, 0.0], - [0.0, 1.0, 0.0, 0.0], - [0.0, 0.0, 1.0, 3.0], # Pull camera back - [0.0, 0.0, 0.0, 1.0] -]) -scene.add(camera, pose=camera_pose) - -r = pyrender.OffscreenRenderer(512, 512) -flags = pyrender.RenderFlags.RGBA -color, depth = r.render(scene, flags=flags) -# -im = Image.fromarray((color)) # .new("RGBA", (512, 512), (0, 0, 0, 0) ) - -draw_to_terminal(im) +frames = [] +try: + while True: + pl.camera.Azimuth(1) + image = pl.screenshot(transparent_background=True, window_size=(512, 512)) + frames.append(Image.fromarray(image)) + set_position(y-25, x) + draw_to_terminal(Image.fromarray(image)) +finally: + show_cursor() diff --git a/kitty.py b/kitty.py index 6182a05..6889396 100755 --- a/kitty.py +++ b/kitty.py @@ -1,5 +1,8 @@ #!/usr/bin/env python3 +import re import sys +import termios +import tty from base64 import standard_b64encode from io import BytesIO @@ -8,7 +11,7 @@ from PIL import Image, ImageDraw def draw_to_terminal(img: Image.Image) -> None: buffer: BytesIO = BytesIO() img.save(buffer, format='PNG') - write_chunked(a='T', f=100, data=buffer.getvalue()) + write_chunked(a='T', i=1, f=100, q=2, data=buffer.getvalue()) def serialize_gr_command(**cmd): payload = cmd.pop('payload', None) @@ -32,6 +35,65 @@ def write_chunked(**cmd): sys.stdout.flush() cmd.clear() +def hide_cursor(): + sys.stdout.write("\x1b[?25l") + sys.stdout.flush() + +def show_cursor(): + sys.stdout.write("\x1b[?25h") + sys.stdout.flush() + +def set_position(y, x): + sys.stdout.write(f"\x1b[{y};{x}H") + sys.stdout.flush() + +def get_position(): + # Save the current terminal settings + fd = sys.stdin.fileno() + old_settings = termios.tcgetattr(fd) + + try: + # Set terminal to raw mode + tty.setraw(fd) + + # Send the ESC[6n command to request cursor position + sys.stdout.write("\x1b[6n") + sys.stdout.flush() + + # Read the response: ESC [ row ; col R + response = '' + while True: + ch = sys.stdin.read(1) + response += ch + if ch == 'R': + break + + finally: + # Restore the terminal settings + termios.tcsetattr(fd, termios.TCSANOW, old_settings) + + # Parse the response using regex + match = re.search(r'\[(\d+);(\d+)R', response) + if match: + y, x = map(int, match.groups()) + return y, x + else: + raise ValueError("Failed to parse cursor position response") + + +# sys.stdout.write("\x1b[6n") +# sys.stdout.flush() +# response = '' +# while True: +# ch = sys.stdin.read(1) +# response += ch +# if ch == 'R': +# break +# match = re.search(r'\[(\d+);(\d+)R', response) +# if match: +# y, x = map(int, match.groups()) +# return y, x + if __name__ == '__main__': i = Image.new("RGB", (100, 100), (0, 0, 0)) d = ImageDraw.Draw(i) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..5a26a95 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,11 @@ +[project] +name = "kglobe" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +requires-python = ">=3.13" +dependencies = [ + "numpy<2", + "pyrender>=0.1.45", + "pyvista>=0.45.3", +]