Ved home   Plugins   Technical documentation

Ved plugins

This page details how to install or develop plugins for Ved.

Last updated: Friday 15 March 2024 02:01 (UTC) (this is the last edit date of the file)

How to install plugins

The plugins folder can be found at:

To install a plugin, simply place the plugin in that folder, either as a .zip or as a folder. To disable an installed plugin, you don't have to remove it from the plugins folder, simply rename it to make the name start with a #.

How to make plugins

For an example of a plugin, check example_plugin.zip (1.1, now contains source edits) (TODO: this example is very old, it should be updated). There's a technical documentation of Ved that can be found here. You'll probably need to look at Ved's code while developing the plugin, and you can find it at the repository. You can also unzip the .love (it's actually a zip).

Ved is written in Lua and uses the LÖVE framework. So to be able to make plugins, it would help a lot to be familiar with that. To start making a plugin, make a new folder for it in the plugins folder (see above). You can name it anything you want, but the name isn't shown inside Ved itself, instead, the name you specify in the info file (info.lua) is. info.lua is a file inside your plugin folder, containing the name for your plugin, a description, author name, version number, the minimum version of Ved that is required for the plugin to work, and some other things.
An example for the info file can be found here: info.lua

Next, to integrate the plugin with Ved, you can use hooks, or you can make the plugin edit Ved source code (see below). To use hooks, make a folder called hooks in your plugin folder.

Hooks

Plugins can make use of hooks, which are specific points in the Ved code where plugin code can be run. For example, there is a hook that is called after displaying everything on the screen, so you can use that hook to display something related to your plugin. Hooks are called in every state (whether they're plugin-specific states or default Ved states).

Hook nameFunctionDescriptionArgsAdded
love_draw_end love.draw This is called at the end of love.draw(), thus can be used to draw something after everything else has been drawn. a58
love_load_start love.load This is called at the start of love.load(), before the config file has even been loaded, and (since 1.10.0) before the window has been first created.
Before 1.3.3: The compatibility layer for LÖVE 0.10.x will also not yet have been loaded, so be careful.
a58
love_load_end love.load This is called at the end of love.load(). a58
love_update_start love.update This is called at the start of love.update(). dt a58
love_update_end love.update This is called near the end of love.update(). dt a58
love_keypressed_start love.keypressed This is called at the start of love.keypressed(key). key a58/a59
love_keyreleased_start love.keyreleased This is called at the start of love.keyreleased(key). key a58/a59
love_mousepressed_start love.mousepressed This is called at the start of love.mousepressed(x, y, button).
Before 1.10.0: This was also called for wheel movements, with the button constants "wu" and "wd".
x, y, button a58/a59
love_mousereleased_start love.mousereleased This is called at the start of love.mousereleased(x, y, button). x, y, button a58/a59
love_wheelmoved_start love.wheelmoved This is called at the start of love.wheelmoved(xm, ym). xm, ym 1.10.0
func This is called at the end of the func.lua script, so you can add your own functions here. a58
func_loadstate loadstate (tostate & to_astate) This is called when going to a new state, so you can add code to prepare loading a custom state you may have added. Use in_astate(name, state) to check what the new state is (example: in_astate("my_1st_plug", 0), see technical documentation).
Before 1.1.4: The variable new contains the new state which is being loaded.
Since 1.11.1: to_astate(name, new, dontinitialize, ...) now has a vararg (...), which is passed to this hook.
... a58/a59
love_draw_state love.draw Here you can add drawing code for custom states. Use in_astate(name, state) to check what the current state is, and if your code recognizes a state and handles it, it should set statecaught to true, so there will not be an error message saying the state wasn't recognized.
Before 1.1.4: The state variable was used instead of in_astate().
a58
love_load_win love.load This is called in love.load() only if the operating system is Windows. b10
love_load_mac love.load This is called in love.load() only if the operating system is Mac OS X. b10
love_load_lin love.load This is called in love.load() only if the operating system is Linux. b10
love_load_luv love.load This is called in love.load() only if the operating system is something other than Windows, OS X or Linux. b10
love_directorydropped love.directorydropped This is called in love.directorydropped(path). Note that this was added in LÖVE 0.10.0, so in 0.9.x this hook will never be called. path 1.4.3
love_filedropped love.filedropped This is called in love.filedropped(file). Note that this was added in LÖVE 0.10.0, so in 0.9.x this hook will never be called. file 1.4.3
love_focus_gained love.focus This is called in love.focus(f), if f is true. 1.4.3
love_focus_lost love.focus This is called in love.focus(f), if f is false. 1.4.3
love_focus love.focus This is called in love.focus(f), regardless of the value of f, in case this suits you better. If f is true then focus is gained, false if lost. f 1.4.3

To use a hook, place a file with the name of the hook and the .lua extension in the hooks folder in your plugin. So to use the hook called love_draw_end, you need a file love_draw_end.lua inside YourPlugin/hooks/.

To use the args in your hook, you can use .... So in love_update_start, which has the variable dt, you'd put local dt = ... at the top of your hook. In love_mousepressed_start, which has three arguments, you can use local x, y, button = ....

If you need a hook that doesn't exist yet or have an idea for one, or if you need further help with developing a plugin, don't hesitate to tell Dav!

Source edits

As of Ved beta 2, plugins can do find and replace operations on files in the Ved source code. Every internal Lua file can be modified this way, except for main.lua, corefunc.lua, plugins.lua, errorhandler.lua, incompatmain*.lua, and all versions of love*compat.lua.

The file sourceedits.lua in your plugins folder controls these source edits. It contains an array in the following format:

sourceedits =
{
	["SOURCENAME"] =
	{  -- First file to edit: SOURCENAME.lua
		{  -- Edit 1 in that file
			find = [[
FIND CODE
]],
			replace = [[
REPLACE BY THIS
]],
			ignore_error = false,
			luapattern = false,
			allowmultiple = false, -- allowmultiple nyi
		},
		{  -- Edit 2 in that file
			...
		},
	},
	["SOURCE2"] =
	{  -- Second file to edit: SOURCE2.lua
		...
	},
}
ignore_error, luapattern and allowmultiple are all optional and false by default.

If ignore_error is false (or missing), and the edit can't be made because the find code can't be found in the source file, then an orange warning screen will be shown to the user (which they can then dismiss and continue loading). If ignore_error is true, then this warning screen will not be shown.

If luapattern is true, then find will be interpreted as being in pattern format (aka Lua's regex, click here and here for more information), if false or missing it will just be searched as a plain snippet of code.

allowmultiple is currently not yet implemented, but if false it would warn if the same edit is being made multiple times in the same file.

If you need to include ]] in your find and/or replacement string, it's possible to include it by replacing it with something like ]] .. "]]" .. [[

Example:

sourceedits =
{
	["func"] =
	{
		{
			find = [[
function setColorArr(yourarray)
	love.graphics.setColor(yourarray[1], yourarray[2], yourarray[3])
end]],
			replace = [[
function setColorArr(yourarray)
	love.graphics.setColor(yourarray[3], yourarray[2], yourarray[1])
end]],
			ignore_error = false,
			luapattern = false,
			allowmultiple = false,
		},
	},
}
This changes the setColorArr function in func.lua so red and blue color values are swapped around for syntax highlighting in the script editor. This is also included in the updated example plugin.

It does not matter whether your plugin files use Unix-style (LF) line endings, Windows-style (CR+LF) ones, or even classic Mac (CR) ones. Make sure your Ved source files use LF ones, however! If you downloaded a packaged version (.love or Windows/Mac version), it'll probably be fine.

Including files

It's also possible to include entire source files in your plugin, which will be considered as being inside Ved's root directory. Included source files go in the include folder in your plugin. After that, it can just be included with ved_require("your_file"), in a hook or otherwise. Note that this is not much different from how you would normally include a file in Lua: require("your_file").

Warning: this is only intended for your own (original) plugin files, not edited versions of Ved source files (even though it will work)! Adding an entire file will stop official Ved updates from affecting these files (yes, after downloading a new version of Ved) and also overrides any other plugin editing them.

In Ved 1.1.4 and later, you can also have subfolders inside the include folder, so it's probably a good idea to put all your included files in a folder with the name of your plugin to avoid clashes with other plugins or future files in Ved, and then just include them with something like ved_require("my_1st_plug/drawingcode").

As of Ved 1.11.1-pre22, it is preferred to use dots instead of slashes in ved_requires: ved_require("my_1st_plug.drawingcode"). Slashes are still supported, however.

Including assets like images is not yet supported in this way, this may be added later!

Plugin UIs/states

In Ved 1.11.1 and higher, the best way for plugins to add their own states (or "screens") is by including them in a uis folder. You can then jump to these with to_astate(name).

A UI's folder can contain callbacks which are only called when that state is active (like draw.lua or keypressed.lua), as well as elements.lua which has a table of Elements, which are described further in the technical documentation.

As opposed to hooks, these files are expected to return a function (or in the case of elements.lua, a table). So elements.lua should look somewhat like return {}, all the others should look somewhat like return function() end.

A template for a UI folder can be found here.

Callback nameDescriptionArgsAdded
load Called when the state is entered (using to_astate). ... 1.11.1
elements A sequential table of elements 1.11.1
draw Called in love.draw 1.11.1
update Called in love.update dt 1.11.1
keypressed Called in love.keypressed, unless any right click menus or dialogs are open key 1.11.1
keyreleased Called in love.keyreleased, unless any right click menus or dialogs are open key 1.11.1
mousepressed Called in love.mousepressed, unless any right click menus or dialogs are open x, y, button 1.11.1
mousereleased Called in love.mousereleased, unless any right click menus or dialogs are open x, y, button 1.11.1
wheelmoved Called in love.wheelmoved, unless any dialogs are open (in case you're wondering, right click menus close upon scrolling) xm, ym 1.11.1

Technical documentation

There's a technical documentation of Ved that can be found here.

Ved home   Plugins   Technical documentation