Decompiled source of ComfortMagicBubbles v1.0.0

ComfortMagicBubbles/ComfortMagicBubbles.dll

Decompiled 2 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using ComfortMagicBubbles.Bootstrap;
using ComfortMagicBubbles.Configuration;
using ComfortMagicBubbles.Core;
using ComfortMagicBubbles.Features.Bubbles.Domain;
using ComfortMagicBubbles.Features.Bubbles.Infrastructure;
using ComfortMagicBubbles.Integrations.Harmony;
using ComfortMagicBubbles.Integrations.Unity;
using ComfortMagicBubbles.Integrations.Valheim;
using ComfortMagicBubbles.Presentation.Hub.Registration;
using ComfortMagicBubbles.Presentation.Hub.ViewModels;
using ComfortMagicBubbles.Ui;
using HarmonyLib;
using Jotunn.Utils;
using KydlCore.Common;
using KydlCore.Core;
using KydlCore.Features.Diagnostics.Contracts;
using KydlCore.Features.Hub.Contracts;
using KydlCore.Ui;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ComfortMagicBubbles.Ui
{
	internal sealed class BubbleRowPage
	{
		internal string Label { get; }

		internal bool UseGame { get; }

		internal string Hex { get; }

		internal Action<bool> OnUseGame { get; }

		internal Action<string> OnHex { get; }

		internal BubbleRowPage(string label, bool useGame, string hex, Action<bool> onUseGame, Action<string> onHex)
		{
			Label = label;
			UseGame = useGame;
			Hex = hex;
			OnUseGame = onUseGame ?? ((Action<bool>)delegate
			{
			});
			OnHex = onHex ?? ((Action<string>)delegate
			{
			});
		}
	}
	internal sealed class BubbleKindPage
	{
		internal string Title { get; }

		internal int Opacity { get; }

		internal bool DistortionFree { get; }

		internal int Reflection { get; }

		internal Action<int> OnOpacity { get; }

		internal Action<bool> OnDistortionFree { get; }

		internal Action<int> OnReflection { get; }

		internal IList<BubbleRowPage> Rows { get; }

		internal PatternPage Pattern { get; }

		internal BubbleKindPage(string title, int opacity, bool distortionFree, Action<int> onOpacity, Action<bool> onDistortionFree, IList<BubbleRowPage> rows, int reflection = 100, Action<int> onReflection = null, PatternPage pattern = null)
		{
			Pattern = pattern;
			Title = title;
			Opacity = opacity;
			DistortionFree = distortionFree;
			Reflection = reflection;
			OnReflection = onReflection ?? ((Action<int>)delegate
			{
			});
			OnOpacity = onOpacity ?? ((Action<int>)delegate
			{
			});
			OnDistortionFree = onDistortionFree ?? ((Action<bool>)delegate
			{
			});
			Rows = rows ?? new List<BubbleRowPage>();
		}
	}
	internal sealed class PatternPage
	{
		internal IList<string> Choices { get; }

		internal string Chosen { get; }

		internal int Strength { get; }

		internal int Speed { get; }

		internal int Density { get; }

		internal Action<string> OnChosen { get; }

		internal Action<int> OnStrength { get; }

		internal Action<int> OnSpeed { get; }

		internal Action<int> OnDensity { get; }

		internal PatternPage(IList<string> choices, string chosen, int strength, int speed, int density, Action<string> onChosen, Action<int> onStrength, Action<int> onSpeed, Action<int> onDensity)
		{
			Choices = choices ?? new List<string>();
			Chosen = chosen;
			Strength = strength;
			Speed = speed;
			Density = density;
			OnChosen = onChosen ?? ((Action<string>)delegate
			{
			});
			OnStrength = onStrength ?? ((Action<int>)delegate
			{
			});
			OnSpeed = onSpeed ?? ((Action<int>)delegate
			{
			});
			OnDensity = onDensity ?? ((Action<int>)delegate
			{
			});
		}
	}
	internal sealed class FadeNumberPage
	{
		internal string Label { get; }

		internal float Min { get; }

		internal float Max { get; }

		internal bool WholeNumbers { get; }

		internal float Value { get; }

		internal Action<float> OnValue { get; }

		internal FadeNumberPage(string label, float min, float max, bool wholeNumbers, float value, Action<float> onValue)
		{
			Label = label;
			Min = min;
			Max = max;
			WholeNumbers = wholeNumbers;
			Value = value;
			OnValue = onValue ?? ((Action<float>)delegate
			{
			});
		}
	}
	internal sealed class FadeRulePage
	{
		internal string Title { get; }

		internal string Note { get; }

		internal bool On { get; }

		internal int FadeToPercent { get; }

		internal Action<bool> OnOn { get; }

		internal Action<int> OnFadeTo { get; }

		internal IList<FadeNumberPage> Numbers { get; }

		internal FadeRulePage(string title, string note, bool on, int fadeToPercent, Action<bool> onOn, Action<int> onFadeTo, IList<FadeNumberPage> numbers)
		{
			Title = title;
			Note = note;
			On = on;
			FadeToPercent = fadeToPercent;
			OnOn = onOn ?? ((Action<bool>)delegate
			{
			});
			OnFadeTo = onFadeTo ?? ((Action<int>)delegate
			{
			});
			Numbers = numbers ?? new List<FadeNumberPage>();
		}
	}
	internal sealed class AutoFadePage
	{
		internal bool Enabled { get; }

		internal Action<bool> OnEnabled { get; }

		internal FadeNumberPage Blend { get; }

		internal IList<FadeRulePage> Rules { get; }

		internal AutoFadePage(bool enabled, Action<bool> onEnabled, FadeNumberPage blend, IList<FadeRulePage> rules)
		{
			Enabled = enabled;
			Blend = blend;
			OnEnabled = onEnabled ?? ((Action<bool>)delegate
			{
			});
			Rules = rules ?? new List<FadeRulePage>();
		}
	}
	internal sealed class BubblesPage
	{
		internal IList<BubbleKindPage> Kinds { get; }

		internal AutoFadePage AutoFade { get; }

		internal BubblesPage(IList<BubbleKindPage> kinds, AutoFadePage autoFade = null)
		{
			Kinds = kinds ?? new List<BubbleKindPage>();
			AutoFade = autoFade;
		}
	}
	internal static class BubblesTabView
	{
		internal static VisualElement Build(Func<string, string> text, BubblesPage page)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			VisualElement val = new VisualElement();
			if (page.Kinds.Count == 0)
			{
				val.Add((VisualElement)(object)UiControls.Note("No bubble kinds."));
				return val;
			}
			List<string> titles = new List<string>();
			foreach (BubbleKindPage kind in page.Kinds)
			{
				titles.Add(kind.Title);
			}
			VisualElement content = new VisualElement();
			val.Add(UiControls.Heading("Bubble"));
			val.Add((VisualElement)(object)UiControls.Dropdown((IList<string>)titles, titles[0], (Func<string, string>)((string t) => t), (Action<string>)delegate(string chosen)
			{
				Fill(content, page.Kinds[Math.Max(0, titles.IndexOf(chosen))]);
			}));
			val.Add(content);
			Fill(content, page.Kinds[0]);
			if (page.AutoFade != null)
			{
				val.Add(AutoFade(page.AutoFade));
			}
			UiLog.Verbose("BubblesTabView: built, " + page.Kinds.Count + " kind(s), auto-fade block " + (page.AutoFade != null));
			return val;
		}

		private static VisualElement AutoFade(AutoFadePage fade)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			VisualElement val = new VisualElement();
			val.Add(UiControls.Heading("Auto-fade"));
			val.Add((VisualElement)(object)UiControls.Note("Bubbles dim by themselves where they block the view. When several rules apply, the strongest fade wins. 'Fade to' = how much of the normal look is left (100 = not at all, 0 = invisible)."));
			val.Add(UiControls.Toggle("Auto-fade on", fade.Enabled, fade.OnEnabled));
			if (fade.Blend != null)
			{
				val.Add(Number(fade.Blend));
			}
			foreach (FadeRulePage rule in fade.Rules)
			{
				val.Add(UiControls.Heading(rule.Title));
				if (!string.IsNullOrEmpty(rule.Note))
				{
					val.Add((VisualElement)(object)UiControls.Note(rule.Note));
				}
				val.Add(UiControls.Toggle("Enabled", rule.On, rule.OnOn));
				val.Add(UiControls.Row("Fade to (%)", UiControls.Slider(0f, 100f, (float)rule.FadeToPercent, "0", (Action<float>)delegate(float v)
				{
					rule.OnFadeTo((int)Math.Round(v));
				})));
				foreach (FadeNumberPage number in rule.Numbers)
				{
					val.Add(Number(number));
				}
			}
			return val;
		}

		private static VisualElement Number(FadeNumberPage number)
		{
			return UiControls.Row(number.Label, UiControls.Slider(number.Min, number.Max, number.Value, number.WholeNumbers ? "0" : "0.0", number.OnValue));
		}

		private static void Fill(VisualElement content, BubbleKindPage kind)
		{
			content.Clear();
			content.Add(UiControls.Heading("Look - " + kind.Title));
			content.Add((VisualElement)(object)UiControls.Note("The same for every bubble of this weapon, whoever wears it, and for every colour below."));
			content.Add(UiControls.Row("Opacity (%)", UiControls.Slider(0f, 100f, (float)kind.Opacity, "0", (Action<float>)delegate(float v)
			{
				kind.OnOpacity((int)Math.Round(v));
			})));
			content.Add(UiControls.Toggle("Distortion-free (no bending of the view)", kind.DistortionFree, kind.OnDistortionFree));
			content.Add(UiControls.Row("Reflection (%)", UiControls.Slider(0f, 100f, (float)kind.Reflection, "0", (Action<float>)delegate(float v)
			{
				kind.OnReflection((int)Math.Round(v));
			})));
			if (kind.Pattern != null)
			{
				AddPattern(content, kind);
			}
			content.Add(UiControls.Heading("Colour - " + kind.Title));
			content.Add((VisualElement)(object)UiControls.Note("An extra on top of the look. 'Default color' ON keeps the game's own colour for that target. 'Pick colour', then Apply: the colour is saved and 'Default color' is turned off, so it is used. The small square shows the saved colour (faded while 'Default color' is on)."));
			foreach (BubbleRowPage row in kind.Rows)
			{
				content.Add(Row(row));
			}
		}

		private static void AddPattern(VisualElement content, BubbleKindPage kind)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			PatternPage pattern = kind.Pattern;
			content.Add(UiControls.Heading("Pattern - " + kind.Title));
			content.Add((VisualElement)(object)UiControls.Note("Draws a pattern on the bubble. It uses the colour you pick below (or its own colour while 'Default color' is on), the opacity, reflection and distortion settings above."));
			VisualElement sliders = new VisualElement();
			sliders.Add(UiControls.Row("Strength (%)", UiControls.Slider(0f, 200f, (float)pattern.Strength, "0", (Action<float>)delegate(float v)
			{
				pattern.OnStrength((int)Math.Round(v));
			})));
			sliders.Add(UiControls.Row("Speed (%)", UiControls.Slider(0f, 400f, (float)pattern.Speed, "0", (Action<float>)delegate(float v)
			{
				pattern.OnSpeed((int)Math.Round(v));
			})));
			sliders.Add(UiControls.Row("Density (%)", UiControls.Slider(25f, 400f, (float)pattern.Density, "0", (Action<float>)delegate(float v)
			{
				pattern.OnDensity((int)Math.Round(v));
			})));
			sliders.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)((pattern.Chosen == pattern.Choices[0]) ? 1 : 0));
			content.Add(UiControls.Row("Pattern", (VisualElement)(object)UiControls.Dropdown(pattern.Choices, pattern.Chosen, (Func<string, string>)((string t) => t), (Action<string>)delegate(string chosen)
			{
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				pattern.OnChosen(chosen);
				sliders.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)((chosen == pattern.Choices[0]) ? 1 : 0));
			})));
			content.Add(sliders);
		}

		private static VisualElement Row(BubbleRowPage row)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			VisualElement val = new VisualElement();
			val.style.flexShrink = StyleFloat.op_Implicit(0f);
			string saved = row.Hex;
			string pending = row.Hex;
			bool useGame = row.UseGame;
			VisualElement swatch = new VisualElement();
			swatch.style.width = StyleLength.op_Implicit(28f);
			swatch.style.height = StyleLength.op_Implicit(22f);
			swatch.style.flexShrink = StyleFloat.op_Implicit(0f);
			swatch.style.marginLeft = StyleLength.op_Implicit(6f);
			UiKit.Radius(swatch, 4f);
			UiKit.Borders(swatch, 1f, UiKit.Border);
			VisualElement toggleSlot = new VisualElement();
			toggleSlot.style.flexShrink = StyleFloat.op_Implicit(0f);
			ShowToggle(useGame);
			ShowSwatch();
			UiColorPicker picker = new UiColorPicker(saved, (Action<string>)delegate(string hex)
			{
				pending = hex;
			}, false);
			TextField hexField = UQueryExtensions.Q<TextField>(picker.Root, (string)null, (string)null);
			VisualElement panel = new VisualElement();
			panel.style.flexShrink = StyleFloat.op_Implicit(0f);
			panel.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)1);
			panel.Add(picker.Root);
			bool open = false;
			Button val2 = UiControls.Button("Apply", (Action)delegate
			{
				string text2 = ((hexField == null) ? null : ((BaseField<string>)(object)hexField).value?.Trim());
				if (!string.IsNullOrEmpty(text2))
				{
					string text3 = (text2.StartsWith("#") ? text2 : ("#" + text2));
					Color val4 = default(Color);
					if (text3.Length == 7 && ColorUtility.TryParseHtmlString(text3, ref val4))
					{
						pending = text3.ToUpperInvariant();
					}
				}
				row.OnHex(pending);
				saved = pending;
				if (useGame)
				{
					useGame = false;
					row.OnUseGame(obj: false);
					ShowToggle(on: false);
				}
				ShowSwatch();
				SetOpen(value: false);
			}, true);
			panel.Add(UiControls.Line((VisualElement[])(object)new VisualElement[2]
			{
				(VisualElement)val2,
				(VisualElement)UiControls.Note("Saves the colour and turns 'Default color' off for this row.")
			}));
			Button val3 = UiControls.Button("Pick colour", (Action)delegate
			{
				SetOpen(!open);
			}, false);
			string text = row.Label.Replace(" ", "");
			((VisualElement)val3).name = "CmbPick_" + text;
			((VisualElement)val2).name = "CmbApply_" + text;
			if (hexField != null)
			{
				((VisualElement)hexField).name = "CmbHex_" + text;
			}
			val.Add(UiControls.Row(row.Label, UiControls.Line((VisualElement[])(object)new VisualElement[3]
			{
				toggleSlot,
				(VisualElement)val3,
				swatch
			})));
			val.Add(panel);
			return val;
			void SetOpen(bool value)
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				open = value;
				Color val4 = default(Color);
				if (open && ColorUtility.TryParseHtmlString(saved, ref val4))
				{
					picker.Set(val4);
					pending = saved;
				}
				panel.style.display = StyleEnum<DisplayStyle>.op_Implicit((DisplayStyle)(!open));
			}
			void ShowSwatch()
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				Color val4 = default(Color);
				if (ColorUtility.TryParseHtmlString(saved, ref val4))
				{
					swatch.style.backgroundColor = StyleColor.op_Implicit(val4);
				}
				swatch.style.opacity = StyleFloat.op_Implicit(useGame ? 0.35f : 1f);
				swatch.tooltip = saved + (useGame ? " (not used while 'Default color' is on)" : "");
			}
			void ShowToggle(bool on)
			{
				toggleSlot.Clear();
				toggleSlot.Add(UiControls.Toggle("Default color", on, (Action<bool>)delegate(bool v)
				{
					useGame = v;
					row.OnUseGame(v);
					ShowSwatch();
				}));
			}
		}
	}
	internal sealed class DetailGroup
	{
		internal readonly string Title;

		internal readonly List<DetailRow> Rows = new List<DetailRow>();

		internal DetailGroup(string title)
		{
			Title = title ?? "";
		}

		internal DetailRow Add(string label, string value, string maxValue = "")
		{
			DetailRow detailRow = new DetailRow(label, value, maxValue);
			Rows.Add(detailRow);
			return detailRow;
		}

		public override string ToString()
		{
			return Title + " (" + Rows.Count + " rows)";
		}
	}
	internal sealed class DetailRow
	{
		internal readonly string Label;

		internal readonly string Value;

		internal readonly string MaxValue;

		internal bool HasMax => MaxValue.Length > 0;

		internal DetailRow(string label, string value, string maxValue = "")
		{
			Label = label ?? "";
			Value = value ?? "";
			MaxValue = maxValue ?? "";
		}

		public override string ToString()
		{
			return Label + " = " + Value + (HasMax ? (" -> " + MaxValue) : "");
		}
	}
	internal static class DetailsView
	{
		private const float LabelWidth = 210f;

		private const float ValueWidth = 140f;

		internal static VisualElement Build(IList<DetailGroup> groups, string qualityHeader, string maxQualityHeader)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			VisualElement val = new VisualElement
			{
				name = "kydl-details"
			};
			val.style.flexShrink = StyleFloat.op_Implicit(0f);
			int num = 0;
			if (groups != null)
			{
				foreach (DetailGroup group in groups)
				{
					val.Add(UiControls.Heading(group.Title));
					bool flag = false;
					foreach (DetailRow row in group.Rows)
					{
						if (row.HasMax)
						{
							flag = true;
							break;
						}
					}
					if (flag)
					{
						val.Add(ColumnHeader(qualityHeader, maxQualityHeader));
					}
					foreach (DetailRow row2 in group.Rows)
					{
						val.Add(StatRow(row2, flag));
						num++;
					}
				}
			}
			UiLog.Verbose("DetailsView: " + (groups?.Count ?? 0) + " group(s), " + num + " row(s)");
			return val;
		}

		private static VisualElement ColumnHeader(string q, string max)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			VisualElement obj = RowBox();
			obj.Add((VisualElement)(object)Cell("", 210f, UiKit.TextDim, 18f));
			obj.Add((VisualElement)(object)Cell(q ?? "", 140f, UiKit.TextDim, 18f));
			obj.Add((VisualElement)(object)Cell(max ?? "", 140f, UiKit.TextDim, 18f));
			return obj;
		}

		private static VisualElement StatRow(DetailRow row, bool blockHasMax)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			VisualElement val = RowBox();
			val.Add((VisualElement)(object)Cell(row.Label, 210f, UiKit.TextDim, 22f));
			val.Add((VisualElement)(object)Cell(row.Value, (blockHasMax && row.HasMax) ? 140f : (-1f), UiKit.Text, 22f));
			if (blockHasMax && row.HasMax)
			{
				val.Add((VisualElement)(object)Cell(row.MaxValue, 140f, UiKit.Gold, 22f));
			}
			return val;
		}

		private static VisualElement RowBox()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			VisualElement val = new VisualElement();
			val.style.flexDirection = StyleEnum<FlexDirection>.op_Implicit((FlexDirection)2);
			val.style.alignItems = StyleEnum<Align>.op_Implicit((Align)1);
			val.style.flexShrink = StyleFloat.op_Implicit(0f);
			val.style.marginTop = StyleLength.op_Implicit(2f);
			val.style.marginBottom = StyleLength.op_Implicit(2f);
			return val;
		}

		private static Label Cell(string content, float width, Color color, float size)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			Label val = UiKit.Label(content, size, color, false);
			((VisualElement)val).style.whiteSpace = StyleEnum<WhiteSpace>.op_Implicit((WhiteSpace)0);
			if (width >= 0f)
			{
				((VisualElement)val).style.width = StyleLength.op_Implicit(width);
				((VisualElement)val).style.flexShrink = StyleFloat.op_Implicit(0f);
			}
			else
			{
				((VisualElement)val).style.flexGrow = StyleFloat.op_Implicit(1f);
				((VisualElement)val).style.flexShrink = StyleFloat.op_Implicit(1f);
			}
			return val;
		}
	}
	internal interface IModelScene : IDisposable
	{
		Texture Texture { get; }

		bool Show(string modelId);

		bool Resize(int widthPx, int heightPx);

		bool Render(float yawDeg, float pitchDeg, float zoom, float panX, float panY, float panZ);
	}
	internal sealed class ModelViewerRig : IModelScene, IDisposable
	{
		internal static readonly Vector3 Park = new Vector3(0f, -1500f, 0f);

		internal const float FieldOfView = 30f;

		private const float LogEverySeconds = 0.5f;

		private readonly Func<string, GameObject> _makeModel;

		private readonly ViewerSettings _settings;

		private readonly Action<string> _log;

		private readonly int _layer;

		private readonly string _rigName;

		private GameObject _root;

		private GameObject _pivot;

		private GameObject _model;

		private Camera _camera;

		private readonly List<Light> _lights = new List<Light>();

		private RenderTexture _texture;

		private string _modelId;

		private float _halfWidth;

		private float _halfHeight;

		private float _radius;

		private float _lastLog = -100f;

		private float _lastLightLog = -100f;

		private int _renders;

		public Texture Texture => (Texture)(object)_texture;

		internal unsafe ModelViewerRig(Func<string, GameObject> makeModel, int layer, ViewerSettings settings, Color background, Action<string> log, string rigName = "Kydl_ViewerRig")
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			_makeModel = makeModel;
			_settings = settings ?? new ViewerSettings();
			_log = log;
			_layer = Mathf.Clamp(layer, 0, 31);
			_rigName = (string.IsNullOrEmpty(rigName) ? "Kydl_ViewerRig" : rigName);
			if (_layer != layer)
			{
				Log("ModelViewerRig: layer " + layer + " is outside 0..31, using " + _layer);
			}
			_root = new GameObject(_rigName);
			_root.transform.position = Park;
			_pivot = new GameObject("Pivot");
			_pivot.transform.SetParent(_root.transform, false);
			GameObject val = new GameObject("Camera");
			val.transform.SetParent(_root.transform, false);
			_camera = val.AddComponent<Camera>();
			((Behaviour)_camera).enabled = false;
			_camera.cullingMask = 1 << _layer;
			_camera.clearFlags = (CameraClearFlags)2;
			_camera.backgroundColor = background;
			_camera.fieldOfView = 30f;
			_camera.nearClipPlane = 0.02f;
			_camera.farClipPlane = 200f;
			_camera.allowHDR = false;
			_camera.useOcclusionCulling = false;
			_camera.renderingPath = (RenderingPath)1;
			AddLight(val.transform, "KeyLight", new Vector3(25f, 30f, 0f), _settings.KeyLight);
			AddLight(val.transform, "FillLight", new Vector3(-10f, -45f, 0f), _settings.FillLight);
			string[] obj = new string[10]
			{
				"ModelViewerRig: made at ",
				V(Park),
				", layer ",
				_layer.ToString(),
				", fov ",
				30f.ToString(),
				" deg, background ",
				null,
				null,
				null
			};
			Color val2 = background;
			obj[7] = ((object)(*(Color*)(&val2))/*cast due to .constrained prefix*/).ToString();
			obj[8] = ", ";
			obj[9] = _settings?.ToString();
			Log(string.Concat(obj));
		}

		private void AddLight(Transform parent, string name, Vector3 euler, float intensity)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			val.transform.localRotation = Quaternion.Euler(euler);
			Light val2 = val.AddComponent<Light>();
			val2.type = (LightType)1;
			val2.intensity = intensity;
			val2.color = new Color(1f, 0.96f, 0.9f);
			val2.shadows = (LightShadows)0;
			val2.cullingMask = 1 << _layer;
			val2.renderMode = (LightRenderMode)1;
			((Behaviour)val2).enabled = false;
			_lights.Add(val2);
		}

		public bool Show(string modelId)
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_0243: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_026d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0277: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0345: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null)
			{
				Log("ModelViewerRig: Show(" + modelId + ") after Dispose - ignored");
				return false;
			}
			if ((Object)(object)_model != (Object)null)
			{
				_model.SetActive(false);
				Object.Destroy((Object)(object)_model);
				_model = null;
			}
			_modelId = modelId;
			if (string.IsNullOrEmpty(modelId))
			{
				Log("ModelViewerRig: no model to show");
				return false;
			}
			GameObject val = null;
			Log("ModelViewerRig: making the model '" + modelId + "'");
			try
			{
				val = ((_makeModel != null) ? _makeModel(modelId) : null);
			}
			catch (Exception ex)
			{
				Log("ModelViewerRig: making the model '" + modelId + "' failed: " + ex.GetType().Name + ": " + ex.Message);
			}
			if ((Object)(object)val == (Object)null)
			{
				Log("ModelViewerRig: no model for '" + modelId + "' (model maker gave null)");
				return false;
			}
			_model = val;
			_pivot.transform.localRotation = Quaternion.identity;
			_model.transform.SetParent(_pivot.transform, false);
			_model.transform.localPosition = Vector3.zero;
			_model.transform.localRotation = Quaternion.identity;
			int num = Prepare(_model);
			if (num == 0)
			{
				Log("ModelViewerRig: model '" + modelId + "' has no renderers - nothing to see");
				return false;
			}
			Bounds val2 = WorldBounds(_model);
			Vector3 size = ((Bounds)(ref val2)).size;
			Quaternion localRotation = Quaternion.identity;
			string text = "X";
			if (size.y >= size.x && size.y >= size.z)
			{
				localRotation = Quaternion.Euler(0f, 0f, -90f);
				text = "Y";
			}
			else if (size.z >= size.x && size.z >= size.y)
			{
				localRotation = Quaternion.Euler(0f, 90f, 0f);
				text = "Z";
			}
			_model.transform.localRotation = localRotation;
			Bounds val3 = WorldBounds(_model);
			Transform transform = _model.transform;
			transform.position -= ((Bounds)(ref val3)).center - _pivot.transform.position;
			Bounds val4 = WorldBounds(_model);
			_halfWidth = ((Bounds)(ref val4)).extents.x;
			_halfHeight = Mathf.Max(((Bounds)(ref val4)).extents.y, ((Bounds)(ref val4)).extents.z);
			Vector3 extents = ((Bounds)(ref val4)).extents;
			_radius = ((Vector3)(ref extents)).magnitude;
			Log("ModelViewerRig: showing '" + modelId + "': " + num + " renderer(s), size " + V(((Bounds)(ref val2)).size) + " m, longest axis " + text + " laid across, centre offset " + V(((Bounds)(ref val4)).center - _pivot.transform.position) + " m, half width " + F(_halfWidth) + " / height " + F(_halfHeight) + " / radius " + F(_radius) + " m");
			return true;
		}

		private int Prepare(GameObject model)
		{
			int num = 0;
			int num2 = 0;
			Transform[] componentsInChildren = model.GetComponentsInChildren<Transform>(true);
			int i;
			for (i = 0; i < componentsInChildren.Length; i++)
			{
				((Component)componentsInChildren[i]).gameObject.layer = _layer;
			}
			Renderer[] componentsInChildren2 = model.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer obj in componentsInChildren2)
			{
				obj.shadowCastingMode = (ShadowCastingMode)0;
				obj.receiveShadows = false;
				SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((obj is SkinnedMeshRenderer) ? obj : null);
				if ((Object)(object)val != (Object)null)
				{
					val.updateWhenOffscreen = true;
				}
				num++;
			}
			Collider[] componentsInChildren3 = model.GetComponentsInChildren<Collider>(true);
			for (i = 0; i < componentsInChildren3.Length; i++)
			{
				componentsInChildren3[i].enabled = false;
				num2++;
			}
			string[] obj2 = new string[9]
			{
				"ModelViewerRig: prepared model '",
				((Object)model).name,
				"': ",
				num.ToString(),
				" renderer(s) on layer ",
				null,
				null,
				null,
				null
			};
			i = _layer;
			obj2[5] = i.ToString();
			obj2[6] = ", ";
			obj2[7] = num2.ToString();
			obj2[8] = " collider(s) off";
			Log(string.Concat(obj2));
			return num;
		}

		private static Bounds WorldBounds(GameObject go)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = go.GetComponentsInChildren<Renderer>(true);
			if (componentsInChildren.Length == 0)
			{
				return new Bounds(go.transform.position, Vector3.zero);
			}
			Bounds bounds = componentsInChildren[0].bounds;
			for (int i = 1; i < componentsInChildren.Length; i++)
			{
				((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds);
			}
			return bounds;
		}

		public bool Resize(int widthPx, int heightPx)
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Expected O, but got Unknown
			if ((Object)(object)_root == (Object)null)
			{
				Log("ModelViewerRig: Resize after Dispose - ignored");
				return false;
			}
			int num = Mathf.Clamp(widthPx, 16, 4096);
			int num2 = Mathf.Clamp(heightPx, 16, 4096);
			if ((Object)(object)_texture != (Object)null && ((Texture)_texture).width == num && ((Texture)_texture).height == num2)
			{
				return true;
			}
			if ((Object)(object)_texture != (Object)null)
			{
				_camera.targetTexture = null;
				_texture.Release();
				Object.Destroy((Object)(object)_texture);
			}
			_texture = new RenderTexture(num, num2, 24, (RenderTextureFormat)0)
			{
				name = _rigName + "_Texture",
				antiAliasing = 4
			};
			_texture.Create();
			_camera.targetTexture = _texture;
			Log("ModelViewerRig: texture " + num + "x" + num2 + " px (asked " + widthPx + "x" + heightPx + ")");
			return true;
		}

		public bool Render(float yawDeg, float pitchDeg, float zoom, float panX, float panY, float panZ)
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null || (Object)(object)_texture == (Object)null)
			{
				Log("ModelViewerRig: Render skipped (" + (((Object)(object)_root == (Object)null) ? "disposed" : "no texture yet") + ")");
				return false;
			}
			float num = (float)((Texture)_texture).width / (float)((Texture)_texture).height;
			float num2 = ViewerMath.FitDistance(_halfWidth, _halfHeight, _radius, 30f, num, _settings.Margin);
			float num3 = num2 / Mathf.Max(0.01f, zoom);
			float num4 = 2f * num2 * Mathf.Tan((float)Math.PI / 12f);
			Vector3 val = new Vector3(panX, panY, panZ) * num4;
			ViewerMath.Orbit(yawDeg, pitchDeg, num3, out var x, out var y, out var z);
			Vector3 val2 = _pivot.transform.position + val;
			((Component)_camera).transform.position = val2 + new Vector3(x, y, z);
			((Component)_camera).transform.LookAt(val2, Vector3.up);
			_camera.nearClipPlane = Mathf.Clamp(num3 - ((Vector3)(ref val)).magnitude - _radius * 1.2f, 0.01f, 0.5f);
			RenderLit();
			_renders++;
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup - _lastLog >= 0.5f)
			{
				_lastLog = realtimeSinceStartup;
				Log("ModelViewerRig: render #" + _renders + " of " + (_modelId ?? "nothing") + ": yaw " + F(yawDeg) + " / pitch " + F(pitchDeg) + " deg, zoom x" + F(zoom) + ", fit " + F(num2) + " m, distance " + F(num3) + " m, aspect " + F(num) + ", pan " + V(val) + " m (" + V(new Vector3(panX, panY, panZ)) + " view heights of " + F(num4) + " m), near " + F(_camera.nearClipPlane) + " m, model " + (((Object)(object)_model != (Object)null) ? "shown" : "none"));
			}
			return true;
		}

		private unsafe void RenderLit()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0257: Unknown result type (might be due to invalid IL or missing references)
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			AmbientMode ambientMode = RenderSettings.ambientMode;
			Color ambientLight = RenderSettings.ambientLight;
			float ambientIntensity = RenderSettings.ambientIntensity;
			bool fog = RenderSettings.fog;
			try
			{
				if (_lights.Count > 0 && (Object)(object)_lights[0] != (Object)null)
				{
					_lights[0].intensity = _settings.KeyLight;
				}
				if (_lights.Count > 1 && (Object)(object)_lights[1] != (Object)null)
				{
					_lights[1].intensity = _settings.FillLight;
				}
				for (int i = 0; i < _lights.Count; i++)
				{
					if ((Object)(object)_lights[i] != (Object)null)
					{
						((Behaviour)_lights[i]).enabled = true;
					}
				}
				RenderSettings.ambientMode = (AmbientMode)3;
				RenderSettings.ambientLight = new Color(_settings.Ambient, _settings.Ambient * 0.95f, _settings.Ambient * 0.9f);
				RenderSettings.ambientIntensity = 1f;
				RenderSettings.fog = false;
				_camera.Render();
			}
			finally
			{
				int num = 0;
				for (int j = 0; j < _lights.Count; j++)
				{
					if ((Object)(object)_lights[j] != (Object)null)
					{
						((Behaviour)_lights[j]).enabled = false;
						if (((Behaviour)_lights[j]).enabled)
						{
							num++;
						}
					}
				}
				float realtimeSinceStartup = Time.realtimeSinceStartup;
				if (realtimeSinceStartup - _lastLightLog >= 2f)
				{
					_lastLightLog = realtimeSinceStartup;
					string[] obj = new string[12]
					{
						"ModelViewerRig: lights ",
						_lights.Count.ToString(),
						" switched on for this render only, ",
						num.ToString(),
						" still on after it (expect 0); ambient put back to ",
						((object)(*(AmbientMode*)(&ambientMode))/*cast due to .constrained prefix*/).ToString(),
						" / ",
						null,
						null,
						null,
						null,
						null
					};
					Color val = ambientLight;
					obj[7] = ((object)(*(Color*)(&val))/*cast due to .constrained prefix*/).ToString();
					obj[8] = " x";
					obj[9] = ambientIntensity.ToString();
					obj[10] = ", fog ";
					obj[11] = fog.ToString();
					Log(string.Concat(obj));
				}
				RenderSettings.ambientMode = ambientMode;
				RenderSettings.ambientLight = ambientLight;
				RenderSettings.ambientIntensity = ambientIntensity;
				RenderSettings.fog = fog;
			}
		}

		public void Dispose()
		{
			if (!((Object)(object)_root == (Object)null))
			{
				if ((Object)(object)_camera != (Object)null)
				{
					_camera.targetTexture = null;
				}
				if ((Object)(object)_texture != (Object)null)
				{
					_texture.Release();
					Object.Destroy((Object)(object)_texture);
					_texture = null;
				}
				Object.Destroy((Object)(object)_root);
				_root = null;
				_model = null;
				_camera = null;
				Log("ModelViewerRig: disposed after " + _renders + " render(s)");
			}
		}

		private static string F(float v)
		{
			return v.ToString("0.###", CultureInfo.InvariantCulture);
		}

		private static string V(Vector3 v)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			return "(" + F(v.x) + ", " + F(v.y) + ", " + F(v.z) + ")";
		}

		private void Log(string s)
		{
			if (_log != null)
			{
				_log(s);
			}
		}
	}
	internal static class ModelViewportView
	{
		private sealed class Viewport
		{
			private readonly IModelScene _scene;

			private readonly ViewerOrbit _orbit;

			private readonly Image _image;

			private readonly VisualElement _frame;

			private readonly string _modelId;

			private bool _dragging;

			private bool _panning;

			private int _dragButton = -1;

			private Vector2 _last;

			private int _pointer = -1;

			internal Viewport(string title, string modelId, IModelScene scene, ViewerSettings settings, VisualElement frame, string hint, string reset)
			{
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0088: Expected O, but got Unknown
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0126: Unknown result type (might be due to invalid IL or missing references)
				//IL_0139: Unknown result type (might be due to invalid IL or missing references)
				//IL_014e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0163: Unknown result type (might be due to invalid IL or missing references)
				//IL_0190: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fb: Expected O, but got Unknown
				//IL_0202: Unknown result type (might be due to invalid IL or missing references)
				//IL_0217: Unknown result type (might be due to invalid IL or missing references)
				//IL_022c: Unknown result type (might be due to invalid IL or missing references)
				//IL_023d: Unknown result type (might be due to invalid IL or missing references)
				Viewport viewport = this;
				_scene = scene;
				_frame = frame;
				_modelId = modelId;
				_orbit = new ViewerOrbit(settings, (Action<string>)UiLog.Verbose);
				_image = new Image
				{
					name = "kydl-viewport-image",
					scaleMode = (ScaleMode)0
				};
				((VisualElement)_image).style.position = StyleEnum<Position>.op_Implicit((Position)1);
				((VisualElement)_image).style.left = StyleLength.op_Implicit(0f);
				((VisualElement)_image).style.top = StyleLength.op_Implicit(0f);
				((VisualElement)_image).style.right = StyleLength.op_Implicit(0f);
				((VisualElement)_image).style.bottom = StyleLength.op_Implicit(0f);
				frame.Add((VisualElement)(object)_image);
				Label val = UiKit.Label(title ?? "", 24f, UiKit.Gold, true);
				((VisualElement)val).style.position = StyleEnum<Position>.op_Implicit((Position)1);
				((VisualElement)val).style.left = StyleLength.op_Implicit(10f);
				((VisualElement)val).style.top = StyleLength.op_Implicit(6f);
				((VisualElement)val).pickingMode = (PickingMode)1;
				frame.Add((VisualElement)(object)val);
				Label val2 = UiKit.Label(hint ?? "", 18f, UiKit.TextDim, false);
				((VisualElement)val2).style.position = StyleEnum<Position>.op_Implicit((Position)1);
				((VisualElement)val2).style.left = StyleLength.op_Implicit(10f);
				((VisualElement)val2).style.bottom = StyleLength.op_Implicit(8f);
				((VisualElement)val2).pickingMode = (PickingMode)1;
				frame.Add((VisualElement)(object)val2);
				VisualElement val3 = new VisualElement
				{
					name = "kydl-viewport-buttons"
				};
				val3.style.position = StyleEnum<Position>.op_Implicit((Position)1);
				val3.style.right = StyleLength.op_Implicit(6f);
				val3.style.bottom = StyleLength.op_Implicit(4f);
				val3.style.flexDirection = StyleEnum<FlexDirection>.op_Implicit((FlexDirection)2);
				val3.Add((VisualElement)(object)UiControls.Button("+", (Action)delegate
				{
					viewport.Changed(viewport._orbit.StepZoom(1f), "zoom in button");
				}, false));
				val3.Add((VisualElement)(object)UiControls.Button("-", (Action)delegate
				{
					viewport.Changed(viewport._orbit.StepZoom(-1f), "zoom out button");
				}, false));
				val3.Add((VisualElement)(object)UiControls.Button(reset ?? "Reset", (Action)delegate
				{
					viewport.Changed(viewport._orbit.Reset(), "reset button");
				}, false));
				frame.Add(val3);
				((CallbackEventHandler)_image).RegisterCallback<PointerDownEvent>((EventCallback<PointerDownEvent>)OnDown, (TrickleDown)0);
				((CallbackEventHandler)_image).RegisterCallback<PointerMoveEvent>((EventCallback<PointerMoveEvent>)OnMove, (TrickleDown)0);
				((CallbackEventHandler)_image).RegisterCallback<PointerUpEvent>((EventCallback<PointerUpEvent>)OnUp, (TrickleDown)0);
				((CallbackEventHandler)_image).RegisterCallback<PointerCaptureOutEvent>((EventCallback<PointerCaptureOutEvent>)delegate
				{
					viewport.EndDrag("capture lost");
				}, (TrickleDown)0);
				((CallbackEventHandler)frame).RegisterCallback<WheelEvent>((EventCallback<WheelEvent>)OnWheel, (TrickleDown)0);
				((CallbackEventHandler)frame).RegisterCallback<GeometryChangedEvent>((EventCallback<GeometryChangedEvent>)delegate
				{
					viewport.OnResized(frame);
				}, (TrickleDown)0);
				((CallbackEventHandler)frame).RegisterCallback<DetachFromPanelEvent>((EventCallback<DetachFromPanelEvent>)delegate
				{
					viewport.Teardown();
				}, (TrickleDown)0);
				bool flag = _scene.Show(_modelId);
				_orbit.Reset();
				UiLog.Verbose("ModelViewportView: 3D viewport built for '" + _modelId + "', model " + (flag ? "shown" : "NOT shown (see the ModelViewerRig lines above)") + " (" + settings?.ToString() + ")");
			}

			private void OnDown(PointerDownEvent e)
			{
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_0118: Unknown result type (might be due to invalid IL or missing references)
				if (((PointerEventBase<PointerDownEvent>)(object)e).button == 0 || ((PointerEventBase<PointerDownEvent>)(object)e).button == 1)
				{
					if (_dragging)
					{
						UiLog.Verbose("ModelViewportView: button " + ((PointerEventBase<PointerDownEvent>)(object)e).button + " pressed during a " + (_panning ? "pan" : "rotate") + " drag (button " + _dragButton + ") - ignored");
						return;
					}
					_dragging = true;
					_panning = ((PointerEventBase<PointerDownEvent>)(object)e).button == 1;
					_dragButton = ((PointerEventBase<PointerDownEvent>)(object)e).button;
					_pointer = ((PointerEventBase<PointerDownEvent>)(object)e).pointerId;
					_last = new Vector2(((PointerEventBase<PointerDownEvent>)(object)e).position.x, ((PointerEventBase<PointerDownEvent>)(object)e).position.y);
					PointerCaptureHelper.CapturePointer((IEventHandler)(object)_image, ((PointerEventBase<PointerDownEvent>)(object)e).pointerId);
					((EventBase)e).StopPropagation();
					UiLog.Verbose("ModelViewportView: " + (_panning ? "pan" : "rotate") + " drag started at " + P(_last) + " (button " + ((PointerEventBase<PointerDownEvent>)(object)e).button + ", pointer " + ((PointerEventBase<PointerDownEvent>)(object)e).pointerId + ", frame " + FrameHeightPx().ToString("0", CultureInfo.InvariantCulture) + " UI px high)");
				}
			}

			private void OnMove(PointerMoveEvent e)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0043: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0084: Unknown result type (might be due to invalid IL or missing references)
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				if (!_dragging || ((PointerEventBase<PointerMoveEvent>)(object)e).pointerId != _pointer)
				{
					return;
				}
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(((PointerEventBase<PointerMoveEvent>)(object)e).position.x, ((PointerEventBase<PointerMoveEvent>)(object)e).position.y);
				Vector2 val2 = val - _last;
				_last = val;
				if (!(((Vector2)(ref val2)).sqrMagnitude <= 0f))
				{
					if (_panning ? _orbit.Pan(val2.x, val2.y, FrameHeightPx()) : _orbit.Drag(val2.x, val2.y))
					{
						Draw(null);
					}
					((EventBase)e).StopPropagation();
				}
			}

			private void OnUp(PointerUpEvent e)
			{
				if (((PointerEventBase<PointerUpEvent>)(object)e).button == _dragButton && ((PointerEventBase<PointerUpEvent>)(object)e).pointerId == _pointer)
				{
					if (PointerCaptureHelper.HasPointerCapture((IEventHandler)(object)_image, ((PointerEventBase<PointerUpEvent>)(object)e).pointerId))
					{
						PointerCaptureHelper.ReleasePointer((IEventHandler)(object)_image, ((PointerEventBase<PointerUpEvent>)(object)e).pointerId);
					}
					EndDrag("button " + ((PointerEventBase<PointerUpEvent>)(object)e).button + " released");
					((EventBase)e).StopPropagation();
				}
			}

			private void EndDrag(string why)
			{
				if (_dragging)
				{
					_dragging = false;
					_pointer = -1;
					UiLog.Verbose("ModelViewportView: " + (_panning ? "pan" : "rotate") + " drag ended (" + why + "), view " + _orbit);
					_panning = false;
					_dragButton = -1;
				}
			}

			private float FrameHeightPx()
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				Rect contentRect = _frame.contentRect;
				return ((Rect)(ref contentRect)).height;
			}

			private void OnWheel(WheelEvent e)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Unknown result type (might be due to invalid IL or missing references)
				Changed(_orbit.Wheel(e.delta.y), "wheel " + e.delta.y.ToString("0.##", CultureInfo.InvariantCulture));
				((EventBase)e).StopPropagation();
			}

			private void OnResized(VisualElement frame)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				Rect contentRect = frame.contentRect;
				float num = PixelsPerPoint();
				int num2 = Mathf.RoundToInt(((Rect)(ref contentRect)).width * num);
				int num3 = Mathf.RoundToInt(((Rect)(ref contentRect)).height * num);
				if (num2 < 16 || num3 < 16)
				{
					UiLog.Verbose("ModelViewportView: frame " + ((Rect)(ref contentRect)).width + "x" + ((Rect)(ref contentRect)).height + " UI px is too small (hidden tab?), no texture");
					return;
				}
				UiLog.Verbose("ModelViewportView: frame " + ((Rect)(ref contentRect)).width.ToString("0", CultureInfo.InvariantCulture) + "x" + ((Rect)(ref contentRect)).height.ToString("0", CultureInfo.InvariantCulture) + " UI px x " + num.ToString("0.###", CultureInfo.InvariantCulture) + " = " + num2 + "x" + num3 + " screen px");
				if (_scene.Resize(num2, num3))
				{
					_image.image = _scene.Texture;
				}
				Draw("resized");
			}

			private static float PixelsPerPoint()
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Invalid comparison between Unknown and I4
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				PanelSettings settings = UiKit.Settings;
				if (!((Object)(object)settings == (Object)null) && (int)settings.scaleMode == 2)
				{
					Vector2Int referenceResolution = settings.referenceResolution;
					if (((Vector2Int)(ref referenceResolution)).y > 0)
					{
						float num = (((Object)(object)settings.targetTexture != (Object)null) ? ((Texture)settings.targetTexture).height : Screen.height);
						referenceResolution = settings.referenceResolution;
						return Mathf.Clamp(num / (float)((Vector2Int)(ref referenceResolution)).y, 0.25f, 8f);
					}
				}
				return 1f;
			}

			private void Changed(bool changed, string why)
			{
				if (changed)
				{
					Draw(why);
					return;
				}
				UiLog.Verbose("ModelViewportView: " + why + " - view unchanged (" + _orbit?.ToString() + ")");
			}

			private void Draw(string why)
			{
				bool flag = _scene.Render(_orbit.Yaw, _orbit.Pitch, _orbit.Zoom, _orbit.PanX, _orbit.PanY, _orbit.PanZ);
				((VisualElement)_image).MarkDirtyRepaint();
				if (why != null)
				{
					UiLog.Verbose("ModelViewportView: drawn after " + why + " (" + _orbit?.ToString() + ")" + (flag ? "" : " - scene did not render"));
				}
			}

			private void Teardown()
			{
				_image.image = null;
				_scene.Dispose();
				UiLog.Verbose("ModelViewportView: viewport closed, 3D scene of '" + _modelId + "' disposed");
			}

			private static string P(Vector2 v)
			{
				return "(" + v.x.ToString("0", CultureInfo.InvariantCulture) + ", " + v.y.ToString("0", CultureInfo.InvariantCulture) + ")";
			}
		}

		internal static VisualElement Build(string title, string modelId, Func<IModelScene> makeScene, ViewerSettings settings, string hint, string reset, string unavailable)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			settings = settings ?? new ViewerSettings();
			settings.Clamp((Action<string>)UiLog.Verbose);
			VisualElement val = new VisualElement
			{
				name = "kydl-viewport"
			};
			val.style.flexShrink = StyleFloat.op_Implicit(0f);
			val.style.height = StyleLength.op_Implicit(settings.FrameHeight);
			val.style.marginTop = StyleLength.op_Implicit(10f);
			val.style.backgroundColor = StyleColor.op_Implicit(UiKit.Track);
			UiKit.Borders(val, 1f, UiKit.Border);
			UiKit.Radius(val, 4f);
			val.style.overflow = StyleEnum<Overflow>.op_Implicit((Overflow)1);
			IModelScene modelScene = null;
			try
			{
				modelScene = makeScene?.Invoke();
			}
			catch (Exception ex)
			{
				UiLog.Error("ModelViewportView: making the 3D scene failed: " + ex.GetType().Name + ": " + ex.Message);
			}
			if (modelScene == null)
			{
				val.style.justifyContent = StyleEnum<Justify>.op_Implicit((Justify)1);
				val.style.alignItems = StyleEnum<Align>.op_Implicit((Align)2);
				val.Add((VisualElement)(object)UiKit.Label(title ?? "", 24f, UiKit.TextDim, true));
				val.Add((VisualElement)(object)UiKit.Label(unavailable ?? "", 22f, UiKit.TextDim, false));
				UiLog.Verbose("ModelViewportView: no 3D scene, showing the title '" + title + "' only");
				return val;
			}
			new Viewport(title, modelId, modelScene, settings, val, hint, reset);
			return val;
		}
	}
	internal sealed class TabBar
	{
		private const float RailMargin = 18f;

		private readonly List<Button> _buttons = new List<Button>();

		private readonly Action<int> _changed;

		private int _selected = -1;

		internal VisualElement Root { get; private set; }

		internal int Selected => _selected;

		internal TabBar(IList<string> names, int selected, Action<int> changed)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			_changed = changed;
			Root = new VisualElement
			{
				name = "kydl-tabs"
			};
			Root.style.flexDirection = StyleEnum<FlexDirection>.op_Implicit((FlexDirection)2);
			Root.style.flexShrink = StyleFloat.op_Implicit(0f);
			Root.style.marginLeft = StyleLength.op_Implicit(18f);
			Root.style.marginRight = StyleLength.op_Implicit(18f);
			Root.style.marginTop = StyleLength.op_Implicit(8f);
			Root.style.borderBottomWidth = StyleFloat.op_Implicit(1f);
			Root.style.borderBottomColor = StyleColor.op_Implicit(UiKit.Border);
			for (int i = 0; i < names.Count; i++)
			{
				int index = i;
				Button val = new Button((Action)delegate
				{
					Select(index);
				})
				{
					text = names[i]
				};
				((VisualElement)val).style.fontSize = StyleLength.op_Implicit(21f);
				((VisualElement)val).style.flexShrink = StyleFloat.op_Implicit(0f);
				((VisualElement)val).style.marginLeft = StyleLength.op_Implicit(0f);
				((VisualElement)val).style.marginRight = StyleLength.op_Implicit(4f);
				((VisualElement)val).style.marginTop = StyleLength.op_Implicit(0f);
				((VisualElement)val).style.marginBottom = StyleLength.op_Implicit(0f);
				UiKit.Pad((VisualElement)(object)val, 8f, 22f);
				((VisualElement)val).style.borderTopWidth = StyleFloat.op_Implicit(0f);
				((VisualElement)val).style.borderLeftWidth = StyleFloat.op_Implicit(0f);
				((VisualElement)val).style.borderRightWidth = StyleFloat.op_Implicit(0f);
				((VisualElement)val).style.borderBottomWidth = StyleFloat.op_Implicit(3f);
				UiKit.Radius((VisualElement)(object)val, 0f);
				UiKit.Fade((VisualElement)(object)val, new string[2] { "background-color", "color" });
				((CallbackEventHandler)val).RegisterCallback<PointerEnterEvent>((EventCallback<PointerEnterEvent>)delegate
				{
					Paint(index, hover: true);
				}, (TrickleDown)0);
				((CallbackEventHandler)val).RegisterCallback<PointerLeaveEvent>((EventCallback<PointerLeaveEvent>)delegate
				{
					Paint(index, hover: false);
				}, (TrickleDown)0);
				_buttons.Add(val);
				Root.Add((VisualElement)(object)val);
			}
			Show(Mathf.Clamp(selected, 0, Math.Max(0, names.Count - 1)));
			UiLog.Verbose("TabBar: built with " + names.Count + " tab(s) [" + string.Join(", ", names) + "], selected " + _selected);
		}

		internal bool Select(int index)
		{
			if (index < 0 || index >= _buttons.Count)
			{
				UiLog.Verbose("TabBar: tab " + index + " does not exist (" + _buttons.Count + " tabs), selection stays " + _selected);
				return _selected == index;
			}
			if (index == _selected)
			{
				return _selected == index;
			}
			UiLog.Verbose("TabBar: tab " + _selected + " -> " + index + " ('" + ((TextElement)_buttons[index]).text + "')");
			Show(index);
			if (_changed != null)
			{
				_changed(index);
			}
			return _selected == index;
		}

		private void Show(int index)
		{
			_selected = index;
			for (int i = 0; i < _buttons.Count; i++)
			{
				Paint(i, hover: false);
			}
		}

		private void Paint(int index, bool hover)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			Button obj = _buttons[index];
			bool flag = index == _selected;
			((VisualElement)obj).style.backgroundColor = StyleColor.op_Implicit(flag ? UiKit.PanelLight : (hover ? UiKit.PanelHover : Color.clear));
			((VisualElement)obj).style.color = StyleColor.op_Implicit(flag ? UiKit.Gold : (hover ? UiKit.Text : UiKit.TextDim));
			((VisualElement)obj).style.borderBottomColor = StyleColor.op_Implicit(flag ? UiKit.Gold : Color.clear);
		}
	}
	internal static class UiText
	{
		internal static readonly Dictionary<string, string> En = new Dictionary<string, string>
		{
			{ "comfortmagicbubbles_menu_title", "ComfortMagicBubbles" },
			{ "comfortmagicbubbles_menu_footer", "Esc to close" },
			{ "comfortmagicbubbles_tab_settings", "Settings" }
		};

		internal static string English(string key)
		{
			if (!En.TryGetValue(key, out var value))
			{
				return key;
			}
			return value;
		}
	}
	internal static class ViewerMath
	{
		private const double Rad = Math.PI / 180.0;

		internal const float MinDistanceRadii = 1.5f;

		internal static float FitDistance(float halfWidth, float halfHeight, float radius, float verticalFovDeg, float aspect, float margin)
		{
			if (!(verticalFovDeg > 1f) || !(verticalFovDeg < 179f))
			{
				verticalFovDeg = 30f;
			}
			if (!(aspect > 0.01f) || float.IsInfinity(aspect))
			{
				aspect = 1f;
			}
			if (!(margin >= 0f) || float.IsInfinity(margin))
			{
				margin = 0f;
			}
			if (!(radius > 0f) || float.IsInfinity(radius))
			{
				radius = 0.5f;
			}
			halfWidth = ((halfWidth > 0f && !float.IsInfinity(halfWidth)) ? halfWidth : radius);
			halfHeight = ((halfHeight > 0f && !float.IsInfinity(halfHeight)) ? halfHeight : radius);
			double num = Math.Tan((double)verticalFovDeg * 0.5 * (Math.PI / 180.0));
			double num2 = num * (double)aspect;
			double num3 = 1.0 + (double)margin;
			double val = (double)halfWidth * num3 / num2;
			double val2 = (double)halfHeight * num3 / num;
			return (float)Math.Max(radius * 1.5f, Math.Max(val, val2));
		}

		internal static float ClampPitch(float pitch, float limit)
		{
			limit = Math.Max(0f, Math.Min(89f, float.IsNaN(limit) ? 0f : limit));
			if (float.IsNaN(pitch))
			{
				return 0f;
			}
			return Math.Max(0f - limit, Math.Min(limit, pitch));
		}

		internal static float WrapYaw(float yaw)
		{
			if (float.IsNaN(yaw) || float.IsInfinity(yaw))
			{
				return 0f;
			}
			double num = (double)yaw % 360.0;
			if (num > 180.0)
			{
				num -= 360.0;
			}
			if (num <= -180.0)
			{
				num += 360.0;
			}
			return (float)num;
		}

		internal static float StepZoom(float zoom, float steps, float factor, float min, float max)
		{
			if (!(min > 0f))
			{
				min = 0.01f;
			}
			if (max < min)
			{
				max = min;
			}
			if (!(factor > 1f))
			{
				factor = 1f;
			}
			if (!(zoom > 0f) || float.IsInfinity(zoom))
			{
				zoom = 1f;
			}
			double val = (double)zoom * Math.Pow(factor, float.IsNaN(steps) ? 0f : steps);
			return (float)Math.Max(min, Math.Min(max, val));
		}

		internal static void Orbit(float yawDeg, float pitchDeg, float distance, out float x, out float y, out float z)
		{
			double num = (double)yawDeg * (Math.PI / 180.0);
			double num2 = (double)pitchDeg * (Math.PI / 180.0);
			double num3 = (double)distance * Math.Cos(num2);
			x = (float)((0.0 - num3) * Math.Sin(num));
			y = (float)((double)distance * Math.Sin(num2));
			z = (float)((0.0 - num3) * Math.Cos(num));
		}

		internal static void CameraAxes(float yawDeg, float pitchDeg, out float rx, out float ry, out float rz, out float ux, out float uy, out float uz)
		{
			double num = (double)yawDeg * (Math.PI / 180.0);
			double num2 = (double)pitchDeg * (Math.PI / 180.0);
			double num3 = Math.Sin(num);
			double num4 = Math.Cos(num);
			double num5 = Math.Sin(num2);
			double num6 = Math.Cos(num2);
			rx = (float)num4;
			ry = 0f;
			rz = (float)(0.0 - num3);
			ux = (float)(num5 * num3);
			uy = (float)num6;
			uz = (float)(num5 * num4);
		}

		internal static bool ClampLength(ref float x, ref float y, ref float z, float limit)
		{
			if (float.IsNaN(x) || float.IsNaN(y) || float.IsNaN(z))
			{
				x = 0f;
				y = 0f;
				z = 0f;
				return true;
			}
			limit = (float.IsNaN(limit) ? 0f : Math.Max(0f, limit));
			double num = Math.Sqrt((double)x * (double)x + (double)y * (double)y + (double)z * (double)z);
			if (num <= (double)limit)
			{
				return false;
			}
			double num2 = ((num > 0.0) ? ((double)limit / num) : 0.0);
			x = (float)((double)x * num2);
			y = (float)((double)y * num2);
			z = (float)((double)z * num2);
			return true;
		}
	}
	internal sealed class ViewerOrbit
	{
		private readonly ViewerSettings _settings;

		private const float Tiny = 1E-06f;

		private readonly Action<string> _log;

		internal float Yaw { get; private set; }

		internal float Pitch { get; private set; }

		internal float Zoom { get; private set; }

		internal float PanX { get; private set; }

		internal float PanY { get; private set; }

		internal float PanZ { get; private set; }

		private static bool Differs(float a, float b)
		{
			return !(Math.Abs(a - b) <= 1E-06f);
		}

		internal ViewerOrbit(ViewerSettings settings, Action<string> log = null)
		{
			_settings = settings ?? new ViewerSettings();
			_log = log;
			Reset();
		}

		internal bool Reset()
		{
			float num = ViewerMath.WrapYaw(_settings.StartYaw);
			float num2 = ViewerMath.ClampPitch(_settings.StartPitch, _settings.PitchLimit);
			bool flag = PanX != 0f || PanY != 0f || PanZ != 0f;
			bool flag2 = Differs(num, Yaw) || Differs(num2, Pitch) || Differs(Zoom, 1f) || flag;
			Yaw = num;
			Pitch = num2;
			Zoom = 1f;
			PanX = 0f;
			PanY = 0f;
			PanZ = 0f;
			Log("ViewerOrbit: reset to " + this?.ToString() + (flag2 ? "" : " (already there)"));
			return flag2;
		}

		internal bool Pan(float dx, float dy, float frameHeightPx)
		{
			if (float.IsNaN(dx) || float.IsNaN(dy))
			{
				Log("ViewerOrbit: pan with NaN ignored");
				return false;
			}
			if (!(frameHeightPx >= 1f) || float.IsInfinity(frameHeightPx))
			{
				Log("ViewerOrbit: pan ignored, frame height " + F(frameHeightPx) + " px is not usable");
				return false;
			}
			float num = _settings.PanSpeed / (frameHeightPx * Math.Max(0.01f, Zoom));
			ViewerMath.CameraAxes(Yaw, Pitch, out var rx, out var ry, out var rz, out var ux, out var uy, out var uz);
			float x = PanX + ((0f - rx) * dx + ux * dy) * num;
			float y = PanY + ((0f - ry) * dx + uy * dy) * num;
			float z = PanZ + ((0f - rz) * dx + uz * dy) * num;
			bool flag = ViewerMath.ClampLength(ref x, ref y, ref z, _settings.PanLimit);
			int num2;
			if (!(Math.Abs(x - PanX) > 1E-06f) && !(Math.Abs(y - PanY) > 1E-06f))
			{
				num2 = ((Math.Abs(z - PanZ) > 1E-06f) ? 1 : 0);
				if (num2 == 0)
				{
					if (flag)
					{
						Log("ViewerOrbit: pan at the limit (" + F(_settings.PanLimit) + " view heights), view " + this);
					}
					return (byte)num2 != 0;
				}
			}
			else
			{
				num2 = 1;
			}
			PanX = x;
			PanY = y;
			PanZ = z;
			return (byte)num2 != 0;
		}

		internal bool Drag(float dx, float dy)
		{
			if (float.IsNaN(dx) || float.IsNaN(dy))
			{
				Log("ViewerOrbit: drag with NaN ignored");
				return false;
			}
			float num = ViewerMath.WrapYaw(Yaw - dx * _settings.RotateSpeed);
			float num2 = ViewerMath.ClampPitch(Pitch + dy * _settings.RotateSpeed, _settings.PitchLimit);
			bool result = Differs(num, Yaw) || Differs(num2, Pitch);
			Yaw = num;
			Pitch = num2;
			return result;
		}

		internal bool StepZoom(float steps)
		{
			float num = ViewerMath.StepZoom(Zoom, steps, _settings.ZoomStep, _settings.ZoomMin, _settings.ZoomMax);
			bool flag = Differs(num, Zoom);
			Log("ViewerOrbit: zoom " + F(Zoom) + " -> " + F(num) + " (" + F(steps) + " step(s), range " + F(_settings.ZoomMin) + ".." + F(_settings.ZoomMax) + ")" + (flag ? "" : " - at the limit"));
			Zoom = num;
			return flag;
		}

		internal bool Wheel(float deltaY)
		{
			if (deltaY == 0f || float.IsNaN(deltaY))
			{
				return false;
			}
			return StepZoom((deltaY > 0f) ? (-1f) : 1f);
		}

		private static string F(float v)
		{
			return v.ToString("0.##", CultureInfo.InvariantCulture);
		}

		public override string ToString()
		{
			return "yaw " + F(Yaw) + " deg, pitch " + F(Pitch) + " deg, zoom x" + F(Zoom) + ", pan (" + F(PanX) + ", " + F(PanY) + ", " + F(PanZ) + ") view heights";
		}

		private void Log(string s)
		{
			if (_log != null)
			{
				_log(s);
			}
		}
	}
	internal sealed class ViewerSettings
	{
		internal const float RotateSpeedMin = 0.05f;

		internal const float RotateSpeedMax = 2f;

		internal const float RotateSpeedDefault = 0.4f;

		internal const float ZoomStepMin = 1.02f;

		internal const float ZoomStepMax = 2f;

		internal const float ZoomStepDefault = 1.2f;

		internal const float ZoomMaxMin = 1f;

		internal const float ZoomMaxMax = 20f;

		internal const float ZoomMaxDefault = 8f;

		internal const float ZoomMinMin = 0.2f;

		internal const float ZoomMinMax = 1f;

		internal const float ZoomMinDefault = 0.5f;

		internal const float PitchLimitMin = 0f;

		internal const float PitchLimitMax = 89f;

		internal const float PitchLimitDefault = 80f;

		internal const float FrameHeightMin = 200f;

		internal const float FrameHeightMax = 800f;

		internal const float FrameHeightDefault = 420f;

		internal const float MarginMin = 0f;

		internal const float MarginMax = 0.5f;

		internal const float MarginDefault = 0.08f;

		internal const float StartYawMin = -180f;

		internal const float StartYawMax = 180f;

		internal const float StartYawDefault = 20f;

		internal const float StartPitchMin = -89f;

		internal const float StartPitchMax = 89f;

		internal const float StartPitchDefault = 12f;

		internal const float PanSpeedMin = 0.2f;

		internal const float PanSpeedMax = 3f;

		internal const float PanSpeedDefault = 1f;

		internal const float PanLimitMin = 0f;

		internal const float PanLimitMax = 3f;

		internal const float PanLimitDefault = 0.8f;

		internal const float KeyLightMin = 0f;

		internal const float KeyLightMax = 2f;

		internal const float KeyLightDefault = 0.7f;

		internal const float FillLightMin = 0f;

		internal const float FillLightMax = 1.5f;

		internal const float FillLightDefault = 0.25f;

		internal const float AmbientMin = 0f;

		internal const float AmbientMax = 1f;

		internal const float AmbientDefault = 0.22f;

		internal float RotateSpeed = 0.4f;

		internal float ZoomStep = 1.2f;

		internal float ZoomMax = 8f;

		internal float ZoomMin = 0.5f;

		internal float PitchLimit = 80f;

		internal float FrameHeight = 420f;

		internal float Margin = 0.08f;

		internal float StartYaw = 20f;

		internal float StartPitch = 12f;

		internal float PanSpeed = 1f;

		internal float PanLimit = 0.8f;

		internal float KeyLight = 0.7f;

		internal float FillLight = 0.25f;

		internal float Ambient = 0.22f;

		internal int Clamp(Action<string> log = null)
		{
			int changed = 0;
			RotateSpeed = Fix("RotateSpeed", RotateSpeed, 0.05f, 2f, 0.4f, ref changed, log);
			ZoomStep = Fix("ZoomStep", ZoomStep, 1.02f, 2f, 1.2f, ref changed, log);
			ZoomMax = Fix("ZoomMax", ZoomMax, 1f, 20f, 8f, ref changed, log);
			ZoomMin = Fix("ZoomMin", ZoomMin, 0.2f, 1f, 0.5f, ref changed, log);
			PitchLimit = Fix("PitchLimit", PitchLimit, 0f, 89f, 80f, ref changed, log);
			FrameHeight = Fix("FrameHeight", FrameHeight, 200f, 800f, 420f, ref changed, log);
			Margin = Fix("Margin", Margin, 0f, 0.5f, 0.08f, ref changed, log);
			StartYaw = Fix("StartYaw", StartYaw, -180f, 180f, 20f, ref changed, log);
			StartPitch = Fix("StartPitch", StartPitch, -89f, 89f, 12f, ref changed, log);
			PanSpeed = Fix("PanSpeed", PanSpeed, 0.2f, 3f, 1f, ref changed, log);
			PanLimit = Fix("PanLimit", PanLimit, 0f, 3f, 0.8f, ref changed, log);
			KeyLight = Fix("KeyLight", KeyLight, 0f, 2f, 0.7f, ref changed, log);
			FillLight = Fix("FillLight", FillLight, 0f, 1.5f, 0.25f, ref changed, log);
			Ambient = Fix("Ambient", Ambient, 0f, 1f, 0.22f, ref changed, log);
			if (StartPitch > PitchLimit || StartPitch < 0f - PitchLimit)
			{
				float startPitch = StartPitch;
				StartPitch = Math.Max(0f - PitchLimit, Math.Min(PitchLimit, StartPitch));
				changed++;
				log?.Invoke("ViewerSettings: StartPitch " + F(startPitch) + " is outside PitchLimit " + F(PitchLimit) + ", using " + F(StartPitch));
			}
			log?.Invoke("ViewerSettings: " + this?.ToString() + " (" + changed + " value(s) put into range)");
			return changed;
		}

		private static float Fix(string name, float v, float min, float max, float def, ref int changed, Action<string> log)
		{
			float num = ((float.IsNaN(v) || float.IsInfinity(v)) ? def : Math.Max(min, Math.Min(max, v)));
			if (!(Math.Abs(num - v) <= 1E-06f))
			{
				changed++;
				log?.Invoke("ViewerSettings: " + name + " " + F(v) + " is outside " + F(min) + ".." + F(max) + ", using " + F(num));
			}
			return num;
		}

		private static string F(float v)
		{
			return v.ToString("0.###", CultureInfo.InvariantCulture);
		}

		public override string ToString()
		{
			return "rotate " + F(RotateSpeed) + " deg/px, zoom step x" + F(ZoomStep) + ", zoom " + F(ZoomMin) + ".." + F(ZoomMax) + ", pitch limit " + F(PitchLimit) + " deg, frame " + F(FrameHeight) + " px, margin " + F(Margin) + ", start yaw " + F(StartYaw) + " / pitch " + F(StartPitch) + " deg, pan speed x" + F(PanSpeed) + ", pan limit " + F(PanLimit) + " view heights, light key " + F(KeyLight) + " / fill " + F(FillLight) + " / ambient " + F(Ambient);
		}
	}
}
namespace ComfortMagicBubbles.Testing
{
	internal static class InGameTests
	{
		private static string Startup_ConfigBound()
		{
			if (ModSettings.EnableAll == null)
			{
				return "FAIL: ModSettings.Bind did not run (EnableAll is null)";
			}
			if (!ModSettings.On)
			{
				return "SKIP: EnableAll is off in the config";
			}
			return "PASS: EnableAll on";
		}

		private static string Startup_FeaturesInstalled()
		{
			ModInstaller current = ModInstaller.Current;
			if (current == null)
			{
				return "FAIL: ModInstaller.Install did not run";
			}
			int num = 0;
			foreach (IFeature item in current.Features.All)
			{
				if (current.Features.IsRunning(item.Id))
				{
					num++;
				}
			}
			ModLog.Verbose("InGameTests: Startup_FeaturesInstalled " + current.Features.Count + " feature(s), " + num + " running");
			if (current.Features.Count <= 0)
			{
				return "FAIL: no feature registered";
			}
			return "PASS: " + current.Features.Count + " feature(s), " + num + " running";
		}

		private static string Startup_CoreLoaded()
		{
			bool flag = Chainloader.PluginInfos.ContainsKey("com.kydldev.KydlCore");
			ModLog.Verbose("InGameTests: Startup_CoreLoaded " + flag);
			if (!flag)
			{
				return "FAIL: com.kydldev.KydlCore is not loaded (this mod requires it)";
			}
			return "PASS: com.kydldev.KydlCore is loaded";
		}

		private static string World_PlayerPresent()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			ModLog.Verbose("InGameTests: World_PlayerPresent player " + (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetPlayerName() : "null"));
			if (!((Object)(object)localPlayer != (Object)null))
			{
				return "FAIL: no local player 5 s after the world loaded";
			}
			string playerName = localPlayer.GetPlayerName();
			Vector3 position = ((Component)localPlayer).transform.position;
			return "PASS: " + playerName + " at " + ((Vector3)(ref position)).ToString("F1");
		}
	}
}
namespace ComfortMagicBubbles.Testing.TestHooks
{
	internal static class BubbleLookTestHooks
	{
		private const int ShotWidth = 480;

		private static float _baseWhiteness = -1f;

		private static float _baseLuma = -1f;

		[TestHook("ComfortMagicBubbles.bubble.whiteness")]
		private static string Whiteness(string who, string effect, string mark)
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			string problem;
			MeshRenderer val = BubbleTestHooks.FindSphere(who, effect, out problem);
			if ((Object)(object)val == (Object)null)
			{
				return problem;
			}
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return BubbleTestHooks.Reason("no main camera");
			}
			if (!Measure(main, val, out var whiteness, out var pixels, out var why, out var mean))
			{
				return BubbleTestHooks.Reason(why);
			}
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			if (mark == "base")
			{
				_baseWhiteness = whiteness;
				_baseLuma = Luma(mean);
				ModLog.Info($"BubbleLookTestHooks: whiteness base {whiteness:0.000} over {pixels} pixel(s)");
				return whiteness.ToString("0.000", invariantCulture);
			}
			if (_baseWhiteness < 0f)
			{
				return BubbleTestHooks.Reason("no base measured (call with mark \"base\" first)");
			}
			float num = whiteness - _baseWhiteness;
			ModLog.Info($"BubbleLookTestHooks: whiteness {whiteness:0.000} vs base {_baseWhiteness:0.000} = {num:+0.000;-0.000} over {pixels} pixel(s)");
			return num.ToString("0.000", invariantCulture);
		}

		[TestHook("ComfortMagicBubbles.bubble.dimming")]
		private static string Dimming(string who, string effect)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			string problem;
			MeshRenderer val = BubbleTestHooks.FindSphere(who, effect, out problem);
			if ((Object)(object)val == (Object)null)
			{
				return problem;
			}
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return BubbleTestHooks.Reason("no main camera");
			}
			if (_baseLuma < 0f)
			{
				return BubbleTestHooks.Reason("no base measured (call bubble.whiteness with mark \"base\" first)");
			}
			if (!Measure(main, val, out var _, out var pixels, out var why, out var mean))
			{
				return BubbleTestHooks.Reason(why);
			}
			float num = _baseLuma - Luma(mean);
			ModLog.Info($"BubbleLookTestHooks: luminance {Luma(mean):0.000} vs base {_baseLuma:0.000} = {num:+0.000;-0.000} darker over {pixels} pixel(s)");
			return num.ToString("0.000", CultureInfo.InvariantCulture);
		}

		private static float Luma(Color c)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			return 0.2126f * c.r + 0.7152f * c.g + 0.0722f * c.b;
		}

		[TestHook("ComfortMagicBubbles.bubble.meanColour")]
		private static string MeanColour(string who, string effect)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			string problem;
			MeshRenderer val = BubbleTestHooks.FindSphere(who, effect, out problem);
			if ((Object)(object)val == (Object)null)
			{
				return problem;
			}
			Camera main = Camera.main;
			if ((Object)(object)main == (Object)null)
			{
				return BubbleTestHooks.Reason("no main camera");
			}
			if (!Measure(main, val, out var _, out var pixels, out var why, out var mean))
			{
				return BubbleTestHooks.Reason(why);
			}
			string text = $"{Mathf.RoundToInt(mean.r * 255f)},{Mathf.RoundToInt(mean.g * 255f)},{Mathf.RoundToInt(mean.b * 255f)}";
			ModLog.Info($"BubbleLookTestHooks: mean colour {text} over {pixels} pixel(s)");
			return text;
		}

		[TestHook("ComfortMagicBubbles.bubble.forceMetallic")]
		private static string ForceMetallic(string who, string effect, double value)
		{
			string problem;
			MeshRenderer val = BubbleTestHooks.FindSphere(who, effect, out problem);
			if ((Object)(object)val == (Object)null)
			{
				return problem;
			}
			Material sharedMaterial = ((Renderer)val).sharedMaterial;
			if ((Object)(object)sharedMaterial == (Object)null || !sharedMaterial.HasProperty("_Metallic"))
			{
				return BubbleTestHooks.Reason("sphere material has no _Metallic");
			}
			sharedMaterial.SetFloat("_Metallic", (float)value);
			return "metallic " + sharedMaterial.GetFloat("_Metallic").ToString("0.00", CultureInfo.InvariantCulture);
		}

		[TestHook("ComfortMagicBubbles.bubble.setFloat")]
		private static string SetFloat(string who, string effect, string prop, double value)
		{
			string problem;
			MeshRenderer val = BubbleTestHooks.FindSphere(who, effect, out problem);
			if ((Object)(object)val == (Object)null)
			{
				return problem;
			}
			Material sharedMaterial = ((Renderer)val).sharedMaterial;
			if ((Object)(object)sharedMaterial == (Object)null || !sharedMaterial.HasProperty(prop))
			{
				return BubbleTestHooks.Reason("sphere material has no " + prop);
			}
			sharedMaterial.SetFloat(prop, (float)value);
			return prop + " = " + sharedMaterial.GetFloat(prop).ToString("0.000", CultureInfo.InvariantCulture);
		}

		[TestHook("ComfortMagicBubbles.bubble.keyword")]
		private static string Keyword(string who, string effect, string keyword, bool on)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			string problem;
			MeshRenderer val = BubbleTestHooks.FindSphere(who, effect, out problem);
			if ((Object)(object)val == (Object)null)
			{
				return problem;
			}
			Material sharedMaterial = ((Renderer)val).sharedMaterial;
			if ((Object)(object)sharedMaterial == (Object)null)
			{
				return BubbleTestHooks.Reason("sphere has no material");
			}
			if (!string.IsNullOrEmpty(keyword))
			{
				if (on)
				{
					sharedMaterial.EnableKeyword(keyword);
				}
				else
				{
					sharedMaterial.DisableKeyword(keyword);
				}
			}
			LocalKeywordSpace keywordSpace = sharedMaterial.shader.keywordSpace;
			string text = string.Join(" ", ((LocalKeywordSpace)(ref keywordSpace)).keywordNames);
			string text2 = "known [" + text + "] on [" + string.Join(" ", sharedMaterial.shaderKeywords) + "]";
			ModLog.Info("BubbleLookTestHooks: " + text2);
			return text2;
		}

		private static bool Measure(Camera camera, MeshRenderer sphere, out float whiteness, out int pixels, out string why, out Color mean)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			whiteness = 0f;
			pixels = 0;
			why = null;
			mean = Color.black;
			int num = 480;
			int num2 = Mathf.Max(1, Mathf.RoundToInt(480f * (float)Screen.height / (float)Mathf.Max(1, Screen.width)));
			Bounds bounds = ((Renderer)sphere).bounds;
			Vector3 val = camera.WorldToViewportPoint(((Bounds)(ref bounds)).center);
			Vector3 val2 = camera.WorldToViewportPoint(((Bounds)(ref bounds)).center + ((Component)camera).transform.right * ((Bounds)(ref bounds)).extents.x);
			if (val.z <= 0f)
			{
				why = "the bubble is behind the camera";
				return false;
			}
			float num3 = val.x * (float)num;
			float num4 = val.y * (float)num2;
			float num5 = Mathf.Abs(val2.x - val.x) * (float)num * 0.9f;
			RenderTexture temporary = RenderTexture.GetTemporary(num, num2, 24, (RenderTextureFormat)0);
			RenderTexture targetTexture = camera.targetTexture;
			RenderTexture active = RenderTexture.active;
			Texture2D val3 = new Texture2D(num, num2, (TextureFormat)4, false);
			try
			{
				camera.targetTexture = temporary;
				camera.Render();
				RenderTexture.active = temporary;
				val3.ReadPixels(new Rect(0f, 0f, (float)num, (float)num2), 0, 0, false);
				val3.Apply(false);
			}
			finally
			{
				camera.targetTexture = targetTexture;
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
			double num6 = 0.0;
			double num7 = 0.0;
			double num8 = 0.0;
			double num9 = 0.0;
			Color32[] pixels2 = val3.GetPixels32();
			Object.Destroy((Object)(object)val3);
			for (int i = Mathf.Max(0, (int)(num4 - num5)); i < Mathf.Min(num2, (int)(num4 + num5) + 1); i++)
			{
				for (int j = Mathf.Max(0, (int)(num3 - num5)); j < Mathf.Min(num, (int)(num3 + num5) + 1); j++)
				{
					float num10 = (float)j - num3;
					float num11 = (float)i - num4;
					if (!(num10 * num10 + num11 * num11 > num5 * num5))
					{
						Color32 val4 = pixels2[i * num + j];
						num6 += (double)((float)Mathf.Min((int)val4.r, Mathf.Min((int)val4.g, (int)val4.b)) / 255f);
						num7 += (double)((float)(int)val4.r / 255f);
						num8 += (double)((float)(int)val4.g / 255f);
						num9 += (double)((float)(int)val4.b / 255f);
						pixels++;
					}
				}
			}
			if (pixels < 50)
			{
				why = $"only {pixels} pixel(s) of the bubble on screen (radius {num5:0.0} px)";
				return false;
			}
			whiteness = (float)(num6 / (double)pixels);
			mean = new Color((float)(num7 / (double)pixels), (float)(num8 / (double)pixels), (float)(num9 / (double)pixels));
			return true;
		}
	}
	internal static class BubbleProbe
	{
		internal const string NoEffect = "none";

		internal const string NoSphere = "no sphere";

		internal const string NoLight = "no light";

		internal const string NoSmoke = "no smoke";

		private const string SphereName = "Sphere";

		private const float FullByte = 255f;

		private const float FullPercent = 100f;

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		private static readonly int PatternOpacityId = Shader.PropertyToID("_Opacity");

		private static readonly FieldRef<StatusEffect, GameObject[]> Instances = AccessTools.FieldRefAccess<StatusEffect, GameObject[]>("m_startEffectInstances");

		internal static MeshRenderer SphereOf(Character wearer, string effect, out string problem)
		{
			StatusEffect statusEffect = wearer.GetSEMan().GetStatusEffect(StringExtensionMethods.GetStableHashCode(effect));
			GameObject[] array = (((Object)(object)statusEffect != (Object)null) ? Instances.Invoke(statusEffect) : null);
			MeshRenderer val = null;
			if (array != null)
			{
				GameObject[] array2 = array;
				foreach (GameObject bubble in array2)
				{
					val = (((Object)(object)val != (Object)null) ? val : SphereIn(bubble));
				}
			}
			problem = (((Object)(object)val != (Object)null) ? null : (((Object)(object)statusEffect == (Object)null) ? "none" : "no sphere"));
			return val;
		}

		internal static MeshRenderer SphereIn(GameObject bubble)
		{
			Transform val = (((Object)(object)bubble != (Object)null) ? bubble.transform.Find("Sphere") : null);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).GetComponent<MeshRenderer>();
		}

		internal static string LightOf(MeshRenderer sphere)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			Light val = (((Object)(object)sphere != (Object)null) ? ((Component)((Component)sphere).transform.parent).GetComponentInChildren<Light>(true) : null);
			if (!((Object)(object)val != (Object)null))
			{
				return "no light";
			}
			return $"{Hex(val.color)}/{Mathf.RoundToInt(BubbleLights.BaseIntensity(val) * 100f)}";
		}

		internal static string SmokeOf(MeshRenderer sphere)
		{
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			ParticleSystem val = null;
			ParticleSystem[] array = (ParticleSystem[])(((Object)(object)sphere != (Object)null) ? ((Array)((Component)((Component)sphere).transform.parent).GetComponentsInChildren<ParticleSystem>(false)) : ((Array)new ParticleSystem[0]));
			foreach (ParticleSystem val2 in array)
			{
				val = (((Object)(object)val != (Object)null) ? val : val2);
			}
			Color val3 = (((Object)(object)val != (Object)null) ? BubbleSmoke.StartColour(val) : Color.clear);
			if (!((Object)(object)val != (Object)null))
			{
				return "no smoke";
			}
			return $"{Hex(val3)}/{Mathf.RoundToInt(val3.a * 100f)}";
		}

		private static string Hex(Color colour)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			return $"#{Mathf.RoundToInt(colour.r * 255f):X2}{Mathf.RoundToInt(colour.g * 255f):X2}{Mathf.RoundToInt(colour.b * 255f):X2}";
		}

		internal static string Look(MeshRenderer sphere)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			Material val = (((Object)(object)sphere != (Object)null) ? ((Renderer)sphere).sharedMaterial : null);
			int num;
			Color val2;
			if ((Object)(object)val != (Object)null)
			{
				num = (val.HasProperty(ColorId) ? 1 : 0);
				if (num != 0)
				{
					val2 = val.GetColor(ColorId);
					goto IL_003f;
				}
			}
			else
			{
				num = 0;
			}
			val2 = Color.clear;
			goto IL_003f;
			IL_003f:
			Color val3 = val2;
			if (num != 0 && val.HasProperty(PatternOpacityId))
			{
				val3.a = val.GetFloat(PatternOpacityId);
			}
			if (num == 0)
			{
				return "no sphere";
			}
			return $"{Hex(val3)}/{Mathf.RoundToInt(val3.a * 100f)}";
		}
	}
	internal static class BubbleSituationTestHooks
	{
		private const float InteriorTestHeight = 5000f;

		private const float GroundClearance = 0.5f;

		[TestHook("ComfortMagicBubbles.bubble.indoors")]
		private static string Indoors(bool inside)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return BubbleTestHooks.Reason("no local player");
			}
			Vector3 position = ((Component)localPlayer).transform.pos