Skip to content
richardTingle edited this page Mar 28, 2024 · 8 revisions

Typed materials is a gradle plugin that allows jMonkeyEngine materials to be statically typed.

Replacing this:

Material shipMaterial = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
shipMaterial.setTexture("DiffuseMap", someTexture);
shipMaterial.setTexture("GlowMap", someOtherTexture);
shipMaterial.setBoolean("UseVertexColor", true);
shipMaterial.setColor("Diffuse", ColorRGBA.White);
shipMaterial.setColor("Ambient", ColorRGBA.White);

With this

LightingMaterial shipMaterial = new LightingMaterial(assetManager);
shipMaterial.setDiffuseMap(someTexture);
shipMaterial.setGlowMap(someOtherTexture);
shipMaterial.setUseVertexColor(true);
shipMaterial.setDiffuse(ColorRGBA.White);
shipMaterial.setAmbient(ColorRGBA.White);

These materials extend the Material class so can be used anywhere a Material could be.

And (where available on the material) including the documentation as a javadoc

image

How do I use the plugin

Bare minimum

In the simplest case where you only want JME materials you can add the following to your build.gradle

buildscript{
    repositories {
        mavenCentral()
    }
}
plugins {
    id 'java'
    id 'com.onemillionworlds.typed-materials' version '1.1.0'
}

typedMaterials {
    jmeMaterials()
}

//jme dependencies as normal

This will provide statically typed materials for the materials found in jme3-core and jme3-effects

Local materials

The plugin can also provide statically typed materials for your own local materials. By default it assumes these materials are found within your module at src/main/resources/MatDefs; if that's the case this is the config

typedMaterials {
    jmeMaterials()
    localMaterialsSearch('com.yoursite.package.to.create.materials.in')
}

If you have your materials in a non standard location that can be passed as additional parameters

typedMaterials {
    jmeMaterials()
    localMaterialsSearch('com.yoursite.package', 'path/to/assets/materials', 'folderAtAssetsRoot')
}

e.g. (if migrating from the old assets folder)

typedMaterials {
    jmeMaterials()
    localMaterialsSearch('com.yoursite.package', 'assets', 'assets')
}

The first parameter is the path to where to find the materials (where to search) and the second is the folder that is the root of the assets (which is used to figure out how much of the directories structure to snip off for the asset name).

If you are also using lombok you may need to use a separate module; see Lombok-compatibility

Non JME library materials

If a 3rd party library is providing materials these can also be registered to generate java classes

typedMaterials {
    ....
    librarySearch("libraryNameMaterials", ".*libraryname.*", "com.libraryname.materials")
}

The parameters are: task name, regex to select library, package to create materials in

Wrappers

In addition to the typed Materials (e.g. UnshadedMaterial) there are also wrappers (e.g. UnshadedMaterialWrapper) these are useful if you are not constructing a material but obtaining one in annother way (e.g. using the getter on a material)

LightingMaterialWrapper lightingMaterial = new LightingMaterialWrapper(someGeometry.getMaterial()));
lightingMaterial.setDiffuseMap(someDiffuseMap)

These do not extend Material but you can get the underlying material back again if needed

lightingMaterial.getMaterial();

Material Factories

In addition to the Typed Materials and wrappers a MaterialFactory will also be generated. It can be used like this

MaterialFactory factory = MaterialFactory.INSTANCE;
LightingMaterial = factory.createMaterial(LightingMaterial.class);

This can be useful for projects that want to use mocking in their tests as the MaterialFactory can be mocked (e.g. using Mockito) to produce mock materials (which would otherwise need a live AssetManager).

How does it work

TypedMaterials scans the .j3md files (both locally and in dependencies) and synthesises classes based on the parameters in the MaterialParameters section of the definition. All classes are created in src/main/generated/java which is added to source.Sets.main.java.srcs in gradle.

Advanced config

The location of the generated java classes can be configured

typedMaterials {
    ...
    generatedSourcesDir = 'src/main/somewhereelse/java'
}

The name of the factory can be configured

typedMaterials {
    ...
    materialFactoryClass = 'com.company.MyFactoryClassName'
}

Requirements

Java 17 or higher