namespace Sandbox; /// /// Adds a 2D skybox to the world /// [Title( "2D Skybox" )] [Category( "Rendering" )] [Icon( "visibility" )] [EditorHandle( "materials/gizmo/2dskybox.png" )] public class SkyBox2D : Component, Component.ExecuteInEditor { SceneCubemap _envProbe; Color _tint = Color.White; [Property] public Color Tint { get => _tint; set { if ( _tint == value ) return; _tint = value; if ( _sceneObject is not null ) { _sceneObject.SkyTint = Tint; } if ( _envProbe is not null ) { _envProbe.TintColor = Tint; } } } [Property, Description( "Whether to use the skybox for lighting as an envmap probe" ), MakeDirty, DefaultValue( true )] public bool SkyIndirectLighting { get; set; } = true; Material _material = Material.Load( "materials/skybox/skybox_day_01.vmat" ); // todo - better default [Property] public Material SkyMaterial { get => _material; set { if ( _material == value ) return; if ( value.native.IsNull ) return; // Only allow sky materials if ( !value.ShaderName.Contains( "sky" ) ) return; _material = value; if ( _sceneObject is not null ) { _sceneObject.SkyMaterial = _material; } if ( _envProbe is not null ) { _envProbe.Texture = SkyTexture; } } } public Texture SkyTexture => _material.GetTexture( "g_tSkyTexture" ); SceneSkyBox _sceneObject; protected override void OnAwake() { Tags.Add( "skybox" ); base.OnAwake(); } protected override void OnEnabled() { if ( SkyMaterial is null ) return; Assert.True( !_sceneObject.IsValid() ); Assert.NotNull( Scene ); _sceneObject = new SceneSkyBox( Scene.SceneWorld, SkyMaterial ); _sceneObject.SkyTint = Tint; _sceneObject.Tags.SetFrom( Tags ); OnTransformChanged(); Transform.OnTransformChanged += OnTransformChanged; OnDirty(); } protected override void OnDisabled() { Transform.OnTransformChanged -= OnTransformChanged; _sceneObject?.Delete(); _sceneObject = null; _envProbe?.Delete(); _envProbe = null; } private void OnTransformChanged() { if ( _sceneObject.IsValid() ) _sceneObject.Transform = WorldTransform.WithScale( 1.0f ); if ( _envProbe.IsValid() ) _envProbe.Transform = WorldTransform.WithScale( 1.0f ); } internal static void InitializeFromLegacy( GameObject go, Sandbox.MapLoader.ObjectEntry kv ) { var component = go.Components.Create(); var skyMaterial = kv.GetResource( "skyname" ); var tintColor = kv.GetValue( "tint_color" ); var usesIbl = kv.GetValue( "ibl", true ); if ( skyMaterial is null ) { Log.Warning( $"Failed to load skybox material \"{kv.GetValue( "skyname" )}\"" ); return; } /* var startDisabled = kv.GetValue( "StartDisabled" ); var fogType = kv.GetValue( "fog_type" ); var fogMinStart = kv.GetValue( "angular_fog_min_start" ); var fogMinEnd = kv.GetValue( "angular_fog_min_end" ); var fogMaxStart = kv.GetValue( "angular_fog_max_start" ); var fogMaxEnd = kv.GetValue( "angular_fog_max_end" ); var fogParams = new SceneSkyBox.FogParamInfo { FogType = fogType, FogMinStart = fogMinStart, FogMinEnd = fogMinEnd, FogMaxStart = fogMaxStart, FogMaxEnd = fogMaxEnd, }; */ component.Tint = tintColor; component.SkyMaterial = skyMaterial; component.SkyIndirectLighting = usesIbl; } /// /// Tags have been updated /// protected override void OnTagsChanged() { _sceneObject?.Tags.SetFrom( Tags ); if ( _envProbe.IsValid() ) { _envProbe.Tags.SetFrom( Tags ); _envProbe.RenderDirty(); } } protected override void OnDirty() { base.OnDirty(); if ( !Active ) return; _envProbe?.Delete(); _envProbe = null; // Set up our global env probe // -5 means it's of lowest priority in ordering if ( SkyIndirectLighting ) { _envProbe = new SceneCubemap( Scene.SceneWorld, SkyTexture, BBox.FromPositionAndSize( Vector3.Zero, int.MaxValue ), WorldTransform.WithScale( 1 ), Tint, -5, 0.01f ); _envProbe.Tags.SetFrom( Tags ); } } }