Skip to content
This repository has been archived by the owner on Nov 9, 2023. It is now read-only.

Commit

Permalink
Merge pull request #107 from dfgHiatus/wizards
Browse files Browse the repository at this point in the history
Added LOD wizard, general purpose map wizard
  • Loading branch information
Xlinka authored Sep 18, 2022
2 parents ea28fae + 8f46ac9 commit 62495eb
Show file tree
Hide file tree
Showing 3 changed files with 373 additions and 1 deletion.
171 changes: 171 additions & 0 deletions Components/Wizards/LODWizard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
using BaseX;
using FrooxEngine.UIX;
using System.Linq;
using static FrooxEngine.LODGroup;

namespace FrooxEngine
{
[Category("Add-ons/Wizards")]
public class LODWizard : Component
{
private const string LOD_GROUP_PREFIX = "<LOD_GROUP>";

private const string LOD_1 = "<LOD_1>";
[Range(0f, 1f, "0.00")]
public readonly Sync<float> ScreenRelativeTransitionHeight_1;
[Range(0f, 1f, "0.00")]
public readonly Sync<float> FadeTransitionWidth_1;

private const string LOD_2 = "<LOD_2>";
[Range(0f, 1f, "0.00")]
public readonly Sync<float> ScreenRelativeTransitionHeight_2;
[Range(0f, 1f, "0.00")]
public readonly Sync<float> FadeTransitionWidth_2;

private const string LOD_3 = "<LOD_3>";
[Range(0f, 1f, "0.00")]
public readonly Sync<float> ScreenRelativeTransitionHeight_3;
[Range(0f, 1f, "0.00")]
public readonly Sync<float> FadeTransitionWidth_3;

private const string LOD_4 = "<LOD_4>";
[Range(0f, 1f, "0.00")]
public readonly Sync<float> ScreenRelativeTransitionHeight_4;
[Range(0f, 1f, "0.00")]
public readonly Sync<float> FadeTransitionWidth_4;

public readonly SyncRef<Slot> ProcessRoot;
public readonly Sync<bool> CrossFade;
public readonly Sync<bool> AnimateCrossFading;

protected override void OnAttach()
{
base.OnAttach();
CrossFade.Value = false;
AnimateCrossFading.Value = false;

Slot.Name = "Map Wizard";
Slot.Tag = "Developer";
NeosCanvasPanel neosCanvasPanel = Slot.AttachComponent<NeosCanvasPanel>();
neosCanvasPanel.Panel.AddCloseButton();
neosCanvasPanel.Panel.Title = this.GetLocalized("LOD Wizard");
neosCanvasPanel.CanvasSize = new float2(600f, 600f);
neosCanvasPanel.PhysicalHeight = 0.5f;

UIBuilder ui = new UIBuilder(neosCanvasPanel.Canvas);
ui.VerticalLayout(4f);
ui.Style.MinHeight = 24f;
ui.Style.PreferredHeight = 24f;
UIBuilder uIBuilder = ui;
LocaleString text = "Wizard.LightSources.Header".AsLocaleKey("<b>{0}</b>");
uIBuilder.Text(in text);
UIBuilder uIBuilder2 = ui;
text = "Wizard.LightSources.ProcessRoot".AsLocaleKey();
uIBuilder2.Text(in text);
ui.Next("Process Root");
ui.Current.AttachComponent<RefEditor>().Setup(ProcessRoot);
UIBuilder uIBuilder3 = ui;

text = "Cross Fade".AsLocaleKey();
uIBuilder3.HorizontalElementWithLabel(in text, 0.8f, () => ui.BooleanMemberEditor(CrossFade));
UIBuilder uIBuilder4 = ui;
text = "Animate Cross Fading".AsLocaleKey();
uIBuilder4.HorizontalElementWithLabel(in text, 0.8f, () => ui.BooleanMemberEditor(AnimateCrossFading));

UIBuilder uIBuilder5 = ui;
text = "LOD Group 1 ScreenRelativeTransitionHeight".AsLocaleKey();
uIBuilder5.HorizontalElementWithLabel(in text, 0.8f, () => ui.PrimitiveMemberEditor(ScreenRelativeTransitionHeight_1));
UIBuilder uIBuilder6 = ui;
text = "LOD Group 1 FadeTransitionWidth".AsLocaleKey();
uIBuilder6.HorizontalElementWithLabel(in text, 0.8f, () => ui.PrimitiveMemberEditor(FadeTransitionWidth_1));
UIBuilder uIBuilder7 = ui;
text = "LOD Group 2 ScreenRelativeTransitionHeight".AsLocaleKey();
uIBuilder7.HorizontalElementWithLabel(in text, 0.8f, () => ui.PrimitiveMemberEditor(ScreenRelativeTransitionHeight_2));
UIBuilder uIBuilder8 = ui;
text = "LOD Group 2 FadeTransitionWidth".AsLocaleKey();
uIBuilder8.HorizontalElementWithLabel(in text, 0.8f, () => ui.PrimitiveMemberEditor(FadeTransitionWidth_2));
UIBuilder uIBuilder9 = ui;
text = "LOD Group 3 ScreenRelativeTransitionHeight".AsLocaleKey();
uIBuilder9.HorizontalElementWithLabel(in text, 0.8f, () => ui.PrimitiveMemberEditor(ScreenRelativeTransitionHeight_3));
UIBuilder uIBuilder10 = ui;
text = "LOD Group 3 FadeTransitionWidth".AsLocaleKey();
uIBuilder10.HorizontalElementWithLabel(in text, 0.8f, () => ui.PrimitiveMemberEditor(FadeTransitionWidth_3));
UIBuilder uIBuilder11 = ui;
text = "LOD Group 4 ScreenRelativeTransitionHeight".AsLocaleKey();
uIBuilder11.HorizontalElementWithLabel(in text, 0.8f, () => ui.PrimitiveMemberEditor(ScreenRelativeTransitionHeight_4));
UIBuilder uIBuilder12 = ui;
text = "LOD Group 4 FadeTransitionWidth".AsLocaleKey();
uIBuilder12.HorizontalElementWithLabel(in text, 0.8f, () => ui.PrimitiveMemberEditor(FadeTransitionWidth_4));

UIBuilder uIBuilder13 = ui;
text = "-------";
uIBuilder13.Text(in text);
UIBuilder uIBuilder14 = ui;
text = "Setup LOD Groups".AsLocaleKey();
uIBuilder14.Button(in text, SetupLODs);
UIBuilder uIBuilder15 = ui;
text = "-------";
uIBuilder15.Text(in text);
}

[SyncMethod]
private void SetupLODs(IButton button, ButtonEventData eventData)
{
var lodGroupCanidate = ProcessRoot.Target.GetComponent<LODGroup>();
if (lodGroupCanidate == null)
{
lodGroupCanidate = ProcessRoot.Target.AttachComponent<LODGroup>();
lodGroupCanidate.CrossFade.Value = CrossFade.Value;
lodGroupCanidate.AnimateCrossFading.Value = AnimateCrossFading.Value;
}

// Note: Given FrooxEngine's implementation of the AddLOD method, it is impossible to nest LOD groups within eachother.
// This is because it calls Renderers.AddRange(root.GetComponentsInChildren<MeshRenderer>()), which is recursive.

// In other words, your heirachy should look something like this:
//
// ProcessRoot
// ...
// - ...
// - <LOD_GROUP>My Group
// -- <LOD_1>Level 1
// -- <LOD_2>Level 2
// -- <LOD_3>Level 3
// -- <LOD_4>Level 4
// -- ...
// - ...
// ...
//

// Where additional slots are ignored. Here, this would populate ProcessRoot's LODGroup with 4 LODs,
// Adhering to Unity's LOD standard. I don't think this implicity supports the culled state,
// Might be best to have a ColliderUserTracker to drive the entire mesh root.

LOD lod;
foreach (var child in ProcessRoot.Target.GetAllChildren().Where(x => x.Name.StartsWith(LOD_GROUP_PREFIX)))
{
switch (child.Name)
{
case LOD_1:
lod = lodGroupCanidate.AddLOD(ScreenRelativeTransitionHeight_1.Value, child);
lod.FadeTransitionWidth.Value = FadeTransitionWidth_1;
break;
case LOD_2:
lod = lodGroupCanidate.AddLOD(ScreenRelativeTransitionHeight_2.Value, child);
lod.FadeTransitionWidth.Value = FadeTransitionWidth_2;
break;
case LOD_3:
lod = lodGroupCanidate.AddLOD(ScreenRelativeTransitionHeight_3.Value, child);
lod.FadeTransitionWidth.Value = FadeTransitionWidth_3;
break;
case LOD_4:
lod = lodGroupCanidate.AddLOD(ScreenRelativeTransitionHeight_4.Value, child);
lod.FadeTransitionWidth.Value = FadeTransitionWidth_4;
break;
default:
break;
}
}
}
}
}
199 changes: 199 additions & 0 deletions Components/Wizards/MapWizard.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
using System;
using BaseX;
using FrooxEngine.UIX;

namespace FrooxEngine
{
[Category("Add-ons/Wizards")]
public class MapWizard : Component, IDeveloperInterface, IComponent, IComponentBase, IDestroyable, IWorker, IWorldElement, IUpdatable, IChangeable, IAudioUpdatable, IInitializable, ILinkable
{
public readonly SyncRef<Slot> Root;

public readonly Sync<bool> ProcessPointLights;

public readonly Sync<bool> ProcessSpotLights;

public readonly Sync<bool> ProcessDirectionalLights;

public readonly Sync<bool> ProcessDisabled;

public readonly Sync<bool> ProcessColor;

public readonly Sync<color> Color;

public readonly SyncRef<TextField> ProcessTags;

public readonly SyncRef<FloatTextEditorParser> _intensityField;

public readonly SyncRef<FloatTextEditorParser> _intensityFieldMultiplicative;

public readonly SyncRef<FloatTextEditorParser> _extentField;

protected override void OnAttach()
{
base.OnAttach();
ProcessPointLights.Value = true;
ProcessSpotLights.Value = true;
ProcessDirectionalLights.Value = true;
ProcessDisabled.Value = false;
ProcessColor.Value = false;

Slot.Name = "Map Wizard";
Slot.Tag = "Developer";
NeosCanvasPanel neosCanvasPanel = Slot.AttachComponent<NeosCanvasPanel>();
neosCanvasPanel.Panel.AddCloseButton();
neosCanvasPanel.Panel.Title = this.GetLocalized("Wizard.LightSources.Title");
neosCanvasPanel.CanvasSize = new float2(600f, 600f);
neosCanvasPanel.PhysicalHeight = 0.5f;
UIBuilder ui = new UIBuilder(neosCanvasPanel.Canvas);
ui.VerticalLayout(4f);
ui.Style.MinHeight = 24f;
ui.Style.PreferredHeight = 24f;
UIBuilder uIBuilder = ui;
LocaleString text = "Wizard.LightSources.Header".AsLocaleKey("<b>{0}</b>");
uIBuilder.Text(in text);
UIBuilder uIBuilder2 = ui;
text = "Wizard.LightSources.ProcessRoot".AsLocaleKey();
uIBuilder2.Text(in text);
ui.Next("Root");
ui.Current.AttachComponent<RefEditor>().Setup(Root);
UIBuilder uIBuilder3 = ui;
text = "Wizard.LightSources.PointLights".AsLocaleKey();
uIBuilder3.HorizontalElementWithLabel(in text, 0.8f, () => ui.BooleanMemberEditor(ProcessPointLights));
UIBuilder uIBuilder4 = ui;
text = "Wizard.LightSources.SpotLights".AsLocaleKey();
uIBuilder4.HorizontalElementWithLabel(in text, 0.8f, () => ui.BooleanMemberEditor(ProcessSpotLights));
UIBuilder uIBuilder5 = ui;
text = "Wizard.LightSources.DirectionalLights".AsLocaleKey();
uIBuilder5.HorizontalElementWithLabel(in text, 0.8f, () => ui.BooleanMemberEditor(ProcessDirectionalLights));
UIBuilder uIBuilder6 = ui;
text = "Wizard.LightSources.DisabledLights".AsLocaleKey();
uIBuilder6.HorizontalElementWithLabel(in text, 0.8f, () => ui.BooleanMemberEditor(ProcessDisabled));
SyncRef<TextField> tag = ProcessTags;
UIBuilder uIBuilder7 = ui;
text = "Wizard.LightSources.WithTag".AsLocaleKey();
tag.Target = uIBuilder7.HorizontalElementWithLabel(in text, 0.8f, () => ui.TextField());
// UIBuilder uIBuilder8 = ui;
// uIBuilder8.ColorMemberEditor(Color, "LightSources with Color");
text = "-------";

UIBuilder uIBuilder9 = ui;
uIBuilder9.Text(in text);
_intensityField.Target = ui.FloatField(0f, 8f);
UIBuilder uIBuilder10 = ui;
text = "Set light intensity to value".AsLocaleKey();
uIBuilder10.Button(in text, ChangeIntensity);
text = "-------";

uIBuilder10.Text(in text);
_intensityFieldMultiplicative.Target = ui.FloatField(0f, 8f);
UIBuilder uIBuilder11 = ui;
text = "Multiply light intensity by value".AsLocaleKey();
uIBuilder11.Button(in text, ChangeIntensityMultiplicative);
UIBuilder uIBuilder12 = ui;
text = "-------";

UIBuilder uIBuilder13 = ui;
uIBuilder13.Text(in text);
_extentField.Target = ui.FloatField(0f, 50f);
UIBuilder uIBuilder14 = ui;
text = "Set light range to value".AsLocaleKey();
uIBuilder14.Button(in text, SetExtent);
text = "-------";
}
protected override void OnStart()
{
base.OnStart();
Slot.GetComponentInChildrenOrParents<Canvas>()?.MarkDeveloper();
}

[SyncMethod]
private void ChangeIntensity(IButton button, ButtonEventData eventData)
{
ForeachLight(delegate (Light l)
{
l.Intensity.Value = _intensityField.Target.ParsedValue;
});
}

[SyncMethod]
private void ChangeIntensityMultiplicative(IButton button, ButtonEventData eventData)
{
ForeachLight(delegate (Light l)
{
l.Intensity.Value *= _intensityFieldMultiplicative.Target.ParsedValue;
});
}

[SyncMethod]
private void SetExtent(IButton button, ButtonEventData eventData)
{
ForeachLight(delegate (Light l)
{
switch (l.LightType.Value)
{
case LightType.Spot:
var globalPosSpot = l.Slot.GlobalPosition;
var spotHit = Physics.RaycastOne(globalPosSpot, l.Slot.Down, _extentField.Target.ParsedValue);
if (spotHit.HasValue)
{
var clamped = MathX.Clamp(spotHit.Value.Distance, 0, _extentField.Target.ParsedValue);
l.Range.Value = clamped;
l.Intensity.Value = clamped / 10;
}
else
{
l.Range.Value = _extentField.Target.ParsedValue;
l.Intensity.Value = _extentField.Target.ParsedValue / 10;
}
break;
case LightType.Point:
var globalPosPoint = l.Slot.GlobalPosition;
ICollider pointHit = Physics.SphereBoolSweepOne(globalPosPoint, float3.Zero, _extentField.Target.ParsedValue);
if (pointHit == null)
{
l.Range.Value = _extentField.Target.ParsedValue;
l.Intensity.Value = _extentField.Target.ParsedValue / 10;
return;
}
for (int i = 0; i < _extentField.Target.ParsedValue; i++)
{
pointHit = Physics.SphereBoolSweepOne(globalPosPoint, float3.Zero, i);
if (pointHit != null)
break;
}
var dist = MathX.Distance(pointHit.Slot.GlobalPosition, globalPosPoint);
l.Range.Value = dist;
l.Intensity.Value = dist / 10;
break;
}
});
}

private void ForeachLight(Action<Light> process)
{
string tag = ProcessTags.Target.TargetString;
float4 canidate = Color.Value;
foreach (Light componentsInChild in (Root.Target ?? World.RootSlot).GetComponentsInChildren(delegate (Light l)
{
if (!ProcessDisabled.Value && (!l.Enabled || !l.Slot.IsActive))
{
return false;
}
float4 copy = l.Color.Value;
return (string.IsNullOrEmpty(tag) || !(l.Slot.Tag != tag)) &&
(!ProcessColor.Value || MathX.Approximately(in copy, in canidate)) &&
l.LightType.Value switch
{
LightType.Point => ProcessPointLights.Value,
LightType.Directional => ProcessDirectionalLights.Value,
LightType.Spot => ProcessSpotLights.Value,
_ => false,
};
}))
{
process(componentsInChild);
}
}
}
}
4 changes: 3 additions & 1 deletion NEOSPlus.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@
<Compile Include="Components\Physics\Cloth\ClothSphereConnector.cs" />
<Compile Include="Components\Utility\GrabberSimulator.cs" />
<Compile Include="Components\Wizards\MeshColliderManagementTools.cs" />
<Compile Include="Components\Wizards\LODWizard.cs" />
<Compile Include="Components\Wizards\MapWizard.cs" />
<Compile Include="Components\Audio\FFT\FFTSource.cs" />
<Compile Include="Logix\Avatar\AvatarRootSlot.cs" />
<Compile Include="Logix\Avatar\NearestUserList.cs" />
Expand Down Expand Up @@ -223,4 +225,4 @@
<PostBuildEvent>cd "$(ProjectDir)"
powershell -NoProfile -ExecutionPolicy Bypass ./Scripts/PostBuild.ps1 '$(NeosPath)' $(ConfigurationName)</PostBuildEvent>
</PropertyGroup>
</Project>
</Project>

0 comments on commit 62495eb

Please sign in to comment.