regex fix

This commit is contained in:
bk_office
2026-04-27 19:46:10 +08:00
parent d80d8d91c2
commit cf52ea683b
9 changed files with 174 additions and 72 deletions

View File

@ -14,7 +14,7 @@ example:
"""
from dataclasses import dataclass
import re
import regex as re
from dataclasses import dataclass
@dataclass
class Command:
@ -23,7 +23,7 @@ class Command:
class CommandChainParser:
CHAIN_PATTERN = r"^(([a-zA-Z0-9.]+(?:\(([^()]*|(?1)+)(\s*\,\s*(?1))*\))?)(\.(?1))*)"
CHAIN_PATTERN = r"^(([a-zA-Z0-9]+(?:\(([^()]*|(?1)+)(\s*\,\s*(?1))*\))?)(\.(?1))*)"
def __init__(self, _command_chain: str) -> None:
self.command_chain = _command_chain
@ -40,7 +40,7 @@ class CommandChainParser:
class CommandParser:
CMD_PATTERN = r"^(([a-zA-Z0-9.]+(?:\(([^()]*|(?1)+)(\s*\,\s*(?1))*\))?))"
CMD_PATTERN = r"^(([a-zA-Z0-9]+(?:\(([^()]*|(?1)+)(\s*\,\s*(?1))*\))?))"
ID_PATTERN = r"^[a-zA-Z]+(?=\(|\.|$)"
def __init__(self, _command: str) -> None:

View File

@ -6,13 +6,16 @@ import moderngl
import numpy as np
from PIL import Image
from konabot.plugins.marchtoy.scene import Scene
from nonebot import logger
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, backend='egl')
ctx = moderngl.create_context(standalone=True)
ctx.gc_mode = "auto"
try:
program = ctx.program(

View File

@ -3,7 +3,7 @@ from konabot.plugins.marchtoy.texture import Texture
from konabot.plugins.marchtoy.utilities import ArgParser, Formatter
from nonebot import logger
from typing import Optional
import re
OBJECT_ENTRIES = {}
@ -74,7 +74,7 @@ class Transform:
def p_expr(self) -> str:
inv = np.linalg.inv(self.t) # + 1e-5 * np.identity(4, dtype=np.float32))
return f"({Formatter.vec4(inv)} * vec4(p, 1.0)).xyz"
return f"({Formatter.to_vec4(inv)} * vec4(p, 1.0)).xyz"
class Object:
@ -172,22 +172,37 @@ class Capsule(Object):
@make_obj("smoothed", "mix")
class Smoothed(Object):
def __init__(self, _a = None, _b = None, _k: float = 0.25):
def __init__(self, _k: float = 0.25):
super().__init__()
self.a_index: int = _a
self.b: Optional[Object] = _b
self.block_a: str = "INF"
self.block_b: str = "INF"
self.k: float = _k
def parse_args(self, args: str):
# from konabot.plugins.marchtoy.command import CommandChainParser
from konabot.plugins.marchtoy.scene import Scene
from konabot.plugins.marchtoy.command import CommandChainParser
try:
raise Exception
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)
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)
except Exception as e:
raise Exception(f"cannot build smoothed object over {args}: {e}")
def sdf_block_glsl(self):
return f"smin({self.a.sdf_block_glsl()}, {self.b.sdf_block_glsl()}, {self.k})"
return f"smin({self.block_a}, {self.block_b}, {self.k})"
@make_obj("camera", "cam")
class Camera(Object):

View File

@ -15,6 +15,7 @@ class Scene:
cmd_queue = CommandParser(raw_cmd)
cmd_obj = next(cmd_queue)
obj_id, obj_args = cmd_obj.id, cmd_obj.args
logger.info(f"parsing object: {obj_id} with args {obj_args}")
obj_instance: Optional[Object] = None
if obj_id in OBJECT_ENTRIES:
obj_cls = OBJECT_ENTRIES[obj_id]
@ -30,10 +31,11 @@ class Scene:
) from e
else:
raise Exception(f"{obj_id} is not a valid object type.")
logger.info(f"parsed object {obj_id}({obj_args})")
if obj_instance != None:
for cmd in cmd_queue:
op_id, op_args = cmd.id, cmd.args
logger.info(f"parsing operation {op_id} with args {op_args}")
if op_id in OPERATION_ENTRIES:
op_func = OPERATION_ENTRIES[op_id]
if not callable(op_func):
@ -41,11 +43,14 @@ class Scene:
op_func(obj_instance, op_args)
else:
raise Exception(f"{op_id} is not a valid operation.")
logger.info(f"parsed operation {op_id}({op_args})")
try:
sdf_block = obj_instance.sdf_block_glsl()
self.canvas_objs.append((obj_instance, sdf_block))
logger.info(f"parsed sdf {sdf_block}")
except:
logger.info(f"parsed camera")
if type(obj_instance) == Camera:
self.camera = obj_instance

View File

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

View File

@ -1,41 +0,0 @@
from command import Scene
import skia
import struct
from PIL import Image
import numpy as np
# 暂时先照抄小帕的了,之后有空再单独封装一下
async def render(instruction: str, res: tuple[int, int]):
scene = Scene(instruction)
width, height = res
surface = skia.Surface(width, height)
sksl_code = scene.compile()
runtime_effect = skia.RuntimeEffect.MakeForShader(sksl_code)
if runtime_effect is None:
raise Exception("cannot compile sksl shader")
uv_uniform = struct.pack("ff", float(width), float(height))
uniform_data = skia.Data.MakeWithCopy(uv_uniform)
shader = runtime_effect.makeShader(uniform_data, None, 0)
canvas = surface.getCanvas()
canvas.clear(skia.Color(0, 0, 0, 0))
paint = skia.Paint()
paint.setShader(shader)
canvas.drawRect(skia.Rect.MakeWH(width, height), paint)
image = surface.makeImageSnapshot()
target_info = skia.ImageInfo.Make(
image.width(),
image.height(),
skia.ColorType.kBGRA_8888_ColorType,
skia.AlphaType.kPremul_AlphaType,
)
pixel_data = bytearray(
image.width() * image.height() * 4
) # 4 bytes per pixel (BGRA)
success = image.readPixels(target_info, pixel_data, target_info.minRowBytes())
img_array = np.frombuffer(pixel_data, dtype=np.uint8).reshape((height, width, 4))
rgb_array = img_array[:, :, [2, 1, 0]]
pil_img = Image.fromarray(rgb_array)
return pil_img

View File

@ -1,19 +1,10 @@
import numpy as np
import regex as re
from konabot.plugins.marchtoy.texture import COLORS
class Formatter:
@staticmethod
def float4x4(m: np.ndarray) -> str:
if m.shape != (4, 4):
m = np.identity(4)
v_0 = ", ".join([str(x) for x in m[:, 0]])
v_1 = ", ".join([str(x) for x in m[:, 1]])
v_2 = ", ".join([str(x) for x in m[:, 2]])
v_3 = ", ".join([str(x) for x in m[:, 3]])
return f"float4x4(float4({v_0}), float4({v_1}), float4({v_2}), float4({v_3}))"
@staticmethod
def vec4(m: np.ndarray) -> str:
def to_vec4(m: np.ndarray) -> str:
if m.shape != (4, 4):
m = np.identity(4)
v_0 = ", ".join([str(x) for x in m[:, 0]])
@ -30,13 +21,12 @@ class ArgParser:
def to_params(args: str, delim: str = ',') -> list[str]:
_params = args.replace(" ", "").split(delim)
params: list[str] = []
# while 还是太过于令人生畏了
# 还是避免 while 为好
for param in _params:
if param == "":
continue
if param != "":
params.append(param)
return paramss
return params
@staticmethod
def as_float(args: list[str], default: float = 0.0) -> float:
try: