Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ workspace = true
default = ["wayland"]
wayland = ["processing_render/wayland"]
x11 = ["processing_render/x11"]
python = ["processing_render/python"]

[workspace]
resolver = "3"
Expand Down
2 changes: 1 addition & 1 deletion crates/processing_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod error;
#[unsafe(no_mangle)]
pub extern "C" fn processing_init() {
error::clear_error();
error::check(init);
error::check(|| init(None));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll eventually need to accept configuration over FFI

}

/// Create a WebGPU surface from a macOS NSWindow handle.
Expand Down
2 changes: 1 addition & 1 deletion crates/processing_pyo3/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ x11 = ["processing/x11"]

[dependencies]
pyo3 = "0.27.0"
processing = { workspace = true }
processing = { workspace = true, features = ["python"] }
bevy = { workspace = true }
glfw = { version = "0.60.0"}

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions crates/processing_pyo3/examples/background_image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from processing import *

def setup():
size(800, 600)

def draw():
background(220)
image("images/logo.png")


# TODO: this should happen implicitly on module load somehow
run()
12 changes: 10 additions & 2 deletions crates/processing_pyo3/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ impl Drop for Graphics {
#[pymethods]
impl Graphics {
#[new]
pub fn new(width: u32, height: u32) -> PyResult<Self> {
pub fn new(width: u32, height: u32, asset_path: &str) -> PyResult<Self> {
let glfw_ctx =
GlfwContext::new(width, height).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;

init().map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;
let mut config = Config::new();
config.set(ConfigKey::AssetRootPath, asset_path.to_string());
init(Some(config)).map_err(|e| PyRuntimeError::new_err(format!("{e}")))?;

let surface = glfw_ctx
.create_surface(width, height, 1.0)
Expand Down Expand Up @@ -122,6 +124,12 @@ impl Graphics {
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn image(&self, file: &str) -> PyResult<()> {
let image = image_load(file).unwrap();
graphics_record_command(self.entity, DrawCommand::BackgroundImage(image))
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
}

pub fn push_matrix(&self) -> PyResult<()> {
graphics_record_command(self.entity, DrawCommand::PushMatrix)
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
Expand Down
46 changes: 33 additions & 13 deletions crates/processing_pyo3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! receiver.
//!
//! To allow Python users to create a similar experience, we provide module-level
//! functions that forward to a singleton Graphics object bepub(crate) pub(crate) hind the scenes.
//! functions that forward to a singleton Graphics object pub(crate) behind the scenes.
mod glfw;
mod graphics;

Expand All @@ -16,23 +16,37 @@ use pyo3::{exceptions::PyRuntimeError, prelude::*};

#[pymodule]
fn processing(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<Graphics>()?;
m.add_function(wrap_pyfunction!(size, m)?)?;
m.add_function(wrap_pyfunction!(run, m)?)?;
m.add_function(wrap_pyfunction!(background, m)?)?;
m.add_function(wrap_pyfunction!(fill, m)?)?;
m.add_function(wrap_pyfunction!(no_fill, m)?)?;
m.add_function(wrap_pyfunction!(stroke, m)?)?;
m.add_function(wrap_pyfunction!(no_stroke, m)?)?;
m.add_function(wrap_pyfunction!(stroke_weight, m)?)?;
m.add_function(wrap_pyfunction!(rect, m)?)?;
Ok(())
Python::attach(|py| {
let sys = PyModule::import(py, "sys")?;
let argv: Vec<String> = sys.getattr("argv")?.extract()?;
let filename: &str = argv[0].as_str();
let os = PyModule::import(py, "os")?;
let path = os.getattr("path")?;
let dirname = path.getattr("dirname")?.call1((filename,))?;
let abspath = path.getattr("abspath")?.call1((dirname,))?;
let abspath = path.getattr("join")?.call1((abspath, "assets"))?;

m.add("_root_dir", abspath)?;
m.add_class::<Graphics>()?;
m.add_function(wrap_pyfunction!(size, m)?)?;
m.add_function(wrap_pyfunction!(run, m)?)?;
m.add_function(wrap_pyfunction!(background, m)?)?;
m.add_function(wrap_pyfunction!(fill, m)?)?;
m.add_function(wrap_pyfunction!(no_fill, m)?)?;
m.add_function(wrap_pyfunction!(stroke, m)?)?;
m.add_function(wrap_pyfunction!(no_stroke, m)?)?;
m.add_function(wrap_pyfunction!(stroke_weight, m)?)?;
m.add_function(wrap_pyfunction!(rect, m)?)?;
m.add_function(wrap_pyfunction!(image, m)?)?;
Ok(())
})
}

#[pyfunction]
#[pyo3(pass_module)]
fn size(module: &Bound<'_, PyModule>, width: u32, height: u32) -> PyResult<()> {
let graphics = Graphics::new(width, height)?;
let asset_path: String = module.getattr("_root_dir")?.extract()?;
let graphics = Graphics::new(width, height, asset_path.as_str())?;
module.setattr("_graphics", graphics)?;
Ok(())
}
Expand Down Expand Up @@ -122,3 +136,9 @@ fn rect(
) -> PyResult<()> {
get_graphics(module)?.rect(x, y, w, h, tl, tr, br, bl)
}

#[pyfunction]
#[pyo3(pass_module, signature = (image_file))]
fn image(module: &Bound<'_, PyModule>, image_file: &str) -> PyResult<()> {
get_graphics(module)?.image(image_file)
}
3 changes: 2 additions & 1 deletion crates/processing_render/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ workspace = true
default = []
wayland = ["bevy/wayland"]
x11 = ["bevy/x11"]
python = []

[dependencies]
bevy = { workspace = true }
Expand All @@ -32,4 +33,4 @@ windows = { version = "0.58", features = ["Win32_Foundation", "Win32_System_Libr
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
js-sys = "0.3"
web-sys = { version = "0.3", features = ["Window", "Document", "HtmlCanvasElement"] }
web-sys = { version = "0.3", features = ["Window", "Document", "HtmlCanvasElement"] }
32 changes: 32 additions & 0 deletions crates/processing_render/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//! Options object for configuring various aspects of libprocessing.
//!
//! To add a new Config just add a new enum with associated value

use std::collections::HashMap;

#[derive(Hash, Eq, PartialEq)]
pub enum ConfigKey {
AssetRootPath,
}
// TODO: Consider Box<dyn Any> instead of String
pub type ConfigMap = HashMap<ConfigKey, String>;
pub struct Config {
map: ConfigMap,
}

impl Config {
pub fn new() -> Self {
// TODO consider defaults
Config {
map: ConfigMap::new(),
}
}

pub fn get(&self, k: ConfigKey) -> Option<&String> {
self.map.get(&k)
}

pub fn set(&mut self, k: ConfigKey, v: String) {
self.map.insert(k, v);
}
}
5 changes: 5 additions & 0 deletions crates/processing_render/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//! It can be created from raw pixel data, loaded from disk, resized, and read back to CPU memory.
use std::path::PathBuf;

#[cfg(feature = "python")]
use bevy::asset::{AssetPath, io::AssetSourceId};
use bevy::{
asset::{
LoadState, RenderAssetUsages, handle_internal_asset_events, io::embedded::GetAssetServer,
Expand Down Expand Up @@ -138,6 +140,9 @@ pub fn from_handle(
}

pub fn load(In(path): In<PathBuf>, world: &mut World) -> Result<Entity> {
#[cfg(feature = "python")]
let path = AssetPath::from_path_buf(path).with_source(AssetSourceId::from("assets_directory"));

let handle: Handle<bevy::image::Image> = world.get_asset_server().load(path);
while let LoadState::Loading = world.get_asset_server().load_state(&handle) {
world.run_system_once(handle_internal_asset_events).unwrap();
Expand Down
23 changes: 20 additions & 3 deletions crates/processing_render/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod config;
pub mod error;
mod graphics;
pub mod image;
Expand All @@ -6,6 +7,10 @@ mod surface;

use std::{cell::RefCell, num::NonZero, path::PathBuf, sync::OnceLock};

use config::*;

#[cfg(feature = "python")]
use bevy::asset::io::AssetSourceBuilder;
#[cfg(not(target_arch = "wasm32"))]
use bevy::log::tracing_subscriber;
use bevy::{
Expand Down Expand Up @@ -202,7 +207,7 @@ pub fn surface_resize(graphics_entity: Entity, width: u32, height: u32) -> error
})
}

fn create_app() -> App {
fn create_app(_config: Config) -> App {
let mut app = App::new();

#[cfg(not(target_arch = "wasm32"))]
Expand All @@ -227,6 +232,15 @@ fn create_app() -> App {
..default()
});

#[cfg(feature = "python")]
{
let asset_path = _config.get(ConfigKey::AssetRootPath).unwrap();
app.register_asset_source(
"assets_directory",
AssetSourceBuilder::platform_default(asset_path, None),
);
}

app.add_plugins(plugins);
app.add_plugins((ImagePlugin, GraphicsPlugin, SurfacePlugin));
app.add_systems(First, (clear_transient_meshes, activate_cameras))
Expand Down Expand Up @@ -257,14 +271,17 @@ fn set_app(app: App) {

/// Initialize the app, if not already initialized. Must be called from the main thread and cannot
/// be called concurrently from multiple threads.
/// asset_path is Optional because only python needs to use it.
#[cfg(not(target_arch = "wasm32"))]
pub fn init() -> error::Result<()> {
pub fn init(config: Option<Config>) -> error::Result<()> {
let config = config.unwrap_or_else(|| Config::new());

setup_tracing()?;
if is_already_init()? {
return Ok(());
}

let mut app = create_app();
let mut app = create_app(config);
app.finish();
app.cleanup();
set_app(app);
Expand Down
2 changes: 1 addition & 1 deletion examples/background_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(400, 400)?;
init()?;
init(None)?;

let width = 400;
let height = 400;
Expand Down
2 changes: 1 addition & 1 deletion examples/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(400, 400)?;
init()?;
init(None)?;

let width = 400;
let height = 400;
Expand Down
2 changes: 1 addition & 1 deletion examples/transforms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn main() {

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(400, 400)?;
init()?;
init(None)?;

let surface = glfw_ctx.create_surface(400, 400, 1.0)?;
let graphics = graphics_create(surface, 400, 400)?;
Expand Down
2 changes: 1 addition & 1 deletion examples/update_pixels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn main() {

fn sketch() -> error::Result<()> {
let mut glfw_ctx = GlfwContext::new(100, 100)?;
init()?;
init(None)?;

let width = 100;
let height = 100;
Expand Down
2 changes: 1 addition & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pub use bevy::prelude::default;
pub use processing_render::{render::command::DrawCommand, *};
pub use processing_render::{config::*, render::command::DrawCommand, *};
Loading