Skip to content
LB-- edited this page Apr 11, 2013 · 9 revisions

<< Home | Tutorials >> / Setting up the ACEs >>

Note: This tutorial is designed for an in-development version of EDIF - get it here

If you've used rSDK, you'll know that macros were abused in such a way that lawyer James McLaughlin filed a lawsuit against rSDK developer James McLaughlin, which led to the creation of EDIF by the hands of Anders Riggelsen and James McLaughlin. EDIF aims to make Windows extension development more natural by using real C++, namely a real C++ class for the heart of the extension. It also aims to make language conversions easier - simply by swapping out the external JSON with a translated one, you can translate (almost) the entire extension.

To start, download EDIF by clicking the download as ZIP button (or click the convenient link), then extract EDIF to its own folder somewhere. You should find these:

  • Extensions - This directory contains the project folders for all one hundred of the amazing extensions you will create in your lifetime.
  • Inc - This is the includes folder, which is essentially all the MMF2 SDK headers and the EDIF header. You shouldn't need to bother with these. These files are global to all extensions.
  • Lib - This is the libraries folder, which contains a couple MMF2 SDK libraries and also the source files for EDIF. You shouldn't need to bother with these either, unless there is a bug in EDIF. These files are also global to all extensions.
  • .gitattributes - This is a file for Git functionality, you can delete it if you want to.
  • .gitignore - This is also a file for Git functionality, you can also delete it if you want to.
  • README.md - This is the readme file, as shown at the bottom of the repo. It is written in GutHub Flavored MarkDown, so it is best viewed here on *gasp* GitHub.

Open the Extensions folder and create a copy of the Template project folder. This copied folder will become your first EDIF extension. Go ahead and fire up your favorite flavor of VC++ (2008 or above, express edition will work) and open the Template.sln file. You don't need to worry about renaming the project or solution unless you often lose track of which extension you're working on and need some indicator in the title bar of VC++. Expand the "This Extension" tree on the left and all sub-trees. Oh boy, that's a lot of files. Don't worry - for basic extensions, you'll only have to deal with a few of them. Comments throughout the files can also guide you if you are familiar with C++ and the SDK, in which case you don't really need this guide. The comments are not full documentation - for a complete reference, see the Reference.

Extension Project Overview

  • Edittime - This contains files that deal with edittime behavior for your extension. For now, you only need to be concerned with one line of one file.
  • Properties.cpp - In the function GetPropValue, change the "Default.EDIF.Template.0" text to whatever version number you want, eg "Beta #1" or "Build #1" or "Version Number One", etc. That's it for now! This file is used to define the properties of your cool extension. There is a lot of flexability in what you can do with the properties, and this is where all the cool stuff happens with the editdata.
  • EditData.hpp - This class header, which is included by Common.h just before including Extension.hpp, is where you can set up information and variables that need to be stored at edittime, such as the variables proeprties correspond to. The default state of the EditData class is suitable for most extensions without properties, though, so usually you can let this be.
  • TextProps.cpp - If your extension displays text at edittime, this is where you should go to get that fancy text properties tab that text extensions have. Just let MMF2 know which properties your extension supports and implement the getters and setters for those properties.
  • CustomParams.cpp - Have you ever wanted to make a custom parameter dialog? Have you ever wondered how Jax got that cool open file dialog for INI++? This is the place to go. Here you can define the custom parameters your extension uses. In the JSON, "Custom#" will represent a custom parameter. Just "Custom" by itself will be the same as "Custom0". You don't have to go in order either (you can skip to "Custom1337" if you want).
  • Edittime.cpp - Functions that didn't get split into any of the above files are in here. This is generally where the frame editor interacts with your extension. One key function is MakeIconEx - this is where you can adjust the transparent color of your icon if you don't use an Alpha channel.
  • General - The files in this folder are used by both the Edittime and the Runtime portions of your extension.
  • Common.h - This is the common header file to all the source files in your extension. Anything you put in here is, for all intents and purposes, global. You might want to include your favorite headers and favorite inline functions to make your development life easier.
  • General.cpp - These are general functions that are used both at edittime and runtime. You might need to edit some things in here for some of your truly brilliant extensions, but for the most part you can safely leave this alone.
  • Resource Files - These files are involved with/actually are resources that get stored inside your built extension MFX. You'll want to change a couple very important things before publishing the first beta version of your awesome new extension.
  • Icon.png - All good extensions have good icons. Your extensions will be great, so you should have a great icon for it. It can be any size you want - EDIF will adapt the code for you - but the standard is 32x32 pixels. (To adjust the transparent color, you'll have to edit a line in Edittime.cpp, described below).
  • Ext.json - The most important file - the JSON. This is where you define your new extension's information, menus, and the signatures of your extension's Actions/Conditions/Expressions (A/C/Es for short). RickyRombo is working on a JSON Generator utility for public use, but it won't work for everything (and currently needs updating for the latest version of EDIF). The example JSON should be enough, however, to get you started on the basics. The JSON syntax is critical - one mistake prevents MMF2 from loading your extension. Additionally, if the JSON A/C/Es don't match up correctly to the A/C/Es you have defined in your Extension class, the best case scenario is that your extension will crash at runtime. Some would complain that this is as bad as setting up the A/C/E jump tables in the original SDK, but after a while it becomes easier - it has a clear, defined syntax, and you can actually tell what what you're writing means. (The double-what is intentional, in case you were wondering).
  • Resource.h - If you need to store resource files, this is where you put the IDs for them. For most extensions, though, you don't need to bother with this.
  • Ext.rc - This is your extension's resources file. You can edit it as plain text if you use VC++ Express Edition. For most extensions you won't need to mess with this.
  • Runtime - By default, everything in here should be ready to go for your first extension to be amazing.
  • Runtime.cpp - This is where the generic runtime functions are defined, namely stuff for collision masks and Start/End App/Frame functions, and the WindowProc function. You shouldn't need to edit anything in here for most simple extensions - all the cool runtime stuff gets done in the Extension class.
  • Debugger.cpp - This is where you can interact with the run-from-MMF2 debugger. You can have custom values displayed for your extension and even have some be editable. This can be useful if you want to see your extension's internal values from the MMF2 debugger as with any other object. Most third-party extensions don't utilize the debugger however, which is all the more reason for you to do so with each of your amazing extensions.
  • Text.cpp - This is the runtime version of the TextProps.cpp file from edittime - it is essentially the same, except for runtime.
  • The Extension Class - Finally, the bulk of your extension and the place you'll be spending most of your time in. These files define the Extension class, which contains the runtime variables your extension will deal with as well as member functions for the A/C/Es.
  • Extension.hpp - This header file, which is included by Common.h, is where you define the Extension class. Place your variables in this class and declare your A/C/Es just like in the JSON, and maybe tweak the OEFLAGS and OEPREFS. Other than that, the real stuff happens in the source files.
  • Extension.cpp - This is where you define your extension's constructor and destructor. From other SDKs, these parallel CreateRunObject and DestroyRunObject, except you use your extension class instance instead of rdPtr and you don't need to call constructors or use pointers unnecessarily. In the constructor you must link your A/C/E function names to their IDs in the JSON file. Usually you don't ever need to write anything in the destructor, because C++ is a nice language where destructors are called automagically. Also in this file you define Handle (HandleRunObject), Display (DisplayRunObject), Pause & Continue (PauseRunObject & ContinueRunObject), and Save & Load (SaveRunObject & LoadRunObject), which are all instance member functions of your Extension class. There are also the "Action", "Condition", and "Expression" functions, which are called when there's no A/C/E linked to an ID at runtime. Usually if they get called it means you forgot to link something, but you can also use them as a feature in some cases. For now, you can ignore them, or just put MessageBox functions in that let you know that an A/C/E is unlinked. (Make sure the message only appears once, otherwise you may have a hard time closing the running application).
  • Actions.cpp, Conditions.cpp, Expressions.cpp - As you would expect, this is where you define each of your Actions, Conditions, and Expressions. If, for instance, your actions are the only place you need to use a certain library or functions, you can have them just be included in Actions.cpp to save the compiler from having to deal with them in other source files. Other than that, make sure your definitions match the declarations in Extension.hpp.
  • Ext.def - This is how the VC++ linker knows which functions to export and what names and ordinals to export them with. Some functions in the SDK are optional and are commented out both in their respective files and here in the Ext.def file. If you implement one of these optional functions, you need to uncomment the function in here as well. For most extensions, however, you won't need to deal with this file at all.

Compiling

Firstly, make sure you change the project name from "Template" to the name you want for your extension's MFX file - make sure the name contains no spaces or other odd characters (the name will be used as identifiers for the exporters) so e.g. letters and underscores only, and numbers as long as they are not at the start. The name is what will come before ".mfx", and once you distribute a version with that name you shouldn't change it, because if you do, it makes it very difficult or even impossible for people to upgrade to the new version of your extension.

Before you get too far into wiring all the beautiful code required to make your new extension awesome, you should check to make sure that you can properly compile EDIF projects. Start by compiling the "Edittime" project configuration. When you run the compiler, the output should look similar to this:

1>------ Rebuild All started: Project: Template, Configuration: Edittime Win32 ------
1>Deleting intermediate and output files for project 'Template', configuration 'Edittime|Win32'
1>Compiling...
1>CustomParams.cpp
1>Edif.Runtime.cpp
1>Edif.General.cpp
1>Edif.Edittime.cpp
1>Edif.cpp
1>ObjectSelection.cpp
1>Extension.cpp
1>Expressions.cpp
1>Conditions.cpp
1>Actions.cpp
1>Text.cpp
1>Runtime.cpp
1>Debugger.cpp
1>General.cpp
1>TextProps.cpp
1>Properties.cpp
1>Edittime.cpp
1>Generating Code...
1>Compiling...
1>json.c
1>Compiling resources...
1>Microsoft (R) Windows (R) Resource Compiler Version 6.1.6723.1
1>Copyright (C) Microsoft Corporation.  All rights reserved.
1>Linking...
1>   Creating library .\ReleaseEditor/Template.lib and object .\ReleaseEditor/Template.exp
1>Performing Post-Build Event...
1>MFX File: c:\Users\My Username\Desktop\EDIF\Extensions\MyReallyCool-Object\MFX\Extensions\Template.mfx
1>MFX Destination: \Extensions
1>MMF2 Dev Path: C:\Program Files\Multimedia Fusion Developer 2
1>        1 file(s) copied.
1>ERROR: The system was unable to find the specified registry key or value.
1>You don't have MMF2 Standard
1>Build log was saved at "file://c:\Users\My Username\Desktop\EDIF\Extensions\MyReallyCool-Object\ReleaseEditor\BuildLog.htm"
1>Template - 0 error(s), 0 warning(s)
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

When you build any of the project configurations, the built MFXs get put into some sub-folder of the MFX directory in your project directory. This is set up so that you can literally zip the contents of the MFX folder (read:not the MFX folder itself, the contents of it) and distribute that once you've built each of the supported build configurations. You'll also notice in the output something rather interesting:

1>Performing Post-Build Event...
1>MFX File: c:\Users\My Username\Desktop\EDIF\Extensions\MyReallyCool-Object\MFX\Extensions\Template.mfx
1>MFX Destination: \Extensions
1>MMF2 Dev Path: C:\Program Files\Multimedia Fusion Developer 2
1>        1 file(s) copied.
1>ERROR: The system was unable to find the specified registry key or value.
1>You don't have MMF2 Standard

When you build your extension, EDIF automatically copies the built MFX to the correct directory of both your MMF2 Standard installation and your MMF2 Developer installation. If you don't have one or the other, or both, you'll get errors, but it won't affect compilation. This automatic install is done as a convenience for you, so you can continue testing your extension without having to constantly install each new version. You still have to close MMF2 when you build your extension, though. As another cool note, the MMF2 paths are detected from the registry, so even if you installed MMF2 to an odd location, EDIF can still copy the built MFX to your MMF2 installation.

Once you've performed the test build, fire up your favorite flavor of MMF2 and make sure you can successfully add your extension to the frame editor and run the application without it crashing. If you get an error message while MMF2 is on the loading screen, it means you have a syntax error in the JSON.

The build configurations

EDIF lets you build Debug, Edittime, and Runtime versions of your extension for each of normal, HWA, and Unicode. (Vitalize was supported in the past, but has sense been deprecated). This leaves you with 9 build configurations to choose from. The Debug and Edittime configurations will work both for edittime and runtime, where as the Runtime configurations, as the names suggest, will only work for runtime. Each build configuration builds to a different path:

  • Debug: MFX/Extensions/
  • Debug HWA: MFX/Extensions/HWA/
  • Debug Unicode: MFX/Extensions/Unicode/
  • Edittime: MFX/Extensions/
  • Edittime HWA: MFX/Extensions/HWA/
  • Edittime Unicode: MFX/Extensions/Unicode/
  • Runtime: MFX/Data/Runtime/
  • Runtime HWA: MFX/Data/Runtime/HWA/
  • Runtime Unicode: MFX/Data/Runtime/Unicode/

This is designed so that you can open the MFX folder in your project directory, ZIP its contents, and distribute the zip as your extension, which can then be extracted directly to the MMF2 root folder for proper installation. Only the .mfx files are placed here - you must be responsible for including the /Help/Your Extension/ and /Examples/Your Extension/ folders (you should prefer Help and Examples over a Readme). Another important thing to note: The default filename for your extension is Template.mfx - you must change your project name in VC++, as it will affect all 9 build configurations. Do not try to change the build filename in the project linker settings. This is the number one mistake to be made - you forget to change the filename and you've already created all the example MFAs, what will you do then?

In the Runtime configurations, the macro RUN_ONLY is defined. You can use this to exclude edittime-only code from the runtime version of your extension, making it more compact:

#ifndef RUN_ONLY
	//edittime-only code
#endif

You will see this many times throughout EDIF.

As a helpful hint, VC++ has a batch build feature under Build -> batch Build... which lets you select all the configurations you want to build and build them all at once. This is useful to leave running while you do something else, then you can come back and distribute the new version of your extension.

Tell me more!

Check out the Tutorials, which have a lot of useful information for you.

Common "Extension Development Is Frustrating"-problems

"I'm tired of seeing all these comments, but I don't want to delete them."

In VC++, you should see a + on the line number next to the start of the comment. Click it to toggle the visibility of the comment - it'll stay around, it just won't bother you anymore.

"My extension crashes on certain A/C/Es."

Check your JSON file and make sure it matches exactly the declarations and definitions of the A/C/Es in your Extension class. Also note that when defining the A/C/Es in the JSON, the order is important - since you don't specify which ID you're dealing with, the first definition is 0, then 1, and so on - so no skipping IDs to allow for future functions.

"I just created a new version of my extension after releasing the previous version, and now MFAs are scrambled and even crash in the event editor."

You can't rearrange the IDs of your A/C/Es - once you start making MFAs or you release the extension to the public, the IDs you paired are set in stone. You'll just need to set aside your OCD and accept that related functions can't always have consecutive IDs.

"I've lost all or part of my extension and/or need to revert to my old JSON file, and I have access to the public download for that version."

Download that public version. If you stored the JSON externally, you have that, but your code is still gone. If you didn't store your JSON externally (the default), then open your MFX in your favorite plain text editor (e.g. Notepad++) and search for some string that was in your JSON. You can recover the entire JSON from the resources in your MFX with a plain text editor in this way. You still can't get your beautiful, amazing code back, though - sorry. Rewrites generally tend to be better, though, since you know the best way to go about the implementation and design, and you have your old JSON as a reference guide to make the new extension compatible as an update to the old one.

Clone this wiki locally