[oden] Garbage assets, need to rewrite to IO
This commit is contained in:
parent
75fcc427ac
commit
17805fa4a6
17 changed files with 240 additions and 94 deletions
|
|
@ -69,7 +69,7 @@ where
|
|||
*ret
|
||||
}
|
||||
}
|
||||
Err(Error::Exception(e, _)) => unsafe {
|
||||
Err(Error::Exception(e, _, _)) => unsafe {
|
||||
// If we returned `Error::Exception` then we're propagating an
|
||||
// exception through the JS stack, just flip it.
|
||||
let exc = &e.val;
|
||||
|
|
|
|||
|
|
@ -308,7 +308,12 @@ impl ContextRef {
|
|||
pub(crate) fn exception_error(&self) -> Error {
|
||||
let exc = self.exception();
|
||||
let desc = exc.to_string(&self).unwrap_or_else(|_| String::new());
|
||||
Error::Exception(exc, desc)
|
||||
let stack = exc
|
||||
.get_property(&self, "stack")
|
||||
.and_then(|stack| stack.to_string(&self))
|
||||
.unwrap_or_else(|_| String::new());
|
||||
|
||||
Error::Exception(exc, desc, stack)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{ContextRef, Error, Result, Value, ValueRef};
|
||||
use crate::{ContextRef, Error, Result, Value, ValueRef, ValueType};
|
||||
use std::num::TryFromIntError;
|
||||
|
||||
pub trait TryFromValue: Sized {
|
||||
|
|
@ -105,10 +105,24 @@ impl TryFromValue for Value {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFromValue for () {
|
||||
#[inline]
|
||||
fn try_from_value(value: &ValueRef, _ctx: &ContextRef) -> Result<Self> {
|
||||
if value.is_undefined() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::InvalidType {
|
||||
expected: ValueType::Undefined,
|
||||
found: value.value_type(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TryFromValue> TryFromValue for Option<T> {
|
||||
#[inline]
|
||||
fn try_from_value(value: &ValueRef, ctx: &ContextRef) -> Result<Self> {
|
||||
if value.is_undefined() {
|
||||
if value.is_null() || value.is_undefined() {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(T::try_from_value(value, ctx)?))
|
||||
|
|
|
|||
|
|
@ -7,21 +7,21 @@ pub trait TryIntoValue {
|
|||
impl TryIntoValue for u8 {
|
||||
#[inline]
|
||||
fn try_into_value(self, ctx: &ContextRef) -> ValueResult {
|
||||
ctx.new_u64(self)
|
||||
ctx.new_u32(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryIntoValue for u16 {
|
||||
#[inline]
|
||||
fn try_into_value(self, ctx: &ContextRef) -> ValueResult {
|
||||
ctx.new_u64(self)
|
||||
ctx.new_u32(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryIntoValue for u32 {
|
||||
#[inline]
|
||||
fn try_into_value(self, ctx: &ContextRef) -> ValueResult {
|
||||
ctx.new_u64(self)
|
||||
ctx.new_u32(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ impl TryIntoValue for Error {
|
|||
}
|
||||
Error::ConversionError(e) => Err(Error::ConversionError(e)),
|
||||
Error::RustFunctionError(e) => Err(Error::RustFunctionError(e)),
|
||||
Error::Exception(v, d) => Err(Error::Exception(v.dup(ctx), d)),
|
||||
Error::Exception(v, d, s) => Err(Error::Exception(v.dup(ctx), d, s)),
|
||||
Error::OutOfMemory => Err(Error::OutOfMemory),
|
||||
Error::IOError(e) => Err(Error::IOError(e)),
|
||||
Error::ParseError(name, err) => Err(Error::ParseError(name, err)),
|
||||
|
|
@ -135,8 +135,15 @@ impl<T: TryIntoValue> TryIntoValue for Option<T> {
|
|||
#[inline]
|
||||
fn try_into_value(self, ctx: &ContextRef) -> ValueResult {
|
||||
match self {
|
||||
None => Ok(ctx.undefined()),
|
||||
None => Ok(ctx.null()),
|
||||
Some(v) => v.try_into_value(ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryIntoValue for () {
|
||||
#[inline]
|
||||
fn try_into_value(self, ctx: &ContextRef) -> ValueResult {
|
||||
Ok(ctx.undefined())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub use conversion::*;
|
|||
pub use runtime::Runtime;
|
||||
pub use value::{Value, ValueRef, ValueType};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error("too many classes have been registered")]
|
||||
TooManyClasses,
|
||||
|
|
@ -39,8 +39,8 @@ pub enum Error {
|
|||
ConversionError(String),
|
||||
#[error("an error occurred calling a rust function: {0}")]
|
||||
RustFunctionError(String),
|
||||
#[error("an exception was thrown during evaluation: {1}")]
|
||||
Exception(Value, String),
|
||||
#[error("an exception was thrown during evaluation: {1}\nStack: {2}")]
|
||||
Exception(Value, String, String),
|
||||
#[error("out of memory")]
|
||||
OutOfMemory,
|
||||
#[error("an io error occurred: {0}")]
|
||||
|
|
@ -66,7 +66,7 @@ pub type ValueResult = core::result::Result<Value, Error>;
|
|||
|
||||
pub(crate) fn throw_error(context: &ContextRef, error: Error) -> sys::JSValue {
|
||||
match error {
|
||||
Error::Exception(v, _) => unsafe {
|
||||
Error::Exception(v, _, _) => unsafe {
|
||||
sys::JS_DupValue(context.ctx, v.val);
|
||||
sys::JS_Throw(context.ctx, v.val)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -164,7 +164,7 @@ unsafe extern "C" fn init_func<T: NativeModule>(
|
|||
let context = ContextRef::from_raw(ctx);
|
||||
match NativeModuleState::<T>::define(&context, m) {
|
||||
Ok(_) => 0,
|
||||
Err(Error::Exception(e, _)) => unsafe {
|
||||
Err(Error::Exception(e, _, _)) => unsafe {
|
||||
// If we returned `Error::Exception` then we're propagating an
|
||||
// exception through the JS stack, just flip it.
|
||||
let exc = &e.val;
|
||||
|
|
|
|||
|
|
@ -137,9 +137,7 @@ impl ValueRef {
|
|||
let mut res: u32 = 0;
|
||||
let ret = sys::JS_ToUint32(ctx.ctx, &mut res, self.val);
|
||||
if ret < 0 {
|
||||
let exc = ctx.exception();
|
||||
let desc = exc.to_string(&ctx).unwrap_or_else(|_| String::new());
|
||||
Err(Error::Exception(exc, desc))
|
||||
Err(ctx.exception_error())
|
||||
} else {
|
||||
Ok(res)
|
||||
}
|
||||
|
|
|
|||
5
src/assets.ts
Normal file
5
src/assets.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import * as core from "asset-core";
|
||||
|
||||
export function load_texture(path: string): number {
|
||||
return core.load_texture(path);
|
||||
}
|
||||
|
|
@ -51,3 +51,12 @@ export function spr(
|
|||
sh = sh || h;
|
||||
core.spr(x, y, w, h, sx, sy, sw, sh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the specified texture as the current texture for calls to e.g. spr().
|
||||
*
|
||||
* @param id - The identifier of the texture to use.
|
||||
*/
|
||||
export function use_texture(id: number) {
|
||||
core.use_texture(id);
|
||||
}
|
||||
|
|
|
|||
108
src/lib.rs
108
src/lib.rs
|
|
@ -1,4 +1,5 @@
|
|||
use bytemuck;
|
||||
use std::collections::HashMap;
|
||||
use wgpu::util::DeviceExt;
|
||||
use winit::{
|
||||
event::*,
|
||||
|
|
@ -65,7 +66,8 @@ struct State {
|
|||
vertex_buffer: wgpu::Buffer,
|
||||
max_vertices: usize,
|
||||
|
||||
diffuse_bind_group: wgpu::BindGroup,
|
||||
sprite_bind_group_layout: wgpu::BindGroupLayout,
|
||||
sprite_textures: HashMap<u32, wgpu::BindGroup>,
|
||||
|
||||
screen_uniform: ScreenUniforms,
|
||||
screen_uniform_buffer: wgpu::Buffer,
|
||||
|
|
@ -146,11 +148,12 @@ impl State {
|
|||
};
|
||||
surface.configure(&device, &config);
|
||||
|
||||
let diffuse_bytes = include_bytes!("happy-tree.png");
|
||||
let diffuse_texture =
|
||||
texture::Texture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png").unwrap();
|
||||
// TODO: DELETE THIS
|
||||
// let diffuse_bytes = include_bytes!("happy-tree.png");
|
||||
// let diffuse_texture =
|
||||
// texture::Texture::from_bytes(&device, &queue, diffuse_bytes, "happy-tree.png").unwrap();
|
||||
|
||||
let texture_bind_group_layout =
|
||||
let sprite_bind_group_layout =
|
||||
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
|
||||
entries: &[
|
||||
wgpu::BindGroupLayoutEntry {
|
||||
|
|
@ -172,23 +175,24 @@ impl State {
|
|||
count: None,
|
||||
},
|
||||
],
|
||||
label: Some("texture_bind_group_layout"),
|
||||
label: Some("sprite_bind_group_layout"),
|
||||
});
|
||||
|
||||
let diffuse_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &texture_bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(&diffuse_texture.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler),
|
||||
},
|
||||
],
|
||||
label: Some("diffuse_bind_group"),
|
||||
});
|
||||
// TODO: DELETE THIS
|
||||
// let sprite_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
// layout: &sprite_bind_group_layout,
|
||||
// entries: &[
|
||||
// wgpu::BindGroupEntry {
|
||||
// binding: 0,
|
||||
// resource: wgpu::BindingResource::TextureView(&diffuse_texture.view),
|
||||
// },
|
||||
// wgpu::BindGroupEntry {
|
||||
// binding: 1,
|
||||
// resource: wgpu::BindingResource::Sampler(&diffuse_texture.sampler),
|
||||
// },
|
||||
// ],
|
||||
// label: Some("diffuse_bind_group"),
|
||||
// });
|
||||
|
||||
let screen_uniform = ScreenUniforms::new(size.width, size.height);
|
||||
let screen_uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
|
|
@ -229,10 +233,7 @@ impl State {
|
|||
let render_pipeline_layout =
|
||||
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Render Pipeline Layout"),
|
||||
bind_group_layouts: &[
|
||||
&texture_bind_group_layout,
|
||||
&screen_uniform_bind_group_layout,
|
||||
],
|
||||
bind_group_layouts: &[&sprite_bind_group_layout, &screen_uniform_bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
|
|
@ -294,7 +295,8 @@ impl State {
|
|||
render_pipeline,
|
||||
vertex_buffer,
|
||||
max_vertices,
|
||||
diffuse_bind_group,
|
||||
sprite_bind_group_layout,
|
||||
sprite_textures: HashMap::new(),
|
||||
screen_uniform,
|
||||
screen_uniform_buffer,
|
||||
screen_uniform_bind_group,
|
||||
|
|
@ -348,6 +350,31 @@ impl State {
|
|||
color: Some(cc.color),
|
||||
commands: Vec::new(),
|
||||
}),
|
||||
GraphicsCommand::CreateTexture(ct) => {
|
||||
let texture = texture::Texture::from_image(
|
||||
&self.device,
|
||||
&self.queue,
|
||||
&ct.image,
|
||||
Some(&ct.label),
|
||||
);
|
||||
let sprite_bind_group =
|
||||
self.device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
layout: &self.sprite_bind_group_layout,
|
||||
entries: &[
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 0,
|
||||
resource: wgpu::BindingResource::TextureView(&texture.view),
|
||||
},
|
||||
wgpu::BindGroupEntry {
|
||||
binding: 1,
|
||||
resource: wgpu::BindingResource::Sampler(&texture.sampler),
|
||||
},
|
||||
],
|
||||
label: Some(&ct.label),
|
||||
});
|
||||
|
||||
self.sprite_textures.insert(ct.id, sprite_bind_group);
|
||||
}
|
||||
GraphicsCommand::EndFrame => (),
|
||||
other => match passes.last_mut() {
|
||||
Some(pass) => pass.commands.push(other),
|
||||
|
|
@ -395,6 +422,7 @@ impl State {
|
|||
depth_stencil_attachment: None,
|
||||
});
|
||||
|
||||
let mut texture_id = None;
|
||||
vertices.clear();
|
||||
for command in pass.commands {
|
||||
match command {
|
||||
|
|
@ -428,19 +456,29 @@ impl State {
|
|||
});
|
||||
}
|
||||
|
||||
GraphicsCommand::Clear(_) => (), // Already handled
|
||||
GraphicsCommand::EndFrame => (), // Should never appear
|
||||
GraphicsCommand::UseTexture(id) => texture_id = Some(id),
|
||||
GraphicsCommand::CreateTexture(_) => (), // Already handled
|
||||
GraphicsCommand::Clear(_) => (), // Already handled
|
||||
GraphicsCommand::EndFrame => (), // Should never appear
|
||||
}
|
||||
}
|
||||
|
||||
assert!(vertices.len() < self.max_vertices); // !
|
||||
self.queue
|
||||
.write_buffer(&self.vertex_buffer, 0, bytemuck::cast_slice(&vertices));
|
||||
render_pass.set_pipeline(&self.render_pipeline);
|
||||
render_pass.set_bind_group(0, &self.diffuse_bind_group, &[]);
|
||||
render_pass.set_bind_group(1, &self.screen_uniform_bind_group, &[]);
|
||||
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
||||
render_pass.draw(0..(vertices.len() as u32), 0..1);
|
||||
if let Some(id) = texture_id {
|
||||
assert!(vertices.len() < self.max_vertices); // !
|
||||
self.queue.write_buffer(
|
||||
&self.vertex_buffer,
|
||||
0,
|
||||
bytemuck::cast_slice(&vertices),
|
||||
);
|
||||
render_pass.set_pipeline(&self.render_pipeline);
|
||||
|
||||
let bind_group = self.sprite_textures.get(&id).unwrap();
|
||||
render_pass.set_bind_group(0, bind_group, &[]);
|
||||
|
||||
render_pass.set_bind_group(1, &self.screen_uniform_bind_group, &[]);
|
||||
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
|
||||
render_pass.draw(0..(vertices.len() as u32), 0..1);
|
||||
}
|
||||
}
|
||||
|
||||
// Submit will accept anything that implements IntoIter
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
import { cls, print, spr } from "./graphics.ts";
|
||||
import { cls, print, spr, use_texture } from "./graphics.ts";
|
||||
import { load_texture } from "./assets.ts";
|
||||
|
||||
let the_texture = 0;
|
||||
|
||||
export function init() {
|
||||
print("Hello world!");
|
||||
the_texture = load_texture("./src/happy-tree.png");
|
||||
}
|
||||
|
||||
export function update() {}
|
||||
|
||||
export function draw() {
|
||||
cls(0.1, 0.2, 0.3);
|
||||
use_texture(the_texture);
|
||||
spr((320 - 256) / 2, 0, 256, 240, 0, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ use graphics::GraphicsCommand;
|
|||
mod typescript;
|
||||
use typescript::transpile_to_javascript;
|
||||
|
||||
pub mod assets;
|
||||
|
||||
struct Loader {}
|
||||
|
||||
impl Loader {
|
||||
|
|
@ -42,6 +44,7 @@ pub struct ScriptContext {
|
|||
draw: Value,
|
||||
|
||||
gfx: graphics::GraphicsAPI,
|
||||
_assets: assets::AssetsAPI,
|
||||
gfx_receive: Receiver<graphics::GraphicsCommand>,
|
||||
}
|
||||
|
||||
|
|
@ -56,8 +59,10 @@ impl ScriptContext {
|
|||
|
||||
let (gfx_send, gfx_receive) = channel();
|
||||
|
||||
let gfx = graphics::GraphicsAPI::define(&context, gfx_send)
|
||||
let gfx = graphics::GraphicsAPI::define(&context, gfx_send.clone())
|
||||
.expect("Graphics module should load without error");
|
||||
let assets = assets::AssetsAPI::define(&context, gfx_send.clone())
|
||||
.expect("Assets module should load without error");
|
||||
|
||||
let module = context
|
||||
.import_module("./src/main.ts", "")
|
||||
|
|
@ -82,6 +87,8 @@ impl ScriptContext {
|
|||
|
||||
gfx,
|
||||
gfx_receive,
|
||||
|
||||
_assets: assets,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
56
src/script/assets.rs
Normal file
56
src/script/assets.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
use crate::script::graphics::{CreateTextureCommand, GraphicsCommand};
|
||||
use oden_js::{module::native::NativeModuleBuilder, ContextRef, Error, Result};
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct AssetsImpl {
|
||||
next_texture_id: AtomicU32,
|
||||
gfx_sender: Sender<GraphicsCommand>,
|
||||
}
|
||||
|
||||
impl AssetsImpl {
|
||||
fn new(sender: Sender<GraphicsCommand>) -> Self {
|
||||
AssetsImpl {
|
||||
gfx_sender: sender,
|
||||
next_texture_id: AtomicU32::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn load_texture(&self, path: &str) -> Result<u32> {
|
||||
let bytes = std::fs::read(path)?;
|
||||
let image = match image::load_from_memory(&bytes) {
|
||||
Ok(i) => i,
|
||||
Err(e) => return Err(Error::RustFunctionError(format!("{e}"))),
|
||||
};
|
||||
|
||||
let id = self.next_texture_id.fetch_add(1, Ordering::SeqCst);
|
||||
let _ = self
|
||||
.gfx_sender
|
||||
.send(GraphicsCommand::CreateTexture(CreateTextureCommand {
|
||||
id,
|
||||
image,
|
||||
label: path.into(),
|
||||
}));
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AssetsAPI {}
|
||||
|
||||
impl AssetsAPI {
|
||||
pub fn define(ctx: &ContextRef, sender: Sender<GraphicsCommand>) -> oden_js::Result<Self> {
|
||||
let assets = Arc::new(AssetsImpl::new(sender));
|
||||
let mut builder = NativeModuleBuilder::new(ctx);
|
||||
{
|
||||
let assets = assets.clone();
|
||||
builder.export(
|
||||
"load_texture",
|
||||
ctx.new_fn(move |_ctx: &ContextRef, p: String| assets.load_texture(&p))?,
|
||||
)?;
|
||||
}
|
||||
builder.build("asset-core")?;
|
||||
Ok(AssetsAPI {})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use oden_js::{module, ContextRef, Value, ValueResult};
|
||||
use oden_js::{module, ContextRef};
|
||||
use std::sync::mpsc::Sender;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
@ -24,11 +24,20 @@ pub struct SpriteCommand {
|
|||
pub sh: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CreateTextureCommand {
|
||||
pub id: u32,
|
||||
pub image: image::DynamicImage,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GraphicsCommand {
|
||||
Clear(ClearCommand),
|
||||
Print(PrintCommand),
|
||||
Sprite(SpriteCommand),
|
||||
CreateTexture(CreateTextureCommand),
|
||||
UseTexture(u32),
|
||||
EndFrame,
|
||||
}
|
||||
|
||||
|
|
@ -41,33 +50,19 @@ impl GraphicsImpl {
|
|||
GraphicsImpl { sender }
|
||||
}
|
||||
|
||||
fn print_fn(&self, ctx: &ContextRef, text: String) -> ValueResult {
|
||||
fn print(&self, text: String) -> () {
|
||||
let _ = self
|
||||
.sender
|
||||
.send(GraphicsCommand::Print(PrintCommand { text }));
|
||||
|
||||
Ok(Value::undefined(ctx))
|
||||
}
|
||||
|
||||
fn cls_fn(&self, ctx: &ContextRef, r: f64, g: f64, b: f64) -> ValueResult {
|
||||
fn cls(&self, r: f64, g: f64, b: f64) -> () {
|
||||
let _ = self.sender.send(GraphicsCommand::Clear(ClearCommand {
|
||||
color: [r, g, b, 1.0],
|
||||
}));
|
||||
Ok(Value::undefined(ctx))
|
||||
}
|
||||
|
||||
fn spr_fn(
|
||||
&self,
|
||||
ctx: &ContextRef,
|
||||
x: f32,
|
||||
y: f32,
|
||||
w: f32,
|
||||
h: f32,
|
||||
u: f32,
|
||||
v: f32,
|
||||
sw: f32,
|
||||
sh: f32,
|
||||
) -> ValueResult {
|
||||
fn spr(&self, x: f32, y: f32, w: f32, h: f32, u: f32, v: f32, sw: f32, sh: f32) {
|
||||
let _ = self.sender.send(GraphicsCommand::Sprite(SpriteCommand {
|
||||
x,
|
||||
y,
|
||||
|
|
@ -78,7 +73,10 @@ impl GraphicsImpl {
|
|||
sw,
|
||||
sh,
|
||||
}));
|
||||
Ok(Value::undefined(ctx))
|
||||
}
|
||||
|
||||
fn use_texture(&self, id: u32) {
|
||||
let _ = self.sender.send(GraphicsCommand::UseTexture(id));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -94,16 +92,14 @@ impl GraphicsAPI {
|
|||
let gfx = gfx.clone();
|
||||
builder.export(
|
||||
"print",
|
||||
ctx.new_fn(move |ctx: &ContextRef, t: String| gfx.print_fn(ctx, t))?,
|
||||
ctx.new_fn(move |_: &ContextRef, t: String| gfx.print(t))?,
|
||||
)?;
|
||||
}
|
||||
{
|
||||
let gfx = gfx.clone();
|
||||
builder.export(
|
||||
"cls",
|
||||
ctx.new_fn(move |ctx: &ContextRef, r: f64, g: f64, b: f64| {
|
||||
gfx.cls_fn(ctx, r, g, b)
|
||||
})?,
|
||||
ctx.new_fn(move |_: &ContextRef, r: f64, g: f64, b: f64| gfx.cls(r, g, b))?,
|
||||
)?;
|
||||
}
|
||||
{
|
||||
|
|
@ -111,7 +107,7 @@ impl GraphicsAPI {
|
|||
builder.export(
|
||||
"spr",
|
||||
ctx.new_fn(
|
||||
move |ctx: &ContextRef,
|
||||
move |_: &ContextRef,
|
||||
x: f32,
|
||||
y: f32,
|
||||
w: f32,
|
||||
|
|
@ -119,12 +115,17 @@ impl GraphicsAPI {
|
|||
u: f32,
|
||||
v: f32,
|
||||
sw: f32,
|
||||
sh: f32| {
|
||||
gfx.spr_fn(ctx, x, y, w, h, u, v, sw, sh)
|
||||
},
|
||||
sh: f32| gfx.spr(x, y, w, h, u, v, sw, sh),
|
||||
)?,
|
||||
)?;
|
||||
}
|
||||
{
|
||||
let gfx = gfx.clone();
|
||||
builder.export(
|
||||
"use_texture",
|
||||
ctx.new_fn(move |_: &ContextRef, id: u32| gfx.use_texture(id))?,
|
||||
)?;
|
||||
}
|
||||
builder.build("graphics-core")?;
|
||||
Ok(GraphicsAPI { gfx })
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
use anyhow::*;
|
||||
use image::GenericImageView;
|
||||
|
||||
pub struct Texture {
|
||||
|
|
@ -8,22 +7,22 @@ pub struct Texture {
|
|||
}
|
||||
|
||||
impl Texture {
|
||||
pub fn from_bytes(
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
bytes: &[u8],
|
||||
label: &str,
|
||||
) -> Result<Self> {
|
||||
let img = image::load_from_memory(bytes)?;
|
||||
Self::from_image(device, queue, &img, Some(label))
|
||||
}
|
||||
// pub fn from_bytes(
|
||||
// device: &wgpu::Device,
|
||||
// queue: &wgpu::Queue,
|
||||
// bytes: &[u8],
|
||||
// label: &str,
|
||||
// ) -> Result<Self> {
|
||||
// let img = image::load_from_memory(bytes)?;
|
||||
// Ok(Self::from_image(device, queue, &img, Some(label)))
|
||||
// }
|
||||
|
||||
pub fn from_image(
|
||||
device: &wgpu::Device,
|
||||
queue: &wgpu::Queue,
|
||||
img: &image::DynamicImage,
|
||||
label: Option<&str>,
|
||||
) -> Result<Self> {
|
||||
) -> Self {
|
||||
let rgba = img.to_rgba8();
|
||||
let dimensions = img.dimensions();
|
||||
|
||||
|
|
@ -70,10 +69,10 @@ impl Texture {
|
|||
..Default::default()
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
Self {
|
||||
texture,
|
||||
view,
|
||||
sampler,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
types/asset-core.d.ts
vendored
Normal file
1
types/asset-core.d.ts
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
export function load_texture(path: string): number;
|
||||
1
types/graphics-core.d.ts
vendored
1
types/graphics-core.d.ts
vendored
|
|
@ -12,3 +12,4 @@ export function spr(
|
|||
sw: number,
|
||||
sh: number
|
||||
);
|
||||
export function use_texture(id: number);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue