Compare commits
10 Commits
f17bc694cc
...
337b83450f
| Author | SHA1 | Date |
|---|---|---|
|
|
337b83450f | |
|
|
9ba4dee953 | |
|
|
9df43797a1 | |
|
|
c85d762ecf | |
|
|
98565b175c | |
|
|
b9b9fc393c | |
|
|
2e63947569 | |
|
|
cb6bce2ba5 | |
|
|
e96052c286 | |
|
|
ca1dca8414 |
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +1,9 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"lua_modules/filesystem"
|
"lua_modules/filesystem",
|
||||||
|
"lua_modules/rerun_lua"
|
||||||
]
|
]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
mlua = { version = "0.9.1", features = ["lua54", "module"] }
|
mlua = { version = "0.9.1", features = ["lua54", "module", "serde", "serialize"] }
|
||||||
4
justfile
4
justfile
|
|
@ -5,6 +5,10 @@ run-fs: (lua "fs.example.lua")
|
||||||
build-filesystem: (_copy-so "dev" "filesystem")
|
build-filesystem: (_copy-so "dev" "filesystem")
|
||||||
deploy-fs: (_deploy "filesystem")
|
deploy-fs: (_deploy "filesystem")
|
||||||
|
|
||||||
|
run-rr: (lua "rr.example.lua")
|
||||||
|
build-rr: (_copy-so "dev" "rerun_lua")
|
||||||
|
deploy-rr: (_deploy "rerun_lua")
|
||||||
|
|
||||||
lua file:
|
lua file:
|
||||||
LUA_CPATH=c_modules/?.so lua lua/{{file}}
|
LUA_CPATH=c_modules/?.so lua lua/{{file}}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,77 +1,13 @@
|
||||||
local fs = require("filesystem")
|
local fs = require("filesystem")
|
||||||
|
|
||||||
local dirs = fs.directory("/Users/kinch/Desktop/Rebuild World")
|
local root = fs.directory(".")
|
||||||
|
|
||||||
local FileTree = {foo = "bar"}
|
string.starts_with = function(self, str)
|
||||||
function FileTree:new(iterator)
|
return self:find('^' .. str) ~= nil
|
||||||
local file_tree = {
|
|
||||||
iterator = iterator,
|
|
||||||
filters = {}
|
|
||||||
}
|
|
||||||
setmetatable(file_tree, self)
|
|
||||||
self.__index = self
|
|
||||||
return file_tree
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function FileTree:filter(filter_fn)
|
for entry in root do
|
||||||
table.insert(self.filters, filter_fn)
|
if not entry.rel_path:starts_with("%.") then
|
||||||
return self
|
print(entry.rel_path)
|
||||||
end
|
|
||||||
|
|
||||||
function FileTree:__call()
|
|
||||||
local next = self.iterator()
|
|
||||||
if next == nil then
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
for k,filter in pairs(self.filters) do
|
|
||||||
if (not filter(next)) then
|
|
||||||
return self()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return next
|
|
||||||
end
|
|
||||||
|
|
||||||
function is_dir(entry)
|
|
||||||
return entry:is_dir()
|
|
||||||
end
|
|
||||||
|
|
||||||
function starts_with(prefix)
|
|
||||||
return function(entry)
|
|
||||||
return entry.path:find("^"..prefix)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function does_not(predicate)
|
|
||||||
return function(...) return not predicate(...) end
|
|
||||||
end
|
|
||||||
|
|
||||||
local comic_dir = FileTree:new(fs.directory("."))
|
|
||||||
comic_dir:filter(is_dir)
|
|
||||||
|
|
||||||
for chapter_dir in comic_dir do
|
|
||||||
FileTree:new(fs.directory(chapter_dir)):filter(does_not(starts_with("./")))
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--for dir in dirs do
|
|
||||||
-- if dir:is_dir() then
|
|
||||||
-- for sub_dir in fs.directory(dir.path) do
|
|
||||||
-- print(sub_dir)
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--end
|
|
||||||
|
|
||||||
--for dir in dirs do
|
|
||||||
-- local files = dir:filter {
|
|
||||||
-- exclude = function(file)
|
|
||||||
-- return file.is_file and not file.basename:starts_with("._")
|
|
||||||
-- end
|
|
||||||
-- }
|
|
||||||
--
|
|
||||||
-- zip {
|
|
||||||
-- from = files,
|
|
||||||
-- into = dir.basename,
|
|
||||||
-- extension = "cbz",
|
|
||||||
-- }
|
|
||||||
--end
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
local rr = require("rerun_lua")
|
||||||
|
|
||||||
|
|
||||||
|
function bbox(ms_ocr_bbox)
|
||||||
|
return rr.rect_xyxy {
|
||||||
|
ms_ocr_bbox[1],
|
||||||
|
ms_ocr_bbox[2],
|
||||||
|
ms_ocr_bbox[5],
|
||||||
|
ms_ocr_bbox[6],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function paragraphs(ms_form_result)
|
||||||
|
local result = {}
|
||||||
|
for _, paragraph in ipairs(ms_form_result.analyzeResult.paragraphs) do
|
||||||
|
for _, region in ipairs(paragraph.boundingRegions) do
|
||||||
|
table.insert(result, {
|
||||||
|
text = paragraph.content,
|
||||||
|
page = region.pageNumber,
|
||||||
|
bbox = bbox(region.polygon)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function lines(ms_form_result)
|
||||||
|
local result = {}
|
||||||
|
for _, page in ipairs(ms_form_result.analyzeResult.pages) do
|
||||||
|
for _, line in ipairs(page.lines) do
|
||||||
|
table.insert(result, {
|
||||||
|
text = line.content,
|
||||||
|
page = page.pageNumber,
|
||||||
|
bbox = bbox(line.polygon)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function words(ms_form_result)
|
||||||
|
local result = {}
|
||||||
|
for _, page in ipairs(ms_form_result.analyzeResult.pages) do
|
||||||
|
for _, word in ipairs(page.words) do
|
||||||
|
table.insert(result, {
|
||||||
|
text = word.content,
|
||||||
|
page = page.pageNumber,
|
||||||
|
bbox = bbox(word.polygon)
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local ms_form = rr.json("/Users/tbr/Desktop/ms_form.json")
|
||||||
|
|
||||||
|
local record = rr.recording("example-2")
|
||||||
|
record:image("54-0", "/Users/tbr/Desktop/00054-0.png")
|
||||||
|
record:text_objects("54-0/ms-forms/paragraphs",paragraphs(ms_form))
|
||||||
|
record:text_objects("54-0/ms-forms/lines",lines(ms_form))
|
||||||
|
record:text_objects("54-0/ms-forms/words",words(ms_form))
|
||||||
|
|
@ -7,4 +7,7 @@ edition = "2021"
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
thiserror = "1.0.48"
|
||||||
mlua = { workspace = true }
|
mlua = { workspace = true }
|
||||||
|
zip = "0.6"
|
||||||
|
walkdir = "2.4.0"
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
use crate::driver_filesystem::filesystem_resource::FilesystemResourceLocation;
|
||||||
|
use crate::resource::{DynResource, DynResourceLocation, Resource, ResourceLocation};
|
||||||
|
use crate::source::ResourceSource;
|
||||||
|
use std::fs::rename;
|
||||||
|
use std::io::Sink;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
|
pub struct DirectorySource {
|
||||||
|
location: String,
|
||||||
|
iter: walkdir::IntoIter,
|
||||||
|
}
|
||||||
|
impl DirectorySource {
|
||||||
|
pub fn open_dir(location: String) -> Self {
|
||||||
|
let iter = WalkDir::new(location.clone()).into_iter();
|
||||||
|
DirectorySource { location, iter }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceSource for DirectorySource {
|
||||||
|
fn location(&self) -> DynResourceLocation {
|
||||||
|
Box::new(FilesystemResourceLocation::from(PathBuf::from(
|
||||||
|
self.location.clone(),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for DirectorySource {
|
||||||
|
type Item = DynResourceLocation;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
use crate::resource::ResourceLocation;
|
||||||
|
self.iter
|
||||||
|
.next()
|
||||||
|
.map(|entry| entry.unwrap())
|
||||||
|
.map(|entry| entry.path().strip_prefix("./").unwrap().to_path_buf())
|
||||||
|
.map(|entry| {
|
||||||
|
let loc = FilesystemResourceLocation::from(entry);
|
||||||
|
Box::new(loc) as Box<dyn ResourceLocation>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
use crate::resource::ResourceLocation;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub struct FilesystemResourceLocation {
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceLocation for FilesystemResourceLocation {
|
||||||
|
fn location(&self) -> String {
|
||||||
|
self.path.display().to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PathBuf> for FilesystemResourceLocation {
|
||||||
|
fn from(path: PathBuf) -> Self {
|
||||||
|
FilesystemResourceLocation { path }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod directory_source;
|
||||||
|
pub mod filesystem_resource;
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
use crate::sink::ResourceSink;
|
||||||
|
use std::iter::Zip;
|
||||||
|
|
||||||
|
mod zip_zink;
|
||||||
|
|
||||||
|
pub struct ZipZink {}
|
||||||
|
|
||||||
|
impl ResourceSink for ZipZink {}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
use mlua::prelude::{LuaError, LuaResult};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum FsError {
|
||||||
|
#[error("fs error happened: {msg}")]
|
||||||
|
GenericError { msg: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Res<T = ()> = Result<T, FsError>;
|
||||||
|
|
||||||
|
impl From<FsError> for LuaError {
|
||||||
|
fn from(fs_error: FsError) -> Self {
|
||||||
|
LuaError::RuntimeError(fs_error.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,19 @@
|
||||||
mod types;
|
mod driver_filesystem;
|
||||||
|
mod driver_zip_archive;
|
||||||
|
mod error;
|
||||||
|
mod lua_bindings;
|
||||||
|
mod operations;
|
||||||
|
mod resource;
|
||||||
|
mod sink;
|
||||||
|
mod source;
|
||||||
|
|
||||||
use crate::types::file_tree::*;
|
use crate::source::DynResourceSource;
|
||||||
|
use driver_filesystem::directory_source::DirectorySource;
|
||||||
use mlua::prelude::*;
|
use mlua::prelude::*;
|
||||||
|
|
||||||
fn directory(lua: &Lua, path: String) -> LuaResult<DirectoryFileTreeIter> {
|
fn directory(lua: &Lua, path: String) -> LuaResult<DynResourceSource> {
|
||||||
let read_dir = std::fs::read_dir(path).unwrap();
|
let source = DirectorySource::open_dir(path);
|
||||||
Ok(DirectoryFileTreeIter { read_dir })
|
Ok(Box::new(source))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[mlua::lua_module]
|
#[mlua::lua_module]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
use crate::resource::DynResourceLocation;
|
||||||
|
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
|
||||||
|
|
||||||
|
mod resource_bindings;
|
||||||
|
mod source_bindings;
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
use crate::resource::DynResourceLocation;
|
||||||
|
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
|
||||||
|
|
||||||
|
impl UserData for DynResourceLocation {
|
||||||
|
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
||||||
|
fields.add_field_method_get("rel_path", |lua, this| Ok(this.location()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_meta_method_mut(MetaMethod::ToString, |lua, this, _: ()| Ok(this.location()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
use crate::source::DynResourceSource;
|
||||||
|
use mlua::{MetaMethod, UserData, UserDataMethods};
|
||||||
|
|
||||||
|
impl UserData for DynResourceSource {
|
||||||
|
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_meta_method_mut(MetaMethod::Call, |lua, this, _: ()| Ok(this.next()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
mod operation_copy;
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
use crate::sink::DynResourceSink;
|
||||||
|
use crate::source::DynResourceSource;
|
||||||
|
|
||||||
|
pub fn copy_operation(from: DynResourceSource, to: DynResourceSink) {}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
use crate::sink::ResourceSink;
|
||||||
|
use crate::source::ResourceSource;
|
||||||
|
|
||||||
|
/// Points to a resource. Think of it as a path.
|
||||||
|
pub trait ResourceLocation {
|
||||||
|
fn location(&self) -> String;
|
||||||
|
}
|
||||||
|
/// A concrete resource. Think of as a directory or a file
|
||||||
|
pub trait Resource {}
|
||||||
|
// A resource ready to be read. Think of it as a open file for reading
|
||||||
|
pub trait ResourceInputStream: std::io::Read {}
|
||||||
|
// A resource ready to be written. Think of it as a open file for reading
|
||||||
|
pub trait ResourceOutputStream: std::io::Write {}
|
||||||
|
pub type DynResource = Box<dyn Resource>;
|
||||||
|
pub type DynResourceLocation = Box<dyn ResourceLocation>;
|
||||||
|
pub type DynResourceInputStream = Box<dyn ResourceInputStream>;
|
||||||
|
pub type DynResourceOutputStream = Box<dyn ResourceOutputStream>;
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
// mod zip_sink;
|
||||||
|
|
||||||
|
use crate::resource::{Resource, ResourceInputStream};
|
||||||
|
|
||||||
|
pub trait ResourceSink {
|
||||||
|
// fn add_file(&mut self, input_stream: DynResourceInputStream) {}
|
||||||
|
}
|
||||||
|
pub type DynResourceSink = Box<dyn ResourceSink>;
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
use crate::resource::{DynResource, DynResourceLocation};
|
||||||
|
pub trait ResourceSource: Iterator<Item = DynResourceLocation> {
|
||||||
|
fn location(&self) -> DynResourceLocation;
|
||||||
|
}
|
||||||
|
pub type DynResourceSource = Box<dyn ResourceSource<Item = DynResourceLocation>>;
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
use crate::types::file_tree::ResourceType::{Directory, RegularFile};
|
|
||||||
use mlua::{MetaMethod, UserData, UserDataFields, UserDataMethods};
|
|
||||||
use std::fs::{DirEntry, FileType, ReadDir};
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
pub enum ResourceType {
|
|
||||||
Directory,
|
|
||||||
RegularFile,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<FileType> for ResourceType {
|
|
||||||
fn from(file_type: FileType) -> Self {
|
|
||||||
if file_type.is_file() {
|
|
||||||
RegularFile
|
|
||||||
} else {
|
|
||||||
Directory
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Resource {
|
|
||||||
fn path(&self) -> String;
|
|
||||||
fn file_type(&self) -> ResourceType;
|
|
||||||
fn is_dir(&self) -> bool {
|
|
||||||
if let Directory = self.file_type() {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn is_file(&self) -> bool {
|
|
||||||
if let RegularFile = self.file_type() {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub struct FileSystemResource {
|
|
||||||
path: PathBuf,
|
|
||||||
}
|
|
||||||
impl Resource for FileSystemResource {
|
|
||||||
fn path(&self) -> String {
|
|
||||||
self.path.display().to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn file_type(&self) -> ResourceType {
|
|
||||||
self.path.metadata().unwrap().file_type().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait FileTreeIter<RES: Resource>: Iterator<Item = RES> {}
|
|
||||||
|
|
||||||
pub struct DirectoryFileTreeIter {
|
|
||||||
pub read_dir: ReadDir,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Iterator for DirectoryFileTreeIter {
|
|
||||||
type Item = FileSystemResource;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
self.read_dir.next().map(|entry| entry.unwrap().into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DirEntry> for FileSystemResource {
|
|
||||||
fn from(value: DirEntry) -> Self {
|
|
||||||
FileSystemResource { path: value.path() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UserData for DirectoryFileTreeIter {
|
|
||||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
|
||||||
methods.add_meta_method_mut(MetaMethod::Call, |lua, dir_iter, _: ()| Ok(dir_iter.next()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl UserData for FileSystemResource {
|
|
||||||
fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) {
|
|
||||||
fields.add_field_method_get("path", |lua, fsr| Ok(fsr.path.display().to_string()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
|
|
||||||
methods.add_meta_method(MetaMethod::ToString, |lua, fsr, _: ()| Ok(fsr.path()));
|
|
||||||
methods.add_method("is_dir", |lua, fsr, _: ()| Ok(fsr.is_dir()));
|
|
||||||
methods.add_method("is_file", |lua, fsr, _: ()| Ok(fsr.is_file()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
pub mod file_tree;
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "rerun_lua"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
image = { version = "0.24.7", features = ["png", "jpeg", "tiff"] }
|
||||||
|
mlua = { workspace = true }
|
||||||
|
rerun = "0.8.2"
|
||||||
|
serde_json = "1.0.107"
|
||||||
|
serde = { version = "1.0.188", features = ["derive"] }
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::BufReader;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use mlua::{AnyUserData, Function, MetaMethod, Table, TableExt, UserData, UserDataRef};
|
||||||
|
use mlua::prelude::*;
|
||||||
|
use rerun::{MsgSender, RecordingStream, RecordingStreamBuilder};
|
||||||
|
use rerun::components::{Rect2D, Tensor, Vec4D};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TextObject {
|
||||||
|
pub text: String,
|
||||||
|
pub bbox: Rect2D,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UserData for TextObject {
|
||||||
|
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||||
|
methods.add_meta_method(MetaMethod::ToString, |_lua, this, _:()| {
|
||||||
|
Ok(format!("{:?}", this))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'lua> FromLua<'lua> for TextObject {
|
||||||
|
fn from_lua(value: LuaValue<'lua>, lua: &'lua Lua) -> LuaResult<Self> {
|
||||||
|
let table = value.as_table().ok_or(LuaError::RuntimeError("invalid args for text_object".to_string()))?;
|
||||||
|
let rect = table.get::<_, UserDataRef<Rect2D>>("bbox")?.clone();
|
||||||
|
Ok(TextObject {
|
||||||
|
text: table.get("text")?,
|
||||||
|
bbox: rect
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn json(lua: &Lua, path: String) -> LuaResult<LuaValue> {
|
||||||
|
let file = File::open(path.as_str())
|
||||||
|
.map_err(|error| LuaError::RuntimeError(format!("could not open json path: {path}. Error: {error}")))?;
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
let json_value: serde_json::Value = serde_json::from_reader(reader)
|
||||||
|
.map_err(|error| LuaError::RuntimeError(format!("could not parse json at: {path}. Error: {error}")))?;
|
||||||
|
lua.to_value(&json_value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recording(lua: &Lua, name: String) -> LuaResult<AnyUserData> {
|
||||||
|
let stream = RecordingStreamBuilder::new(name)
|
||||||
|
.connect(rerun::default_server_addr(), None)
|
||||||
|
.map_err(|err| LuaError::RuntimeError(err.to_string()))?;
|
||||||
|
lua.create_any_userdata(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rect_xyxy(lua: &Lua, points: [f32;4]) -> LuaResult<AnyUserData> {
|
||||||
|
let rect = Rect2D::XYXY(Vec4D(points).into());
|
||||||
|
lua.create_any_userdata(rect)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register_bindings(lua: &Lua) -> LuaResult<()> {
|
||||||
|
|
||||||
|
lua.register_userdata_type::<Rect2D>(|reg| {
|
||||||
|
reg.add_meta_method(MetaMethod::ToString, |lua, this, _:()| Ok(format!("{:?}", this)))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
lua.register_userdata_type::<RecordingStream>(|reg|{
|
||||||
|
reg.add_method("image", |lua, this, (entity_path, image_path): (String,String)| {
|
||||||
|
let image_tensor = Tensor::from_image_file(PathBuf::from(image_path.as_str()).as_path())
|
||||||
|
.map_err(|error| LuaError::RuntimeError(format!("Could not read image file {image_path}. Error: {error}")))?;
|
||||||
|
MsgSender::new(entity_path)
|
||||||
|
.with_timeless(true)
|
||||||
|
.with_component(&[image_tensor])
|
||||||
|
.map_err(|error| LuaError::RuntimeError(format!("Could not send message: {}", error)))?
|
||||||
|
.send(this)
|
||||||
|
.map_err(|error| LuaError::RuntimeError(format!("Could not send message {error}")))?;
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
|
reg.add_method("text_objects", |lua, this, (entity_path, objects): (String, Vec<TextObject>)| {
|
||||||
|
let rects: Vec<Rect2D> = objects.into_iter()
|
||||||
|
.map(|t| t.bbox)
|
||||||
|
.collect();
|
||||||
|
MsgSender::new(entity_path)
|
||||||
|
.with_timeless(true)
|
||||||
|
.with_component(rects.as_slice())
|
||||||
|
.map_err(|error| LuaError::RuntimeError(format!("Could not send message: {}", error)))?
|
||||||
|
.send(this)
|
||||||
|
.map_err(|error| LuaError::RuntimeError(format!("Could not send message {error}")))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[mlua::lua_module]
|
||||||
|
fn rerun_lua(lua: &Lua) -> LuaResult<LuaTable> {
|
||||||
|
register_bindings(lua)?;
|
||||||
|
let exports = lua.create_table()?;
|
||||||
|
exports.set("recording", lua.create_function(recording)?)?;
|
||||||
|
exports.set("json", lua.create_function(json)?)?;
|
||||||
|
exports.set("rect_xyxy", lua.create_function(rect_xyxy)?)?;
|
||||||
|
Ok(exports)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue