Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Unity-plugin] Context menu for creating Unity terrain components #1504

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions unity/Editor/Components/MjGeomEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,26 @@ private static void AddMatchingGeom(MenuCommand menuCommand) {
GameObject.DestroyImmediate(geom);
}
}

void OnEnable() {
// Ensure we only subscribe handler once
EditorApplication.contextualPropertyMenu -= OnHeightFieldContextMenu;
EditorApplication.contextualPropertyMenu += OnHeightFieldContextMenu;
}

void OnDestroy() {
EditorApplication.contextualPropertyMenu -= OnHeightFieldContextMenu;
}

void OnHeightFieldContextMenu(GenericMenu menu, SerializedProperty property) {
if (property.type != nameof(MjHeightFieldShape))
return;

menu.AddItem(new GUIContent("Add Unity Terrain"), false, () =>
{
var geom = target as MjGeom;
geom.HField.AddTerrain();
});
}
}
}
27 changes: 25 additions & 2 deletions unity/Runtime/Components/Shapes/MjHeightFieldShape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,24 @@
using System.Linq;
using System.Xml;
using UnityEngine;

// internal imports
namespace Mujoco {

[Serializable]
public class MjHeightFieldShape : IMjShape {
[Tooltip("Terrain's heightmap should have a minimum value of zero (fully black).")]
[Tooltip("Terrain's heightmap should have a minimum value of zero (fully black). Right click HField to add Unity Terrain."),
ContextMenuItem("Add Unity Terrain", "AddTerrain")]
public Terrain Terrain;

[Tooltip("The path, relative to Application.dataPath, where the heightmap " +
"data will be saved/exported in PNG format. Leave blank if hfield data should " +
"be set instead programmatically (faster).")]
public string HeightMapExportPath;

[Tooltip("This thickness will be added below the 0 height in the hfield, to prevent penetration. ")]
public float BaseHeight = 0.1f;

public bool ExportImage => !string.IsNullOrEmpty(HeightMapExportPath);

public string FullHeightMapPath => Path.GetFullPath(Path.Combine(Application.dataPath,
Expand Down Expand Up @@ -75,7 +80,7 @@ public unsafe void ToMjcf(XmlElement mjcf, Transform transform) {
var assetName = scene.GenerationContext.AddHeightFieldAsset(this);

if (Application.isPlaying) {
scene.postInitEvent += (unused_first, unused_second) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to add these names for our internal tools, please leave them as is.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I thought it was my editor applying style, I'll swap it back.

scene.postInitEvent += (_, _) =>
HeightFieldId =
MujocoLib.mj_name2id(scene.Model, (int)MujocoLib.mjtObj.mjOBJ_HFIELD, assetName);
}
Expand Down Expand Up @@ -160,5 +165,23 @@ public Tuple<Vector3[], int[]> BuildMesh() {
}

public void DebugDraw(Transform transform) {}

public void AddTerrain() {
GameObject terrainObject = new GameObject("Terrain");
Terrain newTerrain = terrainObject.AddComponent<Terrain>();
newTerrain.terrainData = new TerrainData();
newTerrain.terrainData.size = new Vector3(100, 1, 100);

var transform = GameObject
.FindObjectsByType<MjGeom>(FindObjectsInactive.Include, FindObjectsSortMode.None)
.First(g => g.HField == this).transform;

terrainObject.transform.parent = transform;
newTerrain.materialTemplate = new Material(Shader.Find("Nature/Terrain/Diffuse"));
var coll = newTerrain.gameObject.AddComponent<TerrainCollider>();
coll.terrainData = newTerrain.terrainData;
Terrain = newTerrain;
terrainObject.transform.localPosition = new Vector3(-50, 0, -50);
}
}
}
3 changes: 1 addition & 2 deletions unity/Runtime/Tools/MjcfGenerationContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ private static void GenerateHeightFieldMjcf(MjHeightFieldShape hFieldComponent,
mjcf.SetAttribute("ncol", hFieldComponent.HeightMapWidth.ToString());
}

var baseHeight = hFieldComponent.Terrain.transform.localPosition.y +
hFieldComponent.MinimumHeight;
var baseHeight = hFieldComponent.BaseHeight;
var heightRange = Mathf.Clamp(
hFieldComponent.MaximumHeight - hFieldComponent.MinimumHeight,
0.00001f,
Expand Down
Loading