Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Files loaded by Glue can be used to either create "save objects" and "runtime objects". Save objects are objects which can be loaded directly from file. Save objects are typically not added to the FlatRedBall Engine, nor do they require loading other files which use content managers (such as Texture2Ds). Runtime objects are typically used in games. Runtime objects can be used for one or more of the following purposes:
To render graphics to the screen
To perform collision
To position or manage other runtime objects
Runtime objects are often either directly added to FlatRedBall managers (if they inherit from the PositionedObject or include objects which are added to managers). In this case the runtime object needs two calls:
An "add to managers" method which is responsible for adding the object and any contained objects to the FlatRedBall Engine
A "remove from managers" or "destroy" method which removes the object and all contained objects from FlatRedBall managers
Objects which follow a number of guidelines regarding add to managers and destroy can be used in Glue in advanced and useful scenarios. This article discusses these guidelines which can be used when constructing runtime objects to be loaded by glue.
The code which adds an object and its contained objects to FlatRedBall managers should:
Be a separate call from the code that instantiates the runtime object
Should either not be called by the code that instantiates the runtime object, or should be optionally called
Should be a public method.
Should not load any data from-file. All from-file loading should be done in instantiation/initialization. .
The reason for the separation between initialization and add to managers enables Glue to do the following when your runtime object is contained in a Screen or Entity:
Instantiation of Screens and Entities on a non-primary thread.
Pooling of Entities.
The ability to be added to a Layer (instantiation and layering are typically done on two separate calls for FlatRedBall objects)
All runtime objects should have some type of destroy method/logic. The destroy method is responsible for removing the object and all contained objects from FlatRedBall managers.
Runtime objects which are created from files should support a Clone method. The reason for this is because a single instance may be loaded from file, but then multiple instances may be needed if multiple Entities use the same file.
This article discusses how to modify your content CSV to support creating a "runtime object" from a file. A runtime object is an object which typically has the following characteristics:
It has every-frame activity
It has some kind of membership in the FlatRedBall managers (such as it adds Sprites to the SpriteManager, PositionedObjects to the SpriteManager, or Text instances to the TextManager)
It must be removed or destroyed
To distinguish between the two, a non-runtime object would be an object that simply represents the contents of a file such as a Texture2D or a "save" object. A runtime object is an object that is typically visible or has collision, and interacts with other runtime objects ( for example Sprites, Entities, or shapes).
For this article we'll start with a very simple setup:
Create a Glue project
Create a single Screen in this Glue project
Create a file for the desired type you're working with
Place the file under your newly-created Screen's files folder on disk
For this article we'll assume your file is called MyFile.ext and the Screen is called MyScreen.
Next we'll add/modify the CSV to handle this new file. For this we'll assume that the runtime object made by MyFile.ext is "MyRuntimeObject" and the save object is "MyRuntimeSave". Therefore, the CSV should look like this:
Now that you have MyScreen and MyFile.ext created:
Right-click on your MyScreen's Files item
Select "Add File"->"Existing File"
Select MyFile.ext
At this point your object should be loaded, created as an instance, and added to managers. You can verify this by either looking in the generated code for "AddToManagers" or running the game (assuming AddToManagers will properly make your object visible).
Note: So far this example uses a Screen. The reason for this is because creating runtime objects from files is slightly easier to do in Screens. If an object that can be a runtime object is added as a file to a Screen, Glue assumes that you intend to add the object to managers. Therefore, no additional work is needed aside from simply adding the file to a Screen. Entites require a little more work, as we will see in the following section.
Entities require a small amount more of work to create objects. Specifically you must both add a file and also add an object to be created from this file. To do this:
Create a new Entity. I'll use the name "MyEntity"
Right-click on the Entity's "Files" item
Select "Add File"->"Existing File"
Select MyFile.ext
Right-click on MyEntity's "Objects" item
Select "Add Object"
Select the "From File" option
Select MyFile.ext (which will probably include a folder path"
Name the object appropriately. I'll use the name "MyFileObject"
Change the newly-created Object's "SourceName" to "Entire File (MyRuntimeObject)
FriendlyName (required)
CanBeObject(bool)
QualifiedRuntimeTypeName
QualifiedSaveTypeName
Extension
AddToManagersMethod
CustomLoadMethod
DestroyMethod
CanBeCloned
CustomCloneMethod
MyRuntimeObject (.ext)
TRUE
QualifiedType = ProjectNamespace.RuntimeTypes.MyRuntimeObject
ProjectNamespace.SaveTypes.MyRuntimeSave
ext
this.AddToManagers()
{THIS} = ProjectNamespace.SaveObjects.MyRuntimeSave.FromFile("{FILE_NAME}").ToRuntime()
this.Destroy()
TRUE
this.Clone()
The "Scan for Unreferenced Files" menu option performs a scan of all files referenced by the currently loaded Visual Studio project. Any file which is not directly or indirectly referenced by a file in Glue will be identified as unreferenced. Glue does not do a source-code scan of your project as it would be difficult and in many cases impossible to do so, so files referenced only by code may still be considered unreferenced. To keep this list accurate game projects should include all relevant files in Glue, especially as this helps make content loading/unloading more predictable. Once the scan completes Glue will present a window with all unreferenced files. Once a file is selected it can be removed from all projects (main and synced) by clicking the "Remove references" button:
The Content Pipeline Settings menu item opens the Content Pipeline tab in Glue. This tab controls settings for content pipeline behavior in Glue.
This plugin is still in the early stages. Additional options may be added in the future to control how content is built.
This checkbox controls whether all PNGs in the project will be loaded using the content pipeline. By default this value is false. Checking this value will perform the following actions:
Glue will build all PNGs into .XNB files in a special folder depending on the project type. Each project will have a separate folder with XNBs
Glue will change all PNG references for all projects to point to the built XNB files
Glue will generate aliases for all PNGs so that no code changes are required when referencing the PNGs
Using the content pipeline for PNG files has some benefits, but these benefits also have some downsides. Fortunately, your project can switch switch between using the content pipeline and loading PNG's directly at any point simply by checking or unchecking the Load all PNGs using Content Pipeline checkbox.
The biggest benefit of using the Content Pipeline is that image files loaded from XNB will load faster compared to using PNGs. Note that the slower-loading of PNGs is a FlatRedBall-specific cost. Readers who are using MonoGame without using FlatRedBall may not see speed improvements when moving to XNB loading. The reason for the improved load time is because FlatRedBall performs extra processing when loading PNG files so Texture2Ds include premultiplied alpha. If a Texture2D is loaded from a content pipeline XNB, no additional processing is necessary. This additional processing can result in a significant load time increase - in some cases more than doubling the amount of time a screen takes to load. Content Pipeline XNBs may also use hardware compression (depending on the platform), which results in Texture2D instances using less video memory, and rendering more quickly due to improved caching.
When using the Content Pipeline, PNG files must be converted to XNB files. This conversion is performed whenever a PNG is changed (either when saved locally or when downloaded through version control). Large projects with multiple platforms may take some time (such as over 1 minute) to process all XNB files. Some platforms do not compress image XNBs, which means a corresponding XNB may take more space on disk than the original PNG. Fortunately, this is not as important on some platforsm such as Android because the .apk file itself is zipped.
Typically FlatRedBall loads files using extensions, such as: var texture = FlatRedBallServices.Load<Texture2D>("myImage.png"); However, in XNA/MonoGame, files loaded through the content pipeline do not use an extension. For example, to load a texture from a .XNB file (a processed content file), the extension would be omitted, as shown in the following code: var texture = FlatRedBallServices.Load<Texture2D>("myImage"); The content pipeline settings in Glue are intended to be swapped without requiring any changes to custom or generated code. Therefore, even when using the content pipeline, the code must be able to load a file with its extension, such as "myImage.png". To resolve this, Glue generates a method called SetFileAliases . This method will associate the file with its extension with the file without its extension. Internally when FlatRedBall is told to load a file, it will check if that file exists in the FileAliases list, and if so, it will use the alias. Therefore, any code written which may reference a file by extension does not need to change when switching to the content pipeline.
CSV files are used by Glue to control which file types are available, and to tell Glue how to generate code to load them and create instances in code. Standard FlatRedBall types (such as Scene and AnimationChainList) are represented in a CSV file which is stored in the following location: Global content types:
Project-specific types:
Glue allows for the creation of additional CSVs which can define how to load and generate code for custom content types. The New Content CSV menu option creates a new CSV file which Glue will automatically load on startup (Glue must be restarted for new or changed files to be used).
To create a new CSV file:
Select the Content->"Additional Content"->"New Content CSV..." menu option
Enter the name of the CSV to add. Since Glue can support any number of CSVs we recommend creating new CSVs for categories of objects rather than continually appending to existing CSVs.
Select whether you would like this new CSV to apply to all projects or only your current project. This will impact the location of where the CSV is saved.
An explorer window will appear displaying the newly created CSV (along with any other existing CSVs)
Objects can be instantiated directly inside the Objects folder of Screens or Entities. Typically these instances are of standard types such as Sprite or TileShapeCollection. Also, the type of instances can be entity types, such as an instance of a Player in the GameScreen. If your game includes a special type which is not an entity type, the FlatRedBall Editor can display this type by adding it to a custom type CSV.
As an example, consider a custom PositionedObject class. The class doesn't need to have any functionality, it just needs to be defined in your project so that generated code can work with it. Therefore, an empty class will do, as shown in the following snippet:
Now we can add this type to a custom CSV.
Select Content -> Additional Content -> New Content CSV...
Enter the name ProjectSpecificContent and click OK
A folder should open displaying the newly-created ProjectSpecificContent.csv. Double-click it to open it in the default spreadsheet application installed on your machine
Enter the values for properties as specified below:
Friendly Name: CustomType
CanBeObject: true
QualifiedRuntimeTypeName: QualifiedType = CustomTypeProject.CustomType (this should be your qualified name)
AddToManagersMethod: FlatRedBall.SpriteManager.AddPositionedObject(this)
DestroyMethod: FlatRedBall.SpriteManager.RemovePositionedObject(this)
ShouldAttach: true
IsPositionedObject: true
AdjustRelativeZ: this.RelativeZ += value
For examples on how to work with this CSV file, see the ContentTypes.csv file which is located relative to the GlueFormsCore.exe project, or in the Visual Studio project if you are building from source. Once you have modified and saved the CSV, shut down and restart the FlatRedBall Editor. If the file was loaded correctly you will see output which looks similar to the following text:
You can now right-click on the Objects under any Screen or Entity and you should see your type.
Since this type is also a PositionedObject, your entities can use it as their base.
By default instances of new types that you create do not have any variables visible in the Variables tab. You can change this by adding variables which you would like automatically visible by modifying the VariableDefinitions column. The standard ContentTypes.csv file provides a great example of how to define VariableDefinitions. One of the largest set of variables is on the Sprite's VariableDefinitions column.
Add as many variables as you would like available. Also, you are not limited to PositionedObject properties. If you add new properties to your type in code, you can expose these to the FlatRedBall Editor by modifying the VariableDefinitions column.
Each entry (usually one row) in a CSV defines how a file type is loaded into a runtime object. This code tells Glue how to generate code to load and interact with various file formats. Before creating an entry in a CSV, you will first need to create a new file format (or use an existing file format) which can be loaded along with an object that the file can be loaded into. For example, if you are using a custom XML file to define the layout of a level in a puzzle game, you may first create an XML file which can contain information about the level, then a class which can hold the information loaded from the XML file. Once you have created this file format and a class to hold its information, will want to test out the loading of this data in custom code first to verify that it is working correctly before you begin to integrate it into Glue.
Note: There are typically two types of objects that a file is loaded into in FlatRedBall. The general terms for these types of objects are "save objects" and "runtime objects". Save objects are objects which are typically not used directly in games. They serve as objects which can hold data in a format that is very similar to how the data is stored in a serialized (XML, CSV, or other format) state. Runtime objects are typically objects which are used in actual games. Runtime objects typically have some type of graphical component, often require a content manager to create, and have some component which is added to FlatRedBall managers.
For an example, we'll use custom file format (.lin) and load it into a new class called LinesOfText which will be a class that contains a string array. The LinesOfText object is somewhat of a trivial class, but again we'll create and use this for the sake of keeping the tutorial simple.
For this example we'll use the following LinesOfText class:
If you're following along, create a new class in your project called LinesOfText, then paste the text above into the newly-created class.
Now that we have the runtime type (the LinesOfText class) defined and in our project, we can information to a custom CSV file. To create the CSV file:
Open Glue
Select the Content->"Additional Content"->New Content CSV..." menu item
Enter the name LinesOfTextContent. Typically you would call the CSV to indicate the library or game that is associated with the content types.
Click OK
Next we'll add information to the new CSV:
Open the newly-created CSV file in a spreadsheet program (such as Excel or OpenOffice Calc)
Add data to the following columns:
The CSV file contains many fields which can be used to customize the way Glue interacts with your file and runtime types, but the list above is the minimum requirement for loading a custom file type. In other words, we don't cover all available columns in this tutorial, just the necessary ones. The columns are listed together in the table above to keep the example smaller, but they may be spaced out in the CSV. Let's look at the individual columns to understand what they mean.
The "FriendlyName (required)" column specifies the name of the file type as it appears in the new file window's drop down. It is marked as "(required)" because each entry can contain multiple values for some of the add methods (which we don't cover in this tutorial). The most common format is to list the runtime class name along with its extension in parenthesis. In our case: "LineOfText (.lin)"
The QualifiedRuntimeTypeName column specifies the name of the runtime object that is created when the file is loaded. This is the type of the member that will be added to the Screen or Entity that contains the class. The name must be fully-qualified as to avoid conflicts with same-named types in different namespaces, and to enable Glue to add instances to generated code without generating compile errors. The reason "QualifiedType = " must be prefixed is because as of September 10, 2012 Glue supports platform-specific runtime types. We won't cover how to use that functionality in this tutorial.
The QualifiedSaveTypeName is the name of the class that is responsible for loading the file from its file format and creating an instance of the runtime object. In our case we simply use the same class (LinesOfText) as both the "Save" object as well as the runtime object, so the two types are the same. Some types (like Scene) have separate "Save" objcts (like SceneSave).
The extension tells Glue which extensions to associate to the runtime type. This is used when creating new files, when adding existing files, and if multiple types use the same extension, to allow the user to specify the type. In our case the extension is "lin".
This is the line of code (or multiple lines of code) which Glue will use to instantiate the runtime object. In this case two parts of the line are replaced. {THIS} is replaced by the name of the instance that is being created, and {FILE_NAME} is replaced by the file name to load.
Once you have created/modified the content CSV file, you will need to restart Glue. After Glue starts, you can add a .lin file to your project as follows:
Create a Screen or Entity to hold the new file
Right-click on Files and select "Add File"->"New File"
The drop-down under "Select the file type:" should include an entry for the .lin file type. Select "LineOfText (.lin)"
Click OK
How does Glue make new files? Since Glue does not understand the structure of custom files, it will create an empty file with the given extension. Many applications will automatically open up when you create a file with extensions that they handle, so this is often desirable behavior.
Once a file has been added to your Screen or Entity it is immediately available in code. The instance added to code will match the name of the object in Glue - which by default will be LineOfTextFile. For example, to access each line of text in the loaded file, you could add the following code to the custom code of your Screen/Entity:
**File members are static:**By default files be static when added to Screens and Entities. Keep this in mind if typing "this" before the "LineOfTextFile".
FriendlyName (required) | QualifiedRuntimeTypeName | QualifiedSaveTypeName | Extension | CustomLoadMethod |
LineOfText (.lin) | QualifiedType = ProjectNamespace.RuntimeTypes.LinesOfText | ProjectNamespace.RuntimeTypes.LinesOfText | lin | {THIS} = ProjectNamespace.RuntimeTypes.LinesOfText.FromFile("{FILE_NAME}") |