KSP-Conformal-Decals/Source/ConformalDecals/ProjectionPartTarget.cs

85 lines
3.1 KiB
C#
Raw Normal View History

2021-01-01 05:05:30 +00:00
using System;
using System.Collections.Generic;
2021-01-01 22:02:46 +00:00
using ConformalDecals.Util;
2021-01-01 05:05:30 +00:00
using UnityEngine;
namespace ConformalDecals {
public class ProjectionPartTarget : IProjectionTarget {
2021-01-01 22:02:46 +00:00
public const string NodeName = "PART_TARGET";
// enabled flag
public bool enabled;
// locked flag, to prevent re-projection of loaded targets
public readonly bool locked;
2021-01-01 05:05:30 +00:00
public readonly Part part;
2021-01-01 22:02:46 +00:00
public readonly List<ProjectionMeshTarget> meshTargets = new List<ProjectionMeshTarget>();
2021-01-01 05:05:30 +00:00
public ProjectionPartTarget(Part part, bool useBaseNormal) {
this.part = part;
2021-01-01 22:02:46 +00:00
locked = false;
2021-01-01 05:05:30 +00:00
foreach (var renderer in part.FindModelComponents<MeshRenderer>()) {
var target = renderer.transform;
var filter = target.GetComponent<MeshFilter>();
// check if the target has any missing data
if (!ProjectionMeshTarget.ValidateTarget(target, renderer, filter)) continue;
// create new ProjectionTarget to represent the renderer
var projectionTarget = new ProjectionMeshTarget(target, part.transform, renderer, filter.sharedMesh, useBaseNormal);
// add the target to the list
meshTargets.Add(projectionTarget);
}
}
2021-01-01 22:02:46 +00:00
public ProjectionPartTarget(ConfigNode node, Vessel vessel, bool useBaseNormal) {
if (node == null) throw new ArgumentNullException(nameof(node));
locked = true;
enabled = true;
var flightID = ParseUtil.ParseUint(node, "part");
part = vessel[flightID];
if (part == null) throw new IndexOutOfRangeException("Vessel returned null part, part must be destroyed or detached");
var root = part.transform;
foreach (var meshTargetNode in node.GetNodes(ProjectionMeshTarget.NodeName)) {
meshTargets.Add(new ProjectionMeshTarget(meshTargetNode, root, useBaseNormal));
}
Logging.Log($"Loaded target for part {part.name}");
}
public bool Project(Matrix4x4 orthoMatrix, Transform projector, Bounds projectionBounds) {
if (locked) return true; // dont overwrite saved targets in flight mode
enabled = false;
2021-01-01 05:05:30 +00:00
foreach (var meshTarget in meshTargets) {
2021-01-01 22:02:46 +00:00
enabled |= meshTarget.Project(orthoMatrix, projector, projectionBounds);
2021-01-01 05:05:30 +00:00
}
2021-01-01 22:02:46 +00:00
return enabled;
2021-01-01 05:05:30 +00:00
}
public void Render(Material decalMaterial, MaterialPropertyBlock partMPB, Camera camera) {
foreach (var target in meshTargets) {
target.Render(decalMaterial, partMPB, camera);
}
}
public ConfigNode Save() {
2021-01-01 22:02:46 +00:00
var node = new ConfigNode(NodeName);
2021-01-01 05:05:30 +00:00
node.AddValue("part", part.flightID);
foreach (var meshTarget in meshTargets) {
2021-01-01 22:02:46 +00:00
if (meshTarget.enabled) node.AddNode(meshTarget.Save());
2021-01-01 05:05:30 +00:00
}
2021-01-01 22:02:46 +00:00
Logging.Log($"Saved target for part {part.name}");
2021-01-01 05:05:30 +00:00
return node;
}
}
}