regex fix

This commit is contained in:
bk_office
2026-04-27 21:18:05 +08:00
parent cf52ea683b
commit 733114b941
8 changed files with 58 additions and 48 deletions

View File

@ -2,6 +2,7 @@ from nonebot import on_command
from nonebot.adapters import Message
from nonebot_plugin_alconna import UniMessage
from nonebot.params import CommandArg
import konabot.plugins.marchtoy.gl_render as render
# import konabot.plugins.marchtoy.cpu_render as render
import io
@ -10,10 +11,11 @@ cmd_marchtoy = on_command("march")
async def _(args: Message = CommandArg()):
if cmd := args.extract_plain_text():
try:
img = await render.render(cmd, (512, 512))
img = await render.render(cmd, (256, 256))
buffer = io.BytesIO()
# img.show()
img.save(buffer, format="PNG")
# img.save("/mnt/d/output.png", format="GIF")
img.save(buffer, format="GIF")
buffer.seek(0)
await cmd_marchtoy.send(await UniMessage().image(raw=buffer).export())
except Exception as e:

View File

@ -16,6 +16,8 @@ example:
from dataclasses import dataclass
import regex as re
from dataclasses import dataclass
@dataclass
class Command:
id: str
@ -40,8 +42,10 @@ class CommandChainParser:
class CommandParser:
CMD_PATTERN = r"^(([a-zA-Z0-9]+(?:\(([^()]*|(?1)+)(\s*\,\s*(?1))*\))?))"
CMD_PATTERN = r"^[a-zA-Z]+(?:\(([0-9.]+|(([a-zA-Z0-9]+(?:\(([^()]*|(?1)+)(\s*\,\s*(?1))*\))?)(\.(?1))*))(\s*\,\s*(?1))*\))?"
ID_PATTERN = r"^[a-zA-Z]+(?=\(|\.|$)"
ARG_PATTERN = CommandChainParser.CHAIN_PATTERN
TRIM_PATTERN = r"^\s*\,\s*"
def __init__(self, _command: str) -> None:
self.command = _command
@ -53,10 +57,17 @@ class CommandParser:
if query := re.match(CommandParser.CMD_PATTERN, self.command):
cmd = query[0]
if cmd_id_qry := re.match(CommandParser.ID_PATTERN, cmd):
cmd_id = cmd_id_qry[0]
id = cmd_id_qry[0]
cmd_args = cmd[len(id) + 1 : -1] # .replace(" ", "").split(",")
args: list[str] = []
self.command = self.command[len(cmd) + 1 :]
cmd_args = cmd[len(cmd_id) + 1 : -1]#.replace(" ", "").split(",")
while cmd_arg_qry := re.match(CommandParser.ARG_PATTERN, cmd_args):
arg = cmd_arg_qry[0]
args.append(arg)
cmd_args = cmd_args[len(arg) :]
if trim_qry := re.match(CommandParser.TRIM_PATTERN, cmd_args):
cmd_args = cmd_args[len(trim_qry[0]) :]
# while "" in cmd_args:
# cmd_args.remove("")
return Command(cmd_id, cmd_args)
raise StopIteration
# cmd_args.remove("")
return Command(id, args)
raise StopIteration

View File

@ -8,23 +8,23 @@ from PIL import Image
from konabot.plugins.marchtoy.scene import Scene
from nonebot import logger
PATH = pathlib.Path(__file__).parent / "shaders"
with (PATH / "vert.glsl").open(encoding='utf-8') as f:
VS_SRC = f.read()
async def render(command: str, res: tuple[int, int]):
fs = Scene(command).compile()
# logger.warning(fs)
PATH = pathlib.Path(__file__).parent / "shaders"
with (PATH / "vert.glsl").open(encoding='utf-8') as f:
vs = f.read()
ctx = moderngl.create_context(standalone=True)
ctx = moderngl.create_context(standalone=True, backend="egl")
ctx.gc_mode = "auto"
try:
program = ctx.program(
vertex_shader=vs,
vertex_shader=VS_SRC,
fragment_shader=fs
)
except Exception as e:
raise Exception(f"cannot compile glsl: {e}") from e
uniform = program['u_resolution']
uniform = program["u_resolution"]
uniform.write(np.array(res, dtype=np.float32))
vertices = np.array([-1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0], dtype=np.float32)
indices = np.array([0, 1, 2, 1, 2, 3], dtype=np.int32)

View File

@ -82,7 +82,7 @@ class Object:
self.transform: Transform = Transform()
self.texture: Texture = Texture()
def parse_args(self, args: str):
def parse_args(self, args: list[str]):
raise NotImplementedError
def get_transformed(self, p: np.ndarray) -> np.ndarray:
@ -104,7 +104,7 @@ class Cube(Object):
self.size = _size
def parse_args(self, args: str):
self.size = ArgParser.as_vec3(ArgParser.to_params(args))
self.size = ArgParser.as_vec3(args)
def sdf_block_glsl(self) -> str:
return f"sdCube({self.transform.p_expr()}, vec3({self.size[0]}, {self.size[1]}, {self.size[2]}))"
@ -116,7 +116,7 @@ class Sphere(Object):
self.radius = _radius
def parse_args(self, args: str):
self.radius = ArgParser.as_float(ArgParser.to_params(args))
self.radius = ArgParser.as_float(args)
def sdf_block_glsl(self) -> str:
return f"sdSphere({self.transform.p_expr()}, {self.radius})"
@ -130,7 +130,7 @@ class Cylinder(Object):
self.height = _height
def parse_args(self, args: str):
param = ArgParser.as_vec2(ArgParser.to_params(args))
param = ArgParser.as_vec2(args)
self.radius = param[0]
self.height = param[1]
@ -146,8 +146,8 @@ class Torus(Object):
self.r1 = _r1
self.r2 = _r2
def parse_args(self, args: str):
param = ArgParser.as_vec2(ArgParser.to_params(args))
def parse_args(self, args: list[str]):
param = ArgParser.as_vec2(args)
self.r1 = param[0]
self.r2 = param[1]
@ -162,8 +162,8 @@ class Capsule(Object):
self.h = _h
self.r = _r
def parse_args(self, args: str):
param = ArgParser.as_vec2(ArgParser.to_params(args))
def parse_args(self, args: list[str]):
param = ArgParser.as_vec2(args)
self.h = param[0]
self.r = param[1]
@ -178,25 +178,17 @@ class Smoothed(Object):
self.block_b: str = "INF"
self.k: float = _k
def parse_args(self, args: str):
def parse_args(self, args: list[str]):
from konabot.plugins.marchtoy.scene import Scene
from konabot.plugins.marchtoy.command import CommandChainParser
try:
args = args.replace(" ", "")
cmd_chain_a = next(CommandChainParser(args))
args = args[len(cmd_chain_a):]
if trim := re.match(r"^[\s]*\,[\s]*", args):
args = args[len(trim[0]):]
cmd_chain_b = next(CommandChainParser(args))
args = args[len(cmd_chain_b):]
if trim := re.match(r"^[\s]*\,[\s]*", args):
args = args[len(trim[0]):]
scene_a = Scene(cmd_chain_a)
scene_b = Scene(cmd_chain_b)
if not len(args) >= 2:
raise Exception("expecting at least 2 args")
scene_a = Scene(args[0])
scene_b = Scene(args[1])
self.block_a = scene_a.canvas_objs[0][1]
self.block_b = scene_b.canvas_objs[0][1]
# logger.warning(args)
# self.k = ArgParser.as_float(args)
if len(args) > 2:
self.k = ArgParser.as_float(args[2], 0.25)
except Exception as e:
raise Exception(f"cannot build smoothed object over {args}: {e}")
@ -211,6 +203,6 @@ class Camera(Object):
self.focus = _focus
self.transform.translate(5.0, 5.0, 5.0).lookat(0.0, 0.0, 0.0)
def parse_args(self, args: str):
self.focus = ArgParser.as_float(ArgParser.to_params(args))
def parse_args(self, args: list[str]):
self.focus = ArgParser.as_float(args)

View File

@ -44,7 +44,7 @@ def color(obj: Object, args: list[str]):
col = ArgParser.as_vec4(args)
obj.texture.color = (col[0], col[1], col[2], col[3])
else:
raise Exception("unknown color")
raise Exception("invalid argument number")
except:
raise Exception("unknown color")

View File

@ -3,6 +3,10 @@ import pathlib
import numpy as np
from nonebot import logger
PATH = pathlib.Path(__file__).parent / "shaders" / "frag.glsl"
with PATH.open(encoding="utf-8") as f:
FS_SRC = f.read()
class Scene:
def __init__(self, _instruction: str) -> None:
from konabot.plugins.marchtoy.command import CommandChainParser, CommandParser
@ -57,10 +61,8 @@ class Scene:
def __str__(self) -> str:
return ", ".join([str(type(obj)) for obj in self.canvas_objs])
def compile(self, fs_src: str = "frag.glsl") -> str:
PATH = pathlib.Path(__file__).parent / "shaders" / fs_src
with PATH.open(encoding="utf-8") as f:
content = f.read()
def compile(self) -> str:
sdf_block: str = ""
color_block: str = ""
@ -76,7 +78,8 @@ class Scene:
f"{color[0]}, {color[1]}, {color[2]}, {color[3]});\n"
)
index += 1
content = FS_SRC
content = content.replace("<SDF_BLOCK>", sdf_block)
content = content.replace("<COLOR_BLOCK>", color_block)

View File

@ -1,8 +1,10 @@
#version 330
const float EPS = 0.001;
const int MAX_ITER = 64;
uniform vec2 u_resolution;
out vec4 fragColor;
struct sdQuery {
float value;
int obj_id;

View File

@ -34,8 +34,8 @@ class ArgParser:
x = float(args[0])
return x
except:
raise Exception(f"cannot parse {args}")
return default
# raise Exception(f"cannot parse {args}")
return default
@staticmethod
def as_vec2(