Utils/TintMaskComponent.cs
using HC3;
public interface ITintMaskEvents : ISceneEvent<ITintMaskEvents>
{
/// <summary>
/// Called when a tint mask component has changed its colors.
/// </summary>
public void OnColorsChanged( TintMaskComponent component ) { }
}
[Title( "Tint Mask Controller" )]
[Category( "Rendering" )]
public sealed class TintMaskComponent : Component, Component.ExecuteInEditor
{
List<ModelRenderer> Renderers { get; set; } = new();
[Property] public bool PrimaryEnabled { get; set; } = true;
[Property, ShowIf( nameof( PrimaryEnabled ), true ), Change( nameof( UpdateTint ) )]
public TycoonColor PrimaryColor { get; set; } = Color.Red;
[Property] public bool SecondaryEnabled { get; set; } = false;
[Property, ShowIf( nameof( SecondaryEnabled ), true ), Change( nameof( UpdateTint ) )]
public TycoonColor SecondaryColor { get; set; } = Color.White;
[Property] public bool AccentEnabled { get; set; } = false;
[Property, ShowIf( nameof( AccentEnabled ), true ), Change( nameof( UpdateTint ) )]
public TycoonColor AccentColor { get; set; } = Color.White;
[Property] public bool DetailEnabled { get; set; } = false;
[Property, ShowIf( nameof( DetailEnabled ), true ), Change( nameof( UpdateTint ) )]
public TycoonColor DetailColor { get; set; } = Color.White;
protected override void OnStart()
{
if ( GameObject.Tags.Has( "placing" ) ) return;
Renderers = Components.GetAll<ModelRenderer>( FindMode.EverythingInSelfAndChildren ).ToList();
UpdateTint();
}
public void InEditor()
{
if ( GameObject.Tags.Has( "placing" ) ) return;
Renderers = Components.GetAll<ModelRenderer>( FindMode.EverythingInSelfAndChildren ).ToList();
UpdateTint();
}
/// <summary>
/// Set and broadcast a change to the primary color.
/// </summary>
[Rpc.Broadcast]
public void SetPrimaryColor( Color color )
{
PrimaryColor = color;
ITintMaskEvents.PostToGameObject( GameObject.Root, x => x.OnColorsChanged( this ) );
Stats.Increment( "building.tinted" );
}
/// <summary>
/// Set and broadcast a change to the secondary color.
/// </summary>
[Rpc.Broadcast]
public void SetSecondaryColor( Color color )
{
SecondaryColor = color;
ITintMaskEvents.PostToGameObject( GameObject.Root, x => x.OnColorsChanged( this ) );
Stats.Increment( "building.tinted" );
}
/// <summary>
/// Set and broadcast a change to the accent color.
/// </summary>
[Rpc.Broadcast]
public void SetAccentColor( Color color )
{
AccentColor = color;
ITintMaskEvents.PostToGameObject( GameObject.Root, x => x.OnColorsChanged( this ) );
Stats.Increment( "building.tinted" );
}
/// <summary>
/// Set and broadcast a change to the detail color.
/// </summary>
[Rpc.Broadcast]
public void SetDetailColor( Color color )
{
DetailColor = color;
ITintMaskEvents.PostToGameObject( GameObject.Root, x => x.OnColorsChanged( this ) );
Stats.Increment( "building.tinted" );
}
private void UpdateTint()
{
foreach ( var renderer in Renderers )
{
if ( renderer is null ) continue;
renderer.SceneObject.Batchable = false;
renderer.SceneObject.Attributes.Set( "redChannel", PrimaryColor.Value );
renderer.SceneObject.Attributes.Set( "greenChannel", SecondaryColor.Value );
renderer.SceneObject.Attributes.Set( "blueChannel", AccentColor.Value );
renderer.SceneObject.Attributes.Set( "alphaChannel", DetailColor.Value );
}
}
}
public enum TintChannel
{
Primary,
Secondary,
Accent,
Detail
}