forked from mttu-developers/konabot
regex fix
This commit is contained in:
@ -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:
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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):
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
@ -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:
|
||||
|
||||
Reference in New Issue
Block a user