Spline Tools for MapMagic
Spline Tools for MapMagic
Welcome to Spline Tools, an extension for MapMagic, a node based procedural and infinite game map generator.
To use this addon a full version of MapMagic is required.
While MapMagic itself can generate infinite maps, this addon can only be used if a finite map is required. It allows to limit the map size by creating an island/continent or generating mountains at the borders that cannot be passed.
Limiting the world to a defined size allows to generate stuff that crosses multiple chunks and requires knowledge of the neighbors.
Tutorials
Generators
Map Generators
- Path
- Bounded Shape
- Path Flatten
- Path Carve
- Flatten+ (Legacy)
- Flatten+ V2
- Flatten Stamp (Legacy)
- Flatten Stamp V2
- Flatten Stamp Objects
- Heights Cache (MM1)
Spline Generators
- Connections (Legacy, MM1)
- Connections V2
- Combine Edges
- Split Edges
- Rivers (Unstable)
- Cut Water Crossings (Unstable)
Object Generators
- Bounded Scatter (Legacy, MM1)
- Bounded Scatter V2
- Manual Scatter
- Extract Nodes (Legacy)
- Path Scatter
- Radius Scatter
- Combine Nodes
- Split Nodes
- Nodes > Objects
- Edges > Nodes
Other Generators
Output Generators
- R.A.M River (Unstable)
- R.A.M Road (Unstable)
- R.A.M Lake (Unstable)
Biome Generators (MM2 only)
- Biome Height Sync (MM2)
- Biome Edges (MM2)
- Biome Nodes (MM2)
- Biome Objects (MM2)
Getting started
Setup
It is assumed that a basic setup of MapMagic is already up and running.
First the main script Map Magic - Spline Tools must be added to your scene. You can add it to the same gameObject that already holds MapMagic, but you are free to add it to any other gameObject. If you use MapMagic's Copy Components To Terrain feature, it is recommended to use a dedicated gameObject for SplineTools since running multiple instances is discouraged.
Enable colorized generators for MapMagic 2
This step is optional and will give you colorized links and generators in your MM2 graphs.
It requires modifying one of MM2's in order to allow defining colors for custom generators. Please only do this when you feel comfortable with this. This step needs to be redone after every update of MapMagic 2 until out-of-the-box support is added.
This has been tested with MM2 version 2.1.8. When using a different version, the code may look different and this step may either still work or fail. Always make sure you can safely revert any changes.
Required modifications
Remove the following methods from the MapMagic.Nodes.GUI.GeneratorDraw class, found near the end of the file.
Code to remove / comment out
public static Color GetGeneratorColor (Type genericType)
{
if (StylesCache.isPro) return GetGeneratorColorPro(genericType);
Color color;
if (genericType == typeof(MatrixWorld)) color = new Color(0.4f, 0.666f, 1f, 1f);
else if (genericType == typeof(TransitionsList)) color = new Color(0.444f, 0.871f, 0.382f, 1f);
else if (genericType == typeof(SplineSys)) color = new Color(1f, 0.6f, 0f, 1f);
else if (genericType == typeof(Den.Tools.Splines.SplineSys)) color = new Color(1f, 0.6f, 0f, 1f);
else if (genericType == typeof(IBiome)) color = new Color(0.45f, 0.55f, 0.56f, 1f);
else if (genericType == typeof(MatrixSet)) color = new Color(0.3f, 0.444f, 0.75f, 1f);
else color = new Color(0.65f, 0.65f, 0.65f, 1);
return color;
}
private static Color GetGeneratorColorPro (Type genericType)
{
Color color;
if (genericType == typeof(MatrixWorld)) color = new Color(0, 0.325f, 0.75f, 0.7f);
else if (genericType == typeof(TransitionsList)) color = new Color(0.13f, 0.65f, 0, 0.65f);
else if (genericType == typeof(SplineSys)) color = new Color(0.65f, 0.325f, 0f, 0.7f);
else if (genericType == typeof(Den.Tools.Splines.SplineSys)) color = new Color(0.65f, 0.325f, 0f, 0.7f);
else if (genericType == typeof(IBiome)) color = new Color(0.45f, 0.55f, 0.56f, 1f);
else if (genericType == typeof(MatrixSet)) color = new Color(0, 0.2f, 0.5f, 0.7f);
else color = new Color(0.65f, 0.65f, 0.65f, 1);
return color;
}
public static Color GetLinkColor (Type genericType)
{
bool isPro = StylesCache.isPro;
if (genericType == typeof(MatrixWorld))
{
if (isPro) return new Color(0, 0.5f, 1f, 1f);
else return new Color(0, 0.333f, 0.666f, 1f);
}
if (genericType == typeof(TransitionsList))
{
if (isPro) return new Color(0.2f, 1f, 0, 1f);
else return new Color(0, 0.465f, 0, 1f);
}
if (genericType == typeof(SplineSys))
{
if (isPro) return new Color(1f, 0.5f, 0f, 1f);
else return new Color(0.666f, 0.333f, 0, 1f);
}
if (genericType == typeof(Den.Tools.Splines.SplineSys))
{
if (isPro) return new Color(1f, 0.5f, 0f, 1f);
else return new Color(0.666f, 0.333f, 0, 1f);
}
if (genericType == typeof(MatrixSet))
{
if (isPro) return new Color(0, 0.25f, 0.5f, 1f);
else return new Color(0, 0.16f, 0.333f, 1f);
}
return Color.gray;
}And add the following code at the same place instead.
Code to add
public static readonly List<Func<Type, Color?>> getThirdPartyGeneratorColors = new List<Func<Type, Color?>>();
public static readonly List<Func<Type, Color?>> getThirdPartyGeneratorProColors = new List<Func<Type, Color?>>();
public static readonly List<Func<Type, Color?>> getThirdPartyLinkColors = new List<Func<Type, Color?>>();
public static readonly List<Func<Type, Color?>> getThirdPartyLinkProColors = new List<Func<Type, Color?>>();
public static Color GetGeneratorColor(Type genericType)
{
if (StylesCache.isPro) return GetGeneratorColorPro(genericType);
if (genericType == typeof(MatrixWorld)) return new Color(0.4f, 0.666f, 1f, 1f);
if (genericType == typeof(TransitionsList)) return new Color(0.444f, 0.871f, 0.382f, 1f);
if (genericType == typeof(SplineSys)) return new Color(1f, 0.6f, 0f, 1f);
if (genericType == typeof(Den.Tools.Splines.SplineSys)) return new Color(1f, 0.6f, 0f, 1f);
if (genericType == typeof(IBiome)) return new Color(0.45f, 0.55f, 0.56f, 1f);
if (genericType == typeof(MatrixSet)) return new Color(0.3f, 0.444f, 0.75f, 1f);
foreach (var func in getThirdPartyGeneratorColors)
{
Color? thirdPartyColor = func.Invoke(genericType);
if (thirdPartyColor != null) return thirdPartyColor.Value;
}
return new Color(0.65f, 0.65f, 0.65f, 1);
}
private static Color GetGeneratorColorPro(Type genericType)
{
if (genericType == typeof(MatrixWorld)) return new Color(0, 0.325f, 0.75f, 0.7f);
if (genericType == typeof(TransitionsList)) return new Color(0.13f, 0.65f, 0, 0.65f);
if (genericType == typeof(SplineSys)) return new Color(0.65f, 0.325f, 0f, 0.7f);
if (genericType == typeof(Den.Tools.Splines.SplineSys)) return new Color(0.65f, 0.325f, 0f, 0.7f);
if (genericType == typeof(IBiome)) return new Color(0.45f, 0.55f, 0.56f, 1f);
if (genericType == typeof(MatrixSet)) return new Color(0, 0.2f, 0.5f, 0.7f);
foreach (var func in getThirdPartyGeneratorProColors)
{
Color? thirdPartyColor = func.Invoke(genericType);
if (thirdPartyColor != null) return thirdPartyColor.Value;
}
return new Color(0.65f, 0.65f, 0.65f, 1);
}
public static Color GetLinkColor (Type genericType)
{
bool isPro = StylesCache.isPro;
if (genericType == typeof(MatrixWorld))
{
if (isPro) return new Color(0, 0.5f, 1f, 1f);
else return new Color(0, 0.333f, 0.666f, 1f);
}
if (genericType == typeof(TransitionsList))
{
if (isPro) return new Color(0.2f, 1f, 0, 1f);
else return new Color(0, 0.465f, 0, 1f);
}
if (genericType == typeof(SplineSys))
{
if (isPro) return new Color(1f, 0.5f, 0f, 1f);
else return new Color(0.666f, 0.333f, 0, 1f);
}
if (genericType == typeof(Den.Tools.Splines.SplineSys))
{
if (isPro) return new Color(1f, 0.5f, 0f, 1f);
else return new Color(0.666f, 0.333f, 0, 1f);
}
if (genericType == typeof(MatrixSet))
{
if (isPro) return new Color(0, 0.25f, 0.5f, 1f);
else return new Color(0, 0.16f, 0.333f, 1f);
}
if (isPro)
{
foreach (var func in getThirdPartyLinkProColors)
{
Color? thirdPartyColor = func.Invoke(genericType);
if (thirdPartyColor != null) return thirdPartyColor.Value;
}
} else
{
foreach (var func in getThirdPartyLinkColors)
{
Color? thirdPartyColor = func.Invoke(genericType);
if (thirdPartyColor != null) return thirdPartyColor.Value;
}
}
return Color.gray;
}The SplineTools script will then automatically recognize the changes and enable color support.
If you want to revert these changes you may need to remove the ST_MM_2_COLORS compiler flag manually to fix compile errors.
The Main Script
The script in the inspector looks like this:
- Log Level - Useful for debugging purposes. Enabling Debug logging may slow down generation.
- Space - Select the Coordinate space (World vs. MapMagic) to display values in SplineTools' generators. Note that the values of the standard MapMagic generators are not affected by this.
- Height Cache Size (Memory) - Size of the height map cache in memory in MegaBytes.
- Height Cache Size (Disk) - Size of the height map cache on disk in MegaBytes. A value of 0 will disable disk caching.
- Spill to Disk Threshold (ms) - Memory-cached height maps that took longer than this to generate will be spilled to disk once the memory cache limit is reached. All other cached height maps will be discarded and re-computed on demand.
- Cache (Sub)Directory - Where to persist the disk-cached height maps.
- Clear, Rebuild - Reset and/or rebuild the state of the Cache and WorldGraph.
- Show Coord - Show the exact coordinate on terrain under the mouse cursor position.
- Refresh Integrations - Trigger a scan for integrable assets in the project.
Please note that MapMagic's Generate Changed and Force Generate All will NOT reset the WorldGraphs or the cache. Every time you make changes to generators that affect the creation of nodes or edges, you must use the Clear & Rebuild buttons of this script. Some generators may also cache the height input, so you have to at least clear the height cache in order to see the effect of changes.
Integrations
All possible integrations will be automatically detected. It is possible to use the button Refresh Integrations to force a detection, if a compatible asset has been imported or removed but the automatic detection did not work.
Compatible Assets:
- River Auto Material, required for the R.A.M River and R.A.M Lake outputs for Unity <= 2018.2
- River Auto Material 2019, required for the R.A.M River and R.A.M Lake outputs for Unity 2018.3+
WorldGraph Components
Here is a short overview of the most important components:
Recommended Workflow
When integrating SplineTools into a MapMagic Graph, it is recommended to use the height-related generators in an overall order similar to this:
- Basic height generation
- Scatter global POI
- Flatten global POI
- Generate global connections
- Flatten paths
- Scatter local POI
- Flatten local POI
- Generate local connections
- Flatten local connections
- Erosion (with flattened connections masked out)
The generator order for textures is not that critical, but keeping it close to the height generator order will most likely be what you want.
Scripting API
See here.
FAQ / Common Issues
Flying / displaced edges
There are multiple possibilities:
- Stale graph: Make sure your graph is not stale by using the
Clear & Rebuildbutton. - Usage of HeightsCache with unsupported input: Since most of MapMagic's generators need special handling to be scaled down in some way, the usage of unhandled generators will lead to wrong results. Use the Preview output to check if the normal and the low-resolution terrain match.
- Usage of HeightsCache with very low resolution: With too low resolution the details will get lost.
- Using the wrong height input for ConnectionsGenerator: Different connection steps may require different height input to e.g. consider already flattened areas.
Biomes
Usage of SplineTools with Biomes is partially supported for MapMagic 2, see MapMagic 2 Biomes.
Usage with Biomes for MapMagic 1 is not supported.
Compilation fails because the wrong version of R.A.M is detected after upgrade/downgrade
Go to the Player Settings and remove the entries ST_RAM or ST_RAM_2019 from the Scripting Define Symbols. After this the correct new R.A.M version should be detected.
Migration to 0.6.0
Since a full reinstall is required for version 0.6.0, all SplineTools nodes in you MapMagic graphs will disappear unless you prepare them for migration.
If you want migrate your graphs, save your scene in text format (before upgrading), open it with a text editor and replace all occurrences of ArctiumStudios. with ArctiumStudios.SplineTools.. This will preserve the overall graph, but most of the values will still be reset to their defaults.
MapMagic 2
Support for MapMagic 2 is built-in, but is marked as 'Unstable' at least until MapMagic 2 officially supports third party / custom generators.


