Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
30 changes: 27 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,24 @@
- [x] Add a way to pick the prefered text editor (with vscode as default)
- [x] Write the bundle.py script to watch the specs defined in plugins.md
- [x] Manage files that the editor needs to work that are not inside the editor binary in a cross-platform way.
- [ ] Automatically manage the `luau-api` folder (create it when the project is created, verify its integrity on load, etc...)
- [ ] Show plugins in the editor
- [x] Show plugins in the editor
- [x] Automatically manage the `luau-api` folder (create it when the project is created, verify its integrity on load, etc...)
- [x] Automatically unpack dynamic libs in the plugins folder.
- [ ] Find a way to avoid crashes caused by dylibs plugins (use abi-stable instead of libloading for safe ffi)
- [ ] Check the version of the plugin and only allow loading if the version of the plugin matches the vectarine version (maybe the plugin can have a version range?)
- [ ] Add all editor hooks (debug menu)
- [ ] Reload plugins in the editor
- [ ] Show supported platforms in the editor
- [ ] Add ability to load/unload plugins from the editor from the filesystem
- [x] Automatically manage the "plugins" field in the game.vecta file of projects opened in the editor
- [x] Show supported platforms in the editor
- [x] Add ability to load/unload plugins from the editor from the filesystem
- [ ] Add ability to download plugins from the editor
- [ ] Add documentation on how to create and use plugins
- [ ] Test that it works on Linux
- [ ] Test that it works on Windows
- [ ] Emscripten compatibility using JS as a bridge
- [ ] Move generic resource trait to the SDK so that plugins can define custom resources. (the plugin will need access to the resources object.)
- [ ] For fastlist, add a concept of a 'gap' value which is empty and is used to make filtering and slicing operations simpler. A gap is a Vec2 with NaNs. You can merge fastlist to discard the gaps.
- [ ] Inside 'Help' add an 'Issues' button that opens to a window where errors related to the editor (bad installation, missing permissions, etc...) are shown instead of discarding all results all of the time.
- [ ] Screens (from the screen API) should be called layers. You should have a stack of layers.
- [ ] Screenshot API
- [ ] Lua function to screenshot (probably just turn a canvas into a PNG)
Expand Down
9 changes: 9 additions & 0 deletions docs/engine/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,15 @@ to the trusted plugins folder.

When the list of plugins of the game changes, the game is restarted to have a coherent state.

## Dynamic loading

On some OS, a dynamic library needs to be associated with a file and cannot come from memory. To solve this, the plugin folder contains both the `.dll` / `.so` / etc... and the `.vectaplugin` files.
If the dynamic library file does not exist, we generate it automatically.

Before execution we check the hash of the dynamic library against the hash inside the `.vectaplugin` to prevent anything fishy.

This type of verification only exists in the editor. The runtime trusts the game's plugins.

## In the game

When the game is distributed, only the relevant native code is shipped in the `.vecta` package. As start-up, the game is able to extract the .dlls/.so/.dynlib from the zip to execute them.
Expand Down
20 changes: 18 additions & 2 deletions docs/user-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ end
```

As you save, the game updates instantly.
See the `luau-api` folder for a list of available functions lua.
See the `luau-api` folder for a list of available functions lua. This folder is automatically generated by vectarine and its content should not be modified manually.

With a Luau extension / plugin installed, your text editor be able to autocomplete your code using the functions in `luau-api`. `luau-api` is a great source of documentation and can be though of as a companion to this manual.

Expand Down Expand Up @@ -839,13 +839,29 @@ It can also mean that you forgot to put `runtime.js` and `runtime.wasm` in the s

You put these files in a zip and upload it to [itch.io](https://itch.io) if you want.

# 🧩 Extending Vectarine with Plugins

Plugins are a way to add features to the vectarine editor and to your game. Plugins can add new interfaces in the editor, new luau functions, and do basically anything.
Because of this, using a plugin in a game requires that you trust the author.

Plugins exist in the form of files with the `.vectaplugin` extension. Vectarine stores a list of trusted plugins that you can use in your games to a `plugins` folder.
You can open it using the "Open plugins folder" button in the "Plugin manager". When you download a plugin, add it to this folder and refresh the list for it to appear.

Games have their own list of plugins in their `plugins` folder which should be next to the `game.vecta` file. For security reasons,
**the vectarine editor will only load plugins from a game if they are also in the `plugins` folder of the editor** and are thus trusted plugins!

If you want to make your own plugins, check the [README](https://github.com/vanyle/vectarine/tree/main/vectarine-plugin-template) of the vectarine plugin template on Github.

When you export a game to a specific platform, the parts of the plugin needed for that platform are obtained from the `.vectabundle` and are stored inside the output file.

# 👥 Collaborating on a project

Working on a game with other people is more fun!

## Vectarine and Git

Vectarine works well with version control systems like [Git](https://git-scm.com/). If you already now Git, use it!
Vectarine works well with version control systems like [Git](https://git-scm.com/). If you already now Git, use it! You can add "luau-api" to your .gitignore
as it is automatically generated by Vectarine when the project is loaded.

If you don't know Git, do not use it, it is complex to learn.

Expand Down
2 changes: 2 additions & 0 deletions editor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ which = "8.0.0"
zip = "6.0.0"
directories = "6.0.0"
blake3 = "1.8.3"
base64 = "0.22.1"
toml_edit = "0.25.4"

[[bin]]
name = "vecta"
Expand Down
2 changes: 2 additions & 0 deletions editor/src/editorconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ pub struct EditorConfig {
pub is_profiler_window_shown: bool,
pub is_plugins_window_shown: bool,
pub is_export_window_shown: bool,
// The preference window should be closed when opening Vectarine
#[serde(skip_serializing, skip_deserializing)]
pub is_preferences_window_shown: bool,
pub is_always_on_top: bool,
pub is_editor_always_on_top: bool,
Expand Down
30 changes: 25 additions & 5 deletions editor/src/editorinterface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use crate::{
},
egui_sdl2_platform,
export::exportinterface::draw_editor_export,
pluginsystem::trustedplugin::{self, PluginEntry, TrustedPlugin},
projectstate::ProjectState,
};
use editorconsole::draw_editor_console;
Expand Down Expand Up @@ -66,6 +67,8 @@ pub struct EditorState {
pub editor_batch_draw: BatchDraw2d,
debouncer: Rc<RefCell<Debouncer<notify::RecommendedWatcher, RecommendedCache>>>,

pub plugins: Vec<PluginEntry>,

pub game_error: Option<crate::luau::InfiniteLoopError>,
}

Expand Down Expand Up @@ -98,6 +101,7 @@ impl EditorState {
let video = self.video.clone();
let window = self.window.clone();
let debouncer = self.debouncer.clone();
let trusted_plugins = self.get_trusted_plugins();

LocalFileSystem.read_file(
geteditorpaths::get_editor_config_path()
Expand Down Expand Up @@ -135,6 +139,7 @@ impl EditorState {
gl,
video,
window,
&trusted_plugins,
|loaded_project| {
if let Ok(loaded_project) = loaded_project {
project.replace(Some(loaded_project));
Expand Down Expand Up @@ -179,6 +184,7 @@ impl EditorState {
.expect("Failed to create debouncer"),
)),
game_error: None,
plugins: trustedplugin::load_plugins(),
}
}

Expand All @@ -196,9 +202,12 @@ impl EditorState {
self.gl.clone(),
self.video.clone(),
self.window.clone(),
&self.get_trusted_plugins(),
|project| {
match project {
Ok(p) => self.project.borrow_mut().replace(p),
Ok(p) => {
self.project.borrow_mut().replace(p);
}
Err(e) => {
callback(Err(e));
return;
Expand Down Expand Up @@ -254,6 +263,11 @@ impl EditorState {
let ctx = platform.context();

draw_editor_menu(self, &ctx);

if self.project.borrow().is_none() {
draw_empty_screen(self, &ctx);
}

draw_editor_console(self, &ctx);
draw_editor_resources(self, painter, &ctx);
draw_editor_watcher(self, &ctx);
Expand All @@ -262,10 +276,6 @@ impl EditorState {
draw_editor_plugin_manager(self, &ctx);
draw_editor_preferences(self, &ctx);

if self.project.borrow().is_none() {
draw_empty_screen(self, &ctx);
}

// Stop drawing the egui frame and get the full output
let full_output = platform.end_frame(&mut self.video.borrow_mut());
match full_output {
Expand Down Expand Up @@ -298,6 +308,16 @@ impl EditorState {
platform.handle_event(event, sdl, &self.video.borrow());
}
}

pub fn get_trusted_plugins(&self) -> Vec<TrustedPlugin> {
self.plugins
.iter()
.filter_map(|entry| match entry {
PluginEntry::Trusted(trusted_plugin) => Some(trusted_plugin.clone()),
PluginEntry::Malformed(_) => None,
})
.collect::<Vec<TrustedPlugin>>()
}
}

pub fn handle_close_events(latest_events: &[sdl2::event::Event]) {
Expand Down
Loading