Skip to content

Tutorial: Creating the JSON

LB-- edited this page Dec 31, 2012 · 4 revisions

<< Tutorials / << Setting up the ACEs | Adding properties and editdata >>

As you learned in the previous tutorial, your extension's Actions, Conditions, and Expressions are linked to IDs. In turn, you assign information to these IDs using the JSON, which describes your extension's information, menus, and A/C/E parameter names and types. It is vital that the JSON matches your A/C/E functions exactly - minor differences can cause crashes and bugs. If you're coming from rSDK, the idea of the JSON may seem ludicrous; the JSON exists and is separate from the A/C/Es for these reasons:

  • The JSON can be external to the MFX, which allows language translations of the extension without changing the MFX
  • The JSON can be used with a blank EDIF Extension to make the boilerplate Windows version of an extension that only works in a particular export (Flash, HTML5, Anaconda, iOS, etc.)
  • The JSON serves as a centralized place to change all text for an extension
The JSON format is detailed at http://www.json.org/ and can serve as a reference for what valid syntax is, but for the most part with EDIF you only need to be concerned with the layout of the JSON. This is the example JSON provided with the template project:
{
	"About":
	{
		"Name": "EDIF Template Object",
		"Author": "Your Name",
		"Copyright": "Copyright © 2012 Your Name",
		"Comment": "A sentence or two to describe your extension,\nwith up to four lines of text.",
		"URL": "http://www.example.com/",
		"Help": "Help/My New EDIF Extension/Help.chm",
		"Identifier": "X&pl"
	},

	"ActionMenu":
	[
		"Separator",
		[0, "Action Example"],
		"Separator",
		["Sub Menu",
			[1, "Second Action Example"]
		],
		"Separator",
		[0, "A Disabled Menu Item", true],
		"Separator"
	],
	"ConditionMenu":
	[
		"Separator",
		[0, "Are two numbers equal?"]
	],
	"ExpressionMenu":
	[
		"Separator",
		[0, "Add two numbers"],
		[1, "Hello world"],
		"Separator"
	],

	"Actions":
	[
		{	"Title": "Action Example with parameter %0",
			"Parameters":
			[
				["Integer", "Example Parameter"]
			]
		},
		{	"Title": "Second Action Example"
		}
	],
	"Conditions":
	[
		{	"Title": "%o: Are %0 and %1 equal?",
			"Parameters":
			[
				["Integer", "First number"],
				["Integer", "Second number"]
			],
			"Triggered": false
		}
	],
	"Expressions":
	[
		{	"Title": "Add(",
			"Returns": "Integer",
			"Parameters":
			[
				["Integer", "First number"],
				["Integer", "Second number"]
			]
		},
		{	"Title": "HelloWorld$(",
			"Returns": "Text"
		}
	]
}
Notice how the entire JSON is wrapped in curly braces `{}`, this is important to note if you are updating from an older version of EDIF that used the older JSON parser. Also note how everything is comma delimited - you can disable the requirement to use commas by editing Common.h and uncommenting `#define UsingJsonWithoutCommas` which will generally make older JSONs fully compatible after wrapping them in curly braces.

The first main section of the JSON is the About section:

"About":
{
	"Name": "EDIF Template Object",
	"Author": "Your Name",
	"Copyright": "Copyright © 2012 Your Name",
	"Comment": "A sentence or two to describe your extension,\nwith up to four lines of text.",
	"URL": "http://www.example.com/",
	"Help": "Help/My New EDIF Extension/Help.chm",
	"Identifier": "X&pl"
}
Name is the name of your extension, displayed in MMF2's Insert New Object list. If two objects have the same display name, MMF2 will number the duplicate entries starting at 2. Author is, of course, your preferred name or username, and likewise for Copyright.

Comment is the description text shown at the bottom of the Insert New Object dialog in MMF2. This textarea is 4 lines tall without scrollbars, and it has line wrapping, so try to keep to a minimum of text and lines - not everyone has the same width and height for the dialog as you do.

URL and Help are your website and extension help file, respectively, and are displayed in the information properties tab of your extension. The help file path is relative to the MMF2 root directory.

Identifier is used by MMF2 to keep rack of your extension in various ways, and shot not change once decided. It can be any four characters (it is always stored as a 32-bit number) and it should be unique - having two different extensions with the same identifier can cause issues when both are in use in MMF2.

Next are the menus for your A/C/Es:

"ActionMenu":
[
	"Separator",
	[0, "Action Example"],
	"Separator",
	["Sub Menu",
		[1, "Second Action Example"]
	],
	"Separator",
	[0, "A Disabled Menu Item", true],
	"Separator"
],
"ConditionMenu":
[
	"Separator",
	[0, "Are two numbers equal?"]
],
"ExpressionMenu":
[
	"Separator",
	[0, "Add two numbers"],
	[1, "Hello world"],
	"Separator"
]
The Action and Expression menus should start and end with separators, and the COndition menu should start with a separator but not end with one. This is an aesthetic recommendation - you will see why when you look ate the menus in MMF2; MMF2's own menu items are not by default separated from your own.

An A/C/E in the menu is a list with the first element being the ID of the A/C/E and the second element being the text displayed in the menu:

[0, "Action Example"]
An optional third parameter o true is used to indicate that the menu entry should be disabled, in which case the ID does not matter:
[0, "A Disabled Menu Item", true]

Next are the actual definitions for each individual Action, Condition, and Expression. Actions need to know their display string and their parameters, if any:

"Actions":
[
	{	"Title": "Action Example with parameter %0",
		"Parameters":
		[
			["Integer", "Example Parameter"]
		]
	},
	{	"Title": "Second Action Example"
	}
]
Title is the display string shown in MMF2 when you hover over a checkmark. %0, %1, ..., %e, and %f correspond to parameters 0-15, respectively. This applies to Conditions as well.

Each parameter has a type and a name. Actions and Conditions support these parameter types: (Taken from Edif.cpp)

  • Text or String: a string expression, passed as a const TCHAR *.
  • Filename or File: a file parameter, which can be used to include files in the built EXE, or the user can enter a string expression. Passed as a const TCHAR *.
  • Float: a 32-bit floating-point expression, passed as a 32-bit float.
  • Integer: a 32-bit integral expression, passed as a 32-bit signed int.
  • Object:
  • Position:
  • Create:
  • SysCreate:
  • Animation:
  • Nothing:
  • Player:
  • Every:
  • Key:
  • Speed:
  • JoyDirection:
  • Shoot:
  • Zone:
  • Color or Colour:
  • Frame:
  • SampleLoop:
  • MusicLoop:
  • NewDirection:
  • TextNumber:
  • Click:
  • Program:
  • Custom or Custom* where * is any number with any number of digits:
Conditions are the same as Actions, except that conditions can be set as Trigger/Immediate conditions:
"Conditions":
[
	{	"Title": "%o: Are %0 and %1 equal?",
		"Parameters":
		[
			["Integer", "First number"],
			["Integer", "Second number"]
		],
		"Triggered": false
	}
]
Triggered indicates whether the condition should be a red immediate event or not, which can only be triggered by code in your extension. Currently in EDIF, a condition is negateable only if it is not triggered.

Only conditions support these parameters:

  • Comparison:
  • StringComparison:
Expressions are the same as actions except that they have to indicate a return type, and the title has o include the opening parenthesis:
"Expressions":
[
	{	"Title": "Add(",
		"Returns": "Integer",
		"Parameters":
		[
			["Integer", "First number"],
			["Integer", "Second number"]
		]
	},
	{	"Title": "HelloWorld$(",
		"Returns": "Text"
	}
]
Returns is the expression return type. Expressions can only accept and return these types:
  • Text or String: a string value, passed/returned as a const TCHAR *. If returned, the string must remain alive as long as MMF2 needs it - it is recommended to use Runtime.CopyString() for this.
  • Float: a 32-bit floating point number, passed/returned as a float.
  • Integer: a 32-bit integral number, passed/returned as a signed int.
With this new knowledge of what parameter types are supported, you may have to adjust some of your code - but don't be discouraged. Once created, the JSON is easy to maintain - just be sure to keep eveything in the same order - IDs are based on the order you define the A/C/Es in the JSON, with 0 being the first. You should never reassign or shift IDs once set up - you'll just have to settle with things not being organized the way you would like.

<< Tutorials / << Setting up the ACEs | Adding properties and editdata >>