30个发布版本
0.6.2 | 2024年1月28日 |
---|---|
0.6.1 | 2024年1月28日 |
0.5.3 | 2021年10月25日 |
0.4.0 | 2021年10月8日 |
0.1.17 | 2021年9月29日 |
#106 in WebAssembly
28 每月下载量
240KB
3.5K SLoC
aframe-rs
这是一个为 Rust 编写的 Aframe 库。它仍然相当实验性,很多东西都可能发生变化。我开始写这个是为了好玩,看看我能否在 yew 应用中玩 aframe。它开始变得相当庞大,所以我决定将所有特定的 yew 东西抽象出来,并开始创建一个单独的库。这里还有很多缺失的东西和要完成的事情,但现在已经有的都是可工作的。
设置
初始化
此 crate 包含一个 init
功能,可以启用以允许从异步函数中进行初始化
async fn app_main() -> Result<(), aframe::InitError>
{
aframe::init_aframe().await?;
// ... Now you can safely continue
}
您也可以通过将 Aframe 脚本添加到您的 HTML 标题中简单地初始化
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
使用
您可以使用此 crate 的 Htmlify
trait 输出原始 HTML,或者使用 yew-support
功能创建一个 yew 组件(在下面的说明中描述)以输出您的实际 Aframe 场景。
API
场景
实例化场景
scene!
组件
定义新的组件
component_def!
声明定义组件的结构
component_struct!
simple_enum!
complex_enum!
实例化组件结构
component!
有关更多信息以及预定义组件结构,请参阅 component 模块。
自定义几何形状
定义新的自定义几何形状
geometry_def!
尚未实现
geometry_struct!
宏用于声明自定义几何形状数据的结构geometry!
宏在实例化自定义几何形状时作为辅助工具
实体 & 原始形状
实例化实体或定义的原始形状
entity!
定义新的原始形状
primitive!
资产
assets!
和 mixin!
宏用于定义一个 Assets
结构。
系统
着色器
Htmlify
Htmlify
trait 用于从此 crate 提供的结构中生成 HTML。这已被抽象为单独的 crate
您可以使用它将场景直接放入 DOM 中,使用 web_sys crate,这使得此 crate 即使在没有支持框架的情况下也可以使用
// Say we have some `Scene` structure already constructed:
let body = web_sys::window()?.document()?.body()?;
body.append_with_node_1(scene.as_element()?.as_ref())?;
// Or even simpler:
htmlify::append_to_document_body(&scene);
这是一个使用 wasm-bindgen-test
创建的完全功能的页面的基本示例: 测试示例
系统API
Aframe 的最低级调用定义在 sys
模块中
registerPrimitive
registerComponent
registerSystem
registerShader
registerGeometry
registerElement
yew_support功能
yew_support
功能为这个crate添加了yew支持。其核心是实现了 From<&Scene> for Html
以及一些其他转换到yew的Html类型。
有关示例,请参阅 yew-ext模块页面
正在开发/缺失的功能
- 事件处理
- 状态处理
- 对自定义几何体的高级支持
- 访问Aframe实用函数
- 一些组件实现仍然接受字符串,而它们可以接受枚举或更具体的结构
示例
以下是yew中构建场景的完整示例(这也可以作为在yew上下文之外使用 scene!
宏的有效示例)
html!
{
<Aframe scene =
{
// Using this contant to clean up some fluff in the code below.
const CURSOR_COLOR: [(Cow<'static, str>, Cow<'static, str>); 1] =
[(Cow::Borrowed("color"), Cow::Borrowed("lightblue"))];
scene!
{
// TODO: Some of these attributes are actually components, they need to be implemented in the library!
attributes: ("inspector", "true"), ("embedded", "true"), ("cursor", "rayOrigin: mouse"),
("mixin", "intersect_ray"), ("style", "min-height: 50px;"),
assets: assets!
{
// Assume we have a few assets available to use
Image::new("ramen", "/pics/ramen.png"),
Image::new("noise", "/pics/noise.bmp"),
// Create a mixin for shadows to know what to interact with
mixin!
{
"intersect_ray",
("raycaster", component!
{
RayCaster,
objects: List(Cow::Borrowed(&[Cow::Borrowed("#ramen-cube, #water")]))
})
}
},
children:
// The camera rig
entity!
{
attributes: ("id", "rig"),
components:
("position", component::Position { x: 0.0, y: 0.0, z: 0.0 }),
("geometry", component!
{
component::Geometry,
primitive: component::GeometryPrimitive::Ring
{
radius_inner: 0.06,
radius_outer: 0.2,
segments_theta: 32,
segments_phi: 8,
theta_start: 0.0,
theta_length: 360.0
}
}),
("material", component!
{
component::Material,
props: component::MaterialProps(Cow::Borrowed(&CURSOR_COLOR)),
opacity: 0.8
}),
children:
// The camera
entity!
{
attributes: ("id", "camera"),
components:
("position", component::Position { x: 0.0, y: 1.8, z: 0.0 }),
("camera", component!(component::Camera)),
("look-controls", component!(component::LookControls))
},
},
entity!
{
attributes: ("id", "cube-rig"),
components:
("position", component::Position{x: 0.0, y: 2.5, z: -2.0}),
("sound", component!
{
component::Sound,
src: Cow::Borrowed("#ambient_music"),
volume: 0.5
}),
("light", component!
{
component::Light,
light_type: component::LightType::Point
{
decay: 1.0,
distance: 50.0,
shadow: component::OptionalLocalShadow::NoCast{},
},
intensity: 0.0
}),
("animation__mouseenter", component!
{
component::Animation,
property: Cow::Borrowed("light.intensity"),
to: Cow::Borrowed("1.0"),
start_events: component::List(Cow::Borrowed(&[Cow::Borrowed("mouseenter")])),
dur: 250
}),
("animation__mouseleave", component!
{
component::Animation,
property: Cow::Borrowed("light.intensity"),
to: Cow::Borrowed("0.0"),
start_events: component::List(Cow::Borrowed(&[Cow::Borrowed("mouseleave")])),
dur: 250
}),
// This assumes the existence of a primitive registered as "ramen-cube"
children: entity!
{
primitive: "ramen-cube",
attributes: ("id", "ramen-cube"),
components: // None
}
},
// Ambient light
entity!
{
attributes: ("id", "ambient-light"),
components: ("light", component!
{
component::Light,
light_type: component::LightType::Ambient{},
color: color::GREY73,
intensity: 0.2
})
},
// Directional light
entity!
{
attributes: ("id", "directional-light"),
components:
("position", component::Position{ x: 0.5, y: 1.0, z: 1.0 }),
("light", component!
{
component::Light,
light_type: component::LightType::Directional
{
shadow: component::OptionalDirectionalShadow::Cast
{
shadow: component!
{
component::DirectionalShadow
}
}
},
color: color::WHITE,
intensity: 0.1
})
},
// The sky
entity!
{
primitive: "a-sky",
attributes: ("id", "sky"),
components: ("material", component!
{
component::Material,
// This assumes the existence of a shader registered as "strobe"
shader: Cow::Borrowed("strobe"),
props: component::MaterialProps(Cow::Owned(vec!
(
(Cow::Borrowed("color"), Cow::Borrowed("black")),
(Cow::Borrowed("color2"), Cow::Borrowed("#222222"))
)))
})
},
// The ocean
entity!
{
primitive: "a-ocean",
attributes: ("id", "water"), ("depth", "100"), ("width", "100"), ("amplitude", "0.5"),
components: ("material", component!
{
component::Material,
// This assumes the existence of a shader registered as "water"
shader: Cow::Borrowed("water"),
props: component::MaterialProps(Cow::Owned(vec!((Cow::Borrowed("transparent"), Cow::Borrowed("true")))))
})
}
}
} />
}
依赖项
~11–15MB
~265K SLoC