Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
FlatRedBall Plugins are powerful and flexible, allowing custom code to be used to modify how the editor behaves. Plugins can be used to perform almost any type of custom behavior in FRB. Examples of what can be done with plugins include:
Adding new tabs with Custom UI. This UI can include WPF text boxes, buttons, and even SkiaSharp windows.
Defining new file and object types using AssetTypeInfos
Injecting custom code into generated code files, including in Screens, Entities, and Game1
Defining file dependencies which FRB can use to manage Visual Studio project files and to notify the user of missing dependencies
Adding entire code files and .dlls directly in a project
Directly access the file system, FRB project files, Visual Studio project, and code files for any purpose
Checking for and reporting errors.
If you've run the FlatRedBall Editor, then you've already used functionality provided by the plugin system. In fact, almost the entirety of FRB is now constructed through plugins. Every red rectangle in the following picture represents a different plugin.
Note that the code project for the FRB Editor is called Glue, so the plugin documentations use the terms "FlatRedBall Editor" and "Glue" interchangeably.
Typical Glue plugins are created as a regular .NET class library. This class library will need to reference Glue libraries so that it can access Glue objects. A Glue plugin can contain one or more .dll files, and any additional files such as icons or code/content which may be injected into a project. Although not necessary, plugin .dll files can also include embedded resources. The easiest way to create a plugin (as will be shown in later tutorials) is to download the FlatRedBall source and create a copy of the Glue .sln file. This will allow you to compile and debug your plugin against Glue source while Glue is running.
Typically when developing a plugin, the plugin .dll files will be copied to a location where Glue will automatically load them when it starts up. Any loaded plugin can then be exported to a .plug file through Glue (as will be shown in a later tutorial). These .plug files can be distributed however you like - including through email, hosting on a website, or on github.
A common plugin type is one that can modify NamedObjectSave instances. Thee types of plugins exist throughout FlatRedBall. For example, the Collision tab is a plugin which allows modifying NamedObjectSave instances which are collision relationships.
This tutorial shows how to create a plugin which can display and modify custom properties on a NamedObjectSave.
The first step is to create a new plugin. This tutorial skips these steps since earlier plugins explain how to create a new plugin. This tutorial uses a plugin called ExampleNamedObjectPlugin. The class name will follow the convention of prepending the word "Main", creating a class called MainExampleNamedObjectPlugin.
This Plugin contains the following classes:
ExampleView - a WPF view which lets the user view and edit properties on the selected NamedObjectSave
ExampleViewModel - the ViewModel which binds to ExampleView using standard MVVM. It inherits from PropertyListContainerViewModel which provides automatic saving of properties to disk.
MainExampleNamedObjectPlugin - this plugin is responsible for creating the view and viewmodel, and deciding when to show the view
The ExampleView defines the UI for editing the properties on the selected NamedObjectSave. It contains a checkbox to edit a boolean property and a text box to edit a string property. The following is the XAML for this view:
The preview for this view should look like the following image:
Note that this view expects a ViewModel with properties BoolProperty and StringProperty.
The ExampleViewModel should include the two properties mentioned above. If the plugin inherits from the PropertyListContainerViewModel class, it will provide the following functionality:
Automatic notification of property changes
Setting the property on the underlying NamedObjectSave
Automatic saving of the NamedObjectSave to disk
The syntax for using the PropertyListContainerViewModel is similar to using the built-in FlatRedBall ViewModel class.
The main plugin class will respond to a selected tree node and decide whether it should create the view. Plugins can create views and viewmodels when first starting up, or they can do so lazily - only when needed. The following implementation shows how to create the view and viewmodel lazily:
The example above uses the ViewModel's null status to determine if the view and viewmodel have been created. If ViewModel is null, then CreateViewAndViewModel is called which performs a one-time initialization of the view and viewmodel. Assigning the ViewModel's GlueObject automatically associates the namedObjectSave with the ViewModel, resulting in its properties being used to populate StringProperty and BoolProperty - the two properties with the SyncedProperty attributes. Setting these properties through the bound UI automatically updates the JSON for the entity, as shown in the following gif:
No additional work is needed to persist the properties to disk. Whenever the values are assigned, they are automatically saved to disk. If Glue is closed and re-opened, the values will be loaded from the Entity's JSON file and automatically displayed in the UI.
This tutorial provides instructions for creating a Glue plugin class project.
Whether you create a new .sln depends on whether you plan on making a plugin that will be part of the main FlatRedBall repository. If your plugin is intended to be part of the FlatRedBall repository, please discuss your plans in Discord to make sure it will be accepted as a core library. If you are not sure if you want to include it in the main FRB repository, or if you intend this to be separate from the FRB repository, then you create your own .sln. Keep in mind that you do not need to create a new .sln for every plugin you are developing - it may be convenient to have multiple plugins in one .sln file. To create a new .sln file:
Open Visual Studio. If you are using a different IDE such as Rider, you will need to modiyf the steps.
Select the option to create a new project
Select Class Library and click Next
Enter a name and location for your new project and click Next
Select .NET 6.0 as the Framework - this is the current .NET version used in the FlatRedBall Editor as of January 2024, but it will likely change in the future. Click Create.
To link the necessary Glue libraries in your project:
Right-click on the Solution
Select Add -> Existing Project
Navigate to the folder where you have cloned the FlatRedBall Respository. For example, it may be at C:\Users\YourUserName\Documents\GitHub\FlatRedBall
Select the PluginLibraries.csprojj file located at <FlatRedBall Root>/FRBDK/Glue/PluginLibraries/PluginLibraries.csproj
Once this is added to your project, add the PluginLibraries as a dependency to your plugin project. You may notice that your project has a warning in the projects node in the Solution Explorer. To solve this problem, double-click your csproj and modify it:
Set the TargetFramework to net6.0-windows
Add the <UseWPF>true</UseWPF>
tag in teh same PropertyGroup.
For example, after the modifications your .csproj may look like the following csproj:
Now you have a project that is ready to go as a plugin project! Next we'll create our first plugin class.
Before creating a plugin, be sure that you have downloaded the FlatRedBall and Gum repositories, and that you have successfully built and run the FlatRedBall Editor from source. For more information see the .
FlatRedBall plugins can add custom UI to Glue which are hosted in tabs. Tabs can be always visible or in response to events (such as when a file is selected). This tutorial will show how to create a tab that displays information about the selected file.
First we will create a WPF user control in our project:
Right-click on your project and select Add -> New Folder
Name the folder Controls
Right-click on the newly-created folder
Select Add -> New Item...
Select the Installed -> Visual C# Items -> WPF category
Select User Controls (WPF)
Enter the name MainControl (more complicated plugins may have multiple controls)
Click Add
To test the control, we will add a TextBlock at first. Modify the XAML code as shown in the following code:
Now we'll show the control whenever the user selects a file, but hide it whenever another object is selected. To do this, modify the MainTutorialPlugin.cs file as shown in the following snippet:
Let's break down some of the parts of the code above.
This is a delegate which is raised whenever an item is selected. Subscribing to this allows a plugin to perform custom logic when the user selects an item in the tree view. In this case, we will call the HandleItemSelected method. Glue plugins define dozens of delegates such as when a project is loaded, a file changes, or an object is added to an entity.
GlueState.Self provides information about the current state of Glue, including which objects are selected in the tree view. In this case we are checking if a file is selected, which would be represented by the CurrentReferencedFileSave member.
Removes the tab associated with this plugin from Glue - the tab will still be held in memory but it will not display.
AddToTab adds the argument control to the argument tab. In this case we are adding our main control to the center tab control. We only need to call this method once - after that the tab is associated with the center tab and we can call AddTab .
Rebuilding the plugin (make sure to build solution or explicitly select Build on the plugin project) will result in the tab being shown when a file is selected.
Every FlatRedBall plugin must have one class which implements PluginBase. This tutorial provides instructions for implementing the PluginBase class in a plugin.
To add a main plugin class to your project:
Right-click on your project (mine is TutorialPlugin)
Select Add -> New Item...
Enter the name for your plugin (I will name mine MainTutorialPlugin)
Click the Add button
We will make the following modifications to our class:
So far our plugin doesn't do anything yet, but it does have all of the requirements to be an active plugin which can be detected by Glue.
Now that our plugin is ready to be used in Glue, we can add it to be loaded by Glue. While developing plugins, we can add a post-build process to copy the compiled .dll to a location where Glue will find it. To do this:
Right-click on your plugin project and select Properties
Click the Build -> Event category
Create a script in the Post-build event command line: section to create a directory and copy your .dll. You may need to modify the path to point to the correct location.
Notice that the script above assumes that the plugin is called TutorialPlugin - change the script as necessary if your plugin is named differently.
Build your project, then take a moment to verify that your plugin was successfully copied to the Plugins folder in the Glue bin folder.
Glue will automatically load any files in the plugins folder. Our plugin is set up to be loaded, so we can run Glue to see it. We can run Glue from Visual Studio to see our plugin in the plugin Window:
Run Glue from Visual Studio
Once Glue has finished loading, select the Plugin -> Manage Plugins menu item
Look for Tutorial Plugin in the list of plugins (or whatever FriendlyName your plugin is returning)
Note that the plugin is displaying its version of 1.0. Increasing the version number is a good way to verify that your changes are making their way into Glue if you're unsure. You can optionally specify the version number in your plugin, as shown in the following code:
The WPF framework can be used with the MVVM (https://en.wikipedia.org/wiki/Model–view–viewmodel) pattern. Glue provides a useful ViewModel class which can be used as the base class for view models in plugins. This tutorial will show you how to use the MVVM pattern to display data.
Developers familiar with MVVM can implement view models according to their own preferred patterns or frameworks, but we will be covering one way to implement view models using Glue's base ViewModel class. Specifically we will be modifying the plugin from the previous tutorial to display information about the selected file. First, we'll create a view model for the control:
Right-click on the plugin project and select Add -> New Folder
Name the folder ViewModels
Right-click on the newly-created folder and select Add -> Class
Enter the name MainControlViewModel
Click Add
Next we'll modify the view model to implement the base ViewModel class and to have properties for displaying information about the file. Modify MainControlViewModel.cs as shown in the following code snippet:
The code above can be used to display the file name and write time of the selected file in our MainControl. Next, we'll update the XAML to add TextBlocks with binding, as shown in the following XAML:
Finally we can create add a MainControlViewModel instance to our MainTutorialPlugin class and assign the view model in the HandleItemSelected method, as shown in the following code snippet:
Now we can run our project and see information about the selected file.
Glue can notify plugins when a file changes. To respond to these changes, the plugin can use the ReactToFileChangeHandler delegate, as shown in the following code snippet:
We an change files which are selected and the plugin will be notified of the change and will automatically update the displayed information.
This tutorial will cover how to add files to a project using FlatRedBall plugins. We will be adding .cs files to a project when the project is initially loaded.
The first step is to create a Glue Plugin project. To do this:
Launch the NewProjectCreator through the start menu.
Select "Glue Plugin Template"
Enter the project name
Select the location
Click "Make my project!"
Next we'll add files that we want added to our project. To do this:
Create one or more files that you would like to include through your plugin
Add these files into your plugin project
For each file in your project, right-click and select "Properties"
Change "Build Action" to "Embedded Resource"
Once you've added the files you want to include we'll write the code to include these files in projects that Glue is managing. First, add an instance of a CodeBuildItemAdder:
Next we'll write the code to add the "Embedded Resource" files to the project managed by Glue. Add the following code to your plugin class' StartUp method:
The code above is pulled from a project where the project name is StateInterpolationPlugin, and the files Back.cs and Bounce.cs were added directly in the project (as opposed to being added in a folder). If the files are added in a folder (such as MyFolder) then you will need to change the file names (such as "StateInterpolationPlugin.MyFolder.Back.cs"). After making the "Add" calls, we need to tell the CodeBuildItemAdder where to save the files in the project that it is going to modify. To do this, add the following call:
This will result in the files being placed in a folder called "DesiredOutputFolder". Finally we'll need to tell Glue that these files should be added to the project. To do this:
If your files do not show up, you can troubleshoot the process as follows:
Look at the output window of Glue - if your plugin has crashed then Glue will display a callstack
Put try/catch statements around relevant code, such as PerformAddAndSave, and see the exception message for more information on what might be happening
Select Plugins->Manage Plugins to see all plugins and investigate any failures which may have occurred.
That's all there is to it. Now all of the code items marked as Embedded Resource and added to the CodeBuildItemAdder will be added to any project loaded with Glue when the plugin is installed.
To create a .plug file:
Open Glue
Select "Plugins"->"Create Plugin"
Select the folder inside Glue's Plugins folder that contains your plugin. If you are using Windows 7, this may be located in "c:/Program Files (x86)/FlatRedBall/FRBDK/Xna 4 Tools/Plugins"
Click OK
Select the location and file name for the exported plugin and click OK
You will now have a .plug file which you can share with others or upload to GlueVault.
Glue plugins can be used to load custom files beyond the standard files that can be loaded natively (such as .png). This document shows how to load a custom file format.
Glue uses a type called AssetTypeInfo to define the types of objects that are recognized by Glue. The AssetTypeInfo contains a variety of information about how to work with a file. The following properties are needed when adding support for new file formats:
QualifiedRuntimeTypeName - the qualified (includes namespace) runtime type of the class created when the file is loaded. For example Microsoft.Xna.Framework.Graphics.Texture2D
Extension - the file extension of the file supported. For example png
FriendlyName - a name shown to the user in the FRB Editor so they can select the type. For example Texture2D
CustomLoadFunc - a method which returns the string which is injected in generated code to create the runtime object.
AddToManagersFunc - a method which returns a string which is injected in generated code to add the runtime object to managers. This is only required if the object that is created is an object which can be added to managers. For example, a Texture2D is not added to managers, but a LayeredTileMap (Tiled map) is added to managers.
The CustomLoadFunc and AddToManagersFunc methods can return a single line of code or they can return a complex initialization block. For the sake of convenience for the user, if possible the generated code should return as few lines of code as possible. In other words, rather than creating a large block of code to load a file or to add the file to managers, this code should be contained in a class or method which can be called either in generated code or custom code. Some games require the flexibility of being able to load content in custom code, and users will appreciate any simplicity your plugin provides.
In most cases a plugin defines and adds its AssetTypeInfo instances when the plugin first starts. In rare cases a plugin may add and remove AssetTypeInfo instances in response to projects being loaded and unloaded.
In the simplest case, an AssetTypeInfo can be added in a plugin's StartUp method. For example, code to add an AssetTypeInfo might look like the following code snippet:
todo: add example code
If you have written and tested a plugin, and you're now ready to share it with others, congratulations! Glue makes this process very easy. Glue supports exporting a plugin (which may be just one file or multiple files) as a single file with the .plug extension. .plug files can be shared directly with other developers or uploaded on .
Press the "..." button to find the folder that contains your plugin