You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
KSP-Conformal-Decals/Source/ConformalDecals/MaterialProperties/MaterialTextureProperty.cs

139 lines
5.0 KiB
C#

using System;
using ConformalDecals.Util;
using UnityEngine;
namespace ConformalDecals.MaterialProperties {
public class MaterialTextureProperty : MaterialProperty {
[SerializeField] public bool isNormal;
[SerializeField] public bool isMain;
[SerializeField] public bool autoScale;
[SerializeField] public bool autoTile;
[SerializeField] private string _textureUrl;
[SerializeField] private Texture2D _texture;
[SerializeField] private bool _hasTile;
[SerializeField] private Rect _tileRect;
[SerializeField] private Vector2 _scale = Vector2.one;
[SerializeField] private Vector2 _textureOffset;
[SerializeField] private Vector2 _textureScale = Vector2.one;
[SerializeField] private float _aspectRatioOverride = -1.0f;
public Texture2D Texture {
get => _texture;
set => _texture = value;
}
public string TextureUrl {
get => _textureUrl;
set {
_texture = LoadTexture(value, isNormal);
_textureUrl = value;
}
}
public int Width => _texture.width;
public int Height => _texture.height;
public int MaskedWidth => _hasTile ? (int) _tileRect.width : _texture.width;
public int MaskedHeight => _hasTile ? (int) _tileRect.height : _texture.height;
public Vector2 Dimensions => new Vector2(_texture.width, _texture.height);
public Vector2 MaskedDimensions => _hasTile ? _tileRect.size : Dimensions;
public float AspectRatio {
get {
if (_aspectRatioOverride > 0) return _aspectRatioOverride;
if (_texture == null) return 1;
return MaskedHeight / (float) MaskedWidth;
}
set => _aspectRatioOverride = value;
}
public override void ParseNode(ConfigNode node) {
base.ParseNode(node);
ParseUtil.ParseBoolIndirect(ref isMain, node, "isMain");
ParseUtil.ParseBoolIndirect(ref isNormal, node, "isNormalMap");
ParseUtil.ParseBoolIndirect(ref autoScale, node, "autoScale");
ParseUtil.ParseBoolIndirect(ref autoTile, node, "autoTile");
if (!autoTile) {
ParseUtil.ParseRectIndirect(ref _tileRect, node, "tile");
}
if (ParseUtil.ParseStringIndirect(ref _textureUrl, node, "textureUrl")) {
_texture = LoadTexture(_textureUrl, isNormal);
}
if (_texture == null) {
_texture = isNormal ? DecalConfig.BlankNormal : Texture2D.whiteTexture;
}
}
public override void Modify(Material material) {
if (material == null) throw new ArgumentNullException(nameof(material));
if (_texture == null) {
_texture = isNormal ? DecalConfig.BlankNormal : Texture2D.whiteTexture;
}
material.SetTexture(_propertyID, _texture);
material.SetTextureOffset(_propertyID, _textureOffset);
material.SetTextureScale(_propertyID, _textureScale * _scale);
if (_propertyName != "_Decal") material.EnableKeyword("DECAL" + _propertyName.ToUpper());
}
public override void Remove(Material material) {
if (material == null) throw new ArgumentNullException(nameof(material));
base.Remove(material);
if (_propertyName != "_Decal") material.DisableKeyword("DECAL" + _propertyName.ToUpper());
}
public void SetScale(Vector2 scale) {
_scale = scale;
}
public void SetTile(Rect tile) {
SetTile(tile, Dimensions);
}
public void SetTile(Rect tile, Vector2 mainTexDimensions) {
var scale = tile.size;
var offset = tile.position;
// invert y axis to deal with DXT image orientation
offset.y = mainTexDimensions.y - offset.y - tile.height;
// fit to given dimensions
scale /= mainTexDimensions;
offset /= mainTexDimensions;
_tileRect = tile;
_hasTile = true;
_textureScale = scale;
_textureOffset = offset;
}
private static Texture2D LoadTexture(string textureUrl, bool isNormal) {
//Logging.Log($"loading texture '{textureUrl}', isNormalMap = {isNormal}");
if ((string.IsNullOrEmpty(textureUrl) && isNormal) || textureUrl == "Bump") {
return Texture2D.normalTexture;
}
if ((string.IsNullOrEmpty(textureUrl) && !isNormal) || textureUrl == "White") {
return Texture2D.whiteTexture;
}
if (textureUrl == "Black") {
return Texture2D.blackTexture;
}
var texture = GameDatabase.Instance.GetTexture(textureUrl, isNormal);
if (texture == null) throw new Exception($"Cannot get texture '{textureUrl}', isNormalMap = {isNormal}");
return texture;
}
}
}