Created
February 18, 2018 00:16
-
-
Save tomazsaraiva/0be2c923a8c5b5b2590c4bcac90e961f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
[CustomEditor(typeof(MaterialScaleModifier))] | |
public class MaterialScaleModifierInspector : Editor | |
{ | |
private MaterialScaleModifier _target; | |
private Renderer _renderer; | |
private Vector3 _scale; | |
private Texture2D _texture; | |
public override void OnInspectorGUI() | |
{ | |
base.DrawDefaultInspector(); | |
if(GUI.changed) | |
{ | |
_target.ScaleTexture(); | |
} | |
} | |
void OnEnable() | |
{ | |
_target = (MaterialScaleModifier)target; | |
_renderer = _target.Renderer; | |
_scale = _target.transform.localScale; | |
_texture = (Texture2D)_renderer.sharedMaterial.mainTexture; | |
EditorApplication.update += OnUpdate; | |
} | |
void OnUpdate() | |
{ | |
if(_target != null) | |
{ | |
Vector3 scale = _target.transform.localScale; | |
Texture2D texture = (Texture2D)_renderer.sharedMaterial.mainTexture; | |
if (_scale != scale || _texture != texture) | |
{ | |
_target.ScaleTexture(); | |
_scale = scale; | |
_texture = texture; | |
} | |
} | |
} | |
void OnDisable() | |
{ | |
EditorApplication.update -= OnUpdate; | |
_target = null; | |
} | |
} | |
#endif | |
public class MaterialScaleModifier : MonoBehaviour | |
{ | |
public enum ScaleMode | |
{ | |
Stretch, | |
Fit, | |
Crop | |
} | |
// serializables | |
[SerializeField] | |
private ScaleMode _scaleMode; | |
// properties | |
public Renderer Renderer | |
{ | |
get | |
{ | |
if(_renderer == null) | |
{ | |
_renderer = GetComponent<Renderer>(); | |
} | |
return _renderer; | |
} | |
} | |
// fields | |
private Renderer _renderer; | |
// MonoBehaviour | |
void Awake() | |
{ | |
if(Renderer == null) | |
{ | |
#if UNITY_EDITOR || DEVELOPMENT_BUILD | |
Debug.LogError("GameObject does not have a Renderer"); | |
#endif | |
} | |
} | |
void Start() | |
{ | |
ScaleTexture(); | |
} | |
// Texture2dScaleMode | |
public void ScaleTexture() | |
{ | |
if (Renderer != null && | |
Renderer.sharedMaterial != null && | |
Renderer.sharedMaterial.mainTexture != null) | |
{ | |
Vector2 textureSize = GetTextureSize(); | |
float rendererHeight = textureSize.x / GetRendererSizeRatio(); | |
float rendererWidth = textureSize.y * GetRendererSizeRatio(); | |
float diffWidth = rendererWidth - textureSize.x; | |
float diffHeight = rendererHeight - textureSize.y; | |
float diffMin = Mathf.Min(diffWidth, diffHeight); | |
float scaleX = 1.0f; | |
float scaleY = 1.0f; | |
float offsetX = 0; | |
float offsetY = 0; | |
TextureWrapMode wrapMode = TextureWrapMode.Repeat; | |
switch (_scaleMode) | |
{ | |
case ScaleMode.Stretch: | |
// the default one, nothing to see here | |
break; | |
case ScaleMode.Fit: // scale to the smaller side | |
wrapMode = TextureWrapMode.Clamp; | |
if (diffMin == diffWidth) | |
{ | |
ScaleToWidth(ref scaleY, ref offsetY); | |
} | |
else | |
{ | |
ScaleToHeight(ref scaleX, ref offsetX); | |
} | |
break; | |
case ScaleMode.Crop: // scale to the larger side | |
if (diffMin == diffWidth) | |
{ | |
ScaleToHeight(ref scaleX, ref offsetX); | |
} | |
else | |
{ | |
ScaleToWidth(ref scaleY, ref offsetY); | |
} | |
break; | |
} | |
Renderer.sharedMaterial.mainTexture.wrapMode = wrapMode; | |
Renderer.sharedMaterial.mainTextureScale = new Vector2(scaleX, scaleY); | |
Renderer.sharedMaterial.mainTextureOffset = new Vector2(offsetX, offsetY); | |
} | |
} | |
private void ScaleToWidth(ref float scaleY, ref float offsetY) | |
{ | |
Vector2 textureSize = GetTextureSize(); | |
// if we maintain the image width | |
// get the object height assuming the object width is equal to the texture width | |
float rendererHeight = textureSize.x / GetRendererSizeRatio(); | |
// get the corresponding percentage of the texture height inside the object height | |
scaleY = rendererHeight / textureSize.y; | |
// to center the image we would move it to the object height center minus half the image height | |
float offset = rendererHeight / 2 - textureSize.y / 2; | |
// get the corresponding percentage of the centering offset | |
offsetY = (offset * scaleY / rendererHeight) * -1; | |
} | |
private void ScaleToHeight(ref float scaleX, ref float offsetX) | |
{ | |
Vector2 textureSize = GetTextureSize(); | |
// if we maintain the image height | |
// get the object width assuming the object height is equal to the texture height | |
float rendererWidth = textureSize.y * GetRendererSizeRatio(); | |
// get the corresponding percentage of the texture width inside the object width | |
scaleX = rendererWidth / textureSize.x; | |
// to center the image we would move it to the object width center minus half the image width | |
float offset = rendererWidth / 2 - textureSize.x / 2; | |
// get the corresponding percentage of the centering offset | |
offsetX = (offset * scaleX / rendererWidth) * -1; | |
} | |
private Renderer GetRenderer() | |
{ | |
return GetComponent<Renderer>(); | |
} | |
private Vector2 GetRendererSize() | |
{ | |
return Renderer.bounds.size; | |
} | |
private float GetRendererSizeRatio() | |
{ | |
float min = Mathf.Min(Renderer.bounds.size.x, Renderer.bounds.size.y, Renderer.bounds.size.z); | |
float ratio = 0; | |
if(min == Renderer.bounds.size.x) | |
{ | |
ratio = Renderer.bounds.size.z / Renderer.bounds.size.y; | |
} | |
else if(min == Renderer.bounds.size.y) | |
{ | |
ratio = Renderer.bounds.size.x / Renderer.bounds.size.z; | |
} | |
else | |
{ | |
ratio = Renderer.bounds.size.x / Renderer.bounds.size.y; | |
} | |
return ratio; | |
} | |
private Vector2 GetTextureSize() | |
{ | |
return new Vector2(Renderer.sharedMaterial.mainTexture.width, Renderer.sharedMaterial.mainTexture.height); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment