Compare commits
23 Commits
Author | SHA1 | Date | |
---|---|---|---|
1cae51ecb9 | |||
d9b6085d7f | |||
33cf9f0561 | |||
40745c4f6f | |||
e40e960ef2 | |||
76ca43a645 | |||
b5f7a8cc6f | |||
88ad707f39 | |||
66eea1f106 | |||
a51001a875 | |||
d2782012ac | |||
63c8f0f4f5 | |||
46a16d1169 | |||
2f4e1d64dc | |||
f21ec098db | |||
41b9aafd54 | |||
bf0ed47ceb | |||
fdf0205c98 | |||
5327b201c7 | |||
99b9c527b4 | |||
6e703075e9 | |||
53545ab5a2 | |||
dd4f0b9245 |
463
Cargo.lock
generated
463
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -7,10 +7,12 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
bytemuck = { version = "1.13.1", features = ["derive"] }
|
||||
color-print = "0.3.5"
|
||||
configparser = "3.0.2"
|
||||
ddsfile = "0.5.1"
|
||||
glam = "0.24.1"
|
||||
lazy-regex = "3.0.2"
|
||||
mlua = { version = "0.9.4", features = ["luau-jit"] }
|
||||
obj = "0.10.2"
|
||||
parking_lot = "0.12.1"
|
||||
pollster = "0.3.0"
|
||||
@ -20,8 +22,8 @@ rbx_reflection_database = "0.2.7"
|
||||
rbx_xml = "0.13.1"
|
||||
vbsp = "0.5.0"
|
||||
vmdl = "0.1.1"
|
||||
wgpu = "0.18.0"
|
||||
winit = { version = "0.29.2", features = ["rwh_05"] }
|
||||
wgpu = "0.19.0"
|
||||
winit = { version = "0.29.2" }
|
||||
|
||||
#[profile.release]
|
||||
#lto = true
|
||||
|
52
luau/tests/RobloxSandbox.lua
Normal file
52
luau/tests/RobloxSandbox.lua
Normal file
@ -0,0 +1,52 @@
|
||||
type workspace = {[string]: {number}}
|
||||
type Service = {}
|
||||
|
||||
export type exports = {[string]: {workspace | number | {}}}
|
||||
|
||||
local workspace: workspace = {}
|
||||
local RS = {
|
||||
RenderStepped = {},
|
||||
Stepped = {},
|
||||
Heartbeat = {}
|
||||
}
|
||||
local game = setmetatable({
|
||||
Workspace = workspace,
|
||||
Players = {},
|
||||
RunService = RS
|
||||
}, {
|
||||
__index = function(self,i)
|
||||
return rawget(self,i)
|
||||
end,
|
||||
__newindex = function(self,i,_)
|
||||
--Roblox actually does this
|
||||
local t = type(i)
|
||||
return t == "Object" and "Unable to assign property Game. Property is read only" or `Unable to assign property Game. Object expected, got {t}`
|
||||
end,
|
||||
__metatable = "This metatable is locked."
|
||||
})
|
||||
|
||||
function game:GetService(service: string): Service
|
||||
return self[service]
|
||||
end
|
||||
function game:service(service: string): Service
|
||||
return self:GetService(service)
|
||||
end
|
||||
function game:FindService(service: string): boolean | Service
|
||||
return self[service] and self[service]
|
||||
end
|
||||
|
||||
local tick = os.clock() --just be better (Roblox wants you to use this instead of "tick" anyways because of Wine)
|
||||
local task = {
|
||||
wait = {},
|
||||
delay = {},
|
||||
defer = {}
|
||||
}
|
||||
|
||||
local exports: exports = {
|
||||
game = game, Game = game,
|
||||
workspace = workspace, Workspace = workspace,
|
||||
tick = tick,
|
||||
task = task
|
||||
}
|
||||
|
||||
return exports
|
20
luau/tests/Vector.lua
Normal file
20
luau/tests/Vector.lua
Normal file
@ -0,0 +1,20 @@
|
||||
local vec2 = Vector.new(1,2)
|
||||
local vec3 = Vector.new(1,2,3)
|
||||
local vec4 = Vector.new(1,2,3,4)
|
||||
|
||||
local function InspectVectorTable(Vector: {[string]: number})
|
||||
local aye: {string} = {"{"}
|
||||
for k,v in Vector do
|
||||
table.insert(aye, `{tostring(k)}={tostring(v)}`)
|
||||
end
|
||||
table.insert(aye, "}")
|
||||
return table.concat(aye, " ")
|
||||
end
|
||||
|
||||
print("----StrafeLua----")
|
||||
warn(_VERSION)
|
||||
print(`Vector.new = {InspectVectorTable(Vector.new())}`)
|
||||
print(`vec2 = {InspectVectorTable(vec2)}`)
|
||||
print(`vec3 = {InspectVectorTable(vec3)}`)
|
||||
print(`vec4 = {InspectVectorTable(vec4)}`)
|
||||
print("-----------------")
|
48
luau/typemap.lua
Normal file
48
luau/typemap.lua
Normal file
@ -0,0 +1,48 @@
|
||||
--A type map for the luau analyzer
|
||||
type f32 = number
|
||||
|
||||
type struct_Vector2 = {x: f32, y: f32}
|
||||
type struct_Vector3 = struct_Vector2 & {z: f32}
|
||||
type struct_Vector4 = struct_Vector3 & {w: f32}
|
||||
|
||||
export type warn = (message: string) -> ()
|
||||
|
||||
export type Vector2 = {
|
||||
new: (x: f32?, y: f32?) -> struct_Vector2,
|
||||
ONE: struct_Vector2,
|
||||
ZERO: struct_Vector2,
|
||||
NEG_ZERO: struct_Vector2,
|
||||
NEG_ONE: struct_Vector2,
|
||||
NEG_X: struct_Vector2,
|
||||
NEG_Y: struct_Vector2,
|
||||
}
|
||||
export type Vector3 = {
|
||||
new: (x: f32?, y: f32?, z: f32?) -> struct_Vector3,
|
||||
ONE: struct_Vector3,
|
||||
ZERO: struct_Vector3,
|
||||
NEG_ZERO: struct_Vector3,
|
||||
NEG_ONE: struct_Vector3,
|
||||
NEG_X: struct_Vector3,
|
||||
NEG_Y: struct_Vector3,
|
||||
}
|
||||
export type Vector4 = {
|
||||
new: (x: f32?, y: f32?, z: f32?, w: f32?) -> struct_Vector4,
|
||||
ONE: struct_Vector4,
|
||||
ZERO: struct_Vector4,
|
||||
NEG_ZERO: struct_Vector4,
|
||||
NEG_ONE: struct_Vector4,
|
||||
NEG_X: struct_Vector4,
|
||||
NEG_Y: struct_Vector4,
|
||||
}
|
||||
|
||||
local Vector2: Vector2 = Vector2
|
||||
local Vector3: Vector3 = Vector3
|
||||
local Vector4: Vector4 = Vector4
|
||||
local warn: warn = warn
|
||||
|
||||
return {
|
||||
Vector2 = Vector2,
|
||||
Vector3 = Vector3,
|
||||
Vector4 = Vector4,
|
||||
warn = warn
|
||||
}
|
@ -203,6 +203,7 @@ impl GraphicsState{
|
||||
label: Some(format!("Texture{}",texture_id).as_str()),
|
||||
view_formats: &[],
|
||||
},
|
||||
wgpu::util::TextureDataOrder::LayerMajor,
|
||||
&image.data,
|
||||
);
|
||||
texture.create_view(&wgpu::TextureViewDescriptor {
|
||||
@ -700,6 +701,7 @@ impl GraphicsState{
|
||||
label: Some("Skybox Texture"),
|
||||
view_formats: &[],
|
||||
},
|
||||
wgpu::util::TextureDataOrder::LayerMajor,
|
||||
&skybox_image.data,
|
||||
);
|
||||
|
||||
@ -740,6 +742,7 @@ impl GraphicsState{
|
||||
label: Some("Squid Texture"),
|
||||
view_formats: &[],
|
||||
},
|
||||
wgpu::util::TextureDataOrder::LayerMajor,
|
||||
&image.data,
|
||||
);
|
||||
|
||||
|
@ -18,7 +18,7 @@ WorkerDescription{
|
||||
pub fn new<'a>(
|
||||
mut graphics:crate::graphics::GraphicsState,
|
||||
mut config:wgpu::SurfaceConfiguration,
|
||||
surface:wgpu::Surface,
|
||||
surface:wgpu::Surface<'a>,
|
||||
device:wgpu::Device,
|
||||
queue:wgpu::Queue,
|
||||
)->crate::compat_worker::INWorker<'a,Instruction>{
|
||||
|
95
src/luau.rs
Normal file
95
src/luau.rs
Normal file
@ -0,0 +1,95 @@
|
||||
use mlua::{Lua as Luau, Result};
|
||||
use glam::{Vec2, Vec3, Vec4, Quat};
|
||||
use color_print::cprintln;
|
||||
|
||||
const STRAFE_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
||||
struct StrafeluaGlobals {
|
||||
vm: Luau,
|
||||
}
|
||||
trait Luavm {
|
||||
fn new_vm(isolated: bool) -> StrafeluaGlobals {
|
||||
let vm = Luau::new();
|
||||
vm.sandbox(isolated).unwrap();
|
||||
if isolated {
|
||||
//Prevent bad actors
|
||||
vm.globals().set("getfenv", mlua::Nil).unwrap(); //Deprecated in Luau but not removed *yet*
|
||||
vm.globals().set("setfenv", mlua::Nil).unwrap(); //same with this
|
||||
vm.globals().set("loadstring", mlua::Nil).unwrap();
|
||||
};
|
||||
|
||||
let luau_version: String = vm.globals().get("_VERSION").unwrap();
|
||||
vm.globals().set("_VERSION", format!("StrafeLuau {}, {}", STRAFE_VERSION, luau_version)).unwrap();
|
||||
|
||||
StrafeluaGlobals {vm}
|
||||
}
|
||||
|
||||
fn warn(&self) -> mlua::Function;
|
||||
fn vector(&self) -> mlua::Table;
|
||||
}
|
||||
|
||||
impl Luavm for StrafeluaGlobals {
|
||||
//Debug stuff
|
||||
fn warn(&self) -> mlua::Function {
|
||||
return self.vm.create_function(|_, message: mlua::String| {
|
||||
match Some(message) {
|
||||
Some(lua_string) => cprintln!("<yellow>{}</yellow>", lua_string.to_str().unwrap()),
|
||||
None => println!("Nothing provided to warn"),
|
||||
};
|
||||
Ok(())
|
||||
}).unwrap();
|
||||
}
|
||||
|
||||
fn vector(&self) -> mlua::Table {
|
||||
let field_vector = self.vm.create_table().unwrap();
|
||||
|
||||
field_vector.set("new", self.vm.create_function(|this: &Luau, (x,y,z,w): (Option<mlua::Number>, Option<mlua::Number>, Option<mlua::Number>, Option<mlua::Number>)| {
|
||||
let vector = this.create_table().unwrap();
|
||||
vector.set("x", x.unwrap_or(0.0)).unwrap();
|
||||
vector.set("y", y.unwrap_or(0.0)).unwrap();
|
||||
vector.set("z", z.unwrap_or(0.0)).unwrap();
|
||||
vector.set("w", w.unwrap_or(0.0)).unwrap();
|
||||
Ok(vector)
|
||||
}).unwrap()).unwrap();
|
||||
|
||||
let vector_one2 = self.vm.create_table().unwrap();
|
||||
vector_one2.set("x", 1.0).unwrap();
|
||||
vector_one2.set("y", 1.0).unwrap();
|
||||
vector_one2.set("z", 0.0).unwrap();
|
||||
vector_one2.set("w", 0.0).unwrap();
|
||||
field_vector.set("one2", vector_one2).unwrap();
|
||||
|
||||
let vector_one3 = self.vm.create_table().unwrap();
|
||||
vector_one3.set("x", 1.0).unwrap();
|
||||
vector_one3.set("y", 1.0).unwrap();
|
||||
vector_one3.set("z", 1.0).unwrap();
|
||||
vector_one3.set("w", 0.0).unwrap();
|
||||
field_vector.set("one3", vector_one3).unwrap();
|
||||
|
||||
let vector_one4 = self.vm.create_table().unwrap();
|
||||
vector_one4.set("x", 1.0).unwrap();
|
||||
vector_one4.set("y", 1.0).unwrap();
|
||||
vector_one4.set("z", 1.0).unwrap();
|
||||
vector_one4.set("w", 1.0).unwrap();
|
||||
field_vector.set("one4", vector_one4).unwrap();
|
||||
|
||||
return field_vector
|
||||
}
|
||||
}
|
||||
|
||||
/// Prevent strafe client from panicking when there is a Lua error related to syntax or anything else Lua related
|
||||
pub fn error_wrapper(execute_result: Result<()>) {
|
||||
match execute_result {
|
||||
Ok(t) => t,
|
||||
Err(e) => cprintln!("[StrafeLua ERROR]: <red>{}</red>", e),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_state(isolated: bool) -> Result<Luau> {
|
||||
let strafelua = StrafeluaGlobals::new_vm(isolated);
|
||||
|
||||
strafelua.vm.globals().set("warn", strafelua.warn()).unwrap();
|
||||
strafelua.vm.globals().set("Vector", strafelua.vector()).unwrap();
|
||||
|
||||
Ok(strafelua.vm)
|
||||
}
|
30
src/main.rs
30
src/main.rs
@ -1,5 +1,6 @@
|
||||
mod bvh;
|
||||
mod aabb;
|
||||
mod luau;
|
||||
mod model;
|
||||
mod setup;
|
||||
mod window;
|
||||
@ -117,6 +118,31 @@ pub fn default_models()->model::IndexedModelInstances{
|
||||
}
|
||||
|
||||
fn main(){
|
||||
let context=setup::setup(format!("Strafe Client v{}",env!("CARGO_PKG_VERSION")).as_str());
|
||||
context.start();//creates and runs a window context
|
||||
let strafelua_vm = luau::new_state(true).expect("Failed to load strafe lua");
|
||||
luau::error_wrapper(strafelua_vm.load(r#"
|
||||
local vec2 = Vector.new(1,2)
|
||||
local vec3 = Vector.new(1,2,3)
|
||||
local vec4 = Vector.new(1,2,3,4)
|
||||
|
||||
local function InspectVectorTable(Vector: {[string]: number})
|
||||
local aye: {string} = {"{"}
|
||||
for k,v in Vector do
|
||||
table.insert(aye, `{tostring(k)}={tostring(v)}`)
|
||||
end
|
||||
table.insert(aye, "}")
|
||||
return table.concat(aye, " ")
|
||||
end
|
||||
|
||||
print("----StrafeLua----")
|
||||
warn(_VERSION)
|
||||
print(`Vector.new = {InspectVectorTable(Vector.new())}`)
|
||||
print(`vec2 = {InspectVectorTable(vec2)}`)
|
||||
print(`vec3 = {InspectVectorTable(vec3)}`)
|
||||
print(`vec4 = {InspectVectorTable(vec4)}`)
|
||||
print("-----------------")
|
||||
"#).exec());
|
||||
//Lua syntax error!: SyntaxError { message: "[string \"src/main.rs:122:18\"]:7: Expected ')' (to close '(' at column 7), got ','", incomplete_input: false }
|
||||
//we got our first lua syntax error, todo: make an error handler in luau.rs
|
||||
|
||||
setup::setup_and_start(format!("Strafe Client v{}",env!("CARGO_PKG_VERSION")));
|
||||
}
|
||||
|
71
src/setup.rs
71
src/setup.rs
@ -46,21 +46,21 @@ fn create_instance()->SetupContextPartial1{
|
||||
}
|
||||
}
|
||||
impl SetupContextPartial1{
|
||||
fn create_surface(self,window:&winit::window::Window)->Result<SetupContextPartial2,wgpu::CreateSurfaceError>{
|
||||
fn create_surface<'a>(self,window:&'a winit::window::Window)->Result<SetupContextPartial2<'a>,wgpu::CreateSurfaceError>{
|
||||
Ok(SetupContextPartial2{
|
||||
backends:self.backends,
|
||||
surface:unsafe{self.instance.create_surface(window)}?,
|
||||
surface:self.instance.create_surface(window)?,
|
||||
instance:self.instance,
|
||||
})
|
||||
}
|
||||
}
|
||||
struct SetupContextPartial2{
|
||||
struct SetupContextPartial2<'a>{
|
||||
backends:wgpu::Backends,
|
||||
instance:wgpu::Instance,
|
||||
surface:wgpu::Surface,
|
||||
surface:wgpu::Surface<'a>,
|
||||
}
|
||||
impl SetupContextPartial2{
|
||||
fn pick_adapter(self)->SetupContextPartial3{
|
||||
impl<'a> SetupContextPartial2<'a>{
|
||||
fn pick_adapter(self)->SetupContextPartial3<'a>{
|
||||
let adapter;
|
||||
|
||||
//TODO: prefer adapter that implements optional features
|
||||
@ -122,13 +122,13 @@ impl SetupContextPartial2{
|
||||
}
|
||||
}
|
||||
}
|
||||
struct SetupContextPartial3{
|
||||
struct SetupContextPartial3<'a>{
|
||||
instance:wgpu::Instance,
|
||||
surface:wgpu::Surface,
|
||||
surface:wgpu::Surface<'a>,
|
||||
adapter:wgpu::Adapter,
|
||||
}
|
||||
impl SetupContextPartial3{
|
||||
fn request_device(self)->SetupContextPartial4{
|
||||
impl<'a> SetupContextPartial3<'a>{
|
||||
fn request_device(self)->SetupContextPartial4<'a>{
|
||||
let optional_features=optional_features();
|
||||
let required_features=required_features();
|
||||
|
||||
@ -140,8 +140,8 @@ impl SetupContextPartial3{
|
||||
.request_device(
|
||||
&wgpu::DeviceDescriptor {
|
||||
label: None,
|
||||
features: (optional_features & self.adapter.features()) | required_features,
|
||||
limits: needed_limits,
|
||||
required_features: (optional_features & self.adapter.features()) | required_features,
|
||||
required_limits: needed_limits,
|
||||
},
|
||||
trace_dir.ok().as_ref().map(std::path::Path::new),
|
||||
))
|
||||
@ -156,15 +156,15 @@ impl SetupContextPartial3{
|
||||
}
|
||||
}
|
||||
}
|
||||
struct SetupContextPartial4{
|
||||
struct SetupContextPartial4<'a>{
|
||||
instance:wgpu::Instance,
|
||||
surface:wgpu::Surface,
|
||||
surface:wgpu::Surface<'a>,
|
||||
adapter:wgpu::Adapter,
|
||||
device:wgpu::Device,
|
||||
queue:wgpu::Queue,
|
||||
}
|
||||
impl SetupContextPartial4{
|
||||
fn configure_surface(self,size:&winit::dpi::PhysicalSize<u32>)->SetupContext{
|
||||
impl<'a> SetupContextPartial4<'a>{
|
||||
fn configure_surface(self,size:&'a winit::dpi::PhysicalSize<u32>)->SetupContext<'a>{
|
||||
let mut config=self.surface
|
||||
.get_default_config(&self.adapter, size.width, size.height)
|
||||
.expect("Surface isn't supported by the adapter.");
|
||||
@ -182,65 +182,42 @@ impl SetupContextPartial4{
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct SetupContext{
|
||||
pub struct SetupContext<'a>{
|
||||
pub instance:wgpu::Instance,
|
||||
pub surface:wgpu::Surface,
|
||||
pub surface:wgpu::Surface<'a>,
|
||||
pub device:wgpu::Device,
|
||||
pub queue:wgpu::Queue,
|
||||
pub config:wgpu::SurfaceConfiguration,
|
||||
}
|
||||
|
||||
pub fn setup(title:&str)->SetupContextSetup{
|
||||
pub fn setup_and_start(title:String){
|
||||
let event_loop=winit::event_loop::EventLoop::new().unwrap();
|
||||
|
||||
let window=create_window(title,&event_loop).unwrap();
|
||||
|
||||
println!("Initializing the surface...");
|
||||
|
||||
let partial_1=create_instance();
|
||||
|
||||
let window=create_window(title.as_str(),&event_loop).unwrap();
|
||||
|
||||
let partial_2=partial_1.create_surface(&window).unwrap();
|
||||
|
||||
let partial_3=partial_2.pick_adapter();
|
||||
|
||||
let partial_4=partial_3.request_device();
|
||||
|
||||
SetupContextSetup{
|
||||
window,
|
||||
event_loop,
|
||||
partial_context:partial_4,
|
||||
}
|
||||
}
|
||||
let size=window.inner_size();
|
||||
|
||||
pub struct SetupContextSetup{
|
||||
window:winit::window::Window,
|
||||
event_loop:winit::event_loop::EventLoop<()>,
|
||||
partial_context:SetupContextPartial4,
|
||||
}
|
||||
|
||||
impl SetupContextSetup{
|
||||
fn into_split(self)->(winit::window::Window,winit::event_loop::EventLoop<()>,SetupContext){
|
||||
let size=self.window.inner_size();
|
||||
//Steal values and drop self
|
||||
(
|
||||
self.window,
|
||||
self.event_loop,
|
||||
self.partial_context.configure_surface(&size),
|
||||
)
|
||||
}
|
||||
pub fn start(self){
|
||||
let (window,event_loop,setup_context)=self.into_split();
|
||||
let setup_context=partial_4.configure_surface(&size);
|
||||
|
||||
//dedicated thread to ping request redraw back and resize the window doesn't seem logical
|
||||
|
||||
let window=crate::window::WindowContextSetup::new(&setup_context,window);
|
||||
let window=crate::window::WindowContextSetup::new(&setup_context,&window);
|
||||
//the thread that spawns the physics thread
|
||||
let window_thread=window.into_worker(setup_context);
|
||||
|
||||
println!("Entering event loop...");
|
||||
let root_time=std::time::Instant::now();
|
||||
run_event_loop(event_loop,window_thread,root_time).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn run_event_loop(
|
||||
|
@ -15,7 +15,7 @@ struct WindowContext<'a>{
|
||||
mouse:crate::physics::MouseState,//std::sync::Arc<std::sync::Mutex<>>
|
||||
screen_size:glam::UVec2,
|
||||
user_settings:crate::settings::UserSettings,
|
||||
window:winit::window::Window,
|
||||
window:&'a winit::window::Window,
|
||||
physics_thread:crate::compat_worker::QNWorker<'a, TimedInstruction<crate::physics_worker::Instruction>>,
|
||||
}
|
||||
|
||||
@ -158,15 +158,15 @@ impl WindowContext<'_>{
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WindowContextSetup{
|
||||
pub struct WindowContextSetup<'a>{
|
||||
user_settings:crate::settings::UserSettings,
|
||||
window:winit::window::Window,
|
||||
window:&'a winit::window::Window,
|
||||
physics:crate::physics::PhysicsState,
|
||||
graphics:crate::graphics::GraphicsState,
|
||||
}
|
||||
|
||||
impl WindowContextSetup{
|
||||
pub fn new(context:&crate::setup::SetupContext,window:winit::window::Window)->Self{
|
||||
impl<'a> WindowContextSetup<'a>{
|
||||
pub fn new(context:&crate::setup::SetupContext,window:&'a winit::window::Window)->Self{
|
||||
//wee
|
||||
let user_settings=crate::settings::read_user_settings();
|
||||
|
||||
@ -194,7 +194,7 @@ impl WindowContextSetup{
|
||||
}
|
||||
}
|
||||
|
||||
fn into_context<'a>(self,setup_context:crate::setup::SetupContext)->WindowContext<'a>{
|
||||
fn into_context(self,setup_context:crate::setup::SetupContext<'a>)->WindowContext<'a>{
|
||||
let screen_size=glam::uvec2(setup_context.config.width,setup_context.config.height);
|
||||
let graphics_thread=crate::graphics_worker::new(self.graphics,setup_context.config,setup_context.surface,setup_context.device,setup_context.queue);
|
||||
WindowContext{
|
||||
@ -208,7 +208,7 @@ impl WindowContextSetup{
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_worker<'a>(self,setup_context:crate::setup::SetupContext)->crate::compat_worker::QNWorker<'a,TimedInstruction<WindowInstruction>>{
|
||||
pub fn into_worker(self,setup_context:crate::setup::SetupContext<'a>)->crate::compat_worker::QNWorker<'a,TimedInstruction<WindowInstruction>>{
|
||||
let mut window_context=self.into_context(setup_context);
|
||||
crate::compat_worker::QNWorker::new(move |ins:TimedInstruction<WindowInstruction>|{
|
||||
match ins.instruction{
|
||||
|
Loading…
Reference in New Issue
Block a user